--[[
rebind: min_sdk=3.11.0
rebind: name=Keyboard and Mouse to Joypad
rebind: version=1.0.0
rebind: hardware_only=true
rebind: mouse_block=true
rebind: permissions=none
]]
local GAIN = 0.35 -- right stick deflection per mouse count per ms
local SMOOTH = 0.55 -- share of the last stick value kept each tick
local IDLE_MS = 250 -- hand the axes back to a real controller after this
rb.bind.remap("Space", "PadA")
rb.bind.remap("F", "PadB")
rb.bind.remap("R", "PadX")
rb.bind.remap("T", "PadY")
rb.bind.remap("Q", "PadLB")
rb.bind.remap("E", "PadRB")
local captured = true
local held = {}
local trigger = { LT = 0, RT = 0 }
local acc_x, acc_y, stick_x, stick_y = 0, 0, 0, 0
local idle_ms, driving = 0, false
local function clamp(v)
return math.max(-1, math.min(1, v))
end
local function button_held()
for _, key in ipairs({ "Space", "F", "R", "T", "Q", "E" }) do
if rb.input.is_down(key) then
return true
end
end
return false
end
rb.on("move", function(dx, dy)
if not captured then
return true
end
acc_x += dx
acc_y += dy
return false
end)
rb.on("tick", function(dt_ms)
if dt_ms <= 0 then
return
end
stick_x = stick_x * SMOOTH + clamp(acc_x / dt_ms * GAIN) * (1 - SMOOTH)
stick_y = stick_y * SMOOTH + clamp(acc_y / dt_ms * GAIN) * (1 - SMOOTH)
acc_x, acc_y = 0, 0
if math.abs(stick_x) < 0.02 then
stick_x = 0
end
if math.abs(stick_y) < 0.02 then
stick_y = 0
end
local lx = (held.D and 1 or 0) - (held.A and 1 or 0)
local ly = (held.S and 1 or 0) - (held.W and 1 or 0)
if lx ~= 0 and ly ~= 0 then
lx, ly = lx * 0.7071, ly * 0.7071
end
local active = stick_x ~= 0 or stick_y ~= 0 or lx ~= 0 or ly ~= 0
or trigger.LT > 0 or trigger.RT > 0
idle_ms = if active then 0 else idle_ms + dt_ms
if idle_ms >= IDLE_MS then
-- an axis a script sets stays set, so give the axes back to the
-- controller. joypad_reset also releases the script's buttons, so
-- wait while a button key is held.
if driving and not button_held() then
rb.hid.joypad_reset()
driving = false
end
return
end
driving = true
rb.hid.axis("RightX", stick_x)
rb.hid.axis("RightY", stick_y)
rb.hid.axis("LeftX", lx)
rb.hid.axis("LeftY", ly)
rb.hid.axis("LT", trigger.LT)
rb.hid.axis("RT", trigger.RT)
end)
for _, key in ipairs({ "W", "A", "S", "D" }) do
rb.bind(key, function()
held[key] = true
end, {
release = function()
held[key] = nil
end,
})
end
-- while the mouse is released, `when` lets clicks through as normal clicks
local function click(button, axis)
rb.bind(button, function()
trigger[axis] = 1
end, {
when = function()
return captured
end,
release = function()
trigger[axis] = 0
end,
})
end
click("Mouse1", "RT")
click("Mouse2", "LT")
rb.bind("F9", function()
captured = not captured
stick_x, stick_y, acc_x, acc_y = 0, 0, 0, 0
trigger.LT, trigger.RT = 0, 0
rb.ui.notify(if captured then "Mouse drives the right stick" else "Mouse released")
end)
rb.bind("F10", function()
rb.script.exit("F10 pressed")
end)