2024-06-03 08:52:08 +08:00
|
|
|
|
#region
|
|
|
|
|
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
2023-09-30 23:09:43 +08:00
|
|
|
|
using nadena.dev.ndmf;
|
2024-06-03 08:52:08 +08:00
|
|
|
|
using UnityEditor;
|
|
|
|
|
using UnityEditor.Animations;
|
|
|
|
|
using UnityEngine;
|
2024-10-20 09:58:41 +08:00
|
|
|
|
#if MA_VRCSDK3_AVATARS
|
2024-07-07 12:39:42 +08:00
|
|
|
|
using VRC.SDK3.Avatars.Components;
|
2024-10-20 09:58:41 +08:00
|
|
|
|
#endif
|
2024-06-03 08:52:08 +08:00
|
|
|
|
|
|
|
|
|
#endregion
|
2023-09-30 23:09:43 +08:00
|
|
|
|
|
|
|
|
|
namespace nadena.dev.modular_avatar.animation
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// This extension context amortizes a number of animation-related processing steps - notably,
|
|
|
|
|
/// collecting the set of all animation clips from the animators, and committing changes to them
|
|
|
|
|
/// in a deferred manner.
|
|
|
|
|
///
|
|
|
|
|
/// Restrictions: While this context is active, any changes to clips must be done by editing them via
|
|
|
|
|
/// ClipHolders in the AnimationDatabase. Any newly added clips must be registered in the AnimationDatabase,
|
|
|
|
|
/// and any new references to clips require setting appropriate ClipCommitActions.
|
|
|
|
|
///
|
|
|
|
|
/// New references to objects created in clips must use paths obtained from the
|
|
|
|
|
/// ObjectRenameTracker.GetObjectIdentifier method.
|
|
|
|
|
/// </summary>
|
|
|
|
|
internal sealed class AnimationServicesContext : IExtensionContext
|
|
|
|
|
{
|
2024-06-03 08:52:08 +08:00
|
|
|
|
private BuildContext _context;
|
2023-09-30 23:09:43 +08:00
|
|
|
|
private AnimationDatabase _animationDatabase;
|
|
|
|
|
private PathMappings _pathMappings;
|
2024-07-07 12:39:42 +08:00
|
|
|
|
private ReadableProperty _readableProperty;
|
|
|
|
|
|
2024-06-03 08:52:08 +08:00
|
|
|
|
private Dictionary<GameObject, string> _selfProxies = new();
|
2023-09-30 23:09:43 +08:00
|
|
|
|
|
|
|
|
|
public void OnActivate(BuildContext context)
|
|
|
|
|
{
|
2024-06-03 08:52:08 +08:00
|
|
|
|
_context = context;
|
|
|
|
|
|
2023-09-30 23:09:43 +08:00
|
|
|
|
_animationDatabase = new AnimationDatabase();
|
|
|
|
|
_animationDatabase.OnActivate(context);
|
|
|
|
|
|
|
|
|
|
_pathMappings = new PathMappings();
|
|
|
|
|
_pathMappings.OnActivate(context, _animationDatabase);
|
2024-07-07 12:39:42 +08:00
|
|
|
|
|
|
|
|
|
_readableProperty = new ReadableProperty(_context, _animationDatabase, this);
|
2023-09-30 23:09:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void OnDeactivate(BuildContext context)
|
|
|
|
|
{
|
|
|
|
|
_pathMappings.OnDeactivate(context);
|
|
|
|
|
_animationDatabase.Commit();
|
|
|
|
|
|
|
|
|
|
_pathMappings = null;
|
|
|
|
|
_animationDatabase = null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public AnimationDatabase AnimationDatabase
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
if (_animationDatabase == null)
|
|
|
|
|
{
|
|
|
|
|
throw new InvalidOperationException(
|
|
|
|
|
"AnimationDatabase is not available outside of the AnimationServicesContext");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return _animationDatabase;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public PathMappings PathMappings
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
if (_pathMappings == null)
|
|
|
|
|
{
|
|
|
|
|
throw new InvalidOperationException(
|
|
|
|
|
"ObjectRenameTracker is not available outside of the AnimationServicesContext");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return _pathMappings;
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-06-03 08:52:08 +08:00
|
|
|
|
|
2024-07-29 11:22:32 +08:00
|
|
|
|
public IEnumerable<(EditorCurveBinding, string)> BoundReadableProperties => _readableProperty.BoundProperties;
|
|
|
|
|
|
2024-07-07 12:39:42 +08:00
|
|
|
|
// HACK: This is a temporary crutch until we rework the entire animator services system
|
|
|
|
|
public void AddPropertyDefinition(AnimatorControllerParameter paramDef)
|
|
|
|
|
{
|
2024-10-20 09:58:41 +08:00
|
|
|
|
#if MA_VRCSDK3_AVATARS
|
2024-10-28 01:06:35 +08:00
|
|
|
|
if (!_context.AvatarDescriptor) return;
|
|
|
|
|
|
2024-07-07 12:39:42 +08:00
|
|
|
|
var fx = (AnimatorController)
|
|
|
|
|
_context.AvatarDescriptor.baseAnimationLayers
|
|
|
|
|
.First(l => l.type == VRCAvatarDescriptor.AnimLayerType.FX)
|
|
|
|
|
.animatorController;
|
|
|
|
|
|
|
|
|
|
fx.parameters = fx.parameters.Concat(new[] { paramDef }).ToArray();
|
2024-10-20 09:58:41 +08:00
|
|
|
|
#endif
|
2024-07-07 12:39:42 +08:00
|
|
|
|
}
|
|
|
|
|
|
2024-08-06 12:50:35 +08:00
|
|
|
|
public string GetActiveSelfProxy(GameObject obj)
|
2024-08-04 10:56:07 +08:00
|
|
|
|
{
|
|
|
|
|
if (_selfProxies.TryGetValue(obj, out var paramName) && !string.IsNullOrEmpty(paramName)) return paramName;
|
|
|
|
|
|
|
|
|
|
var path = PathMappings.GetObjectIdentifier(obj);
|
|
|
|
|
|
|
|
|
|
paramName = _readableProperty.ForActiveSelf(path);
|
|
|
|
|
_selfProxies[obj] = paramName;
|
|
|
|
|
|
|
|
|
|
return paramName;
|
|
|
|
|
}
|
2024-08-06 12:50:35 +08:00
|
|
|
|
|
|
|
|
|
public bool ObjectHasAnimations(GameObject obj)
|
|
|
|
|
{
|
|
|
|
|
var path = PathMappings.GetObjectIdentifier(obj);
|
|
|
|
|
var clips = AnimationDatabase.ClipsForPath(path);
|
|
|
|
|
return clips != null && !clips.IsEmpty;
|
|
|
|
|
}
|
2023-09-30 23:09:43 +08:00
|
|
|
|
}
|
|
|
|
|
}
|