diff --git a/Editor/Animation/AnimationDatabase.cs b/Editor/Animation/AnimationDatabase.cs
deleted file mode 100644
index d34ddff8..00000000
--- a/Editor/Animation/AnimationDatabase.cs
+++ /dev/null
@@ -1,430 +0,0 @@
-#region
-
-using System;
-using System.Collections.Generic;
-using System.Collections.Immutable;
-using nadena.dev.modular_avatar.core.editor;
-using nadena.dev.modular_avatar.editor.ErrorReporting;
-using nadena.dev.ndmf;
-using UnityEditor;
-using UnityEditor.Animations;
-using UnityEngine;
-using UnityEngine.Profiling;
-using BuildContext = nadena.dev.ndmf.BuildContext;
-#if MA_VRCSDK3_AVATARS
-using VRC.SDK3.Avatars.Components;
-#endif
-
-#endregion
-
-namespace nadena.dev.modular_avatar.animation
-{
- ///
- /// The animation database records the set of all clips which are used in the avatar, and which paths they
- /// manipulate.
- ///
- internal class AnimationDatabase
- {
- internal class ClipHolder
- {
- private readonly AnimationDatabase ParentDatabase;
-
- private Motion _currentClip;
-
- internal Motion CurrentClip
- {
- get
- {
- ParentDatabase.InvalidateCaches();
- return _currentClip;
- }
- set
- {
- ParentDatabase.InvalidateCaches();
- _currentClip = value;
- }
- }
-
- private Motion _originalClip;
-
- internal Motion OriginalClip
- {
- get => _originalClip;
- set
- {
- _originalClip = value;
-
- var baseClip = ObjectRegistry.GetReference(value)?.Object as AnimationClip;
-
- IsProxyAnimation = false;
- if (value != null && Util.IsProxyAnimation(value))
- {
- IsProxyAnimation = true;
- }
- else if (baseClip != null && Util.IsProxyAnimation(baseClip))
- {
- // RenameParametersPass replaces proxy clips outside of the purview of the animation database,
- // so trace this using ObjectRegistry and correct the reference.
- IsProxyAnimation = true;
- _originalClip = baseClip;
- }
- }
- }
-
- internal bool IsProxyAnimation { private set; get; }
-
- internal ClipHolder(AnimationDatabase parentDatabase, Motion clip)
- {
- ParentDatabase = parentDatabase;
- CurrentClip = OriginalClip = clip;
- }
-
- ///
- /// Returns the current clip without invalidating caches. Do not modify this clip without taking extra
- /// steps to invalidate caches on the AnimationDatabase.
- ///
- ///
- internal Motion GetCurrentClipUnsafe()
- {
- return _currentClip;
- }
-
- public void SetCurrentNoInvalidate(Motion newMotion)
- {
- _currentClip = newMotion;
- }
- }
-
- private BuildContext _context;
-
- private List _clipCommitActions = new List();
- private List _clips = new List();
-#if MA_VRCSDK3_AVATARS_3_5_2_OR_NEWER
- private HashSet _playAudios = new HashSet();
-#endif
-
- private Dictionary> _pathToClip = null;
-
- internal AnimationDatabase()
- {
- Debug.Log("Creating animation database");
- }
-
- internal void Commit()
- {
- Profiler.BeginSample("AnimationDatabase.Commit");
- foreach (var clip in _clips)
- {
- if (clip.IsProxyAnimation) clip.CurrentClip = clip.OriginalClip;
- }
-
- Profiler.BeginSample("UpdateClipProperties");
- foreach (var clip in _clips)
- {
- // Changing the "high quality curve" setting can result in behavior changes (but can happen accidentally
- // as we manipulate curves)
- if (clip.CurrentClip != clip.OriginalClip && clip.CurrentClip != null && clip.OriginalClip != null)
- {
- SerializedObject before = new SerializedObject(clip.OriginalClip);
- SerializedObject after = new SerializedObject(clip.CurrentClip);
-
- var before_prop = before.FindProperty("m_UseHighQualityCurve");
- var after_prop = after.FindProperty("m_UseHighQualityCurve");
-
- if (after_prop.boolValue != before_prop.boolValue)
- {
- after_prop.boolValue = before_prop.boolValue;
- after.ApplyModifiedPropertiesWithoutUndo();
- }
- }
- }
- Profiler.EndSample();
-
- Profiler.BeginSample("ClipCommitActions");
- foreach (var action in _clipCommitActions)
- {
- action();
- }
- Profiler.EndSample();
-
- Profiler.EndSample();
- }
-
- internal void OnActivate(BuildContext context)
- {
- _context = context;
-
- AnimationUtil.CloneAllControllers(context);
-
-#if MA_VRCSDK3_AVATARS
- var avatarDescriptor = context.AvatarDescriptor;
- if (!avatarDescriptor) return;
-
- foreach (var layer in avatarDescriptor.baseAnimationLayers)
- {
- BootstrapLayer(layer);
- }
-
- foreach (var layer in avatarDescriptor.specialAnimationLayers)
- {
- BootstrapLayer(layer);
- }
-
- void BootstrapLayer(VRCAvatarDescriptor.CustomAnimLayer layer)
- {
- if (!layer.isDefault && layer.animatorController is AnimatorController ac &&
- context.IsTemporaryAsset(ac))
- {
- BuildReport.ReportingObject(ac, () =>
- {
- foreach (var state in Util.States(ac))
- {
- RegisterState(state);
- }
- });
- }
- }
-#endif
- }
-
- ///
- /// Registers a motion and all its reachable submotions with the animation database. The processClip callback,
- /// if provided, will be invoked for each newly discovered clip.
- ///
- ///
- ///
- ///
- internal void RegisterState(AnimatorState state, Action processClip = null)
- {
- Dictionary _originalToHolder = new Dictionary();
-
- if (processClip == null) processClip = (_) => { };
-
-#if MA_VRCSDK3_AVATARS_3_5_2_OR_NEWER
- foreach (var behavior in state.behaviours)
- {
- if (behavior is VRCAnimatorPlayAudio playAudio)
- {
- _playAudios.Add(playAudio);
- }
- }
-#endif
-
- if (state.motion == null) return;
-
- var clipHolder = RegisterMotion(state.motion, state, processClip, _originalToHolder);
- state.motion = clipHolder.CurrentClip;
-
- _clipCommitActions.Add(() =>
- {
- state.motion = clipHolder.CurrentClip;
- MaybeSaveClip(clipHolder.CurrentClip);
- });
- }
-
- internal void ForeachClip(Action processClip)
- {
- foreach (var clipHolder in _clips)
- {
- processClip(clipHolder);
- }
- }
-
-#if MA_VRCSDK3_AVATARS_3_5_2_OR_NEWER
- internal void ForeachPlayAudio(Action processPlayAudio)
- {
- foreach (var playAudioHolder in _playAudios)
- {
- processPlayAudio(playAudioHolder);
- }
- }
-#endif
-
- ///
- /// Returns a list of clips which touched the given _original_ path. This path is subject to basepath remapping,
- /// but not object movement remapping.
- ///
- ///
- ///
- internal ImmutableArray ClipsForPath(string path)
- {
- HydrateCaches();
-
- if (_pathToClip.TryGetValue(path, out var clips))
- {
- return clips.ToImmutableArray();
- }
- else
- {
- return ImmutableArray.Empty;
- }
- }
-
- private ClipHolder RegisterMotion(
- Motion motion,
- AnimatorState state,
- Action processClip,
- Dictionary originalToHolder
- )
- {
- if (motion == null)
- {
- return new ClipHolder(this, null);
- }
-
- if (originalToHolder.TryGetValue(motion, out var holder))
- {
- return holder;
- }
-
- InvalidateCaches();
-
- Motion cloned = motion;
- if (!_context.IsTemporaryAsset(motion))
- {
- // Protect the original animations from mutations by creating temporary clones; in the case of a proxy
- // animation, we'll restore the original in a later pass
- // cloned = Object.Instantiate(motion); - Object.Instantiate can't be used on AnimationClips and BlendTrees
-
- cloned = (Motion)motion.GetType().GetConstructor(new Type[0]).Invoke(new object[0]);
- EditorUtility.CopySerialized(motion, cloned);
-
- ObjectRegistry.RegisterReplacedObject(motion, cloned);
- }
-
- switch (cloned)
- {
- case AnimationClip clip:
- {
- holder = new ClipHolder(this, clip);
- processClip(holder);
- _clips.Add(holder);
- break;
- }
- case BlendTree tree:
- {
- holder = RegisterBlendtree(tree, state, processClip, originalToHolder);
- break;
- }
- }
-
- holder.OriginalClip = motion;
-
- originalToHolder[motion] = holder;
- return holder;
- }
-
- private void InvalidateCaches()
- {
- _pathToClip = null;
- }
-
- private void HydrateCaches()
- {
- if (_pathToClip == null)
- {
- _pathToClip = new Dictionary>();
- foreach (var clip in _clips)
- {
- RecordPaths(clip);
- }
- }
- }
-
- private void RecordPaths(ClipHolder holder)
- {
- var clip = holder.GetCurrentClipUnsafe() as AnimationClip;
-
- foreach (var binding in AnimationUtility.GetCurveBindings(clip))
- {
- var path = binding.path;
- AddPath(path);
- }
-
- foreach (var binding in AnimationUtility.GetObjectReferenceCurveBindings(clip))
- {
- var path = binding.path;
- AddPath(path);
- }
-
- void AddPath(string p0)
- {
- if (!_pathToClip.TryGetValue(p0, out var clips))
- {
- clips = new HashSet();
- _pathToClip[p0] = clips;
- }
-
- clips.Add(holder);
- }
- }
-
- private ClipHolder RegisterBlendtree(
- BlendTree tree,
- AnimatorState state,
- Action processClip,
- Dictionary originalToHolder
- )
- {
- if (!_context.IsTemporaryAsset(tree))
- {
- throw new Exception("Blendtree must be a temporary asset");
- }
-
- var treeHolder = new ClipHolder(this, tree);
-
- var children = tree.children;
- var holders = new ClipHolder[children.Length];
-
- for (int i = 0; i < children.Length; i++)
- {
- holders[i] = RegisterMotion(children[i].motion, state, processClip, originalToHolder);
- children[i].motion = holders[i].CurrentClip;
- }
-
- tree.children = children;
-
- _clipCommitActions.Add(() =>
- {
- var dirty = false;
- for (int i = 0; i < children.Length; i++)
- {
- var curClip = holders[i].CurrentClip;
- if (children[i].motion != curClip)
- {
- children[i].motion = curClip;
- dirty = true;
- }
-
- MaybeSaveClip(curClip);
- }
-
- if (dirty)
- {
- tree.children = children;
- EditorUtility.SetDirty(tree);
- }
- });
-
- return treeHolder;
- }
-
- private void MaybeSaveClip(Motion curClip)
- {
- Profiler.BeginSample("MaybeSaveClip");
- if (curClip != null && !EditorUtility.IsPersistent(curClip) && EditorUtility.IsPersistent(_context.AssetContainer) && _context.AssetContainer != null)
- {
- try
- {
- _context.AssetSaver.SaveAsset(curClip);
- }
- catch (Exception e)
- {
- Debug.LogException(e);
- throw;
- }
- }
- Profiler.EndSample();
- }
- }
-}
\ No newline at end of file
diff --git a/Editor/Animation/AnimationDatabase.cs.meta b/Editor/Animation/AnimationDatabase.cs.meta
deleted file mode 100644
index 05c197ba..00000000
--- a/Editor/Animation/AnimationDatabase.cs.meta
+++ /dev/null
@@ -1,3 +0,0 @@
-fileFormatVersion: 2
-guid: 11130986120e452b8dc8db0d19aa71fc
-timeCreated: 1671624207
\ No newline at end of file
diff --git a/Editor/Animation/AnimationServicesContext.cs b/Editor/Animation/AnimationServicesContext.cs
deleted file mode 100644
index 642f7573..00000000
--- a/Editor/Animation/AnimationServicesContext.cs
+++ /dev/null
@@ -1,82 +0,0 @@
-#region
-
-using System;
-using System.Collections.Generic;
-using nadena.dev.ndmf;
-using UnityEngine;
-#if MA_VRCSDK3_AVATARS
-#endif
-
-#endregion
-
-namespace nadena.dev.modular_avatar.animation
-{
- ///
- /// 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.
- ///
- internal sealed class AnimationServicesContext : IExtensionContext
- {
- private BuildContext _context;
- private AnimationDatabase _animationDatabase;
- private PathMappings _pathMappings;
-
- private Dictionary _selfProxies = new();
-
- public void OnActivate(BuildContext context)
- {
- _context = context;
-
- _animationDatabase = new AnimationDatabase();
- _animationDatabase.OnActivate(context);
-
- _pathMappings = new PathMappings();
- _pathMappings.OnActivate(context, _animationDatabase);
- }
-
- 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;
- }
- }
- }
-}
\ No newline at end of file
diff --git a/Editor/Animation/AnimationServicesContext.cs.meta b/Editor/Animation/AnimationServicesContext.cs.meta
deleted file mode 100644
index 8eefb71b..00000000
--- a/Editor/Animation/AnimationServicesContext.cs.meta
+++ /dev/null
@@ -1,3 +0,0 @@
-fileFormatVersion: 2
-guid: c2c26040d44d4dacb838aceced3b3e52
-timeCreated: 1696063949
\ No newline at end of file
diff --git a/Editor/Animation/AnimationUtil.cs b/Editor/Animation/AnimationUtil.cs
deleted file mode 100644
index 1016cba9..00000000
--- a/Editor/Animation/AnimationUtil.cs
+++ /dev/null
@@ -1,224 +0,0 @@
-#region
-
-using System;
-using System.Collections.Generic;
-using nadena.dev.ndmf;
-using UnityEditor;
-using UnityEditor.Animations;
-using UnityEngine;
-
-#if MA_VRCSDK3_AVATARS
-using VRC.SDK3.Avatars.Components;
-#endif
-
-#endregion
-
-namespace nadena.dev.modular_avatar.animation
-{
- internal static class AnimationUtil
- {
- private const string SAMPLE_PATH_PACKAGE =
- "Packages/com.vrchat.avatars/Samples/AV3 Demo Assets/Animation/Controllers";
-
- private const string SAMPLE_PATH_LEGACY = "Assets/VRCSDK/Examples3/Animation/Controllers";
-
- private const string GUID_GESTURE_HANDSONLY_MASK = "b2b8bad9583e56a46a3e21795e96ad92";
-
-
- public static AnimatorController DeepCloneAnimator(BuildContext context, RuntimeAnimatorController controller)
- {
- if (controller == null) return null;
-
- var merger = new AnimatorCombiner(context, controller.name + " (cloned)");
- switch (controller)
- {
- case AnimatorController ac:
- merger.AddController("", ac, null);
- break;
- case AnimatorOverrideController oac:
- merger.AddOverrideController("", oac, null);
- break;
- default:
- throw new Exception("Unknown RuntimeAnimatorContoller type " + controller.GetType());
- }
-
- var clone = merger.Finish();
- ObjectRegistry.RegisterReplacedObject(controller, clone);
- return clone;
- }
-
- internal static void CloneAllControllers(BuildContext context)
- {
- // Ensure all of the controllers on the avatar descriptor point to temporary assets.
- // This helps reduce the risk that we'll accidentally modify the original assets.
-
-#if MA_VRCSDK3_AVATARS
- if (!context.AvatarDescriptor) return;
-
- context.AvatarDescriptor.baseAnimationLayers =
- CloneLayers(context, context.AvatarDescriptor.baseAnimationLayers);
- context.AvatarDescriptor.specialAnimationLayers =
- CloneLayers(context, context.AvatarDescriptor.specialAnimationLayers);
-#endif
- }
-
-#if MA_VRCSDK3_AVATARS
- private static VRCAvatarDescriptor.CustomAnimLayer[] CloneLayers(
- BuildContext context,
- VRCAvatarDescriptor.CustomAnimLayer[] layers
- )
- {
- if (layers == null) return null;
-
- for (int i = 0; i < layers.Length; i++)
- {
- var layer = layers[i];
- if (layer.animatorController != null && !context.IsTemporaryAsset(layer.animatorController))
- {
- layer.animatorController = DeepCloneAnimator(context, layer.animatorController);
- }
-
- layers[i] = layer;
- }
-
- return layers;
- }
-
- public static AnimatorController GetOrInitializeController(
- this BuildContext context,
- VRCAvatarDescriptor.AnimLayerType type)
- {
- return FindLayer(context.AvatarDescriptor.baseAnimationLayers)
- ?? FindLayer(context.AvatarDescriptor.specialAnimationLayers);
-
- AnimatorController FindLayer(VRCAvatarDescriptor.CustomAnimLayer[] layers)
- {
- for (int i = 0; i < layers.Length; i++)
- {
- var layer = layers[i];
- if (layer.type == type)
- {
- if (layer.animatorController == null || layer.isDefault)
- {
- layer.animatorController = ResolveLayerController(layer);
- if (type == VRCAvatarDescriptor.AnimLayerType.Gesture)
- {
- layer.mask = AssetDatabase.LoadAssetAtPath(
- AssetDatabase.GUIDToAssetPath(GUID_GESTURE_HANDSONLY_MASK)
- );
- }
-
- layers[i] = layer;
- }
-
- return layer.animatorController as AnimatorController;
- }
- }
-
- return null;
- }
- }
-
-
- private static AnimatorController ResolveLayerController(VRCAvatarDescriptor.CustomAnimLayer layer)
- {
- AnimatorController controller = null;
-
- if (!layer.isDefault && layer.animatorController != null &&
- layer.animatorController is AnimatorController c)
- {
- controller = c;
- }
- else
- {
- string name;
- switch (layer.type)
- {
- case VRCAvatarDescriptor.AnimLayerType.Action:
- name = "Action";
- break;
- case VRCAvatarDescriptor.AnimLayerType.Additive:
- name = "Idle";
- break;
- case VRCAvatarDescriptor.AnimLayerType.Base:
- name = "Locomotion";
- break;
- case VRCAvatarDescriptor.AnimLayerType.Gesture:
- name = "Hands";
- break;
- case VRCAvatarDescriptor.AnimLayerType.Sitting:
- name = "Sitting";
- break;
- case VRCAvatarDescriptor.AnimLayerType.FX:
- name = "Face";
- break;
- case VRCAvatarDescriptor.AnimLayerType.TPose:
- name = "UtilityTPose";
- break;
- case VRCAvatarDescriptor.AnimLayerType.IKPose:
- name = "UtilityIKPose";
- break;
- default:
- name = null;
- break;
- }
-
- if (name != null)
- {
- name = "/vrc_AvatarV3" + name + "Layer.controller";
-
- controller = AssetDatabase.LoadAssetAtPath(SAMPLE_PATH_PACKAGE + name);
- if (controller == null)
- {
- controller = AssetDatabase.LoadAssetAtPath(SAMPLE_PATH_LEGACY + name);
- }
- }
- }
-
- return controller;
- }
-#endif
-
- public static bool IsProxyAnimation(this Motion m)
- {
- var path = AssetDatabase.GetAssetPath(m);
-
- // This is a fairly wide condition in order to deal with:
- // 1. Future additions of proxy animations (so GUIDs are out)
- // 2. Unitypackage based installations of the VRCSDK
- // 3. VCC based installations of the VRCSDK
- // 4. Very old VCC based installations of the VRCSDK where proxy animations were copied into Assets
- return path.Contains("/AV3 Demo Assets/Animation/ProxyAnim/proxy")
- || path.Contains("/VRCSDK/Examples3/Animation/ProxyAnim/proxy")
- || path.StartsWith("Packages/com.vrchat.");
- }
-
-
- ///
- /// Enumerates all state machines and sub-state machines starting from a specific starting ASM
- ///
- ///
- ///
- internal static IEnumerable ReachableStateMachines(this AnimatorStateMachine asm)
- {
- HashSet visitedStateMachines = new HashSet();
- Queue pending = new Queue();
-
- pending.Enqueue(asm);
-
- while (pending.Count > 0)
- {
- var next = pending.Dequeue();
- if (visitedStateMachines.Contains(next)) continue;
- visitedStateMachines.Add(next);
-
- foreach (var child in next.stateMachines)
- {
- if (child.stateMachine != null) pending.Enqueue(child.stateMachine);
- }
-
- yield return next;
- }
- }
- }
-}
\ No newline at end of file
diff --git a/Editor/Animation/AnimationUtil.cs.meta b/Editor/Animation/AnimationUtil.cs.meta
deleted file mode 100644
index 53df83a0..00000000
--- a/Editor/Animation/AnimationUtil.cs.meta
+++ /dev/null
@@ -1,3 +0,0 @@
-fileFormatVersion: 2
-guid: af583e8ac3104fa4f8466741614219a0
-timeCreated: 1691238553
\ No newline at end of file
diff --git a/Editor/Animation/AnimatorCombiner.cs b/Editor/Animation/AnimatorCombiner.cs
deleted file mode 100644
index ea886afa..00000000
--- a/Editor/Animation/AnimatorCombiner.cs
+++ /dev/null
@@ -1,625 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2022 bd_
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#region
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using nadena.dev.modular_avatar.editor.ErrorReporting;
-using nadena.dev.ndmf;
-using nadena.dev.ndmf.util;
-using UnityEditor;
-using UnityEditor.Animations;
-using UnityEngine;
-using Object = UnityEngine.Object;
-
-#if MA_VRCSDK3_AVATARS
-using VRC.SDK3.Avatars.Components;
-using VRC.SDKBase;
-#endif
-
-#endregion
-
-namespace nadena.dev.modular_avatar.animation
-{
- internal class AnimatorCombiner
- {
- private readonly BuildContext _context;
- private readonly AnimatorController _combined;
-
- private readonly DeepClone _deepClone;
-
- private List _layers = new List();
-
- private Dictionary _parameters =
- new Dictionary();
-
- private Dictionary _parameterSource =
- new Dictionary();
-
- private Dictionary, Motion> _motions =
- new Dictionary, Motion>();
-
- private Dictionary, AnimatorStateMachine> _stateMachines =
- new Dictionary, AnimatorStateMachine>();
-
- private Dictionary