Sequencer, is a powerful cinematic tool used for creating, editing, and controlling complex cinematic sequences, cutscenes, and interactive storytelling experiences within a game or interactive project. It allows to create Level Sequence
(single file) as well as Master Sequence
that is a Sequence
containing Level Sequence
(s).
Level Sequences serve several purposes:
- Cinematic Storytelling: Level Sequences are primarily used for creating cinematic sequences and cutscenes within a game. They allow developers to craft visually engaging storytelling moments, including camera animations, character animations, and scripted events.
- Animation Control: They enable the precise control of animations, both for characters and objects. Animations can be keyframed and synchronized to the timeline, offering fine-grained control over character movements, facial expressions, and other animations.
- Camera Work: Level Sequences provide tools for crafting dynamic camera movements and shots. Cinematographers can set up camera angles, field of view, focus, and depth of field to create cinematic visuals.
- Audio Integration: Audio cues and soundtracks can be integrated into Level Sequences to synchronize sound effects and music with the on-screen action.
- Real-time Interaction: Level Sequences can also be used for real-time interaction and gameplay sequences, allowing developers to create dynamic events that respond to player actions.
- Non-linear Storytelling: They enable non-linear storytelling by branching sequences based on conditions or player choices, making them versatile for creating interactive narratives.
- Editing Environment: Unreal Engine Sequencer provides a user-friendly timeline-based editing environment with features like keyframing, blending, and visual effects, making it suitable for artists, designers, and animators.
- Performance Capture: Level Sequences can be used in conjunction with performance capture technologies, such as motion capture and facial animation systems, to create lifelike character animations.
Overall, Level Sequences are essential for creating engaging cinematic and storytelling experiences in Unreal Engine, bridging the gap between gameplay and narrative elements in interactive projects.
- Prefix for Level Sequence asset files:
LS_
Classes Inheritance Hiearchy
Load Level Sequence (Helper function)
/**
* Load Level Sequence
*
* @param LevelSequencePath The path of the level sequence asset: "/Game/Folder/MyLevelSequence"
* @param bOutSuccess If the action was a success or not
* @param OutInfoMsg Error message in a case of bOutSuccess == false
* @return The loaded ULevelSequence*
*/
UFUNCTION(BlueprintCallable, Category = "Add Remove Actor From Level Sequence")
static ULevelSequence* LoadLevelSequence(FString LevelSequencePath, bool& bOutSuccess, FString& OutInfoMsg);
#include "LevelSequence.h" // LevelSequence
ULevelSequence* UExampleClass::LoadLevelSequence(FString LevelSequencePath, bool &bOutSuccess, FString &OutInfoMsg)
{
ULevelSequence* LevelSequence = Cast<ULevelSequence>(StaticLoadObject(ULevelSequence::StaticClass(), nullptr, *LevelSequencePath));
bOutSuccess = (LevelSequence != nullptr);
if (!bOutSuccess) OutInfoMsg = FString::Printf(TEXT("Get Level Sequence at path '%s' Failed - Level Sequence isn't valid."), *LevelSequencePath);
return LevelSequence;
}
PrivateDependencyModuleNames.AddRange
(
new string[]
{
// Default Modules
"Core",
"CoreUObject",
"Engine",
// New Modules
"LevelSequence",
}
);
Add / Remove Possessable Actors In Level Sequence
The code below adds already existing Actor
type of component in the scene into defined Level Sequence
. If the actor is not placed in the scene, use Add Spawnable Actors In Level Sequence process istead. It's very similar function that differs especially in linking at asset by it's name instead of pointing at the actor itself.
Get Actor Guid From Level Sequence
/**
* Get actor guid from level sequence
*
* @param Actor The actor to get from the level sequence
* @param LevelSequencePath The path of the level sequence asset: "/Game/Folder/MyLevelSequence"
* @param bOutSuccess If the action was a success or not
* @param OutInfoMsg More information about the action's result
*
* @return The guid of the actor in the level sequence
*/
UFUNCTION(BlueprintCallable, Category = "Add Remove Actor From Level Sequence")
static FGuid GetActorGuidFromLevelSequence(AActor* Actor, FString LevelSequencePath, bool& bOutSuccess, FString& OutInfoMsg);
#include "LevelSequence.h" // LevelSequence
#include "MovieScene.h" // MovieScene
FGuid UExampleClass::GetActorGuidFromLevelSequence(AActor* Actor, FString LevelSequencePath, bool& bOutSuccess, FString& OutInfoMsg)
{
// Validate Actor
if (Actor == nullptr)
{
bOutSuccess = false;
OutInfoMsg = FString::Printf(TEXT("Get Actor Guid From Level Sequence Failed - Actor isn't valid. '%s'"), *LevelSequencePath);
return FGuid();
}
// Load Level Sequence
ULevelSequence* LevelSequence = UExampleClass::LoadLevelSequence(LevelSequencePath, bOutSuccess, OutInfoMsg);
if (LevelSequence == nullptr) return FGuid();
// Get Actor Guid from Level Sequence
FGuid Guid = LevelSequence->FindBindingFromObject(Actor, Actor->GetWorld());
bOutSuccess = Guid.IsValid();
FString SucceededOrFailed = bOutSuccess ? "Succeeded" : "Failed";
OutInfoMsg = FString::Printf(TEXT("Get Actor Guid From Level Sequence %s - '%s'"), *SucceededOrFailed, *LevelSequencePath);
return Guid;
}
PrivateDependencyModuleNames.AddRange
(
new string[]
{
// Default Modules
"Core",
"CoreUObject",
"Engine",
// New Modules
"LevelSequence",
"MovieScene",
}
);
Add an actor into a level sequence
/**
* Add an actor into a level sequence
*
* @param Actor The actor to add in the level sequence
* @param LevelSequencePath The path of the level sequence asset: "/Game/Folder/MyLevelSequence"
* @param bOutSuccess If the action was a success or not
* @param OutInfoMsg More information about the action's result
*
* @return The guid of the actor in the level sequence
*/
UFUNCTION(BlueprintCallable, Category = "Add Remove Actor From Level Sequence")
static FGuid AddActorIntoLevelSequence(AActor* Actor, FString LevelSequencePath, bool& bOutSuccess, FString& OutInfoMsg);
#include "LevelSequence.h" // LevelSequence
#include "MovieScene.h" // MovieScene
FGuid UExampleClass::AddActorIntoLevelSequence(AActor* Actor, FString LevelSequencePath, bool& bOutSuccess, FString& OutInfoMsg)
{
// Get Actor Guid
FGuid Guid = GetActorGuidFromLevelSequence(Actor, LevelSequencePath, bOutSuccess, OutInfoMsg);
if (Guid.IsValid())
{
bOutSuccess = false;
OutInfoMsg = FString::Printf(TEXT("Add Actor Into Level Sequence Failed - Actor is already in the level sequence. '%s'"), *LevelSequencePath);
return Guid;
}
// Validate Actor
if (Actor == nullptr)
{
bOutSuccess = false;
OutInfoMsg = FString::Printf(TEXT("Add Actor Into Level Sequence Failed - Actor isn't valid. '%s'"), *LevelSequencePath);
return FGuid();
}
// Load Level Sequence
ULevelSequence* LevelSequence = UExampleClass::LoadLevelSequence(LevelSequencePath, bOutSuccess, OutInfoMsg);
if (LevelSequence == nullptr) return FGuid();
// Create Actor Track into Level Sequence and link it with the Actor
Guid = Cast<UMovieSceneSequence>(LevelSequence)->CreatePossessable(Actor);
bOutSuccess = true;
OutInfoMsg = FString::Printf(TEXT("Add Actor Into Level Sequence Succeeded - '%s'"), *LevelSequencePath);
return Guid;
}
PrivateDependencyModuleNames.AddRange
(
new string[]
{
// Default Modules
"Core",
"CoreUObject",
"Engine",
// New Modules
"LevelSequence",
"MovieScene",
}
);
Remove an actor from a level sequence
/**
* Remove an actor from a level sequence
*
* @param Actor The actor to remove from the level sequence
* @param LevelSequencePath The path of the level sequence asset: "/Game/Folder/MyLevelSequence"
* @param OutInfoMsg More information about the action's result
* @param return If the action was a success or not
*/
UFUNCTION(BlueprintCallable, Category = "Add Remove Actor From Level Sequence")
static bool RemoveActorFromLevelSequence(AActor* Actor, FString LevelSequencePath, FString& OutInfoMsg);
#include "LevelSequence.h" // LevelSequence
#include "MovieScene.h" // MovieScene
bool UExampleClass::RemoveActorFromLevelSequence(AActor* Actor, FString LevelSequencePath, FString& OutInfoMsg)
{
bool bOutSuccess;
// Get Actor Guid
FGuid Guid = GetActorGuidFromLevelSequence(Actor, LevelSequencePath, bOutSuccess, OutInfoMsg);
if (!Guid.IsValid()) return false;
// Load Level Sequence
ULevelSequence* LevelSequence = UExampleClass::LoadLevelSequence(LevelSequencePath, bOutSuccess, OutInfoMsg);
if (LevelSequence == nullptr) return false;
// Unbind Track from Actor
LevelSequence->UnbindPossessableObjects(Guid);
// Remove Actor Track from Level Sequence
bOutSuccess = LevelSequence->MovieScene->RemovePossessable(Guid);
FString SucceededOrFailed = bOutSuccess ? "Succeeded" : "Failed";
OutInfoMsg = FString::Printf(TEXT("Remove Actor From Level Sequence %s - '%s'"), *SucceededOrFailed, *LevelSequencePath);
return bOutSuccess;
}
PrivateDependencyModuleNames.AddRange
(
new string[]
{
// Default Modules
"Core",
"CoreUObject",
"Engine",
// New Modules
"LevelSequence",
"MovieScene",
}
);
Add / Remove Spawnable Actors In Level Sequence
The code below allows to place any Spawnable (not present in the level yet) Actor
type of asset from Content Drawer
to Level Sequence
as well as Level Outliner
(level).
As Spawnable
, there's possible to have any number of instances of the same actor in the Level Sequence
.
Get spawnable guid from level sequence based on its name
/**
* Get spawnable guid from level sequence based on its name
*
* @param SpawnableName The name of the spawnable once in the sequencer (used to identify it)
* @param LevelSequencePath The path of the level sequence asset: "/Game/Folder/MyLevelSequence"
* @param bOutSuccess If the action was a success or not
* @param OutInfoMsg More information about the action's result
*
* @return The guid of the spawnable in the level sequence
*/
UFUNCTION(BlueprintCallable, Category = "Add Remove Spawnable From Level Sequence")
static FGuid GetSpawnableGuidFromLevelSequence(FString SpawnableName, FString LevelSequencePath, bool& bOutSuccess, FString& OutInfoMsg);
#include "LevelSequence.h" // LevelSequence
#include "MovieScene.h" // MovieScene
FGuid UExampleClass::GetSpawnableGuidFromLevelSequence(FString SpawnableName, FString LevelSequencePath, bool& bOutSuccess, FString& OutInfoMsg)
{
// Load Level Sequence
ULevelSequence* LevelSequence = UExampleClass::LoadLevelSequence(LevelSequencePath, bOutSuccess, OutInfoMsg);
if (LevelSequence == nullptr) return FGuid();
// Get Spawnable Guid from Level Sequence
FGuid Guid = FGuid();
for (int X = 0; X < LevelSequence->MovieScene->GetSpawnableCount(); X++)
{
FMovieSceneSpawnable Spawnable = LevelSequence->MovieScene->GetSpawnable(X);
FString Name = LevelSequence->MovieScene->GetObjectDisplayName(Spawnable.GetGuid()).ToString();
if (Name == SpawnableName)
{
Guid = Spawnable.GetGuid();
break;
}
}
bOutSuccess = Guid.IsValid();
FString SucceededOrFailed = bOutSuccess ? "Succeeded" : "Failed";
OutInfoMsg = FString::Printf(TEXT("Get Spawnable Guid From Level Sequence %s - '%s'"), *SucceededOrFailed, *LevelSequencePath);
return Guid;
}
PrivateDependencyModuleNames.AddRange
(
new string[]
{
// Default Modules
"Core",
"CoreUObject",
"Engine",
// New Modules
"LevelSequence",
"MovieScene",
}
);
Add a spawnable into a level sequence
/**
* Add a spawnable into a level sequence
*
* @param SpawnableName The name of the spawnable once in the sequencer (used to identify it)
* @param AssetPath The path of the asset to spawn in the level sequence: "/Game/Folder/MyStaticMesh"
* @param LevelSequencePath The path of the level sequence asset: "/Game/Folder/MyLevelSequence"
* @param bOutSuccess If the action was a success or not
* @param OutInfoMsg More information about the action's result
*
* @return The guid of the actor in the level sequence
*/
UFUNCTION(BlueprintCallable, Category = "Add Remove Spawnable From Level Sequence")
static FGuid AddSpawnableIntoLevelSequence(FString SpawnableName, FString AssetPath, FString LevelSequencePath, bool& bOutSuccess, FString& OutInfoMsg);
#include "LevelSequence.h" // LevelSequence
#include "MovieScene.h" // MovieScene
FGuid UExampleClass::AddSpawnableIntoLevelSequence(FString SpawnableName, FString AssetPath, FString LevelSequencePath, bool& bOutSuccess, FString& OutInfoMsg)
{
// Get Spawnable Guid
FGuid Guid = GetSpawnableGuidFromLevelSequence(SpawnableName, LevelSequencePath, bOutSuccess, OutInfoMsg);
if (Guid.IsValid())
{
bOutSuccess = false;
OutInfoMsg = FString::Printf(TEXT("Add Spawnable Into Level Sequence Failed - Spawnable is already in the level sequence. '%s'"), *LevelSequencePath);
return Guid;
}
// Load Level Sequence
ULevelSequence* LevelSequence = UExampleClass::LoadLevelSequence(LevelSequencePath, bOutSuccess, OutInfoMsg);
if (LevelSequence == nullptr) return FGuid();
// Validate asset to use as a spawnable
UObject* SpawnableTemplate = Cast<UObject>(StaticLoadObject(UObject::StaticClass(), nullptr, *AssetPath));
if (SpawnableTemplate == nullptr)
{
bOutSuccess = false;
OutInfoMsg = FString::Printf(TEXT("Add Spawnable Into Level Sequence Failed - Spawnable template isn't valid. '%s'"), *LevelSequencePath);
return FGuid();
}
// Create Spawnable Track in Level Sequence
Guid = Cast<UMovieSceneSequence>(LevelSequence)->CreateSpawnable(SpawnableTemplate);
if (!Guid.IsValid())
{
bOutSuccess = false;
OutInfoMsg = FString::Printf(TEXT("Add Spawnable Into Level Sequence Failed - Cannot add asset in level sequence. '%s'"), *AssetPath);
return FGuid();
}
// Rename the Spawnable to be able to find it later
LevelSequence->MovieScene->SetObjectDisplayName(Guid, FText::FromString(SpawnableName));
bOutSuccess = true;
OutInfoMsg = FString::Printf(TEXT("Add Spawnable Into Level Sequence Succeeded - '%s'"), *LevelSequencePath);
return Guid;
}
PrivateDependencyModuleNames.AddRange
(
new string[]
{
// Default Modules
"Core",
"CoreUObject",
"Engine",
// New Modules
"LevelSequence",
"MovieScene",
}
);
Note, that each instance need to have an unique SpawnableName
for option to be placed into a Level Sequence
.
Remove a spawnable from a level sequence
/**
* Remove a spawnable from a level sequence
*
* @param SpawnableName The name of the spawnable in the sequencer (used to identify it)
* @param LevelSequencePath The path of the level sequence asset: "/Game/Folder/MyLevelSequence"
* @param bOutSuccess If the action was a success or not
* @param OutInfoMsg More information about the action's result
* @param return If the action was a success or not
*/
UFUNCTION(BlueprintCallable, Category = "Add Remove Spawnable From Level Sequence")
static bool RemoveSpawnableFromLevelSequence(FString SpawnableName, FString LevelSequencePath, FString& OutInfoMsg);
#include "LevelSequence.h" // LevelSequence
#include "MovieScene.h" // MovieScene
bool UExampleClass::RemoveSpawnableFromLevelSequence(FString SpawnableName, FString LevelSequencePath, FString& OutInfoMsg)
{
// Get Spawnable Guid
FGuid Guid = GetSpawnableGuidFromLevelSequence(SpawnableName, LevelSequencePath, bOutSuccess, OutInfoMsg);
if (!Guid.IsValid()) return false
// Load Level Sequence
ULevelSequence* LevelSequence = UExampleClass::LoadLevelSequence(LevelSequencePath, bOutSuccess, OutInfoMsg);
if (LevelSequence == nullptr) return false;
// Remove Spawnable from Level Sequence
bool bOutSuccess = LevelSequence->MovieScene->RemoveSpawnable(Guid);
FString SucceededOrFailed = bOutSuccess ? "Succeeded" : "Failed";
OutInfoMsg = FString::Printf(TEXT("Remove Spawnable From Level Sequence %s - '%s'"), *SucceededOrFailed, *LevelSequencePath);
return true;
}
PrivateDependencyModuleNames.AddRange
(
new string[]
{
// Default Modules
"Core",
"CoreUObject",
"Engine",
// New Modules
"LevelSequence",
"MovieScene",
}
);
Add Animation In Level Sequence
/**
* Add an animation to an actor in a level sequence
*
* @param Actor The actor in the level sequence
* @param LevelSequencePath The path of the level sequence asset: "/Game/Folder/MyLevelSequence"
* @param AnimationPath The path of the animation to assign to the actor: "/Game/Folder/MyAnimation"
* @param StartFrame Start frame of the animation section in the level sequence
* @param EndFrame End frame of the animation section in the level sequence
* @param OutInfoMsg More information about the action's result
* @param return If the action was a success or not
*/
UFUNCTION(BlueprintCallable, Category = "Add Animation In Level Sequence")
static bool AddAnimationInLevelSequence(AActor* Actor, FString LevelSequencePath, FString AnimationPath, int StartFrame, int EndFrame, FString& OutInfoMsg);
#include "LevelSequence.h" // LevelSequence
#include "MovieScene.h" // MovieScene
#include "Tracks/MovieSceneSkeletalAnimationTrack.h" // MovieSceneTracks
#include "MovieSceneSection.h" // MovieScene
void UExampleClass::AddAnimationInLevelSequence(AActor* Actor, FString LevelSequencePath, FString AnimationPath, int StartFrame, int EndFrame, FString& OutInfoMsg)
{
// Load Animation
UAnimSequence* Animation = Cast<UAnimSequence>(StaticLoadObject(UAnimSequence::StaticClass(), nullptr, *AnimationPath));
if (Animation == nullptr)
{
OutInfoMsg = FString::Printf(TEXT("Add Animation To Actor In Level Sequence Failed - Animation isn't valid. '%s'"), *AnimationPath);
return false;
}
// Get Actor Guid
FGuid Guid = UExampleClass::GetActorGuidFromLevelSequence(Actor, LevelSequencePath, bOutSuccess, OutInfoMsg);
if (!Guid.IsValid()) return false;
// Load Level Sequence
ULevelSequence* LevelSequence = UExampleClass::LoadLevelSequence(LevelSequencePath, bOutSuccess, OutInfoMsg);
if (LevelSequence == nullptr) return false;
// Find Track on which to add the Animation
UMovieSceneSkeletalAnimationTrack* AnimTrack = LevelSequence->MovieScene->FindTrack<UMovieSceneSkeletalAnimationTrack>(Guid);
if (AnimTrack == nullptr)
{
// Create Track if doesn't exist
AnimTrack = LevelSequence->MovieScene->AddTrack<UMovieSceneSkeletalAnimationTrack>(Guid);
if (AnimTrack == nullptr)
{
OutInfoMsg = FString::Printf(TEXT("Add Animation To Actor In Level Sequence Failed - Was not able to create Track '%s'"), *LevelSequencePath);
return false;
}
}
// Calculate the Tick Value for the input frame numbers. Level Sequence works in ticks, not in frames and quantity of ticks varies based on TickResolution and DisplayRate.
int FrameTickValue = LevelSequence->MovieScene->GetTickResolution().AsDecimal() / LevelSequence->MovieScene->GetDisplayRate().AsDecimal();
// Add Animation on Track
UMovieSceneSection* Section = AnimTrack->AddNewAnimation(FFrameNumber(StartFrame * FrameTickValue), Animation);
if (Section == nullptr)
{
OutInfoMsg = FString::Printf(TEXT("Add Animation To Actor In Level Sequence Failed - Was not able to create Section '%s'"), *LevelSequencePath);
return false;
}
// Set end frame
if (EndFrame > StartFrame)
{
Section->SetEndFrame(FFrameNumber(EndFrame * FrameTickValue));
}
// Update the tracks in the Level Sequence
AnimTrack->Modify();
OutInfoMsg = FString::Printf(TEXT("Add Animation To Actor In Level Sequence Succeeded - '%s'\n'%s'"), *AnimationPath, *LevelSequencePath);
return true;
}
PrivateDependencyModuleNames.AddRange
(
new string[]
{
// Default Modules
"Core",
"CoreUObject",
"Engine",
// New Modules
"LevelSequence",
"MovieScene",
"MovieSceneTracks",
}
);
Add / Remove Camera Cut Track In Level Sequence
Get a camera cut track from a level sequence
/**
* Get a camera cut track from a level sequence
*
* @param LevelSequencePath The path of the level sequence asset: "/Game/Folder/MyLevelSequence"
* @param bOutSuccess If the action was a success or not
* @param OutInfoMsg More information about the action's result
*
* @return The camera cut track
*/
UFUNCTION(BlueprintCallable, Category = "Add Remove Camera Cut Track From Level Sequence")
static class UMovieSceneCameraCutTrack* GetCameraCutTrackFromLevelSequence(FString LevelSequencePath, bool& bOutSuccess, FString& OutInfoMsg);
#include "LevelSequence.h" // LevelSequence
#include "MovieScene.h" // MovieScene
#include "Tracks/MovieSceneCameraCutTrack.h" // MovieSceneTracks
#include "Sections/MovieSceneCameraCutSection.h" // MovieScene
#include "Camera/CameraActor.h" // Engine
UMovieSceneCameraCutTrack* UExampleClass::GetCameraCutTrackFromLevelSequence(FString LevelSequencePath, bool& bOutSuccess, FString& OutInfoMsg)
{
// Load Level Sequence
ULevelSequence* LevelSequence = UExampleClass::LoadLevelSequence(LevelSequencePath, bOutSuccess, OutInfoMsg);
if (LevelSequence == nullptr) return FGuid();
// Get the camera cut track
UMovieSceneCameraCutTrack* CameraCutTrack = Cast<UMovieSceneCameraCutTrack>(LevelSequence->MovieScene->GetCameraCutTrack());
bOutSuccess = CameraCutTrack != nullptr;
FString SucceededOrFailed = bOutSuccess ? "Succeeded" : "Failed";
OutInfoMsg = FString::Printf(TEXT("Get Camera Cut Track From Level Sequence %s - '%s'"), *SucceededOrFailed, *LevelSequencePath);
return CameraCutTrack;
}
PrivateDependencyModuleNames.AddRange
(
new string[]
{
// Default Modules
"Core",
"CoreUObject",
"Engine",
// New Modules
"LevelSequence",
"MovieScene",
"MovieSceneTracks",
}
);
Add a camera cut track to a level sequence
/**
* Add a camera cut track to a level sequence
*
* @param LevelSequencePath The path of the level sequence asset: "/Game/Folder/MyLevelSequence"
* @param bOutSuccess If the action was a success or not
* @param OutInfoMsg More information about the action's result
*
* @return The camera cut track
*/
UFUNCTION(BlueprintCallable, Category = "Add Remove Camera Cut Track From Level Sequence")
static class UMovieSceneCameraCutTrack* AddCameraCutTrackInLevelSequence(FString LevelSequencePath, bool& bOutSuccess, FString& OutInfoMsg);
#include "LevelSequence.h" // LevelSequence
#include "MovieScene.h" // MovieScene
#include "Tracks/MovieSceneCameraCutTrack.h" // MovieSceneTracks
#include "Sections/MovieSceneCameraCutSection.h" // MovieScene
#include "Camera/CameraActor.h" // Engine
UMovieSceneCameraCutTrack* UExampleClass::AddCameraCutTrackInLevelSequence(FString LevelSequencePath, bool& bOutSuccess, FString& OutInfoMsg)
{
// Check if there's a camera cut track in the level sequence
UMovieSceneCameraCutTrack* CameraCutTrack = GetCameraCutTrackFromLevelSequence(LevelSequencePath, bOutSuccess, OutInfoMsg);
if (CameraCutTrack != nullptr)
{
bOutSuccess = false;
OutInfoMsg = FString::Printf(TEXT("Add Camera Cut Track In Level Sequence Failed - Track already in level sequence. '%s'"), *LevelSequencePath);
return CameraCutTrack;
}
// Load Level Sequence
ULevelSequence* LevelSequence = UExampleClass::LoadLevelSequence(LevelSequencePath, bOutSuccess, OutInfoMsg);
if (LevelSequence == nullptr) return nullptr;
// Add track
CameraCutTrack = Cast<UMovieSceneCameraCutTrack>(LevelSequence->MovieScene->AddCameraCutTrack(UMovieSceneCameraCutTrack::StaticClass()));
bOutSuccess = true;
OutInfoMsg = FString::Printf(TEXT("Add Camera Cut Track In Level Sequence Succeeded - '%s'"), *LevelSequencePath);
return CameraCutTrack;
}
PrivateDependencyModuleNames.AddRange
(
new string[]
{
// Default Modules
"Core",
"CoreUObject",
"Engine",
// New Modules
"LevelSequence",
"MovieScene",
"MovieSceneTracks",
}
);
Remove a camera cut track from a level sequence
/**
* Remove a camera cut track from a level sequence
*
* @param LevelSequencePath The path of the level sequence asset: "/Game/Folder/MyLevelSequence"
* @param OutInfoMsg More information about the action's result
* @param return If the action was a success or not
*/
UFUNCTION(BlueprintCallable, Category = "Add Remove Camera Cut Track From Level Sequence")
static bool RemoveCameraCutTrackFromLevelSequence(FString LevelSequencePath, FString& OutInfoMsg);
#include "LevelSequence.h" // LevelSequence
#include "MovieScene.h" // MovieScene
#include "Tracks/MovieSceneCameraCutTrack.h" // MovieSceneTracks
#include "Sections/MovieSceneCameraCutSection.h" // MovieScene
#include "Camera/CameraActor.h" // Engine
bool UExampleClass::RemoveCameraCutTrackFromLevelSequence(FString LevelSequencePath, FString& OutInfoMsg)
{
bool bOutSuccess;
// Check if there's a camera cut track in the level sequence
UMovieSceneCameraCutTrack* CameraCutTrack = GetCameraCutTrackFromLevelSequence(LevelSequencePath, bOutSuccess, OutInfoMsg);
if (CameraCutTrack == nullptr) return false;
// Load Level Sequence
ULevelSequence* LevelSequence = UExampleClass::LoadLevelSequence(LevelSequencePath, bOutSuccess, OutInfoMsg);
if (LevelSequence == nullptr) return false;
// Remove track
LevelSequence->MovieScene->RemoveCameraCutTrack();
OutInfoMsg = FString::Printf(TEXT("Remove Camera Cut Track From Level Sequence Succeeded - '%s'"), *LevelSequencePath);
return true;
}
PrivateDependencyModuleNames.AddRange
(
new string[]
{
// Default Modules
"Core",
"CoreUObject",
"Engine",
// New Modules
"LevelSequence",
"MovieScene",
"MovieSceneTracks",
}
);
Link a camera to a camera cut track in a level sequence
/**
* Link a camera to a camera cut track in a level sequence
*
* @param LevelSequencePath The path of the level sequence asset: "/Game/Folder/MyLevelSequence"
* @param CameraActor The camera actor to link to the track
* @param StartFrame Start frame of the camera section in the level sequence
* @param EndFrame End frame of the camera section in the level sequence
* @param OutInfoMsg More information about the action's result
* @param return If the action was a success or not
*/
UFUNCTION(BlueprintCallable, Category = "Add Remove Camera Cut Track From Level Sequence")
static bool LinkCameraToCameraCutTrack(FString LevelSequencePath, class ACameraActor* CameraActor, int StartFrame, int EndFrame, FString& OutInfoMsg);
#include "LevelSequence.h" // LevelSequence
#include "MovieScene.h" // MovieScene
#include "Tracks/MovieSceneCameraCutTrack.h" // MovieSceneTracks
#include "Sections/MovieSceneCameraCutSection.h" // MovieScene
#include "Camera/CameraActor.h" // Engine
bool UExampleClass::LinkCameraToCameraCutTrack(FString LevelSequencePath, ACameraActor* CameraActor, int StartFrame, int EndFrame, FString& OutInfoMsg)
{
bool bOutSuccess;
// Make sure camera is valid
if (CameraActor == nullptr)
{
OutInfoMsg = FString::Printf(TEXT("Link Camera To Camera Cut Track Failed - Camera actor isn't valid. '%s'"), *LevelSequencePath);
return false;
}
// Check if there's a camera cut track in the level sequence
UMovieSceneCameraCutTrack* CameraCutTrack = GetCameraCutTrackFromLevelSequenceGetCameraCutTrackFromLevelSequence(LevelSequencePath, bOutSuccess, OutInfoMsg);
if (CameraCutTrack == nullptr)
{
OutInfoMsg = FString::Printf(TEXT("Link Camera To Camera Cut Track Failed - Camera cut track isn't valid. '%s'"), *LevelSequencePath);
return false;
}
// Add camera actor in level sequence
FGuid Guid = UExampleClass::AddActorIntoLevelSequence(CameraActor, LevelSequencePath, bOutSuccess, OutInfoMsg);
if (!Guid.IsValid())
{
OutInfoMsg = FString::Printf(TEXT("Link Camera To Camera Cut Track Failed - Failed to add camera actor in level sequence. '%s'"), *LevelSequencePath);
return false;
}
// Load Level Sequence
ULevelSequence* LevelSequence = UExampleClass::LoadLevelSequence(LevelSequencePath, bOutSuccess, OutInfoMsg);
if (LevelSequence == nullptr) return false;
// Calculate the Tick Value for the input frame numbers.
// Level Sequence works in ticks, not in frames and quantity of ticks varies based on TickResolution and DisplayRate.
int FrameTickValue = LevelSequence->MovieScene->GetTickResolution().AsDecimal() / LevelSequence->MovieScene->GetDisplayRate().AsDecimal();
// Link camera to camera cut track
UMovieSceneCameraCutSection* Section = CameraCutTrack->AddNewCameraCut(UE::MovieScene::FRelativeObjectBindingID(Guid), FFrameNumber(StartFrame * FrameTickValue));
if (Section == nullptr)
{
OutInfoMsg = FString::Printf(TEXT("Link Camera To Camera Cut Track Failed - Was not able to create Section '%s'"), *LevelSequencePath);
return flase;
}
// Set end frame
if (EndFrame > StartFrame) Section->SetEndFrame(FFrameNumber(EndFrame * FrameTickValue));
OutInfoMsg = FString::Printf(TEXT("Link Camera To Camera Cut Track Succeeded - '%s'"), *LevelSequencePath);
return true;
}
PrivateDependencyModuleNames.AddRange
(
new string[]
{
// Default Modules
"Core",
"CoreUObject",
"Engine",
// New Modules
"LevelSequence",
"MovieScene",
"MovieSceneTracks",
}
);
Add / Remove Folder(s) In Level Sequence
Get a folder from a level sequence
/**
* Get a folder from a level sequence
*
* @param LevelSequencePath The path of the level sequence asset: "/Game/Folder/MyLevelSequence"
* @param FolderName The name of the folder
* @param bOutSuccess If the action was a success or not
* @param OutInfoMsg More information about the action's result
*
* @return The folder
*/
UFUNCTION(BlueprintCallable, Category = "Add Remove Folder From Level Sequence")
static class UMovieSceneFolder* GetFolderFromLevelSequence(FString LevelSequencePath, FString FolderName, bool& bOutSuccess, FString& OutInfoMsg);
#include "LevelSequence.h" // LevelSequence
#include "MovieScene.h" // MovieScene
#include "MovieSceneFolder.h" // MovieScene
UMovieSceneFolder* UExampleClass::GetFolderFromLevelSequence(FString LevelSequencePath, FString FolderName, bool& bOutSuccess, FString& OutInfoMsg)
{
// Load Level Sequence
ULevelSequence* LevelSequence = UExampleClass::LoadLevelSequence(LevelSequencePath, bOutSuccess, OutInfoMsg);
if (LevelSequence == nullptr) return nullptr;
// Find existing folder
UMovieSceneFolder* ExistingFolder = nullptr;
for (UMovieSceneFolder* Folder : LevelSequence->MovieScene->GetRootFolders())
{
if (Folder->GetFolderName().ToString() == FolderName)
{
ExistingFolder = Folder;
break;
}
}
bOutSuccess = ExistingFolder != nullptr;
FString SucceededOrFailed = bOutSuccess ? "Succeeded" : "Failed";
OutInfoMsg = FString::Printf(TEXT("Get Folder From Level Sequence %s - '%s'"), *SucceededOrFailed, *LevelSequencePath);
return ExistingFolder;
}
PrivateDependencyModuleNames.AddRange
(
new string[]
{
// Default Modules
"Core",
"CoreUObject",
"Engine",
// New Modules
"LevelSequence",
"MovieScene",
}
);
Add a folder to a level sequence
/**
* Add a folder to a level sequence
*
* @param LevelSequencePath The path of the level sequence asset: "/Game/Folder/MyLevelSequence"
* @param FolderName The name of the folder
* @param bOutSuccess If the action was a success or not
* @param OutInfoMsg More information about the action's result
*
* @return The folder
*/
UFUNCTION(BlueprintCallable, Category = "Add Remove Folder From Level Sequence")
static class UMovieSceneFolder* AddFolderInLevelSequence(FString LevelSequencePath, FString FolderName, bool& bOutSuccess, FString& OutInfoMsg);
#include "LevelSequence.h" // LevelSequence
#include "MovieScene.h" // MovieScene
#include "MovieSceneFolder.h" // MovieScene
UMovieSceneFolder* UExampleClass::AddFolderInLevelSequence(FString LevelSequencePath, FString FolderName, bool& bOutSuccess, FString& OutInfoMsg)
{
// Check for existing folder
UMovieSceneFolder* Folder = GetFolderFromLevelSequence(LevelSequencePath, FolderName, bOutSuccess, OutInfoMsg);
if (Folder != nullptr)
{
bOutSuccess = false;
OutInfoMsg = FString::Printf(TEXT("Add Folder In Level Sequence Failed - Folder already exists. '%s'\n'%s'"), *FolderName, *LevelSequencePath);
return Folder;
}
// Load Level Sequence
ULevelSequence* LevelSequence = UExampleClass::LoadLevelSequence(LevelSequencePath, bOutSuccess, OutInfoMsg);
if (LevelSequence == nullptr) return nullptr;
// Create folder
Folder = NewObject<UMovieSceneFolder>(LevelSequence->MovieScene, NAME_None, RF_Transactional);
Folder->SetFolderName(*FolderName);
// Add folder in level sequence
LevelSequence->MovieScene->AddRootFolder(Folder);
bOutSuccess = true;
OutInfoMsg = FString::Printf(TEXT("Add Folder In Level Sequence Succeeded - '%s'\n'%s'"), *FolderName, *LevelSequencePath);
return Folder;
}
PrivateDependencyModuleNames.AddRange
(
new string[]
{
// Default Modules
"Core",
"CoreUObject",
"Engine",
// New Modules
"LevelSequence",
"MovieScene",
}
);
Remove a folder from a level sequence
/**
* Remove a folder from a level sequence
*
* @param LevelSequencePath The path of the level sequence asset: "/Game/Folder/MyLevelSequence"
* @param FolderName The name of the folder
* @param bOutSuccess If the action was a success or not
* @param OutInfoMsg More information about the action's result
*/
UFUNCTION(BlueprintCallable, Category = "Add Remove Folder From Level Sequence")
static void RemoveFolderFromLevelSequence(FString LevelSequencePath, FString FolderName, bool& bOutSuccess, FString& OutInfoMsg);
#include "LevelSequence.h" // LevelSequence
#include "MovieScene.h" // MovieScene
#include "MovieSceneFolder.h" // MovieScene
void UExampleClass::RemoveFolderFromLevelSequence(FString LevelSequencePath, FString FolderName, bool& bOutSuccess, FString& OutInfoMsg)
{
// Check for existing folder
UMovieSceneFolder* Folder = GetFolderFromLevelSequence(LevelSequencePath, FolderName, bOutSuccess, OutInfoMsg);
if (Folder == nullptr)
{
bOutSuccess = false;
OutInfoMsg = FString::Printf(TEXT("Remove Folder From Level Sequence Failed - Folder doesn't exist. '%s'\n'%s'"), *FolderName, *LevelSequencePath);
return;
}
// Load Level Sequence
ULevelSequence* LevelSequence = UExampleClass::LoadLevelSequence(LevelSequencePath, bOutSuccess, OutInfoMsg);
if (LevelSequence == nullptr) return;
// Remove folder from level sequence
LevelSequence->MovieScene->RemoveRootFolder(Folder);
bOutSuccess = true;
OutInfoMsg = FString::Printf(TEXT("Remove Folder From Level Sequence Succeeded - '%s'\n'%s'"), *FolderName, *LevelSequencePath);
}
PrivateDependencyModuleNames.AddRange
(
new string[]
{
// Default Modules
"Core",
"CoreUObject",
"Engine",
// New Modules
"LevelSequence",
"MovieScene",
}
);
Move an actor in a folder in a level sequence
/**
* Move an actor in a folder in a level sequence
*
* @param LevelSequencePath The path of the level sequence asset: "/Game/Folder/MyLevelSequence"
* @param FolderName The name of the folder
* @param Actor The actor to move into the folder
* @param bOutSuccess If the action was a success or not
* @param OutInfoMsg More information about the action's result
*/
UFUNCTION(BlueprintCallable, Category = "Add Remove Folder From Level Sequence")
static void MoveActorInFolderInLevelSequence(FString LevelSequencePath, FString FolderName, AActor* Actor, bool& bOutSuccess, FString& OutInfoMsg);
#include "LevelSequence.h" // LevelSequence
#include "MovieScene.h" // MovieScene
#include "MovieSceneFolder.h" // MovieScene
void UExampleClass::MoveActorInFolderInLevelSequence(FString LevelSequencePath, FString FolderName, AActor* Actor, bool& bOutSuccess, FString& OutInfoMsg)
{
// Get folder
UMovieSceneFolder* Folder = GetFolderFromLevelSequence(LevelSequencePath, FolderName, bOutSuccess, OutInfoMsg);
if (Folder == nullptr)
{
bOutSuccess = false;
OutInfoMsg = FString::Printf(TEXT("Move Actor In Folder In Level Sequence Failed - Folder doesn't exist. '%s'\n'%s'"), *FolderName, *LevelSequencePath);
return;
}
// Get actor from level sequence
FGuid Guid = UExampleClass::GetActorGuidFromLevelSequence(Actor, LevelSequencePath, bOutSuccess, OutInfoMsg);
if (!Guid.IsValid())
{
bOutSuccess = false;
OutInfoMsg = FString::Printf(TEXT("Move Actor In Folder In Level Sequence Failed - Actor is not in level sequence. '%s'"), *LevelSequencePath);
return;
}
// Is the actor in the folder
if (Folder->GetChildObjectBindings().Contains(Guid))
{
bOutSuccess = false;
OutInfoMsg = FString::Printf(TEXT("Move Actor In Folder In Level Sequence Failed - Actor is already in folder. '%s'"), *LevelSequencePath);
return;
}
// Move actor in folder
Folder->AddChildObjectBinding(Guid);
bOutSuccess = true;
OutInfoMsg = FString::Printf(TEXT("Move Actor In Folder In Level Sequence Succeeded - '%s'\n'%s'"), *FolderName, *LevelSequencePath);
}
PrivateDependencyModuleNames.AddRange
(
new string[]
{
// Default Modules
"Core",
"CoreUObject",
"Engine",
// New Modules
"LevelSequence",
"MovieScene",
}
);
Move an actor out of a folder in a level sequence
/**
* Move an actor out of a folder in a level sequence
*
* @param LevelSequencePath The path of the level sequence asset: "/Game/Folder/MyLevelSequence"
* @param FolderName The name of the folder
* @param Actor The actor to move out of the folder
* @param bOutSuccess If the action was a success or not
* @param OutInfoMsg More information about the action's result
*/
UFUNCTION(BlueprintCallable, Category = "Add Remove Folder From Level Sequence")
static void MoveActorOutOfFolderInLevelSequence(FString LevelSequencePath, FString FolderName, AActor* Actor, bool& bOutSuccess, FString& OutInfoMsg);
#include "LevelSequence.h" // LevelSequence
#include "MovieScene.h" // MovieScene
#include "MovieSceneFolder.h" // MovieScene
void UExampleClass::MoveActorOutOfFolderInLevelSequence(FString LevelSequencePath, FString FolderName, AActor* Actor, bool& bOutSuccess, FString& OutInfoMsg)
{
// Get folder
UMovieSceneFolder* Folder = GetFolderFromLevelSequence(LevelSequencePath, FolderName, bOutSuccess, OutInfoMsg);
if (Folder == nullptr)
{
bOutSuccess = false;
OutInfoMsg = FString::Printf(TEXT("Move Actor Out Of Folder In Level Sequence Failed - Folder doesn't exist. '%s'\n'%s'"), *FolderName, *LevelSequencePath);
return;
}
// Get actor from level sequence
FGuid Guid = UExampleClass::GetActorGuidFromLevelSequence(Actor, LevelSequencePath, bOutSuccess, OutInfoMsg);
if (!Guid.IsValid())
{
bOutSuccess = false;
OutInfoMsg = FString::Printf(TEXT("Move Actor Out Of Folder In Level Sequence Failed - Actor is not in level sequence. '%s'"), *LevelSequencePath);
return;
}
// Is the actor in the folder
if (!Folder->GetChildObjectBindings().Contains(Guid))
{
bOutSuccess = false;
OutInfoMsg = FString::Printf(TEXT("Move Actor Out Of Folder In Level Sequence Failed - Actor is not in folder. '%s'"), *LevelSequencePath);
return;
}
// Move actor out of folder
Folder->RemoveChildObjectBinding(Guid);
bOutSuccess = true;
OutInfoMsg = FString::Printf(TEXT("Move Actor Out Of Folder In Level Sequence Succeeded - '%s'\n'%s'"), *FolderName, *LevelSequencePath);
}
PrivateDependencyModuleNames.AddRange
(
new string[]
{
// Default Modules
"Core",
"CoreUObject",
"Engine",
// New Modules
"LevelSequence",
"MovieScene",
}
);
Add / Remove Shot(s) In Level Sequence
Get a shot track from a level sequence
/**
* Get a shot track from a level sequence
*
* @param LevelSequencePath The path of the level sequence asset: "/Game/Folder/MyLevelSequence"
* @param bOutSuccess If the action was a success or not
* @param OutInfoMsg More information about the action's result
*
* @return The shot track
*/
UFUNCTION(BlueprintCallable, Category = "Shot Track in Level Sequence")
static class UMovieSceneCinematicShotTrack* GetShotTrackFromLevelSequence(FString LevelSequencePath, bool& bOutSuccess, FString& OutInfoMsg);
#include "LevelSequence.h" // LevelSequence
#include "MovieScene.h" // MovieScene
#include "Tracks/MovieSceneCinematicShotTrack.h" // MovieSceneTracks
UMovieSceneCinematicShotTrack* UExampleClass::GetShotTrackFromLevelSequence(FString LevelSequencePath, bool& bOutSuccess, FString& OutInfoMsg)
{
// Load Level Sequence
ULevelSequence* LevelSequence = UExampleClass::LoadLevelSequence(LevelSequencePath, bOutSuccess, OutInfoMsg);
if (LevelSequence == nullptr) return nullptr;
// Get the shot track
UMovieSceneCinematicShotTrack* ShotTrack = LevelSequence->MovieScene->FindTrack<UMovieSceneCinematicShotTrack>();
bOutSuccess = ShotTrack != nullptr;
FString SucceededOrFailed = bOutSuccess ? "Succeeded" : "Failed";
OutInfoMsg = FString::Printf(TEXT("Get Shot Track From Level Sequence %s - '%s'"), *SucceededOrFailed, *LevelSequencePath);
return ShotTrack;
}
PrivateDependencyModuleNames.AddRange
(
new string[]
{
// Default Modules
"Core",
"CoreUObject",
"Engine",
// New Modules
"LevelSequence",
"MovieScene",
MovieSceneTracks,
}
);
Add a shot track to a level sequence
/**
* Add a shot track to a level sequence
*
* @param LevelSequencePath The path of the level sequence asset: "/Game/Folder/MyLevelSequence"
* @param bOutSuccess If the action was a success or not
* @param OutInfoMsg More information about the action's result
*
* @return The shot track
*/
UFUNCTION(BlueprintCallable, Category = "Shot Track in Level Sequence")
static class UMovieSceneCinematicShotTrack* AddShotTrackInLevelSequence(FString LevelSequencePath, bool& bOutSuccess, FString& OutInfoMsg);
#include "LevelSequence.h" // LevelSequence
#include "MovieScene.h" // MovieScene
#include "Tracks/MovieSceneCinematicShotTrack.h" // MovieSceneTracks
UMovieSceneCinematicShotTrack* UExampleClass::AddShotTrackInLevelSequence(FString LevelSequencePath, bool& bOutSuccess, FString& OutInfoMsg)
{
// Check if there's a shot track in the level sequence
UMovieSceneCinematicShotTrack* ShotTrack = GetShotTrackFromLevelSequence(LevelSequencePath, bOutSuccess, OutInfoMsg);
if (ShotTrack != nullptr)
{
bOutSuccess = false;
OutInfoMsg = FString::Printf(TEXT("Add Shot Track In Level Sequence Failed - Track already in level sequence. '%s'"), *LevelSequencePath);
return ShotTrack;
}
// Load Level Sequence
ULevelSequence* LevelSequence = UExampleClass::LoadLevelSequence(LevelSequencePath, bOutSuccess, OutInfoMsg);
if (LevelSequence == nullptr) return nullptr;
// Add track
ShotTrack = LevelSequence->MovieScene->AddTrack<UMovieSceneCinematicShotTrack>();
bOutSuccess = true;
OutInfoMsg = FString::Printf(TEXT("Add Shot Track In Level Sequence Succeeded - '%s'"), *LevelSequencePath);
return ShotTrack;
}
PrivateDependencyModuleNames.AddRange
(
new string[]
{
// Default Modules
"Core",
"CoreUObject",
"Engine",
// New Modules
"LevelSequence",
"MovieScene",
MovieSceneTracks,
}
);
Remove a shot track from a level sequence
/**
* Remove a shot track from a level sequence
*
* @param LevelSequencePath The path of the level sequence asset: "/Game/Folder/MyLevelSequence"
* @param bOutSuccess If the action was a success or not
* @param OutInfoMsg More information about the action's result
*/
UFUNCTION(BlueprintCallable, Category = "Shot Track in Level Sequence")
static void RemoveShotTrackFromLevelSequence(FString LevelSequencePath, bool& bOutSuccess, FString& OutInfoMsg);
#include "LevelSequence.h" // LevelSequence
#include "MovieScene.h" // MovieScene
#include "Tracks/MovieSceneCinematicShotTrack.h" // MovieSceneTracks
void UExampleClass::RemoveShotTrackFromLevelSequence(FString LevelSequencePath, bool& bOutSuccess, FString& OutInfoMsg)
{
// Check if there's a shot track in the level sequence
UMovieSceneCinematicShotTrack* ShotTrack = GetShotTrackFromLevelSequence(LevelSequencePath, bOutSuccess, OutInfoMsg);
if (ShotTrack == nullptr) return;
// Load Level Sequence
ULevelSequence* LevelSequence = UExampleClass::LoadLevelSequence(LevelSequencePath, bOutSuccess, OutInfoMsg);
if (LevelSequence == nullptr) return;
// Remove track
LevelSequence->MovieScene->RemoveTrack(*ShotTrack);
bOutSuccess = true;
OutInfoMsg = FString::Printf(TEXT("Remove Shot Track From Level Sequence Succeeded - '%s'"), *LevelSequencePath);
}
PrivateDependencyModuleNames.AddRange
(
new string[]
{
// Default Modules
"Core",
"CoreUObject",
"Engine",
// New Modules
"LevelSequence",
"MovieScene",
MovieSceneTracks,
}
);
Link a level sequence to a shot track in a level sequence
/**
* Link a level sequence to a shot track in a level sequence
*
* @param LevelSequencePath The path of the level sequence asset: "/Game/Folder/MyLevelSequence"
* @param Shot The level sequence to link to the track as a shot
* @param StartFrame Start frame of the shot section in the level sequence
* @param EndFrame End frame of the shot section in the level sequence
* @param bOutSuccess If the action was a success or not
* @param OutInfoMsg More information about the action's result
*/
UFUNCTION(BlueprintCallable, Category = "Shot Track in Level Sequence")
static void LinkShotToShotTrack(FString LevelSequencePath, class ULevelSequence* Shot, int StartFrame, int EndFrame, bool& bOutSuccess, FString& OutInfoMsg);
#include "LevelSequence.h" // LevelSequence
#include "MovieScene.h" // MovieScene
#include "Tracks/MovieSceneCinematicShotTrack.h" // MovieSceneTracks
void UExampleClass::LinkShotToShotTrack(FString LevelSequencePath, ULevelSequence* Shot, int StartFrame, int EndFrame, bool& bOutSuccess, FString& OutInfoMsg)
{
// Make sure level sequence is valid
if (Shot == nullptr)
{
bOutSuccess = false;
OutInfoMsg = FString::Printf(TEXT("Link Shot To Shot Track Failed - Shot isn't valid. '%s'"), *LevelSequencePath);
return;
}
// Check if there's a shot track in the level sequence
UMovieSceneCinematicShotTrack* ShotTrack = GetShotTrackFromLevelSequence(LevelSequencePath, bOutSuccess, OutInfoMsg);
if (ShotTrack == nullptr)
{
bOutSuccess = false;
OutInfoMsg = FString::Printf(TEXT("Link Shot To Shot Track Failed - Shot track isn't valid. '%s'"), *LevelSequencePath);
return;
}
// Load Level Sequence
ULevelSequence* LevelSequence = UExampleClass::LoadLevelSequence(LevelSequencePath, bOutSuccess, OutInfoMsg);
if (LevelSequence == nullptr) return;
// Calculate the amount of Ticks Per Frame for the input frame numbers.
// Level Sequence works in ticks, not in frames and quantity of ticks varies based on TickResolution and DisplayRate.
int TicksPerFrame = LevelSequence->MovieScene->GetTickResolution().AsDecimal() / LevelSequence->MovieScene->GetDisplayRate().AsDecimal();
// Link shot to shot track
UMovieSceneSubSection* Section = ShotTrack->AddSequence(Shot, FFrameNumber(StartFrame * TicksPerFrame), (EndFrame - StartFrame) * TicksPerFrame);
bOutSuccess = Section != nullptr;
FString SucceededOrFailed = bOutSuccess ? "Succeeded" : "Failed";
OutInfoMsg = FString::Printf(TEXT("Link Shot To Shot Track %s - '%s'"), *SucceededOrFailed, *LevelSequencePath);
}
PrivateDependencyModuleNames.AddRange
(
new string[]
{
// Default Modules
"Core",
"CoreUObject",
"Engine",
// New Modules
"LevelSequence",
"MovieScene",
MovieSceneTracks,
}
);
Add / Remove Subsequence In Level Sequence
Get a subsequence track from a level sequence
/**
* Get a subsequence track from a level sequence
*
* @param LevelSequencePath The path of the level sequence asset: "/Game/Folder/MyLevelSequence"
* @param bOutSuccess If the action was a success or not
* @param OutInfoMsg More information about the action's result
*
* @return The subsequence track
*/
UFUNCTION(BlueprintCallable, Category = "Subsequence In Level Sequence")
static class UMovieSceneSubTrack* GetSubsequenceTrackFromLevelSequence(FString LevelSequencePath, bool& bOutSuccess, FString& OutInfoMsg);
#include "LevelSequence.h" // LevelSequence
#include "MovieScene.h" // MovieScene
#include "Tracks/MovieSceneSubTrack.h" // MovieScene
UMovieSceneSubTrack* UExampleClass::GetSubsequenceTrackFromLevelSequence(FString LevelSequencePath, bool& bOutSuccess, FString& OutInfoMsg)
{
// Load Level Sequence
ULevelSequence* LevelSequence = UExampleClass::LoadLevelSequence(LevelSequencePath, bOutSuccess, OutInfoMsg);
if (LevelSequence == nullptr) return nullptr;
// Get the Subsequence track
UMovieSceneSubTrack* SubsequenceTrack = LevelSequence->MovieScene->FindTrack<UMovieSceneSubTrack>();
bOutSuccess = SubsequenceTrack != nullptr;
FString SucceededOrFailed = bOutSuccess ? "Succeeded" : "Failed";
OutInfoMsg = FString::Printf(TEXT("Get Subsequence Track From Level Sequence %s - '%s'"), *SucceededOrFailed, *LevelSequencePath);
return SubsequenceTrack;
}
PrivateDependencyModuleNames.AddRange
(
new string[]
{
// Default Modules
"Core",
"CoreUObject",
"Engine",
// New Modules
"LevelSequence",
"MovieScene",
}
);
Add a subsequence track to a level sequence
/**
* Add a subsequence track to a level sequence
*
* @param LevelSequencePath The path of the level sequence asset: "/Game/Folder/MyLevelSequence"
* @param bOutSuccess If the action was a success or not
* @param OutInfoMsg More information about the action's result
*
* @return The subsequence track
*/
UFUNCTION(BlueprintCallable, Category = "Subsequence In Level Sequence")
static class UMovieSceneSubTrack* AddSubsequenceTrackInLevelSequence(FString LevelSequencePath, bool& bOutSuccess, FString& OutInfoMsg);
#include "LevelSequence.h" // LevelSequence
#include "MovieScene.h" // MovieScene
#include "Tracks/MovieSceneSubTrack.h" // MovieScene
UMovieSceneSubTrack* UExampleClass::AddSubsequenceTrackInLevelSequence(FString LevelSequencePath, bool& bOutSuccess, FString& OutInfoMsg)
{
// Check if there's a Subsequence track in the level sequence
UMovieSceneSubTrack* SubsequenceTrack = GetSubsequenceTrackFromLevelSequence(LevelSequencePath, bOutSuccess, OutInfoMsg);
if (SubsequenceTrack != nullptr)
{
bOutSuccess = false;
OutInfoMsg = FString::Printf(TEXT("Add Subsequence Track In Level Sequence Failed - Track already in level sequence. '%s'"), *LevelSequencePath);
return SubsequenceTrack;
}
// Load Level Sequence
ULevelSequence* LevelSequence = UExampleClass::LoadLevelSequence(LevelSequencePath, bOutSuccess, OutInfoMsg);
if (LevelSequence == nullptr) return nullptr;
// Add track
SubsequenceTrack = LevelSequence->MovieScene->AddTrack<UMovieSceneSubTrack>();
bOutSuccess = true;
OutInfoMsg = FString::Printf(TEXT("Add Subsequence Track In Level Sequence Succeeded - '%s'"), *LevelSequencePath);
return SubsequenceTrack;
}
PrivateDependencyModuleNames.AddRange
(
new string[]
{
// Default Modules
"Core",
"CoreUObject",
"Engine",
// New Modules
"LevelSequence",
"MovieScene",
}
);
Remove a subsequence track from a level sequence
/**
* Remove a subsequence track from a level sequence
*
* @param LevelSequencePath The path of the level sequence asset: "/Game/Folder/MyLevelSequence"
* @param bOutSuccess If the action was a success or not
* @param OutInfoMsg More information about the action's result
*/
UFUNCTION(BlueprintCallable, Category = "Subsequence In Level Sequence")
static void RemoveSubsequenceTrackFromLevelSequence(FString LevelSequencePath, bool& bOutSuccess, FString& OutInfoMsg);
#include "LevelSequence.h" // LevelSequence
#include "MovieScene.h" // MovieScene
#include "Tracks/MovieSceneSubTrack.h" // MovieScene
void UExampleClass::RemoveSubsequenceTrackFromLevelSequence(FString LevelSequencePath, bool& bOutSuccess, FString& OutInfoMsg)
{
// Check if there's a Subsequence track in the level sequence
UMovieSceneSubTrack* SubsequenceTrack = GetSubsequenceTrackFromLevelSequence(LevelSequencePath, bOutSuccess, OutInfoMsg);
if (SubsequenceTrack == nullptr) return;
// Load Level Sequence
ULevelSequence* LevelSequence = UExampleClass::LoadLevelSequence(LevelSequencePath, bOutSuccess, OutInfoMsg);
if (LevelSequence == nullptr) return;
// Remove track
LevelSequence->MovieScene->RemoveTrack(*SubsequenceTrack);
bOutSuccess = true;
OutInfoMsg = FString::Printf(TEXT("Remove Subsequence Track From Level Sequence Succeeded - '%s'"), *LevelSequencePath);
}
PrivateDependencyModuleNames.AddRange
(
new string[]
{
// Default Modules
"Core",
"CoreUObject",
"Engine",
// New Modules
"LevelSequence",
"MovieScene",
}
);
Remove a subsequence track from a level sequence
/**
* Link a level sequence to a subsequence track in a level sequence
*
* @param LevelSequencePath The path of the level sequence asset: "/Game/Folder/MyLevelSequence"
* @param Subsequence The level sequence to link to the track as a subsequence
* @param StartFrame Start frame of the subsequence section in the level sequence
* @param EndFrame End frame of the subsequence section in the level sequence
* @param bOutSuccess If the action was a success or not
* @param OutInfoMsg More information about the action's result
*/
UFUNCTION(BlueprintCallable, Category = "Subsequence In Level Sequence")
static void LinkSequenceToSubsequenceTrack(FString LevelSequencePath, ULevelSequence* Sequence, int StartFrame, int EndFrame, bool& bOutSuccess, FString& OutInfoMsg);
#include "LevelSequence.h" // LevelSequence
#include "MovieScene.h" // MovieScene
#include "Tracks/MovieSceneSubTrack.h" // MovieScene
void UExampleClass::LinkSequenceToSubsequenceTrack(FString LevelSequencePath, ULevelSequence* Sequence, int StartFrame, int EndFrame, bool& bOutSuccess, FString& OutInfoMsg)
{
// Make sure level sequence is valid
if (Sequence == nullptr)
{
bOutSuccess = false;
OutInfoMsg = FString::Printf(TEXT("Link Sequence To Subsequence Track Failed - Sequence isn't valid. '%s'"), *LevelSequencePath);
return;
}
// Check if there's a Subsequence track in the level sequence
UMovieSceneSubTrack* SubsequenceTrack = GetSubsequenceTrackFromLevelSequenceGetSubsequenceTrackFromLevelSequence(LevelSequencePath, bOutSuccess, OutInfoMsg);
if (SubsequenceTrack == nullptr)
{
bOutSuccess = false;
OutInfoMsg = FString::Printf(TEXT("Link Subsequence To Subsequence Track Failed - Subsequence track isn't valid. '%s'"), *LevelSequencePath);
return;
}
// Load Level Sequence
ULevelSequence* LevelSequence = UExampleClass::LoadLevelSequence(LevelSequencePath, bOutSuccess, OutInfoMsg);
if (LevelSequence == nullptr) return;
// Calculate the amount of Ticks Per Frame for the input frame numbers.
// Level Sequence works in ticks, not in frames and quantity of ticks varies based on TickResolution and DisplayRate.
int TicksPerFrame = LevelSequence->MovieScene->GetTickResolution().AsDecimal() / LevelSequence->MovieScene->GetDisplayRate().AsDecimal();
// Link Subsequence to Subsequence track
UMovieSceneSubSection* Section = SubsequenceTrack->AddSequence(Sequence, FFrameNumber(StartFrame * TicksPerFrame), (EndFrame - StartFrame) * TicksPerFrame);
bOutSuccess = Section != nullptr;
FString SucceededOrFailed = bOutSuccess ? "Succeeded" : "Failed";
OutInfoMsg = FString::Printf(TEXT("Link Sequence To Subsequence Track %s - '%s'"), *SucceededOrFailed, *LevelSequencePath);
}
PrivateDependencyModuleNames.AddRange
(
new string[]
{
// Default Modules
"Core",
"CoreUObject",
"Engine",
// New Modules
"LevelSequence",
"MovieScene",
}
);
Add / Remove Level Visibility Track In Level Sequence
Get a level visibility track from a level sequence
/**
* Get a level visibility track from a level sequence
*
* @param LevelSequencePath The path of the level sequence asset: "/Game/Folder/MyLevelSequence"
* @param bOutSuccess If the action was a success or not
* @param OutInfoMsg More information about the action's result
*
* @return The level visibility track
*/
UFUNCTION(BlueprintCallable, Category = "Level Visibility Track In Level Sequence")
static class UMovieSceneLevelVisibilityTrack* GetLevelVisibilityTrackFromLevelSequence(FString LevelSequencePath, bool& bOutSuccess, FString& OutInfoMsg);
#include "LevelSequence.h" // LevelSequence
#include "MovieScene.h" // MovieScene
#include "Tracks/MovieSceneLevelVisibilityTrack.h" // MovieSceneTracks
#include "Sections/MovieSceneLevelVisibilitySection.h" // MovieSceneTracks
UMovieSceneLevelVisibilityTrack* UExampleClass::GetLevelVisibilityTrackFromLevelSequence(FString LevelSequencePath, bool& bOutSuccess, FString& OutInfoMsg)
{
// Load Level Sequence
ULevelSequence* LevelSequence = UExampleClass::LoadLevelSequence(LevelSequencePath, bOutSuccess, OutInfoMsg);
if (LevelSequence == nullptr) return nullptr;
// Get the level visibility track
UMovieSceneLevelVisibilityTrack* LevelVisibilityTrack = LevelSequence->MovieScene->FindTrack<UMovieSceneLevelVisibilityTrack>();
bOutSuccess = LevelVisibilityTrack != nullptr;
FString SucceededOrFailed = bOutSuccess ? "Succeeded" : "Failed";
OutInfoMsg = FString::Printf(TEXT("Get Level Visibility Track From Level Sequence %s - '%s'"), *SucceededOrFailed, *LevelSequencePath);
return LevelVisibilityTrack;
}
PrivateDependencyModuleNames.AddRange
(
new string[]
{
// Default Modules
"Core",
"CoreUObject",
"Engine",
// New Modules
"LevelSequence",
"MovieScene",
MovieSceneTracks,
}
);
Add a level visibility track to a level sequence
/**
* Add a level visibility track to a level sequence
*
* @param LevelSequencePath The path of the level sequence asset: "/Game/Folder/MyLevelSequence"
* @param bOutSuccess If the action was a success or not
* @param OutInfoMsg More information about the action's result
*
* @return The level visibility track
*/
UFUNCTION(BlueprintCallable, Category = "Level Visibility Track In Level Sequence")
static class UMovieSceneLevelVisibilityTrack* AddLevelVisibilityTrackInLevelSequence(FString LevelSequencePath, bool& bOutSuccess, FString& OutInfoMsg);
#include "LevelSequence.h" // LevelSequence
#include "MovieScene.h" // MovieScene
#include "Tracks/MovieSceneLevelVisibilityTrack.h" // MovieSceneTracks
#include "Sections/MovieSceneLevelVisibilitySection.h" // MovieSceneTracks
UMovieSceneLevelVisibilityTrack* UExampleClass::AddLevelVisibilityTrackInLevelSequence(FString LevelSequencePath, bool& bOutSuccess, FString& OutInfoMsg)
{
// Check if there's a level visibility track in the level sequence
UMovieSceneLevelVisibilityTrack* LevelVisibilityTrack = GetLevelVisibilityTrackFromLevelSequence(LevelSequencePath, bOutSuccess, OutInfoMsg);
if (LevelVisibilityTrack != nullptr)
{
bOutSuccess = false;
OutInfoMsg = FString::Printf(TEXT("Add Level Visibility Track In Level Sequence Failed - Track already in level sequence. '%s'"), *LevelSequencePath);
return LevelVisibilityTrack;
}
// Load Level Sequence
ULevelSequence* LevelSequence = UExampleClass::LoadLevelSequence(LevelSequencePath, bOutSuccess, OutInfoMsg);
if (LevelSequence == nullptr) return nullptr;
// Add track
LevelVisibilityTrack = LevelSequence->MovieScene->AddTrack<UMovieSceneLevelVisibilityTrack>();
bOutSuccess = true;
OutInfoMsg = FString::Printf(TEXT("Add Level Visibility Track In Level Sequence Succeeded - '%s'"), *LevelSequencePath);
return LevelVisibilityTrack;
}
PrivateDependencyModuleNames.AddRange
(
new string[]
{
// Default Modules
"Core",
"CoreUObject",
"Engine",
// New Modules
"LevelSequence",
"MovieScene",
MovieSceneTracks,
}
);
Remove a level visibility track from a level sequence
/**
* Remove a level visibility track from a level sequence
*
* @param LevelSequencePath The path of the level sequence asset: "/Game/Folder/MyLevelSequence"
* @param bOutSuccess If the action was a success or not
* @param OutInfoMsg More information about the action's result
*/
UFUNCTION(BlueprintCallable, Category = "Level Visibility Track In Level Sequence")
static void RemoveLevelVisibilityTrackFromLevelSequence(FString LevelSequencePath, bool& bOutSuccess, FString& OutInfoMsg);
#include "LevelSequence.h" // LevelSequence
#include "MovieScene.h" // MovieScene
#include "Tracks/MovieSceneLevelVisibilityTrack.h" // MovieSceneTracks
#include "Sections/MovieSceneLevelVisibilitySection.h" // MovieSceneTracks
void UExampleClass::RemoveLevelVisibilityTrackFromLevelSequence(FString LevelSequencePath, bool& bOutSuccess, FString& OutInfoMsg)
{
// Check if there's a level visibility track in the level sequence
UMovieSceneLevelVisibilityTrack* LevelVisibilityTrack = GetLevelVisibilityTrackFromLevelSequence(LevelSequencePath, bOutSuccess, OutInfoMsg);
if (LevelVisibilityTrack == nullptr) return;
// Load Level Sequence
ULevelSequence* LevelSequence = UExampleClass::LoadLevelSequence(LevelSequencePath, bOutSuccess, OutInfoMsg);
if (LevelSequence == nullptr) return;
// Remove track
LevelSequence->MovieScene->RemoveTrack(*LevelVisibilityTrack);
bOutSuccess = true;
OutInfoMsg = FString::Printf(TEXT("Remove Level Visibility Track From Level Sequence Succeeded - '%s'"), *LevelSequencePath);
}
PrivateDependencyModuleNames.AddRange
(
new string[]
{
// Default Modules
"Core",
"CoreUObject",
"Engine",
// New Modules
"LevelSequence",
"MovieScene",
MovieSceneTracks,
}
);
Link a level sequence to a level visibility track in a level sequence
/**
* Link a level sequence to a level visibility track in a level sequence
*
* @param LevelSequencePath The path of the level sequence asset: "/Game/Folder/MyLevelSequence"
* @param LevelName The name of the level affected by the section
* @param LevelVisibility If true, the level will be set to visible
* @param StartFrame Start frame of the level visibility section in the level sequence
* @param EndFrame End frame of the level visibility section in the level sequence
* @param bOutSuccess If the action was a success or not
* @param OutInfoMsg More information about the action's result
*/
UFUNCTION(BlueprintCallable, Category = "Level Visibility Track In Level Sequence")
static void AddSectionToLevelVisibilityTrack(FString LevelSequencePath, FString LevelName, bool LevelVisibility, int StartFrame, int EndFrame, bool& bOutSuccess, FString& OutInfoMsg);
#include "LevelSequence.h" // LevelSequence
#include "MovieScene.h" // MovieScene
#include "Tracks/MovieSceneLevelVisibilityTrack.h" // MovieSceneTracks
#include "Sections/MovieSceneLevelVisibilitySection.h" // MovieSceneTracks
void UExampleClass::AddSectionToLevelVisibilityTrack(FString LevelSequencePath, FString LevelName, bool LevelVisibility, int StartFrame, int EndFrame, bool& bOutSuccess, FString& OutInfoMsg)
{
// Check if there's a level visibility track in the level sequence
UMovieSceneLevelVisibilityTrack* LevelVisibilityTrack = GetLevelVisibilityTrackFromLevelSequence(LevelSequencePath, bOutSuccess, OutInfoMsg);
if (LevelVisibilityTrack == nullptr)
{
bOutSuccess = false;
OutInfoMsg = FString::Printf(TEXT("Add Section To Level Visibility Track Failed - Level visibility track isn't valid. '%s'"), *LevelSequencePath);
return;
}
// Create section
UMovieSceneLevelVisibilitySection* Section = Cast<UMovieSceneLevelVisibilitySection>(LevelVisibilityTrack->CreateNewSection());
if (Section == nullptr)
{
bOutSuccess = false;
OutInfoMsg = FString::Printf(TEXT("Add Section To Level Visibility Track Failed - Failed to create section. '%s'"), *LevelSequencePath);
return;
}
// Set affected level and desired visibility
Section->SetLevelNames(TArray<FName>({ *LevelName }));
Section->SetVisibility(LevelVisibility ? ELevelVisibility::Visible : ELevelVisibility::Hidden);
// Calculate the amount of Ticks Per Frame for the input frame numbers.
// Level Sequence works in ticks, not in frames and quantity of ticks varies based on TickResolution and DisplayRate.
ULevelSequence* LevelSequence = CastMovieScene->GetDisplayRate().AsDecimal();
// Set frame range of the section
Section->SetRange(TRange<FFrameNumber>(FFrameNumber(StartFrame * TicksPerFrame), FFrameNumber(EndFrame * TicksPerFrame)));
// Place the section on a new row so it doesn't fight against another section
int RowIndex = -1;
for (UMovieSceneSection* ExistingSection : LevelVisibilityTrack->GetAllSections())
{
RowIndex = FMath::Max(RowIndex, ExistingSection->GetRowIndex());
}
Section->SetRowIndex(RowIndex + 1);
// Add section to level visibility track
LevelVisibilityTrack->AddSection(*Section);
bOutSuccess = true;
OutInfoMsg = FString::Printf(TEXT("Add Section To Level Visibility Track Succeeded - '%s'"), *LevelSequencePath);
}
PrivateDependencyModuleNames.AddRange
(
new string[]
{
// Default Modules
"Core",
"CoreUObject",
"Engine",
// New Modules
"LevelSequence",
"MovieScene",
MovieSceneTracks,
}
);
Add / Remove Transform Track In Level Sequence
Get the transform track from an actor in a level sequence
/**
* Get the transform track from an actor in a level sequence
*
* @param LevelSequencePath The path of the level sequence asset: "/Game/Folder/MyLevelSequence"
* @param Actor The actor in the level sequence
* @param bOutSuccess If the action was a success or not
* @param OutInfoMsg More information about the action's result
*
* @return The transform track
*/
UFUNCTION(BlueprintCallable, Category = "Transform Track In Level Sequence")
static class UMovieScene3DTransformTrack* GetTransformTrackFromActorInLevelSequence(FString LevelSequencePath, AActor* Actor, bool& bOutSuccess, FString& OutInfoMsg);
#include "LevelSequence.h" // LevelSequence
#include "MovieScene.h" // MovieScene
#include "Tracks/MovieScene3DTransformTrack.h" // MovieSceneTracks
#include "Sections/MovieScene3DTransformSection.h" // MovieSceneTracks
UMovieScene3DTransformTrack* UExampleClass::GetTransformTrackFromActorInLevelSequence(FString LevelSequencePath, AActor* Actor, bool& bOutSuccess, FString& OutInfoMsg)
{
// Get actor Guid
FGuid Guid = UExampleClass::GetActorGuidFromLevelSequence(Actor, LevelSequencePath, bOutSuccess, OutInfoMsg);
if (!Guid.IsValid()) return nullptr;
// Load Level Sequence
ULevelSequence* LevelSequence = UExampleClass::LoadLevelSequence(LevelSequencePath, bOutSuccess, OutInfoMsg);
if (LevelSequence == nullptr) return nullptr;
// Get the transform track
UMovieScene3DTransformTrack* TransformTrack = LevelSequence->MovieScene->FindTrack<UMovieScene3DTransformTrack>(Guid);
bOutSuccess = TransformTrack != nullptr;
FString SucceededOrFailed = bOutSuccess ? "Succeeded" : "Failed";
OutInfoMsg = FString::Printf(TEXT("Get Transform Track From Actor In Level Sequence %s - '%s'"), *SucceededOrFailed, *LevelSequencePath);
return TransformTrack;
}
PrivateDependencyModuleNames.AddRange
(
new string[]
{
// Default Modules
"Core",
"CoreUObject",
"Engine",
// New Modules
"LevelSequence",
"MovieScene",
MovieSceneTracks,
}
);
Add a transform track to an actor in a level sequence
/**
* Add a transform track to an actor in a level sequence
*
* @param LevelSequencePath The path of the level sequence asset: "/Game/Folder/MyLevelSequence"
* @param Actor The actor in the level sequence
* @param bOutSuccess If the action was a success or not
* @param OutInfoMsg More information about the action's result
*
* @return The transform track
*/
UFUNCTION(BlueprintCallable, Category = "Transform Track In Level Sequence")
static class UMovieScene3DTransformTrack* AddTransformTrackToActorInLevelSequence(FString LevelSequencePath, AActor* Actor, bool& bOutSuccess, FString& OutInfoMsg);
#include "LevelSequence.h" // LevelSequence
#include "MovieScene.h" // MovieScene
#include "Tracks/MovieScene3DTransformTrack.h" // MovieSceneTracks
#include "Sections/MovieScene3DTransformSection.h" // MovieSceneTracks
UMovieScene3DTransformTrack* UExampleClass::AddTransformTrackToActorInLevelSequence(FString LevelSequencePath, AActor* Actor, bool& bOutSuccess, FString& OutInfoMsg)
{
// Check if there's a transform track in the level sequence
UMovieScene3DTransformTrack* TransformTrack = GetTransformTrackFromActorInLevelSequence(LevelSequencePath, Actor, bOutSuccess, OutInfoMsg);
if (TransformTrack != nullptr)
{
bOutSuccess = false;
OutInfoMsg = FString::Printf(TEXT("Add Transform Track In Level Sequence Failed - Track already in level sequence. '%s'"), *LevelSequencePath);
return TransformTrack;
}
// Get actor Guid
FGuid Guid = UExampleClass::GetActorGuidFromLevelSequence(Actor, LevelSequencePath, bOutSuccess, OutInfoMsg);
if (!Guid.IsValid()) return nullptr;
// Load Level Sequence
ULevelSequence* LevelSequence = UExampleClass::LoadLevelSequence(LevelSequencePath, bOutSuccess, OutInfoMsg);
if (LevelSequence == nullptr) return nullptr;
// Add track
TransformTrack = LevelSequence->MovieScene->AddTrack<UMovieScene3DTransformTrack>(Guid);
bOutSuccess = true;
OutInfoMsg = FString::Printf(TEXT("Add Transform Track In Level Sequence Succeeded - '%s'"), *LevelSequencePath);
return TransformTrack;
}
PrivateDependencyModuleNames.AddRange
(
new string[]
{
// Default Modules
"Core",
"CoreUObject",
"Engine",
// New Modules
"LevelSequence",
"MovieScene",
MovieSceneTracks,
}
);
Remove a transform track from an actor in a level sequence
/**
* Remove a transform track from an actor in a level sequence
*
* @param LevelSequencePath The path of the level sequence asset: "/Game/Folder/MyLevelSequence"
* @param Actor The actor in the level sequence
* @param bOutSuccess If the action was a success or not
* @param OutInfoMsg More information about the action's result
*/
UFUNCTION(BlueprintCallable, Category = "Transform Track In Level Sequence")
static void RemoveTransformTrackFromActorInLevelSequence(FString LevelSequencePath, AActor* Actor, bool& bOutSuccess, FString& OutInfoMsg);
#include "LevelSequence.h" // LevelSequence
#include "MovieScene.h" // MovieScene
#include "Tracks/MovieScene3DTransformTrack.h" // MovieSceneTracks
#include "Sections/MovieScene3DTransformSection.h" // MovieSceneTracks
void UExampleClass::RemoveTransformTrackFromActorInLevelSequence(FString LevelSequencePath, AActor* Actor, bool& bOutSuccess, FString& OutInfoMsg)
{
// Check if there's a transform track in the level sequence
UMovieScene3DTransformTrack* TransformTrack = GetTransformTrackFromActorInLevelSequence(LevelSequencePath, Actor, bOutSuccess, OutInfoMsg);
if (TransformTrack == nullptr) return;
// Load level sequence
ULevelSequence* LevelSequence = Cast<ULevelSequence>(StaticLoadObject(ULevelSequence::StaticClass(), nullptr, *LevelSequencePath));
// Remove track
LevelSequence->MovieScene->RemoveTrack(*TransformTrack);
bOutSuccess = true;
OutInfoMsg = FString::Printf(TEXT("Remove Transform Track From Actor In Level Sequence Succeeded - '%s'"), *LevelSequencePath);
}
PrivateDependencyModuleNames.AddRange
(
new string[]
{
// Default Modules
"Core",
"CoreUObject",
"Engine",
// New Modules
"LevelSequence",
"MovieScene",
MovieSceneTracks,
}
);
Get the transform section from an actor in a level sequence
/**
* Get the transform section from an actor in a level sequence
*
* @param LevelSequencePath The path of the level sequence asset: "/Game/Folder/MyLevelSequence"
* @param Actor The actor in the level sequence
* @param SectionIndex Index of the section
* @param bOutSuccess If the action was a success or not
* @param OutInfoMsg More information about the action's result
*
* @return The transform section
*/
UFUNCTION(BlueprintCallable, Category = "Transform Track In Level Sequence")
static class UMovieScene3DTransformSection* GetTransformSectionFromActorInLevelSequence(FString LevelSequencePath, AActor* Actor, int SectionIndex, bool& bOutSuccess, FString& OutInfoMsg);
#include "LevelSequence.h" // LevelSequence
#include "MovieScene.h" // MovieScene
#include "Tracks/MovieScene3DTransformTrack.h" // MovieSceneTracks
#include "Sections/MovieScene3DTransformSection.h" // MovieSceneTracks
UMovieScene3DTransformSection* UExampleClass::GetTransformSectionFromActorInLevelSequence(FString LevelSequencePath, AActor* Actor, int SectionIndex, bool& bOutSuccess, FString& OutInfoMsg)
{
// Check if there's a transform track in the level sequence
UMovieScene3DTransformTrack* TransformTrack = GetTransformTrackFromActorInLevelSequence(LevelSequencePath, Actor, bOutSuccess, OutInfoMsg);
if (TransformTrack == nullptr) return nullptr;
// Get all sections
TArray<UMovieSceneSection*> AllSections = TransformTrack->GetAllSections();
// Make sure index is valid
if (SectionIndex < 0 || SectionIndex >= AllSections.Num())
{
bOutSuccess = false;
OutInfoMsg = FString::Printf(TEXT("Get Transform Section From Actor In Level Sequence Failed - Section index is invalid. '%s'"), *LevelSequencePath);
return nullptr;
}
// Return section
bOutSuccess = true;
OutInfoMsg = FString::Printf(TEXT("Get Transform Section From Actor In Level Sequence Succeeded - '%s'"), *LevelSequencePath);
return Cast<UMovieScene3DTransformSection>(AllSections[SectionIndex]);
}
PrivateDependencyModuleNames.AddRange
(
new string[]
{
// Default Modules
"Core",
"CoreUObject",
"Engine",
// New Modules
"LevelSequence",
"MovieScene",
MovieSceneTracks,
}
);
Add a transform section to an actor in a level sequence
#include "Evaluation/Blending/MovieSceneBlendType.h" // MovieScene
/**
* Add a transform section to an actor in a level sequence
*
* @param LevelSequencePath The path of the level sequence asset: "/Game/Folder/MyLevelSequence"
* @param Actor The actor in the level sequence
* @param StartFrame Start frame of the section
* @param EndFrame End frame of the section
* @param BlendType Blend type of the section
* @param bOutSuccess If the action was a success or not
* @param OutInfoMsg More information about the action's result
*
* @return The transform section
*/
UFUNCTION(BlueprintCallable, Category = "Transform Track In Level Sequence")
static class UMovieScene3DTransformSection* AddTransformSectionToActorInLevelSequence(FString LevelSequencePath, AActor* Actor, int StartFrame, int EndFrame, EMovieSceneBlendType BlendType, bool& bOutSuccess, FString& OutInfoMsg);
#include "LevelSequence.h" // LevelSequence
#include "MovieScene.h" // MovieScene
#include "Tracks/MovieScene3DTransformTrack.h" // MovieSceneTracks
#include "Sections/MovieScene3DTransformSection.h" // MovieSceneTracks
UMovieScene3DTransformSection* UExampleClass::AddTransformSectionToActorInLevelSequence(FString LevelSequencePath, AActor* Actor, int StartFrame, int EndFrame, EMovieSceneBlendType BlendType, bool& bOutSuccess, FString& OutInfoMsg) {
// Check if there's a transform track in the level sequence
UMovieScene3DTransformTrack* TransformTrack = GetTransformTrackFromActorInLevelSequence(LevelSequencePath, Actor, bOutSuccess, OutInfoMsg);
if (TransformTrack == nullptr) return nullptr;
// Create section
UMovieScene3DTransformSection* TransformSection = Cast<UMovieScene3DTransformSection>(TransformTrack->CreateNewSection());
if (TransformSection == nullptr)
{
bOutSuccess = false;
OutInfoMsg = FString::Printf(TEXT("Add Transform Section To Actor In Level Sequence Failed - Failed to create section. '%s'"), *LevelSequencePath);
return nullptr;
}
// Calculate the amount of Ticks Per Frame for the input frame numbers.
// Level Sequence works in ticks, not in frames and quantity of ticks varies based on TickResolution and DisplayRate.
ULevelSequence* LevelSequence = Cast<ULevelSequence>(StaticLoadObject(ULevelSequence::StaticClass(), nullptr, *LevelSequencePath));
int TicksPerFrame = LevelSequence->MovieScene->GetTickResolution().AsDecimal() / LevelSequence->MovieScene->GetDisplayRate().AsDecimal();
// Set frame range of the section
TransformSection->SetRange(TRange<FFrameNumber>(FFrameNumber(StartFrame * TicksPerFrame), FFrameNumber(EndFrame * TicksPerFrame)));
// Set blend type
TransformSection->SetBlendType(BlendType);
// Place the section on a new row so it doesn't fight against another section
int RowIndex = -1;
for (UMovieSceneSection* ExistingSection : TransformTrack->GetAllSections())
{
RowIndex = FMath::Max(RowIndex, ExistingSection->GetRowIndex());
}
TransformSection->SetRowIndex(RowIndex + 1);
// Add section to track
TransformTrack->AddSection(*TransformSection);
bOutSuccess = true;
OutInfoMsg = FString::Printf(TEXT("Add Transform Section To Actor In Level Sequence Succeeded - '%s'"), *LevelSequencePath);
return TransformSection;
}
PrivateDependencyModuleNames.AddRange
(
new string[]
{
// Default Modules
"Core",
"CoreUObject",
"Engine",
// New Modules
"LevelSequence",
"MovieScene",
MovieSceneTracks,
}
);
Remove a transform section from an actor in a level sequence
/**
* Remove a transform section from an actor in a level sequence
*
* @param LevelSequencePath The path of the level sequence asset: "/Game/Folder/MyLevelSequence"
* @param Actor The actor in the level sequence
* @param SectionIndex Index of the section
* @param bOutSuccess If the action was a success or not
* @param OutInfoMsg More information about the action's result
*/
UFUNCTION(BlueprintCallable, Category = "Transform Track In Level Sequence")
static void RemoveTransformSectionFromActorInLevelSequence(FString LevelSequencePath, AActor* Actor, int SectionIndex, bool& bOutSuccess, FString& OutInfoMsg);
#include "LevelSequence.h" // LevelSequence
#include "MovieScene.h" // MovieScene
#include "Tracks/MovieScene3DTransformTrack.h" // MovieSceneTracks
#include "Sections/MovieScene3DTransformSection.h" // MovieSceneTracks
void UExampleClass::RemoveTransformSectionFromActorInLevelSequence(FString LevelSequencePath, AActor* Actor, int SectionIndex, bool& bOutSuccess, FString& OutInfoMsg)
{
// Check if there's a transform track in the level sequence
UMovieScene3DTransformSection* TransformSection = GetTransformSectionFromActorInLevelSequence(LevelSequencePath, Actor, SectionIndex, bOutSuccess, OutInfoMsg);
if (TransformSection == nullptr) return;
// Get track
UMovieScene3DTransformTrack* TransformTrack = GetTransformTrackFromActorInLevelSequence(LevelSequencePath, Actor, bOutSuccess, OutInfoMsg);
// Remove section
TransformTrack->RemoveSection(*TransformSection);
// Refresh level sequence
TransformTrack->Modify();
bOutSuccess = true;
OutInfoMsg = FString::Printf(TEXT("Remove Transform Section From Actor In Level Sequence Succeeded - '%s'"), *LevelSequencePath);
}
PrivateDependencyModuleNames.AddRange
(
new string[]
{
// Default Modules
"Core",
"CoreUObject",
"Engine",
// New Modules
"LevelSequence",
"MovieScene",
MovieSceneTracks,
}
);
Add / Remove Keyframe to / from transform section In Level Sequence
Add a keyframe to a transform section in a level sequence
/**
* Add a keyframe to a transform section in a level sequence
*
* @param LevelSequencePath The path of the level sequence asset: "/Game/Folder/MyLevelSequence"
* @param Actor The actor in the level sequence
* @param SectionIndex Index of the section
* @param Frame Frame number
* @param Transform Value to apply to the keys
* @param KeyInterpolation Interpolation of the keys: 0=Cubic, 1=Linear, 2=Constant
* @param bOutSuccess If the action was a success or not
* @param OutInfoMsg More information about the action's result
*/
UFUNCTION(BlueprintCallable, Category = "Alex Quevillon - Add Transform Keyframe In Level Sequence")
static void AddTransformKeyframe(FString LevelSequencePath, AActor* Actor, int SectionIndex, int Frame, FTransform Transform, int KeyInterpolation, bool& bOutSuccess, FString& OutInfoMsg);
#include "LevelSequence.h" // LevelSequence
#include "MovieScene.h" // MovieScene
#include "MovieSceneSection.h" // MovieScene
#include "Sections/MovieScene3DTransformSection.h" // MovieSceneTracks
#include "Channels/MovieSceneChannelProxy.h" // MovieScene
#include "Channels/MovieSceneDoubleChannel.h" // MovieScene
void UExampleClass::AddTransformKeyframe(FString LevelSequencePath, AActor* Actor, int SectionIndex, int Frame, FTransform Transform, int KeyInterpolation, bool& bOutSuccess, FString& OutInfoMsg)
{
// Get the section
UMovieScene3DTransformSection* Section = UExampleClass::GetTransformSectionFromActorInLevelSequence(LevelSequencePath, Actor, SectionIndex, bOutSuccess, OutInfoMsg);
if (Section == nullptr)
{
bOutSuccess = false;
OutInfoMsg = FString::Printf(TEXT("Add Transform Keyframe Failed - Transform section is not valid. '%s'"), *LevelSequencePath);
return;
}
// Remove previous keyframe if there's one
RemoveTransformKeyframe(LevelSequencePath, Actor, SectionIndex, Frame, bOutSuccess, OutInfoMsg);
// Location
AddKeyframeToDoubleChannel(Section, 0, Frame, Transform.GetLocation().X, KeyInterpolation, bOutSuccess, OutInfoMsg);
AddKeyframeToDoubleChannel(Section, 1, Frame, Transform.GetLocation().Y, KeyInterpolation, bOutSuccess, OutInfoMsg);
AddKeyframeToDoubleChannel(Section, 2, Frame, Transform.GetLocation().Z, KeyInterpolation, bOutSuccess, OutInfoMsg);
// Rotation
AddKeyframeToDoubleChannel(Section, 3, Frame, Transform.Rotator().Roll, KeyInterpolation, bOutSuccess, OutInfoMsg);
AddKeyframeToDoubleChannel(Section, 4, Frame, Transform.Rotator().Pitch, KeyInterpolation, bOutSuccess, OutInfoMsg);
AddKeyframeToDoubleChannel(Section, 5, Frame, Transform.Rotator().Yaw, KeyInterpolation, bOutSuccess, OutInfoMsg);
// Scale
AddKeyframeToDoubleChannel(Section, 6, Frame, Transform.GetScale3D().X, KeyInterpolation, bOutSuccess, OutInfoMsg);
AddKeyframeToDoubleChannel(Section, 7, Frame, Transform.GetScale3D().Y, KeyInterpolation, bOutSuccess, OutInfoMsg);
AddKeyframeToDoubleChannel(Section, 8, Frame, Transform.GetScale3D().Z, KeyInterpolation, bOutSuccess, OutInfoMsg);
OutInfoMsg = bOutSuccess ? FString::Printf(TEXT("Add Transform Keyframe Succeeded - '%s'"), *LevelSequencePath) : OutInfoMsg;
}
PrivateDependencyModuleNames.AddRange
(
new string[]
{
// Default Modules
"Core",
"CoreUObject",
"Engine",
// New Modules
"LevelSequence",
"MovieScene",
MovieSceneTracks,
}
);
Remove a keyframe from a transform section in a level sequence
/**
* Remove a keyframe from a transform section in a level sequence
*
* @param LevelSequencePath The path of the level sequence asset: "/Game/Folder/MyLevelSequence"
* @param Actor The actor in the level sequence
* @param SectionIndex Index of the section
* @param Frame Frame number
* @param bOutSuccess If the action was a success or not
* @param OutInfoMsg More information about the action's result
*/
UFUNCTION(BlueprintCallable, Category = "Alex Quevillon - Add Transform Keyframe In Level Sequence")
static void RemoveTransformKeyframe(FString LevelSequencePath, AActor* Actor, int SectionIndex, int Frame, bool& bOutSuccess, FString& OutInfoMsg);
#include "LevelSequence.h" // LevelSequence
#include "MovieScene.h" // MovieScene
#include "MovieSceneSection.h" // MovieScene
#include "Sections/MovieScene3DTransformSection.h" // MovieSceneTracks
#include "Channels/MovieSceneChannelProxy.h" // MovieScene
#include "Channels/MovieSceneDoubleChannel.h" // MovieScene
void UExampleClass::RemoveTransformKeyframe(FString LevelSequencePath, AActor* Actor, int SectionIndex, int Frame, bool& bOutSuccess, FString& OutInfoMsg)
{
// Get the section
UMovieScene3DTransformSection* Section = UExampleClass::GetTransformSectionFromActorInLevelSequence(LevelSequencePath, Actor, SectionIndex, bOutSuccess, OutInfoMsg);
if (Section == nullptr)
{
bOutSuccess = false;
OutInfoMsg = FString::Printf(TEXT("Remove Transform Keyframe Failed - Transform section is not valid. '%s'"), *LevelSequencePath);
return;
}
// Location
RemoveKeyframeFromDoubleChannel(Section, 0, Frame, bOutSuccess, OutInfoMsg);
RemoveKeyframeFromDoubleChannel(Section, 1, Frame, bOutSuccess, OutInfoMsg);
RemoveKeyframeFromDoubleChannel(Section, 2, Frame, bOutSuccess, OutInfoMsg);
// Rotation
RemoveKeyframeFromDoubleChannel(Section, 3, Frame, bOutSuccess, OutInfoMsg);
RemoveKeyframeFromDoubleChannel(Section, 4, Frame, bOutSuccess, OutInfoMsg);
RemoveKeyframeFromDoubleChannel(Section, 5, Frame, bOutSuccess, OutInfoMsg);
// Scale
RemoveKeyframeFromDoubleChannel(Section, 6, Frame, bOutSuccess, OutInfoMsg);
RemoveKeyframeFromDoubleChannel(Section, 7, Frame, bOutSuccess, OutInfoMsg);
RemoveKeyframeFromDoubleChannel(Section, 8, Frame, bOutSuccess, OutInfoMsg);
OutInfoMsg = bOutSuccess ? FString::Printf(TEXT("Remove Transform Keyframe Succeeded - '%s'"), *LevelSequencePath) : OutInfoMsg;
}
PrivateDependencyModuleNames.AddRange
(
new string[]
{
// Default Modules
"Core",
"CoreUObject",
"Engine",
// New Modules
"LevelSequence",
"MovieScene",
MovieSceneTracks,
}
);
Add a keyframe to a double channel in a level sequence
/**
* Add a keyframe to a double channel in a level sequence
*
* @param Section Section to modify
* @param ChannelIndex Index of the channel
* @param Frame Frame number
* @param Value Value to apply to the keyframe
* @param KeyInterpolation Interpolation of the keys: 0=Cubic, 1=Linear, 2=Constant
* @param bOutSuccess If the action was a success or not
* @param OutInfoMsg More information about the action's result
*/
UFUNCTION(BlueprintCallable, Category = "Alex Quevillon - Add Transform Keyframe In Level Sequence")
static void AddKeyframeToDoubleChannel(UMovieSceneSection* Section, int ChannelIndex, int Frame, double Value, int KeyInterpolation, bool& bOutSuccess, FString& OutInfoMsg);
#include "LevelSequence.h" // LevelSequence
#include "MovieScene.h" // MovieScene
#include "MovieSceneSection.h" // MovieScene
#include "Sections/MovieScene3DTransformSection.h" // MovieSceneTracks
#include "Channels/MovieSceneChannelProxy.h" // MovieScene
#include "Channels/MovieSceneDoubleChannel.h" // MovieScene
void UExampleClass::AddKeyframeToDoubleChannel(UMovieSceneSection* Section, int ChannelIndex, int Frame, double Value, int KeyInterpolation, bool& bOutSuccess, FString& OutInfoMsg)
{
// Make sure section is valid
if (Section == nullptr)
{
bOutSuccess = false;
OutInfoMsg = FString::Printf(TEXT("Add Keyframe To Double Channel Failed - Section is not valid."));
return;
}
// Get the channel
FMovieSceneDoubleChannel* Channel = Section->GetChannelProxy().GetChannel<FMovieSceneDoubleChannel>(ChannelIndex);
if (Channel == nullptr)
{
bOutSuccess = false;
OutInfoMsg = FString::Printf(TEXT("Add Keyframe To Double Channel Failed - Channel is not valid."));
return;
}
// Calculate the amount of Ticks Per Frame for the input frame numbers.
// Level Sequence works in ticks, not in frames and quantity of ticks varies based on TickResolution and DisplayRate.
ULevelSequence* LevelSequence = Cast<ULevelSequence>(Section->GetOutermostObject());;
int TicksPerFrame = LevelSequence->MovieScene->GetTickResolution().AsDecimal() / LevelSequence->MovieScene->GetDisplayRate().AsDecimal();
FFrameNumber FrameNumber = FFrameNumber(Frame * TicksPerFrame);
// Add key to channel
if (KeyInterpolation == 0)
{
Channel->AddCubicKey(FrameNumber, Value);
}
else if (KeyInterpolation == 1)
{
Channel->AddLinearKey(FrameNumber, Value);
}
else
{
Channel->AddConstantKey(FrameNumber, Value);
}
// Refresh section
Section->Modify();
bOutSuccess = true;
OutInfoMsg = FString::Printf(TEXT("Add Keyframe To Double Channel Succeeded"));
}
PrivateDependencyModuleNames.AddRange
(
new string[]
{
// Default Modules
"Core",
"CoreUObject",
"Engine",
// New Modules
"LevelSequence",
"MovieScene",
MovieSceneTracks,
}
);
Remove a keyframe from a double channel in a level sequence
/**
* Remove a keyframe from a double channel in a level sequence
*
* @param Section Section to modify
* @param ChannelIndex Index of the channel
* @param Frame Frame number
* @param bOutSuccess If the action was a success or not
* @param OutInfoMsg More information about the action's result
*/
UFUNCTION(BlueprintCallable, Category = "Alex Quevillon - Add Transform Keyframe In Level Sequence")
static void RemoveKeyframeFromDoubleChannel(UMovieSceneSection* Section, int ChannelIndex, int Frame, bool& bOutSuccess, FString& OutInfoMsg);
#include "LevelSequence.h" // LevelSequence
#include "MovieScene.h" // MovieScene
#include "MovieSceneSection.h" // MovieScene
#include "Sections/MovieScene3DTransformSection.h" // MovieSceneTracks
#include "Channels/MovieSceneChannelProxy.h" // MovieScene
#include "Channels/MovieSceneDoubleChannel.h" // MovieScene
void UExampleClass::RemoveKeyframeFromDoubleChannel(UMovieSceneSection* Section, int ChannelIndex, int Frame, bool& bOutSuccess, FString& OutInfoMsg)
{
// Make sure section is valid
if (Section == nullptr)
{
bOutSuccess = false;
OutInfoMsg = FString::Printf(TEXT("Remove Keyframe From Double Channel Failed - Section is not valid."));
return;
}
// Get the channel
FMovieSceneDoubleChannel* Channel = Section->GetChannelProxy().GetChannel<FMovieSceneDoubleChannel>(ChannelIndex);
if (Channel == nullptr)
{
bOutSuccess = false;
OutInfoMsg = FString::Printf(TEXT("Remove Keyframe From Double Channel Failed - Channel is not valid."));
return;
}
// Calculate the amount of Ticks Per Frame for the input frame numbers.
// Level Sequence works in ticks, not in frames and quantity of ticks varies based on TickResolution and DisplayRate.
ULevelSequence* LevelSequence = Cast<ULevelSequence>(Section->GetOutermostObject());;
int TicksPerFrame = LevelSequence->MovieScene->GetTickResolution().AsDecimal() / LevelSequence->MovieScene->GetDisplayRate().AsDecimal();
FFrameNumber FrameNumber = FFrameNumber(Frame * TicksPerFrame);
// Find key we want to remove
TArray<FFrameNumber> UnusedKeyTimes;
TArray<FKeyHandle> KeyHandles;
Channel->GetKeys(TRange<FFrameNumber>(FrameNumber, FrameNumber), &UnusedKeyTimes, &KeyHandles);
// Remove key
Channel->DeleteKeys(KeyHandles);
// Refresh section
Section->Modify();
bOutSuccess = true;
OutInfoMsg = FString::Printf(TEXT("Remove Keyframe From Double Channel Succeeded"));
}
PrivateDependencyModuleNames.AddRange
(
new string[]
{
// Default Modules
"Core",
"CoreUObject",
"Engine",
// New Modules
"LevelSequence",
"MovieScene",
MovieSceneTracks,
}
);
Modify a keyframe interpolation in a transform section in a level sequence
#include "Curves/RealCurve.h" // Engine
/**
* Modify a keyframe interpolation in a transform section in a level sequence
*
* @param LevelSequencePath The path of the level sequence asset: "/Game/Folder/MyLevelSequence"
* @param Actor The actor in the level sequence
* @param SectionIndex Index of the section in the transform track
* @param ChannelIndex Index of the channel in the section
* @param Frame Frame number
* @param Value Value to apply to the key
* @param InterpMode Interpolation of the key: 0=Cubic, 1=Linear, 2=Constant
* @param TangentMode Tangents of the key: 0=Auto, 1=User, 2=Break
* @param ArriveTangent Arrive tangent of the key
* @param LeaveTangent Leave tangent of the key
* @param bOutSuccess If the action was a success or not
* @param OutInfoMsg More information about the action's result
*/
UFUNCTION(BlueprintCallable, Category = "Alex Quevillon - Set Keyframe Interpolation In Level Sequence")
static void SetKeyframeInterpolationInTransformTrack(FString LevelSequencePath, AActor* Actor, int SectionIndex, int ChannelIndex, int Frame, double Value, ERichCurveInterpMode InterpMode, ERichCurveTangentMode TangentMode, float ArriveTangent, float LeaveTangent, bool& bOutSuccess, FString& OutInfoMsg);
#include "LevelSequence.h" // LevelSequence
#include "MovieScene.h" // MovieScene
#include "MovieSceneSection.h" // MovieScene
#include "Sections/MovieScene3DTransformSection.h" // MovieSceneTracks
#include "Channels/MovieSceneChannelProxy.h" // MovieScene
#include "Channels/MovieSceneDoubleChannel.h" // MovieScene
void UExampleClass::SetKeyframeInterpolationInTransformTrack(FString LevelSequencePath, AActor* Actor, int SectionIndex, int ChannelIndex, int Frame, double Value, ERichCurveInterpMode InterpMode, ERichCurveTangentMode TangentMode, float ArriveTangent, float LeaveTangent, bool& bOutSuccess, FString& OutInfoMsg)
{
// Get the section
UMovieScene3DTransformSection* Section = UExampleClass::GetTransformSectionFromActorInLevelSequence(LevelSequencePath, Actor, SectionIndex, bOutSuccess, OutInfoMsg);
if (Section == nullptr)
{
bOutSuccess = false;
OutInfoMsg = FString::Printf(TEXT("Set Keyframe Interpolation In Double Channel Failed - Transform section is not valid. '%s'"), *LevelSequencePath);
return;
}
// Get the channel
FMovieSceneDoubleChannel* Channel = Section->GetChannelProxy().GetChannel<FMovieSceneDoubleChannel>(ChannelIndex);
if (Channel == nullptr)
{
bOutSuccess = false;
OutInfoMsg = FString::Printf(TEXT("Set Keyframe Interpolation In Double Channel Failed - Channel is not valid. '%s'"), *LevelSequencePath);
return;
}
// Calculate the amount of Ticks Per Frame for the input frame numbers.
// Level Sequence works in ticks, not in frames and quantity of ticks varies based on TickResolution and DisplayRate.
ULevelSequence* LevelSequence = Cast<ULevelSequence>(Section->GetOutermostObject());;
int TicksPerFrame = LevelSequence->MovieScene->GetTickResolution().AsDecimal() / LevelSequence->MovieScene->GetDisplayRate().AsDecimal();
FFrameNumber FrameNumber = FFrameNumber(Frame * TicksPerFrame);
// Find key(s) we want to modify
TArray<FFrameNumber> UnusedKeyTimes;
TArray<FKeyHandle> KeyHandles;
Channel->GetKeys(TRange<FFrameNumber>(FrameNumber, FrameNumber), &UnusedKeyTimes, &KeyHandles);
for (FKeyHandle Handle : KeyHandles)
{
// Find index
int Index = Channel->GetData().GetIndex(Handle);
// Apply settings
Channel->GetData().GetValues()[Index].Value = Value;
Channel->GetData().GetValues()[Index].InterpMode = InterpMode;
Channel->GetData().GetValues()[Index].TangentMode = TangentMode;
if (TangentMode == ERichCurveTangentMode::RCTM_Auto)
{
// When auto, should keep the tangents to 0 so Unreal controls them
Channel->GetData().GetValues()[Index].Tangent.ArriveTangent = 0.0f;
Channel->GetData().GetValues()[Index].Tangent.LeaveTangent = 0.0f;
}
else if (TangentMode == ERichCurveTangentMode::RCTM_User)
{
// When User, both tangents should be the same, in this case, we're using the ArriveTangent only
Channel->GetData().GetValues()[Index].Tangent.ArriveTangent = ArriveTangent;
Channel->GetData().GetValues()[Index].Tangent.LeaveTangent = ArriveTangent;
}
else if (TangentMode == ERichCurveTangentMode::RCTM_Break)
{
// When Brek, we can do anything we want
Channel->GetData().GetValues()[Index].Tangent.ArriveTangent = ArriveTangent;
Channel->GetData().GetValues()[Index].Tangent.LeaveTangent = LeaveTangent;
}
}
// Refresh section
Section->Modify();
bOutSuccess = true;
OutInfoMsg = FString::Printf(TEXT("Set Keyframe Interpolation In Double Channel Succeeded - '%s'"), *LevelSequencePath);
}
PrivateDependencyModuleNames.AddRange
(
new string[]
{
// Default Modules
"Core",
"CoreUObject",
"Engine",
// Required Modules
"LevelSequence",
"MovieScene",
MovieSceneTracks,
}
);
Visibility Keyframe In Level Sequence with C++
Add a keyframe to a Visibility track
#include "Kismet/BlueprintFunctionLibrary.h" // Engine
/**
* Add a keyframe to a Visibility track in a level sequence
*
* @param LevelSequencePath The path of the level sequence asset: "/Game/Folder/MyLevelSequence"
* @param Actor The actor in the level sequence
* @param Frame Frame number
* @param Visibility Value to apply to the key
* @param bOutSuccess If the action was a success or not
* @param OutInfoMsg More information about the action's result
*/
UFUNCTION(BlueprintCallable, Category = "Alex Quevillon - Visibility Keyframe In Level Sequence")
static void AddVisibilityKeyframe(FString LevelSequencePath, AActor* Actor, int Frame, bool Visibility, bool& bOutSuccess, FString& OutInfoMsg);
#include "LevelSequence.h" // LevelSequence
#include "MovieScene.h" // MovieScene
#include "MovieSceneSection.h" // MovieScene
#include "Tracks/MovieSceneVisibilityTrack.h" // MovieSceneTracks
#include "Sections/MovieSceneBoolSection.h" // MovieSceneTracks
#include "Channels/MovieSceneChannelProxy.h" // MovieScene
#include "Channels/MovieSceneBoolChannel.h" // MovieScene
void UExampleClass::AddVisibilityKeyframe(FString LevelSequencePath, AActor* Actor, int Frame, bool Visibility, bool& bOutSuccess, FString& OutInfoMsg)
{
// Remove previous keyframe if there's one
RemoveVisibilityKeyframe(LevelSequencePath, Actor, Frame, bOutSuccess, OutInfoMsg);
// Get actor Guid
FGuid Guid = UExampleClass::GetActorGuidFromLevelSequence(Actor, LevelSequencePath, bOutSuccess, OutInfoMsg);
if (!Guid.IsValid()) return;
// Load level sequence & calculate the amount of Ticks Per Frame for the input frame numbers.
// Level Sequence works in ticks, not in frames and quantity of ticks varies based on TickResolution and DisplayRate.
ULevelSequence* LevelSequence = Cast<ULevelSequence>(StaticLoadObject(ULevelSequence::StaticClass(), nullptr, *LevelSequencePath));
int TicksPerFrame = LevelSequence->MovieScene->GetTickResolution().AsDecimal() / LevelSequence->MovieScene->GetDisplayRate().AsDecimal();
FFrameNumber FrameNumber = FFrameNumber(Frame * TicksPerFrame);
// Get the visibility track
UMovieSceneVisibilityTrack* VisibilityTrack = LevelSequence->MovieScene->FindTrack<UMovieSceneVisibilityTrack>(Guid);
// Or create it if it doesn't exist
if (VisibilityTrack == nullptr) VisibilityTrack = LevelSequence->MovieScene->AddTrack<UMovieSceneVisibilityTrack>(Guid);
// Get the visibility section. Or create it if it doesn't exist
bool bSectionAdded = false;
UMovieSceneBoolSection* BoolSection = Cast<UMovieSceneBoolSection>(VisibilityTrack->FindOrAddSection(FrameNumber, bSectionAdded));
if (bSectionAdded) BoolSection->SetRange(TRange<FFrameNumber>::All());
// Get the channel
FMovieSceneBoolChannel* Channel = BoolSection->GetChannelProxy().GetChannel<FMovieSceneBoolChannel>(0);
// Add keyframe
Channel->AddKeys({ FrameNumber }, { Visibility });
// Refresh level sequence
VisibilityTrack->Modify();
BoolSection->Modify();
bOutSuccess = true;
OutInfoMsg = FString::Printf(TEXT("Add Visibility Keyframe Succeeded - '%s'"), *LevelSequencePath);
}
PrivateDependencyModuleNames.AddRange
(
new string[]
{
// Default Modules
"Core",
"CoreUObject",
"Engine",
// Required Modules
"LevelSequence",
"MovieScene",
MovieSceneTracks,
}
);
Remove a keyframe from a Visibility track in a level sequence
#include "Kismet/BlueprintFunctionLibrary.h" // Engine
/**
* Remove a keyframe from a Visibility track in a level sequence
*
* @param LevelSequencePath The path of the level sequence asset: "/Game/Folder/MyLevelSequence"
* @param Actor The actor in the level sequence
* @param Frame Frame number
* @param bOutSuccess If the action was a success or not
* @param OutInfoMsg More information about the action's result
*/
UFUNCTION(BlueprintCallable, Category = "Alex Quevillon - Visibility Keyframe In Level Sequence")
static void RemoveVisibilityKeyframe(FString LevelSequencePath, AActor* Actor, int Frame, bool& bOutSuccess, FString& OutInfoMsg);
#include "LevelSequence.h" // LevelSequence
#include "MovieScene.h" // MovieScene
#include "MovieSceneSection.h" // MovieScene
#include "Tracks/MovieSceneVisibilityTrack.h" // MovieSceneTracks
#include "Sections/MovieSceneBoolSection.h" // MovieSceneTracks
#include "Channels/MovieSceneChannelProxy.h" // MovieScene
#include "Channels/MovieSceneBoolChannel.h" // MovieScene
void UExampleClass::RemoveVisibilityKeyframe(FString LevelSequencePath, AActor* Actor, int Frame, bool& bOutSuccess, FString& OutInfoMsg)
{
// Get actor Guid
FGuid Guid = UExampleClass::GetActorGuidFromLevelSequence(Actor, LevelSequencePath, bOutSuccess, OutInfoMsg);
if (!Guid.IsValid()) return;
// Load level sequence & calculate the amount of Ticks Per Frame for the input frame numbers.
// Level Sequence works in ticks, not in frames and quantity of ticks varies based on TickResolution and DisplayRate.
ULevelSequence* LevelSequence = Cast<ULevelSequence>(StaticLoadObject(ULevelSequence::StaticClass(), nullptr, *LevelSequencePath));
int TicksPerFrame = LevelSequence->MovieScene->GetTickResolution().AsDecimal() / LevelSequence->MovieScene->GetDisplayRate().AsDecimal();
FFrameNumber FrameNumber = FFrameNumber(Frame * TicksPerFrame);
// Get the visibility track
UMovieSceneVisibilityTrack* VisibilityTrack = LevelSequence->MovieScene->FindTrack<UMovieSceneVisibilityTrack>(Guid);
if (VisibilityTrack == nullptr)
{
bOutSuccess = false;
OutInfoMsg = FString::Printf(TEXT("Remove Visibility Keyframe Failed - Visibility track is not valid. '%s'"), *LevelSequencePath);
return;
}
// Get the visibility section.
UMovieSceneBoolSection* BoolSection = Cast<UMovieSceneBoolSection>(VisibilityTrack->FindSection(FrameNumber));
if (BoolSection == nullptr)
{
bOutSuccess = false;
OutInfoMsg = FString::Printf(TEXT("Remove Visibility Keyframe Failed - Visibility section is not valid. '%s'"), *LevelSequencePath);
return;
}
// Get the channel
FMovieSceneBoolChannel* Channel = BoolSection->GetChannelProxy().GetChannel<FMovieSceneBoolChannel>(0);
// Find key we want to remove
TArray<FFrameNumber> UnusedKeyTimes;
TArray<FKeyHandle> KeyHandles;
Channel->GetKeys(TRange<FFrameNumber>(FrameNumber, FrameNumber), &UnusedKeyTimes, &KeyHandles);
// Remove key
Channel->DeleteKeys(KeyHandles);
// Refresh section
VisibilityTrack->Modify();
BoolSection->Modify();
bOutSuccess = true;
OutInfoMsg = FString::Printf(TEXT("Remove Visibility Keyframe Succeeded - '%s'"), *LevelSequencePath);
}
PrivateDependencyModuleNames.AddRange
(
new string[]
{
// Default Modules
"Core",
"CoreUObject",
"Engine",
// Required Modules
"LevelSequence",
"MovieScene",
MovieSceneTracks,
}
);
Add Material Parameter Collection Keyframe In Level Sequence
The code below allows to modify material of any linked Mesh or Actor.
#include "Kismet/BlueprintFunctionLibrary.h" // Engine
/**
* Add a keyframe to a Mpc float or color section in a level sequence
*
* @param LevelSequence The level sequence asset
* @param Frame Frame number
* @param Collection Material parameter collection asset
* @param Parameter Name of the material parameter
* @param FloatValue Value to apply to the float parameter
* @param ColorValue Value to apply to the color parameter
* @param bColor If true, apply ColorValue, else apply FloatValue
* @param bOutSuccess If the action was a success or not
* @param OutInfoMsg More information about the action's result
*/
UFUNCTION(BlueprintCallable, Category = "Alex Quevillon - Add Material Parameter Collection Keyframe In Level Sequence")
static void AddMpcKeyframe(class ULevelSequence* LevelSequence, class UMaterialParameterCollection* Collection, int Frame, FString Parameter, float FloatValue, FLinearColor ColorValue, bool bColor, bool& bOutSuccess, FString& OutInfoMsg);
#include "LevelSequence.h" // LevelSequence
#include "MovieScene.h" // MovieScene
#include "MovieSceneSection.h" // MovieScene
#include "Tracks/MovieSceneMaterialParameterCollectionTrack.h" // MovieSceneTracks
#include "Materials/MaterialParameterCollection.h" // Engine
void UExampleClass::AddMpcKeyframe(ULevelSequence* LevelSequence, UMaterialParameterCollection* Collection, int Frame, FString Parameter, float FloatValue, FLinearColor ColorValue, bool bColor, bool& bOutSuccess, FString& OutInfoMsg)
{
// Validate Level Sequence
if (LevelSequence == nullptr)
{
bOutSuccess = false;
OutInfoMsg = FString::Printf(TEXT("Add Mpc Float Keyframe Failed - Level Sequence is not valid"));
return;
}
// Validate MPC
if (Collection == nullptr)
{
bOutSuccess = false;
OutInfoMsg = FString::Printf(TEXT("Add Mpc Float Keyframe Failed - Material Parameter Collection is not valid"));
return;
}
// Get the Mpc track
TArray<UMovieSceneTrack*> Tracks = LevelSequence->MovieScene->GetTracks();
UMovieSceneMaterialParameterCollectionTrack* MpcTrack = nullptr;
for (UMovieSceneTrack* Track : Tracks)
{
UMovieSceneMaterialParameterCollectionTrack* MpcT = Cast<UMovieSceneMaterialParameterCollectionTrack>(Track);
if (MpcT != nullptr && MpcT->MPC == Collection)
{
MpcTrack = MpcT;
break;
}
}
// Or create it if it doesn't exist
if (MpcTrack == nullptr)
{
MpcTrack = LevelSequence->MovieScene->AddTrack<UMovieSceneMaterialParameterCollectionTrack>();
MpcTrack->MPC = Collection;
MpcTrack->SetDisplayName(FText::FromString(Collection->GetName()));
}
// Get section or create if if it doesn't exist
UMovieSceneSection* MpcSection = nullptr;
if (MpcTrack->GetAllSections().Num() > 0)
{
MpcSection = MpcTrack->GetAllSections()[0];
}
else
{
MpcSection = MpcTrack->CreateNewSection();
MpcSection->SetRange(TRange<FFrameNumber>::All());
MpcTrack->AddSection(*MpcSection);
}
// Calculate the amount of Ticks Per Frame for the input frame numbers.
// Level Sequence works in ticks, not in frames and quantity of ticks varies based on TickResolution and DisplayRate.
int TicksPerFrame = LevelSequence->MovieScene->GetTickResolution().AsDecimal() / LevelSequence->MovieScene->GetDisplayRate().AsDecimal();
FFrameNumber FrameNumber = FFrameNumber(Frame * TicksPerFrame);
if (bColor)
{
// Add Color Keyframe
MpcTrack->AddColorParameterKey(*Parameter, FrameNumber, ColorValue);
}
else
{
// Add Scalar Keyframe
MpcTrack->AddScalarParameterKey(*Parameter, FrameNumber, FloatValue);
}
// Refresh level sequence
MpcTrack->Modify();
MpcSection->Modify();
bOutSuccess = true;
OutInfoMsg = FString::Printf(TEXT("Add Mpc Keyframe Succeeded"));
}
PrivateDependencyModuleNames.AddRange
(
new string[]
{
// Default Modules
"Core",
"CoreUObject",
"Engine",
// Required Modules
"LevelSequence",
"MovieScene",
MovieSceneTracks,
}
);
Add BP Variables Keyframe In Level Sequence
The code below allows to add and update the value of Blueprint variables (exposed to cinematics) for any linked Blueprint Actor in the Level Sequence.
#include "Kismet/BlueprintFunctionLibrary.h" // Engine
/**
* Add a keyframe to a few BP actor variables in a level sequence
*
* @param LevelSequence The level sequence asset
* @param Actor The actor in the level sequence
* @param Frame Frame number
* @param bOutSuccess If the action was a success or not
* @param OutInfoMsg More information about the action's result
*/
UFUNCTION(BlueprintCallable, Category = "Alex Quevillon - Add Material Parameter Collection Keyframe In Level Sequence")
static void AddBpVariableKeyframe(class ULevelSequence* LevelSequence, AActor* Actor, int Frame, bool& bOutSuccess, FString& OutInfoMsg);
#include "LevelSequence.h" // LevelSequence
#include "MovieScene.h" // MovieScene
#include "MovieSceneSection.h" // MovieScene
#include "Tracks/MovieSceneBoolTrack.h" // MovieSceneTracks
#include "Sections/MovieSceneBoolSection.h" // MovieSceneTracks
#include "Channels/MovieSceneBoolChannel.h" // MovieScene
#include "Tracks/MovieSceneFloatTrack.h "// MovieSceneTracks
#include "Sections/MovieSceneFloatSection.h" // MovieSceneTracks
#include "Channels/MovieSceneFloatChannel.h" // MovieScene
#include "Tracks/MovieSceneByteTrack.h "// MovieSceneTracks
#include "Sections/MovieSceneByteSection.h" // MovieSceneTracks
#include "Channels/MovieSceneByteChannel.h" // MovieScene
void UExampleClass::AddBpVariableKeyframe(ULevelSequence* LevelSequence, AActor* Actor, int Frame, bool& bOutSuccess, FString& OutInfoMsg)
{
// Validate Level Sequence
if (LevelSequence == nullptr)
{
bOutSuccess = false;
OutInfoMsg = FString::Printf(TEXT("Add BP Variable Keyframe Failed - Level Sequence is not valid"));
return;
}
// Get actor Guid
FGuid Guid = UExampleClass::GetActorGuidFromLevelSequence(Actor, LevelSequence->GetPathName(), bOutSuccess, OutInfoMsg);
if (!Guid.IsValid()) return;
// Calculate the amount of Ticks Per Frame for the input frame numbers.
// Level Sequence works in ticks, not in frames and quantity of ticks varies based on TickResolution and DisplayRate.
int TicksPerFrame = LevelSequence->MovieScene->GetTickResolution().AsDecimal() / LevelSequence->MovieScene->GetDisplayRate().AsDecimal();
FFrameNumber FrameNumber = FFrameNumber(Frame * TicksPerFrame);
// Bool variable
{
// Get variable track
UMovieSceneBoolTrack* Track = LevelSequence->MovieScene->FindTrack<UMovieSceneBoolTrack>(Guid, "MyBpBoolVariableName");
// Or create it if it doesn't exist
if (Track == nullptr)
{
Track = LevelSequence->MovieScene->AddTrack<UMovieSceneBoolTrack>(Guid);
Track->SetPropertyNameAndPath("MyBpBoolVariableName", "MyBpBoolVariableName");
// To find the PropertyName & PropertyPath, add a breakpoint in UMovieScenePropertyTrack::SetPropertyNameAndPath and add the track manually in editor
}
// Get the section or create it if it doesn't exist
bool bSectionAdded = false;
UMovieSceneBoolSection* Section = Cast<UMovieSceneBoolSection>(Track->FindOrAddSection(FrameNumber, bSectionAdded));
if (bSectionAdded) Section->SetRange(TRange<FFrameNumber>::All());
// Get the channel
FMovieSceneBoolChannel* Channel = Section->GetChannelProxy().GetChannel<FMovieSceneBoolChannel>(0);
// Add keyframe
Channel->AddKeys({ FrameNumber }, { FMath::RandBool() });
// Refresh level sequence
Track->Modify();
Section->Modify();
}
// Float variable
{
// Get variable track
UMovieSceneFloatTrack* Track = LevelSequence->MovieScene->FindTrack<UMovieSceneFloatTrack>(Guid, "MyBpFloatVariableName");
// Or create it if it doesn't exist
if (Track == nullptr)
{
Track = LevelSequence->MovieScene->AddTrack<UMovieSceneFloatTrack>(Guid);
Track->SetPropertyNameAndPath("MyBpFloatVariableName", "MyBpFloatVariableName");
}
// Get the section or create it if it doesn't exist
bool bSectionAdded = false;
UMovieSceneFloatSection* Section = Cast<UMovieSceneFloatSection>(Track->FindOrAddSection(FrameNumber, bSectionAdded));
if (bSectionAdded) Section->SetRange(TRange<FFrameNumber>::All());
// Get the channel
FMovieSceneFloatChannel* Channel = Section->GetChannelProxy().GetChannel<FMovieSceneFloatChannel>(0);
// Add keyframe
Channel->AddLinearKey(FrameNumber, FMath::RandRange(-100.0f, 100.0f));
// Refresh level sequence
Track->Modify();
Section->Modify();
}
// Byte variable
{
// Get variable track
UMovieSceneByteTrack* Track = LevelSequence->MovieScene->FindTrack<UMovieSceneByteTrack>(Guid, "MyBpByteVariableName");
// Or create it if it doesn't exist
if (Track == nullptr)
{
Track = LevelSequence->MovieScene->AddTrack<UMovieSceneByteTrack>(Guid);
Track->SetPropertyNameAndPath("MyBpByteVariableName", "MyBpByteVariableName");
}
// Get the section or create it if it doesn't exist
bool bSectionAdded = false;
UMovieSceneByteSection* Section = Cast<UMovieSceneByteSection>(Track->FindOrAddSection(FrameNumber, bSectionAdded));
if (bSectionAdded) Section->SetRange(TRange<FFrameNumber>::All());
// Get the channel
FMovieSceneByteChannel* Channel = Section->GetChannelProxy().GetChannel<FMovieSceneByteChannel>(0);
// Add keyframe
Channel->AddKeys({ FrameNumber }, { uint8(FMath::RandRange(0, 7)) });
// Refresh level sequence
Track->Modify();
Section->Modify();
}
bOutSuccess = true;
OutInfoMsg = FString::Printf(TEXT("Add BP Variable Keyframe Succeeded"));
}
PrivateDependencyModuleNames.AddRange
(
new string[]
{
// Default Modules
"Core",
"CoreUObject",
"Engine",
// Required Modules
"LevelSequence",
"MovieScene",
MovieSceneTracks,
}
);
Start the Render of a Level Sequence
#include "Kismet/BlueprintFunctionLibrary.h" // Engine
/**
* Start a render process
*
* @param LevelSequence The level sequence asset to render
* @param OutputDirectory Where to save the output: "C:/Temp/MyRenderFolder"
* @param bRenderAsMovie If true, will render a movie. Otherwise, will render individual frames
* @param bOutSuccess If the action was a success or not
* @param OutInfoMsg More information about the action's result
*/
UFUNCTION(BlueprintCallable, Category = "Alex Quevillon - Start the Render of a Level Sequence")
static void StartLevelSequenceRender(class ULevelSequence* LevelSequence, FString OutputDirectory, bool bRenderAsMovie, bool& bOutSuccess, FString& OutInfoMsg);
#include "LevelSequenceActor.h" // LevelSequence
#include "SequencerTools.h" // SequencerScriptingEditor
#include "AutomatedLevelSequenceCapture.h" // MovieSceneTools
#include "Protocols/ImageSequenceProtocol.h" // MovieSceneCapture
#include "Protocols/VideoCaptureProtocol.h" // MovieSceneCapture & AVIWriter
#include "Protocols/AudioCaptureProtocol.h" // MovieSceneCapture
void UExampleClass::StartLevelSequenceRender(ULevelSequence* LevelSequence, FString OutputDirectory, bool bRenderAsMovie, bool& bOutSuccess, FString& OutInfoMsg)
{
// Validate Level Sequence
if (LevelSequence == nullptr)
{
bOutSuccess = false;
OutInfoMsg = FString::Printf(TEXT("Start Level Sequence Render Failed - Level Sequence is not valid"));
return;
}
// Create Capture Settings (Same as Render Movie Settings window)
UAutomatedLevelSequenceCapture* Capture = NewObject<UAutomatedLevelSequenceCapture>();
// Level sequence
Capture->LevelSequenceAsset = LevelSequence;
// Output directory
FDirectoryPath DirPath;
DirPath.Path = OutputDirectory;
Capture->Settings.OutputDirectory = DirPath;
// Render type
if (bRenderAsMovie)
{
Capture->SetImageCaptureProtocolType(UVideoCaptureProtocol::StaticClass());
Cast<UVideoCaptureProtocol>(Capture->ImageCaptureProtocol)->bUseCompression = true;
Cast<UVideoCaptureProtocol>(Capture->ImageCaptureProtocol)->CompressionQuality = 75;
// Possible Classes: UNullAudioCaptureProtocol, UMasterAudioSubmixCaptureProtocol
Capture->SetAudioCaptureProtocolType(UNullAudioCaptureProtocol::StaticClass());
}
else
{
// Possible Classes: UImageSequenceProtocol_JPG, UImageSequenceProtocol_PNG, UImageSequenceProtocol_BMP, UImageSequenceProtocol_EXR
Capture->SetImageCaptureProtocolType(UImageSequenceProtocol_PNG::StaticClass());
Cast<UImageSequenceProtocol_PNG>(Capture->ImageCaptureProtocol)->CompressionQuality = 75;
}
// UMovieSceneCapture
Capture->bUseSeparateProcess = true; // If true, set bCloseEditorWhenCaptureStarts, AdditionalCommandLineArguments & InheritedCommandLineArguments.
Capture->bCloseEditorWhenCaptureStarts = false;
Capture->AdditionalCommandLineArguments = "-NOSCREENMESSAGES";
Capture->InheritedCommandLineArguments = "-skipcompile";
// FMovieSceneCaptureSettings
Capture->Settings.GameModeOverride = nullptr;
Capture->Settings.OutputFormat = "{shot}_{frame}";
Capture->Settings.bOverwriteExisting = true;
Capture->Settings.bUseRelativeFrameNumbers = false;
Capture->Settings.HandleFrames = 0;
Capture->Settings.ZeroPadFrameNumbers = 0;
Capture->Settings.FrameRate = FFrameRate(30, 1);
Capture->Settings.bUseCustomFrameRate = false; // If true, set CustomFrameRate
Capture->Settings.Resolution = FCaptureResolution(1920, 1080);
Capture->Settings.bEnableTextureStreaming = false;
Capture->Settings.bCinematicEngineScalability = false;
Capture->Settings.bCinematicMode = false; // If true, set bAllowMovement, bAllowTurning, bShowPlayer, bShowHUD
Capture->Settings.bUsePathTracer = false; // If true, set PathTracerSamplePerPixel
// UAutomatedLevelSequenceCapture
Capture->ShotName = "MyRender";
Capture->bUseCustomStartFrame = false; // If true, set CustomStartFrame
Capture->bUseCustomEndFrame = false; // If true, set CustomEndFrame
Capture->WarmUpFrameCount = 0;
Capture->DelayBeforeWarmUp = 0.0f;
Capture->DelayBeforeShotWarmUp = 0.0f;
Capture->DelayEveryFrame = 0.0f;
Capture->bWriteEditDecisionList = false;
Capture->bWriteFinalCutProXML = false;
// ULevelSequenceBurnInOptions
ULevelSequenceBurnInOptions* BurnIn = NewObject<ULevelSequenceBurnInOptions>();
BurnIn->bUseBurnIn = true;
Capture->BurnInOptions = BurnIn;
// Start Render
USequencerToolsFunctionLibrary::RenderMovie(Capture, FOnRenderMovieStopped());
bOutSuccess = true;
OutInfoMsg = FString::Printf(TEXT("Start Level Sequence Render Succeeded"));
}
PrivateDependencyModuleNames.AddRange
(
new string[]
{
// Default Modules
"Core",
"CoreUObject",
"Engine",
// Required Modules
"LevelSequence",
"SequencerScriptingEditor",
"MovieSceneTools",
"MovieSceneCapture",
"AVIWriter",
}
);