In-VR menu: replace chunky prop-knob panel with Godot Control UI in a SubViewport
WorldPanel is now the project's one SubViewport screen: MainMenu (tabs Player /
World / System; Return to spawn, Recalibrate body, Reset props, Ping, click
volume slider, scrollable log, FPS, Close) rendered by MenuScreen into a
960x640 SubViewport on a thin 0.36x0.24 m panel.
Input = touch-first hybrid cursor injected as mouse events: both controller
rays are projected analytically onto the panel plane, converted to viewport
pixels and pushed via Viewport.PushInput (MouseMotion/MouseButton, wheel from
thumbstick). Stylus tip within 6 cm = touch cursor (press crossing 0.6 cm from
the front, release past 1.8 cm); farther = laser cursor with trigger edge. One
owning hand per viewport. Haptic tick + synthesized click on press.
Kept: ax_button summon/dismiss, XROrigin3D parenting, grip drag (direct/laser)
with head re-orient, IsBlocking/IsPanelCollider. Locomotion's beam now takes
its length from WorldPanel.TryGetLaserDistance (no beam while touching) and
starts at the stylus tip. Recalibrate calls Recalibrate() on the first node in
group "calibration" (disabled when absent).
New headless regression scenes/menu_spike.tscn ("MENU: overall PASS").
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
3a990c6dbe
commit
661fe1089a
11 files changed
+1281
-316
No files matched your search
+12
-5
@@ -7,6 +7,7 @@ public partial class Locomotion : Node
|
||||
private const float RayLength = 50f;
|
||||
private const float LaserMinDistance = 0.35f;
|
||||
private const float MarkerNearDistance = 1.2f;
|
||||
private const float LaserStart = 0.12f;
|
||||
|
||||
private XROrigin3D _origin;
|
||||
private XRCamera3D _camera;
|
||||
@@ -78,7 +79,7 @@ public partial class Locomotion : Node
|
||||
Node3D pivot = new() { Visible = false };
|
||||
pivot.AddChild(beam);
|
||||
Basis rot = Basis.FromEuler(new Vector3(-Mathf.Pi / 2f, 0, 0));
|
||||
pivot.Transform = new Transform3D(rot, new Vector3(0, 0, -0.12f));
|
||||
pivot.Transform = new Transform3D(rot, new Vector3(0, 0, -LaserStart));
|
||||
controller.AddChild(pivot);
|
||||
return pivot;
|
||||
}
|
||||
@@ -127,13 +128,19 @@ public partial class Locomotion : Node
|
||||
|
||||
bool show = false;
|
||||
float dist = 0f;
|
||||
if (hit.TryGetValue("collider", out Variant collider) && collider.As<Node>() is Node node)
|
||||
if (WorldPanel.TryGetLaserDistance(controller, out float panelDist))
|
||||
{
|
||||
// The menu decides touch vs laser itself (tip near the surface = touch, no beam).
|
||||
dist = panelDist;
|
||||
show = dist > LaserMinDistance;
|
||||
}
|
||||
else if (hit.TryGetValue("collider", out Variant collider) && collider.As<Node>() is Node node)
|
||||
{
|
||||
bool interactive;
|
||||
if (node.GetParent() is TeleportMarker marker)
|
||||
interactive = !marker.IsNear;
|
||||
else
|
||||
interactive = WorldPanel.IsPanelCollider(node);
|
||||
interactive = false; // panel hit but the menu isn't in laser mode for this hand
|
||||
if (interactive && hit.TryGetValue("position", out Variant posVariant))
|
||||
{
|
||||
dist = from.DistanceTo(posVariant.As<Vector3>());
|
||||
@@ -142,8 +149,8 @@ public partial class Locomotion : Node
|
||||
}
|
||||
|
||||
laser.Visible = show;
|
||||
if (show)
|
||||
laser.Scale = new Vector3(1, dist, 1);
|
||||
if (show) // beam starts at the stylus tip (LaserStart ahead of the controller)
|
||||
laser.Scale = new Vector3(1, Mathf.Max(0.01f, dist - LaserStart), 1);
|
||||
}
|
||||
|
||||
private void CheckTeleport(XRController3D controller, ref bool wasPressed)
|
||||
|
||||
Reference in new issue
Block a user