在AEScript中,要表示当前焦点的时间轴合成,可以使用app.project.activeItem
。但有一个小问题,如果项目面板处于焦点状态,它将表示项目面板内当前选定的项目,而不是时间轴合成。
这样一来,当使用带有用户UI界面的脚本,并在按下按钮时执行与时间轴合成内图层相关的操作时,如果用户恰巧选择了项目面板,那么可能会处理完全不同合成内的图层。
为了解决这个问题,可以通过代码强制选择时间轴合成。有一种方法是将查看器设置为活动状态,但是每次按下按钮时查看器会闪烁,给人不太好的视觉效果。
因此,我创建了一个函数,它并不强制选择时间轴合成,而是可以判断"当前没有选择时间轴合成"。以下是代码示例:
function mGetActiveItemNotOnPanel() {
var mAi = app.project.activeItem;
// 1.如果没有活动项目,则返回Null。
// 2.如果是面板,则可能是选择数为零或多个。
// 3.或者没有选择时间轴、查看器或流程图。
if (mAi === null) { return null; }
// 如果活动项目不是合成(即选择了面板以外的项目),则返回Null。
if (!(mAi instanceof CompItem)) { return null; }
// 主要处理
// 检查活动项目是面板中唯一选定的合成,还是选择了时间轴等。
// 如果选择从面板中移除,但不变为Null,那么活动的是时间轴等,因此返回它。
if (mAi.selected === false) { return mAi; }
// 如果选择在面板内,则取消活动项目的面板选择,并重新定义。
mAi.selected = false;
var mNewAi = app.project.activeItem;
// 如果新的活动项目是Null,则之前活动的是面板内的项目,因此返回Null。
//(将面板选择恢复原样)。
if (mNewAi === null) {
mAi.selected = true;
return null;
}
// 如果取消活动项目的选择并重新定义后仍不是Null,
// 则说明选择了时间轴等,因此返回新的活动项目。
//(将面板选择恢复原样)。
mAi.selected = true;
return mNewAi;
}
再来个不带注释的版本
function mGetActiveItemNotOnPanel(){
var mAi = app.project.activeItem;
if( mAi === null ){ return null; }
if( mAi instanceof CompItem !== true ){ return null; }
if( mAi.selected === false ){ return mAi; }
mAi.selected = false;
mNewAi = app.project.activeItem;
if( mNewAi === null ){
mAi.selected = true;
return null;
}
mAi.selected = true;
return mNewAi;
}
这是一个函数,如果时间轴合成未被选择,则返回null;如果已被选择,则返回该合成。使用这个函数,您可以确保在警报或信息面板中强制用户选择时间轴合成。
我们要判断的是“焦点是在面板还是在时间轴”。通过不同的条件进行筛选。现在让我们详细查看代码。
if (mAi === null) { return null; }
当活动项目为null时,表示焦点在面板上,并且面板内没有选择或选择了多个项目。如果焦点在时间轴上,活动项目不会为null。因此,如果活动项目为null,则可以确定焦点在面板上,因此返回null。
通过上述代码,我们可以确定两种可能的情况,即活动项目不为null时:
此时可能的状态
- 焦点在面板上,有任意一个选中项(无论选中项是否为合成)
- 焦点是时间轴,面板中的选择无关紧要(可以是多个、一个或零个)
继续。
if( mAi instanceof CompItem !== true ){ return null;}
如果活动项目是组合以外的任何类型的项目,它将返回 null,因为焦点不应该是时间轴。
而一旦过了这条线,状态就更加有限了。
此时可能的状态
- 焦点是一个面板,被选中的是一个合成
- 焦点是时间轴,面板中的选择无关紧要(可以是多个、一个或零个)
继续。
if( mAi.selected === false ){ return mAi;}
这就是这个剧本的秘密!
首先,在前面的 if 语句中,此时我们已经确定活动项不为空。
然而,除了时间轴被聚焦的情况下,selected 是不可能为 false 的,所以我们返回 activeItem。
(如果面板被聚焦,那么active item表示“一个”selected“item”,所以selected不能为false。)并且我通过了这一行,
如果selected为true则状态进一步限定。
此时可能的状态
- 焦点是一个面板,被选中的是一个组件
- 焦点为时间轴,面板中选择为多个或一个,选择与时间轴相同的合成
最后
mAi.selected = false;
mNewAi = app.project.activeItem;
if( mNewAi === null ){
mAi.selected = true;
return null;
}
mAi.selected = true;
return mNewAi;
我们故意取消了selected,重新定义了活动项目,并判断新的活动项目是否为null。
如果焦点在面板上,并且选择了一个合成,当取消该合成的selected后,新的活动项目将为null,因此在这种情况下返回null。
如果焦点在时间轴上,并且在面板内选择了与时间轴相同的合成(无论是否选择了其他项目),取消面板内的selected并重新定义活动项目后,它仍然不会为null。
因此,在这种情况下,我们返回新的活动项目。
(在最后一行的部分。虽然在每个return之前都使用了return来结束处理,而不是使用if和else进行条件分支,但if和else并没有特别的意义)。
由于两种情况都取消了selected,我们在各自的返回之前将其恢复为选中状态。
就是这样了!
如果是为自己编写的脚本,可能并不是特别必要,但如果是用于发布的脚本,最好还是做一下这个处理。
请随意使用!
■附注
为了可读性考虑,将焦点限定为“面板还是时间轴”的两个选项,但严格来说是“面板还是时间轴/查看器/流程图”的两个选项。由于时间轴、查看器和流程图是相关联的,只要选择了其中一个,它们会对时间轴合成执行操作。问题出现在“以为是时间轴,但选择了面板中的其他项目”的情况,因此,时间轴与查看器和流程图的关联在这个脚本中并不成问题。