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
|
||||||
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
|
-- Apply the templates
|
||||||
function apply_templates(meta, styles, subs, 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
|
-- run all run-once code snippets
|
||||||
for k, t in pairs(templates.once) do
|
for k, t in pairs(templates.once) do
|
||||||
assert(t.code, "WTF, a 'once' template without code?")
|
assert(t.code, "WTF, a 'once' template without code?")
|
||||||
local f, err = loadstring(t.code, "template code once")
|
run_template_code(t, tenv)
|
||||||
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
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- start processing lines
|
-- start processing lines
|
||||||
|
@ -256,6 +264,7 @@ function apply_templates(meta, styles, subs, templates)
|
||||||
l.comment = true
|
l.comment = true
|
||||||
l.effect = "karaoke"
|
l.effect = "karaoke"
|
||||||
subs[i] = l
|
subs[i] = l
|
||||||
|
l.i = i
|
||||||
-- and then run it through the templates
|
-- and then run it through the templates
|
||||||
apply_line(meta, styles, subs, l, templates, tenv)
|
apply_line(meta, styles, subs, l, templates, tenv)
|
||||||
end
|
end
|
||||||
|
@ -263,21 +272,223 @@ function apply_templates(meta, styles, subs, templates)
|
||||||
end
|
end
|
||||||
|
|
||||||
function apply_line(meta, styles, subs, line, templates, tenv)
|
function apply_line(meta, styles, subs, line, templates, tenv)
|
||||||
-- apply all line templates
|
-- Tell whether any templates were applied to this line, needed to know whether the original line should be removed from input
|
||||||
for k, t in pairs(templates.line) do
|
local applied_templates = false
|
||||||
|
|
||||||
|
-- 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
|
||||||
|
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
|
end
|
||||||
-- loop over syllables
|
|
||||||
for i = 0, line.karaoke.n do
|
tenv.orgline = line
|
||||||
local syl = line.karaoke[i]
|
tenv.line = nil
|
||||||
-- apply syllable templates
|
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 character templates
|
-- 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
|
end
|
||||||
-- loop over furigana
|
|
||||||
|
-- Loop over furigana
|
||||||
for i = 1, line.furi.n do
|
for i = 1, line.furi.n do
|
||||||
|
-- TODO
|
||||||
end
|
end
|
||||||
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
|
-- Main function to do the templating
|
||||||
function filter_apply_templates(subs, config)
|
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.center = line.left + line.width / 2
|
||||||
line.right = line.left + line.width
|
line.right = line.left + line.width
|
||||||
line.x = line.left
|
line.x = line.left
|
||||||
|
line.halign = "left"
|
||||||
elseif line.styleref.align == 2 or line.styleref.align == 5 or line.styleref.align == 8 then
|
elseif line.styleref.align == 2 or line.styleref.align == 5 or line.styleref.align == 8 then
|
||||||
-- Centered
|
-- Centered
|
||||||
line.left = (meta.res_x - line.eff_margin_l - line.eff_margin_r - line.width) / 2 + line.eff_margin_l
|
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.center = line.left + line.width / 2
|
||||||
line.right = line.left + line.width
|
line.right = line.left + line.width
|
||||||
line.x = line.center
|
line.x = line.center
|
||||||
|
line.halign = "center"
|
||||||
elseif line.styleref.align == 3 or line.styleref.align == 6 or line.styleref.align == 9 then
|
elseif line.styleref.align == 3 or line.styleref.align == 6 or line.styleref.align == 9 then
|
||||||
-- Right aligned
|
-- Right aligned
|
||||||
line.left = meta.res_x - line.eff_margin_r - line.width
|
line.left = meta.res_x - line.eff_margin_r - line.width
|
||||||
line.center = line.left + line.width / 2
|
line.center = line.left + line.width / 2
|
||||||
line.right = line.left + line.width
|
line.right = line.left + line.width
|
||||||
line.x = line.right
|
line.x = line.right
|
||||||
|
line.halign = "right"
|
||||||
end
|
end
|
||||||
line.hcenter = line.center
|
line.hcenter = line.center
|
||||||
if line.styleref.align >=1 and line.styleref.align <= 3 then
|
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.middle = line.bottom - line.height / 2
|
||||||
line.top = line.bottom - line.height
|
line.top = line.bottom - line.height
|
||||||
line.y = line.bottom
|
line.y = line.bottom
|
||||||
|
line.valign = "bottom"
|
||||||
elseif line.styleref.align >= 4 and line.styleref.align <= 6 then
|
elseif line.styleref.align >= 4 and line.styleref.align <= 6 then
|
||||||
-- Mid aligned
|
-- Mid aligned
|
||||||
line.top = (meta.res_y - line.eff_margin_t - line.eff_margin_b) / 2 + line.eff_margin_t
|
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.middle = line.top + line.height / 2
|
||||||
line.bottom = line.top + line.height
|
line.bottom = line.top + line.height
|
||||||
line.y = line.middle
|
line.y = line.middle
|
||||||
|
line.valign = "middle"
|
||||||
elseif line.styleref.align >= 7 and line.styleref.align <= 9 then
|
elseif line.styleref.align >= 7 and line.styleref.align <= 9 then
|
||||||
-- Top aligned
|
-- Top aligned
|
||||||
line.top = line.eff_margin_t
|
line.top = line.eff_margin_t
|
||||||
line.middle = line.top + line.height / 2
|
line.middle = line.top + line.height / 2
|
||||||
line.bottom = line.top + line.height
|
line.bottom = line.top + line.height
|
||||||
line.y = line.top
|
line.y = line.top
|
||||||
|
line.valign = "top"
|
||||||
end
|
end
|
||||||
line.vcenter = line.middle
|
line.vcenter = line.middle
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue