2019-12-26 15:33:43 -05:00
// Copyright Epic Games, Inc. All Rights Reserved.
2019-10-01 20:41:42 -04:00
# include "MovieSceneEventUtils.h"
# include "Algo/Find.h"
# include "UObject/StrongObjectPtr.h"
# include "UObject/Package.h"
2022-04-05 18:58:45 -04:00
# include "MovieScene.h"
2019-10-01 20:41:42 -04:00
# include "MovieSceneSequence.h"
# include "Sections/MovieSceneEventSectionBase.h"
# include "Tracks/MovieSceneEventTrack.h"
2019-11-12 21:52:54 -05:00
# include "MovieSceneEventBlueprintExtension.h"
2019-10-01 20:41:42 -04:00
# include "ScopedTransaction.h"
2021-10-25 20:05:28 -04:00
# include "Framework/Notifications/NotificationManager.h"
# include "Widgets/Notifications/SNotificationList.h"
2019-10-01 20:41:42 -04:00
2021-03-18 15:20:03 -04:00
# include "GameFramework/Actor.h"
2019-10-01 20:41:42 -04:00
# include "Engine/Blueprint.h"
# include "KismetCompiler.h"
# include "K2Node_CustomEvent.h"
# include "K2Node_VariableGet.h"
# include "K2Node_CallFunction.h"
# include "K2Node_FunctionEntry.h"
# include "K2Node_EditablePinBase.h"
2021-03-18 15:20:03 -04:00
# include "K2Node_DynamicCast.h"
# include "Kismet/KismetSystemLibrary.h"
2019-10-01 20:41:42 -04:00
# include "Kismet2/BlueprintEditorUtils.h"
# include "Kismet2/KismetEditorUtilities.h"
# include "Kismet2/Kismet2NameValidators.h"
# define LOCTEXT_NAMESPACE "MovieSceneEventUtils"
FMovieSceneEventEndpointParameters FMovieSceneEventEndpointParameters : : Generate ( UMovieSceneEventTrack * Track )
{
check ( Track ) ;
UMovieScene * MovieScene = Track - > GetTypedOuter < UMovieScene > ( ) ;
FGuid ObjectBindingID ;
if ( MovieScene - > FindTrackBinding ( * Track , ObjectBindingID ) )
{
return Generate ( MovieScene , ObjectBindingID ) ;
}
FMovieSceneEventEndpointParameters Params ;
2020-08-11 01:36:57 -04:00
Params . SanitizedObjectName = TEXT ( " None " ) ;
Params . SanitizedEventName = TEXT ( " SequenceEvent " ) ;
2019-10-01 20:41:42 -04:00
return Params ;
}
FMovieSceneEventEndpointParameters FMovieSceneEventEndpointParameters : : Generate ( UMovieScene * MovieScene , const FGuid & ObjectBindingID )
{
check ( MovieScene ) ;
FMovieSceneEventEndpointParameters Params ;
if ( ObjectBindingID . IsValid ( ) )
{
Params . SanitizedObjectName = MovieScene - > GetObjectDisplayName ( ObjectBindingID ) . ToString ( ) ;
for ( TCHAR & Char : Params . SanitizedObjectName )
{
if ( FCString : : Strchr ( INVALID_NAME_CHARACTERS , Char ) ! = nullptr )
{
Char = ' _ ' ;
}
}
Params . SanitizedEventName = Params . SanitizedObjectName + TEXT ( " _Event " ) ;
if ( FMovieScenePossessable * Possessable = MovieScene - > FindPossessable ( ObjectBindingID ) )
{
Params . BoundObjectPinClass = const_cast < UClass * > ( Possessable - > GetPossessedObjectClass ( ) ) ;
}
else if ( FMovieSceneSpawnable * Spawnable = MovieScene - > FindSpawnable ( ObjectBindingID ) )
{
Params . BoundObjectPinClass = Spawnable - > GetObjectTemplate ( ) - > GetClass ( ) ;
}
}
else
{
Params . BoundObjectPinClass = nullptr ;
Params . SanitizedObjectName = TEXT ( " None " ) ;
Params . SanitizedEventName = TEXT ( " SequenceEvent " ) ;
}
return Params ;
}
UK2Node_CustomEvent * FMovieSceneEventUtils : : BindNewUserFacingEvent ( FMovieSceneEvent * EntryPoint , UMovieSceneEventSectionBase * EventSection , UBlueprint * Blueprint )
{
check ( EntryPoint & & EventSection & & Blueprint ) ;
UMovieSceneEventTrack * Track = EventSection - > GetTypedOuter < UMovieSceneEventTrack > ( ) ;
// Modify necessary objects
EventSection - > Modify ( ) ;
Blueprint - > Modify ( ) ;
// Ensure the section is bound to the blueprint function generation event
2019-11-12 21:52:54 -05:00
FMovieSceneEventUtils : : BindEventSectionToBlueprint ( EventSection , Blueprint ) ;
2019-10-01 20:41:42 -04:00
// Create the new user-facing event node
FMovieSceneEventEndpointParameters Params = FMovieSceneEventEndpointParameters : : Generate ( Track ) ;
UK2Node_CustomEvent * NewEventNode = CreateUserFacingEvent ( Blueprint , Params ) ;
if ( NewEventNode )
{
// Bind the node to the event entry point
UEdGraphPin * BoundObjectPin = FMovieSceneEventUtils : : FindBoundObjectPin ( NewEventNode , Params . BoundObjectPinClass ) ;
FMovieSceneEventUtils : : SetEndpoint ( EntryPoint , EventSection , NewEventNode , BoundObjectPin ) ;
}
return NewEventNode ;
}
UK2Node_CustomEvent * FMovieSceneEventUtils : : CreateUserFacingEvent ( UBlueprint * Blueprint , const FMovieSceneEventEndpointParameters & Parameters )
{
static const TCHAR * const EventGraphName = TEXT ( " Sequencer Events " ) ;
UEdGraph * SequenceEventGraph = FindObject < UEdGraph > ( Blueprint , EventGraphName ) ;
if ( ! SequenceEventGraph )
{
SequenceEventGraph = FBlueprintEditorUtils : : CreateNewGraph ( Blueprint , EventGraphName , UEdGraph : : StaticClass ( ) , UEdGraphSchema_K2 : : StaticClass ( ) ) ;
SequenceEventGraph - > GraphGuid = FGuid : : NewGuid ( ) ;
Blueprint - > UbergraphPages . Add ( SequenceEventGraph ) ;
}
// Create a custom event node to replace the original event node imported from text
UK2Node_CustomEvent * CustomEventNode = NewObject < UK2Node_CustomEvent > ( SequenceEventGraph ) ;
check ( Parameters . SanitizedEventName . Len ( ) ! = 0 ) ;
CustomEventNode - > CustomFunctionName = FBlueprintEditorUtils : : FindUniqueKismetName ( Blueprint , Parameters . SanitizedEventName ) ;
// Ensure that it is editable
CustomEventNode - > bIsEditable = true ;
CustomEventNode - > CreateNewGuid ( ) ;
CustomEventNode - > PostPlacedNewNode ( ) ;
CustomEventNode - > AllocateDefaultPins ( ) ;
const FVector2D NewPosition = SequenceEventGraph - > GetGoodPlaceForNewNode ( ) ;
CustomEventNode - > NodePosX = NewPosition . X ;
CustomEventNode - > NodePosY = NewPosition . Y ;
if ( Parameters . BoundObjectPinClass ! = nullptr )
{
FEdGraphPinType PinType ;
PinType . PinCategory = UEdGraphSchema_K2 : : PC_Object ;
PinType . PinSubCategoryObject = Parameters . BoundObjectPinClass ;
CustomEventNode - > CreateUserDefinedPin ( * Parameters . SanitizedObjectName , PinType , EGPD_Output , true ) ;
}
SequenceEventGraph - > AddNode ( CustomEventNode , false , false ) ;
FBlueprintEditorUtils : : ValidateBlueprintChildVariables ( Blueprint , CustomEventNode - > CustomFunctionName ) ;
FBlueprintEditorUtils : : MarkBlueprintAsStructurallyModified ( Blueprint ) ;
return CustomEventNode ;
}
UK2Node * FMovieSceneEventUtils : : FindEndpoint ( FMovieSceneEvent * EntryPoint , UMovieSceneEventSectionBase * EventSection , UBlueprint * OwnerBlueprint )
{
check ( OwnerBlueprint ) ;
check ( EntryPoint ) ;
2020-09-01 14:07:48 -04:00
if ( EntryPoint - > WeakEndpoint . IsStale ( ) )
{
return nullptr ;
}
if ( UK2Node * Node = Cast < UK2Node > ( EntryPoint - > WeakEndpoint . Get ( ) ) )
{
return Node ;
}
if ( ! EntryPoint - > GraphGuid_DEPRECATED . IsValid ( ) )
2019-10-01 20:41:42 -04:00
{
return nullptr ;
}
2020-09-01 14:07:48 -04:00
if ( EntryPoint - > NodeGuid_DEPRECATED . IsValid ( ) )
2019-10-01 20:41:42 -04:00
{
for ( UEdGraph * Graph : OwnerBlueprint - > UbergraphPages )
{
2020-09-01 14:07:48 -04:00
if ( Graph - > GraphGuid = = EntryPoint - > GraphGuid_DEPRECATED )
2019-10-01 20:41:42 -04:00
{
for ( UEdGraphNode * Node : Graph - > Nodes )
{
2020-09-01 14:07:48 -04:00
if ( Node - > NodeGuid = = EntryPoint - > NodeGuid_DEPRECATED )
2019-10-01 20:41:42 -04:00
{
UK2Node_CustomEvent * CustomEvent = Cast < UK2Node_CustomEvent > ( Node ) ;
if ( ensureMsgf ( CustomEvent , TEXT ( " Encountered an event entry point node that is bound to something other than a custom event " ) ) )
{
CustomEvent - > OnUserDefinedPinRenamed ( ) . AddUObject ( EventSection , & UMovieSceneEventSectionBase : : OnUserDefinedPinRenamed ) ;
2020-09-01 14:07:48 -04:00
EntryPoint - > WeakEndpoint = CustomEvent ;
2019-10-01 20:41:42 -04:00
return CustomEvent ;
}
}
}
}
}
}
// If the node guid is invalid, this must be a function graph on the BP
else for ( UEdGraph * Graph : OwnerBlueprint - > FunctionGraphs )
{
2020-09-01 14:07:48 -04:00
if ( Graph - > GraphGuid = = EntryPoint - > GraphGuid_DEPRECATED )
2019-10-01 20:41:42 -04:00
{
for ( UEdGraphNode * Node : Graph - > Nodes )
{
if ( UK2Node_FunctionEntry * FunctionEntry = Cast < UK2Node_FunctionEntry > ( Node ) )
{
FunctionEntry - > OnUserDefinedPinRenamed ( ) . AddUObject ( EventSection , & UMovieSceneEventSectionBase : : OnUserDefinedPinRenamed ) ;
2020-09-01 14:07:48 -04:00
EntryPoint - > WeakEndpoint = FunctionEntry ;
2019-10-01 20:41:42 -04:00
return FunctionEntry ;
}
}
}
}
return nullptr ;
}
UEdGraphPin * FMovieSceneEventUtils : : FindBoundObjectPin ( UK2Node * InEndpoint , UClass * BoundObjectPinClass )
{
if ( ! BoundObjectPinClass )
{
return nullptr ;
}
for ( UEdGraphPin * Pin : InEndpoint - > Pins )
{
if ( Pin - > Direction = = EGPD_Output & & Pin - > PinType . PinCategory = = UEdGraphSchema_K2 : : PC_Object & & Pin - > PinType . PinSubCategoryObject = = BoundObjectPinClass )
{
return Pin ;
}
}
return nullptr ;
}
void FMovieSceneEventUtils : : SetEndpoint ( FMovieSceneEvent * EntryPoint , UMovieSceneEventSectionBase * EventSection , UK2Node * InNewEndpoint , UEdGraphPin * BoundObjectPin )
{
check ( EntryPoint ) ;
2020-09-01 14:07:48 -04:00
UK2Node * ExistingEndpoint = CastChecked < UK2Node > ( EntryPoint - > WeakEndpoint . Get ( ) , ECastCheckedType : : NullAllowed ) ;
2019-10-01 20:41:42 -04:00
if ( ExistingEndpoint )
{
ExistingEndpoint - > OnUserDefinedPinRenamed ( ) . RemoveAll ( EventSection ) ;
}
if ( InNewEndpoint )
{
const bool bIsFunction = InNewEndpoint - > IsA < UK2Node_FunctionEntry > ( ) ;
const bool bIsCustomEvent = InNewEndpoint - > IsA < UK2Node_CustomEvent > ( ) ;
checkf ( bIsFunction | | bIsCustomEvent , TEXT ( " Only functions and custom events are supported as event endpoints " ) ) ;
if ( BoundObjectPin )
{
EntryPoint - > BoundObjectPinName = BoundObjectPin - > GetFName ( ) ;
}
else
{
EntryPoint - > BoundObjectPinName = NAME_None ;
}
InNewEndpoint - > OnUserDefinedPinRenamed ( ) . AddUObject ( EventSection , & UMovieSceneEventSectionBase : : OnUserDefinedPinRenamed ) ;
2020-09-01 14:07:48 -04:00
EntryPoint - > WeakEndpoint = InNewEndpoint ;
2019-10-01 20:41:42 -04:00
}
else
{
2020-09-01 14:07:48 -04:00
EntryPoint - > WeakEndpoint = nullptr ;
2019-10-01 20:41:42 -04:00
EntryPoint - > BoundObjectPinName = NAME_None ;
}
}
UK2Node_FunctionEntry * FMovieSceneEventUtils : : GenerateEntryPoint ( UMovieSceneEventSectionBase * EventSection , FMovieSceneEvent * EntrypointDefinition , FKismetCompilerContext * Compiler , UEdGraphNode * Endpoint )
{
check ( EventSection & & Compiler & & Endpoint ) ;
UBlueprint * Blueprint = Compiler - > Blueprint ;
UFunction * EndpointFunction = nullptr ;
// Find the function that we need to call on the skeleton class
{
if ( UK2Node_Event * Event = Cast < UK2Node_Event > ( Endpoint ) )
{
EndpointFunction = Blueprint - > SkeletonGeneratedClass ? Blueprint - > SkeletonGeneratedClass - > FindFunctionByName ( Event - > GetFunctionName ( ) ) : nullptr ;
}
else if ( UK2Node_FunctionEntry * EndpointEntry = Cast < UK2Node_FunctionEntry > ( Endpoint ) )
{
EndpointFunction = EndpointEntry - > FindSignatureFunction ( ) ;
}
else
{
Compiler - > MessageLog . Error ( * LOCTEXT ( " InvalidEndpoint_Error " , " Sequencer event is bound to an invalid endpoint node @@ " ) . ToString ( ) , Endpoint ) ;
}
}
if ( EndpointFunction = = nullptr )
{
return nullptr ;
}
// @todo: use a more destriptive name for event entry points?
2019-10-15 15:58:41 -04:00
static FString DefaultEventEntryName = TEXT ( " SequenceEvent__ENTRYPOINT " ) ;
UEdGraph * EntryPointGraph = Compiler - > SpawnIntermediateFunctionGraph ( DefaultEventEntryName + Blueprint - > GetName ( ) ) ;
2019-10-01 20:41:42 -04:00
check ( EntryPointGraph - > Nodes . Num ( ) = = 1 ) ;
const UEdGraphSchema * Schema = EntryPointGraph - > GetSchema ( ) ;
UK2Node_FunctionEntry * FunctionEntry = CastChecked < UK2Node_FunctionEntry > ( EntryPointGraph - > Nodes [ 0 ] ) ;
// -------------------------------------------------------------------------------------
// Locate and initialize the function entry node
{
int32 ExtraFunctionFlags = ( FUNC_BlueprintEvent | FUNC_Public ) ;
FunctionEntry - > AddExtraFlags ( ExtraFunctionFlags ) ;
FunctionEntry - > bIsEditable = false ;
FunctionEntry - > MetaData . Category = LOCTEXT ( " DefaultCategory " , " Sequencer Event Endpoints " ) ;
FunctionEntry - > MetaData . bCallInEditor = EndpointFunction - > GetBoolMetaData ( FBlueprintMetadata : : MD_CallInEditor ) ;
}
// -------------------------------------------------------------------------------------
// Create a function call node to invoke the endpoint function itself
UK2Node_CallFunction * CallFunctionNode = NewObject < UK2Node_CallFunction > ( EntryPointGraph ) ;
{
CallFunctionNode - > CreateNewGuid ( ) ;
CallFunctionNode - > PostPlacedNewNode ( ) ;
CallFunctionNode - > FunctionReference . SetSelfMember ( EndpointFunction - > GetFName ( ) ) ;
CallFunctionNode - > ReconstructNode ( ) ;
CallFunctionNode - > NodePosX = FunctionEntry - > NodePosX + 400.f ;
CallFunctionNode - > NodePosY = FunctionEntry - > NodePosY - 16.f ;
EntryPointGraph - > AddNode ( CallFunctionNode , false , false ) ;
}
// -------------------------------------------------------------------------------------
// Create a pin for the bound object if possible
if ( EntrypointDefinition - > BoundObjectPinName ! = NAME_None )
{
UEdGraphPin * BoundObjectPin = CallFunctionNode - > FindPin ( EntrypointDefinition - > BoundObjectPinName , EGPD_Input ) ;
if ( BoundObjectPin )
{
UEdGraphPin * BoundObjectPinInput = FunctionEntry - > CreateUserDefinedPin ( BoundObjectPin - > PinName , BoundObjectPin - > PinType , EGPD_Output , true ) ;
if ( BoundObjectPinInput )
{
BoundObjectPinInput - > MakeLinkTo ( BoundObjectPin ) ;
}
}
}
// -------------------------------------------------------------------------------------
// Wire up the function entry 'then' pin to the call function 'execute' pin
{
// Wire up the exec nodes
UEdGraphPin * ThenPin = FunctionEntry - > FindPin ( UEdGraphSchema_K2 : : PN_Then , EGPD_Output ) ;
UEdGraphPin * ExecPin = CallFunctionNode - > FindPin ( UEdGraphSchema_K2 : : PN_Execute , EGPD_Input ) ;
if ( ensure ( ThenPin & & ExecPin ) )
{
ThenPin - > MakeLinkTo ( ExecPin ) ;
}
}
// -------------------------------------------------------------------------------------
// Set pin defaults for each of the relevant pins on the call function node according to the payload
{
TArray < FName , TInlineAllocator < 8 > > ValidPinNames ;
// Gather all input pins for the function call
for ( UEdGraphPin * Pin : CallFunctionNode - > Pins )
{
// Only consider input pins that are data, and not already connected
if ( Pin - > Direction ! = EGPD_Input | | Pin - > PinName = = UEdGraphSchema_K2 : : PN_Execute | | Pin - > PinName = = UEdGraphSchema_K2 : : PN_Self | | Pin - > LinkedTo . Num ( ) ! = 0 )
{
continue ;
}
const FMovieSceneEventPayloadVariable * PayloadVariable = EntrypointDefinition - > PayloadVariables . Find ( Pin - > PinName ) ;
2021-03-18 15:20:03 -04:00
if ( ! PayloadVariable )
{
continue ;
}
UClass * PinObjectType = Cast < UClass > ( Pin - > PinType . PinSubCategoryObject . Get ( ) ) ;
const bool bIsRawActorPin = Pin - > PinType . PinCategory = = UEdGraphSchema_K2 : : PC_Object & & PinObjectType & & PinObjectType - > IsChildOf ( AActor : : StaticClass ( ) ) ;
if ( bIsRawActorPin )
{
// Raw actor properties are represented as soft object ptrs under the hood so that we can still serialize them
// To make this work, we have to make the following graph:
// MakeSoftObjectPath('<ActorPath>') -> Conv_SoftObjPathToSoftObjRef() -> Conv_SoftObjectReferenceToObject() -> Cast<ActorType>()
UK2Node_CallFunction * MakeSoftObjectPathNode = Compiler - > SpawnIntermediateNode < UK2Node_CallFunction > ( CallFunctionNode , EntryPointGraph ) ;
MakeSoftObjectPathNode - > FunctionReference . SetExternalMember ( GET_FUNCTION_NAME_CHECKED ( UKismetSystemLibrary , MakeSoftObjectPath ) , UKismetSystemLibrary : : StaticClass ( ) ) ;
MakeSoftObjectPathNode - > AllocateDefaultPins ( ) ;
UK2Node_CallFunction * ConvertToSoftObjectRef = Compiler - > SpawnIntermediateNode < UK2Node_CallFunction > ( CallFunctionNode , EntryPointGraph ) ;
ConvertToSoftObjectRef - > FunctionReference . SetExternalMember ( GET_FUNCTION_NAME_CHECKED ( UKismetSystemLibrary , Conv_SoftObjPathToSoftObjRef ) , UKismetSystemLibrary : : StaticClass ( ) ) ;
ConvertToSoftObjectRef - > AllocateDefaultPins ( ) ;
UK2Node_CallFunction * ConvertToObjectFunc = Compiler - > SpawnIntermediateNode < UK2Node_CallFunction > ( CallFunctionNode , EntryPointGraph ) ;
ConvertToObjectFunc - > FunctionReference . SetExternalMember ( GET_FUNCTION_NAME_CHECKED ( UKismetSystemLibrary , Conv_SoftObjectReferenceToObject ) , UKismetSystemLibrary : : StaticClass ( ) ) ;
ConvertToObjectFunc - > AllocateDefaultPins ( ) ;
UK2Node_DynamicCast * CastNode = Compiler - > SpawnIntermediateNode < UK2Node_DynamicCast > ( CallFunctionNode , EntryPointGraph ) ;
CastNode - > SetPurity ( true ) ;
CastNode - > TargetType = PinObjectType ;
CastNode - > AllocateDefaultPins ( ) ;
UEdGraphPin * PathInput = MakeSoftObjectPathNode - > FindPin ( FName ( " PathString " ) ) ;
UEdGraphPin * PathOutput = MakeSoftObjectPathNode - > GetReturnValuePin ( ) ;
UEdGraphPin * SoftRefInput = ConvertToSoftObjectRef - > FindPin ( FName ( " SoftObjectPath " ) ) ;
UEdGraphPin * SoftRefOutput = ConvertToSoftObjectRef - > GetReturnValuePin ( ) ;
UEdGraphPin * ConvertInput = ConvertToObjectFunc - > FindPin ( FName ( " SoftObject " ) ) ;
UEdGraphPin * ConvertOutput = ConvertToObjectFunc - > GetReturnValuePin ( ) ;
UEdGraphPin * CastInput = CastNode - > GetCastSourcePin ( ) ;
UEdGraphPin * CastOutput = CastNode - > GetCastResultPin ( ) ;
if ( ! PathInput | | ! PathOutput | | ! SoftRefInput | | ! SoftRefOutput | | ! ConvertInput | | ! ConvertOutput | | ! CastInput | | ! CastOutput )
{
Compiler - > MessageLog . Error ( * LOCTEXT ( " ActorFacadeError " , " GenerateEntryPoint: Failed to generate soft-ptr facade for AActor payload property property @@. @@ " ) . ToString ( ) , * Pin - > PinName . ToString ( ) , Endpoint ) ;
continue ;
}
// Set the default value for the path string
const bool bMarkAsModified = false ;
Schema - > TrySetDefaultValue ( * PathInput , PayloadVariable - > Value , bMarkAsModified ) ;
bool bSuccess = true ;
bSuccess & = Schema - > TryCreateConnection ( PathOutput , SoftRefInput ) ;
bSuccess & = Schema - > TryCreateConnection ( SoftRefOutput , ConvertInput ) ;
bSuccess & = Schema - > TryCreateConnection ( ConvertOutput , CastInput ) ;
bSuccess & = Schema - > TryCreateConnection ( CastOutput , Pin ) ;
if ( ! bSuccess )
{
Compiler - > MessageLog . Error ( * LOCTEXT ( " ActorFacadeConnectionError " , " GenerateEntryPoint: Failed to connect nodes for soft-ptr facade in AActor payload property @@. @@ " ) . ToString ( ) , * Pin - > PinName . ToString ( ) , Endpoint ) ;
}
ValidPinNames . Add ( Pin - > PinName ) ;
}
else
2019-10-01 20:41:42 -04:00
{
bool bMarkAsModified = false ;
Schema - > TrySetDefaultValue ( * Pin , PayloadVariable - > Value , bMarkAsModified ) ;
ValidPinNames . Add ( Pin - > PinName ) ;
}
}
// Remove any invalid payload variable names
if ( ValidPinNames . Num ( ) ! = EntrypointDefinition - > PayloadVariables . Num ( ) )
{
for ( auto It = EntrypointDefinition - > PayloadVariables . CreateIterator ( ) ; It ; + + It )
{
if ( ! ValidPinNames . Contains ( It - > Key ) )
{
Compiler - > MessageLog . Note ( * FText : : Format ( LOCTEXT ( " PayloadParameterRemoved " , " Stale Sequencer event payload parameter %s has been removed. " ) , FText : : FromName ( It - > Key ) ) . ToString ( ) ) ;
It . RemoveCurrent ( ) ;
}
}
}
}
return FunctionEntry ;
}
2019-11-12 21:52:54 -05:00
void FMovieSceneEventUtils : : BindEventSectionToBlueprint ( UMovieSceneEventSectionBase * EventSection , UBlueprint * DirectorBP )
{
check ( EventSection & & DirectorBP ) ;
2022-03-23 18:12:22 -04:00
for ( TObjectPtr < UBlueprintExtension > Extension : DirectorBP - > GetExtensions ( ) )
2019-11-12 21:52:54 -05:00
{
UMovieSceneEventBlueprintExtension * EventExtension = Cast < UMovieSceneEventBlueprintExtension > ( Extension ) ;
if ( EventExtension )
{
EventExtension - > Add ( EventSection ) ;
return ;
}
}
UMovieSceneEventBlueprintExtension * EventExtension = NewObject < UMovieSceneEventBlueprintExtension > ( DirectorBP ) ;
EventExtension - > Add ( EventSection ) ;
2022-03-23 18:12:22 -04:00
DirectorBP - > AddExtension ( EventExtension ) ;
2019-11-12 21:52:54 -05:00
}
2021-10-12 21:21:22 -04:00
void FMovieSceneEventUtils : : RemoveEndpointsForEventSection ( UMovieSceneEventSectionBase * EventSection , UBlueprint * DirectorBP )
{
check ( EventSection & & DirectorBP ) ;
static const TCHAR * const EventGraphName = TEXT ( " Sequencer Events " ) ;
UEdGraph * SequenceEventGraph = FindObject < UEdGraph > ( DirectorBP , EventGraphName ) ;
if ( SequenceEventGraph )
{
for ( FMovieSceneEvent & EntryPoint : EventSection - > GetAllEntryPoints ( ) )
{
UEdGraphNode * Endpoint = FMovieSceneEventUtils : : FindEndpoint ( & EntryPoint , EventSection , DirectorBP ) ;
if ( Endpoint )
{
UE_LOG ( LogMovieScene , Display , TEXT ( " Removing event: %s from: %s " ) , * GetNameSafe ( Endpoint ) , * GetNameSafe ( DirectorBP ) ) ;
SequenceEventGraph - > RemoveNode ( Endpoint ) ;
}
}
}
}
2021-10-25 20:05:28 -04:00
void FMovieSceneEventUtils : : RemoveUnusedCustomEvents ( const TArray < TWeakObjectPtr < UMovieSceneEventSectionBase > > & EventSections , UBlueprint * DirectorBP )
{
check ( DirectorBP ) ;
static const TCHAR * const EventGraphName = TEXT ( " Sequencer Events " ) ;
UEdGraph * SequenceEventGraph = FindObject < UEdGraph > ( DirectorBP , EventGraphName ) ;
if ( SequenceEventGraph )
{
TArray < UK2Node_CustomEvent * > ExistingNodes ;
SequenceEventGraph - > GetNodesOfClass ( ExistingNodes ) ;
TSet < UEdGraphNode * > Endpoints ;
for ( TWeakObjectPtr < UMovieSceneEventSectionBase > WeakEventSection : EventSections )
{
UMovieSceneEventSectionBase * EventSection = WeakEventSection . Get ( ) ;
if ( ! EventSection )
{
continue ;
}
for ( FMovieSceneEvent & EntryPoint : EventSection - > GetAllEntryPoints ( ) )
{
if ( UEdGraphNode * Endpoint = FMovieSceneEventUtils : : FindEndpoint ( & EntryPoint , EventSection , DirectorBP ) )
{
Endpoints . Add ( Endpoint ) ;
}
}
}
FScopedTransaction RemoveUnusedCustomEvents ( LOCTEXT ( " RemoveUnusedCustomEvents " , " Remove Unused Custom Events " ) ) ;
for ( UK2Node_CustomEvent * ExistingNode : ExistingNodes )
{
const bool bHasEntryPoint = Endpoints . Contains ( ExistingNode ) ;
if ( ! bHasEntryPoint )
{
FNotificationInfo Info ( FText : : Format ( LOCTEXT ( " RemoveUnusedCustomEventNotify " , " Remove unused custom event {0} from {1} " ) , FText : : FromString ( GetNameSafe ( ExistingNode ) ) , FText : : FromString ( GetNameSafe ( DirectorBP ) ) ) ) ;
Info . ExpireDuration = 3.f ;
FSlateNotificationManager : : Get ( ) . AddNotification ( Info ) ;
2021-11-07 23:43:01 -05:00
UE_LOG ( LogMovieScene , Display , TEXT ( " Remove unused custom event %s from %s " ) , * GetNameSafe ( ExistingNode ) , * GetNameSafe ( DirectorBP ) ) ;
2021-10-25 20:05:28 -04:00
DirectorBP - > Modify ( ) ;
SequenceEventGraph - > RemoveNode ( ExistingNode ) ;
}
}
}
}
2019-10-01 20:41:42 -04:00
# undef LOCTEXT_NAMESPACE