Last active
July 16, 2020 18:50
-
-
Save The0x539/f0de983ca1416cc9f92caa9f66f0e75d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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