diff options
Diffstat (limited to '.config/mvi/scripts/ruler.lua')
| -rw-r--r-- | .config/mvi/scripts/ruler.lua | 388 |
1 files changed, 0 insertions, 388 deletions
diff --git a/.config/mvi/scripts/ruler.lua b/.config/mvi/scripts/ruler.lua deleted file mode 100644 index 60355ce..0000000 --- a/.config/mvi/scripts/ruler.lua +++ /dev/null @@ -1,388 +0,0 @@ -local opts = { - show_distance=true, - show_coordinates=true, - coordinates_space="image", - show_angles="degrees", - line_width=2, - dots_radius=3, - font_size=36, - line_color="33", - confirm_bindings="MBTN_LEFT,ENTER", - exit_bindings="ESC", - set_first_point_on_begin=false, - clear_on_second_point_set=false, -} -(require 'mp.options').read_options(opts) - -function split(input) - local ret = {} - for str in string.gmatch(input, "([^,]+)") do - ret[#ret + 1] = str - end - return ret -end -opts.confirm_bindings=split(opts.confirm_bindings) -opts.exit_bindings=split(opts.exit_bindings) - -local msg = require 'mp.msg' -local assdraw = require 'mp.assdraw' - -local video_dimensions_stale = true - -function get_video_dimensions() - -- this function is very much ripped from video/out/aspect.c in mpv's source - if not video_dimensions_stale then return _video_dimensions end - local video_params = mp.get_property_native("video-out-params") - if not video_params then - _video_dimensions = nil - return nil - end - if not _timestamp then _timestamp = 0 end - _timestamp = _timestamp + 1 - _video_dimensions = { - timestamp = _timestamp, - top_left = { 0, 0 }, - bottom_right = { 0, 0 }, - size = { 0, 0 }, - ratios = { 0, 0 }, -- by how much the original video got scaled - } - local keep_aspect = mp.get_property_bool("keepaspect") - local w = video_params["w"] - local h = video_params["h"] - local dw = video_params["dw"] - local dh = video_params["dh"] - if mp.get_property_number("video-rotate") % 180 == 90 then - w, h = h,w - dw, dh = dh, dw - end - local window_w, window_h = mp.get_osd_size() - - if keep_aspect then - local unscaled = mp.get_property_native("video-unscaled") - local panscan = mp.get_property_number("panscan") - - local fwidth = window_w - local fheight = math.floor(window_w / dw * dh) - if fheight > window_h or fheight < h then - local tmpw = math.floor(window_h / dh * dw) - if tmpw <= window_w then - fheight = window_h - fwidth = tmpw - end - end - local vo_panscan_area = window_h - fheight - local f_w = fwidth / fheight - local f_h = 1 - if vo_panscan_area == 0 then - vo_panscan_area = window_h - fwidth - f_w = 1 - f_h = fheight / fwidth - end - if unscaled or unscaled == "downscale-big" then - vo_panscan_area = 0 - if unscaled or (dw <= window_w and dh <= window_h) then - fwidth = dw - fheight = dh - end - end - - local scaled_width = fwidth + math.floor(vo_panscan_area * panscan * f_w) - local scaled_height = fheight + math.floor(vo_panscan_area * panscan * f_h) - - local split_scaling = function (dst_size, scaled_src_size, zoom, align, pan) - scaled_src_size = math.floor(scaled_src_size * 2 ^ zoom) - align = (align + 1) / 2 - local dst_start = math.floor((dst_size - scaled_src_size) * align + pan * scaled_src_size) - if dst_start < 0 then - --account for C int cast truncating as opposed to flooring - dst_start = dst_start + 1 - end - local dst_end = dst_start + scaled_src_size; - if dst_start >= dst_end then - dst_start = 0 - dst_end = 1 - end - return dst_start, dst_end - end - local zoom = mp.get_property_number("video-zoom") - - local align_x = mp.get_property_number("video-align-x") - local pan_x = mp.get_property_number("video-pan-x") - _video_dimensions.top_left[1], _video_dimensions.bottom_right[1] = split_scaling(window_w, scaled_width, zoom, align_x, pan_x) - - local align_y = mp.get_property_number("video-align-y") - local pan_y = mp.get_property_number("video-pan-y") - _video_dimensions.top_left[2], _video_dimensions.bottom_right[2] = split_scaling(window_h, scaled_height, zoom, align_y, pan_y) - else - _video_dimensions.top_left[1] = 0 - _video_dimensions.bottom_right[1] = window_w - _video_dimensions.top_left[2] = 0 - _video_dimensions.bottom_right[2] = window_h - end - _video_dimensions.size[1] = _video_dimensions.bottom_right[1] - _video_dimensions.top_left[1] - _video_dimensions.size[2] = _video_dimensions.bottom_right[2] - _video_dimensions.top_left[2] - _video_dimensions.ratios[1] = _video_dimensions.size[1] / w - _video_dimensions.ratios[2] = _video_dimensions.size[2] / h - video_dimensions_stale = false - return _video_dimensions -end - -for _, p in ipairs({ - "keepaspect", - "video-out-params", - "video-unscaled", - "panscan", - "video-zoom", - "video-align-x", - "video-pan-x", - "video-align-y", - "video-pan-y", - "osd-width", - "osd-height", -}) do - mp.observe_property(p, nil, function() video_dimensions_stale = true end) -end - -local state = 0 -- {0,1,2,3} = {inactive,setting first point,setting second point,done} -local first_point = nil -- in video space coordinates -local second_point = nil -- in video space coordinates - -function draw_ass(ass) - local ww, wh = mp.get_osd_size() - mp.set_osd_ass(ww, wh, ass) -end - -function cursor_video_space() - local dim = get_video_dimensions() - if not dim then return nil end - local mx, my = mp.get_mouse_pos() - local ret = {} - ret[1] = (mx - dim.top_left[1]) / dim.ratios[1] - ret[2] = (my - dim.top_left[2]) / dim.ratios[2] - return ret -end - -function video_space_to_screen(point) - local dim = get_video_dimensions() - if not dim then return nil end - local ret = {} - ret[1] = point[1] * dim.ratios[1] + dim.top_left[1] - ret[2] = point[2] * dim.ratios[2] + dim.top_left[2] - return ret -end - -function refresh() - local dim = get_video_dimensions() - if not dim then - draw_ass("") - return - end - - local line_start = {} - local line_end = {} - if second_point then - line_start.image = first_point - line_start.screen = video_space_to_screen(first_point) - line_end.image = second_point - line_end.screen = video_space_to_screen(second_point) - elseif first_point then - line_start.image = first_point - line_start.screen = video_space_to_screen(first_point) - line_end.image = cursor_video_space() - line_end.screen = {} - line_end.screen[1], line_end.screen[2] = mp.get_mouse_pos() - else - local mx, my = mp.get_mouse_pos() - line_start.image = cursor_video_space() - line_start.screen = {} - line_start.screen[1], line_start.screen[2] = mp.get_mouse_pos() - line_end = line_start - end - local distinct = (math.abs(line_start.screen[1] - line_end.screen[1]) >= 1 - or math.abs(line_start.screen[2] - line_end.screen[2]) >= 1) - - local a = assdraw:ass_new() - local draw_setup = function(bord) - a:new_event() - a:pos(0,0) - a:append("{\\bord" .. bord .. "}") - a:append("{\\shad0}") - local r = opts.line_color - a:append("{\\3c&H".. r .. r .. r .. "&}") - a:append("{\\1a&HFF}") - a:append("{\\2a&HFF}") - a:append("{\\3a&H00}") - a:append("{\\4a&HFF}") - a:draw_start() - end - local dot = function(pos, size) - draw_setup(size) - a:move_to(pos[1], pos[2]-0.5) - a:line_to(pos[1], pos[2]+0.5) - end - local line = function(from, to, size) - draw_setup(size) - a:move_to(from[1], from[2]) - a:line_to(to[1], to[2]) - end - if distinct then - dot(line_start.screen, opts.dots_radius) - line(line_start.screen, line_end.screen, opts.line_width) - dot(line_end.screen, opts.dots_radius) - else - dot(line_start.screen, opts.dots_radius) - end - - local line_info = function() - if not opts.show_distance then return end - a:new_event() - a:append("{\\fs36}{\\bord1}") - a:pos((line_start.screen[1] + line_end.screen[1]) / 2, (line_start.screen[2] + line_end.screen[2]) / 2) - local an = 1 - if line_start.image[1] < line_end.image[1] then an = an + 2 end - if line_start.image[2] < line_end.image[2] then an = an + 6 end - a:an(an) - local image = math.sqrt(math.pow(line_start.image[1] - line_end.image[1], 2) + math.pow(line_start.image[2] - line_end.image[2], 2)) - local screen = math.sqrt(math.pow(line_start.screen[1] - line_end.screen[1], 2) + math.pow(line_start.screen[2] - line_end.screen[2], 2)) - if opts.coordinates_space == "both" then - a:append(string.format("image: %.1f\\Nscreen: %.1f", image, screen)) - elseif opts.coordinates_space == "image" then - a:append(string.format("%.1f", image)) - elseif opts.coordinates_space == "window" then - a:append(string.format("%.1f", screen)) - end - end - local dot_info = function(pos, opposite) - if not opts.show_coordinates then return end - a:new_event() - a:append("{\\fs" .. opts.font_size .."}{\\bord1}") - a:pos(pos.screen[1], pos.screen[2]) - local an - if distinct then - an = 1 - if line_start.image[1] > line_end.image[1] then an = an + 2 end - if line_start.image[2] < line_end.image[2] then an = an + 6 end - else - an = 7 - end - if opposite then - an = 9 + 1 - an - end - a:an(an) - if opts.coordinates_space == "both" then - a:append(string.format("image: %.1f, %.1f\\Nscreen: %i, %i", - pos.image[1], pos.image[2], pos.screen[1], pos.screen[2])) - elseif opts.coordinates_space == "image" then - a:append(string.format("%.1f, %.1f", pos.image[1], pos.image[2])) - elseif opts.coordinates_space == "window" then - a:append(string.format("%i, %i", pos.screen[1], pos.screen[2])) - end - end - dot_info(line_start, true) - if distinct then - line_info() - dot_info(line_end, false) - end - if distinct and opts.show_angles ~= "no" then - local dist = 50 - local pos_from_angle = function(mult, angle) - return { - line_start.screen[1] + mult * dist * math.cos(angle), - line_start.screen[2] + mult * dist * math.sin(angle), - } - end - local extended = { line_start.screen[1], line_start.screen[2] } - if line_end.screen[1] > line_start.screen[1] then - extended[1] = extended[1] + dist - else - extended[1] = extended[1] - dist - end - line(line_start.screen, extended, math.max(0, opts.line_width-0.5)) - local angle = math.atan(math.abs(line_start.image[2] - line_end.image[2]) / math.abs(line_start.image[1] - line_end.image[1])) - local fix_angle - local an - if line_end.image[2] < line_start.image[2] and line_end.image[1] > line_start.image[1] then - -- upper-right - an = 4 - fix_angle = function(angle) return - angle end - elseif line_end.image[2] < line_start.image[2] then - -- upper-left - an = 6 - fix_angle = function(angle) return math.pi + angle end - elseif line_end.image[1] < line_start.image[1] then - -- bottom-left - an = 6 - fix_angle = function(angle) return math.pi - angle end - else - -- bottom-right - an = 4 - fix_angle = function(angle) return angle end - end - -- should implement this https://math.stackexchange.com/questions/873224/calculate-control-points-of-cubic-bezier-curve-approximating-a-part-of-a-circle - local cp1 = pos_from_angle(1, fix_angle(angle*1/4)) - local cp2 = pos_from_angle(1, fix_angle(angle*3/4)) - local p2 = pos_from_angle(1, fix_angle(angle)) - a:bezier_curve(cp1[1], cp1[2], cp2[1], cp2[2], p2[1], p2[2]) - - a:new_event() - a:append("{\\fs" .. opts.font_size .."}{\\bord1}") - local text_pos = pos_from_angle(1.1, fix_angle(angle*2/3)) -- you'd think /2 would make more sense, but *2/3 looks better - a:pos(text_pos[1], text_pos[2]) - a:an(an) - if opts.show_angles == "both" then - a:append(string.format("%.2f\\N%.1f°", angle, angle / math.pi * 180)) - elseif opts.show_angles == "degrees" then - a:append(string.format("%.1f°", angle / math.pi * 180)) - elseif opts.show_angles == "radians" then - a:append(string.format("%.2f", angle)) - end - end - - draw_ass(a.text) -end - -function next() - if state == 0 then - mp.register_idle(refresh) - mp.add_forced_key_binding("mouse_move", "ruler-mouse-move", function() end) -- only used to get an idle event on mouse move - for _,key in ipairs(opts.confirm_bindings) do - mp.add_forced_key_binding(key, "ruler-next-" .. key, next) - end - for _,key in ipairs(opts.exit_bindings) do - mp.add_forced_key_binding(key, "ruler-stop-" .. key, stop) - end - state = 1 - if opts.set_first_point_on_begin then - next() - end - elseif state == 1 then - first_point = cursor_video_space() - state = 2 - elseif state == 2 then - state = 3 - second_point = cursor_video_space() - if opts.clear_on_second_point_set then - next() - end - else - stop() - end -end - -function stop() - if state == 0 then return end - mp.unregister_idle(refresh) - for _,key in ipairs(opts.confirm_bindings) do - mp.remove_key_binding("ruler-next-" .. key) - end - for _,key in ipairs(opts.exit_bindings) do - mp.remove_key_binding("ruler-stop-" .. key) - end - mp.remove_key_binding("ruler-mouse-move") - state = 0 - first_point = nil - second_point = nil - draw_ass("") -end - -mp.add_key_binding(nil, "ruler", next) |