// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "MovieSceneFwd.h" #include "Delegates/Delegate.h" #include "Containers/List.h" namespace UE { namespace MovieScene { struct FDataEventScope { FSimpleMulticastDelegate OnBracketClosed; MOVIESCENE_API FDataEventScope(); MOVIESCENE_API ~FDataEventScope(); }; template class TIntrusiveEventHandler : public TIntrusiveLinkedList>, public T { protected: virtual ~TIntrusiveEventHandler() { this->Unlink(); } }; template struct TNonIntrusiveEventHandler : public TLinkedList { TNonIntrusiveEventHandler() {} TNonIntrusiveEventHandler(T* InInstance) : TLinkedList(InInstance) {} ~TNonIntrusiveEventHandler() { this->Unlink(); } }; template struct TDataEventContainer { #if UE_MOVIESCENE_EVENTS ~TDataEventContainer() { if (IntrusiveHandlers) { IntrusiveHandlers->Unlink(); } if (NonIntrusiveHandlers) { NonIntrusiveHandlers->Unlink(); } } template void Trigger(FuncType&& Func, ArgTypes&&... Args) const { for (typename TIntrusiveLinkedList>::TIterator It(IntrusiveHandlers); It; ) { TIntrusiveEventHandler& Current = *It; // Increment before invoking to ensure that removals inside the invocation do not cause the iteration to return prematurely ++It; Invoke(Func, Current, Forward(Args)...); } for (typename TNonIntrusiveEventHandler::TIterator It(NonIntrusiveHandlers); It; ) { EventInterface* Current = *It; // Increment before invoking to ensure that removals inside the invocation do not cause the iteration to return prematurely ++It; Invoke(Func, Current, Forward(Args)...); } } void Link(TIntrusiveEventHandler* InLink) const { check(!InLink->IsLinked()); InLink->LinkHead(IntrusiveHandlers); } void Link(TNonIntrusiveEventHandler& InLink, EventInterface* Instance) const { check(!InLink.IsLinked()); InLink = TNonIntrusiveEventHandler(Instance); InLink.LinkHead(NonIntrusiveHandlers); } private: mutable TIntrusiveEventHandler* IntrusiveHandlers = nullptr; mutable TLinkedList* NonIntrusiveHandlers = nullptr; #else template void Trigger(ArgTypes&&...) const {} #endif }; } // namespace MovieScene } // namespace UE