// %BANNER_BEGIN%
// ---------------------------------------------------------------------
// %COPYRIGHT_BEGIN%
// Copyright (c) (2024) Magic Leap, Inc. All Rights Reserved.
// Use of this file is governed by the Software License Agreement, located here: https://www.magicleap.com/software-license-agreement-ml2
// Terms and conditions applicable to third-party materials accompanying this distribution may also be found in the top-level NOTICE file appearing herein.
// %COPYRIGHT_END%
// ---------------------------------------------------------------------
// %BANNER_END%
using UnityEngine;
using UnityEditor;
using System.IO;
using System;
namespace MagicLeap
{
[InitializeOnLoad]
public sealed class MagicLeapSDKUtil
{
private const string kManifestPath = ".metadata/sdk.manifest";
private const string kMagicLeapSDKRoot = "MagicLeapSDKRoot";
private const UnityEditor.BuildTarget kBuildTarget = BuildTarget.Android;
private static uint minApiLevel = 0;
[Serializable]
private class SDKManifest
{
public string schemaVersion = null;
public string label = null;
public string version = null;
public string mldb = null;
}
///
/// If the MLSDK path is set in the editor preferences and points to a valid sdk.
///
public static bool SdkAvailable
{
get
{
var path = SdkPath;
if (string.IsNullOrEmpty(path))
return false;
return Directory.Exists(path.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar));
}
}
public static uint MinimumApiLevel
{
get
{
if(minApiLevel == 0)
{
try
{
var result = UnityEngine.XR.MagicLeap.Native.MagicLeapNativeBindings.MLUnitySdkGetMinApiLevel(out minApiLevel);
UnityEngine.XR.MagicLeap.MLResult.DidNativeCallSucceed(result, nameof(UnityEngine.XR.MagicLeap.Native.MagicLeapNativeBindings.MLUnitySdkGetMinApiLevel));
}
catch(DllNotFoundException)
{
Debug.LogWarning($"Native plugins have not been built for host ({Application.platform}). Minimum API level can't be queried.");
}
}
return minApiLevel;
}
}
///
/// MLSDK path for the android target.
///
public static string SdkPath
{
get { return GetSDKPath(kBuildTarget); }
set { SetSDKPath(kBuildTarget, value); }
}
///
/// MLSDK version
///
public static Version SdkVersion => new Version(JsonUtility.FromJson(File.ReadAllText(Path.Combine(SdkPath, kManifestPath))).version);
///
/// Get the MLSDK path based on provided command-line argument or environment variable.
///
private static string GetSDKPath(BuildTarget target)
{
if (target == BuildTarget.Android)
{
string path = GetMLSDKCmdLineArg();
if (string.IsNullOrEmpty(path))
{
path = SessionState.GetString(kMagicLeapSDKRoot, null);
if (string.IsNullOrEmpty(path))
{
// We now only ever need the MLSDK path when running some TestRunner tests and this is generally only
// done in CI by passing a "-mlsdk" argument to the Unity command line. Therefore the call to GetMLSDKCmdLineArg()
// above should be enough to take care of this. In the rare event someone is trying to run the tests locally in the editor,
// this makes the assumption it's a developer with the common "MLSDK" environment variable set on their dev environment
path = Environment.GetEnvironmentVariable("MLSDK");
}
}
return path;
}
string targetPath = SessionState.GetString(target.ToString() + "SDKRoot", kMagicLeapSDKRoot);
if (string.IsNullOrEmpty(targetPath))
{
Debug.LogWarningFormat("MagicLeapSDKUtil couldn't determine SDK path for BuildTarget {0}.", target.ToString());
}
return targetPath;
}
private static string GetMLSDKCmdLineArg()
{
string path = "";
var args = new System.Collections.Generic.List(Environment.GetCommandLineArgs());
var mlsdkParam = args.IndexOf("-mlsdk");
if (mlsdkParam >= 0 && mlsdkParam < args.Count - 1)
{
path = args[mlsdkParam + 1].Replace("\\", "/");
Debug.Log("GetSDKPath got -mlsdk path from command line args: " + path);
}
return path;
}
private static void SetSDKPath(BuildTarget target, string path)
{
if (target == BuildTarget.Android)
{
SessionState.SetString(kMagicLeapSDKRoot, path);
}
else
{
SessionState.SetString(target.ToString() + "SDKRoot", path);
}
}
}
}