81 using FDelegate = TDelegate<FunctionSignature, FDefaultDelegateUserPolicy>;
85 TTuple<std::decay_t<Args>...>,
92 bHasBroadcasted =
true;
98 MulticastDelegate.Broadcast(Forward<Args>(args)...);
100 for (
const FDelegateHandle& handle : OnlyNextDelegates)
101 MulticastDelegate.Remove(handle);
103 OnlyNextDelegates.Empty();
115 template <
typename... OptionalObject>
requires (
sizeof...(OptionalObject) <= 1)
118 return From(Forward<OptionalObject>(
object)..., &TEventDelegate::Broadcast);
135 return AddInternal(delegate, invokeMode);
142 template <CSameAs<FDelegate>... Delegates>
153 template <CSameAs<FDelegate>... Delegates>
156 WithHelper(Add(delegates)...);
170 template <CDynamicDelegate DynamicDelegateType>
174 return AddInternal(
AsNative(dynamicDelegate), invokeMode, FDelegateHandle(), dynamicDelegate.GetUObject(), dynamicDelegate.GetFunctionName());
190 template <CDynamicDelegate DynamicDelegateType>
194 return AddUniqueInternal(
AsNative(dynamicDelegate), invokeMode, dynamicDelegate.GetUObject(), dynamicDelegate.GetFunctionName());
198 bool RemoveInternal(
const FDelegateHandle& delegateHandle)
200 const bool result = MulticastDelegate.Remove(delegateHandle);
202 if (
const FBoundUFunction* key = BoundUFunctionsMap.FindKey(delegateHandle))
203 BoundUFunctionsMap.Remove(*key);
205 OnlyNextDelegates.Remove(delegateHandle);
218 bool Remove(
const FDelegateHandle& delegateHandle)
221 return RemoveInternal(delegateHandle);
231 template <
class DynamicDelegateType>
232 bool Remove(
const DynamicDelegateType& dynamicDelegate)
235 FDelegateHandle delegateHandle;
236 if (BoundUFunctionsMap.RemoveAndCopyValue(FBoundUFunction(dynamicDelegate.GetUObject(), dynamicDelegate.GetFunctionName()), delegateHandle))
237 return RemoveInternal(delegateHandle);
252 for (
auto it = BoundUFunctionsMap.CreateIterator(); it; ++it)
253 if (!it.Key().Key.IsValid() || it.Key().Key.Get() == inUserObject)
256 return MulticastDelegate.RemoveAll(inUserObject);
263 MulticastDelegate.Clear();
264 OnlyNextDelegates.Reset();
265 BoundUFunctionsMap.Reset();
266 bHasBroadcasted =
false;
273 return bHasBroadcasted;
278 FDelegateHandle AddUniqueInternal(
281 const UObject* boundObject,
282 const FName& boundFunctionName
284 FDelegateHandle uniqueHandle;
286 if (
const FDelegateHandle* delegateHandle = BoundUFunctionsMap.Find(FBoundUFunction(boundObject, boundFunctionName)))
287 uniqueHandle = *delegateHandle;
289 return AddInternal(delegate, invokeMode, uniqueHandle, boundObject, boundFunctionName);
292 FDelegateHandle AddInternal(
295 FDelegateHandle
const& uniqueHandle = FDelegateHandle(),
296 const UObject* boundObject =
nullptr,
297 FName
const& boundFunctionName = NAME_None
299 const int32 actualInvokeMode = invokeMode ==
DefaultInvocation ? DefaultInvokeMode : invokeMode;
303 CallBelated(delegate);
304 return FDelegateHandle();
307 FDelegateHandle outputHandle = uniqueHandle;
308 if (!outputHandle.IsValid())
310 outputHandle = MulticastDelegate.Add(delegate);
312 if (boundObject && boundFunctionName != NAME_None)
313 BoundUFunctionsMap.Add(FBoundUFunction(boundObject, boundFunctionName), outputHandle);
316 OnlyNextDelegates.Add(outputHandle);
320 CallBelated(delegate);
325 void CallBelated(FDelegate& delegate)
330 using FBoundUFunction = TPair<TWeakObjectPtr<const UObject>, FName>;
332 bool bHasBroadcasted =
false;
334 TSet<FDelegateHandle> OnlyNextDelegates;
335 TMap<FBoundUFunction, FDelegateHandle> BoundUFunctionsMap;
336 TOptional<ArgumentsCache> Cache;
337 TMulticastDelegate<void(Args...), FDefaultDelegateUserPolicy> MulticastDelegate;