Adding some hooks for xdress benefit

This commit is contained in:
bd_ 2022-09-11 15:30:57 -07:00 committed by bd_
parent d96ee7a718
commit 441865cd22
3 changed files with 47 additions and 30 deletions

View File

@ -37,7 +37,7 @@ namespace net.fushizen.modular_avatar.core.editor
private readonly AnimatorController _combined; private readonly AnimatorController _combined;
private List<AnimatorControllerLayer> _layers = new List<AnimatorControllerLayer>(); private List<AnimatorControllerLayer> _layers = new List<AnimatorControllerLayer>();
private Dictionary<String, AnimatorControllerParameter> _parameters = private Dictionary<String, AnimatorControllerParameter> _parameters =
new Dictionary<string, AnimatorControllerParameter>(); new Dictionary<string, AnimatorControllerParameter>();
@ -49,7 +49,7 @@ namespace net.fushizen.modular_avatar.core.editor
public AnimatorCombiner() public AnimatorCombiner()
{ {
_combined = Util.CreateContainer(); _combined = Util.CreateAnimator();
} }
public AnimatorController Finish() public AnimatorController Finish()
@ -67,12 +67,13 @@ namespace net.fushizen.modular_avatar.core.editor
{ {
if (acp.type != param.type) 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; continue;
} }
_parameters.Add(param.name, param); _parameters.Add(param.name, param);
} }
@ -109,7 +110,7 @@ namespace net.fushizen.modular_avatar.core.editor
{ {
return asm; return asm;
} }
asm = deepClone(layerStateMachine, (obj) => customClone(obj, basePath)); asm = deepClone(layerStateMachine, (obj) => customClone(obj, basePath));
_stateMachines[cacheKey] = asm; _stateMachines[cacheKey] = asm;
@ -127,11 +128,11 @@ namespace net.fushizen.modular_avatar.core.editor
return PathMappings.MapPath(basePath + binding.path, binding.type == typeof(Transform)); return PathMappings.MapPath(basePath + binding.path, binding.type == typeof(Transform));
} }
} }
private Object customClone(Object o, string basePath) private Object customClone(Object o, string basePath)
{ {
if (basePath == "") return null; if (basePath == "") return null;
if (o is AnimationClip clip) if (o is AnimationClip clip)
{ {
AnimationClip newClip = new AnimationClip(); AnimationClip newClip = new AnimationClip();
@ -145,7 +146,7 @@ namespace net.fushizen.modular_avatar.core.editor
newClip.SetCurve(newBinding.path, newBinding.type, newBinding.propertyName, newClip.SetCurve(newBinding.path, newBinding.type, newBinding.propertyName,
AnimationUtility.GetEditorCurve(clip, binding)); AnimationUtility.GetEditorCurve(clip, binding));
} }
foreach (var objBinding in AnimationUtility.GetObjectReferenceCurveBindings(clip)) foreach (var objBinding in AnimationUtility.GetObjectReferenceCurveBindings(clip))
{ {
var newBinding = objBinding; var newBinding = objBinding;
@ -161,7 +162,8 @@ namespace net.fushizen.modular_avatar.core.editor
AnimationUtility.SetAnimationClipSettings(newClip, AnimationUtility.GetAnimationClipSettings(clip)); AnimationUtility.SetAnimationClipSettings(newClip, AnimationUtility.GetAnimationClipSettings(clip));
return newClip; return newClip;
} else if (o is Texture) }
else if (o is Texture)
{ {
return o; return o;
} }
@ -174,12 +176,12 @@ namespace net.fushizen.modular_avatar.core.editor
private T deepClone<T>(T original, private T deepClone<T>(T original,
Func<Object, Object> visitor, Func<Object, Object> visitor,
Dictionary<Object, Object> cloneMap = null Dictionary<Object, Object> cloneMap = null
) where T : Object ) where T : Object
{ {
if (original == null) return null; if (original == null) return null;
if (cloneMap == null) cloneMap = new Dictionary<Object, Object>(); if (cloneMap == null) cloneMap = new Dictionary<Object, Object>();
if (cloneMap.ContainsKey(original)) if (cloneMap.ContainsKey(original))
{ {
return (T) cloneMap[original]; return (T) cloneMap[original];
@ -195,13 +197,14 @@ namespace net.fushizen.modular_avatar.core.editor
var ctor = original.GetType().GetConstructor(Type.EmptyTypes); var ctor = original.GetType().GetConstructor(Type.EmptyTypes);
if (ctor == null || original is ScriptableObject) if (ctor == null || original is ScriptableObject)
{ {
obj = Object.Instantiate(original); obj = Object.Instantiate(original);
} }
else else
{ {
obj = (T) ctor.Invoke(Array.Empty<object>()); obj = (T) ctor.Invoke(Array.Empty<object>());
EditorUtility.CopySerialized(original, obj); EditorUtility.CopySerialized(original, obj);
} }
cloneMap[original] = obj; cloneMap[original] = obj;
AssetDatabase.AddObjectToAsset(obj, _combined); AssetDatabase.AddObjectToAsset(obj, _combined);

View File

@ -23,22 +23,24 @@
*/ */
using System; using System;
using System.Reflection;
using UnityEditor; using UnityEditor;
using UnityEngine; using UnityEngine;
using VRC.SDK3.Avatars.Components;
using VRC.SDKBase.Editor.BuildPipeline; using VRC.SDKBase.Editor.BuildPipeline;
namespace net.fushizen.modular_avatar.core.editor namespace net.fushizen.modular_avatar.core.editor
{ {
[InitializeOnLoad] [InitializeOnLoad]
internal class AvatarProcessor : IVRCSDKPreprocessAvatarCallback, IVRCSDKPostprocessAvatarCallback public class AvatarProcessor : IVRCSDKPreprocessAvatarCallback, IVRCSDKPostprocessAvatarCallback
{ {
public delegate void AvatarProcessorCallback(GameObject obj);
public static event AvatarProcessorCallback AfterProcessing;
static AvatarProcessor() static AvatarProcessor()
{ {
EditorApplication.playModeStateChanged += OnPlayModeStateChanged; EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
} }
private static void OnPlayModeStateChanged(PlayModeStateChange obj) private static void OnPlayModeStateChanged(PlayModeStateChange obj)
{ {
if (obj == PlayModeStateChange.EnteredEditMode) if (obj == PlayModeStateChange.EnteredEditMode)
@ -48,7 +50,7 @@ namespace net.fushizen.modular_avatar.core.editor
} }
public int callbackOrder => -9000; public int callbackOrder => -9000;
public void OnPostprocessAvatar() public void OnPostprocessAvatar()
{ {
Util.DeleteTemporaryAssets(); Util.DeleteTemporaryAssets();
@ -77,11 +79,13 @@ namespace net.fushizen.modular_avatar.core.editor
new RetargetMeshes().OnPreprocessAvatar(avatarGameObject); new RetargetMeshes().OnPreprocessAvatar(avatarGameObject);
new BoneProxyProcessor().OnPreprocessAvatar(avatarGameObject); new BoneProxyProcessor().OnPreprocessAvatar(avatarGameObject);
new MergeAnimatorProcessor().OnPreprocessAvatar(avatarGameObject); new MergeAnimatorProcessor().OnPreprocessAvatar(avatarGameObject);
foreach (var component in avatarGameObject.GetComponentsInChildren<AvatarTagComponent>(true)) foreach (var component in avatarGameObject.GetComponentsInChildren<AvatarTagComponent>(true))
{ {
UnityEngine.Object.DestroyImmediate(component); UnityEngine.Object.DestroyImmediate(component);
} }
AfterProcessing?.Invoke(avatarGameObject);
} }
} }
} }

View File

@ -24,6 +24,7 @@
using UnityEditor; using UnityEditor;
using UnityEditor.Animations; using UnityEditor.Animations;
using UnityEngine;
using VRC.SDKBase.Editor.BuildPipeline; using VRC.SDKBase.Editor.BuildPipeline;
namespace net.fushizen.modular_avatar.core.editor namespace net.fushizen.modular_avatar.core.editor
@ -31,37 +32,46 @@ namespace net.fushizen.modular_avatar.core.editor
internal class CleanupTempAssets : IVRCSDKPostprocessAvatarCallback internal class CleanupTempAssets : IVRCSDKPostprocessAvatarCallback
{ {
public int callbackOrder => 99999; public int callbackOrder => 99999;
public void OnPostprocessAvatar() public void OnPostprocessAvatar()
{ {
Util.DeleteTemporaryAssets(); Util.DeleteTemporaryAssets();
} }
} }
[InitializeOnLoad] [InitializeOnLoad]
public static class Util public static class Util
{ {
internal const string generatedAssetsSubdirectory = "999_Modular_Avatar_Generated"; private const string generatedAssetsSubdirectory = "999_Modular_Avatar_Generated";
internal const string generatedAssetsPath = "Assets/" + generatedAssetsSubdirectory; private const string generatedAssetsPath = "Assets/" + generatedAssetsSubdirectory;
static Util() static Util()
{ {
RuntimeUtil.delayCall = (cb) => EditorApplication.delayCall += cb.Invoke; RuntimeUtil.delayCall = (cb) => EditorApplication.delayCall += cb.Invoke;
} }
static internal AnimatorController CreateContainer() public static AnimatorController CreateAnimator(AnimatorController toClone = null)
{ {
var container = new AnimatorController(); AnimatorController controller;
AssetDatabase.CreateAsset(container, GenerateAssetPath()); 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"; return GetGeneratedAssetsFolder() + "/" + GUID.Generate() + ".asset";
} }
internal static string GetGeneratedAssetsFolder() private static string GetGeneratedAssetsFolder()
{ {
if (!AssetDatabase.IsValidFolder(generatedAssetsPath)) if (!AssetDatabase.IsValidFolder(generatedAssetsPath))
{ {
@ -71,12 +81,12 @@ namespace net.fushizen.modular_avatar.core.editor
return generatedAssetsPath; return generatedAssetsPath;
} }
static internal void DeleteTemporaryAssets() internal static void DeleteTemporaryAssets()
{ {
EditorApplication.delayCall += () => EditorApplication.delayCall += () =>
{ {
AssetDatabase.SaveAssets(); AssetDatabase.SaveAssets();
var subdir = generatedAssetsPath; var subdir = generatedAssetsPath;
AssetDatabase.DeleteAsset(subdir); AssetDatabase.DeleteAsset(subdir);