forked from mia/Aegisub
Add support for variable loops in kara-templater, and add a few more utility functions.
- Variable loops are controlled using the tenv.maxloop(newmax) function to set the loop counter max. This is a wrapper around setting tenv.maxj. - Add tenv.relayer(newlayer) function for changing the Layer of an output line. - Add tenv.restyle(newstyle) function for changing the Style of an output line, despite this usually breaking positioning/sizing information. - tenv.maxloops is an alias for tenv.maxloop. - tenv.loopctl(newj, newmaxj) controls both loop variables if anyone wants to do that. This closes #753 but documentation still needs to be written. Originally committed to SVN as r2913.
This commit is contained in:
parent
277adad41f
commit
d71fa2d85c
1 changed files with 59 additions and 10 deletions
|
@ -265,6 +265,26 @@ function matching_templates(templates, line, tenv)
|
||||||
return test_next
|
return test_next
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Iterator function, run a loop using tenv.j and tenv.maxj as loop controllers
|
||||||
|
function template_loop(tenv, initmaxj)
|
||||||
|
local oldmaxj = initmaxj
|
||||||
|
tenv.maxj = initmaxj
|
||||||
|
tenv.j = 0
|
||||||
|
local function itor()
|
||||||
|
if tenv.j >= tenv.maxj or aegisub.progress.is_cancelled() then
|
||||||
|
return nil
|
||||||
|
else
|
||||||
|
tenv.j = tenv.j + 1
|
||||||
|
if oldmaxj ~= tenv.maxj then
|
||||||
|
aegisub.debug.out(5, "Number of loop iterations changed from %d to %d\n", oldmaxj, tenv.maxj)
|
||||||
|
oldmaxj = tenv.maxj
|
||||||
|
end
|
||||||
|
return tenv.j, tenv.maxj
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return itor
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Apply the templates
|
-- Apply the templates
|
||||||
function apply_templates(meta, styles, subs, templates)
|
function apply_templates(meta, styles, subs, templates)
|
||||||
|
@ -278,6 +298,8 @@ function apply_templates(meta, styles, subs, templates)
|
||||||
}
|
}
|
||||||
tenv.tenv = tenv
|
tenv.tenv = tenv
|
||||||
|
|
||||||
|
-- Define helper functions in tenv
|
||||||
|
|
||||||
tenv.retime = function(mode, addstart, addend)
|
tenv.retime = function(mode, addstart, addend)
|
||||||
local line, syl = tenv.line, tenv.syl
|
local line, syl = tenv.line, tenv.syl
|
||||||
local newstart, newend = line.start_time, line.end_time
|
local newstart, newend = line.start_time, line.end_time
|
||||||
|
@ -322,8 +344,31 @@ function apply_templates(meta, styles, subs, templates)
|
||||||
line.duration = newend - newstart
|
line.duration = newend - newstart
|
||||||
return ""
|
return ""
|
||||||
end
|
end
|
||||||
|
|
||||||
tenv.fxgroup = {}
|
tenv.fxgroup = {}
|
||||||
|
|
||||||
|
tenv.relayer = function(layer)
|
||||||
|
line.layer = layer
|
||||||
|
return ""
|
||||||
|
end
|
||||||
|
|
||||||
|
tenv.restyle = function(style)
|
||||||
|
line.style = style
|
||||||
|
line.styleref = styles[style]
|
||||||
|
return ""
|
||||||
|
end
|
||||||
|
|
||||||
|
tenv.maxloop = function(newmaxj)
|
||||||
|
tenv.maxj = newmaxj
|
||||||
|
return ""
|
||||||
|
end
|
||||||
|
tenv.maxloops = tenv.maxloop
|
||||||
|
tenv.loopctl = function(newj, newmaxj)
|
||||||
|
tenv.j = newj
|
||||||
|
tenv.maxj = newmaxj
|
||||||
|
return ""
|
||||||
|
end
|
||||||
|
|
||||||
-- 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?")
|
||||||
|
@ -443,8 +488,7 @@ function apply_line(meta, styles, subs, line, templates, tenv)
|
||||||
-- Apply all line templates
|
-- Apply all line templates
|
||||||
aegisub.debug.out(5, "Running line templates\n")
|
aegisub.debug.out(5, "Running line templates\n")
|
||||||
for t in matching_templates(templates.line, line, tenv) do
|
for t in matching_templates(templates.line, line, tenv) do
|
||||||
tenv.j = 0
|
if aegisub.progress.is_cancelled() then break end
|
||||||
tenv.maxj = t.loops
|
|
||||||
|
|
||||||
-- Set varctx for per-line variables
|
-- Set varctx for per-line variables
|
||||||
varctx["start"] = varctx.lstart
|
varctx["start"] = varctx.lstart
|
||||||
|
@ -464,11 +508,15 @@ function apply_line(meta, styles, subs, line, templates, tenv)
|
||||||
varctx.x = varctx.lx
|
varctx.x = varctx.lx
|
||||||
varctx.y = varctx.ly
|
varctx.y = varctx.ly
|
||||||
|
|
||||||
while tenv.j < t.loops do
|
for j, maxj in template_loop(tenv, t.loops) do
|
||||||
tenv.j = tenv.j + 1
|
|
||||||
if t.code then
|
if t.code then
|
||||||
aegisub.debug.out(5, "Code template, %s\n", t.code)
|
aegisub.debug.out(5, "Code template, %s\n", t.code)
|
||||||
tenv.line = line
|
tenv.line = line
|
||||||
|
-- Although run_code_template also performs template looping this works
|
||||||
|
-- by "luck", since by the time the first loop of this outer loop completes
|
||||||
|
-- the one run by run_code_template has already performed all iterations
|
||||||
|
-- and has tenv.j and tenv.maxj in a loop-ending state, causing the outer
|
||||||
|
-- loop to only ever run once.
|
||||||
run_code_template(t, tenv)
|
run_code_template(t, tenv)
|
||||||
else
|
else
|
||||||
aegisub.debug.out(5, "Line template, pre = '%s', t = '%s'\n", t.pre, t.t)
|
aegisub.debug.out(5, "Line template, pre = '%s', t = '%s'\n", t.pre, t.t)
|
||||||
|
@ -512,6 +560,7 @@ function apply_line(meta, styles, subs, line, templates, tenv)
|
||||||
|
|
||||||
-- Loop over syllables
|
-- Loop over syllables
|
||||||
for i = 0, line.kara.n do
|
for i = 0, line.kara.n do
|
||||||
|
if aegisub.progress.is_cancelled() then break end
|
||||||
local syl = line.kara[i]
|
local syl = line.kara[i]
|
||||||
|
|
||||||
aegisub.debug.out(5, "Applying templates to syllable: %s\n", syl.text)
|
aegisub.debug.out(5, "Applying templates to syllable: %s\n", syl.text)
|
||||||
|
@ -522,6 +571,7 @@ function apply_line(meta, styles, subs, line, templates, tenv)
|
||||||
|
|
||||||
-- Loop over furigana
|
-- Loop over furigana
|
||||||
for i = 1, line.furi.n do
|
for i = 1, line.furi.n do
|
||||||
|
if aegisub.progress.is_cancelled() then break end
|
||||||
local furi = line.furi[i]
|
local furi = line.furi[i]
|
||||||
|
|
||||||
aegisub.debug.out(5, "Applying templates to furigana: %s\n", furi.text)
|
aegisub.debug.out(5, "Applying templates to furigana: %s\n", furi.text)
|
||||||
|
@ -540,9 +590,7 @@ function run_code_template(template, tenv)
|
||||||
else
|
else
|
||||||
local pcall = pcall
|
local pcall = pcall
|
||||||
setfenv(f, tenv)
|
setfenv(f, tenv)
|
||||||
tenv.maxj = template.loops
|
for j, maxj in template_loop(tenv, template.loops) do
|
||||||
for j = 1, template.loops do
|
|
||||||
tenv.j = j
|
|
||||||
local res, err = pcall(f)
|
local res, err = pcall(f)
|
||||||
if not res then
|
if not res then
|
||||||
aegisub.debug.out(2, "Runtime error in template code: %s\nCode producing error: %s\n\n", err, template.code)
|
aegisub.debug.out(2, "Runtime error in template code: %s\nCode producing error: %s\n\n", err, template.code)
|
||||||
|
@ -604,6 +652,8 @@ function apply_syllable_templates(syl, line, templates, tenv, varctx, subs)
|
||||||
|
|
||||||
-- Loop over all templates matching the line style
|
-- Loop over all templates matching the line style
|
||||||
for t in matching_templates(templates, line, tenv) do
|
for t in matching_templates(templates, line, tenv) do
|
||||||
|
if aegisub.progress.is_cancelled() then break end
|
||||||
|
|
||||||
tenv.syl = syl
|
tenv.syl = syl
|
||||||
tenv.basesyl = syl
|
tenv.basesyl = syl
|
||||||
set_ctx_syl(varctx, line, syl)
|
set_ctx_syl(varctx, line, syl)
|
||||||
|
@ -631,6 +681,7 @@ end
|
||||||
|
|
||||||
function apply_one_syllable_template(syl, line, template, tenv, varctx, subs, skip_perchar, skip_multi)
|
function apply_one_syllable_template(syl, line, template, tenv, varctx, subs, skip_perchar, skip_multi)
|
||||||
local t = template
|
local t = template
|
||||||
|
if aegisub.progress.is_cancelled() then return false end
|
||||||
|
|
||||||
aegisub.debug.out(5, "Applying template to one syllable with text: %s\n", syl.text)
|
aegisub.debug.out(5, "Applying template to one syllable with text: %s\n", syl.text)
|
||||||
|
|
||||||
|
@ -697,9 +748,7 @@ function apply_one_syllable_template(syl, line, template, tenv, varctx, subs, sk
|
||||||
run_code_template(t, tenv)
|
run_code_template(t, tenv)
|
||||||
else
|
else
|
||||||
aegisub.debug.out(5, "Running %d effect loops\n", t.loops)
|
aegisub.debug.out(5, "Running %d effect loops\n", t.loops)
|
||||||
tenv.maxj = t.loops
|
for j, maxj in template_loop(tenv, t.loops) do
|
||||||
for j = 1, t.loops do
|
|
||||||
tenv.j = j
|
|
||||||
local newline = table.copy(line)
|
local newline = table.copy(line)
|
||||||
newline.styleref = syl.style
|
newline.styleref = syl.style
|
||||||
newline.style = syl.style.name
|
newline.style = syl.style.name
|
||||||
|
|
Loading…
Reference in a new issue