mirror of
https://github.com/Cesarus85/ringfall-mjolnir-vr.git
synced 2026-10-18 00:00:29 +02:00
Compare commits
6
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
32cc1cb206 | ||
|
|
adf220d344 | ||
|
|
32ad9ed6b0 | ||
|
|
cf19bcfdfa | ||
|
|
3b5796f1a0 | ||
|
|
68135a712d |
No files matched your search
+101
-6
@@ -35,7 +35,7 @@ named where code is taken over.
|
||||
| --- | --- | --- |
|
||||
| 1 | Steam Frame CPU time: Mesa's trace markers off (after astromaddie/HaloCE-VR), no `glGet` stalls in the visibility counters' copies | **done** (in `main` 2026-10-06): markers quieted, no problems; the frame's work about unchanged (11-12.5 ms of 13.9 in a bot game) |
|
||||
| 3a | Visible arms and hands: the arms by IK to the controllers, fingers by trigger and grip | **done** (in `main` 2026-10-06; Quest 3 and Steam Frame good; 0.02 ms a frame) |
|
||||
| 2 | Controls and comfort: left-handed mode, buttons remapped, flashlight by tapping the head, finer turning and vignette choices, graphics presets and refresh rate in the VR options | first part **done** (in `main` 2026-10-06; Quest 3 and Steam Frame good): left-handed mode, graphics presets, refresh rate and resolution in the VR options. Left: buttons remapped, flashlight by tapping the head, finer turning and vignette choices |
|
||||
| 2 | Controls and comfort: left-handed mode, buttons remapped, flashlight by tapping the head, finer turning and vignette choices, graphics presets and refresh rate in the VR options | first part **done** (in `main` 2026-10-06; Quest 3 and Steam Frame good): left-handed mode, graphics presets, refresh rate and resolution in the VR options. Second part **built** (branch `feature/vr-comfort`, headset test pending): buttons remapped, flashlight by tapping the head, finer turning and vignette choices |
|
||||
| 3b | The whole body: torso from head and hands, legs and feet following in the room; full / arms only / hands only | |
|
||||
| 3c | Weapons held physically, holsters at shoulder and hip (the buttons stay) | |
|
||||
| 3d | Other VR players shown with their heads, hands and bodies (today their bodies move as flat players' do: only their aim and throws come from their hands) | |
|
||||
@@ -106,7 +106,7 @@ the GPU's fill.
|
||||
|
||||
VR options (Y): two pages, PLAY (the comfort rows, "Weapon hand",
|
||||
"Mirrored controls") and MORE ("Graphics", "Refresh rate", "Resolution",
|
||||
the controller buttons page, Quit). The refresh rate steps through what
|
||||
the controller buttons page, Quit); four since the second part (below). The refresh rate steps through what
|
||||
the runtime offers and changes at once; on the Steam Frame the row shows
|
||||
SteamOS's rate. The resolution (`vr.resolution_scale`, 70-120%) takes a
|
||||
restart. The controller buttons page shows the layout as set.
|
||||
@@ -136,6 +136,100 @@ To try in the headset (Quest 3 and Steam Frame):
|
||||
in a bot game; Max on the Quest at 90 Hz; refresh rates 72/80/90/120
|
||||
on the Quest; the Frame's row.
|
||||
|
||||
## Step 2, second part (built)
|
||||
|
||||
On branch `feature/vr-comfort`, not yet tried in the headset. The VR
|
||||
options (Y) have four pages: PLAY ("Weapon hand", "Mirrored controls",
|
||||
laser, crosshair, motion tracker, body, fingers, the Warthog's wheel),
|
||||
COMFORT (turning, the vignettes), BUTTONS (the actions' buttons, the
|
||||
flashlight's tap, "Reset buttons to defaults", the controller buttons
|
||||
page) and MORE (graphics, refresh rate, resolution, Quit).
|
||||
|
||||
Buttons remapped (BUTTONS page; `vr.c` `controls_remapped`):
|
||||
- Jump, the flashlight (held: switch grenades), action/reload, switch
|
||||
weapon, crouch, zoom and melee each go on one of seven buttons: A, B,
|
||||
X, Y, the move stick's click, the turning stick's, the weapon hand's
|
||||
grip. Moving an action to a button swaps it with the action there, so
|
||||
none is ever left without one.
|
||||
- The triggers, the free hand's grip, the menu button, the Steam Frame's
|
||||
bumpers, D-pad and View button keep theirs; the menus keep the buttons
|
||||
as they are.
|
||||
- Applied after the left-handed mirroring, on the gamepad's sides: the
|
||||
same on the Touch and the Frame controllers, and a left-handed player's
|
||||
buttons are the mirror image of the right-handed ones (on the Frame,
|
||||
mirrored, the left D-pad's). The defaults are the old layout, the
|
||||
host's bindings and the ABI unchanged.
|
||||
- The melee's aim and jab follow its button; the grips on a Warthog's
|
||||
wheel press nothing, whatever the grip does.
|
||||
- The controller buttons page shows each action where its button is.
|
||||
|
||||
Flashlight by tapping the head (`vr.c` `flashlight_gesture_update`,
|
||||
after HaloCE-Quest-VR, CC0): either hand to the side or the top of the
|
||||
head and away, as a tap, toggles it; the button still does. A zone in
|
||||
the head's axes beside or over the head, never more than 6 cm in front
|
||||
of the eyes (a scope at the eye, a two-handed weapon, a punch and the
|
||||
wrist's tracker are in front of the face); the hand comes from 35 cm
|
||||
away, slower than 3 m/s, stays 40 to 600 ms, alone, and leaves; a second
|
||||
between toggles. None in the menus, with a grenade held or just thrown,
|
||||
just after a melee, with both hands on the weapon, the weapon hand while
|
||||
the scope is drawn, a hand on the wheel. A short rumble in the tapping
|
||||
hand. Its logic was run in a harness off the headset; the feel is the
|
||||
headset's to judge.
|
||||
|
||||
Comfort (COMFORT page): snap turns 10 to 45 degrees by 5, 60, 75, 90;
|
||||
smooth turning 30 to 150 degrees a second by 15, then to 300 by 30; the
|
||||
vehicle vignette Off, 15 to 100%; the on-foot vignette (off by default)
|
||||
while the stick turns smoothly, or also while the move stick moves, as
|
||||
far as the sticks are pushed, with its own strength. The old values are
|
||||
among the steps; defaults unchanged.
|
||||
|
||||
Transparent geometry: room for 2048 groups a window (the Xbox's 384,
|
||||
below).
|
||||
|
||||
| Setting | Values |
|
||||
| --- | --- |
|
||||
| `vr.button_jump` | `"a"` (default), `"b"`, `"x"`, `"y"`, `"move_stick"`, `"turn_stick"`, `"grip"`: as right-handed, mirrored with `vr.mirror_controls` |
|
||||
| `vr.button_light` | the flashlight, held switch grenades; `"b"` (default) |
|
||||
| `vr.button_action` | action, reload; `"x"` (default) |
|
||||
| `vr.button_weapon` | switch weapon; `"y"` (default) |
|
||||
| `vr.button_crouch` | `"move_stick"` (default) |
|
||||
| `vr.button_zoom` | `"turn_stick"` (default) |
|
||||
| `vr.button_melee` | `"grip"` (default) |
|
||||
| `vr.flashlight_gesture` | `true` (default): a tap of the head toggles the flashlight |
|
||||
| `vr.foot_vignette` | `"off"` (default), `"turning"` (smooth turns), `"moving"` (and moving) |
|
||||
| `vr.foot_vignette_strength` | 0.15 to 1, `0.7` (default) |
|
||||
| `debug.vr_options` | `false` (default); `true` shows the VR options off the headset (the emulator) |
|
||||
|
||||
Checked in the emulator (`debug.vr_options`): the four pages without
|
||||
overlaps, each row's values, swaps and reset, the controller buttons page
|
||||
right- and left-handed after swaps, the settings kept over a restart, a
|
||||
15-bot game as before.
|
||||
|
||||
To try in the headset (Quest 3 and Steam Frame):
|
||||
1. Defaults: every button as before (jump, light/held grenades, action,
|
||||
switch weapon, crouch, zoom, melee by grip and by swing), right- and
|
||||
left-handed, mirrored and not; the menus' A and B.
|
||||
2. BUTTONS: swap jump and melee (jump on the grip, melee on A): both work,
|
||||
the melee jabs and aims where the head looks; light on a stick click
|
||||
(tap: light, hold: grenades); the controller buttons page says so.
|
||||
At the Warthog's wheel with jump on the grip: no jump while holding
|
||||
the wheel. Reset: all back.
|
||||
3. The same left-handed with mirrored controls (on the Frame the left
|
||||
D-pad), and with `Mirrored controls: Off`.
|
||||
4. Flashlight tap with either hand, beside the head and over it; the
|
||||
rumble; the flashlight button still works. No toggle while: aiming
|
||||
through the sniper's and the pistol's scope, holding the weapon with
|
||||
both hands, holding and throwing a grenade (overhand past the ear),
|
||||
punching and swinging, putting on or adjusting the headset with both
|
||||
hands or one, looking at the wrist's tracker, at the wheel.
|
||||
5. COMFORT: snap 10 and 90, smooth 30 and 300; vehicle vignette 15% and
|
||||
100%; on-foot vignette "Smooth turns" (nothing with snap turns),
|
||||
"Moving, turning", strength 15% and 100%; no vignette in a vehicle
|
||||
from the on-foot one, none in the menus.
|
||||
6. A game of 30 and more players: effects, glass and water stay; the log
|
||||
(`adb logcat -s halo`) says `rasterizer: N transparent geometry groups
|
||||
in a window` once a window passes 384; frame time as before.
|
||||
|
||||
## Step 3a (done)
|
||||
|
||||
Tried on the Quest 3 and the Steam Frame, in `main`. The arm IK,
|
||||
@@ -194,10 +288,11 @@ the left hand animated through reloads.
|
||||
- Multiview on the Steam Frame: why the eyes do not fuse there (suspected
|
||||
Mesa zink/Turnip); tools in branch `frame/doubled-images` (86335828),
|
||||
not merged.
|
||||
- Transparent geometry groups: the Xbox's 384 a window overflow in games
|
||||
of 30 and more players.
|
||||
- The VR on-screen keyboard shows a password in the clear while it is
|
||||
typed.
|
||||
- Transparent geometry groups: the Xbox's 384 a window overflowed in
|
||||
games of 30 and more players (the last submitted, glass, water,
|
||||
particles, contrails, vanished). Raised to 2048 (320 KB) on
|
||||
`feature/vr-comfort`, to check in a large game (step 2, second part,
|
||||
test 6); upstream still has 384.
|
||||
|
||||
## Headset tests (2026-10-06, all three in `main`)
|
||||
|
||||
|
||||
@@ -162,6 +162,9 @@ enum
|
||||
int halo_vr_body_mode(void);
|
||||
/* a hand has just been thrust forward: a melee attack (xinput_sdl.c) */
|
||||
int halo_vr_melee(void);
|
||||
/* a hand has just tapped the head (vr.flashlight_gesture): the flashlight's
|
||||
button, for a moment (xinput_sdl.c) */
|
||||
int halo_vr_flashlight_tap(void);
|
||||
/* the weight of the melee attack under way, from the swing's speed (0..1;
|
||||
0 with none): the game scales melee damage by the player's run instead,
|
||||
and in VR a player punches standing (units.c) */
|
||||
@@ -252,6 +255,39 @@ int halo_vr_controller_layout(void);
|
||||
/* the hand that holds the weapon (HALO_XR_HAND_*: 1 the right, 0 the left,
|
||||
vr.handedness) */
|
||||
int halo_vr_weapon_hand(void);
|
||||
/* The game's actions on the controllers' buttons (vr.button_*; the VR
|
||||
options' BUTTONS page): each action on one of seven buttons, named as
|
||||
right-handed (A and B on the right controller, X and Y, the Quest's, on
|
||||
the left; the move stick's click, the turning stick's, the weapon hand's
|
||||
grip); left-handed with vr.mirror_controls, their mirror images. The
|
||||
actions are numbered by the button each has by default. The triggers, the
|
||||
free hand's grip, the menu button and the Steam Frame's bumpers, D-pad and
|
||||
View button keep theirs; the menus keep the buttons as they are. */
|
||||
enum
|
||||
{
|
||||
HALO_VR_INPUT_A = 0,
|
||||
HALO_VR_INPUT_B,
|
||||
HALO_VR_INPUT_X,
|
||||
HALO_VR_INPUT_Y,
|
||||
HALO_VR_INPUT_MOVE_STICK,
|
||||
HALO_VR_INPUT_TURN_STICK,
|
||||
HALO_VR_INPUT_GRIP,
|
||||
HALO_VR_INPUT_COUNT,
|
||||
|
||||
HALO_VR_ACTION_JUMP = HALO_VR_INPUT_A,
|
||||
HALO_VR_ACTION_LIGHT = HALO_VR_INPUT_B, /* a tap the flashlight; held, switch grenades */
|
||||
HALO_VR_ACTION_ACTION = HALO_VR_INPUT_X, /* action, reload */
|
||||
HALO_VR_ACTION_WEAPON = HALO_VR_INPUT_Y, /* switch weapon */
|
||||
HALO_VR_ACTION_CROUCH = HALO_VR_INPUT_MOVE_STICK,
|
||||
HALO_VR_ACTION_ZOOM = HALO_VR_INPUT_TURN_STICK,
|
||||
HALO_VR_ACTION_MELEE = HALO_VR_INPUT_GRIP,
|
||||
HALO_VR_ACTION_COUNT = HALO_VR_INPUT_COUNT,
|
||||
};
|
||||
/* an action's setting ("vr.button_jump"), a button's value in it ("a"),
|
||||
and the button an action is on, as set */
|
||||
const char *halo_vr_action_setting(int action);
|
||||
const char *halo_vr_input_value(int input);
|
||||
int halo_vr_action_input(int action);
|
||||
/* the graphics preset (vr.graphics; HALO_VR_GRAPHICS_HIGH outside VR): which
|
||||
effects are drawn (port/linux/game/vr_graphics.c), and with "max" the
|
||||
models lit for each pixel and larger shadows (d3d8_gl.c) */
|
||||
|
||||
@@ -201,6 +201,28 @@ static const struct config_setting config_settings[] =
|
||||
"and the left one turns, X jumps and A reloads (on the Steam Frame the\n"
|
||||
"D-pad takes A, B, X and Y as their mirror image); false keeps them as\n"
|
||||
"right-handed. The menus keep their buttons either way." },
|
||||
{ "vr.button_jump", _config_string, "\"a\"", "HALO_VR_BUTTON_JUMP", _environment_value, _platform_android,
|
||||
"The button each of the game's actions is on (the VR options' BUTTONS\n"
|
||||
"page swaps them): \"a\", \"b\", \"x\", \"y\" (A and B on the right\n"
|
||||
"controller, X and Y the Quest's on the left; the Steam Frame has all\n"
|
||||
"four on the right), \"move_stick\" and \"turn_stick\" (their clicks),\n"
|
||||
"\"grip\" (the weapon hand's), named as right-handed: left-handed with\n"
|
||||
"mirror_controls, their mirror images. Jump," },
|
||||
{ "vr.button_light", _config_string, "\"b\"", "HALO_VR_BUTTON_LIGHT", _environment_value, _platform_android,
|
||||
"the flashlight (held: switch grenades)," },
|
||||
{ "vr.button_action", _config_string, "\"x\"", "HALO_VR_BUTTON_ACTION", _environment_value, _platform_android,
|
||||
"action and reload," },
|
||||
{ "vr.button_weapon", _config_string, "\"y\"", "HALO_VR_BUTTON_WEAPON", _environment_value, _platform_android,
|
||||
"switch weapon," },
|
||||
{ "vr.button_crouch", _config_string, "\"move_stick\"", "HALO_VR_BUTTON_CROUCH", _environment_value,
|
||||
_platform_android,
|
||||
"crouch," },
|
||||
{ "vr.button_zoom", _config_string, "\"turn_stick\"", "HALO_VR_BUTTON_ZOOM", _environment_value,
|
||||
_platform_android,
|
||||
"zoom" },
|
||||
{ "vr.button_melee", _config_string, "\"grip\"", "HALO_VR_BUTTON_MELEE", _environment_value, _platform_android,
|
||||
"and melee. The triggers, the free hand's grip and the menu button keep\n"
|
||||
"theirs, as do the menus." },
|
||||
{ "vr.laser", _config_boolean, "false", "HALO_VR_LASER", _environment_value, _platform_android,
|
||||
"A laser from the weapon to what it aims at (with aim_with = \"controller\")." },
|
||||
{ "vr.crosshair", _config_boolean, "true", "HALO_VR_CROSSHAIR", _environment_value, _platform_android,
|
||||
@@ -229,6 +251,13 @@ static const struct config_setting config_settings[] =
|
||||
{ "vr.arm_ik", _config_boolean, "true", "HALO_VR_ARM_IK", _environment_value, _platform_android,
|
||||
"The free hand's arm bends at the elbow to reach it from the shoulder;\n"
|
||||
"false keeps the arm's shape as on the weapon, pointed at the shoulder." },
|
||||
{ "vr.flashlight_gesture", _config_boolean, "true", "HALO_VR_FLASHLIGHT_GESTURE", _environment_value,
|
||||
_platform_android,
|
||||
"Tapping the side or the top of your head with either hand (to it and\n"
|
||||
"away again) turns the flashlight on or off; the flashlight's button\n"
|
||||
"still does. Not while aiming through a scope, holding the weapon with\n"
|
||||
"both hands, holding or throwing a grenade, just after a melee, or with\n"
|
||||
"both hands at the head." },
|
||||
{ "vr.melee_swing_speed", _config_real, "2.0", "HALO_VR_MELEE_SWING", _environment_value, _platform_android,
|
||||
"Thrusting a hand forward faster than this, in metres per second, is a\n"
|
||||
"melee attack (the weapon hand's grip is too); 0 turns it off." },
|
||||
@@ -304,6 +333,13 @@ static const struct config_setting config_settings[] =
|
||||
{ "vr.comfort_vignette", _config_real, "0.7", "HALO_VR_COMFORT_VIGNETTE", _environment_value, _platform_android,
|
||||
"How far the view darkens from its edges while a vehicle turns you\n"
|
||||
"(0 never, 1 to a small window)." },
|
||||
{ "vr.foot_vignette", _config_string, "\"off\"", "HALO_VR_FOOT_VIGNETTE", _environment_value, _platform_android,
|
||||
"On foot, the view darkens from its edges too: \"turning\" while the stick\n"
|
||||
"turns you smoothly (smooth_turn), \"moving\" while a stick turns or moves\n"
|
||||
"you, as far as it is pushed; \"off\" never." },
|
||||
{ "vr.foot_vignette_strength", _config_real, "0.7", "HALO_VR_FOOT_VIGNETTE_STRENGTH", _environment_value,
|
||||
_platform_android,
|
||||
"How far it darkens then (as comfort_vignette)." },
|
||||
{ "vr.motion_tracker_on_wrist", _config_boolean, "true", "HALO_VR_MOTION_TRACKER_WRIST", _environment_value,
|
||||
_platform_android,
|
||||
"Show the motion tracker on the back of the left wrist, like a watch (turn\n"
|
||||
@@ -324,9 +360,11 @@ static const struct config_setting config_settings[] =
|
||||
{ "vr.smooth_turn", _config_boolean, "false", "HALO_VR_SMOOTH_TURN", _environment_value, _platform_android,
|
||||
"The right stick turns smoothly; false turns in steps (snap_turn_degrees)." },
|
||||
{ "vr.snap_turn_degrees", _config_real, "30.0", "HALO_VR_SNAP_TURN", _environment_value, _platform_android,
|
||||
"How far a flick of the right stick turns." },
|
||||
"How far a flick of the right stick turns, in degrees (the VR options step\n"
|
||||
"through 10 to 45 by 5, 60, 75 and 90)." },
|
||||
{ "vr.smooth_turn_speed", _config_real, "120.0", "HALO_VR_SMOOTH_TURN_SPEED", _environment_value, _platform_android,
|
||||
"Degrees per second the right stick turns at, fully pushed, with smooth_turn." },
|
||||
"Degrees per second the right stick turns at, fully pushed, with smooth_turn\n"
|
||||
"(the VR options step through 30 to 150 by 15, then to 300 by 30)." },
|
||||
{ "vr.cinematics_in_3d", _config_boolean, "false", "HALO_VR_CINEMATICS_3D", _environment_value, _platform_android,
|
||||
"Show cinematics around you, from the cinematic camera; false shows them\n"
|
||||
"on the screen in front of you (easier on the stomach)." },
|
||||
@@ -573,6 +611,9 @@ static const struct config_setting config_settings[] =
|
||||
"The headset's layer copies: 1 deferred (no waits for the GL thread or the\n"
|
||||
"GPU in the middle of the frame), 0 each one restored and released at once,\n"
|
||||
"-1 as the runtime needs (deferred on SteamVR). Read when the app starts." },
|
||||
{ "debug.vr_options", _config_boolean, "false", "HALO_DEBUG_VR_OPTIONS", _environment_value, _platform_android,
|
||||
"Off the headset (the emulator), show the VR options panel on the main\n"
|
||||
"and pause menus all the same, for checking its pages." },
|
||||
{ "debug.mirror_first_person", _config_boolean, "false", "HALO_MIRROR_FIRST_PERSON", _environment_value,
|
||||
_platform_android,
|
||||
"Off the headset (flat), the first-person weapon drawn mirrored, as the\n"
|
||||
|
||||
+334
-21
@@ -17,6 +17,28 @@ yaw plus the head's.
|
||||
|
||||
#include "halo_vr.h"
|
||||
|
||||
/* the actions' settings and the buttons' values in them (halo_vr.h's
|
||||
HALO_VR_ACTION_* and HALO_VR_INPUT_*), by number */
|
||||
static const char *const vr_action_settings[HALO_VR_ACTION_COUNT] =
|
||||
{
|
||||
"vr.button_jump", "vr.button_light", "vr.button_action", "vr.button_weapon", "vr.button_crouch",
|
||||
"vr.button_zoom", "vr.button_melee",
|
||||
};
|
||||
static const char *const vr_input_values[HALO_VR_INPUT_COUNT] =
|
||||
{
|
||||
"a", "b", "x", "y", "move_stick", "turn_stick", "grip",
|
||||
};
|
||||
|
||||
const char *halo_vr_action_setting(int action)
|
||||
{
|
||||
return action >= 0 && action < HALO_VR_ACTION_COUNT ? vr_action_settings[action] : "";
|
||||
}
|
||||
|
||||
const char *halo_vr_input_value(int input)
|
||||
{
|
||||
return input >= 0 && input < HALO_VR_INPUT_COUNT ? vr_input_values[input] : "";
|
||||
}
|
||||
|
||||
#ifdef HALO_ANDROID
|
||||
|
||||
#include "platform.h"
|
||||
@@ -36,6 +58,14 @@ yaw plus the head's.
|
||||
/* the facing the game changes itself by more than this (a respawn, a
|
||||
teleport, a vehicle's seat) turns the body with it */
|
||||
#define FACING_JUMP (10.0f * PI / 180.0f)
|
||||
/* vr.foot_vignette: none on foot, while the stick turns smoothly, and
|
||||
while a stick turns smoothly or moves */
|
||||
enum
|
||||
{
|
||||
FOOT_VIGNETTE_OFF = 0,
|
||||
FOOT_VIGNETTE_TURNING,
|
||||
FOOT_VIGNETTE_MOVING,
|
||||
};
|
||||
|
||||
static struct
|
||||
{
|
||||
@@ -133,9 +163,13 @@ static struct
|
||||
float vehicle_steer_smoothing; /* seconds */
|
||||
float steer[2]; /* the steering as smoothed: aside, up (-1..1) */
|
||||
unsigned long long steer_last_us;
|
||||
/* the comfort vignette: how strong at most, now, and the heading it
|
||||
last saw */
|
||||
/* the comfort vignette: how strong at most in a vehicle, on foot
|
||||
(vr.foot_vignette: FOOT_VIGNETTE_*) and how strong there, now, and the
|
||||
heading it last saw */
|
||||
float comfort_vignette;
|
||||
int foot_vignette;
|
||||
float foot_vignette_strength;
|
||||
int seated; /* in a vehicle's seat, whatever the view */
|
||||
float vignette;
|
||||
float vignette_last_yaw;
|
||||
int vignette_yaw_valid;
|
||||
@@ -178,6 +212,7 @@ static struct
|
||||
captured, and where its disc is in LOCAL space */
|
||||
int scope_pass;
|
||||
int scope_captured;
|
||||
int scope_last_frame; /* the scope was drawn the frame before */
|
||||
struct halo_xr_pose scope_pose;
|
||||
int motion_tracker_on_wrist;
|
||||
float motion_tracker_size;
|
||||
@@ -220,9 +255,23 @@ static struct
|
||||
/* until when a melee attack aims where the head looks: its damage is
|
||||
dealt some ticks into the attack, along the unit's aim */
|
||||
unsigned long long melee_aim_until_us;
|
||||
int melee_grip_down;
|
||||
int melee_button_down;
|
||||
float melee_strength; /* 0..1, the last attack's swing */
|
||||
unsigned long long melee_jab_start_us; /* the weapon hand's grip's attack: the weapon jabs */
|
||||
/* the flashlight by tapping the head (flashlight_gesture_update,
|
||||
vr.flashlight_gesture): each hand where it was (the head's axes) and
|
||||
whether it has been away from the head since its last tap; the hand at
|
||||
the head now and since when (-1: none); when the next toggle may come,
|
||||
and until when the game sees the flashlight's button */
|
||||
int flashlight_gesture;
|
||||
float tap_last[HALO_XR_HAND_COUNT][3];
|
||||
int tap_last_valid[HALO_XR_HAND_COUNT];
|
||||
int tap_armed[HALO_XR_HAND_COUNT];
|
||||
int tap_hand;
|
||||
unsigned long long tap_entered_us;
|
||||
unsigned long long tap_last_us;
|
||||
unsigned long long tap_ready_us;
|
||||
unsigned long long flashlight_until_us;
|
||||
unsigned long long melee_jab_start_us; /* the melee button's attack: the weapon jabs */
|
||||
/* the laser along the barrel, for the frame it was set in */
|
||||
unsigned long frame_number;
|
||||
unsigned long laser_frame;
|
||||
@@ -250,6 +299,9 @@ static struct
|
||||
vr.mirror_controls the sticks and face buttons mirrored too */
|
||||
int left_handed;
|
||||
int mirror_controls;
|
||||
/* the button each action is on (vr.button_*: HALO_VR_INPUT_* by
|
||||
HALO_VR_ACTION_*) */
|
||||
int action_inputs[HALO_VR_ACTION_COUNT];
|
||||
/* vr.refresh_rate as last asked for (the VR options change it), and
|
||||
vr.resolution_scale as the app started with it */
|
||||
float refresh_rate_wanted;
|
||||
@@ -307,6 +359,7 @@ static int name_pose(const float point[3], struct halo_xr_pose *pose, float *wid
|
||||
static int weapon_hand_tracked(short local_player_index);
|
||||
static void controller_axes(float forward[3], float up[3], float right[3]);
|
||||
static void hand_offset(float out[3]);
|
||||
static void controls_in_play(struct halo_xr_hand hands[HALO_XR_HAND_COUNT]);
|
||||
|
||||
/* the hand that holds the weapon, the free one (the grenade, the
|
||||
foregrip), and the one whose stick turns the body and steers */
|
||||
@@ -494,6 +547,14 @@ static void vr_read_live_settings(void)
|
||||
vr.laser = config_boolean("vr.laser");
|
||||
vr.vehicle_wheel = config_boolean("vr.vehicle_wheel");
|
||||
vr.comfort_vignette = (float)config_real("vr.comfort_vignette");
|
||||
{
|
||||
const char *foot = config_string("vr.foot_vignette");
|
||||
|
||||
vr.foot_vignette = !strcmp(foot, "moving") ? FOOT_VIGNETTE_MOVING :
|
||||
!strcmp(foot, "turning") ? FOOT_VIGNETTE_TURNING : FOOT_VIGNETTE_OFF;
|
||||
}
|
||||
vr.foot_vignette_strength = (float)config_real("vr.foot_vignette_strength");
|
||||
vr.flashlight_gesture = config_boolean("vr.flashlight_gesture");
|
||||
vr.fingers = config_boolean("vr.fingers");
|
||||
vr.arm_ik = config_boolean("vr.arm_ik");
|
||||
{
|
||||
@@ -517,6 +578,12 @@ static void vr_read_live_settings(void)
|
||||
vr.left_handed = left_handed;
|
||||
vr.mirror_controls = config_boolean("vr.mirror_controls");
|
||||
}
|
||||
{
|
||||
int action;
|
||||
|
||||
for (action = 0; action < HALO_VR_ACTION_COUNT; action++)
|
||||
vr.action_inputs[action] = halo_vr_action_input(action);
|
||||
}
|
||||
{
|
||||
/* (the refresh rate changes at once where the runtime lets it) */
|
||||
float refresh_rate = (float)config_real("vr.refresh_rate");
|
||||
@@ -535,6 +602,7 @@ void halo_vr_initialize(void)
|
||||
if (vr.active || !getenv("HALO_VR"))
|
||||
return;
|
||||
vr_read_live_settings();
|
||||
vr.tap_hand = -1;
|
||||
vr.cinematics_3d = config_boolean("vr.cinematics_in_3d");
|
||||
vr.hud_distance = (float)config_real("vr.hud_distance");
|
||||
vr.hud_width = 2.0f * vr.hud_distance * tanf((float)config_real("vr.hud_field_of_view") * PI / 360.0f);
|
||||
@@ -619,6 +687,22 @@ int halo_vr_weapon_hand(void)
|
||||
return weapon_hand();
|
||||
}
|
||||
|
||||
int halo_vr_action_input(int action)
|
||||
{
|
||||
const char *value;
|
||||
int input;
|
||||
|
||||
if (action < 0 || action >= HALO_VR_ACTION_COUNT)
|
||||
return HALO_VR_INPUT_A;
|
||||
value = config_string(vr_action_settings[action]);
|
||||
for (input = 0; input < HALO_VR_INPUT_COUNT; input++)
|
||||
{
|
||||
if (!strcmp(value, vr_input_values[input]))
|
||||
return input;
|
||||
}
|
||||
return action;
|
||||
}
|
||||
|
||||
int halo_vr_refresh_rates(float *rates, int maximum, float *current)
|
||||
{
|
||||
*current = 0.0f;
|
||||
@@ -980,18 +1064,21 @@ static void melee_update(void)
|
||||
|
||||
vr.hand_last_us = now;
|
||||
{
|
||||
/* the weapon hand's grip's melee attack (xinput_sdl.c) aims the
|
||||
same way */
|
||||
int grip_down = vr.frame.hands[weapon_hand()].active &&
|
||||
(vr.frame.hands[weapon_hand()].buttons & HALO_XR_BUTTON_SQUEEZE);
|
||||
/* the melee button's attack (xinput_sdl.c; the weapon hand's grip
|
||||
unless vr.button_melee moves it) aims the same way */
|
||||
struct halo_xr_hand hands[HALO_XR_HAND_COUNT];
|
||||
int button_down;
|
||||
|
||||
if (grip_down && !vr.melee_grip_down)
|
||||
memcpy(hands, vr.frame.hands, sizeof(hands));
|
||||
controls_in_play(hands);
|
||||
button_down = (hands[HALO_XR_HAND_RIGHT].buttons & HALO_XR_BUTTON_SQUEEZE) != 0;
|
||||
if (button_down && !vr.melee_button_down)
|
||||
{
|
||||
vr.melee_aim_until_us = now + 700000;
|
||||
vr.melee_strength = 0.75f;
|
||||
vr.melee_jab_start_us = now;
|
||||
}
|
||||
vr.melee_grip_down = grip_down;
|
||||
vr.melee_button_down = button_down;
|
||||
}
|
||||
quaternion_rotate(vr.frame.head.orientation, look, facing);
|
||||
facing[1] = 0.0f;
|
||||
@@ -1038,6 +1125,148 @@ static void melee_update(void)
|
||||
}
|
||||
}
|
||||
|
||||
/* The flashlight by tapping the head (vr.flashlight_gesture; after
|
||||
HaloCE-Quest-VR, CC0, whose off hand brought near the head's middle
|
||||
toggles it): either hand brought to the side or the top of the head and
|
||||
away again, as a tap, toggles the flashlight; its button still does.
|
||||
|
||||
The zone is in the head's axes (metres from between the eyes; x right,
|
||||
y up, z back): beside the head, from 7 to 24 cm out, 10 cm below the eyes
|
||||
to 18 cm above them; or over it, within 12 cm of its middle line, 8 to
|
||||
30 cm up; either way no further forward than 6 cm before the eyes, so a
|
||||
scope held to the eye, a two-handed weapon and a punch, all in front of
|
||||
the face, are not in it. A tap is a hand coming from 35 cm or more from
|
||||
the head's middle into the zone, slower than 3 m/s (a grenade's throw
|
||||
past the ear is faster), staying 40 to 600 ms (adjusting the headset
|
||||
takes longer) alone (both hands at the head adjust it), and leaving it 4
|
||||
cm past its edges; toggles are a second apart. No taps while the menus
|
||||
are up, while a grenade is held or just thrown, after a melee, with both
|
||||
hands on the weapon, with the weapon hand at the scope, or with a hand on
|
||||
a Warthog's wheel. */
|
||||
#define TAP_SPEED 3.0f
|
||||
#define TAP_AWAY 0.35f
|
||||
#define TAP_MARGIN 0.04f
|
||||
#define TAP_DWELL_SHORTEST 40000ULL
|
||||
#define TAP_DWELL_LONGEST 600000ULL
|
||||
#define TAP_COOLDOWN 1000000ULL
|
||||
|
||||
static int tap_zone(const float local[3], float margin)
|
||||
{
|
||||
float x = fabsf(local[0]), y = local[1], z = local[2];
|
||||
|
||||
if (z < -0.06f - margin || z > 0.18f + margin)
|
||||
return 0;
|
||||
if (x >= 0.07f - margin && x <= 0.24f + margin && y >= -0.10f - margin && y <= 0.18f + margin)
|
||||
return 1;
|
||||
return x <= 0.12f + margin && y >= 0.08f - margin && y <= 0.30f + margin;
|
||||
}
|
||||
|
||||
static void flashlight_gesture_update(void)
|
||||
{
|
||||
unsigned long long now = now_us();
|
||||
float seconds = vr.tap_last_us ? (float)(now - vr.tap_last_us) * 1e-6f : 0.0f;
|
||||
float inverse[4];
|
||||
int blocked, hand;
|
||||
|
||||
vr.tap_last_us = now;
|
||||
inverse[0] = -vr.frame.head.orientation[0];
|
||||
inverse[1] = -vr.frame.head.orientation[1];
|
||||
inverse[2] = -vr.frame.head.orientation[2];
|
||||
inverse[3] = vr.frame.head.orientation[3];
|
||||
blocked = !vr.flashlight_gesture || !vr.frame.focused || vr.last_overlay_mode == HALO_XR_OVERLAY_SCREEN ||
|
||||
vr.recentre_frames > 0 || vr.grenade_held || now - vr.grenade_released_us < 600000 ||
|
||||
now < vr.melee_ready_us || vr.two_hand_latched;
|
||||
for (hand = 0; hand < HALO_XR_HAND_COUNT; hand++)
|
||||
{
|
||||
const struct halo_xr_hand *state = &vr.frame.hands[hand];
|
||||
float relative[3], local[3], away[3], speed = 0.0f;
|
||||
int axis, inside, outside;
|
||||
|
||||
if (!state->active || !(state->flags & HALO_XR_POSE_VALID))
|
||||
{
|
||||
vr.tap_last_valid[hand] = 0;
|
||||
vr.tap_armed[hand] = 0;
|
||||
if (vr.tap_hand == hand)
|
||||
vr.tap_hand = -1;
|
||||
continue;
|
||||
}
|
||||
for (axis = 0; axis < 3; axis++)
|
||||
relative[axis] = state->grip.position[axis] - vr.frame.head.position[axis];
|
||||
quaternion_rotate(inverse, relative, local);
|
||||
if (vr.tap_last_valid[hand] && seconds > 0.0f && seconds < 0.1f)
|
||||
{
|
||||
float moved[3];
|
||||
|
||||
for (axis = 0; axis < 3; axis++)
|
||||
moved[axis] = local[axis] - vr.tap_last[hand][axis];
|
||||
speed = sqrtf(moved[0] * moved[0] + moved[1] * moved[1] + moved[2] * moved[2]) / seconds;
|
||||
}
|
||||
memcpy(vr.tap_last[hand], local, sizeof(vr.tap_last[hand]));
|
||||
vr.tap_last_valid[hand] = 1;
|
||||
away[0] = local[0];
|
||||
away[1] = local[1];
|
||||
away[2] = local[2] - 0.10f;
|
||||
if (sqrtf(away[0] * away[0] + away[1] * away[1] + away[2] * away[2]) > TAP_AWAY)
|
||||
vr.tap_armed[hand] = 1;
|
||||
inside = tap_zone(local, 0.0f);
|
||||
outside = !tap_zone(local, TAP_MARGIN);
|
||||
if (blocked || (vr.wheel_hands & (1 << hand)) || (hand == weapon_hand() && vr.scope_last_frame))
|
||||
{
|
||||
/* (a hand that may be at the head for another reason taps
|
||||
only once it has been away again) */
|
||||
if (inside)
|
||||
vr.tap_armed[hand] = 0;
|
||||
if (vr.tap_hand == hand)
|
||||
vr.tap_hand = -1;
|
||||
continue;
|
||||
}
|
||||
if (vr.tap_hand == hand)
|
||||
{
|
||||
unsigned long long dwell = now - vr.tap_entered_us;
|
||||
|
||||
if (dwell > TAP_DWELL_LONGEST)
|
||||
{
|
||||
vr.tap_hand = -1;
|
||||
}
|
||||
else if (outside)
|
||||
{
|
||||
vr.tap_hand = -1;
|
||||
if (dwell >= TAP_DWELL_SHORTEST && now >= vr.tap_ready_us)
|
||||
{
|
||||
vr.flashlight_until_us = now + 100000;
|
||||
vr.tap_ready_us = now + TAP_COOLDOWN;
|
||||
host_xr_haptic(hand, 0.5f, 0.05f);
|
||||
platform_log("VR: flashlight, %s hand at the head for %llu ms", hand ? "right" : "left",
|
||||
dwell / 1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (inside && vr.tap_armed[hand])
|
||||
{
|
||||
vr.tap_armed[hand] = 0;
|
||||
if (vr.tap_hand >= 0)
|
||||
{
|
||||
/* (both hands at the head: the headset adjusted) */
|
||||
vr.tap_hand = -1;
|
||||
}
|
||||
else if (speed <= TAP_SPEED)
|
||||
{
|
||||
vr.tap_hand = hand;
|
||||
vr.tap_entered_us = now;
|
||||
}
|
||||
}
|
||||
else if (inside && vr.tap_hand >= 0)
|
||||
{
|
||||
vr.tap_hand = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int halo_vr_flashlight_tap(void)
|
||||
{
|
||||
return vr.active && now_us() < vr.flashlight_until_us;
|
||||
}
|
||||
|
||||
/* The fingers, from where they rest on the controller (after
|
||||
HaloCE-Quest-VR, CC0, its vr_frame.c): the thumb curled while it touches
|
||||
the stick, a button or the rest, half curled where the controller does not
|
||||
@@ -1378,13 +1607,45 @@ int halo_vr_wheel_held(void)
|
||||
}
|
||||
|
||||
/* The comfort vignette: while a vehicle turns the player (from 15 degrees a
|
||||
second, fully at 60), the eye images darken from their edges; it comes in
|
||||
quickly and goes slowly. */
|
||||
second, fully at 60), the eye images darken from their edges; on foot
|
||||
(vr.foot_vignette), while the turning stick turns smoothly and, with
|
||||
"moving", the move stick moves, as far as they are pushed (fully at three
|
||||
quarters). It comes in quickly and goes slowly. */
|
||||
static float foot_vignette_target(void)
|
||||
{
|
||||
const struct halo_xr_hand *turn = &vr.frame.hands[turn_hand()];
|
||||
const struct halo_xr_hand *move = &vr.frame.hands[turn_hand() == HALO_XR_HAND_RIGHT ? HALO_XR_HAND_LEFT :
|
||||
HALO_XR_HAND_RIGHT];
|
||||
float push = 0.0f;
|
||||
|
||||
if (vr.foot_vignette == FOOT_VIGNETTE_OFF || vr.foot_vignette_strength <= 0.0f || vr.seated ||
|
||||
!vr.frame.focused || vr.last_overlay_mode == HALO_XR_OVERLAY_SCREEN)
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
if (vr.smooth_turn && turn->active)
|
||||
push = fabsf(turn->thumbstick[0]);
|
||||
if (vr.foot_vignette == FOOT_VIGNETTE_MOVING && move->active)
|
||||
{
|
||||
float moving = sqrtf(move->thumbstick[0] * move->thumbstick[0] + move->thumbstick[1] * move->thumbstick[1]);
|
||||
|
||||
if (moving > push)
|
||||
push = moving;
|
||||
}
|
||||
/* (beyond the sticks' dead zone, 0.15) */
|
||||
push = (push - 0.15f) / 0.6f;
|
||||
if (push < 0.0f)
|
||||
push = 0.0f;
|
||||
if (push > 1.0f)
|
||||
push = 1.0f;
|
||||
return push * (vr.foot_vignette_strength > 1.0f ? 1.0f : vr.foot_vignette_strength);
|
||||
}
|
||||
|
||||
static void vignette_update(void)
|
||||
{
|
||||
unsigned long long now = now_us();
|
||||
float seconds = vr.vignette_last_us ? (float)(now - vr.vignette_last_us) * 1e-6f : 0.0f;
|
||||
float target = 0.0f, rate;
|
||||
float target = foot_vignette_target(), rate;
|
||||
|
||||
vr.vignette_last_us = now;
|
||||
if (seconds > 0.1f)
|
||||
@@ -1396,13 +1657,15 @@ static void vignette_update(void)
|
||||
if (vr.vignette_yaw_valid && seconds > 0.0f)
|
||||
{
|
||||
float turning = fabsf(wrap_angle(yaw - vr.vignette_last_yaw)) / seconds;
|
||||
float vehicle = (turning - 15.0f * PI / 180.0f) / (45.0f * PI / 180.0f);
|
||||
|
||||
target = (turning - 15.0f * PI / 180.0f) / (45.0f * PI / 180.0f);
|
||||
if (target < 0.0f)
|
||||
target = 0.0f;
|
||||
if (target > 1.0f)
|
||||
target = 1.0f;
|
||||
target *= vr.comfort_vignette;
|
||||
if (vehicle < 0.0f)
|
||||
vehicle = 0.0f;
|
||||
if (vehicle > 1.0f)
|
||||
vehicle = 1.0f;
|
||||
vehicle *= vr.comfort_vignette;
|
||||
if (vehicle > target)
|
||||
target = vehicle;
|
||||
}
|
||||
vr.vignette_last_yaw = yaw;
|
||||
vr.vignette_yaw_valid = 1;
|
||||
@@ -1423,6 +1686,7 @@ void halo_vr_set_seat(short local_player_index, int seat, int armed, float vehic
|
||||
{
|
||||
if (!vr.active || local_player_index != 0)
|
||||
return;
|
||||
vr.seated = seat != HALO_VR_SEAT_NONE;
|
||||
if (!vr.vehicle_first_person)
|
||||
seat = HALO_VR_SEAT_NONE;
|
||||
vr.seat_yaw = vehicle_yaw;
|
||||
@@ -1581,6 +1845,7 @@ void halo_vr_frame_begin(void)
|
||||
vr.frame_begun = 1;
|
||||
vr.frame_number++;
|
||||
vr.eyes_captured = 0;
|
||||
vr.scope_last_frame = vr.scope_captured;
|
||||
vr.scope_captured = 0;
|
||||
vr.crosshair_captured = 0;
|
||||
vr.name_count = 0;
|
||||
@@ -1607,6 +1872,7 @@ void halo_vr_frame_begin(void)
|
||||
look_update();
|
||||
grenade_update();
|
||||
melee_update();
|
||||
flashlight_gesture_update();
|
||||
fingers_update();
|
||||
torso_update();
|
||||
}
|
||||
@@ -3046,6 +3312,51 @@ static void controllers_mirrored(struct halo_xr_hand hands[HALO_XR_HAND_COUNT])
|
||||
}
|
||||
}
|
||||
|
||||
/* The buttons the actions are on (vr.button_*), as the gamepad's sides
|
||||
have them once mirrored: A and B the right hand's, X and Y the left's
|
||||
A and B, the move stick's click the left's, the turning stick's the
|
||||
right's, the grip the right's (the weapon hand's). Each action's button
|
||||
is read and handed on as the button the action has by default, which
|
||||
xinput_sdl.c turns into it; with the defaults nothing changes. The grips
|
||||
holding a Warthog's wheel press nothing. */
|
||||
static const int input_hands[HALO_VR_INPUT_COUNT] =
|
||||
{
|
||||
HALO_XR_HAND_RIGHT, HALO_XR_HAND_RIGHT, HALO_XR_HAND_LEFT, HALO_XR_HAND_LEFT, HALO_XR_HAND_LEFT,
|
||||
HALO_XR_HAND_RIGHT, HALO_XR_HAND_RIGHT,
|
||||
};
|
||||
static const int input_buttons[HALO_VR_INPUT_COUNT] =
|
||||
{
|
||||
HALO_XR_BUTTON_A, HALO_XR_BUTTON_B, HALO_XR_BUTTON_A, HALO_XR_BUTTON_B, HALO_XR_BUTTON_THUMBSTICK,
|
||||
HALO_XR_BUTTON_THUMBSTICK, HALO_XR_BUTTON_SQUEEZE,
|
||||
};
|
||||
|
||||
static void controls_remapped(struct halo_xr_hand hands[HALO_XR_HAND_COUNT])
|
||||
{
|
||||
int down[HALO_VR_INPUT_COUNT];
|
||||
int input, action;
|
||||
|
||||
for (input = 0; input < HALO_VR_INPUT_COUNT; input++)
|
||||
down[input] = (hands[input_hands[input]].buttons & input_buttons[input]) != 0;
|
||||
if (vr.wheel_hands)
|
||||
down[HALO_VR_INPUT_GRIP] = 0;
|
||||
for (input = 0; input < HALO_VR_INPUT_COUNT; input++)
|
||||
hands[input_hands[input]].buttons &= ~input_buttons[input];
|
||||
for (action = 0; action < HALO_VR_ACTION_COUNT; action++)
|
||||
{
|
||||
if (down[vr.action_inputs[action]])
|
||||
hands[input_hands[action]].buttons |= input_buttons[action];
|
||||
}
|
||||
}
|
||||
|
||||
/* the controllers as the game is played with them: mirrored (left-handed)
|
||||
and the actions on their buttons */
|
||||
static void controls_in_play(struct halo_xr_hand hands[HALO_XR_HAND_COUNT])
|
||||
{
|
||||
if (vr.left_handed)
|
||||
controllers_mirrored(hands);
|
||||
controls_remapped(hands);
|
||||
}
|
||||
|
||||
/* the controllers, for the gamepad the game reads (xinput_sdl.c) */
|
||||
int halo_vr_controllers(struct halo_xr_hand hands[HALO_XR_HAND_COUNT], int *menus)
|
||||
{
|
||||
@@ -3053,8 +3364,8 @@ int halo_vr_controllers(struct halo_xr_hand hands[HALO_XR_HAND_COUNT], int *menu
|
||||
return 0;
|
||||
memcpy(hands, vr.frame.hands, sizeof(vr.frame.hands));
|
||||
*menus = vr.last_overlay_mode == HALO_XR_OVERLAY_SCREEN;
|
||||
if (vr.left_handed && !*menus)
|
||||
controllers_mirrored(hands);
|
||||
if (!*menus)
|
||||
controls_in_play(hands);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -3062,6 +3373,7 @@ int halo_vr_controllers(struct halo_xr_hand hands[HALO_XR_HAND_COUNT], int *menu
|
||||
|
||||
int halo_vr_controller_layout(void) { return 0; }
|
||||
int halo_vr_weapon_hand(void) { return 1; }
|
||||
int halo_vr_action_input(int action) { return action; }
|
||||
int halo_vr_graphics(void) { return HALO_VR_GRAPHICS_HIGH; }
|
||||
int halo_vr_refresh_rates(float *rates, int maximum, float *current)
|
||||
{
|
||||
@@ -3128,6 +3440,7 @@ void halo_vr_debug_look(short local_player_index, const float unit_looking[3], i
|
||||
(void)local_player_index; (void)unit_looking; (void)in_vehicle;
|
||||
}
|
||||
int halo_vr_melee(void) { return 0; }
|
||||
int halo_vr_flashlight_tap(void) { return 0; }
|
||||
int halo_vr_finger_curls(short local_player_index, int hand, float curls[4])
|
||||
{
|
||||
(void)local_player_index; (void)hand; (void)curls;
|
||||
|
||||
@@ -840,7 +840,9 @@ In play, laid out for VR shooters rather than by position:
|
||||
|
||||
right trigger fire left trigger grenade: held in the hand, thrown as it lets go (vr.c)
|
||||
right grip melee (B) left grip hold the weapon with both hands (vr.c)
|
||||
(a hand thrust forward, vr.melee_swing_speed, is a melee attack too)
|
||||
(a hand thrust forward, vr.melee_swing_speed, is a melee attack too;
|
||||
a hand tapped on the side or top of the head, vr.flashlight_gesture,
|
||||
the flashlight)
|
||||
A jump X action, reload (X), as the game's prompts say
|
||||
B flashlight (white); held, switch grenade (black)
|
||||
Y switch weapon (Y)
|
||||
@@ -859,6 +861,11 @@ face buttons too (the right stick moves, X jumps, A reloads; on the Steam
|
||||
Frame the left D-pad takes A, B, X and Y). Here "right" and "left" are the
|
||||
sides so handed over.
|
||||
|
||||
The VR options' BUTTONS page (vr.button_*) moves jump, the flashlight,
|
||||
action, switch weapon, crouch, zoom and melee between A, B, X, Y, the
|
||||
stick clicks and the weapon hand's grip: vr.c hands each action's button
|
||||
over as the one above, so "A" here is the jump wherever it is.
|
||||
|
||||
In the menus the buttons are the Xbox's by position: A accepts, B goes back. */
|
||||
|
||||
#include "guest_host.h"
|
||||
@@ -866,6 +873,7 @@ In the menus the buttons are the Xbox's by position: A accepts, B goes back. */
|
||||
|
||||
int halo_vr_controllers(struct halo_xr_hand hands[HALO_XR_HAND_COUNT], int *menus);
|
||||
int halo_vr_wheel_held(void);
|
||||
int halo_vr_flashlight_tap(void);
|
||||
|
||||
/* a click that stands for the pad's A (ui_widget.c: the screen where
|
||||
controllers join by pressing it), held a moment */
|
||||
@@ -937,14 +945,15 @@ static void vr_gamepad_state(XINPUT_GAMEPAD *pad)
|
||||
}
|
||||
merge_button(pad, XINPUT_GAMEPAD_A, (right->buttons & HALO_XR_BUTTON_A) != 0);
|
||||
merge_button(pad, XINPUT_GAMEPAD_X, (left->buttons & HALO_XR_BUTTON_A) != 0);
|
||||
/* (the grips holding a Warthog's wheel are not a blow) */
|
||||
merge_button(pad, XINPUT_GAMEPAD_B,
|
||||
((right->buttons & HALO_XR_BUTTON_SQUEEZE) != 0 && !halo_vr_wheel_held()) || halo_vr_melee());
|
||||
/* (the grips holding a Warthog's wheel are not a blow: vr.c) */
|
||||
merge_button(pad, XINPUT_GAMEPAD_B, (right->buttons & HALO_XR_BUTTON_SQUEEZE) != 0 || halo_vr_melee());
|
||||
merge_button(pad, XINPUT_GAMEPAD_Y, (left->buttons & HALO_XR_BUTTON_B) != 0);
|
||||
/* (the Steam Frame's bumpers: the left switches grenades, the right is
|
||||
the flashlight) */
|
||||
merge_button(pad, XINPUT_GAMEPAD_BLACK, (left->buttons & HALO_XR_BUTTON_BUMPER) != 0);
|
||||
merge_button(pad, XINPUT_GAMEPAD_WHITE, (right->buttons & HALO_XR_BUTTON_BUMPER) != 0);
|
||||
/* (and a tap of the head, vr.flashlight_gesture: vr.c) */
|
||||
merge_button(pad, XINPUT_GAMEPAD_WHITE,
|
||||
(right->buttons & HALO_XR_BUTTON_BUMPER) != 0 || halo_vr_flashlight_tap());
|
||||
{
|
||||
/* B: a tap is the flashlight, holding it switches grenades; the
|
||||
game sees a short press of either */
|
||||
|
||||
+360
-52
@@ -6648,6 +6648,7 @@ double config_real(char const *name);
|
||||
char const *config_string(char const *name);
|
||||
int config_write(char const *name, char const *value);
|
||||
int config_write_boolean(char const *name, int value);
|
||||
int config_default(char const *name, char *text, size_t size);
|
||||
|
||||
enum
|
||||
{
|
||||
@@ -6655,6 +6656,8 @@ enum
|
||||
_vr_option_snap_angle,
|
||||
_vr_option_smooth_speed,
|
||||
_vr_option_vignette,
|
||||
_vr_option_foot_vignette,
|
||||
_vr_option_foot_vignette_strength,
|
||||
_vr_option_wheel,
|
||||
_vr_option_handedness,
|
||||
_vr_option_mirror_controls,
|
||||
@@ -6663,6 +6666,11 @@ enum
|
||||
_vr_option_motion_tracker,
|
||||
_vr_option_body,
|
||||
_vr_option_fingers,
|
||||
/* (the game's actions on the buttons, HALO_VR_ACTION_*'s order) */
|
||||
_vr_option_button_first,
|
||||
_vr_option_button_last = _vr_option_button_first + HALO_VR_ACTION_COUNT - 1,
|
||||
_vr_option_flashlight_gesture,
|
||||
_vr_option_buttons_reset,
|
||||
_vr_option_graphics,
|
||||
_vr_option_refresh_rate,
|
||||
_vr_option_resolution,
|
||||
@@ -6675,7 +6683,17 @@ enum
|
||||
VR_OPTIONS_ROW_HEIGHT = 22,
|
||||
VR_OPTIONS_FOOTER = 362,
|
||||
VR_OPTIONS_PER_PAGE = 12,
|
||||
NUMBER_OF_VR_OPTION_PAGES = 2,
|
||||
|
||||
_vr_options_page_play = 0,
|
||||
_vr_options_page_comfort,
|
||||
_vr_options_page_buttons,
|
||||
_vr_options_page_more,
|
||||
NUMBER_OF_VR_OPTION_PAGES,
|
||||
|
||||
/* (the pages' tabs, beside the title, as wide as there is room) */
|
||||
VR_OPTIONS_TABS_LEFT = 216,
|
||||
VR_OPTIONS_TABS_RIGHT = 528,
|
||||
VR_OPTIONS_TAB_WIDTH = (VR_OPTIONS_TABS_RIGHT - VR_OPTIONS_TABS_LEFT) / NUMBER_OF_VR_OPTION_PAGES,
|
||||
|
||||
_vr_controls_on_foot = 0,
|
||||
_vr_controls_vehicles,
|
||||
@@ -6694,14 +6712,22 @@ static struct
|
||||
} ui_vr_options_globals;
|
||||
|
||||
/* the panel's pages (its tabs), their rows in order (NONE past the last) */
|
||||
static char const *const vr_option_page_names[NUMBER_OF_VR_OPTION_PAGES] = { "PLAY", "MORE" };
|
||||
static char const *const vr_option_page_names[NUMBER_OF_VR_OPTION_PAGES] = { "PLAY", "COMFORT", "BUTTONS", "MORE" };
|
||||
static short const vr_option_pages[NUMBER_OF_VR_OPTION_PAGES][VR_OPTIONS_PER_PAGE] =
|
||||
{
|
||||
{ _vr_option_turning, _vr_option_snap_angle, _vr_option_smooth_speed, _vr_option_vignette, _vr_option_wheel,
|
||||
_vr_option_handedness, _vr_option_mirror_controls, _vr_option_laser, _vr_option_crosshair,
|
||||
_vr_option_motion_tracker, _vr_option_body, _vr_option_fingers },
|
||||
{ _vr_option_graphics, _vr_option_refresh_rate, _vr_option_resolution, _vr_option_controls, _vr_option_quit,
|
||||
NONE, NONE, NONE, NONE, NONE, NONE, NONE },
|
||||
{ _vr_option_handedness, _vr_option_mirror_controls, _vr_option_laser, _vr_option_crosshair,
|
||||
_vr_option_motion_tracker, _vr_option_body, _vr_option_fingers, _vr_option_wheel,
|
||||
NONE, NONE, NONE, NONE },
|
||||
{ _vr_option_turning, _vr_option_snap_angle, _vr_option_smooth_speed, _vr_option_vignette,
|
||||
_vr_option_foot_vignette, _vr_option_foot_vignette_strength,
|
||||
NONE, NONE, NONE, NONE, NONE, NONE },
|
||||
{ _vr_option_button_first + HALO_VR_ACTION_JUMP, _vr_option_button_first + HALO_VR_ACTION_LIGHT,
|
||||
_vr_option_button_first + HALO_VR_ACTION_ACTION, _vr_option_button_first + HALO_VR_ACTION_WEAPON,
|
||||
_vr_option_button_first + HALO_VR_ACTION_CROUCH, _vr_option_button_first + HALO_VR_ACTION_ZOOM,
|
||||
_vr_option_button_first + HALO_VR_ACTION_MELEE, _vr_option_flashlight_gesture, _vr_option_buttons_reset,
|
||||
_vr_option_controls, NONE, NONE },
|
||||
{ _vr_option_graphics, _vr_option_refresh_rate, _vr_option_resolution, _vr_option_quit,
|
||||
NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE },
|
||||
};
|
||||
|
||||
/* the page a row is on, and its place there */
|
||||
@@ -6754,12 +6780,151 @@ static boolean ui_vr_controls_mirrored(
|
||||
return ui_vr_left_handed() && config_boolean("vr.mirror_controls");
|
||||
}
|
||||
|
||||
/* Where a button the game's actions go on (HALO_VR_INPUT_*) is, as the
|
||||
hands are set: its controller (0 the left, 1 the right) and its name,
|
||||
short under its controller on the controls page, or full in the
|
||||
options' rows. On the Quest A and B are on the right, X and Y on the
|
||||
left, and mirrored the other way round; on the Steam Frame all four are
|
||||
on the right, and mirrored the left D-pad takes them (down, left, right,
|
||||
up). The sticks' clicks change sides with them; the grip is the weapon
|
||||
hand's. */
|
||||
static char const *ui_vr_input_name(
|
||||
short input,
|
||||
boolean full,
|
||||
short *column)
|
||||
{
|
||||
static char const *const buttons[] = { "A", "B", "X", "Y" };
|
||||
static char const *const quest_mirrored[] = { "X", "Y", "A", "B" };
|
||||
static char const *const frame_mirrored[] = { "D-pad down", "D-pad left", "D-pad right", "D-pad up" };
|
||||
boolean frame = halo_vr_controller_layout() == 1;
|
||||
boolean mirrored = ui_vr_controls_mirrored();
|
||||
short side;
|
||||
char const *name;
|
||||
|
||||
switch (input)
|
||||
{
|
||||
case HALO_VR_INPUT_MOVE_STICK:
|
||||
case HALO_VR_INPUT_TURN_STICK:
|
||||
side = (short)((input == HALO_VR_INPUT_TURN_STICK) != (mirrored != 0));
|
||||
name = full ? (side ? "Right stick click" : "Left stick click") : "Stick click";
|
||||
break;
|
||||
case HALO_VR_INPUT_GRIP:
|
||||
side = (short)(ui_vr_left_handed() ? 0 : 1);
|
||||
name = full ? (side ? "Right grip" : "Left grip") : "Grip";
|
||||
break;
|
||||
default:
|
||||
input = (short)PIN(input, HALO_VR_INPUT_A, HALO_VR_INPUT_Y);
|
||||
if (frame)
|
||||
{
|
||||
side = (short)(mirrored ? 0 : 1);
|
||||
name = mirrored ? frame_mirrored[input] : buttons[input];
|
||||
}
|
||||
else
|
||||
{
|
||||
side = (short)((input <= HALO_VR_INPUT_B) != (mirrored != 0));
|
||||
name = mirrored ? quest_mirrored[input] : buttons[input];
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (column)
|
||||
*column = side;
|
||||
return name;
|
||||
}
|
||||
|
||||
/* the game's actions on the buttons (HALO_VR_ACTION_*'s order): as the
|
||||
options' rows name them, and in short (the Steam Frame's stick lines) */
|
||||
static char const *const vr_action_names[HALO_VR_ACTION_COUNT] =
|
||||
{
|
||||
"Jump", "Light; held: grenades", "Action, reload", "Switch weapon", "Crouch", "Zoom", "Melee",
|
||||
};
|
||||
static char const *const vr_action_short_names[HALO_VR_ACTION_COUNT] =
|
||||
{
|
||||
"jump", "light", "action", "weapon", "crouch", "zoom", "melee",
|
||||
};
|
||||
|
||||
/* an action moved to the next button or the one before: the action that
|
||||
was there takes its old one (so that every action keeps a button) */
|
||||
static void ui_vr_options_button_change(
|
||||
short action,
|
||||
short change)
|
||||
{
|
||||
short input = (short)halo_vr_action_input(action);
|
||||
short wanted = (short)((input + change + HALO_VR_INPUT_COUNT) % HALO_VR_INPUT_COUNT);
|
||||
short other;
|
||||
|
||||
for (other = 0; other < HALO_VR_ACTION_COUNT; other++)
|
||||
{
|
||||
if (other != action && halo_vr_action_input(other) == wanted)
|
||||
config_write(halo_vr_action_setting(other), halo_vr_input_value(input));
|
||||
}
|
||||
config_write(halo_vr_action_setting(action), halo_vr_input_value(wanted));
|
||||
}
|
||||
|
||||
static boolean ui_vr_options_buttons_default(
|
||||
void)
|
||||
{
|
||||
short action;
|
||||
|
||||
for (action = 0; action < HALO_VR_ACTION_COUNT; action++)
|
||||
{
|
||||
if (halo_vr_action_input(action) != action)
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void ui_vr_options_buttons_reset(
|
||||
void)
|
||||
{
|
||||
short action;
|
||||
|
||||
for (action = 0; action < HALO_VR_ACTION_COUNT; action++)
|
||||
{
|
||||
char text[32];
|
||||
|
||||
if (config_default(halo_vr_action_setting(action), text, sizeof(text)))
|
||||
config_write(halo_vr_action_setting(action), text);
|
||||
}
|
||||
}
|
||||
|
||||
void platform_request_quit(void);
|
||||
|
||||
static real const vr_snap_angles[] = { 30.0f, 45.0f, 60.0f, 90.0f };
|
||||
static real const vr_smooth_speeds[] = { 60.0f, 90.0f, 120.0f, 150.0f, 180.0f };
|
||||
static real const vr_vignettes[] = { 0.0f, 0.35f, 0.7f, 1.0f };
|
||||
static char const *const vr_vignette_names[] = { "Off", "Light", "Medium", "Strong" };
|
||||
/* (in finer steps than they had: the old values among them) */
|
||||
static real const vr_snap_angles[] = { 10.0f, 15.0f, 20.0f, 25.0f, 30.0f, 35.0f, 40.0f, 45.0f, 60.0f, 75.0f, 90.0f };
|
||||
static real const vr_smooth_speeds[] = { 30.0f, 45.0f, 60.0f, 75.0f, 90.0f, 105.0f, 120.0f, 135.0f, 150.0f, 180.0f,
|
||||
210.0f, 240.0f, 270.0f, 300.0f };
|
||||
static real const vr_vignettes[] = { 0.0f, 0.15f, 0.25f, 0.35f, 0.5f, 0.6f, 0.7f, 0.85f, 1.0f };
|
||||
/* the on-foot vignette's strengths (vr.foot_vignette_strength: the
|
||||
vignettes' without Off), and vr.foot_vignette's values */
|
||||
static real const vr_foot_vignette_strengths[] = { 0.15f, 0.25f, 0.35f, 0.5f, 0.6f, 0.7f, 0.85f, 1.0f };
|
||||
static char const *const vr_foot_vignettes[] = { "off", "turning", "moving" };
|
||||
static char const *const vr_foot_vignette_names[] = { "Off", "Smooth turns", "Moving, turning" };
|
||||
|
||||
static short ui_vr_options_foot_vignette(
|
||||
void)
|
||||
{
|
||||
char const *mode = config_string("vr.foot_vignette");
|
||||
short index;
|
||||
|
||||
for (index = 0; index < (short)NUMBEROF(vr_foot_vignettes); index++)
|
||||
{
|
||||
if (mode && strcmp(mode, vr_foot_vignettes[index]) == 0)
|
||||
return index;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* a vignette's strength as the rows show it: Off, or how far it darkens */
|
||||
static void ui_vr_options_vignette_text(
|
||||
char *text,
|
||||
size_t size,
|
||||
real strength)
|
||||
{
|
||||
if (strength <= 0.0f)
|
||||
snprintf(text, size, "Off");
|
||||
else
|
||||
snprintf(text, size, "%.0f%%", strength * 100.0f);
|
||||
}
|
||||
/* vr.body's values, and as the panel shows them */
|
||||
static char const *const vr_bodies[] = { "arms", "hands", "off" };
|
||||
static char const *const vr_body_names[] = { "Arms and hands", "Hands only", "Weapon only" };
|
||||
@@ -6838,8 +7003,9 @@ static boolean ui_vr_options_screen(
|
||||
{
|
||||
struct widget_instance *screen = widget_globals.active_widgets[0];
|
||||
|
||||
/* (the Xbox's main menu, or the PC version's: vr.menus) */
|
||||
return halo_vr_active() && screen && screen->name &&
|
||||
/* (the Xbox's main menu, or the PC version's: vr.menus; off the
|
||||
headset with debug.vr_options, to check the pages) */
|
||||
return (halo_vr_active() || config_boolean("debug.vr_options")) && screen && screen->name &&
|
||||
(main_menu_screen_is_active() || strstr(screen->name, "pause_game") != NULL ||
|
||||
strcmp(screen->name, "main_menu") == 0);
|
||||
}
|
||||
@@ -6891,6 +7057,14 @@ static void ui_vr_options_change(
|
||||
case _vr_option_vignette:
|
||||
ui_vr_options_step("vr.comfort_vignette", vr_vignettes, NUMBEROF(vr_vignettes), change);
|
||||
break;
|
||||
case _vr_option_foot_vignette:
|
||||
config_write("vr.foot_vignette", vr_foot_vignettes[(ui_vr_options_foot_vignette() + change +
|
||||
(short)NUMBEROF(vr_foot_vignettes)) % (short)NUMBEROF(vr_foot_vignettes)]);
|
||||
break;
|
||||
case _vr_option_foot_vignette_strength:
|
||||
ui_vr_options_step("vr.foot_vignette_strength", vr_foot_vignette_strengths,
|
||||
NUMBEROF(vr_foot_vignette_strengths), change);
|
||||
break;
|
||||
case _vr_option_wheel: config_write_boolean("vr.vehicle_wheel", !config_boolean("vr.vehicle_wheel")); break;
|
||||
case _vr_option_handedness: config_write("vr.handedness", ui_vr_left_handed() ? "right" : "left"); break;
|
||||
case _vr_option_mirror_controls:
|
||||
@@ -6928,6 +7102,12 @@ static void ui_vr_options_change(
|
||||
case _vr_option_resolution:
|
||||
ui_vr_options_step("vr.resolution_scale", vr_resolution_scales, NUMBEROF(vr_resolution_scales), change);
|
||||
break;
|
||||
case _vr_option_flashlight_gesture:
|
||||
config_write_boolean("vr.flashlight_gesture", !config_boolean("vr.flashlight_gesture"));
|
||||
break;
|
||||
case _vr_option_buttons_reset:
|
||||
ui_vr_options_buttons_reset();
|
||||
break;
|
||||
case _vr_option_controls:
|
||||
ui_vr_options_globals.controls = TRUE;
|
||||
ui_vr_options_globals.page = _vr_controls_on_foot;
|
||||
@@ -6940,6 +7120,11 @@ static void ui_vr_options_change(
|
||||
ui_vr_options_globals.quit_armed = TRUE;
|
||||
break;
|
||||
}
|
||||
if (ui_vr_options_globals.selection >= _vr_option_button_first &&
|
||||
ui_vr_options_globals.selection <= _vr_option_button_last)
|
||||
{
|
||||
ui_vr_options_button_change((short)(ui_vr_options_globals.selection - _vr_option_button_first), change);
|
||||
}
|
||||
ui_play_audio_feedback_sound(_ui_audio_feedback_forward);
|
||||
}
|
||||
|
||||
@@ -7056,7 +7241,8 @@ static boolean ui_vr_options_take_event(
|
||||
{
|
||||
ui_vr_options_change(1);
|
||||
}
|
||||
else if (change && ui_vr_options_globals.selection != _vr_option_controls)
|
||||
else if (change && ui_vr_options_globals.selection != _vr_option_controls &&
|
||||
ui_vr_options_globals.selection != _vr_option_buttons_reset)
|
||||
{
|
||||
ui_vr_options_change(change);
|
||||
}
|
||||
@@ -7113,10 +7299,11 @@ static boolean ui_vr_options_take_pointer(
|
||||
{
|
||||
short page = ui_vr_options_page_of(ui_vr_options_globals.selection, NULL);
|
||||
|
||||
if (pointer->left_clicks && y >= 68 && y < 88 && x >= 330 && x < 514)
|
||||
if (pointer->left_clicks && y >= 68 && y < 88 && x >= VR_OPTIONS_TABS_LEFT && x < VR_OPTIONS_TABS_RIGHT)
|
||||
{
|
||||
/* (a tab: its page) */
|
||||
short tab = (short)PIN((x - 330) / 92, 0, NUMBER_OF_VR_OPTION_PAGES - 1);
|
||||
short tab = (short)PIN((x - VR_OPTIONS_TABS_LEFT) / VR_OPTIONS_TAB_WIDTH, 0,
|
||||
NUMBER_OF_VR_OPTION_PAGES - 1);
|
||||
|
||||
if (tab != page)
|
||||
{
|
||||
@@ -7196,6 +7383,77 @@ static void ui_vr_controls_add(
|
||||
}
|
||||
}
|
||||
|
||||
/* the action on a button (vr.button_*; the swaps keep one on each) */
|
||||
static short ui_vr_input_action(
|
||||
short input)
|
||||
{
|
||||
short action;
|
||||
|
||||
for (action = 0; action < HALO_VR_ACTION_COUNT; action++)
|
||||
{
|
||||
if (halo_vr_action_input(action) == input)
|
||||
return action;
|
||||
}
|
||||
return input;
|
||||
}
|
||||
|
||||
/* in a vehicle: the action button gets in and out, the light's is the
|
||||
flashlight */
|
||||
static void ui_vr_controls_add_vehicle_actions(
|
||||
struct ui_vr_controls_column columns[2])
|
||||
{
|
||||
short column;
|
||||
char const *name = ui_vr_input_name((short)halo_vr_action_input(HALO_VR_ACTION_ACTION), FALSE, &column);
|
||||
|
||||
ui_vr_controls_add(&columns[column], name, "Get in, get out");
|
||||
name = ui_vr_input_name((short)halo_vr_action_input(HALO_VR_ACTION_LIGHT), FALSE, &column);
|
||||
ui_vr_controls_add(&columns[column], name, "Flashlight");
|
||||
}
|
||||
|
||||
/* an action's line under the controller its button is on (vr.button_*), as
|
||||
the Quest's page words it or, shorter, the Steam Frame's (whose page has
|
||||
more lines) */
|
||||
static void ui_vr_controls_add_action(
|
||||
struct ui_vr_controls_column columns[2],
|
||||
short action,
|
||||
boolean frame)
|
||||
{
|
||||
/* (one action is held: its name lives on with the column) */
|
||||
static char held[24];
|
||||
short column;
|
||||
char const *name = ui_vr_input_name((short)halo_vr_action_input(action), FALSE, &column);
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case HALO_VR_ACTION_LIGHT:
|
||||
if (frame)
|
||||
{
|
||||
ui_vr_controls_add(&columns[column], name, "Light; held: grenades");
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(held, sizeof(held), "%s held", strcmp(name, "Stick click") == 0 ? "Click" : name);
|
||||
ui_vr_controls_add(&columns[column], name, "Flashlight");
|
||||
ui_vr_controls_add(&columns[column], held, "Switch grenades");
|
||||
}
|
||||
break;
|
||||
case HALO_VR_ACTION_MELEE:
|
||||
if (frame)
|
||||
{
|
||||
ui_vr_controls_add(&columns[column], name, "Melee (or punch)");
|
||||
}
|
||||
else
|
||||
{
|
||||
ui_vr_controls_add(&columns[column], name, "Melee (or punch");
|
||||
ui_vr_controls_add(&columns[column], "", "forward)");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ui_vr_controls_add(&columns[column], name, vr_action_names[action]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void ui_vr_controls_column_render(
|
||||
short x,
|
||||
short y,
|
||||
@@ -7264,26 +7522,27 @@ static void ui_vr_controls_render(
|
||||
{
|
||||
/* the Steam Frame's controllers: A, B, X, Y and a menu button on the
|
||||
right one, a D-pad and a View button on the left one; mirrored, the
|
||||
D-pad does what A, B, X and Y do (down, left, right, up) */
|
||||
char const *jump = mirrored ? "D-pad down" : "A";
|
||||
char const *light = mirrored ? "D-pad left" : "B";
|
||||
char const *act = mirrored ? "D-pad right" : "X";
|
||||
char const *weapon = mirrored ? "D-pad up" : "Y";
|
||||
short buttons = mirrored ? 0 : 1;
|
||||
D-pad does what A, B, X and Y do (down, left, right, up). The sticks'
|
||||
clicks on the sticks' lines, to keep to the page's lines */
|
||||
static char move_line[32], turn_line[32];
|
||||
|
||||
switch (ui_vr_options_globals.page)
|
||||
{
|
||||
case _vr_controls_on_foot:
|
||||
ui_vr_controls_add(&columns[move], "Stick", "Move; click: crouch");
|
||||
ui_vr_controls_add(&columns[turn], "Stick", "Turn; click: zoom");
|
||||
snprintf(move_line, sizeof(move_line), "Move; click: %s",
|
||||
vr_action_short_names[ui_vr_input_action(HALO_VR_INPUT_MOVE_STICK)]);
|
||||
snprintf(turn_line, sizeof(turn_line), "Turn; click: %s",
|
||||
vr_action_short_names[ui_vr_input_action(HALO_VR_INPUT_TURN_STICK)]);
|
||||
ui_vr_controls_add(&columns[move], "Stick", move_line);
|
||||
ui_vr_controls_add(&columns[turn], "Stick", turn_line);
|
||||
ui_vr_controls_add(&columns[gun], "Trigger", "Fire");
|
||||
ui_vr_controls_add(&columns[free_column], "Trigger", "Grenade: hold, throw");
|
||||
ui_vr_controls_add(&columns[gun], "Grip", "Melee (or punch)");
|
||||
ui_vr_controls_add_action(columns, ui_vr_input_action(HALO_VR_INPUT_GRIP), TRUE);
|
||||
ui_vr_controls_add(&columns[free_column], "Grip", "Weapon in both hands");
|
||||
ui_vr_controls_add(&columns[buttons], jump, "Jump");
|
||||
ui_vr_controls_add(&columns[buttons], light, "Light; held: grenades");
|
||||
ui_vr_controls_add(&columns[buttons], act, "Action, reload");
|
||||
ui_vr_controls_add(&columns[buttons], weapon, "Switch weapon");
|
||||
ui_vr_controls_add_action(columns, ui_vr_input_action(HALO_VR_INPUT_A), TRUE);
|
||||
ui_vr_controls_add_action(columns, ui_vr_input_action(HALO_VR_INPUT_B), TRUE);
|
||||
ui_vr_controls_add_action(columns, ui_vr_input_action(HALO_VR_INPUT_X), TRUE);
|
||||
ui_vr_controls_add_action(columns, ui_vr_input_action(HALO_VR_INPUT_Y), TRUE);
|
||||
ui_vr_controls_add(&columns[mirrored ? 0 : 1], "Bumper", "Flashlight");
|
||||
ui_vr_controls_add(&columns[mirrored ? 1 : 0], "Bumper", "Switch grenades");
|
||||
ui_vr_controls_add(&columns[0], "View", "Scores");
|
||||
@@ -7294,6 +7553,8 @@ static void ui_vr_controls_render(
|
||||
ui_vr_controls_add(&columns[1], "Menu", "Pause");
|
||||
ui_vr_controls_note(320, wrist_note);
|
||||
ui_vr_controls_note(340, "Scope: zoom, and look through the disc above the weapon.");
|
||||
if (config_boolean("vr.flashlight_gesture"))
|
||||
ui_vr_controls_note(360, "Tap the side or top of your head: the flashlight.");
|
||||
break;
|
||||
case _vr_controls_vehicles:
|
||||
ui_vr_controls_add(&columns[move], "Stick", "Drive");
|
||||
@@ -7302,8 +7563,7 @@ static void ui_vr_controls_render(
|
||||
ui_vr_controls_add(&columns[gun], "Trigger", "Fire");
|
||||
ui_vr_controls_add(&columns[free_column], "Trigger", "Second weapon");
|
||||
ui_vr_controls_add(&columns[free_column], "", "(Banshee, tank)");
|
||||
ui_vr_controls_add(&columns[buttons], act, "Get in, get out");
|
||||
ui_vr_controls_add(&columns[buttons], light, "Flashlight");
|
||||
ui_vr_controls_add_vehicle_actions(columns);
|
||||
break;
|
||||
default:
|
||||
ui_vr_controls_add(&columns[0], "Stick", "Choose");
|
||||
@@ -7322,31 +7582,28 @@ static void ui_vr_controls_render(
|
||||
/* the Quest's: A and B on the right controller, X, Y and the menu
|
||||
button on the left; mirrored, X and Y do what A and B do, and the
|
||||
other way round */
|
||||
short jumps = mirrored ? 0 : 1;
|
||||
short acts = (short)(1 - jumps);
|
||||
|
||||
switch (ui_vr_options_globals.page)
|
||||
{
|
||||
case _vr_controls_on_foot:
|
||||
ui_vr_controls_add(&columns[move], "Stick", "Move");
|
||||
ui_vr_controls_add(&columns[move], "Stick click", "Crouch");
|
||||
ui_vr_controls_add_action(columns, ui_vr_input_action(HALO_VR_INPUT_MOVE_STICK), FALSE);
|
||||
ui_vr_controls_add(&columns[turn], "Stick", "Turn");
|
||||
ui_vr_controls_add(&columns[turn], "Stick click", "Zoom");
|
||||
ui_vr_controls_add_action(columns, ui_vr_input_action(HALO_VR_INPUT_TURN_STICK), FALSE);
|
||||
ui_vr_controls_add(&columns[gun], "Trigger", "Fire");
|
||||
ui_vr_controls_add(&columns[gun], "Grip", "Melee (or punch");
|
||||
ui_vr_controls_add(&columns[gun], "", "forward)");
|
||||
ui_vr_controls_add_action(columns, ui_vr_input_action(HALO_VR_INPUT_GRIP), FALSE);
|
||||
ui_vr_controls_add(&columns[free_column], "Trigger", "Grenade: hold it,");
|
||||
ui_vr_controls_add(&columns[free_column], "", "let go as you throw");
|
||||
ui_vr_controls_add(&columns[free_column], "Grip", "Weapon in both hands");
|
||||
ui_vr_controls_add(&columns[jumps], jumps ? "A" : "X", "Jump");
|
||||
ui_vr_controls_add(&columns[jumps], jumps ? "B" : "Y", "Flashlight");
|
||||
ui_vr_controls_add(&columns[jumps], jumps ? "B held" : "Y held", "Switch grenades");
|
||||
ui_vr_controls_add(&columns[acts], acts ? "A" : "X", "Action, reload");
|
||||
ui_vr_controls_add(&columns[acts], acts ? "B" : "Y", "Switch weapon");
|
||||
ui_vr_controls_add_action(columns, ui_vr_input_action(HALO_VR_INPUT_A), FALSE);
|
||||
ui_vr_controls_add_action(columns, ui_vr_input_action(HALO_VR_INPUT_B), FALSE);
|
||||
ui_vr_controls_add_action(columns, ui_vr_input_action(HALO_VR_INPUT_X), FALSE);
|
||||
ui_vr_controls_add_action(columns, ui_vr_input_action(HALO_VR_INPUT_Y), FALSE);
|
||||
ui_vr_controls_add(&columns[0], "Menu", "Pause");
|
||||
ui_vr_controls_note(320, wrist_note);
|
||||
ui_vr_controls_note(340, "Scope: zoom, and look through the disc above the weapon.");
|
||||
ui_vr_controls_note(360, "Hold the Meta button to recentre the view.");
|
||||
if (config_boolean("vr.flashlight_gesture"))
|
||||
ui_vr_controls_note(380, "Tap the side or top of your head: the flashlight.");
|
||||
break;
|
||||
case _vr_controls_vehicles:
|
||||
ui_vr_controls_add(&columns[move], "Stick", "Drive");
|
||||
@@ -7355,8 +7612,7 @@ static void ui_vr_controls_render(
|
||||
ui_vr_controls_add(&columns[gun], "Trigger", "Fire");
|
||||
ui_vr_controls_add(&columns[free_column], "Trigger", "Second weapon");
|
||||
ui_vr_controls_add(&columns[free_column], "", "(Banshee, tank)");
|
||||
ui_vr_controls_add(&columns[acts], acts ? "A" : "X", "Get in, get out");
|
||||
ui_vr_controls_add(&columns[jumps], jumps ? "B" : "Y", "Flashlight");
|
||||
ui_vr_controls_add_vehicle_actions(columns);
|
||||
break;
|
||||
default:
|
||||
ui_vr_controls_add(&columns[0], "Stick", "Choose");
|
||||
@@ -7373,6 +7629,9 @@ static void ui_vr_controls_render(
|
||||
ui_vr_controls_column_render(right, y, &columns[1]);
|
||||
switch (ui_vr_options_globals.page)
|
||||
{
|
||||
case _vr_controls_on_foot:
|
||||
/* (its notes are with its lines, above) */
|
||||
break;
|
||||
case _vr_controls_vehicles:
|
||||
ui_vr_controls_note(300, "Warthog: grip the wheel with one hand or both and turn it.");
|
||||
ui_vr_controls_note(320, left_handed ? "Holding it, the left trigger accelerates, the right one brakes" :
|
||||
@@ -7429,15 +7688,15 @@ static void ui_vr_options_render(
|
||||
ui_join_code_draw_quad(110, 62, 530, 396, 0xFF050A18);
|
||||
ui_join_code_draw_quad(110, 62, 530, 64, 0xFF3A6EA5);
|
||||
ui_join_code_draw_quad(110, 394, 530, 396, 0xFF3A6EA5);
|
||||
ui_join_code_draw_text(126, 330, 72, "VR OPTIONS", FALSE, 0, &title_color);
|
||||
ui_join_code_draw_text(126, VR_OPTIONS_TABS_LEFT, 72, "VR OPTIONS", FALSE, 0, &title_color);
|
||||
/* (the pages' tabs, beside the title) */
|
||||
for (tab = 0; tab < NUMBER_OF_VR_OPTION_PAGES; tab++)
|
||||
{
|
||||
short x0 = (short)(330 + tab * 92);
|
||||
short x0 = (short)(VR_OPTIONS_TABS_LEFT + tab * VR_OPTIONS_TAB_WIDTH);
|
||||
|
||||
if (tab == page)
|
||||
ui_join_code_draw_quad(x0, 68, (short)(x0 + 88), 88, 0x803A6EA5);
|
||||
ui_join_code_draw_text(x0, (short)(x0 + 88), 72, vr_option_page_names[tab], FALSE, 2,
|
||||
ui_join_code_draw_quad(x0, 68, (short)(x0 + VR_OPTIONS_TAB_WIDTH - 4), 88, 0x803A6EA5);
|
||||
ui_join_code_draw_text(x0, (short)(x0 + VR_OPTIONS_TAB_WIDTH - 4), 72, vr_option_page_names[tab], FALSE, 2,
|
||||
tab == page ? &text_color : &dim_color);
|
||||
}
|
||||
for (row = 0; row < ui_vr_options_page_rows(page); row++)
|
||||
@@ -7467,10 +7726,23 @@ static void ui_vr_options_render(
|
||||
unused = !smooth;
|
||||
break;
|
||||
case _vr_option_vignette:
|
||||
label = "Vehicle comfort vignette";
|
||||
snprintf(value, sizeof(value), "%s", vr_vignette_names[ui_vr_options_nearest(
|
||||
label = "Vehicle vignette";
|
||||
ui_vr_options_vignette_text(value, sizeof(value), vr_vignettes[ui_vr_options_nearest(
|
||||
(real)config_real("vr.comfort_vignette"), vr_vignettes, NUMBEROF(vr_vignettes))]);
|
||||
break;
|
||||
case _vr_option_foot_vignette:
|
||||
label = "On-foot vignette";
|
||||
snprintf(value, sizeof(value), "%s", vr_foot_vignette_names[ui_vr_options_foot_vignette()]);
|
||||
/* (smooth turns alone, with snap turning: nothing to darken) */
|
||||
unused = ui_vr_options_foot_vignette() == 1 && !smooth;
|
||||
break;
|
||||
case _vr_option_foot_vignette_strength:
|
||||
label = "On-foot vignette strength";
|
||||
ui_vr_options_vignette_text(value, sizeof(value), vr_foot_vignette_strengths[ui_vr_options_nearest(
|
||||
(real)config_real("vr.foot_vignette_strength"), vr_foot_vignette_strengths,
|
||||
NUMBEROF(vr_foot_vignette_strengths))]);
|
||||
unused = ui_vr_options_foot_vignette() == 0;
|
||||
break;
|
||||
case _vr_option_wheel:
|
||||
label = "Warthog steering wheel";
|
||||
snprintf(value, sizeof(value), "%s", config_boolean("vr.vehicle_wheel") ? "On" : "Off (stick)");
|
||||
@@ -7537,9 +7809,27 @@ static void ui_vr_options_render(
|
||||
snprintf(value, sizeof(value), "%.0f%%", scale * 100.0f);
|
||||
break;
|
||||
}
|
||||
case _vr_option_flashlight_gesture:
|
||||
label = "Light by tapping the head";
|
||||
snprintf(value, sizeof(value), "%s", config_boolean("vr.flashlight_gesture") ? "On" : "Off");
|
||||
break;
|
||||
case _vr_option_buttons_reset:
|
||||
label = "Reset buttons to defaults";
|
||||
unused = ui_vr_options_buttons_default();
|
||||
break;
|
||||
case _vr_option_controls:
|
||||
label = "Controller buttons...";
|
||||
break;
|
||||
default:
|
||||
if (option >= _vr_option_button_first && option <= _vr_option_button_last)
|
||||
{
|
||||
short action = (short)(option - _vr_option_button_first);
|
||||
|
||||
label = vr_action_names[action];
|
||||
snprintf(value, sizeof(value), "%s", ui_vr_input_name((short)halo_vr_action_input(action), TRUE,
|
||||
NULL));
|
||||
}
|
||||
break;
|
||||
case _vr_option_quit:
|
||||
label = ui_vr_options_globals.quit_armed && ui_vr_options_globals.selection == _vr_option_quit ?
|
||||
"Quit Halo? Once more to quit" : "Quit Halo";
|
||||
@@ -7556,7 +7846,25 @@ static void ui_vr_options_render(
|
||||
ui_join_code_draw_text(330, 512, y, shown, FALSE, 1, unused ? &dim_color : &text_color);
|
||||
}
|
||||
}
|
||||
if (page == 1)
|
||||
if (page == _vr_options_page_comfort)
|
||||
{
|
||||
/* (what the vignettes do) */
|
||||
ui_join_code_draw_text(128, 512, 248, "The vignette darkens the view from its edges while the", FALSE, 0,
|
||||
&dim_color);
|
||||
ui_join_code_draw_text(128, 512, 266, "game moves you: in a vehicle as it turns you; on foot, if", FALSE, 0,
|
||||
&dim_color);
|
||||
ui_join_code_draw_text(128, 512, 284, "on, as the sticks turn you smoothly (and move you).", FALSE, 0,
|
||||
&dim_color);
|
||||
}
|
||||
if (page == _vr_options_page_buttons)
|
||||
{
|
||||
/* (what the buttons' rows do) */
|
||||
ui_join_code_draw_text(128, 512, 320, "An action moved to a button swaps with the one there;", FALSE, 0,
|
||||
&dim_color);
|
||||
ui_join_code_draw_text(128, 512, 338, "left-handed and mirrored, the buttons are mirrored too.", FALSE, 0,
|
||||
&dim_color);
|
||||
}
|
||||
if (page == _vr_options_page_more)
|
||||
{
|
||||
/* (what the graphics rows do) */
|
||||
ui_join_code_draw_text(128, 512, 230, "Graphics: Medium and Low leave effects out (shadows,", FALSE, 0,
|
||||
|
||||
@@ -31,7 +31,14 @@ enum
|
||||
RASTERIZER_MAXIMUM_TRIANGLES_PER_TRIANGLE_BUFFER = 24576,
|
||||
RASTERIZER_MAXIMUM_DEBUG_PRIMITIVES = 131072,
|
||||
RASTERIZER_MAXIMUM_DEBUG_VERTICES = 393216,
|
||||
RASTERIZER_MAXIMUM_TRANSPARENT_GEOMETRY_GROUPS = 384,
|
||||
/* port: the Xbox's 384 groups a window (each a model's transparent part,
|
||||
a particle system, a contrail, a light volume, a window's or water's
|
||||
surface) are spent in games of 30 and more players, and whatever is
|
||||
submitted after the last is dropped, the structure's glass and water
|
||||
and the particles first (render_window submits the objects before
|
||||
them). Their indices are shorts, the pending flags a bit vector of
|
||||
this size: 2048 groups take 320 KB. */
|
||||
RASTERIZER_MAXIMUM_TRANSPARENT_GEOMETRY_GROUPS = 2048,
|
||||
RASTERIZER_MAXIMUM_TRANSPARENT_GEOMETRY_GROUPS2 = 32,
|
||||
RASTERIZER_MAXIMUM_DYNAMIC_TRIANGLES = 32768,
|
||||
RASTERIZER_MAXIMUM_DYNAMIC_TRIANGLE_BUFFERS = 1024,
|
||||
|
||||
@@ -150,6 +150,7 @@ typedef char transparent_geometry_group_cortana_hack_offset_assert[
|
||||
/* ---------- prototypes */
|
||||
static void rasterizer_sort_external(
|
||||
void);
|
||||
void platform_log(char const *format, ...);
|
||||
|
||||
/* ---------- globals */
|
||||
|
||||
@@ -162,6 +163,9 @@ static long transparent_geometry_group_count = 0;
|
||||
static long transparent_geometry_group_count2 = 0;
|
||||
static short *transparent_geometry_group_sorted_indices = NULL;
|
||||
static short transparent_geometry_next_group_sorted_index = 0;
|
||||
/* port: the most groups a window has had, logged as it passes the Xbox's
|
||||
384 and every 128 beyond (rasterizer.h) */
|
||||
static long transparent_geometry_group_count_logged = 384;
|
||||
|
||||
|
||||
/* ---------- public code */
|
||||
@@ -200,6 +204,12 @@ boolean rasterizer_transparent_geometry_initialize(
|
||||
void rasterizer_transparent_geometry_begin(
|
||||
void)
|
||||
{
|
||||
if (transparent_geometry_group_count>transparent_geometry_group_count_logged)
|
||||
{
|
||||
platform_log("rasterizer: %ld transparent geometry groups in a window (the Xbox had room for 384, the port %d)",
|
||||
transparent_geometry_group_count, RASTERIZER_MAXIMUM_TRANSPARENT_GEOMETRY_GROUPS);
|
||||
transparent_geometry_group_count_logged = (transparent_geometry_group_count/128 + 1)*128;
|
||||
}
|
||||
transparent_geometry_group_count = 0;
|
||||
transparent_geometry_next_group_sorted_index = 0;
|
||||
memset(transparent_geometry_group_pending_flags, 0,
|
||||
|
||||
Reference in new issue
Block a user