void FSubMovieSceneTrackInstance::Update( float Position, float LastPosition, const TArray<UObject*>& RuntimeObjects, class IMovieScenePlayer& Player ) 
{
	const TArray<UMovieSceneSection*>& AllSections = SubMovieSceneTrack->GetAllSections();

	TArray<UMovieSceneSection*> TraversedSections = MovieSceneHelpers::GetTraversedSections( AllSections, Position, LastPosition );

	for( int32 SectionIndex = 0; SectionIndex < TraversedSections.Num(); ++SectionIndex )
	{
		USubMovieSceneSection* Section = CastChecked<USubMovieSceneSection>( TraversedSections[SectionIndex] );

		TSharedPtr<FMovieSceneSequenceInstance> Instance = SubMovieSceneInstances.FindRef( Section );

		FMovieSceneSequenceInstance* InstancePtr = Instance.Get();

		if( InstancePtr )
		{
			TRange<float> TimeRange = InstancePtr->GetMovieSceneTimeRange();

			// Position for the movie scene needs to be in local space
			float LocalDelta = TimeRange.GetLowerBoundValue() - Section->GetStartTime();
			float LocalPosition = Position + LocalDelta;


			InstancePtr->Update(LocalPosition, LastPosition + LocalDelta, Player);
		}
	}

}
void FMovieSceneSpawnTrackInstance::Update(EMovieSceneUpdateData& UpdateData, const TArray<TWeakObjectPtr<UObject>>& RuntimeObjects, IMovieScenePlayer& Player, FMovieSceneSequenceInstance& SequenceInstance)
{
	IMovieSceneSpawnRegister& SpawnRegister = Player.GetSpawnRegister();
	FMovieSceneSpawnable* Spawnable = SequenceInstance.GetSequence()->GetMovieScene()->FindSpawnable(Track->GetObjectId());

	TRange<float> Range = SequenceInstance.GetTimeRange();

	const bool bIsPreview = Player.IsPreview();

	// If we're evaluating outside of the instance's time range, and the sequence owns the spawnable, there's no reason to evaluate - it should already be destroyed
	if (Spawnable && Spawnable->GetSpawnOwnership() == ESpawnOwnership::InnerSequence && !Range.Contains(UpdateData.Position))
	{
		bool bDestroy = true;
#if WITH_EDITORONLY_DATA
		bDestroy = !Spawnable->ShouldIgnoreOwnershipInEditor();
		// Don't destroy cameras while previewing
		if (bIsPreview && MovieSceneHelpers::CameraComponentFromActor(Cast<AActor>(Spawnable->GetObjectTemplate())))
		{
			bDestroy = false;
		}
#endif
		if (bDestroy)
		{
			SpawnRegister.DestroySpawnedObject(Track->GetObjectId(), SequenceInstance, Player);
			return;
		}
	}

	bool bIsSpawned = false;
	if (Track->Eval(UpdateData.Position, UpdateData.LastPosition, bIsSpawned))
	{
		// Spawn the object if needed
		if (bIsSpawned && RuntimeObjects.Num() == 0)
		{
			SpawnRegister.SpawnObject(Track->GetObjectId(), SequenceInstance, Player);
		}

		// Destroy the object if needed
		if (!bIsSpawned && RuntimeObjects.Num() != 0)
		{
			SpawnRegister.DestroySpawnedObject(Track->GetObjectId(), SequenceInstance, Player);
		}
	}
}
void FMovieSceneActorReferenceTrackInstance::Update(EMovieSceneUpdateData& UpdateData, const TArray<TWeakObjectPtr<UObject>>& RuntimeObjects, class IMovieScenePlayer& Player, FMovieSceneSequenceInstance& SequenceInstance ) 
{
	// TODO: Support default values.
	FGuid ActorReferenceGuid;
	if( ActorReferenceTrack->Eval( UpdateData.Position, UpdateData.LastPosition, ActorReferenceGuid ) )
	{
		AActor* CurrentActor = nullptr;
		if (GuidToActorCache.Contains(ActorReferenceGuid))
		{
			TWeakObjectPtr<AActor> CachedActor = *GuidToActorCache.Find(ActorReferenceGuid);
			if (CachedActor.IsValid())
			{
				CurrentActor = CachedActor.Get();
			}
		}

		if (CurrentActor == nullptr)
		{
			TArray<TWeakObjectPtr<UObject>> RuntimeObjectsForGuid;
			Player.GetRuntimeObjects(SequenceInstance.AsShared(), ActorReferenceGuid, RuntimeObjectsForGuid);
	
			if (RuntimeObjectsForGuid.Num() == 1)
			{
				AActor* ActorForGuid = Cast<AActor>(RuntimeObjectsForGuid[0].Get());

				if (ActorForGuid != nullptr)
				{
					CurrentActor = ActorForGuid;
					if (CurrentActor != nullptr)
					{
						GuidToActorCache.Add(ActorReferenceGuid, CurrentActor);
					}
				}
			}
		}

		if (CurrentActor != nullptr)
		{
			for (auto ObjectPtr : RuntimeObjects)
			{
				UObject* Object = ObjectPtr.Get();
				PropertyBindings->CallFunction<AActor*>(Object, &CurrentActor);
			}
		}
	}
}
void FMovieSceneActorReferenceTrackInstance::Update(EMovieSceneUpdateData& UpdateData, const TArray<TWeakObjectPtr<UObject>>& RuntimeObjects, class IMovieScenePlayer& Player, FMovieSceneSequenceInstance& SequenceInstance ) 
{
	
	FGuid ActorReferenceGuid;
	if( ActorReferenceTrack->Eval( UpdateData.Position, UpdateData.LastPosition, ActorReferenceGuid ) )
	{
		AActor* CurrentActor;
		AActor** CachedActorPtr = GuidToActorCache.Find( ActorReferenceGuid );

		if (CachedActorPtr != nullptr)
		{
			CurrentActor = *CachedActorPtr;
		}
		else
		{
			TArray<TWeakObjectPtr<UObject>> RuntimeObjectsForGuid;
			Player.GetRuntimeObjects(SequenceInstance.AsShared(), ActorReferenceGuid, RuntimeObjectsForGuid);
	
			if (RuntimeObjectsForGuid.Num() == 1)
			{
				AActor* ActorForGuid = Cast<AActor>(RuntimeObjectsForGuid[0].Get());

				if (ActorForGuid != nullptr)
				{
					CurrentActor = ActorForGuid;
					GuidToActorCache.Add(ActorReferenceGuid, CurrentActor);
				}
			}
		}

		for (auto ObjectPtr : RuntimeObjects)
		{
			UObject* Object = ObjectPtr.Get();
			PropertyBindings->CallFunction<AActor*>(Object, &CurrentActor);
		}
	}
}