From 7b1f08ef608adc0650bf90565304580318a2cd01 Mon Sep 17 00:00:00 2001 From: historia Date: Sun, 6 Sep 2026 14:08:42 -0400 Subject: 0bsd license --- LICENSE | 13 ++++++++ README.md | 101 ++++++++++++++++----------------------------------------- vrising-cam.py | 13 +++++--- 3 files changed, 49 insertions(+), 78 deletions(-) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..d3061a3 --- /dev/null +++ b/LICENSE @@ -0,0 +1,13 @@ +Zero-Clause BSD +============= + +Permission to use, copy, modify, and/or distribute this software for +any purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE +FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY +DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN +AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 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). diff --git a/vrising-cam.py b/vrising-cam.py index c2a6666..feae2be 100755 --- a/vrising-cam.py +++ b/vrising-cam.py @@ -43,13 +43,16 @@ kernel input headers (linux/input.h): """ UINPUT_HINT = """\ -uinput access is missing. Fix one of two ways: +uinput access is missing (/dev/uinput could not be opened for writing). +Fix one of two ways: a) quick: rerun with sudo: sudo {script} - b) one-time setup to run as your normal user (recommended): - echo 'KERNEL=="uinput", MODE="0660", GROUP="input", TAG+="uaccess"' | sudo tee /etc/udev/rules.d/70-vrising-cam.rules + b) grant your user write access to /dev/uinput: membership in the + "input" group is enough on most distros (Arch included); if your + distro ships /dev/uinput root-only (e.g. Debian/Ubuntu), add a udev + rule for it, e.g.: + echo 'KERNEL=="uinput", MODE="0660", GROUP="input"' | 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 so the input group applies) + (then log out and back in if the group membership is new) """ DEV_PERM_HINT = """\ -- cgit v1.2.3