Steady Hand

@rebind / steady-handv0.1.2Public

Filters small involuntary movements and smooths the rest, so the pointer follows your intent. Requires Rebind Link.

Files

Older release. Installs get 0.1.2.

main.luau1.5 KB

-- Steady Hand: hold movement back until it adds up to a real move, then let
-- it out smoothly. Tremor that goes back and forth cancels before it ever
-- reaches the pointer; slow, deliberate movement adds up and gets through.

local cfg = UI.Schema({
  smoothing = UI.Slider(50, {
    min = 0,
    max = 90,
    suffix = "%",
    label = "Smoothing",
    tooltip = "Higher is steadier, with a little more lag",
  }),
  threshold = UI.Slider(5, {
    min = 1,
    max = 20,
    suffix = " counts",
    label = "Ignore movement smaller than",
  }),
})

-- movement received but not yet sent, and whether it is flowing out
local px, py = 0, 0
local flowing = false

local function reset()
  px, py, flowing = 0, 0, false
end

-- the share of the pending movement sent this tick, at least one count
local function step(pending, share)
  if pending == 0 then
    return 0
  end
  local out = math.round(pending * share)
  if out == 0 then
    out = if pending > 0 then 1 else -1
  end
  return out
end

function OnMove(dx, dy)
  px += dx
  py += dy
  return false
end

function OnTick()
  if not flowing then
    if math.sqrt(px * px + py * py) < cfg.threshold then
      return
    end
    flowing = true
  end
  local share = 1 - cfg.smoothing / 100
  local ox, oy = step(px, share), step(py, share)
  px -= ox
  py -= oy
  if ox ~= 0 or oy ~= 0 then
    HID.Move(ox, oy)
  end
  if px == 0 and py == 0 then
    flowing = false
  end
end

function OnStop()
  reset()
end

function OnBlur()
  reset()
end

3 files, 3.2 KB.