1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
|
using System;
using System.Collections.Generic;
using System.Linq;
using Unity.XR.CoreUtils.Editor;
using UnityEditor.PackageManager;
using UnityEditor.PackageManager.Requests;
using UnityEngine;
using UnityEngine.XR.Interaction.Toolkit;
#if UNITY_INPUT_SYSTEM_PROJECT_WIDE_ACTIONS
using UnityEngine.InputSystem;
#endif
namespace UnityEditor.XR.Interaction.Toolkit.Samples
{
/// <summary>
/// Unity Editor class which registers Project Validation rules for the Starter Assets sample package.
/// </summary>
class StarterAssetsSampleProjectValidation
{
const string k_Category = "XR Interaction Toolkit";
const string k_StarterAssetsSampleName = "Starter Assets";
const string k_TeleportLayerName = "Teleport";
const int k_TeleportLayerIndex = 31;
const string k_ProjectValidationSettingsPath = "Project/XR Plug-in Management/Project Validation";
const string k_ShaderGraphPackageName = "com.unity.shadergraph";
#if UNITY_INPUT_SYSTEM_PROJECT_WIDE_ACTIONS
const string k_InputSystemPackageName = "com.unity.inputsystem";
static readonly PackageVersion s_RecommendedPackageVersion = new PackageVersion("1.11.0");
const string k_InputActionAssetName = "XRI Default Input Actions";
const string k_InputActionAssetGuid = "c348712bda248c246b8c49b3db54643f";
#endif
static readonly BuildTargetGroup[] s_BuildTargetGroups =
((BuildTargetGroup[])Enum.GetValues(typeof(BuildTargetGroup))).Distinct().ToArray();
static readonly List<BuildValidationRule> s_BuildValidationRules = new List<BuildValidationRule>();
static AddRequest s_ShaderGraphPackageAddRequest;
#if UNITY_INPUT_SYSTEM_PROJECT_WIDE_ACTIONS
static AddRequest s_InputSystemPackageAddRequest;
#endif
[InitializeOnLoadMethod]
static void RegisterProjectValidationRules()
{
// In the Player Settings UI we have to delay the call one frame to let the settings provider get initialized
// since we need to access the settings asset to set the rule's non-delegate properties (FixItAutomatic).
EditorApplication.delayCall += AddRulesAndRunCheck;
}
static void AddRulesAndRunCheck()
{
if (s_BuildValidationRules.Count == 0)
{
s_BuildValidationRules.Add(
new BuildValidationRule
{
Category = k_Category,
Message = $"[{k_StarterAssetsSampleName}] Interaction Layer {k_TeleportLayerIndex} should be set to '{k_TeleportLayerName}' for teleportation locomotion.",
FixItMessage = $"XR Interaction Toolkit samples reserve Interaction Layer {k_TeleportLayerIndex} for teleportation locomotion. Set Interaction Layer {k_TeleportLayerIndex} to '{k_TeleportLayerName}' to prevent conflicts.",
HelpText = "Please note Interaction Layers are unique to the XR Interaction Toolkit and can be found in Edit > Project Settings > XR Plug-in Management > XR Interaction Toolkit",
FixItAutomatic = InteractionLayerSettings.Instance.IsLayerEmpty(k_TeleportLayerIndex) || IsInteractionLayerTeleport(),
Error = false,
CheckPredicate = IsInteractionLayerTeleport,
FixIt = () =>
{
if (InteractionLayerSettings.Instance.IsLayerEmpty(k_TeleportLayerIndex) || DisplayTeleportDialog())
InteractionLayerSettings.Instance.SetLayerNameAt(k_TeleportLayerIndex, k_TeleportLayerName);
else
SettingsService.OpenProjectSettings(XRInteractionToolkitSettingsProvider.k_SettingsPath);
},
});
s_BuildValidationRules.Add(
new BuildValidationRule
{
IsRuleEnabled = () => s_ShaderGraphPackageAddRequest == null || s_ShaderGraphPackageAddRequest.IsCompleted,
Message = $"[{k_StarterAssetsSampleName}] Shader Graph ({k_ShaderGraphPackageName}) package must be installed for materials used in this sample.",
Category = k_Category,
CheckPredicate = () => PackageVersionUtility.IsPackageInstalled(k_ShaderGraphPackageName),
FixIt = () =>
{
s_ShaderGraphPackageAddRequest = Client.Add(k_ShaderGraphPackageName);
if (s_ShaderGraphPackageAddRequest.Error != null)
{
Debug.LogError($"Package installation error: {s_ShaderGraphPackageAddRequest.Error}: {s_ShaderGraphPackageAddRequest.Error.message}");
}
},
FixItAutomatic = true,
Error = false,
});
#if UNITY_INPUT_SYSTEM_PROJECT_WIDE_ACTIONS
s_BuildValidationRules.Add(
new BuildValidationRule
{
IsRuleEnabled = () => s_InputSystemPackageAddRequest == null || s_InputSystemPackageAddRequest.IsCompleted,
Message = $"[{k_StarterAssetsSampleName}] Input System ({k_InputSystemPackageName}) package must be at version {s_RecommendedPackageVersion} or higher to use Project-wide Actions with {k_InputActionAssetName}.",
Category = k_Category,
CheckPredicate = () => InputSystem.actions == null || PackageVersionUtility.GetPackageVersion(k_InputSystemPackageName) >= s_RecommendedPackageVersion,
FixIt = () =>
{
if (s_InputSystemPackageAddRequest == null || s_InputSystemPackageAddRequest.IsCompleted)
InstallOrUpdateInputSystem();
},
HelpText = "This version added support for automatic loading of custom extensions of InputProcessor, InputInteraction, and InputBindingComposite defined by this package.",
FixItAutomatic = true,
Error = InputSystem.actions != null && (InputSystem.actions.name == k_InputActionAssetName || AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(InputSystem.actions)) == k_InputActionAssetGuid),
});
#endif
}
foreach (var buildTargetGroup in s_BuildTargetGroups)
{
BuildValidator.AddRules(buildTargetGroup, s_BuildValidationRules);
}
ShowWindowIfIssuesExist();
}
static void ShowWindowIfIssuesExist()
{
foreach (var validation in s_BuildValidationRules)
{
if (validation.CheckPredicate == null || !validation.CheckPredicate.Invoke())
{
ShowWindow();
return;
}
}
}
internal static void ShowWindow()
{
// Delay opening the window since sometimes other settings in the player settings provider redirect to the
// project validation window causing serialized objects to be nullified.
EditorApplication.delayCall += () =>
{
SettingsService.OpenProjectSettings(k_ProjectValidationSettingsPath);
};
}
static bool IsInteractionLayerTeleport()
{
return string.Equals(InteractionLayerSettings.Instance.GetLayerNameAt(k_TeleportLayerIndex), k_TeleportLayerName, StringComparison.OrdinalIgnoreCase);
}
static bool DisplayTeleportDialog()
{
return EditorUtility.DisplayDialog(
"Fixing Teleport Interaction Layer",
$"Interaction Layer {k_TeleportLayerIndex} for teleportation locomotion is currently set to '{InteractionLayerSettings.Instance.GetLayerNameAt(k_TeleportLayerIndex)}' instead of '{k_TeleportLayerName}'",
"Automatically Replace",
"Cancel");
}
#if UNITY_INPUT_SYSTEM_PROJECT_WIDE_ACTIONS
static void InstallOrUpdateInputSystem()
{
// Set a 3-second timeout for request to avoid editor lockup
var currentTime = DateTime.Now;
var endTime = currentTime + TimeSpan.FromSeconds(3);
var request = Client.Search(k_InputSystemPackageName);
if (request.Status == StatusCode.InProgress)
{
Debug.Log($"Searching for ({k_InputSystemPackageName}) in Unity Package Registry.");
while (request.Status == StatusCode.InProgress && currentTime < endTime)
currentTime = DateTime.Now;
}
var addRequest = k_InputSystemPackageName;
if (request.Status == StatusCode.Success && request.Result.Length > 0)
{
var versions = request.Result[0].versions;
#if UNITY_2022_2_OR_NEWER
var recommendedVersion = new PackageVersion(versions.recommended);
#else
var recommendedVersion = new PackageVersion(versions.verified);
#endif
var latestCompatible = new PackageVersion(versions.latestCompatible);
if (recommendedVersion < s_RecommendedPackageVersion && s_RecommendedPackageVersion <= latestCompatible)
addRequest = $"{k_InputSystemPackageName}@{s_RecommendedPackageVersion}";
}
s_InputSystemPackageAddRequest = Client.Add(addRequest);
if (s_InputSystemPackageAddRequest.Error != null)
{
Debug.LogError($"Package installation error: {s_InputSystemPackageAddRequest.Error}: {s_InputSystemPackageAddRequest.Error.message}");
}
}
#endif
}
}
|