diff options
Diffstat (limited to '.config/mpv/scripts/uosc_shared/elements/Speed.lua')
| -rw-r--r-- | .config/mpv/scripts/uosc_shared/elements/Speed.lua | 183 | 
1 files changed, 183 insertions, 0 deletions
| diff --git a/.config/mpv/scripts/uosc_shared/elements/Speed.lua b/.config/mpv/scripts/uosc_shared/elements/Speed.lua new file mode 100644 index 0000000..9681ccf --- /dev/null +++ b/.config/mpv/scripts/uosc_shared/elements/Speed.lua @@ -0,0 +1,183 @@ +local Element = require('uosc_shared/elements/Element') + +---@alias Dragging { start_time: number; start_x: number; distance: number; speed_distance: number; start_speed: number; } + +---@class Speed : Element +local Speed = class(Element) + +---@param props? ElementProps +function Speed:new(props) return Class.new(self, props) --[[@as Speed]] end +function Speed:init(props) +	Element.init(self, 'speed', props) + +	self.width = 0 +	self.height = 0 +	self.notches = 10 +	self.notch_every = 0.1 +	---@type number +	self.notch_spacing = nil +	---@type number +	self.font_size = nil +	---@type Dragging|nil +	self.dragging = nil +end + +function Speed:on_coordinates() +	self.height, self.width = self.by - self.ay, self.bx - self.ax +	self.notch_spacing = self.width / (self.notches + 1) +	self.font_size = round(self.height * 0.48 * options.font_scale) +end + +function Speed:speed_step(speed, up) +	if options.speed_step_is_factor then +		if up then +			return speed * options.speed_step +		else +			return speed * 1 / options.speed_step +		end +	else +		if up then +			return speed + options.speed_step +		else +			return speed - options.speed_step +		end +	end +end + +function Speed:on_mbtn_left_down() +	-- Don't accept clicks while hidden. +	if self:get_visibility() <= 0 then return end +	self:tween_stop() -- Stop and cleanup possible ongoing animations +	self.dragging = { +		start_time = mp.get_time(), +		start_x = cursor.x, +		distance = 0, +		speed_distance = 0, +		start_speed = state.speed, +	} +end + +function Speed:on_global_mouse_move() +	if not self.dragging then return end + +	self.dragging.distance = cursor.x - self.dragging.start_x +	self.dragging.speed_distance = (-self.dragging.distance / self.notch_spacing * self.notch_every) + +	local speed_current = state.speed +	local speed_drag_current = self.dragging.start_speed + self.dragging.speed_distance +	speed_drag_current = clamp(0.01, speed_drag_current, 100) +	local drag_dir_up = speed_drag_current > speed_current + +	local speed_step_next = speed_current +	local speed_drag_diff = math.abs(speed_drag_current - speed_current) +	while math.abs(speed_step_next - speed_current) < speed_drag_diff do +		speed_step_next = self:speed_step(speed_step_next, drag_dir_up) +	end +	local speed_step_prev = self:speed_step(speed_step_next, not drag_dir_up) + +	local speed_new = speed_step_prev +	local speed_next_diff = math.abs(speed_drag_current - speed_step_next) +	local speed_prev_diff = math.abs(speed_drag_current - speed_step_prev) +	if speed_next_diff < speed_prev_diff then +		speed_new = speed_step_next +	end + +	if speed_new ~= speed_current then +		mp.set_property_native('speed', speed_new) +	end +end + +function Speed:on_mbtn_left_up() +	-- Reset speed on short clicks +	if self.dragging and math.abs(self.dragging.distance) < 6 and mp.get_time() - self.dragging.start_time < 0.15 then +		mp.set_property_native('speed', 1) +	end +end + +function Speed:on_global_mbtn_left_up() +	self.dragging = nil +	request_render() +end + +function Speed:on_global_mouse_leave() +	self.dragging = nil +	request_render() +end + +function Speed:on_wheel_up() mp.set_property_native('speed', self:speed_step(state.speed, true)) end +function Speed:on_wheel_down() mp.set_property_native('speed', self:speed_step(state.speed, false)) end + +function Speed:render() +	local visibility = self:get_visibility() +	local opacity = self.dragging and 1 or visibility + +	if opacity <= 0 then return end + +	local ass = assdraw.ass_new() + +	-- Background +	ass:rect(self.ax, self.ay, self.bx, self.by, {color = bg, radius = 2, opacity = opacity * options.speed_opacity}) + +	-- Coordinates +	local ax, ay = self.ax, self.ay +	local bx, by = self.bx, ay + self.height +	local half_width = (self.width / 2) +	local half_x = ax + half_width + +	-- Notches +	local speed_at_center = state.speed +	if self.dragging then +		speed_at_center = self.dragging.start_speed + self.dragging.speed_distance +		speed_at_center = clamp(0.01, speed_at_center, 100) +	end +	local nearest_notch_speed = round(speed_at_center / self.notch_every) * self.notch_every +	local nearest_notch_x = half_x + (((nearest_notch_speed - speed_at_center) / self.notch_every) * self.notch_spacing) +	local guide_size = math.floor(self.height / 7.5) +	local notch_by = by - guide_size +	local notch_ay_big = ay + round(self.font_size * 1.1) +	local notch_ay_medium = notch_ay_big + ((notch_by - notch_ay_big) * 0.2) +	local notch_ay_small = notch_ay_big + ((notch_by - notch_ay_big) * 0.4) +	local from_to_index = math.floor(self.notches / 2) + +	for i = -from_to_index, from_to_index do +		local notch_speed = nearest_notch_speed + (i * self.notch_every) + +		if notch_speed >= 0 and notch_speed <= 100 then +			local notch_x = nearest_notch_x + (i * self.notch_spacing) +			local notch_thickness = 1 +			local notch_ay = notch_ay_small +			if (notch_speed % (self.notch_every * 10)) < 0.00000001 then +				notch_ay = notch_ay_big +				notch_thickness = 1.5 +			elseif (notch_speed % (self.notch_every * 5)) < 0.00000001 then +				notch_ay = notch_ay_medium +			end + +			ass:rect(notch_x - notch_thickness, notch_ay, notch_x + notch_thickness, notch_by, { +				color = fg, border = 1, border_color = bg, +				opacity = math.min(1.2 - (math.abs((notch_x - ax - half_width) / half_width)), 1) * opacity, +			}) +		end +	end + +	-- Center guide +	ass:new_event() +	ass:append('{\\rDefault\\an7\\blur0\\bord1\\shad0\\1c&H' .. fg .. '\\3c&H' .. bg .. '}') +	ass:opacity(opacity) +	ass:pos(0, 0) +	ass:draw_start() +	ass:move_to(half_x, by - 2 - guide_size) +	ass:line_to(half_x + guide_size, by - 2) +	ass:line_to(half_x - guide_size, by - 2) +	ass:draw_stop() + +	-- Speed value +	local speed_text = (round(state.speed * 100) / 100) .. 'x' +	ass:txt(half_x, ay + (notch_ay_big - ay) / 2, 5, speed_text, { +		size = self.font_size, color = bgt, border = options.text_border, border_color = bg, opacity = opacity, +	}) + +	return ass +end + +return Speed | 
