mixedreality/com.microsoft.mixedreality..../Services/DiagnosticsSystem/MixedRealityDiagnosticsSyst...

417 lines
13 KiB
C#

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using System.Runtime.CompilerServices;
using Unity.Profiling;
using UnityEngine;
using UnityEngine.EventSystems;
[assembly: InternalsVisibleTo("Microsoft.MixedReality.Toolkit.Tests.PlayModeTests")]
namespace Microsoft.MixedReality.Toolkit.Diagnostics
{
/// <summary>
/// The default implementation of the <see cref="Microsoft.MixedReality.Toolkit.Diagnostics.IMixedRealityDiagnosticsSystem"/>
/// </summary>
[HelpURL("https://docs.microsoft.com/windows/mixed-reality/mrtk-unity/features/diagnostics/diagnostics-system-getting-started")]
public class MixedRealityDiagnosticsSystem : BaseCoreSystem, IMixedRealityDiagnosticsSystem
{
/// <summary>
/// Constructor.
/// </summary>
/// <param name="registrar">The <see cref="IMixedRealityServiceRegistrar"/> instance that loaded the service.</param>
/// <param name="profile">The configuration profile for the service.</param>
[System.Obsolete("This constructor is obsolete (registrar parameter is no longer required) and will be removed in a future version of the Microsoft Mixed Reality Toolkit.")]
public MixedRealityDiagnosticsSystem(
IMixedRealityServiceRegistrar registrar,
MixedRealityDiagnosticsProfile profile) : this(profile)
{
Registrar = registrar;
}
/// <summary>
/// Constructor.
/// </summary>
/// <param name="profile">The configuration profile for the service.</param>
public MixedRealityDiagnosticsSystem(
MixedRealityDiagnosticsProfile profile) : base(profile)
{ }
/// <inheritdoc/>
public override string Name { get; protected set; } = "Mixed Reality Diagnostics System";
/// <summary>
/// The parent object under which all visualization game objects will be placed.
/// </summary>
private GameObject diagnosticVisualizationParent = null;
/// <summary>
/// Creates the diagnostic visualizations and parents them so that the scene hierarchy does not get overly cluttered.
/// </summary>
private void CreateVisualizations()
{
diagnosticVisualizationParent = new GameObject("Diagnostics");
diagnosticVisualizationParent.AddComponent<DiagnosticsSystemVoiceControls>();
MixedRealityPlayspace.AddChild(diagnosticVisualizationParent.transform);
diagnosticVisualizationParent.SetActive(ShowDiagnostics);
// visual profiler settings
visualProfiler = diagnosticVisualizationParent.AddComponent<MixedRealityToolkitVisualProfiler>();
visualProfiler.WindowParent = diagnosticVisualizationParent.transform;
visualProfiler.IsVisible = ShowProfiler;
visualProfiler.FrameInfoVisible = ShowFrameInfo;
visualProfiler.MemoryStatsVisible = ShowMemoryStats;
visualProfiler.FrameSampleRate = FrameSampleRate;
visualProfiler.WindowAnchor = WindowAnchor;
visualProfiler.WindowOffset = WindowOffset;
visualProfiler.WindowScale = WindowScale;
visualProfiler.WindowFollowSpeed = WindowFollowSpeed;
visualProfiler.ShowProfilerDuringMRC = ShowProfilerDuringMRC;
}
private MixedRealityToolkitVisualProfiler visualProfiler = null;
#region IMixedRealityService
/// <inheritdoc />
public override void Initialize()
{
if (!Application.isPlaying) { return; }
MixedRealityDiagnosticsProfile profile = ConfigurationProfile as MixedRealityDiagnosticsProfile;
if (profile == null) { return; }
base.Initialize();
eventData = new DiagnosticsEventData(EventSystem.current);
// Apply profile settings
ShowDiagnostics = profile.ShowDiagnostics;
ShowProfiler = profile.ShowProfiler;
ShowFrameInfo = profile.ShowFrameInfo;
ShowMemoryStats = profile.ShowMemoryStats;
FrameSampleRate = profile.FrameSampleRate;
WindowAnchor = profile.WindowAnchor;
WindowOffset = profile.WindowOffset;
WindowScale = profile.WindowScale;
WindowFollowSpeed = profile.WindowFollowSpeed;
ShowProfilerDuringMRC = profile.ShowProfilerDuringMRC;
CreateVisualizations();
}
/// <inheritdoc />
public override void Destroy()
{
if (diagnosticVisualizationParent != null)
{
if (Application.isEditor)
{
Object.DestroyImmediate(diagnosticVisualizationParent);
}
else
{
diagnosticVisualizationParent.transform.DetachChildren();
Object.Destroy(diagnosticVisualizationParent);
}
diagnosticVisualizationParent = null;
}
base.Destroy();
}
#endregion IMixedRealityService
#region IMixedRealityDiagnosticsSystem
private MixedRealityDiagnosticsProfile diagnosticsSystemProfile = null;
/// <inheritdoc/>
public MixedRealityDiagnosticsProfile DiagnosticsSystemProfile
{
get
{
if (diagnosticsSystemProfile == null)
{
diagnosticsSystemProfile = ConfigurationProfile as MixedRealityDiagnosticsProfile;
}
return diagnosticsSystemProfile;
}
}
private bool showDiagnostics;
/// <inheritdoc />
public bool ShowDiagnostics
{
get { return showDiagnostics; }
set
{
if (value != showDiagnostics)
{
showDiagnostics = value;
// The voice commands are handled by the diagnosticVisualizationParent GameObject, we cannot disable the parent
// or we lose the ability to re-show the visualizations. Instead, disable each visualization as appropriate.
if (ShowProfiler)
{
visualProfiler.IsVisible = value;
}
}
}
}
private bool showProfiler;
/// <inheritdoc />
public bool ShowProfiler
{
get
{
return showProfiler;
}
set
{
if (value != showProfiler)
{
showProfiler = value;
if ((visualProfiler != null) && ShowDiagnostics)
{
visualProfiler.IsVisible = value;
}
}
}
}
private bool showFrameInfo;
/// <inheritdoc />
public bool ShowFrameInfo
{
get
{
return showFrameInfo;
}
set
{
if (value != showFrameInfo)
{
showFrameInfo = value;
if (visualProfiler != null)
{
visualProfiler.FrameInfoVisible = value;
}
}
}
}
private bool showMemoryStats;
/// <inheritdoc />
public bool ShowMemoryStats
{
get
{
return showMemoryStats;
}
set
{
if (value != showMemoryStats)
{
showMemoryStats = value;
if (visualProfiler != null)
{
visualProfiler.MemoryStatsVisible = value;
}
}
}
}
private float frameSampleRate = 0.1f;
/// <inheritdoc />
public float FrameSampleRate
{
get
{
return frameSampleRate;
}
set
{
if (!Mathf.Approximately(frameSampleRate, value))
{
frameSampleRate = value;
if (visualProfiler != null)
{
visualProfiler.FrameSampleRate = frameSampleRate;
}
}
}
}
#endregion IMixedRealityDiagnosticsSystem
#region IMixedRealityEventSource
private DiagnosticsEventData eventData;
/// <inheritdoc />
public uint SourceId => (uint)SourceName.GetHashCode();
/// <inheritdoc />
public string SourceName => "Mixed Reality Diagnostics System";
/// <inheritdoc />
public new bool Equals(object x, object y) => false;
/// <inheritdoc />
public int GetHashCode(object obj) => SourceName.GetHashCode();
internal void RaiseDiagnosticsChanged()
{
eventData.Initialize(this);
HandleEvent(eventData, OnDiagnosticsChanged);
}
private static readonly ProfilerMarker OnDiagnosticsChangedPerfMarker = new ProfilerMarker("[MRTK] MixedRealityDiagnosticsSystem.OnDiagnosticsChanged - Raise event");
/// <summary>
/// Event sent whenever the diagnostics visualization changes.
/// </summary>
private static readonly ExecuteEvents.EventFunction<IMixedRealityDiagnosticsHandler> OnDiagnosticsChanged =
delegate (IMixedRealityDiagnosticsHandler handler, BaseEventData eventData)
{
using (OnDiagnosticsChangedPerfMarker.Auto())
{
var diagnosticsEventsData = ExecuteEvents.ValidateEventData<DiagnosticsEventData>(eventData);
handler.OnDiagnosticSettingsChanged(diagnosticsEventsData);
}
};
#endregion IMixedRealityEventSource
private TextAnchor windowAnchor = TextAnchor.LowerCenter;
/// <summary>
/// What part of the view port to anchor the window to.
/// </summary>
public TextAnchor WindowAnchor
{
get { return windowAnchor; }
set
{
if (value != windowAnchor)
{
windowAnchor = value;
if (visualProfiler != null)
{
visualProfiler.WindowAnchor = windowAnchor;
}
}
}
}
private Vector2 windowOffset = new Vector2(0.1f, 0.1f);
/// <summary>
/// The offset from the view port center applied based on the window anchor selection.
/// </summary>
public Vector2 WindowOffset
{
get { return windowOffset; }
set
{
if (value != windowOffset)
{
windowOffset = value;
if (visualProfiler != null)
{
visualProfiler.WindowOffset = windowOffset;
}
}
}
}
private float windowScale = 1.0f;
/// <summary>
/// Use to scale the window size up or down, can simulate a zooming effect.
/// </summary>
public float WindowScale
{
get { return windowScale; }
set
{
if (value != windowScale)
{
windowScale = value;
if (visualProfiler != null)
{
visualProfiler.WindowScale = windowScale;
}
}
}
}
private float windowFollowSpeed = 5.0f;
/// <summary>
/// How quickly to interpolate the window towards its target position and rotation.
/// </summary>
public float WindowFollowSpeed
{
get { return windowFollowSpeed; }
set
{
if (value != windowFollowSpeed)
{
windowFollowSpeed = value;
if (visualProfiler != null)
{
visualProfiler.WindowFollowSpeed = windowFollowSpeed;
}
}
}
}
private bool showProfilerDuringMRC = false;
/// <summary>
/// If the diagnostics profiler should be visible while a mixed reality capture is happening on HoloLens.
/// </summary>
/// <remarks>This is not usually recommended, as MRC can have an effect on an app's frame rate.</remarks>
public bool ShowProfilerDuringMRC
{
get { return showProfilerDuringMRC; }
set
{
if (value != showProfilerDuringMRC)
{
showProfilerDuringMRC = value;
if (visualProfiler != null)
{
visualProfiler.ShowProfilerDuringMRC = showProfilerDuringMRC;
}
}
}
}
}
}