From 7fea476ef446c1da8e1031b6691ca0541baeb0a6 Mon Sep 17 00:00:00 2001 From: Unity Technologies <@unity.com> Date: Wed, 10 Apr 2019 00:00:00 +0200 Subject: [PATCH] com.unity.xr.management@2.0.0-preview.9 ## [2.0.0-preview.9] - 2019-4-10 * Fix package validation console errors. ## [2.0.0-preview.8] - 2019-4-10 * Fix package validation compilation errors. * Remove .github folder from npm packaging. ## [2.0.0-preview.7] - 2019-4-10 * Streamlining of the management system. Move XR Manager to a singleton instance on XRGeneralSettings that is populated by an XRManagerSettings instance that the user can switch in and out. __NOTE: This removes the ability to use XRManagement for per scene situations. For hybrid or manual scenes the user will be responsible for instantiating/loading the XRManagerSettings instance they want and dealing with lifecycle themselves.__ --- CHANGELOG.md | 12 +- Documentation~/EndUser.md | 25 +- Documentation~/Provider.md | 8 +- Documentation~/com.unity.xr.management.md | 4 +- Editor/TutorialInfo.meta | 8 + Editor/TutorialInfo/Icons.meta | 8 + Editor/TutorialInfo/Icons/HDIcon.png | Bin 0 -> 23643 bytes Editor/TutorialInfo/Icons/HDIcon.png.meta | 128 ++++++++ Editor/TutorialInfo/Icons/Help_Icon.png | Bin 0 -> 18108 bytes Editor/TutorialInfo/Icons/Help_Icon.png.meta | 128 ++++++++ Editor/TutorialInfo/Scripts.meta | 8 + Editor/TutorialInfo/Scripts/Editor.meta | 8 + .../Scripts/Editor/ReadmeEditor.cs | 159 +++++++++ .../Scripts/Editor/ReadmeEditor.cs.meta | 11 + Editor/TutorialInfo/Scripts/XRReadme.cs | 14 + Editor/TutorialInfo/Scripts/XRReadme.cs.meta | 11 + Editor/TutorialInfo/XRCuratedPackages.asset | 22 ++ .../TutorialInfo/XRCuratedPackages.asset.meta | 8 + Editor/TutorialInfo/XRReadme.asset | 31 ++ Editor/TutorialInfo/XRReadme.asset.meta | 8 + Editor/XRGeneralBuildProcessor.cs | 12 +- Editor/XRManagerEditor.cs | 306 +++++++++++++++--- Editor/XRSettingsManager.cs | 60 +++- Runtime/XRCuratedPackages.cs | 31 ++ Runtime/XRCuratedPackages.cs.meta | 11 + Runtime/XRGeneralSettings.cs | 27 +- .../{XRManager.cs => XRManagerSettings.cs} | 30 +- ...ager.cs.meta => XRManagerSettings.cs.meta} | 0 Samples~/Editor.meta | 2 +- Samples~/SampleLoader.cs | 1 + Tests/Editor/EditorTests.cs | 5 +- Tests/Runtime/RuntimeTests.cs | 28 +- .../StandaloneSubsystem.cs | 15 +- package.json | 4 +- 34 files changed, 986 insertions(+), 147 deletions(-) create mode 100644 Editor/TutorialInfo.meta create mode 100644 Editor/TutorialInfo/Icons.meta create mode 100644 Editor/TutorialInfo/Icons/HDIcon.png create mode 100644 Editor/TutorialInfo/Icons/HDIcon.png.meta create mode 100644 Editor/TutorialInfo/Icons/Help_Icon.png create mode 100644 Editor/TutorialInfo/Icons/Help_Icon.png.meta create mode 100644 Editor/TutorialInfo/Scripts.meta create mode 100644 Editor/TutorialInfo/Scripts/Editor.meta create mode 100644 Editor/TutorialInfo/Scripts/Editor/ReadmeEditor.cs create mode 100644 Editor/TutorialInfo/Scripts/Editor/ReadmeEditor.cs.meta create mode 100644 Editor/TutorialInfo/Scripts/XRReadme.cs create mode 100644 Editor/TutorialInfo/Scripts/XRReadme.cs.meta create mode 100644 Editor/TutorialInfo/XRCuratedPackages.asset create mode 100644 Editor/TutorialInfo/XRCuratedPackages.asset.meta create mode 100644 Editor/TutorialInfo/XRReadme.asset create mode 100644 Editor/TutorialInfo/XRReadme.asset.meta create mode 100644 Runtime/XRCuratedPackages.cs create mode 100644 Runtime/XRCuratedPackages.cs.meta rename Runtime/{XRManager.cs => XRManagerSettings.cs} (92%) rename Runtime/{XRManager.cs.meta => XRManagerSettings.cs.meta} (100%) diff --git a/CHANGELOG.md b/CHANGELOG.md index e953d37..2eaf232 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,8 +4,18 @@ All notable changes to this package will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## [2.0.0-preview.9] - 2019-4-10 +* Fix package validation console errors. + +## [2.0.0-preview.8] - 2019-4-10 +* Fix package validation compilation errors. +* Remove .github folder from npm packaging. + +## [2.0.0-preview.7] - 2019-4-10 +* Streamlining of the management system. Move XR Manager to a singleton instance on XRGeneralSettings that is populated by an XRManagerSettings instance that the user can switch in and out. __NOTE: This removes the ability to use XRManagement for per scene situations. For hybrid or manual scenes the user will be responsible for instantiating/loading the XRManagerSettings instance they want and dealing with lifecycle themselves.__ + ## [2.0.0-preview.6] - 2019-3-29 -Fix up package repo information for rel mgmt. +* Fix up package repo information for rel mgmt. ## [2.0.0-preview.5] - 2019-2-5 * Split documentation into separate audience files for End Users and Providers. diff --git a/Documentation~/EndUser.md b/Documentation~/EndUser.md index ef61773..a3984b1 100644 --- a/Documentation~/EndUser.md +++ b/Documentation~/EndUser.md @@ -4,28 +4,17 @@ At package install time, the package may prompt you to create an instance of a loader and an instance of settings for the package. This step is entirely optional and is there simply to help the user get things going at installation time. -If you wish not to create this at installation time, the appropriate portion of the editor that require them (**XRManager** and **Unified Settings** will) prompt you to create them as well. +If you wish not to create this at installation time, the appropriate portion of the editor that require them (**XRManagerSettingsSettings** and **Unified Settings** will) prompt you to create them as well. -## Add an **XRManager** instance to your scene - -### If you wish to start XR SDK on a per scene basis (i.e. start in 2D and transition into VR) -* Create a new empty Game Object in your scene. -* Add an instance of the **XRManager** component to this new Game Object. -* Use the **XRManager** component Inspector UI to add/create, remove and reorder the loaders you wish to use. - -When the scene loads, XR Manager will attempt to create and start the set of subsystems for the first loader that successfully initializes. Unless otherwise specified, XR Manager will manage the lifetime of the XR SDK session within the life time of the scene. - -### If you wish to start XR SDK at launch and keep it running throughout the app lifetime. -* Open and scene and create an empty **Game Object**. Add an **XR Manager** component to that **Game Object**. -* Drag the **Game Object** to the Project heirarchy and create a prefab from that instance. Delete the **Game Object** instance from the scene. -* Open the prefab in the Prefab Editor and go to the inspector for the prefab. -* Populate the **XR Manager** instance with the set of loaders you wish to use for your application. +### Set up XR SDK settings with loaders you want to run. * Navigate to **Unified Settings**. -* Select the top level **XR** node. Drag the prefab to the XR Manager Instance and drop it. This prefab is now assigned to the global XR settings system and will be used to manage the lifetime of the XR SDK for the lifetime of the application. +* Select the top level **XR** node. +* Modify loaders -The instance of the **Game Object** that contains the **XR Manager** component instance you wish to use can be set/accessed using **XRGeneralSettings.Instance.m_LoaderManagerInstance**. This allows you to change the prefab instance that you want to use at build time so that you can change loader configuration depending on build target. +**NOTE**: You can always manually control the XR SDK system by accessing the **XRManagerSettingsSettings.activeLoader** field once XR SDK has been initialized. -**NOTE**: You can always manually control the XR SDK system by accessing the **XRManager.activeLoader** field once XR SDK has been initialized. +### If you wish to start XR SDK on a per scene basis (i.e. start in 2D and transition into VR) +* Use the **XRGeneralSettings.Instance.m_LoaderManagerInstance** to add/create, remove and reorder the loaders you wish to use from the script. ## Customize build and runtime settings diff --git a/Documentation~/Provider.md b/Documentation~/Provider.md index 9cdcdb7..591d4e5 100644 --- a/Documentation~/Provider.md +++ b/Documentation~/Provider.md @@ -2,7 +2,7 @@ ## Lifecycle Management -This package provides for management of **XR SDK** subsystem lifecycle without the need for boilerplate code. The **XRManager** class provides a component that can be added to a game object in the scene that will manage initialization, start, stop and de-initialization of a set of subsystems defined by an **XRLoader** instance. The **XRManager** instance can handle all of the lifecycle management, init/de-init only, subsystem start/stop only or can leave all of it up to the user. +This package provides for management of **XR SDK** subsystem lifecycle without the need for boilerplate code. The **XRManagerSettings** class provides a scriptable object that can be used by the app for start, stop and de-initialization of a set of subsystems defined by an **XRLoader** instance. A provider must create a subclass of **XRLoader** to make a loader available for their particular runtime scheme. @@ -27,9 +27,9 @@ There is a class called **XRLoaderHelper** which you can derive from to handle s An **XRLoader** is simply a **ScriptableObject** and as such, the user is able to create and instance (or more if they want) of the loader. Each **XRLoader** subclass defines the subsystems and their load order and is responsible for managing the set of subsystems they require. -A user will add all the **XRLoaders** instances they created to the Loaders property on the **XRManager**, arranging them in the load order that they desire. +A user will add all the **XRLoaders** instances they created to the Loaders property on the **XRManagerSettings**, arranging them in the load order that they desire. -When asked to initialize, **XRManager** will call each **XRLoader** instance it has a reference to in the order it has and attempt to initialize each one. The first loader that succeeds initialization becomes the active loader and all further attempts to initialize are stopped. From this point the user can ask for the static **XRManager.ActiveLoader** instance to get access to the active loader. If initialization fails for all loaders, **ActiveLoader** is set to null. +When asked to initialize, **XRManagerSettings** will call each **XRLoader** instance it has a reference to in the order it has and attempt to initialize each one. The first loader that succeeds initialization becomes the active loader and all further attempts to initialize are stopped. From this point the user can ask for the static **XRManagerSettings.ActiveLoader** instance to get access to the active loader. If initialization fails for all loaders, **ActiveLoader** is set to null. Scene based Automatic lifecycle management hooks into the following **MonoBehaviour** callback points: @@ -109,7 +109,7 @@ If you need more extensive support and/or absolute control you can copy the **Sa ## Package Initialization -Given the need for **ScriptableObject** instance to support loaders and settings, the user will be forced to create these instances at some point. Both **XRManager** and the **Unified Settings** support can handle creating the necessary instances on demand but it may be beneficial to create these up front at package installation. If you derive a class from **XRPackageInitializationBase** and fill out the interface properties and methods the management system will provide for creation of default instances of your loader and settings at installation. Creation of each one is driven by prompting the user if it is OK to do that and, if so, creating the instance in the appropriate default location in the Assets folder. For loaders this is Assets/XR/Loaders. For settings this is Assets/XR/Settings. While these are the recommended locations for putting these package based objects they do not have to be located there. The user is free to move them around as long as we can find at least one instance of each type for each package. +Given the need for **ScriptableObject** instance to support loaders and settings, the user will be forced to create these instances at some point. Both **XRManagerSettings** and the **Unified Settings** support can handle creating the necessary instances on demand but it may be beneficial to create these up front at package installation. If you derive a class from **XRPackageInitializationBase** and fill out the interface properties and methods the management system will provide for creation of default instances of your loader and settings at installation. Creation of each one is driven by prompting the user if it is OK to do that and, if so, creating the instance in the appropriate default location in the Assets folder. For loaders this is Assets/XR/Loaders. For settings this is Assets/XR/Settings. While these are the recommended locations for putting these package based objects they do not have to be located there. The user is free to move them around as long as we can find at least one instance of each type for each package. # Installing *XR SDK Management* diff --git a/Documentation~/com.unity.xr.management.md b/Documentation~/com.unity.xr.management.md index 3ed234f..5c16189 100644 --- a/Documentation~/com.unity.xr.management.md +++ b/Documentation~/com.unity.xr.management.md @@ -66,8 +66,8 @@ This version of **XR SDK Management** is compatible with the following versions This version of **XR SDK Management** includes: -* **XRManager** - This is a **MonoBehaviour** that can be added to a **GameObject** in a scene and provides for management of **XRLoader** instances and their lifecycle. -* **XRLoader** - This is the base class all loaders should derive from. It provides a basic the **XRManager** can use to manage lifecycle and a simple API to allow users to request specific subsystems from the loader as and when needed. +* **XRManagerSettingsSettingsSettings** - This is a **ScriptableBehaviour** that can be accessed from the script and provides for management of **XRLoader** instances and their lifecycle. +* **XRLoader** - This is the base class all loaders should derive from. It provides a basic the **XRManagerSettingsSettingsSettings** can use to manage lifecycle and a simple API to allow users to request specific subsystems from the loader as and when needed. * **XRConfigurationData** - This is an attribute that allows for build and runtime settings to be hosted within the **Unified Settings** window. All instances will be hosted under the top level **XR** entry within the **Unified Settings** window under the name supplied as part of the attribute. The management package will maintain and manage the lifecycle for one instance of the build settings using **EditorBuildSettings** config object API, stored with the key provided in the attribute. At any time, the provider or the user is free access the configuration settings instance by asking **EditorBuildSettings** for the instance associated with the chosen key (as set in the attribute). * **XRPackageInitializationBase** - Helper class to derive from that simplifies some of the busy work for package initialization. Helps to create a default instance of the packages XRLoader and default settings at the time of package installation. Initialization is run once only and the package developer should not depend on the user creating the specified instances. * **XRBuildHelper** - Abstract class useful for handling some boilerplate around moving settings from Editor -> Runtime. Derive from this class and specific the appropriate settings type and the system will take care of marshaling that type from EditorUserBuildSettings to PlayerSettings to be used at runtime. diff --git a/Editor/TutorialInfo.meta b/Editor/TutorialInfo.meta new file mode 100644 index 0000000..5f5d0b8 --- /dev/null +++ b/Editor/TutorialInfo.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6ab42e0f6ae068a49a1b3192e6ed3965 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/TutorialInfo/Icons.meta b/Editor/TutorialInfo/Icons.meta new file mode 100644 index 0000000..be20efb --- /dev/null +++ b/Editor/TutorialInfo/Icons.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8421683a2fdcf39488231904646c9848 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/TutorialInfo/Icons/HDIcon.png b/Editor/TutorialInfo/Icons/HDIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..ecf6781a74dfee4109885a3f6b1cc19df9d916ff GIT binary patch literal 23643 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 literal 0 HcmV?d00001 diff --git a/Editor/TutorialInfo/Icons/HDIcon.png.meta b/Editor/TutorialInfo/Icons/HDIcon.png.meta new file mode 100644 index 0000000..495b9c8 --- /dev/null +++ b/Editor/TutorialInfo/Icons/HDIcon.png.meta @@ -0,0 +1,128 @@ +fileFormatVersion: 2 +guid: 9b84c330de497af4793fd7b376afed13 +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 5 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: 4 + mipBias: -1 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + singleChannelComponent: 0 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - serializedVersion: 2 + buildTarget: DefaultTexturePlatform + maxTextureSize: 8192 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Standalone + maxTextureSize: 8192 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: iPhone + maxTextureSize: 8192 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Android + maxTextureSize: 8192 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Windows Store Apps + maxTextureSize: 8192 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + vertices: [] + indices: + edges: [] + weights: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/TutorialInfo/Icons/Help_Icon.png b/Editor/TutorialInfo/Icons/Help_Icon.png new file mode 100644 index 0000000000000000000000000000000000000000..91fa21586231dbb04e158442e6f87dc6c60efbb5 GIT binary patch literal 18108 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 F{tL_Hfk*%V literal 0 HcmV?d00001 diff --git a/Editor/TutorialInfo/Icons/Help_Icon.png.meta b/Editor/TutorialInfo/Icons/Help_Icon.png.meta new file mode 100644 index 0000000..86cc13a --- /dev/null +++ b/Editor/TutorialInfo/Icons/Help_Icon.png.meta @@ -0,0 +1,128 @@ +fileFormatVersion: 2 +guid: 9266273b8f123004195741f969177dda +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 5 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: 1 + mipBias: -1 + wrapU: 1 + wrapV: 1 + wrapW: -1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 2 + textureShape: 1 + singleChannelComponent: 0 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - serializedVersion: 2 + buildTarget: DefaultTexturePlatform + maxTextureSize: 8192 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Standalone + maxTextureSize: 8192 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: iPhone + maxTextureSize: 8192 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Android + maxTextureSize: 8192 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Windows Store Apps + maxTextureSize: 8192 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + vertices: [] + indices: + edges: [] + weights: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/TutorialInfo/Scripts.meta b/Editor/TutorialInfo/Scripts.meta new file mode 100644 index 0000000..32f5f96 --- /dev/null +++ b/Editor/TutorialInfo/Scripts.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: fc961c42af7900e4386039fb5f4df1a8 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/TutorialInfo/Scripts/Editor.meta b/Editor/TutorialInfo/Scripts/Editor.meta new file mode 100644 index 0000000..1cae470 --- /dev/null +++ b/Editor/TutorialInfo/Scripts/Editor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: aa1f78f8fcd4e5a4b8cb5905c9e23ff5 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/TutorialInfo/Scripts/Editor/ReadmeEditor.cs b/Editor/TutorialInfo/Scripts/Editor/ReadmeEditor.cs new file mode 100644 index 0000000..0a854c8 --- /dev/null +++ b/Editor/TutorialInfo/Scripts/Editor/ReadmeEditor.cs @@ -0,0 +1,159 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using UnityEditor; +using System; +using System.IO; +using System.Reflection; + +[CustomEditor(typeof(XRReadme))] +[InitializeOnLoad] +public class ReadmeEditor : Editor { + + static string kShowedReadmeSessionStateName = "XRReadmeEditor.showedReadme"; + + static float kSpace = 16f; + + static ReadmeEditor() + { + EditorApplication.delayCall += SelectReadmeAutomatically; + } + + static void SelectReadmeAutomatically() + { + if (!SessionState.GetBool(kShowedReadmeSessionStateName, false )) + { + var readme = SelectReadme(); + SessionState.SetBool(kShowedReadmeSessionStateName, true); + + if (readme && !readme.loadedLayout) + { + LoadLayout(); + readme.loadedLayout = true; + } + } + } + + static void LoadLayout() + { + var assembly = typeof(EditorApplication).Assembly; + var windowLayoutType = assembly.GetType("UnityEditor.InspectorWindow", true); + EditorWindow window = EditorWindow.GetWindow(windowLayoutType); + window.Show(); + SettingsService.OpenProjectSettings("XR"); + } + + [MenuItem("Help/Show XR SDK Instructions")] + static XRReadme SelectReadme() + { + var ids = AssetDatabase.FindAssets("XRReadme t:XRReadme"); + if (ids.Length == 1) + { + var readmeObject = AssetDatabase.LoadMainAssetAtPath(AssetDatabase.GUIDToAssetPath(ids[0])); + + Selection.objects = new UnityEngine.Object[]{readmeObject}; + + return (XRReadme)readmeObject; + } + else + { + Debug.Log("Couldn't find a readme"); + return null; + } + } + + protected override void OnHeaderGUI() + { + var readme = (XRReadme)target; + Init(); + + var iconWidth = Mathf.Min(EditorGUIUtility.currentViewWidth/3f - 20f, 128f); + + GUILayout.BeginHorizontal("In BigTitle"); + { + GUILayout.Label(readme.icon, GUILayout.Width(iconWidth), GUILayout.Height(iconWidth)); + GUILayout.Label(readme.title, TitleStyle); + } + GUILayout.EndHorizontal(); + } + + public override void OnInspectorGUI() + { + var readme = (XRReadme)target; + Init(); + + foreach (var section in readme.sections) + { + if (!string.IsNullOrEmpty(section.heading)) + { + GUILayout.Label(section.heading, HeadingStyle); + } + if (!string.IsNullOrEmpty(section.text)) + { + GUILayout.Label(section.text, BodyStyle); + } + if (!string.IsNullOrEmpty(section.linkText)) + { + if (LinkLabel(new GUIContent(section.linkText))) + { + Application.OpenURL(section.url); + } + } + GUILayout.Space(kSpace); + } + } + + + bool m_Initialized; + + GUIStyle LinkStyle { get { return m_LinkStyle; } } + [SerializeField] GUIStyle m_LinkStyle; + + GUIStyle TitleStyle { get { return m_TitleStyle; } } + [SerializeField] GUIStyle m_TitleStyle; + + GUIStyle HeadingStyle { get { return m_HeadingStyle; } } + [SerializeField] GUIStyle m_HeadingStyle; + + GUIStyle BodyStyle { get { return m_BodyStyle; } } + [SerializeField] GUIStyle m_BodyStyle; + + void Init() + { + if (m_Initialized) + return; + m_BodyStyle = new GUIStyle(EditorStyles.label); + m_BodyStyle.wordWrap = true; + m_BodyStyle.fontSize = 14; + + m_TitleStyle = new GUIStyle(m_BodyStyle); + m_TitleStyle.fontSize = 26; + + m_HeadingStyle = new GUIStyle(m_BodyStyle); + m_HeadingStyle.fontSize = 18 ; + + m_LinkStyle = new GUIStyle(m_BodyStyle); + m_LinkStyle.wordWrap = false; + // Match selection color which works nicely for both light and dark skins + m_LinkStyle.normal.textColor = new Color (0x00/255f, 0x78/255f, 0xDA/255f, 1f); + m_LinkStyle.stretchWidth = false; + + m_Initialized = true; + } + + bool LinkLabel (GUIContent label, params GUILayoutOption[] options) + { + var position = GUILayoutUtility.GetRect(label, LinkStyle, options); + + Handles.BeginGUI (); + Handles.color = LinkStyle.normal.textColor; + Handles.DrawLine (new Vector3(position.xMin, position.yMax), new Vector3(position.xMax, position.yMax)); + Handles.color = Color.white; + Handles.EndGUI (); + + EditorGUIUtility.AddCursorRect (position, MouseCursor.Link); + + return GUI.Button (position, label, LinkStyle); + } +} + diff --git a/Editor/TutorialInfo/Scripts/Editor/ReadmeEditor.cs.meta b/Editor/TutorialInfo/Scripts/Editor/ReadmeEditor.cs.meta new file mode 100644 index 0000000..201a05d --- /dev/null +++ b/Editor/TutorialInfo/Scripts/Editor/ReadmeEditor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 95a7a4c1deec9f343a0ef7853597a25b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/TutorialInfo/Scripts/XRReadme.cs b/Editor/TutorialInfo/Scripts/XRReadme.cs new file mode 100644 index 0000000..bcb4f86 --- /dev/null +++ b/Editor/TutorialInfo/Scripts/XRReadme.cs @@ -0,0 +1,14 @@ +using System; +using UnityEngine; + +public class XRReadme : ScriptableObject { + public Texture2D icon; + public string title; + public Section[] sections; + public bool loadedLayout; + + [Serializable] + public class Section { + public string heading, text, linkText, url; + } +} diff --git a/Editor/TutorialInfo/Scripts/XRReadme.cs.meta b/Editor/TutorialInfo/Scripts/XRReadme.cs.meta new file mode 100644 index 0000000..7fabde5 --- /dev/null +++ b/Editor/TutorialInfo/Scripts/XRReadme.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d25c3c2b4b8cb4a08b84af9c69ab8011 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/TutorialInfo/XRCuratedPackages.asset b/Editor/TutorialInfo/XRCuratedPackages.asset new file mode 100644 index 0000000..cbad965 --- /dev/null +++ b/Editor/TutorialInfo/XRCuratedPackages.asset @@ -0,0 +1,22 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_GeneratorAsset: {fileID: 0} + m_Script: {fileID: 11500000, guid: e5b070e20b4035c43810cb53fceb8a3b, type: 3} + m_Name: XRCuratedPackages + m_EditorClassIdentifier: + CuratedPackages: + - MenuTitle: Oculus Loader + PackageName: com.unity.xr.oculus + LoaderTypeInfo: Oculus Loader + - MenuTitle: Windows MR Loader + PackageName: com.unity.xr.windowsmr + LoaderTypeInfo: Windows MR Loader diff --git a/Editor/TutorialInfo/XRCuratedPackages.asset.meta b/Editor/TutorialInfo/XRCuratedPackages.asset.meta new file mode 100644 index 0000000..624df92 --- /dev/null +++ b/Editor/TutorialInfo/XRCuratedPackages.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 410f93f6ce0694e63a9fc1304e085729 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/TutorialInfo/XRReadme.asset b/Editor/TutorialInfo/XRReadme.asset new file mode 100644 index 0000000..e48375d --- /dev/null +++ b/Editor/TutorialInfo/XRReadme.asset @@ -0,0 +1,31 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_GeneratorAsset: {fileID: 0} + m_Script: {fileID: 11500000, guid: d25c3c2b4b8cb4a08b84af9c69ab8011, type: 3} + m_Name: XRReadme + m_EditorClassIdentifier: + icon: {fileID: 2800000, guid: 9b84c330de497af4793fd7b376afed13, type: 3} + title: XR Managment Package (Preview) + sections: + - heading: XR Managment Package + text: 'XR Managment package allows you to configure your project to use XR SDK architecture for your XR projects. ' + linkText: Preview Forum + url: CREATE_URL + - heading: + text: 'To learn how to move from legacy VR project and use new XR Managment go here :' + linkText: Convert to new XR SDK + url: CREATE_URL + - heading: + text: 'To Get Started, head to Project Settings/XR. More information available here :' + linkText: How to use XR Managment + url: CREATE_URL + loadedLayout: 0 diff --git a/Editor/TutorialInfo/XRReadme.asset.meta b/Editor/TutorialInfo/XRReadme.asset.meta new file mode 100644 index 0000000..b662fa1 --- /dev/null +++ b/Editor/TutorialInfo/XRReadme.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 791810df25fad465daa2ae0ceb290539 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/XRGeneralBuildProcessor.cs b/Editor/XRGeneralBuildProcessor.cs index b39ba6b..20b582d 100644 --- a/Editor/XRGeneralBuildProcessor.cs +++ b/Editor/XRGeneralBuildProcessor.cs @@ -61,17 +61,13 @@ public void OnPreprocessBuild(BuildReport report) // store off some info about the first loader in the list for PreInit boot.config purposes preInitInfo = null; - GameObject loaderManager = settings.LoaderManagerInstance; + XRManagerSettings loaderManager = settings.AssignedSettings; if (loaderManager != null) { - XRManager manager = loaderManager.GetComponent() as XRManager; - if (manager != null) + List loaders = loaderManager.loaders; + if (loaders.Count >= 1) { - List loaders = manager.loaders; - if (loaders.Count >= 1) - { - preInitInfo = new PreInitInfo(loaders[0] as IXRLoaderPreInit, report.summary.platform, report.summary.platformGroup); - } + preInitInfo = new PreInitInfo(loaders[0] as IXRLoaderPreInit, report.summary.platform, report.summary.platformGroup); } } diff --git a/Editor/XRManagerEditor.cs b/Editor/XRManagerEditor.cs index 57a9cbf..aebbe94 100644 --- a/Editor/XRManagerEditor.cs +++ b/Editor/XRManagerEditor.cs @@ -11,12 +11,11 @@ namespace UnityEditor.XR.Management { - class LoaderInfo : IEquatable + internal class LoaderInfo : IEquatable { public Type loaderType; public string assetName; public XRLoader instance; - public bool isUsed; public override bool Equals(object obj) { @@ -30,14 +29,13 @@ public override int GetHashCode() { var hashCode = (loaderType != null ? loaderType.GetHashCode() : 0); hashCode = (hashCode * 397) ^ (instance != null ? instance.GetHashCode() : 0); - hashCode = (hashCode * 397) ^ isUsed.GetHashCode(); return hashCode; } } public bool Equals(LoaderInfo other) { - return other != null && Equals(loaderType, other.loaderType) && Equals(instance, other.instance) && isUsed == other.isUsed; + return other != null && Equals(loaderType, other.loaderType) && Equals(instance, other.instance); } } @@ -46,27 +44,44 @@ class LoaderOrderUI const string k_ErrorGettingProviderSubsystem = "Error attempting to get object data for xr manager loaders."; const string k_AtLeastOneLoaderInstance = "Must add at least one XRLoader instance."; + const string k_AvailableMenuSeparator = "Available/"; + const string k_SuggestedMenuSeparator = "Download/"; + ReorderableList m_OrderedList = null; List m_LoadersInUse = new List(); List m_LoadersNotInUse = new List(); + XRCuratedPackages m_CuratedLoaders; + SerializedProperty m_LoaderProperty; bool m_ShouldReload = false; + Action m_onUpdate; + + public LoaderOrderUI(List loaderInfos, XRCuratedPackages curatedPackages, List loadersInUse, SerializedProperty loaderProperty, Action onUpdate) + { + Reset(loaderInfos, curatedPackages, loadersInUse, loaderProperty, onUpdate); + } - public LoaderOrderUI(List loaderInfos, SerializedProperty loaderProperty) + public void Reset(List loaderInfos, XRCuratedPackages curatedInfo, List loadersInUse, SerializedProperty loaderProperty, Action onUpdate) { + m_onUpdate = onUpdate; + m_LoaderProperty = loaderProperty; + m_CuratedLoaders = curatedInfo; + m_LoadersInUse = loadersInUse; + m_LoadersNotInUse.Clear(); + foreach (var info in loaderInfos) { - if (info.isUsed) - { - m_LoadersInUse.Add(info); - } - else + if (!m_LoadersInUse.Contains(info)) { m_LoadersNotInUse.Add(info); } } + + DownloadDefferedLoad(); + + m_ShouldReload = true; } void DrawElementCallback(Rect rect, int index, bool isActive, bool isFocused) @@ -81,6 +96,26 @@ float GetElementHeight(int index) return m_OrderedList.elementHeight; } + public bool CheckIfChanged(List listToCompare) + { + if (m_LoaderProperty != null && m_LoaderProperty.isArray) + { + int index = 0; + foreach (LoaderInfo info in listToCompare) + { + var target = (XRLoader)m_LoaderProperty.GetArrayElementAtIndex(index).objectReferenceValue; + + if(info.instance != target) + { + return true; + } + index++; + } + } + + return false; + } + void UpdateSerializedProperty() { if (m_LoaderProperty != null && m_LoaderProperty.isArray) @@ -98,6 +133,9 @@ void UpdateSerializedProperty() m_LoaderProperty.serializedObject.ApplyModifiedProperties(); } + + if(m_onUpdate != null) + m_onUpdate(); } void ReorderLoaderList(ReorderableList list) @@ -110,29 +148,146 @@ void DrawAddDropdown(Rect rect, ReorderableList list) GenericMenu menu = new GenericMenu(); int index = 0; - foreach (var info in m_LoadersNotInUse) + if(m_LoadersNotInUse.Count > 0) { - string name = info.assetName; - if (String.IsNullOrEmpty(name) && info.loaderType != null) + foreach (var info in m_LoadersNotInUse) { - name = EditorUtilities.TypeNameToString(info.loaderType); + string name = info.assetName; + if (String.IsNullOrEmpty(name) && info.loaderType != null) + { + name = EditorUtilities.TypeNameToString(info.loaderType); + } + + if (info.instance == null) + name = name + " (create new)"; + + menu.AddItem(new GUIContent(string.Format("{1}{0}. {2}", index + 1, k_AvailableMenuSeparator, name)), false, AddLoaderMenuSelected, index); + index++; } + } - if (info.instance == null) - name = name + " (create new)"; + index = 0; + if (m_CuratedLoaders != null) + { + foreach (var info in m_CuratedLoaders.CuratedPackages) + { + if (CheckIfCuratedLoaderExists(m_LoadersInUse, info) || CheckIfCuratedLoaderExists(m_LoadersNotInUse, info)) + { + continue; + } - menu.AddItem(new GUIContent(name), false, AddLoaderMenuSelected, index); - index++; + string name = info.MenuTitle; + + menu.AddItem(new GUIContent(string.Format("{1}{0}. {2}", index + 1, k_SuggestedMenuSeparator, name)), false, DownloadLoaderMenuSelected, info); + index++; + } } menu.ShowAsContext(); } + private bool CheckIfCuratedLoaderExists(List loaders, CuratedInfo info) + { + var skip = false; + foreach (var loadedInfo in loaders) + { + var assets = AssetDatabase.FindAssets(String.Format("t:{0}", loadedInfo.loaderType)); + + if (assets.Length > 0) + { + string path = AssetDatabase.GUIDToAssetPath(assets[0]); + + var typeName = EditorUtilities.TypeNameToString(loadedInfo.loaderType); + + if (path.Contains(info.PackageName) || string.Equals(typeName, info.LoaderTypeInfo)) + { + skip = true; + break; + } + } + } + + return skip; + } + + static List m_defferedLoadPackages = new List(); + static PackageManager.Requests.ListRequest m_listRequest; + + void DownloadLoaderMenuSelected(object data) + { + var info = (CuratedInfo)data; + PackageManager.Client.Add(info.PackageName); + + EditorPrefs.SetString("defferedLoadPackage", info.PackageName); + + AssetDatabase.Refresh(); + } + + void DownloadDefferedLoad() + { + if(m_listRequest == null) + { + m_listRequest = PackageManager.Client.List(); + } + + if (m_listRequest.IsCompleted) + { + var listResult = m_listRequest.Result; + + if (EditorPrefs.HasKey("defferedLoadPackage")) + { + var loadPackage = EditorPrefs.GetString("defferedLoadPackage"); + + PackageManager.PackageInfo info = listResult.FirstOrDefault(p => p.name == loadPackage); + if (info != null) + { + if (InsertPackageXRLoaderToList(info)) + { + EditorPrefs.DeleteKey("defferedLoadPackage"); + } + } + else + { + m_listRequest = PackageManager.Client.List(); + } + } + } + } + + bool InsertPackageXRLoaderToList(PackageManager.PackageInfo packageInfo) + { + List newInfos = new List(); + + XRManagerSettingsEditor.GetAllKnownLoaderInfos(newInfos); + + foreach(var info in newInfos) + { + var assets = AssetDatabase.FindAssets(String.Format("t:{0}", info.loaderType)); + + if (assets.Length > 0) + { + string path = AssetDatabase.GUIDToAssetPath(assets[0]); + if(path.Contains(packageInfo.name)) + { + AddLoaderMenu(info); + return true; + } + } + } + + return false; + } + void AddLoaderMenuSelected(object data) { int selected = (int)data; LoaderInfo info = m_LoadersNotInUse[selected]; + AddLoaderMenu(info); + } + + void AddLoaderMenu(LoaderInfo info) + { if (info.instance == null) { string newAssetName = String.Format("{0}.asset", EditorUtilities.TypeNameToString(info.loaderType)); @@ -151,7 +306,6 @@ void AddLoaderMenuSelected(object data) } m_LoadersNotInUse.Remove(info); - info.isUsed = true; m_LoadersInUse.Add(info); UpdateSerializedProperty(); } @@ -163,8 +317,9 @@ void RemoveInstanceFromList(ReorderableList list) if (info.loaderType != null) { - info.isUsed = false; - m_LoadersNotInUse.Add(info); + m_LoadersInUse.Remove(info); + + m_ShouldReload = true; } UpdateSerializedProperty(); } @@ -188,7 +343,7 @@ public bool OnGUI() m_OrderedList.DoLayoutList(); - if (!m_LoadersInUse.Any() && !m_LoadersNotInUse.Any()) + if (!m_LoadersInUse.Any()) { EditorGUILayout.HelpBox(k_AtLeastOneLoaderInstance, MessageType.Warning); } @@ -198,11 +353,11 @@ public bool OnGUI() } - [CustomEditor(typeof(XRManager))] - public class XRManagerEditor : Editor + [CustomEditor(typeof(XRManagerSettings))] + public class XRManagerSettingsEditor : Editor { // Simple class to give us updates when the asset database changes. - class AssetCallbacks : AssetPostprocessor + public class AssetCallbacks : AssetPostprocessor { static bool s_EditorUpdatable = false; public static System.Action Callback { get; set; } @@ -231,14 +386,15 @@ static void EditorUpdatable() } } - SerializedProperty m_AutomaticLoading = null; - SerializedProperty m_AutomaticRunning = null; + SerializedProperty m_RequiresSettingsUpdate = null; SerializedProperty m_LoaderList = null; static GUIContent k_AutoLoadLabel = EditorGUIUtility.TrTextContent("Automatic Loading"); static GUIContent k_AutoRunLabel = EditorGUIUtility.TrTextContent("Automatic Running"); List m_AllLoaderInfos = new List(); + List m_AssignedLoaderInfos = new List(); + XRCuratedPackages m_CuratedInfo; LoaderOrderUI m_LoadOrderUI = null; bool m_MustReloadData = true; @@ -250,35 +406,76 @@ void AssetProcessorCallback() void OnEnable() { - AssetCallbacks.Callback = AssetProcessorCallback; + PopulateCuratedLoaders(); + + AssetCallbacks.Callback += AssetProcessorCallback; ReloadData(); } + public bool ShouldReloadInSettings + { + get + { + if (m_RequiresSettingsUpdate != null) + { + serializedObject.Update(); + + return m_RequiresSettingsUpdate.boolValue; + } + return false; + } + set + { + if (m_RequiresSettingsUpdate == null) + PopulateProperty("m_RequiresSettingsUpdate", ref m_RequiresSettingsUpdate); + + if (m_RequiresSettingsUpdate != null) + { + m_RequiresSettingsUpdate.boolValue = value; + + serializedObject.ApplyModifiedProperties(); + } + } + } + public void OnDisable() { - AssetCallbacks.Callback = null; + AssetCallbacks.Callback -= null; } void ReloadData() { if (m_LoaderList == null || m_LoaderList.serializedObject == null) return; - - m_LoadOrderUI = null; - + m_AllLoaderInfos.Clear(); + + m_AssignedLoaderInfos.Clear(); + + PopulateCuratedLoaders(); PopulateLoaderInfosFromCurrentAssignedLoaders(); PopulateLoaderInfosFromUnassignedLoaders(); + } + + void PopulateCuratedLoaders() + { + var assets = AssetDatabase.FindAssets(String.Format("t:{0}", typeof(XRCuratedPackages))); + + if(assets.Length > 0) + { + string path = AssetDatabase.GUIDToAssetPath(assets[0]); - m_MustReloadData = false; + if(m_CuratedInfo == null) + m_CuratedInfo = AssetDatabase.LoadAssetAtPath(path, typeof(XRCuratedPackages)) as XRCuratedPackages; + } } void PopulateLoaderInfosFromUnassignedLoaders() { List newInfos = new List(); - + GetAllKnownLoaderInfos(newInfos); MergeLoaderInfos(newInfos); } @@ -309,7 +506,7 @@ void MergeLoaderInfos(List newInfos) } } - static void GetAllKnownLoaderInfos(List newInfos) + internal static void GetAllKnownLoaderInfos(List newInfos) { var loaderTypes = TypeLoaderExtensions.GetAllTypesWithInterface(); foreach (Type loaderType in loaderTypes) @@ -361,7 +558,8 @@ void PopulateLoaderInfosFromCurrentAssignedLoaders() info.loaderType = (prop.objectReferenceValue == null) ? null : prop.objectReferenceValue.GetType(); info.assetName = AssetNameFromInstance(prop.objectReferenceValue); info.instance = prop.objectReferenceValue as XRLoader; - info.isUsed = true; + + m_AssignedLoaderInfos.Add(info); m_AllLoaderInfos.Add(info); } } @@ -375,25 +573,45 @@ public override void OnInspectorGUI() { if (serializedObject == null || serializedObject.targetObject == null) return; - - PopulateProperty("m_AutomaticLoading", ref m_AutomaticLoading); - PopulateProperty("m_AutomaticRunning", ref m_AutomaticRunning); + + PopulateProperty("m_RequiresSettingsUpdate", ref m_RequiresSettingsUpdate); PopulateProperty("m_Loaders", ref m_LoaderList); serializedObject.Update(); + m_LoaderList.serializedObject.ApplyModifiedProperties(); if (m_MustReloadData) ReloadData(); + + if (m_LoadOrderUI == null) + { + m_LoadOrderUI = new LoaderOrderUI(m_AllLoaderInfos, m_CuratedInfo, m_AssignedLoaderInfos, m_LoaderList, () => + { + m_RequiresSettingsUpdate.boolValue = true; + LoaderOrderUICallback(); + }); + } + else + { + if (m_RequiresSettingsUpdate.boolValue == true || m_LoadOrderUI.CheckIfChanged(m_AssignedLoaderInfos) || EditorPrefs.HasKey("defferedLoadPackage")) + { + ReloadData(); - EditorGUILayout.PropertyField(m_AutomaticLoading, k_AutoLoadLabel); - if (m_AutomaticLoading.boolValue) - EditorGUILayout.PropertyField(m_AutomaticRunning, k_AutoRunLabel); - - if (m_LoadOrderUI == null) m_LoadOrderUI = new LoaderOrderUI(m_AllLoaderInfos, m_LoaderList); + m_LoadOrderUI.Reset(m_AllLoaderInfos, m_CuratedInfo, m_AssignedLoaderInfos, m_LoaderList, null); + } + } m_MustReloadData = m_LoadOrderUI.OnGUI(); serializedObject.ApplyModifiedProperties(); } + + private void LoaderOrderUICallback() + { + m_LoaderList.serializedObject.ApplyModifiedProperties(); + + m_MustReloadData = true; + ReloadData(); + } } } diff --git a/Editor/XRSettingsManager.cs b/Editor/XRSettingsManager.cs index 13efc93..8ff8296 100644 --- a/Editor/XRSettingsManager.cs +++ b/Editor/XRSettingsManager.cs @@ -23,9 +23,12 @@ class XRSettingsManager : SettingsProvider static GUIContent s_LoaderXRManagerLabel = new GUIContent("XR Manager Instance"); static GUIContent s_LoaderInitOnStartLabel = new GUIContent("Initialize on Startup"); + static GUIContent s_SettingsDetailsFoldout = new GUIContent("Details"); SerializedObject m_SettingsWrapper; + private Dictionary CachedSettingsEditor = new Dictionary(); + static XRGeneralSettingsPerBuildTarget currentSettings { get @@ -121,6 +124,8 @@ public override void OnActivate(string searchContext, VisualElement rootElement) public override void OnDeactivate() { m_SettingsWrapper = null; + + CachedSettingsEditor.Clear(); } public override void OnGUI(string searchContext) @@ -143,13 +148,46 @@ public override void OnGUI(string searchContext) serializedSettingsObject.Update(); SerializedProperty loaderProp = serializedSettingsObject.FindProperty("m_LoaderManagerInstance"); - var obj = EditorGUILayout.ObjectField(s_LoaderXRManagerLabel, loaderProp.objectReferenceValue, typeof(GameObject), false) as GameObject; - if (obj != null && obj.GetComponent() != null) + + if (!CachedSettingsEditor.ContainsKey(buildTargetGroup)) + { + CachedSettingsEditor.Add(buildTargetGroup, null); + } + + if (loaderProp.objectReferenceValue == null) + { + var xrManagerSettings = ScriptableObject.CreateInstance() as XRManagerSettings; + AssetDatabase.AddObjectToAsset(xrManagerSettings, AssetDatabase.GetAssetOrScenePath(currentSettings)); + loaderProp.objectReferenceValue = xrManagerSettings; + serializedSettingsObject.ApplyModifiedProperties(); + } + + EditorGUI.BeginChangeCheck(); + var obj = EditorGUILayout.ObjectField(s_LoaderXRManagerLabel, loaderProp.objectReferenceValue, typeof(XRManagerSettings), false) as XRManagerSettings; + + if (EditorGUI.EndChangeCheck()) + { + CachedSettingsEditor[buildTargetGroup] = null; + } + + if (obj != null) { - XRManager inst = obj.GetComponent(); - inst.automaticLoading = false; - inst.automaticRunning = false; loaderProp.objectReferenceValue = obj; + + if(CachedSettingsEditor[buildTargetGroup] == null) + { + CachedSettingsEditor[buildTargetGroup] = Editor.CreateEditor(obj); + + if (CachedSettingsEditor[buildTargetGroup] == null) + { + Debug.LogError("Failed to create a view for XR Settings Instance"); + } + } + + if (CachedSettingsEditor[buildTargetGroup] != null) + { + CachedSettingsEditor[buildTargetGroup].OnInspectorGUI(); + } } else if (obj != null) { @@ -157,24 +195,18 @@ public override void OnGUI(string searchContext) } else if (obj == null) { - settings.LoaderManagerInstance = null; + settings.AssignedSettings = null; loaderProp.objectReferenceValue = null; } - SerializedProperty initOnStartProp = serializedSettingsObject.FindProperty("m_InitManagerOnStart"); - EditorGUILayout.PropertyField(initOnStartProp, s_LoaderInitOnStartLabel); - - EditorGUILayout.HelpBox("Select a prefab that has an XRManager component assigned to it." + - " If initialize is enabled, this will be used to initialize the XR SDK at application start, " + - "and the assigned manager instance will have automatic loading and running disabled.\n\n" + - "If initialize is disabled, the manager will only be used to do minimal pre-initialization at engine startup.", MessageType.Info); - serializedSettingsObject.ApplyModifiedProperties(); EditorGUILayout.EndBuildTargetSelectionGrouping(); m_SettingsWrapper.ApplyModifiedProperties(); } + + base.OnGUI(searchContext); } } diff --git a/Runtime/XRCuratedPackages.cs b/Runtime/XRCuratedPackages.cs new file mode 100644 index 0000000..f8d1261 --- /dev/null +++ b/Runtime/XRCuratedPackages.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections; +using System.Collections.Generic; + +using UnityEditor; + +using UnityEngine; +#if UNITY_2019_1_OR_NEWER +using UnityEngine.UIElements; +#else +using UnityEngine.Experimental.UIElements; +#endif +using UnityEngine.Serialization; +using UnityEngine.XR.Management; + +namespace UnityEngine.XR.Management +{ + [Serializable] + public class CuratedInfo + { + public string MenuTitle; + public string PackageName; + public string LoaderTypeInfo; + } + + public sealed class XRCuratedPackages : ScriptableObject + { + [SerializeField] + public CuratedInfo[] CuratedPackages; + } +} diff --git a/Runtime/XRCuratedPackages.cs.meta b/Runtime/XRCuratedPackages.cs.meta new file mode 100644 index 0000000..e82eedb --- /dev/null +++ b/Runtime/XRCuratedPackages.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e5b070e20b4035c43810cb53fceb8a3b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/XRGeneralSettings.cs b/Runtime/XRGeneralSettings.cs index 256e8ba..4b23e89 100644 --- a/Runtime/XRGeneralSettings.cs +++ b/Runtime/XRGeneralSettings.cs @@ -16,18 +16,18 @@ public class XRGeneralSettings : ScriptableObject internal static XRGeneralSettings s_RuntimeSettingsInstance = null; [SerializeField] - internal GameObject m_LoaderManagerInstance = null; + internal XRManagerSettings m_LoaderManagerInstance = null; [SerializeField] internal bool m_InitManagerOnStart = true; - public GameObject Manager + public XRManagerSettings Manager { get { return m_LoaderManagerInstance; } set { m_LoaderManagerInstance = value; } } - private XRManager m_XRManager = null; + private XRManagerSettings m_XRManager = null; public static XRGeneralSettings Instance { @@ -37,7 +37,7 @@ public static XRGeneralSettings Instance } } - public GameObject LoaderManagerInstance + public XRManagerSettings AssignedSettings { get { @@ -46,17 +46,6 @@ public GameObject LoaderManagerInstance #if UNITY_EDITOR set { - GameObject go = value as GameObject; - if (go != null) - { - XRManager goc = go.GetComponent() as XRManager; - if (goc == null) - { - Debug.LogError("Attempting to assing a game object intance that does not contaion an XRManager component on it."); - return; - } - } - m_LoaderManagerInstance = value; } #endif @@ -180,7 +169,7 @@ private void InitXRSDK() if (XRGeneralSettings.Instance == null || XRGeneralSettings.Instance.m_LoaderManagerInstance == null || XRGeneralSettings.Instance.m_InitManagerOnStart == false) return; - m_XRManager = XRGeneralSettings.Instance.m_LoaderManagerInstance.GetComponent(); + m_XRManager = XRGeneralSettings.Instance.m_LoaderManagerInstance; if (m_XRManager == null) { Debug.LogError("Assigned GameObject for XR Management loading is invalid. XR SDK will not be automatically loaded."); @@ -194,7 +183,7 @@ private void InitXRSDK() private void StartXRSDK() { - if (m_XRManager != null && XRManager.activeLoader != null) + if (m_XRManager != null && m_XRManager.activeLoader != null) { m_XRManager.StartSubsystems(); } @@ -202,7 +191,7 @@ private void StartXRSDK() private void StopXRSDK() { - if (m_XRManager != null && XRManager.activeLoader != null) + if (m_XRManager != null && m_XRManager.activeLoader != null) { m_XRManager.StopSubsystems(); } @@ -210,7 +199,7 @@ private void StopXRSDK() private void DeInitXRSDK() { - if (m_XRManager != null && XRManager.activeLoader != null) + if (m_XRManager != null && m_XRManager.activeLoader != null) { m_XRManager.DeinitializeLoader(); m_XRManager = null; diff --git a/Runtime/XRManager.cs b/Runtime/XRManagerSettings.cs similarity index 92% rename from Runtime/XRManager.cs rename to Runtime/XRManagerSettings.cs index 60ae9d5..016b957 100644 --- a/Runtime/XRManager.cs +++ b/Runtime/XRManagerSettings.cs @@ -36,15 +36,25 @@ namespace UnityEngine.XR.Management /// * OnDisable -> . Ask the active loader to stop all subsystems. /// * OnDestroy -> . Deinitialize and remove the active loader. /// - public sealed class XRManager : MonoBehaviour + [CreateAssetMenu(fileName = "XRSettings", menuName = "XRSettings", order = 1)] + public sealed class XRManagerSettings : ScriptableObject { [HideInInspector] bool m_InitializationComplete = false; +#pragma warning disable 414 + // This property is only used by the scriptable object editing part of the system and as such no one + // directly references it. Have to manually disable the console warning here so that we can + // get a clean console report. + [HideInInspector] + [SerializeField] + bool m_RequiresSettingsUpdate = false; +#pragma warning restore 414 + [SerializeField] [Tooltip("Determines if the XR Manager instance is responsible for creating and destroying the appropriate loader instance.")] [FormerlySerializedAs("AutomaticLoading")] - bool m_AutomaticLoading = true; + bool m_AutomaticLoading = false; /// /// Get and set Automatic Loading state for this manager. When this is true, the manager will automatically call @@ -61,7 +71,7 @@ public bool automaticLoading [SerializeField] [Tooltip("Determines if the XR Manager instance is responsible for starting and stopping subsystems for the active loader instance.")] [FormerlySerializedAs("AutomaticRunning")] - bool m_AutomaticRunning = true; + bool m_AutomaticRunning = false; /// /// Get and set automatic running state for this manager. When set to true the manager will call @@ -96,7 +106,7 @@ public List loaders /// public bool isInitializationComplete { - get { return m_InitializationComplete; } + get { return m_InitializationComplete; } } [HideInInspector] @@ -107,7 +117,7 @@ public bool isInitializationComplete /// /// [HideInInspector] - public static XRLoader activeLoader { get { return s_ActiveLoader; } private set { s_ActiveLoader = value; }} + public XRLoader activeLoader { get { return s_ActiveLoader; } private set { s_ActiveLoader = value; } } /// /// Return the current active loader, cast to the requested type. Useful shortcut when you need @@ -117,7 +127,7 @@ public bool isInitializationComplete /// < Requested type of the loader> /// /// < The active loader as requested type, or null.> - public static T ActiveLoaderAs() where T : XRLoader + public T ActiveLoaderAs() where T : XRLoader { return activeLoader as T; } @@ -262,14 +272,6 @@ public void DeinitializeLoader() m_InitializationComplete = false; } - void OnEnable() - { - if (automaticLoading) - { - StartCoroutine(InitializeLoader()); - } - } - // Use this for initialization void Start() { diff --git a/Runtime/XRManager.cs.meta b/Runtime/XRManagerSettings.cs.meta similarity index 100% rename from Runtime/XRManager.cs.meta rename to Runtime/XRManagerSettings.cs.meta diff --git a/Samples~/Editor.meta b/Samples~/Editor.meta index ec7d595..430ec86 100644 --- a/Samples~/Editor.meta +++ b/Samples~/Editor.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 45285ff0f0a22470a9b0709b0dfba7e9 +guid: f2f51cbe2f868114a9897eaca901d062 folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/Samples~/SampleLoader.cs b/Samples~/SampleLoader.cs index e5ad53e..5e7e5d3 100644 --- a/Samples~/SampleLoader.cs +++ b/Samples~/SampleLoader.cs @@ -7,6 +7,7 @@ using UnityEngine.Experimental; using UnityEngine.Experimental.XR; +using UnityEngine.XR; namespace Samples { diff --git a/Tests/Editor/EditorTests.cs b/Tests/Editor/EditorTests.cs index 7143716..9a897a3 100644 --- a/Tests/Editor/EditorTests.cs +++ b/Tests/Editor/EditorTests.cs @@ -23,14 +23,13 @@ class XRGeneralSettingsTests UnityEngine.Object currentSettings = null; - GameObject testManager = null; + XRManagerSettings testManager = null; XRGeneralSettings testSettings = null; [SetUp] public void SetupTest() { - testManager = new GameObject("Test Manager"); - testManager.AddComponent(); + testManager = ScriptableObject.CreateInstance(); testSettings = ScriptableObject.CreateInstance() as XRGeneralSettings; testSettings.Manager = testManager; diff --git a/Tests/Runtime/RuntimeTests.cs b/Tests/Runtime/RuntimeTests.cs index e805ae7..d0cf4d1 100644 --- a/Tests/Runtime/RuntimeTests.cs +++ b/Tests/Runtime/RuntimeTests.cs @@ -18,7 +18,7 @@ namespace Unity.XR.Management.Tests [TestFixture(3, 2)] class ManualLifetimeTests { - GameObject m_GameManager = null; + XRManagerSettings m_Manager; List m_Loaders = new List(); int m_LoaderCount; int m_LoaderIndexToWin; @@ -32,8 +32,7 @@ public ManualLifetimeTests(int loaderCount, int loaderIndexToWin) [SetUp] public void SetupXRManagerTest() { - m_GameManager = new GameObject(); - XRManager manager = m_GameManager.AddComponent() as XRManager; + var manager = ScriptableObject.CreateInstance(); manager.automaticLoading = false; m_Loaders = new List(); @@ -51,35 +50,32 @@ public void SetupXRManagerTest() [TearDown] public void TeardownXRManagerTest() { - Object.Destroy(m_GameManager); - m_GameManager = null; + Object.Destroy(m_Manager); + m_Manager = null; } [UnityTest] public IEnumerator CheckActivatedLoader() { - Assert.IsNotNull(m_GameManager); + Assert.IsNotNull(m_Manager); - XRManager manager = m_GameManager.GetComponent() as XRManager; - Assert.IsNotNull(manager); - - yield return manager.InitializeLoader(); + yield return m_Manager.InitializeLoader(); if (m_LoaderIndexToWin < 0 || m_LoaderIndexToWin >= m_Loaders.Count) { - Assert.IsNull(XRManager.activeLoader); + Assert.IsNull(m_Manager.activeLoader); } else { - Assert.IsNotNull(XRManager.activeLoader); - Assert.AreEqual(m_Loaders[m_LoaderIndexToWin], XRManager.activeLoader); + Assert.IsNotNull(m_Manager.activeLoader); + Assert.AreEqual(m_Loaders[m_LoaderIndexToWin], m_Manager.activeLoader); } - manager.DeinitializeLoader(); + m_Manager.DeinitializeLoader(); - Assert.IsNull(XRManager.activeLoader); + Assert.IsNull(m_Manager.activeLoader); - manager.loaders.Clear(); + m_Manager.loaders.Clear(); } } } diff --git a/Tests/StandaloneSubsystem/StandaloneSubsystem.cs b/Tests/StandaloneSubsystem/StandaloneSubsystem.cs index 20a5000..f61e215 100644 --- a/Tests/StandaloneSubsystem/StandaloneSubsystem.cs +++ b/Tests/StandaloneSubsystem/StandaloneSubsystem.cs @@ -8,26 +8,39 @@ namespace Unity.XR.Management.Tests.Standalone { public class StandaloneSubsystem : Subsystem { + private bool isRunning = false; + public override bool running + { + get + { + return isRunning; + } + } + public event Action startCalled; public event Action stopCalled; public event Action destroyCalled; + public override void Start() { + isRunning = true; if (startCalled != null) startCalled.Invoke(); } public override void Stop() { + isRunning = false; if (stopCalled != null) stopCalled.Invoke(); } public override void Destroy() { + isRunning = false; if (destroyCalled != null) destroyCalled.Invoke(); } } -} \ No newline at end of file +} diff --git a/package.json b/package.json index c8a9b87..ffe1e75 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "com.unity.xr.management", "displayName": "XR SDK Management", - "version": "2.0.0-preview.6", + "version": "2.0.0-preview.9", "unity": "2019.1", "description": "Package to provide for simple management of XR SDK loading, unloading and configuration.", "keywords": [ @@ -18,7 +18,7 @@ "repository": { "type": "git", "url": "https://gitlab.cds.internal.unity3d.com/xr/sdk/xr-management.git", - "revision": "7f28475d38aab750a9f47bd60a4c034f9b9a9569" + "revision": "35c1b26696b84daa77e7144b70e76668fc1a3fd7" }, "samples": [ {