void FMovieSceneSequenceInstance::RefreshInstance( IMovieScenePlayer& Player )
{
	if(MovieSceneSequence.IsValid())
	{
		UMovieScene* MovieScene = MovieSceneSequence->GetMovieScene();
		TimeRange = MovieScene->GetPlaybackRange();

		UMovieSceneTrack* CameraCutTrack = MovieScene->GetCameraCutTrack();

		if (CameraCutTrack != nullptr)
		{
			FMovieSceneInstanceMap CameraCutTrackInstanceMap;

			if (CameraCutTrackInstance.IsValid())
			{
				CameraCutTrackInstanceMap.Add(CameraCutTrack, CameraCutTrackInstance);
			}

			TArray<TWeakObjectPtr<UObject>> Objects;
			TArray<UMovieSceneTrack*> Tracks;
			Tracks.Add(CameraCutTrack);
			RefreshInstanceMap(Tracks, Objects, CameraCutTrackInstanceMap, Player);

			CameraCutTrackInstance = CameraCutTrackInstanceMap.FindRef(CameraCutTrack);
		}
		else if(CameraCutTrackInstance.IsValid())
		{
			CameraCutTrackInstance->ClearInstance(Player, *this);
			CameraCutTrackInstance.Reset();
		}

		// Get all the master tracks and create instances for them if needed
		const TArray<UMovieSceneTrack*>& MasterTracks = MovieScene->GetMasterTracks();
		TArray<TWeakObjectPtr<UObject>> Objects;
		RefreshInstanceMap( MasterTracks, Objects, MasterTrackInstances, Player );

		TSet< FGuid > FoundObjectBindings;
		// Get all tracks for each object binding and create instances for them if needed
		const TArray<FMovieSceneBinding>& ObjectBindings = MovieScene->GetBindings();
		for( int32 BindingIndex = 0; BindingIndex < ObjectBindings.Num(); ++BindingIndex )
		{
			const FMovieSceneBinding& ObjectBinding = ObjectBindings[BindingIndex];

			// Create an instance for this object binding
			FMovieSceneObjectBindingInstance& BindingInstance = ObjectBindingInstances.FindOrAdd( ObjectBinding.GetObjectGuid() );
			BindingInstance.ObjectGuid = ObjectBinding.GetObjectGuid();

			FoundObjectBindings.Add( ObjectBinding.GetObjectGuid() );

			// Populate the runtime objects for this instance of the binding.
			// @todo sequencer: SubSequences: We need to know which actors were removed and which actors were added so we know which saved actor state to restore/create
			BindingInstance.RuntimeObjects.Empty();
			Player.GetRuntimeObjects( SharedThis( this ), BindingInstance.ObjectGuid, BindingInstance.RuntimeObjects );

			// Refresh the instance's tracks
			const TArray<UMovieSceneTrack*>& Tracks = ObjectBinding.GetTracks();
			RefreshInstanceMap( Tracks, BindingInstance.RuntimeObjects, BindingInstance.TrackInstances, Player );
		}

		IMovieSceneSpawnRegister& SpawnRegister = Player.GetSpawnRegister();

		// Remove object binding instances which are no longer bound
		TMap<FGuid, FMovieSceneObjectBindingInstance>::TIterator It = ObjectBindingInstances.CreateIterator();
		for( ; It; ++It )
		{
			if( !FoundObjectBindings.Contains( It.Key() ) )
			{
				SpawnRegister.DestroySpawnedObject(It.Key(), *this, Player);

				// The instance no longer is bound to an existing guid
				It.RemoveCurrent();
			}
		}
	}
}
Ejemplo n.º 2
0
void FSequencerNodeTree::Update()
{
	// @todo Sequencer - This update pass is too aggressive.  Some nodes may still be valid
	Empty();

	UMovieScene* MovieScene = Sequencer.GetFocusedMovieSceneSequence()->GetMovieScene();

	TArray< TSharedRef<FSequencerDisplayNode> > NewRootNodes;

	// Get the master tracks  so we can get sections from them
	const TArray<UMovieSceneTrack*>& MasterTracks = MovieScene->GetMasterTracks();

	for( UMovieSceneTrack* Track : MasterTracks )
	{
		UMovieSceneTrack& TrackRef = *Track;

		TSharedRef<FTrackNode> SectionNode = MakeShareable( new FTrackNode( TrackRef.GetTrackName(), TrackRef, NULL, *this ) );
		NewRootNodes.Add( SectionNode );
	
		MakeSectionInterfaces( TrackRef, SectionNode );

		SectionNode->PinNode();
	}


	const TArray<FMovieSceneBinding>& Bindings = MovieScene->GetBindings();

	TMap<FGuid, const FMovieSceneBinding*> GuidToBindingMap;
	for (const FMovieSceneBinding& Binding : Bindings)
	{
		GuidToBindingMap.Add(Binding.GetObjectGuid(), &Binding);
	}

	// Make nodes for all object bindings
	TArray< TSharedRef<FSequencerDisplayNode> > NewObjectNodes;
	for( const FMovieSceneBinding& Binding : Bindings )
	{
		TSharedRef<FObjectBindingNode> ObjectBindingNode = AddObjectBinding( Binding.GetName(), Binding.GetObjectGuid(), GuidToBindingMap, NewObjectNodes );

		const TArray<UMovieSceneTrack*>& Tracks = Binding.GetTracks();

		for( UMovieSceneTrack* Track : Tracks )
		{
			UMovieSceneTrack& TrackRef = *Track;

			FName SectionName = TrackRef.GetTrackName();
			check( SectionName != NAME_None );

			TSharedRef<FTrackNode> SectionAreaNode = ObjectBindingNode->AddSectionAreaNode( SectionName, TrackRef );
			MakeSectionInterfaces( TrackRef, SectionAreaNode );
		}
	}

	struct FObjectNodeSorter
	{
		bool operator()( const TSharedRef<FSequencerDisplayNode>& A, const TSharedRef<FSequencerDisplayNode>& B ) const
		{
			if (A->GetType() == ESequencerNode::Object && B->GetType() != ESequencerNode::Object)
			{
				return true;
			}
			if (A->GetType() != ESequencerNode::Object && B->GetType() == ESequencerNode::Object)
			{
				return false;
			}
			return A->GetDisplayName().ToString() < B->GetDisplayName().ToString();
		}
	};

	NewObjectNodes.Sort( FObjectNodeSorter() );
	for (TSharedRef<FSequencerDisplayNode> NewObjectNode : NewObjectNodes)
	{
		NewObjectNode->SortChildNodes(FObjectNodeSorter());
	}

	NewRootNodes.Append(NewObjectNodes);

	// Look for a shot track.  It will always come first if it exists
	UMovieSceneTrack* ShotTrack = MovieScene->GetShotTrack();
	if( ShotTrack )
	{
		TSharedRef<FTrackNode> SectionNode = MakeShareable( new FTrackNode( ShotTrack->GetTrackName(), *ShotTrack, NULL, *this ) );

		// Shot track always comes first
		RootNodes.Add( SectionNode );

		MakeSectionInterfaces( *ShotTrack, SectionNode );

		SectionNode->PinNode();
	}

	// Add all other nodes after the shot track
	RootNodes.Append( NewRootNodes );

	// Set up virtual offsets, and expansion states
	float VerticalOffset = 0.f;
	for (auto& Node : RootNodes)
	{
		Node->Traverse_ParentFirst([&](FSequencerDisplayNode& InNode){

			float VerticalTop = VerticalOffset;
			VerticalOffset += InNode.GetNodeHeight() + InNode.GetNodePadding().Combined();
			InNode.Initialize(VerticalTop, VerticalOffset);
			return true;
		});

	}

	// Re-filter the tree after updating 
	// @todo Sequencer - Newly added sections may need to be visible even when there is a filter
	FilterNodes( FilterString );
}