aboutsummaryrefslogtreecommitdiff
path: root/README.md
diff options
context:
space:
mode:
authorhistoria <historiavg@proton.me>2026-09-06 13:35:35 -0400
committerhistoria <historiavg@proton.me>2026-09-06 13:35:35 -0400
commit40f108547126a3402d2285fe7e3353f0afddb24d (patch)
tree399662d854cba73d49d4ae2cd065603d8e661764 /README.md
downloadvrising-camera-40f108547126a3402d2285fe7e3353f0afddb24d.tar.gz
initial commit
Diffstat (limited to 'README.md')
-rw-r--r--README.md95
1 files changed, 95 insertions, 0 deletions
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..0094eb1
--- /dev/null
+++ b/README.md
@@ -0,0 +1,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)