Files
UnrealEngine/Engine/Plugins/Animation/LiveLinkHub/Source/LiveLinkHubMessaging/Private/LiveLinkHubMessages.cpp
2025-05-18 13:04:45 +08:00

137 lines
5.2 KiB
C++

// 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<FLiveLinkSubjectKey> FindSubjectKey(ILiveLinkClient* LiveLinkClient, FName SubjectName)
{
TArray<FLiveLinkSubjectKey> 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<ULiveLinkHubCustomTimeStep>(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>(ILiveLinkClient::ModularFeatureName);
ULiveLinkHubCustomTimeStep* NewCustomTimeStep = NewObject<ULiveLinkHubCustomTimeStep>(GEngine, ULiveLinkHubCustomTimeStep::StaticClass());
NewCustomTimeStep->LiveLinkDataRate = CustomTimeStepRate;
NewCustomTimeStep->bLockStepMode = bLockStepMode;
NewCustomTimeStep->FrameRateDivider = FrameRateDivider;
if (TOptional<FLiveLinkSubjectKey> 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>(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<USystemTimeTimecodeProvider>(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<FLiveLinkSubjectKey> Target = UE::LiveLinkHubMessages::Private::FindSubjectKey(LiveLinkClient, SubjectName);
if (Target)
{
FName ObjectName = MakeUniqueObjectName(GEngine, ULiveLinkTimecodeProvider::StaticClass(), "DefaultLiveLinkTimecodeProvider");
ULiveLinkTimecodeProvider* LiveLinkProvider = NewObject<ULiveLinkTimecodeProvider>(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" ) );
}
}