From 353da5574c812f6eb7a1eb6f5cf64dec429d9cd8 Mon Sep 17 00:00:00 2001 From: TORISOUP Date: Thu, 19 Apr 2018 23:26:31 +0900 Subject: [PATCH] Add await support --- Scripts/Format/VRMImporter.cs | 82 +++++++++++++++++++++++----------- Scripts/UniTask/Schedulable.cs | 64 +++++++++++++++++++++++++- 2 files changed, 120 insertions(+), 26 deletions(-) diff --git a/Scripts/Format/VRMImporter.cs b/Scripts/Format/VRMImporter.cs index 9808ab9d9..ab6eab8d1 100644 --- a/Scripts/Format/VRMImporter.cs +++ b/Scripts/Format/VRMImporter.cs @@ -75,12 +75,12 @@ namespace VRM public static CreateMaterialFunc GetMaterialFunc(List materials) { - var CreateDefault= gltfImporter.CreateMaterialFuncFromShader(Shader.Find("VRM/UnlitTexture")); + var CreateDefault = gltfImporter.CreateMaterialFuncFromShader(Shader.Find("VRM/UnlitTexture")); var CreateZWrite = gltfImporter.CreateMaterialFuncFromShader(Shader.Find("VRM/UnlitTransparentZWrite")); CreateMaterialFunc fallback = (ctx, i) => { var vrm = ctx.GLTF as glTF_VRM; - if(vrm!=null && vrm.materials[i].name.ToLower().Contains("zwrite")) + if (vrm != null && vrm.materials[i].name.ToLower().Contains("zwrite")) { // 一応。不要かも Debug.Log("fallback to VRM/UnlitTransparentZWrite"); @@ -326,7 +326,7 @@ namespace VRM asset.MaterialValues = group.materialValues.Select(x => { var value = new Vector4(); - for(int i=0; i y.name==x.materialName).GetColor(x.propertyName), + BaseValue = context.Materials.First(y => y.name == x.materialName).GetColor(x.propertyName), }; }) .ToArray(); @@ -523,6 +523,36 @@ namespace VRM yield return null; } +#if (NET_4_6 && UNITY_2018_1_OR_NEWER) + /// + /// Gets an awaiter that returns the loaded GameObject. + /// + public static Schedulable LoadVrmAsync(string path) + { + var context = new VRMImporterContext(path); + context.ParseVrm(File.ReadAllBytes(path)); + return LoadVrmAsyncInternal(context); + } + + /// + /// Gets an awaiter that returns the loaded GameObject. + /// + public static Schedulable LoadVrmAsync(Byte[] bytes) + { + var context = new VRMImporterContext(); + context.ParseVrm(bytes); + return LoadVrmAsync(context); + } + + /// + /// Gets an awaiter that returns the loaded GameObject. + /// + public static Schedulable LoadVrmAsync(VRMImporterContext ctx) + { + return LoadVrmAsyncInternal(ctx); + } +#endif + public static void LoadVrmAsync(string path, Action onLoaded) { var context = new VRMImporterContext(path); @@ -538,10 +568,16 @@ namespace VRM } public static void LoadVrmAsync(VRMImporterContext ctx, Action onLoaded) + { + LoadVrmAsyncInternal(ctx) + .Subscribe(Scheduler.MainThread, onLoaded, Debug.LogError); + } + + private static Schedulable LoadVrmAsyncInternal(VRMImporterContext ctx) { var schedulable = Schedulable.Create(); - schedulable + return schedulable .AddTask(Scheduler.ThreadPool, () => { ctx.GLTF.baseDir = Path.GetDirectoryName(ctx.Path); @@ -584,28 +620,24 @@ namespace VRM .ContinueWithCoroutine(Scheduler.MainThread, () => LoadNodes(ctx)) .ContinueWithCoroutine(Scheduler.MainThread, () => BuildHierarchy(ctx)) .ContinueWith(Scheduler.MainThread, _ => VRMImporter.OnLoadModel(ctx)) - .Subscribe(Scheduler.MainThread, - _ => - { - /* - Debug.LogFormat("task end: {0}/{1}/{2}/{3}", - ctx.Textures.Count, - ctx.Materials.Count, - ctx.Meshes.Count, - ctx.Nodes.Count - ); - */ - ctx.Root.name = Path.GetFileNameWithoutExtension(ctx.Path); + .ContinueWith(Scheduler.MainThread, + _ => + { + /* + Debug.LogFormat("task end: {0}/{1}/{2}/{3}", + ctx.Textures.Count, + ctx.Materials.Count, + ctx.Meshes.Count, + ctx.Nodes.Count + ); + */ + ctx.Root.name = Path.GetFileNameWithoutExtension(ctx.Path); - // 非表示のメッシュを表示する - ctx.ShowMeshes(); + // 非表示のメッシュを表示する + ctx.ShowMeshes(); - onLoaded(ctx.Root); - }, ex => - { - Debug.LogError(ex); - }) - ; + return ctx.Root; + }); } #endregion } diff --git a/Scripts/UniTask/Schedulable.cs b/Scripts/UniTask/Schedulable.cs index aa53759b2..8f751d3a6 100644 --- a/Scripts/UniTask/Schedulable.cs +++ b/Scripts/UniTask/Schedulable.cs @@ -1,7 +1,10 @@ using System; using System.Collections; using System.Collections.Generic; - +#if (NET_4_6 && UNITY_2018_1_OR_NEWER) +using System.Threading; +using System.Runtime.CompilerServices; +#endif namespace UniTask { @@ -182,6 +185,13 @@ namespace UniTask TaskChain.Schedule(schedulable.GetRoot(), onError); } +#if (NET_4_6 && UNITY_2018_1_OR_NEWER) + public static SchedulableAwaiter GetAwaiter(this Schedulable schedulable) + { + return new SchedulableAwaiter(schedulable, true); + } +#endif + /* public static ISchedulable Sequencial(IEnumerable> schedulables, Action mergePred) { @@ -223,5 +233,57 @@ namespace UniTask }, scheduler); } */ +#if (NET_4_6 && UNITY_2018_1_OR_NEWER) + public class SchedulableAwaiter : INotifyCompletion + { + private readonly Schedulable target = null; + + private T result; + + private readonly bool continueOnCapturedContext; + + public T GetResult() + { + return result; + } + + public bool IsCompleted { get; private set; } + + public SchedulableAwaiter(Schedulable target) + { + this.target = target; + continueOnCapturedContext = true; + } + + public SchedulableAwaiter(Schedulable target, bool continueOnCapturedContext) + { + this.target = target; + this.continueOnCapturedContext = continueOnCapturedContext; + } + + public void OnCompleted(Action continuation) + { + var context = SynchronizationContext.Current; + if (continueOnCapturedContext && context != null) + { + target.Subscribe(target.Parent.Schedulder, r => + { + result = r; + IsCompleted = true; + context.Post(_ => continuation(), null); + }, ex => { throw ex; }); + } + else + { + target.Subscribe(target.Parent.Schedulder, r => + { + result = r; + IsCompleted = true; + continuation(); + }, ex => { throw ex; }); + } + } + } +#endif } }