Add configurable game/initial screen width and distance, with a bundled first-run config
build / build (push) Successful in 2m41s
build / build (push) Successful in 2m41s
- Video Options tab offers width and distance presets independently for the Initial Screen (splash/intro/menu) and Game Screen (gameplay) profiles, with their preset step/offset configurable via questshock.config.json. - Ships res/questshock.config.default.json as the initial config on first run (or whenever questshock.config.json doesn't exist yet), refreshed from the APK on every launch without touching a user's own saved config.
This commit is contained in:
@@ -48,7 +48,7 @@ static const float kHandColor[2][4] = {
|
||||
// MenuOverlay.HEIGHT).
|
||||
#define KEYBOARD_TITLE_BAR_V_FRACTION (90.0f / 768.0f)
|
||||
#define KEYBOARD_CLOSE_BUTTON_U_FRACTION (1.0f - 160.0f / 1024.0f)
|
||||
#define MENU_TITLE_BAR_V_FRACTION (56.0f / 552.0f)
|
||||
#define MENU_TITLE_BAR_V_FRACTION (56.0f / 800.0f)
|
||||
#define MENU_DRAG_HANDLE_U_FRACTION 1.0f
|
||||
|
||||
static XrInstance g_instance = XR_NULL_HANDLE;
|
||||
@@ -642,35 +642,97 @@ static void xr_input_build_beam(int hand, const XrSpaceLocation *location, float
|
||||
g_beam_quad_valid[hand] = true;
|
||||
}
|
||||
|
||||
// Hit-tests this hand's ray against the game quad (xr_get_game_quad_extent())
|
||||
// Hit-tests this hand's ray against the game screen (xr_get_game_quad_extent())
|
||||
// - the lowest-priority target, tried only once neither the keyboard nor
|
||||
// menu overlay claimed the ray this frame (or, symmetrically, once this
|
||||
// hand already has a pending mouse-down on the game quad - see
|
||||
// hand already has a pending mouse-down on the game screen - see
|
||||
// g_game_touch_active and the keyboard/menu call sites in
|
||||
// xr_input_sync_and_draw()). outU/outV (only meaningful when the
|
||||
// returned hit is true) let the caller drive the game's own mouse cursor
|
||||
// via xr_mouse.h. Returns plain `hit` - drag/touch dispatch for actual
|
||||
// clicks is the caller's responsibility (xr_mouse_click()), not this
|
||||
// function's, unlike xr_input_try_overlay().
|
||||
//
|
||||
// Two shapes: a flat plane (centralAngle == 0, the default and the only
|
||||
// shape this function supported before screen curving existed - kept
|
||||
// byte-for-byte unchanged as its own branch below, so nobody who never
|
||||
// touches the new Video Options curve setting sees any change at all), or
|
||||
// a curved cylinder segment. The curve is horizontal-only (like a real
|
||||
// curved monitor) - the cylinder's vertical axis runs parallel to the
|
||||
// screen's own local Y at (x=0, z=Zc) for every y, so y drops out of the
|
||||
// lateral-surface intersection test entirely; halfHeight bounds the
|
||||
// vertical extent exactly like the flat case, unchanged.
|
||||
static bool xr_input_try_game_quad(int hand, const XrSpaceLocation *location, float fx, float fy,
|
||||
float fz, bool *outPlaneHit, float *outPlaneDistance,
|
||||
float *outU, float *outV) {
|
||||
float distance, halfWidth, halfHeight;
|
||||
xr_get_game_quad_extent(&distance, &halfWidth, &halfHeight);
|
||||
float distance, halfWidth, halfHeight, radius, centralAngle;
|
||||
xr_get_game_quad_extent(&distance, &halfWidth, &halfHeight, &radius, ¢ralAngle);
|
||||
|
||||
bool planeHit = false, hit = false;
|
||||
float u = 0.0f, v = 0.0f, t = 0.0f;
|
||||
if (fabsf(fz) > 1e-5f) {
|
||||
t = (-distance - location->pose.position.z) / fz;
|
||||
if (t > 0.0f) {
|
||||
planeHit = true;
|
||||
float cx = (location->pose.position.x + t * fx) / halfWidth;
|
||||
float cy = (location->pose.position.y + t * fy) / halfHeight;
|
||||
hit = fabsf(cx) <= 1.0f && fabsf(cy) <= 1.0f;
|
||||
u = (cx + 1.0f) * 0.5f;
|
||||
v = (1.0f - cy) * 0.5f;
|
||||
|
||||
if (centralAngle <= 0.0f) {
|
||||
if (fabsf(fz) > 1e-5f) {
|
||||
t = (-distance - location->pose.position.z) / fz;
|
||||
if (t > 0.0f) {
|
||||
planeHit = true;
|
||||
float cx = (location->pose.position.x + t * fx) / halfWidth;
|
||||
float cy = (location->pose.position.y + t * fy) / halfHeight;
|
||||
hit = fabsf(cx) <= 1.0f && fabsf(cy) <= 1.0f;
|
||||
u = (cx + 1.0f) * 0.5f;
|
||||
v = (1.0f - cy) * 0.5f;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Zc: the cylinder's axis position along Z (see xr_session.c's
|
||||
// own concavity-derivation comment - same offset the render path
|
||||
// uses to place the actual XrCompositionLayerCylinderKHR, so the
|
||||
// two can never disagree about where the surface actually is).
|
||||
float Zc = -distance + radius;
|
||||
float x0 = location->pose.position.x;
|
||||
float dz0 = location->pose.position.z - Zc;
|
||||
|
||||
// Ray-vs-infinite-cylinder quadratic (only x/z participate, per
|
||||
// this function's own comment above) - A<=~0 means the ray runs
|
||||
// parallel to the axis (never crosses the lateral surface),
|
||||
// mirroring the flat case's fabsf(fz)>1e-5f guard.
|
||||
float A = fx * fx + fz * fz;
|
||||
if (A > 1e-8f) {
|
||||
float B = 2.0f * (fx * x0 + fz * dz0);
|
||||
float C = x0 * x0 + dz0 * dz0 - radius * radius;
|
||||
float disc = B * B - 4.0f * A * C;
|
||||
if (disc >= 0.0f) {
|
||||
float sq = sqrtf(disc);
|
||||
// Smallest positive root - the near intersection, correct
|
||||
// both for the normal case (viewer inside the cylinder,
|
||||
// so exactly one root is positive) and if the viewer ever
|
||||
// ends up outside it.
|
||||
float t1 = (-B - sq) / (2.0f * A);
|
||||
float t2 = (-B + sq) / (2.0f * A);
|
||||
if (t1 > 0.0f)
|
||||
t = t1;
|
||||
else if (t2 > 0.0f)
|
||||
t = t2;
|
||||
if (t > 0.0f) {
|
||||
planeHit = true;
|
||||
float px = location->pose.position.x + t * fx;
|
||||
float py = location->pose.position.y + t * fy;
|
||||
float pz = location->pose.position.z + t * fz;
|
||||
// Signed angle from center (angle 0 is dead ahead,
|
||||
// matching the flat case's cx==0 being dead center) -
|
||||
// bounded by the configured centralAngle instead of a
|
||||
// halfWidth.
|
||||
float phi = atan2f(px, Zc - pz);
|
||||
float halfAngle = centralAngle * 0.5f;
|
||||
float cy = py / halfHeight;
|
||||
hit = fabsf(phi) <= halfAngle && fabsf(cy) <= 1.0f;
|
||||
u = (phi / halfAngle + 1.0f) * 0.5f;
|
||||
v = (1.0f - cy) * 0.5f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*outPlaneHit = planeHit;
|
||||
*outPlaneDistance = t;
|
||||
*outU = u;
|
||||
|
||||
Reference in New Issue
Block a user