本帖最后由 Lambholl 于 2026-1-19 23:13 编辑
先声明一下,我使用的kara-templater是AegisubDC版本中的修改版,因此有一些特性不一样,比如可以使用原版不能用的code char noblank等。
这个改版templater我认为还是挺好用的,因为《大神之路》这类教程告诉你可以用char,可以用noblank,实际上这两个一起用的需求我认为也不小。
为什么写这个帖子呢,因为期末考复习疯了,想来放松一下,虽然这种帖子应该没什么人看
以后也可能会更一些别的思路(下次期末考?)总之先写这个吧
在line模板执行过程中,提前获取下一行的宽度
具体有什么应用呢?个人应用在 BV1tF4m1u7FF 和 BV1GJkeBdEke的0:25-1:03 中。
这里一个用的是\frx旋转字幕,同时在开始和结束处用\fscx调整宽度,让两行的宽度在旋转时能够无缝衔接。
另一个是用来给横向\t \clip来制作「扫描」的效果,同时为了给「扫描」过程加上加速度(先加速再减速,转场动画的常见处理方式),需要取两行中较宽的一个数字作为clip起点和终点。
知周所众,想要当前行的宽度能被下一行读到,只需要使用code once初始化一个数组,在code line中把当前行的line.width加进去就行了。
但是要读取下一行,就没有提供这种方法了。
翻阅官方文档的执行顺序可以知道,在执行完所有的code once之后,会按顺序扫描所有的待处理行,如果是应该被执行模板的行(特效栏为空且非注释行|特效栏为karaoke),执行所有匹配的code line和template line
也就是说,模板执行是按待处理行出现的顺序执行的,例如我们有这几行:
- Comment: 0,0:02:09.29,0:02:12.22,OP-JP3,,0,0,0,karaoke,これから何回も何回も何回も
- Comment: 0,0:02:12.22,0:02:15.06,OP-JP3,,0,0,0,karaoke,何回も季節は巡る
- Comment: 0,0:02:15.06,0:02:18.20,OP-JP3,,0,0,0,karaoke,そのたび何回も何回も何回も
- Comment: 0,0:02:18.20,0:02:21.03,OP-JP3,,0,0,0,karaoke,君とこの場所に
- Comment: 0,0:02:21.03,0:02:27.01,OP-JP3,,0,0,0,karaoke,月は輝き 星は瞬く
- Comment: 0,0:02:27.01,0:02:32.91,OP-JP3,,0,0,0,karaoke,その身果てるまで照らせるように
复制代码 将OP-JP3复制一遍,再把这几行复制一遍:
- Comment: 0,0:02:09.29,0:02:12.35,OP-JP3_2,,0,0,0,karaoke,これから何回も何回も何回も
- Comment: 0,0:02:09.29,0:02:12.35,OP-JP3_2,,0,0,0,karaoke,これから何回も何回も何回も
- Comment: 0,0:02:12.35,0:02:15.06,OP-JP3_2,,0,0,0,karaoke,何回も季節は巡る
- Comment: 0,0:02:15.06,0:02:18.26,OP-JP3_2,,0,0,0,karaoke,そのたび何回も何回も何回も
- Comment: 0,0:02:18.26,0:02:21.03,OP-JP3_2,,0,0,0,karaoke,君とこの場所に
- Comment: 0,0:02:21.03,0:02:27.01,OP-JP3_2,,0,0,0,karaoke,月は輝き 星は瞬く
- Comment: 0,0:02:27.01,0:02:32.91,OP-JP3_2,,0,0,0,karaoke,その身果てるまで照らせるように
- Comment: 0,0:02:27.01,0:02:32.91,OP-JP3_2,,0,0,0,karaoke,その身果てるまで照らせるように
- Comment: 0,0:02:09.29,0:02:12.22,OP-JP3,,0,0,0,karaoke,これから何回も何回も何回も
- Comment: 0,0:02:12.22,0:02:15.06,OP-JP3,,0,0,0,karaoke,何回も季節は巡る
- Comment: 0,0:02:15.06,0:02:18.20,OP-JP3,,0,0,0,karaoke,そのたび何回も何回も何回も
- Comment: 0,0:02:18.20,0:02:21.03,OP-JP3,,0,0,0,karaoke,君とこの場所に
- Comment: 0,0:02:21.03,0:02:27.01,OP-JP3,,0,0,0,karaoke,月は輝き 星は瞬く
- Comment: 0,0:02:27.01,0:02:32.91,OP-JP3,,0,0,0,karaoke,その身果てるまで照らせるように
复制代码 于是,在执行模板的过程中,就会先执行上面 OP-JP3_2 的模板,再执行下面 OP-JP3 的模板。
上面的 OP-JP3_2 不写template,只写code把自己的宽度存进去即可,下面的 OP-JP3 就可以读取它上下一行的宽度。
这里将头尾两行各复制一遍,是为了更轻松地处理边界情况,即第一行读取上一行的宽度、最后一行读取下一行的宽度,都能读到自身的宽度,这样在相应进行\fscx的时候,就可以自然计算出\fscx100
当然,也可以选择在读取的代码中加if i<=1,if i>=#arrayWidth 来进行处理,这样处理更加低耦合、高内聚,是更好的写法。
那么按照上述思路,我的代码就变成了:
- Comment: 0,0:00:00.00,0:00:00.00,OP-JP3_2,,0,0,0,code,len_3_jp = {}
- Comment: 0,0:00:00.00,0:00:00.00,OP-JP3_2,,0,0,0,code line,table.insert(len_3_jp, line.width)
- Comment: 0,0:00:00.00,0:00:00.00,OP-JP3,,0,0,0,code,i3jp = 1
- Comment: 0,0:00:00.00,0:00:00.00,OP-JP3,,0,0,0,code,function getLen3(mode) local result = len_3_jp[i3jp+mode+1] if mode==1 then i3jp=i3jp+1 end return result end
- Comment: 0,0:00:00.00,0:00:00.00,OP-JP3,,0,0,0,code,function getPercent3(mode) local len1 = getLen3(mode) local len2 = getLen3(mode+1) local lenT = {len1,len2} local perc = (len1+len2)/lenT[1-mode]/2*100 return perc end
- Comment: 0,0:00:00.00,0:00:00.00,OP-JP3,,0,0,0,template line,!restyle('OP-JP2')!{\blur3\an5\pos($lcenter,$lmiddle)\frx90\fscx!getPercent3(-1)!\t(0,120,0.75,\frx0\fscx100)\t(!$ldur-120!,!$ldur!,1.33,\frx-90\fscx!getPercent3(0)!)}
- Comment: 0,0:00:00.00,0:00:00.00,OP-JP3,,0,0,0,,
复制代码 首先用 len_3_jp 存储 OP-JP3_2 每一行的宽度,然后 OP-JP3 就能读取了,指针是 i3_jp
为了减少代码冗余,这里 getLen3 用 mode 来进行区分读取的是上一行还是下一行。在里面给索引的指针+1([i3jp+mode+1])是因为第一行重复了一遍,因此索引的指针应该+1。
下面的 getPercent3 实际模拟的就是一个窗口,读取第 i+mode 行和 i+mode+1 行的宽度计算,因此计算上一行和这一行的平均宽度时,mode=-1,计算这一行和下一行时,mode=0
大概就是如此,写了这么多,也不知道也没有说明白,如有纰漏请指出(
|