5 using System.Collections.Generic;
7 using System.Text.RegularExpressions;
19 private const int SpatialMappingLayerId = 31;
20 private const string SpatialMappingLayerName =
"Spatial Mapping";
22 private const string SharingServiceURL =
"https://raw.githubusercontent.com/Microsoft/MixedRealityToolkit-Unity/master/External/HoloToolkit/Sharing/Server/SharingService.exe";
27 private List<string> axisNames =
new List<string>();
32 private SerializedObject inputManagerAsset;
37 private readonly InputManagerAxis[] newInputAxes =
49 new InputManagerAxis() { Name =
InputMappingAxisUtility.
XBOX_A, PositiveButton =
"joystick button 0", Gravity = 1000, Dead = 0.001f, Sensitivity = 1000, Type = AxisType.KeyOrMouseButton, Axis = 1 },
50 new InputManagerAxis() { Name =
InputMappingAxisUtility.
XBOX_B, PositiveButton =
"joystick button 1", Gravity = 1000, Dead = 0.001f, Sensitivity = 1000, Type = AxisType.KeyOrMouseButton, Axis = 1 },
51 new InputManagerAxis() { Name =
InputMappingAxisUtility.
XBOX_X, PositiveButton =
"joystick button 2", Gravity = 1000, Dead = 0.001f, Sensitivity = 1000, Type = AxisType.KeyOrMouseButton, Axis = 1 },
52 new InputManagerAxis() { Name =
InputMappingAxisUtility.
XBOX_Y, PositiveButton =
"joystick button 3", Gravity = 1000, Dead = 0.001f, Sensitivity = 1000, Type = AxisType.KeyOrMouseButton, Axis = 1 },
55 new InputManagerAxis() { Name =
InputMappingAxisUtility.
CONTROLLER_LEFT_MENU, PositiveButton =
"joystick button 6", Gravity = 1000, Dead = 0.001f, Sensitivity = 1000, Type = AxisType.KeyOrMouseButton, Axis = 1 },
64 private readonly InputManagerAxis[] obsoleteInputAxes = { };
66 private bool updateToolkitAxes;
75 TargetOccludedDevices,
78 DotNetScriptingBackend,
79 SetDefaultSpatialMappingLayer
95 private class InputManagerAxis
97 public string Name =
"";
98 public string DescriptiveName =
"";
99 public string DescriptiveNegativeName =
"";
100 public string NegativeButton =
"";
101 public string PositiveButton =
"";
102 public string AltNegativeButton =
"";
103 public string AltPositiveButton =
"";
104 public float Gravity = 0.0f;
105 public float Dead = 0.0f;
106 public float Sensitivity = 0.0f;
107 public bool Snap =
false;
108 public bool Invert =
false;
109 public AxisType Type =
default(AxisType);
111 public int JoyNum = 0;
114 #endregion // Nested Types 116 #region Overrides / Event Handlers 125 if (EditorUserBuildSettings.activeBuildTarget != BuildTarget.WSAPlayer)
127 #if UNITY_2017_1_OR_NEWER 128 EditorUserBuildSettings.SwitchActiveBuildTargetAsync(BuildTargetGroup.WSA, BuildTarget.WSAPlayer);
130 EditorUserBuildSettings.SwitchActiveBuildTarget(BuildTargetGroup.WSA, BuildTarget.WSAPlayer);
135 UpdateSettings(EditorUserBuildSettings.activeBuildTarget);
140 EditorUserBuildSettings.SwitchActiveBuildTarget(BuildTargetGroup.Standalone, BuildTarget.StandaloneWindows64);
167 throw new ArgumentOutOfRangeException();
172 private void UpdateSettings(BuildTarget currentBuildTarget)
176 string sharingServiceDirectory = Directory.GetParent(Path.GetFullPath(Application.dataPath)).FullName +
"\\External\\HoloToolkit\\Sharing\\Server";
177 string sharingServicePath = sharingServiceDirectory +
"\\SharingService.exe";
178 if (!File.Exists(sharingServicePath) &&
179 EditorUtility.DisplayDialog(
"Attention!",
180 "You're missing the Sharing Service Executable in your project.\n\n" +
181 "Would you like to download the missing files from GitHub?\n\n" +
182 "Alternatively, you can download it yourself or specify a target IP to connect to at runtime on the Sharing Stage.",
185 using (var webRequest = UnityWebRequest.Get(SharingServiceURL))
187 #if UNITY_2017_2_OR_NEWER 188 webRequest.SendWebRequest();
192 while (!webRequest.isDone)
194 if (webRequest.downloadProgress > -1)
196 EditorUtility.DisplayProgressBar(
197 "Downloading the SharingService executable from GitHub",
198 "Progress...", webRequest.downloadProgress);
202 EditorUtility.ClearProgressBar();
204 #if UNITY_2017_1_OR_NEWER 205 if (webRequest.isNetworkError || webRequest.isHttpError)
207 if (webRequest.isError)
210 Debug.LogError(
"Network Error: " + webRequest.error);
214 byte[] sharingServiceData = webRequest.downloadHandler.data;
215 Directory.CreateDirectory(sharingServiceDirectory);
216 File.WriteAllBytes(sharingServicePath, sharingServiceData);
222 Debug.LogFormat(
"Alternatively, you can download from this link: {0}", SharingServiceURL);
225 PlayerSettings.WSA.SetCapability(PlayerSettings.WSACapability.InternetClientServer,
true);
226 PlayerSettings.WSA.SetCapability(PlayerSettings.WSACapability.PrivateNetworkClientServer,
true);
230 PlayerSettings.WSA.SetCapability(PlayerSettings.WSACapability.InternetClient,
false);
231 PlayerSettings.WSA.SetCapability(PlayerSettings.WSACapability.InternetClientServer,
false);
232 PlayerSettings.WSA.SetCapability(PlayerSettings.WSACapability.PrivateNetworkClientServer,
false);
235 if (updateToolkitAxes)
240 inputManagerAsset =
new SerializedObject(AssetDatabase.LoadAssetAtPath(
"ProjectSettings/InputManager.asset", typeof(
UnityEngine.Object)));
244 foreach (InputManagerAxis axis
in newInputAxes)
246 if (!DoesAxisNameExist(axis.Name))
255 foreach (InputManagerAxis axis
in newInputAxes)
257 if (DoesAxisNameExist(axis.Name))
259 RemoveAxis(axis.Name);
263 foreach (InputManagerAxis axis
in obsoleteInputAxes)
265 if (DoesAxisNameExist(axis.Name))
267 RemoveAxis(axis.Name);
272 inputManagerAsset.ApplyModifiedProperties();
275 if (currentBuildTarget != BuildTarget.WSAPlayer)
277 AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate);
282 EditorUserBuildSettings.wsaUWPBuildType = Values[
ProjectSetting.WsaUwpBuildToD3D]
283 ? WSAUWPBuildType.D3D
284 : WSAUWPBuildType.XAML;
286 UnityEditorInternal.VR.VREditor.SetVREnabledOnTargetGroup(BuildTargetGroup.WSA, Values[
ProjectSetting.WsaEnableXR]);
290 EditorUserBuildSettings.wsaSubtarget = WSASubtarget.AnyDevice;
291 UnityEditorInternal.VR.VREditor.SetVREnabledDevicesOnTargetGroup(BuildTargetGroup.WSA,
new[] {
"None" });
292 PlayerSettings.WSA.SetCapability(PlayerSettings.WSACapability.HumanInterfaceDevice,
false);
297 #if !UNITY_2017_2_OR_NEWER 302 EditorUserBuildSettings.wsaSubtarget = WSASubtarget.HoloLens;
303 #if UNITY_2017_2_OR_NEWER 304 UnityEditorInternal.VR.VREditor.SetVREnabledDevicesOnTargetGroup(BuildTargetGroup.WSA,
new[] {
"WindowsMR" });
306 UnityEditorInternal.VR.VREditor.SetVREnabledDevicesOnTargetGroup(BuildTargetGroup.WSA,
new[] {
"HoloLens" });
308 PlayerSettings.WSA.SetCapability(PlayerSettings.WSACapability.HumanInterfaceDevice, Values[
ProjectSetting.UseInputManagerAxes]);
311 for (var i = 0; i < QualitySettings.names.Length; i++)
313 QualitySettings.DecreaseLevel(
true);
318 EditorUserBuildSettings.wsaSubtarget = WSASubtarget.PC;
319 UnityEditorInternal.VR.VREditor.SetVREnabledDevicesOnTargetGroup(BuildTargetGroup.WSA,
new[] {
"WindowsMR" });
320 PlayerSettings.WSA.SetCapability(PlayerSettings.WSACapability.HumanInterfaceDevice,
false);
323 for (var i = 0; i < QualitySettings.names.Length; i++)
325 QualitySettings.IncreaseLevel(
true);
329 int currentQualityLevel = QualitySettings.GetQualityLevel();
337 string settingsPath =
"ProjectSettings/QualitySettings.asset";
338 string matchPattern =
@"(m_PerPlatformDefaultQuality.*Windows Store Apps:) (\d+)";
339 string replacePattern =
@"$1 " + currentQualityLevel;
341 string settings = File.ReadAllText(settingsPath);
342 settings = Regex.Replace(settings, matchPattern, replacePattern, RegexOptions.Singleline);
344 File.WriteAllText(settingsPath, settings);
348 Debug.LogException(e);
352 PlayerSettings.SetScriptingBackend(BuildTargetGroup.WSA,
354 ? ScriptingImplementation.WinRTDotNET
355 : ScriptingImplementation.IL2CPP);
359 if (SetSpatialMappingLayer())
362 PlayerSettings.WSA.SetCapability(PlayerSettings.WSACapability.SpatialPerception,
true);
366 EditorUtility.DisplayDialog(
"Attention!",
367 "Unable to set the Spatial Mapping layer.\n\n" +
368 "This likely means that layer " + SpatialMappingLayerId.ToString() +
" is already in use.\n\n" +
369 "Please check your project's Tags && Layers settings in the Inspector.",
374 AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate);
384 Names[
ProjectSetting.BuildWsaUwp] =
"Target Windows Universal UWP";
386 "<b>Required</b>\n\n" +
387 "Switches the currently active target to produce a Store app targeting the Universal Windows Platform.\n\n" +
388 "<color=#ffff00ff><b>Note:</b></color> Cross platform development can be done with this toolkit, but many features and " +
389 "tools will not work if the build target is not Windows Universal.";
393 "<b>Required</b>\n\n" +
394 "Enables 'Windows Holographic' for Windows Store apps.\n\n" +
395 "If disabled, your application will run as a normal UWP app on PC, and will launch as a 2D app on HoloLens.\n\n" +
396 "<color=#ff0000ff><b>Warning!</b></color> HoloLens and tools like 'Holographic Remoting' will not function without this enabled.";
401 "Produces an app that targets Direct3D instead of XAML.\n\n" +
402 "Pure Direct3D apps run faster than applications that include XAML. This option should remain checked unless you plan to " +
403 "overlay Unity content with XAML content or you plan to switch between Unity views and XAML views at runtime.";
405 Names[
ProjectSetting.TargetOccludedDevices] =
"Target Occluded Devices";
407 "Changes the target Device and updates the default quality settings, if needed. Occluded devices are generally VR hardware (like the Acer HMD) " +
408 "that do not have a 'see through' display, while transparent devices (like the HoloLens) are generally AR hardware where users can see " +
409 "and interact with digital elements in the physical world around them.\n\n" +
410 #if !UNITY_2017_2_OR_NEWER 411 "<color=#ff0000ff><b>Warning!</b></color> Occluded Devices are only supported in Unity 2017.2 and newer and cannot be enabled.\n\n" +
413 "<color=#ffff00ff><b>Note:</b></color> If you're not targeting Occluded devices, It's generally recommended that Transparent devices use " +
414 "the lowest default quality setting, and is set automatically for you. This can be manually changed in your the Project's Quality Settings.";
416 Names[
ProjectSetting.SharingServices] =
"Enable Sharing Services";
418 "Enables the use of the Sharing Services in your project for all apps on any platform.\n\n" +
419 "<color=#ffff00ff><b>Note:</b></color> Start the Sharing Server via 'Mixed Reality Toolkit/Sharing Service/Launch Sharing Service'.\n\n" +
420 "<color=#ffff00ff><b>Note:</b></color> The InternetClientServer and PrivateNetworkClientServer capabilities will be enabled in the " +
421 "appx manifest for you.";
423 Names[
ProjectSetting.UseInputManagerAxes] =
"Use Toolkit-specific InputManager axes";
425 "Enables the use of the Xbox Controller for all apps on any platform.\n\n" +
426 "To remove the added axes, simply disable this setting.\n\n" +
427 "<color=#ffff00ff><b>Note:</b></color> The HoloLens platform target requires the HID capability to be defined in the appx manifest. " +
428 "This capability is automatically enabled for you if you select this setting, \"Enable XR\", and don't select \"Target Occluded Devices\".";
430 Names[
ProjectSetting.DotNetScriptingBackend] =
"Enable .NET scripting backend";
433 "If you have the .NET unity module installed this will update the backend scripting profile, otherwise the scripting backend will be IL2CPP.";
435 Names[
ProjectSetting.SetDefaultSpatialMappingLayer] =
"Set Default Spatial Mapping Layer";
438 "Sets the default Spatial Mapping physics layer.\n\n" +
439 "On HoloLens, this enables specifying the Spatial Mapping mesh for collision detection and raycasting.\n\n" +
440 "<color=#ffff00ff><b>Note:</b></color> Selecting \"Set Default Spatial Mapping Layer\" implies the project will be using Spatial Mapping. " +
441 "The Spatial Perception capability is automatically enabled for you.";
448 #if UNITY_2017_1_OR_NEWER 452 minSize =
new Vector2(350, 350);
456 private void OnDisable()
458 if (inputManagerAsset != null)
460 inputManagerAsset.Dispose();
464 #endregion // Overrides / Event Handlers 466 private void AddAxis(InputManagerAxis axis)
468 SerializedProperty axesProperty = inputManagerAsset.FindProperty(
"m_Axes");
471 axesProperty.arraySize++;
474 SerializedProperty axisProperty = axesProperty.GetArrayElementAtIndex(axesProperty.arraySize - 1);
477 while (axisProperty.Next(
true))
479 switch (axisProperty.name)
482 axisProperty.stringValue = axis.Name;
484 case "descriptiveName":
485 axisProperty.stringValue = axis.DescriptiveName;
487 case "descriptiveNegativeName":
488 axisProperty.stringValue = axis.DescriptiveNegativeName;
490 case "negativeButton":
491 axisProperty.stringValue = axis.NegativeButton;
493 case "positiveButton":
494 axisProperty.stringValue = axis.PositiveButton;
496 case "altNegativeButton":
497 axisProperty.stringValue = axis.AltNegativeButton;
499 case "altPositiveButton":
500 axisProperty.stringValue = axis.AltPositiveButton;
503 axisProperty.floatValue = axis.Gravity;
506 axisProperty.floatValue = axis.Dead;
509 axisProperty.floatValue = axis.Sensitivity;
512 axisProperty.boolValue = axis.Snap;
515 axisProperty.boolValue = axis.Invert;
518 axisProperty.intValue = (int)axis.Type;
521 axisProperty.intValue = axis.Axis - 1;
524 axisProperty.intValue = axis.JoyNum;
530 private void RemoveAxis(
string axis)
532 SerializedProperty axesProperty = inputManagerAsset.FindProperty(
"m_Axes");
535 while (axisNames.Contains(axis))
537 int index = axisNames.IndexOf(axis);
538 axesProperty.DeleteArrayElementAtIndex(index);
539 axisNames.RemoveAt(index);
546 private bool DoesAxisNameExist(
string axisName)
548 if (axisNames.Count == 0 || inputManagerAsset.UpdateIfRequiredOrScript())
550 RefreshLocalAxesList();
553 return axisNames.Contains(axisName);
559 private void RefreshLocalAxesList()
563 SerializedProperty axesProperty = inputManagerAsset.FindProperty(
"m_Axes");
565 for (
int i = 0; i < axesProperty.arraySize; i++)
567 axisNames.Add(axesProperty.GetArrayElementAtIndex(i).displayName);
577 private bool SetSpatialMappingLayer()
579 UnityEngine.Object[] tagAssets = AssetDatabase.LoadAllAssetsAtPath(
"ProjectSettings/TagManager.asset");
580 if ((tagAssets == null) ||
581 (tagAssets.Length == 0))
586 SerializedObject tagsManager =
new SerializedObject(tagAssets);
587 if (tagsManager == null)
592 SerializedProperty layers = tagsManager.FindProperty(
"layers");
598 SerializedProperty spatialMappingLayer = layers.GetArrayElementAtIndex(SpatialMappingLayerId);
599 if (spatialMappingLayer.stringValue == SpatialMappingLayerName)
604 else if (spatialMappingLayer.stringValue !=
string.Empty)
611 spatialMappingLayer.stringValue = SpatialMappingLayerName;
612 return tagsManager.ApplyModifiedProperties();
618 private void SaveMenuSettings()