mirror of
https://github.com/bdunderscore/modular-avatar.git
synced 2025-02-01 19:22:55 +08:00
Adding some hooks for xdress benefit
This commit is contained in:
parent
d96ee7a718
commit
441865cd22
@ -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);
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user