void FSlomoTrackEditor::HandleAddSlomoTrackMenuEntryExecute()
{
	UMovieScene* MovieScene = GetFocusedMovieScene();

	if (MovieScene == nullptr)
	{
		return;
	}

	UMovieSceneTrack* SlomoTrack = MovieScene->FindMasterTrack<UMovieSceneSlomoTrack>();

	if (SlomoTrack != nullptr)
	{
		return;
	}

	const FScopedTransaction Transaction(NSLOCTEXT("Sequencer", "AddSlomoTrack_Transaction", "Add Play Rate Track"));

	MovieScene->Modify();
		
	SlomoTrack = FindOrCreateMasterTrack<UMovieSceneSlomoTrack>().Track;
	ensure(SlomoTrack);

	UMovieSceneSection* NewSection = SlomoTrack->CreateNewSection();
	ensure(NewSection);

	SlomoTrack->AddSection(*NewSection);

	GetSequencer()->NotifyMovieSceneDataChanged();
}
Ejemplo n.º 2
0
void FSequencer::DeleteSection(class UMovieSceneSection* Section)
{
	UMovieScene* MovieScene = GetFocusedMovieScene();
	
	bool bAnythingRemoved = false;

	UMovieSceneTrack* Track = CastChecked<UMovieSceneTrack>( Section->GetOuter() );

	// If this check fails then the section is outered to a type that doesnt know about the section
	//checkSlow( Track->HasSection(Section) );
	
	Track->SetFlags( RF_Transactional );

	FScopedTransaction DeleteSectionTransaction( NSLOCTEXT("Sequencer", "DeleteSection_Transaction", "Delete Section") );
	
	Track->Modify();

	Track->RemoveSection(Section);

	bAnythingRemoved = true;
	
	if( bAnythingRemoved )
	{
		UpdateRuntimeInstances();
	}
}
Ejemplo n.º 3
0
void FSequencer::FilterToShotSections(const TArray< TWeakObjectPtr<class UMovieSceneSection> >& ShotSections, bool bZoomToShotBounds )
{
	TArray< TWeakObjectPtr<UMovieSceneSection> > ActualShotSections;
	for (int32 i = 0; i < ShotSections.Num(); ++i)
	{
		if (ShotSections[i]->IsA<UMovieSceneShotSection>())
		{
			ActualShotSections.Add(ShotSections[i]);
		}
	}

	bool bWasPreviouslyFiltering = IsShotFilteringOn();
	bool bIsNowFiltering = ActualShotSections.Num() > 0;

	FilteringShots.Empty();
	UnfilterableSections.Empty();
	UnfilterableObjects.Empty();

	if (bIsNowFiltering)
	{
		for ( int32 ShotSectionIndex = 0; ShotSectionIndex < ActualShotSections.Num(); ++ShotSectionIndex )
		{
			FilteringShots.Add( ActualShotSections[ShotSectionIndex] );
		}

		// populate unfilterable shots - shots that started not filtered
		TArray< TWeakObjectPtr<class UMovieSceneSection> > TempUnfilterableSections;
		const TArray<UMovieSceneSection*>& AllSections = GetFocusedMovieScene()->GetAllSections();
		for (int32 SectionIndex = 0; SectionIndex < AllSections.Num(); ++SectionIndex)
		{
			UMovieSceneSection* Section = AllSections[SectionIndex];
			if (!Section->IsA<UMovieSceneShotSection>() && IsSectionVisible(Section))
			{
				TempUnfilterableSections.Add(Section);
			}
		}
		// wait until after we've collected them all before applying in order to
		// prevent wastefully searching through UnfilterableSections in IsSectionVisible
		UnfilterableSections = TempUnfilterableSections;
	}

	if (!bWasPreviouslyFiltering && bIsNowFiltering)
	{
		OverlayAnimation.Play( SequencerWidget.ToSharedRef() );
	}
	else if (bWasPreviouslyFiltering && !bIsNowFiltering) 
	{
		OverlayAnimation.PlayReverse( SequencerWidget.ToSharedRef() );
	}

	if( bZoomToShotBounds )
	{
		// zoom in
		OnViewRangeChanged(GetTimeBounds(), true);
	}

	SequencerWidget->UpdateBreadcrumbs(ActualShotSections);
}
Ejemplo n.º 4
0
void FSequencer::OnActorsDropped( const TArray<TWeakObjectPtr<AActor> >& Actors )
{
	bool bPossessableAdded = false;
	for( TWeakObjectPtr<AActor> WeakActor : Actors )
	{
		AActor* Actor = WeakActor.Get();
		if( Actor != NULL )
		{
			// Grab the MovieScene that is currently focused.  We'll add our Blueprint as an inner of the
			// MovieScene asset.
			UMovieScene* OwnerMovieScene = GetFocusedMovieScene();
			
			// @todo sequencer: Undo doesn't seem to be working at all
			const FScopedTransaction Transaction( LOCTEXT("UndoPossessingObject", "Possess Object with MovieScene") );
			
			// Possess the object!
			{
				// Create a new possessable
				OwnerMovieScene->Modify();
				
				const FGuid PossessableGuid = OwnerMovieScene->AddPossessable( Actor->GetActorLabel(), Actor->GetClass() );
				 
				if ( IsShotFilteringOn() )
				{
					AddUnfilterableObject(PossessableGuid);
				}
				
				ObjectBindingManager->BindPossessableObject( PossessableGuid, *Actor );
				
				bPossessableAdded = true;
			}
		}
	}
	
	if( bPossessableAdded )
	{
		SpawnOrDestroyPuppetObjects( GetFocusedMovieSceneInstance() );
		
		NotifyMovieSceneDataChanged();
	}
}
Ejemplo n.º 5
0
void FSequencer::AddSubMovieScene( UMovieScene* SubMovieScene )
{
	// @todo Sequencer - sub-moviescenes This should be moved to the sub-moviescene editor
	SubMovieScene->SetFlags( RF_Transactional );
	
	// Grab the MovieScene that is currently focused.  THis is the movie scene that will contain the sub-moviescene
	UMovieScene* OwnerMovieScene = GetFocusedMovieScene();

	// @todo sequencer: Undo doesn't seem to be working at all
	const FScopedTransaction Transaction( LOCTEXT("UndoAddingObject", "Add Object to MovieScene") );

	OwnerMovieScene->Modify();

	UMovieSceneTrack* Type = OwnerMovieScene->FindMasterTrack( USubMovieSceneTrack::StaticClass() ) ;
	if( !Type )
	{
		Type = OwnerMovieScene->AddMasterTrack( USubMovieSceneTrack::StaticClass() );
	}

	USubMovieSceneTrack* SubMovieSceneType = CastChecked<USubMovieSceneTrack>( Type );

	SubMovieSceneType->AddMovieSceneSection( SubMovieScene, ScrubPosition );
}
Ejemplo n.º 6
0
TRange<float> FSequencer::GetTimeBounds() const
{
	// When recording, we never want to constrain the time bound range.  You might not even have any sections or keys yet
	// but we need to be able to move the time cursor during playback so you can capture data in real-time
	if( PlaybackState == EMovieScenePlayerStatus::Recording )
	{
		return TRange<float>( -100000.0f, 100000.0f );
	}

	const UMovieScene* MovieScene = GetFocusedMovieScene();
	const UMovieSceneTrack* AnimatableShot = MovieScene->FindMasterTrack( UMovieSceneDirectorTrack::StaticClass() );
	if (AnimatableShot)
	{
		// try getting filtered shot boundaries
		TRange<float> Bounds = GetFilteringShotsTimeBounds();
		if (!Bounds.IsEmpty()) {return Bounds;}

		// try getting the bounds of all shots
		Bounds = AnimatableShot->GetSectionBoundaries();
		if (!Bounds.IsEmpty()) {return Bounds;}
	}
	
	return MovieScene->GetTimeRange();
}
Ejemplo n.º 7
0
FGuid FSequencer::AddSpawnableForAssetOrClass( UObject* Object, UObject* CounterpartGamePreviewObject )
{
	FGuid NewSpawnableGuid;
	
	if( ObjectBindingManager->AllowsSpawnableObjects() )
	{
		// Grab the MovieScene that is currently focused.  We'll add our Blueprint as an inner of the
		// MovieScene asset.
		UMovieScene* OwnerMovieScene = GetFocusedMovieScene();

		// @todo sequencer: Undo doesn't seem to be working at all
		const FScopedTransaction Transaction( LOCTEXT("UndoAddingObject", "Add Object to MovieScene") );

		// Use the class as the spawnable's name if this is an actor class, otherwise just use the object name (asset)
		const bool bIsActorClass = Object->IsA( AActor::StaticClass() ) && !Object->HasAnyFlags( RF_ArchetypeObject );
		const FName AssetName = bIsActorClass ? Object->GetClass()->GetFName() : Object->GetFName();

		// Inner objects don't need a name (it will be auto-generated by the UObject system), but we want one in this case
		// because the class of any actors that are created from this Blueprint may end up being user-facing.
		const FName BlueprintName = MakeUniqueObjectName( OwnerMovieScene, UBlueprint::StaticClass(), AssetName );

		// Use the asset name as the initial spawnable name
		const FString NewSpawnableName = AssetName.ToString();		// @todo sequencer: Need UI to allow user to rename these slots

		// Create our new blueprint!
		UBlueprint* NewBlueprint = NULL;
		{
			// @todo sequencer: Add support for forcing specific factories for an asset
			UActorFactory* FactoryToUse = NULL;
			if( bIsActorClass )
			{
				// Placing an actor class directly::
				FactoryToUse = GEditor->FindActorFactoryForActorClass( Object->GetClass() );
			}
			else
			{
				// Placing an asset
				FactoryToUse = FActorFactoryAssetProxy::GetFactoryForAssetObject( Object );
			}

			if( FactoryToUse != NULL )
			{
				// Create the blueprint
				NewBlueprint = FactoryToUse->CreateBlueprint( Object, OwnerMovieScene, BlueprintName );
			}
			else if( bIsActorClass )
			{
				// We don't have a factory, but we can still try to create a blueprint for this actor class
				NewBlueprint = FKismetEditorUtilities::CreateBlueprint( Object->GetClass(), OwnerMovieScene, BlueprintName, EBlueprintType::BPTYPE_Normal, UBlueprint::StaticClass(), UBlueprintGeneratedClass::StaticClass() );
			}
		}

		if( ensure( NewBlueprint != NULL ) )
		{
			if( NewBlueprint->GeneratedClass != NULL && FBlueprintEditorUtils::IsActorBased( NewBlueprint ) )
			{
				AActor* ActorCDO = CastChecked< AActor >( NewBlueprint->GeneratedClass->ClassDefaultObject );

				// If we have a counterpart object, then copy the properties from that object back into our blueprint's CDO
				// @todo sequencer livecapture: This isn't really good enough to handle complex actors.  The dynamically-spawned actor could have components that
				// were created in its construction script or via straight-up C++ code.  Instead what we should probably do is duplicate the PIE actor and generate
				// our CDO from that duplicate.  It could get pretty complex though.
				if( CounterpartGamePreviewObject != NULL )
				{
					AActor* CounterpartGamePreviewActor = CastChecked< AActor >( CounterpartGamePreviewObject );
					CopyActorProperties( CounterpartGamePreviewActor, ActorCDO );
				}
				else
				{
					// Place the new spawnable in front of the camera (unless we were automatically created from a PIE actor)
					PlaceActorInFrontOfCamera( ActorCDO );
				}
			}

			NewSpawnableGuid = OwnerMovieScene->AddSpawnable( NewSpawnableName, NewBlueprint, CounterpartGamePreviewObject );

			if (IsShotFilteringOn())
			{
				AddUnfilterableObject(NewSpawnableGuid);
			}
		}
	
	}

	return NewSpawnableGuid;
}
Ejemplo n.º 8
0
void FSequencer::OnRequestNodeDeleted( TSharedRef<const FSequencerDisplayNode>& NodeToBeDeleted )
{
	bool bAnySpawnablesRemoved = false;
	bool bAnythingRemoved = false;
	
	TSharedRef<FMovieSceneInstance> MovieSceneInstance = GetFocusedMovieSceneInstance();
	UMovieScene* OwnerMovieScene = MovieSceneInstance->GetMovieScene();

	// Only object nodes or section areas can be deleted
	if( NodeToBeDeleted->GetType() == ESequencerNode::Object  )
	{
		OwnerMovieScene->SetFlags( RF_Transactional );
		const FGuid& BindingToRemove = StaticCastSharedRef<const FObjectBindingNode>( NodeToBeDeleted )->GetObjectBinding();

		//@todo Sequencer - add transaction
		
		// Try to remove as a spawnable first
		bool bRemoved = OwnerMovieScene->RemoveSpawnable( BindingToRemove );
		if( bRemoved )
		{
			bAnySpawnablesRemoved = true;
		}

		if( !bRemoved )
		{
			// The guid should be associated with a possessable if it wasnt a spawnable
			bRemoved = OwnerMovieScene->RemovePossessable( BindingToRemove );
			
			// @todo Sequencer - undo needs to work here
			ObjectBindingManager->UnbindPossessableObjects( BindingToRemove );
			
			// If this check fails the guid was not associated with a spawnable or possessable so there was an invalid guid being stored on a node
			check( bRemoved );
		}

		bAnythingRemoved = true;
	}
	else if( NodeToBeDeleted->GetType() == ESequencerNode::Track  )
	{
		TSharedRef<const FTrackNode> SectionAreaNode = StaticCastSharedRef<const FTrackNode>( NodeToBeDeleted );
		UMovieSceneTrack* Track = SectionAreaNode->GetTrack();

		UMovieScene* FocusedMovieScene = GetFocusedMovieScene();

		FocusedMovieScene->SetFlags( RF_Transactional );
		
		if( FocusedMovieScene->IsAMasterTrack( Track ) )
		{
			FocusedMovieScene->RemoveMasterTrack( Track );
		}
		else
		{
			FocusedMovieScene->RemoveTrack( Track );
		}
		
		bAnythingRemoved = true;
	}

	
	if( bAnythingRemoved )
	{
		if( bAnySpawnablesRemoved )
		{
			// @todo Sequencer Sub-MovieScenes needs to destroy objects for all movie scenes that had this node
			SpawnOrDestroyPuppetObjects( MovieSceneInstance );
		}

		NotifyMovieSceneDataChanged();
	}
}