Files
iChris4andClaude Opus 5 dd7f046214 Toggle the first-person camera with a right thumbstick click
Clicking the right thumbstick flips first person exactly as the F10
checkbox does, and saves it the same way. It works on the VR controllers
in either presentation (with a short tick on the right controller) and on
any other gamepad while VR is running. It never reached the game: SDL's
stick click only lands in Aurora's extended buttons.

A click counts on release, and only if the left thumbstick stayed up and
the headset settings panel stayed closed throughout, so the two-thumbstick
panel chord in gamepad mode never toggles the camera. A gamepad whose
right stick click is bound to a GameCube control on its port, as a button
or in an input expression, keeps it for the game. The XR side only posts
a request; the toggle itself runs on the game thread with the checkbox.

[vr] first_person_toggle_click (default true) and a checkbox under the
camera toggle turn the click off. mkw_vr_camera_toggle_tests covers the
click rule.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 15:03:17 +02:00

45 lines
1.3 KiB
C++

// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
// The right thumbstick click that toggles the first-person camera, on the VR
// controllers and on any gamepad while VR runs (F10 > VR >
// first_person_toggle_click). Kept free of OpenXR and SDL so it is tested
// headlessly (tests/vr_camera_toggle_tests.cpp).
namespace mkw::vr {
// One clean click of a button: it fires on release, and only if its partner
// (the other thumbstick, which with it opens the headset settings panel on a
// gamepad) stayed up and nothing owned the controllers at any point during the
// press. Firing on release is what lets a two-stick chord pass untouched.
class ClickToggle {
public:
bool Update(bool held, bool partner_held, bool blocked) noexcept {
if (held) {
if (!held_) {
held_ = true;
spoiled_ = partner_held || blocked;
} else if (partner_held || blocked) {
spoiled_ = true;
}
return false;
}
const bool fire = held_ && !spoiled_ && !blocked;
held_ = false;
spoiled_ = false;
return fire;
}
void Reset() noexcept {
held_ = false;
spoiled_ = false;
}
bool Held() const noexcept { return held_; }
private:
bool held_ = false;
bool spoiled_ = false;
};
} // namespace mkw::vr