// Copyright Epic Games, Inc. All Rights Reserved. #include "LiveLinkHubMessages.h" #include "Engine/Engine.h" #include "Engine/SystemTimeTimecodeProvider.h" #include "Engine/World.h" #include "Features/IModularFeatures.h" #include "ILiveLinkClient.h" #include "ILiveLinkModule.h" const FName UE::LiveLinkHub::Private::LiveLinkHubProviderType = TEXT("LiveLinkHub"); FName FLiveLinkHubMessageAnnotation::ProviderTypeAnnotation = TEXT("ProviderType"); FName FLiveLinkHubMessageAnnotation::AutoConnectModeAnnotation = TEXT("AutoConnect"); FName FLiveLinkHubMessageAnnotation::IdAnnotation = TEXT("Id"); DEFINE_LOG_CATEGORY_STATIC(LogLiveLinkHubMessages, Log, All); namespace UE::LiveLinkHubMessages::Private { TOptional FindSubjectKey(ILiveLinkClient* LiveLinkClient, FName SubjectName) { TArray Subjects = LiveLinkClient->GetSubjects(true, true); // We need to map the named subject to the list of subject keys available. for (const FLiveLinkSubjectKey& Key : Subjects) { if (Key.SubjectName == SubjectName) { return Key; } } return {}; } } void FLiveLinkHubCustomTimeStepSettings::AssignCustomTimeStepToEngine() const { IModularFeatures& ModularFeatures = IModularFeatures::Get(); if (!ModularFeatures.IsModularFeatureAvailable(ILiveLinkClient::ModularFeatureName)) { return; } if (GEngine == nullptr) { return; } if (bResetCustomTimeStep) { UEngineCustomTimeStep* CurrentCustomTimeStep = GEngine->GetCustomTimeStep(); if (Cast(CurrentCustomTimeStep)) { UE_LOG(LogLiveLinkHubMessages, Display, TEXT("CustomTimeStep reset event")); // We only issue a timestep reset if we are a LiveLinkHubCustomTimeStep. This way we don't reset any custom time step that the user // may have set in the editor. GEngine->Exec(GEngine->GetCurrentPlayWorld(nullptr), TEXT("CustomTimeStep.reset")); } return; } UE_LOG(LogLiveLinkHubMessages, Display, TEXT("CustomTimeStep change event %s - %s"), *SubjectName.ToString(), *CustomTimeStepRate.ToPrettyText().ToString()); ILiveLinkClient* LiveLinkClient = &ModularFeatures.GetModularFeature(ILiveLinkClient::ModularFeatureName); ULiveLinkHubCustomTimeStep* NewCustomTimeStep = NewObject(GEngine, ULiveLinkHubCustomTimeStep::StaticClass()); NewCustomTimeStep->LiveLinkDataRate = CustomTimeStepRate; NewCustomTimeStep->bLockStepMode = bLockStepMode; NewCustomTimeStep->FrameRateDivider = FrameRateDivider; if (TOptional Target = UE::LiveLinkHubMessages::Private::FindSubjectKey(LiveLinkClient, SubjectName)) { NewCustomTimeStep->SubjectKey = *Target; } else { // Note: We must set the subject name because the livelink custom time step will use it to try to match new subjects being added. NewCustomTimeStep->SubjectKey = FLiveLinkSubjectKey{FGuid(), SubjectName}; } // Override the custom timestep for the engine. GEngine->SetCustomTimeStep(NewCustomTimeStep); } void FLiveLinkHubTimecodeSettings::AssignTimecodeSettingsAsProviderToEngine() const { IModularFeatures& ModularFeatures = IModularFeatures::Get(); if (!ModularFeatures.IsModularFeatureAvailable(ILiveLinkClient::ModularFeatureName) || GEngine == nullptr) { return; } ILiveLinkClient* LiveLinkClient = &ModularFeatures.GetModularFeature(ILiveLinkClient::ModularFeatureName); UE_LOG(LogLiveLinkHubMessages, Display, TEXT("Time code change event %s - %s"), *UEnum::GetValueAsName(Source).ToString(), *SubjectName.ToString()); if (Source == ELiveLinkHubTimecodeSource::SystemTimeEditor) { // If we are using system time, construct a new system time code provider with the target framerate. FName ObjectName = MakeUniqueObjectName(GEngine, USystemTimeTimecodeProvider::StaticClass(), "DefaultTimecodeProvider"); USystemTimeTimecodeProvider* NewTimecodeProvider = NewObject(GEngine, ObjectName); NewTimecodeProvider->FrameRate = DesiredFrameRate; NewTimecodeProvider->FrameDelay = FrameDelay; GEngine->SetTimecodeProvider(NewTimecodeProvider); UE_LOG(LogLiveLinkHubMessages, Display, TEXT("System Time Timecode provider set.")); } else if (Source == ELiveLinkHubTimecodeSource::UseSubjectName) { TOptional Target = UE::LiveLinkHubMessages::Private::FindSubjectKey(LiveLinkClient, SubjectName); if (Target) { FName ObjectName = MakeUniqueObjectName(GEngine, ULiveLinkTimecodeProvider::StaticClass(), "DefaultLiveLinkTimecodeProvider"); ULiveLinkTimecodeProvider* LiveLinkProvider = NewObject(GEngine, ObjectName); LiveLinkProvider->SetTargetSubjectKey(*Target); LiveLinkProvider->OverrideFrameRate = DesiredFrameRate; LiveLinkProvider->FrameDelay = FrameDelay; LiveLinkProvider->BufferSize = BufferSize; GEngine->SetTimecodeProvider(LiveLinkProvider); UE_LOG(LogLiveLinkHubMessages, Display, TEXT("Live Link Timecode provider assigned to %s."), *SubjectName.ToString()); } else { UE_LOG(LogLiveLinkHubMessages, Warning, TEXT("Failed to assign Live Link Timecode provider to %s."), *SubjectName.ToString()); } } else { // Force the timecode provider to reset back to the default setting. GEngine->Exec( GEngine->GetCurrentPlayWorld(nullptr), TEXT( "TimecodeProvider.reset" ) ); } }