From 7c0feb1b67ff253c9a49baae347ec1599e5c6f45 Mon Sep 17 00:00:00 2001 From: suzuryg <77635213+suzuryg@users.noreply.github.com> Date: Fri, 25 Aug 2023 02:52:16 +0900 Subject: [PATCH] fix: Fix to ensure upload doesn't interrupt if TrackingControlDisabler execution fails (#25) --- .../Components/MA/TrackingControlDisabler.cs | 70 +++++++++++++++++-- 1 file changed, 66 insertions(+), 4 deletions(-) diff --git a/Packages/jp.suzuryg.face-emo/Runtime/Components/MA/TrackingControlDisabler.cs b/Packages/jp.suzuryg.face-emo/Runtime/Components/MA/TrackingControlDisabler.cs index 2be54be1..9e337902 100644 --- a/Packages/jp.suzuryg.face-emo/Runtime/Components/MA/TrackingControlDisabler.cs +++ b/Packages/jp.suzuryg.face-emo/Runtime/Components/MA/TrackingControlDisabler.cs @@ -1,5 +1,7 @@ using Suzuryg.FaceEmo.Domain; using System.Collections.Generic; +using System.Globalization; +using System.Linq; using UnityEngine; using VRC.SDK3.Avatars.Components; using VRC.SDKBase; @@ -15,7 +17,8 @@ namespace Suzuryg.FaceEmo.Components.MA public class TrackingControlDisabler : RunBeforeModularAvatar { // TODO: Is asset creation needed? - private static readonly string DestinationPath = $"Assets/Suzuryg/{DomainConstants.SystemName}/Generated/TrackingControlDisabled.controller"; + private static readonly string DestinationDir = $"Assets/Suzuryg/{DomainConstants.SystemName}/Generated"; + private static readonly string DestinationPath = DestinationDir + "/TrackingControlDisabled.controller"; public override void OnPreProcessAvatar() { @@ -45,11 +48,12 @@ public override void OnPreProcessAvatar() // TODO: Is asset creation needed? // VRC_AnimatorTrackingControl is not references to the AnimatorController but values held in the AnimatorController, // so if the AnimatorController is copied, changing the destination asset will not affect the original AnimatorController. + if (!AssetDatabase.IsValidFolder(DestinationDir)) + { CreateFolder(); } + var originalPath = AssetDatabase.GetAssetPath(originalFxController); if (!AssetDatabase.CopyAsset(originalPath, DestinationPath)) // TODO: Suppress warnings (missing script) - { - throw new FaceEmoException("Faild to clone Fx controller."); - } + { ShowErrorMessage(originalPath); } var clonedFxController = AssetDatabase.LoadAssetAtPath(DestinationPath); // Disable tracking controls @@ -63,6 +67,39 @@ public override void OnPreProcessAvatar() } #if UNITY_EDITOR + private static void CreateFolder() + { + CreateFolderRecursively(DestinationDir); + if (AssetDatabase.IsValidFolder(DestinationDir)) + { + Debug.Log("Folder created: " + DestinationDir); + } + else + { + Debug.LogError("Failed to create folder: " + DestinationDir); + } + } + + private static void ShowErrorMessage(string originalPath) + { + string errorMessage = string.Empty; + var currentCulture = CultureInfo.CurrentCulture; + if (currentCulture.Name == "ja-JP") + { + errorMessage += "VRC Animator Tracing Controlの無効化に失敗しました。\n" + + "表情が正しく動かない場合、元々のアバターのFXレイヤーから表情操作のレイヤーを削除してください。\n" + + "レイヤーを削除する際は、作業の前に必ずバックアップを作成してください。"; + } + else + { + errorMessage += "Failed to disable VRC Animator Tracing Control.\n" + + "If the facial expressions do not work correctly, please delete the facial expression control layers from the original avatar's FX layer.\n" + + "Be sure to make a backup before deleting the layer."; + } + errorMessage += $"\n\n{originalPath} -> {DestinationPath}"; + EditorUtility.DisplayDialog(DomainConstants.SystemName, errorMessage, "OK"); + } + private static void DisableTrackingControlRecursively(AnimatorStateMachine animatorStateMachine) { foreach (var childStateMachine in animatorStateMachine.stateMachines) @@ -88,6 +125,31 @@ private static void DisableTrackingControlRecursively(AnimatorStateMachine anima } } } + + // https://hacchi-man.hatenablog.com/entry/2020/08/23/220000 + private static void CreateFolderRecursively(string path) + { + // If it doesn't start with Assets, it can't be processed. + if (!path.StartsWith("Assets/")) + { + return; + } + + // AssetDatabase, so the delimiter is /. + var dirs = path.Split('/'); + var combinePath = dirs[0]; + + // Skip the Assets part. + foreach (var dir in dirs.Skip(1)) + { + // Check existence of directory + if (!AssetDatabase.IsValidFolder(combinePath + '/' + dir)) + { + AssetDatabase.CreateFolder(combinePath, dir); + } + combinePath += '/' + dir; + } + } #endif } }