Semi-complete kara-templater implementation, regular syl and line handling should be in place now (untested though)
Originally committed to SVN as r1007.
This commit is contained in:
parent
5b0255a59d
commit
06d5929bea
2 changed files with 235 additions and 18 deletions
|
@ -221,6 +221,23 @@ function parse_template(meta, styles, line, templates, mods)
|
|||
end
|
||||
end
|
||||
|
||||
-- Iterator function, return all templates that apply to the given line
|
||||
function matching_templates(templates, line)
|
||||
local lastkey = 0
|
||||
local function test_next()
|
||||
lastkey = lastkey + 1
|
||||
local t = templates[lastkey]
|
||||
if not t then
|
||||
return nil
|
||||
elseif t.style == line.style or not t.style then
|
||||
return t
|
||||
else
|
||||
return test_next()
|
||||
end
|
||||
end
|
||||
return test_next
|
||||
end
|
||||
|
||||
|
||||
-- Apply the templates
|
||||
function apply_templates(meta, styles, subs, templates)
|
||||
|
@ -234,16 +251,7 @@ function apply_templates(meta, styles, subs, templates)
|
|||
-- run all run-once code snippets
|
||||
for k, t in pairs(templates.once) do
|
||||
assert(t.code, "WTF, a 'once' template without code?")
|
||||
local f, err = loadstring(t.code, "template code once")
|
||||
if not f then
|
||||
aegisub.debug.out(2, "Failed to parse Lua code: %s\nCode that failed to parse: %s\n\n", err, t.code)
|
||||
else
|
||||
setfenv(f, tenv)
|
||||
local res, err = pcall(f)
|
||||
if not res then
|
||||
aegisub.debug.out(2, "Runtime error in template code: %s\nCode producing error: %s\n\n", err, t.code)
|
||||
end
|
||||
end
|
||||
run_template_code(t, tenv)
|
||||
end
|
||||
|
||||
-- start processing lines
|
||||
|
@ -256,6 +264,7 @@ function apply_templates(meta, styles, subs, templates)
|
|||
l.comment = true
|
||||
l.effect = "karaoke"
|
||||
subs[i] = l
|
||||
l.i = i
|
||||
-- and then run it through the templates
|
||||
apply_line(meta, styles, subs, l, templates, tenv)
|
||||
end
|
||||
|
@ -263,21 +272,223 @@ function apply_templates(meta, styles, subs, templates)
|
|||
end
|
||||
|
||||
function apply_line(meta, styles, subs, line, templates, tenv)
|
||||
-- apply all line templates
|
||||
for k, t in pairs(templates.line) do
|
||||
end
|
||||
-- loop over syllables
|
||||
for i = 0, line.karaoke.n do
|
||||
local syl = line.karaoke[i]
|
||||
-- apply syllable templates
|
||||
-- Tell whether any templates were applied to this line, needed to know whether the original line should be removed from input
|
||||
local applied_templates = false
|
||||
|
||||
-- apply character templates
|
||||
-- General variable replacement context
|
||||
local varctx = {
|
||||
layer = line.layer,
|
||||
lstart = line.start_time,
|
||||
lend = line.end_time,
|
||||
ldur = line.duration,
|
||||
lmid = line.start_time + line.duration/2,
|
||||
style = line.style,
|
||||
actor = line.actor,
|
||||
margin_l = ((line.margin_l > 0) and line.margin_l) or line.styleref.margin_l,
|
||||
margin_r = ((line.margin_r > 0) and line.margin_r) or line.styleref.margin_r,
|
||||
margin_t = ((line.margin_t > 0) and line.margin_t) or line.styleref.margin_t,
|
||||
margin_b = ((line.margin_b > 0) and line.margin_b) or line.styleref.margin_b,
|
||||
margin_v = ((line.margin_t > 0) and line.margin_t) or line.styleref.margin_t,
|
||||
syln = line.karaoke.n,
|
||||
li = line.i,
|
||||
lleft = line.left,
|
||||
lcenter = line.left + line.width/2,
|
||||
lright = line.left + line.width,
|
||||
lx = line.x,
|
||||
ly = line.y
|
||||
-- TODO: more positioning vars
|
||||
}
|
||||
|
||||
-- Specific for whole-line processing
|
||||
varctx["start"] = varctx.lstart
|
||||
varctx["end"] = varctx.lend
|
||||
varctx.dur = varctx.ldur
|
||||
varctx.mid = varctx.lmid
|
||||
varctx.i = varctx.li
|
||||
varctx.left = varctx.lleft
|
||||
varctx.center = varctx.lcenter
|
||||
varctx.right = varctx.lright
|
||||
varctx.x = varctx.lx
|
||||
varctx.y = varctx.ly
|
||||
|
||||
local function set_ctx_syl(syl)
|
||||
varctx.sstart = syl.start_time
|
||||
varctx.send = syl.end_time
|
||||
varctx.sdur = syl.duration
|
||||
varctx.smid = syl.start_time + syl.duration / 2
|
||||
varctx["start"] = varctx.sstart
|
||||
varctx["end"] = varctx.send
|
||||
varctx.dur = varctx.sdur
|
||||
varctx.mid = varctx.smid
|
||||
varctx.si = syl.i
|
||||
varctx.i = varctx.si
|
||||
varctx.sleft = syl.left
|
||||
varctx.scenter = syl.center
|
||||
varctx.sright = syl.right
|
||||
if line.halign == "left" then
|
||||
varctx.sx = varctx.lleft + syl.left
|
||||
elseif line.halign == "center" then
|
||||
varctx.sx = varctx.lleft + syl.center
|
||||
elseif line.halign == "right" then
|
||||
varctx.sx = varctx.lleft + syl.right
|
||||
end
|
||||
-- loop over furigana
|
||||
varctx.sy = line.y
|
||||
varctx.left = varctx.sleft
|
||||
varctx.center = varctx.scenter
|
||||
varctx.right = varctx.sright
|
||||
varctx.x = varctx.sx
|
||||
varctx.y = varctx.sy
|
||||
end
|
||||
|
||||
tenv.orgline = line
|
||||
tenv.line = nil
|
||||
tenv.syl = nil
|
||||
tenv.char = nil
|
||||
tenv.furi = nil
|
||||
|
||||
-- Apply all line templates
|
||||
for t in matching_templates(templates.line, line) do
|
||||
if t.code then
|
||||
run_template_code(t, tenv)
|
||||
else
|
||||
applied_templates = true
|
||||
local newline = table.copy(line)
|
||||
tenv.line = newline
|
||||
newline.text = ""
|
||||
if t.pre ~= "" then
|
||||
newline.text = newline.text .. run_text_template(t.pre, tenv, varctx)
|
||||
end
|
||||
if t.t ~= "" then
|
||||
for i = 1, line.kara.n do
|
||||
local syl = line.kara[i]
|
||||
tenv.syl = syl
|
||||
set_ctx_syl(syl)
|
||||
newline.text = newline.text .. run_text_template(t.t, tenv, varctx)
|
||||
if t.addtext then
|
||||
if t.keeptags then
|
||||
newline.text = newline.text .. syl.text
|
||||
else
|
||||
newline.text = newline.text .. syl.text_stripped
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
-- hmm, no main template for the line... put original text in
|
||||
newline.text = newline.text .. line.text
|
||||
end
|
||||
newline.effect = "fx"
|
||||
subs.append(newline)
|
||||
end
|
||||
end
|
||||
|
||||
-- Loop over syllables
|
||||
for i = 0, line.kara.n do
|
||||
local syl = line.kara[i]
|
||||
|
||||
-- Apply syllable templates
|
||||
for t in matching_templates(templates.syl, line) do
|
||||
tenv.syl = syl
|
||||
set_ctx_syl(syl)
|
||||
|
||||
if not t.inline_fx or t.inline_fx == syl.inline_fx then
|
||||
if t.code then
|
||||
run_code_template(t, tenv)
|
||||
elseif t.multi then
|
||||
for hl = 1, syl.highlights.n do
|
||||
local hldata = syl.highlights[hl]
|
||||
local hlsyl = table.copy(syl)
|
||||
hlsyl.start_time = hldata.start_time
|
||||
hlsyl.end_time = hldata.end_time
|
||||
hlsyl.duration = hldata.duration
|
||||
tenv.basesyl = syl
|
||||
tenv.syl = hlsyl
|
||||
set_ctx_syl(hlsyl)
|
||||
|
||||
for j = 1, t.loops do
|
||||
tenv.j = j
|
||||
local newline = table.copy(line)
|
||||
tenv.line = newline
|
||||
newline.text = run_text_template(t, tenv, varctx)
|
||||
if t.addtext then
|
||||
newline.text = newline.text .. syl.text_stripped
|
||||
end
|
||||
newline.effect = "fx"
|
||||
subs.append(newline)
|
||||
end
|
||||
end
|
||||
else
|
||||
for j = 1, t.loops do
|
||||
tenv.j = j
|
||||
local newline = table.copy(line)
|
||||
tenv.line = newline
|
||||
newline.text = run_text_template(t, tenv, varctx)
|
||||
if t.addtext then
|
||||
newline.text = newline.text .. syl.text_stripped
|
||||
end
|
||||
newline.effect = "fx"
|
||||
subs.append(newline)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Apply character templates
|
||||
-- TODO
|
||||
end
|
||||
|
||||
-- Loop over furigana
|
||||
for i = 1, line.furi.n do
|
||||
-- TODO
|
||||
end
|
||||
end
|
||||
|
||||
function run_code_template(template, tenv)
|
||||
local f, err = loadstring(template.code, "template code")
|
||||
if not f then
|
||||
aegisub.debug.out(2, "Failed to parse Lua code: %s\nCode that failed to parse: %s\n\n", err, template.code)
|
||||
else
|
||||
setfenv(f, tenv)
|
||||
for j = 1, template.loops do
|
||||
tenv.j = j
|
||||
local res, err = pcall(f)
|
||||
if not res then
|
||||
aegisub.debug.out(2, "Runtime error in template code: %s\nCode producing error: %s\n\n", err, template.code)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function run_text_template(template, tenv, varctx)
|
||||
local res = template
|
||||
|
||||
-- Replace the variables in the string (this is probably faster than using a custom function, but doesn't provide error reporting)
|
||||
if varctx then
|
||||
res = string.gsub(res, "$([%a_]+)", varctx)
|
||||
end
|
||||
|
||||
-- Function for evaluating expressions
|
||||
local function expression_evaluator(expression)
|
||||
f, err = loadstring(string.format("return (%s)", expression))
|
||||
if (err) ~= nil then
|
||||
aegisub.debug.out(2, "Error parsing expression: %s\nExpression producing error: %s\nTemplate with expression: %s\n\n", err, expression, template)
|
||||
return "!" .. expression .. "!"
|
||||
else
|
||||
setfenv(f, tenv)
|
||||
local res, val = pcall(f)
|
||||
if res then
|
||||
return val
|
||||
else
|
||||
aegisub.debug.out(2, "Runtime error in template expression: %s\nExpression producing error: %s\nTemplate with expression: %s\n\n", val, expression, template)
|
||||
return "!" .. expression .. "!"
|
||||
end
|
||||
end
|
||||
end
|
||||
-- Find and evaluate expressions
|
||||
res = string.gsub(res , "!(.-)!", expression_evaluator)
|
||||
|
||||
return res
|
||||
end
|
||||
|
||||
|
||||
-- Main function to do the templating
|
||||
function filter_apply_templates(subs, config)
|
||||
|
|
|
@ -210,18 +210,21 @@ function karaskel.preproc_line(subs, meta, styles, line)
|
|||
line.center = line.left + line.width / 2
|
||||
line.right = line.left + line.width
|
||||
line.x = line.left
|
||||
line.halign = "left"
|
||||
elseif line.styleref.align == 2 or line.styleref.align == 5 or line.styleref.align == 8 then
|
||||
-- Centered
|
||||
line.left = (meta.res_x - line.eff_margin_l - line.eff_margin_r - line.width) / 2 + line.eff_margin_l
|
||||
line.center = line.left + line.width / 2
|
||||
line.right = line.left + line.width
|
||||
line.x = line.center
|
||||
line.halign = "center"
|
||||
elseif line.styleref.align == 3 or line.styleref.align == 6 or line.styleref.align == 9 then
|
||||
-- Right aligned
|
||||
line.left = meta.res_x - line.eff_margin_r - line.width
|
||||
line.center = line.left + line.width / 2
|
||||
line.right = line.left + line.width
|
||||
line.x = line.right
|
||||
line.halign = "right"
|
||||
end
|
||||
line.hcenter = line.center
|
||||
if line.styleref.align >=1 and line.styleref.align <= 3 then
|
||||
|
@ -230,18 +233,21 @@ function karaskel.preproc_line(subs, meta, styles, line)
|
|||
line.middle = line.bottom - line.height / 2
|
||||
line.top = line.bottom - line.height
|
||||
line.y = line.bottom
|
||||
line.valign = "bottom"
|
||||
elseif line.styleref.align >= 4 and line.styleref.align <= 6 then
|
||||
-- Mid aligned
|
||||
line.top = (meta.res_y - line.eff_margin_t - line.eff_margin_b) / 2 + line.eff_margin_t
|
||||
line.middle = line.top + line.height / 2
|
||||
line.bottom = line.top + line.height
|
||||
line.y = line.middle
|
||||
line.valign = "middle"
|
||||
elseif line.styleref.align >= 7 and line.styleref.align <= 9 then
|
||||
-- Top aligned
|
||||
line.top = line.eff_margin_t
|
||||
line.middle = line.top + line.height / 2
|
||||
line.bottom = line.top + line.height
|
||||
line.y = line.top
|
||||
line.valign = "top"
|
||||
end
|
||||
line.vcenter = line.middle
|
||||
|
||||
|
|
Loading…
Reference in a new issue