diff --git a/Assets/MediaPipe/Examples/Scripts/AsyncOperationAwaiter.cs b/Assets/MediaPipe/Examples/Scripts/AsyncOperationAwaiter.cs new file mode 100644 index 000000000..ae1f0ea2a --- /dev/null +++ b/Assets/MediaPipe/Examples/Scripts/AsyncOperationAwaiter.cs @@ -0,0 +1,23 @@ +using System; +using System.Runtime.CompilerServices; +using UnityEngine; + +public class AsyncOperationAwaiter : INotifyCompletion where T : AsyncOperation { + T _asyncOperation; + + public AsyncOperationAwaiter(T asyncOperation) { + _asyncOperation = asyncOperation; + } + + public bool IsCompleted { + get { return _asyncOperation.isDone; } + } + + public T GetResult() { + return _asyncOperation; + } + + public void OnCompleted(Action continuation) { + _asyncOperation.completed += _ => { continuation(); }; + } +} diff --git a/Assets/MediaPipe/Examples/Scripts/DemoAssetManager.cs.meta b/Assets/MediaPipe/Examples/Scripts/AsyncOperationAwaiter.cs.meta similarity index 83% rename from Assets/MediaPipe/Examples/Scripts/DemoAssetManager.cs.meta rename to Assets/MediaPipe/Examples/Scripts/AsyncOperationAwaiter.cs.meta index 7bb1124a3..4639be0ba 100644 --- a/Assets/MediaPipe/Examples/Scripts/DemoAssetManager.cs.meta +++ b/Assets/MediaPipe/Examples/Scripts/AsyncOperationAwaiter.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 59b6eca57891f074aae0dc89ce1a14ef +guid: 076320119f383982eabd4278ac4f950c MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Assets/MediaPipe/Examples/Scripts/AsyncOperationExtension.cs b/Assets/MediaPipe/Examples/Scripts/AsyncOperationExtension.cs new file mode 100644 index 000000000..fc30cec81 --- /dev/null +++ b/Assets/MediaPipe/Examples/Scripts/AsyncOperationExtension.cs @@ -0,0 +1,7 @@ +using UnityEngine; + +public static class AsyncOperationExtension { + public static AsyncOperationAwaiter GetAwaiter(this T operation) where T : AsyncOperation { + return new AsyncOperationAwaiter(operation); + } +} diff --git a/Assets/MediaPipe/SDK/Scripts/Util/AssetManager.cs.meta b/Assets/MediaPipe/Examples/Scripts/AsyncOperationExtension.cs.meta similarity index 83% rename from Assets/MediaPipe/SDK/Scripts/Util/AssetManager.cs.meta rename to Assets/MediaPipe/Examples/Scripts/AsyncOperationExtension.cs.meta index 014b6c4d5..11c6ae576 100644 --- a/Assets/MediaPipe/SDK/Scripts/Util/AssetManager.cs.meta +++ b/Assets/MediaPipe/Examples/Scripts/AsyncOperationExtension.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: efe69ee29850f23ccb8cdcb2b438f87a +guid: 70be8e0c8a430d477b86885d8e9287ad MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Assets/MediaPipe/Examples/Scripts/DemoAssetManager.cs b/Assets/MediaPipe/Examples/Scripts/DemoAssetManager.cs deleted file mode 100644 index efb3a76f6..000000000 --- a/Assets/MediaPipe/Examples/Scripts/DemoAssetManager.cs +++ /dev/null @@ -1,77 +0,0 @@ -using Mediapipe; -using System; -using System.IO; -using System.Linq; -using System.Threading.Tasks; -using UnityEngine; - -public sealed class DemoAssetManager : AssetManager { - private static readonly Lazy lazy = new Lazy(() => new DemoAssetManager()); - public static DemoAssetManager Instance { get { return lazy.Value; } } - private readonly static string CacheRootPath = Path.Combine(Application.persistentDataPath, "Cache"); - private readonly static string ModelCacheRootPath = Path.Combine(CacheRootPath, "MediaPipe", "Models"); - - private AssetBundle _mediaPipeModels; - private AssetBundle MediaPipeModels { - get { - if (_mediaPipeModels != null) { - return _mediaPipeModels; - } - - return _mediaPipeModels = AssetBundle.LoadFromFile(Path.Combine(Application.streamingAssetsPath, "AssetBundles", "mediapipe", "models")); - } - } - - private DemoAssetManager() : base() { - if (!Directory.Exists(ModelCacheRootPath)) { - Directory.CreateDirectory(ModelCacheRootPath); - } - } - - public async void LoadAllAssetsAsync() { - var bundle = MediaPipeModels; - - if (bundle == null) { - Debug.LogError("Failed to load assets"); - return; - } - - await Task.WhenAll(bundle.LoadAllAssets().Select((asset) => WriteCacheFileAsync(asset)).ToArray()); - } - - public override string CacheFileFromAsset(string assetPath) { - var assetName = Path.GetFileNameWithoutExtension(assetPath); - var cachePath = CachePathFor(assetName); - - if (File.Exists(cachePath)) { - return cachePath; - } - - return null; - } - - public override bool ReadFile(string path, IntPtr dst) { - var cachePath = CacheFileFromAsset(path); - - if (!File.Exists(cachePath)) { - return false; - } - - var asset = File.ReadAllBytes(cachePath); - ResourceUtil.CopyBytes(dst, asset); - return true; - } - - private string CachePathFor(string assetName) { - return Path.Combine(ModelCacheRootPath, assetName); - } - - private async Task WriteCacheFileAsync(TextAsset asset) { - var path = CachePathFor(asset.name); - - using (FileStream sourceStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, bufferSize: 4096, useAsync: true)) { - var bytes = asset.bytes; - await sourceStream.WriteAsync(bytes, 0, bytes.Length); - }; - } -} diff --git a/Assets/MediaPipe/Examples/Scripts/ResourceManager.meta b/Assets/MediaPipe/Examples/Scripts/ResourceManager.meta new file mode 100644 index 000000000..756a1d50d --- /dev/null +++ b/Assets/MediaPipe/Examples/Scripts/ResourceManager.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6980fc6117c073707aa303b7e72e2ac6 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MediaPipe/Examples/Scripts/ResourceManager/AssetBundleManager.cs b/Assets/MediaPipe/Examples/Scripts/ResourceManager/AssetBundleManager.cs new file mode 100644 index 000000000..6ee10bbfa --- /dev/null +++ b/Assets/MediaPipe/Examples/Scripts/ResourceManager/AssetBundleManager.cs @@ -0,0 +1,84 @@ +using Mediapipe; +using System; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using UnityEngine; + +public sealed class AssetBundleManager : ResourceManager { + private static readonly Lazy lazy = new Lazy(() => new AssetBundleManager()); + public static AssetBundleManager Instance { get { return lazy.Value; } } + private readonly static string CacheRootPath = Path.Combine(Application.persistentDataPath, "Cache"); + private readonly static string ModelCacheRootPath = Path.Combine(CacheRootPath, "MediaPipe", "Models"); + + private AssetBundleManager() : base() { + if (!Directory.Exists(ModelCacheRootPath)) { + Directory.CreateDirectory(ModelCacheRootPath); + } + } + + public async Task LoadAllAssetsAsync() { + Debug.Log("Starting to load assets"); + + var bundleLoadReq = await AssetBundle.LoadFromFileAsync(Path.Combine(Application.streamingAssetsPath, "AssetBundles", "mediapipe", "models")); + + if (bundleLoadReq.assetBundle == null) { + Debug.LogError("Failed to load the AssetBundle"); + return; + } + + var assetLoadReq = await bundleLoadReq.assetBundle.LoadAllAssetsAsync(); + if (assetLoadReq.allAssets == null) { + Debug.LogError("Failed to load assets"); + return; + } + + var loadTasks = assetLoadReq.allAssets.Select((asset) => WriteCacheFileAsync((TextAsset)asset)); + await Task.WhenAll(loadTasks); + Debug.Log("Loaded all assets"); + } + + protected override string CacheFileFromAsset(string assetPath) { + var assetName = Path.GetFileNameWithoutExtension(assetPath); + var cachePath = CachePathFor(assetName); + + if (File.Exists(cachePath)) { + return cachePath; + } + + return null; + } + + protected override bool ReadFile(string path, IntPtr dst) { + var cachePath = CacheFileFromAsset(path); + + if (!File.Exists(cachePath)) { + return false; + } + + var asset = File.ReadAllBytes(cachePath); + ResourceUtil.CopyBytes(dst, asset); + return true; + } + + private string CachePathFor(string assetName) { + return Path.Combine(ModelCacheRootPath, assetName); + } + + private async Task WriteCacheFileAsync(TextAsset asset) { + var path = CachePathFor(asset.name); + var bytes = asset.bytes; + Debug.Log($"Saving {asset.name} to {path} (length={bytes.Length})"); + + FileStream sourceStream = null; + + try { + sourceStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, bufferSize: 4096, useAsync: true); + await sourceStream.WriteAsync(bytes, 0, bytes.Length); + } finally { + if (sourceStream != null) { + sourceStream.Close(); + } + } + } +} diff --git a/Assets/MediaPipe/Examples/Scripts/ResourceManager/AssetBundleManager.cs.meta b/Assets/MediaPipe/Examples/Scripts/ResourceManager/AssetBundleManager.cs.meta new file mode 100644 index 000000000..b39e8b288 --- /dev/null +++ b/Assets/MediaPipe/Examples/Scripts/ResourceManager/AssetBundleManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a592086b26fe37b35862231ff60aa32a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MediaPipe/Examples/Scripts/SceneDirector.cs b/Assets/MediaPipe/Examples/Scripts/SceneDirector.cs index 44a452f5d..81108756e 100644 --- a/Assets/MediaPipe/Examples/Scripts/SceneDirector.cs +++ b/Assets/MediaPipe/Examples/Scripts/SceneDirector.cs @@ -1,3 +1,4 @@ +using System; using System.IO; using System.Collections; @@ -20,6 +21,9 @@ public class SceneDirector : MonoBehaviour { const int MAX_WAIT_FRAME = 50; + bool IsAssetLoaded = false; + bool IsAssetLoadFailed = false; + void OnEnable() { var nameForGlog = Path.Combine(Application.dataPath, "MediaPipePlugin"); var logDir = Path.Combine(Application.persistentDataPath, "Logs", "MediaPipe"); @@ -31,7 +35,7 @@ void OnEnable() { UnsafeNativeMethods.InitGoogleLogging(nameForGlog, logDir); } - void Start() { + async void Start() { webCamScreen = GameObject.Find("WebCamScreen"); if (useGPU) { @@ -41,8 +45,15 @@ void Start() { gpuHelper.InitializeForTest(gpuResources); } - DemoAssetManager.Instance.LoadAllAssetsAsync(); - ResourceUtil.InitializeResourceManager(DemoAssetManager.Instance); + ResourceUtil.InitializeResourceManager(AssetBundleManager.Instance); + + try { + await AssetBundleManager.Instance.LoadAllAssetsAsync(); + IsAssetLoaded = true; + } catch (Exception e) { + Debug.LogError(e); + IsAssetLoadFailed = true; + } } void OnDisable() { @@ -111,6 +122,17 @@ IEnumerator RunGraph() { yield break; } + if (!IsAssetLoaded && !IsAssetLoadFailed) { + Debug.Log("Waiting for assets to be loaded..."); + } + + yield return new WaitUntil(() => IsAssetLoaded || IsAssetLoadFailed); + + if (IsAssetLoadFailed) { + Debug.LogError("Failed to load assets. Stopping..."); + yield break; + } + graphContainer = Instantiate(graphPrefab); var graph = graphContainer.GetComponent>(); diff --git a/Assets/MediaPipe/SDK/Scripts/Util/AssetManager.cs b/Assets/MediaPipe/SDK/Scripts/Util/ResourceManager.cs similarity index 79% rename from Assets/MediaPipe/SDK/Scripts/Util/AssetManager.cs rename to Assets/MediaPipe/SDK/Scripts/Util/ResourceManager.cs index 1a10b6acb..0612fb2a3 100644 --- a/Assets/MediaPipe/SDK/Scripts/Util/AssetManager.cs +++ b/Assets/MediaPipe/SDK/Scripts/Util/ResourceManager.cs @@ -2,7 +2,7 @@ using System.Runtime.InteropServices; namespace Mediapipe { - public abstract class AssetManager { + public abstract class ResourceManager { [UnmanagedFunctionPointer(CallingConvention.StdCall)] private delegate string CacheFilePathResolver(string path); private readonly CacheFilePathResolver cacheFilePathResolver; @@ -11,7 +11,7 @@ public abstract class AssetManager { private delegate bool ReadFileHandler(string path, IntPtr dst); private readonly ReadFileHandler readFileHandler; - protected AssetManager() { + protected ResourceManager() { cacheFilePathResolver = CacheFileFromAsset; readFileHandler = ReadFile; } @@ -24,8 +24,8 @@ public IntPtr GetReadFileHandlerPtr() { return Marshal.GetFunctionPointerForDelegate(readFileHandler); } - public abstract string CacheFileFromAsset(string assetPath); + protected abstract string CacheFileFromAsset(string assetPath); - public abstract bool ReadFile(string path, IntPtr dst); + protected abstract bool ReadFile(string path, IntPtr dst); } } diff --git a/Assets/MediaPipe/SDK/Scripts/Util/ResourceManager.cs.meta b/Assets/MediaPipe/SDK/Scripts/Util/ResourceManager.cs.meta new file mode 100644 index 000000000..ca1c57bdb --- /dev/null +++ b/Assets/MediaPipe/SDK/Scripts/Util/ResourceManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a4e51cc091c70c661943c15038a905da +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/MediaPipe/SDK/Scripts/Util/ResourceUtil.cs b/Assets/MediaPipe/SDK/Scripts/Util/ResourceUtil.cs index e64012a1d..96021c8ae 100644 --- a/Assets/MediaPipe/SDK/Scripts/Util/ResourceUtil.cs +++ b/Assets/MediaPipe/SDK/Scripts/Util/ResourceUtil.cs @@ -2,8 +2,8 @@ namespace Mediapipe { public class ResourceUtil { - public static void InitializeResourceManager(AssetManager assetManager) { - UnsafeNativeMethods.MpResourceManagerInitialize(assetManager.GetCacheFilePathResolverPtr(), assetManager.GetReadFileHandlerPtr()); + public static void InitializeResourceManager(ResourceManager resourceManager) { + UnsafeNativeMethods.MpResourceManagerInitialize(resourceManager.GetCacheFilePathResolverPtr(), resourceManager.GetReadFileHandlerPtr()); } public static void CopyBytes(IntPtr dst, byte[] src) { diff --git a/ProjectSettings/GraphicsSettings.asset b/ProjectSettings/GraphicsSettings.asset index 71c9e0f54..4654e1330 100644 --- a/ProjectSettings/GraphicsSettings.asset +++ b/ProjectSettings/GraphicsSettings.asset @@ -34,7 +34,6 @@ GraphicsSettings: - {fileID: 16000, guid: 0000000000000000f000000000000000, type: 0} - {fileID: 16001, guid: 0000000000000000f000000000000000, type: 0} - {fileID: 17000, guid: 0000000000000000f000000000000000, type: 0} - - {fileID: 16003, guid: 0000000000000000f000000000000000, type: 0} m_PreloadedShaders: [] m_SpritesDefaultMaterial: {fileID: 10754, guid: 0000000000000000f000000000000000, type: 0}