VrCalibrationRig.cs
using Sandbox;
/// <summary>Local-only VR join rig: tracked camera, no locomotion, WorldPanel calibration UI.</summary>
public sealed class VrCalibrationRig : Component
{
public PlayerSession Session { get; set; }
private CameraComponent _camera;
private GameObject _panelGo;
private const float PanelDistance = 40f;
private const float PanelHeightOffset = -4f;
/// <summary>Call after the VR root (with camera) has been parented under this rig.</summary>
public void EnsurePanel()
{
ResolveCamera();
if ( !_panelGo.IsValid() )
CreateWorldPanel();
}
protected override void OnUpdate()
{
ResolveCamera();
if ( !_panelGo.IsValid() )
CreateWorldPanel();
UpdatePanelTransform();
}
private void ResolveCamera()
{
if ( _camera.IsValid() )
return;
_camera = Components.Get<CameraComponent>( FindMode.EnabledInSelfAndDescendants );
}
protected override void OnDestroy()
{
if ( _panelGo.IsValid() )
_panelGo.Destroy();
_panelGo = null;
}
/// <summary>Eye height above this rig's floor origin, matching in-game duck measurement.</summary>
public float MeasureEyeHeight()
{
if ( !_camera.IsValid() )
return Input.VR.Head.Position.z;
return _camera.WorldPosition.z - WorldPosition.z;
}
private void CreateWorldPanel()
{
_panelGo = new GameObject( parent: GameObject, name: "HeightCalibrationPanel" )
{
NetworkMode = NetworkMode.Never
};
var worldPanel = _panelGo.AddComponent<WorldPanel>();
worldPanel.PanelSize = new Vector2( 700f, 560f );
worldPanel.RenderScale = 0.25f;
worldPanel.LookAtCamera = true;
worldPanel.InteractionRange = 1000f;
_panelGo.AddComponent<HeightCalibrationPanel>();
Log.Info( "VrCalibrationRig: HeightCalibrationPanel WorldPanel created." );
UpdatePanelTransform();
}
private void UpdatePanelTransform()
{
if ( !_panelGo.IsValid() )
return;
if ( _camera.IsValid() )
{
var camTx = _camera.WorldTransform;
_panelGo.WorldPosition = camTx.Position
+ camTx.Forward * PanelDistance
+ camTx.Up * PanelHeightOffset;
return;
}
// Fallback before headset tracking settles: place in front of the spawn facing.
_panelGo.WorldPosition = WorldPosition
+ WorldRotation.Forward * PanelDistance
+ Vector3.Up * 60f;
}
}