Files
ApexSurgery/Assets/Oculus/VR/Editor/OVRProjectSetup/Tasks/OVRConfigurationTask.cs
T
2025-07-04 20:33:06 +03:00

271 lines
9.6 KiB
C#

/*
* 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
}