VR4Medical/ICI/Library/PackageCache/com.unity.xr.interaction.toolkit@42ef3600567b/Editor/ProjectValidation/ProjectValidationUtility.cs
2025-07-29 13:45:50 +03:00

182 lines
8.4 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Unity.XR.CoreUtils.Editor;
using UnityEngine;
namespace UnityEditor.XR.Interaction.Toolkit.ProjectValidation
{
/// <summary>
/// Utility class to help with project validation for XR Interaction Toolkit and Samples.
/// </summary>
internal static class ProjectValidationUtility
{
const string k_SamplesRootDirectoryName = "Samples";
/// <summary>
/// This is the minimum version of the Starter Assets sample for the XR Interaction Toolkit that enforces correct behavior
/// of newly added properties, prefabs, or input actions.
/// </summary>
public static readonly PackageVersion minimumXRIStarterAssetsSampleVersion = new PackageVersion("3.1.0");
/// <summary>
/// Dictionary used to cache packages imported samples. The dictionary key is the package display name as displayed in package Samples directory.
/// </summary>
static Dictionary<string, PackageSampleData> s_PackageSampleCache;
struct PackageSampleData
{
public string packageDisplayName;
public Dictionary<string, SampleData> importedSamples;
}
/// <summary>
/// Struct containing data about a sample.
/// </summary>
struct SampleData
{
/// <summary>
/// The display name of the sample, matches the directory.
/// </summary>
public string sampleName;
/// <summary>
/// The display name of the package the sample is from.
/// </summary>
public string packageDisplayName;
/// <summary>
/// The version of the package the sample is imported from.
/// </summary>
public PackageVersion packageVersion;
}
/// <summary>
/// Searches for a sample, <see cref="sampleDisplayName"/> from a specified package, <see cref="packageDisplayName"/>.
/// The search is done by iterating through the Samples directory, but will utilize cached data if available.
/// This function is version agnostic and will return true if the sample is found in any version of the package's
/// sample directory.
/// </summary>
/// <param name="packageDisplayName">The name of the package directory that contains the sample.</param>
/// <param name="sampleDisplayName">The name of the sample directory to search for.</param>
/// <returns>Returns <see langword="true"/> if the sample is found in the Samples directory of the specified
/// package. Otherwise, returns <see langword="false"/>.</returns>
/// <seealso cref="SampleImportMeetsMinimumVersion"/>
public static bool HasSampleImported(string packageDisplayName, string sampleDisplayName)
{
if (s_PackageSampleCache == null)
{
UpdatePackageSampleCache();
if (s_PackageSampleCache == null)
return false;
}
return s_PackageSampleCache.TryGetValue(packageDisplayName, out var sampleData) && sampleData.importedSamples.ContainsKey(sampleDisplayName);
}
/// <summary>
/// Searches for the imported samples from a specified package.
/// </summary>
/// <param name="packageDisplayName">The display name of the package (directory that contains the samples).</param>
/// <param name="results">The list to populate with the unordered collection of imported samples.</param>
public static void GetImportedSamples(string packageDisplayName, List<(string sampleName, PackageVersion packageVersion)> results)
{
results.Clear();
if (s_PackageSampleCache == null)
{
UpdatePackageSampleCache();
if (s_PackageSampleCache == null)
return;
}
if (s_PackageSampleCache.TryGetValue(packageDisplayName, out var sampleData))
{
foreach (var importedSample in sampleData.importedSamples)
{
results.Add((importedSample.Value.sampleName, importedSample.Value.packageVersion));
}
}
}
/// <summary>
/// Searches for a sample, <see cref="sampleDisplayName"/> from a specified package, <see cref="packageDisplayName"/>
/// and compares the sample version.
/// </summary>
/// <param name="packageDisplayName">The name of the package directory that contains the sample.</param>
/// <param name="sampleDisplayName">The name of the sample directory to search for.</param>
/// <param name="minVersion">The minimum package version the sample should be imported from.</param>
/// <returns>Returns <see langword="true"/> if the sample is found in the Samples directory of the specified
/// package and the imported sample's version is greater than or equal to the <see cref="minVersion"/>.</returns>
public static bool SampleImportMeetsMinimumVersion(string packageDisplayName, string sampleDisplayName, PackageVersion minVersion)
{
if (HasSampleImported(packageDisplayName, sampleDisplayName))
return s_PackageSampleCache[packageDisplayName].importedSamples[sampleDisplayName].packageVersion >= minVersion;
return false;
}
/// <summary>
/// Iterates through Samples directory and caches sample and package data.
/// </summary>
static void UpdatePackageSampleCache()
{
if (s_PackageSampleCache == null)
{
try
{
s_PackageSampleCache = new Dictionary<string, PackageSampleData>();
var delimiter = Path.DirectorySeparatorChar;
var sampleRootPath = Path.Combine(Path.GetFileName(Application.dataPath), k_SamplesRootDirectoryName);
if (!Directory.Exists(sampleRootPath))
{
Debug.LogWarning($"Could not find Samples directory ({sampleRootPath}). Failed to update package sample cache.");
return;
}
// Iterate through all package directories in Samples directory
var allSamplePackagesPaths = Directory.GetDirectories(sampleRootPath);
foreach (var packageDirectoryPath in allSamplePackagesPaths)
{
var packageDisplayName = packageDirectoryPath.Split(delimiter).Last();
// To contain all samples for this package
var sampleMap = new Dictionary<string, SampleData>();
// Iterate through all version directories in package
var versionDirectoryPaths = Directory.GetDirectories(packageDirectoryPath);
foreach (var versionDirectoryPath in versionDirectoryPaths)
{
var versionName = versionDirectoryPath.Split(delimiter).Last();
var packageVersion = new PackageVersion(versionName);
// Iterate through all sample directories in version
var samplesDirectoryPaths = Directory.GetDirectories(versionDirectoryPath);
foreach (var sampleDirectoryPath in samplesDirectoryPaths)
{
var sampleName = sampleDirectoryPath.Split(delimiter).Last();
sampleMap.Add(sampleName, new SampleData
{
sampleName = sampleName,
packageDisplayName = packageDisplayName,
packageVersion = packageVersion,
});
}
}
var packageCacheData = new PackageSampleData { packageDisplayName = packageDisplayName, importedSamples = sampleMap, };
s_PackageSampleCache[packageDisplayName] = packageCacheData;
}
}
catch (Exception e)
{
Debug.LogError("Failed to update package sample cache. " + e.Message);
}
}
}
}
}