SequenceRecorder
SequenceRecorder
#Overview
name: SequenceRecorder
This variable is created as a Console Variable (cvar).
- type:
Cmd
- help:
Enables the Sequence Recorder tab
It is referenced in 19
C++ source files.
#Summary
#Usage in the C++ source code
The purpose of SequenceRecorder is to provide functionality for recording gameplay and actor movements in Unreal Engine, allowing developers to create cinematic sequences or capture in-game actions for later use or analysis.
SequenceRecorder is primarily used in the editor environment and is part of the Unreal Engine’s editor toolset. Based on the callsites, it interacts with several subsystems and modules:
- Sequencer module
- MediaCompositingEditor module
- GameplayAbilities system
- ActorGroupDetailsCustomization
The value of this variable is typically set when the SequenceRecorder module is loaded or initialized. It’s often accessed through the FModuleManager to get the module instance.
Other variables that interact with SequenceRecorder include:
- RecorderExtender
- SequenceRecorderGroupNameTextBox
- SequenceRecorderTab
Developers should be aware of the following when using SequenceRecorder:
- It’s primarily an editor-time tool, not meant for runtime use.
- It can be extended with custom functionality using ISequenceRecorderExtender.
- It interacts with the Sequencer system for creating and manipulating sequences.
- It has the ability to record actor movements and gameplay actions.
Best practices when using SequenceRecorder:
- Ensure the module is loaded before attempting to use its functionality.
- Use the provided interfaces and extension points rather than directly modifying the core implementation.
- Be mindful of performance implications when recording extensive gameplay or complex scenes.
- Properly manage any custom extensions added to the SequenceRecorder to avoid memory leaks or conflicts.
- Use the SequenceRecorder in conjunction with other Unreal Engine tools like Sequencer for best results in creating cinematic content.
#References in C++ code
#Callsites
This variable is referenced in the following C++ source code:
#Loc: <Workspace>/Engine/Source/Editor/SequenceRecorder/Private/SequenceRecorderModule.cpp:894
Scope: file
Source code excerpt:
static FAutoConsoleCommand CVarEnableSequenceRecorder(
TEXT("SequenceRecorder"),
TEXT("Enables the Sequence Recorder tab"),
FConsoleCommandWithArgsDelegate::CreateLambda([](const TArray<FString>& Args)
{
FSequenceRecorderModule& SequenceRecorder = FModuleManager::GetModuleChecked<FSequenceRecorderModule>("SequenceRecorder");
SequenceRecorder.TabSpawnerEntry->SetMenuType(ETabSpawnerMenuType::Enabled);
}),
#Loc: <Workspace>/Engine/Plugins/Media/MediaCompositing/Source/MediaCompositingEditor/Private/MediaCompositingEditor.cpp:30
Scope (from outer to inner):
file
class class FMediaCompositingEditorModule : public IModuleInterface
function virtual void StartupModule
Source code excerpt:
PropertyTrackEditorBindingHandle = SequencerModule.RegisterPropertyTrackEditor<FMediaPlayerPropertyTrackEditor>();
ISequenceRecorder& SequenceRecorder = FModuleManager::LoadModuleChecked<ISequenceRecorder>("SequenceRecorder");
RecorderExtender = MakeShared<FMediaSequenceRecorderExtender>();
SequenceRecorder.AddSequenceRecorderExtender(RecorderExtender);
}
virtual void ShutdownModule() override
{
ISequenceRecorder* SequenceRecorder = FModuleManager::Get().GetModulePtr<ISequenceRecorder>("SequenceRecorder");
if (SequenceRecorder && RecorderExtender.IsValid())
{
SequenceRecorder->RemoveSequenceRecorderExtender(RecorderExtender);
}
RecorderExtender.Reset();
FMediaCompositingEditorStyle::Destroy();
ISequencerModule* SequencerModulePtr = FModuleManager::Get().GetModulePtr<ISequencerModule>("Sequencer");
#Loc: <Workspace>/Engine/Plugins/Runtime/GameplayAbilities/Source/GameplayAbilities/Private/GameplayCueManager.cpp:456
Scope (from outer to inner):
file
function AGameplayCueNotify_Actor* UGameplayCueManager::GetInstancedCueActor
Source code excerpt:
#if WITH_EDITOR
// let things know that we 'spawned'
ISequenceRecorder& SequenceRecorder = FModuleManager::LoadModuleChecked<ISequenceRecorder>("SequenceRecorder");
SequenceRecorder.NotifyActorStartRecording(RecycledCue);
#endif
return RecycledCue;
}
}
#Loc: <Workspace>/Engine/Plugins/Runtime/GameplayAbilities/Source/GameplayAbilities/Private/GameplayCueManager.cpp:551
Scope (from outer to inner):
file
function void UGameplayCueManager::NotifyGameplayCueActorFinished
Source code excerpt:
#if WITH_EDITOR
// let things know that we 'de-spawned'
ISequenceRecorder& SequenceRecorder = FModuleManager::LoadModuleChecked<ISequenceRecorder>("SequenceRecorder");
SequenceRecorder.NotifyActorStopRecording(Actor);
#endif
return;
}
UE_CLOG((GameplayCueActorRecycleDebug > 0), LogAbilitySystem, Error, TEXT("Could not Recycle CueActor %s, Destroying"), *GetNameSafe(Actor));
}
#Loc: <Workspace>/Engine/Source/Editor/SequenceRecorder/Private/ActorGroupDetailsCustomization.cpp:110
Scope (from outer to inner):
file
function TSharedRef<SWidget> FActorGroupDetailsCustomization::CreateRecordingGroupButton
lambda-function
Source code excerpt:
.IsEnabled_Lambda([this, LocalCommandPtr]()
{
return SequenceRecorder.Pin()->GetCommandList()->CanExecuteAction(LocalCommandPtr.Pin().ToSharedRef());
})
.OnClicked(FOnClicked::CreateLambda([this, LocalCommandPtr]()
{
return SequenceRecorder.Pin()->GetCommandList()->ExecuteAction(LocalCommandPtr.Pin().ToSharedRef()) ? FReply::Handled() : FReply::Unhandled();
}))
[
SNew(SHorizontalBox)
+SHorizontalBox::Slot()
.VAlign(VAlign_Center)
.AutoWidth()
#Loc: <Workspace>/Engine/Source/Editor/SequenceRecorder/Private/ActorGroupDetailsCustomization.cpp:140
Scope (from outer to inner):
file
function TSharedRef<SWidget> FActorGroupDetailsCustomization::FillRecordingProfileOptions
Source code excerpt:
{
const bool bShouldCloseWindowAfterMenuSelection = true;
FMenuBuilder MenuBuilder(bShouldCloseWindowAfterMenuSelection, SequenceRecorder.Pin()->GetCommandList());
TSharedPtr<SSequenceRecorder> LocalSequenceRecorder = SequenceRecorder.Pin();
const FSequenceRecorderCommands& Commands = FSequenceRecorderCommands::Get();
MenuBuilder.BeginSection("CurrentActorGroup", LOCTEXT("CurrentRecordingActorGroupMenu", "Current Actor Group"));
{
MenuBuilder.AddMenuEntry(Commands.DuplicateRecordingGroup);
}
MenuBuilder.EndSection();
#Loc: <Workspace>/Engine/Source/Editor/SequenceRecorder/Private/ActorGroupDetailsCustomization.cpp:241
Scope (from outer to inner):
file
function void FActorGroupDetailsCustomization::HandleRecordingGroupNameCommitted
Source code excerpt:
// cbb: Force load to update sequence names, etc
SequenceRecorder.Pin()->HandleLoadRecordingActorGroup(NewName);
}
}
}
#undef LOCTEXT_NAMESPACE
#Loc: <Workspace>/Engine/Source/Editor/SequenceRecorder/Private/ActorGroupDetailsCustomization.h:22
Scope (from outer to inner):
file
class class FActorGroupDetailsCustomization : public IDetailCustomization
function FActorGroupDetailsCustomization
Source code excerpt:
FActorGroupDetailsCustomization(TWeakPtr<SSequenceRecorder> InSequenceRecorder)
{
SequenceRecorder = InSequenceRecorder;
}
/** IDetailCustomization interface */
virtual void CustomizeDetails(IDetailLayoutBuilder& DetailBuilder) override;
private:
#Loc: <Workspace>/Engine/Source/Editor/SequenceRecorder/Private/ActorGroupDetailsCustomization.h:33
Scope (from outer to inner):
file
class class FActorGroupDetailsCustomization : public IDetailCustomization
Source code excerpt:
void HandleRecordingGroupNameCommitted(const FText& InText, ETextCommit::Type InCommitType);
TSharedPtr<SEditableTextBox> SequenceRecorderGroupNameTextBox;
TWeakPtr<SSequenceRecorder> SequenceRecorder;
};
#Loc: <Workspace>/Engine/Source/Editor/SequenceRecorder/Private/SSequenceRecorder.cpp:342
Scope (from outer to inner):
file
class class SSequenceRecorderDeprecationMessage : public SCompoundWidget
function FReply DismissWarningForever
Source code excerpt:
if (GConfig)
{
GConfig->SetBool(TEXT("SequenceRecorder"), TEXT("HasDismissedDeprecationWarning"), true, GEditorIni);
if (FEngineAnalytics::IsAvailable())
{
FEngineAnalytics::GetProvider().RecordEvent(TEXT("Editor.SequenceRecorder.DeprecationWarning.Dimissed"));
}
}
#Loc: <Workspace>/Engine/Source/Editor/SequenceRecorder/Private/SSequenceRecorder.cpp:358
Scope (from outer to inner):
file
class class SSequenceRecorderDeprecationMessage : public SCompoundWidget
function EVisibility GetWarningMessageVisibility
Source code excerpt:
{
bool bDismissed = false;
GConfig->GetBool(TEXT("SequenceRecorder"), TEXT("HasDismissedDeprecationWarning"), bDismissed, GEditorIni);
return bDismissed ? EVisibility::Collapsed : EVisibility::Visible;
}
return EVisibility::Collapsed;
}
#Loc: <Workspace>/Engine/Source/Editor/SequenceRecorder/Private/SequenceRecorder.cpp:94
Scope (from outer to inner):
file
function FSequenceRecorder& FSequenceRecorder::Get
Source code excerpt:
FSequenceRecorder& FSequenceRecorder::Get()
{
static FSequenceRecorder SequenceRecorder;
return SequenceRecorder;
}
bool FSequenceRecorder::IsRecordingQueued(AActor* Actor) const
{
for (UActorRecording* QueuedRecording : QueuedActorRecordings)
#Loc: <Workspace>/Engine/Source/Editor/SequenceRecorder/Private/SequenceRecorderModule.cpp:771
Scope (from outer to inner):
file
class class FSequenceRecorderModule : public ISequenceRecorder, private FSelfRegisteringExec
Source code excerpt:
/** Add an extension to the SequenceRecorder */
virtual void AddSequenceRecorderExtender(TSharedPtr<ISequenceRecorderExtender> SequenceRecorderExternder) override
{
FSequenceRecorder::Get().GetSequenceRecorderExtenders().Add(SequenceRecorderExternder);
// Rebuild the UI
TSharedPtr<SDockTab> SequenceRecorderTabPtr = SequenceRecorderTab.Pin();
#Loc: <Workspace>/Engine/Source/Editor/SequenceRecorder/Private/SequenceRecorderModule.cpp:784
Scope (from outer to inner):
file
class class FSequenceRecorderModule : public ISequenceRecorder, private FSelfRegisteringExec
Source code excerpt:
}
/** Remove an extension from the SequenceRecorder */
virtual void RemoveSequenceRecorderExtender(TSharedPtr<ISequenceRecorderExtender> SequenceRecorderExternder) override
{
FSequenceRecorder::Get().GetSequenceRecorderExtenders().Remove(SequenceRecorderExternder);
if (!IsEngineExitRequested())
{
// Rebuild the UI
#Loc: <Workspace>/Engine/Source/Editor/SequenceRecorder/Private/SequenceRecorderModule.cpp:863
Scope (from outer to inner):
file
class class FSequenceRecorderModule : public ISequenceRecorder, private FSelfRegisteringExec
function static TSharedRef<SDockTab> SpawnSequenceRecorderTab
Source code excerpt:
MajorTab->SetContent(SNew(SSequenceRecorder));
FSequenceRecorderModule& SequenceRecorder = FModuleManager::GetModuleChecked<FSequenceRecorderModule>("SequenceRecorder");
SequenceRecorder.SequenceRecorderTab = MajorTab;
return MajorTab.ToSharedRef();
}
static void DrawDebug(UCanvas* InCanvas, APlayerController* InPlayerController)
{
#Loc: <Workspace>/Engine/Source/Editor/SequenceRecorder/Private/SequenceRecorderModule.cpp:903
Scope: file
Source code excerpt:
ECVF_Default);
IMPLEMENT_MODULE( FSequenceRecorderModule, SequenceRecorder )
#undef LOCTEXT_NAMESPACE
#Loc: <Workspace>/Engine/Source/Editor/SequenceRecorder/Public/ISequenceRecorder.h:161
Scope (from outer to inner):
file
class class ISequenceRecorder : public IModuleInterface
Source code excerpt:
virtual FOnRecordingGroupAdded& OnRecordingGroupAdded() = 0;
/** Add an extension to the SequenceRecorder */
virtual void AddSequenceRecorderExtender(TSharedPtr<ISequenceRecorderExtender> SequenceRecorderExternder) = 0;
/** Remove an extension from the SequenceRecorder */
virtual void RemoveSequenceRecorderExtender(TSharedPtr<ISequenceRecorderExtender> SequenceRecorderExternder) = 0;
/**
* Play the current single node instance on the PreviewComponent from time [0, GetLength()], and record to NewAsset
*
* @param: PreviewComponent - this component should contains SingleNodeInstance with time-line based asset, currently support AnimSequence or AnimComposite
#Loc: <Workspace>/Engine/Source/Editor/SequenceRecorderSections/Private/MovieScene3DAttachSectionRecorder.cpp:56
Scope (from outer to inner):
file
function void FMovieScene3DAttachSectionRecorder::Record
Source code excerpt:
AActor* AttachedToActor = SequenceRecorderUtils::GetAttachment(ActorToRecord.Get(), SocketName, ComponentName);
ISequenceRecorder& SequenceRecorder = FModuleManager::GetModuleChecked<ISequenceRecorder>("SequenceRecorder");
FGuid Guid = SequenceRecorder.GetRecordingGuid(AttachedToActor);
if(AttachedToActor && Guid.IsValid())
{
// create the track if we haven't already
if(!AttachTrack.IsValid())
{
AttachTrack = MovieScene->AddTrack<UMovieScene3DAttachTrack>(ObjectGuid);
#Loc: <Workspace>/Engine/Source/Runtime/Launch/Private/LaunchEngineLoop.cpp:4964
Scope (from outer to inner):
file
function int32 FEngineLoop::Init
Source code excerpt:
}
FModuleManager::Get().LoadModule(TEXT("SequenceRecorder"));
FModuleManager::Get().LoadModule(TEXT("SequenceRecorderSections"));
#endif
GIsRunning = true;
if (!GIsEditor)