aboutsummaryrefslogtreecommitdiff
path: root/README.md
blob: 0094eb135a569aafa23cdb50d8755dc01fb775fa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# vrising-cam

Hold **Q / E** to rotate the camera in V Rising on Linux, by emulating the
game's "Rotate camera" gesture: holding the right mouse button while streaming
relative mouse motion. The emulation happens at the kernel level (uinput), so
it works the same on X11 and Wayland — verified on KDE Plasma Wayland with the
game running through plain Steam/Proton.

Single-file, no services: the first run creates a `.venv` next to the script,
installs `evdev`, and re-executes itself inside it. The script only acts while
its process is running; `Ctrl+C` to stop, and the emulated right mouse button
is always released on exit (including on SIGTERM and crashes, via `atexit`).

## Usage

```
./vrising-cam.py                 # hold Q = rotate left, hold E = rotate right
```

While running, the process watches your keyboard's `/dev/input/event*` nodes
for Q / E, presses the emulated right mouse button for as long as either key
is held, and emits relative X motion at a continuous rate.

### Options

| Flag | Meaning |
| --- | --- |
| `--speed N` | rotation speed in relative X units per second (default `2000`) |
| `--tick-ms N` | milliseconds between motion ticks (default `1.0`; lower = smoother, higher = lighter) |
| `--ease SECONDS` | ramp speed up over `SECONDS` on press and decay on release (`0` = off; try `0.15`) |
| `--invert` | swap the rotation direction of Q and E |
| `-v`, `--verbose` | log key presses/releases, RMB injection, measured motion rate |
| `--test-rmb [SECONDS]` | self-test: hold the injected RMB for `SECONDS` (default 3) and read events back from the kernel; no keyboard needed |
| `--check` | show detected keyboards, uinput and grab status, then exit |

### Tuning the feel

- **Smoothness** comes from the fractional accumulator: ticks deliver 0–1 unit
  each at a fine cadence, so motion is progress-continuous instead of pulsing.
  The default 1 ms tick keeps bursts at 0–1 unit practically throughout; bulge
  the interval (e.g. `--tick-ms 50`) for a lighter pipeline if you ever need to.
- **Speed**: `--speed 1000` is a slow orbit; `3000+` is a fast spin. Because
  motion is rate-continuous, `--speed` directly maps to how fast the camera
  rotates.
- **Ease**: `--ease 0.15` gives short smoothstep accel after pressing and a
  linear decay on key release (the emulated RMB stays held during the decay,
  then releases). `--ease 0` (default) is instant — some people prefer that.
  The previous caveat applies while tap-spinning: easing shapes hold-and-drag
  feel, not button clicks.
- Q held together with E cancels out (no motion) but keeps the RMB hold.

### CPU cost

Idle the loop wakes 4×/s via `select`. While rotating, it wakes once per tick
(1000/s at the default 1 ms) plus one kernel write per emitted event — well
under 1% of one core on any modern machine.

## Setup on Arch (KDE Wayland / X11 alike)

1. Make `/dev/uinput` writable:

   ```
   echo 'KERNEL=="uinput", MODE="0660", GROUP="input", TAG+="uaccess"' | sudo tee /etc/udev/rules.d/70-vrising-cam.rules
   sudo udevadm control --reload-rules && sudo udevadm trigger
   sudo usermod -aG input $USER   # log out and back in
   ```
2. Ensure the `uinput` module loads at boot:

   ```
   sudo modprobe uinput
   echo uinput | sudo tee /etc/modules-load.d/uinput.conf
   ```
3. Run `./vrising-cam.py --check` — it should print `READY`:
   `/dev/uinput` openable, your keyboards listed exposing Q+E, and no
   "exclusively grabbed" warnings.

## Troubleshooting

- **No camera rotation at all** → run with `-v`: hold Q and watch for
  `key: Q press` lines. No lines while rotating means some other process
  exclusively grabbed your keyboard (`EVIOCGRAB`; remappers like
  keyd/kanata/kmonad do this) — the script warns about that with `--check`
  and `-v`.
- **Keys detected but desktop/game shows nothing** → run the self-test
  `./vrising-cam.py --test-rmb`: if `kernel read-back: OK` still shows no
  reaction on the desktop, get `sudo libinput debug-events`
  (`sudo pacman -S libinput-tools` on current Arch) and watch for
  `BTN_RIGHT` lines while the test runs.
- **Stop quickly** → `Ctrl+C` (or `kill`, also emulated) — the emulated RMB
  is released in the `finally`/`atexit` path.

## Files

- `vrising-cam.py` — the whole program (single file by design)
- `.venv/` — auto-created next to the script on first run (git-ignored)