forked from unanimated/luaegisub
-
Notifications
You must be signed in to change notification settings - Fork 1
/
import.lua
2062 lines (1870 loc) · 94.9 KB
/
import.lua
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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
script_name="Unimportant"
script_description="Import stuff, number stuff, chapter stuff, replace stuff, do other stuff to stuff."
script_author="unanimated"
script_url1="http://unanimated.xtreemhost.com/ts/import.lua"
script_url2="https://raw.githubusercontent.com/unanimated/luaegisub/master/import.lua"
script_version="2.2"
require "clipboard"
re=require'aegisub.re'
function addtag(tag,text) text=text:gsub("^({\\[^}]-)}","%1"..tag.."}") return text end
function round(num) num=math.floor(num+0.5) return num end
-- IMPORT/EXPORT -------------------------------------------------------------------------------------
function important(subs,sel,act)
aline=subs[act]
atext=aline.text
atags=atext:match("^{(\\[^}]-)}")
if atags==nil then atags="" end
atags=atags:gsub("\\move%([^%)]+%)","")
atxt=atext:gsub("^{\\[^}]-}","")
-- create table from user data (lyrics)
sdata={}
if res.mega=="update lyrics" and res.dat=="" then aegisub.dialog.display({{x=0,y=0,width=1,height=1,class="label",label="No lyrics given."}},{"ok"},{cancel='ok'}) aegisub.cancel()
else
res.dat=res.dat.."\n"
for dataline in res.dat:gmatch("(.-)\n") do
if dataline~="" then table.insert(sdata,dataline) end
end
end
-- user input
sub1=res.rep1
sub2=res.rep2
sub3=res.rep3
zer=res.zeros
rest=res.rest
-- this checks whether the pattern for lines with lyrics was found
songcheck=0
-- paths
scriptpath=aegisub.decode_path("?script")
if script_path=="relative" then path=scriptpath.."\\"..relative_path end
if script_path=="absolute" then path=absolute_path end
-- IMPORT --
if res.mega:match("import") then
noshift=false defect=false keeptxt=false deline=false
-- import-single-sign GUI
if res.mega=="import sign" then
press,reslt=aegisub.dialog.display({
{x=0,y=0,width=1,height=1,class="label",label="File name:"},
{x=0,y=1,width=2,height=1,class="edit",name="signame"},
{x=1,y=0,width=2,height=1,class="dropdown",name="signs",items={"title","eptitle","custom","eyecatch"},value="custom"},
{x=2,y=1,width=1,height=1,class="label",label=".ass"},
{x=0,y=2,width=3,height=1,class="checkbox",name="matchtime",label="keep current line's times",value=true,},
{x=0,y=3,width=3,height=1,class="checkbox",name="keeptext",label="keep current line's text",value=false,},
{x=0,y=4,width=3,height=1,class="checkbox",name="keeptags",label="combine tags (current overrides) ",value=false,},
{x=0,y=5,width=3,height=1,class="checkbox",name="addtags",label="combine tags (imported overrides)",value=false,},
{x=0,y=6,width=3,height=1,class="checkbox",name="noshift",label="don't shift times (import as is)",value=false,},
{x=0,y=7,width=3,height=1,class="checkbox",name="deline",label="delete original line",value=false,},
},{"OK","Cancel"},{ok='OK',close='Cancel'})
if press=="Cancel" then aegisub.cancel() end
if reslt.signs=="custom" then signame=reslt.signame else signame=reslt.signs end
noshift=reslt.noshift keeptxt=reslt.keeptext deline=reslt.deline
keeptags=reslt.keeptags addtags=reslt.addtags
end
-- read signs.ass
if res.mega=="import signs" then
file=io.open(path.."signs.ass")
if file==nil then aegisub.dialog.display({{x=0,y=0,width=1,height=1,class="label",label=path.."signs.ass\nNo such file."}},{"ok"},{cancel='ok'}) aegisub.cancel() end
signs=file:read("*all")
io.close(file)
end
-- sort out if using OP, ED, signs, or whatever .ass and read the file
songtype=res.mega:match("import (%a+)")
if songtype=="sign" then songtype=signame end
file=io.open(path..songtype..".ass")
if file==nil then aegisub.dialog.display({{x=0,y=0,width=1,height=1,class="label",label=path..songtype..".ass\nNo such file."}},{"ok"},{cancel='ok'}) aegisub.cancel() end
song=file:read("*all")
io.close(file)
-- cleanup useless stuff
song=song:gsub("^.-(Dialogue:)","%1")
song=song.."\n"
song=song:gsub("\n\n$","\n")
song=song:gsub("%[[^%]]-%]\n","\n")
-- make table out of lines
slines={}
for sline in song:gmatch("(.-)\n") do
if sline~="" then table.insert(slines,sline) end
end
-- save (some) current line properties
btext=atext
basetime=aline.start_time
basend=aline.end_time
basestyle=aline.style
baselayer=aline.layer
-- import-signs list and GUI
if res.mega=="import signs" then
-- make a table of signs in signs.ass
signlist={}
signlistxt=""
for x=1,#slines do
efct=slines[x]:match("%a+: %d+,[^,]-,[^,]-,[^,]-,[^,]-,[^,]-,[^,]-,[^,]-(,[^,]-,).*")
--aegisub.log("\n efct "..efct)
esfct=esc(efct)
if not signlistxt:match(esfct) then signlistxt=signlistxt..efct end
end
for sn in signlistxt:gmatch(",([^,]-),") do table.insert(signlist,sn) end
-- import-signs GUI
button,reslt=aegisub.dialog.display({
{x=0,y=0,width=1,height=1,class="label",label="Choose a sign to import:"},
{x=0,y=1,width=1,height=1,class="dropdown",name="impsign",items=signlist,value=signlist[1]},
{x=0,y=2,width=1,height=1,class="checkbox",name="matchtime",label="keep current line's times",value=true,},
{x=0,y=3,width=1,height=1,class="checkbox",name="keeptext",label="keep current line's text",value=false,},
{x=0,y=4,width=1,height=1,class="checkbox",name="keeptags",label="combine tags (current overrides) ",value=false,},
{x=0,y=5,width=1,height=1,class="checkbox",name="addtags",label="combine tags (imported overrides)",value=false,},
{x=0,y=6,width=1,height=1,class="checkbox",name="noshift",label="don't shift times (import as is)",value=false,},
{x=0,y=7,width=1,height=1,class="checkbox",name="defect",label="delete 'effect'",value=false,},
{x=0,y=8,width=1,height=1,class="checkbox",name="deline",label="delete original line",value=false,},
},{"OK","Cancel"},{ok='OK',close='Cancel'})
if button=="Cancel" then aegisub.cancel() end
if button=="OK" then whatsign=reslt.impsign end
noshift=reslt.noshift defect=reslt.defect keeptxt=reslt.keeptext deline=reslt.deline
keeptags=reslt.keeptags addtags=reslt.addtags
-- nuke lines for the other signs
for x=#slines,1,-1 do
efct=slines[x]:match("%a+: %d+,[^,]-,[^,]-,[^,]-,[^,]-,[^,]-,[^,]-,[^,]-,([^,]-),.*")
if efct~=whatsign then table.remove(slines,x) end
end
end
-- check start time of the first line (for overall shifting)
starttime=slines[1]:match("%a+: %d+,([^,]+)")
shiftime=string2time(starttime)
if res.mega:match("sign") and noshift then shiftime=0 end
-- importing lines from whatever .ass
for x=#slines,1,-1 do
local ltype,layer,s_time,e_time,style,actor,margl,margr,margv,eff,txt=slines[x]:match("(%a+): (%d+),([^,]-),([^,]-),([^,]-),([^,]-),([^,]-),([^,]-),([^,]-),([^,]-),(.*)")
l2=aline
if ltype=="Comment" then l2.comment=true else l2.comment=false end
l2.layer=layer
-- timing/shifting depending on settings
if res.mega:match("import sign") and reslt.matchtime then l2.start_time=basetime l2.end_time=basend else
s_time=string2time(s_time)
e_time=string2time(e_time)
if not noshift then s_time=s_time+basetime e_time=e_time+basetime end
l2.start_time=s_time-shiftime
l2.end_time=e_time-shiftime
end
l2.style=style
l2.actor=actor
l2.margin_l=margl
l2.margin_r=margr
l2.margin_t=margv
l2.effect=eff
if defect then l2.effect="" end
l2.text=txt
atext=txt
if keeptxt and actor~="x" then
btext2=btext:gsub("{\\[^}]-}","")
l2.text=l2.text:gsub("^({\\[^}]-}).*","%1"..btext2) atext=btext2
end
if keeptags and actor~="x" then
l2.text=addtag(atags,l2.text)
l2.text=l2.text:gsub("({%*?\\[^}]-})",function(tg) return duplikill(tg) end)
end
if addtags and actor~="x" then
l2.text="{"..atags.."}"..l2.text
l2.text=l2.text:gsub("{(\\[^}]-)}{(\\[^}]-)}","{%1%2}")
:gsub("({%*?\\[^}]-})",function(tg) return duplikill(tg) end)
end
--aegisub.log("\n btext "..btext)
subs.insert(act+1,l2)
end
-- delete line if not keeping
if deline then res.keep=false end
if not res.keep then subs.delete(act) else
-- keep line, restore initial state + comment out
atext=btext aline.comment=true aline.start_time=basetime aline.end_time=basend aline.style=basestyle aline.actor="" aline.effect=""
aline.layer=baselayer aline.text=atext subs[act]=aline
end
end
-- EXPORT --
if res.mega=="export sign" then
exportsign=""
for x, i in ipairs(sel) do
line=subs[i]
text=line.text
if line.effect=="" then aegisub.dialog.display({{class="label",label="Effect must contain name."}},{"OK"},{close='OK'}) aegisub.cancel() end
if x==1 then snam=line.effect end
exportsign=exportsign..line.raw.."\n"
end
press,reslt=aegisub.dialog.display({
{x=0,y=0,width=2,height=1,class="dropdown",name="addsign",
items={"Add to signs.ass","Save to new file:"},value="Add to signs.ass"},
{x=0,y=1,width=2,height=1,class="edit",name="newsign",value=snam},
},{"OK","Cancel"},{ok='OK',close='Cancel'})
if press=="Cancel" then aegisub.cancel() end
if press=="OK" then
newsgn=reslt.newsign:gsub("%.ass$","")
if reslt.addsign=="Add to signs.ass" then file=io.open(path.."signs.ass","a") exportsign="\n"..exportsign end
if reslt.addsign=="Save to new file:" then file=io.open(path..newsgn..".ass","w") end
file:write(exportsign)
file:close()
end
end
-- Update Lyrics
if res.mega=="update lyrics" then
sup1=esc(sub1) sup2=esc(sub2)
for x, i in ipairs(sel) do
progress("Updating Lyrics... "..round(x/#sel)*100 .."%")
local line=subs[i]
local text=subs[i].text
songlyr=sdata
if line.style:match(rest) then stylecheck=1 else stylecheck=0 end
if res.restr and stylecheck==0 then pass=0 else pass=1 end
if res.field=="actor" then marker=line.actor
elseif res.field=="effect" then marker=line.effect end
denumber=marker:gsub("%d","")
-- marked lines
if marker:match(sup1.."%d+"..sup2) and denumber==sub1..sub2 and pass==1 then
index=tonumber(marker:match(sup1.."(%d+)"..sup2))
puretext=text:gsub("{%*?\\[^}]-}","")
lastag=text:match("({\\[^}]-}).$")
if songlyr[index]~=nil and songlyr[index]~=puretext then
text=text:gsub("^({\\[^}]-}).*","%1"..songlyr[index])
if not text:match("^{\\[^}]-}") then text=songlyr[index] end
end
songcheck=1
if songlyr[index]~=puretext then
if lastag~=nil then text=text:gsub("(.)$",lastag.."%1") end
change=" (Changed)"
else change=""
end
aegisub.log("\nupdate: "..puretext.." --> "..songlyr[index]..change)
end
line.text=text
subs[i]=line
end
end
if res.mega=="update lyrics" and songcheck==0 then press,reslt=aegisub.dialog.display({{x=0,y=0,width=1,height=1,class="label",label="The "..res.field.." field of selected lines doesn't match given pattern \""..sub1.."#"..sub2.."\".\n(Or style pattern wasn't matched if restriction enabled.)\n#=number sequence"}},{"ok"},{cancel='ok'}) end
noshift=nil defect=nil keeptxt=nil deline=nil keeptags=nil addtags=nil
end
-- NUMBERS -------------------------------------------------------------------------------------
function numbers(subs,sel)
z=zer:len()
if sub3:match("[,/;]") then startn,int=sub3:match("(%d+)[,/;](%d+)") else startn=sub3:gsub("%[.-%]","") int=1 end
if sub3:match("%[") then numcycle=tonumber(sub3:match("%[(%d+)%]")) else numcycle=0 end
if sub3=="" then startn=1 end
startn=tonumber(startn)
if startn==nil or numcycle>0 and startn>numcycle then
aegisub.dialog.display({{class="label",label="Wrong parameters."}},{"OK"},{close='OK'})
aegisub.cancel()
end
for i=1,#sel do
line=subs[sel[i]]
text=subs[sel[i]].text
if res.modzero=="number lines" then
progress("Numbering... "..round(i/#sel)*100 .."%")
index=i
count=math.ceil(index/int)+(startn-1)
if numcycle>0 and count>numcycle then repeat count=count-(numcycle-startn+1) until count<=numcycle end
count=tostring(count)
if z>count:len() then repeat count="0"..count until z==count:len() end
number=sub1..count..sub2
if res.field=="actor" then line.actor=number end
if res.field=="effect" then line.effect=number end
if res.field=="layer" then line.layer=count end
end
if res.modzero=="add to marker" then
progress("Adding... "..round(i/#sel)*100 .."%")
if res.field=="actor" then line.actor=sub1..line.actor..sub2
elseif res.field=="effect" then line.effect=sub1..line.effect..sub2
elseif res.field=="text" then text=sub1..text..sub2
end
end
line.text=text
subs[sel[i]]=line
end
end
-- CHAPTERS -------------------------------------------------------------------------------------
function chopters(subs,sel)
if res.marker=="effect" and res.nam=="effect" then
aegisub.dialog.display({{class="label",label="Error. Both marker and name cannot be 'effect'."}},{"OK"},{close='OK'}) aegisub.cancel()
end
if res.chmark then
if res.lang~="" then kap=res.lang else kap=res.chap end
for x, i in ipairs(sel) do
line=subs[i]
text=line.text
if res.marker=="actor" then line.actor="chptr" end
if res.marker=="effect" then line.effect="chptr" end
if res.marker=="comment" then text=text.."{chptr}" end
if res.nam=="effect" then line.effect=kap end
if res.nam=="comment" then text="{"..kap.."}"..text end
line.text=text
subs[i]=line
end
else
euid=2013
chptrs={}
subchptrs={}
if res.lang=="" then clang="eng" else clang=res.lang end
for i=1, #subs do
if subs[i].class == "info" then
if subs[i].key=="Video File" then videoname=subs[i].value videoname=videoname:gsub("%.mkv","") end
end
if subs[i].class == "dialogue" then
local line=subs[i]
local text=subs[i].text
local actor=line.actor
local effect=line.effect
local start=line.start_time
if text:match("{[Cc]hapter}") or text:match("{[Cc]hptr}") or text:match("{[Cc]hap}") then comment="chapter" else comment="" end
if res.marker=="actor" then marker=actor:lower() end
if res.marker=="effect" then marker=effect:lower() end
if res.marker=="comment" then marker=comment:lower() end
if marker=="chapter" or marker=="chptr" or marker=="chap" then
if res.nam=="comment" then
name=text:match("^{([^}]*)}")
name=name:gsub(" [Ff]irst [Ff]rame","")
name=name:gsub(" [Ss]tart","")
name=name:gsub("part a","Part A")
name=name:gsub("part b","Part B")
name=name:gsub("preview","Preview")
else
name=effect
end
if name:match("::") then main,subname=name:match("(.+)::(.+)") sub=1
else sub=0
end
lineid=start+2013
timecode=math.floor(start/1000)
tc1=math.floor(timecode/60)
tc2=timecode%60
tc3=start%1000
tc4="00"
if tc2==60 then tc2=0 tc1=tc1+1 end
if tc1>119 then tc1=tc1-120 tc4="02" end
if tc1>59 then tc1=tc1-60 tc4="01" end
if tc1<10 then tc1="0"..tc1 end
if tc2<10 then tc2="0"..tc2 end
if tc3<100 then tc3="0"..tc3 end
linetime=tc4..":"..tc1..":"..tc2.."."..tc3
if linetime=="00:00:00.00" then linetime="00:00:00.033" end
if sub==0 then
cur_chptr={id=lineid,name=name,tim=linetime}
table.insert(chptrs,cur_chptr)
else
cur_chptr={id=lineid,subname=subname,tim=linetime,main=main}
table.insert(subchptrs,cur_chptr)
end
end
if line.style=="Default" then euid=euid+text:len() end
end
end
-- subchapters
subchapters={}
for c=1,#subchptrs do
local ch=subchptrs[c]
ch_main=ch.main
ch_uid=ch.id
ch_name=ch.subname
ch_time=ch.tim
schapter=" <ChapterAtom>\n <ChapterDisplay>\n <ChapterString>"..ch_name.."</ChapterString>\n <ChapterLanguage>"..clang.."</ChapterLanguage>\n </ChapterDisplay>\n <ChapterUID>"..ch_uid.."</ChapterUID>\n <ChapterTimeStart>"..ch_time.."</ChapterTimeStart>\n <ChapterFlagHidden>0</ChapterFlagHidden>\n <ChapterFlagEnabled>1</ChapterFlagEnabled>\n </ChapterAtom>\n"
subchapter={main=ch_main,chap=schapter}
table.insert(subchapters,subchapter)
end
-- chapters
insert_chapters=""
if res.intro then
insert_chapters=" <ChapterAtom>\n <ChapterUID>"..#subs.."</ChapterUID>\n <ChapterFlagHidden>0</ChapterFlagHidden>\n <ChapterFlagEnabled>1</ChapterFlagEnabled>\n <ChapterDisplay>\n <ChapterString>Intro</ChapterString>\n <ChapterLanguage>"..clang.."</ChapterLanguage>\n </ChapterDisplay>\n <ChapterTimeStart>00:00:00.033</ChapterTimeStart>\n </ChapterAtom>\n"
end
table.sort(chptrs,function(a,b) return a.tim<b.tim end)
for c=1,#chptrs do
local ch=chptrs[c]
ch_uid=ch.id
ch_name=ch.name
ch_time=ch.tim
local subchaps=""
for c=1,#subchapters do
local subc=subchapters[c]
if subc.main==ch_name then subchaps=subchaps..subc.chap end
end
chapter=" <ChapterAtom>\n <ChapterUID>"..ch_uid.."</ChapterUID>\n <ChapterFlagHidden>0</ChapterFlagHidden>\n <ChapterFlagEnabled>1</ChapterFlagEnabled>\n <ChapterDisplay>\n <ChapterString>"..ch_name.."</ChapterString>\n <ChapterLanguage>"..clang.."</ChapterLanguage>\n </ChapterDisplay>\n"..subchaps.." <ChapterTimeStart>"..ch_time.."</ChapterTimeStart>\n </ChapterAtom>\n"
insert_chapters=insert_chapters..chapter
end
chapters="<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n<Chapters>\n <EditionEntry>\n <EditionFlagHidden>0</EditionFlagHidden>\n <EditionFlagDefault>0</EditionFlagDefault>\n <EditionUID>"..euid.."</EditionUID>\n"..insert_chapters.." </EditionEntry>\n</Chapters>"
chdialog=
{{x=0,y=0,width=35,height=1,class="label",label="Text to export:"},
{x=0,y=1,width=35,height=20,class="textbox",name="copytext",value=chapters},
{x=0,y=21,width=35,height=1,class="label",label="File will be saved in the same folder as the .ass file."},}
pressed,reslt=aegisub.dialog.display(chdialog,{"Save xml file","Cancel","Copy to clipboard",},{cancel='Cancel'})
if pressed=="Copy to clipboard" then clipboard.set(chapters) end
if pressed=="Save xml file" then
scriptpath=aegisub.decode_path("?script")
scriptname=aegisub.file_name()
scriptname=scriptname:gsub("%.ass","")
if ch_script_path=="relative" then path=scriptpath.."\\"..relative_path end
if ch_script_path=="absolute" then path=absolute_path end
if res.sav=="script" then filename=scriptname else filename=videoname end
local file=io.open(path.."\\"..filename..".xml", "w")
file:write(chapters)
file:close()
end
end
end
-- STUFF -------------------------------------------------------------------------------------
function stuff(subs,sel)
repl=0
data={} raw=res.dat.."\n"
for dataline in raw:gmatch("(.-)\n") do table.insert(data,dataline) end
-- DATES GUI --
if res.stuff=="format dates" then
dategui=
{{x=0,y=0,class="dropdown",name="date",value="January 1st",items={"January 1","January 1st","1st of January","1st January"}},
{x=1,y=0,class="checkbox",name="log",label="log",value=false,}}
pres,rez=aegisub.dialog.display(dategui,{"OK","Cancel"},{ok='OK',close='Cancel'})
if pres=="Cancel" then aegisub.cancel() end
datelog=""
end
-- EXPLODE GUI --
if res.stuff=="explode" then
-- remember values
if exploded then
exx=expl_dist_x exy=expl_dist_y htype=ex_hor vtype=ex_ver expropx=xprop expropy=yprop exf=exfad cfad=cfade
exinvx=xinv exinvy=yinv implo=implode exquence=exseq exkom=excom seqinv=invseq seqpercent=seqpc rmmbr=exremember
else
exx=0 exy=0 htype="all" vtype="all" expropx=false expropy=false exf=0 cfad=0 exinvx=false exinvy=false
implo=false exquence=false exkom=false seqinv=false seqpercent=100 rmmbr=false
end
explodegui={
{x=0,y=0,class="label",label="Horizontal distance: "},
{x=1,y=0,class="floatedit",name="edistx",value=exx,hint="Maximum horizontal distance for move"},
{x=0,y=1,class="label",label="Vertical distance: "},
{x=1,y=1,class="floatedit",name="edisty",value=exy,hint="Maximum vertical distance for move"},
{x=2,y=0,class="label",label="direction: "},
{x=3,y=0,class="dropdown",name="hortype",value=htype,items={"only left","mostly left","all","mostly right","only right"}},
{x=4,y=0,class="checkbox",name="xprop",label="proportional",value=expropx,hint="Uniform move rather than random"},
{x=5,y=0,class="checkbox",name="xinv",label="inverse",value=exinvx,hint="Uniform move in the other direction"},
{x=2,y=1,class="label",label="direction: "},
{x=3,y=1,class="dropdown",name="vertype",value=vtype,items={"only up","mostly up","all","mostly down","only down"}},
{x=4,y=1,class="checkbox",name="yprop",label="proportional",value=expropy,hint="Uniform move rather than random"},
{x=5,y=1,class="checkbox",name="yinv",label="inverse",value=exinvy,hint="Uniform move in the other direction"},
{x=0,y=2,class="checkbox",name="ecfo",label="Custom fade:",hint="Default is line length",value=cfad},
{x=1,y=2,class="floatedit",name="exfad",value=exf},
{x=2,y=2,class="checkbox",name="exseq",label="sequence",value=exquence,hint="move in a sequence instead of all at the same time"},
{x=3,y=2,class="floatedit",name="seqpc",value=seqpercent,step=nil,min=1,max=100,hint="how much time should the sequence take up"},
{x=4,y=2,class="label",label="% of move"},
{x=5,y=2,class="checkbox",name="invseq",label="inverse",value=seqinv,hint="inverse sequence"},
{x=0,y=3,class="checkbox",name="impl",label="Implode",value=implo},
{x=1,y=3,class="checkbox",name="rem",label="Same for all lines",value=rmmbr,hint="use only for layered lines with the same text"},
{x=3,y=3,class="checkbox",name="excom",label="Leave original line commented out",value=exkom,width=3},
}
pres,rez=aegisub.dialog.display(explodegui,{"OK","Cancel"},{ok='OK',close='Cancel'})
if pres=="Cancel" then aegisub.cancel() end
expl_dist_x=rez.edistx expl_dist_y=rez.edisty
exfad=rez.exfad cfade=rez.ecfo
ex_hor=rez.hortype ex_ver=rez.vertype
xprop=rez.xprop yprop=rez.yprop
xinv=rez.xinv yinv=rez.yinv
implode=rez.impl exseq=rez.exseq
seqpc=round(rez.seqpc) invseq=rez.invseq
exremember=rez.rem excom=rez.excom
exploded=true
end
-- Randomized Transforms GUI --
if res.stuff=="randomized transforms" then
rine=subs[sel[1]]
durone=rine.end_time-rine.start_time
rtgui={
{x=0,y=0,class="checkbox",name="rtfad",label="Random Fade",width=2,value=true},
{x=0,y=1,class="checkbox",name="rtdur",label="Random Duration",width=2,value=true},
{x=2,y=0,class="label",label="Min: "},
{x=2,y=1,class="label",label="Max: "},
{x=3,y=0,class="floatedit",name="minfad",width=1,value=math.floor(durone/5),min=0},
{x=3,y=1,class="floatedit",name="maxfad",width=1,value=durone},
{x=4,y=0,class="checkbox",name="rtin",label="Fade In",width=3,value=false,hint="In instead of Out"},
{x=4,y=1,class="checkbox",name="maxisdur",label="Max = Current Duration",width=4,value=true,hint="The maximum will be the duration of each selected line"},
{x=0,y=3,class="label",label="Transform"},
{x=1,y=3,class="dropdown",name="rttag",value="blur",
items={"blur","bord","shad","fs","fsp","fscx","fscy","fax","fay","frz","frx","fry","xbord","ybord","xshad","yshad"}},
{x=2,y=3,class="label",label="Min: "},
{x=4,y=3,class="label",label=" Max: "},
{x=3,y=3,class="floatedit",name="mintfn",width=1,value=0,hint="Minimum value for a given tag"},
{x=5,y=3,class="floatedit",name="maxtfn",width=3,value=0,hint="Maximum value for a given tag"},
{x=0,y=4,class="label",width=2,label="Colour Transform"},
{x=2,y=4,class="label",label="Max: "},
{x=3,y=4,class="floatedit",name="rtmaxc",value=100,min=1,max=100,hint="Maximum % of colour change.\nColour tag must be present. Otherwise set to 100%."},
{x=4,y=4,class="label",label="%"},
{x=5,y=4,class="checkbox",name="rtc1",label="\\c ",value=true},
{x=6,y=4,class="checkbox",name="rtc3",label="\\3c ",value=false},
{x=7,y=4,class="checkbox",name="rtc4",label="\\4c ",value=false},
{x=0,y=5,class="checkbox",name="rtacc",label="Use Acceleration",width=2,value=false},
{x=2,y=5,class="label",label="Min: "},
{x=3,y=5,class="floatedit",name="minacc",width=1,value=1,min=0},
{x=4,y=5,class="label",label=" Max:"},
{x=5,y=5,class="floatedit",name="maxacc",width=3,value=1,min=0},
{x=0,y=6,class="checkbox",name="rtmx",label="Random Move X",width=2,value=false},
{x=2,y=6,class="label",label="Min: "},
{x=3,y=6,class="floatedit",name="minmx",width=1,value=0},
{x=4,y=6,class="label",label=" Max:"},
{x=5,y=6,class="floatedit",name="maxmx",width=3,value=0},
{x=0,y=7,class="checkbox",name="rtmy",label="Random Move Y",width=2,value=false},
{x=2,y=7,class="label",label="Min: "},
{x=3,y=7,class="floatedit",name="minmy",width=1,value=0},
{x=4,y=7,class="label",label=" Max:"},
{x=5,y=7,class="floatedit",name="maxmy",width=3,value=0},
}
if rtremember then
for key,val in ipairs(rtgui) do
if val.class~="label" then val.value=rez[val.name] end
end
end
rtchoice={"Fade/Duration","Number Transform","Colour Transform","Help","Cancel"}
rthlp={"Fade/Duration","Number Transform","Colour Transform","Cancel"}
pres,rez=aegisub.dialog.display(rtgui,rtchoice,{ok='Fade/Duration',close='Cancel'})
if pres=="Help" then
rthelp={x=0,y=8,width=8,height=4,class="textbox",value="This is supposed to be used after 'split into letters' or with gradients.\n\nFade/Duration Example: Min: 500, Max: 2000.\nA random number between those is generated for each line, let's say 850.\nThis line's duration will be 850ms, and it will have a 850ms fade out.\n\nNumber Transform Example: Blur, Min: 0.6, Max: 2.5\nRandom number generated: 1.7. Line will have: \\t(\\blur1.7)\n\nRandom Colour Transform creates transforms to random colours. \nMax % transform limits how much the colour can change.\n\nAccel works with either transform function.\n\nRandom Move works as an additional option with any function.\nIt can be used on its own if you uncheck other stuff. Works with Fade In."}
table.insert(rtgui,rthelp)
pres,rez=aegisub.dialog.display(rtgui,rthlp,{ok='Fade/Duration',close='Cancel'})
end
if pres=="Cancel" then aegisub.cancel() end
if pres=="Fade/Duration" then RTM="FD" end
if pres=="Number Transform" then RTM="NT" end
if pres=="Colour Transform" then RTM="CT" end
rtremember=true
RTF=rez.rtfad RTD=rez.rtdur
MnF=rez.minfad MxF=rez.maxfad
RTin=rez.rtin RTMax=rez.maxisdur
RTT=rez.rttag MnT=rez.mintfn MxT=rez.maxtfn
RTA=rez.rtacc MnA=rez.minacc MxA=rez.maxacc
MnX=rez.minmx MxX=rez.maxmx MnY=rez.minmy MxY=rez.maxmy
MxC=round(rez.rtmaxc*255/100)
rtcol={}
if rez.rtc1 then table.insert(rtcol,1) end
if rez.rtc3 then table.insert(rtcol,3) end
if rez.rtc4 then table.insert(rtcol,4) end
end
-- Clone Clip GUI --
if res.stuff=="clone clip" then
if clone_h~=nil then cchc=clone_h else cchc=1 end
if clone_v~=nil then ccvc=clone_v else ccvc=1 end
if dist_h~=nil then cchd=dist_h else cchd=0 end
if dist_v~=nil then ccvd=dist_v else ccvd=0 end
ccgui={
{x=0,y=0,class="label",label="Horizontal distance: "},
{x=1,y=0,class="floatedit",name="hdist",value=cchd},
{x=0,y=1,class="label",label="Horizontal clones: "},
{x=1,y=1,class="floatedit",name="hclone",value=cchc,step=1,min=1},
{x=0,y=2,class="label",label="Vertical distance: "},
{x=1,y=2,class="floatedit",name="vdist",value=ccvd},
{x=0,y=3,class="label",label="Vertical clones: "},
{x=1,y=3,class="floatedit",name="vclone",value=ccvc,step=1,min=1},
}
pres,rez=aegisub.dialog.display(ccgui,{"OK","Cancel"},{ok='OK',close='Cancel'})
if pres=="Cancel" then aegisub.cancel() end
clone_h=rez.hclone dist_h=rez.hdist
clone_v=rez.vclone dist_v=rez.vdist
end
-- DISSOLVE GUI ---------------------------------------------------------------------------------------------
if res.stuff=="dissolve text" then
if dlast then ddistance=v_dist ddlines=dlines dshape=shape dalter=alternate dissin=disin otherd=otherdis v2direction=v2d
else ddistance=10 ddlines=10 dshape="square" dalter=true dissin=false otherd=false v2direction="randomly"
end
dissgui={
{x=0,y=0,class="label",label="Distance between points: "},
{x=1,y=0,class="floatedit",name="ddist",value=ddistance,min=4,step=2},
{x=0,y=1,class="label",label="Shape of clips:"},
{x=1,y=1,class="dropdown",name="shape",items={"square","square 2","diamond","triangle 1","triangle 2","hexagon","wave/hexagram","vertical lines","horizontal lines"},value=dshape},
{x=0,y=2,class="checkbox",name="alt",label="Shift even rows (all except vertical/horizontal lines)",value=dalter,width=2},
{x=0,y=3,class="checkbox",name="disin",label="Reverse effect (fade in rather than out)",value=dissin,width=2},
{x=0,y=4,class="checkbox",name="otherdiss",label="Dissolve v2. ... Lines:",value=otherd,hint="only square, diamond, vertical lines"},
{x=1,y=4,class="floatedit",name="modlines",value=ddlines,min=6,step=2},
{x=0,y=5,class="label",label=" Dissolve v2: Dissolve"},
{x=1,y=5,class="dropdown",name="v2dir",items={"randomly","from top","from bottom","from left","from right"},value=v2direction},
}
pres,rez=aegisub.dialog.display(dissgui,{"OK","What Is This","Cancel"},{ok='OK',close='Cancel'})
if pres=="What Is This" then
dishelp={x=0,y=6,width=10,height=8,class="textbox",value="The script can either automatically draw a clip around the text,\nor you can make your own clip.\nThe automation only considers position, alignment, and scaling,\nso for anything more complex, make your own.\nYou can just try it without a clip,\nand if the result isn't right, draw a clip first. (Only 4 points!)\n\n'Distance between points' will be the distance between the\nstarting points of all the little iclips.\nLess Distance = more clips = more lag,\nso use the lowest values only for smaller text.\nYou can run this on one line or fbf lines.\nThe ideal 'fade' is as many frames as the given Distance.\nThat way the clips grow by 1 pixel per frame.\nAny other way doesn't look too good,\nbut you can apply Distance 10 over 20 lines\nand have each 2 consecutive lines identical.\nMore Distance than lines doesn't look so bad, and the effect is 'faster'.\nIf you apply this to 1 line, the line will be split to have the effect applied to as many frames as the Distance is. (This is preferred.)\nFor hexagon, the actual distance is twice the input. (It grows faster.)\n\nThe shapes should be self-explanatory, so just experiment.\n\n'Shift even rows' means that even rows will have an offset\nfrom odd rows by half of the given Distance.\nNot checking this will have a slightly different and less regular effect,\nthough it also depends on the shape. Again, experiment.\n\nIf you need to apply this to several layers, you have to do it one by one. The GUI remembers last values. But more layers = more lag.\n\nAll kinds of things can make this lag, so use carefully.\nLines are less laggy than other shapes.\nHorizontal lines are the least laggy. (Unless you have vertical text.)\n\nFor longer fades, use more Distance.\nThis works great with vertical lines but is pretty useless with horizontal.\n\n'Reverse effect' is like fade in while the default is fade out.\nWith one line selected, it applies to the first frames.\n\n'Dissolve v2' is a different kind of dissolve\nand only works with square, diamond, and vertical lines.\nLine count for this is independent on distance between points.\nIt's the only effect that allows Distance 4.\n'Shift even rows' has no effect here.\n\nYou can set a direction of Dissolve v2.\nObviously top and bottom is nonsense for vertical lines.\n'Reverse effect' reverses the direction too, so choose the opposite.\n\nThere may be weird results with some combinations of settings.\nThere may be some malfunctions, as the script is pretty complex.\nSome of them -might- be fixed by reloading automation scripts.\nMakes no sense with \\move. Nukes \\fad.\n\nThere are some fun side effects.\nFor example with 'square 2' and 'Shift even rows',\nyou get a brick wall on the last frame."}
table.insert(dissgui,dishelp)
pres,rez=aegisub.dialog.display(dissgui,{"OK","Cancel"},{ok='OK',close='Cancel'})
end
if pres=="Cancel" then aegisub.cancel() end
dlast=true
v_dist=rez.ddist
shape=rez.shape
alternate=rez.alt
disin=rez.disin
otherdis=rez.otherdiss
dlines=rez.modlines
v2d=rez.v2dir
dis2=false
if v2d=="randomly" then dir=5 end
if v2d=="from top" then dir=8 end
if v2d=="from bottom" then dir=2 end
if v2d=="from left" then dir=4 end
if v2d=="from right" then dir=6 end
if not otherdis and v_dist==4 then
aegisub.dialog.display({{class="label",label="Distance 4 is only allowed for square mod. Changing to 6."}},{"OK"},{close='OK'})
v_dist=6
end
if otherdis then
if shape=="square" or shape=="diamond" or shape=="vertical lines" then dis2=true else dis2=false end
if shape=="square" then alternate=false end
if shape=="diamond" then alternate=true end
end
if dis2 and #sel==1 then linez=dlines
elseif dis2 and #sel>1 then linez=#sel
else linez=v_dist end
-- DISSOLVE create lines if only one selected ------------------------
if #sel==1 then
rine=subs[sel[1]]
rine.text=rine.text:gsub("\\fad%(.-%)","")
start=rine.start_time endt=rine.end_time
startf=ms2fr(start) endf=ms2fr(endt)
lframes=ms2fr(endt-start)
if lframes<linez then
aegisub.dialog.display({{class="label",label="Line must be at least "..linez.." frames long."}},
{"OK"},{close='OK'}) aegisub.cancel()
end
if disin then
for l=1,linez do
rine.start_time=fr2ms(startf+l-1)
rine.end_time=fr2ms(startf+l)
subs.insert(sel[1],rine)
sel[1]=sel[1]+1
end
for s=1,linez do table.insert(sel,sel[1]-s) end
table.sort(sel)
rine.start_time=fr2ms(startf+linez)
rine.end_time=endt
subs[sel[#sel]]=rine
table.remove(sel,#sel)
else
for l=1,linez do
rine.start_time=fr2ms(endf-l)
rine.end_time=fr2ms(endf-l+1)
subs.insert(sel[1]+1,rine)
end
for s=1,linez do table.insert(sel,sel[1]+s) end
rine.start_time=start
rine.end_time=fr2ms(endf-linez)
subs[sel[1]]=rine
table.remove(sel,1)
end
end
if disin then table.sort(sel,function(a,b) return a>b end) end
-- DISSOLVE Initial Calculations -----------------------------------------------------------------
line=subs[sel[1]]
text=line.text
text=text:gsub("\\clip%(([%d%.%-]+),([%d%.%-]+),([%d%.%-]+),([%d%.%-]+)%)",function(a,b,c,d)
a=math.floor(a) b=math.floor(b) c=math.ceil(c) d=math.ceil(d)
return string.format("\\clip(m %d %d l %d %d %d %d %d %d)",a,b,c,b,c,d,a,d) end)
-- draw clip when no clip present
if not text:match("\\clip") then
styleref=stylechk(subs,line.style)
vis=text:gsub("{[^}]-}","")
width,height,descent,ext_lead=aegisub.text_extents(styleref,vis)
bord=text:match("\\bord([%d%.]+)") if bord==nil then bord=styleref.outline end
bord=math.ceil(bord)
scx=text:match("\\fscx([%d%.]+)") if scx==nil then scx=styleref.scale_x end scx=scx/100
scy=text:match("\\fscy([%d%.]+)") if scy==nil then scy=styleref.scale_y end scy=scy/100
wi=round(width)
he=round(height)
text2=getpos(subs,text)
if not text:match("\\pos") then text=text2 end
xx,yy=text:match("\\pos%(([%d%.%-]+),([%d%.%-]+)%)")
if h_al=="left" then cx1=xx cx2=xx+wi*scx end
if h_al=="right" then cx1=xx-wi*scx cx2=xx end
if h_al=="mid" then cx1=xx-wi/2*scx cx2=xx+wi/2*scx end
if v_al=="top" then cy1=yy cy2=yy+he*scy end
if v_al=="bottom" then cy1=yy-he*scy cy2=yy end
if v_al=="mid" then cy1=yy-he/2*scy cy2=yy+he/2*scy end
cx1=math.floor(cx1-bord) cx2=math.ceil(cx2+bord)
cy1=math.floor(cy1-bord) cy2=math.ceil(cy2+bord)
text=addtag("\\clip(m "..cx1.." "..cy1.." l "..cx2.." "..cy1.." "..cx2.." "..cy2.." "..cx1.." "..cy2..")",text)
end
-- get outermost clip points even if it's irregular (though it should be fucking regular)
exes={} wais={}
klip=text:match("\\clip%(m [%d%-]+ [%d%-]+ l [%d%-]+ [%d%-]+ [%d%-]+ [%d%-]+ [%d%-]+ [%d%-]+")
for ex,wai in klip:gmatch("([%d%-]+) ([%d%-]+)") do
table.insert(exes,tonumber(ex))
table.insert(wais,tonumber(wai))
end
table.sort(exes) table.sort(wais)
x1=exes[1]-2 x2=exes[4]+2 y1=wais[1]-2 y2=wais[4]+2
width=x2-x1 height=y2-y1
h_dist=2*v_dist
if shape=="hexagon" then h_dist=math.floor(h_dist*2) end
rows=math.ceil(height/v_dist)
rows2=math.ceil(height/v_dist/2)
points=math.ceil(width/h_dist)+1
if shape=="horizontal lines" then vert=2*v_dist rows=math.ceil(rows/2)+1 else vert=v_dist end
if shape:match("triangle") or shape=="wave/hexagram" then rows=rows+1 end
xpoints={}
for w=1,points do point=x1+h_dist*(w-1) table.insert(xpoints,point) end
ypoints={}
for w=1,rows do point=y1+vert*(w-1) table.insert(ypoints,point) end
ypoints2={}
for w=1,rows2 do point=y1+2*v_dist*(w-1) table.insert(ypoints2,point) end
-- this is all centers of individual iclip shapes
allpoints1={}
for w=1,#ypoints do
for z=1,#xpoints do
u=0
if alternate and w%2==0 then u=h_dist/2 else u=0 end -- every even row is shifted by half of h_dist from odd rows
rnum=math.random(2000,6000)
if dir==5 then rindex=rnum end
if dir==8 then rindex=rnum*ypoints[w]^2 end
if dir==4 then rindex=rnum*xpoints[z]^2 end
if dir==2 then rindex=0-rnum*ypoints[w]^2 end
if dir==6 then rindex=0-rnum*xpoints[z]^2 end
point={xpoints[z]+u,ypoints[w],rindex}
table.insert(allpoints1,point)
end
end
allpoints2={}
for w=1,#ypoints2 do
for z=1,#xpoints do
u=0
if alternate and w%2==0 then u=h_dist/2 else u=0 end -- every even row is shifted by half of h_dist from odd rows
rnum=math.random(2000,6000)
if dir==5 then rindex=rnum end
if dir==8 then rindex=rnum*ypoints2[w]^2 end
if dir==4 then rindex=rnum*xpoints[z]^2 end
if dir==2 then rindex=0-rnum*ypoints2[w]^2 end
if dir==6 then rindex=0-rnum*xpoints[z]^2 end
point={xpoints[z]+u,ypoints2[w],rindex}
table.insert(allpoints2,point)
end
end
if dis2 and shape=="square" or shape=="square 2" or shape=="hexagon" then allpoints=allpoints2 else allpoints=allpoints1 end
if dis2 and shape=="vertical lines" then allpoints={}
for w=1,#xpoints do
rnum=math.random(2000,6000)
if dir==4 then rindex=rnum*xpoints[w]^2
elseif dir==6 then rindex=0-rnum*xpoints[w]^2
else rindex=rnum end
table.insert(allpoints,{xpoints[w],0,rindex})
end
end
if dis2 then table.sort(allpoints,function(a,b) return a[3]<b[3] end) end
-- DISSOLVE v2 Calculations ------------------------------------------
if dis2 then d2c=0 fullclip="" dis2tab={} rnd=1 ppl=#allpoints/linez
for w=1,#allpoints do
pt=allpoints[w]
vd=v_dist
if shape=="square" then
krip="m "..pt[1]-vd.." "..pt[2]-vd.." l "..pt[1]+vd.." "..pt[2]-vd.." "..pt[1]+vd.." "..pt[2]+vd.." "..pt[1]-vd.." "..pt[2]+vd.." "
end
if shape=="diamond" then
krip="m "..pt[1].." "..pt[2]-vd.." l "..pt[1]+vd.." "..pt[2].." "..pt[1].." "..pt[2]+vd.." "..pt[1]-vd.." "..pt[2].." "
end
if shape=="vertical lines" then
krip="m "..pt[1]-v_dist.." "..y1.." l "..pt[1]+v_dist.." "..y1.." "..pt[1]+v_dist.." "..y2.." "..pt[1]-v_dist.." "..y2.." "
end
fullclip=fullclip..krip
d2c=d2c+1
if d2c>=math.floor(ppl) and w>=ppl*rnd then d2c=0 rnd=rnd+1 table.insert(dis2tab,fullclip) end
end
end
-- DISSOLVE END --------------------------------------------------------------------
end
if res.stuff:match("replacer") then table.sort(sel,function(a,b) return a>b end) end
-- LINES START HERE ----------------------------------------------------------------------
for i=#sel,1,-1 do
line=subs[sel[i]]
text=line.text
style=line.style
if res.stuff=="save/load" and i==1 then
if savedata==nil then savedata="" end
if res.dat~="" then
savedata=savedata.."\n\n"..res.dat
savedata=savedata
:gsub("^\n\n","")
:gsub("\n\n\n","\n\n")
aegisub.dialog.display({{class="label",label="Data saved.",x=0,y=0,width=20,height=2}},{"OK"},{close='OK'})
else
aegisub.dialog.display({{x=0,y=0,width=50,height=18,class="textbox",name="savetxt",value=savedata},},{"OK"},{close='OK'})
end
end
if res.stuff=="lua replacer" then
lim=sub3:match("^%d+")
if lim==nil then limit=1 else limit=tonumber(lim) end
replicant1=sub1:gsub("\\","\\"):gsub("\\\\","\\")
replicant2=sub2:gsub("\\","\\"):gsub("\\\\","\\")
tk=text
count=0
repeat
text=text:gsub(replicant1,replicant2) count=count+1
until count==limit
if text~=tk then repl=repl+1
if res.log then
r1=replicant1:gsub("%%%(","_L_"):gsub("%%%)","_R_"):gsub("%(",""):gsub("%)",""):gsub("_L_","%%%("):gsub("_R_","%%%)")
for l1 in tk:gmatch(r1) do
aegisub.log("\nOrig: "..l1)
l2=l1:gsub(replicant1,replicant2)
aegisub.log("\nMod: "..l2)
end
end
end
end
if res.stuff=="perl replacer" then
lim=sub3:match("^%d+")
if lim==nil then limit=1 else limit=tonumber(lim) end
replicant1=sub1:gsub("\\","\\"):gsub("\\\\","\\")
replicant2=sub2:gsub("\\","\\"):gsub("\\\\","\\")
tk=text
count=0
repeat
text=re.sub(text,replicant1,replicant2) count=count+1
until count==limit
if text~=tk then repl=repl+1
if res.log then
for r1 in re.gfind(tk,replicant1) do
aegisub.log("\nOrig: "..r1)
r2=re.sub(r1,replicant1,replicant2)
aegisub.log("\nMod: "..r2)
end
end
end
end
if res.stuff=="lua calc" then
lim=sub3:match("^%d+")
if lim==nil then limit=1 else limit=tonumber(lim) end
replicant1=sub1:gsub("\\","\\")
replicant2=sub2:gsub("\\","\\")
replicant1=sub1:gsub("\\\\","\\")
replicant2=sub2:gsub("\\\\","\\")
replicant2="||"..replicant2.."||"
replicant2=replicant2:gsub("%.%.","||")
tk=text
count=0
repeat
text=text:gsub(replicant1,function(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p)
tab1={"a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p"}
tab2={a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p}
r2=replicant2
asd=1
repeat
for r=1,16 do
r2=r2
:gsub(tab1[r].."%*([%d%.]+)",function(num) return tab2[r]*tonumber(num) end)
:gsub(tab1[r].."%/([%d%.]+)",function(num) return tab2[r]/tonumber(num) end)
:gsub(tab1[r].."%+([%d%.]+)",function(num) return tab2[r]+tonumber(num) end)
:gsub(tab1[r].."%-([%d%.]+)",function(num) return tab2[r]-tonumber(num) end)
:gsub("([%d%.]+)%*([%d%.]+)",function(n1,n2) return tonumber(n1)*tonumber(n2) end)
:gsub("([%d%.]+)%/([%d%.]+)",function(n1,n2) return tonumber(n1)/tonumber(n2) end)
:gsub("([%d%.]+)%+([%d%.]+)",function(n1,n2) return tonumber(n1)+tonumber(n2) end)
:gsub("([%d%.]+)%-([%d%.]+)",function(n1,n2) return tonumber(n1)-tonumber(n2) end)
end
for r=1,16 do
if tab2[r]~=nil then
r2=r2:gsub("([|%*%/%+%-])"..tab1[r].."|","%1"..tab2[r].."|")
r2=r2:gsub("%("..tab1[r].."%)","("..tab2[r]..")")
end
end
r2=r2:gsub("round%(([^%)]+)%)",function(num) return math.floor(tonumber(num)+0.5) end)
asd=asd+1
until not r2:match("[%*%/%+%-]") or asd==12
r2=r2:gsub("||","")
return r2 end) count=count+1
until count==limit
if text~=tk then repl=repl+1 end
end
if res.stuff=="add comment" then
text=text.."{"..res.dat.."}"
end
if res.stuff=="add comment line by line" then
kom=data[i]
if kom~=nil then text=text.."{"..kom.."}" end
end
if res.stuff=="make comments visible" then
text=text:gsub("{([^\\}]-)}","%1")
end
if res.stuff=="switch commented/visible" then
text=text
:gsub("\\N","_br_")
:gsub("{([^\\}]-)}","}%1{")
:gsub("^([^{]+)","{%1")
:gsub("([^}]+)$","%1}")
:gsub("([^}])({\\[^}]-})([^{])","%1}%2{%3")
:gsub("^({\\[^}]-})([^{])","%1{%2")
:gsub("([^}])({\\[^}]-})$","%1}%2")
:gsub("{}","")
:gsub("_br_","\\N")
end
if res.stuff=="reverse text" then
tags=text:match("^{\\[^}]-}") if tags==nil then tags="" end
text=text:gsub("{[^}]-}","")
nt=""
for l in text:gmatch(".") do nt=l..nt end
text=tags..nt
end
if res.stuff=="reverse words" then
tags=text:match("^{\\[^}]-}") if tags==nil then tags="" end
text=text:gsub("{[^}]-}","")
nt=""
for l in text:gmatch("[^%s]+") do nt=" "..l..nt end
nt=nt:gsub("^ ","")
text=tags..nt
end