mirror of
https://github.com/mitch030504/Wiicompiled_VR_Frame.git
synced 2026-10-06 02:00:14 +02:00
Add Flat Screen mode for VR races and update settings accordingly
This commit is contained in:
1 parent
2a89fac79d
commit
2a4686191e
16 files changed
+161
-50
No files matched your search
@@ -45,6 +45,7 @@ world_units_per_meter = 500.0
|
|||||||
hud_distance_meters = 2.0
|
hud_distance_meters = 2.0
|
||||||
hud_width_meters = 2.4
|
hud_width_meters = 2.4
|
||||||
hud_virtual_screen = true
|
hud_virtual_screen = true
|
||||||
|
flat_screen = false
|
||||||
stop_at_display_copy = true
|
stop_at_display_copy = true
|
||||||
skip_copy_clears = true
|
skip_copy_clears = true
|
||||||
first_person = false
|
first_person = false
|
||||||
@@ -139,10 +140,19 @@ and 0.8 on the Quest, whose mobile GPU needs the headroom.
|
|||||||
launch and govern both the menu screen and the in-race 2D screen, so 2D content keeps its place
|
launch and govern both the menu screen and the in-race 2D screen, so 2D content keeps its place
|
||||||
across the transition. `hud_virtual_screen` decides whether the race's 2D layer uses that screen;
|
across the transition. `hud_virtual_screen` decides whether the race's 2D layer uses that screen;
|
||||||
it is live and can be flipped from the F10 settings bar.
|
it is live and can be flipped from the F10 settings bar.
|
||||||
|
`flat_screen` (default off) keeps races on that same flat screen, as the menus are, instead of
|
||||||
|
immersive stereo: the whole race, 3D world and HUD alike, is the game's own picture on the quad, as
|
||||||
|
in DolphinXR's Flat Screen mode. The first-person camera, hand steering, the lean-back angle, VR
|
||||||
|
frame interpolation and `hud_virtual_screen` shape only the immersive race view, so none of them
|
||||||
|
apply while it is on; the right-thumbstick first-person toggle is ignored rather than changing the saved
|
||||||
|
setting. It is live, as **F10 → VR → Flat Screen mode** (the headset panel's VR tab) and the Quest
|
||||||
|
launcher's Settings page, and turning it on or off mid-race switches on the next frame through the
|
||||||
|
presentation policy's safety generation.
|
||||||
`passthrough` (Quest only, default on) shows the room through the headset's cameras around the
|
`passthrough` (Quest only, default on) shows the room through the headset's cameras around the
|
||||||
menu screen and every other virtual screen, instead of black: an `XR_FB_passthrough`
|
menu screen and every other virtual screen, instead of black: an `XR_FB_passthrough`
|
||||||
reconstruction layer submitted under the screen's quad, as PPSSPP VR does, with the blend mode
|
reconstruction layer submitted under the screen's quad, as PPSSPP VR does, with the blend mode
|
||||||
left `OPAQUE`. An immersive race never shows it, and the cameras are paused for the race. It is
|
left `OPAQUE`. An immersive race never shows it, and the cameras are paused for the race; a race in
|
||||||
|
`flat_screen` is a virtual screen like the menus, so the room shows around it too. It is
|
||||||
live, from the headset panel's VR tab or the launcher's Settings page. The app declares
|
live, from the headset panel's VR tab or the launcher's Settings page. The app declares
|
||||||
`com.oculus.feature.PASSTHROUGH`, without which Horizon OS composites nothing for that layer.
|
`com.oculus.feature.PASSTHROUGH`, without which Horizon OS composites nothing for that layer.
|
||||||
So that the room frames the picture rather than black bands, the Quest's menu quad shows only the
|
So that the room frames the picture rather than black bands, the Quest's menu quad shows only the
|
||||||
@@ -187,19 +197,21 @@ Touch controllers. The port is served through KPAD like a Bluetooth remote
|
|||||||
| --- | --- |
|
| --- | --- |
|
||||||
| Right A | A |
|
| Right A | A |
|
||||||
| Right trigger | B |
|
| Right trigger | B |
|
||||||
|
| Right B | C (look behind) |
|
||||||
| Right stick up / down | 1 / 2 |
|
| Right stick up / down | 1 / 2 |
|
||||||
| Left X | − |
|
| Left X | − |
|
||||||
| Left menu | + |
|
| Left menu | + |
|
||||||
| Left stick | Nunchuk stick |
|
| Left stick | Nunchuk stick |
|
||||||
| Left trigger | Z |
|
| Left trigger | Z |
|
||||||
| Left grip | C |
|
|
||||||
| Left Y | Settings panel (not a Wii button) |
|
| Left Y | Settings panel (not a Wii button) |
|
||||||
|
| Either grip | Takes hold of the wheel (not a Wii button) |
|
||||||
| Right stick click | First-person camera on / off (not a Wii button) |
|
| Right stick click | First-person camera on / off (not a Wii button) |
|
||||||
| Right controller motion and aim | Wii Remote accelerometer and pointer |
|
| Right controller motion and aim | Wii Remote accelerometer and pointer |
|
||||||
| Left controller motion | Nunchuk accelerometer |
|
| Left controller motion | Nunchuk accelerometer |
|
||||||
|
|
||||||
Analog inputs count as pressed past half travel. Right B, right stick left / right and the left
|
Analog inputs count as pressed past half travel. The grips, right stick left / right and the left
|
||||||
stick click are unbound, and no controller button presses HOME. The game's Wii Remote rumble vibrates
|
stick click press no Wii button, and nothing presses HOME. C sits on right B rather than a grip
|
||||||
|
because hand steering holds a grip down for a whole corner, and C is the game's look-behind. The game's Wii Remote rumble vibrates
|
||||||
both controllers, subject to the ordinary controller-vibration switch.
|
both controllers, subject to the ordinary controller-vibration switch.
|
||||||
|
|
||||||
**Motion.** Each XR frame the aim and grip poses are located at the measured current time
|
**Motion.** Each XR frame the aim and grip poses are located at the measured current time
|
||||||
@@ -234,8 +246,8 @@ Raw IR camera dots in `KPADGetUnifiedWpadStatus` stay invalid; the game reads th
|
|||||||
controllers operate the panel and the game sees them idle.
|
controllers operate the panel and the game sees them idle.
|
||||||
|
|
||||||
**Hand steering.** With `hand_steering` on, in the first-person cockpit, a grip squeezed near the
|
**Hand steering.** With `hand_steering` on, in the first-person cockpit, a grip squeezed near the
|
||||||
steering wheel takes hold of it, and while held the wheel steers through the Nunchuk stick's X axis
|
steering wheel takes hold of it, and while held the wheel steers through the Nunchuk stick's X axis;
|
||||||
and that grip stops pressing C; see [Steering wheel and hand
|
see [Steering wheel and hand
|
||||||
steering](#steering-wheel-and-hand-steering). Turning the wheel moves the controllers, and the game's
|
steering](#steering-wheel-and-hand-steering). Turning the wheel moves the controllers, and the game's
|
||||||
own motion detection still reads them, so a sharp enough turn can read as a shake.
|
own motion detection still reads them, so a sharp enough turn can read as a shake.
|
||||||
|
|
||||||
@@ -377,8 +389,9 @@ sliders exist because the comfortable value is a matter of taste and is best jud
|
|||||||
headset.
|
headset.
|
||||||
|
|
||||||
The mode engages only in a single-screen race, the same content that already qualifies for
|
The mode engages only in a single-screen race, the same content that already qualifies for
|
||||||
immersive stereo. Menus, split-screen, and the virtual-screen fallback are unaffected, and so is
|
immersive stereo. Menus, split-screen, `flat_screen`, and the virtual-screen fallback are
|
||||||
the desktop mirror, which keeps showing the game's ordinary third-person view. If the kart or
|
unaffected, and so is the desktop mirror, which keeps showing the game's ordinary third-person
|
||||||
|
view. If the kart or
|
||||||
camera cannot be read the camera stays where the game put it rather than guessing.
|
camera cannot be read the camera stays where the game put it rather than guessing.
|
||||||
|
|
||||||
Your own driver sits exactly where your eyes are, so their head would fill the view.
|
Your own driver sits exactly where your eyes are, so their head would fill the view.
|
||||||
@@ -453,8 +466,8 @@ and `wheel_haptics` gives a short pulse on grab and release.
|
|||||||
|
|
||||||
While the wheel is held it replaces the left stick's X axis, in both the Wii Remote and the gamepad
|
While the wheel is held it replaces the left stick's X axis, in both the Wii Remote and the gamepad
|
||||||
presentation, and the game keeps its own steering curve. The stick's Y axis still aims items, and a
|
presentation, and the game keeps its own steering curve. The stick's Y axis still aims items, and a
|
||||||
holding grip no longer reaches the game (it would press C on the Nunchuk or a shoulder on the
|
holding grip no longer reaches the game (a shoulder on the gamepad; the Wii Remote presentation
|
||||||
gamepad); the triggers, A and the right stick are unchanged. Releasing both grips gives steering back
|
leaves the grips unbound for this reason); the triggers, A and the right stick are unchanged. Releasing both grips gives steering back
|
||||||
to the stick. The settings panel withholds the wheel like any other input.
|
to the stick. The settings panel withholds the wheel like any other input.
|
||||||
|
|
||||||
**A USB wheel.** With a USB wheel and pedals set up (see the README), the wheel drives the race as
|
**A USB wheel.** With a USB wheel and pedals set up (see the README), the wheel drives the race as
|
||||||
@@ -498,6 +511,10 @@ The runtime deliberately fails safe instead of guessing which Mario Kart camera
|
|||||||
confirm exactly one distinct race camera for the current GX frame.
|
confirm exactly one distinct race camera for the current GX frame.
|
||||||
- Leaving the race or observing zero or multiple cameras immediately returns presentation to the
|
- Leaving the race or observing zero or multiple cameras immediately returns presentation to the
|
||||||
virtual screen. Session/runtime loss safely tears down XR and continues on the desktop mirror.
|
virtual screen. Session/runtime loss safely tears down XR and continues on the desktop mirror.
|
||||||
|
- `flat_screen` clears the policy's `immersive_races`, so a race stays on the virtual screen
|
||||||
|
however complete the observations are. Changing it advances the safety generation like any
|
||||||
|
other change of presentation, and the pacing thread still treats that race as a race: pipeline
|
||||||
|
caches are not stored mid-race on the virtual screen either.
|
||||||
|
|
||||||
Aurora records the original GX frame once and replays it for both OpenXR eyes. Perspective GX draws
|
Aurora records the original GX frame once and replays it for both OpenXR eyes. Perspective GX draws
|
||||||
receive asymmetric headset projections, while the game's 2D layer goes on a fixed virtual screen
|
receive asymmetric headset projections, while the game's 2D layer goes on a fixed virtual screen
|
||||||
|
|||||||
@@ -114,15 +114,23 @@ class SettingsPage(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun buildVr() {
|
private fun buildVr() {
|
||||||
val firstPerson = { c: TomlConfig -> c.bool("vr", "first_person") ?: false }
|
// Flat Screen mode keeps races on the menu screen, which none of the race view rows reach.
|
||||||
|
val immersive = { c: TomlConfig -> !(c.bool("vr", "flat_screen") ?: false) }
|
||||||
|
val firstPerson = { c: TomlConfig -> immersive(c) && (c.bool("vr", "first_person") ?: false) }
|
||||||
// The steering wheel and hand steering belong to the cockpit seat.
|
// The steering wheel and hand steering belong to the cockpit seat.
|
||||||
val cockpit = { c: TomlConfig -> firstPerson(c) && stringIndex(c, "vr", "first_person_seat", SEATS) == 0 }
|
val cockpit = { c: TomlConfig -> firstPerson(c) && stringIndex(c, "vr", "first_person_seat", SEATS) == 0 }
|
||||||
section(R.string.section_vr_camera) {
|
section(R.string.section_vr_camera) {
|
||||||
|
toggle(
|
||||||
|
R.string.vr_flat_screen, R.string.vr_flat_screen_helper,
|
||||||
|
read = { !immersive(it) },
|
||||||
|
write = { c, value -> c.setBool("vr", "flat_screen", value) },
|
||||||
|
)
|
||||||
choice(
|
choice(
|
||||||
R.string.vr_camera, R.string.vr_camera_helper,
|
R.string.vr_camera, R.string.vr_camera_helper,
|
||||||
listOf(R.string.vr_camera_chase, R.string.vr_camera_first_person),
|
listOf(R.string.vr_camera_chase, R.string.vr_camera_first_person),
|
||||||
read = { if (firstPerson(it)) 1 else 0 },
|
read = { if (it.bool("vr", "first_person") == true) 1 else 0 },
|
||||||
write = { c, index -> c.setBool("vr", "first_person", index == 1) },
|
write = { c, index -> c.setBool("vr", "first_person", index == 1) },
|
||||||
|
enabledIf = immersive,
|
||||||
)
|
)
|
||||||
choice(
|
choice(
|
||||||
R.string.vr_rotation, R.string.vr_rotation_helper,
|
R.string.vr_rotation, R.string.vr_rotation_helper,
|
||||||
@@ -172,6 +180,7 @@ class SettingsPage(
|
|||||||
read = { number(it, "vr", "lean_back_degrees", -45.0, 45.0, 0.0) },
|
read = { number(it, "vr", "lean_back_degrees", -45.0, 45.0, 0.0) },
|
||||||
format = { "%.0f°".format(it) },
|
format = { "%.0f°".format(it) },
|
||||||
write = { c, value -> c.setFloat("vr", "lean_back_degrees", value) },
|
write = { c, value -> c.setFloat("vr", "lean_back_degrees", value) },
|
||||||
|
enabledIf = immersive,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
section(R.string.section_vr_headset) {
|
section(R.string.section_vr_headset) {
|
||||||
@@ -203,6 +212,7 @@ class SettingsPage(
|
|||||||
R.string.vr_hud_screen, R.string.vr_hud_screen_helper,
|
R.string.vr_hud_screen, R.string.vr_hud_screen_helper,
|
||||||
read = { it.bool("vr", "hud_virtual_screen") ?: true },
|
read = { it.bool("vr", "hud_virtual_screen") ?: true },
|
||||||
write = { c, value -> c.setBool("vr", "hud_virtual_screen", value) },
|
write = { c, value -> c.setBool("vr", "hud_virtual_screen", value) },
|
||||||
|
enabledIf = immersive,
|
||||||
)
|
)
|
||||||
slider(
|
slider(
|
||||||
R.string.vr_hud_distance, R.string.vr_hud_distance_helper, 0.5, 5.0, 0.1,
|
R.string.vr_hud_distance, R.string.vr_hud_distance_helper, 0.5, 5.0, 0.1,
|
||||||
|
|||||||
@@ -172,6 +172,8 @@
|
|||||||
|
|
||||||
<!-- VR tab -->
|
<!-- VR tab -->
|
||||||
<string name="section_vr_camera">Camera</string>
|
<string name="section_vr_camera">Camera</string>
|
||||||
|
<string name="vr_flat_screen">Flat Screen mode</string>
|
||||||
|
<string name="vr_flat_screen_helper">Plays races on the same flat screen as the menus instead of all around you. The camera settings below do not apply while it is on.</string>
|
||||||
<string name="vr_camera">Camera</string>
|
<string name="vr_camera">Camera</string>
|
||||||
<string name="vr_camera_helper">Ride behind the kart like the game, or sit in the driver\'s seat.</string>
|
<string name="vr_camera_helper">Ride behind the kart like the game, or sit in the driver\'s seat.</string>
|
||||||
<string name="vr_camera_chase">Chase camera</string>
|
<string name="vr_camera_chase">Chase camera</string>
|
||||||
@@ -218,7 +220,7 @@
|
|||||||
<string name="vr_hud_width">Screen width</string>
|
<string name="vr_hud_width">Screen width</string>
|
||||||
<string name="vr_hud_width_helper">How wide the menu screen and race HUD are.</string>
|
<string name="vr_hud_width_helper">How wide the menu screen and race HUD are.</string>
|
||||||
<string name="vr_passthrough">Passthrough around the menu screen</string>
|
<string name="vr_passthrough">Passthrough around the menu screen</string>
|
||||||
<string name="vr_passthrough_helper">Shows your room through the headset\'s cameras around the menus instead of black. Races stay fully virtual.</string>
|
<string name="vr_passthrough_helper">Shows your room through the headset\'s cameras around the menus instead of black. Races stay fully virtual, except in Flat Screen mode.</string>
|
||||||
|
|
||||||
<!-- Graphics tab -->
|
<!-- Graphics tab -->
|
||||||
<string name="section_graphics">Rendering</string>
|
<string name="section_graphics">Rendering</string>
|
||||||
@@ -256,7 +258,7 @@
|
|||||||
<string name="controls_map_z">Z</string>
|
<string name="controls_map_z">Z</string>
|
||||||
<string name="controls_map_z_value">Left trigger</string>
|
<string name="controls_map_z_value">Left trigger</string>
|
||||||
<string name="controls_map_c">C</string>
|
<string name="controls_map_c">C</string>
|
||||||
<string name="controls_map_c_value">Left grip</string>
|
<string name="controls_map_c_value">Right B</string>
|
||||||
<string name="controls_map_pointer">Pointer and motion</string>
|
<string name="controls_map_pointer">Pointer and motion</string>
|
||||||
<string name="controls_map_pointer_value">Aim and move the right controller</string>
|
<string name="controls_map_pointer_value">Aim and move the right controller</string>
|
||||||
<string name="controls_map_panel">Settings panel</string>
|
<string name="controls_map_panel">Settings panel</string>
|
||||||
|
|||||||
+3
-2
@@ -165,7 +165,8 @@ suggested for `oculus/touch_controller` and `khr/simple_controller`.
|
|||||||
(created on first use) or pauses it as each presentation arrives, and submits
|
(created on first use) or pauses it as each presentation arrives, and submits
|
||||||
it first, under the virtual screen's quad, or alone while there is no image
|
it first, under the virtual screen's quad, or alone while there is no image
|
||||||
yet (startup, a recenter). An immersive race never submits it and pauses the
|
yet (startup, a recenter). An immersive race never submits it and pauses the
|
||||||
cameras. The quad is cropped to the snapshot Aurora letterboxes into the
|
cameras; a `flat_screen` race is a virtual screen, so it keeps the room.
|
||||||
|
The quad is cropped to the snapshot Aurora letterboxes into the
|
||||||
nearly square eye image (`OpenXRVirtualScreenContentRect`), or its black
|
nearly square eye image (`OpenXRVirtualScreenContentRect`), or its black
|
||||||
bands would frame the picture against the room. The manifest's `com.oculus.feature.PASSTHROUGH` is what lets Horizon
|
bands would frame the picture against the room. The manifest's `com.oculus.feature.PASSTHROUGH` is what lets Horizon
|
||||||
OS composite it; DolphinXR found that without it every call succeeds and the
|
OS composite it; DolphinXR found that without it every call succeeds and the
|
||||||
@@ -182,7 +183,7 @@ The app opens on `LauncherActivity` (`android/app/src/main/java/org/wiicompiled/
|
|||||||
a 2D Horizon OS panel modelled on the PC launcher, WheelWizard VR, and using its
|
a 2D Horizon OS panel modelled on the PC launcher, WheelWizard VR, and using its
|
||||||
palette. **Home** has the Play button and reports a missing or incomplete `DATA`
|
palette. **Home** has the Play button and reports a missing or incomplete `DATA`
|
||||||
(the check is the runtime's own `IsDvdDataRoot`: `files/` and `sys/fst.bin`).
|
(the check is the runtime's own `IsDvdDataRoot`: `files/` and `sys/fst.bin`).
|
||||||
**Settings** edits `Config.toml` in tabs: VR (camera, rotation, driver hiding,
|
**Settings** edits `Config.toml` in tabs: VR (Flat Screen mode, camera, rotation, driver hiding,
|
||||||
seat, hand steering, lean back, render scale, VR interpolation, virtual screen
|
seat, hand steering, lean back, render scale, VR interpolation, virtual screen
|
||||||
size and distance),
|
size and distance),
|
||||||
Graphics (resolution, widescreen, bloom, shader stutter), Controls (controller
|
Graphics (resolution, widescreen, bloom, shader stutter), Controls (controller
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ struct RuntimeUserConfig {
|
|||||||
std::optional<float> vrHudDistanceMeters;
|
std::optional<float> vrHudDistanceMeters;
|
||||||
std::optional<float> vrHudWidthMeters;
|
std::optional<float> vrHudWidthMeters;
|
||||||
std::optional<bool> vrHudVirtualScreen;
|
std::optional<bool> vrHudVirtualScreen;
|
||||||
|
std::optional<bool> vrFlatScreen;
|
||||||
std::optional<bool> vrPassthrough;
|
std::optional<bool> vrPassthrough;
|
||||||
std::optional<bool> vrStopAtDisplayCopy;
|
std::optional<bool> vrStopAtDisplayCopy;
|
||||||
std::optional<bool> vrSkipCopyClears;
|
std::optional<bool> vrSkipCopyClears;
|
||||||
@@ -496,6 +497,11 @@ inline void EnsureConfigFile() {
|
|||||||
"# Changeable live from the F10 menu; the two sizes above place\n"
|
"# Changeable live from the F10 menu; the two sizes above place\n"
|
||||||
"# that screen and the menu screen alike and are read at launch.\n"
|
"# that screen and the menu screen alike and are read at launch.\n"
|
||||||
"hud_virtual_screen = true\n"
|
"hud_virtual_screen = true\n"
|
||||||
|
"# Flat Screen mode keeps races on that same screen, as the\n"
|
||||||
|
"# menus are, instead of all around you: no stereo race view, no\n"
|
||||||
|
"# first-person camera or hand steering. Changeable live from the\n"
|
||||||
|
"# F10 menu.\n"
|
||||||
|
"flat_screen = false\n"
|
||||||
"# EFB replay controls for the per-eye views, changeable live\n"
|
"# EFB replay controls for the per-eye views, changeable live\n"
|
||||||
"# from the F10 menu. stop_at_display_copy ends each eye at the\n"
|
"# from the F10 menu. stop_at_display_copy ends each eye at the\n"
|
||||||
"# frame's final GXCopyDisp; skip_copy_clears drops the EFB\n"
|
"# frame's final GXCopyDisp; skip_copy_clears drops the EFB\n"
|
||||||
@@ -747,6 +753,7 @@ inline RuntimeUserConfig ParseConfigDocument(const toml::value& document) {
|
|||||||
config.vrHudWidthMeters = *value;
|
config.vrHudWidthMeters = *value;
|
||||||
}
|
}
|
||||||
config.vrHudVirtualScreen = FindConfigValue<bool>(document, "vr", "hud_virtual_screen");
|
config.vrHudVirtualScreen = FindConfigValue<bool>(document, "vr", "hud_virtual_screen");
|
||||||
|
config.vrFlatScreen = FindConfigValue<bool>(document, "vr", "flat_screen");
|
||||||
config.vrPassthrough = FindConfigValue<bool>(document, "vr", "passthrough");
|
config.vrPassthrough = FindConfigValue<bool>(document, "vr", "passthrough");
|
||||||
config.vrStopAtDisplayCopy = FindConfigValue<bool>(document, "vr", "stop_at_display_copy");
|
config.vrStopAtDisplayCopy = FindConfigValue<bool>(document, "vr", "stop_at_display_copy");
|
||||||
config.vrSkipCopyClears = FindConfigValue<bool>(document, "vr", "skip_copy_clears");
|
config.vrSkipCopyClears = FindConfigValue<bool>(document, "vr", "skip_copy_clears");
|
||||||
@@ -1061,6 +1068,11 @@ inline bool SetVrHudVirtualScreen(bool value) {
|
|||||||
return WriteSetting("vr", "hud_virtual_screen", value ? "true" : "false");
|
return WriteSetting("vr", "hud_virtual_screen", value ? "true" : "false");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool SetVrFlatScreen(bool value) {
|
||||||
|
Mutable().vrFlatScreen = value;
|
||||||
|
return WriteSetting("vr", "flat_screen", value ? "true" : "false");
|
||||||
|
}
|
||||||
|
|
||||||
inline bool SetVrPassthrough(bool value) {
|
inline bool SetVrPassthrough(bool value) {
|
||||||
Mutable().vrPassthrough = value;
|
Mutable().vrPassthrough = value;
|
||||||
return WriteSetting("vr", "passthrough", value ? "true" : "false");
|
return WriteSetting("vr", "passthrough", value ? "true" : "false");
|
||||||
@@ -1518,9 +1530,16 @@ inline bool VrHudVirtualScreen(bool fallback = true) {
|
|||||||
return Get().vrHudVirtualScreen.value_or(fallback);
|
return Get().vrHudVirtualScreen.value_or(fallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Races on the flat virtual screen the menus use, instead of immersive
|
||||||
|
// stereo. The launcher's Settings page shows the same default.
|
||||||
|
inline bool VrFlatScreen(bool fallback = false) {
|
||||||
|
return Get().vrFlatScreen.value_or(fallback);
|
||||||
|
}
|
||||||
|
|
||||||
// The room, through the headset's cameras, around the menu screen and every
|
// The room, through the headset's cameras, around the menu screen and every
|
||||||
// other virtual screen (never in a race). Only the Quest offers it; the
|
// other virtual screen, a Flat Screen race included (never an immersive
|
||||||
// launcher's Settings page shows the same default.
|
// race). Only the Quest offers it; the launcher's Settings page shows the same
|
||||||
|
// default.
|
||||||
inline bool VrPassthrough(bool fallback = true) {
|
inline bool VrPassthrough(bool fallback = true) {
|
||||||
return Get().vrPassthrough.value_or(fallback);
|
return Get().vrPassthrough.value_or(fallback);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ inline constexpr uint32_t kMkwVRRequiredImmersiveBindings =
|
|||||||
|
|
||||||
struct MkwVRPolicyConfig {
|
struct MkwVRPolicyConfig {
|
||||||
bool enabled = false;
|
bool enabled = false;
|
||||||
|
// False is Flat Screen mode: races stay on the virtual screen the menus use.
|
||||||
bool immersive_races = true;
|
bool immersive_races = true;
|
||||||
float world_units_per_meter = 500.0f;
|
float world_units_per_meter = 500.0f;
|
||||||
float hud_distance_meters = 2.0f;
|
float hud_distance_meters = 2.0f;
|
||||||
@@ -151,6 +152,9 @@ void MkwVRPolicySetFirstPersonEngaged(bool engaged) noexcept;
|
|||||||
// MkwVRPolicyConfigure so the F10 slider can retune it during a race without
|
// MkwVRPolicyConfigure so the F10 slider can retune it during a race without
|
||||||
// republishing (and revalidating) the whole configuration.
|
// republishing (and revalidating) the whole configuration.
|
||||||
void MkwVRPolicySetFirstPersonUnitsPerMeter(float units_per_meter) noexcept;
|
void MkwVRPolicySetFirstPersonUnitsPerMeter(float units_per_meter) noexcept;
|
||||||
|
// Flat Screen mode, live from the F10 menu. Unlike the scale above this changes
|
||||||
|
// which content is safe to present, so it advances the safety generation.
|
||||||
|
void MkwVRPolicySetImmersiveRaces(bool enabled) noexcept;
|
||||||
MkwVRPolicySnapshot MkwVRPolicyGetSnapshot() noexcept;
|
MkwVRPolicySnapshot MkwVRPolicyGetSnapshot() noexcept;
|
||||||
|
|
||||||
// This classifier is deliberately structural rather than heuristic: future
|
// This classifier is deliberately structural rather than heuristic: future
|
||||||
|
|||||||
@@ -79,10 +79,11 @@ inline float MaxWheelAngle(bool bike, const WheelTuning& tuning) noexcept {
|
|||||||
return clamped * 0.01745329252f;
|
return clamped * 0.01745329252f;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Grips only grab. While a hand holds the wheel its squeeze is released for the
|
// Grips only grab. As a Wii Remote they press nothing at all (C, the game's
|
||||||
// game, where it would press C on the Nunchuk or a shoulder on the gamepad, and
|
// look-behind, is right B); as a gamepad they are the shoulders, so a holding
|
||||||
// the wheel replaces the left stick's X axis, which both controller modes steer
|
// hand's squeeze is released for the game. The wheel replaces the left stick's
|
||||||
// with. The stick's Y axis keeps aiming items forwards and backwards.
|
// X axis, which both controller modes steer with, and the stick's Y axis keeps
|
||||||
|
// aiming items forwards and backwards.
|
||||||
inline void ApplyHandSteering(std::array<wii_remote::HandInputs, 2>& hands, const WheelState& wheel) noexcept {
|
inline void ApplyHandSteering(std::array<wii_remote::HandInputs, 2>& hands, const WheelState& wheel) noexcept {
|
||||||
for (size_t hand = 0; hand < hands.size(); ++hand) {
|
for (size_t hand = 0; hand < hands.size(); ++hand) {
|
||||||
if (wheel.held[hand]) {
|
if (wheel.held[hand]) {
|
||||||
|
|||||||
@@ -63,7 +63,8 @@ struct OpenXRPointerScreen {
|
|||||||
// the seated frame every frame. With hand steering on, a squeezed grip near the
|
// the seated frame every frame. With hand steering on, a squeezed grip near the
|
||||||
// steering wheel or handlebar takes hold of it; while held, the wheel replaces
|
// steering wheel or handlebar takes hold of it; while held, the wheel replaces
|
||||||
// the left stick's X axis in both presentations and that grip no longer reaches
|
// the left stick's X axis in both presentations and that grip no longer reaches
|
||||||
// the game (C on the Nunchuk, a shoulder on the gamepad).
|
// the game (a shoulder on the gamepad; as a Wii Remote the grips are unbound,
|
||||||
|
// so a hand on the wheel cannot hold down a button).
|
||||||
//
|
//
|
||||||
// A right-thumbstick click on its own toggles the first-person camera, as its
|
// A right-thumbstick click on its own toggles the first-person camera, as its
|
||||||
// F10 checkbox does (first_person_toggle_click).
|
// F10 checkbox does (first_person_toggle_click).
|
||||||
|
|||||||
@@ -342,10 +342,12 @@ struct HandInputs {
|
|||||||
|
|
||||||
// Adapted from DolphinXR's default "OpenXR Wii Remote" profile
|
// Adapted from DolphinXR's default "OpenXR Wii Remote" profile
|
||||||
// (Data/Sys/Profiles/Wiimote):
|
// (Data/Sys/Profiles/Wiimote):
|
||||||
// right A -> A, right trigger -> B, right stick up/down -> 1/2,
|
// right A -> A, right trigger -> B, right B -> C, right stick up/down -> 1/2,
|
||||||
// left X -> -, left menu -> +,
|
// left X -> -, left menu -> +,
|
||||||
// left grip -> C, left trigger -> Z, left stick -> Nunchuk stick.
|
// left trigger -> Z, left stick -> Nunchuk stick.
|
||||||
// HOME has no button; left Y opens the settings panel (openxr_settings_panel.h).
|
// HOME has no button; left Y opens the settings panel (openxr_settings_panel.h).
|
||||||
|
// The grips press nothing: they take hold of the wheel (openxr_driving.h), and C
|
||||||
|
// is the game's look-behind, which a hand on the wheel would otherwise hold down.
|
||||||
inline uint32_t RemoteButtons(const HandInputs& left, const HandInputs& right) noexcept {
|
inline uint32_t RemoteButtons(const HandInputs& left, const HandInputs& right) noexcept {
|
||||||
uint32_t hold = 0;
|
uint32_t hold = 0;
|
||||||
const auto press = [&hold](bool held, uint32_t bit) {
|
const auto press = [&hold](bool held, uint32_t bit) {
|
||||||
@@ -355,11 +357,11 @@ inline uint32_t RemoteButtons(const HandInputs& left, const HandInputs& right) n
|
|||||||
};
|
};
|
||||||
press(right.primary, kButtonA);
|
press(right.primary, kButtonA);
|
||||||
press(right.trigger > kPressThreshold, kButtonB);
|
press(right.trigger > kPressThreshold, kButtonB);
|
||||||
|
press(right.secondary, kButtonC);
|
||||||
press(right.stick_y > kPressThreshold, kButtonOne);
|
press(right.stick_y > kPressThreshold, kButtonOne);
|
||||||
press(right.stick_y < -kPressThreshold, kButtonTwo);
|
press(right.stick_y < -kPressThreshold, kButtonTwo);
|
||||||
press(left.primary, kButtonMinus);
|
press(left.primary, kButtonMinus);
|
||||||
press(left.menu, kButtonPlus);
|
press(left.menu, kButtonPlus);
|
||||||
press(left.squeeze > kPressThreshold, kButtonC);
|
|
||||||
press(left.trigger > kPressThreshold, kButtonZ);
|
press(left.trigger > kPressThreshold, kButtonZ);
|
||||||
return hold;
|
return hold;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -141,6 +141,7 @@ bool g_vrEnabled = RuntimeConfigFile::VrEnabled(true);
|
|||||||
bool g_vrStopAtDisplayCopy = RuntimeConfigFile::VrStopAtDisplayCopy(true);
|
bool g_vrStopAtDisplayCopy = RuntimeConfigFile::VrStopAtDisplayCopy(true);
|
||||||
bool g_vrSkipCopyClears = RuntimeConfigFile::VrSkipCopyClears(true);
|
bool g_vrSkipCopyClears = RuntimeConfigFile::VrSkipCopyClears(true);
|
||||||
bool g_vrHudVirtualScreen = RuntimeConfigFile::VrHudVirtualScreen(true);
|
bool g_vrHudVirtualScreen = RuntimeConfigFile::VrHudVirtualScreen(true);
|
||||||
|
bool g_vrFlatScreen = RuntimeConfigFile::VrFlatScreen();
|
||||||
#if defined(__ANDROID__)
|
#if defined(__ANDROID__)
|
||||||
bool g_vrPassthrough = RuntimeConfigFile::VrPassthrough();
|
bool g_vrPassthrough = RuntimeConfigFile::VrPassthrough();
|
||||||
#endif
|
#endif
|
||||||
@@ -1354,8 +1355,9 @@ void DrawVrSettings() {
|
|||||||
ImGui::SetTooltip(
|
ImGui::SetTooltip(
|
||||||
"Wii Remote + Nunchuk: the right controller is a Wii Remote, with motion and a pointer "
|
"Wii Remote + Nunchuk: the right controller is a Wii Remote, with motion and a pointer "
|
||||||
"that lands where you aim on the virtual screen; the left one is the Nunchuk.\n"
|
"that lands where you aim on the virtual screen; the left one is the Nunchuk.\n"
|
||||||
" Right: A = A, trigger = B, stick up/down = 1/2\n"
|
" Right: A = A, trigger = B, B = C (look behind), stick up/down = 1/2\n"
|
||||||
" Left: stick = Nunchuk stick, trigger = Z, grip = C, X = -, menu = +, Y = settings panel\n"
|
" Left: stick = Nunchuk stick, trigger = Z, X = -, menu = +, Y = settings panel\n"
|
||||||
|
" The grips press nothing; they take hold of the wheel with hand steering.\n"
|
||||||
"Gamepad: both controllers are one ordinary controller, read as a GameCube pad.\n"
|
"Gamepad: both controllers are one ordinary controller, read as a GameCube pad.\n"
|
||||||
"Applies immediately; the game sees the controller change as a reconnection.");
|
"Applies immediately; the game sees the controller change as a reconnection.");
|
||||||
}
|
}
|
||||||
@@ -1424,11 +1426,13 @@ void DrawVrSettings() {
|
|||||||
ImGui::PopTextWrapPos();
|
ImGui::PopTextWrapPos();
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
ImGui::Text("VR 2D layer");
|
ImGui::Text("VR 2D layer");
|
||||||
|
ImGui::BeginDisabled(g_vrFlatScreen);
|
||||||
if (ImGui::Checkbox("2D layer on a virtual screen", &g_vrHudVirtualScreen)) {
|
if (ImGui::Checkbox("2D layer on a virtual screen", &g_vrHudVirtualScreen)) {
|
||||||
ApplyVrHudVirtualScreen();
|
ApplyVrHudVirtualScreen();
|
||||||
RuntimeConfigFile::SetVrHudVirtualScreen(g_vrHudVirtualScreen);
|
RuntimeConfigFile::SetVrHudVirtualScreen(g_vrHudVirtualScreen);
|
||||||
}
|
}
|
||||||
if (ImGui::IsItemHovered()) {
|
ImGui::EndDisabled();
|
||||||
|
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) {
|
||||||
ImGui::SetTooltip(
|
ImGui::SetTooltip(
|
||||||
"Puts the minimap, race position, item roulette and the rest of the race HUD on a "
|
"Puts the minimap, race position, item roulette and the rest of the race HUD on a "
|
||||||
"screen fixed ahead of the kart camera. Turn off to leave them stretched across "
|
"screen fixed ahead of the kart camera. Turn off to leave them stretched across "
|
||||||
@@ -1467,13 +1471,15 @@ void DrawVrSettings() {
|
|||||||
ImGui::SetTooltip("Click to rebind. Esc cancels, Backspace unbinds.");
|
ImGui::SetTooltip("Click to rebind. Esc cancels, Backspace unbinds.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ImGui::BeginDisabled(g_vrFlatScreen);
|
||||||
if (ImGui::SliderFloat("Lean back angle (deg)", &g_vrLeanBackDegrees,
|
if (ImGui::SliderFloat("Lean back angle (deg)", &g_vrLeanBackDegrees,
|
||||||
-RuntimeConfigFile::kVrLeanBackDegreesLimit,
|
-RuntimeConfigFile::kVrLeanBackDegreesLimit,
|
||||||
RuntimeConfigFile::kVrLeanBackDegreesLimit, "%.1f")) {
|
RuntimeConfigFile::kVrLeanBackDegreesLimit, "%.1f")) {
|
||||||
mkw::vr::OpenXRSetLeanBackDegrees(g_vrLeanBackDegrees);
|
mkw::vr::OpenXRSetLeanBackDegrees(g_vrLeanBackDegrees);
|
||||||
RuntimeConfigFile::SetVrLeanBackDegrees(g_vrLeanBackDegrees);
|
RuntimeConfigFile::SetVrLeanBackDegrees(g_vrLeanBackDegrees);
|
||||||
}
|
}
|
||||||
if (ImGui::IsItemHovered()) {
|
ImGui::EndDisabled();
|
||||||
|
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) {
|
||||||
ImGui::SetTooltip(
|
ImGui::SetTooltip(
|
||||||
"Tilts the game camera back with you when you play reclined, so set it to "
|
"Tilts the game camera back with you when you play reclined, so set it to "
|
||||||
"roughly how far back your seat is and the track comes back in front of you "
|
"roughly how far back your seat is and the track comes back in front of you "
|
||||||
@@ -1489,12 +1495,26 @@ void DrawVrSettings() {
|
|||||||
if (ImGui::IsItemHovered()) {
|
if (ImGui::IsItemHovered()) {
|
||||||
ImGui::SetTooltip(
|
ImGui::SetTooltip(
|
||||||
"Shows your room through the headset's cameras around the menu screen and every "
|
"Shows your room through the headset's cameras around the menu screen and every "
|
||||||
"other screen outside a race, instead of black. Races stay fully virtual. "
|
"other screen outside an immersive race, instead of black. Immersive races stay "
|
||||||
|
"fully virtual; the Flat Screen race has the room around it too. "
|
||||||
"Applies immediately.");
|
"Applies immediately.");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
ImGui::Text("VR camera");
|
ImGui::Text("VR camera");
|
||||||
|
if (ImGui::Checkbox("Flat Screen mode", &g_vrFlatScreen)) {
|
||||||
|
RuntimeConfigFile::SetVrFlatScreen(g_vrFlatScreen);
|
||||||
|
mkw::vr::MkwVRPolicySetImmersiveRaces(!g_vrFlatScreen);
|
||||||
|
mkw::vr::MkwVRFirstPersonApplyConfiguredSettings();
|
||||||
|
}
|
||||||
|
if (ImGui::IsItemHovered()) {
|
||||||
|
ImGui::SetTooltip(
|
||||||
|
"Plays races on the same flat screen as the menus, through the game's own camera, "
|
||||||
|
"instead of all around you in stereo. The first-person camera, hand steering and "
|
||||||
|
"the race view settings do not apply while it is on. Applies immediately.");
|
||||||
|
}
|
||||||
|
// Everything below shapes the immersive race view, which Flat Screen mode replaces.
|
||||||
|
ImGui::BeginDisabled(g_vrFlatScreen);
|
||||||
if (ImGui::Checkbox("First-person camera", &g_vrFirstPerson)) {
|
if (ImGui::Checkbox("First-person camera", &g_vrFirstPerson)) {
|
||||||
RuntimeConfigFile::SetVrFirstPerson(g_vrFirstPerson);
|
RuntimeConfigFile::SetVrFirstPerson(g_vrFirstPerson);
|
||||||
mkw::vr::MkwVRFirstPersonApplyConfiguredSettings();
|
mkw::vr::MkwVRFirstPersonApplyConfiguredSettings();
|
||||||
@@ -1643,11 +1663,15 @@ void DrawVrSettings() {
|
|||||||
mkw::vr::MkwVRFirstPersonApplyConfiguredSettings();
|
mkw::vr::MkwVRFirstPersonApplyConfiguredSettings();
|
||||||
ApplyVrHudVirtualScreen();
|
ApplyVrHudVirtualScreen();
|
||||||
}
|
}
|
||||||
|
ImGui::EndDisabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
// The right-thumbstick click: flips the first-person camera exactly as its
|
// The right-thumbstick click: flips the first-person camera exactly as its
|
||||||
// checkbox does. Game thread.
|
// checkbox does, so it does nothing in Flat Screen mode either. Game thread.
|
||||||
void ToggleFirstPersonCamera() {
|
void ToggleFirstPersonCamera() {
|
||||||
|
if (g_vrFlatScreen) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
g_vrFirstPerson = !g_vrFirstPerson;
|
g_vrFirstPerson = !g_vrFirstPerson;
|
||||||
RuntimeConfigFile::SetVrFirstPerson(g_vrFirstPerson);
|
RuntimeConfigFile::SetVrFirstPerson(g_vrFirstPerson);
|
||||||
mkw::vr::MkwVRFirstPersonApplyConfiguredSettings();
|
mkw::vr::MkwVRFirstPersonApplyConfiguredSettings();
|
||||||
|
|||||||
@@ -1213,8 +1213,11 @@ void MkwVRFirstPersonApplyConfiguredSettings() noexcept {
|
|||||||
const FirstPersonRotation rotation = mode == "full" ? FirstPersonRotation::Full
|
const FirstPersonRotation rotation = mode == "full" ? FirstPersonRotation::Full
|
||||||
: mode == "yaw_pitch" ? FirstPersonRotation::YawPitch
|
: mode == "yaw_pitch" ? FirstPersonRotation::YawPitch
|
||||||
: FirstPersonRotation::YawOnly;
|
: FirstPersonRotation::YawOnly;
|
||||||
MkwVRFirstPersonConfigure(RuntimeConfigFile::VrFirstPerson(false), offsets, units_per_meter,
|
// Flat Screen mode shows the race on the menu screen through the game's own
|
||||||
rotation);
|
// camera, where a hidden driver would only be missing from the kart.
|
||||||
|
MkwVRFirstPersonConfigure(RuntimeConfigFile::VrFirstPerson(false) &&
|
||||||
|
!RuntimeConfigFile::VrFlatScreen(),
|
||||||
|
offsets, units_per_meter, rotation);
|
||||||
MkwVRPolicySetFirstPersonUnitsPerMeter(units_per_meter);
|
MkwVRPolicySetFirstPersonUnitsPerMeter(units_per_meter);
|
||||||
const bool cockpit = RuntimeConfigFile::VrFirstPersonSeat() != "custom";
|
const bool cockpit = RuntimeConfigFile::VrFirstPersonSeat() != "custom";
|
||||||
const float cockpit_units = RuntimeConfigFile::VrCockpitUnitsPerMeter();
|
const float cockpit_units = RuntimeConfigFile::VrCockpitUnitsPerMeter();
|
||||||
|
|||||||
@@ -257,6 +257,11 @@ void MkwVRPolicySetFirstPersonUnitsPerMeter(float units_per_meter) noexcept {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MkwVRPolicySetImmersiveRaces(bool enabled) noexcept {
|
||||||
|
std::lock_guard<std::mutex> lock(g_policy_mutex);
|
||||||
|
ApplyPolicyMutation([&] { g_policy.config.immersive_races = enabled; });
|
||||||
|
}
|
||||||
|
|
||||||
MkwVRPolicySnapshot MkwVRPolicyGetSnapshot() noexcept {
|
MkwVRPolicySnapshot MkwVRPolicyGetSnapshot() noexcept {
|
||||||
std::lock_guard<std::mutex> lock(g_policy_mutex);
|
std::lock_guard<std::mutex> lock(g_policy_mutex);
|
||||||
MkwVRPolicySnapshot snapshot;
|
MkwVRPolicySnapshot snapshot;
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ void ConfigurePolicy(bool enabled) noexcept {
|
|||||||
MkwVRPolicyReset();
|
MkwVRPolicyReset();
|
||||||
MkwVRPolicyConfig config{};
|
MkwVRPolicyConfig config{};
|
||||||
config.enabled = enabled;
|
config.enabled = enabled;
|
||||||
config.immersive_races = true;
|
config.immersive_races = !RuntimeConfigFile::VrFlatScreen();
|
||||||
config.world_units_per_meter = RuntimeConfigFile::VrWorldUnitsPerMeter(500.0f);
|
config.world_units_per_meter = RuntimeConfigFile::VrWorldUnitsPerMeter(500.0f);
|
||||||
config.hud_distance_meters = RuntimeConfigFile::VrHudDistanceMeters(2.0f);
|
config.hud_distance_meters = RuntimeConfigFile::VrHudDistanceMeters(2.0f);
|
||||||
config.hud_width_meters = RuntimeConfigFile::VrHudWidthMeters(2.4f);
|
config.hud_width_meters = RuntimeConfigFile::VrHudWidthMeters(2.4f);
|
||||||
@@ -753,7 +753,7 @@ private:
|
|||||||
bool fatal = false;
|
bool fatal = false;
|
||||||
uint32_t consecutive_skips = 0;
|
uint32_t consecutive_skips = 0;
|
||||||
bool store_gate_set = false;
|
bool store_gate_set = false;
|
||||||
bool store_gate_immersive = false;
|
bool store_gate_racing = false;
|
||||||
bool presentation_logged = false;
|
bool presentation_logged = false;
|
||||||
VRPresentationMode logged_presentation = VRPresentationMode::Desktop;
|
VRPresentationMode logged_presentation = VRPresentationMode::Desktop;
|
||||||
uint32_t presentation_log_count = 0;
|
uint32_t presentation_log_count = 0;
|
||||||
@@ -840,8 +840,9 @@ private:
|
|||||||
aurora_get_stereo_screen_aspects(&picture_aspect, &snapshot_aspect)) {
|
aurora_get_stereo_screen_aspects(&picture_aspect, &snapshot_aspect)) {
|
||||||
presentation.quad_content_aspect = snapshot_aspect;
|
presentation.quad_content_aspect = snapshot_aspect;
|
||||||
}
|
}
|
||||||
// The room around the menu screen and every other virtual screen; a race is
|
// The room around the menu screen and every other virtual screen, a
|
||||||
// fully virtual, and the cameras are paused for it.
|
// Flat Screen race included; an immersive race is fully virtual, and the
|
||||||
|
// cameras are paused for it.
|
||||||
presentation.passthrough = !immersive && passthrough_.load(std::memory_order_relaxed);
|
presentation.passthrough = !immersive && passthrough_.load(std::memory_order_relaxed);
|
||||||
// The settings panel gets a compositor layer of its own while it is
|
// The settings panel gets a compositor layer of its own while it is
|
||||||
// open, and Aurora leaves it out of the eyes. A backend that could
|
// open, and Aurora leaves it out of the eyes. A backend that could
|
||||||
@@ -852,12 +853,14 @@ private:
|
|||||||
|
|
||||||
// Pipeline caches are stored where their stall is invisible: once when a race ends,
|
// Pipeline caches are stored where their stall is invisible: once when a race ends,
|
||||||
// and by the compiler itself while the headset shows the virtual screen. Never
|
// and by the compiler itself while the headset shows the virtual screen. Never
|
||||||
// mid-race.
|
// mid-race, and a race on the virtual screen (Flat Screen mode) is still a race.
|
||||||
if (!store_gate_set || immersive != store_gate_immersive) {
|
const bool racing = immersive || (!policy.config.immersive_races &&
|
||||||
const bool left_race = store_gate_set && store_gate_immersive && !immersive;
|
policy.scene.mode == VRSceneMode::Race);
|
||||||
|
if (!store_gate_set || racing != store_gate_racing) {
|
||||||
|
const bool left_race = store_gate_set && store_gate_racing && !racing;
|
||||||
store_gate_set = true;
|
store_gate_set = true;
|
||||||
store_gate_immersive = immersive;
|
store_gate_racing = racing;
|
||||||
aurora_set_pipeline_cache_idle_store(!immersive);
|
aurora_set_pipeline_cache_idle_store(!racing);
|
||||||
if (left_race) {
|
if (left_race) {
|
||||||
aurora_store_pipeline_caches();
|
aurora_store_pipeline_caches();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ void TestHandOff() {
|
|||||||
CheckNear(hands[0].stick_x, 0.6f, "a held wheel steers through the left stick");
|
CheckNear(hands[0].stick_x, 0.6f, "a held wheel steers through the left stick");
|
||||||
CheckNear(hands[0].stick_y, 0.8f, "the stick keeps aiming items");
|
CheckNear(hands[0].stick_y, 0.8f, "the stick keeps aiming items");
|
||||||
CheckNear(hands[0].squeeze, 1.0f, "a free hand's grip still reaches the game");
|
CheckNear(hands[0].squeeze, 1.0f, "a free hand's grip still reaches the game");
|
||||||
CheckNear(hands[1].squeeze, 0.0f, "a holding grip does not press C or a shoulder");
|
CheckNear(hands[1].squeeze, 0.0f, "a holding grip does not press a shoulder");
|
||||||
|
|
||||||
wheel.held = {true, true};
|
wheel.held = {true, true};
|
||||||
wheel.steering = 3.0f;
|
wheel.steering = 3.0f;
|
||||||
|
|||||||
@@ -73,6 +73,22 @@ int main() {
|
|||||||
check(MkwVRPolicyGetSnapshot().presentation == VRPresentationMode::VirtualScreen, "race entry needs fresh camera");
|
check(MkwVRPolicyGetSnapshot().presentation == VRPresentationMode::VirtualScreen, "race entry needs fresh camera");
|
||||||
MkwVRPolicyPublishRaceCamera(camera);
|
MkwVRPolicyPublishRaceCamera(camera);
|
||||||
check(MkwVRPolicyGetSnapshot().presentation == VRPresentationMode::ImmersiveRace, "race resumes with fresh camera");
|
check(MkwVRPolicyGetSnapshot().presentation == VRPresentationMode::ImmersiveRace, "race resumes with fresh camera");
|
||||||
|
{
|
||||||
|
const uint64_t immersive_tag = MkwVRPolicyGetSnapshot().content_tag;
|
||||||
|
MkwVRPolicySetFirstPersonEngaged(true);
|
||||||
|
MkwVRPolicySetImmersiveRaces(false);
|
||||||
|
const auto flat = MkwVRPolicyGetSnapshot();
|
||||||
|
check(flat.presentation == VRPresentationMode::VirtualScreen, "Flat Screen mode keeps races on the screen");
|
||||||
|
check(flat.content_tag != immersive_tag, "Flat Screen mode must invalidate immersive packets");
|
||||||
|
check(!flat.first_person_engaged, "Flat Screen mode never engages first person");
|
||||||
|
check(MkwVRPolicyRouteDraw(VRDrawClass::PerspectiveWorld, flat) == VRDrawRoute::VirtualScreen,
|
||||||
|
"Flat Screen mode routes the race world to the screen");
|
||||||
|
MkwVRPolicySetFirstPersonEngaged(false);
|
||||||
|
MkwVRPolicySetImmersiveRaces(true);
|
||||||
|
const auto resumed = MkwVRPolicyGetSnapshot();
|
||||||
|
check(resumed.presentation == VRPresentationMode::ImmersiveRace, "leaving Flat Screen mode resumes the race");
|
||||||
|
check(resumed.content_tag != flat.content_tag, "leaving Flat Screen mode must invalidate screen packets");
|
||||||
|
}
|
||||||
MkwVRPolicySetSessionActive(false);
|
MkwVRPolicySetSessionActive(false);
|
||||||
check(MkwVRPolicyGetSnapshot().presentation == VRPresentationMode::Desktop, "inactive session uses desktop");
|
check(MkwVRPolicyGetSnapshot().presentation == VRPresentationMode::Desktop, "inactive session uses desktop");
|
||||||
return failures == 0 ? 0 : 1;
|
return failures == 0 ? 0 : 1;
|
||||||
|
|||||||
@@ -240,7 +240,9 @@ void TestButtons() {
|
|||||||
|
|
||||||
right.primary = true;
|
right.primary = true;
|
||||||
right.trigger = 0.6f;
|
right.trigger = 0.6f;
|
||||||
Check(RemoteButtons(left, right) == (kButtonA | kButtonB), "right A and trigger are A and B");
|
right.secondary = true;
|
||||||
|
Check(RemoteButtons(left, right) == (kButtonA | kButtonB | kButtonC),
|
||||||
|
"right A, trigger and B are A, B and C");
|
||||||
|
|
||||||
right = {};
|
right = {};
|
||||||
right.stick_y = 0.9f;
|
right.stick_y = 0.9f;
|
||||||
@@ -260,16 +262,17 @@ void TestButtons() {
|
|||||||
left.menu = true;
|
left.menu = true;
|
||||||
Check(RemoteButtons(left, right) == (kButtonMinus | kButtonPlus), "left X and menu are - and +");
|
Check(RemoteButtons(left, right) == (kButtonMinus | kButtonPlus), "left X and menu are - and +");
|
||||||
left = {};
|
left = {};
|
||||||
left.squeeze = 0.8f;
|
|
||||||
left.trigger = 0.7f;
|
left.trigger = 0.7f;
|
||||||
Check(RemoteButtons(left, right) == (kButtonC | kButtonZ), "left grip and trigger are C and Z");
|
Check(RemoteButtons(left, right) == kButtonZ, "left trigger is Z");
|
||||||
// Left Y is the settings panel's button, and nothing presses HOME.
|
// Left Y is the settings panel's button, the grips take hold of the steering
|
||||||
|
// wheel, and nothing presses HOME.
|
||||||
left = {};
|
left = {};
|
||||||
left.secondary = true;
|
left.secondary = true;
|
||||||
right.secondary = true;
|
left.squeeze = 0.8f;
|
||||||
|
right.squeeze = 0.8f;
|
||||||
right.thumbstick_click = true;
|
right.thumbstick_click = true;
|
||||||
left.thumbstick_click = true;
|
left.thumbstick_click = true;
|
||||||
Check(RemoteButtons(left, right) == 0, "left Y, right B and the stick clicks are unbound");
|
Check(RemoteButtons(left, right) == 0, "left Y, the grips and the stick clicks are unbound");
|
||||||
left = {};
|
left = {};
|
||||||
right = {};
|
right = {};
|
||||||
left.menu = true;
|
left.menu = true;
|
||||||
|
|||||||
Reference in new issue
Block a user