/* * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * Licensed under the Oculus SDK License Agreement (the "License"); * you may not use the Oculus SDK except in compliance with the License, * which is provided at the time of installation or download, or which * otherwise accompanies this software in either electronic or hard copy form. * * You may obtain a copy of the License at * * https://developer.oculus.com/licenses/oculussdk/ * * Unless required by applicable law or agreed to in writing, the Oculus SDK * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System.Collections.Generic; using UnityEditor; using System; using System.Linq; using UnityEngine; /// /// Core System for the OVRProjectSetup Tool /// /// /// This static class manages that can be added at any point. /// Use the AddTask method to add and register . /// public static class OVRProjectSetup { public enum TaskLevel { Optional = 0, Recommended = 1, Required = 2 } public enum TaskGroup { All = 0, Compatibility = 1, Rendering = 2, Quality = 3, Physics = 4, Packages = 5, Features = 6, Miscellaneous = 7 } private static readonly OVRConfigurationTaskRegistry _principalRegistry; internal static OVRConfigurationTaskRegistry Registry { get; private set; } internal static OVRConfigurationTaskProcessorQueue ProcessorQueue { get; } internal const string KeyPrefix = "OVRProjectSetup"; internal static OVRProjectSetupSettingBool Enabled; internal static OVRProjectSetupSettingBool RequiredThrowErrors; internal static readonly OVRProjectSetupSettingBool AllowLogs = new OVRProjectSetupProjectSettingBool("AllowLogs", false, "Log outstanding issues"); internal static readonly OVRProjectSetupSettingBool ShowStatusIcon = new OVRProjectSetupProjectSettingBool("ShowStatusIcon", true, "Show Status Icon"); internal static readonly OVRProjectSetupSettingBool ProduceReportOnBuild = new OVRProjectSetupProjectSettingBool("ProduceReportOnBuild", false, "Produce Report on Build"); private static readonly HashSet SupportedPlatforms = new HashSet { BuildTargetGroup.Android, BuildTargetGroup.Standalone }; static OVRProjectSetup() { _principalRegistry = new OVRConfigurationTaskRegistry(); ProcessorQueue = new OVRConfigurationTaskProcessorQueue(); ConsoleLinkEventHandler.OnConsoleLink += OnConsoleLink; RestoreRegistry(); ProcessorQueue.OnProcessorCompleted += RefreshBuildStatusMenuSubText; var statusItem = new OVRStatusMenu.Item() { Name = "Project Setup Tool", Color = OVREditorUtils.HexToColor("#4e4e4e"), Icon = OVREditorUtils.CreateContent("ovr_icon_upst.png", OVRGUIContent.Source.ProjectSetupToolIcons), InfoTextDelegate = GetMenuSubText, OnClickDelegate = OnStatusMenuClick, Order = 0 }; OVRStatusMenu.RegisterItem(statusItem); } private static string _statusMenuSubText; private static void RefreshBuildStatusMenuSubText(OVRConfigurationTaskProcessor processor) { var updater = processor as OVRConfigurationTaskUpdater; var summary = updater?.Summary; _statusMenuSubText = summary?.ComputeNoticeMessage(); } public static string GetMenuSubText() => _statusMenuSubText; private static void OnStatusMenuClick() { OVRProjectSetupSettingsProvider.OpenSettingsWindow(OVRProjectSetupSettingsProvider.Origins.Icon); } internal static void SetupTemporaryRegistry() { Registry = new OVRConfigurationTaskRegistry(); Enabled = new OVRProjectSetupConstSettingBool("Enabled", true, "Enabled"); RequiredThrowErrors = new OVRProjectSetupConstSettingBool("RequiredThrowErrors", false, "Required throw errors"); OVRProjectSetupUpdater.SetupTemporaryRegistry(); } internal static void RestoreRegistry() { Registry = _principalRegistry; Enabled = new OVRProjectSetupConstSettingBool("Enabled", true, "Enabled"); RequiredThrowErrors = new OVRProjectSetupProjectSettingBool("RequiredThrowErrors", false, "Required throw errors"); OVRProjectSetupUpdater.RestoreRegistry(); } private static void OnConsoleLink(Dictionary infos) { if (infos.TryGetValue("href", out var href)) { if (href == OVRConfigurationTask.ConsoleLinkHref) { OVRProjectSetupSettingsProvider.OpenSettingsWindow(OVRProjectSetupSettingsProvider.Origins.Console); } } } internal static IEnumerable GetTasks(BuildTargetGroup buildTargetGroup, bool refresh) { return Registry.GetTasks(buildTargetGroup, refresh); } /// /// Add an to the Setup Tool. /// /// /// This methods adds and registers an already created to the SetupTool. /// We recommend the use of the other AddTask method with all the required parameters to create the task. /// /// The task that will get registered to the Setup Tool. /// Possible causes : /// - a task with the same unique ID already has been registered (conflict in hash generated from description message). internal static void AddTask(OVRConfigurationTask task) { Registry.AddTask(task); } /// /// Add an to the Setup Tool. /// /// /// This methods creates, adds and registers an to the SetupTool. /// Please note that the Message or ConditionalMessage parameters have to be unique since they are being hashed to generate a Unique ID for the task. /// Those tasks, once added, are not meant to be removed from the Setup Tool, and will get checked at some key points. /// This method is the one entry point for developers to add their own sanity checks, technical requirements or other recommendations. /// You can use the conditional parameters that accepts lambdas or delegates for more complex behaviours if needed. /// /// Category that fits the task. Feel free to add more to the enum if relevant. Do not use "All". /// Delegate that checks if the Configuration Task is validated or not. /// Platform for which this Configuration Task applies. Use "Unknown" for any. /// Delegate that validates the Configuration Task. /// Severity (or behaviour) of the Configuration Task. /// Use this delegate for more control or complex behaviours over the level parameter. /// Description of the Configuration Task. /// Use this delegate for more control or complex behaviours over the message parameter. /// Description of the actual fix for the Task. /// Use this delegate for more control or complex behaviours over the fixMessage parameter. /// Url to more information about the Configuration Task. /// Use this delegate for more control or complex behaviours over the url parameter. /// Checks if the task is valid. If not, it will be ignored by the Setup Tool. /// Use this delegate for more control or complex behaviours over the validity parameter. /// Possible causes : /// - If either message or conditionalMessage do not provide a valid non null string /// - isDone is null /// - fix is null /// Possible causes : /// - group is set to "All". This category is not meant to be used to describe a task. /// - a task with the same unique ID already has been registered (conflict in hash generated from description message). public static void AddTask( OVRProjectSetup.TaskGroup group, Func isDone, BuildTargetGroup platform = BuildTargetGroup.Unknown, Action fix = null, OVRProjectSetup.TaskLevel level = OVRProjectSetup.TaskLevel.Recommended, Func conditionalLevel = null, string message = null, Func conditionalMessage = null, string fixMessage = null, Func conditionalFixMessage = null, string url = null, Func conditionalUrl = null, bool validity = true, Func conditionalValidity = null ) { var optionalLevel = OptionalLambdaType.Create(level, conditionalLevel, true); var optionalMessage = OptionalLambdaType.Create(message, conditionalMessage, true); var optionalFixMessage = OptionalLambdaType.Create(fixMessage, conditionalFixMessage, true); var optionalUrl = OptionalLambdaType.Create(url, conditionalUrl, true); var optionalValidity = OptionalLambdaType.Create(validity, conditionalValidity, true); AddTask(new OVRConfigurationTask(group, platform, isDone, fix, optionalLevel, optionalMessage, optionalFixMessage, optionalUrl, optionalValidity)); } internal static bool IsPlatformSupported(BuildTargetGroup buildTargetGroup) { return SupportedPlatforms.Contains(buildTargetGroup); } internal enum LogMessages { Disabled = 0, Summary = 1, Changed = 2, All = 3, } private const int LoopExitCount = 4; internal static void FixTasks( BuildTargetGroup buildTargetGroup, Func, List> filter = null, LogMessages logMessages = LogMessages.Disabled, bool blocking = true, Action onCompleted = null) { var fixer = new OVRConfigurationTaskFixer(Registry, buildTargetGroup, filter, logMessages, blocking, onCompleted); ProcessorQueue.Request(fixer); } internal static void FixTask( BuildTargetGroup buildTargetGroup, OVRConfigurationTask task, LogMessages logMessages = LogMessages.Disabled, bool blocking = true, Action onCompleted = null ) { // TODO : A bit overkill for just one task var filter = (Func, List>)(tasks => tasks.Where(otherTask => otherTask == task).ToList()); var fixer = new OVRConfigurationTaskFixer(Registry, buildTargetGroup, filter, logMessages, blocking, onCompleted); ProcessorQueue.Request(fixer); } internal static void UpdateTasks( BuildTargetGroup buildTargetGroup, Func, List> filter = null, LogMessages logMessages = LogMessages.Disabled, bool blocking = true, Action onCompleted = null) { var updater = new OVRConfigurationTaskUpdater(Registry, buildTargetGroup, filter, logMessages, blocking, onCompleted); ProcessorQueue.Request(updater); } }