// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "CoreMinimal.h" #include "IMessageContext.h" #include "LiveLinkMessages.h" #include "LiveLinkProvider.h" #include "MessageEndpoint.h" PRAGMA_DISABLE_DEPRECATION_WARNINGS // Subject that the application has told us about struct FTrackedSubject { // Ref skeleton to go with transform data FLiveLinkRefSkeleton RefSkeleton; // Bone transform data TArray Transforms; // Curve data TArray Curves; // MetaData for subject FLiveLinkMetaData MetaData; // Incrementing time (application time) for interpolation purposes double Time; }; PRAGMA_ENABLE_DEPRECATION_WARNINGS struct LIVELINKMESSAGEBUSFRAMEWORK_API FLiveLinkProvider : public ILiveLinkProvider { private: const FString ProviderName; const FString MachineName; TSharedPtr MessageEndpoint; // Lock to stop multiple threads accessing the CurrentPreset at the same time mutable FCriticalSection CriticalSection; // Array of our current connections TArray ConnectedAddresses; // Cache of our current subject state TArray StaticDatas; TArray FrameDatas; TMap Subjects; // Delegate to notify interested parties when the client sources have changed FLiveLinkProviderConnectionStatusChanged OnConnectionStatusChanged; private: //Message bus message handlers void HandlePingMessage(const FLiveLinkPingMessage& Message, const TSharedRef& Context); void HandleHeartbeat(const FLiveLinkHeartbeatMessage& Message, const TSharedRef& Context); // End message bus message handlers FTrackedSubject& GetTrackedSubject(const FName& SubjectName); void SendSubject(FName SubjectName, const struct FTrackedSubject& Subject); void SendSubjectFrame(FName SubjectName, const struct FTrackedSubject& Subject); // Get the cached data for the named subject FTrackedStaticData* GetLastSubjectStaticData(const FName& SubjectName); FTrackedFrameData* GetLastSubjectFrameData(const FName& SubjectName); void SetLastSubjectStaticData(FName SubjectName, TSubclassOf Role, FLiveLinkStaticDataStruct&& StaticData, TMap&& Annotations); void SetLastSubjectFrameData(FName SubjectName, FLiveLinkFrameDataStruct&& FrameData, TMap&& SubjectAnnotations); // Clear a existing track subject void ClearTrackedSubject(const FName& SubjectName); // Get the connected addresses that should receive livelink data. void GetFilteredAddresses(FName SubjectName, TArray& Addresses); // Serialize animation frame data into a compressed payload to reduce throughput. struct FLiveLinkSerializedFrameData SerializeAnimationData(struct FLiveLinkAnimationFrameData* AnimData); protected: // Update connected addresses and send information to the connected source void HandleConnectMessage(const FLiveLinkConnectMessage& Message, const TSharedRef& Context); // Create the message bus message endoing responsble for dispatching message bus messages to their respective handlers void CreateMessageEndpoint(struct FMessageEndpointBuilder& EndpointBuilder); // Get the addresses of all connected instances. void GetConnectedAddresses(TArray& Addresses); // Validate our current connections, removing those that have timed out. void ValidateConnections(); // Close a connection using its address. void CloseConnection(FMessageAddress Address); // Get the cached data struct for a subject TPair GetLastSubjectStaticDataStruct(FName SubjectName); template void SendMessage(MessageType* Message, EMessageFlags Flags = EMessageFlags::None) { if (!Message) { return; } TArray Addresses; GetConnectedAddresses(Addresses); if (Addresses.Num() != 0) { MessageEndpoint->Send(Message, Flags, {}, nullptr, Addresses, FTimespan::Zero(), FDateTime::MaxValue()); } } template void SendMessage(MessageType* Message, const FMessageAddress& Address, EMessageFlags Flags = EMessageFlags::None) { if (!Message || !Address.IsValid()) { return; } MessageEndpoint->Send(Message, Flags, {}, nullptr, { Address }, FTimespan::Zero(), FDateTime::MaxValue()); } template void SendMessage(MessageType* Message, const TArray& Addresses, EMessageFlags Flags = EMessageFlags::None) { if (!Message || !Addresses.Num()) { return; } MessageEndpoint->Send(Message, Flags, {}, nullptr, Addresses, FTimespan::Zero(), FDateTime::MaxValue()); } template void Publish(MessageType* Message) { if (!Message) { return; } MessageEndpoint->Publish(Message); } template void Subscribe() { if (MessageEndpoint.IsValid()) { MessageEndpoint->Subscribe(); } } const FString& GetProviderName() const { return ProviderName; } const FString& GetMachineName() const { return MachineName; } // Called after ValidateConnections removes invalid connections virtual void OnConnectionsClosed(const TArray& ClosedAddresses) {} // Get annotations to include on every message sent by this provider virtual TMap GetAnnotations() const { #if WITH_ENGINE // When running a game/editor, mark this provider as an unreal client. FString TopologyModeValue = StaticEnum()->GetNameStringByValue(static_cast(ELiveLinkTopologyMode::UnrealClient)); return { {FLiveLinkMessageAnnotation::TopologyModeAnnotation, MoveTemp(TopologyModeValue)} }; #endif return {}; } // Get whether a combination of a subject/client should receive livelink data. virtual bool ShouldTransmitToSubject_AnyThread(FName SubjectName, FMessageAddress Address) const { return true; } // Send a clear subject message to indicate that the subject should be removed from the connected client. void SendClearSubjectToConnections(FName SubjectName); // Get the MessageBus address of the provider. FMessageAddress GetEndpointAddress() const; // Constructor for derived classes that allows specifying that no endpoint should be created. FLiveLinkProvider(const FString& InProviderName, bool bInCreateEndpoint); public: FLiveLinkProvider(const FString& InProviderName); FLiveLinkProvider(const FString& InProviderName, struct FMessageEndpointBuilder&& EndpointBuilder); virtual ~FLiveLinkProvider() override; virtual void UpdateSubject(const FName& SubjectName, const TArray& BoneNames, const TArray& BoneParents); virtual bool UpdateSubjectStaticData(const FName SubjectName, TSubclassOf Role, FLiveLinkStaticDataStruct&& StaticData, const TMap& ExtraAnnotations = {}) override; virtual void ClearSubject(const FName& SubjectName); virtual void RemoveSubject(const FName SubjectName) override; PRAGMA_DISABLE_DEPRECATION_WARNINGS virtual void UpdateSubjectFrame(const FName& SubjectName, const TArray& BoneTransforms, const TArray& CurveData, double Time); virtual void UpdateSubjectFrame(const FName& SubjectName, const TArray& BoneTransforms, const TArray& CurveData, const FLiveLinkMetaData& MetaData, double Time); PRAGMA_ENABLE_DEPRECATION_WARNINGS virtual bool UpdateSubjectFrameData(const FName SubjectName, FLiveLinkFrameDataStruct&& FrameData, const TMap& ExtraAnnotations = {}) override; virtual bool HasConnection() const override; virtual FDelegateHandle RegisterConnStatusChangedHandle(const FLiveLinkProviderConnectionStatusChanged::FDelegate& ConnStatusChanged) override; virtual void UnregisterConnStatusChangedHandle(FDelegateHandle Handle) override; };