diff --git a/Packages/net.fushizen.modular-avatar/Editor/AnimatorMerger.cs b/Packages/net.fushizen.modular-avatar/Editor/AnimatorMerger.cs index 0f6baa57..f3f3488a 100644 --- a/Packages/net.fushizen.modular-avatar/Editor/AnimatorMerger.cs +++ b/Packages/net.fushizen.modular-avatar/Editor/AnimatorMerger.cs @@ -37,7 +37,7 @@ namespace net.fushizen.modular_avatar.core.editor private readonly AnimatorController _combined; private List _layers = new List(); - + private Dictionary _parameters = new Dictionary(); @@ -49,7 +49,7 @@ namespace net.fushizen.modular_avatar.core.editor public AnimatorCombiner() { - _combined = Util.CreateContainer(); + _combined = Util.CreateAnimator(); } public AnimatorController Finish() @@ -67,12 +67,13 @@ namespace net.fushizen.modular_avatar.core.editor { if (acp.type != param.type) { - throw new Exception($"Parameter {param.name} has different types in {basePath} and {controller.name}"); + throw new Exception( + $"Parameter {param.name} has different types in {basePath} and {controller.name}"); } continue; } - + _parameters.Add(param.name, param); } @@ -109,7 +110,7 @@ namespace net.fushizen.modular_avatar.core.editor { return asm; } - + asm = deepClone(layerStateMachine, (obj) => customClone(obj, basePath)); _stateMachines[cacheKey] = asm; @@ -127,11 +128,11 @@ namespace net.fushizen.modular_avatar.core.editor return PathMappings.MapPath(basePath + binding.path, binding.type == typeof(Transform)); } } - + private Object customClone(Object o, string basePath) { if (basePath == "") return null; - + if (o is AnimationClip clip) { AnimationClip newClip = new AnimationClip(); @@ -145,7 +146,7 @@ namespace net.fushizen.modular_avatar.core.editor newClip.SetCurve(newBinding.path, newBinding.type, newBinding.propertyName, AnimationUtility.GetEditorCurve(clip, binding)); } - + foreach (var objBinding in AnimationUtility.GetObjectReferenceCurveBindings(clip)) { var newBinding = objBinding; @@ -161,7 +162,8 @@ namespace net.fushizen.modular_avatar.core.editor AnimationUtility.SetAnimationClipSettings(newClip, AnimationUtility.GetAnimationClipSettings(clip)); return newClip; - } else if (o is Texture) + } + else if (o is Texture) { return o; } @@ -174,12 +176,12 @@ namespace net.fushizen.modular_avatar.core.editor private T deepClone(T original, Func visitor, Dictionary cloneMap = null - ) where T : Object + ) where T : Object { if (original == null) return null; - + if (cloneMap == null) cloneMap = new Dictionary(); - + if (cloneMap.ContainsKey(original)) { return (T) cloneMap[original]; @@ -195,13 +197,14 @@ namespace net.fushizen.modular_avatar.core.editor var ctor = original.GetType().GetConstructor(Type.EmptyTypes); if (ctor == null || original is ScriptableObject) { - obj = Object.Instantiate(original); + obj = Object.Instantiate(original); } else { obj = (T) ctor.Invoke(Array.Empty()); EditorUtility.CopySerialized(original, obj); } + cloneMap[original] = obj; AssetDatabase.AddObjectToAsset(obj, _combined); diff --git a/Packages/net.fushizen.modular-avatar/Editor/AvatarProcessor.cs b/Packages/net.fushizen.modular-avatar/Editor/AvatarProcessor.cs index 1a2f2d02..bd9e40cf 100644 --- a/Packages/net.fushizen.modular-avatar/Editor/AvatarProcessor.cs +++ b/Packages/net.fushizen.modular-avatar/Editor/AvatarProcessor.cs @@ -23,22 +23,24 @@ */ using System; -using System.Reflection; using UnityEditor; using UnityEngine; -using VRC.SDK3.Avatars.Components; using VRC.SDKBase.Editor.BuildPipeline; namespace net.fushizen.modular_avatar.core.editor { [InitializeOnLoad] - internal class AvatarProcessor : IVRCSDKPreprocessAvatarCallback, IVRCSDKPostprocessAvatarCallback + public class AvatarProcessor : IVRCSDKPreprocessAvatarCallback, IVRCSDKPostprocessAvatarCallback { + public delegate void AvatarProcessorCallback(GameObject obj); + + public static event AvatarProcessorCallback AfterProcessing; + static AvatarProcessor() { EditorApplication.playModeStateChanged += OnPlayModeStateChanged; } - + private static void OnPlayModeStateChanged(PlayModeStateChange obj) { if (obj == PlayModeStateChange.EnteredEditMode) @@ -48,7 +50,7 @@ namespace net.fushizen.modular_avatar.core.editor } public int callbackOrder => -9000; - + public void OnPostprocessAvatar() { Util.DeleteTemporaryAssets(); @@ -77,11 +79,13 @@ namespace net.fushizen.modular_avatar.core.editor new RetargetMeshes().OnPreprocessAvatar(avatarGameObject); new BoneProxyProcessor().OnPreprocessAvatar(avatarGameObject); new MergeAnimatorProcessor().OnPreprocessAvatar(avatarGameObject); - + foreach (var component in avatarGameObject.GetComponentsInChildren(true)) { UnityEngine.Object.DestroyImmediate(component); } + + AfterProcessing?.Invoke(avatarGameObject); } } } \ No newline at end of file diff --git a/Packages/net.fushizen.modular-avatar/Editor/Util.cs b/Packages/net.fushizen.modular-avatar/Editor/Util.cs index ff6813f5..031e59ee 100644 --- a/Packages/net.fushizen.modular-avatar/Editor/Util.cs +++ b/Packages/net.fushizen.modular-avatar/Editor/Util.cs @@ -24,6 +24,7 @@ using UnityEditor; using UnityEditor.Animations; +using UnityEngine; using VRC.SDKBase.Editor.BuildPipeline; namespace net.fushizen.modular_avatar.core.editor @@ -31,37 +32,46 @@ namespace net.fushizen.modular_avatar.core.editor internal class CleanupTempAssets : IVRCSDKPostprocessAvatarCallback { public int callbackOrder => 99999; + public void OnPostprocessAvatar() { Util.DeleteTemporaryAssets(); } } - + [InitializeOnLoad] public static class Util { - internal const string generatedAssetsSubdirectory = "999_Modular_Avatar_Generated"; - internal const string generatedAssetsPath = "Assets/" + generatedAssetsSubdirectory; + private const string generatedAssetsSubdirectory = "999_Modular_Avatar_Generated"; + private const string generatedAssetsPath = "Assets/" + generatedAssetsSubdirectory; static Util() { RuntimeUtil.delayCall = (cb) => EditorApplication.delayCall += cb.Invoke; } - static internal AnimatorController CreateContainer() + public static AnimatorController CreateAnimator(AnimatorController toClone = null) { - var container = new AnimatorController(); - AssetDatabase.CreateAsset(container, GenerateAssetPath()); + AnimatorController controller; + if (toClone != null) + { + controller = Object.Instantiate(toClone); + } + else + { + controller = new AnimatorController(); + } + AssetDatabase.CreateAsset(controller, GenerateAssetPath()); - return container; + return controller; } - internal static string GenerateAssetPath() + public static string GenerateAssetPath() { return GetGeneratedAssetsFolder() + "/" + GUID.Generate() + ".asset"; } - internal static string GetGeneratedAssetsFolder() + private static string GetGeneratedAssetsFolder() { if (!AssetDatabase.IsValidFolder(generatedAssetsPath)) { @@ -71,12 +81,12 @@ namespace net.fushizen.modular_avatar.core.editor return generatedAssetsPath; } - static internal void DeleteTemporaryAssets() + internal static void DeleteTemporaryAssets() { EditorApplication.delayCall += () => { AssetDatabase.SaveAssets(); - + var subdir = generatedAssetsPath; AssetDatabase.DeleteAsset(subdir);