Files
UnrealEngineUWP/Engine/Source/Runtime/LevelSequence/Private/LevelSequence.cpp

1014 lines
35 KiB
C++
Raw Normal View History

// Copyright Epic Games, Inc. All Rights Reserved.
#include "LevelSequence.h"
#include "IMovieSceneMetaData.h"
#include "MovieSceneMetaData.h"
#include "Engine/EngineTypes.h"
#include "HAL/IConsoleManager.h"
#include "UniversalObjectLocator.h"
#include "UniversalObjectLocatorFragmentType.h"
#include "UniversalObjectLocatorResolveParameterBuffer.inl"
#include "UniversalObjectLocators/ActorLocatorFragment.h"
#include "WorldPartition/IWorldPartitionObjectResolver.h"
#include "LegacyLazyObjectPtrFragment.h"
#include "SubObjectLocator.h"
#include "Components/ActorComponent.h"
#include "Components/SkeletalMeshComponent.h"
#include "GameFramework/Actor.h"
#include "LevelSequenceDirector.h"
#include "Engine/Engine.h"
#include "MovieScene.h"
#include "MovieSceneCommonHelpers.h"
#include "UObject/AssetRegistryTagsContext.h"
#include "UObject/Package.h"
#include "UObject/UObjectHash.h"
#include "Animation/AnimInstance.h"
#include "LevelSequenceModule.h"
#include "MovieSceneSpawnableAnnotation.h"
#include "Tracks/MovieScene3DAttachTrack.h"
#include "Tracks/MovieScene3DPathTrack.h"
#include "Tracks/MovieSceneAudioTrack.h"
#include "Tracks/MovieSceneCameraCutTrack.h"
#include "Tracks/MovieSceneCinematicShotTrack.h"
#include "Tracks/MovieSceneEventTrack.h"
#include "Tracks/MovieSceneFadeTrack.h"
#include "Tracks/MovieSceneLevelVisibilityTrack.h"
#include "Tracks/MovieSceneDataLayerTrack.h"
#include "Tracks/MovieSceneMaterialParameterCollectionTrack.h"
#include "Tracks/MovieSceneSkeletalAnimationTrack.h"
#include "Tracks/MovieSceneSlomoTrack.h"
#include "Tracks/MovieSceneSpawnTrack.h"
#include "Tracks/MovieSceneSubTrack.h"
#include "Tracks/MovieSceneTimeWarpTrack.h"
#include "Tracks/MovieSceneCVarTrack.h"
#include "Tracks/MovieSceneBindingLifetimeTrack.h"
#include "Modules/ModuleManager.h"
#include "LevelSequencePlayer.h"
#include "Compilation/MovieSceneCompiledDataManager.h"
#include "Evaluation/MovieSceneEvaluationTemplateInstance.h"
#include "UniversalObjectLocators/AnimInstanceLocatorFragment.h"
#include "Engine/AssetUserData.h"
#include "Misc/App.h"
#include "Misc/DateTime.h"
Sequencer- Resubmission of changelist 34065553 that had been backed out for a versioning issue which is now fixed. Original description below: Sequencer- Dynamic Binding Refactor Refactor the 'Dynamic Binding' blueprint system to be Custom Bindings rather than tied directly to FMovieScenePossessable and FMovieSceneSpawnable. As part of this: ? Created UMovieSceneReplaceableDirectorBlueprintBinding and UMovieSceneSpawnableDirectorBlueprintBinding to replace the Possessable and Spawnable versions of DynamicBindings ? Deprecated the DynamicBinding references on possessable and spawnable and created Postload fixup code to automatically create custom bindings instead ? Note that because the previous Dynamic Bindings operated as overrides and the new ones don't, there is a no longer supported path which is using Possessables as a preview in editor for Possessable Dynamic Bindings. Now if you don't mark 'Call in Editor' for a Replaceable Director Blueprint binding, you'll need to define a spawnable preview binding for the binding in order to work with it in Sequencer. ? Since UMG also used Dynamic Bindings on possessables, temporarily add DynamicBinding as a member variable on FWidgetAnimationBinding and create postload logic to move DynamicBindings to live on there for WidgetAnimations. ? USD has custom code to create dynamic bindings automatically for its use case. Convert this also to use the new custom binding system. ? Some cleanup on object binding right-click menus was done as part of this. ? Some further MovieSceneSequence API deprecation and refactoring has been done for the creation of bindings to add SharedPlaybackState where possible which was necessary for dynamic binding setup. FMovieSceneSpawnable deprecation in Level Sequences Since I was having to write postload fixup logic for FMovieSceneSpawnables with Dynamic Bindings that converted these to FMovieScenePossessables with custom bindings, it felt like a good chance to deprecate all FMovieSceneSpawnable use in Level Sequences. I chose at this time not to deprecate FMovieSceneSpawnable use for non-Level-Sequence Movie Scene Sequences. This includes Day Sequences, Template Sequences, Actor Sequences, Widget Animations, Niagara Sequences, and some Meta Human sequences. I made this choice because to do so would require also refactoring those sequence types to use MovieSceneBindingReferences in order to enable custom bindings for those sequence types. This will be a future refactor. Some notes on this deprecation. ? I kept MovieScene specific code that references or creates FMovieSceneSpawnables due to not refactoring all MovieSceneSequences ? Binding creation code in tools such as Sequencer will check for the presence of Binding References and create custom bindings if present, otherwise will still create FMovieSceneSpawnables ? AvaSequences required some extra work to make this change, including some changes and bugfixes to copy/pasting bindings to move away from custom avalanche copy/paste code, as the copy/paste code for custom bindings is a bit intricate and I didn't want to duplicate it. ? Chaos Cache has been moved away from using an object spawner and instead uses a custom spawnable actor binding inheriting from the regular spawnable actor binding. ? Actor and Take Recording has been updated to support custom spawnable bindings ? Meta Human specific code has been updated to support custom spawnable bindings when using Level Sequences ? FortniteMainBranchObjectVersion has been bumped Crash fix As part of the USD work, I found a crash bug where the Binding Properties menu would hold a reference to a level sequence. In the case of USD, the outer of the sequences can be the level, and this caused issues when switching levels. To fix this I ended up needing to add some events when menus are being dismissed so I could clean up these references. #jira UE-209839, UE-209548, UE-213115, UE-214195, UE-214443 #rb Marc.Audy #lockdown Marc.Audy [FYI] juan.portillo, Viktar.Mikhalchuk, Darrien.Blanchard, patrick.boutot [CL 34127005 by david bromberg in ue5-main branch]
2024-06-05 11:54:07 -04:00
#include "UObject/FortniteMainBranchObjectVersion.h"
#include "Bindings/MovieSceneSpawnableDirectorBlueprintBinding.h"
#include "Bindings/MovieSceneReplaceableDirectorBlueprintBinding.h"
#include "Bindings/MovieSceneSpawnableActorBinding.h"
#include "MovieSceneFolder.h"
#include "Sections/MovieSceneBindingLifetimeSection.h"
#include UE_INLINE_GENERATED_CPP_BY_NAME(LevelSequence)
#if WITH_EDITOR
#include "UObject/SequencerObjectVersion.h"
#include "UObject/ObjectRedirector.h"
ULevelSequence::FPostDuplicateEvent ULevelSequence::PostDuplicateEvent;
Sequencer- Resubmission of changelist 34065553 that had been backed out for a versioning issue which is now fixed. Original description below: Sequencer- Dynamic Binding Refactor Refactor the 'Dynamic Binding' blueprint system to be Custom Bindings rather than tied directly to FMovieScenePossessable and FMovieSceneSpawnable. As part of this: ? Created UMovieSceneReplaceableDirectorBlueprintBinding and UMovieSceneSpawnableDirectorBlueprintBinding to replace the Possessable and Spawnable versions of DynamicBindings ? Deprecated the DynamicBinding references on possessable and spawnable and created Postload fixup code to automatically create custom bindings instead ? Note that because the previous Dynamic Bindings operated as overrides and the new ones don't, there is a no longer supported path which is using Possessables as a preview in editor for Possessable Dynamic Bindings. Now if you don't mark 'Call in Editor' for a Replaceable Director Blueprint binding, you'll need to define a spawnable preview binding for the binding in order to work with it in Sequencer. ? Since UMG also used Dynamic Bindings on possessables, temporarily add DynamicBinding as a member variable on FWidgetAnimationBinding and create postload logic to move DynamicBindings to live on there for WidgetAnimations. ? USD has custom code to create dynamic bindings automatically for its use case. Convert this also to use the new custom binding system. ? Some cleanup on object binding right-click menus was done as part of this. ? Some further MovieSceneSequence API deprecation and refactoring has been done for the creation of bindings to add SharedPlaybackState where possible which was necessary for dynamic binding setup. FMovieSceneSpawnable deprecation in Level Sequences Since I was having to write postload fixup logic for FMovieSceneSpawnables with Dynamic Bindings that converted these to FMovieScenePossessables with custom bindings, it felt like a good chance to deprecate all FMovieSceneSpawnable use in Level Sequences. I chose at this time not to deprecate FMovieSceneSpawnable use for non-Level-Sequence Movie Scene Sequences. This includes Day Sequences, Template Sequences, Actor Sequences, Widget Animations, Niagara Sequences, and some Meta Human sequences. I made this choice because to do so would require also refactoring those sequence types to use MovieSceneBindingReferences in order to enable custom bindings for those sequence types. This will be a future refactor. Some notes on this deprecation. ? I kept MovieScene specific code that references or creates FMovieSceneSpawnables due to not refactoring all MovieSceneSequences ? Binding creation code in tools such as Sequencer will check for the presence of Binding References and create custom bindings if present, otherwise will still create FMovieSceneSpawnables ? AvaSequences required some extra work to make this change, including some changes and bugfixes to copy/pasting bindings to move away from custom avalanche copy/paste code, as the copy/paste code for custom bindings is a bit intricate and I didn't want to duplicate it. ? Chaos Cache has been moved away from using an object spawner and instead uses a custom spawnable actor binding inheriting from the regular spawnable actor binding. ? Actor and Take Recording has been updated to support custom spawnable bindings ? Meta Human specific code has been updated to support custom spawnable bindings when using Level Sequences ? FortniteMainBranchObjectVersion has been bumped Crash fix As part of the USD work, I found a crash bug where the Binding Properties menu would hold a reference to a level sequence. In the case of USD, the outer of the sequences can be the level, and this caused issues when switching levels. To fix this I ended up needing to add some events when menus are being dismissed so I could clean up these references. #jira UE-209839, UE-209548, UE-213115, UE-214195, UE-214443 #rb Marc.Audy #lockdown Marc.Audy [FYI] juan.portillo, Viktar.Mikhalchuk, Darrien.Blanchard, patrick.boutot [CL 34127005 by david bromberg in ue5-main branch]
2024-06-05 11:54:07 -04:00
ULevelSequence::FFixupDynamicBindingsEvent ULevelSequence::FixupDynamicBindingsEvent;
#endif
static TAutoConsoleVariable<int32> CVarDefaultLockEngineToDisplayRate(
TEXT("LevelSequence.DefaultLockEngineToDisplayRate"),
0,
TEXT("0: Playback locked to playback frames\n1: Unlocked playback with sub frame interpolation"),
ECVF_Default);
static TAutoConsoleVariable<FString> CVarDefaultTickResolution(
TEXT("LevelSequence.DefaultTickResolution"),
TEXT("24000fps"),
TEXT("Specifies the default tick resolution for newly created level sequences. Examples: 30 fps, 120/1 (120 fps), 30000/1001 (29.97), 0.01s (10ms)."),
ECVF_Default);
static TAutoConsoleVariable<FString> CVarDefaultDisplayRate(
TEXT("LevelSequence.DefaultDisplayRate"),
TEXT("30fps"),
TEXT("Specifies the default display frame rate for newly created level sequences; also defines frame locked frame rate where sequences are set to be frame locked. Examples: 30 fps, 120/1 (120 fps), 30000/1001 (29.97), 0.01s (10ms)."),
ECVF_Default);
static TAutoConsoleVariable<int32> CVarDefaultClockSource(
TEXT("LevelSequence.DefaultClockSource"),
0,
TEXT("Specifies the default clock source for newly created level sequences. 0: Tick, 1: Platform, 2: Audio, 3: RelativeTimecode, 4: Timecode, 5: Custom"),
ECVF_Default);
ULevelSequence::ULevelSequence(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
, MovieScene(nullptr)
{
bParentContextsAreSignificant = true;
}
void ULevelSequence::Initialize()
{
MovieScene = NewObject<UMovieScene>(this, NAME_None, RF_Transactional);
const bool bFrameLocked = CVarDefaultLockEngineToDisplayRate.GetValueOnGameThread() != 0;
MovieScene->SetEvaluationType( bFrameLocked ? EMovieSceneEvaluationType::FrameLocked : EMovieSceneEvaluationType::WithSubFrames );
FFrameRate TickResolution(60000, 1);
TryParseString(TickResolution, *CVarDefaultTickResolution.GetValueOnGameThread());
MovieScene->SetTickResolutionDirectly(TickResolution);
FFrameRate DisplayRate(30, 1);
TryParseString(DisplayRate, *CVarDefaultDisplayRate.GetValueOnGameThread());
MovieScene->SetDisplayRate(DisplayRate);
int32 ClockSource = CVarDefaultClockSource.GetValueOnGameThread();
MovieScene->SetClockSource((EUpdateClockSource)ClockSource);
#if WITH_EDITOR
UMovieSceneMetaData* MetaData = FindOrAddMetaData<UMovieSceneMetaData>();
MetaData->SetCreated(FDateTime::UtcNow());
MetaData->SetAuthor(FApp::GetSessionOwner());
#endif
}
UObject* ULevelSequence::MakeSpawnableTemplateFromInstance(UObject& InSourceObject, FName ObjectName)
{
return MovieSceneHelpers::MakeSpawnableTemplateFromInstance(InSourceObject, MovieScene, ObjectName);
}
bool ULevelSequence::CanAnimateObject(UObject& InObject) const
{
return InObject.IsA<AActor>() || InObject.IsA<UActorComponent>() || InObject.IsA<UAnimInstance>();
}
#if WITH_EDITOR
ETrackSupport ULevelSequence::IsTrackSupportedImpl(TSubclassOf<class UMovieSceneTrack> InTrackClass) const
{
if (InTrackClass == UMovieScene3DAttachTrack::StaticClass() ||
InTrackClass == UMovieScene3DPathTrack::StaticClass() ||
InTrackClass == UMovieSceneAudioTrack::StaticClass() ||
InTrackClass == UMovieSceneCameraCutTrack::StaticClass() ||
InTrackClass == UMovieSceneCinematicShotTrack::StaticClass() ||
InTrackClass == UMovieSceneEventTrack::StaticClass() ||
InTrackClass == UMovieSceneFadeTrack::StaticClass() ||
InTrackClass == UMovieSceneLevelVisibilityTrack::StaticClass() ||
InTrackClass == UMovieSceneDataLayerTrack::StaticClass() ||
InTrackClass == UMovieSceneMaterialParameterCollectionTrack::StaticClass() ||
InTrackClass == UMovieSceneSkeletalAnimationTrack::StaticClass() ||
InTrackClass == UMovieSceneSlomoTrack::StaticClass() ||
InTrackClass == UMovieSceneSpawnTrack::StaticClass() ||
InTrackClass == UMovieSceneSubTrack::StaticClass() ||
InTrackClass == UMovieSceneCVarTrack::StaticClass() ||
InTrackClass == UMovieSceneBindingLifetimeTrack::StaticClass() ||
InTrackClass == UMovieSceneTimeWarpTrack::StaticClass())
{
return ETrackSupport::Supported;
}
return Super::IsTrackSupportedImpl(InTrackClass);
}
void ULevelSequence::GetAssetRegistryTags(TArray<FAssetRegistryTag>& OutTags) const
{
PRAGMA_DISABLE_DEPRECATION_WARNINGS;
Super::GetAssetRegistryTags(OutTags);
PRAGMA_ENABLE_DEPRECATION_WARNINGS;
}
void ULevelSequence::GetAssetRegistryTags(FAssetRegistryTagsContext Context) const
{
#if WITH_EDITORONLY_DATA
if (DirectorBlueprint)
{
DirectorBlueprint->GetAssetRegistryTags(Context);
}
#endif
for (UObject* MetaData : MetaDataObjects)
{
IMovieSceneMetaDataInterface* MetaDataInterface = Cast<IMovieSceneMetaDataInterface>(MetaData);
if (MetaDataInterface)
{
PRAGMA_DISABLE_DEPRECATION_WARNINGS;
TArray<UObject::FAssetRegistryTag> DeprecatedFunctionTags;
MetaDataInterface->ExtendAssetRegistryTags(DeprecatedFunctionTags);
for (UObject::FAssetRegistryTag& Tag : DeprecatedFunctionTags)
{
Context.AddTag(MoveTemp(Tag));
}
PRAGMA_ENABLE_DEPRECATION_WARNINGS;
MetaDataInterface->ExtendAssetRegistryTags(Context);
}
}
Super::GetAssetRegistryTags(Context);
}
void ULevelSequence::GetAssetRegistryTagMetadata(TMap<FName, FAssetRegistryTagMetadata>& OutMetadata) const
{
for (UObject* MetaData : MetaDataObjects)
{
IMovieSceneMetaDataInterface* MetaDataInterface = Cast<IMovieSceneMetaDataInterface>(MetaData);
if (MetaDataInterface)
{
MetaDataInterface->ExtendAssetRegistryTagMetaData(OutMetadata);
}
}
Super::GetAssetRegistryTagMetadata(OutMetadata);
}
void ULevelSequence::ThreadedPostLoadAssetRegistryTagsOverride(FPostLoadAssetRegistryTagsContext& Context) const
{
Super::ThreadedPostLoadAssetRegistryTagsOverride(Context);
// GetAssetRegistryTags appends the DirectorBlueprint tags to the World's tags, so we also have to run the Blueprint ThreadedPostLoadAssetRegistryTagsOverride
UBlueprint::PostLoadBlueprintAssetRegistryTags(Context);
}
void PurgeLegacyBlueprints(UObject* InObject, UPackage* Package)
{
if (UBlueprint* BP = Cast<UBlueprint>(InObject))
{
UPackage* TransientPackage = GetTransientPackage();
{
FString OldName = BP->GetName();
BP->ClearFlags(RF_Public);
BP->SetFlags(RF_Transient);
BP->RemoveFromRoot();
FName NewName = MakeUniqueObjectName(TransientPackage, UBlueprint::StaticClass(), *FString::Printf(TEXT("DEAD_SPAWNABLE_BLUEPRINT_%s"), *BP->GetName()));
BP->Rename(*NewName.ToString(), GetTransientPackage(), REN_NonTransactional | REN_DoNotDirty);
UE_LOG(LogLevelSequence, Log, TEXT("Discarding blueprint '%s' from package '%s'."), *OldName, *Package->GetName());
}
if (BP->GeneratedClass)
{
FName OldName = BP->GeneratedClass->GetFName();
UObject* OldOuter = BP->GeneratedClass->GetOuter();
UClass* SuperClass = BP->GeneratedClass->GetSuperClass();
if( BP->GeneratedClass->ClassDefaultObject )
{
BP->GeneratedClass->ClassDefaultObject->ClearFlags(RF_Public);
BP->GeneratedClass->ClassDefaultObject->SetFlags(RF_Transient);
BP->GeneratedClass->ClassDefaultObject->RemoveFromRoot();
}
BP->GeneratedClass->ClearFlags(RF_Public);
BP->GeneratedClass->SetFlags(RF_Transient);
BP->GeneratedClass->ClassFlags |= CLASS_Deprecated;
BP->GeneratedClass->RemoveFromRoot();
FName NewName = MakeUniqueObjectName(TransientPackage, BP->GeneratedClass, *FString::Printf(TEXT("DEAD_SPAWNABLE_BP_CLASS_%s_C"), *BP->GeneratedClass->ClassGeneratedBy->GetName()));
BP->GeneratedClass->Rename(*NewName.ToString(), GetTransientPackage(), REN_DoNotDirty | REN_NonTransactional);
if (SuperClass)
{
UObjectRedirector* Redirector = NewObject<UObjectRedirector>(OldOuter, OldName);
Redirector->DestinationObject = SuperClass;
UE_LOG(LogLevelSequence, Log, TEXT("Discarding generated class '%s' from package '%s'. Replacing with redirector to '%s'"), *OldName.ToString(), *Package->GetName(), *SuperClass->GetName());
}
else
{
UE_LOG(LogLevelSequence, Log, TEXT("Discarding generated class '%s' from package '%s'. Unable to create redirector due to no super class."), *OldName.ToString(), *Package->GetName());
}
}
}
}
#endif
void ULevelSequence::PostDuplicate(bool bDuplicateForPIE)
{
Super::PostDuplicate(bDuplicateForPIE);
#if WITH_EDITORONLY_DATA
if (DirectorBlueprint)
{
DirectorClass = DirectorBlueprint->GeneratedClass.Get();
// Remove the binding for the director blueprint recompilation and re-add it to be sure there is only one entry in the list
DirectorBlueprint->OnCompiled().RemoveAll(this);
DirectorBlueprint->OnCompiled().AddUObject(this, &ULevelSequence::OnDirectorRecompiled);
}
else
{
DirectorClass = nullptr;
}
#endif
#if WITH_EDITOR
if (PostDuplicateEvent.IsBound())
{
PostDuplicateEvent.Execute(this);
}
#endif
#if WITH_EDITOR
UMovieSceneMetaData* MetaData = FindOrAddMetaData<UMovieSceneMetaData>();
MetaData->SetCreated(FDateTime::UtcNow());
MetaData->SetAuthor(FApp::GetSessionOwner());
MetaData->SetNotes(FString()); // Intentionally clear the notes
#endif
}
void ULevelSequence::PostLoad()
{
Super::PostLoad();
#if WITH_EDITOR
if (MovieScene)
{
// Remove any invalid object bindings. This was moved from PostInitProperties
// because it has to happen after the asset has actually been serialized.
TSet<FGuid> ValidObjectBindings;
for (int32 Index = 0; Index < MovieScene->GetSpawnableCount(); ++Index)
{
ValidObjectBindings.Add(MovieScene->GetSpawnable(Index).GetGuid());
}
for (int32 Index = 0; Index < MovieScene->GetPossessableCount(); ++Index)
{
ValidObjectBindings.Add(MovieScene->GetPossessable(Index).GetGuid());
}
BindingReferences.RemoveInvalidBindings(ValidObjectBindings);
}
if (!DirectorBlueprint)
{
UBlueprint* PhantomDirector = FindObject<UBlueprint>(this, TEXT("SequenceDirector"));
if (!ensureMsgf(!PhantomDirector, TEXT("Phantom sequence director found in sequence '%s' which has a nullptr DirectorBlueprint. Re-assigning to prevent future crash."), *GetName()))
{
DirectorBlueprint = PhantomDirector;
}
}
if (DirectorBlueprint)
{
DirectorBlueprint->ClearFlags(RF_Standalone);
// Remove the binding for the director blueprint recompilation and re-add it to be sure there is only one entry in the list
DirectorBlueprint->OnCompiled().RemoveAll(this);
DirectorBlueprint->OnCompiled().AddUObject(this, &ULevelSequence::OnDirectorRecompiled);
if (DirectorBlueprint->Rename(*GetDirectorBlueprintName(), nullptr, (REN_NonTransactional | REN_DoNotDirty | REN_Test | REN_DontCreateRedirectors)))
{
DirectorBlueprint->Rename(*GetDirectorBlueprintName(), nullptr, (REN_NonTransactional | REN_DoNotDirty | REN_DontCreateRedirectors));
}
}
if (MovieScene)
{
TSet<FGuid> InvalidSpawnables;
for (int32 Index = 0; Index < MovieScene->GetSpawnableCount(); ++Index)
{
FMovieSceneSpawnable& Spawnable = MovieScene->GetSpawnable(Index);
if (!Spawnable.GetObjectTemplate())
{
if (Spawnable.GeneratedClass_DEPRECATED && Spawnable.GeneratedClass_DEPRECATED->ClassGeneratedBy)
{
const FName TemplateName = MakeUniqueObjectName(MovieScene, UObject::StaticClass(), Spawnable.GeneratedClass_DEPRECATED->ClassGeneratedBy->GetFName());
UObject* NewTemplate = NewObject<UObject>(MovieScene, Spawnable.GeneratedClass_DEPRECATED->GetSuperClass(), TemplateName);
if (NewTemplate)
{
Spawnable.CopyObjectTemplate(*NewTemplate, *this);
}
}
}
if (!Spawnable.GetObjectTemplate())
{
InvalidSpawnables.Add(Spawnable.GetGuid());
UE_LOG(LogLevelSequence, Warning, TEXT("Spawnable '%s' with ID '%s' does not have a valid object template"), *Spawnable.GetName(), *Spawnable.GetGuid().ToString());
}
}
}
if (GetLinkerCustomVersion(FSequencerObjectVersion::GUID) < FSequencerObjectVersion::PurgeSpawnableBlueprints)
{
// Remove any old generated classes from the package that will have been left behind from when we used blueprints for spawnables
{
UPackage* Package = GetOutermost();
TArray<UObject*> PackageSubobjects;
GetObjectsWithOuter(Package, PackageSubobjects, false);
for (UObject* ObjectInPackage : PackageSubobjects)
{
PurgeLegacyBlueprints(ObjectInPackage, Package);
}
}
}
for (TPair<FGuid, FLevelSequenceLegacyObjectReference>& Pair : ObjectReferences_DEPRECATED.Map)
{
if (Pair.Value.ObjectId.IsValid())
{
FUniversalObjectLocator NewLocator;
NewLocator.AddFragment<FLegacyLazyObjectPtrFragment>(Pair.Value.ObjectId.GetGuid());
BindingReferences.FMovieSceneBindingReferences::AddBinding(Pair.Key, MoveTemp(NewLocator));
}
else if (Pair.Value.ObjectPath.Len() > 0)
{
FUniversalObjectLocator NewLocator;
NewLocator.AddFragment<FSubObjectLocator>(Pair.Value.ObjectPath);
BindingReferences.FMovieSceneBindingReferences::AddBinding(Pair.Key, MoveTemp(NewLocator));
}
}
ObjectReferences_DEPRECATED.Map.Empty();
Sequencer- Resubmission of changelist 34065553 that had been backed out for a versioning issue which is now fixed. Original description below: Sequencer- Dynamic Binding Refactor Refactor the 'Dynamic Binding' blueprint system to be Custom Bindings rather than tied directly to FMovieScenePossessable and FMovieSceneSpawnable. As part of this: ? Created UMovieSceneReplaceableDirectorBlueprintBinding and UMovieSceneSpawnableDirectorBlueprintBinding to replace the Possessable and Spawnable versions of DynamicBindings ? Deprecated the DynamicBinding references on possessable and spawnable and created Postload fixup code to automatically create custom bindings instead ? Note that because the previous Dynamic Bindings operated as overrides and the new ones don't, there is a no longer supported path which is using Possessables as a preview in editor for Possessable Dynamic Bindings. Now if you don't mark 'Call in Editor' for a Replaceable Director Blueprint binding, you'll need to define a spawnable preview binding for the binding in order to work with it in Sequencer. ? Since UMG also used Dynamic Bindings on possessables, temporarily add DynamicBinding as a member variable on FWidgetAnimationBinding and create postload logic to move DynamicBindings to live on there for WidgetAnimations. ? USD has custom code to create dynamic bindings automatically for its use case. Convert this also to use the new custom binding system. ? Some cleanup on object binding right-click menus was done as part of this. ? Some further MovieSceneSequence API deprecation and refactoring has been done for the creation of bindings to add SharedPlaybackState where possible which was necessary for dynamic binding setup. FMovieSceneSpawnable deprecation in Level Sequences Since I was having to write postload fixup logic for FMovieSceneSpawnables with Dynamic Bindings that converted these to FMovieScenePossessables with custom bindings, it felt like a good chance to deprecate all FMovieSceneSpawnable use in Level Sequences. I chose at this time not to deprecate FMovieSceneSpawnable use for non-Level-Sequence Movie Scene Sequences. This includes Day Sequences, Template Sequences, Actor Sequences, Widget Animations, Niagara Sequences, and some Meta Human sequences. I made this choice because to do so would require also refactoring those sequence types to use MovieSceneBindingReferences in order to enable custom bindings for those sequence types. This will be a future refactor. Some notes on this deprecation. ? I kept MovieScene specific code that references or creates FMovieSceneSpawnables due to not refactoring all MovieSceneSequences ? Binding creation code in tools such as Sequencer will check for the presence of Binding References and create custom bindings if present, otherwise will still create FMovieSceneSpawnables ? AvaSequences required some extra work to make this change, including some changes and bugfixes to copy/pasting bindings to move away from custom avalanche copy/paste code, as the copy/paste code for custom bindings is a bit intricate and I didn't want to duplicate it. ? Chaos Cache has been moved away from using an object spawner and instead uses a custom spawnable actor binding inheriting from the regular spawnable actor binding. ? Actor and Take Recording has been updated to support custom spawnable bindings ? Meta Human specific code has been updated to support custom spawnable bindings when using Level Sequences ? FortniteMainBranchObjectVersion has been bumped Crash fix As part of the USD work, I found a crash bug where the Binding Properties menu would hold a reference to a level sequence. In the case of USD, the outer of the sequences can be the level, and this caused issues when switching levels. To fix this I ended up needing to add some events when menus are being dismissed so I could clean up these references. #jira UE-209839, UE-209548, UE-213115, UE-214195, UE-214443 #rb Marc.Audy #lockdown Marc.Audy [FYI] juan.portillo, Viktar.Mikhalchuk, Darrien.Blanchard, patrick.boutot [CL 34127005 by david bromberg in ue5-main branch]
2024-06-05 11:54:07 -04:00
if (GetLinkerCustomVersion(FFortniteMainBranchObjectVersion::GUID) < FFortniteMainBranchObjectVersion::LevelSequenceUpgradeDynamicBindings)
{
bool bConvertedDynamicBinding = ConvertOldSpawnables();
for (int32 Index = 0; Index < MovieScene->GetPossessableCount(); ++Index)
{
FMovieScenePossessable& Possessable = MovieScene->GetPossessable(Index);
if (Possessable.DynamicBinding_DEPRECATED.Function)
{
bConvertedDynamicBinding = true;
ConvertDynamicBindingPossessable(Possessable);
}
}
if (bConvertedDynamicBinding && FixupDynamicBindingsEvent.IsBound())
{
FixupDynamicBindingsEvent.Broadcast(this);
}
}
#endif
}
Sequencer- Resubmission of changelist 34065553 that had been backed out for a versioning issue which is now fixed. Original description below: Sequencer- Dynamic Binding Refactor Refactor the 'Dynamic Binding' blueprint system to be Custom Bindings rather than tied directly to FMovieScenePossessable and FMovieSceneSpawnable. As part of this: ? Created UMovieSceneReplaceableDirectorBlueprintBinding and UMovieSceneSpawnableDirectorBlueprintBinding to replace the Possessable and Spawnable versions of DynamicBindings ? Deprecated the DynamicBinding references on possessable and spawnable and created Postload fixup code to automatically create custom bindings instead ? Note that because the previous Dynamic Bindings operated as overrides and the new ones don't, there is a no longer supported path which is using Possessables as a preview in editor for Possessable Dynamic Bindings. Now if you don't mark 'Call in Editor' for a Replaceable Director Blueprint binding, you'll need to define a spawnable preview binding for the binding in order to work with it in Sequencer. ? Since UMG also used Dynamic Bindings on possessables, temporarily add DynamicBinding as a member variable on FWidgetAnimationBinding and create postload logic to move DynamicBindings to live on there for WidgetAnimations. ? USD has custom code to create dynamic bindings automatically for its use case. Convert this also to use the new custom binding system. ? Some cleanup on object binding right-click menus was done as part of this. ? Some further MovieSceneSequence API deprecation and refactoring has been done for the creation of bindings to add SharedPlaybackState where possible which was necessary for dynamic binding setup. FMovieSceneSpawnable deprecation in Level Sequences Since I was having to write postload fixup logic for FMovieSceneSpawnables with Dynamic Bindings that converted these to FMovieScenePossessables with custom bindings, it felt like a good chance to deprecate all FMovieSceneSpawnable use in Level Sequences. I chose at this time not to deprecate FMovieSceneSpawnable use for non-Level-Sequence Movie Scene Sequences. This includes Day Sequences, Template Sequences, Actor Sequences, Widget Animations, Niagara Sequences, and some Meta Human sequences. I made this choice because to do so would require also refactoring those sequence types to use MovieSceneBindingReferences in order to enable custom bindings for those sequence types. This will be a future refactor. Some notes on this deprecation. ? I kept MovieScene specific code that references or creates FMovieSceneSpawnables due to not refactoring all MovieSceneSequences ? Binding creation code in tools such as Sequencer will check for the presence of Binding References and create custom bindings if present, otherwise will still create FMovieSceneSpawnables ? AvaSequences required some extra work to make this change, including some changes and bugfixes to copy/pasting bindings to move away from custom avalanche copy/paste code, as the copy/paste code for custom bindings is a bit intricate and I didn't want to duplicate it. ? Chaos Cache has been moved away from using an object spawner and instead uses a custom spawnable actor binding inheriting from the regular spawnable actor binding. ? Actor and Take Recording has been updated to support custom spawnable bindings ? Meta Human specific code has been updated to support custom spawnable bindings when using Level Sequences ? FortniteMainBranchObjectVersion has been bumped Crash fix As part of the USD work, I found a crash bug where the Binding Properties menu would hold a reference to a level sequence. In the case of USD, the outer of the sequences can be the level, and this caused issues when switching levels. To fix this I ended up needing to add some events when menus are being dismissed so I could clean up these references. #jira UE-209839, UE-209548, UE-213115, UE-214195, UE-214443 #rb Marc.Audy #lockdown Marc.Audy [FYI] juan.portillo, Viktar.Mikhalchuk, Darrien.Blanchard, patrick.boutot [CL 34127005 by david bromberg in ue5-main branch]
2024-06-05 11:54:07 -04:00
#if WITH_EDITOR
bool ULevelSequence::ConvertOldSpawnables()
{
bool bConvertedDynamicBinding = false;
while (MovieScene->GetSpawnableCount() > 0)
{
FMovieSceneSpawnable& Spawnable = MovieScene->GetSpawnable(0);
FMovieScenePossessable* CreatedPossessable = nullptr;
UObject* ObjectToConvert = Spawnable.GetObjectTemplate();
UClass* CustomBindingType = nullptr;
if (Spawnable.DynamicBinding_DEPRECATED.Function)
{
CustomBindingType = UMovieSceneSpawnableDirectorBlueprintBinding::StaticClass();
}
else
{
// Search through custom binding types to find one that best supports the template type
static TArray<const TSubclassOf<UMovieSceneCustomBinding>> CachedCustomBindingTypes;
static bool CustomBindingTypesCached = false;
if (!CustomBindingTypesCached)
{
CustomBindingTypesCached = true;
MovieSceneHelpers::GetPrioritySortedCustomBindingTypes(CachedCustomBindingTypes);
}
for (const TSubclassOf<UMovieSceneCustomBinding>& CandidateCustomBindingType : CachedCustomBindingTypes)
{
if (CandidateCustomBindingType && CandidateCustomBindingType->IsChildOf(UMovieSceneSpawnableBindingBase::StaticClass()) && CandidateCustomBindingType->GetDefaultObject<UMovieSceneCustomBinding>()->SupportsBindingCreationFromObject(Spawnable.GetObjectTemplate()))
{
CustomBindingType = CandidateCustomBindingType;
break;
}
}
}
if (!CustomBindingType)
{
UE_LOG(LogLevelSequence, Warning, TEXT("Could not upgrade Spawnable '%s' with ID '%s'"), *Spawnable.GetName(), *Spawnable.GetGuid().ToString());
break;
}
UMovieSceneCustomBinding* NewCustomBinding = CustomBindingType->GetDefaultObject<UMovieSceneCustomBinding>()->CreateNewCustomBinding(ObjectToConvert, *MovieScene);
if (!NewCustomBinding)
{
UE_LOG(LogLevelSequence, Warning, TEXT("Could not upgrade Spawnable '%s' with ID '%s'"), *Spawnable.GetName(), *Spawnable.GetGuid().ToString());
break;
}
if (UMovieSceneSpawnableDirectorBlueprintBinding* DirectorBlueprintBinding = Cast<UMovieSceneSpawnableDirectorBlueprintBinding>(NewCustomBinding))
{
// Copy over the binding info
DirectorBlueprintBinding->DynamicBinding = Spawnable.DynamicBinding_DEPRECATED;
bConvertedDynamicBinding = true;
}
else if (UMovieSceneSpawnableActorBinding* SpawnableActorBinding = Cast<UMovieSceneSpawnableActorBinding>(NewCustomBinding))
{
SpawnableActorBinding->bNetAddressableName = Spawnable.bNetAddressableName;
SpawnableActorBinding->LevelName = Spawnable.LevelName;
SpawnableActorBinding->bContinuouslyRespawn = Spawnable.bContinuouslyRespawn;
SpawnableActorBinding->SpawnOwnership = Spawnable.GetSpawnOwnership();
}
FString PossessableName = Spawnable.GetName();
FGuid SpawnableGuid = Spawnable.GetGuid();
FMovieScenePossessable NewPossessable(PossessableName, NewCustomBinding->GetBoundObjectClass());
// Steal guid
NewPossessable.SetGuid(SpawnableGuid);
if (FMovieSceneBinding* SpawnableBinding = MovieScene->FindBinding(SpawnableGuid))
{
// Copy binding and track references to be tied to the new possessable
FMovieSceneBinding PossessableBinding = *SpawnableBinding;
// Add the custom binding. We use the spawnable binding here since it won't have a binding reference yet, and we need to steal the id
BindingReferences.AddOrReplaceBinding(SpawnableGuid, NewCustomBinding, 0);
// Remove the spawnable and all its' sub tracks
if (MovieScene->RemoveSpawnable(SpawnableGuid))
{
// Add the new possessable with the copied binding
MovieScene->AddPossessable(NewPossessable, PossessableBinding);
}
}
}
return bConvertedDynamicBinding;
}
void ULevelSequence::ConvertDynamicBindingPossessable(FMovieScenePossessable& Possessable)
{
UMovieSceneReplaceableDirectorBlueprintBinding* NewCustomBinding = nullptr;
const FName InstancedBindingName = MakeUniqueObjectName(MovieScene, UObject::StaticClass(), *FString(Possessable.GetName() + TEXT("_CustomBinding")));
NewCustomBinding = NewObject<UMovieSceneReplaceableDirectorBlueprintBinding>(MovieScene, UMovieSceneReplaceableDirectorBlueprintBinding::StaticClass(), InstancedBindingName, RF_Transactional);
if (!NewCustomBinding)
{
return;
}
if (UMovieSceneReplaceableDirectorBlueprintBinding* DirectorBlueprintBinding = Cast<UMovieSceneReplaceableDirectorBlueprintBinding>(NewCustomBinding))
{
// Copy over the binding info
DirectorBlueprintBinding->DynamicBinding = Possessable.DynamicBinding_DEPRECATED;
Possessable.DynamicBinding_DEPRECATED = FMovieSceneDynamicBinding();
}
// Replace the current binding with the new one. We call RemoveBinding first because if there were multiple bindings for this track,
// they would have been overridden with the Dynamic Binding anyway, and so we ensure that stays the same by keeping only one binding
BindingReferences.RemoveBinding(Possessable.GetGuid());
BindingReferences.AddOrReplaceBinding(Possessable.GetGuid(), NewCustomBinding, 0);
// Add a binding lifetime track if not present
UMovieSceneBindingLifetimeTrack* BindingLifetimeTrack = Cast<UMovieSceneBindingLifetimeTrack>(MovieScene->FindTrack(UMovieSceneBindingLifetimeTrack::StaticClass(), Possessable.GetGuid(), NAME_None));
if (!BindingLifetimeTrack)
{
BindingLifetimeTrack = Cast<UMovieSceneBindingLifetimeTrack>(MovieScene->AddTrack(UMovieSceneBindingLifetimeTrack::StaticClass(), Possessable.GetGuid()));
}
if (BindingLifetimeTrack && BindingLifetimeTrack->GetAllSections().IsEmpty())
{
UMovieSceneBindingLifetimeSection* BindingLifetimeSection = Cast<UMovieSceneBindingLifetimeSection>(BindingLifetimeTrack->CreateNewSection());
BindingLifetimeSection->SetRange(TRange<FFrameNumber>::All());
BindingLifetimeTrack->AddSection(*BindingLifetimeSection);
}
}
#endif
#if WITH_EDITORONLY_DATA
void ULevelSequence::DeclareConstructClasses(TArray<FTopLevelAssetPath>& OutConstructClasses, const UClass* SpecificSubclass)
{
Super::DeclareConstructClasses(OutConstructClasses, SpecificSubclass);
OutConstructClasses.Add(FTopLevelAssetPath(UObjectRedirector::StaticClass()));
OutConstructClasses.Add(FTopLevelAssetPath(UMovieSceneSpawnableActorBinding::StaticClass()));
OutConstructClasses.Add(FTopLevelAssetPath(UMovieSceneSpawnableDirectorBlueprintBinding::StaticClass()));
}
#endif
void ULevelSequence::PostInitProperties()
{
Super::PostInitProperties();
}
bool ULevelSequence::Rename(const TCHAR* NewName, UObject* NewOuter, ERenameFlags Flags)
{
bool bRetVal = Super::Rename(NewName, NewOuter, Flags);
#if WITH_EDITOR
if (DirectorBlueprint)
{
DirectorBlueprint->Rename(*GetDirectorBlueprintName(), this, Flags);
}
#endif
return bRetVal;
}
void ULevelSequence::BindPossessableObject(const FGuid& ObjectId, UObject& PossessedObject, UObject* Context)
{
if (Context)
{
BindingReferences.AddBinding(ObjectId, &PossessedObject, Context);
}
}
bool ULevelSequence::CanPossessObject(UObject& Object, UObject* InPlaybackContext) const
{
return true;
}
void ULevelSequence::LocateBoundObjects(const FGuid& ObjectId, UObject* Context, const FLevelSequenceBindingReference::FResolveBindingParams& InResolveBindingParams, TArray<UObject*, TInlineAllocator<1>>& OutObjects) const
{
using namespace UE::UniversalObjectLocator;
TResolveParamsWithBuffer<128> ResolveParams;
ResolveParams.AddParameter(FActorLocatorFragmentResolveParameter::ParameterType,
InResolveBindingParams.StreamingWorld,
InResolveBindingParams.WorldPartitionResolveData ? InResolveBindingParams.WorldPartitionResolveData->ContainerID : FActorContainerID(),
InResolveBindingParams.WorldPartitionResolveData ? InResolveBindingParams.WorldPartitionResolveData->SourceWorldAssetPath : InResolveBindingParams.StreamedLevelAssetPath
);
Sequencer- Resubmission of changelist 34065553 that had been backed out for a versioning issue which is now fixed. Original description below: Sequencer- Dynamic Binding Refactor Refactor the 'Dynamic Binding' blueprint system to be Custom Bindings rather than tied directly to FMovieScenePossessable and FMovieSceneSpawnable. As part of this: ? Created UMovieSceneReplaceableDirectorBlueprintBinding and UMovieSceneSpawnableDirectorBlueprintBinding to replace the Possessable and Spawnable versions of DynamicBindings ? Deprecated the DynamicBinding references on possessable and spawnable and created Postload fixup code to automatically create custom bindings instead ? Note that because the previous Dynamic Bindings operated as overrides and the new ones don't, there is a no longer supported path which is using Possessables as a preview in editor for Possessable Dynamic Bindings. Now if you don't mark 'Call in Editor' for a Replaceable Director Blueprint binding, you'll need to define a spawnable preview binding for the binding in order to work with it in Sequencer. ? Since UMG also used Dynamic Bindings on possessables, temporarily add DynamicBinding as a member variable on FWidgetAnimationBinding and create postload logic to move DynamicBindings to live on there for WidgetAnimations. ? USD has custom code to create dynamic bindings automatically for its use case. Convert this also to use the new custom binding system. ? Some cleanup on object binding right-click menus was done as part of this. ? Some further MovieSceneSequence API deprecation and refactoring has been done for the creation of bindings to add SharedPlaybackState where possible which was necessary for dynamic binding setup. FMovieSceneSpawnable deprecation in Level Sequences Since I was having to write postload fixup logic for FMovieSceneSpawnables with Dynamic Bindings that converted these to FMovieScenePossessables with custom bindings, it felt like a good chance to deprecate all FMovieSceneSpawnable use in Level Sequences. I chose at this time not to deprecate FMovieSceneSpawnable use for non-Level-Sequence Movie Scene Sequences. This includes Day Sequences, Template Sequences, Actor Sequences, Widget Animations, Niagara Sequences, and some Meta Human sequences. I made this choice because to do so would require also refactoring those sequence types to use MovieSceneBindingReferences in order to enable custom bindings for those sequence types. This will be a future refactor. Some notes on this deprecation. ? I kept MovieScene specific code that references or creates FMovieSceneSpawnables due to not refactoring all MovieSceneSequences ? Binding creation code in tools such as Sequencer will check for the presence of Binding References and create custom bindings if present, otherwise will still create FMovieSceneSpawnables ? AvaSequences required some extra work to make this change, including some changes and bugfixes to copy/pasting bindings to move away from custom avalanche copy/paste code, as the copy/paste code for custom bindings is a bit intricate and I didn't want to duplicate it. ? Chaos Cache has been moved away from using an object spawner and instead uses a custom spawnable actor binding inheriting from the regular spawnable actor binding. ? Actor and Take Recording has been updated to support custom spawnable bindings ? Meta Human specific code has been updated to support custom spawnable bindings when using Level Sequences ? FortniteMainBranchObjectVersion has been bumped Crash fix As part of the USD work, I found a crash bug where the Binding Properties menu would hold a reference to a level sequence. In the case of USD, the outer of the sequences can be the level, and this caused issues when switching levels. To fix this I ended up needing to add some events when menus are being dismissed so I could clean up these references. #jira UE-209839, UE-209548, UE-213115, UE-214195, UE-214443 #rb Marc.Audy #lockdown Marc.Audy [FYI] juan.portillo, Viktar.Mikhalchuk, Darrien.Blanchard, patrick.boutot [CL 34127005 by david bromberg in ue5-main branch]
2024-06-05 11:54:07 -04:00
LocateBoundObjects(ObjectId, ResolveParams, nullptr, OutObjects);
}
FGuid ULevelSequence::FindBindingFromObject(UObject* InObject, UObject* Context) const
{
PRAGMA_DISABLE_DEPRECATION_WARNINGS
return UMovieSceneSequence::FindBindingFromObject(InObject, Context);
PRAGMA_ENABLE_DEPRECATION_WARNINGS
}
FGuid ULevelSequence::FindBindingFromObject(UObject* InObject, TSharedRef<const UE::MovieScene::FSharedPlaybackState> SharedPlaybackState) const
{
if (InObject)
{
if (FMovieSceneEvaluationState* EvaluationState = SharedPlaybackState->FindCapability<FMovieSceneEvaluationState>())
{
FMovieSceneSequenceID SequenceID = EvaluationState->FindSequenceId(this);
return EvaluationState->FindCachedObjectId(*InObject, SequenceID, SharedPlaybackState);
}
}
return FGuid();
}
void ULevelSequence::GatherExpiredObjects(const FMovieSceneObjectCache& InObjectCache, TArray<FGuid>& OutInvalidIDs) const
{
using namespace UE::UniversalObjectLocator;
TArrayView<const FMovieSceneBindingReference> References = BindingReferences.GetAllReferences();
for (int32 Index = 0; Index < References.Num(); ++Index)
{
const FMovieSceneBindingReference& Reference = References[Index];
if (Reference.Locator.GetLastFragmentTypeHandle() == FAnimInstanceLocatorFragment::FragmentType)
{
for (TWeakObjectPtr<> WeakObject : InObjectCache.IterateBoundObjects(Reference.ID))
{
UAnimInstance* AnimInstance = Cast<UAnimInstance>(WeakObject.Get());
if (!AnimInstance || !AnimInstance->GetOwningComponent() || AnimInstance->GetOwningComponent()->GetAnimInstance() != AnimInstance)
{
OutInvalidIDs.Add(Reference.ID);
}
}
// Skip over subsequent matched IDs
while (Index < References.Num()-1 && References[Index+1].ID == Reference.ID)
{
++Index;
}
}
}
}
UMovieScene* ULevelSequence::GetMovieScene() const
{
return MovieScene;
}
UObject* ULevelSequence::GetParentObject(UObject* Object) const
{
if (UActorComponent* Component = Cast<UActorComponent>(Object))
{
return Component->GetOwner();
}
if (UAnimInstance* AnimInstance = Cast<UAnimInstance>(Object))
{
if (AnimInstance->GetWorld())
{
return AnimInstance->GetOwningComponent();
}
}
return nullptr;
}
bool ULevelSequence::AllowsSpawnableObjects() const
{
TArray<const TSubclassOf<UMovieSceneCustomBinding>> CustomBindingTypes;
MovieSceneHelpers::GetPrioritySortedCustomBindingTypes(CustomBindingTypes);
for (const TSubclassOf<UMovieSceneCustomBinding>& CustomBindingType : CustomBindingTypes)
{
const bool bIsCustomSpawnableBinding = CustomBindingType->IsChildOf<UMovieSceneSpawnableBindingBase>();
if (bIsCustomSpawnableBinding)
{
return true;
}
}
return false;
}
Sequencer- Refactor Bindings to support inherited Custom Bindings. With this checkin, the binding system inside Level Sequences has been refactored to allow C++ custom binding classes inheriting from a new class, UMovieSceneCustomBinding. Custom bindings are held as instanced UObjects inside FMovieSceneBindingReference, alongside the Universal Object Locator. In the case where a custom binding has been specified, the UOL will be ignored. The intention with this change is to allow developers to create their own arbitrary methods of binding any UObject to a track inside Sequencer. Examples of this include: * Runtime dynamic bindings to spawned NPC or player characters (e.g. in UEFN) with a different spawned preview character * Blueprint-specified dynamic bindings * Spawnable bindings based on something other than a AActor template * Scene Graph/Prefabs Alongside the base UMovieSceneCustomBinding class, a new hierarchy of spawnable custom binding classes has been created as the basis for allowing spawnable bindings that don't require object templates, and may instead require other asset references, for example UEFN NPC character spawnables requiring an NPC Character Definition asset. This hierarchy is currently. UMovieSceneCustomBinding <- UMovieSceneSpawnableBindingBase <- UMovieSceneSpawnableActorBindingBase <- UMovieSceneSpawnableActorBinding. This hierarchy allows for spawnables of non-actor types, spawnables of actor types not based on templates, and finally UMovieSceneSpawnableActorBinding, which is a re-implementation of FMovieSceneSpawnable inside the custom binding system. Going forward, we will be moving to deprecate FMovieSceneSpawnable in UE Sequencer in favor of the custom spawnable binding types. Sequences with FMovieSceneSpawnables will continue to function as normal, but new spawnables in new sequences will use UMovieSceneSpawnableActorBinding under the hood. These will technically have FMovieScenePossessable structs created for them for now rather than FMovieSceneSpawnable structs. This should be mostly invisible to the user. In addition, I've added a separate hierarchy of custom bindings called 'Replaceable' bindings. A 'Replaceable' is a binding type that will expect in runtime to always be overridden by a different object that may not be available in editor. UMovieSceneReplaceableBinding will hold in EDITORONLY_DATA a UMovieSceneSpawnableBindingBase to provide a preview while within Sequencer. Included in this is a UMovieSceneReplaceableActorBinding, which uses the UMovieSceneSpawnableActorBinding internally to spawn its preview, and has no implementation to find the actor during runtime- it relies on the user overriding the actor binding using the existing BindingOverrides method on LevelSequenceActor. Next Steps: * UEFN custom bindings will be built upon this system, to allow UEFN users multiple ways to override bindings. * UEFN custom spawnable bindings will be built upon this system, to allow UEFN users a way to spawn actors and objects within Sequencer with their lifetime managed by Sequencer * With this change, we have a cleaner way of incorporating the 'dynamic binding' work that uses the Director Blueprint to create a spawnable or possessable. This should be incorporated into the UCustomBinding hierarchy. * Once Verse supports it, we should add Verse custom binding logic * We need to add a Universal Object Locator type that can reference any other binding in the sequence hierarchy. This will allow us to adapt the existing 'Spawnable Parent' possessable binding logic to reference any other type of binding, not just spawnable ones. * Eventually we will fully deprecate FMovieSceneSpawnable Further notes: * A previous imagined version of this system used the cache as a way to allow locators to spawn actors and register them with Sequencer. This change removes this code. * Custom Spawnable Bindings use the Binding Lifetime Track to determine their spawn lifetime rather than the old spawn track. This unifies the concept of the lifetime of an object binding within sequencer for both spawnables and possessables. * As FMovieScenePossessable and FMovieSceneBindingReferences allows multiple bindings per guid, this change now allows multiple spawnables to be spawned and controlled by a single binding track. However, some of the editor tooling code doesn't currently handle this properly and at times assumes a single binding. This should be resolved one way or the other. * The UX for this allows UCustomBindings to handle creating bindings from any dragged in object using a priority system- Sequencer will ask all classes in priority order if they support binding creation from that object. * The UX supports unique overlay icons and tooltips for different types of bindings * The UX allows each binding type to decide whether it can convert a current binding into its own type and then do so * Currently there is some manual instanced detail customization for UMovieSceneCustomSpawnableActorBinding. We use instanced customization so that the UX has the sequencer context. This should both be improved (to allow ways to choose a class/template via this UI), as well as extended so that clients outside of the Movie Scene plugin can register instanced detail customizations for their own binding types. * Where possible, Sequencer APIs around spawnables have been refactored to take guids rather than FMovieSceneSpawnable references. In particular, custom spawnables do still use the spawn register, but do not use actor spawners- instead the UMovieSceneCustomBinding class is given the responsiblity of spawning/destroying the object/actor. This created an awkward API for USD export, which had overridden the spawn register to unhide/hide actors rather than spawning/destroying them. This could use some more work. MetaHumanPerformanceExportUtils will also need to be refactored at some point to use the custom spawnable binding system. * FSequencerUtilities::CreateBinding and CreateGenericBinding has been refactored to accept binding parameters and now supports creating custom bindings including spawnables, as well as replacing existing bindings and adding additional bindings to an existing guid. [REVIEW] [at]ue-sequencer #jira UE-199299, FORT-582815, UE-209594 #rb Andrew.Rodham, daniel.coelho, Max.Chen [CL 32218187 by david bromberg in ue5-main branch]
2024-03-13 12:48:46 -04:00
bool ULevelSequence::AllowsCustomBindings() const
{
return true;
}
bool ULevelSequence::CanRebindPossessable(const FMovieScenePossessable& InPossessable) const
{
return !InPossessable.GetParent().IsValid();
}
void ULevelSequence::UnbindPossessableObjects(const FGuid& ObjectId)
{
BindingReferences.RemoveBinding(ObjectId);
}
void ULevelSequence::UnbindObjects(const FGuid& ObjectId, const TArray<UObject*>& InObjects, UObject* InContext)
{
BindingReferences.RemoveObjects(ObjectId, InObjects, InContext);
}
void ULevelSequence::UnbindInvalidObjects(const FGuid& ObjectId, UObject* InContext)
{
BindingReferences.RemoveInvalidObjects(ObjectId, InContext);
}
const FMovieSceneBindingReferences* ULevelSequence::GetBindingReferences() const
{
return &BindingReferences;
}
#if WITH_EDITOR
UBlueprint* ULevelSequence::GetDirectorBlueprint() const
{
return DirectorBlueprint;
}
FString ULevelSequence::GetDirectorBlueprintName() const
{
return GetDisplayName().ToString() + "_DirectorBP";
}
void ULevelSequence::SetDirectorBlueprint(UBlueprint* NewDirectorBlueprint)
{
if (DirectorBlueprint)
{
DirectorBlueprint->OnCompiled().RemoveAll(this);
}
DirectorBlueprint = NewDirectorBlueprint;
if (DirectorBlueprint)
{
DirectorClass = NewDirectorBlueprint->GeneratedClass.Get();
DirectorBlueprint->OnCompiled().AddUObject(this, &ULevelSequence::OnDirectorRecompiled);
}
else
{
DirectorClass = nullptr;
}
MarkAsChanged();
}
void ULevelSequence::OnDirectorRecompiled(UBlueprint* InCompiledBlueprint)
{
ensure(InCompiledBlueprint == DirectorBlueprint);
DirectorClass = DirectorBlueprint->GeneratedClass.Get();
MarkAsChanged();
}
FGuid ULevelSequence::FindOrAddBinding(UObject* InObject)
{
using namespace UE::MovieScene;
UObject* PlaybackContext = InObject ? InObject->GetWorld() : nullptr;
if (!InObject || !PlaybackContext)
{
return FGuid();
}
AActor* Actor = Cast<AActor>(InObject);
if (Actor && Actor->ActorHasTag("SequencerActor"))
{
TOptional<FMovieSceneSpawnableAnnotation> Annotation = FMovieSceneSpawnableAnnotation::Find(Actor);
if (Annotation.IsSet() && Annotation->OriginatingSequence == this)
{
return Annotation->ObjectBindingID;
}
// If this actor is a spawnable and is not in the same originating sequence, it's likely a spawnable that will be possessed.
// SetSpawnableObjectBindingID will need to be called on that possessable.
}
UObject* ParentObject = GetParentObject(InObject);
FGuid ParentGuid = ParentObject ? FindOrAddBinding(ParentObject) : FGuid();
if (ParentObject && !ParentGuid.IsValid())
{
UE_LOG(LogLevelSequence, Error, TEXT("Unable to possess object '%s' because it's parent could not be bound."), *InObject->GetName());
return FGuid();
}
// Perform a potentially slow lookup of every possessable binding in the sequence to see if we already have this
{
FSharedPlaybackStateCreateParams CreateParams;
CreateParams.PlaybackContext = PlaybackContext;
TSharedRef<FSharedPlaybackState> TransientPlaybackState = MakeShared<FSharedPlaybackState>(*this, CreateParams);
FMovieSceneEvaluationState State;
TransientPlaybackState->AddCapabilityRaw(&State);
State.AssignSequence(MovieSceneSequenceID::Root, *this, TransientPlaybackState);
FGuid ExistingID = State.FindObjectId(*InObject, MovieSceneSequenceID::Root, TransientPlaybackState);
if (ExistingID.IsValid())
{
return ExistingID;
}
}
// We have to possess this object
if (!CanPossessObject(*InObject, PlaybackContext))
{
return FGuid();
}
FString NewName = Actor ? Actor->GetActorLabel() : InObject->GetName();
const FGuid NewGuid = MovieScene->AddPossessable(NewName, InObject->GetClass());
// Attempt to use the parent as a context if necessary
UObject* BindingContext = ParentObject && AreParentContextsSignificant() ? ParentObject : PlaybackContext;
// Set up parent/child guids for possessables within spawnables
if (ParentGuid.IsValid())
{
FMovieScenePossessable* ChildPossessable = MovieScene->FindPossessable(NewGuid);
if (ensure(ChildPossessable))
{
ChildPossessable->SetParent(ParentGuid, MovieScene);
}
}
BindPossessableObject(NewGuid, *InObject, BindingContext);
return NewGuid;
}
FGuid ULevelSequence::CreatePossessable(UObject* ObjectToPossess)
{
return FindOrAddBinding(ObjectToPossess);
}
FGuid ULevelSequence::CreateSpawnable(UObject* ObjectToSpawn)
{
if (!MovieScene || !ObjectToSpawn)
{
return FGuid();
}
Sequencer- Resubmission of changelist 34065553 that had been backed out for a versioning issue which is now fixed. Original description below: Sequencer- Dynamic Binding Refactor Refactor the 'Dynamic Binding' blueprint system to be Custom Bindings rather than tied directly to FMovieScenePossessable and FMovieSceneSpawnable. As part of this: ? Created UMovieSceneReplaceableDirectorBlueprintBinding and UMovieSceneSpawnableDirectorBlueprintBinding to replace the Possessable and Spawnable versions of DynamicBindings ? Deprecated the DynamicBinding references on possessable and spawnable and created Postload fixup code to automatically create custom bindings instead ? Note that because the previous Dynamic Bindings operated as overrides and the new ones don't, there is a no longer supported path which is using Possessables as a preview in editor for Possessable Dynamic Bindings. Now if you don't mark 'Call in Editor' for a Replaceable Director Blueprint binding, you'll need to define a spawnable preview binding for the binding in order to work with it in Sequencer. ? Since UMG also used Dynamic Bindings on possessables, temporarily add DynamicBinding as a member variable on FWidgetAnimationBinding and create postload logic to move DynamicBindings to live on there for WidgetAnimations. ? USD has custom code to create dynamic bindings automatically for its use case. Convert this also to use the new custom binding system. ? Some cleanup on object binding right-click menus was done as part of this. ? Some further MovieSceneSequence API deprecation and refactoring has been done for the creation of bindings to add SharedPlaybackState where possible which was necessary for dynamic binding setup. FMovieSceneSpawnable deprecation in Level Sequences Since I was having to write postload fixup logic for FMovieSceneSpawnables with Dynamic Bindings that converted these to FMovieScenePossessables with custom bindings, it felt like a good chance to deprecate all FMovieSceneSpawnable use in Level Sequences. I chose at this time not to deprecate FMovieSceneSpawnable use for non-Level-Sequence Movie Scene Sequences. This includes Day Sequences, Template Sequences, Actor Sequences, Widget Animations, Niagara Sequences, and some Meta Human sequences. I made this choice because to do so would require also refactoring those sequence types to use MovieSceneBindingReferences in order to enable custom bindings for those sequence types. This will be a future refactor. Some notes on this deprecation. ? I kept MovieScene specific code that references or creates FMovieSceneSpawnables due to not refactoring all MovieSceneSequences ? Binding creation code in tools such as Sequencer will check for the presence of Binding References and create custom bindings if present, otherwise will still create FMovieSceneSpawnables ? AvaSequences required some extra work to make this change, including some changes and bugfixes to copy/pasting bindings to move away from custom avalanche copy/paste code, as the copy/paste code for custom bindings is a bit intricate and I didn't want to duplicate it. ? Chaos Cache has been moved away from using an object spawner and instead uses a custom spawnable actor binding inheriting from the regular spawnable actor binding. ? Actor and Take Recording has been updated to support custom spawnable bindings ? Meta Human specific code has been updated to support custom spawnable bindings when using Level Sequences ? FortniteMainBranchObjectVersion has been bumped Crash fix As part of the USD work, I found a crash bug where the Binding Properties menu would hold a reference to a level sequence. In the case of USD, the outer of the sequences can be the level, and this caused issues when switching levels. To fix this I ended up needing to add some events when menus are being dismissed so I could clean up these references. #jira UE-209839, UE-209548, UE-213115, UE-214195, UE-214443 #rb Marc.Audy #lockdown Marc.Audy [FYI] juan.portillo, Viktar.Mikhalchuk, Darrien.Blanchard, patrick.boutot [CL 34127005 by david bromberg in ue5-main branch]
2024-06-05 11:54:07 -04:00
FGuid NewGuid = MovieSceneHelpers::TryCreateCustomSpawnableBinding(this, ObjectToSpawn);
Sequencer- Resubmission of changelist 34065553 that had been backed out for a versioning issue which is now fixed. Original description below: Sequencer- Dynamic Binding Refactor Refactor the 'Dynamic Binding' blueprint system to be Custom Bindings rather than tied directly to FMovieScenePossessable and FMovieSceneSpawnable. As part of this: ? Created UMovieSceneReplaceableDirectorBlueprintBinding and UMovieSceneSpawnableDirectorBlueprintBinding to replace the Possessable and Spawnable versions of DynamicBindings ? Deprecated the DynamicBinding references on possessable and spawnable and created Postload fixup code to automatically create custom bindings instead ? Note that because the previous Dynamic Bindings operated as overrides and the new ones don't, there is a no longer supported path which is using Possessables as a preview in editor for Possessable Dynamic Bindings. Now if you don't mark 'Call in Editor' for a Replaceable Director Blueprint binding, you'll need to define a spawnable preview binding for the binding in order to work with it in Sequencer. ? Since UMG also used Dynamic Bindings on possessables, temporarily add DynamicBinding as a member variable on FWidgetAnimationBinding and create postload logic to move DynamicBindings to live on there for WidgetAnimations. ? USD has custom code to create dynamic bindings automatically for its use case. Convert this also to use the new custom binding system. ? Some cleanup on object binding right-click menus was done as part of this. ? Some further MovieSceneSequence API deprecation and refactoring has been done for the creation of bindings to add SharedPlaybackState where possible which was necessary for dynamic binding setup. FMovieSceneSpawnable deprecation in Level Sequences Since I was having to write postload fixup logic for FMovieSceneSpawnables with Dynamic Bindings that converted these to FMovieScenePossessables with custom bindings, it felt like a good chance to deprecate all FMovieSceneSpawnable use in Level Sequences. I chose at this time not to deprecate FMovieSceneSpawnable use for non-Level-Sequence Movie Scene Sequences. This includes Day Sequences, Template Sequences, Actor Sequences, Widget Animations, Niagara Sequences, and some Meta Human sequences. I made this choice because to do so would require also refactoring those sequence types to use MovieSceneBindingReferences in order to enable custom bindings for those sequence types. This will be a future refactor. Some notes on this deprecation. ? I kept MovieScene specific code that references or creates FMovieSceneSpawnables due to not refactoring all MovieSceneSequences ? Binding creation code in tools such as Sequencer will check for the presence of Binding References and create custom bindings if present, otherwise will still create FMovieSceneSpawnables ? AvaSequences required some extra work to make this change, including some changes and bugfixes to copy/pasting bindings to move away from custom avalanche copy/paste code, as the copy/paste code for custom bindings is a bit intricate and I didn't want to duplicate it. ? Chaos Cache has been moved away from using an object spawner and instead uses a custom spawnable actor binding inheriting from the regular spawnable actor binding. ? Actor and Take Recording has been updated to support custom spawnable bindings ? Meta Human specific code has been updated to support custom spawnable bindings when using Level Sequences ? FortniteMainBranchObjectVersion has been bumped Crash fix As part of the USD work, I found a crash bug where the Binding Properties menu would hold a reference to a level sequence. In the case of USD, the outer of the sequences can be the level, and this caused issues when switching levels. To fix this I ended up needing to add some events when menus are being dismissed so I could clean up these references. #jira UE-209839, UE-209548, UE-213115, UE-214195, UE-214443 #rb Marc.Audy #lockdown Marc.Audy [FYI] juan.portillo, Viktar.Mikhalchuk, Darrien.Blanchard, patrick.boutot [CL 34127005 by david bromberg in ue5-main branch]
2024-06-05 11:54:07 -04:00
UMovieSceneSpawnTrack* NewSpawnTrack = MovieScene->AddTrack<UMovieSceneSpawnTrack>(NewGuid);
if (NewSpawnTrack)
{
Sequencer- Resubmission of changelist 34065553 that had been backed out for a versioning issue which is now fixed. Original description below: Sequencer- Dynamic Binding Refactor Refactor the 'Dynamic Binding' blueprint system to be Custom Bindings rather than tied directly to FMovieScenePossessable and FMovieSceneSpawnable. As part of this: ? Created UMovieSceneReplaceableDirectorBlueprintBinding and UMovieSceneSpawnableDirectorBlueprintBinding to replace the Possessable and Spawnable versions of DynamicBindings ? Deprecated the DynamicBinding references on possessable and spawnable and created Postload fixup code to automatically create custom bindings instead ? Note that because the previous Dynamic Bindings operated as overrides and the new ones don't, there is a no longer supported path which is using Possessables as a preview in editor for Possessable Dynamic Bindings. Now if you don't mark 'Call in Editor' for a Replaceable Director Blueprint binding, you'll need to define a spawnable preview binding for the binding in order to work with it in Sequencer. ? Since UMG also used Dynamic Bindings on possessables, temporarily add DynamicBinding as a member variable on FWidgetAnimationBinding and create postload logic to move DynamicBindings to live on there for WidgetAnimations. ? USD has custom code to create dynamic bindings automatically for its use case. Convert this also to use the new custom binding system. ? Some cleanup on object binding right-click menus was done as part of this. ? Some further MovieSceneSequence API deprecation and refactoring has been done for the creation of bindings to add SharedPlaybackState where possible which was necessary for dynamic binding setup. FMovieSceneSpawnable deprecation in Level Sequences Since I was having to write postload fixup logic for FMovieSceneSpawnables with Dynamic Bindings that converted these to FMovieScenePossessables with custom bindings, it felt like a good chance to deprecate all FMovieSceneSpawnable use in Level Sequences. I chose at this time not to deprecate FMovieSceneSpawnable use for non-Level-Sequence Movie Scene Sequences. This includes Day Sequences, Template Sequences, Actor Sequences, Widget Animations, Niagara Sequences, and some Meta Human sequences. I made this choice because to do so would require also refactoring those sequence types to use MovieSceneBindingReferences in order to enable custom bindings for those sequence types. This will be a future refactor. Some notes on this deprecation. ? I kept MovieScene specific code that references or creates FMovieSceneSpawnables due to not refactoring all MovieSceneSequences ? Binding creation code in tools such as Sequencer will check for the presence of Binding References and create custom bindings if present, otherwise will still create FMovieSceneSpawnables ? AvaSequences required some extra work to make this change, including some changes and bugfixes to copy/pasting bindings to move away from custom avalanche copy/paste code, as the copy/paste code for custom bindings is a bit intricate and I didn't want to duplicate it. ? Chaos Cache has been moved away from using an object spawner and instead uses a custom spawnable actor binding inheriting from the regular spawnable actor binding. ? Actor and Take Recording has been updated to support custom spawnable bindings ? Meta Human specific code has been updated to support custom spawnable bindings when using Level Sequences ? FortniteMainBranchObjectVersion has been bumped Crash fix As part of the USD work, I found a crash bug where the Binding Properties menu would hold a reference to a level sequence. In the case of USD, the outer of the sequences can be the level, and this caused issues when switching levels. To fix this I ended up needing to add some events when menus are being dismissed so I could clean up these references. #jira UE-209839, UE-209548, UE-213115, UE-214195, UE-214443 #rb Marc.Audy #lockdown Marc.Audy [FYI] juan.portillo, Viktar.Mikhalchuk, Darrien.Blanchard, patrick.boutot [CL 34127005 by david bromberg in ue5-main branch]
2024-06-05 11:54:07 -04:00
NewSpawnTrack->Modify();
Sequencer- Resubmission of changelist 34065553 that had been backed out for a versioning issue which is now fixed. Original description below: Sequencer- Dynamic Binding Refactor Refactor the 'Dynamic Binding' blueprint system to be Custom Bindings rather than tied directly to FMovieScenePossessable and FMovieSceneSpawnable. As part of this: ? Created UMovieSceneReplaceableDirectorBlueprintBinding and UMovieSceneSpawnableDirectorBlueprintBinding to replace the Possessable and Spawnable versions of DynamicBindings ? Deprecated the DynamicBinding references on possessable and spawnable and created Postload fixup code to automatically create custom bindings instead ? Note that because the previous Dynamic Bindings operated as overrides and the new ones don't, there is a no longer supported path which is using Possessables as a preview in editor for Possessable Dynamic Bindings. Now if you don't mark 'Call in Editor' for a Replaceable Director Blueprint binding, you'll need to define a spawnable preview binding for the binding in order to work with it in Sequencer. ? Since UMG also used Dynamic Bindings on possessables, temporarily add DynamicBinding as a member variable on FWidgetAnimationBinding and create postload logic to move DynamicBindings to live on there for WidgetAnimations. ? USD has custom code to create dynamic bindings automatically for its use case. Convert this also to use the new custom binding system. ? Some cleanup on object binding right-click menus was done as part of this. ? Some further MovieSceneSequence API deprecation and refactoring has been done for the creation of bindings to add SharedPlaybackState where possible which was necessary for dynamic binding setup. FMovieSceneSpawnable deprecation in Level Sequences Since I was having to write postload fixup logic for FMovieSceneSpawnables with Dynamic Bindings that converted these to FMovieScenePossessables with custom bindings, it felt like a good chance to deprecate all FMovieSceneSpawnable use in Level Sequences. I chose at this time not to deprecate FMovieSceneSpawnable use for non-Level-Sequence Movie Scene Sequences. This includes Day Sequences, Template Sequences, Actor Sequences, Widget Animations, Niagara Sequences, and some Meta Human sequences. I made this choice because to do so would require also refactoring those sequence types to use MovieSceneBindingReferences in order to enable custom bindings for those sequence types. This will be a future refactor. Some notes on this deprecation. ? I kept MovieScene specific code that references or creates FMovieSceneSpawnables due to not refactoring all MovieSceneSequences ? Binding creation code in tools such as Sequencer will check for the presence of Binding References and create custom bindings if present, otherwise will still create FMovieSceneSpawnables ? AvaSequences required some extra work to make this change, including some changes and bugfixes to copy/pasting bindings to move away from custom avalanche copy/paste code, as the copy/paste code for custom bindings is a bit intricate and I didn't want to duplicate it. ? Chaos Cache has been moved away from using an object spawner and instead uses a custom spawnable actor binding inheriting from the regular spawnable actor binding. ? Actor and Take Recording has been updated to support custom spawnable bindings ? Meta Human specific code has been updated to support custom spawnable bindings when using Level Sequences ? FortniteMainBranchObjectVersion has been bumped Crash fix As part of the USD work, I found a crash bug where the Binding Properties menu would hold a reference to a level sequence. In the case of USD, the outer of the sequences can be the level, and this caused issues when switching levels. To fix this I ended up needing to add some events when menus are being dismissed so I could clean up these references. #jira UE-209839, UE-209548, UE-213115, UE-214195, UE-214443 #rb Marc.Audy #lockdown Marc.Audy [FYI] juan.portillo, Viktar.Mikhalchuk, Darrien.Blanchard, patrick.boutot [CL 34127005 by david bromberg in ue5-main branch]
2024-06-05 11:54:07 -04:00
NewSpawnTrack->AddSection(*NewSpawnTrack->CreateNewSection());
}
Sequencer- Resubmission of changelist 34065553 that had been backed out for a versioning issue which is now fixed. Original description below: Sequencer- Dynamic Binding Refactor Refactor the 'Dynamic Binding' blueprint system to be Custom Bindings rather than tied directly to FMovieScenePossessable and FMovieSceneSpawnable. As part of this: ? Created UMovieSceneReplaceableDirectorBlueprintBinding and UMovieSceneSpawnableDirectorBlueprintBinding to replace the Possessable and Spawnable versions of DynamicBindings ? Deprecated the DynamicBinding references on possessable and spawnable and created Postload fixup code to automatically create custom bindings instead ? Note that because the previous Dynamic Bindings operated as overrides and the new ones don't, there is a no longer supported path which is using Possessables as a preview in editor for Possessable Dynamic Bindings. Now if you don't mark 'Call in Editor' for a Replaceable Director Blueprint binding, you'll need to define a spawnable preview binding for the binding in order to work with it in Sequencer. ? Since UMG also used Dynamic Bindings on possessables, temporarily add DynamicBinding as a member variable on FWidgetAnimationBinding and create postload logic to move DynamicBindings to live on there for WidgetAnimations. ? USD has custom code to create dynamic bindings automatically for its use case. Convert this also to use the new custom binding system. ? Some cleanup on object binding right-click menus was done as part of this. ? Some further MovieSceneSequence API deprecation and refactoring has been done for the creation of bindings to add SharedPlaybackState where possible which was necessary for dynamic binding setup. FMovieSceneSpawnable deprecation in Level Sequences Since I was having to write postload fixup logic for FMovieSceneSpawnables with Dynamic Bindings that converted these to FMovieScenePossessables with custom bindings, it felt like a good chance to deprecate all FMovieSceneSpawnable use in Level Sequences. I chose at this time not to deprecate FMovieSceneSpawnable use for non-Level-Sequence Movie Scene Sequences. This includes Day Sequences, Template Sequences, Actor Sequences, Widget Animations, Niagara Sequences, and some Meta Human sequences. I made this choice because to do so would require also refactoring those sequence types to use MovieSceneBindingReferences in order to enable custom bindings for those sequence types. This will be a future refactor. Some notes on this deprecation. ? I kept MovieScene specific code that references or creates FMovieSceneSpawnables due to not refactoring all MovieSceneSequences ? Binding creation code in tools such as Sequencer will check for the presence of Binding References and create custom bindings if present, otherwise will still create FMovieSceneSpawnables ? AvaSequences required some extra work to make this change, including some changes and bugfixes to copy/pasting bindings to move away from custom avalanche copy/paste code, as the copy/paste code for custom bindings is a bit intricate and I didn't want to duplicate it. ? Chaos Cache has been moved away from using an object spawner and instead uses a custom spawnable actor binding inheriting from the regular spawnable actor binding. ? Actor and Take Recording has been updated to support custom spawnable bindings ? Meta Human specific code has been updated to support custom spawnable bindings when using Level Sequences ? FortniteMainBranchObjectVersion has been bumped Crash fix As part of the USD work, I found a crash bug where the Binding Properties menu would hold a reference to a level sequence. In the case of USD, the outer of the sequences can be the level, and this caused issues when switching levels. To fix this I ended up needing to add some events when menus are being dismissed so I could clean up these references. #jira UE-209839, UE-209548, UE-213115, UE-214195, UE-214443 #rb Marc.Audy #lockdown Marc.Audy [FYI] juan.portillo, Viktar.Mikhalchuk, Darrien.Blanchard, patrick.boutot [CL 34127005 by david bromberg in ue5-main branch]
2024-06-05 11:54:07 -04:00
return NewGuid;
}
#endif // WITH_EDITOR
UObject* ULevelSequence::CreateDirectorInstance(TSharedRef<const FSharedPlaybackState> SharedPlaybackState, FMovieSceneSequenceID SequenceID)
{
UObject* DirectorOuter = SharedPlaybackState->GetPlaybackContext();
IMovieScenePlayer* OptionalPlayer = UE::MovieScene::FPlayerIndexPlaybackCapability::GetPlayer(SharedPlaybackState);
#if WITH_EDITOR
if (!UMovieScene::IsTrackClassAllowed(ULevelSequenceDirector::StaticClass()))
{
return nullptr;
}
#endif
if (DirectorClass && DirectorOuter && DirectorClass->IsChildOf(ULevelSequenceDirector::StaticClass()))
{
FName DirectorName = NAME_None;
#if WITH_EDITOR
// Give it a pretty name so it shows up in the debug instances drop down nicely
DirectorName = MakeUniqueObjectName(DirectorOuter, DirectorClass, *(GetFName().ToString() + TEXT("_Director")));
#endif
ULevelSequencePlayer* LevelSequencePlayer = nullptr;
if (OptionalPlayer)
{
LevelSequencePlayer = Cast<ULevelSequencePlayer>(OptionalPlayer->AsUObject());
}
ULevelSequenceDirector* NewDirector = NewObject<ULevelSequenceDirector>(DirectorOuter, DirectorClass, DirectorName, RF_Transient);
NewDirector->SubSequenceID = SequenceID.GetInternalValue();
NewDirector->WeakLinker = SharedPlaybackState->GetLinker();
NewDirector->InstanceID = SharedPlaybackState->GetRootInstanceHandle().InstanceID;
NewDirector->InstanceSerial = SharedPlaybackState->GetRootInstanceHandle().InstanceSerial;
NewDirector->Player = LevelSequencePlayer;
NewDirector->MovieScenePlayerIndex = OptionalPlayer ? OptionalPlayer->GetUniqueIndex() : INDEX_NONE;
NewDirector->OnCreated();
return NewDirector;
}
return nullptr;
}
void ULevelSequence::AddAssetUserData(UAssetUserData* InUserData)
{
if (InUserData != NULL)
{
UAssetUserData* ExistingData = GetAssetUserDataOfClass(InUserData->GetClass());
if (ExistingData != NULL)
{
AssetUserData.Remove(ExistingData);
}
AssetUserData.Add(InUserData);
}
}
UAssetUserData* ULevelSequence::GetAssetUserDataOfClass(TSubclassOf<UAssetUserData> InUserDataClass)
{
for (int32 DataIdx = 0; DataIdx < AssetUserData.Num(); DataIdx++)
{
UAssetUserData* Datum = AssetUserData[DataIdx];
if (Datum != NULL && Datum->IsA(InUserDataClass))
{
return Datum;
}
}
return NULL;
}
void ULevelSequence::RemoveUserDataOfClass(TSubclassOf<UAssetUserData> InUserDataClass)
{
for (int32 DataIdx = 0; DataIdx < AssetUserData.Num(); DataIdx++)
{
UAssetUserData* Datum = AssetUserData[DataIdx];
if (Datum != NULL && Datum->IsA(InUserDataClass))
{
AssetUserData.RemoveAt(DataIdx);
return;
}
}
}
const TArray<UAssetUserData*>* ULevelSequence::GetAssetUserDataArray() const
{
return &ToRawPtrTArrayUnsafe(AssetUserData);
}
#if WITH_EDITOR
void ULevelSequence::IterateDynamicBindings(TFunction<void(const FGuid&, FMovieSceneDynamicBinding&)> InCallback)
Sequencer- Resubmission of changelist 34065553 that had been backed out for a versioning issue which is now fixed. Original description below: Sequencer- Dynamic Binding Refactor Refactor the 'Dynamic Binding' blueprint system to be Custom Bindings rather than tied directly to FMovieScenePossessable and FMovieSceneSpawnable. As part of this: ? Created UMovieSceneReplaceableDirectorBlueprintBinding and UMovieSceneSpawnableDirectorBlueprintBinding to replace the Possessable and Spawnable versions of DynamicBindings ? Deprecated the DynamicBinding references on possessable and spawnable and created Postload fixup code to automatically create custom bindings instead ? Note that because the previous Dynamic Bindings operated as overrides and the new ones don't, there is a no longer supported path which is using Possessables as a preview in editor for Possessable Dynamic Bindings. Now if you don't mark 'Call in Editor' for a Replaceable Director Blueprint binding, you'll need to define a spawnable preview binding for the binding in order to work with it in Sequencer. ? Since UMG also used Dynamic Bindings on possessables, temporarily add DynamicBinding as a member variable on FWidgetAnimationBinding and create postload logic to move DynamicBindings to live on there for WidgetAnimations. ? USD has custom code to create dynamic bindings automatically for its use case. Convert this also to use the new custom binding system. ? Some cleanup on object binding right-click menus was done as part of this. ? Some further MovieSceneSequence API deprecation and refactoring has been done for the creation of bindings to add SharedPlaybackState where possible which was necessary for dynamic binding setup. FMovieSceneSpawnable deprecation in Level Sequences Since I was having to write postload fixup logic for FMovieSceneSpawnables with Dynamic Bindings that converted these to FMovieScenePossessables with custom bindings, it felt like a good chance to deprecate all FMovieSceneSpawnable use in Level Sequences. I chose at this time not to deprecate FMovieSceneSpawnable use for non-Level-Sequence Movie Scene Sequences. This includes Day Sequences, Template Sequences, Actor Sequences, Widget Animations, Niagara Sequences, and some Meta Human sequences. I made this choice because to do so would require also refactoring those sequence types to use MovieSceneBindingReferences in order to enable custom bindings for those sequence types. This will be a future refactor. Some notes on this deprecation. ? I kept MovieScene specific code that references or creates FMovieSceneSpawnables due to not refactoring all MovieSceneSequences ? Binding creation code in tools such as Sequencer will check for the presence of Binding References and create custom bindings if present, otherwise will still create FMovieSceneSpawnables ? AvaSequences required some extra work to make this change, including some changes and bugfixes to copy/pasting bindings to move away from custom avalanche copy/paste code, as the copy/paste code for custom bindings is a bit intricate and I didn't want to duplicate it. ? Chaos Cache has been moved away from using an object spawner and instead uses a custom spawnable actor binding inheriting from the regular spawnable actor binding. ? Actor and Take Recording has been updated to support custom spawnable bindings ? Meta Human specific code has been updated to support custom spawnable bindings when using Level Sequences ? FortniteMainBranchObjectVersion has been bumped Crash fix As part of the USD work, I found a crash bug where the Binding Properties menu would hold a reference to a level sequence. In the case of USD, the outer of the sequences can be the level, and this caused issues when switching levels. To fix this I ended up needing to add some events when menus are being dismissed so I could clean up these references. #jira UE-209839, UE-209548, UE-213115, UE-214195, UE-214443 #rb Marc.Audy #lockdown Marc.Audy [FYI] juan.portillo, Viktar.Mikhalchuk, Darrien.Blanchard, patrick.boutot [CL 34127005 by david bromberg in ue5-main branch]
2024-06-05 11:54:07 -04:00
{
for (FMovieSceneBindingReference& BindingReference : BindingReferences.GetAllReferences())
{
if (BindingReference.CustomBinding)
{
if (UMovieSceneReplaceableDirectorBlueprintBinding* ReplaceableDirectorBlueprintBinding = Cast<UMovieSceneReplaceableDirectorBlueprintBinding>(BindingReference.CustomBinding))
{
InCallback(BindingReference.ID, ReplaceableDirectorBlueprintBinding->DynamicBinding);
}
// We can't use 'AsSpawnable' here because we don't have playback state and we might not have a world context.
// This should only be called from an editor context though, so we can just check the inner spawnable.
// If the binding is itself a spawnable director blueprint binding, then iterate over it
if (UMovieSceneSpawnableDirectorBlueprintBinding* SpawnableDirectorBlueprintBinding = Cast<UMovieSceneSpawnableDirectorBlueprintBinding>(BindingReference.CustomBinding))
Sequencer- Resubmission of changelist 34065553 that had been backed out for a versioning issue which is now fixed. Original description below: Sequencer- Dynamic Binding Refactor Refactor the 'Dynamic Binding' blueprint system to be Custom Bindings rather than tied directly to FMovieScenePossessable and FMovieSceneSpawnable. As part of this: ? Created UMovieSceneReplaceableDirectorBlueprintBinding and UMovieSceneSpawnableDirectorBlueprintBinding to replace the Possessable and Spawnable versions of DynamicBindings ? Deprecated the DynamicBinding references on possessable and spawnable and created Postload fixup code to automatically create custom bindings instead ? Note that because the previous Dynamic Bindings operated as overrides and the new ones don't, there is a no longer supported path which is using Possessables as a preview in editor for Possessable Dynamic Bindings. Now if you don't mark 'Call in Editor' for a Replaceable Director Blueprint binding, you'll need to define a spawnable preview binding for the binding in order to work with it in Sequencer. ? Since UMG also used Dynamic Bindings on possessables, temporarily add DynamicBinding as a member variable on FWidgetAnimationBinding and create postload logic to move DynamicBindings to live on there for WidgetAnimations. ? USD has custom code to create dynamic bindings automatically for its use case. Convert this also to use the new custom binding system. ? Some cleanup on object binding right-click menus was done as part of this. ? Some further MovieSceneSequence API deprecation and refactoring has been done for the creation of bindings to add SharedPlaybackState where possible which was necessary for dynamic binding setup. FMovieSceneSpawnable deprecation in Level Sequences Since I was having to write postload fixup logic for FMovieSceneSpawnables with Dynamic Bindings that converted these to FMovieScenePossessables with custom bindings, it felt like a good chance to deprecate all FMovieSceneSpawnable use in Level Sequences. I chose at this time not to deprecate FMovieSceneSpawnable use for non-Level-Sequence Movie Scene Sequences. This includes Day Sequences, Template Sequences, Actor Sequences, Widget Animations, Niagara Sequences, and some Meta Human sequences. I made this choice because to do so would require also refactoring those sequence types to use MovieSceneBindingReferences in order to enable custom bindings for those sequence types. This will be a future refactor. Some notes on this deprecation. ? I kept MovieScene specific code that references or creates FMovieSceneSpawnables due to not refactoring all MovieSceneSequences ? Binding creation code in tools such as Sequencer will check for the presence of Binding References and create custom bindings if present, otherwise will still create FMovieSceneSpawnables ? AvaSequences required some extra work to make this change, including some changes and bugfixes to copy/pasting bindings to move away from custom avalanche copy/paste code, as the copy/paste code for custom bindings is a bit intricate and I didn't want to duplicate it. ? Chaos Cache has been moved away from using an object spawner and instead uses a custom spawnable actor binding inheriting from the regular spawnable actor binding. ? Actor and Take Recording has been updated to support custom spawnable bindings ? Meta Human specific code has been updated to support custom spawnable bindings when using Level Sequences ? FortniteMainBranchObjectVersion has been bumped Crash fix As part of the USD work, I found a crash bug where the Binding Properties menu would hold a reference to a level sequence. In the case of USD, the outer of the sequences can be the level, and this caused issues when switching levels. To fix this I ended up needing to add some events when menus are being dismissed so I could clean up these references. #jira UE-209839, UE-209548, UE-213115, UE-214195, UE-214443 #rb Marc.Audy #lockdown Marc.Audy [FYI] juan.portillo, Viktar.Mikhalchuk, Darrien.Blanchard, patrick.boutot [CL 34127005 by david bromberg in ue5-main branch]
2024-06-05 11:54:07 -04:00
{
InCallback(BindingReference.ID, SpawnableDirectorBlueprintBinding->DynamicBinding);
}
else if (UMovieSceneReplaceableBindingBase* ReplaceableBinding = Cast<UMovieSceneReplaceableBindingBase>(BindingReference.CustomBinding))
{
if (UMovieSceneSpawnableDirectorBlueprintBinding* InnerSpawnableDirectorBlueprintBinding = Cast<UMovieSceneSpawnableDirectorBlueprintBinding>(ReplaceableBinding->PreviewSpawnable))
{
InCallback(BindingReference.ID, InnerSpawnableDirectorBlueprintBinding->DynamicBinding);
}
}
Sequencer- Resubmission of changelist 34065553 that had been backed out for a versioning issue which is now fixed. Original description below: Sequencer- Dynamic Binding Refactor Refactor the 'Dynamic Binding' blueprint system to be Custom Bindings rather than tied directly to FMovieScenePossessable and FMovieSceneSpawnable. As part of this: ? Created UMovieSceneReplaceableDirectorBlueprintBinding and UMovieSceneSpawnableDirectorBlueprintBinding to replace the Possessable and Spawnable versions of DynamicBindings ? Deprecated the DynamicBinding references on possessable and spawnable and created Postload fixup code to automatically create custom bindings instead ? Note that because the previous Dynamic Bindings operated as overrides and the new ones don't, there is a no longer supported path which is using Possessables as a preview in editor for Possessable Dynamic Bindings. Now if you don't mark 'Call in Editor' for a Replaceable Director Blueprint binding, you'll need to define a spawnable preview binding for the binding in order to work with it in Sequencer. ? Since UMG also used Dynamic Bindings on possessables, temporarily add DynamicBinding as a member variable on FWidgetAnimationBinding and create postload logic to move DynamicBindings to live on there for WidgetAnimations. ? USD has custom code to create dynamic bindings automatically for its use case. Convert this also to use the new custom binding system. ? Some cleanup on object binding right-click menus was done as part of this. ? Some further MovieSceneSequence API deprecation and refactoring has been done for the creation of bindings to add SharedPlaybackState where possible which was necessary for dynamic binding setup. FMovieSceneSpawnable deprecation in Level Sequences Since I was having to write postload fixup logic for FMovieSceneSpawnables with Dynamic Bindings that converted these to FMovieScenePossessables with custom bindings, it felt like a good chance to deprecate all FMovieSceneSpawnable use in Level Sequences. I chose at this time not to deprecate FMovieSceneSpawnable use for non-Level-Sequence Movie Scene Sequences. This includes Day Sequences, Template Sequences, Actor Sequences, Widget Animations, Niagara Sequences, and some Meta Human sequences. I made this choice because to do so would require also refactoring those sequence types to use MovieSceneBindingReferences in order to enable custom bindings for those sequence types. This will be a future refactor. Some notes on this deprecation. ? I kept MovieScene specific code that references or creates FMovieSceneSpawnables due to not refactoring all MovieSceneSequences ? Binding creation code in tools such as Sequencer will check for the presence of Binding References and create custom bindings if present, otherwise will still create FMovieSceneSpawnables ? AvaSequences required some extra work to make this change, including some changes and bugfixes to copy/pasting bindings to move away from custom avalanche copy/paste code, as the copy/paste code for custom bindings is a bit intricate and I didn't want to duplicate it. ? Chaos Cache has been moved away from using an object spawner and instead uses a custom spawnable actor binding inheriting from the regular spawnable actor binding. ? Actor and Take Recording has been updated to support custom spawnable bindings ? Meta Human specific code has been updated to support custom spawnable bindings when using Level Sequences ? FortniteMainBranchObjectVersion has been bumped Crash fix As part of the USD work, I found a crash bug where the Binding Properties menu would hold a reference to a level sequence. In the case of USD, the outer of the sequences can be the level, and this caused issues when switching levels. To fix this I ended up needing to add some events when menus are being dismissed so I could clean up these references. #jira UE-209839, UE-209548, UE-213115, UE-214195, UE-214443 #rb Marc.Audy #lockdown Marc.Audy [FYI] juan.portillo, Viktar.Mikhalchuk, Darrien.Blanchard, patrick.boutot [CL 34127005 by david bromberg in ue5-main branch]
2024-06-05 11:54:07 -04:00
}
}
}
#endif