From 5ebaa1e3ec2e9bf4fbb39c616fac30c3a95cc438 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Thu, 6 Mar 2025 22:22:51 +0900 Subject: [PATCH] VRM10ViewerController.cs --- .../VRM10Viewer/{ => UI}/VRM10Loaded.cs | 0 .../VRM10Viewer/{ => UI}/VRM10Loaded.cs.meta | 0 .../VRM10Viewer/UI/VRM10ViewerController.cs | 344 +++++++++++ .../UI/VRM10ViewerController.cs.meta | 11 + .../VRM10Viewer/UI/VRM10ViewerUI.cs | 547 +++++------------- 5 files changed, 502 insertions(+), 400 deletions(-) rename Assets/VRM10_Samples/VRM10Viewer/{ => UI}/VRM10Loaded.cs (100%) rename Assets/VRM10_Samples/VRM10Viewer/{ => UI}/VRM10Loaded.cs.meta (100%) create mode 100644 Assets/VRM10_Samples/VRM10Viewer/UI/VRM10ViewerController.cs create mode 100644 Assets/VRM10_Samples/VRM10Viewer/UI/VRM10ViewerController.cs.meta diff --git a/Assets/VRM10_Samples/VRM10Viewer/VRM10Loaded.cs b/Assets/VRM10_Samples/VRM10Viewer/UI/VRM10Loaded.cs similarity index 100% rename from Assets/VRM10_Samples/VRM10Viewer/VRM10Loaded.cs rename to Assets/VRM10_Samples/VRM10Viewer/UI/VRM10Loaded.cs diff --git a/Assets/VRM10_Samples/VRM10Viewer/VRM10Loaded.cs.meta b/Assets/VRM10_Samples/VRM10Viewer/UI/VRM10Loaded.cs.meta similarity index 100% rename from Assets/VRM10_Samples/VRM10Viewer/VRM10Loaded.cs.meta rename to Assets/VRM10_Samples/VRM10Viewer/UI/VRM10Loaded.cs.meta diff --git a/Assets/VRM10_Samples/VRM10Viewer/UI/VRM10ViewerController.cs b/Assets/VRM10_Samples/VRM10Viewer/UI/VRM10ViewerController.cs new file mode 100644 index 000000000..bc5aaf09e --- /dev/null +++ b/Assets/VRM10_Samples/VRM10Viewer/UI/VRM10ViewerController.cs @@ -0,0 +1,344 @@ +using System; +using System.Collections; +using System.IO; +using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; +using UniGLTF; +using UniGLTF.SpringBoneJobs.Blittables; +using UnityEngine; +using static UniVRM10.Vrm10; + + +namespace UniVRM10.VRM10Viewer +{ + class VRM10ViewerController : IDisposable + { + private CancellationTokenSource _cancellationTokenSource; + public void Dispose() + { + _cancellationTokenSource?.Dispose(); + } + public void Cancel() + { + if (_cancellationTokenSource != null) + { + _cancellationTokenSource.Cancel(); + } + } + + private TinyMToonrMaterialImporter m_mtoonImporter; + private TinyPbrMaterialImporter m_pbrImporter; + + private Loaded m_loaded; + Loaded Loaded + { + get + { + return m_loaded; + } + set + { + if (m_loaded != null) + { + m_loaded.Dispose(); + m_loaded = null; + } + m_loaded = value; + m_onLoaded(m_loaded); + } + } + + IVrm10Animation m_src = default; + public IVrm10Animation TPose; + public IVrm10Animation Motion + { + get { return m_src; } + set + { + if (m_src != null) + { + m_src.Dispose(); + } + m_src = value; + + TPose = new Vrm10TPose(m_src.ControlRig.Item1.GetRawHipsPosition()); + } + } + Action m_onLoaded; + VrmMetaInformationCallback m_updateMeta; + public VRM10ViewerController( + TinyMToonrMaterialImporter tinyMToon, + TinyPbrMaterialImporter tinyPbr, + VrmMetaInformationCallback updateMeta, + Action onLoaded + ) + { + m_mtoonImporter = tinyMToon; + m_pbrImporter = tinyPbr; + m_onLoaded = onLoaded; + m_updateMeta = updateMeta; + } + + public void ShowBoxMan(bool show) + { + if (Motion != null) + { + Motion.ShowBoxMan(show); + } + } + + [DllImport("__Internal")] + public static extern void WebGL_VRM10_VRM10Viewer_FileDialog(string target, string message); + + string FileDialog() + { +#if UNITY_EDITOR + return UnityEditor.EditorUtility.OpenFilePanel("Open VRM", "", "vrm,glb,gltf,zip"); +#elif UNITY_STANDALONE_WIN + return VRM10FileDialogForWindows.FileDialog("open VRM", "vrm", "glb", "gltf", "zip"); +#elif UNITY_WEBGL + // Open WebGL_VRM10_VRM10Viewer_FileDialog + // see: Assets/UniGLTF/Runtime/Utils/Plugins/OpenFile.jslib + WebGL_VRM10_VRM10Viewer_FileDialog("Canvas", "FileSelected"); + // Control flow does not return here. return empty string with dummy + return null; +#else + return Application.dataPath + "/default.vrm"; +#endif + } + + public IEnumerator LoadCoroutine(string url, LoadOptions opts) + { + var www = new WWW(url); + yield return www; + var _ = LoadModelBytes("WebGL.vrm", www.bytes, opts); + } + + public void OnOpenModelClicked(LoadOptions opts) + { + var path = FileDialog(); + _ = LoadModelPath(path, opts); + } + + public async void OnOpenMotionClicked() + { +#if UNITY_EDITOR + var path = UnityEditor.EditorUtility.OpenFilePanel("Open Motion", "", "bvh,gltf,glb,vrma"); +#elif UNITY_STANDALONE_WIN + var path = VRM10FileDialogForWindows.FileDialog("open Motion", "bvh", "gltf", "glb", "vrma"); +#else + var path = Application.dataPath + "/default.bvh"; +#endif + if (string.IsNullOrEmpty(path)) + { + return; + } + + var ext = Path.GetExtension(path).ToLower(); + if (ext == ".bvh") + { + Motion = BvhMotion.LoadBvhFromPath(path); + return; + } + + // gltf, glb etc... + using GltfData data = new AutoGltfFileParser(path).Parse(); + using var loader = new VrmAnimationImporter(data); + var instance = await loader.LoadAsync(new ImmediateCaller()); + Motion = instance.GetComponent(); + instance.GetComponent().Play(); + } + + public async void OnPastePoseClicked() + { + var text = GUIUtility.systemCopyBuffer; + if (string.IsNullOrEmpty(text)) + { + return; + } + + try + { + Motion = await Vrm10PoseLoader.LoadVrmAnimationPose(text); + } + catch (UniJSON.ParserException) + { + UniGLTFLogger.Warning("UniJSON.ParserException"); + } + catch (UniJSON.DeserializationException) + { + UniGLTFLogger.Warning("UniJSON.DeserializationException"); + } + } + + public void OnResetSpringBoneClicked() + { + if (Loaded != null) + { + if (Loaded.Runtime != null) + { + Loaded.Runtime.SpringBone.RestoreInitialTransform(); + } + } + } + + public void OnReconstructSpringBoneClicked() + { + if (Loaded != null) + { + if (Loaded.Runtime != null) + { + Loaded.Runtime.SpringBone.ReconstructSpringBone(); + } + } + } + + public async Task LoadModelPath(string path, LoadOptions opts) + { + var bytes = await File.ReadAllBytesAsync(path); + await LoadModelBytes(path, bytes, opts); + } + + IMaterialDescriptorGenerator GetMaterialDescriptorGenerator(LoadOptions opts) + { + var useCustomPbr = opts.UseCustomPbrMaterial && m_pbrImporter != null; + var useCustomMToon = opts.UseCustomMToonMaterial && m_mtoonImporter != null; + if (!useCustomPbr && !useCustomMToon) + { + // カスタムしない。デフォルトのローダーを使う + return default; + } + + return OrderedMaterialDescriptorGenerator.CreateCustomGenerator( + useCustomPbr ? m_pbrImporter : null, + useCustomMToon ? m_mtoonImporter : null); + } + + IAwaitCaller GetIAwaitCaller(bool useAsync) + { + if (useAsync) + { + if (Application.platform == RuntimePlatform.WebGLPlayer) + { + return new RuntimeOnlyNoThreadAwaitCaller(); + } + else + { + return new RuntimeOnlyAwaitCaller(); + } + } + else + { + return new ImmediateCaller(); + } + } + + + public async Task LoadModelBytes(string path, byte[] bytes, LoadOptions opts) + { + // cleanup + _cancellationTokenSource?.Dispose(); + _cancellationTokenSource = new CancellationTokenSource(); + var cancellationToken = _cancellationTokenSource.Token; + + try + { + // + // try VRM + // + UniGLTFLogger.Log($"{path}"); + var vrm10Instance = await Vrm10.LoadBytesAsync(bytes, + canLoadVrm0X: true, + showMeshes: false, + awaitCaller: GetIAwaitCaller(opts.UseAsync), + materialGenerator: GetMaterialDescriptorGenerator(opts), + vrmMetaInformationCallback: m_updateMeta, + ct: cancellationToken, + springboneRuntime: opts.UseSpringboneSingelton ? new Vrm10FastSpringboneRuntime() : new Vrm10FastSpringboneRuntimeStandalone()); + if (cancellationToken.IsCancellationRequested) + { + UnityObjectDestroyer.DestroyRuntimeOrEditor(vrm10Instance.gameObject); + cancellationToken.ThrowIfCancellationRequested(); + } + + if (vrm10Instance == null) + { + UniGLTFLogger.Warning("LoadPathAsync is null"); + return; + } + + var instance = vrm10Instance.GetComponent(); + instance.ShowMeshes(); + instance.EnableUpdateWhenOffscreen(); + Loaded = new Loaded(instance); + } + catch (Exception) + { + try + { + // + // fallback gltf + // + var instance = await GltfUtility.LoadBytesAsync(path, bytes, + awaitCaller: GetIAwaitCaller(opts.UseAsync), + materialGenerator: GetMaterialDescriptorGenerator(opts) + ); + instance.ShowMeshes(); + instance.EnableUpdateWhenOffscreen(); + Loaded = new Loaded(instance); + } + catch (Exception ex) + { + if (ex is OperationCanceledException) + { + UniGLTFLogger.Warning($"Canceled to Load: {path}"); + } + else + { + UniGLTFLogger.Error($"Failed to Load: {path}"); + UniGLTFLogger.Exception(ex); + } + } + } + } + + public bool TryUpdate( + bool useTPose, + BlittableModelLevel blittableModelLevel, + out Loaded loaded) + { + loaded = Loaded; + if (loaded == null) + { + return false; + } + if (loaded.Runtime == null) + { + return false; + } + + if (useTPose || Motion == null) + { + loaded.Runtime.VrmAnimation = TPose; + } + else + { + // Automatically retarget in Vrm10Runtime.Process + loaded.Runtime.VrmAnimation = Motion; + } + + loaded.Runtime.SpringBone.SetModelLevel(Loaded.Instance.transform, blittableModelLevel); + + return true; + } + } + + public class LoadOptions + { + public bool UseAsync; + public bool UseSpringboneSingelton; + public bool UseCustomPbrMaterial; + public bool UseCustomMToonMaterial; + } +} \ No newline at end of file diff --git a/Assets/VRM10_Samples/VRM10Viewer/UI/VRM10ViewerController.cs.meta b/Assets/VRM10_Samples/VRM10Viewer/UI/VRM10ViewerController.cs.meta new file mode 100644 index 000000000..8263492a6 --- /dev/null +++ b/Assets/VRM10_Samples/VRM10Viewer/UI/VRM10ViewerController.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 37ba766f2a14fb54690b1d62e2ccf450 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/VRM10_Samples/VRM10Viewer/UI/VRM10ViewerUI.cs b/Assets/VRM10_Samples/VRM10Viewer/UI/VRM10ViewerUI.cs index fdce9a9ad..c313b160c 100644 --- a/Assets/VRM10_Samples/VRM10Viewer/UI/VRM10ViewerUI.cs +++ b/Assets/VRM10_Samples/VRM10Viewer/UI/VRM10ViewerUI.cs @@ -3,15 +3,13 @@ using System.Collections; using System.Collections.Generic; using System.IO; using System.Linq; -using System.Runtime.InteropServices; -using System.Threading; -using System.Threading.Tasks; using UniGLTF; using UniGLTF.SpringBoneJobs.Blittables; using UnityEngine; using UnityEngine.Rendering; using UnityEngine.UI; + namespace UniVRM10.VRM10Viewer { public class VRM10ViewerUI : MonoBehaviour @@ -182,26 +180,6 @@ namespace UniVRM10.VRM10Viewer [SerializeField] Slider m_pitch = default; - IVrm10Animation m_src = default; - public IVrm10Animation Motion - { - get { return m_src; } - set - { - if (m_src != null) - { - m_src.Dispose(); - } - m_src = value; - - TPose = new Vrm10TPose(m_src.ControlRig.Item1.GetRawHipsPosition()); - } - } - - public IVrm10Animation TPose; - - private CancellationTokenSource _cancellationTokenSource; - [Serializable] class TextFields { @@ -428,8 +406,6 @@ namespace UniVRM10.VRM10Viewer #endif } - Loaded m_loaded; - static class ArgumentChecker { static string[] Supported = { @@ -485,23 +461,45 @@ namespace UniVRM10.VRM10Viewer } } + VRM10ViewerController m_controller; VRM10AutoExpression m_autoEmotion; VRM10Blinker m_autoBlink; VRM10AIUEO m_autoLipsync; - private TinyMToonrMaterialImporter m_mtoonImporter; - private TinyPbrMaterialImporter m_pbrImporter; + void OnLoaded(Loaded loaded) + { + m_showBoxMan.isOn = false; + m_happy.OnLoad(loaded.Instance.Vrm.Expression.Happy); + m_angry.OnLoad(loaded.Instance.Vrm.Expression.Angry); + m_sad.OnLoad(loaded.Instance.Vrm.Expression.Sad); + m_relaxed.OnLoad(loaded.Instance.Vrm.Expression.Relaxed); + m_surprised.OnLoad(loaded.Instance.Vrm.Expression.Surprised); + m_lipAa.OnLoad(loaded.Instance.Vrm.Expression.Aa); + m_lipIh.OnLoad(loaded.Instance.Vrm.Expression.Ih); + m_lipOu.OnLoad(loaded.Instance.Vrm.Expression.Ou); + m_lipEe.OnLoad(loaded.Instance.Vrm.Expression.Ee); + m_lipOh.OnLoad(loaded.Instance.Vrm.Expression.Oh); + m_blink.OnLoad(loaded.Instance.Vrm.Expression.Blink); + } + + LoadOptions MakeLoadOptions() + { + return new LoadOptions() + { + UseAsync = m_useAsync.isOn, + UseSpringboneSingelton = m_useSpringboneSingelton.isOn, + UseCustomPbrMaterial = m_useCustomPbrMaterial.isOn, + UseCustomMToonMaterial = m_useCustomMToonMaterial.isOn, + }; + } private void Start() { - if (m_mtoonMaterialOpaque != null && m_mtoonMaterialAlphaBlend != null) - { - m_mtoonImporter = new(m_mtoonMaterialOpaque, m_mtoonMaterialAlphaBlend); - } - if (m_pbrOpaqueMaterial != null && m_pbrAlphaBlendMaterial != null) - { - m_pbrImporter = new(m_pbrOpaqueMaterial, m_pbrAlphaBlendMaterial); - } + m_controller = new( + (m_mtoonMaterialOpaque != null && m_mtoonMaterialAlphaBlend != null) ? new TinyMToonrMaterialImporter(m_mtoonMaterialOpaque, m_mtoonMaterialAlphaBlend) : null, + (m_pbrOpaqueMaterial != null && m_pbrAlphaBlendMaterial != null) ? new TinyPbrMaterialImporter(m_pbrOpaqueMaterial, m_pbrAlphaBlendMaterial) : null, + m_texts.UpdateMeta, + OnLoaded); // URP かつ WebGL で有効にする m_useCustomMToonMaterial.isOn = Application.platform == RuntimePlatform.WebGLPlayer && GraphicsSettings.renderPipelineAsset != null; @@ -512,26 +510,26 @@ namespace UniVRM10.VRM10Viewer m_version.text = string.Format("VRM10ViewerUI {0}", PackageVersion.VERSION); - m_openModel.onClick.AddListener(OnOpenModelClicked); - m_openMotion.onClick.AddListener(OnOpenMotionClicked); - m_pastePose.onClick.AddListener(OnPastePoseClicked); - m_resetSpringBone.onClick.AddListener(OnResetSpringBoneClicked); - m_reconstructSpringBone.onClick.AddListener(OnReconstructSpringBoneClicked); + m_openModel.onClick.AddListener(() => m_controller.OnOpenModelClicked(MakeLoadOptions())); + m_openMotion.onClick.AddListener(m_controller.OnOpenMotionClicked); + m_pastePose.onClick.AddListener(m_controller.OnPastePoseClicked); + m_resetSpringBone.onClick.AddListener(m_controller.OnResetSpringBoneClicked); + m_reconstructSpringBone.onClick.AddListener(m_controller.OnReconstructSpringBoneClicked); // load initial bvh if (m_motion != null) { - Motion = BvhMotion.LoadBvhFromText(m_motion.text); + m_controller.Motion = BvhMotion.LoadBvhFromText(m_motion.text); if (GraphicsSettings.renderPipelineAsset != null && m_pbrAlphaBlendMaterial != null) { - Motion.SetBoxManMaterial(Instantiate(m_pbrOpaqueMaterial)); + m_controller.Motion.SetBoxManMaterial(Instantiate(m_pbrOpaqueMaterial)); } } if (ArgumentChecker.TryGetFirstLoadable(out var cmd)) { - var _ = LoadModelPath(cmd); + var _ = m_controller.LoadModelPath(cmd, MakeLoadOptions()); } m_texts.Start(); @@ -539,7 +537,7 @@ namespace UniVRM10.VRM10Viewer private void OnDestroy() { - _cancellationTokenSource?.Dispose(); + m_controller.Dispose(); } private void Update() @@ -551,158 +549,112 @@ namespace UniVRM10.VRM10Viewer if (Input.GetKeyDown(KeyCode.Escape)) { - if (_cancellationTokenSource != null) + m_controller.Cancel(); + } + + m_controller.ShowBoxMan(m_showBoxMan.isOn); + if (m_controller.TryUpdate( + m_ui.IsTPose, + new BlittableModelLevel { - _cancellationTokenSource.Cancel(); + ExternalForce = new Vector3(m_springboneExternalX.value, m_springboneExternalY.value, m_springboneExternalZ.value), + StopSpringBoneWriteback = m_springbonePause.isOn, + SupportsScalingAtRuntime = m_springboneScaling.isOn, + }, + out var loaded + )) + { + m_happy.ApplyRuntime(loaded.Instance.Vrm.Expression.Happy); + m_angry.ApplyRuntime(loaded.Instance.Vrm.Expression.Angry); + m_sad.ApplyRuntime(loaded.Instance.Vrm.Expression.Sad); + m_relaxed.ApplyRuntime(loaded.Instance.Vrm.Expression.Relaxed); + m_surprised.ApplyRuntime(loaded.Instance.Vrm.Expression.Surprised); + m_lipAa.ApplyRuntime(loaded.Instance.Vrm.Expression.Aa); + m_lipIh.ApplyRuntime(loaded.Instance.Vrm.Expression.Ih); + m_lipOu.ApplyRuntime(loaded.Instance.Vrm.Expression.Ou); + m_lipEe.ApplyRuntime(loaded.Instance.Vrm.Expression.Ee); + m_lipOh.ApplyRuntime(loaded.Instance.Vrm.Expression.Oh); + m_blink.ApplyRuntime(loaded.Instance.Vrm.Expression.Blink); + + var vrm = loaded.Instance; + if (m_enableAutoExpression.isOn) + { + vrm.Runtime.Expression.SetWeight(ExpressionKey.Happy, m_autoEmotion.Happy); + vrm.Runtime.Expression.SetWeight(ExpressionKey.Angry, m_autoEmotion.Angry); + vrm.Runtime.Expression.SetWeight(ExpressionKey.Sad, m_autoEmotion.Sad); + vrm.Runtime.Expression.SetWeight(ExpressionKey.Relaxed, m_autoEmotion.Relaxed); + vrm.Runtime.Expression.SetWeight(ExpressionKey.Surprised, m_autoEmotion.Surprised); + m_happy.m_expression.SetValueWithoutNotify(m_autoEmotion.Happy); + m_angry.m_expression.SetValueWithoutNotify(m_autoEmotion.Angry); + m_sad.m_expression.SetValueWithoutNotify(m_autoEmotion.Sad); + m_relaxed.m_expression.SetValueWithoutNotify(m_autoEmotion.Relaxed); + m_surprised.m_expression.SetValueWithoutNotify(m_autoEmotion.Surprised); + } + else + { + vrm.Runtime.Expression.SetWeight(ExpressionKey.Happy, m_happy.m_expression.value); + vrm.Runtime.Expression.SetWeight(ExpressionKey.Angry, m_angry.m_expression.value); + vrm.Runtime.Expression.SetWeight(ExpressionKey.Sad, m_sad.m_expression.value); + vrm.Runtime.Expression.SetWeight(ExpressionKey.Relaxed, m_relaxed.m_expression.value); + vrm.Runtime.Expression.SetWeight(ExpressionKey.Surprised, m_surprised.m_expression.value); + } + + if (m_enableLipSync.isOn) + { + vrm.Runtime.Expression.SetWeight(ExpressionKey.Aa, m_autoLipsync.Aa); + vrm.Runtime.Expression.SetWeight(ExpressionKey.Ih, m_autoLipsync.Ih); + vrm.Runtime.Expression.SetWeight(ExpressionKey.Ou, m_autoLipsync.Ou); + vrm.Runtime.Expression.SetWeight(ExpressionKey.Ee, m_autoLipsync.Ee); + vrm.Runtime.Expression.SetWeight(ExpressionKey.Oh, m_autoLipsync.Oh); + m_lipAa.m_expression.SetValueWithoutNotify(m_autoLipsync.Aa); + m_lipIh.m_expression.SetValueWithoutNotify(m_autoLipsync.Ih); + m_lipOu.m_expression.SetValueWithoutNotify(m_autoLipsync.Ou); + m_lipEe.m_expression.SetValueWithoutNotify(m_autoLipsync.Ee); + m_lipOh.m_expression.SetValueWithoutNotify(m_autoLipsync.Oh); + } + else + { + vrm.Runtime.Expression.SetWeight(ExpressionKey.Aa, m_lipAa.m_expression.value); + vrm.Runtime.Expression.SetWeight(ExpressionKey.Ih, m_lipIh.m_expression.value); + vrm.Runtime.Expression.SetWeight(ExpressionKey.Ou, m_lipOu.m_expression.value); + vrm.Runtime.Expression.SetWeight(ExpressionKey.Ee, m_lipEe.m_expression.value); + vrm.Runtime.Expression.SetWeight(ExpressionKey.Oh, m_lipOh.m_expression.value); + } + + if (m_enableAutoBlink.isOn) + { + vrm.Runtime.Expression.SetWeight(ExpressionKey.Blink, m_autoBlink.BlinkValue); + m_blink.m_expression.SetValueWithoutNotify(m_autoBlink.BlinkValue); + } + else + { + vrm.Runtime.Expression.SetWeight(ExpressionKey.Blink, m_blink.m_expression.value); + } + + if (m_useLookAtTarget.isOn) + { + var (yaw, pitch) = vrm.Runtime.LookAt.CalculateYawPitchFromLookAtPosition(m_lookAtTarget.transform.position); + vrm.Runtime.LookAt.SetYawPitchManually(yaw, pitch); + m_yaw.value = yaw; + m_pitch.value = pitch; + } + else + { + vrm.Runtime.LookAt.SetYawPitchManually(m_yaw.value, m_pitch.value); + } + + if (vrm.TryGetBoneTransform(HumanBodyBones.Head, out var head)) + { + var initLocarlRotation = vrm.DefaultTransformStates[head].LocalRotation; + var r = head.rotation * Quaternion.Inverse(initLocarlRotation); + var pos = head.position + + (r * Vector3.forward * 0.7f) + + (r * Vector3.up * 0.07f) + ; + m_faceCamera.position = pos; + m_faceCamera.rotation = r; } } - - if (Motion != null) - { - Motion.ShowBoxMan(m_showBoxMan.isOn); - } - - if (m_loaded != null) - { - var vrm = m_loaded.Instance; - - if (m_loaded.Runtime != null) - { - if (m_ui.IsTPose) - { - m_loaded.Runtime.VrmAnimation = TPose; - } - else if (Motion != null) - { - // Automatically retarget in Vrm10Runtime.Process - m_loaded.Runtime.VrmAnimation = Motion; - } - - m_loaded.Runtime.SpringBone.SetModelLevel(vrm.transform, new BlittableModelLevel - { - ExternalForce = new Vector3(m_springboneExternalX.value, m_springboneExternalY.value, m_springboneExternalZ.value), - StopSpringBoneWriteback = m_springbonePause.isOn, - SupportsScalingAtRuntime = m_springboneScaling.isOn, - }); - - - m_happy.ApplyRuntime(m_loaded.Instance.Vrm.Expression.Happy); - m_angry.ApplyRuntime(m_loaded.Instance.Vrm.Expression.Angry); - m_sad.ApplyRuntime(m_loaded.Instance.Vrm.Expression.Sad); - m_relaxed.ApplyRuntime(m_loaded.Instance.Vrm.Expression.Relaxed); - m_surprised.ApplyRuntime(m_loaded.Instance.Vrm.Expression.Surprised); - m_lipAa.ApplyRuntime(m_loaded.Instance.Vrm.Expression.Aa); - m_lipIh.ApplyRuntime(m_loaded.Instance.Vrm.Expression.Ih); - m_lipOu.ApplyRuntime(m_loaded.Instance.Vrm.Expression.Ou); - m_lipEe.ApplyRuntime(m_loaded.Instance.Vrm.Expression.Ee); - m_lipOh.ApplyRuntime(m_loaded.Instance.Vrm.Expression.Oh); - m_blink.ApplyRuntime(m_loaded.Instance.Vrm.Expression.Blink); - - if (m_enableAutoExpression.isOn) - { - vrm.Runtime.Expression.SetWeight(ExpressionKey.Happy, m_autoEmotion.Happy); - vrm.Runtime.Expression.SetWeight(ExpressionKey.Angry, m_autoEmotion.Angry); - vrm.Runtime.Expression.SetWeight(ExpressionKey.Sad, m_autoEmotion.Sad); - vrm.Runtime.Expression.SetWeight(ExpressionKey.Relaxed, m_autoEmotion.Relaxed); - vrm.Runtime.Expression.SetWeight(ExpressionKey.Surprised, m_autoEmotion.Surprised); - m_happy.m_expression.SetValueWithoutNotify(m_autoEmotion.Happy); - m_angry.m_expression.SetValueWithoutNotify(m_autoEmotion.Angry); - m_sad.m_expression.SetValueWithoutNotify(m_autoEmotion.Sad); - m_relaxed.m_expression.SetValueWithoutNotify(m_autoEmotion.Relaxed); - m_surprised.m_expression.SetValueWithoutNotify(m_autoEmotion.Surprised); - } - else - { - vrm.Runtime.Expression.SetWeight(ExpressionKey.Happy, m_happy.m_expression.value); - vrm.Runtime.Expression.SetWeight(ExpressionKey.Angry, m_angry.m_expression.value); - vrm.Runtime.Expression.SetWeight(ExpressionKey.Sad, m_sad.m_expression.value); - vrm.Runtime.Expression.SetWeight(ExpressionKey.Relaxed, m_relaxed.m_expression.value); - vrm.Runtime.Expression.SetWeight(ExpressionKey.Surprised, m_surprised.m_expression.value); - } - - if (m_enableLipSync.isOn) - { - vrm.Runtime.Expression.SetWeight(ExpressionKey.Aa, m_autoLipsync.Aa); - vrm.Runtime.Expression.SetWeight(ExpressionKey.Ih, m_autoLipsync.Ih); - vrm.Runtime.Expression.SetWeight(ExpressionKey.Ou, m_autoLipsync.Ou); - vrm.Runtime.Expression.SetWeight(ExpressionKey.Ee, m_autoLipsync.Ee); - vrm.Runtime.Expression.SetWeight(ExpressionKey.Oh, m_autoLipsync.Oh); - m_lipAa.m_expression.SetValueWithoutNotify(m_autoLipsync.Aa); - m_lipIh.m_expression.SetValueWithoutNotify(m_autoLipsync.Ih); - m_lipOu.m_expression.SetValueWithoutNotify(m_autoLipsync.Ou); - m_lipEe.m_expression.SetValueWithoutNotify(m_autoLipsync.Ee); - m_lipOh.m_expression.SetValueWithoutNotify(m_autoLipsync.Oh); - } - else - { - vrm.Runtime.Expression.SetWeight(ExpressionKey.Aa, m_lipAa.m_expression.value); - vrm.Runtime.Expression.SetWeight(ExpressionKey.Ih, m_lipIh.m_expression.value); - vrm.Runtime.Expression.SetWeight(ExpressionKey.Ou, m_lipOu.m_expression.value); - vrm.Runtime.Expression.SetWeight(ExpressionKey.Ee, m_lipEe.m_expression.value); - vrm.Runtime.Expression.SetWeight(ExpressionKey.Oh, m_lipOh.m_expression.value); - } - - if (m_enableAutoBlink.isOn) - { - vrm.Runtime.Expression.SetWeight(ExpressionKey.Blink, m_autoBlink.BlinkValue); - m_blink.m_expression.SetValueWithoutNotify(m_autoBlink.BlinkValue); - } - else - { - vrm.Runtime.Expression.SetWeight(ExpressionKey.Blink, m_blink.m_expression.value); - } - - if (m_useLookAtTarget.isOn) - { - var (yaw, pitch) = vrm.Runtime.LookAt.CalculateYawPitchFromLookAtPosition(m_lookAtTarget.transform.position); - vrm.Runtime.LookAt.SetYawPitchManually(yaw, pitch); - m_yaw.value = yaw; - m_pitch.value = pitch; - } - else - { - vrm.Runtime.LookAt.SetYawPitchManually(m_yaw.value, m_pitch.value); - } - - if (vrm.TryGetBoneTransform(HumanBodyBones.Head, out var head)) - { - var initLocarlRotation = vrm.DefaultTransformStates[head].LocalRotation; - var r = head.rotation * Quaternion.Inverse(initLocarlRotation); - var pos = head.position - + (r * Vector3.forward * 0.7f) - + (r * Vector3.up * 0.07f) - ; - m_faceCamera.position = pos; - m_faceCamera.rotation = r; - } - } - } - } - - [DllImport("__Internal")] - public static extern void WebGL_VRM10_VRM10Viewer_FileDialog(string target, string message); - - string FileDialog() - { -#if UNITY_EDITOR - return UnityEditor.EditorUtility.OpenFilePanel("Open VRM", "", "vrm,glb,gltf,zip"); -#elif UNITY_STANDALONE_WIN - return VRM10FileDialogForWindows.FileDialog("open VRM", "vrm", "glb", "gltf", "zip"); -#elif UNITY_WEBGL - // Open WebGL_VRM10_VRM10Viewer_FileDialog - // see: Assets/UniGLTF/Runtime/Utils/Plugins/OpenFile.jslib - WebGL_VRM10_VRM10Viewer_FileDialog("Canvas", "FileSelected"); - // Control flow does not return here. return empty string with dummy - return null; -#else - return Application.dataPath + "/default.vrm"; -#endif - } - - void OnOpenModelClicked() - { - var path = FileDialog(); - _ = LoadModelPath(path); } /// @@ -712,212 +664,7 @@ namespace UniVRM10.VRM10Viewer public void FileSelected(string url) { UniGLTFLogger.Log($"FileSelected: {url}"); - StartCoroutine(LoadCoroutine(url)); - } - - IEnumerator LoadCoroutine(string url) - { - var www = new WWW(url); - yield return www; - var _ = LoadModelBytes("WebGL.vrm", www.bytes); - } - - async void OnOpenMotionClicked() - { -#if UNITY_EDITOR - var path = UnityEditor.EditorUtility.OpenFilePanel("Open Motion", "", "bvh,gltf,glb,vrma"); -#elif UNITY_STANDALONE_WIN - var path = VRM10FileDialogForWindows.FileDialog("open Motion", "bvh", "gltf", "glb", "vrma"); -#else - var path = Application.dataPath + "/default.bvh"; -#endif - if (string.IsNullOrEmpty(path)) - { - return; - } - - var ext = Path.GetExtension(path).ToLower(); - if (ext == ".bvh") - { - Motion = BvhMotion.LoadBvhFromPath(path); - return; - } - - // gltf, glb etc... - using GltfData data = new AutoGltfFileParser(path).Parse(); - using var loader = new VrmAnimationImporter(data); - var instance = await loader.LoadAsync(new ImmediateCaller()); - Motion = instance.GetComponent(); - instance.GetComponent().Play(); - } - - async void OnPastePoseClicked() - { - var text = GUIUtility.systemCopyBuffer; - if (string.IsNullOrEmpty(text)) - { - return; - } - - try - { - Motion = await Vrm10PoseLoader.LoadVrmAnimationPose(text); - } - catch (UniJSON.ParserException) - { - UniGLTFLogger.Warning("UniJSON.ParserException"); - } - catch (UniJSON.DeserializationException) - { - UniGLTFLogger.Warning("UniJSON.DeserializationException"); - } - } - - void OnResetSpringBoneClicked() - { - if (m_loaded != null) - { - if (m_loaded.Runtime != null) - { - m_loaded.Runtime.SpringBone.RestoreInitialTransform(); - } - } - } - - void OnReconstructSpringBoneClicked() - { - if (m_loaded != null) - { - if (m_loaded.Runtime != null) - { - m_loaded.Runtime.SpringBone.ReconstructSpringBone(); - } - } - } - - IMaterialDescriptorGenerator GetMaterialDescriptorGenerator() - { - var useCustomPbr = m_useCustomPbrMaterial.isOn && m_pbrImporter != null; - var useCustomMToon = m_useCustomMToonMaterial.isOn && m_mtoonImporter != null; - if (!useCustomPbr && !useCustomMToon) - { - // カスタムしない。デフォルトのローダーを使う - return default; - } - - return OrderedMaterialDescriptorGenerator.CreateCustomGenerator( - useCustomPbr ? m_pbrImporter : null, - useCustomMToon ? m_mtoonImporter : null); - } - - IAwaitCaller GetIAwaitCaller() - { - if (m_useAsync.isOn) - { - if (Application.platform == RuntimePlatform.WebGLPlayer) - { - return new RuntimeOnlyNoThreadAwaitCaller(); - } - else - { - return new RuntimeOnlyAwaitCaller(); - } - } - else - { - return new ImmediateCaller(); - } - } - - async Task LoadModelPath(string path) - { - var bytes = await File.ReadAllBytesAsync(path); - await LoadModelBytes(path, bytes); - } - - async Task LoadModelBytes(string path, byte[] bytes) - { - // cleanup - m_loaded?.Dispose(); - m_loaded = null; - _cancellationTokenSource?.Dispose(); - _cancellationTokenSource = new CancellationTokenSource(); - var cancellationToken = _cancellationTokenSource.Token; - - try - { - // - // try VRM - // - UniGLTFLogger.Log($"{path}"); - var vrm10Instance = await Vrm10.LoadBytesAsync(bytes, - canLoadVrm0X: true, - showMeshes: false, - awaitCaller: GetIAwaitCaller(), - materialGenerator: GetMaterialDescriptorGenerator(), - vrmMetaInformationCallback: m_texts.UpdateMeta, - ct: cancellationToken, - springboneRuntime: m_useSpringboneSingelton.isOn ? new Vrm10FastSpringboneRuntime() : new Vrm10FastSpringboneRuntimeStandalone()); - if (cancellationToken.IsCancellationRequested) - { - UnityObjectDestroyer.DestroyRuntimeOrEditor(vrm10Instance.gameObject); - cancellationToken.ThrowIfCancellationRequested(); - } - - if (vrm10Instance == null) - { - UniGLTFLogger.Warning("LoadPathAsync is null"); - return; - } - - var instance = vrm10Instance.GetComponent(); - instance.ShowMeshes(); - instance.EnableUpdateWhenOffscreen(); - m_loaded = new Loaded(instance); - m_showBoxMan.isOn = false; - - m_happy.OnLoad(m_loaded.Instance.Vrm.Expression.Happy); - m_angry.OnLoad(m_loaded.Instance.Vrm.Expression.Angry); - m_sad.OnLoad(m_loaded.Instance.Vrm.Expression.Sad); - m_relaxed.OnLoad(m_loaded.Instance.Vrm.Expression.Relaxed); - m_surprised.OnLoad(m_loaded.Instance.Vrm.Expression.Surprised); - m_lipAa.OnLoad(m_loaded.Instance.Vrm.Expression.Aa); - m_lipIh.OnLoad(m_loaded.Instance.Vrm.Expression.Ih); - m_lipOu.OnLoad(m_loaded.Instance.Vrm.Expression.Ou); - m_lipEe.OnLoad(m_loaded.Instance.Vrm.Expression.Ee); - m_lipOh.OnLoad(m_loaded.Instance.Vrm.Expression.Oh); - m_blink.OnLoad(m_loaded.Instance.Vrm.Expression.Blink); - } - catch (Exception) - { - try - { - // - // fallback gltf - // - var instance = await GltfUtility.LoadBytesAsync(path, bytes, - awaitCaller: GetIAwaitCaller(), - materialGenerator: GetMaterialDescriptorGenerator() - ); - - instance.ShowMeshes(); - instance.EnableUpdateWhenOffscreen(); - m_loaded = new Loaded(instance); - m_showBoxMan.isOn = false; - } - catch (Exception ex) - { - if (ex is OperationCanceledException) - { - UniGLTFLogger.Warning($"Canceled to Load: {path}"); - } - else - { - UniGLTFLogger.Error($"Failed to Load: {path}"); - UniGLTFLogger.Exception(ex); - } - } - } + StartCoroutine(m_controller.LoadCoroutine(url, MakeLoadOptions())); } } -} +} \ No newline at end of file