Fix (missing) timeline tracks + lost editable properties on 2nd scene load
FindActorById now skips stale TWeakObjectPtr entries instead of returning the first null match, RegisterActorId prunes stale + same-GUID entries before adding, and Clear() resets the ActorIds map so a fresh scenario starts with no ghost references. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -300,6 +300,10 @@ void UPS_Editor_TimelineSubsystem::Clear()
|
|||||||
bIsPlaying = false;
|
bIsPlaying = false;
|
||||||
LastAppliedValues.Empty();
|
LastAppliedValues.Empty();
|
||||||
PrePlayBaseline.Reset();
|
PrePlayBaseline.Reset();
|
||||||
|
// Drop the old ActorIds — the previous scenario's actors have been destroyed and the
|
||||||
|
// weak references are now stale. Keeping them around confuses FindActorById when the
|
||||||
|
// next scenario happens to reuse the same FGuid (it can return a stale null entry).
|
||||||
|
ActorIds.Reset();
|
||||||
OnTimelineChanged.Broadcast();
|
OnTimelineChanged.Broadcast();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -570,11 +574,18 @@ FGuid UPS_Editor_TimelineSubsystem::FindActorId(AActor* Actor) const
|
|||||||
AActor* UPS_Editor_TimelineSubsystem::FindActorById(const FGuid& Id) const
|
AActor* UPS_Editor_TimelineSubsystem::FindActorById(const FGuid& Id) const
|
||||||
{
|
{
|
||||||
if (!Id.IsValid()) return nullptr;
|
if (!Id.IsValid()) return nullptr;
|
||||||
|
// Iterate every pair: the map can legitimately contain stale weak references from a
|
||||||
|
// previous scenario whose actors were destroyed. Without this check the first match on
|
||||||
|
// GUID can return a null key before we reach the live entry, giving "(missing)" after
|
||||||
|
// the second load of the same scenario.
|
||||||
for (const TPair<TWeakObjectPtr<AActor>, FGuid>& Pair : ActorIds)
|
for (const TPair<TWeakObjectPtr<AActor>, FGuid>& Pair : ActorIds)
|
||||||
{
|
{
|
||||||
if (Pair.Value == Id)
|
if (Pair.Value == Id)
|
||||||
{
|
{
|
||||||
return Pair.Key.Get();
|
if (AActor* Live = Pair.Key.Get())
|
||||||
|
{
|
||||||
|
return Live;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -583,6 +594,16 @@ AActor* UPS_Editor_TimelineSubsystem::FindActorById(const FGuid& Id) const
|
|||||||
void UPS_Editor_TimelineSubsystem::RegisterActorId(AActor* Actor, const FGuid& Id)
|
void UPS_Editor_TimelineSubsystem::RegisterActorId(AActor* Actor, const FGuid& Id)
|
||||||
{
|
{
|
||||||
if (!Actor || !Id.IsValid()) return;
|
if (!Actor || !Id.IsValid()) return;
|
||||||
|
// Prune any stale entries plus any previous entry holding the same GUID (the old actor
|
||||||
|
// has been destroyed and replaced by this one). Keeps the map tight and ensures
|
||||||
|
// FindActorById cannot hit a ghost key with the same GUID.
|
||||||
|
for (auto It = ActorIds.CreateIterator(); It; ++It)
|
||||||
|
{
|
||||||
|
if (!It.Key().IsValid() || It.Value() == Id)
|
||||||
|
{
|
||||||
|
It.RemoveCurrent();
|
||||||
|
}
|
||||||
|
}
|
||||||
ActorIds.Add(TWeakObjectPtr<AActor>(Actor), Id);
|
ActorIds.Add(TWeakObjectPtr<AActor>(Actor), Id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user