--- Require

local mp = require("mp")

--- Constants

local SHADER_META = [[
//!HOOK MAINPRESUB
//!DESC GPU rotate
//!BIND HOOKED
]]

local SHADER_DEFINE = "#define angle"

local SHADER_HOOK = [[
vec4 hook()
{
    float rad = radians(angle);
    float c   = cos(rad);
    float s   = sin(rad);
    mat2  rot = mat2(c, -s, s, c);
    vec2  pos = rot * ((HOOKED_pos - 0.5) * HOOKED_size) * HOOKED_pt + 0.5;
    if (!all(equal(pos, clamp(pos, 0.0, 1.0))))
        return vec4(0.0);
    return HOOKED_tex(pos);
}
]]

--- State

local state = {
    angle  = 0.0,
    shader = nil,
}

--- Functions

local function shader_define()
    return table.concat({SHADER_DEFINE, state.angle}, " ")
end

local function remove()
    if state.shader then
        mp.msg.debug("Removing", state.shader)
        mp.commandv("change-list", "glsl-shaders", "remove", state.shader)
        os.remove(state.shader)
        state.shader = nil
    end
end

local function append(angle)
    state.angle = angle % 360
    remove()
    state.shader = os.tmpname()
    mp.msg.debug("Writing", state.shader)
    local file = io.open(state.shader, "w")
    file:write(table.concat({
        SHADER_META,
        shader_define(),
        SHADER_HOOK,
    }, "\n"))
    file:close()
    mp.commandv("change-list", "glsl-shaders", "append", state.shader)
end

--- Events

mp.register_event("shutdown", remove)

--- Script messages

local function set(angle) append(angle)               end
local function add(angle) append(angle + state.angle) end
mp.register_script_message("set", set)
mp.register_script_message("add", add)
