mirror of
https://github.com/NotAKidoS/NAK_CVR_Mods.git
synced 2025-09-02 22:39:22 +00:00
312 lines
No EOL
10 KiB
C#
312 lines
No EOL
10 KiB
C#
using UnityEngine;
|
|
using UnityEngine.EventSystems;
|
|
using UnityEngine.UI;
|
|
|
|
namespace ABI_RC.Core.Player.Interaction.RaycastImpl
|
|
{
|
|
public class CVRRaycastDebugManager : MonoBehaviour
|
|
{
|
|
#region Singleton
|
|
|
|
private static CVRRaycastDebugManager _instance;
|
|
public static CVRRaycastDebugManager Instance => _instance;
|
|
|
|
public static void Initialize(Camera camera)
|
|
{
|
|
if (_instance != null) return;
|
|
|
|
var go = new GameObject("RaycastDebugManager");
|
|
_instance = go.AddComponent<CVRRaycastDebugManager>();
|
|
DontDestroyOnLoad(go);
|
|
|
|
_instance.Setup(camera);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Private Fields
|
|
|
|
private CVRPlayerRaycasterMouse _raycaster;
|
|
private CVRRaycastResult _lastResult;
|
|
private System.Diagnostics.Stopwatch _stopwatch;
|
|
|
|
// Performance tracking
|
|
private const int ROLLING_AVERAGE_SAMPLES = 60; // 1 second at 60fps
|
|
private readonly float[] _timeHistory = new float[ROLLING_AVERAGE_SAMPLES];
|
|
private int _currentSampleIndex;
|
|
private float _lastRaycastTime;
|
|
private float _minRaycastTime = float.MaxValue;
|
|
private float _maxRaycastTime;
|
|
private float _rollingAverageTime;
|
|
private bool _historyFilled;
|
|
|
|
private const int DEBUG_PANEL_WIDTH = 300;
|
|
private const int DEBUG_PANEL_MARGIN = 10;
|
|
private const float MOUSE_CURSOR_SIZE = 24f;
|
|
private const float CURSOR_OFFSET = MOUSE_CURSOR_SIZE / 2f;
|
|
|
|
private GUIStyle _labelStyle;
|
|
private GUIStyle _headerStyle;
|
|
private GUIStyle _boxStyle;
|
|
|
|
private static readonly Color32 TIMING_COLOR = new(255, 255, 150, 255); // Yellow
|
|
private static readonly Color32 COHTML_COLOR = new(150, 255, 150, 255); // Green
|
|
private static readonly Color32 UI_COLOR = new(150, 150, 255, 255); // Blue
|
|
private static readonly Color32 UNITY_UI_COLOR = new(255, 200, 150, 255); // Orange
|
|
private static readonly Color32 INTERACT_COLOR = new(255, 150, 150, 255); // Red
|
|
private static readonly Color32 WATER_COLOR = new(150, 255, 255, 255); // Cyan
|
|
private static readonly Color32 TELEPATHIC_COLOR = new(255, 150, 255, 255);// Purple
|
|
private static readonly Color32 SELECTABLE_COLOR = new(200, 150, 255, 255);// Light Purple
|
|
|
|
#endregion
|
|
|
|
#region Setup
|
|
|
|
private void Setup(Camera camera)
|
|
{
|
|
_raycaster = new CVRPlayerRaycasterMouse(transform, camera);
|
|
_raycaster.SetLayerMask(Physics.DefaultRaycastLayers);
|
|
_stopwatch = new System.Diagnostics.Stopwatch();
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region MonoBehaviour
|
|
|
|
private void Update()
|
|
{
|
|
_stopwatch.Restart();
|
|
_lastResult = _raycaster.GetRaycastResults();
|
|
_stopwatch.Stop();
|
|
|
|
UpdatePerformanceMetrics();
|
|
}
|
|
|
|
private void UpdatePerformanceMetrics()
|
|
{
|
|
// Calculate current frame time
|
|
_lastRaycastTime = _stopwatch.ElapsedTicks / (float)System.TimeSpan.TicksPerMillisecond;
|
|
|
|
// Update min/max
|
|
_minRaycastTime = Mathf.Min(_minRaycastTime, _lastRaycastTime);
|
|
_maxRaycastTime = Mathf.Max(_maxRaycastTime, _lastRaycastTime);
|
|
|
|
// Update rolling average
|
|
_timeHistory[_currentSampleIndex] = _lastRaycastTime;
|
|
|
|
// Calculate rolling average based on filled samples
|
|
float sum = 0f;
|
|
int sampleCount = _historyFilled ? ROLLING_AVERAGE_SAMPLES : _currentSampleIndex + 1;
|
|
|
|
for (int i = 0; i < sampleCount; i++)
|
|
sum += _timeHistory[i];
|
|
|
|
_rollingAverageTime = sum / sampleCount;
|
|
|
|
// Update index for next frame
|
|
_currentSampleIndex = (_currentSampleIndex + 1) % ROLLING_AVERAGE_SAMPLES;
|
|
if (_currentSampleIndex == 0)
|
|
_historyFilled = true;
|
|
}
|
|
|
|
private void OnGUI()
|
|
{
|
|
InitializeStyles();
|
|
DrawDebugPanel();
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Drawing Methods
|
|
|
|
private void InitializeStyles()
|
|
{
|
|
if (_labelStyle != null) return;
|
|
|
|
_labelStyle = new GUIStyle
|
|
{
|
|
normal = { textColor = Color.white },
|
|
fontSize = 12,
|
|
padding = new RectOffset(5, 5, 2, 2),
|
|
margin = new RectOffset(5, 5, 0, 0)
|
|
};
|
|
|
|
_headerStyle = new GUIStyle
|
|
{
|
|
normal = { textColor = Color.white },
|
|
fontSize = 14,
|
|
fontStyle = FontStyle.Bold,
|
|
padding = new RectOffset(5, 5, 5, 5),
|
|
margin = new RectOffset(5, 5, 5, 5)
|
|
};
|
|
|
|
_boxStyle = new GUIStyle(GUI.skin.box)
|
|
{
|
|
padding = new RectOffset(10, 10, 5, 5),
|
|
margin = new RectOffset(5, 5, 5, 5)
|
|
};
|
|
}
|
|
|
|
private void DrawDebugPanel()
|
|
{
|
|
var rect = new Rect(
|
|
Screen.width - DEBUG_PANEL_WIDTH - DEBUG_PANEL_MARGIN,
|
|
DEBUG_PANEL_MARGIN,
|
|
DEBUG_PANEL_WIDTH,
|
|
Screen.height - (DEBUG_PANEL_MARGIN * 2)
|
|
);
|
|
|
|
GUI.Box(rect, "");
|
|
GUILayout.BeginArea(rect);
|
|
|
|
GUI.backgroundColor = Color.black;
|
|
GUILayout.Label("Raycast Debug Info", _headerStyle);
|
|
|
|
DrawPerformanceSection();
|
|
DrawCohtmlSection();
|
|
DrawUnityUISection();
|
|
DrawSelectableSection();
|
|
DrawInteractionSection();
|
|
DrawWaterSection();
|
|
DrawTelepathicSection();
|
|
DrawWorldHitSection();
|
|
|
|
GUILayout.EndArea();
|
|
}
|
|
|
|
private void DrawPerformanceSection()
|
|
{
|
|
GUI.backgroundColor = TIMING_COLOR;
|
|
GUILayout.BeginVertical(_boxStyle);
|
|
GUILayout.Label("Performance", _headerStyle);
|
|
DrawLabel("Last Raycast", $"{_lastRaycastTime:F3} ms");
|
|
DrawLabel("Average (1s)", $"{_rollingAverageTime:F3} ms");
|
|
DrawLabel("Min", $"{_minRaycastTime:F3} ms");
|
|
DrawLabel("Max", $"{_maxRaycastTime:F3} ms");
|
|
GUILayout.EndVertical();
|
|
}
|
|
|
|
private void DrawCohtmlSection()
|
|
{
|
|
if (!_lastResult.hitCohtml) return;
|
|
|
|
GUI.backgroundColor = COHTML_COLOR;
|
|
GUILayout.BeginVertical(_boxStyle);
|
|
GUILayout.Label("COHTML Hit", _headerStyle);
|
|
DrawLabel("View", _lastResult.hitCohtmlView.name);
|
|
DrawLabel("Coords", _lastResult.hitCohtmlCoords.ToString());
|
|
GUILayout.EndVertical();
|
|
}
|
|
|
|
private void DrawUnityUISection()
|
|
{
|
|
if (!_lastResult.hitUnityUi || _lastResult.hitCanvasElement == null) return;
|
|
|
|
GUI.backgroundColor = UNITY_UI_COLOR;
|
|
GUILayout.BeginVertical(_boxStyle);
|
|
GUILayout.Label("Unity UI Hit", _headerStyle);
|
|
|
|
var canvasElement = _lastResult.hitCanvasElement;
|
|
var gameObject = canvasElement as MonoBehaviour;
|
|
|
|
DrawLabel("Canvas Element", gameObject != null ? gameObject.name : "Unknown");
|
|
DrawLabel("Element Type", canvasElement.GetType().Name);
|
|
|
|
if (gameObject != null)
|
|
{
|
|
DrawLabel("GameObject", gameObject.gameObject.name);
|
|
|
|
if (gameObject.transform.parent != null)
|
|
DrawLabel("Parent", gameObject.transform.parent.name);
|
|
}
|
|
|
|
GUILayout.EndVertical();
|
|
}
|
|
|
|
private void DrawSelectableSection()
|
|
{
|
|
if (_lastResult.hitSelectable == null) return;
|
|
|
|
GUI.backgroundColor = SELECTABLE_COLOR;
|
|
GUILayout.BeginVertical(_boxStyle);
|
|
GUILayout.Label("UI Selectable", _headerStyle);
|
|
DrawLabel("Selectable", _lastResult.hitSelectable.name);
|
|
DrawLabel("Selectable Type", _lastResult.hitSelectable.GetType().Name);
|
|
DrawLabel("Is Interactable", _lastResult.hitSelectable.interactable.ToString());
|
|
DrawLabel("Navigation Mode", _lastResult.hitSelectable.navigation.mode.ToString());
|
|
|
|
if (_lastResult.hitSelectable is Toggle toggle)
|
|
DrawLabel("Toggle State", toggle.isOn.ToString());
|
|
else if (_lastResult.hitSelectable is Slider slider)
|
|
DrawLabel("Slider Value", slider.value.ToString("F2"));
|
|
else if (_lastResult.hitSelectable is Scrollbar scrollbar)
|
|
DrawLabel("Scrollbar Value", scrollbar.value.ToString("F2"));
|
|
|
|
GUILayout.EndVertical();
|
|
}
|
|
|
|
private void DrawInteractionSection()
|
|
{
|
|
if (!_lastResult.hitPickupable && !_lastResult.hitInteractable) return;
|
|
|
|
GUI.backgroundColor = INTERACT_COLOR;
|
|
GUILayout.BeginVertical(_boxStyle);
|
|
GUILayout.Label("Interaction", _headerStyle);
|
|
if (_lastResult.hitPickupable)
|
|
DrawLabel("Pickupable", _lastResult.hitPickupable.name);
|
|
if (_lastResult.hitInteractable)
|
|
DrawLabel("Interactable", _lastResult.hitInteractable.name);
|
|
DrawLabel("Is Proximity", _lastResult.isProximityHit.ToString());
|
|
GUILayout.EndVertical();
|
|
}
|
|
|
|
private void DrawWaterSection()
|
|
{
|
|
if (!_lastResult.hitWater || !_lastResult.waterHit.HasValue) return;
|
|
|
|
GUI.backgroundColor = WATER_COLOR;
|
|
GUILayout.BeginVertical(_boxStyle);
|
|
GUILayout.Label("Water Surface", _headerStyle);
|
|
DrawLabel("Hit Point", _lastResult.waterHit.Value.point.ToString("F2"));
|
|
DrawLabel("Surface Normal", _lastResult.waterHit.Value.normal.ToString("F2"));
|
|
GUILayout.EndVertical();
|
|
}
|
|
|
|
private void DrawTelepathicSection()
|
|
{
|
|
if (!_lastResult.hasTelepathicGrabCandidate) return;
|
|
|
|
GUI.backgroundColor = TELEPATHIC_COLOR;
|
|
GUILayout.BeginVertical(_boxStyle);
|
|
GUILayout.Label("Telepathic Grab", _headerStyle);
|
|
DrawLabel("Target", _lastResult.telepathicPickupable.name);
|
|
DrawLabel("Grab Point", _lastResult.telepathicGrabPoint.ToString("F2"));
|
|
GUILayout.EndVertical();
|
|
}
|
|
|
|
private void DrawWorldHitSection()
|
|
{
|
|
if (_lastResult.hitCohtml ||
|
|
_lastResult.hitPickupable ||
|
|
_lastResult.hitInteractable ||
|
|
_lastResult.hitUnityUi ||
|
|
!_lastResult.hitWorld ||
|
|
_lastResult.hit.collider == null) return;
|
|
|
|
GUI.backgroundColor = Color.grey;
|
|
GUILayout.BeginVertical(_boxStyle);
|
|
GUILayout.Label("World Hit", _headerStyle);
|
|
DrawLabel("Object", _lastResult.hit.collider.name);
|
|
DrawLabel("Distance", _lastResult.hit.distance.ToString("F2"));
|
|
DrawLabel("Point", _lastResult.hit.point.ToString("F2"));
|
|
GUILayout.EndVertical();
|
|
}
|
|
|
|
private void DrawLabel(string label, string value)
|
|
{
|
|
GUILayout.Label($"{label}: {value}", _labelStyle);
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
} |