aboutsummaryrefslogtreecommitdiff
path: root/README.md
diff options
context:
space:
mode:
authorhistoria <historiavg@proton.me>2026-09-06 14:08:42 -0400
committerhistoria <historiavg@proton.me>2026-09-06 14:08:42 -0400
commit7b1f08ef608adc0650bf90565304580318a2cd01 (patch)
tree2370db6478a7ebbfe54066971ce1c8c2887bba25 /README.md
parent40f108547126a3402d2285fe7e3353f0afddb24d (diff)
downloadvrising-camera-7b1f08ef608adc0650bf90565304580318a2cd01.tar.gz
0bsd license
Diffstat (limited to 'README.md')
-rw-r--r--README.md101
1 files changed, 28 insertions, 73 deletions
diff --git a/README.md b/README.md
index 0094eb1..3f16465 100644
--- a/README.md
+++ b/README.md
@@ -1,95 +1,50 @@
-# vrising-cam
+# vrising-camera
-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`).
+This Python script rotates the camera in V-Rising using the Q and E keys on Linux because the game doesn't support bindings that rotate the camera. It uses `uinput` to emulate a right click and drag.
## Usage
+Your user must be part of the input group.
+
```
-./vrising-cam.py # hold Q = rotate left, hold E = rotate right
+sudo usermod -aG input $USER
```
-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.
+Log out/in, then run the script.
+
+```
+./vrising-cam.py
+```
### 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 |
+| 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.
+| `--check` | show detected keyboards, uinput and grab status, then exit |
-### 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:
+1. Your user needs to read the keyboard event devices and, on Arch, that same
+ group membership also grants write access to `/dev/uinput`:
```
- sudo modprobe uinput
- echo uinput | sudo tee /etc/modules-load.d/uinput.conf
+ sudo usermod -aG input $USER # log out and back in afterwards
```
+ (Arch autoloads the `uinput` module on first open; no udev rules needed.)
+2. The script auto-creates `.venv` and installs `evdev` on first run — no
+ extra steps.
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)
+Troubleshooting when something does fail — the script prints a targeted hint:
+`/dev/uinput` unwritable (rare on Arch; sudo or a udev rule fixes it), module
+missing (`modprobe uinput` then add it to `/etc/modules-load.d/`), or
+keyboards unreadable (the `input` group again).