/** * Checks to see if any functions are bound to this multi-cast delegate * * @return True if any functions are bound */ inlinebool IsBound() const { UE_DELEGATES_MT_SCOPED_READ_ACCESS(AccessDetector);
return InvocationList.Num() > 0; }
/** * Checks whether a function delegate is already a member of this multi-cast delegate's invocation list * * @param InDelegate Delegate to check * @return True if the delegate is already in the list. */ boolContains( const TScriptDelegate<TWeakPtr>& InDelegate )const { UE_DELEGATES_MT_SCOPED_READ_ACCESS(AccessDetector);
return InvocationList.Contains( InDelegate ); }
/** * Checks whether a function delegate is already a member of this multi-cast delegate's invocation list * * @param InObject Object of the delegate to check * @param InFunctionName Function name of the delegate to check * @return True if the delegate is already in the list. */ boolContains( const UObject* InObject, FName InFunctionName )const { UE_DELEGATES_MT_SCOPED_READ_ACCESS(AccessDetector);
/** * Adds a function delegate to this multi-cast delegate's invocation list * * @param InDelegate Delegate to add */ voidAdd( const TScriptDelegate<TWeakPtr>& InDelegate ) { UE_DELEGATES_MT_SCOPED_WRITE_ACCESS(AccessDetector);
// First check for any objects that may have expired CompactInvocationList();
// Add the delegate AddInternal( InDelegate ); }
/** * Adds a function delegate to this multi-cast delegate's invocation list if a delegate with the same signature * doesn't already exist in the invocation list * * @param InDelegate Delegate to add */ voidAddUnique( const TScriptDelegate<TWeakPtr>& InDelegate ) { UE_DELEGATES_MT_SCOPED_WRITE_ACCESS(AccessDetector);
// Add the delegate, if possible AddUniqueInternal( InDelegate );
// Then check for any objects that may have expired CompactInvocationList(); }
/** * Removes a function from this multi-cast delegate's invocation list (performance is O(N)). Note that the * order of the delegates may not be preserved! * * @param InDelegate Delegate to remove */ voidRemove( const TScriptDelegate<TWeakPtr>& InDelegate ) { UE_DELEGATES_MT_SCOPED_WRITE_ACCESS(AccessDetector);
// Remove the delegate RemoveInternal( InDelegate );
// Check for any delegates that may have expired CompactInvocationList(); }
/** * Removes a function from this multi-cast delegate's invocation list (performance is O(N)). Note that the * order of the delegates may not be preserved! * * @param InObject Object of the delegate to remove * @param InFunctionName Function name of the delegate to remove */ voidRemove( const UObject* InObject, FName InFunctionName ) { UE_DELEGATES_MT_SCOPED_WRITE_ACCESS(AccessDetector);
// Remove the delegate RemoveInternal( InObject, InFunctionName );
// Check for any delegates that may have expired CompactInvocationList(); }
/** * Removes all delegate bindings from this multicast delegate's * invocation list that are bound to the specified object. * * This method also compacts the invocation list. * * @param InObject The object to remove bindings for. */ voidRemoveAll(const UObject* Object) { UE_DELEGATES_MT_SCOPED_WRITE_ACCESS(AccessDetector);
if (Binding.IsBoundToObject(Object) || Binding.IsCompactable()) { InvocationList.RemoveAtSwap(BindingIndex); } } }
/** * Removes all functions from this delegate's invocation list */ voidClear() { UE_DELEGATES_MT_SCOPED_WRITE_ACCESS(AccessDetector);
InvocationList.Empty(); }
/** * Converts this delegate to a string representation * * @return Delegate in string format */ template <typename UObjectTemplate> inline FString ToString()const { UE_DELEGATES_MT_SCOPED_READ_ACCESS(AccessDetector);
if (UnderlyingArchive.IsSaving()) { // When saving the delegate, clean up the list to make sure there are no bad object references D.CompactInvocationList(); }
Slot << D.InvocationList;
if (UnderlyingArchive.IsLoading()) { // After loading the delegate, clean up the list to make sure there are no bad object references D.CompactInvocationList(); } }
/** * Executes a multi-cast delegate by calling all functions on objects bound to the delegate. Always * safe to call, even if when no objects are bound, or if objects have expired. In general, you should * never call this function directly. Instead, call Broadcast() on a derived class. * * @param Params Parameter structure */ template <classUObjectTemplate> voidProcessMulticastDelegate(void* Parameters) const { UE_DELEGATES_MT_SCOPED_WRITE_ACCESS(AccessDetector);
if( InvocationList.Num() > 0 ) { // Create a copy of the invocation list, just in case the list is modified by one of the callbacks during the broadcast typedef TArray< TScriptDelegate<TWeakPtr>, TInlineAllocator< 4 > > FInlineInvocationList; FInlineInvocationList InvocationListCopy = FInlineInvocationList(InvocationList); // Invoke each bound function for( typename FInlineInvocationList::TConstIterator FunctionIt( InvocationListCopy ); FunctionIt; ++FunctionIt ) { if( FunctionIt->IsBound() ) { // Invoke this delegate! FunctionIt->template ProcessDelegate<UObjectTemplate>(Parameters); } elseif ( FunctionIt->IsCompactable() ) { // Function couldn't be executed, so remove it. Note that because the original list could have been modified by one of the callbacks, we have to search for the function to remove here. RemoveInternal( *FunctionIt ); } } } }
classFTestDelegate:public TBaseDynamicMulticastDelegate<FWeakObjectPtr, __VA_ARGS__> \ { \ public: \ /** Default constructor */ \ FTestDelegate() \ { \ } \ \ /** Construction from an FMulticastScriptDelegate must be explicit. This is really only used by UObject system internals. */ \ explicit FTestDelegate( const TMulticastScriptDelegate<>& InMulticastScriptDelegate ) \ : TBaseDynamicMulticastDelegate<TWeakPtr, __VA_ARGS__>( InMulticastScriptDelegate ) \ { \ } \ \ /** Broadcasts this delegate to all bound objects, except to those that may have expired */ \ void Broadcast( FuncParamList ) const \ { \ FTestDelegate_DelegateWrapper( FUNC_CONCAT( *this ) ); \ } \ };
classFTestDelegate:public TBaseDynamicMulticastDelegate<FWeakObjectPtr, *this> \ { \ public: \ /** Default constructor */ \ FTestDelegate() \ { \ } \ \ /** Construction from an FMulticastScriptDelegate must be explicit. This is really only used by UObject system internals. */ \ explicit FTestDelegate( const TMulticastScriptDelegate<>& InMulticastScriptDelegate ) \ : TBaseDynamicMulticastDelegate<TWeakPtr, __VA_ARGS__>( InMulticastScriptDelegate ) \ { \ } \ \ /** Broadcasts this delegate to all bound objects, except to those that may have expired */ \ void Broadcast( ) const \ { \ FTestDelegate_DelegateWrapper( *this ); \ } \ };