Fix stack overflow when using recursion with nested scene animations
#519
This commit is contained in:
@@ -26,6 +26,7 @@ namespace FlaxEditor.GUI.Timeline
|
|||||||
|
|
||||||
private SceneAnimationPlayer _player;
|
private SceneAnimationPlayer _player;
|
||||||
private bool _showSelected3dTrack = true;
|
private bool _showSelected3dTrack = true;
|
||||||
|
internal Guid _id;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the animation player actor used for the timeline preview.
|
/// Gets or sets the animation player actor used for the timeline preview.
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using FlaxEngine;
|
using FlaxEngine;
|
||||||
|
|
||||||
namespace FlaxEditor.GUI.Timeline.Tracks
|
namespace FlaxEditor.GUI.Timeline.Tracks
|
||||||
@@ -122,5 +123,22 @@ namespace FlaxEditor.GUI.Timeline.Tracks
|
|||||||
: base(ref options)
|
: base(ref options)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void OnAssetChanged()
|
||||||
|
{
|
||||||
|
if (Asset)
|
||||||
|
{
|
||||||
|
var refs = Asset.GetReferences();
|
||||||
|
var id = ((SceneAnimationTimeline)Timeline)._id;
|
||||||
|
if (Asset.ID == id || refs.Contains(id))
|
||||||
|
{
|
||||||
|
Asset = null;
|
||||||
|
throw new Exception("Cannot use nested scene animation (recursion).");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
base.OnAssetChanged();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -852,6 +852,7 @@ namespace FlaxEditor.Windows.Assets
|
|||||||
_isWaitingForTimelineLoad = false;
|
_isWaitingForTimelineLoad = false;
|
||||||
|
|
||||||
// Load timeline data from the asset
|
// Load timeline data from the asset
|
||||||
|
_timeline._id = OriginalAsset.ID;
|
||||||
_timeline.Load(_asset);
|
_timeline.Load(_asset);
|
||||||
|
|
||||||
// Setup
|
// Setup
|
||||||
|
|||||||
@@ -192,7 +192,8 @@ void SceneAnimationPlayer::Tick(float dt)
|
|||||||
_cameraCutCam = nullptr;
|
_cameraCutCam = nullptr;
|
||||||
|
|
||||||
// Tick the animation
|
// Tick the animation
|
||||||
Tick(anim, time, dt, 0);
|
CallStack callStack;
|
||||||
|
Tick(anim, time, dt, 0, callStack);
|
||||||
#if !BUILD_RELEASE
|
#if !BUILD_RELEASE
|
||||||
if (_tracksDataStack.Count() != 0)
|
if (_tracksDataStack.Count() != 0)
|
||||||
{
|
{
|
||||||
@@ -486,9 +487,12 @@ bool SceneAnimationPlayer::TickPropertyTrack(int32 trackIndex, int32 stateIndexO
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneAnimationPlayer::Tick(SceneAnimation* anim, float time, float dt, int32 stateIndexOffset)
|
void SceneAnimationPlayer::Tick(SceneAnimation* anim, float time, float dt, int32 stateIndexOffset, CallStack& callStack)
|
||||||
{
|
{
|
||||||
const float fps = anim->FramesPerSecond;
|
const float fps = anim->FramesPerSecond;
|
||||||
|
#if !BUILD_RELEASE || USE_EDITOR
|
||||||
|
callStack.Add(anim);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Update all tracks
|
// Update all tracks
|
||||||
for (int32 j = 0; j < anim->Tracks.Count(); j++)
|
for (int32 j = 0; j < anim->Tracks.Count(); j++)
|
||||||
@@ -546,7 +550,20 @@ void SceneAnimationPlayer::Tick(SceneAnimation* anim, float time, float dt, int3
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Tick(nestedAnim, mediaTime, dt, stateIndexOffset);
|
#if !BUILD_RELEASE || USE_EDITOR
|
||||||
|
// Validate recursive call
|
||||||
|
if (callStack.Contains(nestedAnim))
|
||||||
|
{
|
||||||
|
LOG(Warning,
|
||||||
|
"Recursive nested scene animation. Animation {0} for nested track {1} on actor {2}.",
|
||||||
|
callStack.Last()->ToString(),
|
||||||
|
nestedAnim->ToString(),
|
||||||
|
ToString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Tick(nestedAnim, mediaTime, dt, stateIndexOffset, callStack);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -202,7 +202,8 @@ private:
|
|||||||
|
|
||||||
void Restore(SceneAnimation* anim, int32 stateIndexOffset);
|
void Restore(SceneAnimation* anim, int32 stateIndexOffset);
|
||||||
bool TickPropertyTrack(int32 trackIndex, int32 stateIndexOffset, SceneAnimation* anim, float time, const SceneAnimation::Track& track, TrackInstance& state, void* target);
|
bool TickPropertyTrack(int32 trackIndex, int32 stateIndexOffset, SceneAnimation* anim, float time, const SceneAnimation::Track& track, TrackInstance& state, void* target);
|
||||||
void Tick(SceneAnimation* anim, float time, float dt, int32 stateIndexOffset);
|
typedef Array<SceneAnimation*, FixedAllocation<8>> CallStack;
|
||||||
|
void Tick(SceneAnimation* anim, float time, float dt, int32 stateIndexOffset, CallStack& callStack);
|
||||||
void Tick();
|
void Tick();
|
||||||
void OnAnimationModified();
|
void OnAnimationModified();
|
||||||
void ResetState();
|
void ResetState();
|
||||||
|
|||||||
Reference in New Issue
Block a user