3493 lines
140 KiB
Lua
3493 lines
140 KiB
Lua
-- Hyperdimensional Relocator offers a plethora of functions, focusing primarily on \pos, \move, \org, \clip, and rotations.
|
|
-- Check Help (Space Travel Guide) for detailed description of all functions.
|
|
|
|
script_name="Hyperdimensional Relocator"
|
|
script_description="Advanced metamorphosis of multidimensional coordinates"
|
|
script_author="reanimated"
|
|
script_url="http://unanimated.hostfree.pw/ts/relocator.lua"
|
|
script_version="4.5"
|
|
script_namespace="ua.Relocator"
|
|
|
|
local haveDepCtrl,DependencyControl,depRec=pcall(require,"l0.DependencyControl")
|
|
if haveDepCtrl then
|
|
script_version="4.5.0"
|
|
depRec=DependencyControl{feed="https://raw.githubusercontent.com/unanimated/luaegisub/master/DependencyControl.json"}
|
|
end
|
|
|
|
re=require'aegisub.re'
|
|
|
|
function cuts(subs,sel)
|
|
ADD=aegisub.dialog.display
|
|
ADP=aegisub.decode_path
|
|
ak=aegisub.cancel
|
|
ms2fr=aegisub.frame_from_ms
|
|
fr2ms=aegisub.ms_from_frame
|
|
keyframes=aegisub.keyframes()
|
|
ATAG="{%*?\\[^}]-}"
|
|
STAG="^{\\[^}]-}"
|
|
failures={}
|
|
relocated=0
|
|
seln=#sel
|
|
for i=1,#subs do if subs[i].class=="dialogue" then line0=i-1 break end end
|
|
end
|
|
|
|
function relocator(subs,sel,act)
|
|
cuts(subs,sel)
|
|
Repositioning={"Align X","Align Y","org to fax","clip to fax","clip to frz","clip to reposition","clip2pos fbf","frz+org2pos","horizontal mirror","vertical mirror","numbers","shake","fbf retrack","trampoline","sine loop","shadow layer","shadow repos.","space out letters","warp text","replicate","fbf X <--> Y","track by clip"}
|
|
Bilocator={"transmove","horizontal","vertical","multimove","clip2move","rvrs. move","shiftstart","shiftmove","move to","move clip","randomove","kill times","full times","set times","zig-zag"}
|
|
Morphing={"round numbers","line2fbf","join fbf lines","move v. clip","set origin","calculate origin","transform clip","set rotation","rotate 180","negative rot","spin doctor","vector2rect.","rect.2vector","clip scale","clip2scale fbf","find centre","extend mask","flip mask","adjust drawing","randomask","randomise...","letterbreak","wordbreak","clip info","[un]hide clip"}
|
|
Rounding={"all","pos","move","org","clip","mask"}
|
|
Freezing={"0","5","10","20","45","70","110","135","160","-5","-10","-20","-45","-70","-110","-135","-160"}
|
|
noneg="\\bord\\shad\\xbord\\ybord\\fs\\blur\\be\\fscx\\fscy_bord_shad_xbord_ybord_fs_blur_be_fscx_fscy"
|
|
|
|
hyperconfig={
|
|
{x=12,y=0,width=2,class="label",label="Teleport "},
|
|
{x=12,y=1,width=4,class="floatedit",name="eks",hint="X"},
|
|
{x=12,y=2,width=4,class="floatedit",name="wai",hint="Y"},
|
|
|
|
{x=0,y=0,width=3,class="label",label="&Repositioning Field"},
|
|
{x=0,y=1,width=2,class="dropdown",name="posi",value="clip to frz",items=Repositioning},
|
|
{x=0,y=2,width=2,class="floatedit",name="post",value=0,hint="disPosition\nAlign X/Y; Shake radius; Mirrors centre point;\nShadow layer: shad; Space Out Letters distance; Warp Text distance; fbf retrack accel"},
|
|
{x=0,y=3,class="checkbox",name="first",label="by first",value=true,hint="reference point = first line\n(Align X/Y; fbf X <--> Y, track by clip)"},
|
|
{x=1,y=3,class="checkbox",name="rota",label="rotate",hint="rotate mirrors\nreverse direction for fbf X <--> Y"},
|
|
{x=0,y=4,class="checkbox",name="layers",label="layers",value=true,hint="synchronise for layers\n(shake; fbf retrack)"},
|
|
{x=1,y=4,class="checkbox",name="smo",label="smooth",hint="smoothen shaking/retrack"},
|
|
{x=1,y=5,class="checkbox",name="sca",label="scaling",hint="add scaling to shake"},
|
|
{x=0,y=6,class="label",label=" &Force:"},
|
|
{x=1,y=6,width=3,class="floatedit",name="force",value=0,hint="shake: scaling value\nfbf retrack: smoothening force\njoin fbf lines: # of lines\nclip scale: scale factor\nrandomask: randomness factor"},
|
|
|
|
{x=3,y=0,width=3,class="label",label="Soul &Bilocator"},
|
|
{x=3,y=1,width=2,class="dropdown",name="move",value="transmove",items=Bilocator},
|
|
{x=3,y=2,width=2,class="checkbox",name="keep",label="keep both",hint="keeps both lines for transmove/mirrors"},
|
|
{x=3,y=3,width=4,class="checkbox",name="rotac",label="rotation acceleration",value=true,hint="transmove option"},
|
|
{x=3,y=4,class="checkbox",name="times",label="times",hint="set \\move times\n(transmove; clip2move; shiftmove; move to)"},
|
|
{x=4,y=4,class="checkbox",name="tra",label="\\&t",hint=""},
|
|
{x=3,y=5,width=3,class="checkbox",name="videofr",label="current frame",hint="set relevant timecode\nto current frame\n(shiftstart, shiftmove)"},
|
|
|
|
{x=6,y=0,width=2,class="label",label="&Morphing Grounds"},
|
|
{x=6,y=1,width=2,class="dropdown",name="mod",value="round numbers",items=Morphing},
|
|
{x=6,y=2,class="label",label="round:"},
|
|
{x=7,y=2,class="dropdown",name="rnd",items=Rounding,value="all"},
|
|
{x=7,y=3,class="dropdown",name="rndec",items={"1","0.1","0.01","0.001"},value="1",hint="rounding"},
|
|
{x=7,y=4,class="dropdown",name="freeze",items=Freezing,value="0"},
|
|
{x=6,y=4,class="checkbox",name="frz",label="frz",value=true,hint=""},
|
|
{x=6,y=5,class="checkbox",name="frx",label="frx",hint=""},
|
|
{x=7,y=5,class="checkbox",name="fry",label="fry",hint=""},
|
|
{x=6,y=6,width=2,class="checkbox",name="delfbf",label="delete orig. line",value=true,hint="delete original line for line2fbf"},
|
|
{x=7,y=7,class="checkbox",name="c2fbf",label="clip2fbf",value=true,hint="line2fbf: shift clip along with \\move"},
|
|
{x=3,y=7,class="checkbox",name="why",label="why?",hint="provides information about the success/failure of operations performed"},
|
|
|
|
{x=4,y=7,class="checkbox",name="X",label="X",hint="Apply to X coordinates\n(fbf retrack, track by clip, clip2move)",value=true},
|
|
{x=6,y=7,class="checkbox",name="Y",label="Y",hint="Apply to Y coordinates\n(fbf retrack, track by clip, clip2move)",value=true},
|
|
|
|
{x=8,y=0,width=3,class="label",label="Cloning Laboratory"},
|
|
{x=8,y=1,width=2,class="checkbox",name="cpos",label="\\&posimove",value=true},
|
|
{x=10,y=1,class="checkbox",name="corg",label="\\&org",value=true},
|
|
{x=8,y=2,class="checkbox",name="cclip",label="\\[&i]clip",value=true},
|
|
{x=9,y=2,width=2,class="checkbox",name="ctclip",label="\\t(\\[i]c&lip)",value=true},
|
|
{x=8,y=6,width=4,class="checkbox",name="cre",label="replicate missing tags",value=true,hint="creates tags if they're not present"},
|
|
{x=8,y=3,width=2,class="checkbox",name="stack",label="stack clips",hint="allows stacking of 1 normal\nand 1 vector clip in one line"},
|
|
{x=8,y=5,width=3,class="checkbox",name="copyrot",label="copy rotations",hint="copies frz, frx, and fry"},
|
|
{x=10,y=3,width=3,class="checkbox",name="klipmatch",label="match type",hint="matches clip type (clip/iclip)"},
|
|
{x=8,y=4,width=3,class="checkbox",name="combine",label="combine vectors",hint="vector clips are merged into one\ninstead of replaced"},
|
|
|
|
{x=13,y=3,width=2,class="checkbox",name="tppos",label="pos",value=true},
|
|
{x=13,y=4,width=2,class="checkbox",name="tpmov",label="move",value=true},
|
|
{x=15,y=3,class="checkbox",name="tporg",label="org",value=true},
|
|
{x=15,y=4,class="checkbox",name="tpclip",label="clip",value=true},
|
|
{x=12,y=4,class="checkbox",name="tpc1",label="c1",value=true,hint="affect top left corner of rectangular clip"},
|
|
{x=12,y=5,class="checkbox",name="tpc2",label="c2",value=true,hint="affect bottom right corner of rectangular clip"},
|
|
{x=15,y=5,class="checkbox",name="tpexp",label="exp",hint="expand rectangular clip in opposite directions"},
|
|
{x=13,y=5,width=2,class="checkbox",name="tpmask",label="mask"},
|
|
{x=14,y=0,width=2,class="checkbox",name="warp",label="&Warp",hint="Warped Teleport"},
|
|
{x=12,y=6,width=4,class="checkbox",name="autopos",label="pos with tags missing",value=true,hint="Teleport position when \\pos tags missing"},
|
|
|
|
{x=0,y=7,width=3,class="checkbox",name="space",label="SpaceTravel &Guide",
|
|
hint="The Typesetter's Guide to the Hyperdimensional Relocator."},
|
|
{x=8,y=7,width=2,class="checkbox",name="rpt",label="Repeat",hint="Repeat with last settings (any function)"},
|
|
{x=10,y=7,width=3,class="checkbox",name="save",label="Save config",hint="Save current configuration"},
|
|
{x=13,y=7,width=3,class="label",label="[Incarnation "..script_version.."]"}
|
|
}
|
|
loadconfig()
|
|
if remember then
|
|
for key,val in ipairs(hyperconfig) do
|
|
if val.name=="posi" then val.value=lastpos end
|
|
if val.name=="move" then val.value=lastmove end
|
|
if val.name=="mod" then val.value=lastmod end
|
|
end
|
|
end
|
|
P,res=ADD(hyperconfig,
|
|
{"Po&sitron Cannon","Hyperspace Tra&vel","Met&amorphosis","&Cloning Sequence","Tel&eportation","Disintegrate"},{close='Disintegrate'})
|
|
if P=="Disintegrate" then ak() end
|
|
|
|
if imprint and res.rpt then res=imprint end
|
|
remember=true imprint=res
|
|
lastpos=res.posi lastmove=res.move lastmod=res.mod
|
|
if res.save then saveconfig() ak() end
|
|
|
|
if P=="Po&sitron Cannon" then if res.space then guide(subs,sel) else sel=positron(subs,sel) end end
|
|
if P=="Hyperspace Tra&vel" then
|
|
if res.move=="multimove" then multimove (subs,sel)
|
|
elseif res.move=="randomove" then randomove (subs,sel)
|
|
else bilocator(subs,sel) end
|
|
end
|
|
if P=="Met&amorphosis" then
|
|
aegisub.progress.title(string.format("Morphing..."))
|
|
if res.mod=="line2fbf" then sel=movetofbf(subs,sel)
|
|
elseif res.mod=="transform clip" then transclip(subs,sel,act)
|
|
elseif res.mod=="join fbf lines" then joinfbflines(subs,sel)
|
|
elseif res.mod=="spin doctor" then spindoc(subs,sel)
|
|
else modifier(subs,sel,act) end
|
|
end
|
|
if P=="&Cloning Sequence" then clone(subs,sel) end
|
|
if P=="Tel&eportation" then teleport(subs,sel) end
|
|
summary()
|
|
return sel
|
|
end
|
|
|
|
|
|
|
|
function positron(subs,sel)
|
|
if not ak then cuts(subs,sel) end
|
|
ps=res.post
|
|
shake={} shaker={}
|
|
count=0
|
|
relocated=0
|
|
nsel={} for z,i in ipairs(sel) do table.insert(nsel,i) end
|
|
if res.posi:match("fbf X") then
|
|
XYtab={}
|
|
for z,i in ipairs(sel) do
|
|
line=subs[i]
|
|
text=line.text
|
|
local X,Y=text:match("\\pos%(([%d.-]+),([%d.-]+)%)")
|
|
if not X then t_error("Line #"..i-line0..": Missing \\pos tag.\nAborting.",1) end
|
|
table.insert(XYtab,{x=X,y=Y})
|
|
end
|
|
if res.first then Xref=XYtab[1].x Yref=XYtab[1].y else Xref=XYtab[#XYtab].x Yref=XYtab[#XYtab].y end
|
|
end
|
|
if res.posi=="numbers" then LL=999999999
|
|
for z,i in ipairs(sel) do
|
|
line=subs[i]
|
|
lay=line.layer
|
|
if lay<LL then LL=lay end
|
|
end
|
|
ind=0 PNS={}
|
|
end
|
|
local re_fail
|
|
|
|
-- Replicate GUI
|
|
if res.posi=="replicate" then
|
|
rplGUI={
|
|
{x=0,y=0,width=2,class="label",label="Replicas:"},
|
|
{x=2,y=0,width=3,class="intedit",name="rep",value=repl or 3,min=1,hint="replicas to create"},
|
|
{x=5,y=0,width=2,class="label",label=" (This is excluding the original line)"},
|
|
{x=0,y=1,width=3,class="label",label="Distances for:"},
|
|
{x=3,y=1,width=1,class="dropdown",name="dtype",items={"each replica","last replica"},value="last replica"},
|
|
{x=4,y=1,width=2,class="label",label=" last replica"},
|
|
{x=6,y=1,width=2,class="label",label="formation curve"},
|
|
{x=0,y=2,width=2,class="label",label="X Distance:"},
|
|
{x=0,y=3,width=2,class="label",label="Y Distance:"},
|
|
{x=2,y=2,width=2,class="floatedit",name="xdist",value=xdist or 0},
|
|
{x=2,y=3,width=2,class="floatedit",name="ydist",value=ydist or 0},
|
|
{x=4,y=2,width=2,class="dropdown",name="xar",items={"absolute","relative"},value="relative",hint="distance type for 'last replica'"},
|
|
{x=4,y=3,width=2,class="dropdown",name="yar",items={"absolute","relative"},value="relative",hint="distance type for 'last replica'"},
|
|
{x=6,y=2,width=2,class="floatedit",name="xcel",value=xcel or 1,min=0,hint="acceleration for 'last replica'"},
|
|
{x=6,y=3,width=2,class="floatedit",name="ycel",value=ycel or 1,min=0,hint="acceleration for 'last replica'"},
|
|
{x=0,y=4,width=6,class="checkbox",name="mov",label="use existing \\move for last replica coordinates"},
|
|
{x=0,y=5,width=2,class="checkbox",name="delay",label="Delay:"},
|
|
{x=2,y=5,width=3,class="intedit",name="del",value=0,min=0},
|
|
{x=5,y=5,width=1,class="label",label="frames"},
|
|
{x=6,y=5,width=2,class="checkbox",name="keepend",label="keep end",hint="try to keep end time\nsame as original if possible"},
|
|
}
|
|
lucid={x=0,y=6,width=8,height=10,class="textbox",value=replika}
|
|
repeat
|
|
if reprez then
|
|
for k,v in ipairs(rplGUI) do
|
|
if v.name then v.value=reprez[v.name] end
|
|
end
|
|
end
|
|
btns={"Replicate","Elucidate","Disintegrate"}
|
|
if pres=="Elucidate" then table.insert(rplGUI,lucid) table.remove(btns,2) end
|
|
pres,rez=ADD(rplGUI,btns,{ok='Replicate',close='Disintegrate'})
|
|
reprez=rez
|
|
until pres~="Elucidate"
|
|
if pres=="Disintegrate" then ak() end
|
|
repl=rez.rep+1
|
|
xcel=rez.xcel if xcel==0 then xcel=1 end
|
|
ycel=rez.ycel if ycel==0 then ycel=1 end
|
|
if rez.mov then moverep=true else moverep=false end
|
|
if rez.dtype=="each replica" and not moverep then dtype=1 xcel=1 ycel=1 else dtype=0 end
|
|
if rez.xar=="absolute" then xabs=true else xabs=false end
|
|
if rez.yar=="absolute" then yabs=true else yabs=false end
|
|
xdist=rez.xdist ydist=rez.ydist
|
|
if rez.delay then replay=rez.del else replay=0 end
|
|
if rez.keepend then endrep=true else endrep=false end
|
|
end
|
|
|
|
-- FBF Retrack Data Gathering
|
|
if res.posi=="fbf retrack" then
|
|
if #sel<3 then t_error("Error: You must select at least 3 lines for 'fbf retrack'.",1) end
|
|
retrack={} truck="" posref={}
|
|
posx1,posy1=subs[sel[1]].text:match("\\pos%(([%d.-]+),([%d.-]+)%)")
|
|
if not posx1 then t_error("Error: Missing \\pos in the first line.",1) end
|
|
posxl,posyl=subs[sel[#sel]].text:match("\\pos%(([%d.-]+),([%d.-]+)%)")
|
|
if not posxl then t_error("Error: Missing \\pos in the last line.",1) end
|
|
-- retrack tab
|
|
for z,i in ipairs(sel) do
|
|
l=subs[i] fr1=ms2fr(l.start_time)
|
|
if not truck:match("|"..fr1.."|") then table.insert(retrack,fr1) truck=truck.."|"..fr1.."|" end
|
|
end
|
|
table.sort(retrack)
|
|
-- posref tab
|
|
if res.smo then
|
|
if res.force==0 then t_error("Smoothening strength is 0, i.e. this won't do anything.\nUse the Force field for strength.",1) end
|
|
for z,i in ipairs(sel) do
|
|
l=subs[i] frame=ms2fr(l.start_time)
|
|
fpos,total=detrack(z,sel,retrack,frame)
|
|
posix,posiy=l.text:match("\\pos%(([%d.-]+),([%d.-]+)%)")
|
|
if not posix then t_error("Error: Missing \\pos in line #"..i-line0..".",1) end
|
|
if not posref[fpos] then posref[fpos]={x=posix,y=posiy} end
|
|
end
|
|
end
|
|
if res.layers and #retrack==1 then t_error("Error: All lines start on the same frame.\nIf you want to change position of signs\non the same frame, uncheck layers.",1) end
|
|
if res.layers then total=#retrack else total=#sel end
|
|
xstep=round((posxl-posx1)/(total-1),2)
|
|
ystep=round((posyl-posy1)/(total-1),2)
|
|
if ps<=0 then ps=1 end
|
|
if res.eks>0 then acx=res.eks else acx=ps end
|
|
if res.wai>0 then acx=res.wai else acy=ps end
|
|
end
|
|
|
|
-- Warp Text initial calculations
|
|
local total,M1,M2,fac,l1,l2,p1,p2,x1,x2,y1,y2,xx,yy,tang,ang,MX,MY,mid
|
|
if res.posi=="warp text" then
|
|
l1=subs[sel[1]]
|
|
l2=subs[sel[#sel]]
|
|
p1=l1.text:match'\\pos%b()'
|
|
p2=l2.text:match'\\pos%b()'
|
|
if not p1 or not p2 then t_error("\\pos tags missing.",1) end
|
|
x1,y1=p1:match'([%d.-]+),([%d.-]+)'
|
|
x2,y2=p2:match'([%d.-]+),([%d.-]+)'
|
|
xx=x2-x1 yy=y2-y1
|
|
dist=math.sqrt(xx^2+yy^2)
|
|
tang=(yy/xx)
|
|
ang=math.deg(math.atan(tang))-90
|
|
MX=math.cos(math.rad(ang))*ps
|
|
MY=math.sin(math.rad(ang))*ps
|
|
MD=dist/2
|
|
end
|
|
|
|
-- Sine Loop / Trampoline
|
|
local X,Y,Z,fr,loop,acc
|
|
if res.posi=="sine loop" or res.posi=="trampoline" then
|
|
X=res.eks
|
|
Y=res.wai
|
|
fr=round(res.force)
|
|
if fr<=0 then fr=10 end
|
|
acc=ps
|
|
if acc<=0 then acc=2 end
|
|
loop=fr+1
|
|
tot=fr*2
|
|
end
|
|
|
|
-- Positron Cannon Lines --
|
|
if res.posi=="space out letters" or res.posi=="track by clip" or res.posi=="sine loop" or res.posi=="trampoline" then table.sort(sel,function(a,b) return a>b end) end
|
|
for z,i in ipairs(sel) do
|
|
progress("Depositing line #"..i-line0.." ["..z.."/"..#sel.."]")
|
|
line=subs[i]
|
|
text=line.text
|
|
nontra=detra(text)
|
|
nopos=nil
|
|
nopos2=nil
|
|
poss=text:match("\\pos%b()")
|
|
movie=text:match("\\move%b()")
|
|
if not poss then nopos=1 end
|
|
if not poss and not movie then nopos2=1 end
|
|
|
|
-- Align X
|
|
if res.posi=="Align X" then
|
|
if z==1 and nopos2 then text=getpos(subs,text) end
|
|
if z==1 and res.first then
|
|
px=text:match("\\pos%(([%d.-]+),")
|
|
if not px then px=text:match("\\move%(([%d.-]+),") end
|
|
relocated=relocated+1
|
|
else
|
|
if nopos2 then text=getpos(subs,text) end
|
|
text=text:gsub("\\pos%(([%d.-]+),([%d.-]+)%)","\\pos("..px..",%2)")
|
|
:gsub("\\move%(([%d.-]+),([%d.-]+),([%d.-]+)",function(x1,y1,x2) m1=px-x1 return "\\move("..px..","..y1..","..x1+m1 end)
|
|
end
|
|
if z>1 and line.text==text then fail("Some lines already in position.") end
|
|
end
|
|
|
|
-- Align Y
|
|
if res.posi=="Align Y" then
|
|
if z==1 and nopos2 then text=getpos(subs,text) end
|
|
if z==1 and res.first then
|
|
py=text:match("\\pos%([%d.-]+,([%d.-]+)")
|
|
if not py then py=text:match("\\move%([%d.-]+,([%d.-]+),") end
|
|
relocated=relocated+1
|
|
else
|
|
if nopos2 then text=getpos(subs,text) end
|
|
text=text:gsub("\\pos%(([%d.-]+),([%d.-]+)%)","\\pos(%1,"..py..")")
|
|
:gsub("(\\move%([%d.-]+),([%d.-]+),([%d.-]+),([%d.-]+)",function(x1,y1,x2,y2) m2=py-y1 return x1..","..py..","..x2..","..y2+m2 end)
|
|
end
|
|
if z>1 and line.text==text then fail("Some lines already in position.") end
|
|
end
|
|
|
|
-- Mirrors
|
|
if res.posi:match"mirror" then
|
|
if nopos2 then text=getpos(subs,text) end
|
|
info(subs)
|
|
if not text:match("^{[^}]-\\an%d") then sr=stylechk(subs,line.style)
|
|
text=text:gsub("^","{\\an"..sr.align.."}") :gsub("({\\an%d)}{\\","%1\\")
|
|
end
|
|
if ps and ps~=0 then resx=2*ps resy=2*ps end
|
|
if res.posi=="horizontal mirror" then
|
|
mirs={"1","4","7","9","6","3"}
|
|
text2=text:gsub("\\pos%(([%d.-]+),([%d.-]+)%)",function(x,y) return "\\pos("..resx-x..","..y..")" end)
|
|
:gsub("\\move%(([%d.-]+),([%d.-]+),([%d.-]+),([%d.-]+)",function(x,y,x2,y2) return "\\move("..resx-x..","..y..","..resx-x2..","..y2 end)
|
|
:gsub("\\an([147369])",function(a) for m=1,6 do if a==mirs[m] then b=mirs[7-m] end end return "\\an"..b end)
|
|
if res.rota then
|
|
if not text2:match("^{[^}]-\\fry") then text2=addtag("\\fry0",text2) end text2=flip("fry",text2)
|
|
end
|
|
else
|
|
mirs={"1","2","3","9","8","7"}
|
|
text2=text:gsub("\\pos%(([%d.-]+),([%d.-]+)%)",function(x,y) return "\\pos("..x..","..resy-y..")" end)
|
|
:gsub("\\move%(([%d.-]+),([%d.-]+),([%d.-]+),([%d.-]+)",function(x,y,x2,y2) return "\\move("..x..","..resy-y..","..x2..","..resy-y2 end)
|
|
:gsub("\\an([123789])",function(a) for m=1,6 do if a==mirs[m] then b=mirs[7-m] end end return "\\an"..b end)
|
|
if res.rota then
|
|
if not text2:match("^{[^}]-\\frx") then text2=addtag("\\frx0",text2) end text2=flip("frx",text2)
|
|
end
|
|
end
|
|
l2=line l2.text=text2
|
|
if res.keep then
|
|
subs.insert(i+1,l2)
|
|
for i=z,#sel do sel[i]=sel[i]+1 end
|
|
else
|
|
if text~=text2 then relocated=relocated+1 else fail("Mirror reflection appears to be in the same location as the object reflected.") end
|
|
text=text2
|
|
end
|
|
end
|
|
|
|
-- org to fax
|
|
if res.posi=="org to fax" then
|
|
if text:match("\\move") then t_error("Line #"..i-line0..": What's \\move doing there??",1) end
|
|
if nopos then text=getpos(subs,text) end
|
|
if not text:match("\\org") then t_error("Missing \\org on line #"..i-line0..".\nAborting.",1) end
|
|
pox,poy=text:match("\\pos%(([%d.-]+),([%d.-]+)")
|
|
orx,ory=text:match("\\org%(([%d.-]+),([%d.-]+)")
|
|
sr=stylechk(subs,line.style)
|
|
rota=nontra:match("^{[^}]-\\frz([%d.-]+)") or sr.angle
|
|
scx=nontra:match("^{[^}]-\\fscx([%d%.]+)") or sr.scale_x
|
|
scy=nontra:match("^{[^}]-\\fscy([%d%.]+)") or sr.scale_y
|
|
scr=scx/scy
|
|
ad=pox-orx
|
|
op=poy-ory
|
|
tang=(ad/op)
|
|
ang1=math.deg(math.atan(tang))
|
|
ang2=ang1-rota
|
|
tangf=math.tan(math.rad(ang2))
|
|
faks=round(tangf/scr,2)
|
|
text=addtag3("\\fax"..faks,text)
|
|
text=text:gsub("\\org%([^%)]+%)","")
|
|
:gsub(ATAG,function(tg) return duplikill(tg) end)
|
|
end
|
|
|
|
-- clip to fax
|
|
if res.posi=="clip to fax" then
|
|
if not text:match("\\i?clip%(m") and not text:match("//i?clip%(m") then t_error("Missing \\clip on line #"..i-line0..".\nAborting.",1) end
|
|
cx1,cy1,cx2,cy2,cx3,cy3,cx4,cy4=text:match("clip%(m ([%d%-]+) ([%d%-]+) l ([%d%-]+) ([%d%-]+) ([%d%-]+) ([%d%-]+) ([%d%-]+) ([%d%-]+)")
|
|
if not cx1 then cx1,cy1,cx2,cy2=text:match("clip%(m ([%d%-]+) ([%d%-]+) l ([%d%-]+) ([%d%-]+)") end
|
|
if not cx1 then t_error("Line #"..i-line0..": Not enough clip points. 2 required.",1) end
|
|
sr=stylechk(subs,line.style)
|
|
rota=nontra:match("^{[^}]-\\frz([%d.-]+)") or sr.angle
|
|
rota2=nontra:match(".*\\frz([%d.-]+)") or sr.angle
|
|
scx=nontra:match("^{[^}]-\\fscx([%d%.]+)") or sr.scale_x
|
|
scy=nontra:match("^{[^}]-\\fscy([%d%.]+)") or sr.scale_y
|
|
scr=scx/scy
|
|
ad=cx1-cx2
|
|
op=cy1-cy2
|
|
tang=(ad/op)
|
|
ang1=math.deg(math.atan(tang))
|
|
ang2=ang1-rota
|
|
tangf=math.tan(math.rad(ang2))
|
|
faks=round(tangf/scr,2)
|
|
text=addtag3("\\fax"..faks,text)
|
|
if cy4 then
|
|
tang2=((cx3-cx4)/(cy3-cy4))
|
|
ang3=math.deg(math.atan(tang2))
|
|
ang4=ang3-rota2
|
|
tangf2=math.tan(math.rad(ang4))
|
|
faks2=round(tangf2,2)
|
|
endcom=""
|
|
repeat text=text:gsub("({[^}]-})%s*$",function(ec) endcom=ec..endcom return "" end)
|
|
until not text:match("}$")
|
|
text=text:gsub("(.)$","{\\fax"..faks2.."}%1")
|
|
vis=nobra(text)
|
|
orig=text:gsub(STAG,"")
|
|
tg=text:match(STAG)
|
|
chars={}
|
|
for ltr in re.gfind(vis,'.') do table.insert(chars,ltr) end
|
|
faxdiff=(faks2-faks)/(#chars-1)
|
|
tt=chars[1]
|
|
for c=2,#chars do
|
|
if chars[c]==" " then tt=tt.." " else tt=tt.."{\\fax"..round((faks+faxdiff*(c-1)),2) .."}"..chars[c] end
|
|
end
|
|
text=tg..tt
|
|
if orig:match("{%*?\\") then text=retextmod(orig,text) end
|
|
text=text..endcom
|
|
end
|
|
text=text:gsub("\\i?clip%b()","")
|
|
:gsub("{(\\[^}]-)}{(\\[^}]-)}","{%1%2}")
|
|
:gsub(ATAG,function(tg) return duplikill(tg) end)
|
|
:gsub("%**}","}")
|
|
end
|
|
|
|
-- clip to frz
|
|
if res.posi=="clip to frz" then
|
|
if not text:match("\\i?clip%(m") and not text:match("//i?clip%(m") then t_error("Missing \\clip on line #"..i-line0..".\nAborting.",1) end
|
|
cx1,cy1,cx2,cy2,cx3,cy3,cx4,cy4=text:match("clip%(m ([%d%-]+) ([%d%-]+) l ([%d%-]+) ([%d%-]+) ([%d%-]+) ([%d%-]+) ([%d%-]+) ([%d%-]+)")
|
|
if not cx1 then cx1,cy1,cx2,cy2=text:match("clip%(m ([%d%-]+) ([%d%-]+) l ([%d%-]+) ([%d%-]+)") end
|
|
if not cx1 then t_error("Line #"..i-line0..": Not enough clip points. 2 required.",1) end
|
|
local ad,op,tang,ang1,rota,ad2,op2,tang2,ang2,rota2
|
|
ad=cx2-cx1
|
|
op=cy1-cy2
|
|
tang=(op/ad)
|
|
ang1=math.deg(math.atan(tang))
|
|
rota=round(ang1,2)
|
|
if ad<0 then rota=rota-180 end
|
|
if cy4 then
|
|
ad2=cx4-cx3
|
|
op2=cy3-cy4
|
|
tang2=(op2/ad2)
|
|
ang2=math.deg(math.atan(tang2))
|
|
rota2=round(ang2,2)
|
|
if ad2<0 then rota2=rota2-180 end
|
|
else rota2=rota
|
|
end
|
|
rota3=(rota+rota2)/2
|
|
text=addtag("\\frz"..rota3,text)
|
|
text=text:gsub("\\i?clip%b()",""):gsub(ATAG,function(tg) return duplikill(tg) end)
|
|
end
|
|
|
|
-- clip to reposition
|
|
if res.posi=="clip to reposition" then
|
|
if not text:match("\\i?clip%(m") and not text:match("//i?clip%(m") then t_error("Missing \\clip on line #"..i-line0..".\nAborting.",1) end
|
|
cx1,cy1,cx2,cy2=text:match("clip%(m ([%d%-]+) ([%d%-]+) l ([%d%-]+) ([%d%-]+)")
|
|
if not cx1 then t_error("Line #"..i-line0..": Not enough clip points. 2 required.",1) end
|
|
repo1=cx2-cx1 repo2=cy2-cy1
|
|
text=text:gsub("\\i?clip%b()","")
|
|
:gsub("\\pos%(([%d.-]+),([%d.-]+)",function(x,y) return "\\pos("..round(x+repo1,2)..","..round(y+repo2,2) end)
|
|
:gsub("\\move%(([%d.-]+),([%d.-]+),([%d.-]+),([%d.-]+)",function(x1,y1,x2,y2)
|
|
return "\\move("..round(x1+repo1,2)..","..round(y1+repo2,2)..","..round(x2+repo1,2)..","..round(y2+repo2,2) end)
|
|
end
|
|
|
|
-- clip2pos fbf
|
|
if res.posi=="clip2pos fbf" then
|
|
local x1,y1=text:match("clip%(m ([%d.-]+) ([%d.-]+)")
|
|
if nopos then text=getpos(subs,text) end
|
|
local newx,newy
|
|
if z==1 then
|
|
if not x1 then t_error("Vector clip not detected on line #"..i-line0..".",1) end
|
|
posx=text:match"\\pos%((%d+%.?%d*)"
|
|
posy=text:match"\\pos%([^,]-,(%d+%.?%d*)"
|
|
refx=x1
|
|
refy=y1
|
|
else
|
|
newx=x1-refx+posx
|
|
newy=y1-refy+posy
|
|
text=text:gsub("\\pos%(([^,]-),([^,]-)%)","\\pos("..newx..","..newy..")")
|
|
end
|
|
text=text:gsub("\\i?clip%b()","")
|
|
end
|
|
|
|
-- frz+org2pos
|
|
if res.posi=="frz+org2pos" then
|
|
if nopos then text=getpos(subs,text) end
|
|
local px,py,ox,oy,rota,X,Y,x,y,pox,poy,tang,ang,ang1
|
|
px,py=text:match("\\pos%((.-),(.-)%)")
|
|
ox,oy=text:match("\\org%((.-),(.-)%)")
|
|
rota=nontra:match("^{[^}]-\\frz([-%d.]+)")
|
|
if px and ox and rota then
|
|
h=math.sqrt((ox-px)^2+(oy-py)^2)
|
|
pox=ox-px
|
|
poy=oy-py
|
|
tang=poy/pox
|
|
ang1=math.deg(math.atan(tang))
|
|
ang=ang1-rota
|
|
X=math.cos(math.rad(ang))*h
|
|
Y=math.sin(math.rad(ang))*h
|
|
if pox<0 then X=0-X Y=0-Y end
|
|
x=round(ox-X,1)
|
|
y=round(oy-Y,1)
|
|
text=text:gsub("\\pos%b()","\\pos("..x..","..y..")"):gsub("\\org%b()","")
|
|
end
|
|
end
|
|
|
|
-- numbers
|
|
if res.posi=="numbers" and line.layer==LL then
|
|
ind=ind+1
|
|
PX=text:match("\\pos%(([^,]-),") or 0
|
|
PY=text:match("\\pos%([^,]-,([^,]-)%)") or 0
|
|
table.insert(PNS,{x=tonumber(PX),y=tonumber(PY)})
|
|
end
|
|
|
|
-- shake
|
|
if res.posi=="shake" then
|
|
if text:match("\\move") then t_error("Line #"..i-line0..": What's \\move doing there??",1) end
|
|
if nopos then text=getpos(subs,text) end
|
|
s=line.start_time
|
|
diam=ps
|
|
scal=res.force
|
|
if diam==0 and not res.sca then diamx=res.eks diamy=res.wai else diamx=diam diamy=diam end
|
|
shx=math.random(-100,100)/100*diamx if res.smo and lshx then shx=(shx+3*lshx)/4 end
|
|
shy=math.random(-100,100)/100*diamy if res.smo and lshy then shy=(shy+3*lshy)/4 end
|
|
shr=math.random(-100,100)/100*diam if res.smo and lshr then shr=(shr+3*lshr)/4 end
|
|
shsx=math.random(-100,100)/100*scal if res.smo and lshsx then shsx=(shsx+3*lshsx)/4 end
|
|
shsy=math.random(-100,100)/100*scal if res.smo and lshsy then shsy=(shsy+3*lshsy)/4 end
|
|
if res.layers then
|
|
ch=0
|
|
for p=1,#shake do sv=shake[p]
|
|
if sv[1]==s then ch=1 shx=sv[2] shy=sv[3] shr=sv[4] shsx=sv[5] shsy=sv[6] end
|
|
end
|
|
if ch==0 then
|
|
a={s,shx,shy,shr,shsx,shsy}
|
|
table.insert(shake,a)
|
|
end
|
|
end
|
|
lshx=shx lshy=shy lshr=shr lshsx=shsx lshsy=shsy
|
|
text=text:gsub("\\pos%(([%d.-]+),([%d.-]+)%)",function(x,y) return "\\pos("..x+shx..","..y+shy..")" end)
|
|
if res.rota then
|
|
text=text:gsub("\\frz([%d.-]+)",function(z) return "\\frz"..z+shr end)
|
|
if not text:match("^{[^}]-\\frz") then text=addtag("\\frz"..shr,text) end
|
|
end
|
|
if res.sca then
|
|
text=text:gsub("(\\fscx)([%d.-]+)",function(x,y) return x..y+shsx end)
|
|
text=text:gsub("(\\fscy)([%d.-]+)",function(x,y) return x..y+shsy end)
|
|
if not nontra:match("^{[^}]-\\fscx") then text=addtag3("\\fscx"..shsx+100,text) end
|
|
if not nontra:match("^{[^}]-\\fscy") then text=addtag3("\\fscy"..shsy+100,text) end
|
|
end
|
|
text=text:gsub("([%d.-]+%d)([\\}%),])",function(a,b) return round(a,2)..b end)
|
|
end
|
|
|
|
if res.posi=="sine loop" or res.posi=="trampoline" then
|
|
local frames,poses,px,py,mx,my,NX,NY
|
|
if nopos then text=getpos(subs,text) end
|
|
px,py=text:match("\\pos%((.-),(.-)%)")
|
|
px2=px+X
|
|
py2=py+Y
|
|
mx=px+(X/2)
|
|
my=py+(Y/2)
|
|
start=line.start_time
|
|
endt=line.end_time
|
|
sfr=ms2fr(start)
|
|
efr=ms2fr(endt)
|
|
frames=efr-sfr
|
|
poses={}
|
|
for f=2,frames do
|
|
Z=f%tot
|
|
if Z==0 then Z=2 end
|
|
if Z>loop then Z=2*loop-Z end
|
|
table.insert(poses,Z)
|
|
|
|
if res.posi=="trampoline" then
|
|
AF=(Z-1)^acc/(fr)^acc
|
|
NX=round(AF*(px2-px)+px,2)
|
|
NY=round(AF*(py2-py)+py,2)
|
|
end
|
|
if res.posi=="sine loop" then
|
|
mid=(loop+1)/2
|
|
if Z==mid then NX=mx NY=my
|
|
elseif Z<mid then
|
|
AF=(Z-1)^acc/(mid-1)^acc
|
|
NX=round(AF*(mx-px)+px,2)
|
|
NY=round(AF*(my-py)+py,2)
|
|
else
|
|
Z2=loop+1-Z
|
|
AF=(Z2-1)^acc/(mid-1)^acc
|
|
NX=round(px2-AF*(px2-mx),2)
|
|
NY=round(py2-AF*(py2-my),2)
|
|
end
|
|
end
|
|
|
|
-- logg(NX..','..NY)
|
|
t2=text:gsub("\\pos%(.-,.-%)","\\pos("..NX..","..NY..")")
|
|
line.text=t2
|
|
line.start_time=fr2ms(sfr+f-1)
|
|
line.end_time=fr2ms(sfr+f)
|
|
subs.insert(i+f-1,line)
|
|
nsel=shiftsel(nsel,i,1)
|
|
end
|
|
line.start_time=fr2ms(sfr)
|
|
line.end_time=fr2ms(sfr+1)
|
|
end
|
|
|
|
-- shadow layer
|
|
if res.posi=="shadow layer" then
|
|
sr=stylechk(subs,line.style)
|
|
text=text:gsub("\\1c","\\c")
|
|
shadcol=nontra:match("^{[^}]-\\4c(&H%x+&)") or sr.color4:gsub("H%x%x","H")
|
|
if ps~=0 then xsh=ps ysh=ps else xsh=res.eks ysh=res.wai end
|
|
if xsh==0 and ysh==0 then
|
|
xs=nontra:match("^{[^}]-\\xshad([%d.-]+)") or nontra:match("^{[^}]-\\shad([%d%.]+)") or sr.shadow
|
|
ys=nontra:match("^{[^}]-\\yshad([%d.-]+)") or nontra:match("^{[^}]-\\shad([%d%.]+)") or sr.shadow
|
|
else xs=xsh ys=ysh
|
|
end
|
|
|
|
if tonumber(xs)>0 or tonumber(ys)>0 then
|
|
text=text:gsub("\\t(%b())",function(t) return "\\tra"..t:gsub("\\","/") end)
|
|
if nopos2 then text=getpos(subs,text) end
|
|
text=text:gsub("\\[xy]?shad([%d.-]+)","")
|
|
bored=nontra:match("^{[^}]-\\bord([%d%.]+)") or sr.outline
|
|
bored=bored-1
|
|
if bored<0 then bored=0 end
|
|
l2=line text2=text
|
|
|
|
text2=text2
|
|
:gsub("\\pos%(([%d.-]+),([%d.-]+)%)",function(a,b) return "\\pos("..a+xs..","..b+ys..")" end)
|
|
:gsub("\\move%(([%d.-]+),([%d.-]+),([%d.-]+),([%d.-]+)",
|
|
function(a,b,c,d) return "\\pos("..a+xs..","..b+ys..","..c+xs..","..d+ys end)
|
|
:gsub(ATAG,function(tag)
|
|
if tag:match("\\4c&H%x+&") then
|
|
tag=tag:gsub("\\3?c&H%x+&","") :gsub("\\4c(&H%x+&)","\\c%1\\3c%1")
|
|
else tag=tag:gsub("\\3?c&H%x+&","")
|
|
end
|
|
if tag:match("\\4a&H%x+&") then
|
|
tag=tag:gsub("\\alpha&H%x+&","") :gsub("\\4a(&H%x+&)","\\alpha%1")
|
|
end
|
|
tag=tag:gsub("\\[13]a&H%x+&","") :gsub("{}","")
|
|
return tag
|
|
end)
|
|
|
|
text2=addtag3("\\bord"..bored,text2)
|
|
text2=addtag3("\\shad0",text2)
|
|
text2=addtag3("\\c"..shadcol,text2)
|
|
text2=addtag3("\\3c"..shadcol,text2)
|
|
text=addtag3("\\shad0",text)
|
|
text=text:gsub("\\tra(%b())",function(t) return "\\t"..t:gsub("/","\\") end)
|
|
|
|
l2.text=text2
|
|
subs.insert(i+1,l2)
|
|
line.layer=line.layer+1
|
|
sel=shiftsel(sel,i,0) nsel=shiftsel(nsel,i,1)
|
|
else fail("It appears to cast no shadow...")
|
|
end
|
|
if z==#sel then sel=nsel end
|
|
end
|
|
|
|
-- Shadow Reposition
|
|
if res.posi=="shadow repos." then
|
|
sr=stylechk(subs,line.style)
|
|
if nopos2 then text=getpos(subs,text) end
|
|
xshad=nontra:match("^{[^}]-\\xshad([^}\\]+)") or nontra:match("^{[^}]-\\shad([^}\\]+)") or sr.shadow
|
|
yshad=nontra:match("^{[^}]-\\yshad([^}\\]+)") or nontra:match("^{[^}]-\\shad([^}\\]+)") or sr.shadow
|
|
text=text:gsub("\\pos%((.-),(.-)%)",function(x,y) return "\\pos("..x-xshad/2 ..","..y-yshad/2 ..")" end)
|
|
:gsub("\\move%((.-),(.-),(.-),([%d.-]+)",function(x,y,xx,yy) return "\\move("..x-xshad/2 ..","..y-yshad/2 ..","..xx-xshad/2 ..","..yy-yshad/2 end)
|
|
if text==line.text then fail("No shadow.") end
|
|
end
|
|
|
|
-- fbf X <--> Y
|
|
if res.posi=="fbf X <--> Y" then
|
|
newY=XYtab[z].x-Xref+Yref if res.rota then newY=Yref-(XYtab[z].x-Xref) end
|
|
newX=XYtab[z].y-Yref+Xref if res.rota then newX=Xref-(XYtab[z].y-Yref) end
|
|
text=text:gsub("\\pos%(([%d.-]+),([%d.-]+)%)","\\pos("..newX..","..newY..")")
|
|
if text==line.text then fail("Some lines already in position.") end
|
|
end
|
|
|
|
-- Space out letters
|
|
visible=text:gsub("%b{}",""):gsub("%s*\\[Nh]%s*"," ")
|
|
letrz=re.find(visible,".")
|
|
if res.posi=="space out letters" and not letrz then fail("No text.") end
|
|
if res.posi=="space out letters" and letrz and #letrz<2 then fail("Not enough letters to split text.") end
|
|
if res.posi=="space out letters" and letrz and #letrz>1 then
|
|
sr=stylechk(subs,line.style)
|
|
acalign=nil
|
|
m1,m2,m3,m4=text:match("\\move%(([%d.-]+),([%d.-]+),([%d.-]+),([%d.-]+)")
|
|
if m1 then
|
|
text=text:gsub("\\move%(([%d.-]+),([%d.-]+)","\\pos(%1,%2)(")
|
|
movX=m3-m1 movY=m4-m2
|
|
end
|
|
text=text:gsub(" *\\[Nh] *"," ")
|
|
if nopos then text=getpos(subs,text) end
|
|
tags=text:match(STAG) or ""
|
|
after=text:gsub(STAG,""):gsub("{[^\\}]-}","")
|
|
local px,py=text:match("\\pos%(([%d.-]+),([%d.-]+)%)")
|
|
local x1,width,w,wtotal,let,spacing,avgspac,ltrspac,xpos,lastxpos,spaces,prevlet,scx,k1,k2,k3,bord,off,inwidth,wdiff,pp,tpos
|
|
scx=nontra:match("^{[^}]-\\fscx([%d%.]+)") or sr.scale_x
|
|
fsp=nontra:match("^{[^}]-\\fsp([%d%.]+)")
|
|
if fsp then sr.spacing=tonumber(fsp) end
|
|
fsize=nontra:match("^{[^}]-\\fs([%d%.]+)")
|
|
if fsize then sr.fontsize=tonumber(fsize) end
|
|
phont=nontra:match("^{[^}]-\\fn([^\\}]+)")
|
|
if phont then sr.fontname=phont end
|
|
bord=nontra:match("^{[^}]-\\bord([%d%.]+)") or sr.outline
|
|
k1,k2,k3=text:match("clip%(([%d.-]+),([%d.-]+),([%d.-]+),")
|
|
letters={} wtotal=0
|
|
for l=1,#letrz do
|
|
local ltr=letrz[l].str
|
|
w=aegisub.text_extents(sr,ltr)
|
|
table.insert(letters,{l=ltr,w=w})
|
|
wtotal=wtotal+w
|
|
leng=re.find(ltr,'.')
|
|
if ltr=="" then
|
|
logg("- Line #"..i-line0..": unexpected re module failure: letter lost - #"..l)
|
|
fail("Re module failure. Some letters seem to have been lost or added.\nPlease rerun the function or rescan Autoload directory.")
|
|
re_fail=true
|
|
elseif #leng>1 then
|
|
logg("- Line #"..i-line0..": unexpected re module failure: multiple letters matched: "..ltr)
|
|
fail("Re module failure. Some letters seem to have been lost or added.\nPlease rerun the function or rescan Autoload directory.")
|
|
re_fail=true
|
|
end
|
|
end
|
|
if #letters~=#letrz then
|
|
logg(#letrz.." -> "..#letrz)
|
|
end
|
|
intags={} cnt=0
|
|
for chars,tag in after:gmatch("([^}]+)({\\[^}]+})") do
|
|
pp=re.find(chars,".")
|
|
tpos=#pp+1+cnt
|
|
intags[tpos]=tag
|
|
cnt=cnt+#pp
|
|
end
|
|
spacing=ps
|
|
avgspac=wtotal/#letters
|
|
off=(letters[1].w-letters[#letters].w)/4*scx/100
|
|
inwidth=(wtotal-letters[1].w/2-letters[#letters].w/2)*scx/100
|
|
if spacing==1 then spacing=round(avgspac*scx)/100 end
|
|
width=(#letters-1)*spacing --off
|
|
|
|
-- klip-based stuff
|
|
if k1 then
|
|
width=(k3-k1)-letters[1].w/2*(scx/100)-letters[#letters].w/2*(scx/100)-(2*bord)
|
|
spacing=(width+2*bord)/(#letters-1)
|
|
px=(k1+k3)/2-off
|
|
tags=tags:gsub("\\i?clip%b()","")
|
|
end
|
|
|
|
-- find starting x point based on alignment
|
|
if not acalign then acalign=text:match("\\an(%d)") or sr.align end
|
|
acalign=tostring(acalign)
|
|
if acalign:match("[147]") then
|
|
tags=tags:gsub("\\an%d","") :gsub("^{","{\\an"..acalign+1)
|
|
:gsub("\\pos%(([%d.-]+)",function(p) return "\\pos("..round(p+(wtotal/2)*(scx/100),2) end)
|
|
end
|
|
if acalign:match("[369]") then
|
|
tags=tags:gsub("\\an%d","") :gsub("^{","{\\an"..acalign-1)
|
|
:gsub("\\pos%(([%d.-]+)",function(p) return "\\pos("..round(p-(wtotal/2)*(scx/100),2) end)
|
|
end
|
|
if not k1 then px,py=tags:match("\\pos%(([%d.-]+),([%d.-]+)%)") end
|
|
acalign=tags:match("\\an(%d)")
|
|
x1=round(px-width/2)
|
|
wdiff=(width-inwidth)/(#letters-1)
|
|
lastxpos=x1
|
|
spaces=0
|
|
-- weird letter-width sorcery starts here
|
|
for t=1,#letters do
|
|
let=letters[t]
|
|
if t>1 then
|
|
prevlet=letters[t-1]
|
|
ltrspac=(let.w+prevlet.w)/2*scx/100+wdiff
|
|
ltrspac=round(ltrspac,2)
|
|
else
|
|
fact1=spacing/(avgspac*scx/100)
|
|
fact2=(let.w-letters[#letters].w)/4*scx/100
|
|
ltrspac=round(fact1*fact2,2)
|
|
end
|
|
if intags[t] then tags=tags..intags[t] tags=tagmerge(tags) tags=duplikill(tags) end
|
|
t2=tags..let.l
|
|
xpos=lastxpos+ltrspac
|
|
XP=xpos
|
|
notra=detra(t2)
|
|
rota=notra:match("^{[^}]-\\frz([-%d.]+)")
|
|
if rota then
|
|
h=px-xpos
|
|
X=math.cos(math.rad(rota))*h
|
|
Y=math.sin(math.rad(rota))*h
|
|
x=round(px-X,1)
|
|
y=round(py+Y,1)
|
|
t2=t2:gsub("\\pos%b()","\\pos("..x..","..y..")")
|
|
else
|
|
t2=t2:gsub("\\pos%(([%d.-]+),([%d.-]+)%)","\\pos("..XP..",%2)")
|
|
end
|
|
if m1 then
|
|
t2=t2:gsub("\\pos%(([%d.-]+),([%d.-]+)%)%(,[%d.-]+,[%d.-]+",function(a,b) return "\\move("..a..","..b..","..a+movX..","..b+movY end)
|
|
end
|
|
lastxpos=xpos
|
|
l2=line
|
|
l2.text=t2
|
|
if t==1 then text=t2 else
|
|
if let.l~=" " then subs.insert(i+t-1-spaces,l2) nsel=shiftsel(nsel,i,1) else count=count-1 spaces=spaces+1 end
|
|
end
|
|
end
|
|
count=count+#letters-1
|
|
end
|
|
|
|
-- Warp Text
|
|
if res.posi=="warp text" and z>1 and z<#sel then
|
|
if not text:match'\\pos%b()' then t_error("Missing \\pos tag on line #"..i-line0..".",1) end
|
|
local xc,yc,CDX,CDY,CD,acc,Mid,MC,DF,D2,NX,NY,AF
|
|
xc,yc=text:match'\\pos%(([%d.-]+),([%d.-]+)%)'
|
|
CDX=xc-x1 CDY=yc-y1
|
|
CD=math.sqrt(CDX^2+CDY^2)
|
|
if CD>MD then
|
|
CDX=x2-xc CDY=y2-yc
|
|
CD=math.sqrt(CDX^2+CDY^2)
|
|
end
|
|
acc=0.8 -- Curve Shaper 1
|
|
if CD<MD then
|
|
AF=(CD)^acc/(MD)^acc
|
|
else
|
|
AF=(dist-CD)^acc/MD^acc
|
|
end
|
|
Mid=MD/10
|
|
DF=Mid/CD -- Curve Shaper 2
|
|
if CD>Mid then DF=9*Mid/(MD-CD) end
|
|
DF=1.6/DF
|
|
D2=math.sqrt(1+DF)
|
|
NX=round(MX*AF*D2+xc,5)
|
|
NY=round(MY*AF*D2+yc,5)
|
|
DF=DF^2.5 -- Curve Shaper 2.5
|
|
FF=(6*(ps/dist))^2 -- Random Weird Factor 1
|
|
if tonumber(xc)<(x2+x1)/2 then
|
|
CDX2=NX-x1
|
|
CDY2=NY-y1
|
|
if CDX2>0 then XF=DF else XF=0-DF end
|
|
if CDY2>0 then YF=DF else YF=0-DF end
|
|
XF2=2*XF*math.abs(CDX2)/(math.abs(CDX2)+math.abs(CDY2))*FF
|
|
YF2=2*YF*math.abs(CDY2)/(math.abs(CDX2)+math.abs(CDY2))*FF
|
|
else
|
|
CDX2=x2-NX
|
|
CDY2=y2-NY
|
|
if CDX2<0 then XF=DF else XF=0-DF end
|
|
if CDY2<0 then YF=DF else YF=0-DF end
|
|
XF2=2*XF*math.abs(CDX2)/(math.abs(CDX2)+math.abs(CDY2))*FF
|
|
YF2=2*YF*math.abs(CDY2)/(math.abs(CDX2)+math.abs(CDY2))*FF
|
|
end
|
|
text=text:gsub("\\pos%(([%d.-]+),([%d.-]+)%)","\\pos("..round(NX-XF2,2)..","..round(NY-YF2,2)..")")
|
|
end
|
|
|
|
-- Track by Clip
|
|
if res.posi=="track by clip" then
|
|
if not res.X and not res.Y then t_error("Neither X nor Y is checked. Nothing to track.",1) end
|
|
klip=text:match("clip%(m .+%)")
|
|
if not klip then t_error("Error: No clip in line #"..i-line0..".",1) end
|
|
if nopos then text=getpos(text,subs) end
|
|
local fr=1 -- how many frames per line
|
|
if ps>=1 then fr=math.floor(ps) end
|
|
local x1,y1=text:match("clip%(m ([-%d.]+) ([-%d.]+)")
|
|
if not x1 then t_error("Error: This clip seems broken.\n"..klip,1) end
|
|
if not res.first then x1,y1=text:match("clip%(m .-([-%d.]+) ([-%d.]+)%)") end -- last frame is default
|
|
local klips={}
|
|
for a,b in klip:gmatch("([-%d.]+) ([-%d.]+)") do table.insert(klips,{x=a-x1,y=b-y1}) end
|
|
start,endt=line.start_time,line.end_time
|
|
for t=#klips,2,-1 do
|
|
kp=klips[t]
|
|
if res.X then x6=kp.x else x6=0 end
|
|
if res.Y then y7=kp.y else y7=0 end
|
|
t2=text:gsub("\\i?clip%b()","")
|
|
:gsub("\\pos%(([^,]+),([^,]+)%)",function(a,b) return "\\pos("..a+x6..","..b+y7..")" end)
|
|
local st=fr2ms(ms2fr(start)+(fr*(t-1)))
|
|
local et=fr2ms(ms2fr(start)+(fr*(t-1))+fr)
|
|
line.start_time=st
|
|
line.end_time=et
|
|
if t==#klips then line.end_time=fr2ms(ms2fr(endt)) end
|
|
line.text=t2
|
|
subs.insert(i+1,line) nsel=shiftsel(nsel,i,1)
|
|
end
|
|
line.start_time=fr2ms(ms2fr(start))
|
|
line.end_time=fr2ms(ms2fr(start)+fr)
|
|
text=text:gsub("\\i?clip%b()","")
|
|
if not res.first then text=text:gsub("\\pos%(([^,]+),([^,]+)%)",function(a,b) return "\\pos("..a+klips[1].x..","..b+klips[1].y..")" end) end
|
|
end
|
|
|
|
-- Replicate
|
|
if res.posi=="replicate" then
|
|
startf=ms2fr(line.start_time)
|
|
endf=ms2fr(line.end_time)
|
|
if moverep then
|
|
x1,y1,mx,my=text:match("\\move%(([^,]+),([^,]+),([^,]+),([^,)]+)")
|
|
if not mx then t_error("Abort: No \\move tag on line #"..i-line0..".",1) end
|
|
rxdist=mx rydist=my
|
|
text=text:gsub("\\move%b()","\\pos("..x1..","..y1..")")
|
|
else
|
|
if nopos and not text:match("\\move") then text=getpos(subs,text) end
|
|
x1,y1=text:match("\\pos%(([^,]+),([^,]-)%)")
|
|
if not x1 then x1,y1=text:match("\\move%(([^,]+),([^,]-),") end
|
|
if dtype==1 then rxdist=xdist*(repl-1)+x1 rydist=ydist*(repl-1)+y1
|
|
else
|
|
if xabs then rxdist=xdist else rxdist=xdist+x1 end
|
|
if yabs then rydist=ydist else rydist=ydist+y1 end
|
|
end
|
|
end
|
|
-- replicating
|
|
for r=repl,1,-1 do
|
|
l2=line
|
|
posx=numgrad(x1,rxdist,repl,r,xcel)
|
|
posy=numgrad(y1,rydist,repl,r,ycel)
|
|
text2=text:gsub("\\pos%b()","\\pos("..posx..","..posy..")")
|
|
:gsub("\\move%(([^,]+),([^,]+),([^,]+),([^,)]+)",function(m1,m2,m3,m4)
|
|
return "\\move("..posx..","..posy..","..m3-m1+posx..","..m4-m2+posy end)
|
|
startf2=startf+replay*(r-1)
|
|
start2=fr2ms(startf2) end2=fr2ms(endf)
|
|
if endrep then if endf<startf2 then end2=fr2ms(startf2+1) end -- keep end or start+1
|
|
else end2=fr2ms(endf+replay*(r-1)) end
|
|
l2.start_time=start2 l2.end_time=end2
|
|
l2.text=text2
|
|
if r==1 then line=l2 else subs.insert(i+1,l2) sel=shiftsel(sel,i,0) nsel=shiftsel(nsel,i,1) end
|
|
end
|
|
line.start_time=fr2ms(startf)
|
|
line.end_time=fr2ms(endf)
|
|
if z==#sel then sel=nsel end
|
|
end
|
|
|
|
-- FBF Retrack
|
|
if res.posi=="fbf retrack" then
|
|
frame=ms2fr(line.start_time)
|
|
fpos,total=detrack(z,sel,retrack,frame)
|
|
if nopos then text=getpos(subs,text) end
|
|
posix,posiy=text:match("\\pos%(([^,]+),([^,]+)%)")
|
|
if fpos>1 and fpos<total then
|
|
if res.smo then
|
|
-- smoothen track, force: 0-100
|
|
smf=math.abs(res.force)/100
|
|
if smf>1 then smf=1 end
|
|
if smf<0 then smf=0 end
|
|
ref=round(math.abs(ps))
|
|
if ref<1 then ref=1 end
|
|
for re=1,ref do
|
|
sm=smf*(1/re)
|
|
if re<fpos and re<total-fpos+1 then
|
|
xref=(posref[fpos-re].x+posref[fpos+re].x)/2
|
|
yref=(posref[fpos-re].y+posref[fpos+re].y)/2
|
|
diffx=round(posix-xref,2)
|
|
diffy=round(posiy-yref,2)
|
|
newdiffx=diffx*sm
|
|
newdiffy=diffy*sm
|
|
newx=round(posix-newdiffx,2)
|
|
newy=round(posiy-newdiffy,2)
|
|
posix=newx posiy=newy
|
|
posref[fpos]={x=newx,y=newy}
|
|
end
|
|
end
|
|
else
|
|
-- regular fbf transform
|
|
newx=numgrad(posx1,posxl,total,fpos,acx)
|
|
newy=numgrad(posy1,posyl,total,fpos,acy)
|
|
end
|
|
if not res.X then newx=posix end
|
|
if not res.Y then newy=posiy end
|
|
text=text:gsub("\\pos%b()","\\pos("..newx..","..newy..")")
|
|
end
|
|
fail("First and last lines won't move.")
|
|
if text==line.text and z>1 and z<#sel then fail("Some lines already in position.") end
|
|
end
|
|
|
|
if line.text~=text then relocated=relocated+1 end
|
|
line.text=text
|
|
subs[i]=line
|
|
end
|
|
|
|
if res.posi=="numbers" then
|
|
NUMGUI=
|
|
{{x=0,y=0,width=3,class="label",label=ind.." lines of layer "..LL.." selected (showing max. 10); pos X / pos Y"}}
|
|
for n=1,#PNS do
|
|
if n==1 then
|
|
table.insert(NUMGUI,{x=0,y=n,class="label",label="Start point:"})
|
|
table.insert(NUMGUI,{x=1,y=n,class="floatedit",value=PNS[n].x})
|
|
table.insert(NUMGUI,{x=2,y=n,class="floatedit",value=PNS[n].y})
|
|
end
|
|
if n>1 and n<11 then
|
|
table.insert(NUMGUI,{x=0,y=n,class="label",label="Line "..n.." offset:"})
|
|
table.insert(NUMGUI,{x=1,y=n,class="edit",value=round(PNS[n].x-PNS[n-1].x,2)})
|
|
table.insert(NUMGUI,{x=2,y=n,class="edit",value=round(PNS[n].y-PNS[n-1].y,2)})
|
|
end
|
|
end
|
|
if #PNS>1 then
|
|
if #PNS>10 then wat=11 else wat=#PNS+1 end
|
|
table.insert(NUMGUI,{x=0,y=wat,class="label",label="Average step:"})
|
|
table.insert(NUMGUI,{x=1,y=wat,class="edit",value=round((PNS[#PNS].x-PNS[1].x)/(ind-1),3)})
|
|
table.insert(NUMGUI,{x=2,y=wat,class="edit",value=round((PNS[#PNS].y-PNS[1].y)/(ind-1),3)})
|
|
press=ADD(NUMGUI,{"k","no"},{ok='k',close='no'})
|
|
if press=="no" then ak() end
|
|
else t_error("You need at least 2 lines on the lowest selected layer",1)
|
|
end
|
|
end
|
|
if re_fail then progress("Lost in Hyperspace") logg("Please run the function again. ('Repeat' should work.)\nIf this keeps happening, try rescanning the Autoload Dir.") end
|
|
table.sort(sel)
|
|
sel=nsel
|
|
return sel
|
|
end
|
|
|
|
|
|
|
|
function bilocator(subs,sel)
|
|
xx=res.eks yy=res.wai rM=res.move
|
|
if rM=="shiftstart" or rM=="shiftmove" then
|
|
if xx==0 and yy==0 then t_error("No coordinates given. Use Teleport input.",1) end
|
|
end
|
|
if rM=="transmove" then
|
|
for z,i in ipairs(sel) do
|
|
if z>1 and i==ii+1 then t_error("Selection must not contain two consecutive lines.\nRead the SpaceTravel Guide to learn how this works.",1) end
|
|
ii=i
|
|
end
|
|
end
|
|
local mid
|
|
for z=#sel,1,-1 do
|
|
i=sel[z]
|
|
progress("Moving through hyperspace... #"..i-line0.." ["..#sel+1-z.."/"..#sel.."]")
|
|
line=subs[i]
|
|
text=line.text
|
|
start=line.start_time
|
|
endt=line.end_time
|
|
nopos=nil
|
|
poss=text:match("\\pos%b()")
|
|
if not poss then nopos=1 end
|
|
|
|
if rM=="transmove" and i<#subs then
|
|
|
|
nextline=subs[i+1]
|
|
text2=nextline.text
|
|
text=text:gsub("\\1c","\\c")
|
|
text2=text2:gsub("\\1c","\\c")
|
|
if xx~=0 or yy~=0 then movt1=xx movt2=yy
|
|
else movt1,movt2=gettimes(start,endt) end
|
|
if res.times then movt=","..movt1..","..movt2 else movt="" end
|
|
|
|
-- move
|
|
if nopos then text=getpos(subs,text) end
|
|
p1=text:match("\\pos%((.-)%)")
|
|
p2=text2:match("\\pos%((.-)%)")
|
|
if p2==nil then t_error("Line #"..i-line0+1 .." is missing \\pos tag.\nAborting.",1) end
|
|
if p2~=p1 then text=text:gsub("\\pos%((.-)%)","\\move(%1,"..p2..movt..")") end
|
|
|
|
-- transforms
|
|
tf=""
|
|
|
|
tftags={"fs","fsp","fscx","fscy","blur","bord","shad","fax","fay"}
|
|
for tg=1,#tftags do
|
|
t=tftags[tg]
|
|
if text2:match("\\"..t.."[%d.-]+") then tag2=text2:match("(\\"..t.."[%d.-]+)")
|
|
if text:match("\\"..t.."[%d.-]+") then tag1=text:match("(\\"..t.."[%d.-]+)") else tag1="" end
|
|
if tag1~=tag2 then tf=tf..tag2 end
|
|
end
|
|
end
|
|
|
|
tfctags={"c","2c","3c","4c","1a","2a","3a","4a","alpha"}
|
|
for tg=1,#tfctags do
|
|
t=tfctags[tg]
|
|
if text2:match("\\"..t.."&H%x+&") then tag2=text2:match("(\\"..t.."&H%x+&)")
|
|
if text:match("\\"..t.."&H%x+&") then tag1=text:match("(\\"..t.."&H%x+&)") else tag1="" end
|
|
if tag1~=tag2 then tf=tf..tag2 end
|
|
end
|
|
end
|
|
|
|
tfrtags={"frz","frx","fry"}
|
|
for tg=1,#tfrtags do
|
|
t=tfrtags[tg]
|
|
if text2:match("\\"..t.."[%d.-]+") then
|
|
tag2=text2:match("(\\"..t.."[%d.-]+)") rr2=tonumber(text2:match("\\"..t.."([%d.-]+)"))
|
|
if text:match("\\"..t.."[%d.-]+") then
|
|
tag1=text:match("(\\"..t.."[%d.-]+)") rr1=tonumber(text:match("\\"..t.."([%d.-]+)"))
|
|
else tag1="" rr1=0 end
|
|
if tag1~=tag2 then
|
|
if res.rotac and math.abs(rr2-rr1)>180 then
|
|
if rr2>rr1 then rr2=rr2-360 tag2="\\frz"..rr2 else
|
|
rr1=rr1-360 text=text:gsub("\\frz[%d.-]+","\\frz"..rr1)
|
|
end
|
|
end
|
|
tf=tf..tag2 end
|
|
end
|
|
end
|
|
|
|
-- apply transform
|
|
if tf~="" then text=text:gsub("^({\\[^}]-)}","%1\\t("..movt:gsub("^,(.*)","%1,")..tf..")}") end
|
|
|
|
-- delete line 2
|
|
if res.keep==false then subs.delete(i+1)
|
|
if z<#sel then
|
|
for s=z+1,#sel do sel[s]=sel[s]-1 end
|
|
end
|
|
end
|
|
|
|
end -- end of transmove
|
|
|
|
if rM=="horizontal" then text=text:gsub("\\move%(([%d.-]+),([%d.-]+),([%d.-]+),([%d.-]+)","\\move(%1,%2,%3,%2") end
|
|
if rM=="vertical" then text=text:gsub("\\move%(([%d.-]+),([%d.-]+),([%d.-]+),([%d.-]+)","\\move(%1,%2,%1,%4") end
|
|
if rM=="rvrs. move" then text=text:gsub("\\move%(([%d.-]+),([%d.-]+),([%d.-]+),([%d.-]+)","\\move(%3,%4,%1,%2") end
|
|
|
|
if rM=="clip2move" then
|
|
if not res.X and not res.Y then t_error("Neither X nor Y checked. Nothing will happen.",1) end
|
|
if xx~=0 or yy~=0 then movt1=xx movt2=yy
|
|
else movt1,movt2=gettimes(start,endt) end
|
|
if res.times then M=","..movt1..","..movt2 else M="" end
|
|
if not text:match("\\i?clip") and not text:match("//i?clip") then t_error("Missing \\clip on line #"..i-line0..". Aborting.",1) end
|
|
cx1,cy1,cx2,cy2,cx3,cy3,cx4,cy4=text:match("clip%(m ([%d%-]+) ([%d%-]+) l ([%d%-]+) ([%d%-]+) ([%d%-]+) ([%d%-]+) ([%d%-]+) ([%d%-]+)")
|
|
if not cx1 then cx1,cy1,cx2,cy2=text:match("clip%(m ([%d%-]+) ([%d%-]+) l ([%d%-]+) ([%d%-]+)") end
|
|
if not cx1 then t_error("Line #"..i-line0..": Not enough clip points. Min. 2 required.",1) end
|
|
if cx4 then
|
|
point1x=(cx2+cx1)/2
|
|
point1y=(cy2+cy1)/2
|
|
point2x=(cx4+cx3)/2
|
|
point2y=(cy4+cy3)/2
|
|
xmov=point2x-point1x
|
|
ymov=point2y-point1y
|
|
else
|
|
xmov=cx2-cx1 ymov=cy2-cy1
|
|
end
|
|
if not res.X then xmov=0 end
|
|
if not res.Y then ymov=0 end
|
|
text=text:gsub("\\move%(([%d.-]+),([%d.-]+),([%d.-]+),([%d.-]+)[^%)]*",function(x,y)
|
|
return "\\move("..x..","..y..","..round(x+xmov,2)..","..round(y+ymov,2)..M end)
|
|
:gsub("\\pos%(([%d.-]+),([%d.-]+)",function(x,y)
|
|
return "\\move("..x..","..y..","..round(x+xmov,2)..","..round(y+ymov,2)..M end)
|
|
:gsub("\\i?clip%b()","")
|
|
end
|
|
|
|
if rM=="shiftstart" then
|
|
text=text:gsub("\\move%(([%d.-]+),([%d.-]+),([%d.-]+),([%d.-]+)([^%)]*)",function(a,b,c,d,e)
|
|
if res.videofr then vfcheck() e=e:gsub("([%d.-]+)(,[%d.-]+)",videopos.."%2") end
|
|
return "\\move("..a+xx..","..b+yy..","..c..","..d..e end)
|
|
if not text:match("\\move") then fail("Some lines don't have \\move tag.") end
|
|
end
|
|
|
|
if rM=="shiftmove" or rM=="move to" then
|
|
movt1,movt2=text:match("\\move%([%d.-]+,[%d.-]+,[%d.-]+,[%d.-]+,([%d.-]+),([%d.-]+)")
|
|
if not movt1 then movt1,movt2=gettimes(start,endt) end
|
|
if res.videofr then vfcheck() end
|
|
if res.times or res.videofr then M=","..movt1..","..movt2 else M="" end
|
|
text=text:gsub("\\move%(([%d.-]+),([%d.-]+),([%d.-]+),([%d.-]+)([^%)]*)",function(a,b,c,d,e)
|
|
if res.videofr then if e~="" then M=e end M=M:gsub("([%d.-]+,)([%d.-]+)","%1"..videopos) end
|
|
if rM=="move to" then c=xx d=yy else c=c+xx d=d+yy end
|
|
return "\\move("..a..","..b..","..c..","..d..M end)
|
|
text=text:gsub("\\pos%(([%d.-]+),([%d.-]+)",function(a,b)
|
|
if res.videofr then M=M:gsub("([%d.-]+,)([%d.-]+)","%1"..videopos) end
|
|
if rM=="move to" then c=xx d=yy else c=a+xx d=b+yy end
|
|
return "\\move("..a..","..b..","..c..","..d..M end)
|
|
if nopos then fail("Some lines don't have \\pos tag.") end
|
|
end
|
|
|
|
if rM=="move clip" then
|
|
m1,m2,m3,m4=text:match("\\move%(([%d.-]+),([%d.-]+),([%d.-]+),([%d.-]+)")
|
|
mt=text:match("\\move%([^,]+,[^,]+,[^,]+,[^,)]+,([%d%.,%-]+)")
|
|
if mt==nil then mt="" else mt=mt.."," end
|
|
klip=text:match("\\i?clip%([%d%.,%-]+%)")
|
|
if not m1 then fail("\\move missing.") end
|
|
if not klip then fail("Rectangular clip missing.") end
|
|
if klip and m1 then
|
|
klip=klip:gsub("(\\i?clip%()([%d.-]+),([%d.-]+),([%d.-]+),([%d.-]+)",
|
|
function(a,b,c,d,e) return a..b+m3-m1..","..c+m4-m2..","..d+m3-m1..","..e+m4-m2 end)
|
|
text=addtag("\\t("..mt..klip..")",text)
|
|
end
|
|
end
|
|
|
|
if rM=="full times" or rM=="set times" then
|
|
startf=ms2fr(start)
|
|
endf=ms2fr(endt)
|
|
start2=fr2ms(startf)
|
|
endt2=fr2ms(endf-1)
|
|
tim=fr2ms(1)
|
|
movt1=start2-start+tim
|
|
movt2=endt2-start+tim
|
|
if rM=="set times" then
|
|
if xx>=0 then movt1=xx else movt1=movt2+xx end
|
|
if yy>0 then movt2=yy else movt2=movt2+yy end
|
|
end
|
|
movt=movt1..","..movt2
|
|
if not text:match("\\move") then fail("Some lines don't have \\move tag.") end
|
|
end
|
|
|
|
if rM=="kill times" then
|
|
if res.tra then text=text:gsub("\\t%([%d.-]-,[%d.-]-,","\\t(")
|
|
else text=text:gsub("\\move%(([^,]+,[^,]+,[^,]+,[^,]+),[^,]+,[^,%)]+","\\move(%1") end
|
|
end
|
|
|
|
if rM=="full times" or rM=="set times" then
|
|
if res.tra then text=text
|
|
:gsub("\\t%([%d.-]-,[%d.-]-,([%d%.]-,)\\","\\t("..movt..",%1\\")
|
|
:gsub("\\t%([%d.-]-,[%d.-]-,\\","\\t("..movt..",\\")
|
|
:gsub("\\t%(([%d%.]-,)\\","\\t("..movt..",%1\\")
|
|
:gsub("\\t%(\\","\\t("..movt..",\\")
|
|
else text=text:gsub("\\move%(([^,]+,[^,]+,[^,]+,[^,%)]+)[^%)]-%)","\\move(%1,"..movt..")") end
|
|
end
|
|
|
|
if rM=="zig-zag" then
|
|
local px,py,dur,poses,tim,X1,Y1,X2,Y2,XX,YY,tid,first,rest,moov,endpos
|
|
if z==#sel then
|
|
rezz=rezz or {}
|
|
local G={
|
|
{x=0,y=0,width=2,class="label",label="Pos A (X,Y):"},
|
|
{x=2,y=0,class="floatedit",name="AX",value=rezz.AX},
|
|
{x=3,y=0,class="floatedit",name="AY",value=rezz.AY},
|
|
{x=0,y=1,width=2,class="label",label="Pos B (X,Y):"},
|
|
{x=2,y=1,class="floatedit",name="BX",value=rezz.BX},
|
|
{x=3,y=1,class="floatedit",name="BY",value=rezz.BY},
|
|
{x=0,y=2,width=2,class="label",label="Interval (ms):"},
|
|
{x=2,y=2,class="floatedit",name="int",value=rezz.int or 500},
|
|
{x=3,y=2,class="label",label="Starting position:"},
|
|
{x=4,y=2,class="dropdown",name="st",items={"A","B","middle"},value="A"},
|
|
|
|
{x=0,y=3,width=2,class="label",label="Shift A (X,Y):"},
|
|
{x=2,y=3,class="floatedit",name="addAX",value=rezz.addAX},
|
|
{x=3,y=3,class="floatedit",name="addAY",value=rezz.addAY},
|
|
{x=0,y=4,width=2,class="label",label="Shift B (X,Y):"},
|
|
{x=2,y=4,class="floatedit",name="addBX",value=rezz.addBX},
|
|
{x=3,y=4,class="floatedit",name="addBY",value=rezz.addBY},
|
|
|
|
{x=4,y=0,class="checkbox",name="line",label="Line's position",value=rezz.line},
|
|
{x=4,y=1,class="checkbox",name="rel",label="Relative to A",value=rezz.rel},
|
|
|
|
{x=0,y=5,width=5,height=8,class="textbox",value="This will split a line into several that will move back and forth between given points A and B over the duration of the current line.\nEach move between A and B has the duration of the given interval.\nShifting means that with each round, the point (A/B) moves by the given distance.\nIf you start at top left (A) and top right (B) and set 0,10 for both shifts, the text will move left-right and go (10 pixels) lower with each round, ending up at the bottom of the screen if given enough time.\nYou can choose starting position, but with shifting, probably only A will work well.\nWith 'middle', the second point is always A, and the move, being half the distance, will only last half the given interval, so the speed is the same.\n'Line's position' means Pos A will be the current position of the line.\n'Relative to A', if set for example to '0,100', means Pos B will be 100 pixels below Pos A.\nUsing both these options at the same time allows for several selected lines to move in unison. If A is line's position and B is absolute, all lines will meet at point B and then go back to where they started."},
|
|
}
|
|
ZZ,rezz=ADD(G,{"Zig-Zag Movement","Cancel"},{ok='Zig-Zag Movement',close='Cancel'})
|
|
if ZZ=="Cancel" then ak() end
|
|
inter=rezz.int
|
|
ST=rezz.st
|
|
AX=rezz.AX AY=rezz.AY BX=rezz.BX BY=rezz.BY
|
|
if rezz.rel then BX=AX+rezz.BX BY=AY+rezz.BY end
|
|
if ST=='middle' then mid=true end
|
|
addAX=rezz.addAX
|
|
addAY=rezz.addAY
|
|
addBX=rezz.addBX
|
|
addBY=rezz.addBY
|
|
end
|
|
dur=endt-start
|
|
if dur<=inter then t_error("Line #"..i-line0..": Line duration must be longer than given interval.",1) end
|
|
poses={}
|
|
if nopos then
|
|
moov=text:match("\\move%(([%d.-]+,[%d.-]+)")
|
|
if not moov then text=getpos(subs,text) end
|
|
end
|
|
px,py=text:match("\\pos%(([%d.-]+),([%d.-]+)")
|
|
if not px then px,py=moov:match("([%d.-]+),([%d.-]+)") end
|
|
if rezz.line then AX=px AY=py end
|
|
if rezz.rel then BX=AX+rezz.BX BY=AY+rezz.BY end
|
|
if ST=='A' then X1=AX Y1=AY X2=BX Y2=BY
|
|
elseif ST=='B' then X1=BX Y1=BY X2=AX Y2=AY
|
|
elseif mid then X1=(BX+AX)/2 Y1=(BY+AY)/2
|
|
end
|
|
table.insert(poses,{X1,Y1})
|
|
first=inter
|
|
rest=dur-inter
|
|
if mid then X1=BX Y1=BY X2=AX Y2=AY first=inter/2 rest=dur-(inter/2) end
|
|
seg=math.ceil(rest/inter)
|
|
|
|
for q=1,seg+1 do
|
|
if q%2==0 then
|
|
-- A [mid/B: B]
|
|
if ST=='A' then
|
|
X1=X1+addAX
|
|
Y1=Y1+addAY
|
|
else
|
|
X1=X1+addBX
|
|
Y1=Y1+addBY
|
|
end
|
|
XX=X1 YY=Y1
|
|
if q==seg+1 then endpos={XX,YY}
|
|
else table.insert(poses,{XX,YY}) end
|
|
else
|
|
-- B [mid/B: A]
|
|
XX=X2 YY=Y2
|
|
if q==seg+1 then endpos={XX,YY}
|
|
else table.insert(poses,{XX,YY}) end
|
|
if ST=='A' then
|
|
X2=X2+addBX
|
|
Y2=Y2+addBY
|
|
else
|
|
X2=X2+addAX
|
|
Y2=Y2+addAY
|
|
end
|
|
end
|
|
end
|
|
tim=fr2ms(1)
|
|
for l=1,#poses do
|
|
-- logg(l)
|
|
if l==1 then tid=first else tid=inter end
|
|
t2=text:gsub("\\pos%b()",""):gsub("\\move%b()","")
|
|
m1=poses[l][1]
|
|
m2=poses[l][2]
|
|
if l==#poses then
|
|
m3=endpos[1]
|
|
m4=endpos[2]
|
|
else
|
|
m3=poses[l+1][1]
|
|
m4=poses[l+1][2]
|
|
end
|
|
start1=start
|
|
if l>1 then
|
|
start1=start+first+(l-2)*inter
|
|
end
|
|
endt1=start1+tid
|
|
if l==#poses then endt1=endt end
|
|
start2=fr2ms(ms2fr(start1))
|
|
endt2=fr2ms(ms2fr(endt1)-1)
|
|
movt1=start2-start1+tim
|
|
movt2=endt2-start1+tim
|
|
mov="\\move("..m1..","..m2..","..m3..","..m4..",0,"..tid..")"
|
|
t2=addtag(mov,t2)
|
|
line.text=t2
|
|
line.start_time=start1
|
|
line.end_time=endt1
|
|
-- logg(t2)
|
|
if l>1 then subs.insert(i+l-1,line) else text=t2 end
|
|
end
|
|
line.start_time=start
|
|
line.end_time=start+first
|
|
end
|
|
|
|
if text~=line.text then relocated=relocated+1 end
|
|
text=roundpar(text,2)
|
|
line.text=text
|
|
subs[i]=line
|
|
end
|
|
end
|
|
|
|
function multimove(subs,sel)
|
|
text=subs[sel[1]].text
|
|
if not text:match("\\move") then t_error("Missing \\move tag on first line.",1) end
|
|
x1,y1,x2,y2,t=text:match("\\move%(([%d.-]+),([%d.-]+),([%d.-]+),([%d.-]+)([^%)]*)%)")
|
|
m1=x2-x1 m2=y2-y1
|
|
fail("First line won't change.")
|
|
for z=2,#sel do
|
|
i=sel[z]
|
|
progress("Synchronizing movement... #"..i-line0.." ["..z.."/"..#sel.."]")
|
|
line=subs[sel[z]]
|
|
text=line.text
|
|
if not text:match("\\pos%b()") and not text:match("\\move%b()") then text=getpos(subs,text) end
|
|
text=text:gsub("\\move%(([%d.-]+),([%d.-]+),[%d.-]+,[%d.-]+,[^%)]+",function(x,y) return "\\move("..x..","..y..","..round(x+m1,2)..","..round(y+m2,2)..t end)
|
|
text=text:gsub("\\pos%(([%d.-]+),([%d.-]+)%)",function(x,y) return "\\move("..x..","..y..","..round(x+m1,2)..","..round(y+m2,2)..t..")" end)
|
|
if line.text~=text then relocated=relocated+1 end
|
|
line.text=text
|
|
subs[sel[z]]=line
|
|
end
|
|
end
|
|
|
|
function randomove(subs,sel)
|
|
T=true
|
|
RMGUI={
|
|
{x=0,y=0,width=2,class="checkbox",name="rmt",label="Time:",value=rmt},
|
|
{x=2,y=0,width=4,class="intedit",name="slow",value=slowd or 50,hint="max slowdown to ... %",max=99,min=1},
|
|
{x=6,y=0,class="label",label="%"},
|
|
|
|
{x=0,y=1,width=2,class="checkbox",name="rms",label="Space:",value=rms},
|
|
{x=2,y=1,class="checkbox",name="rm1",label="x1"},
|
|
{x=3,y=1,class="checkbox",name="rm2",label="y1"},
|
|
{x=4,y=1,class="checkbox",name="rm3",label="x2",value=T},
|
|
{x=5,y=1,class="checkbox",name="rm4",label="y2",value=T},
|
|
|
|
{x=0,y=2,width=2,class="label",label=" Distance:"},
|
|
{x=2,y=2,width=4,class="floatedit",name="rmdist",value=rmd or 0},
|
|
{x=0,y=3,width=2,class="label",label=" Direction:"},
|
|
{x=2,y=3,width=2,class="checkbox",name="plus",label="positive",value=T},
|
|
{x=4,y=3,width=2,class="checkbox",name="minus",label="negative",value=T},
|
|
|
|
{x=0,y=4,width=7,height=4,class="textbox",value="Time - \\move direction doesn't change.\n'50%' means text will move between 50 and 100% of original distance.\n\nSpace - Given coordinates change within given distance and direction.\n\nTime and Space may be combined, but it makes more sense to use just one."}
|
|
}
|
|
P,rez=ADD(RMGUI,{"OK","Cancel"},{ok='OK',close='Cancel'})
|
|
if P=="Cancel" then ak() end
|
|
|
|
rmt=rez.rmt rms=rez.rms
|
|
slowd=rez.slow rmd=rez.rmdist
|
|
rmdp=rez.plus rmdm=rez.minus
|
|
|
|
if not rmt and not rms then t_error("Neither Time nor Space selected.\nSpace-time travel failed.",1) end
|
|
if rms and rmd==0 then t_error("Given distance is 0. This won't have any effect.",1) end
|
|
|
|
plus=0 minus=0
|
|
if rmdp then plus=rmd*100 end
|
|
if rmdm then minus=(0-rmd)*100 end
|
|
|
|
for z,i in ipairs(sel) do
|
|
progress("Randomizing movement... #"..i-line0.." ["..z.."/"..#sel.."]")
|
|
line=subs[i]
|
|
text=line.text
|
|
if text:match("\\move") then
|
|
if rmt then
|
|
movt1,movt2=gettimes(line.start_time,line.end_time)
|
|
text=text:gsub("(\\move%([%d.-]+,[%d.-]+,[%d.-]+,[%d.-]+)%)","%1,"..movt1..","..movt2..")")
|
|
movt3=math.random(movt2,movt2*(100/slowd))
|
|
text=text:gsub("(\\move%([%d.-]+,[%d.-]+,[%d.-]+,[%d.-]+),([%d%.,%-]+)%)","%1,"..movt1..","..movt3..")")
|
|
end
|
|
if rms then
|
|
text=text:gsub("\\move%(([%d.-]+),([%d.-]+),([%d.-]+),([%d.-]+)",
|
|
function(a,b,c,d)
|
|
if rez.rm1 then a=a+math.random(minus,plus)/100 end
|
|
if rez.rm2 then b=b+math.random(minus,plus)/100 end
|
|
if rez.rm3 then c=c+math.random(minus,plus)/100 end
|
|
if rez.rm4 then d=d+math.random(minus,plus)/100 end
|
|
return "\\move("..a..","..b..","..c..","..d end)
|
|
end
|
|
else fail("\\move not present.")
|
|
end
|
|
if text~=line.text then relocated=relocated+1 end
|
|
line.text=text
|
|
subs[i]=line
|
|
end
|
|
end
|
|
|
|
function modifier(subs,sel,act)
|
|
if not ak then cuts(subs,sel) end
|
|
post=res.post force=res.force xx=res.eks yy=res.wai
|
|
if res.rndec then _,rr=res.rndec:gsub("0","") end
|
|
FR={"frx","fry","frz"}
|
|
for z,i in ipairs(sel) do
|
|
progress("Morphing... #"..i-line0.." ["..z.."/"..#sel.."]")
|
|
line=subs[i]
|
|
text=line.text
|
|
nopos=nil
|
|
poss=text:match("\\pos%b()")
|
|
if not poss then nopos=1 end
|
|
|
|
if res.mod=="round numbers" then
|
|
if poss and res.rnd=="all" or poss and res.rnd=="pos" then
|
|
text=text:gsub("\\pos%(([%d.-]+),([%d.-]+)%)",function(a,b) return "\\pos("..round(a,rr)..","..round(b,rr)..")" end)
|
|
end
|
|
if text:match("\\org") and res.rnd=="all" or text:match("\\org") and res.rnd=="org" then
|
|
text=text:gsub("\\org%(([%d.-]+),([%d.-]+)%)",function(a,b) return "\\org("..round(a,rr)..","..round(b,rr)..")" end)
|
|
end
|
|
if text:match("\\move") and res.rnd=="all" or text:match("\\move") and res.rnd=="move" then
|
|
text=text:gsub("\\move%(([%d.-]+),([%d.-]+),([%d.-]+),([%d.-]+)",function(mo1,mo2,mo3,mo4)
|
|
return "\\move("..round(mo1,rr)..","..round(mo2,rr)..","..round(mo3,rr)..","..round(mo4,rr) end)
|
|
end
|
|
if text:match("\\i?clip") and res.rnd=="all" or text:match("\\i?clip") and res.rnd=="clip" then
|
|
for klip in text:gmatch("\\i?clip%([^%)]+%)") do
|
|
if klip:match("m") then rrr=0 else rrr=rr end
|
|
klip2=klip:gsub("([%d.-]+)",function(c) return round(c,rrr) end)
|
|
text=text:gsub(esc(klip),klip2)
|
|
end
|
|
end
|
|
if text:match("\\p1") and res.rnd=="all" or text:match("\\p1") and res.rnd=="mask" then
|
|
tags=text:match(STAG)
|
|
text=text:gsub(STAG,"") :gsub("([%d.-]+)",function(m) return round(m,rr) end)
|
|
text=tags..text
|
|
end
|
|
end
|
|
|
|
if res.mod=="move v. clip" then
|
|
if z==1 then
|
|
if nopos and not text:match("\\move") then text=getpos(subs,text) end
|
|
v1,v2=text:match("\\pos%(([%d.-]+),([%d.-]+)%)")
|
|
if not v1 then t_error("Error. No \\pos tag on first line.",1) end
|
|
fail("No change to line 1.")
|
|
end
|
|
if z~=1 and text:match("\\pos") then v3,v4=text:match("\\pos%(([%d.-]+),([%d.-]+)%)")
|
|
V1=v3-v1 V2=v4-v2
|
|
if text:match("clip%(m [%d%a%s%-%.]+%)") then
|
|
ctext=text:match("clip%(m ([%d%a%s%-%.]+)%)")
|
|
ctext2=ctext:gsub("([%d%-%.]+)%s([%d%-%.]+)",function(a,b) return a+V1.." "..b+V2 end)
|
|
ctext=ctext:gsub("%-","%%-")
|
|
text=text:gsub("clip%(m "..ctext,"clip(m "..ctext2)
|
|
end
|
|
if text:match("clip%(%d+,m [%d%a%s%-%.]+%)") then
|
|
fac,ctext=text:match("clip%((%d+),m ([%d%a%s%-%.]+)%)")
|
|
factor=2^(fac-1)
|
|
ctext2=ctext:gsub("([%d%-%.]+)%s([%d%-%.]+)",function(a,b) return a+factor*V1.." "..b+factor*V2 end)
|
|
ctext=ctext:gsub("%-","%%-")
|
|
text=text:gsub(",m "..ctext,",m "..ctext2)
|
|
end
|
|
if line.text==text then fail("No clip to move.") end
|
|
end
|
|
end
|
|
|
|
if res.mod=="set origin" then
|
|
if nopos then text=getpos(subs,text) end
|
|
text=text:gsub("\\pos%(([%d.-]+),([%d.-]+)%)",function(a,b)
|
|
local X,Y=xx,yy
|
|
if res.warp then X=a+xx Y=b+yy end
|
|
return "\\pos("..a..","..b..")\\org("..X..","..Y..")" end)
|
|
end
|
|
|
|
if res.mod=="calculate origin" then
|
|
local c={}
|
|
local c2={}
|
|
x1,y1,x2,y2,x3,y3,x4,y4=text:match("clip%(m ([%d%-]+) ([%d%-]+) l ([%d%-]+) ([%d%-]+) ([%d%-]+) ([%d%-]+) ([%d%-]+) ([%d%-]+)")
|
|
if not x1 then t_error("Line #"..i-line0..": vectorial clip with 4 points required.\nAborting.",1) end
|
|
cor1={x=tonumber(x1),y=tonumber(y1)} table.insert(c,cor1) table.insert(c2,cor1)
|
|
cor2={x=tonumber(x2),y=tonumber(y2)} table.insert(c,cor2) table.insert(c2,cor2)
|
|
cor3={x=tonumber(x3),y=tonumber(y3)} table.insert(c,cor3) table.insert(c2,cor3)
|
|
cor4={x=tonumber(x4),y=tonumber(y4)} table.insert(c,cor4) table.insert(c2,cor4)
|
|
table.sort(c,function(a,b) return tonumber(a.x)<tonumber(b.x) end) -- sorted by x
|
|
table.sort(c2,function(a,b) return tonumber(a.y)<tonumber(b.y) end) -- sorted by y
|
|
-- i don't even know myself how all this shit works
|
|
xx1=c[1].x yy1=c[1].y
|
|
xx2=c[4].x yy2=c[4].y
|
|
yy3=c2[1].y xx3=c2[1].x
|
|
yy4=c2[4].y xx4=c2[4].x
|
|
distx1=c[2].x-c[1].x disty1=c[2].y-c[1].y
|
|
distx2=c[4].x-c[3].x disty2=c[4].y-c[3].y
|
|
distx3=c2[2].x-c2[1].x disty3=c2[2].y-c2[1].y
|
|
distx4=c2[4].x-c2[3].x disty4=c2[4].y-c2[3].y
|
|
|
|
-- x/y factor / angle / whatever
|
|
fx1=math.abs(disty1/distx1)
|
|
fx2=math.abs(disty2/distx2)
|
|
fx3=math.abs(distx3/disty3)
|
|
fx4=math.abs(distx4/disty4)
|
|
|
|
-- determine if y is going up or down
|
|
cy=1
|
|
if c[2].y>c[1].y then cx1=round(xx1-(yy1-cy)/fx1) else cx1=round(xx1+(yy1-cy)/fx1) end
|
|
if c[4].y>c[3].y then cx2=round(xx2-(yy2-cy)/fx2) else cx2=round(xx2+(yy2-cy)/fx2) end
|
|
top=cx2-cx1
|
|
cy=500
|
|
if c[2].y>c[1].y then cx1=round(xx1-(yy1-cy)/fx1) else cx1=round(xx1+(yy1-cy)/fx1) end
|
|
if c[4].y>c[3].y then cx2=round(xx2-(yy2-cy)/fx2) else cx2=round(xx2+(yy2-cy)/fx2) end
|
|
bot=cx2-cx1
|
|
if top>bot then cy=c2[4].y ycalc=1 else cy=c2[1].y ycalc=-1 end
|
|
|
|
-- LOOK FOR ORG X
|
|
repeat
|
|
if c[2].y>c[1].y then cx1=round(xx1-(yy1-cy)/fx1) else cx1=round(xx1+(yy1-cy)/fx1) end
|
|
if c[4].y>c[3].y then cx2=round(xx2-(yy2-cy)/fx2) else cx2=round(xx2+(yy2-cy)/fx2) end
|
|
cy=cy+ycalc
|
|
until cx1>=cx2 or math.abs(cy)==50000
|
|
org1=cx1
|
|
|
|
-- determine if x is going left or right
|
|
cx=1
|
|
if c2[2].x>c2[1].x then cy1=round(yy3-(xx3-cx)/fx3) else cy1=round(yy3+(xx3-cx)/fx3) end
|
|
if c2[4].x>c2[3].x then cy2=round(yy4-(xx4-cx)/fx4) else cy2=round(yy4+(xx4-cx)/fx4) end
|
|
left=cy2-cy1
|
|
cx=500
|
|
if c2[2].x>c2[1].x then cy1=round(yy3-(xx3-cx)/fx3) else cy1=round(yy3+(xx3-cx)/fx3) end
|
|
if c2[4].x>c2[3].x then cy2=round(yy4-(xx4-cx)/fx4) else cy2=round(yy4+(xx4-cx)/fx4) end
|
|
rite=cy2-cy1
|
|
if left>rite then cx=c[4].x xcalc=1 else cx=c[1].x xcalc=-1 end
|
|
|
|
-- LOOK FOR ORG Y
|
|
repeat
|
|
if c2[2].x>c2[1].x then cy1=round(yy3-(xx3-cx)/fx3) else cy1=round(yy3+(xx3-cx)/fx3) end
|
|
if c2[4].x>c2[3].x then cy2=round(yy4-(xx4-cx)/fx4) else cy2=round(yy4+(xx4-cx)/fx4) end
|
|
cx=cx+xcalc
|
|
until cy1>=cy2 or math.abs(cx)==50000
|
|
org2=cy1
|
|
|
|
text=text:gsub("\\org%([^%)]+%)","")
|
|
text=addtag("\\org("..org1..","..org2..")",text)
|
|
end
|
|
|
|
if res.mod=="set rotation" then rotinhell()
|
|
rota=res.freeze
|
|
for f=1,3 do rot=FR[f]
|
|
if res[rot] then text=addtag3("\\"..rot..rota,text) end
|
|
end
|
|
end
|
|
|
|
if res.mod=="rotate 180" then rotinhell()
|
|
nontra=text:gsub("\\t%b()","")
|
|
for f=1,3 do rot=FR[f]
|
|
if res[rot] then
|
|
if nontra:match("\\"..rot) then text=flip(rot,text) else text=addtag3("\\"..rot.."180",text) end
|
|
end
|
|
end
|
|
end
|
|
|
|
if res.mod=="negative rot" then rotinhell()
|
|
for f=1,3 do rot=FR[f]
|
|
if res[rot] then text=negative(text,180,"\\"..rot) end
|
|
end
|
|
if text==line.text then fail("No rotation to be affected.") end
|
|
end
|
|
|
|
if res.mod=="vector2rect." then
|
|
text=text:gsub("\\(i?)clip%(m ([%d.-]+) ([%d.-]+) l ([%d.-]+) ([%d.-]+) ([%d.-]+) ([%d.-]+) ([%d.-]+) ([%d.-]+)%)","\\%1clip(%2,%3,%6,%7)")
|
|
if text==line.text then fail("No clip to be affected.") end
|
|
end
|
|
|
|
if res.mod=="rect.2vector" then
|
|
text=text:gsub("\\(i?)clip%(([%d.-]+),([%d.-]+),([%d.-]+),([%d.-]+)%)",function(ii,a,b,c,d)
|
|
a,b,c,d=round4(a,b,c,d) return string.format("\\"..ii.."clip(m %d %d l %d %d %d %d %d %d)",a,b,c,b,c,d,a,d) end)
|
|
if text==line.text then fail("No clip to be affected.") end
|
|
end
|
|
|
|
if res.mod=="clip scale" and text:match("\\i?clip%(%d-,?m") then
|
|
oscf=text:match("\\i?clip%((%d+),m")
|
|
if oscf then fact1=2^(oscf-1) else fact1=1 end
|
|
force=round(force)
|
|
if force<1 then force=1 end
|
|
fact2=2^(force-1)
|
|
text=text:gsub("(\\i?clip%()(%d*,?)m ([^%)]+)%)",function(a,b,c)
|
|
return a..force..",m "..c:gsub("([%d.-]+)",function(d) return round(d/fact1*fact2) end)..")" end)
|
|
:gsub("1,m","m")
|
|
end
|
|
if res.mod=="clip scale" and text==line.text then fail("No clip to be affected.") end
|
|
|
|
if res.mod=="clip2scale fbf" then
|
|
local x1,y1,x2,y2=text:match("clip%(m ([%d.-]+) ([%d.-]+) l ([%d.-]+) ([%d.-]+)")
|
|
if not x1 then t_error("Vector clip with 2 points not detected on line #"..i-line0..".",1) end
|
|
if z==1 then
|
|
scx=text:match"^{[^}]-\\fscx(%d+%.?%d*)" or 100
|
|
scy=text:match"^{[^}]-\\fscy(%d+%.?%d*)" or 100
|
|
refx=math.abs(x2-x1)
|
|
refy=math.abs(y2-y1)
|
|
else
|
|
if res.X then linex=math.abs(x2-x1) nscx=round(scx/refx*linex,1) text=addtag3("\\fscx"..nscx,text) end
|
|
if res.Y then liney=math.abs(y2-y1) nscy=round(scy/refy*liney,1) text=addtag3("\\fscy"..nscy,text) end
|
|
end
|
|
text=text:gsub("\\i?clip%b()","")
|
|
end
|
|
|
|
if res.mod=="find centre" then
|
|
if nopos then text=getpos(subs,text) end
|
|
text=text:gsub("\\pos%([^%)]+%)","") t2=text
|
|
text=text:gsub("\\clip%(([%d.-]+),([%d.-]+),([%d.-]+),([%d.-]+)%)",function(a,b,c,d)
|
|
x=round(a/2+c/2) y=round(b/2+d/2) return "\\pos("..x..","..y..")" end)
|
|
if t2==text then t_error("Line #"..i-line0..": rectangular clip required.",1) end
|
|
end
|
|
|
|
if res.mod=="extend mask" then
|
|
if xx==0 and yy==0 then t_error("Error. Both given values are 0.\nUse the Teleport X and Y fields.",1) end
|
|
draw=text:match("}m ([^{]+)")
|
|
if draw then
|
|
draw2=draw:gsub("([%d.-]+) ([%d.-]+)",function(a,b)
|
|
if tonumber(a)>0 then ax=xx elseif tonumber(a)<0 then ax=0-xx else ax=0 end
|
|
if tonumber(b)>0 then by=yy elseif tonumber(b)<0 then by=0-yy else by=0 end
|
|
return a+ax.." "..b+by end)
|
|
draw=esc(draw)
|
|
text=text:gsub("(}m )"..draw,"%1"..draw2)
|
|
else fail("No mask to be affected.")
|
|
end
|
|
end
|
|
|
|
if res.mod=="flip mask" then
|
|
draw=text:match("}m ([^{]+)")
|
|
if draw then
|
|
draw2=draw:gsub("([%d.-]+) ([%d.-]+)",function(a,b) return 0-a.." "..b end)
|
|
draw=esc(draw)
|
|
text=text:gsub("(}m )"..draw,"%1"..draw2)
|
|
else fail("No mask to be flipped.")
|
|
end
|
|
end
|
|
|
|
if res.mod=="adjust drawing" then
|
|
if not text:match("\\p%d") then t_error("No drawing on line #"..i-line0..".",1) end
|
|
-- drawing 2 clip
|
|
if not text:match("\\i?clip") then
|
|
draw=text:match("}m ([^{]+)")
|
|
rota=text:match("^{[^}]-\\frz([-%d.]+)")
|
|
if rota then sr=stylechk(subs,line.style) text=frz_redraw(text,rota,draw,sr) end
|
|
klip="\\clip("..text:match("\\p1[^}]-}(m [^{]*)")..")"
|
|
scx=text:match("\\fscx([%d%.]+)") or 100
|
|
scy=text:match("\\fscy([%d%.]+)") or 100
|
|
if poss then
|
|
local xx,yy=text:match("\\pos%(([%d.-]+),([%d.-]+)%)")
|
|
xx=round(xx) yy=round(yy)
|
|
coord=klip:match("\\clip%(m ([^%)]+)%)")
|
|
coord2=coord:gsub("([%d%-]+) ([%d%-]+)",function(a,b) return round(a*scx/100+xx).." "..round(b*scy/100+yy) end)
|
|
klip=klip:gsub(esc(coord),coord2)
|
|
end
|
|
if nopos then text=text:gsub("^{","{\\pos(0,0)") end
|
|
text=addtag(klip,text)
|
|
-- clip 2 drawing
|
|
else
|
|
text=text:gsub("\\i?clip%(([%d.-]+),([%d.-]+),([%d.-]+),([%d.-]+)%)",function(a,b,c,d)
|
|
a,b,c,d=round4(a,b,c,d) return string.format("\\clip(m %d %d l %d %d %d %d %d %d)",a,b,c,b,c,d,a,d) end)
|
|
klip=text:match("\\i?clip%((m.-)%)")
|
|
if poss then
|
|
local xx,yy=text:match("\\pos%(([%d.-]+),([%d.-]+)%)")
|
|
xx=round(xx) yy=round(yy)
|
|
coord=klip:match("m ([%d%a%s%-]+)")
|
|
coord2=coord:gsub("([%d%-]+)%s([%d%-]+)",function(a,b) return a-xx.." "..b-yy end)
|
|
coord=coord:gsub("%-","%%-")
|
|
klip=klip:gsub(coord,coord2)
|
|
end
|
|
text=text:gsub("(\\p1[^}]-})(m [^{]*)","%1"..klip)
|
|
if nopos then text=text:gsub("^{","{\\pos(0,0)") end
|
|
if text:match("\\an") then text=text:gsub("\\an%d","\\an7") else text=text:gsub("^{","{\\an7") end
|
|
if text:match("\\fscx") then text=text:gsub("\\fscx[%d%.]+","\\fscx100") else text=text:gsub("\\p1","\\fscx100\\p1") end
|
|
if text:match("\\fscy") then text=text:gsub("\\fscy[%d%.]+","\\fscy100") else text=text:gsub("\\p1","\\fscy100\\p1") end
|
|
text=text:gsub("\\i?clip%(.-%)","")
|
|
end
|
|
end
|
|
|
|
if res.mod=="randomask" then
|
|
if force==0 then t_error("No input given. Use the Force field.",1) end
|
|
draw=text:match("}m ([^{]+)")
|
|
if draw then
|
|
draw2=draw:gsub("([%d.-]+)",function(a) return a+math.random(0-force,force) end)
|
|
draw=esc(draw)
|
|
text=text:gsub("(}m )"..draw,"%1"..draw2)
|
|
else fail("No mask to be affected.")
|
|
end
|
|
end
|
|
|
|
if res.mod=="randomise..." then
|
|
if z==1 then
|
|
regtags=true rPos=true rNeg=true
|
|
if rrez and regrand==false then regtags=false end
|
|
if rrez and rrez.rpos==false then rPos=false end
|
|
if rrez and rrez.rneg==false then rNeg=false end
|
|
if not rrez then rrez={} end
|
|
randomgui={
|
|
{x=0,y=0,width=2,class="label",label="Randomisation Value:"},
|
|
{x=2,y=0,width=3,class="floatedit",name="random",value=rnd or 3,hint="values can go up or down by this much\n(won't go under 0 where not applicable)"},
|
|
{x=0,y=1,class="checkbox",name="rpos",label="positive",value=rPos,hint="allow positive RV"},
|
|
{x=1,y=1,class="checkbox",name="rneg",label="neg.",value=rNeg,hint="allow negative RV"},
|
|
{x=2,y=1,class="label",label=" Rounding:"},
|
|
{x=3,y=1,width=2,class="dropdown",name="dec",items={"1","0.1","0.01","0.001"},value=rrez.dec or "0.1",},
|
|
|
|
{x=0,y=2,width=2,class="checkbox",name="ERV",label="use value from:",value=rrez.ERV,hint="this disables all of the above"},
|
|
{x=2,y=2,width=2,class="dropdown",name="from",items={"actor","effect","comment","margin_l","margin_r","margin_v"},value=rrez.from or "effect"},
|
|
{x=4,y=2,class="dropdown",name="set",items={"add","set"},value=rrez.set or "add",hint="add saved values, or set them as they are\n\n(don't use 'set' with clips)"},
|
|
|
|
{x=0,y=3,width=2,class="label",label=" pattern in comment:",hint="word pattern in {random: #} if used"},
|
|
{x=2,y=3,width=3,class="edit",name="compat",value=rrez.compat or "random"},
|
|
|
|
{x=0,y=4,width=2,class="checkbox",name="ntag",label="standard type tag",value=rnt,hint="\\[tag][number]\n(bord, blur, rotations, etc., also alphas)"},
|
|
{x=0,y=5,width=2,class="checkbox",name="reg",label="^ regular tags",value=regtags,hint="i.e. not in transforms"},
|
|
{x=2,y=5,width=3,class="checkbox",name="tr",label="in transforms",value=trand,hint=""},
|
|
{x=2,y=4,width=3,class="edit",name="randomtag",value=rt,hint="separate multiple tags with a comma, e.g. 'bord,shad,blur'"},
|
|
|
|
{x=0,y=6,width=2,class="checkbox",name="ptag1",label="parenthesis tag x",value=rpt1,hint="\\tag(X,y)"},
|
|
{x=0,y=7,width=2,class="checkbox",name="ptag2",label="parenthesis tag y",value=rpt2,hint="\\tag(x,Y)"},
|
|
{x=2,y=6,class="dropdown",name="partag1",items={"pos","move","org","clip","iclip","fad"},value=rrez.partag1 or "pos"},
|
|
{x=2,y=7,class="dropdown",name="partag2",items={"pos","move","org","clip","iclip","fad"},value=rrez.partag2 or "pos"},
|
|
|
|
{x=0,y=8,class="checkbox",name="tt1",label="\\t tc 1",value=rrez.tt1,hint="\\t timecode 1"},
|
|
{x=1,y=8,class="checkbox",name="tt2",label="\\t tc 2",value=rrez.tt2,hint="\\t timecode 2"},
|
|
{x=2,y=8,width=3,class="checkbox",name="tac",label="\\t acceleration",value=rrez.tac},
|
|
}
|
|
rP,rrez=ADD(randomgui,{"Randomise","Explicate","Disintegrate"},{ok='Randomise',close='Disintegrate'})
|
|
if rP=="Explicate" then
|
|
table.insert(randomgui,{x=5,y=0,width=20,height=9,class="textbox",name="tb",value="This can modify values for given tags.\nExample: \\bord5 + RV 3.5 ->\nyou can get anything from \\bord1.5 to \\bord8.5.\nwith only 'positive': 5 - 8.5; 'negative': 1.5 - 5.\nMost tags are the standard type, ie tag+number, so type which ones you want and check the box.\nFor tags like \\bord, negative values will be flipped.\nNote: the tags won't be created; they must exist.\n\nFor parenthesis tags, you can randomise X and Y values separately. You can also modify transform times and accel.\n\nThe use of this is mainly for fbf lines with the same tag, but can be used for multiple inline tags of the same type as well.\n\n'use value from' can use existing values in the fields offered. These can be first generated with Significance. (Or you can get them wherever.)\n\n'add' will add the value from 'effect' to the tag, like the regular function, whereas 'set' will replace it. This offers different options for generating the numbers. This may seem confusing until you generate some values with Significance (v3.1+).\n\n(Using 'set' with clips will make them useless.)"})
|
|
rP,rrez=ADD(randomgui,{"Randomise","Disintegrate"},{ok='Randomise',close='Disintegrate'})
|
|
end
|
|
if rP=="Disintegrate" then ak() end
|
|
rt=rrez.randomtag:gsub("[\\ ]","") rtx=rrez.partag1 rty=rrez.partag2 rpt1=rrez.ptag1 rpt2=rrez.ptag2
|
|
_,deci=rrez.dec:gsub("0","") rnd=rrez.random rnt=rrez.ntag regrand=rrez.reg trand=rrez.tr
|
|
if not rnt and not rpt1 and not rpt2 and not rrez.tt1 and not rrez.tt2 and not rrez.tac then t_error("No tag type selected.",1) end
|
|
if rt=='' and rtx=='' and rty=='' and not rrez.tt1 and not rrez.tt2 and not rrez.tac then t_error("No tags given.",1) end
|
|
if not rrez.rpos and not rrez.rneg and not rrez.ERV then t_error("Either positive or negative values (or both) must be allowed.",1) end
|
|
if rrez.ERV and rrez.set=="set" then SET=true else SET=false end
|
|
end
|
|
RVE=nil
|
|
if rrez.ERV then
|
|
if rrez.from=="comment" then RVE=text:match("{"..esc(rrez.compat)..": (%-?%d+%.?%d*)}") or 0
|
|
else RVE=line[rrez.from:gsub("_v","_t")]
|
|
end
|
|
RVE=tonumber(RVE) or 0
|
|
end
|
|
|
|
-- standard tags
|
|
if rrez.ntag then
|
|
-- block \t tags
|
|
for tra in text:gmatch("\\t(%b())") do
|
|
tra2=tra:gsub("\\","_")
|
|
text=text:gsub(esc(tra),tra2)
|
|
end
|
|
for tg in rt:gmatch("[^,]+") do
|
|
if rrez.reg then text=randomise_tag(text,tg,'\\') end -- regular
|
|
if rrez.tr then text=randomise_tag(text,tg,'_') end -- in \t
|
|
end
|
|
-- unblock \t tags
|
|
for tra in text:gmatch("\\t(%b())") do
|
|
tra2=tra:gsub("_","\\")
|
|
text=text:gsub(esc(tra),tra2)
|
|
end
|
|
end
|
|
|
|
-- parenthesis tags
|
|
if rrez.ptag1 or rrez.ptag2 then
|
|
rndm=RVE or ranDoom(rnd)
|
|
if rrez.ptag1 then
|
|
text=text:gsub("\\"..rtx.."%(([%d.-]+),([%d.-]+)",
|
|
function(x,y) if SET then x=0 end
|
|
return "\\"..rtx.."("..round((x+rndm),deci)..","..y end)
|
|
:gsub("\\"..rtx.."%(([%d.-]+,[%d.-]+,)([%d.-]+),([%d.-]+)",
|
|
function(a,x,y) if SET then x=0 end
|
|
return "\\"..rtx.."("..a..round((x+rndm),deci)..","..y end)
|
|
:gsub("(\\"..rtx.."%(m )([^%)]+)(%))",
|
|
function(s,c,e)
|
|
c=c:gsub("(%-?[%d.]+)( %-?[%d.]+)",function(x,y)
|
|
if SET then x=0 end
|
|
return round((x+rndm),deci)..y
|
|
end)
|
|
return s..c..e end)
|
|
end
|
|
if rrez.ptag2 then
|
|
text=text:gsub("\\"..rty.."%(([%d.-]+),([%d.-]+)",
|
|
function(x,y) if SET then y=0 end
|
|
return "\\"..rty.."("..x..","..round((y+rndm),deci) end)
|
|
:gsub("\\"..rty.."%(([%d.-]+,[%d.-]+,)([%d.-]+),([%d.-]+)",
|
|
function(a,x,y) if SET then y=0 end
|
|
return "\\"..rty.."("..a..x..","..round((y+rndm),deci) end)
|
|
end
|
|
end
|
|
|
|
-- \t times
|
|
if rrez.tt1 then
|
|
text=text:gsub("\\t%((%d+)(,%d+)",function(t1,t2)
|
|
rndm=RVE or ranDoom(rnd)
|
|
if SET then t1=rndm else t1=t1+rndm end
|
|
if t1<0 then t1=0 end
|
|
return "\\t("..t1..t2
|
|
end)
|
|
end
|
|
if rrez.tt2 then
|
|
text=text:gsub("\\t%((%d+,)(%d+)",function(t1,t2)
|
|
rndm=RVE or ranDoom(rnd)
|
|
if SET then t2=rndm else t2=t2+rndm end
|
|
if t2<0 then t2=0 end
|
|
return "\\t("..t1..t2
|
|
end)
|
|
end
|
|
if rrez.tac then
|
|
text=text:gsub("\\t%((%d+,%d+,)(%d+)",function(t1,t2)
|
|
rndm=RVE or ranDoom(rnd)
|
|
if SET then t2=rndm else t2=t2+rndm end
|
|
if t2<0 then t2=0 end
|
|
return "\\t("..t1..t2
|
|
end)
|
|
end
|
|
if text==line.text then fail("No tags to be affected.") end
|
|
end
|
|
|
|
if res.mod=="letterbreak" then
|
|
text=text:gsub("%s*\\N%s*"," ")
|
|
:gsub("^([^{]*)",function(t) return re.sub(t,"([\\w[:punct:]\\s])","\\1\\\\N") end)
|
|
:gsub("}([^{]*)",function(t) return "}"..re.sub(t,"([\\w[:punct:]\\s])","\\1\\\\N") end)
|
|
:gsub("\\N$","")
|
|
if text==line.text then fail("Not enough letters.") end
|
|
end
|
|
|
|
if res.mod=="wordbreak" then
|
|
text=text:gsub(" *$","")
|
|
:gsub("^([^{]*)",function(t) return t:gsub("%s+"," \\N") end)
|
|
:gsub("(}[^{]*)",function(t) return t:gsub("%s+"," \\N") end)
|
|
if text==line.text then fail("Not enough words.") end
|
|
end
|
|
|
|
if res.mod=="[un]hide clip" then
|
|
stags=text:match(STAG) or ""
|
|
stags=trem(stags)
|
|
if stags:match "\\i?clip" then
|
|
for klip in stags:gmatch("\\i?clip%b()") do
|
|
k2=klip:gsub("\\","//")
|
|
stags=stags:gsub(esc(klip),"")
|
|
text=text.."{"..k2.."}"
|
|
end
|
|
elseif text:match "//i?clip" then
|
|
for klip in text:gmatch("//i?clip%b()") do
|
|
k2=klip:gsub("//","\\")
|
|
text=text:gsub(esc(klip),"")
|
|
stags=stags.."{"..k2.."}"
|
|
end
|
|
end
|
|
stags=stags.."{"..trnsfrm.."}"
|
|
stags=stags:gsub("}{","")
|
|
text=stags:gsub("{}","")..text:gsub(STAG,""):gsub("{}","")
|
|
if text==line.text then fail("No clip to be affected.") end
|
|
end
|
|
|
|
if res.mod=="clip info" and subs[i].raw==subs[act].raw then
|
|
local klip=text:match("\\i?clip%(m %-?[%d%.]+ %-?[%d%.]+ l %-?[%d%.]+ %-?[%d%.]+ %-?[%d%.]+ %-?[%d%.]+ %-?[%d%.]+ %-?[%d%.]+%)")
|
|
if not klip then t_error("Vectorial clip with exactly 4 points required on active line. (#"..i-line0..")",1) end
|
|
local K1a,K1b,K2a,K2b,K3a,K3b,K4a,K4b=klip:match("m (%-?[%d%.]+) (%-?[%d%.]+) l (%-?[%d%.]+) (%-?[%d%.]+) (%-?[%d%.]+) (%-?[%d%.]+) (%-?[%d%.]+) (%-?[%d%.]+)")
|
|
points={{x=K1a,y=K1b},{x=K2a,y=K2b},{x=K3a,y=K3b},{x=K4a,y=K4b}}
|
|
table.sort(points,function(a,b) return tonumber(a.x)<tonumber(b.x) end)
|
|
if tonumber(points[1].y)<tonumber(points[2].y) then
|
|
topleft=points[1] bottomleft=points[2]
|
|
else
|
|
bottomleft=points[1] topleft=points[2]
|
|
end
|
|
if tonumber(points[3].y)<tonumber(points[4].y) then
|
|
topright=points[3] bottomright=points[4]
|
|
else
|
|
bottomright=points[3] topright=points[4]
|
|
end
|
|
topwidth=topright.x-topleft.x
|
|
bottomwidth=bottomright.x-bottomleft.x
|
|
leftheight=bottomleft.y-topleft.y
|
|
rightheight=bottomright.y-topright.y
|
|
|
|
wratio1=bottomwidth/topwidth
|
|
if wratio1<1 then wratio=1/wratio1 else wratio=wratio1 end
|
|
wratio=round(wratio,2) or wratio1
|
|
|
|
hratio1=rightheight/leftheight
|
|
if hratio1<1 then hratio=1/hratio1 else hratio=hratio1 end
|
|
hratio=round(hratio,2) or hratio1
|
|
|
|
msg='top width: '..topwidth..'\nmedium width: '..(topwidth+bottomwidth)/2 ..'\nbottom width: '..bottomwidth..
|
|
'\n\nleft height: '..leftheight..'\nmedium height: '..(leftheight+rightheight)/2 ..'\nright height: '..rightheight..
|
|
'\n\ntop/bottom ratio: '..wratio..
|
|
'\nleft/right ratio: '..hratio
|
|
|
|
AX=K2a-K1a
|
|
AY=K2b-K1b
|
|
BX=K4a-K3a
|
|
BY=K4b-K3b
|
|
AA=round(math.sqrt(AX^2+AY^2),2)
|
|
BB=round(math.sqrt(BX^2+BY^2),2)
|
|
msg2='Distance A (1-2): '..AA..
|
|
'\n X: '..AX..'\n Y: '..AY..
|
|
'\nDistance B (3-4): '..BB..
|
|
'\n X: '..BX..'\n Y: '..BY..
|
|
'\n\nratio for B/A A/B'..
|
|
'\ntotal: '..round(BB/AA,2)..' '..round(AA/BB,2)..
|
|
'\nonly X: '..math.abs(round(BX/AX,2))..' '..math.abs(round(AX/BX,2))..
|
|
'\nonly Y: '..math.abs(round(BY/AY,2))..' '..math.abs(round(AY/BY,2))
|
|
|
|
but="Yeah, OK, I got it..."
|
|
CIGUI={
|
|
{x=0,y=0,width=25,class="edit",name="dat",value=klip},
|
|
{x=0,y=1,width=12,height=8,class="textbox",value=msg},
|
|
{x=12,y=1,width=13,height=8,class="textbox",value=msg2},
|
|
{x=0,y=9,width=25,height=3,class="textbox",value='"fsc" will put \\fscx\\fscy tags before last character\nwith values based on the left/right ratio\n(then you can gradient it)'},
|
|
}
|
|
Pr=ADD(CIGUI,{but,"fsc"},{close=but})
|
|
if Pr==but then ak() end
|
|
-- add appropriate scaling before last char
|
|
if Pr=='fsc' then
|
|
sr=stylechk(subs,line.style)
|
|
fscx=text:match("^{[^}]-\\fscx(%d+)") or sr.scale_x
|
|
fscy=text:match("^{[^}]-\\fscy(%d+)") or sr.scale_y
|
|
newX=round(hratio1*fscx)
|
|
newY=round(hratio1*fscy)
|
|
endtag="{\\fscx"..newX.."\\fscy"..newY.."}"
|
|
endc=""
|
|
repeat
|
|
txt,e=text:match("^(.*)({[^}]*})$")
|
|
if e then endc=e..endc text=txt end
|
|
until not text:match("}$")
|
|
text=text:gsub("(.)$",endtag.."%1"):gsub("\\i?clip%b()",""):gsub("{}","")..endc
|
|
end
|
|
end
|
|
|
|
if text~=line.text then relocated=relocated+1 end
|
|
line.text=text
|
|
subs[i]=line
|
|
end
|
|
end
|
|
|
|
function randomise_tag(text,tg,slash)
|
|
slash=slash or '\\'
|
|
text=text:gsub("("..slash..tg..")([%d.-]+)",function(tag,val)
|
|
rndm=RVE or ranDoom(rnd)
|
|
nval=val+rndm
|
|
if SET then nval=rndm end
|
|
if nval<0 and noneg:match(tag) then nval=math.abs(nval) end
|
|
return tag..round(nval,deci)
|
|
end)
|
|
text=text:gsub("("..slash..tg..")(&H%x%x&)",function(tag,val)
|
|
rndm=RVE or ranDoom(rnd)
|
|
val=val:match("&H(%x%x)&")
|
|
nval=(tonumber(val,16))
|
|
nval=round(nval+rndm)
|
|
if SET then nval=round(rndm) end
|
|
if nval<0 then nval=0 end
|
|
if nval>255 then nval=255 end
|
|
nval=tohex(nval)
|
|
return tag.."&H"..nval.."&"
|
|
end)
|
|
return text
|
|
end
|
|
|
|
function ranDoom(rnd)
|
|
rndm=math.random(-100,100)/100*rnd
|
|
if not rrez.rpos and rndm>0 then rndm=0-rndm end
|
|
if not rrez.rneg and rndm<0 then rndm=0-rndm end
|
|
return rndm
|
|
end
|
|
|
|
function movetofbf(subs,sel)
|
|
fra={}
|
|
for z=#sel,1,-1 do
|
|
i=sel[z]
|
|
progress("Dissecting line... #"..i-line0.." ["..#sel+1-z.."/"..#sel.."]")
|
|
line=subs[i]
|
|
text=line.text
|
|
styleref=stylechk(subs,line.style)
|
|
start=line.start_time
|
|
endt=line.end_time
|
|
startf=ms2fr(start)
|
|
endf=ms2fr(endt)
|
|
frames=endf-1-startf
|
|
if frames<0 then t_error("Line #"..i-line0.." is shorther than 1 frame.\nAborting.",1) end
|
|
frnum=frames
|
|
table.insert(fra,frnum)
|
|
l2=line
|
|
frdiff=(fr2ms(startf+1)-fr2ms(startf))/2
|
|
-- Real Start, End, Duration
|
|
RS=fr2ms(startf)
|
|
RE=fr2ms(endf)
|
|
RD=RE-RS
|
|
|
|
for frm=endf-1,startf,-1 do
|
|
l2.text=text
|
|
-- move
|
|
if text:match("\\move") then
|
|
m1,m2,m3,m4=text:match("\\move%(([%d.-]+),([%d.-]+),([%d.-]+),([%d.-]+)")
|
|
mvstart,mvend=text:match("\\move%([%d.-]+,[%d.-]+,[%d.-]+,[%d.-]+,([%d.-]+),([%d.-]+)")
|
|
if mvstart==nil then mvstart=0 end
|
|
if mvend==nil then mvend=RD end
|
|
moffset=mvstart
|
|
CS=fr2ms(startf+frnum)
|
|
frcount=CS-RS
|
|
mlimit=tonumber(mvend)
|
|
mpart=frcount-tonumber(mvstart)+frdiff
|
|
mwhole=mvend-mvstart
|
|
pos1=round((((m3-m1)/mwhole)*mpart+m1),2)
|
|
pos2=round((((m4-m2)/mwhole)*mpart+m2),2)
|
|
xdiff=pos1-m1 ydiff=pos2-m2
|
|
if mpart<0 then pos1=m1 pos2=m2 end
|
|
if mpart>mlimit-moffset then pos1=m3 pos2=m4 end
|
|
l2.text=text:gsub("\\move%([^%)]*%)","\\pos("..pos1..","..pos2..")")
|
|
if res.c2fbf and frm>1 then
|
|
l2.text=l2.text:gsub("(\\i?clip%()([^%)]*)%)",function(kl,ip)
|
|
ip=ip:gsub("([%d.-]+),([%d.-]+),([%d.-]+),([%d.-]+)",function(a,b,c,d)
|
|
return a+xdiff..","..b+ydiff..","..c+xdiff..","..d+ydiff end)
|
|
:gsub("([%d.-]+) ([%d.-]+)",function(a,b)
|
|
return round(a+xdiff).." "..round(b+ydiff) end)
|
|
return kl..ip..")" end)
|
|
end
|
|
end
|
|
-- fade
|
|
if text:match("\\fad%(") then
|
|
l2.text=l2.text:gsub("\\t%b()",function(t) return t:gsub("\\","|") end)
|
|
f1,f2=text:match("\\fad%(([%d%.]+),([%d%.]+)")
|
|
linealfa=text:match("^{[^}]-\\alpha(&H%x%x&)") or "&H00&"
|
|
l2.text=l2.text
|
|
:gsub("^({[^}]-)\\alpha&H%x%x&","%1")
|
|
:gsub("{(.-)\\fad%b()(.-)}","{\\alpha&HFF&%1%2\\t(0,"..f1..",\\alpha"..linealfa..")\\t("..RD-f2..",0,\\alpha&HFF&)}")
|
|
:gsub("(.){(.-)(\\alpha&H%x%x&)(.-)}","%1{%2\\alpha&HFF&\\t(0,"..f1..",%3)\\t("..RD-f2..",0,\\alpha&HFF&)%4}")
|
|
if f1=='0' then l2.text=l2.text:gsub("{\\alpha&HFF&","{") end
|
|
for c=1,4 do
|
|
l2.text,c=l2.text:gsub("{(.-)(\\"..c.."a)(&H%x%x&)(.-)}","{%1%2&HFF&\\t(0,"..f1..",%2%3)\\t("..RD-f2..",0,%2&HFF&)%4}")
|
|
end
|
|
l2.text=l2.text:gsub("|","\\")
|
|
end
|
|
|
|
lastags2=""
|
|
l2.text=l2.text:gsub(ATAG,function(tg) return cleantr(tg) end)
|
|
:gsub(ATAG,function(tg) if tg:match("\\t") then return terraform(tg) else return tg end end)
|
|
|
|
l2.start_time=fr2ms(frm)
|
|
l2.end_time=fr2ms(frm+1)
|
|
subs.insert(i+1,l2)
|
|
frnum=frnum-1
|
|
end
|
|
line.end_time=endt
|
|
line.comment=true
|
|
relocated=relocated+1
|
|
line.text=text
|
|
subs[i]=line
|
|
if res.delfbf then subs.delete(i) end
|
|
end
|
|
-- selection
|
|
sel2={}
|
|
if res.delfbf then fakt=0 else fakt=1 end
|
|
for s=#sel,1,-1 do
|
|
sfr=fra[#sel-s+1]
|
|
-- shift new sel
|
|
for s2=#sel2,1,-1 do sel2[s2]=sel2[s2]+sfr+fakt end
|
|
-- add to new sel
|
|
for f=1,sfr+fakt do table.insert(sel2,sel[s]+f) end
|
|
-- add orig line
|
|
if res.delfbf then table.insert(sel2,sel[s]) end
|
|
end
|
|
sel=sel2
|
|
return sel
|
|
end
|
|
|
|
function terraform(tags)
|
|
ftags=""
|
|
lastags1=""
|
|
for tra in tags:gmatch("(\\t%b())") do
|
|
trstart=0 trend=RD acc=1
|
|
trtimes=tra:match("\\t%(([%d,%.]*)") _,ttt=trtimes:gsub(",","")
|
|
if ttt==1 then acc=tra:match("([%d%.]+)") end
|
|
if ttt==2 then trstart,trend=tra:match("(%d+),(%d+),") end
|
|
if ttt==3 then trstart,trend,acc=tra:match("(%d+),(%d+),([%d%.]+),") end
|
|
if trend=="0" then trend=RD end
|
|
toffset=trstart
|
|
CS=fr2ms(startf+frnum)
|
|
frcount=CS-RS
|
|
tlimit=tonumber(trend)
|
|
tpart=frcount-tonumber(trstart)+frdiff
|
|
twhole=trend-trstart
|
|
nontra=tags:gsub("\\t%b()","")
|
|
acc_fac=(tpart-1)^acc/(twhole-1)^acc
|
|
-- most tags
|
|
for tg, valt in tra:gmatch("\\(%a+)([%d.-]+)") do
|
|
val1=nil
|
|
if nontra:match("^{[^}]-\\"..tg) then val1=nontra:match("^{[^}]-\\"..tg.."([%d.-]+)") end
|
|
if lastags2:match("\\"..tg) then val1=lastags2:match("\\"..tg.."([%d.-]+)") end
|
|
if nontra:match("\\"..tg) then val1=nontra:match("\\"..tg.."([%d.-]+)") end
|
|
if lastags1:match("\\"..tg) then val1=lastags1:match("\\"..tg.."([%d.-]+)") end
|
|
if val1==nil then
|
|
if tg=="bord" or tg=="xbord" or tg=="ybord" then val1=styleref.outline end
|
|
if tg=="shad" or tg=="xshad" or tg=="yshad" then val1=styleref.shadow end
|
|
if tg=="fs" then val1=styleref.fontsize end
|
|
if tg=="fsp" then val1=styleref.spacing end
|
|
if tg=="frz" then val1=styleref.angle end
|
|
if tg=="fscx" then val1=styleref.scale_x end
|
|
if tg=="fscy" then val1=styleref.scale_y end
|
|
if tg=="blur" or tg=="be" or tg=="fax" or tg=="fay" or tg=="frx" or tg=="fry" then val1=0 end
|
|
end
|
|
valf=round(acc_fac*(valt-val1)+val1,2)
|
|
if tpart<0 then valf=val1 end
|
|
if tpart>tlimit-toffset then valf=valt end
|
|
ftags=ftags.."\\"..tg..valf
|
|
--logg("\n val1: "..val1.." valf: "..valf.." tpart: "..tpart.." twhole: "..twhole)
|
|
end
|
|
-- clip
|
|
if tra:match("\\i?clip%([%d%-]") then
|
|
ctype,c1,c2,c3,c4=nontra:match("(\\i?clip%()([%d.-]+),([%d.-]+),([%d.-]+),([%d.-]+)")
|
|
if not ctype then t_error("Error. Looks like you're transforming a clip that's not set in the first place.\n> "..tags,1) end
|
|
ktype,k1,k2,k3,k4=tra:match("(\\i?clip%()([%d.-]+),([%d.-]+),([%d.-]+),([%d.-]+)")
|
|
tc1=round((((k1-c1)/twhole)*tpart+c1),2)
|
|
tc2=round((((k2-c2)/twhole)*tpart+c2),2)
|
|
tc3=round((((k3-c3)/twhole)*tpart+c3),2)
|
|
tc4=round((((k4-c4)/twhole)*tpart+c4),2)
|
|
if tpart<0 then tc1=c1 tc2=c2 tc3=c3 tc4=c4 end
|
|
if tpart>tlimit-toffset then tc1=k1 tc2=k2 tc3=k3 tc4=k4 end
|
|
ftags=ftags..ktype..tc1..","..tc2..","..tc3..","..tc4..")"
|
|
end
|
|
-- colour/alpha
|
|
tra=tra:gsub("\\1c","\\c")
|
|
nontra=nontra:gsub("\\1c","\\c")
|
|
for tg, valt in tra:gmatch("\\(%w+)(&H%x+&)") do
|
|
val1=nil
|
|
if nontra:match("^{[^}]-\\"..tg.."&") then val1=nontra:match("^{[^}]-\\"..tg.."(&H%x+&)") end
|
|
if lastags2:match("\\"..tg) then val1=lastags2:match("\\"..tg.."(&H%x+&)") end
|
|
if nontra:match("\\"..tg) then val1=nontra:match("\\"..tg.."(&H%x+&)") end
|
|
if lastags1:match("\\"..tg) then val1=lastags1:match("\\"..tg.."(&H%x+&)") end
|
|
if val1==nil then
|
|
if tg=="c" then val1=styleref.color1:gsub("H%x%x","H") end
|
|
if tg=="2c" then val1=styleref.color2:gsub("H%x%x","H") end
|
|
if tg=="3c" then val1=styleref.color3:gsub("H%x%x","H") end
|
|
if tg=="4c" then val1=styleref.color4:gsub("H%x%x","H") end
|
|
if tg=="1a" then val1=styleref.color1:gsub("(H%x%x)%x%x%x%x%x%x","%1") end
|
|
if tg=="2a" then val1=styleref.color2:gsub("(H%x%x)%x%x%x%x%x%x","%1") end
|
|
if tg=="3a" then val1=styleref.color3:gsub("(H%x%x)%x%x%x%x%x%x","%1") end
|
|
if tg=="4a" then val1=styleref.color4:gsub("(H%x%x)%x%x%x%x%x%x","%1") end
|
|
if tg=="alpha" then val1="&H00&" end
|
|
end
|
|
valf=acgrad(val1,valt,twhole,tpart,acc)
|
|
if tpart<0 then valf=val1 end
|
|
if tpart>tlimit-toffset then valf=valt end
|
|
ftags=ftags.."\\"..tg..valf
|
|
end
|
|
lastags1=lastags1..ftags
|
|
lastags1=duplikill(lastags1)
|
|
end
|
|
lastags2=lastags2..ftags
|
|
lastags2=duplikill(lastags2)
|
|
tags=tags:gsub("\\t%b()","") :gsub("^({[^}]*)}","%1"..ftags.."}")
|
|
tags=duplikill(tags)
|
|
return tags
|
|
end
|
|
|
|
function joinfbflines(subs,sel)
|
|
join=round(res.force)
|
|
if join<2 then t_error("Minimum of lines to join is 2.\nUse the Force field at the bottom left to enter a number.",1) end
|
|
count=1
|
|
for z,i in ipairs(sel) do
|
|
line=subs[i]
|
|
line.effect=count
|
|
if z==1 then line.effect="1" end
|
|
subs[i]=line
|
|
count=count+1
|
|
if count>join then count=1 end
|
|
end
|
|
-- delete & time
|
|
total=#sel
|
|
for z=#sel,1,-1 do
|
|
i=sel[z]
|
|
line=subs[i]
|
|
if line.effect==tostring(join) then endtime=line.end_time end
|
|
if z==total then endtime=line.end_time end
|
|
if line.effect=="1" then line.end_time=endtime line.effect="" subs[i]=line relocated=relocated+1
|
|
else subs.delete(i) table.remove(sel,#sel) relocated=relocated+1 end
|
|
end
|
|
return sel
|
|
end
|
|
|
|
function rotinhell()
|
|
if not res.frx and not res.fry and not res.frz then t_error("No rotations selected.\nCheck at least one of frx/fry/frz.",1) end
|
|
end
|
|
|
|
function negative(text,m,rot)
|
|
text=text:gsub(rot.."([%d%.]+)",function(r) if tonumber(r)>m then return rot..round((r-360),3) end end)
|
|
return text
|
|
end
|
|
|
|
function frz_redraw(t,rota,draw,sr)
|
|
local X,Y,x,y,width,height
|
|
local ox,oy,xmx,xmn,ymx,ymn,addx,addy=0,0,0,999999,0,999999,0,0
|
|
draw1=draw
|
|
-- deal with align other than 7
|
|
if align~=7 then
|
|
for px,py in draw:gmatch("([-%d.]+) ([-%d.]+)") do
|
|
px=tonumber(px)
|
|
py=tonumber(py)
|
|
if px>xmx then xmx=px end
|
|
if px<xmn then xmn=px end
|
|
if py>ymx then ymx=py end
|
|
if py<ymn then ymn=py end
|
|
end
|
|
width=xmx-xmn
|
|
height=ymx-ymn
|
|
align=tonumber(t:match'\\an(%d)') or sr.align
|
|
hal=align%3
|
|
val=math.ceil(align/3)
|
|
if hal==2 then addx=width/2 elseif hal==0 then addx=width end
|
|
if val==2 then addy=height/2 elseif val==1 then addy=height end
|
|
-- change to an7 + adjust coordinates
|
|
draw1=draw1:gsub("([-%d.]+) ([-%d.]+)",function(px,py)
|
|
return px-addx..' '..py-addy
|
|
end)
|
|
t,c=t:gsub("\\an%d","\\an7")
|
|
if c==0 then t=t:gsub("^{","{\\an7") end
|
|
end
|
|
|
|
-- recalculate coordinates without frz
|
|
draw2=draw1:gsub("([-%d.]+) ([-%d.]+)",function(px,py)
|
|
h=math.sqrt((ox-px)^2+(oy-py)^2)
|
|
pox=ox-px
|
|
poy=oy-py
|
|
tang=poy/pox
|
|
ang1=math.deg(math.atan(tang))
|
|
ang=ang1-rota
|
|
X=math.cos(math.rad(ang))*h
|
|
Y=math.sin(math.rad(ang))*h
|
|
if pox<0 then X=0-X Y=0-Y end
|
|
x=round(ox-X)
|
|
y=round(oy-Y)
|
|
return x..' '..y
|
|
end)
|
|
|
|
-- replace drawing
|
|
t=t:gsub(esc(draw),draw2):gsub("\\frz[-%d.]+","")
|
|
return t
|
|
end
|
|
|
|
function spindoc(subs,sel)
|
|
local G={
|
|
{x=0,y=0,class="label",label="Tag to mess with:"},
|
|
{x=0,y=1,class="label",label="Regular step:"},
|
|
{x=0,y=2,class="label",label="fax/fay step:"},
|
|
{x=1,y=0,class="dropdown",name="spin",items={'frz','frx','fry','fax','fay','xshad','yshad','fsp'},value=spin or 'frz'},
|
|
{x=1,y=1,class="floatedit",name="rot",min=0,value=sdr or 1},
|
|
{x=1,y=2,class="floatedit",name="fax",min=0,value=sdf or 0.01},
|
|
{x=0,y=3,width=2,height=4,class="textbox",value="These are settings for the Spin macros. Choose a tag you want to affect with them and step. Default (without loading this GUI) is frz & 1."},
|
|
}
|
|
SP,rez=aegisub.dialog.display(G,{'OK','Good'},{ok='OK',close='Good'})
|
|
spin=rez.spin
|
|
sdr=rez.rot
|
|
sdf=rez.fax
|
|
end
|
|
|
|
function transclip(subs,sel,act)
|
|
line=subs[act]
|
|
text=line.text
|
|
if not text:match("\\i?clip%([%d.-]+,") then t_error("Error: rectangular clip required on active line.",1) end
|
|
ctype,cc1,cc2,cc3,cc4=text:match("(\\i?clip)%(([%d.-]+),([%d.-]+),([%d.-]+),([%d.-]+)%)")
|
|
clipconfig={
|
|
{x=0,y=0,width=2,class="label",label=" \\clip("},
|
|
{x=2,y=0,width=3,class="edit",name="orclip",value=cc1..","..cc2..","..cc3..","..cc4},
|
|
{x=5,y=0,class="label",label=")"},
|
|
{x=0,y=1,width=2,class="label",label="\\t(\\clip("},
|
|
{x=2,y=1,width=3,class="edit",name="klip",value=cc1..","..cc2..","..cc3..","..cc4},
|
|
{x=5,y=1,class="label",label=")"},
|
|
{x=0,y=2,width=5,class="label",label="Move x and y for new coordinates by:"},
|
|
{x=0,y=3,class="label",label="x:"},
|
|
{x=3,y=3,class="label",label="y:"},
|
|
{x=1,y=3,width=2,class="floatedit",name="eks"},
|
|
{x=4,y=3,class="floatedit",name="wai"},
|
|
{x=0,y=4,width=5,class="label",label="Start / end / accel:"},
|
|
{x=2,y=5,width=2,class="edit",name="accel",value="0,0,1,"},
|
|
{x=4,y=5,class="checkbox",name="two",label="use next line's clip",hint="use clip from the next line (line will be deleted)"},
|
|
}
|
|
buttons={"Transform","Calculate coordinates","Cancel"}
|
|
repeat
|
|
if TCP=="Calculate coordinates" then
|
|
xx=rez.eks yy=rez.wai
|
|
for key,v in ipairs(clipconfig) do
|
|
if v.name=="klip" then v.value=round(cc1+xx,3)..","..round(cc2+yy,3)..","..round(cc3+xx,3)..","..round(cc4+yy,3) end
|
|
if v.name=="accel" then v.value=rez.accel end
|
|
end
|
|
end
|
|
TCP,rez=ADD(clipconfig,buttons,{ok='Transform',close='Cancel'})
|
|
if TCP=="Cancel" then ak() end
|
|
until TCP~="Calculate coordinates"
|
|
if TCP=="Transform" then newcoord=rez.klip end
|
|
|
|
if rez.two then
|
|
nextline=subs[act+1]
|
|
nextext=nextline.text
|
|
if not nextext:match("\\i?clip%([%d.-]+,") then t_error("Error: second line must contain a rectangular clip.",1)
|
|
else
|
|
nextclip=nextext:match("\\i?clip%(([%d%.%-,]+)%)")
|
|
text=text:gsub("^({\\[^}]*)}","%1\\t("..rez.accel..ctype.."("..nextclip.."))}")
|
|
end
|
|
else
|
|
text=text:gsub("^({\\[^}]*)}","%1\\t("..rez.accel..ctype.."("..newcoord.."))}")
|
|
end
|
|
|
|
text=text:gsub("0,0,1,\\","\\")
|
|
if line.text~=text then relocated=relocated+1 end
|
|
if seln>1 then fail("Only active line is affected.") end
|
|
line.text=text
|
|
subs[act]=line
|
|
if rez.two then subs.delete(act+1) end
|
|
end
|
|
|
|
function clone(subs,sel)
|
|
local shift
|
|
xx=res.eks yy=res.wai
|
|
if xx~=0 or yy~=0 then shift=true end
|
|
for z,i in ipairs(sel) do
|
|
progress("Cloning... #"..i-line0.." ["..z.."/"..#sel.."]")
|
|
line=subs[i]
|
|
text=line.text
|
|
nopos=nil
|
|
poss=text:match("\\pos%b()")
|
|
if not poss then nopos=1 end
|
|
|
|
if not text:match("^{\\") then text=text:gsub("^","{\\clone}") end
|
|
|
|
if res.cpos then
|
|
if z==1 then
|
|
move=text:match("\\move%(([^%)]-)%)")
|
|
mov=move
|
|
if nopos and not move then text=getpos(subs,text) else fail("First line won't be changed.") end
|
|
posi=text:match("\\pos%(([^%)]-)%)")
|
|
pos=posi
|
|
end
|
|
if shift and z>1 then
|
|
pos=cl_shift(posi,xx*(z-1),yy*(z-1))
|
|
mov=cl_shift(move,xx*(z-1),yy*(z-1))
|
|
end
|
|
if z>1 and text:match("\\pos") and pos then text=text:gsub("\\pos%b()","\\pos("..pos..")") end
|
|
if z>1 and nopos and not text:match("\\move") and pos and res.cre then
|
|
text=text:gsub("^{\\","{\\pos%("..pos.."%)\\") end
|
|
if z>1 and text:match("\\move") and mov then text=text:gsub("\\move%b()","\\move("..mov..")") end
|
|
if z>1 and not text:match("\\move") and nopos and mov and res.cre then
|
|
text=text:gsub("^{\\","{\\move("..mov..")\\") end
|
|
if z>1 and text==line.text then fail("Some lines already in position") end
|
|
end
|
|
|
|
if res.corg then
|
|
if z==1 then orig=text:match("\\org%(([^%)]-)%)") org=orig end
|
|
if not orig then fail("\\org not present on first line.") end
|
|
if z>1 and orig then
|
|
org=cl_shift(orig,xx*(z-1),yy*(z-1))
|
|
if text:match("\\org") then text=text:gsub("\\org%b()","\\org("..org..")")
|
|
elseif res.cre then text=text:gsub("^({\\[^}]*)}","%1\\org("..org..")}") end
|
|
end
|
|
end
|
|
|
|
if res.copyrot then
|
|
if z==1 then rotz=text:match("\\frz([%d.-]+)") rotx=text:match("\\frx([%d.-]+)") roty=text:match("\\fry([%d.-]+)") end
|
|
if not rotz or not rotx or not roty then fail("Some rotations not present on first line.") end
|
|
if z>1 then
|
|
if rotz then if res.cre then text=addtag3("\\frz"..rotz,text)
|
|
else text=text:gsub("^({[^}]-\\frz)[%d.-]+","%1"..rotz) end end
|
|
if rotx then if res.cre then text=addtag3("\\frx"..rotx,text)
|
|
else text=text:gsub("^({[^}]-\\frx)[%d.-]+","%1"..rotx) end end
|
|
if roty then if res.cre then text=addtag3("\\fry"..roty,text)
|
|
else text=text:gsub("^({[^}]-\\fry)[%d.-]+","%1"..roty) end end
|
|
end
|
|
end
|
|
|
|
if res.cclip then
|
|
-- line 1 - copy
|
|
if z==1 then
|
|
ik,klip=text:match("\\(i?)clip%(([^%)]-)%)")
|
|
klipp=klip
|
|
if klip and klip:match("m") then type1="vector" else type1="normal" end
|
|
end
|
|
if not klip then fail("\\clip not present on first line.") end
|
|
-- lines 2+ - paste / replace
|
|
if shift and z>1 then
|
|
klip=cl_shift(klipp,xx*(z-1),yy*(z-1))
|
|
end
|
|
if z>1 and text:match("\\i?clip") and klip then
|
|
org=cl_shift(orig,xx*(z-1),yy*(z-1))
|
|
ik2,klip2=text:match("\\(i?)clip%(([^%)]-)%)")
|
|
if res.klipmatch then kmatch=ik else kmatch=ik2 end
|
|
if klip2:match("m") then type2="vector" klipv=klip2 else type2="normal" end
|
|
if text:match("\\(i?)clip.-\\(i?)clip") then doubleclip=true ikv,klipv=text:match("\\(i?)clip%((%d?,?m[^%)]-)%)")
|
|
else doubleclip=false end
|
|
if res.combine and type1=="vector" and text:match("\\(i?clip)%(%d?,?m[^%)]-%)") then nklip=klipv.." "..klip else nklip=klip end
|
|
-- 1 clip, stack
|
|
if res.stack and type1~=type2 and not doubleclip then
|
|
text=text:gsub("^({\\[^}]*)}","%1\\"..ik.."clip%("..nklip.."%)}")
|
|
-- 2 clips -> not stack
|
|
elseif doubleclip then
|
|
if type1=="normal" then text=text:gsub("\\(i?clip)%([%d%.,%-]-%)","\\%1%("..nklip.."%)") end
|
|
if type1=="vector" then text=text:gsub("\\(i?clip)%(%d?,?m[^%)]-%)","\\%1%("..nklip.."%)") end
|
|
-- 1 clip, not stack
|
|
elseif type1==type2 and not doubleclip or not res.stack and not doubleclip then
|
|
text=text:gsub("\\i?clip%([^%)]-%)","\\"..kmatch.."clip%("..nklip.."%)")
|
|
end
|
|
end
|
|
-- lines 2+ / paste / create
|
|
if z>1 and not text:match("\\i?clip") and klip and res.cre then
|
|
text=text:gsub("^({\\[^}]*)}","%1\\"..ik.."clip%("..klip.."%)}")
|
|
end
|
|
end
|
|
|
|
if res.ctclip then
|
|
if z==1 then tklip=text:match("\\t%([%d%.,]*\\i?clip%(([^%)]-)%)") end
|
|
if z>1 and text:match("\\i?clip") and tklip then
|
|
text=text:gsub("\\t%(([%d%.,]*)\\(i?clip)%([^%)]-%)","\\t%(%1\\%2%("..tklip.."%)") end
|
|
if z>1 and not text:match("\\t%([%d%.,]*\\i?clip") and tklip and res.cre then
|
|
text=text:gsub("^({\\[^}]*)}","%1\\t%(\\clip%("..tklip.."%)%)}") end
|
|
end
|
|
|
|
text=text:gsub("\\clone",""):gsub("{}","")
|
|
if line.text~=text then relocated=relocated+1 end
|
|
line.text=text
|
|
subs[i]=line
|
|
end
|
|
end
|
|
|
|
function cl_shift(coord,X,Y)
|
|
if not coord then return nil end
|
|
coord=coord:gsub("([%-%d.]+),([%-%d.]+)",function(x,y)
|
|
return x+X..','..y+Y
|
|
end,2)
|
|
if coord:match "m" then
|
|
coord=coord:gsub("([%-%d.]+) ([%-%d.]+)",function(x,y)
|
|
return x+X..' '..y+Y
|
|
end)
|
|
end
|
|
return coord
|
|
end
|
|
|
|
function teleport(subs,sel)
|
|
if not ak then cuts(subs,sel) end
|
|
tpfx=0 tpfy=0
|
|
if res.warp then
|
|
telemod={
|
|
{x=2,y=0,class="label",label=" Warped Teleportation"},
|
|
{x=2,y=1,class="floatedit",name="eggs",hint="X"},
|
|
{x=2,y=2,class="floatedit",name="why",hint="Y"},
|
|
{x=2,y=3,class="checkbox",name="fram",label="by frame, not by line",hint="by frame instead of by line - for layered signs"}
|
|
}
|
|
tP,rez=ADD(telemod,{"Warped Teleport","Disintegrate"},{ok='Warped Teleport',close='Disintegrate'})
|
|
if tP=="Disintegrate" then ak() end
|
|
tpfx=rez.eggs tpfy=rez.why fram=rez.fram
|
|
if fram then
|
|
FR={}
|
|
for z,i in ipairs(sel) do
|
|
line=subs[i]
|
|
sfr=ms2fr(line.start_time)
|
|
table.insert(FR,sfr)
|
|
end
|
|
table.sort(FR)
|
|
for z=#FR,1,-1 do if FR[z]==FR[z-1] then table.remove(FR,z) end end
|
|
end
|
|
end
|
|
for z,i in ipairs(sel) do
|
|
progress("Teleporting... #"..i-line0.." ["..z.."/"..#sel.."]")
|
|
line=subs[i]
|
|
text=line.text
|
|
style=line.style
|
|
nopos=nil
|
|
poss=text:match("\\pos%b()")
|
|
if not poss then nopos=1 end
|
|
xx=res.eks
|
|
yy=res.wai
|
|
if xx==0 and yy==0 then fail("Distance given was zero.") end
|
|
zT=z
|
|
if fram then sfr=ms2fr(line.start_time)
|
|
for f=1,#FR do if sfr==FR[f] then zT=f break end end
|
|
end
|
|
fx=tpfx*(zT-1)
|
|
fy=tpfy*(zT-1)
|
|
|
|
if res.tppos then
|
|
if res.autopos and nopos and not text:match("\\move") then text=getpos(subs,text) end
|
|
text=text:gsub("\\pos%(([%d.-]+),([%d.-]+)%)",function(a,b) return "\\pos("..a+xx+fx..","..b+yy+fy..")" end)
|
|
end
|
|
|
|
if res.tporg then
|
|
text=text:gsub("\\org%(([%d.-]+),([%d.-]+)%)",function(a,b) return "\\org("..a+xx+fx..","..b+yy+fy..")" end)
|
|
end
|
|
|
|
if res.tpmov then
|
|
text=text:gsub("\\move%(([%d.-]+),([%d.-]+),([%d.-]+),([%d.-]+)",
|
|
function(a,b,c,d) return "\\move("..a+xx+fx..","..b+yy+fy..","..c+xx+fx..","..d+yy+fy end)
|
|
end
|
|
|
|
if res.tpclip then
|
|
text=text:gsub("clip%(([%d.-]+),([%d.-]+),([%d.-]+),([%d.-]+)",function(a,b,c,d)
|
|
xd=xx+fx yd=yy+fy
|
|
if res.tpexp then a=a-xd b=b-yd elseif res.tpc1 then a=a+xd b=b+yd end
|
|
if res.tpexp or res.tpc2 then c=c+xd d=d+yd end
|
|
return "clip("..a..","..b..","..c..","..d end)
|
|
|
|
if text:match("clip%(m [%d%a%s%-%.]+%)") then
|
|
ctext=text:match("clip%(m ([%d%a%s%-%.]+)%)")
|
|
ctext2=ctext:gsub("([%d%-%.]+)%s([%d%-%.]+)",function(a,b) return a+xx+fx.." "..b+yy+fy end)
|
|
ctext=ctext:gsub("%-","%%-")
|
|
text=text:gsub("clip%(m "..ctext,"clip(m "..ctext2)
|
|
end
|
|
|
|
if text:match("clip%(%d+,m [%d%a%s%-%.]+%)") then
|
|
fac,ctext=text:match("clip%((%d+),m ([%d%a%s%-%.]+)%)")
|
|
factor=2^(fac-1)
|
|
ctext2=ctext:gsub("([%d%-%.]+)%s([%d%-%.]+)",function(a,b) return a+factor*xx+fx.." "..b+factor*yy+fy end)
|
|
ctext=ctext:gsub("%-","%%-")
|
|
text=text:gsub(",m "..ctext,",m "..ctext2)
|
|
end
|
|
end
|
|
|
|
if res.tpmask then
|
|
draw=text:match("}m ([^{]+)")
|
|
draw2=draw:gsub("([%d.-]+) ([%d.-]+)",function(a,b) return round(a+xx+fx).." "..round(b+yy+fy) end)
|
|
draw=esc(draw)
|
|
text=text:gsub("(}m )"..draw,"%1"..draw2)
|
|
end
|
|
|
|
if text~=line.text then relocated=relocated+1 end
|
|
text=roundpar(text,2)
|
|
line.text=text
|
|
subs[i]=line
|
|
end
|
|
end
|
|
|
|
|
|
-- reanimatools ----------------------------------------------------------
|
|
function esc(str) str=str:gsub("[%%%(%)%[%]%.%-%+%*%?%^%$]","%%%1") return str end
|
|
function round(n,dec) dec=dec or 0 n=math.floor(n*10^dec+0.5)/10^dec return n end
|
|
function rnd3(n) n=math.floor(n*10^3+0.5)/10^3 return n end
|
|
function wrap(str) return "{"..str.."}" end
|
|
function detra(t) return t:gsub("\\t%b()","") end
|
|
function nobra(t) return t:gsub("%b{}","") end
|
|
function nobrea(t) return t:gsub("%b{}",""):gsub("\\[Nh]","") end
|
|
function nobrea1(t) return t:gsub("%b{}",""):gsub(" *\\[Nh] *"," ") end
|
|
function tagmerge(t) repeat t,r=t:gsub("({\\[^}]-)}{(\\[^}]-})","%1%2") until r==0 return t end
|
|
function progress(msg) if aegisub.progress.is_cancelled() then ak() end aegisub.progress.title(msg) end
|
|
function t_error(message,cancel) ADD({{class="label",label=message}},{"OK"},{close='OK'}) if cancel then ak() end end
|
|
function logg(m) m=tf(m) or "nil" aegisub.log("\n "..m) end
|
|
function logg2(m)
|
|
local lt=type(m)
|
|
aegisub.log("\n >> "..lt)
|
|
if lt=='table' then
|
|
aegisub.log(" (#"..#m..")")
|
|
if not m[1] then
|
|
for k,v in pairs(m) do
|
|
if type(v)=='table' then vvv='[table]' elseif type(v)=='number' then vvv=v..' (n)' elseif type(v)=='boolean' then vvv=tf(v) else vvv=v end
|
|
aegisub.log("\n "..k..': '..vvv)
|
|
end
|
|
elseif type(m[1])=='table' then aegisub.log("\n nested table")
|
|
else aegisub.log("\n {"..table.concat(m,', ').."}") end
|
|
else
|
|
m=tf(m) or "nil" aegisub.log("\n "..m)
|
|
end
|
|
end
|
|
function loggtab(m) m=tf(m) or "nil" aegisub.log("\n {"..table.concat(m,';').."}") end
|
|
|
|
function addtag(tag,text) text=text:gsub("^({\\[^}]-)}","%1"..tag.."}") return text end
|
|
|
|
function addtag3(tg,txt)
|
|
no_tf=txt:gsub("\\t%b()","")
|
|
tgt=tg:match("(\\%d?%a+)[%d%-&]") val="[%d%-&]"
|
|
if not tgt then tgt=tg:match("(\\%d?%a+)%b()") val="%b()" end
|
|
if not tgt then tgt=tg:match("\\fn") val="" end
|
|
if not tgt then t_error("adding tag '"..tg.."' failed.") end
|
|
if tgt:match("clip") then txt,r=txt:gsub("^({[^}]-)\\i?clip%b()","%1"..tg)
|
|
if r==0 then txt=txt:gsub("^({\\[^}]-)}","%1"..tg.."}") end
|
|
elseif no_tf:match("^({[^}]-)"..tgt..val) then txt=txt:gsub("^({[^}]-)"..tgt..val.."[^\\}]*","%1"..tg)
|
|
elseif not txt:match("^{\\") then txt="{"..tg.."}"..txt
|
|
elseif txt:match("^{[^}]-\\t") then txt=txt:gsub("^({[^}]-)\\t","%1"..tg.."\\t")
|
|
else txt=txt:gsub("^({\\[^}]-)}","%1"..tg.."}") end
|
|
return txt
|
|
end
|
|
|
|
function round4(a,b,c,d,dec)
|
|
if not dec then dec=1 end
|
|
a=math.floor(a*dec+0.5)/dec
|
|
b=math.floor(b*dec+0.5)/dec
|
|
c=math.floor(c*dec+0.5)/dec
|
|
d=math.floor(d*dec+0.5)/dec
|
|
return a,b,c,d
|
|
end
|
|
|
|
function roundpar(text,dec)
|
|
text=text:gsub("(\\%a%a+)(%b())",function(a,b) return a..b:gsub("([%d.-]+)",function(c) return round(c,dec) end) end)
|
|
return text
|
|
end
|
|
|
|
function getpos(subs,text)
|
|
st=nil defst=nil
|
|
for g=1,#subs do
|
|
if subs[g].class=="info" then
|
|
local k=subs[g].key
|
|
local v=subs[g].value
|
|
if k=="PlayResX" then resx=v end
|
|
if k=="PlayResY" then resy=v end
|
|
end
|
|
if resx==nil then resx=0 end
|
|
if resy==nil then resy=0 end
|
|
if subs[g].class=="style" then
|
|
local s=subs[g]
|
|
if s.name==line.style then st=s break end
|
|
if s.name=="Default" then defst=s end
|
|
end
|
|
if subs[g].class=="dialogue" then
|
|
if defst then st=defst else t_error("Style '"..line.style.."' not found.\nStyle 'Default' not found. ",1) end
|
|
break
|
|
end
|
|
end
|
|
if st then
|
|
acleft=st.margin_l if line.margin_l>0 then acleft=line.margin_l end
|
|
acright=st.margin_r if line.margin_r>0 then acright=line.margin_r end
|
|
acvert=st.margin_t if line.margin_t>0 then acvert=line.margin_t end
|
|
acalign=st.align if text:match("\\an%d") then acalign=text:match("\\an(%d)") end
|
|
aligntop="789" alignbot="123" aligncent="456"
|
|
alignleft="147" alignright="369" alignmid="258"
|
|
if alignleft:match(acalign) then horz=acleft
|
|
elseif alignright:match(acalign) then horz=resx-acright
|
|
elseif alignmid:match(acalign) then horz=resx/2 end
|
|
if aligntop:match(acalign) then vert=acvert
|
|
elseif alignbot:match(acalign) then vert=resy-acvert
|
|
elseif aligncent:match(acalign) then vert=resy/2 end
|
|
end
|
|
if horz>0 and vert>0 then
|
|
if not text:match("^{\\") then text="{\\rel}"..text end
|
|
text=text:gsub("^({\\[^}]-)}","%1\\pos("..horz..","..vert..")}") :gsub("\\rel","")
|
|
end
|
|
return text
|
|
end
|
|
|
|
function gettimes(st,et)
|
|
startf=ms2fr(st)
|
|
endf=ms2fr(et)
|
|
start2=fr2ms(startf)
|
|
endt2=fr2ms(endf-1)
|
|
tim=fr2ms(1)
|
|
movt1=start2-st+tim
|
|
movt2=endt2-st+tim
|
|
return movt1,movt2
|
|
end
|
|
|
|
function vfcheck()
|
|
if aegisub.project_properties==nil then
|
|
t_error("Current frame unknown.\nProbably your Aegisub is too old.\nMinimum required: r8374.",1)
|
|
end
|
|
vframe=aegisub.project_properties().video_position
|
|
if vframe==nil or fr2ms(1)==nil then t_error("Current frame unknown. Probably no video loaded.",1) end
|
|
if line then
|
|
startf=ms2fr(line.start_time) start2=fr2ms(startf) vft=fr2ms(vframe)
|
|
tim=math.floor((fr2ms(vframe+1)-vft)/2) videopos=vft-line.start_time+tim
|
|
end
|
|
end
|
|
|
|
function detrack(z,sel,retrack,frame)
|
|
if res.layers then
|
|
for f=1,#retrack do
|
|
if frame==retrack[f] then fpos=f end
|
|
end
|
|
total=#retrack
|
|
else
|
|
fpos=z
|
|
total=#sel
|
|
end
|
|
return fpos,total
|
|
end
|
|
|
|
function stylechk(subs,sn)
|
|
for i=1,#subs do
|
|
if subs[i].class=="style" then
|
|
local st=subs[i]
|
|
if sn==st.name then sr=st break end
|
|
end
|
|
end
|
|
if sr==nil then t_error("Style '"..sn.."' doesn't exist.",1) end
|
|
return sr
|
|
end
|
|
|
|
function shiftsel(sel,i,mode)
|
|
if i<sel[#sel] then
|
|
for s=1,#sel do if sel[s]>i then sel[s]=sel[s]+1 end end
|
|
end
|
|
if mode==1 then table.insert(sel,i+1) end
|
|
table.sort(sel)
|
|
return sel
|
|
end
|
|
|
|
function flip(rot,text)
|
|
text=text:gsub("\\"..rot.."([%d.-]+)",function(r) r=tonumber(r)
|
|
if r>0 then newrot=r-180 else newrot=r+180 end
|
|
return "\\"..rot..newrot end)
|
|
return text
|
|
end
|
|
|
|
function numgrad(V1,V2,total,l,acc)
|
|
acc=acc or 1
|
|
acc_fac=(l-1)^acc/(total-1)^acc
|
|
VC=round(acc_fac*(V2-V1)+V1,2)
|
|
return VC
|
|
end
|
|
|
|
function acgrad(C1,C2,total,l,acc)
|
|
acc=acc or 1
|
|
acc_fac=(l-1)^acc/(total-1)^acc
|
|
B1,G1,R1=C1:match("(%x%x)(%x%x)(%x%x)")
|
|
B2,G2,R2=C2:match("(%x%x)(%x%x)(%x%x)")
|
|
A1=C1:match("(%x%x)") R1=R1 or A1
|
|
A2=C2:match("(%x%x)") R2=R2 or A2
|
|
nR1=(tonumber(R1,16)) nR2=(tonumber(R2,16))
|
|
R=acc_fac*(nR2-nR1)+nR1
|
|
R=tohex(round(R))
|
|
CC="&H"..R.."&"
|
|
if B1 then
|
|
nG1=(tonumber(G1,16)) nG2=(tonumber(G2,16))
|
|
nB1=(tonumber(B1,16)) nB2=(tonumber(B2,16))
|
|
G=acc_fac*(nG2-nG1)+nG1
|
|
B=acc_fac*(nB2-nB1)+nB1
|
|
G=tohex(round(G))
|
|
B=tohex(round(B))
|
|
CC="&H"..B..G..R.."&"
|
|
end
|
|
return CC
|
|
end
|
|
|
|
function tohex(num)
|
|
n1=math.floor(num/16)
|
|
n2=math.floor(num%16)
|
|
num=tohex1(n1)..tohex1(n2)
|
|
return num
|
|
end
|
|
|
|
function tohex1(num)
|
|
HEX={"1","2","3","4","5","6","7","8","9","A","B","C","D","E"}
|
|
if num<1 then num="0" elseif num>14 then num="F" else num=HEX[num] end
|
|
return num
|
|
end
|
|
|
|
function retextmod(orig,text)
|
|
local v1,v2,c,t2
|
|
v1=nobrea(orig)
|
|
c=0
|
|
repeat
|
|
t2=textmod(orig,text)
|
|
v2=nobrea(text)
|
|
c=c+1
|
|
until v1==v2 or c==666
|
|
if v1~=v2 then logg("Something went wrong with the text...") logg(v1) logg(v2) end
|
|
return t2
|
|
end
|
|
|
|
function textmod(orig,text)
|
|
if text=="" then return orig end
|
|
tk={}
|
|
tg={}
|
|
text=text:gsub("{\\\\k0}","")
|
|
text=tagmerge(text)
|
|
vis=nobra(text)
|
|
ltrmatches=re.find(vis,".")
|
|
if not ltrmatches then logg("text: "..text..'\nvisible: '..vis)
|
|
logg("If you're seeing this, something really weird is happening with the re module.\nTry this again or rescan Autoload.")
|
|
end
|
|
for l=1,#ltrmatches do
|
|
table.insert(tk,ltrmatches[l].str)
|
|
end
|
|
stags=text:match(STAG) or ""
|
|
text=text:gsub(STAG,"") :gsub("{[^\\}]-}","")
|
|
orig=orig:gsub("{([^\\}]+)}",function(c) return wrap("\\\\"..c.."|||") end)
|
|
count=0
|
|
for seq in orig:gmatch("[^{]-{%*?\\[^}]-}") do
|
|
chars,as,tak=seq:match("([^{]-){(%*?)(\\[^}]-)}")
|
|
pos=re.find(chars,".")
|
|
if pos==nil then ps=0+count else ps=#pos+count end
|
|
tgl={p=ps,t=tak,a=as}
|
|
table.insert(tg,tgl)
|
|
count=ps
|
|
end
|
|
count=0
|
|
for seq in text:gmatch("[^{]-{%*?\\[^}]-}") do
|
|
chars,as,tak=seq:match("([^{]-){(%*?)(\\[^}]-)}")
|
|
pos=re.find(chars,".")
|
|
if pos==nil then ps=0+count else ps=#pos+count end
|
|
tgl={p=ps,t=tak,a=as}
|
|
table.insert(tg,tgl)
|
|
count=ps
|
|
end
|
|
newline=""
|
|
for i=1,#tk do
|
|
newline=newline..tk[i]
|
|
newt=""
|
|
for n,t in ipairs(tg) do
|
|
if t.p==i then newt=newt..t.a..t.t end
|
|
end
|
|
if newt~="" then newline=newline.."{"..as..newt.."}" end
|
|
end
|
|
newtext=stags..newline:gsub("(|||)(\\\\)","%1}{%2"):gsub("({[^}]-)\\\\([^\\}]-)|||","{%2}%1")
|
|
text=newtext:gsub("{}","")
|
|
return text
|
|
end
|
|
|
|
function trem(tags)
|
|
trnsfrm=""
|
|
for t in tags:gmatch("\\t%b()") do trnsfrm=trnsfrm..t end
|
|
tags=tags:gsub("\\t%b()","")
|
|
return tags
|
|
end
|
|
|
|
function cleantr(tags)
|
|
trnsfrm=""
|
|
zerotf=""
|
|
for t in tags:gmatch("\\t%b()") do
|
|
if t:match("\\t%(\\") then
|
|
zerotf=zerotf..t:match("\\t%((.*)%)$")
|
|
else
|
|
trnsfrm=trnsfrm..t
|
|
end
|
|
end
|
|
zerotf="\\t("..zerotf..")"
|
|
tags=tags:gsub("\\t%b()",""):gsub("^({[^}]*)}","%1"..zerotf..trnsfrm.."}"):gsub("\\t%(%)","")
|
|
return tags
|
|
end
|
|
|
|
function duplikill(tagz)
|
|
local tags1={"blur","be","bord","shad","xbord","xshad","ybord","yshad","fs","fsp","fscx","fscy","frz","frx","fry","fax","fay"}
|
|
local tags2={"c","2c","3c","4c","1a","2a","3a","4a","alpha"}
|
|
tagz=tagz:gsub("\\t%b()",function(t) return t:gsub("\\","|") end)
|
|
for i=1,#tags1 do
|
|
tag=tags1[i]
|
|
repeat tagz,c=tagz:gsub("|"..tag.."[%d.-]+([^}]-)(\\"..tag.."[%d.-]+)","%1%2") until c==0
|
|
repeat tagz,c=tagz:gsub("\\"..tag.."[%d.-]+([^}]-)(\\"..tag.."[%d.-]+)","%2%1") until c==0
|
|
end
|
|
tagz=tagz:gsub("\\1c&","\\c&")
|
|
for i=1,#tags2 do
|
|
tag=tags2[i]
|
|
repeat tagz,c=tagz:gsub("|"..tag.."&H%x+&([^}]-)(\\"..tag.."&H%x+&)","%1%2") until c==0
|
|
repeat tagz,c=tagz:gsub("\\"..tag.."&H%x+&([^}]-)(\\"..tag.."&H%x+&)","%2%1") until c==0
|
|
end
|
|
repeat tagz,c=tagz:gsub("\\fn[^\\}]+([^}]-)(\\fn[^\\}]+)","%2%1") until c==0
|
|
repeat tagz,c=tagz:gsub("(\\[ibusq])%d(.-)(%1%d)","%2%3") until c==0
|
|
repeat tagz,c=tagz:gsub("(\\an)%d(.-)(%1%d)","%3%2") until c==0
|
|
tagz=tagz:gsub("(|i?clip%(%A-%))(.-)(\\i?clip%(%A-%))","%2%3")
|
|
:gsub("(\\i?clip%b())(.-)(\\i?clip%b())",function(a,b,c)
|
|
if a:match("m") and c:match("m") or not a:match("m") and not c:match("m") then return b..c else return a..b..c end end)
|
|
tagz=tagz:gsub("|","\\"):gsub("\\t%([^\\%)]-%)","")
|
|
return tagz
|
|
end
|
|
|
|
function extrakill(text,o)
|
|
local tags3={"pos","move","org","fad"}
|
|
for i=1,#tags3 do
|
|
tag=tags3[i]
|
|
if o==2 then
|
|
repeat text,c=text:gsub("(\\"..tag.."[^\\}]+)([^}]-)(\\"..tag.."[^\\}]+)","%3%2") until c==0
|
|
else
|
|
repeat text,c=text:gsub("(\\"..tag.."[^\\}]+)([^}]-)(\\"..tag.."[^\\}]+)","%1%2") until c==0
|
|
end
|
|
end
|
|
repeat text,c=text:gsub("(\\pos[^\\}]+)([^}]-)(\\move[^\\}]+)","%1%2") until c==0
|
|
repeat text,c=text:gsub("(\\move[^\\}]+)([^}]-)(\\pos[^\\}]+)","%1%2") until c==0
|
|
return text
|
|
end
|
|
|
|
function fail(msg)
|
|
local q=1
|
|
for i=1,#failures do
|
|
if msg==failures[i] then q=0 end
|
|
end
|
|
if q==1 then table.insert(failures,msg) end
|
|
end
|
|
|
|
function summary()
|
|
if res.why then
|
|
local MSG=''
|
|
if relocated<seln then
|
|
MSG=relocated.." out of "..seln.." lines have successfully completed space travel.\n"..seln-relocated.." lines remain in hibernation.\n\n"
|
|
if #failures>0 then MSG=MSG.."Space travel log:" end
|
|
for i=1,#failures do
|
|
MSG=MSG.."\n> "..failures[i]
|
|
end
|
|
else MSG="All "..relocated.." lines have successfully completed space travel."
|
|
end
|
|
MSG=MSG:gsub("([\n ])1 lines","%11 line"):gsub("line have","line has"):gsub("line remain ","line remains "):gsub("All 1 ","One "):gsub("^(1 out of %d+ lines )have","%1has")
|
|
local funxion=''
|
|
if P=="Positron Cannon" then funxion=res.posi end
|
|
if P=="Hyperspace Travel" then funxion=res.move end
|
|
if P=="Metamorphosis" then funxion=res.mod end
|
|
MSG=MSG.."\n\nYou have used: "..P.." ["..funxion.."]"
|
|
MSG=MSG:gsub(" %[%]",""):gsub("\n\n+","\n\n")
|
|
msgbox(MSG)
|
|
end
|
|
end
|
|
|
|
function msgbox(msg,h,w)
|
|
pres,rez=ADD({{width=w or 30,height=h or 6,class="textbox",value=msg},},{"42"},{close='42'})
|
|
end
|
|
|
|
function info(subs)
|
|
for i=1,#subs do
|
|
if subs[i].class=="info" then
|
|
local k=subs[i].key
|
|
local v=subs[i].value
|
|
if k=="PlayResX" then resx=v end
|
|
if k=="PlayResY" then resy=v end
|
|
end
|
|
if subs[i].class=="dialogue" then break end
|
|
end
|
|
end
|
|
|
|
|
|
-- The Typesetter's Guide to the Hyperdimensional Relocator.
|
|
intro=[[
|
|
Introduction
|
|
|
|
Hyperdimensional Relocator offers a plethora of functions,
|
|
focusing primarily on \pos, \move, \org, \clip, and rotations.
|
|
Anything related to positioning, movement, changing shape, etc.,
|
|
Relocator aims to make it happen.
|
|
|
|
Positron Cannon deals mostly with \pos, Hyperspace Travel with \move,
|
|
Cloning Sequence copies from line to line, Teleportation changes coordinates,
|
|
and Metamorphosis changes various things.
|
|
|
|
]].."Current version: "..script_version.."\n\nUpdate location:\n"..script_url
|
|
|
|
cannon=[[
|
|
'Align X' means all selected \pos tags will have the same given X coordinate. Same with 'Align Y' for Y.
|
|
Useful for aligning multiple signs horizontally/vertically or mocha signs that should move horizontally/vertically.
|
|
'by first' aligns by X or Y from the first line.
|
|
|
|
Horizontal Mirror: Duplicates the line and places it horizontally across the screen, mirrored around the middle.
|
|
If you input a number, it will mirror around that coordinate instead,
|
|
so if you have \pos(300,200) and input is 400, the mirrored result will be \pos(500,200).
|
|
'keep both' will keep the original line along with the mirrored one. 'rotate' will flip the text accordingly.
|
|
Vertical Mirror is the logical vertical counterpart.
|
|
|
|
Shake: Apply to fbf lines with \pos tags to create a shaking effect.
|
|
Input radius for how many pixels the sign may deflect from the original position.
|
|
(Use Teleport coordinates if you want different values for X and Y.)
|
|
'scaling' randomises fscx/y. Value '6 'with fscx150 -> 144-156. (Uses input from the Force field.)
|
|
'rotate' adds shaking to \frz (pos input, degrees). 'smooth' will make shaking smoother.
|
|
'layers' will keep position/rotations the same for all layers. (Same value for same start time.)
|
|
|
|
Trampoline / Sine Loop: Creates fbf movement between point A and point B. Check online manual for details.
|
|
|
|
Shadow Layer: Creates shadow as a new layer. For offset, it uses in this order of priority:
|
|
1. value from Positron or Teleport (xshad, yshad). 2. shadow value from the line. 3. shadow from style.
|
|
|
|
Shadow Reposition: "centers" text with shadow by the \shad distance. With \shad4, moves 2 pixels left & up.
|
|
Works with \[xy]shad. Useful when top layer has shadow & needs centering within bottom layer with border.
|
|
|
|
fbf X <--> Y: The fbf increase/decrease in pos X will become that of pos Y and vice versa.
|
|
If 'by first' is checked, the first line is the reference line (won't change). Otherwise, it's the last line.
|
|
With 'rotate' checked, the resulting direction is reversed. (Recalculator's Mirror adds more options to this.)
|
|
Example: If a sign moves 100 pixels to the right, with 'first' it will move 100px down (or up with 'rotate').
|
|
Without 'first', the directions are the same, but sign will end where it did before, not start.
|
|
|
|
Numbers: Informative only function that shows \pos differences between consecutive selected lines.
|
|
Can be useful if you want to continue a fbf movement and need an idea of the distances required.]]
|
|
|
|
spacewarp=[[
|
|
Space Out Letters: Set a distance, and line will be split into letters with that distance between them.
|
|
Value 1 = regular distance (only split). You can randomly expect about 1% inaccuracy.
|
|
With a rectangular clip, the script tries to fit the text from side to side of the clip.
|
|
\fscx, \fs, \frz, \fn, and \move are supported. Other rotations aren't, and line breaks get nuked.
|
|
\fax is not a problem; \fay will just apply to each letter but not affect position.
|
|
\frz will only work right without \org. Inline tags should work unless they have impact on the size/position.
|
|
|
|
Warp Text: Creates a curve out of spaced out letters (or words). Given value is pixel distance in the centre.
|
|
Positive = convex; negative=concave. Won't work well with extreme values, but it's an easy way to create
|
|
a slight curve, whether the letters are spaced out horizontally or at an angle. First & last letters are fixed.
|
|
]]
|
|
|
|
clipthings=[[
|
|
Org to Fax: Calculates \fax from the line between \pos and \org coordinates.
|
|
|
|
Clip to Fax: Calculates \fax from the line between the first 2 points of a vectorial clip.
|
|
Both of these work with \fscx, \fscy, and \frz.
|
|
If the clip has 4 points, points 3-4 are used to calculate fax for the last character, and a gradient is applied.
|
|
See blog post for more info - http://unanimated.hostfree.pw/itw/tsblok.htm#fax
|
|
|
|
Clip to Frz: Calculates \frz from the first 2 points of a vectorial clip. Direction of text is from point 1 to point 2.
|
|
If the clip has 4 points, the frz is average from 1-2 and 3-4. (Both lines must be in the same direction.)
|
|
This helps when the sign is in the middle of a rectangular area where the top and bottom lines converge.
|
|
|
|
Clip to Reposition: Shifts \pos based on first 2 points of a vectorial clip.
|
|
You can use a reference point in the video image and set the clip points at start/end of the movement.
|
|
|
|
Clip2Pos fbf: This is for manual fbf tracking. Track something in the video with one point of a clip in each frame.
|
|
The first line is a reference point. The \pos of other lines will shift based on the difference between
|
|
the clip on the first line and the clip on the current line. (Starting point is always \pos from line 1.)
|
|
|
|
Frz+Org2Pos: For a line with \frz & \org, \pos is recalculated so that it's at the anchor, and \org is nuked.
|
|
|
|
Track by Clip: Tracks short position sequences with a clip. Follow one point in video with clip points fbf.
|
|
This will create a line for each frame and shift position based on the clip sequence.
|
|
This may help when you want to "track" 3-10 easy frames and don't want to open Mocha for that.
|
|
'by first': reference pos. is the 1st frame, otherwise the last. Timing-wise, tracking always starts on 1st.
|
|
X and Y coordinates are tracked depending on 'X' and 'Y' checkboxes.
|
|
If movement/animation is e.g. each 3 frames, set '3' in disPosition field.]]
|
|
|
|
replika=[[
|
|
Create replicas of selected lines positioned over specified distances.
|
|
'Replicas' is how many replicas of each line you'll make.
|
|
Distances for 'each replica':
|
|
sets distances between two consecutive lines.
|
|
In this mode, distances are always relative, and formation curve is 1.
|
|
Distances for 'last replica':
|
|
distance/coordinates for last replica.
|
|
'relative' distance is from the original.
|
|
'absolute' distance is video coordinates.
|
|
(This way all selected lines can replicate towards the same point.)
|
|
'formation curve' is acceleration for X and Y, if 'last replica' selected.
|
|
'use existing \move for last replica coordinates':
|
|
target coordinates for each line are taken from \move tag.
|
|
This overrides 'each replica' mode.
|
|
All selected lines must have a \move tag. If not checked,
|
|
lines can still have \move, and all coordinates will be shifted.
|
|
'Delay' is by how many frames each replica will be shifted,
|
|
if you want them to appear one by one over time.
|
|
'keep end' will keep end time for such replicas same as the original.
|
|
Otherwise it gets shifted along with start time.
|
|
Should the end time be lower than start time, duration will be 1 frame.
|
|
(You should prevent this from happening as it makes no sense.)]]
|
|
|
|
fbfretrack=[[
|
|
There is simple mode and 'smoothen track' mode.
|
|
|
|
Simple mode is like fbf-transform for position, but it can be applied to several layers at the same time
|
|
and have different accel for X and Y.
|
|
If you check 'layers', the scale is not by selection but by start time.
|
|
You can have subtitles sorted by layers, but each layer must be sorted by time.
|
|
Of course each frame will have the same position for all layers/signs.
|
|
You can use Repositioning Field for accel, or Teleport for separate X/Y accel.
|
|
You can track only X or Y if you check only one of those.
|
|
Without 'layers' checked, it simply goes through selected lines and can be applied to signs in the same frame.
|
|
|
|
'Smoothen track' mode is activated when you check 'smooth'.
|
|
This is designed for smoothening tracking data,
|
|
i.e. it will move positions that stand out closer to the main line of the track.
|
|
It would make no sense to apply this to shaking signs, but if you have trouble tracking something in mocha
|
|
and the sign tends to jump off on some frames, this will pull the jumps back in line.
|
|
You can apply different strength of smoothening, by using the Force Field.
|
|
0 is the lowest strength; 100 is the highest and will make the track a straight line.]]
|
|
|
|
travel=[[
|
|
'Horizontal' move means Y2 will be the same as Y1 so that the sign moves in a straight horizontal manner.
|
|
Same principle for 'vertical.'
|
|
|
|
Multimove: When first line has \move and the others have \pos, \move for them is calculated from the first one.
|
|
|
|
Clip2Move*: Move is calculated from first 2 points of a vectorial clip. Works for \pos, or adjusts \move.
|
|
If you make 4 points, the move is from the centre of line 1 (pt. 1+2) and line 3 (pt. 3+4).
|
|
If you want exactly vertical or horizontal move, check only X or Y.
|
|
|
|
ShiftMove*: Like teleport, but only for the 2nd set of coordinates, ie. X2 and Y2. Uses input from Teleport.
|
|
'current frame' sets -end- timecode to current frame
|
|
|
|
ShiftStart: Similarly, this only shifts the initial \move coordinates.
|
|
'current frame' sets -start- timecode to current frame
|
|
|
|
Reverse Move: Switches the coordinates, reversing the movement direction.
|
|
|
|
Move to*: Teleport input sets target coordinats for \move for all selected lines.
|
|
'current frame' sets end timecode to current frame
|
|
|
|
Move Clip: Moves regular clip along with \move using \t\clip.
|
|
|
|
Kill Times: nukes timecodes from \move / \t tags. (Default: move; checked "\t": transforms)
|
|
Full Times: sets timecodes for \move / \t to the first and last frame.
|
|
Set Times: sets timecodes for \move / \t based on Teleport input. X=start, Y=end.
|
|
Negative values count from end. X=0 -> 0, Y=0 -> end frame. Last 100ms: X=-100,Y=0.
|
|
|
|
*'times' will add timecodes to \move for these functions (from Teleport if given, or just first/last frames).]]
|
|
|
|
transmoo=[[
|
|
Transmove
|
|
Main function: create \move from two lines with \pos.
|
|
Duplicate your line, and position the second one where you want the \move the end.
|
|
Script will create \move from the two positions.
|
|
Second line will be deleted by default; it's there just so you can comfortably set the final position.
|
|
Extra function: to make this a lot more awesome, this can create transforms.
|
|
The second line is used not only for \move coordinates but also for transforms.
|
|
Any tag on line 2 that's different from line 1 will be used to create a transform on line 1.
|
|
So for a \move with transforms, you can set the initial sign and then the final sign while everything is static.
|
|
You can time line 2 to just the last frame. The script only uses timecodes from line 1.
|
|
Text from line 2 is also ignored (assumed to be same as line 1).
|
|
You can time line 2 to start after line 1 and check 'keep both.'
|
|
That way line 1 transforms into line 2, and the sign stays like that for the duration of line 2.
|
|
'Rotation acceleration' - like with fbf-transform, this ensures that transforms of rotations will go the shortest way,
|
|
thus going only 4 degrees from 358 to 2 and not 356 degrees around.
|
|
If the \pos is the same on both lines, only transforms will be applied.
|
|
Logically, you must NOT select 2 consecutive lines when you want to run this,
|
|
though you can select every other line.
|
|
|
|
'times' will add timecodes to \move]]
|
|
|
|
morph=[[
|
|
Round Numbers: rounds coordinates for pos, move, org and clip depending on the 'Round' submenu.
|
|
|
|
Joinfbflines: Select frame-by-frame lines, input number X into Force Field, and each X lines will be joined.
|
|
(same way as with 'Join (keep first)' from the right-click menu)
|
|
|
|
Set Origin: sets \org based on Teleport input. With 'Warp', it's set by given distance from \pos.
|
|
|
|
Set Rotation: adds selected rotation tags with the value from the 'rotation' menu.
|
|
(You can get multiples of 30 using the Aegisub tool while holding Ctrl.)
|
|
|
|
Rotate 180: rotates text by 180 degrees from current values of selected rotations (frx, fry, frz).
|
|
|
|
Negative Rot: keeps the same rotation, but changes to negative (350 -> -10), which helps with transforms.
|
|
|
|
Spin Doctor: These are settings for the two Spin macros. The macros change tag values based on this.
|
|
|
|
Find Centre: A useless function that sets \pos in the centre of a rectangular clip.
|
|
|
|
Randomise: randomises values of given tags. With \fs50 and value 4 you can get fs 46-54.
|
|
For regular type tags, you can input multiple ones with commas between them.
|
|
Also works for alpha, but not colours. Negative values only happen where applicable. Available for \t times.
|
|
|
|
Letterbreak: creates vertical text by putting a linebreak after each letter.
|
|
Wordbreak: replaces spaces with linebreaks.]]
|
|
|
|
morph2fbf=[[
|
|
Line2fbf:
|
|
|
|
Splits a line frame by frame, ie. makes a line for each frame.
|
|
If there's \move, it calculates \pos tags for each line.
|
|
If there are transforms, it calculates values for each line.
|
|
It should deal with all transforms, including inline tags and acceleration.
|
|
Move and transforms can have timecodes. (Though some calculations may end up about 1% off.)
|
|
\fad is supported too, but may not be entirely accurate with complex alphas.
|
|
Very complex lines with multiple transforms are likely to break in some way.
|
|
|
|
'clip2fbf' - clips will be shifted along with \move. (Don't use with clip transforms.)]]
|
|
|
|
morphorg=[[
|
|
Calculate Origin:
|
|
|
|
This calculates \org from a tetragonal vectorial clip you draw.
|
|
Draw a vectorial clip with 4 points, aligned to a surface you need to put your sign on.
|
|
The script will calculate the vanishing points for X and Y and give you \org.
|
|
Make the clip as large as you can, since on a smaller one any inaccuracies will be more obvious.
|
|
If you draw it well enough, the accuracy of the \org point should be pretty decent.
|
|
(It won't work when both points on one side are lower than both points on the other side.)
|
|
See this blog post for more details: http://unanimated.hostfree.pw/itw/tsblok.htm#origin
|
|
]]
|
|
|
|
morphclip=[[
|
|
Move V. Clip: Moves vectorial clip on fbf lines based on \pos tags.
|
|
Note: For decimals on v-clip coordinates: xy-vsfilter OK; libass rounds them; regular vsfilter fails completely.
|
|
|
|
Vector2Rect/Rect.2Vector: converts between rectangular and vectorial clips.
|
|
|
|
Clip Scale: Use Force field to set the X factor in "clip(X,m ", and the clip will be recalculated accordingly.
|
|
|
|
Clip2Scale fbf: Adjusts \fscx and \fscy fbf based on width and height of a 2-point clip. (Check online manual.)
|
|
|
|
Clip Info: For signs with different size on each end, draw a 4-point vectorial clip that reflects the sizes.
|
|
The point is mainly to get the difference in height between left and right sides of a tetragon.
|
|
If the right size is twice the height of left, 'fsc' will put \fscx200\fscy200 before last character.
|
|
More generally, you can get measurements for any two lines and the ratio between them.
|
|
Line A is clip points 1-2, line B is 3-4. This can be used for calculating the scaling of various things.
|
|
Applies only to active line.
|
|
|
|
[Un]Hide Clip: Hides an existing clip in a comment / returns it back. (This has its own macro for hotkeying.)
|
|
|
|
|
|
Transform Clip:
|
|
|
|
Go from \clip(x1,y1,x2,y2) to \clip(x1,y1,x2,y2)\t(\clip(x3,y3,x4,y4)).
|
|
Coordinates are read from the line.
|
|
You can set by how much x and y should change, and new coordinates will be calculated.
|
|
|
|
'use next line's clip' allows you to use clip from the next line.
|
|
Create a line after your current one (or just duplicate), set the clip you want to transform to on it,
|
|
and check 'use next line's clip'.
|
|
The clip from the next line will be used for the transform, and the line will be deleted.]]
|
|
|
|
morphmasks=[[
|
|
Extend Mask: Use Teleport X and Y fields to extend a mask in either or both directions.
|
|
This is mainly intended to easily convert something like a rounded square to another rounded rectangle.
|
|
Works optimally with a 0,0 coordinate in the centre. May do weird things with curves.
|
|
When all coordinates are to one side from 0,0, then this works like shifting.
|
|
|
|
Flip mask: Flips a mask so that when used with its non-flipped counterpart, they create hollow space.
|
|
For example you have a rounded square. Duplicate it, extend one by 10 pixels in each direction, flip it,
|
|
and then merge them. You'll get a 10 px outline.
|
|
|
|
Adjust Drawing: (You must not have an unrelated clip in the line.)
|
|
1. Creates a clip that copies the drawing.
|
|
2. You adjust points with clip tool.
|
|
3. Applies new coordinates to the drawing.
|
|
|
|
Randomask: Moves points in a drawing, each in a random direction, by a factor taken from the Force field.]]
|
|
|
|
cloan=[[
|
|
This copies specified tags from first line to the others.
|
|
Options are position, move, origin point, clip, and rotations.
|
|
|
|
replicate missing tags: creates tags if they're not present
|
|
|
|
stack clips: allows stacking of 1 normal and 1 vector clip in one line
|
|
|
|
match type: if current clip/iclip doesn't match the first line, it will be switched to match
|
|
|
|
combine vectors: if the first line has a vector clip, then for all other lines with vector clips
|
|
the vectors will be combined into 1 clip
|
|
|
|
copy rotations: copies all rotations
|
|
|
|
With Teleport input, you can shift X and Y coordinates more each line by the given values.]]
|
|
|
|
port=[[
|
|
Teleport shifts coordinates for selected tags (\pos\move\org\clip) by given X and Y values.
|
|
It's a simple but powerful tool that allows you to move whole gradients, mocha-tracked signs, etc.
|
|
|
|
Note that the Teleport fields are also used for some other functions, like Shiftstart and Shiftmove.
|
|
These functions don't use the 'Teleportation' button but the one for whatever part of HR they belong to.
|
|
|
|
'mod' allows you to add an extra factor applied line by line.
|
|
For example if you set '5' for 'X', things will shift by extra 5 pixels for each new line.
|
|
|
|
c1 and c2 control whether Teleportation affects top left and/or bottom right corner of a rectangular clip.
|
|
This means that for both X and Y, you can move either one or both sides of the clip.
|
|
|
|
'exp' means a rectangular clip won't be moved but expanded. X 10 means the clip will expand by 10
|
|
to the left and right. This ignores the c1/c2 settings.]]
|
|
|
|
function guide()
|
|
ADD=aegisub.dialog.display
|
|
ak=aegisub.cancel
|
|
stg_top={x=0,y=0,class="label",
|
|
label="The Typesetter's Guide to the Hyperdimensional Relocator. "}
|
|
|
|
stg_toptop={x=1,y=0,class="label",label="Choose topic below."}
|
|
stg_topos={x=1,y=0,class="label",label=" Repositioning Field"}
|
|
stg_toptra={x=1,y=0,class="label",label=" Soul Bilocator"}
|
|
stg_toporph={x=1,y=0,class="label",label=" Morphing Grounds"}
|
|
stg_topseq={x=1,y=0,class="label",label=" Cloning Laboratory"}
|
|
stg_toport={x=1,y=0,class="label",label=" Teleport"}
|
|
|
|
stg_intro={x=0,y=1,width=2,height=10,class="textbox",name="gd",value=intro}
|
|
stg_cannon={x=0,y=1,width=2,height=20,class="textbox",name="gd",value=cannon}
|
|
stg_can_to_things={x=0,y=1,width=2,height=16,class="textbox",name="gd",value=clipthings}
|
|
stg_replicate={x=0,y=1,width=2,height=14,class="textbox",name="gd",value=replika}
|
|
stg_retrack={x=0,y=1,width=2,height=12,class="textbox",name="gd",value=fbfretrack}
|
|
stg_travel={x=0,y=1,width=2,height=17,class="textbox",name="gd",value=travel}
|
|
stg_spacewarp={x=0,y=1,width=2,height=8,class="textbox",name="gd",value=spacewarp}
|
|
stg_transmove={x=0,y=1,width=2,height=13,class="textbox",name="gd",value=transmoo}
|
|
stg_morph={x=0,y=1,width=2,height=15,class="textbox",name="gd",value=morph}
|
|
stg_morph2fbf={x=0,y=1,width=2,height=8,class="textbox",name="gd",value=morph2fbf}
|
|
stg_morphorg={x=0,y=1,width=2,height=8,class="textbox",name="gd",value=morphorg}
|
|
stg_morphclip={x=0,y=1,width=2,height=17,class="textbox",name="gd",value=morphclip}
|
|
stg_morpmsk={x=0,y=1,width=2,height=10,class="textbox",name="gd",value=morphmasks}
|
|
stg_cloan={x=0,y=1,width=2,height=10,class="textbox",name="gd",value=cloan}
|
|
stg_port={x=0,y=1,width=2,height=9,class="textbox",name="gd",value=port}
|
|
|
|
cp_main={"Positron Cannon","Hyperspace Travel","Metamorphosis","Cloning Sequence","Teleportation","Disintegrate"}
|
|
cp_back={"Warp Back"}
|
|
cp_cannon={"Warp Back","Positron Cannon","org/clip Things","Replicate","FBF Retrack","Space Warp"}
|
|
cp_travel={"Warp Back","Hyperspace Travel","Transmove"}
|
|
cp_morph={"Warp Back","Metamorphosis","Line2fbf","Calculate Origin","Clip Operations","Masks/drawings"}
|
|
esk1={close='Disintegrate'}
|
|
esk2={cancel='Warp Back'}
|
|
stg={stg_top,stg_toptop,stg_intro} control_panel=cp_main esk=esk1
|
|
repeat
|
|
stg={stg_top,stg_toptop,stg_intro} control_panel=cp_main esk=esk1
|
|
if press=="Positron Cannon" then stg={stg_top,stg_topos,stg_cannon} control_panel=cp_cannon esk=esk2 end
|
|
if press=="Hyperspace Travel" then stg={stg_top,stg_toptra,stg_travel} control_panel=cp_travel esk=esk2 end
|
|
if press=="Metamorphosis" then stg={stg_top,stg_toporph,stg_morph} control_panel=cp_morph esk=esk2 end
|
|
if press=="Cloning Sequence" then stg={stg_top,stg_topseq,stg_cloan} control_panel=cp_back esk=esk2 end
|
|
if press=="Teleportation" then stg={stg_top,stg_toport,stg_port} control_panel=cp_back esk=esk2 end
|
|
if press=="org/clip Things" then stg={stg_top,stg_topos,stg_can_to_things} control_panel=cp_cannon esk=esk2 end
|
|
if press=="Replicate" then stg={stg_top,stg_topos,stg_replicate} control_panel=cp_cannon esk=esk2 end
|
|
if press=="FBF Retrack" then stg={stg_top,stg_topos,stg_retrack} control_panel=cp_cannon esk=esk2 end
|
|
if press=="Space Warp" then stg={stg_top,stg_topos,stg_spacewarp} control_panel=cp_cannon esk=esk2 end
|
|
if press=="Transmove" then stg={stg_top,stg_topos,stg_transmove} control_panel=cp_travel esk=esk2 end
|
|
if press=="Line2fbf" then stg={stg_top,stg_toporph,stg_morph2fbf} control_panel=cp_morph esk=esk2 end
|
|
if press=="Calculate Origin" then stg={stg_top,stg_toporph,stg_morphorg} control_panel=cp_morph esk=esk2 end
|
|
if press=="Clip Operations" then stg={stg_top,stg_toporph,stg_morphclip} control_panel=cp_morph esk=esk2 end
|
|
if press=="Masks/drawings" then stg={stg_top,stg_toporph,stg_morpmsk} control_panel=cp_morph esk=esk2 end
|
|
if press=="Warp Back" then stg={stg_top,stg_toptop,stg_intro} control_panel=cp_main esk=esk1 end
|
|
press,rez=ADD(stg,control_panel,esk)
|
|
until press=="Disintegrate"
|
|
if press=="Disintegrate" then ak() end
|
|
end
|
|
|
|
|
|
-- Config Stuff --
|
|
function saveconfig()
|
|
hrconf="Hyperconfigator\n\n"
|
|
for key,val in ipairs(hyperconfig) do
|
|
if val.class=="floatedit" or val.class=="dropdown" then
|
|
hrconf=hrconf..val.name..":"..res[val.name].."\n"
|
|
end
|
|
if val.class=="checkbox" and val.name~="save" then
|
|
hrconf=hrconf..val.name..":"..tf(res[val.name]).."\n"
|
|
end
|
|
end
|
|
hyperkonfig=ADP("?user").."\\relocator.conf"
|
|
file=io.open(hyperkonfig,"w")
|
|
file:write(hrconf)
|
|
file:close()
|
|
ADD({{class="label",label="Config saved to:\n"..hyperkonfig}},{"OK"},{close='OK'})
|
|
end
|
|
|
|
function loadconfig()
|
|
rconfig=ADP("?user").."\\relocator.conf"
|
|
file=io.open(rconfig)
|
|
if file~=nil then
|
|
konf=file:read("*all")
|
|
konf=konf:gsub("%-frz%-","rotation")
|
|
io.close(file)
|
|
for key,val in ipairs(hyperconfig) do
|
|
if val.class=="floatedit" or val.class=="checkbox" or val.class=="dropdown" then
|
|
if konf:match(val.name) then val.value=detf(konf:match(val.name..":(.-)\n")) end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function tf(val)
|
|
if val==true then ret="true"
|
|
elseif val==false then ret="false"
|
|
else ret=val end
|
|
return ret
|
|
end
|
|
|
|
function detf(txt)
|
|
if txt=="true" then ret=true
|
|
elseif txt=="false" then ret=false
|
|
else ret=txt end
|
|
return ret
|
|
end
|
|
|
|
function clip2frz(subs,sel,act)
|
|
res={}
|
|
res.posi="clip to frz"
|
|
positron(subs,sel,act)
|
|
end
|
|
|
|
function clip2fax(subs,sel,act)
|
|
res={}
|
|
res.posi="clip to fax"
|
|
positron(subs,sel,act)
|
|
end
|
|
|
|
function v2r(subs,sel,act)
|
|
res={}
|
|
res.mod="vector2rect."
|
|
modifier(subs,sel,act)
|
|
end
|
|
|
|
function r2v(subs,sel,act)
|
|
res={}
|
|
res.mod="rect.2vector"
|
|
modifier(subs,sel,act)
|
|
end
|
|
|
|
function adjust(subs,sel,act)
|
|
res={}
|
|
res.mod="adjust drawing"
|
|
modifier(subs,sel,act)
|
|
end
|
|
|
|
function h_c(subs,sel,act)
|
|
res={}
|
|
res.mod="[un]hide clip"
|
|
modifier(subs,sel,act)
|
|
end
|
|
|
|
function spinPlus(subs,sel) spindoctor(subs,sel,1) end
|
|
|
|
function spinMinus(subs,sel) spindoctor(subs,sel,-1) end
|
|
|
|
function spindoctor(subs,sel,sp)
|
|
spin=spin or 'frz'
|
|
sdr=sdr or 1
|
|
sdf=sdf or 0.01
|
|
spine='_frz_frx_fry_fax_fay_xshad_yshad_fsp_'
|
|
for z,i in ipairs(sel) do
|
|
local l=subs[i]
|
|
local t=l.text
|
|
local tag=spin
|
|
local tg=t:match'>\\(%a+)'
|
|
if tg and spine:match('_'..tg..'_') then tag=tg end
|
|
if tag:match'fa' then SV=sdf else SV=sdr end
|
|
if sp==-1 then SV=0-SV end
|
|
if not t:match('\\'..tag) then t='{\\'..tag..'0}'..t t=t:gsub("{([^}]+)}{([^}]+)}","{%2%1}") end
|
|
if tag==tg then t=t:gsub('(>\\'..tag..')([-%d.]+)',function(t,v) return t..v+SV end) -- 1 tag only ">"
|
|
else t=t:gsub('(\\'..tag..')([-%d.]+)',function(t,v) return t..v+SV end) end -- all in the line
|
|
l.text=t
|
|
subs[i]=l
|
|
end
|
|
end
|
|
|
|
function tpres()
|
|
res=res or {}
|
|
res.tppos=true
|
|
res.tpmov=false
|
|
res.tporg=false
|
|
res.tpclip=false
|
|
res.tpmask=false
|
|
res.warp=false
|
|
res.autopos=true
|
|
res.eks=0
|
|
res.wai=0
|
|
end
|
|
|
|
function tpxp(subs,sel)
|
|
tpres()
|
|
res.eks=1
|
|
teleport(subs,sel)
|
|
end
|
|
|
|
function tpxn(subs,sel)
|
|
tpres()
|
|
res.eks=-1
|
|
teleport(subs,sel)
|
|
end
|
|
|
|
function tpyp(subs,sel)
|
|
tpres()
|
|
res.wai=1
|
|
teleport(subs,sel)
|
|
end
|
|
|
|
function tpyn(subs,sel)
|
|
tpres()
|
|
res.wai=-1
|
|
teleport(subs,sel)
|
|
end
|
|
|
|
if haveDepCtrl then
|
|
depRec:registerMacros({
|
|
{script_name,script_description,relocator},
|
|
{": HELP : / SpaceTravel Guide","SpaceTravel Guide",guide},
|
|
{": Non-GUI macros :/HR: Convert clip to frz","Convert clip to frz",clip2frz},
|
|
{": Non-GUI macros :/HR: Convert clip to fax","Convert clip to fax",clip2fax},
|
|
{": Non-GUI macros :/HR: Convert vector clip to rectangular","Convert vector clip to rectangular",v2r},
|
|
{": Non-GUI macros :/HR: Convert rectangular clip to vector","Convert rectangular clip to vector",r2v},
|
|
{": Non-GUI macros :/HR: Adjust drawing","Adjust drawing",adjust},
|
|
{": Non-GUI macros :/HR: [Un]Hide clip","[un]hide clip",h_c},
|
|
{": Non-GUI macros :/HR: Teleport 1px right","TeleportXP",tpxp},
|
|
{": Non-GUI macros :/HR: Teleport 1px left","TeleportXN",tpxn},
|
|
{": Non-GUI macros :/HR: Teleport 1px down","TeleportYP",tpyp},
|
|
{": Non-GUI macros :/HR: Teleport 1px up","TeleportYN",tpyn},
|
|
{": Non-GUI macros :/HR: Positive Spin","Positive Spin",spinPlus},
|
|
{": Non-GUI macros :/HR: Negative Spin","Negative Spin",spinMinus},
|
|
{": Non-GUI macros :/HR: Spin Doctor","Spin Doctor",spindoc},
|
|
},false)
|
|
else
|
|
aegisub.register_macro(script_name,script_description,relocator)
|
|
aegisub.register_macro(": HELP : / SpaceTravel Guide","SpaceTravel Guide",guide)
|
|
aegisub.register_macro(": Non-GUI macros :/HR: Convert clip to frz","Convert clip to frz",clip2frz)
|
|
aegisub.register_macro(": Non-GUI macros :/HR: Convert clip to fax","Convert clip to fax",clip2fax)
|
|
aegisub.register_macro(": Non-GUI macros :/HR: Convert vector clip to rectangular","Convert vector clip to rectangular",v2r)
|
|
aegisub.register_macro(": Non-GUI macros :/HR: Convert rectangular clip to vector","Convert rectangular clip to vector",r2v)
|
|
aegisub.register_macro(": Non-GUI macros :/HR: Adjust drawing","Adjust drawing",adjust)
|
|
aegisub.register_macro(": Non-GUI macros :/HR: [Un]Hide clip","[un]hide clip",h_c)
|
|
aegisub.register_macro(": Non-GUI macros :/HR: Teleport 1px right","TeleportXP",tpxp)
|
|
aegisub.register_macro(": Non-GUI macros :/HR: Teleport 1px left","TeleportXN",tpxn)
|
|
aegisub.register_macro(": Non-GUI macros :/HR: Teleport 1px down","TeleportYP",tpyp)
|
|
aegisub.register_macro(": Non-GUI macros :/HR: Teleport 1px up","TeleportYN",tpyn)
|
|
aegisub.register_macro(": Non-GUI macros :/HR: Positive Spin","Positive Spin",spinPlus)
|
|
aegisub.register_macro(": Non-GUI macros :/HR: Negative Spin","Negative Spin",spinMinus)
|
|
aegisub.register_macro(": Non-GUI macros :/HR: Spin Doctor","Spin Doctor",spindoc)
|
|
end |