Skip to content

Commit

Permalink
more cleanup for rig/humanoid exporting
Browse files Browse the repository at this point in the history
  • Loading branch information
hybridherbst committed Mar 3, 2023
1 parent 286fe8b commit bbf31ae
Showing 1 changed file with 40 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,6 @@
using UnityEditor;
#endif

#if HAVE_ANIMATIONRIGGING
using UnityEngine.Animations.Rigging;
#endif

namespace UnityGLTF
{
public partial class GLTFSceneExporter
Expand All @@ -34,15 +30,20 @@ internal void CollectClipCurvesBySampling(GameObject root, AnimationClip clip, D
var playableGraph = PlayableGraph.Create();
var animationClipPlayable = (Playable) AnimationClipPlayable.Create(playableGraph, clip);

#if HAVE_ANIMATIONRIGGING
var rig = root.GetComponent<RigBuilder>();
if (rig)
var rigs = root.GetComponents<IAnimationWindowPreview>();
if (rigs != null)
{
rig.StopPreview(); // seems to be needed in some cases because the Rig isn't properly marked as non-initialized by Unity
rig.Clear();
animationClipPlayable = rig.BuildPreviewGraph(playableGraph, animationClipPlayable); // modifies the playable to include Animation Rigging data
foreach (var rig in rigs)
{
rig.StopPreview(); // seems to be needed in some cases because the Rig isn't properly marked as non-initialized by Unity
rig.StartPreview();
animationClipPlayable = rig.BuildPreviewGraph(playableGraph, animationClipPlayable); // modifies the playable to include Animation Rigging data
}
}
else
{
rigs = System.Array.Empty<IAnimationWindowPreview>();
}
#endif

var playableOutput = AnimationPlayableOutput.Create(playableGraph, "Animation", root.GetComponent<Animator>());
playableOutput.SetSourcePlayable(animationClipPlayable);
Expand All @@ -67,6 +68,7 @@ internal void CollectClipCurvesBySampling(GameObject root, AnimationClip clip, D
// limitations of AnimationMode - otherwise prefab modifications will persist...
var isPrefabAsset = PrefabUtility.IsPartOfPrefabAsset(root);
var prefabModifications = isPrefabAsset ? PrefabUtility.GetPropertyModifications(root) : default;
Undo.RegisterFullObjectHierarchyUndo(root, "Animation Sampling");

// add the root since we need to shift it around -
// it will be reset when exiting AnimationMode again and will not be dirty.
Expand All @@ -81,47 +83,59 @@ internal void CollectClipCurvesBySampling(GameObject root, AnimationClip clip, D
}

// first frame
foreach (var rig in rigs) rig.UpdatePreviewGraph(playableGraph);
AnimationMode.SamplePlayableGraph(playableGraph, 0, time);
#if HAVE_ANIMATIONRIGGING
rig.UpdatePreviewGraph(playableGraph);
#endif

// for Animation Rigging its often desired to have one complete loop first, so we need to prewarm to have a nice exportable animation
var prewarm = rigs.Length > 0 && clip.isLooping;
if (prewarm)
{
while (time + timeStep < length)
{
time += timeStep;
foreach (var rig in rigs) rig.UpdatePreviewGraph(playableGraph);
AnimationMode.SamplePlayableGraph(playableGraph, 0, time);
}

// reset time to the start
time = 0;
}

recorder.StartRecording(time);

while (time + timeStep < length)
{
time += timeStep;
foreach (var rig in rigs) rig.UpdatePreviewGraph(playableGraph);
AnimationMode.SamplePlayableGraph(playableGraph, 0, time);
#if HAVE_ANIMATIONRIGGING
rig.UpdatePreviewGraph(playableGraph);
#endif
recorder.UpdateRecording(time);
}

// last frame
time = length;
AnimationMode.SampleAnimationClip(root, clip, time);
foreach (var rig in rigs) rig.UpdatePreviewGraph(playableGraph);
AnimationMode.SamplePlayableGraph(playableGraph, 0, time);
recorder.UpdateRecording(time);

foreach (var rig in rigs) rig.StopPreview();

AnimationMode.EndSampling();
#if UNITY_2020_1_OR_NEWER
AnimationMode.StopAnimationMode(driver);
#else
AnimationMode.StopAnimationMode();
#endif

#if HAVE_ANIMATIONRIGGING
if (rig)
{
rig.StopPreview();
rig.Clear();
}
#endif

// reset prefab modifications if this was a prefab asset
if (isPrefabAsset) {
PrefabUtility.SetPropertyModifications(root, prefabModifications);
}

// seems to be necessary because the animation sampling API doesn't fully work;
// sometimes samples still "leak" into property modifications
Undo.FlushUndoRecordObjects();
Undo.PerformUndo();

recorder.EndRecording(out var data);
if (data == null || !data.Any()) return;

Expand Down

0 comments on commit bbf31ae

Please sign in to comment.