bool F3DAttachTrackEditor::AddKeyInternal( float KeyTime, const TArray<TWeakObjectPtr<UObject>> Objects, const FName SocketName, const FName ComponentName, AActor* ParentActor) { bool bHandleCreated = false; bool bTrackCreated = false; bool bTrackModified = false; FGuid ParentActorId; if (ParentActor != nullptr) { FFindOrCreateHandleResult HandleResult = FindOrCreateHandleToObject(ParentActor); ParentActorId = HandleResult.Handle; bHandleCreated |= HandleResult.bWasCreated; } if (!ParentActorId.IsValid()) { return false; } for( int32 ObjectIndex = 0; ObjectIndex < Objects.Num(); ++ObjectIndex ) { UObject* Object = Objects[ObjectIndex].Get(); FFindOrCreateHandleResult HandleResult = FindOrCreateHandleToObject( Object ); FGuid ObjectHandle = HandleResult.Handle; bHandleCreated |= HandleResult.bWasCreated; if (ObjectHandle.IsValid()) { FFindOrCreateTrackResult TrackResult = FindOrCreateTrackForObject( ObjectHandle, UMovieScene3DAttachTrack::StaticClass()); UMovieSceneTrack* Track = TrackResult.Track; bTrackCreated |= TrackResult.bWasCreated; if (ensure(Track)) { // Clamp to next attach section's start time or the end of the current sequencer view range float AttachEndTime = GetSequencer()->GetViewRange().GetUpperBoundValue(); for (int32 AttachSectionIndex = 0; AttachSectionIndex < Track->GetAllSections().Num(); ++AttachSectionIndex) { float StartTime = Track->GetAllSections()[AttachSectionIndex]->GetStartTime(); float EndTime = Track->GetAllSections()[AttachSectionIndex]->GetEndTime(); if (KeyTime < StartTime) { if (AttachEndTime > StartTime) { AttachEndTime = StartTime; } } } Cast<UMovieScene3DAttachTrack>(Track)->AddConstraint( KeyTime, AttachEndTime, SocketName, ComponentName, ParentActorId ); bTrackModified = true; } } } return bHandleCreated || bTrackCreated || bTrackModified; }
FGuid FSequencer::GetHandleToObject( UObject* Object ) { TSharedRef<FMovieSceneInstance> FocusedMovieSceneInstance = GetFocusedMovieSceneInstance(); UMovieScene* FocusedMovieScene = FocusedMovieSceneInstance->GetMovieScene(); FGuid ObjectGuid = ObjectBindingManager->FindGuidForObject( *FocusedMovieScene, *Object ); if (ObjectGuid.IsValid()) { // Make sure that the possessable is still valid, if it's not remove the binding so new one // can be created. This can happen due to undo. FMovieScenePossessable* Possessable = FocusedMovieScene->FindPossessable(ObjectGuid); if (Possessable == nullptr ) { ObjectBindingManager->UnbindPossessableObjects(ObjectGuid); ObjectGuid.Invalidate(); } } bool bPossessableAdded = false; // If the object guid was not found attempt to add it // Note: Only possessed actors can be added like this if( !ObjectGuid.IsValid() && ObjectBindingManager->CanPossessObject( *Object ) ) { // @todo sequencer: Undo doesn't seem to be working at all const FScopedTransaction Transaction( LOCTEXT("UndoPossessingObject", "Possess Object with MovieScene") ); // Possess the object! { // Create a new possessable FocusedMovieScene->Modify(); ObjectGuid = FocusedMovieScene->AddPossessable( Object->GetName(), Object->GetClass() ); if ( IsShotFilteringOn() ) { AddUnfilterableObject(ObjectGuid); } ObjectBindingManager->BindPossessableObject( ObjectGuid, *Object ); bPossessableAdded = true; } } if( bPossessableAdded ) { SpawnOrDestroyPuppetObjects( GetFocusedMovieSceneInstance() ); NotifyMovieSceneDataChanged(); } return ObjectGuid; }
bool FParticleTrackEditor::AddKeyInternal( float KeyTime, const TArray<TWeakObjectPtr<UObject>> Objects ) { bool bHandleCreated = false; bool bTrackCreated = false; for( int32 ObjectIndex = 0; ObjectIndex < Objects.Num(); ++ObjectIndex ) { UObject* Object = Objects[ObjectIndex].Get(); FFindOrCreateHandleResult HandleResult = FindOrCreateHandleToObject( Object ); FGuid ObjectHandle = HandleResult.Handle; bHandleCreated |= HandleResult.bWasCreated; if (ObjectHandle.IsValid()) { FFindOrCreateTrackResult TrackResult = FindOrCreateTrackForObject(ObjectHandle, UMovieSceneParticleTrack::StaticClass()); UMovieSceneTrack* Track = TrackResult.Track; bTrackCreated |= TrackResult.bWasCreated; if (bTrackCreated && ensure(Track)) { UMovieSceneParticleTrack* ParticleTrack = Cast<UMovieSceneParticleTrack>(Track); ParticleTrack->AddNewSection(KeyTime); ParticleTrack->SetDisplayName(LOCTEXT("TrackName", "Particle System")); } } } return bHandleCreated || bTrackCreated; }
void FMarginTrackEditor::OnKeyMargin( float KeyTime, const FPropertyChangedParams* PropertyChangedParams ) { FMargin MarginValue = *PropertyChangedParams->GetPropertyValue<FMargin>(); FName PropertyName = PropertyChangedParams->PropertyPath.Last()->GetFName(); for( int32 ObjectIndex = 0; ObjectIndex < PropertyChangedParams->ObjectsThatChanged.Num(); ++ObjectIndex ) { UObject* Object = PropertyChangedParams->ObjectsThatChanged[ObjectIndex]; FMarginKey Key; Key.bAddKeyEvenIfUnchanged = !PropertyChangedParams->bRequireAutoKey; Key.CurveName = PropertyChangedParams->StructPropertyNameToKey; Key.Value = MarginValue; FGuid ObjectHandle = FindOrCreateHandleToObject( Object ); if (ObjectHandle.IsValid()) { UMovieSceneTrack* Track = GetTrackForObject( ObjectHandle, UMovieSceneMarginTrack::StaticClass(), PropertyName ); if( ensure( Track ) ) { UMovieSceneMarginTrack* MarginTrack = CastChecked<UMovieSceneMarginTrack>(Track); MarginTrack->SetPropertyNameAndPath( PropertyName, PropertyChangedParams->GetPropertyPathString() ); // Find or add a new section at the auto-key time and changing the property same property // AddKeyToSection is not actually a virtual, it's redefined in each class with a different type bool bSuccessfulAdd = MarginTrack->AddKeyToSection( KeyTime, Key ); if (bSuccessfulAdd) { MarginTrack->SetAsShowable(); } } } } }
UProperty* UUserDefinedStruct::CustomFindProperty(const FName Name) const { const FGuid Guid = FStructureEditorUtils::GetGuidFromPropertyName(Name); UProperty* Property = Guid.IsValid() ? FStructureEditorUtils::GetPropertyByGuid(this, Guid) : NULL; ensure(!Property || Guid == FStructureEditorUtils::GetGuidForProperty(Property)); return Property; }
void FMovieScene3DConstraintTrackInstance::Update( float Position, float LastPosition, const TArray<UObject*>& RuntimeObjects, class IMovieScenePlayer& Player, FMovieSceneSequenceInstance& SequenceInstance, EMovieSceneUpdatePass UpdatePass ) { UMovieScene3DConstraintSection* FirstConstraintSection = nullptr; const TArray<UMovieSceneSection*>& ConstraintSections = ConstraintTrack->GetAllSections(); for (int32 ConstraintIndex = 0; ConstraintIndex < ConstraintSections.Num(); ++ConstraintIndex) { UMovieScene3DConstraintSection* ConstraintSection = CastChecked<UMovieScene3DConstraintSection>(ConstraintSections[ConstraintIndex]); if (ConstraintSection->IsTimeWithinSection(Position) && (FirstConstraintSection == nullptr || FirstConstraintSection->GetRowIndex() > ConstraintSection->GetRowIndex())) { TArray<UObject*> ConstraintObjects; FGuid ConstraintId = ConstraintSection->GetConstraintId(); if (ConstraintId.IsValid()) { Player.GetRuntimeObjects( Player.GetRootMovieSceneSequenceInstance(), ConstraintId, ConstraintObjects); for (int32 ConstraintObjectIndex = 0; ConstraintObjectIndex < ConstraintObjects.Num(); ++ConstraintObjectIndex) { AActor* Actor = Cast<AActor>(ConstraintObjects[ConstraintObjectIndex]); if (Actor) { UpdateConstraint(Position, RuntimeObjects, Actor, ConstraintSection); } } } } } }
bool UMovieScene::RemoveSpawnable( const FGuid& Guid ) { bool bAnythingRemoved = false; if( ensure( Guid.IsValid() ) ) { for( auto SpawnableIter( Spawnables.CreateIterator() ); SpawnableIter; ++SpawnableIter ) { auto& CurSpawnable = *SpawnableIter; if( CurSpawnable.GetGuid() == Guid ) { Modify(); { UClass* GeneratedClass = CurSpawnable.GetClass(); UBlueprint* Blueprint = GeneratedClass ? Cast<UBlueprint>(GeneratedClass->ClassGeneratedBy) : NULL; check(NULL != Blueprint); // @todo sequencer: Also remove created Blueprint inner object. Is this sufficient? Needs to work with Undo too! Blueprint->ClearFlags( RF_Standalone ); // @todo sequencer: Probably not needed for Blueprint Blueprint->MarkPendingKill(); } RemoveObjectBinding( Guid ); // Found it! Spawnables.RemoveAt( SpawnableIter.GetIndex() ); bAnythingRemoved = true; break; } } } return bAnythingRemoved; }
void FProfilerClientManager::RequestLastCapturedFile( const FGuid& InstanceId /*= FGuid()*/ ) { #if STATS if (MessageEndpoint.IsValid() && ActiveSessionId.IsValid()) { if( !InstanceId.IsValid() ) { TArray<FMessageAddress> Instances; for (auto It = Connections.CreateConstIterator(); It; ++It) { Instances.Add(It.Value().ServiceAddress); } MessageEndpoint->Send(new FProfilerServiceRequest(EProfilerRequestType::PRT_SendLastCapturedFile), Instances); } else { const FMessageAddress* MessageAddress = &Connections.Find(InstanceId)->ServiceAddress; if( MessageAddress ) { MessageEndpoint->Send(new FProfilerServiceRequest(EProfilerRequestType::PRT_SendLastCapturedFile), *MessageAddress); } } } #endif }
FKeyPropertyResult FFaceFXAnimationTrackEditor::AddFaceFXSection(FFrameNumber KeyTime, UObject* Object, FFaceFXAnimComponentSet AnimCompSet) { FKeyPropertyResult result; bool bHandleCreated = false; bool bTrackCreated = false; bool bTrackModified = false; FFindOrCreateHandleResult HandleResult = FindOrCreateHandleToObject(Object); FGuid ObjectHandle = HandleResult.Handle; result.bHandleCreated |= HandleResult.bWasCreated; if (ObjectHandle.IsValid()) { FFindOrCreateTrackResult TrackResult = FindOrCreateTrackForObject(ObjectHandle, UFaceFXAnimationTrack::StaticClass()); UMovieSceneTrack* Track = TrackResult.Track; result.bTrackCreated |= TrackResult.bWasCreated; if (UFaceFXAnimationTrack* AnimTrack = Cast<UFaceFXAnimationTrack>(Track)) { AnimTrack->AddSection(KeyTime, AnimCompSet); result.bTrackModified = true; } } return result; }
void FProfilerClientManager::Subscribe( const FGuid& Session ) { #if STATS FGuid OldSessionId = ActiveSessionId; PendingSessionId = Session; if (MessageEndpoint.IsValid()) { if (OldSessionId.IsValid()) { TArray<FGuid> Instances; Connections.GenerateKeyArray(Instances); for (int32 i = 0; i < Instances.Num(); ++i) { MessageEndpoint->Publish(new FProfilerServiceUnsubscribe(OldSessionId, Instances[i]), EMessageScope::Network); // fire the disconnection delegate ProfilerClientDisconnectedDelegate.Broadcast(ActiveSessionId, Instances[i]); } ActiveSessionId.Invalidate(); } ActiveSessionId = PendingSessionId; } Connections.Reset(); #endif }
bool IsValid() const { return MagicNumber == TCP_MESSAGING_TRANSPORT_PROTOCOL_MAGIC && Version == ETcpMessagingVersion::OldestSupportedVersion && NodeId.IsValid(); }
void FProfilerActionManager::ToggleDataPreview_Execute( const FGuid SessionInstanceID ) { // One session instance if( SessionInstanceID.IsValid() ) { const FProfilerSessionRef* ProfilerSessionPtr = This->FindSessionInstance( SessionInstanceID ); if( ProfilerSessionPtr ) { (*ProfilerSessionPtr)->bDataPreviewing = !(*ProfilerSessionPtr)->bDataPreviewing; This->ProfilerClient->SetPreviewState( (*ProfilerSessionPtr)->bDataPreviewing, SessionInstanceID ); } const bool bDataPreviewing = This->IsDataPreviewing(); if( !bDataPreviewing ) { This->bLivePreview = false; } } // All session instances else { const bool bDataPreviewing = !This->IsDataPreviewing(); This->SetDataPreview( bDataPreviewing ); if( !bDataPreviewing ) { This->bLivePreview = false; } } }
void FProfilerClientManager::SetPreviewState( const bool bRequestedPreviewState, const FGuid& InstanceId /*= FGuid()*/ ) { #if STATS if (MessageEndpoint.IsValid() && ActiveSessionId.IsValid()) { if( !InstanceId.IsValid() ) { TArray<FMessageAddress> Instances; for (auto It = Connections.CreateConstIterator(); It; ++It) { Instances.Add(It.Value().ServiceAddress); } MessageEndpoint->Send(new FProfilerServicePreview(bRequestedPreviewState), Instances); } else { const FMessageAddress* MessageAddress = &Connections.Find(InstanceId)->ServiceAddress; if( MessageAddress ) { MessageEndpoint->Send(new FProfilerServicePreview(bRequestedPreviewState), *MessageAddress); } } } #endif }
void FCameraCutTrackEditor::HandleAddCameraCutComboButtonMenuEntryExecute(AActor* Camera) { FGuid ObjectGuid = FindOrCreateHandleToObject(Camera).Handle; if (ObjectGuid.IsValid()) { AnimatablePropertyChanged(FOnKeyProperty::CreateRaw(this, &FCameraCutTrackEditor::AddKeyInternal, ObjectGuid)); } }
void FUdpMessageProcessor::ProcessHelloSegment( FInboundSegment& Segment, FNodeInfo& NodeInfo ) { FGuid RemoteNodeId; *Segment.Data << RemoteNodeId; if (RemoteNodeId.IsValid()) { NodeInfo.ResetIfRestarted(RemoteNodeId); } }
void F3DPathTrackEditor::ActorSocketPicked(const FName SocketName, USceneComponent* Component, AActor* ParentActor, FGuid ObjectGuid, UMovieSceneSection* Section) { if (Section != nullptr) { const FScopedTransaction Transaction(LOCTEXT("UndoSetPath", "Set Path")); UMovieScene3DPathSection* PathSection = (UMovieScene3DPathSection*)(Section); FGuid SplineId = FindOrCreateHandleToObject(ParentActor).Handle; if (SplineId.IsValid()) { PathSection->SetConstraintId(SplineId); } } else if (ObjectGuid.IsValid()) { TArray<TWeakObjectPtr<UObject>> OutObjects; GetSequencer()->GetRuntimeObjects( GetSequencer()->GetFocusedMovieSceneSequenceInstance(), ObjectGuid, OutObjects); AnimatablePropertyChanged( FOnKeyProperty::CreateRaw( this, &F3DPathTrackEditor::AddKeyInternal, OutObjects, ParentActor) ); } }
void FUdpMessageProcessor::ProcessByeSegment( FInboundSegment& Segment, FNodeInfo& NodeInfo ) { FGuid RemoteNodeId; *Segment.Data << RemoteNodeId; if (RemoteNodeId.IsValid()) { if (NodeInfo.NodeId == RemoteNodeId) { RemoveKnownNode(RemoteNodeId); } } }
bool FProfilerActionManager::ToggleShowDataGraph_CanExecute( const FGuid SessionInstanceID ) const { // One session instance if( SessionInstanceID.IsValid() ) { const bool bIsSessionInstanceValid = This->IsSessionInstanceValid( SessionInstanceID ); return bIsSessionInstanceValid; } // All session instances else { return false; } }
ECheckBoxState FProfilerActionManager::ToggleShowDataGraph_GetCheckState( const FGuid SessionInstanceID ) const { // One session instance if( SessionInstanceID.IsValid() ) { const bool bIsSessionInstanceTracked = This->IsSessionInstanceTracked( SessionInstanceID ); return bIsSessionInstanceTracked ? ECheckBoxState::Checked : ECheckBoxState::Unchecked; } // All session instances else { return ECheckBoxState::Unchecked; } }
bool FProfilerActionManager::ToggleShowDataGraph_IsActionButtonVisible( const FGuid SessionInstanceID ) const { // One session instance if( SessionInstanceID.IsValid() ) { return true; } // All session instances else { // Hiding all graphs for all session instances as it doesn't add any useful functionality return false; } }
void F3DAttachTrackEditor::ActorSocketPicked(const FName SocketName, AActor* ParentActor, FGuid ObjectGuid, UMovieSceneSection* Section) { if (ObjectGuid.IsValid()) { TArray<UObject*> OutObjects; GetSequencer()->GetRuntimeObjects( GetSequencer()->GetFocusedMovieSceneSequenceInstance(), ObjectGuid, OutObjects); AnimatablePropertyChanged( FOnKeyProperty::CreateRaw( this, &F3DAttachTrackEditor::AddKeyInternal, OutObjects, SocketName, ParentActor) ); } else if (Section != nullptr) { const FScopedTransaction Transaction(LOCTEXT("UndoSetAttach", "Set Attach")); UMovieScene3DAttachSection* AttachSection = (UMovieScene3DAttachSection*)(Section); FGuid ActorId = FindOrCreateHandleToObject(ParentActor).Handle; if (ActorId.IsValid()) { AttachSection->SetConstraintId(ActorId); AttachSection->AttachSocketName = SocketName; } } }
bool FProfilerActionManager::ToggleDataPreview_CanExecute( const FGuid SessionInstanceID ) const { // One session instance if( SessionInstanceID.IsValid() ) { const bool bIsSessionInstanceValid = This->IsSessionInstanceValid( SessionInstanceID ) && This->ProfilerType == EProfilerSessionTypes::Live; return bIsSessionInstanceValid; } // All session instances else { const bool bCanExecute = This->ActiveSession.IsValid() && This->ProfilerType == EProfilerSessionTypes::Live && This->GetProfilerInstancesNum() > 0; return bCanExecute; } }
const FString FBuildPatchUtils::GetDataTypeOldFilename( const FBuildPatchData::Type DataType, const FString& RootDirectory, const FGuid& Guid ) { check( Guid.IsValid() ); switch ( DataType ) { case FBuildPatchData::ChunkData: return GetChunkOldFilename( RootDirectory, Guid ); case FBuildPatchData::FileData: return GetFileOldFilename( RootDirectory, Guid ); } // Error, didn't case type check( false ); return TEXT( "" ); }
void FProfilerActionManager::ToggleShowDataGraph_Execute( const FGuid SessionInstanceID ) { // One session instance if( SessionInstanceID.IsValid() ) { const bool bIsSessionInstanceTracked = This->IsSessionInstanceTracked( SessionInstanceID ); if( bIsSessionInstanceTracked ) { This->UntrackSessionInstance( SessionInstanceID ); } else { This->TrackSessionInstance( SessionInstanceID ); } } }
void FParticleTrackEditor::AddKeyInternal( float KeyTime, const TArray<UObject*> Objects, bool bTrigger) { for( int32 ObjectIndex = 0; ObjectIndex < Objects.Num(); ++ObjectIndex ) { UObject* Object = Objects[ObjectIndex]; FGuid ObjectHandle = FindOrCreateHandleToObject( Object ); if (ObjectHandle.IsValid()) { UMovieSceneTrack* Track = GetTrackForObject( ObjectHandle, UMovieSceneParticleTrack::StaticClass(), FName("ParticleSystem")); if (ensure(Track)) { Cast<UMovieSceneParticleTrack>(Track)->AddNewParticleSystem( KeyTime, bTrigger ); } } } }
void FAnimationTrackEditor::AddKeyInternal( float KeyTime, const TArray<UObject*> Objects, class UAnimSequence* AnimSequence ) { for( int32 ObjectIndex = 0; ObjectIndex < Objects.Num(); ++ObjectIndex ) { UObject* Object = Objects[ObjectIndex]; FGuid ObjectHandle = FindOrCreateHandleToObject( Object ); if (ObjectHandle.IsValid()) { UMovieSceneTrack* Track = GetTrackForObject( ObjectHandle, UMovieSceneAnimationTrack::StaticClass(), FName("Animation")); if (ensure(Track)) { Cast<UMovieSceneAnimationTrack>(Track)->AddNewAnimation( KeyTime, AnimSequence ); } } } }
void FSequencerObjectBindingNode::HandleLabelsSubMenuCreate(FMenuBuilder& MenuBuilder) { const TSet< TSharedRef<FSequencerDisplayNode> >& SelectedNodes = GetSequencer().GetSelection().GetSelectedOutlinerNodes(); TArray<FGuid> ObjectBindingIds; for (TSharedRef<const FSequencerDisplayNode> SelectedNode : SelectedNodes ) { if (SelectedNode->GetType() == ESequencerNode::Object) { TSharedRef<const FSequencerObjectBindingNode> ObjectBindingNode = StaticCastSharedRef<const FSequencerObjectBindingNode>(SelectedNode); FGuid ObjectBindingId = ObjectBindingNode->GetObjectBinding(); if (ObjectBindingId.IsValid()) { ObjectBindingIds.Add(ObjectBindingId); } } } MenuBuilder.AddWidget(SNew(SSequencerLabelEditor, GetSequencer(), ObjectBindingIds), FText::GetEmpty(), true); }
bool F3DPathTrackEditor::IsActorPickable(const AActor* const ParentActor, FGuid ObjectBinding, UMovieSceneSection* InSection) { // Can't pick the object that this track binds TArray<TWeakObjectPtr<UObject>> OutObjects; GetSequencer()->GetRuntimeObjects( GetSequencer()->GetFocusedMovieSceneSequenceInstance(), ObjectBinding, OutObjects); if (OutObjects.Contains(ParentActor)) { return false; } // Can't pick the object that this track attaches to UMovieScene3DPathSection* PathSection = Cast<UMovieScene3DPathSection>(InSection); if (PathSection != nullptr) { FGuid ConstraintId = PathSection->GetConstraintId(); if (ConstraintId.IsValid()) { TArray<TWeakObjectPtr<UObject>> ConstraintObjects; GetSequencer()->GetRuntimeObjects( GetSequencer()->GetFocusedMovieSceneSequenceInstance(), ConstraintId, ConstraintObjects); if (ConstraintObjects.Contains(ParentActor)) { return false; } } } if (ParentActor->IsListedInSceneOutliner() && !FActorEditorUtils::IsABuilderBrush(ParentActor) && !ParentActor->IsA( AWorldSettings::StaticClass() ) && !ParentActor->IsPendingKill()) { TArray<USplineComponent*> SplineComponents; ParentActor->GetComponents(SplineComponents); if (SplineComponents.Num()) { return true; } } return false; }
ECheckBoxState FProfilerActionManager::ToggleDataPreview_GetCheckState( const FGuid SessionInstanceID ) const { // One session instance if( SessionInstanceID.IsValid() ) { const FProfilerSessionRef* ProfilerSessionPtr = This->FindSessionInstance( SessionInstanceID ); if( ProfilerSessionPtr ) { return (*ProfilerSessionPtr)->bDataPreviewing ? ECheckBoxState::Checked : ECheckBoxState::Unchecked; } else { return ECheckBoxState::Unchecked; } } // All session instances else { const bool bDataPreview = This->IsDataPreviewing(); return bDataPreview ? ECheckBoxState::Checked : ECheckBoxState::Unchecked; } }
TSharedRef<SWidget> FWidgetBlueprintEditor::OnGetAnimationAddMenuContent(TSharedRef<ISequencer> InSequencer) { TArray<FObjectAndDisplayName> BindableObjects; { GetBindableObjects(GetPreview()->GetRootWidget(), BindableObjects); BindableObjects.Sort(); } FMenuBuilder AddMenuBuilder(true, nullptr); for (FObjectAndDisplayName& BindableObject : BindableObjects) { FGuid BoundObjectGuid = SequencerObjectBindingManager->FindGuidForObject(*InSequencer->GetFocusedMovieScene(), *BindableObject.Object); if (!BoundObjectGuid.IsValid()) { FUIAction AddMenuAction(FExecuteAction::CreateSP(this, &FWidgetBlueprintEditor::AddObjectToAnimation, BindableObject.Object)); AddMenuBuilder.AddMenuEntry(BindableObject.DisplayName, FText(), FSlateIcon(), AddMenuAction); } } return AddMenuBuilder.MakeWidget(); }