6dcb5ff4a8
Apparently Lua 5.1 has changed the semantics of table.insert so it's incompatible with the way used in all Auto3 demo scripts etc. Now it's overridden in utils.auto3 and all instances of it in sample scripts etc. replaced with code having the expected behaviour. Originally committed to SVN as r926.
201 lines
7.8 KiB
Lua
201 lines
7.8 KiB
Lua
-- Aegisub Automation demonstration script
|
|
-- Original written by Niels Martin Hansen
|
|
-- Given into the public domain
|
|
-- But still, please don't use the effect generated by this script
|
|
-- (unchanged) for your own works.
|
|
|
|
-- Note that many of the techniques used in this script are heavily deprecated, much of the processing done
|
|
-- is also done by the karaskel scripts.
|
|
-- In fact, this can almost be viewed as an example of how *not* to do things...
|
|
|
|
-- Since this script assumes some rather specific things about the ASS input, it might not be very useful at first.
|
|
-- The original ASS file this was written for is available upon request.
|
|
|
|
include("utils.lua")
|
|
|
|
name = "Advanced karaoke effect"
|
|
description = "An advanced karaoke effect, making heavy use of both line-copying and per-syllable text placement. Also demonstrates how to treat lines differently, based on their style, and syllables differently based on the timing tag used."
|
|
version, kind, configuration = 3, 'basic_ass', {}
|
|
|
|
function process_lines(meta, styles, lines, config)
|
|
local output = { n=0 }
|
|
math.randomseed(5922) -- just to make sure it's initialised the same every time
|
|
for curline = 0, lines.n-1 do
|
|
aegisub.report_progress(curline/lines.n*100)
|
|
local lin = lines[curline]
|
|
if lin.kind == "dialogue" and lin.style == "op romaji" then
|
|
doromaji(lin, output, styles["op romaji"], 30)
|
|
elseif lin.kind == "dialogue" and lin.style == "op kanji" then
|
|
-- Just one of these lines should be uncommented.
|
|
-- This script was written before configuration worked, otherwise it would use configuration
|
|
-- to select which of the two effects to use for "op kanji" style lines.
|
|
--doromaji(lin, output, styles["op kanji"], 20)
|
|
dokanji(lin, output, styles["op kanji"])
|
|
else
|
|
-- Unknown lines are copied verbatim
|
|
output.n = output.n + 1
|
|
output[output.n] = lin
|
|
end
|
|
end
|
|
return output
|
|
end
|
|
|
|
function doromaji(lin, output, sty, linetop)
|
|
aegisub.set_status(lin.text_stripped)
|
|
|
|
--local linetop = 50
|
|
|
|
-- prepare syllable data
|
|
local linewidth = 0
|
|
local syltime = 0
|
|
local syls = {n=0}
|
|
for i = 1, lin.karaoke.n-1 do
|
|
local syl = lin.karaoke[i]
|
|
syl.width, syl.height, syl.descent, syl.extlead = aegisub.text_extents(sty, syl.text_stripped)
|
|
syl.left = linewidth
|
|
syl.start_time = syltime
|
|
syl.end_time = syltime + syl.duration
|
|
syltime = syltime + syl.duration
|
|
if syl.kind == "kf" and (syl.text == " " or syl.text == " ") then
|
|
-- The font this effect was made to work with has too wide spaces, so make those half width
|
|
syl.width = math.floor(syl.width / 2)
|
|
syl.kind = "space"
|
|
elseif syl.kind == "kf" then
|
|
syl.kind = "deco"
|
|
elseif syl.kind == "k" then
|
|
syl.kind = "reg"
|
|
elseif syl.kind == "ko" then
|
|
syl.kind = "dance"
|
|
else
|
|
syl.kind = "ignore"
|
|
end
|
|
if syl.text == "#" then
|
|
syls[syls.n-1].duration = syls[syls.n-1].duration + syl.duration
|
|
syls[syls.n-1].end_time = syls[syls.n-1].end_time + syl.duration
|
|
else
|
|
linewidth = linewidth + syl.width
|
|
syls[syls.n] = syl
|
|
syls.n = syls.n + 1
|
|
end
|
|
end
|
|
local lineofs = math.floor((640 - linewidth) / 2)
|
|
|
|
for i = 0, syls.n-1 do
|
|
local syl = syls[i], copy_line(lin)
|
|
if syl.kind == "space" then
|
|
-- Spaces are skipped. Since the width of them is already incorporated in the position calculations
|
|
-- for the following syllables, they can safely be stripped from output, without losing the spaces.
|
|
elseif syl.kind == "ignore" then
|
|
-- These are actually syllable kinds we don't know what to do about. They are not included in the output.
|
|
else
|
|
local startx, starty, shakex, shakey, enterangle
|
|
-- angle to enter from
|
|
enterangle = math.rad((180 / lin.karaoke.n) * i - 90)
|
|
-- position to enter from (350 pixels from (320, 50))
|
|
startx = math.sin(enterangle)*350 + 320
|
|
starty = linetop - math.cos(enterangle)*350
|
|
if syl.kind == "reg" then
|
|
shakex = (syl.left+lineofs) + math.random(-5, 5)
|
|
shakey = linetop + math.random(-5, 5)
|
|
elseif syl.kind == "deco" then
|
|
shakex, shakey = syl.left+lineofs, linetop
|
|
elseif syl.kind == "dance" then
|
|
shakex = (syl.left+lineofs) + math.random(-5, 5)
|
|
shakey = linetop + math.random(-5, 5)
|
|
end
|
|
-- origin for rotation
|
|
local orgx = syl.left + lineofs + syl.width/2
|
|
local orgy = linetop + syl.height/2
|
|
-- entry effect
|
|
local enterlin = copy_line(lin)
|
|
enterlin.start_time = lin.start_time - 40
|
|
enterlin.end_time = lin.start_time
|
|
enterlin.text = string.format("{\\move(%d,%d,%d,%d)\\fr%d\\t(\\fr0)\\an7}%s", startx, starty, shakex, shakey, -math.deg(enterangle), syl.text)
|
|
output.n = output.n + 1
|
|
output[output.n] = enterlin
|
|
-- main highlight effect
|
|
local newlin = copy_line(lin)
|
|
local hilistart, hilimid, hiliend = syl.start_time*10, (syl.start_time+syl.duration/2)*10, (syl.start_time+syl.duration)*10
|
|
newlin.text = string.format("\\move(%d,%d,%d,%d,%d,%d)\\an7}%s", shakex, shakey, syl.left+lineofs, linetop, hilistart, hiliend, syl.text)
|
|
newlin.layer = 1
|
|
if syl.kind == "dance" then
|
|
local fx = string.format("\\org(%d,%d)\\t(%d,%d,\\fr30)\\t(%d,%d,\\fr-30)\\t(%d,%d,\\3c&H0000ff&)\\t(%d,%d,\\3c&H000080&)\\t(%d,%d,\\fr0)", orgx, orgy, hilistart, hilistart+20, hilistart+20, hiliend, hilistart, hilimid, hilimid, hiliend, hiliend, hiliend+syl.duration*10)
|
|
newlin.text = fx .. newlin.text
|
|
else
|
|
local fx = string.format("\\t(%d,%d,\\3c&H0000ff&)\\t(%d,%d,\\3c&H000080&)", hilistart, hilimid, hilimid, hiliend)
|
|
newlin.text = fx .. newlin.text
|
|
end
|
|
local bord = copy_line(newlin)
|
|
bord.layer = 0
|
|
bord.text = "{" .. bord.text
|
|
newlin.text = "{\\bord0" .. newlin.text
|
|
output.n = output.n + 2
|
|
output[output.n-1] = bord
|
|
output[output.n] = newlin
|
|
-- leave effect
|
|
-- cut the line over in two, lower half "drops down", upper just fades away
|
|
local tophalf = copy_line(lin)
|
|
tophalf.start_time = lin.end_time
|
|
tophalf.end_time = lin.end_time + 100
|
|
tophalf.text = string.format("\\3c&H000080&\\fad(0,700)\\pos(%d,%d)\\an7}%s", syl.left+lineofs, linetop, syl.text_stripped)
|
|
local bottomhalf = copy_line(tophalf)
|
|
tophalf.text = string.format("{\\t(0,200,\\1c&H000080&)\\clip(0,0,640,%d)%s", linetop+syl.height/2, tophalf.text)
|
|
bottomhalf.text = string.format("{\\org(%d,%d)\\clip(0,%d,640,480)\\t(0,200,\\1c&H000080&)\\t(200,1000,1.2,\\frx90\\clip(0,%d,640,480)%s", 320, linetop+syl.height, linetop+syl.height/2, linetop+syl.height, bottomhalf.text)
|
|
output.n = output.n + 2
|
|
output[output.n-1] = tophalf
|
|
output[output.n] = bottomhalf
|
|
end
|
|
end
|
|
end
|
|
|
|
function dokanji(lin, output, sty)
|
|
aegisub.set_status(lin.text_stripped)
|
|
|
|
local fontname = "@HGSHigemoji"
|
|
|
|
local lineheight = 0
|
|
local syltime = 0
|
|
local syls = {n=0}
|
|
for i = 1, lin.karaoke.n-1 do
|
|
local syl = lin.karaoke[i]
|
|
syl.height, syl.width, syl.descent, syl.extlead = aegisub.text_extents(sty, syl.text_stripped)
|
|
syl.start_time = syltime
|
|
syl.end_time = syltime + syl.duration
|
|
syltime = syltime + syl.duration
|
|
if syl.text == "#" then
|
|
syls[syls.n-1].duration = syls[syls.n-1].duration + syl.duration
|
|
syls[syls.n-1].end_time = syls[syls.n-1].end_time + syl.duration
|
|
--elseif syl.text == "" then
|
|
-- skip
|
|
else
|
|
lineheight = lineheight + syl.height
|
|
syls[syls.n] = syl
|
|
syls.n = syls.n + 1
|
|
end
|
|
end
|
|
|
|
for i = 0, syls.n-1 do
|
|
local syl = syls[i]
|
|
local top = 170
|
|
for j = 0, 8 do
|
|
if i+j >= syls.n then
|
|
break
|
|
end
|
|
local newlin = copy_line(lin)
|
|
newlin.start_time = lin.start_time + syl.start_time
|
|
newlin.end_time = newlin.start_time + syl.duration
|
|
local startalpha, targetalpha
|
|
if j == 0 then
|
|
startalpha = 0
|
|
targetalpha = 255
|
|
else
|
|
startalpha = j * 255 / 8
|
|
targetalpha = (j-1) * 255 / 8
|
|
end
|
|
newlin.text = string.format("{\\fn%s\\an7\\fr-90\\move(%d,%d,%d,%d)\\1a&H%2x&\\3a&H%2x&\\t(\\1a&H%2x&\\3a&H%2x&)}%s", fontname, 620, top, 620, top-syl.height, startalpha, startalpha, targetalpha, targetalpha, syls[i+j].text)
|
|
top = top + syls[i+j].height
|
|
output.n = output.n + 1
|
|
output[output.n] = newlin
|
|
end
|
|
end
|
|
end
|