Added First-person "Hide Driver" and "Hide Driver and Kart" & Improved Default FPV Settings

This commit is contained in:
iChris4 committed 2026-09-08 15:43:52 +02:00
1 parent 2742b8d9a2
commit 6440c5bc10
7 files changed
+394 -46

No files matched your search

+69 -16
View File
@@ -60,6 +60,8 @@ struct RuntimeUserConfig {
std::optional<float> vrFirstPersonHeadUpMeters;
std::optional<float> vrFirstPersonHeadForwardMeters;
std::optional<float> vrFirstPersonHeadRightMeters;
std::optional<bool> vrFirstPersonHideDriver;
std::optional<int32_t> vrFirstPersonHiddenModel;
std::optional<float> audioVolume;
std::optional<float> audioMusicVolume;
std::optional<float> audioSoundEffectsVolume;
@@ -134,6 +136,17 @@ inline constexpr const char* kPortableUserDataDirectoryName = "UserData";
// installation.
inline constexpr int kPortableSearchDepth = 4;
// First-person camera defaults and the range its head offsets accept, in one
// place: the config getters, the on-disk template and the F10 bar's reset all
// read them from here, so they cannot drift apart again.
inline constexpr float kVrFirstPersonUnitsPerMeterDefault = 30.0f;
inline constexpr float kVrFirstPersonHeadUpDefault = 3.0f;
inline constexpr float kVrFirstPersonHeadForwardDefault = 0.0f;
inline constexpr float kVrFirstPersonHeadRightDefault = 0.0f;
inline constexpr bool kVrFirstPersonHideDriverDefault = true;
inline constexpr int32_t kVrFirstPersonHiddenModelDefault = 0;
inline constexpr float kVrFirstPersonHeadOffsetLimit = 10.0f;
inline std::string Trim(std::string_view text) {
size_t begin = 0;
while (begin < text.size() && std::isspace(static_cast<unsigned char>(text[begin]))) {
@@ -351,11 +364,18 @@ inline void EnsureConfigFile() {
"# below replaces world_units_per_meter while it is engaged: 10 is\n"
"# life-size, where the 500 above makes the race a small diorama.\n"
"first_person = false\n"
"first_person_units_per_meter = 10.0\n"
"first_person_units_per_meter = 30.0\n"
"# Where the head sits in the kart's own frame, in metres.\n"
"first_person_head_up_meters = 1.0\n"
"first_person_head_up_meters = 3.0\n"
"first_person_head_forward_meters = 12.0\n"
"first_person_head_right_meters = 0.0\n\n"
"first_person_head_right_meters = 0.0\n"
"# In first person the driver sits where your eyes are. Hiding\n"
"# the driver removes the head that would otherwise be in the\n"
"# way; hiding the kart removes the vehicle around you too.\n"
"first_person_hide_driver = true\n"
"# 0 is the driver, which is the usual choice. -1 hides every\n"
"# model of your kart, the vehicle included.\n"
"first_person_hidden_model = 0\n\n"
"[audio]\n"
"volume = 1.0\n"
"music_volume = 1.0\n"
@@ -522,17 +542,26 @@ inline RuntimeUserConfig ParseConfigDocument(const toml::value& document) {
config.vrFirstPersonUnitsPerMeter = *value;
}
if (auto value = FindConfigFloat(document, "vr", "first_person_head_up_meters");
value && *value >= -3.0f && *value <= 3.0f) {
value && *value >= -kVrFirstPersonHeadOffsetLimit &&
*value <= kVrFirstPersonHeadOffsetLimit) {
config.vrFirstPersonHeadUpMeters = *value;
}
if (auto value = FindConfigFloat(document, "vr", "first_person_head_forward_meters");
value && *value >= -3.0f && *value <= 3.0f) {
value && *value >= -kVrFirstPersonHeadOffsetLimit &&
*value <= kVrFirstPersonHeadOffsetLimit) {
config.vrFirstPersonHeadForwardMeters = *value;
}
if (auto value = FindConfigFloat(document, "vr", "first_person_head_right_meters");
value && *value >= -3.0f && *value <= 3.0f) {
value && *value >= -kVrFirstPersonHeadOffsetLimit &&
*value <= kVrFirstPersonHeadOffsetLimit) {
config.vrFirstPersonHeadRightMeters = *value;
}
config.vrFirstPersonHideDriver =
FindConfigValue<bool>(document, "vr", "first_person_hide_driver");
if (auto value = FindConfigInt(document, "vr", "first_person_hidden_model");
value && *value >= -1 && *value <= 31) {
config.vrFirstPersonHiddenModel = static_cast<int32_t>(*value);
}
auto readVolume = [&](std::string_view key) -> std::optional<float> {
auto value = FindConfigFloat(document, "audio", key);
@@ -789,7 +818,7 @@ inline bool SetVrFirstPersonUnitsPerMeter(float value) {
}
inline bool SetVrFirstPersonHeadUpMeters(float value) {
value = std::clamp(value, -3.0f, 3.0f);
value = std::clamp(value, -kVrFirstPersonHeadOffsetLimit, kVrFirstPersonHeadOffsetLimit);
Mutable().vrFirstPersonHeadUpMeters = value;
std::ostringstream formatted;
formatted << value;
@@ -797,15 +826,28 @@ inline bool SetVrFirstPersonHeadUpMeters(float value) {
}
inline bool SetVrFirstPersonHeadForwardMeters(float value) {
value = std::clamp(value, -3.0f, 3.0f);
value = std::clamp(value, -kVrFirstPersonHeadOffsetLimit, kVrFirstPersonHeadOffsetLimit);
Mutable().vrFirstPersonHeadForwardMeters = value;
std::ostringstream formatted;
formatted << value;
return WriteSetting("vr", "first_person_head_forward_meters", formatted.str());
}
inline bool SetVrFirstPersonHideDriver(bool value) {
Mutable().vrFirstPersonHideDriver = value;
return WriteSetting("vr", "first_person_hide_driver", value ? "true" : "false");
}
inline bool SetVrFirstPersonHiddenModel(int32_t value) {
value = std::clamp(value, -1, 31);
Mutable().vrFirstPersonHiddenModel = value;
std::ostringstream formatted;
formatted << value;
return WriteSetting("vr", "first_person_hidden_model", formatted.str());
}
inline bool SetVrFirstPersonHeadRightMeters(float value) {
value = std::clamp(value, -3.0f, 3.0f);
value = std::clamp(value, -kVrFirstPersonHeadOffsetLimit, kVrFirstPersonHeadOffsetLimit);
Mutable().vrFirstPersonHeadRightMeters = value;
std::ostringstream formatted;
formatted << value;
@@ -1064,20 +1106,31 @@ inline bool VrFirstPerson(bool fallback = false) {
return Get().vrFirstPerson.value_or(fallback);
}
inline float VrFirstPersonUnitsPerMeter(float fallback = 10.0f) {
inline float VrFirstPersonUnitsPerMeter(float fallback = kVrFirstPersonUnitsPerMeterDefault) {
return std::clamp(Get().vrFirstPersonUnitsPerMeter.value_or(fallback), 1.0f, 10000.0f);
}
inline float VrFirstPersonHeadUpMeters(float fallback = 1.0f) {
return std::clamp(Get().vrFirstPersonHeadUpMeters.value_or(fallback), -3.0f, 3.0f);
inline float VrFirstPersonHeadUpMeters(float fallback = kVrFirstPersonHeadUpDefault) {
return std::clamp(Get().vrFirstPersonHeadUpMeters.value_or(fallback),
-kVrFirstPersonHeadOffsetLimit, kVrFirstPersonHeadOffsetLimit);
}
inline float VrFirstPersonHeadForwardMeters(float fallback = 0.0f) {
return std::clamp(Get().vrFirstPersonHeadForwardMeters.value_or(fallback), -20.0f, 20.0f);
inline float VrFirstPersonHeadForwardMeters(float fallback = kVrFirstPersonHeadForwardDefault) {
return std::clamp(Get().vrFirstPersonHeadForwardMeters.value_or(fallback),
-kVrFirstPersonHeadOffsetLimit, kVrFirstPersonHeadOffsetLimit);
}
inline float VrFirstPersonHeadRightMeters(float fallback = 0.0f) {
return std::clamp(Get().vrFirstPersonHeadRightMeters.value_or(fallback), -3.0f, 3.0f);
inline float VrFirstPersonHeadRightMeters(float fallback = kVrFirstPersonHeadRightDefault) {
return std::clamp(Get().vrFirstPersonHeadRightMeters.value_or(fallback),
-kVrFirstPersonHeadOffsetLimit, kVrFirstPersonHeadOffsetLimit);
}
inline bool VrFirstPersonHideDriver(bool fallback = kVrFirstPersonHideDriverDefault) {
return Get().vrFirstPersonHideDriver.value_or(fallback);
}
inline int32_t VrFirstPersonHiddenModel(int32_t fallback = kVrFirstPersonHiddenModelDefault) {
return std::clamp(Get().vrFirstPersonHiddenModel.value_or(fallback), -1, 31);
}
inline std::string GraphicsApi(std::string fallback = "auto") {
+5 -1
View File
@@ -23,7 +23,7 @@ inline constexpr Mtx34 kIdentityMtx34{
// frame is the EGG convention: +x right, +y up, +z forward.
struct FirstPersonHeadOffsets {
float right = 0.0f;
float up = 1.0f;
float up = 3.0f;
float forward = 0.0f;
};
@@ -183,6 +183,10 @@ inline bool ComputeFirstPersonAnchor(const Mtx34& view_from_world, const Mtx34&
void MkwVRFirstPersonConfigure(bool enabled, const FirstPersonHeadOffsets& offsets,
float units_per_meter) noexcept;
// While the anchor is driving the view the player's own models can be removed,
// since the driver otherwise sits exactly where the eyes are. This uses the
// game's own visibility fields, and puts them back when it stops.
//
// Reads the current [vr] first-person settings and applies them here and to the
// presentation policy's world scale. The single place those settings are
// interpreted, shared by startup and the F10 settings bar.
+5 -5
View File
@@ -78,11 +78,11 @@ struct MkwVRPolicyConfig {
// immersive race HUD so 2D content keeps its place across the transition.
float hud_width_meters = 2.4f;
float hud_scale = 1.0f;
// World scale used while the first-person camera is engaged. Mario Kart
// Wii is authored at roughly this many units per metre, so it is what
// makes the race read life-size; the third-person default deliberately
// does not, presenting the race as a small diorama instead.
float first_person_units_per_meter = 10.0f;
// World scale used while the first-person camera is engaged. This is what
// makes the race read life-size from the driver's seat; the third-person
// default deliberately does not, presenting it as a small diorama instead.
// Kept in step with RuntimeConfigFile's default, which the F10 bar resets to.
float first_person_units_per_meter = 30.0f;
};
struct MkwVRSceneObservation {