Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updated project configuration checker window #6286

Original file line number Diff line number Diff line change
Expand Up @@ -523,7 +523,7 @@ private void FindShaders()

private bool IsHololensTargeted()
{
return PerfTarget == PerformanceTarget.AR_Headsets && EditorUserBuildSettings.activeBuildTarget == BuildTarget.WSAPlayer;
return PerfTarget == PerformanceTarget.AR_Headsets && MixedRealityOptimizeUtils.IsBuildTargetUWP();
}

private Texture GetTitleIcon(bool isValid)
Expand Down
8 changes: 8 additions & 0 deletions Assets/MixedRealityToolkit/Inspectors/Setup.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.

using Microsoft.MixedReality.Toolkit.Editor;
using UnityEditor;
using UnityEditor.Build;
using UnityEngine;

namespace Microsoft.MixedReality.Toolkit.Utilities.Editor
{
/// <summary>
/// Editor runtime controller for showing Project Configuration window and performance checks logging in current Unity project
/// </summary>
[InitializeOnLoad]
public class MixedRealityEditorSettings : IActiveBuildTargetChanged
{
private const string SessionKey = "_MixedRealityToolkit_Editor_ShownSettingsPrompts";
private const string MSFT_AudioSpatializerPlugin = "MS HRTF Spatializer";

public MixedRealityEditorSettings()
{
callbackOrder = 0;
}

static MixedRealityEditorSettings()
{
// Detect when we enter player mode so we can try checking for optimal configuration
EditorApplication.playModeStateChanged += OnPlayStateModeChanged;

ShowProjectConfigurationDialog();
}

/// <inheritdoc />
public int callbackOrder { get; private set; }

/// <inheritdoc />
public void OnActiveBuildTargetChanged(BuildTarget previousTarget, BuildTarget newTarget)
{
IgnoreProjectConfigForSession = false;
}

/// <summary>
/// Session state wrapper that tracks whether to ignore checking Project Configuration for the current Unity session
/// </summary>
public static bool IgnoreProjectConfigForSession
{
get
{
return SessionState.GetBool(SessionKey, false);
}

set
{
SessionState.SetBool(SessionKey, value);
}
}

private static void OnPlayStateModeChanged(PlayModeStateChange state)
{
if (state == PlayModeStateChange.EnteredPlayMode && MixedRealityPreferences.RunOptimalConfiguration)
{
LogConfigurationWarnings();
}
}

private static void ShowProjectConfigurationDialog()
{
if (!EditorApplication.isPlayingOrWillChangePlaymode
&& !IgnoreProjectConfigForSession
&& !MixedRealityPreferences.IgnoreSettingsPrompt
&& !MixedRealityProjectConfigurator.IsProjectConfigured())
{
MixedRealityProjectConfiguratorWindow.ShowWindow();
}
}

/// <summary>
/// Checks critical project settings and suggests changes to optimize performance via logged warnings
/// </summary>
private static void LogConfigurationWarnings()
{
if (!PlayerSettings.virtualRealitySupported)
{
Debug.LogWarning("<b>Virtual reality supported</b> not enabled. Check <i>XR Settings</i> under <i>Player Settings</i>");
}

if (!MixedRealityOptimizeUtils.IsSinglePassInstanced())
{
Debug.LogWarning("XR stereo rendering mode not set to <b>Single Pass Instanced</b>. See <i>Mixed Reality Toolkit</i> > <i>Utilities</i> > <i>Optimize Window</i> tool for more information to improve performance");
}

// If targeting Windows Mixed Reality platform
if (MixedRealityOptimizeUtils.IsBuildTargetUWP())
{
if (!MixedRealityOptimizeUtils.IsDepthBufferSharingEnabled())
{
// If depth buffer sharing not enabled, advise to enable setting
Debug.LogWarning("<b>Depth Buffer Sharing</b> is not enabled to improve hologram stabilization. See <i>Mixed Reality Toolkit</i> > <i>Utilities</i> > <i>Optimize Window</i> tool for more information to improve performance");
}

if (!MixedRealityOptimizeUtils.IsWMRDepthBufferFormat16bit())
{
// If depth format is 24-bit, advise to consider 16-bit for performance.
Debug.LogWarning("<b>Depth Buffer Sharing</b> has 24-bit depth format selected. Consider using 16-bit for performance. See <i>Mixed Reality Toolkit</i> > <i>Utilities</i> > <i>Optimize Window</i> tool for more information to improve performance");
}

if (!AudioSettings.GetSpatializerPluginName().Equals(MSFT_AudioSpatializerPlugin))
{
// If using UWP, developers should use the Microsoft Audio Spatilizer plugin
Debug.LogWarning("<b>Audio Spatializer Plugin</b> not currently set to <i>" + MSFT_AudioSpatializerPlugin + "</i>. Switch to <i>" + MSFT_AudioSpatializerPlugin + "</i> under <i>Project Settings</i> > <i>Audio</i> > <i>Spatializer Plugin</i>");
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.

using Microsoft.MixedReality.Toolkit.Editor;
using System.Collections.Generic;
using UnityEditor;
using UnityEditor.Compilation;
using UnityEngine;

using MRConfig = Microsoft.MixedReality.Toolkit.Utilities.Editor.MixedRealityProjectConfigurator.Configurations;

namespace Microsoft.MixedReality.Toolkit.Utilities.Editor
{
public class MixedRealityProjectConfiguratorWindow : EditorWindow
{
private Dictionary<MRConfig, bool> trackToggles = new Dictionary<MRConfig, bool>()
{
{MRConfig.ForceTextSerialization, true },
{MRConfig.VisibleMetaFiles, true },
{MRConfig.VirtualRealitySupported, true },
{MRConfig.SinglePassInstancing, true },
{MRConfig.SpatialAwarenessLayer, true },
{MRConfig.MicrophoneCapability, true },
{MRConfig.InternetClientCapability, true },
{MRConfig.SpatialPerceptionCapability, true },
#if UNITY_2019_3_OR_NEWER
{MRConfig.EyeTrackingCapability, true },
#endif
};

private const string WindowKey = "_MixedRealityToolkit_Editor_MixedRealityProjectConfiguratorWindow";
private const float Default_Window_Height = 640.0f;
private const float Default_Window_Width = 400.0f;

private readonly GUIContent ApplyButtonContent = new GUIContent("Apply", "Apply configurations to this Unity Project");
private readonly GUIContent LaterButtonContent = new GUIContent("Later", "Do not show this popup notification until next session");
private readonly GUIContent IgnoreButtonContent = new GUIContent("Ignore", "Modify this preference under Edit > Project Settings > MRTK");

private bool showConfigurations = false;

/// <summary>
/// Show the MRTK Project Configurator utility window or focus if already opened
/// </summary>
[MenuItem("Mixed Reality Toolkit/Utilities/Configure Unity Project", false, 499)]
public static void ShowWindow()
{
// There should be only one configurator window open as a "popup". If already open, then just force focus on our instance
if (IsOpen)
{
Instance.Focus();
}
else
{
var window = ScriptableObject.CreateInstance<MixedRealityProjectConfiguratorWindow>();
window.titleContent = new GUIContent("MRTK Project Configurator", EditorGUIUtility.IconContent("_Popup").image);
window.position = new Rect(Screen.width / 2.0f, Screen.height / 2.0f, Default_Window_Height, Default_Window_Width);
window.ShowUtility();
}
}

public static MixedRealityProjectConfiguratorWindow Instance { get; private set; }

public static bool IsOpen
{
get { return Instance != null; }
}

private void OnEnable()
{
Instance = this;

CompilationPipeline.assemblyCompilationStarted += CompilationPipeline_assemblyCompilationStarted;
}

private void CompilationPipeline_assemblyCompilationStarted(string obj)
{
// There should be only one popup window which is generally tracked by IsOpen
// However, when recompiling, Unity will call OnDestroy for this window but not actually destroy the editor window
// This ensure we have a clean close on recompiles when this EditorWindow was open beforehand
Close();
}

private void OnGUI()
{
MixedRealityInspectorUtility.RenderMixedRealityToolkitLogo();

RenderChoiceDialog();

EditorGUILayout.Space();

showConfigurations = EditorGUILayout.Foldout(showConfigurations, "Modify Configurations", true);
if (showConfigurations)
{
RenderConfigurations();
}
}

private void RenderChoiceDialog()
{
const string dialogTitle = "Apply Default Settings?";
const string dialogContent = "The Mixed Reality Toolkit would like to auto-apply useful settings to this Unity project";
EditorGUILayout.LabelField(dialogTitle, EditorStyles.boldLabel);
EditorGUILayout.LabelField(dialogContent);

using (new EditorGUILayout.HorizontalScope())
{
if (GUILayout.Button(ApplyButtonContent))
{
ApplyConfigurations();
Close();
}

if (GUILayout.Button(LaterButtonContent))
{
MixedRealityEditorSettings.IgnoreProjectConfigForSession = true;
Close();
}

if (GUILayout.Button(IgnoreButtonContent))
{
MixedRealityPreferences.IgnoreSettingsPrompt = true;
Close();
}
}
}

private void RenderConfigurations()
{
EditorGUILayout.LabelField("Enabled options will be applied to the project. Disabled items are already properly configured.");
EditorGUILayout.Space();

EditorGUILayout.LabelField("Project Settings", EditorStyles.boldLabel);
RenderToggle(MRConfig.ForceTextSerialization, "Enable Force Text Serialization");
RenderToggle(MRConfig.VisibleMetaFiles, "Enable Visible meta files");
RenderToggle(MRConfig.VirtualRealitySupported, "Enable VR Supported");
RenderToggle(MRConfig.SinglePassInstancing, "Set Single Pass Instanced rendering path");
RenderToggle(MRConfig.SpatialAwarenessLayer, "Set Default Spatial Awareness Layer");

EditorGUILayout.Space();

if (MixedRealityOptimizeUtils.IsBuildTargetUWP())
{
EditorGUILayout.LabelField("UWP Capabilities", EditorStyles.boldLabel);

RenderToggle(MRConfig.MicrophoneCapability, "Enable Microphone Capability");
RenderToggle(MRConfig.InternetClientCapability, "Enable Internet Client Capability");
RenderToggle(MRConfig.SpatialPerceptionCapability, "Enable Spatial Perception Capability");
#if UNITY_2019_3_OR_NEWER
RenderToggle(MRConfig.EyeTrackingCapability, "Enable Eye Gaze Input Capability");
#endif
}
else
{
trackToggles[MRConfig.MicrophoneCapability] = false;
trackToggles[MRConfig.InternetClientCapability] = false;
trackToggles[MRConfig.SpatialPerceptionCapability] = false;
#if UNITY_2019_3_OR_NEWER
trackToggles[MRConfig.EyeTrackingCapability] = false;
#endif
}
}

private void ApplyConfigurations()
{
var configurationFilter = new HashSet<MRConfig>();
foreach (var item in trackToggles)
{
if (item.Value)
{
configurationFilter.Add(item.Key);
}
}

MixedRealityProjectConfigurator.ConfigureProject(configurationFilter);
}

private void RenderToggle(MRConfig configKey, string title)
{
bool configured = MixedRealityProjectConfigurator.IsConfigured(configKey);
using (new EditorGUI.DisabledGroupScope(configured))
{
if (configured)
{
EditorGUILayout.LabelField(new GUIContent(title, InspectorUIUtility.SuccessIcon));
trackToggles[configKey] = false;
}
else
{
trackToggles[configKey] = EditorGUILayout.ToggleLeft(title, trackToggles[configKey]);
}
}
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.