mirror of
https://github.com/bdunderscore/modular-avatar.git
synced 2025-04-11 23:19:00 +08:00
refactor: use IVirtualize*
This commit is contained in:
parent
e3a01ff58b
commit
e91b8ab6c3
@ -27,6 +27,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using nadena.dev.ndmf.animator;
|
using nadena.dev.ndmf.animator;
|
||||||
|
using UnityEditor;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using VRC.SDK3.Avatars.Components;
|
using VRC.SDK3.Avatars.Components;
|
||||||
using Object = UnityEngine.Object;
|
using Object = UnityEngine.Object;
|
||||||
@ -37,6 +38,23 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
{
|
{
|
||||||
private AnimatorServicesContext _asc;
|
private AnimatorServicesContext _asc;
|
||||||
|
|
||||||
|
[InitializeOnLoadMethod]
|
||||||
|
private static void Init()
|
||||||
|
{
|
||||||
|
ModularAvatarMergeAnimator.GetMotionBasePathCallback = (merge, objectBuildContext) =>
|
||||||
|
{
|
||||||
|
if (merge.pathMode == MergeAnimatorPathMode.Absolute) return "";
|
||||||
|
|
||||||
|
var context = (ndmf.BuildContext)objectBuildContext;
|
||||||
|
|
||||||
|
var targetObject = merge.relativePathRoot.Get(context.AvatarRootTransform);
|
||||||
|
if (targetObject == null) targetObject = merge.gameObject;
|
||||||
|
|
||||||
|
var relativePath = RuntimeUtil.RelativePath(context.AvatarRootObject, targetObject);
|
||||||
|
return relativePath != "" ? relativePath : "";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
internal void OnPreprocessAvatar(GameObject avatarGameObject, BuildContext context)
|
internal void OnPreprocessAvatar(GameObject avatarGameObject, BuildContext context)
|
||||||
{
|
{
|
||||||
_asc = context.PluginBuildContext.Extension<AnimatorServicesContext>();
|
_asc = context.PluginBuildContext.Extension<AnimatorServicesContext>();
|
||||||
@ -92,35 +110,18 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void MergeSingle(BuildContext context, VirtualAnimatorController controller, ModularAvatarMergeAnimator merge, bool? initialWriteDefaults)
|
private void MergeSingle(BuildContext context, VirtualAnimatorController targetController,
|
||||||
|
ModularAvatarMergeAnimator merge, bool? initialWriteDefaults)
|
||||||
{
|
{
|
||||||
if (merge.animator == null)
|
if (merge.animator == null)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var stash = context.PluginBuildContext.GetState<RenamedMergeAnimators>();
|
|
||||||
|
|
||||||
var clonedController = stash.Controllers.GetValueOrDefault(merge)
|
|
||||||
?? _asc.ControllerContext.CloneContext.CloneDistinct(merge.animator);
|
|
||||||
|
|
||||||
string basePath;
|
|
||||||
if (merge.pathMode == MergeAnimatorPathMode.Relative)
|
|
||||||
{
|
|
||||||
var targetObject = merge.relativePathRoot.Get(context.AvatarRootTransform);
|
|
||||||
if (targetObject == null) targetObject = merge.gameObject;
|
|
||||||
|
|
||||||
var relativePath = RuntimeUtil.RelativePath(context.AvatarRootObject, targetObject);
|
var vac = context.PluginBuildContext.Extension<VirtualControllerContext>();
|
||||||
basePath = relativePath != "" ? relativePath + "/" : "";
|
|
||||||
|
|
||||||
var animationIndex = new AnimationIndex(new[] { clonedController });
|
|
||||||
animationIndex.RewritePaths(p => p == "" ? relativePath : basePath + p);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
basePath = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (!vac.Controllers.TryGetValue(merge, out var clonedController)) return;
|
||||||
|
|
||||||
var firstLayer = clonedController.Layers.FirstOrDefault();
|
var firstLayer = clonedController.Layers.FirstOrDefault();
|
||||||
// the first layer in an animator controller always has weight 1.0f (regardless of what is serialized)
|
// the first layer in an animator controller always has weight 1.0f (regardless of what is serialized)
|
||||||
if (firstLayer != null) firstLayer.DefaultWeight = 1.0f;
|
if (firstLayer != null) firstLayer.DefaultWeight = 1.0f;
|
||||||
@ -134,12 +135,13 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
s.WriteDefaultValues = initialWriteDefaults.Value;
|
s.WriteDefaultValues = initialWriteDefaults.Value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
controller.AddLayer(new LayerPriority(merge.layerPriority), l);
|
|
||||||
|
targetController.AddLayer(new LayerPriority(merge.layerPriority), l);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var (name, parameter) in clonedController.Parameters)
|
foreach (var (name, parameter) in clonedController.Parameters)
|
||||||
{
|
{
|
||||||
if (controller.Parameters.TryGetValue(name, out var existingParam))
|
if (targetController.Parameters.TryGetValue(name, out var existingParam))
|
||||||
{
|
{
|
||||||
if (existingParam.type != parameter.type)
|
if (existingParam.type != parameter.type)
|
||||||
{
|
{
|
||||||
@ -156,12 +158,12 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
|
|
||||||
existingParam.type = AnimatorControllerParameterType.Float;
|
existingParam.type = AnimatorControllerParameterType.Float;
|
||||||
|
|
||||||
controller.Parameters = controller.Parameters.SetItem(name, existingParam);
|
targetController.Parameters = targetController.Parameters.SetItem(name, existingParam);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
controller.Parameters = controller.Parameters.Add(name, parameter);
|
targetController.Parameters = targetController.Parameters.Add(name, parameter);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (merge.deleteAttachedAnimator)
|
if (merge.deleteAttachedAnimator)
|
||||||
@ -169,6 +171,8 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
var animator = merge.GetComponent<Animator>();
|
var animator = merge.GetComponent<Animator>();
|
||||||
if (animator != null) Object.DestroyImmediate(animator);
|
if (animator != null) Object.DestroyImmediate(animator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Object.DestroyImmediate(merge);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using nadena.dev.ndmf;
|
using nadena.dev.ndmf;
|
||||||
using nadena.dev.ndmf.animator;
|
using nadena.dev.ndmf.animator;
|
||||||
|
using UnityEditor;
|
||||||
using UnityEditor.Animations;
|
using UnityEditor.Animations;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using VRC.SDK3.Avatars.Components;
|
using VRC.SDK3.Avatars.Components;
|
||||||
@ -22,6 +23,21 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
private VirtualBlendTree _rootBlendTree;
|
private VirtualBlendTree _rootBlendTree;
|
||||||
private HashSet<string> _parameterNames;
|
private HashSet<string> _parameterNames;
|
||||||
|
|
||||||
|
[InitializeOnLoadMethod]
|
||||||
|
private static void Init()
|
||||||
|
{
|
||||||
|
ModularAvatarMergeBlendTree.GetMotionBasePathCallback = (mbt, objectBuildContext) =>
|
||||||
|
{
|
||||||
|
if (mbt.PathMode == MergeAnimatorPathMode.Absolute) return "";
|
||||||
|
|
||||||
|
var buildContext = (ndmf.BuildContext)objectBuildContext;
|
||||||
|
var root = mbt.RelativePathRoot.Get(buildContext.AvatarRootTransform);
|
||||||
|
if (root == null) root = mbt.gameObject;
|
||||||
|
|
||||||
|
return RuntimeUtil.AvatarRootPath(root);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
protected override void Execute(ndmf.BuildContext context)
|
protected override void Execute(ndmf.BuildContext context)
|
||||||
{
|
{
|
||||||
_asc = context.Extension<AnimatorServicesContext>();
|
_asc = context.Extension<AnimatorServicesContext>();
|
||||||
@ -59,48 +75,28 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
|
|
||||||
private void ProcessComponent(BuildContext context, ModularAvatarMergeBlendTree component)
|
private void ProcessComponent(BuildContext context, ModularAvatarMergeBlendTree component)
|
||||||
{
|
{
|
||||||
var stash = context.PluginBuildContext.GetState<RenamedMergeAnimators>();
|
var virtualBlendTree = _asc.ControllerContext.GetVirtualizedMotion(component);
|
||||||
|
|
||||||
BlendTree componentBlendTree = component.BlendTree as BlendTree;
|
if (virtualBlendTree == null)
|
||||||
|
|
||||||
if (componentBlendTree == null)
|
|
||||||
{
|
{
|
||||||
ErrorReport.ReportError(Localization.L, ErrorSeverity.NonFatal, "error.merge_blend_tree.missing_tree");
|
ErrorReport.ReportError(Localization.L, ErrorSeverity.NonFatal, "error.merge_blend_tree.missing_tree");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
string basePath = null;
|
string basePath = null;
|
||||||
string rootPath = null;
|
|
||||||
if (component.PathMode == MergeAnimatorPathMode.Relative)
|
|
||||||
{
|
|
||||||
var root = component.RelativePathRoot.Get(context.AvatarRootTransform);
|
|
||||||
if (root == null) root = component.gameObject;
|
|
||||||
|
|
||||||
rootPath = RuntimeUtil.AvatarRootPath(root);
|
|
||||||
basePath = rootPath + "/";
|
|
||||||
}
|
|
||||||
|
|
||||||
var bt = stash.BlendTrees.GetValueOrDefault(component)
|
|
||||||
?? _asc.ControllerContext.CloneContext.Clone(componentBlendTree);
|
|
||||||
|
|
||||||
if (basePath != null)
|
|
||||||
{
|
|
||||||
var animationIndex = new AnimationIndex(new[] { bt });
|
|
||||||
animationIndex.RewritePaths(p => p == "" ? rootPath : basePath + p);
|
|
||||||
}
|
|
||||||
|
|
||||||
var rootBlend = GetRootBlendTree();
|
var rootBlend = GetRootBlendTree();
|
||||||
|
|
||||||
rootBlend.Children = rootBlend.Children.Add(new()
|
rootBlend.Children = rootBlend.Children.Add(new()
|
||||||
{
|
{
|
||||||
Motion = bt,
|
Motion = virtualBlendTree,
|
||||||
DirectBlendParameter = ALWAYS_ONE,
|
DirectBlendParameter = ALWAYS_ONE,
|
||||||
Threshold = 1,
|
Threshold = 1,
|
||||||
CycleOffset = 1,
|
CycleOffset = 1,
|
||||||
TimeScale = 1,
|
TimeScale = 1,
|
||||||
});
|
});
|
||||||
|
|
||||||
foreach (var asset in bt.AllReachableNodes())
|
foreach (var asset in virtualBlendTree.AllReachableNodes())
|
||||||
{
|
{
|
||||||
if (asset is VirtualBlendTree bt2)
|
if (asset is VirtualBlendTree bt2)
|
||||||
{
|
{
|
||||||
@ -129,6 +125,8 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Object.DestroyImmediate(component);
|
||||||
}
|
}
|
||||||
|
|
||||||
private VirtualBlendTree GetRootBlendTree()
|
private VirtualBlendTree GetRootBlendTree()
|
||||||
|
@ -10,7 +10,6 @@ using nadena.dev.modular_avatar.editor.ErrorReporting;
|
|||||||
using nadena.dev.ndmf;
|
using nadena.dev.ndmf;
|
||||||
using nadena.dev.ndmf.animator;
|
using nadena.dev.ndmf.animator;
|
||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
using UnityEditor.Animations;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using VRC.SDK3.Avatars.Components;
|
using VRC.SDK3.Avatars.Components;
|
||||||
using VRC.SDK3.Avatars.ScriptableObjects;
|
using VRC.SDK3.Avatars.ScriptableObjects;
|
||||||
@ -55,43 +54,6 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
public ImmutableDictionary<string, float> InitialValueOverrides;
|
public ImmutableDictionary<string, float> InitialValueOverrides;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class RenamedMergeAnimators
|
|
||||||
{
|
|
||||||
public AnimatorServicesContext AnimatorServices;
|
|
||||||
public Dictionary<ModularAvatarMergeAnimator, VirtualAnimatorController> Controllers = new();
|
|
||||||
public Dictionary<ModularAvatarMergeBlendTree, VirtualBlendTree> BlendTrees = new();
|
|
||||||
|
|
||||||
public VirtualAnimatorController Clone(ModularAvatarMergeAnimator mama)
|
|
||||||
{
|
|
||||||
if (Controllers.TryGetValue(mama, out var controller))
|
|
||||||
{
|
|
||||||
return controller;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mama.animator == null) return null;
|
|
||||||
|
|
||||||
var cloned = AnimatorServices.ControllerContext.CloneContext.CloneDistinct(mama.animator, mama.layerType);
|
|
||||||
Controllers[mama] = cloned;
|
|
||||||
|
|
||||||
return cloned;
|
|
||||||
}
|
|
||||||
|
|
||||||
public VirtualBlendTree Clone(ModularAvatarMergeBlendTree mbt)
|
|
||||||
{
|
|
||||||
if (BlendTrees.TryGetValue(mbt, out var blendTree))
|
|
||||||
{
|
|
||||||
return blendTree;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mbt.BlendTree is not BlendTree bt) return null;
|
|
||||||
|
|
||||||
var cloned = (VirtualBlendTree)AnimatorServices.ControllerContext.CloneContext.Clone(bt);
|
|
||||||
BlendTrees[mbt] = cloned;
|
|
||||||
|
|
||||||
return cloned;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal class RenameParametersHook
|
internal class RenameParametersHook
|
||||||
{
|
{
|
||||||
private const string DEFAULT_EXP_PARAMS_ASSET_GUID = "03a6d797deb62f0429471c4e17ea99a7";
|
private const string DEFAULT_EXP_PARAMS_ASSET_GUID = "03a6d797deb62f0429471c4e17ea99a7";
|
||||||
@ -200,10 +162,6 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
|
|
||||||
_context = context;
|
_context = context;
|
||||||
|
|
||||||
var stash = _context.PluginBuildContext.GetState<RenamedMergeAnimators>();
|
|
||||||
var asc = _context.PluginBuildContext.Extension<AnimatorServicesContext>();
|
|
||||||
stash.AnimatorServices = asc;
|
|
||||||
|
|
||||||
var syncParams = WalkTree(avatar);
|
var syncParams = WalkTree(avatar);
|
||||||
|
|
||||||
SetExpressionParameters(avatar, syncParams);
|
SetExpressionParameters(avatar, syncParams);
|
||||||
@ -359,6 +317,8 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
GameObject obj
|
GameObject obj
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
var animServices = _context.PluginBuildContext.Extension<AnimatorServicesContext>();
|
||||||
|
|
||||||
var paramInfo = ndmf.ParameterInfo.ForContext(_context.PluginBuildContext);
|
var paramInfo = ndmf.ParameterInfo.ForContext(_context.PluginBuildContext);
|
||||||
|
|
||||||
ImmutableDictionary<string, ParameterInfo> rv = ImmutableDictionary<string, ParameterInfo>.Empty;
|
ImmutableDictionary<string, ParameterInfo> rv = ImmutableDictionary<string, ParameterInfo>.Empty;
|
||||||
@ -406,7 +366,7 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case ModularAvatarMergeAnimator merger:
|
case IVirtualizeAnimatorController virtualized:
|
||||||
{
|
{
|
||||||
var mappings = paramInfo.GetParameterRemappingsAt(obj);
|
var mappings = paramInfo.GetParameterRemappingsAt(obj);
|
||||||
var remap = mappings.SelectMany(item =>
|
var remap = mappings.SelectMany(item =>
|
||||||
@ -421,15 +381,10 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
);
|
);
|
||||||
}).ToImmutableDictionary();
|
}).ToImmutableDictionary();
|
||||||
|
|
||||||
if (merger.animator != null)
|
var controller = animServices.ControllerContext[virtualized];
|
||||||
|
if (controller != null)
|
||||||
{
|
{
|
||||||
var stash = _context.PluginBuildContext.GetState<RenamedMergeAnimators>();
|
|
||||||
|
|
||||||
var controller = stash.Clone(merger);
|
|
||||||
|
|
||||||
ProcessVirtualAnimatorController(controller, remap);
|
ProcessVirtualAnimatorController(controller, remap);
|
||||||
|
|
||||||
stash.Controllers[merger] = controller;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -437,15 +392,10 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
|
|
||||||
case ModularAvatarMergeBlendTree merger:
|
case ModularAvatarMergeBlendTree merger:
|
||||||
{
|
{
|
||||||
var bt = merger.BlendTree as BlendTree;
|
var motion = animServices.ControllerContext.GetVirtualizedMotion(merger);
|
||||||
if (bt != null)
|
if (motion is VirtualBlendTree bt)
|
||||||
{
|
{
|
||||||
var stash = _context.PluginBuildContext.GetState<RenamedMergeAnimators>();
|
ProcessBlendtree(bt, paramInfo.GetParameterRemappingsAt(obj));
|
||||||
|
|
||||||
var virtualbt = stash.Clone(merger);
|
|
||||||
ProcessBlendtree(virtualbt, paramInfo.GetParameterRemappingsAt(obj));
|
|
||||||
|
|
||||||
stash.BlendTrees[merger] = virtualbt;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -23,9 +23,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using nadena.dev.ndmf;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
#if MA_VRCSDK3_AVATARS
|
#if MA_VRCSDK3_AVATARS
|
||||||
using VRC.SDKBase;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace nadena.dev.modular_avatar.core
|
namespace nadena.dev.modular_avatar.core
|
||||||
@ -35,7 +35,7 @@ namespace nadena.dev.modular_avatar.core
|
|||||||
/// inherited by user classes, and will be removed in Modular Avatar 2.0.
|
/// inherited by user classes, and will be removed in Modular Avatar 2.0.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DefaultExecutionOrder(-9999)] // run before av3emu
|
[DefaultExecutionOrder(-9999)] // run before av3emu
|
||||||
public abstract class AvatarTagComponent : MonoBehaviour, IEditorOnly
|
public abstract class AvatarTagComponent : MonoBehaviour, INDMFEditorOnly
|
||||||
{
|
{
|
||||||
internal static event Action OnChangeAction;
|
internal static event Action OnChangeAction;
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#if MA_VRCSDK3_AVATARS
|
#if MA_VRCSDK3_AVATARS
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using nadena.dev.ndmf.animator;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using VRC.SDK3.Avatars.Components;
|
using VRC.SDK3.Avatars.Components;
|
||||||
|
|
||||||
@ -38,8 +39,11 @@ namespace nadena.dev.modular_avatar.core
|
|||||||
|
|
||||||
[AddComponentMenu("Modular Avatar/MA Merge Animator")]
|
[AddComponentMenu("Modular Avatar/MA Merge Animator")]
|
||||||
[HelpURL("https://modular-avatar.nadena.dev/docs/reference/merge-animator?lang=auto")]
|
[HelpURL("https://modular-avatar.nadena.dev/docs/reference/merge-animator?lang=auto")]
|
||||||
public class ModularAvatarMergeAnimator : AvatarTagComponent
|
public class ModularAvatarMergeAnimator : AvatarTagComponent, IVirtualizeAnimatorController
|
||||||
{
|
{
|
||||||
|
internal static Func<ModularAvatarMergeAnimator, object, string> GetMotionBasePathCallback =
|
||||||
|
(_, _) => "";
|
||||||
|
|
||||||
public RuntimeAnimatorController animator;
|
public RuntimeAnimatorController animator;
|
||||||
public VRCAvatarDescriptor.AnimLayerType layerType = VRCAvatarDescriptor.AnimLayerType.FX;
|
public VRCAvatarDescriptor.AnimLayerType layerType = VRCAvatarDescriptor.AnimLayerType.FX;
|
||||||
public bool deleteAttachedAnimator;
|
public bool deleteAttachedAnimator;
|
||||||
@ -47,7 +51,7 @@ namespace nadena.dev.modular_avatar.core
|
|||||||
public bool matchAvatarWriteDefaults;
|
public bool matchAvatarWriteDefaults;
|
||||||
public AvatarObjectReference relativePathRoot = new AvatarObjectReference();
|
public AvatarObjectReference relativePathRoot = new AvatarObjectReference();
|
||||||
public int layerPriority = 0;
|
public int layerPriority = 0;
|
||||||
|
|
||||||
public override void ResolveReferences()
|
public override void ResolveReferences()
|
||||||
{
|
{
|
||||||
// no-op
|
// no-op
|
||||||
@ -67,6 +71,22 @@ namespace nadena.dev.modular_avatar.core
|
|||||||
{
|
{
|
||||||
deleteAttachedAnimator = true;
|
deleteAttachedAnimator = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RuntimeAnimatorController IVirtualizeAnimatorController.AnimatorController
|
||||||
|
{
|
||||||
|
get => animator;
|
||||||
|
set => animator = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
string IVirtualizeAnimatorController.GetMotionBasePath(object ndmfBuildContext, bool clearPath = true)
|
||||||
|
{
|
||||||
|
var path = GetMotionBasePathCallback(this, ndmfBuildContext);
|
||||||
|
if (clearPath) pathMode = MergeAnimatorPathMode.Absolute;
|
||||||
|
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
object IVirtualizeAnimatorController.TargetControllerKey => layerType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,17 +1,41 @@
|
|||||||
#if MA_VRCSDK3_AVATARS
|
#if MA_VRCSDK3_AVATARS
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using API;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using Object = UnityEngine.Object;
|
||||||
|
|
||||||
namespace nadena.dev.modular_avatar.core
|
namespace nadena.dev.modular_avatar.core
|
||||||
{
|
{
|
||||||
[AddComponentMenu("Modular Avatar/MA Merge Blend Tree")]
|
[AddComponentMenu("Modular Avatar/MA Merge Blend Tree")]
|
||||||
[HelpURL("https://modular-avatar.nadena.dev/docs/reference/merge-blend-tree?lang=auto")]
|
[HelpURL("https://modular-avatar.nadena.dev/docs/reference/merge-blend-tree?lang=auto")]
|
||||||
public sealed class ModularAvatarMergeBlendTree : AvatarTagComponent
|
public sealed class ModularAvatarMergeBlendTree : AvatarTagComponent, IVirtualizeMotion
|
||||||
{
|
{
|
||||||
|
internal static Func<ModularAvatarMergeBlendTree, object, string> GetMotionBasePathCallback
|
||||||
|
= (_, _) => "";
|
||||||
|
|
||||||
// We can't actually reference a BlendTree here because it's not available when building a player build
|
// We can't actually reference a BlendTree here because it's not available when building a player build
|
||||||
public UnityEngine.Object BlendTree;
|
public Object BlendTree;
|
||||||
public MergeAnimatorPathMode PathMode = MergeAnimatorPathMode.Relative;
|
public MergeAnimatorPathMode PathMode = MergeAnimatorPathMode.Relative;
|
||||||
public AvatarObjectReference RelativePathRoot = new AvatarObjectReference();
|
public AvatarObjectReference RelativePathRoot = new AvatarObjectReference();
|
||||||
|
|
||||||
|
Motion IVirtualizeMotion.Motion
|
||||||
|
{
|
||||||
|
get => (Motion)BlendTree;
|
||||||
|
set => BlendTree = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
string IVirtualizeMotion.GetMotionBasePath(object ndmfBuildContext, bool clearPath = true)
|
||||||
|
{
|
||||||
|
var path = GetMotionBasePathCallback(this, ndmfBuildContext);
|
||||||
|
|
||||||
|
if (clearPath)
|
||||||
|
{
|
||||||
|
PathMode = MergeAnimatorPathMode.Absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
return path;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,13 +25,14 @@ Transform:
|
|||||||
m_PrefabInstance: {fileID: 0}
|
m_PrefabInstance: {fileID: 0}
|
||||||
m_PrefabAsset: {fileID: 0}
|
m_PrefabAsset: {fileID: 0}
|
||||||
m_GameObject: {fileID: 521542568012153140}
|
m_GameObject: {fileID: 521542568012153140}
|
||||||
|
serializedVersion: 2
|
||||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||||
m_LocalPosition: {x: -1.6884441, y: 1.1147345, z: -4.914471}
|
m_LocalPosition: {x: -1.6884441, y: 1.1147345, z: -4.914471}
|
||||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||||
|
m_ConstrainProportionsScale: 0
|
||||||
m_Children:
|
m_Children:
|
||||||
- {fileID: 6479369535091914718}
|
- {fileID: 6479369535091914718}
|
||||||
m_Father: {fileID: 0}
|
m_Father: {fileID: 0}
|
||||||
m_RootOrder: 0
|
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
--- !u!114 &8063907918941263456
|
--- !u!114 &8063907918941263456
|
||||||
MonoBehaviour:
|
MonoBehaviour:
|
||||||
@ -59,6 +60,7 @@ MonoBehaviour:
|
|||||||
unityVersion:
|
unityVersion:
|
||||||
portraitCameraPositionOffset: {x: 0, y: 0, z: 0}
|
portraitCameraPositionOffset: {x: 0, y: 0, z: 0}
|
||||||
portraitCameraRotationOffset: {x: 0, y: 1, z: 0, w: -0.00000004371139}
|
portraitCameraRotationOffset: {x: 0, y: 1, z: 0, w: -0.00000004371139}
|
||||||
|
networkIDs: []
|
||||||
customExpressions: 0
|
customExpressions: 0
|
||||||
expressionsMenu: {fileID: 0}
|
expressionsMenu: {fileID: 0}
|
||||||
expressionParameters: {fileID: 0}
|
expressionParameters: {fileID: 0}
|
||||||
@ -335,12 +337,13 @@ Transform:
|
|||||||
m_PrefabInstance: {fileID: 0}
|
m_PrefabInstance: {fileID: 0}
|
||||||
m_PrefabAsset: {fileID: 0}
|
m_PrefabAsset: {fileID: 0}
|
||||||
m_GameObject: {fileID: 7379231148671166614}
|
m_GameObject: {fileID: 7379231148671166614}
|
||||||
|
serializedVersion: 2
|
||||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||||
|
m_ConstrainProportionsScale: 0
|
||||||
m_Children: []
|
m_Children: []
|
||||||
m_Father: {fileID: 2616869947308232229}
|
m_Father: {fileID: 2616869947308232229}
|
||||||
m_RootOrder: 0
|
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
--- !u!114 &5229589187063892731
|
--- !u!114 &5229589187063892731
|
||||||
MonoBehaviour:
|
MonoBehaviour:
|
||||||
@ -366,8 +369,12 @@ MonoBehaviour:
|
|||||||
m_Script: {fileID: 11500000, guid: 1bb122659f724ebf85fe095ac02dc339, type: 3}
|
m_Script: {fileID: 11500000, guid: 1bb122659f724ebf85fe095ac02dc339, type: 3}
|
||||||
m_Name:
|
m_Name:
|
||||||
m_EditorClassIdentifier:
|
m_EditorClassIdentifier:
|
||||||
animator: {fileID: 9100000, guid: 22f4686ec8638e243854be6fccb38820, type: 2}
|
animator: {fileID: 9100000, guid: 26ef9d769605a1e46a5ad2768e28ad73, type: 2}
|
||||||
layerType: 5
|
layerType: 5
|
||||||
deleteAttachedAnimator: 0
|
deleteAttachedAnimator: 0
|
||||||
pathMode: 0
|
pathMode: 0
|
||||||
matchAvatarWriteDefaults: 0
|
matchAvatarWriteDefaults: 0
|
||||||
|
relativePathRoot:
|
||||||
|
referencePath:
|
||||||
|
targetObject: {fileID: 0}
|
||||||
|
layerPriority: 0
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
#if MA_VRCSDK3_AVATARS
|
#if MA_VRCSDK3_AVATARS
|
||||||
|
|
||||||
|
using System.Linq;
|
||||||
using nadena.dev.modular_avatar.core.editor;
|
using nadena.dev.modular_avatar.core.editor;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
using UnityEditor.Animations;
|
||||||
using VRC.SDK3.Avatars.Components;
|
using VRC.SDK3.Avatars.Components;
|
||||||
|
|
||||||
namespace modular_avatar_tests.SyncedLayerHandling
|
namespace modular_avatar_tests.SyncedLayerHandling
|
||||||
@ -102,6 +104,7 @@ namespace modular_avatar_tests.SyncedLayerHandling
|
|||||||
var prefab = CreatePrefab("MergedController_AC2.prefab");
|
var prefab = CreatePrefab("MergedController_AC2.prefab");
|
||||||
AvatarProcessor.ProcessAvatar(prefab);
|
AvatarProcessor.ProcessAvatar(prefab);
|
||||||
|
|
||||||
|
var fx = (AnimatorController) FindFxController(prefab).animatorController;
|
||||||
var mainLayer = findFxLayer(prefab, "main");
|
var mainLayer = findFxLayer(prefab, "main");
|
||||||
var syncLayer = findFxLayer(prefab, "sync");
|
var syncLayer = findFxLayer(prefab, "sync");
|
||||||
|
|
||||||
@ -114,7 +117,7 @@ namespace modular_avatar_tests.SyncedLayerHandling
|
|||||||
var layercontrol = overrides[0] as VRCAnimatorLayerControl;
|
var layercontrol = overrides[0] as VRCAnimatorLayerControl;
|
||||||
Assert.NotNull(layercontrol);
|
Assert.NotNull(layercontrol);
|
||||||
|
|
||||||
Assert.AreEqual(1, layercontrol.layer);
|
Assert.AreEqual(layercontrol.layer, fx.layers.TakeWhile(l => l.name != "main").Count());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user