Skip to content

Commit 3a0af8d

Browse files
authored
Merge pull request #6315 from Troy-Ferrell/users/trferrel/project-preferences
Create serializable Project Preferences
2 parents 0dcab03 + e888c7a commit 3a0af8d

21 files changed

+838
-231
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ Assets/TextMesh Pro/
6767
Assets/StreamingAssets/GltfModels/
6868
Assets/StreamingAssets/GltfModels.meta
6969
Assets/StreamingAssets.meta
70+
Assets/MixedRealityToolkit.Generated/*
7071

7172
/mrtk_log_mostRecentET.csv
7273

Assets/MixedRealityToolkit.Tests/EditModeTests/Core/MixedRealityToolkitFilesTests.cs

Lines changed: 101 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,42 +3,100 @@
33

44
using Microsoft.MixedReality.Toolkit.Utilities.Editor;
55
using NUnit.Framework;
6+
using System;
7+
using System.Collections;
8+
using System.Collections.Generic;
9+
using System.IO;
610
using System.Linq;
11+
using UnityEngine.TestTools;
712

813
namespace Microsoft.MixedReality.Toolkit.Tests.Core
914
{
1015
// Tests for the MixedRealityToolkitFiles utility class
1116
public class MixedRealityToolkitFilesTests
1217
{
13-
[Test]
14-
public void TestGetDirectories()
18+
/// <summary>
19+
/// Validate that each module has a corresponding found folder (excluding None/AdHocTesting)
20+
/// </summary>
21+
[UnityTest]
22+
public IEnumerator TestGetDirectories()
1523
{
16-
MixedRealityToolkitModuleType[] moduleTypes = new MixedRealityToolkitModuleType[]
24+
yield return RefreshFiles();
25+
26+
foreach (var moduleType in GetTestModulesTypes())
1727
{
18-
MixedRealityToolkitModuleType.Core,
19-
MixedRealityToolkitModuleType.Providers,
20-
MixedRealityToolkitModuleType.Services,
21-
MixedRealityToolkitModuleType.SDK,
22-
MixedRealityToolkitModuleType.Examples,
23-
MixedRealityToolkitModuleType.Tests,
24-
MixedRealityToolkitModuleType.Extensions,
25-
MixedRealityToolkitModuleType.Tools,
26-
};
28+
var dirs = MixedRealityToolkitFiles.GetDirectories(moduleType);
29+
Assert.IsNotNull(dirs, $"Directory list was null for module type {moduleType.ToString()}");
30+
Assert.IsNotEmpty(dirs, $"Directory list was empty for module type {moduleType.ToString()}");
31+
}
32+
}
2733

28-
MixedRealityToolkitFiles.RefreshFolders();
29-
foreach (var moduleType in moduleTypes)
34+
/// <summary>
35+
/// Test that the MapModulePath API works for each Module Type
36+
/// </summary>
37+
[UnityTest]
38+
public IEnumerator TestMapModulePath()
39+
{
40+
yield return RefreshFiles();
41+
42+
foreach (var moduleType in GetTestModulesTypes())
3043
{
31-
// Validate that each module has a corresponding found folder
32-
Assert.IsTrue(MixedRealityToolkitFiles.GetDirectories(moduleType).Any());
44+
Assert.IsNotNull(MixedRealityToolkitFiles.MapModulePath(moduleType), $"Module Path was null for module type {moduleType.ToString()}");
45+
}
46+
}
47+
48+
/// <summary>
49+
/// Test the ModuleType.None and that no items are found
50+
/// </summary>
51+
[UnityTest]
52+
public IEnumerator TestNoneDirectory()
53+
{
54+
yield return RefreshFiles();
55+
56+
var dirs = MixedRealityToolkitFiles.GetDirectories(MixedRealityToolkitModuleType.None);
57+
Assert.IsNull(dirs, $"Directory list should be null for module type {MixedRealityToolkitModuleType.None.ToString()}");
58+
}
59+
60+
/// <summary>
61+
/// Validate that a Non-MRTK folder is recognized still
62+
/// </summary>
63+
[UnityTest]
64+
public IEnumerator TestAdHocDirectory()
65+
{
66+
string adhocTesting = MixedRealityToolkitModuleType.AdhocTesting.ToString();
67+
string adHocFolderPath = Path.Combine(UnityEngine.Application.dataPath, adhocTesting);
68+
string adHocFolderMetaPath = Path.Combine(UnityEngine.Application.dataPath, adhocTesting + ".meta");
69+
string adHocSentinelFilePath = Path.Combine(adHocFolderPath, "MRTK." + adhocTesting + ".sentinel");
70+
71+
try
72+
{
73+
Directory.CreateDirectory(adHocFolderPath);
74+
using (var file = File.Create(adHocSentinelFilePath))
75+
{
76+
yield return RefreshFiles();
77+
78+
var moduleType = MixedRealityToolkitModuleType.AdhocTesting;
79+
var dirs = MixedRealityToolkitFiles.GetDirectories(moduleType);
80+
Assert.IsNotNull(dirs, $"Directory list was null for module type {moduleType.ToString()}");
81+
Assert.IsNotEmpty(dirs, $"Directory list was empty for module type {moduleType.ToString()}");
82+
}
83+
}
84+
finally
85+
{
86+
// Clean up
87+
Directory.Delete(adHocFolderPath, true);
88+
File.Delete(adHocFolderMetaPath);
3389
}
3490
}
3591

3692
/// <summary>
3793
/// Validates that MixedRealityToolkitFiles is able to reason over MRTK folders when placed in the root Asset directory.
3894
/// </summary>
39-
[Test]
40-
public void TestRootAssetFolderResolution()
95+
[UnityTest]
96+
public IEnumerator TestRootAssetFolderResolution()
4197
{
98+
yield return RefreshFiles();
99+
42100
string resolvedPath = MixedRealityToolkitFiles.MapRelativeFilePathToAbsolutePath("Inspectors\\Data\\EditorWindowOptions.json");
43101
Assert.IsNotNull(resolvedPath);
44102
}
@@ -48,5 +106,30 @@ public void CleanupTests()
48106
{
49107
TestUtilities.EditorTearDownScenes();
50108
}
109+
110+
#region Test Helpers
111+
112+
private static IEnumerator RefreshFiles()
113+
{
114+
MixedRealityToolkitFiles.RefreshFolders();
115+
var task = MixedRealityToolkitFiles.WaitForFolderRefresh();
116+
while (!task.IsCompleted)
117+
{
118+
yield return null;
119+
}
120+
121+
Assert.IsTrue(MixedRealityToolkitFiles.AreFoldersAvailable);
122+
}
123+
124+
private static IEnumerable<MixedRealityToolkitModuleType> GetTestModulesTypes()
125+
{
126+
var excludeTypes = new[] { MixedRealityToolkitModuleType.None, MixedRealityToolkitModuleType.AdhocTesting };
127+
128+
return Enum.GetValues(typeof(MixedRealityToolkitModuleType))
129+
.Cast<MixedRealityToolkitModuleType>()
130+
.Where(t => !excludeTypes.Contains(t));
131+
}
132+
133+
#endregion
51134
}
52135
}
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License. See LICENSE in the project root for license information.
3+
4+
using Microsoft.MixedReality.Toolkit.Utilities.Editor;
5+
using NUnit.Framework;
6+
using System.Collections.Generic;
7+
using UnityEngine;
8+
9+
namespace Microsoft.MixedReality.Toolkit.Tests.Core.Utilities.Editor
10+
{
11+
/// <summary>
12+
/// Test structure to test <see cref="Microsoft.MixedReality.Toolkit.Utilities.Editor.ProjectPreferences"/>
13+
/// </summary>
14+
public class ProjectPreferencesTest : MonoBehaviour
15+
{
16+
private const string BaseKey = "ProjectPreferencesTest_";
17+
private static Dictionary<string, object> TestData = new Dictionary<string, object>
18+
{
19+
{ BaseKey + typeof(bool).Name, (object)true },
20+
{ BaseKey + typeof(float).Name, (object)2.3f },
21+
{ BaseKey + typeof(int).Name, (object)5 },
22+
{ BaseKey + typeof(string).Name, (object)"TEST"},
23+
};
24+
25+
/// <summary>
26+
/// Test basic ProjectPreferences uses of setting a key and then retrieving that item for various data types
27+
/// </summary>
28+
[Test]
29+
public void TestNewPreferences()
30+
{
31+
try
32+
{
33+
foreach (var test in TestData)
34+
{
35+
if (test.Value is float)
36+
{
37+
var value = (float)test.Value;
38+
ProjectPreferences.Set(test.Key, value);
39+
Assert.AreEqual(value, ProjectPreferences.Get(test.Key, 0f));
40+
}
41+
else if (test.Value is bool)
42+
{
43+
var value = (bool)test.Value;
44+
ProjectPreferences.Set(test.Key, value);
45+
Assert.AreEqual(value, ProjectPreferences.Get(test.Key, false));
46+
}
47+
else if (test.Value is int)
48+
{
49+
var value = (int)test.Value;
50+
ProjectPreferences.Set(test.Key, value);
51+
Assert.AreEqual(value, ProjectPreferences.Get(test.Key, 0));
52+
}
53+
else if (test.Value is string)
54+
{
55+
var value = (string)test.Value;
56+
ProjectPreferences.Set(test.Key, value);
57+
Assert.AreEqual(value, ProjectPreferences.Get(test.Key, string.Empty));
58+
}
59+
}
60+
}
61+
finally
62+
{
63+
foreach (var test in TestData)
64+
{
65+
Cleanup(test.Key, test.Value);
66+
}
67+
}
68+
}
69+
70+
/// <summary>
71+
/// Validate that the default value provided with Get is returned for new prefernce entries
72+
/// </summary>
73+
[Test]
74+
public void TestDefaultValues()
75+
{
76+
try
77+
{
78+
foreach (var test in TestData)
79+
{
80+
if (test.Value is float)
81+
{
82+
var value = (float)test.Value;
83+
Assert.AreEqual(value, ProjectPreferences.Get(test.Key, value));
84+
}
85+
else if (test.Value is bool)
86+
{
87+
var value = (bool)test.Value;
88+
Assert.AreEqual(value, ProjectPreferences.Get(test.Key, value));
89+
}
90+
else if (test.Value is int)
91+
{
92+
var value = (int)test.Value;
93+
Assert.AreEqual(value, ProjectPreferences.Get(test.Key, value));
94+
}
95+
else if (test.Value is string)
96+
{
97+
var value = (string)test.Value;
98+
Assert.AreEqual(value, ProjectPreferences.Get(test.Key, value));
99+
}
100+
}
101+
}
102+
finally
103+
{
104+
foreach (var test in TestData)
105+
{
106+
Cleanup(test.Key, test.Value);
107+
}
108+
}
109+
}
110+
111+
private void Cleanup(string key, object value)
112+
{
113+
if (value is float)
114+
{
115+
ProjectPreferences.RemoveFloat(key);
116+
}
117+
else if (value is bool)
118+
{
119+
ProjectPreferences.RemoveBool(key);
120+
}
121+
else if (value is int)
122+
{
123+
ProjectPreferences.RemoveInt(key);
124+
}
125+
else if (value is string)
126+
{
127+
ProjectPreferences.RemoveString(key);
128+
}
129+
}
130+
}
131+
}

Assets/MixedRealityToolkit.Tests/EditModeTests/Core/Utilities/ProjectPreferencesTest.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Assets/MixedRealityToolkit/Inspectors/Profiles/BaseMixedRealityProfileInspector.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ private static string GetSubProfileDropdownKey(SerializedProperty property)
202202
/// </summary>
203203
protected static bool IsProfileLock(BaseMixedRealityProfile profile)
204204
{
205-
return MixedRealityPreferences.LockProfiles && !profile.IsCustomProfile;
205+
return MixedRealityProjectPreferences.LockProfiles && !profile.IsCustomProfile;
206206
}
207207
}
208208
}

Assets/MixedRealityToolkit/Inspectors/Setup/MixedRealityEditorSettings.cs

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -44,20 +44,13 @@ public void OnActiveBuildTargetChanged(BuildTarget previousTarget, BuildTarget n
4444
/// </summary>
4545
public static bool IgnoreProjectConfigForSession
4646
{
47-
get
48-
{
49-
return SessionState.GetBool(SessionKey, false);
50-
}
51-
52-
set
53-
{
54-
SessionState.SetBool(SessionKey, value);
55-
}
47+
get => SessionState.GetBool(SessionKey, false);
48+
set => SessionState.SetBool(SessionKey, value);
5649
}
5750

5851
private static void OnPlayStateModeChanged(PlayModeStateChange state)
5952
{
60-
if (state == PlayModeStateChange.EnteredPlayMode && MixedRealityPreferences.RunOptimalConfiguration)
53+
if (state == PlayModeStateChange.EnteredPlayMode && MixedRealityProjectPreferences.RunOptimalConfiguration)
6154
{
6255
LogConfigurationWarnings();
6356
}
@@ -67,7 +60,7 @@ private static void ShowProjectConfigurationDialog()
6760
{
6861
if (!EditorApplication.isPlayingOrWillChangePlaymode
6962
&& !IgnoreProjectConfigForSession
70-
&& !MixedRealityPreferences.IgnoreSettingsPrompt
63+
&& !MixedRealityProjectPreferences.IgnoreSettingsPrompt
7164
&& !MixedRealityProjectConfigurator.IsProjectConfigured())
7265
{
7366
MixedRealityProjectConfiguratorWindow.ShowWindow();

Assets/MixedRealityToolkit/Inspectors/Setup/MixedRealityProjectConfiguratorWindow.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ private void RenderChoiceDialog()
127127

128128
if (GUILayout.Button(IgnoreButtonContent))
129129
{
130-
MixedRealityPreferences.IgnoreSettingsPrompt = true;
130+
MixedRealityProjectPreferences.IgnoreSettingsPrompt = true;
131131
Close();
132132
}
133133
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License. See LICENSE in the project root for license information.
3+
4+
using UnityEditor;
5+
6+
namespace Microsoft.MixedReality.Toolkit.Utilities.Editor
7+
{
8+
[CustomEditor(typeof(ProjectPreferences))]
9+
internal class ProjectPreferencesInspector : UnityEditor.Editor
10+
{
11+
public override void OnInspectorGUI()
12+
{
13+
EditorGUILayout.HelpBox("Use Project Settings > MRTK to edit project preferences or interact in code via ProjectPreferences.cs", MessageType.Warning);
14+
15+
DrawDefaultInspector();
16+
}
17+
}
18+
}

Assets/MixedRealityToolkit/Inspectors/Setup/ProjectPreferencesInspector.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Assets/MixedRealityToolkit/Inspectors/Utilities/Search/MixedRealitySearchInspectorUtility.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,12 +138,12 @@ private static void DrawSearchResultInterface(UnityEngine.Object target)
138138
}
139139
}
140140

141-
if (MixedRealityPreferences.LockProfiles && !search.IsCustomProfile)
141+
if (MixedRealityProjectPreferences.LockProfiles && !search.IsCustomProfile)
142142
{
143143
EditorGUILayout.HelpBox("Clone this profile to edit default properties.", MessageType.Warning);
144144
}
145145

146-
using (new EditorGUI.DisabledGroupScope(MixedRealityPreferences.LockProfiles && !search.IsCustomProfile))
146+
using (new EditorGUI.DisabledGroupScope(MixedRealityProjectPreferences.LockProfiles && !search.IsCustomProfile))
147147
{
148148
using (new EditorGUI.IndentLevelScope(1))
149149
{

0 commit comments

Comments
 (0)