diff --git a/Editor/MergeAnimatorProcessor.cs b/Editor/MergeAnimatorProcessor.cs index 223cfde7..50efd939 100644 --- a/Editor/MergeAnimatorProcessor.cs +++ b/Editor/MergeAnimatorProcessor.cs @@ -236,8 +236,10 @@ namespace nadena.dev.modular_avatar.core.editor } } - private bool? ProbeWriteDefaults(AnimatorController controller) + internal static bool? ProbeWriteDefaults(AnimatorController controller) { + if (controller == null) return null; + bool hasWDOn = false; bool hasWDOff = false; diff --git a/Editor/ReactiveObjects/AnimationGeneration/ReactiveObjectPass.cs b/Editor/ReactiveObjects/AnimationGeneration/ReactiveObjectPass.cs index b3e49145..793fba66 100644 --- a/Editor/ReactiveObjects/AnimationGeneration/ReactiveObjectPass.cs +++ b/Editor/ReactiveObjects/AnimationGeneration/ReactiveObjectPass.cs @@ -25,6 +25,7 @@ namespace nadena.dev.modular_avatar.core.editor private HashSet activeProps = new(); private AnimationClip _initialStateClip; + private bool _writeDefaults; public ReactiveObjectPass(ndmf.BuildContext context) { @@ -33,6 +34,10 @@ namespace nadena.dev.modular_avatar.core.editor internal void Execute() { + // Having a WD OFF layer after WD ON layers can break WD. We match the behavior of the existing states, + // and if mixed, use WD ON to maximize compatibility. + _writeDefaults = MergeAnimatorProcessor.ProbeWriteDefaults(FindFxController().animatorController as AnimatorController) ?? true; + var analysis = new ReactiveObjectAnalyzer(context).Analyze(context.AvatarRootObject); var shapes = analysis.Shapes; @@ -277,7 +282,7 @@ namespace nadena.dev.modular_avatar.core.editor var initial = new AnimationClip(); var initialState = new AnimatorState(); initialState.motion = initial; - initialState.writeDefaultValues = false; + initialState.writeDefaultValues = _writeDefaults; initialState.name = ""; asm.defaultState = initialState; @@ -349,7 +354,7 @@ namespace nadena.dev.modular_avatar.core.editor state.name = group.ControllingConditions[0].DebugName.Replace(".", "_"); state.motion = clip; - state.writeDefaultValues = false; + state.writeDefaultValues = _writeDefaults; states.Add(new ChildAnimatorState { position = new Vector3(x, y), @@ -525,13 +530,13 @@ namespace nadena.dev.modular_avatar.core.editor private void ApplyController(AnimatorStateMachine asm, string layerName) { - var fx = context.AvatarDescriptor.baseAnimationLayers - .FirstOrDefault(l => l.type == VRCAvatarDescriptor.AnimLayerType.FX); + var fx = FindFxController(); + if (fx.animatorController == null) { throw new InvalidOperationException("No FX layer found"); } - + if (!context.IsTemporaryAsset(fx.animatorController)) { throw new InvalidOperationException("FX layer is not a temporary asset"); @@ -567,5 +572,13 @@ namespace nadena.dev.modular_avatar.core.editor } ).ToArray(); } + + private VRCAvatarDescriptor.CustomAnimLayer FindFxController() + { + var fx = context.AvatarDescriptor.baseAnimationLayers + .FirstOrDefault(l => l.type == VRCAvatarDescriptor.AnimLayerType.FX); + + return fx; + } } }