From 353da5574c812f6eb7a1eb6f5cf64dec429d9cd8 Mon Sep 17 00:00:00 2001 From: TORISOUP Date: Thu, 19 Apr 2018 23:26:31 +0900 Subject: [PATCH 1/4] 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 } } From 68fcedc3f929971aaf71d2472baa314dddff29e4 Mon Sep 17 00:00:00 2001 From: TORISOUP Date: Thu, 19 Apr 2018 23:28:20 +0900 Subject: [PATCH 2/4] fix typo --- Scripts/UniTask/ThreadScheduler.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Scripts/UniTask/ThreadScheduler.cs b/Scripts/UniTask/ThreadScheduler.cs index e5a797588..8695b3efb 100644 --- a/Scripts/UniTask/ThreadScheduler.cs +++ b/Scripts/UniTask/ThreadScheduler.cs @@ -5,11 +5,11 @@ namespace UniTask { public static partial class Scheduler { - private static IScheduler singleWorkerTrehad; + private static IScheduler singleWorkerThread; public static IScheduler SingleWorkerThread { - get { return singleWorkerTrehad ?? (singleWorkerTrehad = new ThreadScheduler()); } + get { return singleWorkerThread ?? (singleWorkerThread = new ThreadScheduler()); } } public class ThreadScheduler : IScheduler From 6a459e3735e83aae162be1fa0e89859bacb7030e Mon Sep 17 00:00:00 2001 From: TORISOUP Date: Sat, 21 Apr 2018 23:18:02 +0900 Subject: [PATCH 3/4] use TaskCompletionSource --- Scripts/Format/VRMImporter.cs | 25 ++++++------- Scripts/UniTask/Schedulable.cs | 66 ++++++---------------------------- 2 files changed, 21 insertions(+), 70 deletions(-) diff --git a/Scripts/Format/VRMImporter.cs b/Scripts/Format/VRMImporter.cs index ab6eab8d1..033f59914 100644 --- a/Scripts/Format/VRMImporter.cs +++ b/Scripts/Format/VRMImporter.cs @@ -6,6 +6,9 @@ using UniGLTF; using System.Collections.Generic; using System.Collections; using UniTask; +#if (NET_4_6 && UNITY_2018_1_OR_NEWER) +using System.Threading.Tasks; +#endif namespace VRM @@ -524,32 +527,26 @@ namespace VRM } #if (NET_4_6 && UNITY_2018_1_OR_NEWER) - /// - /// Gets an awaiter that returns the loaded GameObject. - /// - public static Schedulable LoadVrmAsync(string path) + + public static Task LoadVrmAsync(string path) { var context = new VRMImporterContext(path); context.ParseVrm(File.ReadAllBytes(path)); - return LoadVrmAsyncInternal(context); + return LoadVrmAsyncInternal(context).ToTask(); } - /// - /// Gets an awaiter that returns the loaded GameObject. - /// - public static Schedulable LoadVrmAsync(Byte[] bytes) + + public static Task 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) + + public static Task LoadVrmAsync(VRMImporterContext ctx) { - return LoadVrmAsyncInternal(ctx); + return LoadVrmAsyncInternal(ctx).ToTask(); } #endif diff --git a/Scripts/UniTask/Schedulable.cs b/Scripts/UniTask/Schedulable.cs index 8f751d3a6..bb0237693 100644 --- a/Scripts/UniTask/Schedulable.cs +++ b/Scripts/UniTask/Schedulable.cs @@ -2,8 +2,7 @@ using System.Collections; using System.Collections.Generic; #if (NET_4_6 && UNITY_2018_1_OR_NEWER) -using System.Threading; -using System.Runtime.CompilerServices; +using System.Threading.Tasks; #endif namespace UniTask @@ -186,9 +185,16 @@ namespace UniTask } #if (NET_4_6 && UNITY_2018_1_OR_NEWER) - public static SchedulableAwaiter GetAwaiter(this Schedulable schedulable) + public static Task ToTask(this Schedulable schedulable) { - return new SchedulableAwaiter(schedulable, true); + return ToTask(schedulable, Scheduler.MainThread); + } + + public static Task ToTask(this Schedulable schedulable, IScheduler scheduler) + { + var tcs = new TaskCompletionSource(); + schedulable.Subscribe(scheduler, r => tcs.SetResult(r), ex => tcs.SetException(ex)); + return tcs.Task; } #endif @@ -233,57 +239,5 @@ 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 } } From 288c440ce6ccda9784add68b858db43fbdfafd4c Mon Sep 17 00:00:00 2001 From: TORISOUP Date: Mon, 21 May 2018 22:44:42 +0900 Subject: [PATCH 4/4] Change to TrySet method --- Scripts/UniTask/Schedulable.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Scripts/UniTask/Schedulable.cs b/Scripts/UniTask/Schedulable.cs index bb0237693..3dab6552b 100644 --- a/Scripts/UniTask/Schedulable.cs +++ b/Scripts/UniTask/Schedulable.cs @@ -193,7 +193,7 @@ namespace UniTask public static Task ToTask(this Schedulable schedulable, IScheduler scheduler) { var tcs = new TaskCompletionSource(); - schedulable.Subscribe(scheduler, r => tcs.SetResult(r), ex => tcs.SetException(ex)); + schedulable.Subscribe(scheduler, r => tcs.TrySetResult(r), ex => tcs.TrySetException(ex)); return tcs.Task; } #endif