Initialer Upload neues Unity-Projekt

This commit is contained in:
Daniel Ocks
2025-07-21 09:11:14 +02:00
commit eeca72985b
14558 changed files with 1508140 additions and 0 deletions

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 4b1b824db73a75642b72bb9ecff9c88e
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,144 @@
/*
* 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;
using UnityEditor;
[InitializeOnLoad]
internal static class OVRProjectSetupCompatibilityTasks
{
public static bool IsTargetingARM64 =>
(PlayerSettings.Android.targetArchitectures & AndroidArchitecture.ARM64) != 0;
public static readonly Action<BuildTargetGroup> SetARM64Target = (buildTargetGroup) =>
PlayerSettings.Android.targetArchitectures = AndroidArchitecture.ARM64;
static OVRProjectSetupCompatibilityTasks()
{
var compatibilityTaskGroup = OVRProjectSetup.TaskGroup.Compatibility;
// [Required] Platform has to be supported
OVRProjectSetup.AddTask(
level: OVRProjectSetup.TaskLevel.Required,
group: compatibilityTaskGroup,
isDone: OVRProjectSetup.IsPlatformSupported,
conditionalMessage: buildTargetGroup =>
OVRProjectSetup.IsPlatformSupported(buildTargetGroup)
? $"Build Target ({buildTargetGroup}) is supported"
: $"Build Target ({buildTargetGroup}) is not supported"
);
// [Required] Android minimum level API
OVRProjectSetup.AddTask(
level: OVRProjectSetup.TaskLevel.Required,
group: compatibilityTaskGroup,
platform: BuildTargetGroup.Android,
isDone: buildTargetGroup => PlayerSettings.Android.minSdkVersion >= AndroidSdkVersions.AndroidApiLevel29,
message: "Minimum Android API Level must be at least 29",
fix: buildTargetGroup => PlayerSettings.Android.minSdkVersion = AndroidSdkVersions.AndroidApiLevel29,
fixMessage: "PlayerSettings.Android.minSdkVersion = AndroidSdkVersions.AndroidApiLevel29"
);
// [Required] Android target level API
OVRProjectSetup.AddTask(
level: OVRProjectSetup.TaskLevel.Recommended,
group: compatibilityTaskGroup,
platform: BuildTargetGroup.Android,
isDone: buildTargetGroup =>
PlayerSettings.Android.targetSdkVersion == AndroidSdkVersions.AndroidApiLevelAuto ||
PlayerSettings.Android.targetSdkVersion >= AndroidSdkVersions.AndroidApiLevel29,
message: "Target API should be set to \"Automatic\" as to ensure latest version",
fix: buildTargetGroup => PlayerSettings.Android.targetSdkVersion = AndroidSdkVersions.AndroidApiLevelAuto,
fixMessage: "PlayerSettings.Android.targetSdkVersion = AndroidSdkVersions.AndroidApiLevelAuto"
);
// [Required] Install Location
OVRProjectSetup.AddTask(
level: OVRProjectSetup.TaskLevel.Recommended,
group: compatibilityTaskGroup,
platform: BuildTargetGroup.Android,
isDone: buildTargetGroup =>
PlayerSettings.Android.preferredInstallLocation == AndroidPreferredInstallLocation.Auto,
message: "Install Location should be set to \"Automatic\"",
fix: buildTargetGroup =>
PlayerSettings.Android.preferredInstallLocation = AndroidPreferredInstallLocation.Auto,
fixMessage: "PlayerSettings.Android.preferredInstallLocation = AndroidPreferredInstallLocation.Auto"
);
// [Required] Generate Android Manifest
OVRProjectSetup.AddTask(
level: OVRProjectSetup.TaskLevel.Optional,
group: compatibilityTaskGroup,
platform: BuildTargetGroup.Android,
isDone: buildTargetGroup => OVRManifestPreprocessor.DoesAndroidManifestExist(),
message: "An Android Manifest file is required",
fix: buildTargetGroup => OVRManifestPreprocessor.GenerateManifestForSubmission(),
fixMessage: "Generates a default Manifest file"
);
// ConfigurationTask : IL2CPP when ARM64
OVRProjectSetup.AddTask(
conditionalLevel: buildTargetGroup =>
IsTargetingARM64 ? OVRProjectSetup.TaskLevel.Required : OVRProjectSetup.TaskLevel.Recommended,
group: compatibilityTaskGroup,
platform: BuildTargetGroup.Android,
isDone: buildTargetGroup =>
PlayerSettings.GetScriptingBackend(buildTargetGroup) == ScriptingImplementation.IL2CPP,
conditionalMessage: buildTargetGroup =>
IsTargetingARM64
? "Building the ARM64 architecture requires using IL2CPP as the scripting backend"
: "Using IL2CPP as the scripting backend is recommended",
fix: buildTargetGroup =>
PlayerSettings.SetScriptingBackend(buildTargetGroup, ScriptingImplementation.IL2CPP),
fixMessage: "PlayerSettings.SetScriptingBackend(buildTargetGroup, ScriptingImplementation.IL2CPP)"
);
// ConfigurationTask : ARM64 is recommended
OVRProjectSetup.AddTask(
level: OVRProjectSetup.TaskLevel.Required,
group: compatibilityTaskGroup,
platform: BuildTargetGroup.Android,
isDone: buildTargetGroup => IsTargetingARM64,
message: "Use ARM64 as target architecture",
fix: SetARM64Target,
fixMessage: "PlayerSettings.Android.targetArchitectures = AndroidArchitecture.ARM64"
);
// ConfigurationTask : No Alpha or Beta for production
// This is a task that CANNOT BE FIXED
OVRProjectSetup.AddTask(
level: OVRProjectSetup.TaskLevel.Recommended,
group: compatibilityTaskGroup,
isDone: group => !OVRManager.IsUnityAlphaOrBetaVersion(),
message: "We recommend using a stable version for Oculus Development"
);
// ConfigurationTask : Check that Android TV Compatibility is disabled
OVRProjectSetup.AddTask(
level: OVRProjectSetup.TaskLevel.Required,
platform: BuildTargetGroup.Android,
group: compatibilityTaskGroup,
isDone: group => !PlayerSettings.Android.androidTVCompatibility,
message: "Apps with Android TV Compatibility enabled are not accepted by the Oculus Store",
fix: group => PlayerSettings.Android.androidTVCompatibility = false,
fixMessage: "PlayerSettings.Android.androidTVCompatibility = false"
);
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f23b5d0d61a07874aa97d72200848188
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,23 @@
/*
* 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.
*/
/*
That file was intentionally removed.
*/

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: fc6140a65ceb57243bfbd2ffffe5fc98
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,100 @@
/*
* 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;
using UnityEditor;
using UnityEngine;
[InitializeOnLoad]
internal static class OVRProjectSetupMovementSDKTasks2
{
private const OVRProjectSetup.TaskGroup Group = OVRProjectSetup.TaskGroup.Features;
static OVRProjectSetupMovementSDKTasks2()
{
AddMovementTrackingTasks<OVRBody>(
"Body Tracking",
() => OVRProjectConfig.CachedProjectConfig.bodyTrackingSupport,
ovrManager => ovrManager.requestBodyTrackingPermissionOnStartup,
projectConfig => projectConfig.bodyTrackingSupport = OVRProjectConfig.FeatureSupport.Supported,
ovrManager => ovrManager.requestBodyTrackingPermissionOnStartup = true);
AddMovementTrackingTasks<OVRFaceExpressions>(
"Face Tracking",
() => OVRProjectConfig.CachedProjectConfig.faceTrackingSupport,
ovrManager => ovrManager.requestFaceTrackingPermissionOnStartup,
projectConfig => projectConfig.faceTrackingSupport = OVRProjectConfig.FeatureSupport.Supported,
ovrManager => ovrManager.requestFaceTrackingPermissionOnStartup = true);
AddMovementTrackingTasks<OVREyeGaze>(
"Eye Tracking",
() => OVRProjectConfig.CachedProjectConfig.eyeTrackingSupport,
ovrManager => ovrManager.requestEyeTrackingPermissionOnStartup,
projectConfig => projectConfig.eyeTrackingSupport = OVRProjectConfig.FeatureSupport.Supported,
ovrManager => ovrManager.requestEyeTrackingPermissionOnStartup = true);
}
private static void AddMovementTrackingTasks<T>(string featureName,
Func<OVRProjectConfig.FeatureSupport> supportLevel, Func<OVRManager, bool> permissionRequested,
Action<OVRProjectConfig> enableSupport, Action<OVRManager> enablePermissionRequest) where T : Component
{
OVRProjectSetup.AddTask(
level: OVRProjectSetup.TaskLevel.Required,
group: Group,
isDone: buildTargetGroup => OVRProjectSetupUtils.FindComponentInScene<T>() == null ||
supportLevel() != OVRProjectConfig.FeatureSupport.None,
message: $"When using {featureName} in your project it's required to enable its capability " +
$"in the project config",
fix: buildTargetGroup =>
{
var projectConfig = OVRProjectConfig.CachedProjectConfig;
enableSupport(projectConfig);
OVRProjectConfig.CommitProjectConfig(projectConfig);
},
fixMessage: $"Enable {featureName} support in the project config"
);
OVRProjectSetup.AddTask(
level: OVRProjectSetup.TaskLevel.Required,
group: Group,
isDone: buildTargetGroup =>
{
if (supportLevel() == OVRProjectConfig.FeatureSupport.None)
{
return true;
}
var ovrManager = OVRProjectSetupUtils.FindComponentInScene<OVRManager>();
return !ovrManager || permissionRequested(ovrManager);
},
message: $"Automatically request the {featureName} permission on startup",
fix: buildTargetGroup =>
{
var ovrManager = OVRProjectSetupUtils.FindComponentInScene<OVRManager>();
if (ovrManager != null)
{
enablePermissionRequest(ovrManager);
EditorUtility.SetDirty(ovrManager);
}
},
fixMessage: $"Request {featureName} permission on startup"
);
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0b59f40a4e9d6f340a944dbaa75354ca
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,23 @@
/*
* 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.
*/
/*
That file was intentionally removed.
*/

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1cae49aff62b1d24abd59636906cf874
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,110 @@
/*
* 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 UnityEditor;
[InitializeOnLoad]
internal static class OVRProjectSetupPassthrough
{
private const OVRProjectSetup.TaskGroup Group = OVRProjectSetup.TaskGroup.Features;
static OVRProjectSetupPassthrough()
{
OVRProjectSetup.AddTask(
level: OVRProjectSetup.TaskLevel.Required,
group: Group,
isDone: buildTargetGroup => OVRProjectSetupUtils.FindComponentInScene<OVRPassthroughLayer>() == null ||
OVRProjectConfig.CachedProjectConfig.insightPassthroughSupport !=
OVRProjectConfig.FeatureSupport.None,
message: "When using Passthrough in your project it's required to enable its capability " +
"in the project config",
fix: buildTargetGroup =>
{
var projectConfig = OVRProjectConfig.CachedProjectConfig;
projectConfig.insightPassthroughSupport =
OVRProjectConfig.FeatureSupport.Supported;
OVRProjectConfig.CommitProjectConfig(projectConfig);
},
fixMessage: "Enable Passthrough support in the project config");
OVRProjectSetup.AddTask(
level: OVRProjectSetup.TaskLevel.Required,
group: Group,
isDone: buildTargetGroup =>
{
if (OVRProjectSetupUtils.FindComponentInScene<OVRPassthroughLayer>() == null)
{
return true;
}
var ovrManager = OVRProjectSetupUtils.FindComponentInScene<OVRManager>();
return ovrManager == null || ovrManager.isInsightPassthroughEnabled;
},
message: $"When using Passthrough in your project it's required to enable it in {nameof(OVRManager)}",
fix: buildTargetGroup =>
{
var ovrManager = OVRProjectSetupUtils.FindComponentInScene<OVRManager>();
ovrManager.isInsightPassthroughEnabled = true;
EditorUtility.SetDirty(ovrManager.gameObject);
},
fixMessage: $"Enable Passthrough in the {nameof(OVRManager)}");
OVRProjectSetup.AddTask(
level: OVRProjectSetup.TaskLevel.Required,
group: Group,
isDone: buildTargetGroup => OVRProjectSetupCompatibilityTasks.IsTargetingARM64,
conditionalValidity: buildTargetGroup => OVRProjectConfig.CachedProjectConfig.insightPassthroughSupport !=
OVRProjectConfig.FeatureSupport.None,
message: "When enabling the Passthrough capability in your project it's required to use ARM64 as " +
"the target architecture",
fix: OVRProjectSetupCompatibilityTasks.SetARM64Target,
fixMessage: "PlayerSettings.Android.targetArchitectures = AndroidArchitecture.ARM64"
);
OVRProjectSetup.AddTask(
level: OVRProjectSetup.TaskLevel.Required,
group: Group,
isDone: _ =>
{
var ovrCameraRig = OVRProjectSetupUtils.FindComponentInScene<OVRCameraRig>();
return ovrCameraRig != null &&
OVRPassthroughHelper.HasCentralCamera(ovrCameraRig) &&
OVRPassthroughHelper.IsBackgroundClear(ovrCameraRig);
},
conditionalValidity: _ =>
{
var ovrCameraRig = OVRProjectSetupUtils.FindComponentInScene<OVRCameraRig>();
return ovrCameraRig != null &&
OVRPassthroughHelper.HasCentralCamera(ovrCameraRig) &&
OVRPassthroughHelper.IsAnyPassthroughLayerUnderlay();
},
message: "When using Passthrough as an underlay it's required set the camera background to transparent",
fix: _ =>
{
var ovrCameraRig = OVRProjectSetupUtils.FindComponentInScene<OVRCameraRig>();
if (ovrCameraRig != null && OVRPassthroughHelper.HasCentralCamera(ovrCameraRig))
{
OVRPassthroughHelper.ClearBackground(ovrCameraRig);
}
},
fixMessage: "Clear background of OVRCameraRig"
);
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 340956b8fb5e08e409aeab1bfc3a627d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,60 @@
/*
* 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;
using UnityEditor;
using UnityEngine;
[InitializeOnLoad]
internal static class OVRProjectSetupPhysicsTasks
{
static OVRProjectSetupPhysicsTasks()
{
// [Recommended] Default Contact Offset >= 0.01f
OVRProjectSetup.AddTask(
level: OVRProjectSetup.TaskLevel.Recommended,
group: OVRProjectSetup.TaskGroup.Physics,
isDone: group => Physics.defaultContactOffset >= 0.01f,
message: $"Use Default Context Offset above or equal to 0.01",
fix: group => Physics.defaultContactOffset = 0.01f,
fixMessage: "Physics.defaultContactOffset = 0.01f"
);
// [Recommended] Sleep Threshold >= 0.005f
OVRProjectSetup.AddTask(
level: OVRProjectSetup.TaskLevel.Recommended,
group: OVRProjectSetup.TaskGroup.Physics,
isDone: group => Physics.sleepThreshold >= 0.005f,
message: $"Use Sleep Threshold above or equal to 0.005",
fix: group => Physics.sleepThreshold = 0.005f,
fixMessage: "Physics.sleepThreshold = 0.005f"
);
// [Recommended] Default Solver Iterations <= 8
OVRProjectSetup.AddTask(
level: OVRProjectSetup.TaskLevel.Recommended,
group: OVRProjectSetup.TaskGroup.Physics,
isDone: group => Physics.defaultSolverIterations <= 8,
message: $"Use Default Solver Iteration below or equal to 8",
fix: group => Physics.defaultSolverIterations = 8,
fixMessage: "Physics.defaultSolverIterations = 8"
);
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 8f88d78901e142de81bcf89db9d8499b
timeCreated: 1664783258

View File

@ -0,0 +1,91 @@
/*
* 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 UnityEditor;
using UnityEngine;
[InitializeOnLoad]
internal static class OVRProjectSetupQualityTasks
{
private static readonly int RecommendedPixelLightCountAndroid = 1;
private static readonly int RecommendedPixelLightCountStandalone = 3;
private static int GetRecommendedPixelLightCount(BuildTargetGroup buildTargetGroup)
=> buildTargetGroup == BuildTargetGroup.Standalone
? RecommendedPixelLightCountStandalone
: RecommendedPixelLightCountAndroid;
static OVRProjectSetupQualityTasks()
{
var taskGroup = OVRProjectSetup.TaskGroup.Quality;
// [Recommended] Set Pixel Light Count
OVRProjectSetup.AddTask(
level: OVRProjectSetup.TaskLevel.Recommended,
group: taskGroup,
isDone: buildTargetGroup =>
QualitySettings.pixelLightCount <= GetRecommendedPixelLightCount(buildTargetGroup),
conditionalMessage: buildTargetGroup =>
$"Set maximum pixel lights count to {GetRecommendedPixelLightCount(buildTargetGroup)}",
fix: buildTargetGroup => QualitySettings.pixelLightCount = GetRecommendedPixelLightCount(buildTargetGroup),
conditionalFixMessage: buildTargetGroup =>
$"QualitySettings.pixelLightCount = {GetRecommendedPixelLightCount(buildTargetGroup)}"
);
// [Recommended] Set Texture Quality to Full Res
OVRProjectSetup.AddTask(
level: OVRProjectSetup.TaskLevel.Recommended,
group: taskGroup,
message: "Set Texture Quality to Full Res",
#if UNITY_2022_2_OR_NEWER // masterTextureLimit has become obsolete with 2022.2
isDone: buildTargetGroup => QualitySettings.globalTextureMipmapLimit == 0,
fix: buildTargetGroup => QualitySettings.globalTextureMipmapLimit = 0,
fixMessage: "QualitySettings.globalTextureMipmapLimit = 0"
#else
isDone: buildTargetGroup => QualitySettings.masterTextureLimit == 0,
fix: buildTargetGroup => QualitySettings.masterTextureLimit = 0,
fixMessage: "QualitySettings.masterTextureLimit = 0"
#endif
);
// [Recommended] Enable Anisotropic Filtering
OVRProjectSetup.AddTask(
level: OVRProjectSetup.TaskLevel.Recommended,
group: taskGroup,
isDone: buildTargetGroup => QualitySettings.anisotropicFiltering == AnisotropicFiltering.Enable,
message: "Enable Anisotropic Filtering on a per-texture basis",
fix: buildTargetGroup => QualitySettings.anisotropicFiltering = AnisotropicFiltering.Enable,
fixMessage: "QualitySettings.anisotropicFiltering = AnisotropicFiltering.Enable"
);
// Texture compression : Use ASTC
OVRProjectSetup.AddTask(
level: OVRProjectSetup.TaskLevel.Recommended,
group: taskGroup,
platform: BuildTargetGroup.Android,
isDone: group => EditorUserBuildSettings.androidBuildSubtarget == MobileTextureSubtarget.ASTC ||
EditorUserBuildSettings.androidBuildSubtarget == MobileTextureSubtarget.ETC2,
message: "Optimize Texture Compression : For GPU performance, please use ETC2. In some cases, " +
"ASTC may produce better visuals and is also a viable solution",
fix: group => EditorUserBuildSettings.androidBuildSubtarget = MobileTextureSubtarget.ETC2,
fixMessage: "EditorUserBuildSettings.androidBuildSubtarget = MobileTextureSubtarget.ETC2"
);
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a9f06298f32b7b54985a5a7464381e8d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,368 @@
/*
* 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;
using System.Linq;
using UnityEditor;
using UnityEditor.Rendering;
using UnityEngine;
using UnityEngine.Rendering;
#if USING_URP
using UnityEngine.Rendering.Universal;
#endif
[InitializeOnLoad]
internal static class OVRProjectSetupRenderingTasks
{
#if USING_XR_SDK_OCULUS
private static Unity.XR.Oculus.OculusSettings OculusSettings
{
get
{
UnityEditor.EditorBuildSettings.TryGetConfigObject<Unity.XR.Oculus.OculusSettings>(
"Unity.XR.Oculus.Settings", out var settings);
return settings;
}
}
#endif
#if USING_URP && UNITY_2022_2_OR_NEWER
// Call action for all UniversalRendererData being used, return true if all the return value of action is true
private static bool ForEachRendererData(Func<UniversalRendererData, bool> action)
{
var ret = true;
var pipelineAssets = new System.Collections.Generic.List<RenderPipelineAsset>();
QualitySettings.GetAllRenderPipelineAssetsForPlatform("Android", ref pipelineAssets);
foreach (var pipelineAsset in pipelineAssets)
{
var urpPipelineAsset = pipelineAsset as UniversalRenderPipelineAsset;
// If using URP pipeline
if (urpPipelineAsset)
{
var path = AssetDatabase.GetAssetPath(urpPipelineAsset);
var dependency = AssetDatabase.GetDependencies(path);
for (int i = 0; i < dependency.Length; i++)
{
// Try to read the dependency as UniversalRendererData
if (AssetDatabase.GetMainAssetTypeAtPath(dependency[i]) != typeof(UniversalRendererData))
continue;
UniversalRendererData renderData =
(UniversalRendererData)AssetDatabase.LoadAssetAtPath(dependency[i],
typeof(UniversalRendererData));
if (renderData)
{
ret = ret && action(renderData);
}
if (!ret)
{
break;
}
}
}
}
return ret;
}
#endif
private static GraphicsDeviceType[] GetGraphicsAPIs(BuildTargetGroup buildTargetGroup)
{
var buildTarget = buildTargetGroup.GetBuildTarget();
if (PlayerSettings.GetUseDefaultGraphicsAPIs(buildTarget))
{
return Array.Empty<GraphicsDeviceType>();
}
// Recommends OpenGL ES 3 or Vulkan
return PlayerSettings.GetGraphicsAPIs(buildTarget);
}
static OVRProjectSetupRenderingTasks()
{
const OVRProjectSetup.TaskGroup targetGroup = OVRProjectSetup.TaskGroup.Rendering;
//[Required] Set the color space to linear
OVRProjectSetup.AddTask(
conditionalLevel: buildTargetGroup =>
OVRProjectSetupUtils.IsPackageInstalled(OVRProjectSetupXRTasks.UnityXRPackage)
? OVRProjectSetup.TaskLevel.Required
: OVRProjectSetup.TaskLevel.Recommended,
group: targetGroup,
isDone: buildTargetGroup => PlayerSettings.colorSpace == ColorSpace.Linear,
message: "Color Space is required to be Linear",
fix: buildTargetGroup => PlayerSettings.colorSpace = ColorSpace.Linear,
fixMessage: "PlayerSettings.colorSpace = ColorSpace.Linear"
);
#if USING_XR_SDK_OCULUS && OCULUS_XR_EYE_TRACKED_FOVEATED_RENDERING && UNITY_2021_3_OR_NEWER
//[Required] Use Vulkan and IL2CPP/ARM64 when using ETFR
OVRProjectSetup.AddTask(
level: OVRProjectSetup.TaskLevel.Required,
group: targetGroup,
isDone: buildTargetGroup =>
{
var useIL2CPP = PlayerSettings.GetScriptingBackend(buildTargetGroup) == ScriptingImplementation.IL2CPP;
var useARM64 = PlayerSettings.Android.targetArchitectures == AndroidArchitecture.ARM64;
var useVK = GetGraphicsAPIs(buildTargetGroup).Any(item => item == GraphicsDeviceType.Vulkan);
return useVK && useARM64 && useIL2CPP;
},
message: "Need to use Vulkan for Graphics APIs, IL2CPP for scripting backend, and ARM64 for target architectures when using eye-tracked foveated rendering",
fix: buildTargetGroup =>
{
var buildTarget = buildTargetGroup.GetBuildTarget();
PlayerSettings.Android.targetArchitectures = AndroidArchitecture.ARM64;
PlayerSettings.SetScriptingBackend(buildTargetGroup, ScriptingImplementation.IL2CPP);
PlayerSettings.SetGraphicsAPIs(buildTarget, new[] { GraphicsDeviceType.Vulkan });
},
fixMessage: "Set target architectures to ARM64, scripting backend to IL2CPP, and Graphics APIs to Vulkan for this build.",
conditionalValidity: buildTargetGroup => OculusSettings?.FoveatedRenderingMethod == Unity.XR.Oculus.OculusSettings.FoveationMethod.EyeTrackedFoveatedRendering
);
#endif
//[Required] Disable Graphics Jobs
OVRProjectSetup.AddTask(
level: OVRProjectSetup.TaskLevel.Recommended,
group: targetGroup,
isDone: buildTargetGroup => !PlayerSettings.graphicsJobs,
message: "Disable Graphics Jobs",
fix: buildTargetGroup => PlayerSettings.graphicsJobs = false,
fixMessage: "PlayerSettings.graphicsJobs = false"
);
//[Recommended] Set the Graphics API order for Android
OVRProjectSetup.AddTask(
level: OVRProjectSetup.TaskLevel.Recommended,
platform: BuildTargetGroup.Android,
group: targetGroup,
isDone: buildTargetGroup =>
GetGraphicsAPIs(buildTargetGroup).Any(item =>
item == GraphicsDeviceType.OpenGLES3 || item == GraphicsDeviceType.Vulkan),
message: "Manual selection of Graphic API, favoring Vulkan (or OpenGLES3)",
fix: buildTargetGroup =>
{
var buildTarget = buildTargetGroup.GetBuildTarget();
PlayerSettings.SetUseDefaultGraphicsAPIs(buildTarget, false);
PlayerSettings.SetGraphicsAPIs(buildTarget, new[] { GraphicsDeviceType.Vulkan });
},
fixMessage: "Set Graphics APIs for this build target to Vulkan"
);
//[Required] Set the Graphics API order for Windows
OVRProjectSetup.AddTask(
level: OVRProjectSetup.TaskLevel.Required,
platform: BuildTargetGroup.Standalone,
group: targetGroup,
isDone: buildTargetGroup =>
GetGraphicsAPIs(buildTargetGroup).Any(item =>
item == GraphicsDeviceType.Direct3D11),
message: "Manual selection of Graphic API, favoring Direct3D11",
fix: buildTargetGroup =>
{
var buildTarget = buildTargetGroup.GetBuildTarget();
PlayerSettings.SetUseDefaultGraphicsAPIs(buildTarget, false);
PlayerSettings.SetGraphicsAPIs(buildTarget, new[] { GraphicsDeviceType.Direct3D11 });
},
fixMessage: "Set Graphics APIs for this build target to Direct3D11"
);
//[Recommended] Enable Multithreaded Rendering
OVRProjectSetup.AddTask(
level: OVRProjectSetup.TaskLevel.Recommended,
group: targetGroup,
isDone: buildTargetGroup => PlayerSettings.MTRendering &&
(buildTargetGroup != BuildTargetGroup.Android
|| PlayerSettings.GetMobileMTRendering(buildTargetGroup)),
message: "Enable Multithreaded Rendering",
fix: buildTargetGroup =>
{
PlayerSettings.MTRendering = true;
if (buildTargetGroup == BuildTargetGroup.Android)
{
PlayerSettings.SetMobileMTRendering(buildTargetGroup, true);
}
},
conditionalFixMessage: buildTargetGroup =>
buildTargetGroup == BuildTargetGroup.Android
? "PlayerSettings.MTRendering = true and PlayerSettings.SetMobileMTRendering(buildTargetGroup, true)"
: "PlayerSettings.MTRendering = true"
);
#if USING_XR_SDK_OCULUS
//[Recommended] Select Low Overhead Mode
OVRProjectSetup.AddTask(
level: OVRProjectSetup.TaskLevel.Recommended,
conditionalValidity: buildTargetGroup =>
GetGraphicsAPIs(buildTargetGroup).Contains(GraphicsDeviceType.OpenGLES3),
group: targetGroup,
platform: BuildTargetGroup.Android,
isDone: buildTargetGroup => OculusSettings?.LowOverheadMode ?? true,
message: "Use Low Overhead Mode",
fix: buildTargetGroup =>
{
var setting = OculusSettings;
if (setting != null)
{
setting.LowOverheadMode = true;
EditorUtility.SetDirty(setting);
}
},
fixMessage: "OculusSettings.LowOverheadMode = true"
);
//[Recommended] Enable Dash Support
OVRProjectSetup.AddTask(
level: OVRProjectSetup.TaskLevel.Recommended,
group: targetGroup,
platform: BuildTargetGroup.Standalone,
isDone: buildTargetGroup => OculusSettings?.DashSupport ?? true,
message: "Enable Dash Support",
fix: buildTargetGroup =>
{
var setting = OculusSettings;
if (setting != null)
{
setting.DashSupport = true;
EditorUtility.SetDirty(setting);
}
},
fixMessage: "OculusSettings.DashSupport = true"
);
#endif
//[Recommended] Set the Display Buffer Format to 32 bit
OVRProjectSetup.AddTask(
level: OVRProjectSetup.TaskLevel.Recommended,
group: targetGroup,
isDone: buildTargetGroup =>
PlayerSettings.use32BitDisplayBuffer,
message: "Use 32Bit Display Buffer",
fix: buildTargetGroup => PlayerSettings.use32BitDisplayBuffer = true,
fixMessage: "PlayerSettings.use32BitDisplayBuffer = true"
);
//[Recommended] Set the Rendering Path to Forward
// TODO : Support Scripted Rendering Pipeline?
OVRProjectSetup.AddTask(
level: OVRProjectSetup.TaskLevel.Recommended,
group: targetGroup,
isDone: buildTargetGroup =>
EditorGraphicsSettings.GetTierSettings(buildTargetGroup, Graphics.activeTier).renderingPath ==
RenderingPath.Forward,
message: "Use Forward Rendering Path",
fix: buildTargetGroup =>
{
var renderingTier = EditorGraphicsSettings.GetTierSettings(buildTargetGroup, Graphics.activeTier);
renderingTier.renderingPath =
RenderingPath.Forward;
EditorGraphicsSettings.SetTierSettings(buildTargetGroup, Graphics.activeTier, renderingTier);
},
fixMessage: "renderingTier.renderingPath = RenderingPath.Forward"
);
//[Recommended] Set the Stereo Rendering to Instancing
OVRProjectSetup.AddTask(
level: OVRProjectSetup.TaskLevel.Recommended,
group: targetGroup,
isDone: buildTargetGroup =>
PlayerSettings.stereoRenderingPath == StereoRenderingPath.Instancing,
message: "Use Stereo Rendering Instancing",
fix: buildTargetGroup => PlayerSettings.stereoRenderingPath = StereoRenderingPath.Instancing,
fixMessage: "PlayerSettings.stereoRenderingPath = StereoRenderingPath.Instancing"
);
#if USING_URP && UNITY_2022_2_OR_NEWER
//[Recommended] When using URP, set Intermediate texture to "Auto"
OVRProjectSetup.AddTask(
level: OVRProjectSetup.TaskLevel.Recommended,
group: targetGroup,
isDone: buildTargetGroup =>
ForEachRendererData(rd => { return rd.intermediateTextureMode == IntermediateTextureMode.Auto; }),
message: "Setting the intermate texture mode to \"Always\" might have a performance impact, it is recommended to use \"Auto\"",
fix: buildTargetGroup =>
ForEachRendererData(rd => { rd.intermediateTextureMode = IntermediateTextureMode.Auto; return true; }),
fixMessage: "Set Intermediate texture to \"Auto\""
);
//[Recommended] When using URP, disable SSAO
OVRProjectSetup.AddTask(
level: OVRProjectSetup.TaskLevel.Recommended,
group: targetGroup,
isDone: buildTargetGroup =>
ForEachRendererData(rd =>
{
return rd.rendererFeatures.Count == 0
|| !rd.rendererFeatures.Any(
feature => feature != null && (feature.isActive && feature.GetType().Name == "ScreenSpaceAmbientOcclusion"));
}),
message: "SSAO will have some performace impact, it is recommended to disable SSAO",
fix: buildTargetGroup =>
ForEachRendererData(rd =>
{
rd.rendererFeatures.ForEach(feature =>
{
if (feature != null && feature.GetType().Name == "ScreenSpaceAmbientOcclusion")
feature.SetActive(false);
}
);
return true;
}),
fixMessage: "Disable SSAO"
);
#endif
//[Optional] Use Non-Directional Lightmaps
OVRProjectSetup.AddTask(
level: OVRProjectSetup.TaskLevel.Optional,
group: targetGroup,
isDone: buildTargetGroup =>
{
return LightmapSettings.lightmaps.Length == 0 ||
LightmapSettings.lightmapsMode == LightmapsMode.NonDirectional;
},
message: "Use Non-Directional lightmaps",
fix: buildTargetGroup => LightmapSettings.lightmapsMode = LightmapsMode.NonDirectional,
fixMessage: "LightmapSettings.lightmapsMode = LightmapsMode.NonDirectional"
);
//[Optional] Disable Realtime GI
OVRProjectSetup.AddTask(
level: OVRProjectSetup.TaskLevel.Optional,
group: targetGroup,
isDone: buildTargetGroup => !Lightmapping.realtimeGI,
message: "Disable Realtime Global Illumination",
fix: buildTargetGroup => Lightmapping.realtimeGI = false,
fixMessage: "Lightmapping.realtimeGI = false"
);
//[Optional] GPU Skinning
OVRProjectSetup.AddTask(
level: OVRProjectSetup.TaskLevel.Optional,
platform: BuildTargetGroup.Android,
group: targetGroup,
isDone: buildTargetGroup => PlayerSettings.gpuSkinning,
message: "Consider using GPU Skinning if your application is CPU bound",
fix: buildTargetGroup => PlayerSettings.gpuSkinning = true,
fixMessage: "PlayerSettings.gpuSkinning = true"
);
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 93a7b0b65ecd19943b6eaef8cf457167
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,47 @@
/*
* 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 UnityEditor;
[InitializeOnLoad]
internal static class OVRProjectSetupSceneTasks
{
private const OVRProjectSetup.TaskGroup Group = OVRProjectSetup.TaskGroup.Features;
static OVRProjectSetupSceneTasks()
{
OVRProjectSetup.AddTask(
level: OVRProjectSetup.TaskLevel.Required,
group: Group,
isDone: buildTargetGroup => OVRProjectSetupUtils.FindComponentInScene<OVRSceneManager>() == null ||
OVRProjectConfig.CachedProjectConfig.anchorSupport ==
OVRProjectConfig.AnchorSupport.Enabled,
message: "When using Scene in your project it's required to enable its capability in the project config",
fix: buildTargetGroup =>
{
var projectConfig = OVRProjectConfig.CachedProjectConfig;
projectConfig.anchorSupport = OVRProjectConfig.AnchorSupport.Enabled;
OVRProjectConfig.CommitProjectConfig(projectConfig);
},
fixMessage: "Enable Anchor Support in the project config"
);
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 821c95a26dbfb3f40b9c76b776d3c661
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,58 @@
/*
* 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 UnityEditor;
[InitializeOnLoad]
internal static class OVRProjectSetupVirtualKeyboard
{
private const OVRProjectSetup.TaskGroup Group = OVRProjectSetup.TaskGroup.Features;
static OVRProjectSetupVirtualKeyboard()
{
OVRProjectSetup.AddTask(
level: OVRProjectSetup.TaskLevel.Required,
group: Group,
isDone: _ => OVRProjectSetupUtils.FindComponentInScene<OVRVirtualKeyboard>() == null ||
OVRProjectConfig.CachedProjectConfig.renderModelSupport == OVRProjectConfig.RenderModelSupport.Enabled,
message: "When using Virtual Keyboard in your project it's required to enable Render Model Support",
fix: _ =>
{
var projectConfig = OVRProjectConfig.CachedProjectConfig;
projectConfig.renderModelSupport = OVRProjectConfig.RenderModelSupport.Enabled;
OVRProjectConfig.CommitProjectConfig(projectConfig);
},
fixMessage: "Enable Render Model Support");
OVRProjectSetup.AddTask(
level: OVRProjectSetup.TaskLevel.Required,
group: Group,
isDone: _ => OVRProjectSetupUtils.FindComponentInScene<OVRVirtualKeyboard>() == null ||
OVRProjectConfig.CachedProjectConfig.virtualKeyboardSupport != OVRProjectConfig.FeatureSupport.None,
message: "When using Virtual Keyboard in your project it's required to enable its capability",
fix: _ =>
{
var projectConfig = OVRProjectConfig.CachedProjectConfig;
projectConfig.virtualKeyboardSupport = OVRProjectConfig.FeatureSupport.Supported;
OVRProjectConfig.CommitProjectConfig(projectConfig);
},
fixMessage: "Enable Virtual Keyboard Support");
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 82d658a2879ff5445a9566cdc87ed59b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,173 @@
/*
* 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;
using System.Linq;
using System.Reflection;
using UnityEditor;
using UnityEngine;
#if USING_XR_MANAGEMENT
using UnityEditor.XR.Management;
#endif
#if USING_XR_SDK_OCULUS
using Unity.XR.Oculus;
#endif
[InitializeOnLoad]
internal static class OVRProjectSetupXRTasks
{
internal const string OculusXRPackageName = "com.unity.xr.oculus";
internal const string XRPluginManagementPackageName = "com.unity.xr.management";
internal const string UnityXRPackage = "com.unity.xr.openxr";
private const OVRProjectSetup.TaskGroup XRTaskGroup = OVRProjectSetup.TaskGroup.Packages;
static OVRProjectSetupXRTasks()
{
OVRProjectSetup.AddTask(
conditionalValidity: buildTargetGroup => OVRProjectSetupUtils.PackageManagerListAvailable,
level: OVRProjectSetup.TaskLevel.Required,
group: XRTaskGroup,
isDone: buildTargetGroup => OVRProjectSetupUtils.IsPackageInstalled(OculusXRPackageName),
message: "The Oculus XR Plug-in package must be installed",
fix: buildTargetGroup => OVRProjectSetupUtils.InstallPackage(OculusXRPackageName),
fixMessage: $"Install {OculusXRPackageName} package"
);
OVRProjectSetup.AddTask(
conditionalValidity: buildTargetGroup => OVRProjectSetupUtils.PackageManagerListAvailable,
level: OVRProjectSetup.TaskLevel.Required,
group: XRTaskGroup,
isDone: buildTargetGroup => OVRProjectSetupUtils.IsPackageInstalled(XRPluginManagementPackageName),
message: "The XR Plug-in Management package must be installed",
fix: buildTargetGroup => OVRProjectSetupUtils.InstallPackage(XRPluginManagementPackageName),
fixMessage: $"Install {XRPluginManagementPackageName} package"
);
OVRProjectSetup.AddTask(
conditionalValidity: buildTargetGroup => OVRProjectSetupUtils.PackageManagerListAvailable,
level: OVRProjectSetup.TaskLevel.Recommended,
group: XRTaskGroup,
isDone: buildTargetGroup => !OVRProjectSetupUtils.IsPackageInstalled(UnityXRPackage),
message: "Unity's OpenXR Plugin is not recommended when using the Oculus SDK, " +
"please use Oculus XR Plug-in instead",
fix: buildTargetGroup => OVRProjectSetupUtils.UninstallPackage(UnityXRPackage),
fixMessage: $"Remove the {UnityXRPackage} package"
);
AddXrPluginManagementTasks();
}
private static void AddXrPluginManagementTasks()
{
#if USING_XR_MANAGEMENT && USING_XR_SDK_OCULUS
OVRProjectSetup.AddTask(
conditionalValidity: buildTargetGroup =>
OVRProjectSetupUtils.IsPackageInstalled(XRPluginManagementPackageName),
level: OVRProjectSetup.TaskLevel.Required,
group: XRTaskGroup,
isDone: buildTargetGroup =>
{
var settings = GetXRGeneralSettingsForBuildTarget(buildTargetGroup, false);
if (settings == null)
{
return false;
}
foreach (var loader in settings.Manager.activeLoaders)
{
if (loader as OculusLoader != null)
{
return true;
}
}
return false;
},
message: "Oculus must be added to the XR Plugin active loaders",
fix: buildTargetGroup =>
{
var settings = GetXRGeneralSettingsForBuildTarget(buildTargetGroup, true);
if (settings == null)
{
throw new OVRConfigurationTaskException("Could not find XR Plugin Manager settings");
}
var loadersList = AssetDatabase.FindAssets($"t: {nameof(OculusLoader)}")
.Select(AssetDatabase.GUIDToAssetPath)
.Select(AssetDatabase.LoadAssetAtPath<OculusLoader>).ToList();
OculusLoader oculusLoader;
if (loadersList.Count > 0)
{
oculusLoader = loadersList[0];
}
else
{
oculusLoader = ScriptableObject.CreateInstance<OculusLoader>();
AssetDatabase.CreateAsset(oculusLoader, "Assets/XR/Loaders/Oculus Loader.asset");
}
settings.Manager.TryAddLoader(oculusLoader);
},
fixMessage: "Add Oculus to the XR Plugin active loaders"
);
#endif
}
#if USING_XR_MANAGEMENT && USING_XR_SDK_OCULUS
private static UnityEngine.XR.Management.XRGeneralSettings GetXRGeneralSettingsForBuildTarget(
BuildTargetGroup buildTargetGroup, bool create)
{
var settings = XRGeneralSettingsPerBuildTarget.XRGeneralSettingsForBuildTarget(buildTargetGroup);
if (!create || settings != null)
{
return settings;
}
// we have to create these settings ourselves as
// long as Unity doesn't expose the internal function
// XRGeneralSettingsPerBuildTarget.GetOrCreate()
var settingsKey = UnityEngine.XR.Management.XRGeneralSettings.k_SettingsKey;
EditorBuildSettings.TryGetConfigObject<XRGeneralSettingsPerBuildTarget>(
settingsKey, out var settingsPerBuildTarget);
if (settingsPerBuildTarget == null)
{
settingsPerBuildTarget = ScriptableObject.CreateInstance<XRGeneralSettingsPerBuildTarget>();
if (!AssetDatabase.IsValidFolder("Assets/XR"))
AssetDatabase.CreateFolder("Assets", "XR");
const string assetPath = "Assets/XR/XRGeneralSettingsPerBuildTarget.asset";
AssetDatabase.CreateAsset(settingsPerBuildTarget, assetPath);
AssetDatabase.SaveAssets();
EditorBuildSettings.AddConfigObject(settingsKey, settingsPerBuildTarget, true);
}
if (!settingsPerBuildTarget.HasManagerSettingsForBuildTarget(buildTargetGroup))
{
settingsPerBuildTarget.CreateDefaultManagerSettingsForBuildTarget(buildTargetGroup);
}
return XRGeneralSettingsPerBuildTarget.XRGeneralSettingsForBuildTarget(buildTargetGroup);
}
#endif
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: beb76c27b37f99e43a27f9d2656dafc6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,270 @@
/*
* 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;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
internal class OVRConfigurationTask
{
internal static readonly string ConsoleLinkHref = "OpenOculusProjectSettings";
public Hash128 Uid { get; }
public OVRProjectSetup.TaskGroup Group { get; }
public BuildTargetGroup Platform { get; }
public OptionalLambdaType<BuildTargetGroup, bool> Valid { get; }
public OptionalLambdaType<BuildTargetGroup, OVRProjectSetup.TaskLevel> Level { get; }
public OptionalLambdaType<BuildTargetGroup, string> Message { get; }
public OptionalLambdaType<BuildTargetGroup, string> FixMessage { get; }
public OptionalLambdaType<BuildTargetGroup, string> URL { get; }
public OVRConfigurationTaskSourceCode SourceCode { get; set; }
private Func<BuildTargetGroup, bool> _isDone;
public Func<BuildTargetGroup, bool> IsDone
{
get => GetDoneState;
private set => _isDone = value;
}
public Action<BuildTargetGroup> FixAction { get; }
private readonly Dictionary<BuildTargetGroup, OVRProjectSetupSettingBool> _ignoreSettings =
new Dictionary<BuildTargetGroup, OVRProjectSetupSettingBool>();
private readonly Dictionary<BuildTargetGroup, bool> _isDoneCache = new Dictionary<BuildTargetGroup, bool>();
public OVRConfigurationTask(
OVRProjectSetup.TaskGroup group,
BuildTargetGroup platform,
Func<BuildTargetGroup, bool> isDone,
Action<BuildTargetGroup> fix,
OptionalLambdaType<BuildTargetGroup, OVRProjectSetup.TaskLevel> level,
OptionalLambdaType<BuildTargetGroup, string> message,
OptionalLambdaType<BuildTargetGroup, string> fixMessage,
OptionalLambdaType<BuildTargetGroup, string> url,
OptionalLambdaType<BuildTargetGroup, bool> valid)
{
Platform = platform;
Group = group;
IsDone = isDone;
FixAction = fix;
Level = level;
Message = message;
// If parameters are null, we're creating a OptionalLambdaType that points to default values
// We don't want a null OptionalLambdaType, but we may be okay with an OptionalLambdaType containing a null value
// For the URL for instance
// Mandatory parameters will be checked on the Validate method down below
URL = url ?? new OptionalLambdaTypeWithoutLambda<BuildTargetGroup, string>(null);
FixMessage = fixMessage ?? new OptionalLambdaTypeWithoutLambda<BuildTargetGroup, string>(null);
Valid = valid ?? new OptionalLambdaTypeWithoutLambda<BuildTargetGroup, bool>(true);
// We may want to throw in case of some invalid parameters
Validate();
var hash = new Hash128();
hash.Append(Message.Default);
Uid = hash;
SourceCode = new OVRConfigurationTaskSourceCode(this);
}
private void Validate()
{
if (Group == OVRProjectSetup.TaskGroup.All)
{
throw new ArgumentException(
$"[{nameof(OVRConfigurationTask)}] {nameof(OVRProjectSetup.TaskGroup.All)} is not meant to be used as a {nameof(OVRProjectSetup.TaskGroup)} type");
}
if (_isDone == null)
{
throw new ArgumentNullException(nameof(_isDone));
}
if (Level == null)
{
throw new ArgumentNullException(nameof(Level));
}
if (Message == null || !Message.Valid || string.IsNullOrEmpty(Message.Default))
{
throw new ArgumentNullException(nameof(Message));
}
}
public void InvalidateCache(BuildTargetGroup buildTargetGroup)
{
Level.InvalidateCache(buildTargetGroup);
Message.InvalidateCache(buildTargetGroup);
URL.InvalidateCache(buildTargetGroup);
Valid.InvalidateCache(buildTargetGroup);
}
public bool IsIgnored(BuildTargetGroup buildTargetGroup)
{
return GetIgnoreSetting(buildTargetGroup).Value;
}
public void SetIgnored(BuildTargetGroup buildTargetGroup, bool ignored)
{
GetIgnoreSetting(buildTargetGroup).Value = ignored;
}
public bool Fix(BuildTargetGroup buildTargetGroup)
{
try
{
FixAction(buildTargetGroup);
}
catch (OVRConfigurationTaskException exception)
{
Debug.LogWarning(
$"[Oculus Settings] Failed to fix task \"{Message.GetValue(buildTargetGroup)}\" : {exception}");
}
var hasChanged = UpdateAndGetStateChanged(buildTargetGroup);
if (hasChanged)
{
var fixMessage = FixMessage.GetValue(buildTargetGroup);
Debug.Log(
fixMessage != null
? $"[Oculus Settings] Fixed task \"{Message.GetValue(buildTargetGroup)}\" : {fixMessage}"
: $"[Oculus Settings] Fixed task \"{Message.GetValue(buildTargetGroup)}\"");
}
var isDone = IsDone(buildTargetGroup);
OVRTelemetry.Start(OVRProjectSetupTelemetryEvent.EventTypes.Fix)
.AddAnnotation(OVRProjectSetupTelemetryEvent.AnnotationTypes.Uid, Uid.ToString())
.AddAnnotation(OVRProjectSetupTelemetryEvent.AnnotationTypes.Level,
Level.GetValue(buildTargetGroup).ToString())
.AddAnnotation(OVRProjectSetupTelemetryEvent.AnnotationTypes.Group, Group.ToString())
.AddAnnotation(OVRProjectSetupTelemetryEvent.AnnotationTypes.BuildTargetGroup, buildTargetGroup.ToString())
.AddAnnotation(OVRProjectSetupTelemetryEvent.AnnotationTypes.Value, isDone ? "true" : "false")
.Send();
return isDone;
}
public string ComputeIgnoreUid(BuildTargetGroup buildTargetGroup)
=> $"{OVRProjectSetup.KeyPrefix}.{GetType().Name}.{Uid}.Ignored.{buildTargetGroup.ToString()}";
private OVRProjectSetupSettingBool GetIgnoreSetting(BuildTargetGroup buildTargetGroup)
{
if (!_ignoreSettings.TryGetValue(buildTargetGroup, out var item))
{
var uid = ComputeIgnoreUid(buildTargetGroup);
item = new OVRProjectSetupProjectSettingBool(uid, false);
_ignoreSettings.Add(buildTargetGroup, item);
}
return item;
}
internal bool UpdateAndGetStateChanged(BuildTargetGroup buildTargetGroup)
{
var newState = _isDone(buildTargetGroup);
var didStateChange = true;
if (_isDoneCache.TryGetValue(buildTargetGroup, out var previousState))
{
didStateChange = newState != previousState;
}
_isDoneCache[buildTargetGroup] = newState;
return didStateChange;
}
internal void LogMessage(BuildTargetGroup buildTargetGroup)
{
var logMessage = GetFullLogMessage(buildTargetGroup);
switch (Level.GetValue(buildTargetGroup))
{
case OVRProjectSetup.TaskLevel.Optional:
break;
case OVRProjectSetup.TaskLevel.Recommended:
Debug.LogWarning(logMessage);
break;
case OVRProjectSetup.TaskLevel.Required:
if (OVRProjectSetup.RequiredThrowErrors.Value)
{
Debug.LogError(logMessage);
}
else
{
Debug.LogWarning(logMessage);
}
break;
default:
throw new ArgumentOutOfRangeException();
}
}
internal string GetFullLogMessage(BuildTargetGroup buildTargetGroup)
{
return $"{GetLogMessage(buildTargetGroup)}.\nYou can fix this by going to " +
$"<a href=\"{ConsoleLinkHref}\">Edit > Project Settings > {OVRProjectSetupSettingsProvider.SettingsName}</a>";
}
internal string GetLogMessage(BuildTargetGroup buildTargetGroup)
{
return $"[{Group}] {Message.GetValue(buildTargetGroup)}";
}
private bool GetDoneState(BuildTargetGroup buildTargetGroup)
{
if (_isDoneCache.TryGetValue(buildTargetGroup, out var cachedState))
{
return cachedState;
}
return _isDone(buildTargetGroup);
}
#if UNITY_XR_CORE_UTILS
internal Unity.XR.CoreUtils.Editor.BuildValidationRule ToValidationRule(BuildTargetGroup platform)
{
var validationRule = new Unity.XR.CoreUtils.Editor.BuildValidationRule
{
IsRuleEnabled = () => Valid.GetValue(platform),
Category = Group.ToString(),
Message = Message.GetValue(platform),
CheckPredicate = () => IsDone(platform),
FixIt = () => FixAction(platform),
FixItAutomatic = true,
FixItMessage = FixMessage.GetValue(platform),
HelpText = null,
HelpLink = null,
SceneOnlyValidation = false,
OnClick = null,
Error = Level.GetValue(platform) == OVRProjectSetup.TaskLevel.Required
};
return validationRule;
}
#endif
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 23cf0a62a13a153468744c574d80aab8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,41 @@
/*
* 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;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
public class OVRConfigurationTaskException : Exception
{
public OVRConfigurationTaskException()
{
}
public OVRConfigurationTaskException(string message)
: base(message)
{
}
public OVRConfigurationTaskException(string message, Exception inner)
: base(message, inner)
{
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 7d5dcbd522a347fca62378e9e47b9893
timeCreated: 1664378185

View File

@ -0,0 +1,125 @@
/*
* 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;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
internal class OVRConfigurationTaskRegistry
{
private static readonly List<OVRConfigurationTask> EmptyTasksList = new List<OVRConfigurationTask>(0);
private readonly Dictionary<Hash128, OVRConfigurationTask> _tasksPerUid =
new Dictionary<Hash128, OVRConfigurationTask>();
private readonly List<OVRConfigurationTask> _tasks = new List<OVRConfigurationTask>();
private List<OVRConfigurationTask> Tasks => _tasks;
public void AddTask(OVRConfigurationTask task)
{
var uid = task.Uid;
if (_tasksPerUid.ContainsKey(uid))
{
// This task is already registered
return;
}
_tasks.Add(task);
_tasksPerUid.Add(uid, task);
#if UNITY_XR_CORE_UTILS
RegisterToBuildValidator(task);
#endif
}
#if UNITY_XR_CORE_UTILS
private void RegisterToBuildValidator(OVRConfigurationTask task)
{
if (task.Platform == BuildTargetGroup.Unknown)
{
var buildTargetGroups = Enum.GetValues(typeof(BuildTargetGroup));
foreach (var buildTargetGroup in buildTargetGroups)
{
var targetGroup = (BuildTargetGroup)buildTargetGroup;
RegisterToBuildValidator(targetGroup, task);
}
}
else
{
RegisterToBuildValidator(task.Platform, task);
}
}
private void RegisterToBuildValidator(BuildTargetGroup targetGroup, OVRConfigurationTask task)
{
if (task.Level.GetValue(targetGroup) == OVRProjectSetup.TaskLevel.Optional)
{
return;
}
Unity.XR.CoreUtils.Editor.BuildValidator.AddRules(targetGroup, new []{task.ToValidationRule(task.Platform)});
}
#endif
public void RemoveTask(Hash128 uid)
{
var task = GetTask(uid);
RemoveTask(task);
}
public void RemoveTask(OVRConfigurationTask task)
{
_tasks.Remove(task);
_tasksPerUid.Remove(task.Uid);
}
public OVRConfigurationTask GetTask(Hash128 uid)
{
_tasksPerUid.TryGetValue(uid, out var task);
return task;
}
public void Clear()
{
_tasksPerUid.Clear();
_tasks.Clear();
}
internal IEnumerable<OVRConfigurationTask> GetTasks(BuildTargetGroup buildTargetGroup, bool refresh)
{
if (refresh)
{
foreach (var task in Tasks)
{
task.InvalidateCache(buildTargetGroup);
}
}
return Tasks.Where
(
task => (task.Platform == BuildTargetGroup.Unknown || task.Platform == buildTargetGroup)
&& task.Valid.GetValue(buildTargetGroup)
);
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: fef3c9d3bbb64a21ac221b2b3fbca1ef
timeCreated: 1662024023

View File

@ -0,0 +1,150 @@
/*
* 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;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using UnityEditor;
using UnityEngine;
using Object = UnityEngine.Object;
internal class OVRConfigurationTaskSourceCode
{
private static Func<Object, int, bool> OpenAssetDelegate = AssetDatabase.OpenAsset;
public static void Mock()
{
OpenAssetDelegate = null;
}
public static void Unmock()
{
OpenAssetDelegate = AssetDatabase.OpenAsset;
}
private static IEnumerable<MethodInfo> _expectedMethods;
private static IEnumerable<MethodInfo> ExpectedMethods
{
get
{
if (_expectedMethods == null)
{
_expectedMethods = typeof(OVRProjectSetup).GetMethods(BindingFlags.Public | BindingFlags.Static)
.Where(method => method.Name == "AddTask");
}
return _expectedMethods;
}
}
private OVRConfigurationTask _task;
private readonly StackTrace _stackTrace;
private Object _object;
private bool _processed;
public bool Valid
{
get
{
if (!_processed)
{
ProcessStackTrace();
}
return _object != null;
}
}
public int Line { get; private set; }
public string FilePath { get; private set; }
public OVRConfigurationTaskSourceCode(OVRConfigurationTask task)
{
_task = task;
_stackTrace = new StackTrace(true);
}
public void ProcessStackTrace()
{
if (FindPathAndLine(out var path, out var line))
{
path = path.Replace("\\", "/");
if (path.StartsWith(Application.dataPath))
{
FilePath = Path.Combine("Assets/", path.Substring(Application.dataPath.Length + 1));
Line = line;
_object = AssetDatabase.LoadAssetAtPath(FilePath, typeof(Object));
}
}
_processed = true;
}
public bool Open()
{
if (Valid)
{
OpenAssetDelegate?.Invoke(_object, Line);
}
OVRTelemetry.Start(OVRProjectSetupTelemetryEvent.EventTypes.GoToSource)
.AddAnnotation(OVRProjectSetupTelemetryEvent.AnnotationTypes.Uid, _task.Uid.ToString())
.AddAnnotation(OVRProjectSetupTelemetryEvent.AnnotationTypes.BuildTargetGroup,
BuildTargetGroup.Unknown.ToString())
.AddAnnotation(OVRProjectSetupTelemetryEvent.AnnotationTypes.Value, Valid ? "true" : "false")
.Send();
return Valid;
}
private StackFrame FindStackFrame()
{
// Depth 2, Just before the constructor
StackFrame frame = _stackTrace.GetFrame(2);
var method = frame.GetMethod();
if (ExpectedMethods.Contains(method))
{
// Depth 3, Just before OVRProjectSetup AddTask
frame = _stackTrace.GetFrame(3);
}
return frame;
}
private bool FindPathAndLine(out string path, out int line)
{
var frame = FindStackFrame();
if (frame == null)
{
path = null;
line = -1;
return false;
}
path = frame.GetFileName();
line = frame.GetFileLineNumber();
return true;
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: b25802328957400cb1180db46a429f8b
timeCreated: 1665496546

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: ae567593b4a0438c80fd037782a57588
timeCreated: 1663596823

View File

@ -0,0 +1,89 @@
/*
* 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;
internal class OVRConfigurationTaskFixer : OVRConfigurationTaskProcessor
{
public override int AllocatedTimeInMs => 10;
public override ProcessorType Type => ProcessorType.Fixer;
protected override Func<IEnumerable<OVRConfigurationTask>, List<OVRConfigurationTask>> OpenTasksFilter =>
(Func<IEnumerable<OVRConfigurationTask>, List<OVRConfigurationTask>>)(tasksToFilter => tasksToFilter
.Where(task => task.FixAction != null
&& !task.IsDone(BuildTargetGroup)
&& !task.IsIgnored(BuildTargetGroup))
.ToList());
private const int LoopExitCount = 4;
private bool _hasFixedSome = false;
private int _counter = LoopExitCount;
public OVRConfigurationTaskFixer(
OVRConfigurationTaskRegistry registry,
BuildTargetGroup buildTargetGroup,
Func<IEnumerable<OVRConfigurationTask>, List<OVRConfigurationTask>> filter,
OVRProjectSetup.LogMessages logMessages,
bool blocking,
Action<OVRConfigurationTaskProcessor> onCompleted)
: base(registry, buildTargetGroup, filter, logMessages, blocking, onCompleted)
{
}
protected override void ProcessTask(OVRConfigurationTask task)
{
_hasFixedSome |= task.Fix(BuildTargetGroup);
}
protected override void PrepareTasks()
{
_hasFixedSome = false;
base.PrepareTasks();
}
protected override void Validate()
{
_counter--;
if (_counter <= 0)
{
Debug.LogWarning("[Oculus Settings] Fixing Tasks has exited after too many iterations. " +
"(There might be some contradictory rules leading to a loop)");
return;
}
if (!_hasFixedSome)
{
return;
}
// Preparing a new Run
PrepareTasks();
if (Blocking)
{
Update();
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 6e1fe0a245064a44b8b080a115da8c1d
timeCreated: 1663596864

View File

@ -0,0 +1,127 @@
/*
* 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;
internal abstract class OVRConfigurationTaskProcessor
{
public enum ProcessorType
{
Updater,
Fixer
}
public virtual int AllocatedTimeInMs => 10;
protected abstract void ProcessTask(OVRConfigurationTask task);
public abstract ProcessorType Type { get; }
private BuildTargetGroup _buildTargetGroup;
private OVRProjectSetup.LogMessages _logMessages;
private readonly OVRConfigurationTaskRegistry _registry;
private Func<IEnumerable<OVRConfigurationTask>, List<OVRConfigurationTask>> _filter;
protected abstract Func<IEnumerable<OVRConfigurationTask>, List<OVRConfigurationTask>> OpenTasksFilter { get; }
private List<OVRConfigurationTask> _tasks;
private IEnumerator<OVRConfigurationTask> _enumerator;
private int _startTime;
public bool Blocking { get; set; }
public event Action<OVRConfigurationTaskProcessor> OnComplete;
public BuildTargetGroup BuildTargetGroup => _buildTargetGroup;
public OVRProjectSetup.LogMessages LogMessages => _logMessages;
// Status
public bool Started => _startTime != -1;
public bool Processing => _enumerator != null;
public bool Completed => Started && (_enumerator == null || _enumerator.Current == null);
public List<OVRConfigurationTask> Tasks => _tasks;
protected OVRConfigurationTaskProcessor(OVRConfigurationTaskRegistry registry, BuildTargetGroup buildTargetGroup,
Func<IEnumerable<OVRConfigurationTask>, List<OVRConfigurationTask>> filter,
OVRProjectSetup.LogMessages logMessages,
bool blocking,
Action<OVRConfigurationTaskProcessor> onCompleted)
{
_registry = registry;
_enumerator = null;
_buildTargetGroup = buildTargetGroup;
_logMessages = logMessages;
Blocking = blocking;
_filter = filter;
_startTime = -1;
OnComplete += onCompleted;
}
protected virtual void PrepareTasks()
{
// Get all the tasks from the Setup Tool
var tasks = _registry.GetTasks(_buildTargetGroup, true);
// Apply the caller-provided filter
_tasks = _filter != null ? _filter(tasks) : tasks.ToList();
// When not forced, apply the OpenTaskFilter as well
_tasks = (OpenTasksFilter != null) ? OpenTasksFilter(_tasks) : _tasks;
// Prepare the Enumerator
_enumerator = _tasks.GetEnumerator();
_enumerator.MoveNext();
}
public virtual void OnRequested()
{
}
public virtual void Start()
{
PrepareTasks();
_startTime = Environment.TickCount;
}
public void Update()
{
var updateTime = Environment.TickCount;
var currentTime = updateTime;
while ((Blocking || (currentTime - updateTime < AllocatedTimeInMs)) && _enumerator?.Current != null)
{
ProcessTask(_enumerator.Current);
currentTime = Environment.TickCount;
_enumerator.MoveNext();
}
if (Completed)
{
Validate();
}
}
protected virtual void Validate()
{
}
public virtual void Complete()
{
_enumerator = null;
OnComplete?.Invoke(this);
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: da7a8c3cbcb14aba8b02a89bc05e136f
timeCreated: 1663596850

View File

@ -0,0 +1,149 @@
/*
* 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;
using System.Collections.Generic;
using UnityEditor;
internal class OVRConfigurationTaskProcessorQueue
{
public event Action<OVRConfigurationTaskProcessor> OnProcessorCompleted;
private readonly Queue<OVRConfigurationTaskProcessor> _queue = new Queue<OVRConfigurationTaskProcessor>();
public bool Busy => _queue.Count > 0;
public bool Blocked => Busy && _queue.Peek().Blocking;
public bool BlockedBy(OVRConfigurationTaskProcessor.ProcessorType processorType)
{
foreach (var processor in _queue)
{
if (processor.Type == processorType && processor.Blocking)
{
return true;
}
}
return false;
}
public bool BusyWith(OVRConfigurationTaskProcessor.ProcessorType processorType)
{
foreach (var processor in _queue)
{
if (processor.Type == processorType)
{
return true;
}
}
return false;
}
public void Request(OVRConfigurationTaskProcessor processor)
{
if (!OVRProjectSetup.Enabled.Value)
{
return;
}
Enqueue(processor);
}
private void Enqueue(OVRConfigurationTaskProcessor processor)
{
if (!Busy)
{
// If was empty, then register to editor update
EditorApplication.update += Update;
}
// Enqueue
_queue.Enqueue(processor);
processor.OnRequested();
if (processor.Blocking)
{
// In the case where the newly added processor is blocking
// we'll make all the previously queued processor blocking as well
foreach (var otherProcessor in _queue)
{
otherProcessor.Blocking = true;
}
// Force an update, this will be The blocking update
Update();
}
}
private void Dequeue(OVRConfigurationTaskProcessor processor)
{
// We should only dequeue the current processor
if (processor != _queue.Peek())
{
return;
}
// Dequeue
_queue.Dequeue();
if (!Busy)
{
// Now that it is empty, unregister to editor update
EditorApplication.update -= Update;
}
// Trigger specific callbacks
processor.Complete();
// Trigger global callbacks
OnProcessorCompleted?.Invoke(processor);
}
private void Update()
{
var processor = _queue.Count > 0 ? _queue.Peek() : null;
while (processor != null)
{
if (!processor.Started)
{
processor.Start();
}
processor.Update();
if (processor.Completed)
{
Dequeue(processor);
// Move to the next processor
processor = _queue.Count > 0 ? _queue.Peek() : null;
}
if (!(processor?.Blocking ?? false))
{
// Is the processor is not blocking, we can stop the update until the next update call
processor = null;
}
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 97ad6b63e1e34a329c0b5b3a69e7d8e7
timeCreated: 1663597510

View File

@ -0,0 +1,85 @@
/*
* 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;
internal class OVRConfigurationTaskUpdater : OVRConfigurationTaskProcessor
{
public override int AllocatedTimeInMs => 10;
private readonly OVRConfigurationTaskUpdaterSummary _summary;
protected override Func<IEnumerable<OVRConfigurationTask>, List<OVRConfigurationTask>> OpenTasksFilter =>
(Func<IEnumerable<OVRConfigurationTask>, List<OVRConfigurationTask>>)(tasksToFilter => tasksToFilter
.Where(task => !task.IsIgnored(BuildTargetGroup))
.ToList());
public override ProcessorType Type => ProcessorType.Updater;
public OVRConfigurationTaskUpdaterSummary Summary => _summary;
public OVRConfigurationTaskUpdater(
OVRConfigurationTaskRegistry registry,
BuildTargetGroup buildTargetGroup,
Func<IEnumerable<OVRConfigurationTask>, List<OVRConfigurationTask>> filter,
OVRProjectSetup.LogMessages logMessages,
bool blocking,
Action<OVRConfigurationTaskProcessor> onCompleted)
: base(registry, buildTargetGroup, filter, logMessages, blocking, onCompleted)
{
_summary = new OVRConfigurationTaskUpdaterSummary(BuildTargetGroup);
}
protected override void PrepareTasks()
{
_summary.Reset();
base.PrepareTasks();
}
protected override void ProcessTask(OVRConfigurationTask task)
{
var changedState = task.UpdateAndGetStateChanged(BuildTargetGroup);
Summary.AddTask(task, changedState);
if (task.IsDone(BuildTargetGroup))
{
return;
}
if (LogMessages == OVRProjectSetup.LogMessages.All
|| (LogMessages == OVRProjectSetup.LogMessages.Changed && changedState))
{
task.LogMessage(BuildTargetGroup);
}
}
public override void Complete()
{
Summary.Validate();
if (LogMessages >= OVRProjectSetup.LogMessages.Summary)
{
Summary.Log();
}
base.Complete();
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 36d246eb26384ec88c5d849668cf29a7
timeCreated: 1663591461

View File

@ -0,0 +1,246 @@
/*
* 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 System.Linq;
using UnityEditor;
using UnityEngine;
internal class OVRConfigurationTaskUpdaterSummary
{
private readonly List<OVRConfigurationTask> _doneTasks;
private readonly List<OVRConfigurationTask> _outstandingTasks;
private readonly Dictionary<OVRProjectSetup.TaskLevel, List<OVRConfigurationTask>> _outstandingTasksPerLevel;
private bool HasNewOutstandingTasks { get; set; }
private bool HasAnyChange { get; set; }
public bool HasAvailableFixes => _outstandingTasks.Count > 0;
public bool HasFixes(OVRProjectSetup.TaskLevel taskLevel) => _outstandingTasksPerLevel[taskLevel].Count > 0;
public int GetNumberOfFixes(OVRProjectSetup.TaskLevel taskLevel) => _outstandingTasksPerLevel[taskLevel].Count;
public int GetTotalNumberOfFixes() => _outstandingTasks.Count;
private readonly BuildTargetGroup _buildTargetGroup;
public BuildTargetGroup BuildTargetGroup => _buildTargetGroup;
public OVRConfigurationTaskUpdaterSummary(BuildTargetGroup buildTargetGroup)
{
_buildTargetGroup = buildTargetGroup;
_doneTasks = new List<OVRConfigurationTask>();
_outstandingTasks = new List<OVRConfigurationTask>();
_outstandingTasksPerLevel = new Dictionary<OVRProjectSetup.TaskLevel, List<OVRConfigurationTask>>();
for (var i = OVRProjectSetup.TaskLevel.Required; i >= OVRProjectSetup.TaskLevel.Optional; i--)
{
_outstandingTasksPerLevel.Add(i, new List<OVRConfigurationTask>());
}
}
public void Reset()
{
_doneTasks.Clear();
_outstandingTasks.Clear();
for (var i = OVRProjectSetup.TaskLevel.Required; i >= OVRProjectSetup.TaskLevel.Optional; i--)
{
_outstandingTasksPerLevel[i].Clear();
}
HasNewOutstandingTasks = false;
HasAnyChange = false;
}
public void AddTask(OVRConfigurationTask task, bool changedState)
{
if (task.IsDone(_buildTargetGroup))
{
_doneTasks.Add(task);
}
else
{
_outstandingTasks.Add(task);
_outstandingTasksPerLevel[task.Level.GetValue(_buildTargetGroup)].Add(task);
HasNewOutstandingTasks |= changedState;
}
HasAnyChange |= changedState;
}
public void Validate()
{
if (HasAnyChange)
{
LogEvent();
}
var interactionFlowEvent = OVRProjectSetupSettingsProvider.InteractionFlowEvent;
if (interactionFlowEvent == null)
{
if (GetTotalNumberOfFixes() > 0)
{
interactionFlowEvent = OVRTelemetry
.Start(OVRProjectSetupTelemetryEvent.EventTypes.InteractionFlow)
.AddAnnotation(OVRProjectSetupTelemetryEvent.AnnotationTypes.Level,
HighestFixLevel?.ToString() ?? "None")
.AddAnnotation(OVRProjectSetupTelemetryEvent.AnnotationTypes.Count,
GetNumberOfFixes(HighestFixLevel ?? OVRProjectSetup.TaskLevel.Required).ToString())
.AddAnnotation(OVRProjectSetupTelemetryEvent.AnnotationTypes.Level,
HighestFixLevel?.ToString() ?? "None")
.AddAnnotation(OVRProjectSetupTelemetryEvent.AnnotationTypes.Value,
GetTotalNumberOfFixes().ToString())
.AddAnnotation(OVRProjectSetupTelemetryEvent.AnnotationTypes.BuildTargetGroup,
BuildTargetGroup.ToString());
OVRProjectSetupSettingsProvider.InteractionFlowEvent = interactionFlowEvent;
}
}
else
{
interactionFlowEvent = interactionFlowEvent?.AddAnnotation(
OVRProjectSetupTelemetryEvent.AnnotationTypes.BuildTargetGroupAfter,
BuildTargetGroup.ToString())
.AddAnnotation(OVRProjectSetupTelemetryEvent.AnnotationTypes.ValueAfter,
GetTotalNumberOfFixes().ToString());
OVRProjectSetupSettingsProvider.InteractionFlowEvent = interactionFlowEvent;
}
}
public OVRProjectSetup.TaskLevel? HighestFixLevel
{
get
{
for (var i = OVRProjectSetup.TaskLevel.Required; i >= OVRProjectSetup.TaskLevel.Optional; i--)
{
if (HasFixes(i))
{
return i;
}
}
return null;
}
}
public string GenerateReport(string outputPath = null, string fileName = null)
{
var sortedTasks = _outstandingTasks.Concat(_doneTasks);
return OVRProjectSetupReport.GenerateJson(
sortedTasks,
_buildTargetGroup,
outputPath,
fileName
);
}
public string ComputeNoticeMessage()
{
var highestLevel = HighestFixLevel;
var level = highestLevel ?? OVRProjectSetup.TaskLevel.Optional;
var count = GetNumberOfFixes(level);
if (count == 0)
{
return $"Oculus-Ready for {_buildTargetGroup}";
}
else
{
var message = GetLogMessage(level, count);
return message;
}
}
public string ComputeLogMessage()
{
var highestLevel = HighestFixLevel;
var level = highestLevel ?? OVRProjectSetup.TaskLevel.Optional;
var count = GetNumberOfFixes(level);
var message = GetFullLogMessage(level, count);
return message;
}
public void LogEvent()
{
OVRTelemetry.Start(OVRProjectSetupTelemetryEvent.EventTypes.Summary)
.AddAnnotation(OVRProjectSetupTelemetryEvent.AnnotationTypes.Level, HighestFixLevel?.ToString() ?? "None")
.AddAnnotation(OVRProjectSetupTelemetryEvent.AnnotationTypes.Count,
GetNumberOfFixes(HighestFixLevel ?? OVRProjectSetup.TaskLevel.Required).ToString())
.AddAnnotation(OVRProjectSetupTelemetryEvent.AnnotationTypes.BuildTargetGroup, BuildTargetGroup.ToString())
.AddAnnotation(OVRProjectSetupTelemetryEvent.AnnotationTypes.Value, GetTotalNumberOfFixes().ToString())
.Send();
}
public void Log()
{
if (!HasNewOutstandingTasks)
{
return;
}
var highestLevel = HighestFixLevel;
var message = ComputeLogMessage();
switch (highestLevel)
{
case OVRProjectSetup.TaskLevel.Optional:
{
Debug.Log(message);
}
break;
case OVRProjectSetup.TaskLevel.Recommended:
{
Debug.LogWarning(message);
}
break;
case OVRProjectSetup.TaskLevel.Required:
{
if (OVRProjectSetup.RequiredThrowErrors.Value)
{
Debug.LogError(message);
}
else
{
Debug.LogWarning(message);
}
}
break;
}
}
private static string GetLogMessage(OVRProjectSetup.TaskLevel level, int count)
{
switch (count)
{
case 0:
return $"There are no outstanding {level.ToString()} fixes.";
case 1:
return $"There is 1 outstanding {level.ToString()} fix.";
default:
return $"There are {count} outstanding {level.ToString()} fixes.";
}
}
internal static string GetFullLogMessage(OVRProjectSetup.TaskLevel level, int count)
{
return
$"[Oculus Settings] {GetLogMessage(level, count)}\nFor more information, go to <a href=\"{OVRConfigurationTask.ConsoleLinkHref}\">Edit > Project Settings > {OVRProjectSetupSettingsProvider.SettingsName}</a>";
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: c1baa7891a0f4c63ad746d7e1b35faef
timeCreated: 1660745160