Skip to content

Instantly share code, notes, and snippets.

@The0x539
Last active July 16, 2020 18:50
Show Gist options
  • Save The0x539/f0de983ca1416cc9f92caa9f66f0e75d to your computer and use it in GitHub Desktop.
Save The0x539/f0de983ca1416cc9f92caa9f66f0e75d to your computer and use it in GitHub Desktop.
local tr = aegisub.gettext
script_name = tr't-retime'
script_description = tr'Set start/end timestamps while preserving transform timing'
script_author = 'The0x539'
script_version = '1'
local function splice(str, a, b, replacement)
return str:sub(1, a - 1) .. replacement .. str:sub(b + 1)
end
local function parse_transform(contents)
-- accel just gets lumped in with tags because we can do that
local a, b, t1, t2, tags = contents:find('^%((%-?%d+),(%-?%d+),(.+)%)$')
if a ~= nil then
return tonumber(t1), tonumber(t2), tags
end
local a, b, tags = contents:find('^%((.+)%)$')
if a ~= nil then
return nil, nil, tags
end
error('failed to parse transform args: ' .. contents)
end
local function parse_move(contents)
local a, b, coords, t1, t2 = contents:find('^%((%-?[%d.]+,%-?[%d.]+,%-?[%d.]+,%-?[%d.]+),(%-?%d+),(%-?%d+)%)$')
if a ~= nil then
return coords, tonumber(t1), tonumber(t2)
end
local a, b, coords, t1, t2 = contents:find('^%((%-?[%d.]+,%-?[%d.]+,%-?[%d.]+,%-?[%d.]+)%)$')
if a ~= nil then
return coords, nil, nil
end
error('failed to parse move args: ' .. contents)
end
local function parse_fade(contents)
local a, b, alphas, t1, t2, t3, t4 = contents:find('^%((%d+,%d+,%d+),(%-?%d+),(%-?%d+),(%-?%d+),(%-?%d+)%)$')
if a ~= nil then
return alphas, t1, t2, t3, t4
end
error('failed to parse fade args: ' .. contents)
end
local function process(line, delta_start, delta_end)
local block_index = 1
while true do
local block_a, block_b = line.text:find('{.-}', block_index)
if block_a == nil or block_b == nil then
break
end
block_index = block_b + 1
local block = line.text:sub(block_a, block_b)
local index = 1
while true do
local a, b, contents = block:find('\\t(%b())', index)
if a == nil or b == nil then
break
end
index = b + 1
local t1, t2, tags = parse_transform(contents)
t1 = (t1 or 0) - delta_start
t2 = (t2 or line.duration) - delta_start
local new_tag = ('\\t(%d,%d,%s)'):format(t1, t2, tags)
line.text = splice(line.text, block_a - 1 + a, block_a - 1 + b, new_tag)
end
local a, b, contents = block:find('\\move(%b())')
if contents ~= nil then
local coords, t1, t2 = parse_move(contents)
t1 = (t1 or 0) - delta_start
t2 = (t2 or line.duration) - delta_start
local new_tag = ('\\move(%s,%d,%d)'):format(coords, t1, t2)
line.text = splice(line.text, block_a - 1 + a, block_a - 1 + b, new_tag)
end
local a, b, contents = block:find('\\fade(%b())', index)
if contents ~= nil then
local alphas, t1, t2, t3, t4 = parse_fade(contents)
t1 = tonumber(t1) - delta_start
t2 = tonumber(t2) - delta_start
t3 = tonumber(t3) - delta_start
t4 = tonumber(t4) - delta_start
local new_tag = ('\\fade(%s,%d,%d,%d,%d)'):format(alphas, t1, t2, t3, t4)
line.text = splice(line.text, block_a - 1 + a, block_a - 1 + b, new_tag)
end
end
line.start_time = line.start_time + delta_start
line.end_time = line.end_time + delta_end
end
function process_all(subs, sel, changing_start)
local video_position = aegisub.ms_from_frame(aegisub.project_properties().video_position)
video_position = video_position - (video_position % 10)
for _, li in ipairs(sel) do
local line = subs[li]
local delta_start, delta_end = 0, 0
if changing_start then
delta_start = video_position - line.start_time
else
delta_end = video_position - line.end_time
end
process(line, delta_start, delta_end)
subs[li] = line
end
end
local function set_start(subs, sel, i)
process_all(subs, sel, true)
aegisub.set_undo_point('Snap start to video, preserving transform timing')
end
local function set_end(subs, sel, i)
process_all(subs, sel, false)
aegisub.set_undo_point('Snap end to video, preserving transform timing')
end
aegisub.register_macro('t-retime/Set Start', script_description, set_start)
aegisub.register_macro('t-retime/Set End', script_description, set_end)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment