From 2568852b21c39a5c3cbb5626773b97d1b135b647 Mon Sep 17 00:00:00 2001 From: Simon Therriault Date: Mon, 27 Nov 2023 15:18:32 -0500 Subject: [PATCH] Version 3.0.3 - Reflecting code from UE depot as of November 2023 (5.3, 5.4). - Adding build files for Mobu 2024 --- Source/MobuLiveLinkPlugin2016.Target.cs | 1 + Source/MobuLiveLinkPlugin2017.Build.cs | 10 +- Source/MobuLiveLinkPlugin2017.Target.cs | 11 +- Source/MobuLiveLinkPlugin2018.Target.cs | 1 + Source/MobuLiveLinkPlugin2022.Build.cs | 3 + Source/MobuLiveLinkPlugin2023.Build.cs | 15 + Source/MobuLiveLinkPlugin2023.Target.cs | 11 + Source/MobuLiveLinkPlugin2024.Build.cs | 12 + Source/MobuLiveLinkPlugin2024.Target.cs | 11 + Source/Private/MobuLiveLink.cpp | 86 +-- Source/Private/MobuLiveLinkDevice.cpp | 4 +- Source/Private/MobuLiveLinkLayout.cpp | 2 +- Source/Private/MobuLiveLinkPluginPrivatePCH.h | 3 - Source/Private/MobuLiveLinkUtilities.cpp | 523 +++++++++--------- .../EditorActiveCameraStreamObject.cpp | 248 ++++----- 15 files changed, 509 insertions(+), 432 deletions(-) create mode 100644 Source/MobuLiveLinkPlugin2023.Build.cs create mode 100644 Source/MobuLiveLinkPlugin2023.Target.cs create mode 100644 Source/MobuLiveLinkPlugin2024.Build.cs create mode 100644 Source/MobuLiveLinkPlugin2024.Target.cs delete mode 100644 Source/Private/MobuLiveLinkPluginPrivatePCH.h diff --git a/Source/MobuLiveLinkPlugin2016.Target.cs b/Source/MobuLiveLinkPlugin2016.Target.cs index 6d5b2342..602f01fc 100644 --- a/Source/MobuLiveLinkPlugin2016.Target.cs +++ b/Source/MobuLiveLinkPlugin2016.Target.cs @@ -10,5 +10,6 @@ public MobuLiveLinkPlugin2016Target(TargetInfo Target) : base(Target, "2016") { //Mobu is not strict c++ compliant before Mobu 2019 WindowsPlatform.bStrictConformanceMode = false; + CppStandard = CppStandardVersion.Cpp17; } } \ No newline at end of file diff --git a/Source/MobuLiveLinkPlugin2017.Build.cs b/Source/MobuLiveLinkPlugin2017.Build.cs index 2af6f30a..4f249da5 100644 --- a/Source/MobuLiveLinkPlugin2017.Build.cs +++ b/Source/MobuLiveLinkPlugin2017.Build.cs @@ -7,15 +7,13 @@ public abstract class MobuLiveLinkPluginBase : ModuleRules { public MobuLiveLinkPluginBase(ReadOnlyTargetRules Target, string MobuVersionString) : base(Target) { - PrivatePCHHeaderFile = "Private/MobuLiveLinkPluginPrivatePCH.h"; - - bEnforceIWYU = false; + IWYUSupport = IWYUSupport.None; bUseRTTI = true; + PrivateIncludePathModuleNames.Add("Launch"); + PrivateIncludePaths.AddRange(new string[] { - Path.Combine(EngineDirectory, "Source/Runtime/Launch/Public"), - Path.Combine(EngineDirectory, "Source/Runtime/Launch/Private"), Path.Combine(ModuleDirectory, "StreamObjects/Public"), }); @@ -65,6 +63,8 @@ public MobuLiveLinkPluginBase(ReadOnlyTargetRules Target, string MobuVersionStri PublicAdditionalLibraries.Add(Path.Combine(LibDir, "fbsdk.lib")); } } + + PublicDefinitions.Add("PRODUCT_VERSION=" + MobuVersionString); } } } diff --git a/Source/MobuLiveLinkPlugin2017.Target.cs b/Source/MobuLiveLinkPlugin2017.Target.cs index 11eb1364..444bfc28 100644 --- a/Source/MobuLiveLinkPlugin2017.Target.cs +++ b/Source/MobuLiveLinkPlugin2017.Target.cs @@ -3,7 +3,7 @@ using UnrealBuildTool; using System; using System.IO; -using Tools.DotNETCommon; +using EpicGames.Core; using System.Runtime.CompilerServices; [SupportedPlatforms(UnrealPlatformClass.Desktop)] @@ -54,7 +54,6 @@ public MobuLiveLinkPluginTargetBase(TargetInfo Target, string InMobuVersionStrin // We only need minimal use of the engine for this plugin bBuildDeveloperTools = false; - bUseMallocProfiler = false; bBuildWithEditorOnlyData = true; bCompileAgainstEngine = false; bCompileAgainstCoreUObject = true; @@ -95,6 +94,8 @@ public MobuLiveLinkPluginTargetBase(TargetInfo Target, string InMobuVersionStrin string ResourcesDir = Path.Combine(ProgramsDir, "MobuLiveLink", "Resources"); string PostBuildBinDir = Path.Combine(DefaultBinDir, "MotionBuilder", InMobuVersionString); + string TbbDependency = Path.Combine(EngineBinariesDir, "tbb.dll"); + string TbbMallocDependency = Path.Combine(EngineBinariesDir, "tbbmalloc.dll"); // Copy resources PostBuildSteps.Add(string.Format("echo Copying {0} to {1}...", ResourcesDir, PostBuildBinDir)); @@ -103,6 +104,11 @@ public MobuLiveLinkPluginTargetBase(TargetInfo Target, string InMobuVersionStrin // Copy binaries PostBuildSteps.Add(string.Format("echo Copying {0} to {1}...", EngineBinariesDir, PostBuildBinDir)); PostBuildSteps.Add(string.Format("xcopy /y /i /v \"{0}\\{1}.*\" \"{2}\" 1>nul", EngineBinariesDir, LaunchModuleName, PostBuildBinDir)); + + // Copy support dlls + PostBuildSteps.Add(string.Format("echo Copying {0} to {1}...", TbbDependency, PostBuildBinDir)); + PostBuildSteps.Add(string.Format("xcopy /y /i /r /v \"{0}\" \"{1}\" 1>nul", TbbDependency, PostBuildBinDir)); + PostBuildSteps.Add(string.Format("xcopy /y /i /r /v \"{0}\" \"{1}\" 1>nul", TbbMallocDependency, PostBuildBinDir)); } } @@ -112,5 +118,6 @@ public MobuLiveLinkPlugin2017Target(TargetInfo Target) : base(Target, "2017") { //Mobu is not strict c++ compliant before Mobu 2019 WindowsPlatform.bStrictConformanceMode = false; + CppStandard = CppStandardVersion.Cpp17; } } diff --git a/Source/MobuLiveLinkPlugin2018.Target.cs b/Source/MobuLiveLinkPlugin2018.Target.cs index 9fa57568..1e7f66dd 100644 --- a/Source/MobuLiveLinkPlugin2018.Target.cs +++ b/Source/MobuLiveLinkPlugin2018.Target.cs @@ -10,5 +10,6 @@ public MobuLiveLinkPlugin2018Target(TargetInfo Target) : base(Target, "2018") { //Mobu is not strict c++ compliant before Mobu 2019 WindowsPlatform.bStrictConformanceMode = false; + CppStandard = CppStandardVersion.Cpp17; } } \ No newline at end of file diff --git a/Source/MobuLiveLinkPlugin2022.Build.cs b/Source/MobuLiveLinkPlugin2022.Build.cs index af16378c..05fcca9b 100644 --- a/Source/MobuLiveLinkPlugin2022.Build.cs +++ b/Source/MobuLiveLinkPlugin2022.Build.cs @@ -8,5 +8,8 @@ public class MobuLiveLinkPlugin2022 : MobuLiveLinkPluginBase public MobuLiveLinkPlugin2022(ReadOnlyTargetRules Target) : base(Target, "2022") { CppStandard = CppStandardVersion.Cpp17; + + // Replace with PCHUsageMode.UseExplicitOrSharedPCHs when this plugin can compile with cpp20 + PCHUsage = PCHUsageMode.NoPCHs; } } diff --git a/Source/MobuLiveLinkPlugin2023.Build.cs b/Source/MobuLiveLinkPlugin2023.Build.cs new file mode 100644 index 00000000..2f65deb8 --- /dev/null +++ b/Source/MobuLiveLinkPlugin2023.Build.cs @@ -0,0 +1,15 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +using UnrealBuildTool; +using System.IO; + +public class MobuLiveLinkPlugin2023 : MobuLiveLinkPluginBase +{ + public MobuLiveLinkPlugin2023(ReadOnlyTargetRules Target) : base(Target, "2023") + { + CppStandard = CppStandardVersion.Cpp17; + + // Replace with PCHUsageMode.UseExplicitOrSharedPCHs when this plugin can compile with cpp20 + PCHUsage = PCHUsageMode.NoPCHs; + } +} diff --git a/Source/MobuLiveLinkPlugin2023.Target.cs b/Source/MobuLiveLinkPlugin2023.Target.cs new file mode 100644 index 00000000..6f190e47 --- /dev/null +++ b/Source/MobuLiveLinkPlugin2023.Target.cs @@ -0,0 +1,11 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +using UnrealBuildTool; +using System.Collections.Generic; +using System.IO; + +public class MobuLiveLinkPlugin2023Target : MobuLiveLinkPluginTargetBase +{ + public MobuLiveLinkPlugin2023Target(TargetInfo Target) : base(Target, "2023") + {} +} \ No newline at end of file diff --git a/Source/MobuLiveLinkPlugin2024.Build.cs b/Source/MobuLiveLinkPlugin2024.Build.cs new file mode 100644 index 00000000..adb4e595 --- /dev/null +++ b/Source/MobuLiveLinkPlugin2024.Build.cs @@ -0,0 +1,12 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +using UnrealBuildTool; +using System.IO; + +public class MobuLiveLinkPlugin2024 : MobuLiveLinkPluginBase +{ + public MobuLiveLinkPlugin2024(ReadOnlyTargetRules Target) : base(Target, "2024") + { + CppStandard = CppStandardVersion.Cpp17; + } +} diff --git a/Source/MobuLiveLinkPlugin2024.Target.cs b/Source/MobuLiveLinkPlugin2024.Target.cs new file mode 100644 index 00000000..bcbe1cca --- /dev/null +++ b/Source/MobuLiveLinkPlugin2024.Target.cs @@ -0,0 +1,11 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +using UnrealBuildTool; +using System.Collections.Generic; +using System.IO; + +public class MobuLiveLinkPlugin2024Target : MobuLiveLinkPluginTargetBase +{ + public MobuLiveLinkPlugin2024Target(TargetInfo Target) : base(Target, "2024") + {} +} \ No newline at end of file diff --git a/Source/Private/MobuLiveLink.cpp b/Source/Private/MobuLiveLink.cpp index b25d174c..307c6009 100644 --- a/Source/Private/MobuLiveLink.cpp +++ b/Source/Private/MobuLiveLink.cpp @@ -1,41 +1,45 @@ -// Copyright Epic Games, Inc. All Rights Reserved. - -#include "RequiredProgramMainCPPInclude.h" -#include "MobuLiveLinkCommon.h" - -DEFINE_LOG_CATEGORY_STATIC(LogMoBuPlugin, Log, All); - -IMPLEMENT_APPLICATION(MobuLiveLinkPlugin, "MobuLiveLinkPlugin"); - -//--- Library declaration -FBLibraryDeclare( FMobuLiveLink ) -{ - FBLibraryRegister( FMobuLiveLink ); - FBLibraryRegister( FMobuLiveLinkLayout ); -} -FBLibraryDeclareEnd; - -/************************************************ - * Library functions. - ************************************************/ -bool FBLibrary::LibInit() -{ - GEngineLoop.PreInit(TEXT("MobuLiveLinkPlugin -Messaging")); - - // ensure target platform manager is referenced early as it must be created on the main thread - GetTargetPlatformManager(); - - ProcessNewlyLoadedUObjects(); - - // Tell the module manager that it may now process newly-loaded UObjects when new C++ modules are loaded - FModuleManager::Get().StartProcessingNewlyLoadedObjects(); - FModuleManager::Get().LoadModule(TEXT("UdpMessaging")); - - FBTrace("MobuLiveLink Library Initialized\n"); - return true; -} - -bool FBLibrary::LibOpen() { return true; } -bool FBLibrary::LibReady() { return true; } -bool FBLibrary::LibClose() { return true; } -bool FBLibrary::LibRelease(){ return true; } +// Copyright Epic Games, Inc. All Rights Reserved. + +#include "RequiredProgramMainCPPInclude.h" +#include "MobuLiveLinkCommon.h" + +DEFINE_LOG_CATEGORY_STATIC(LogMoBuPlugin, Log, All); + +IMPLEMENT_APPLICATION(MobuLiveLinkPlugin, "MobuLiveLinkPlugin"); + +//--- Library declaration +FBLibraryDeclare( FMobuLiveLink ) +{ + FBLibraryRegister( FMobuLiveLink ); + FBLibraryRegister( FMobuLiveLinkLayout ); +} +FBLibraryDeclareEnd; + +/************************************************ + * Library functions. + ************************************************/ +bool FBLibrary::LibInit() +{ + GEngineLoop.PreInit(TEXT("MobuLiveLinkPlugin -Messaging")); + + // ensure target platform manager is referenced early as it must be created on the main thread + GetTargetPlatformManager(); + + ProcessNewlyLoadedUObjects(); + + // Tell the module manager that it may now process newly-loaded UObjects when new C++ modules are loaded + FModuleManager::Get().StartProcessingNewlyLoadedObjects(); + FModuleManager::Get().LoadModule(TEXT("UdpMessaging")); + + IPluginManager::Get().LoadModulesForEnabledPlugins(ELoadingPhase::PreDefault); + IPluginManager::Get().LoadModulesForEnabledPlugins(ELoadingPhase::Default); + IPluginManager::Get().LoadModulesForEnabledPlugins(ELoadingPhase::PostDefault); + + FBTrace("MobuLiveLink Library Initialized\n"); + return true; +} + +bool FBLibrary::LibOpen() { return true; } +bool FBLibrary::LibReady() { return true; } +bool FBLibrary::LibClose() { return true; } +bool FBLibrary::LibRelease(){ return true; } diff --git a/Source/Private/MobuLiveLinkDevice.cpp b/Source/Private/MobuLiveLinkDevice.cpp index 18fb1445..c5516b76 100644 --- a/Source/Private/MobuLiveLinkDevice.cpp +++ b/Source/Private/MobuLiveLinkDevice.cpp @@ -150,7 +150,7 @@ bool FMobuLiveLink::DeviceOperation(kDeviceOperations pOperation) void FMobuLiveLink::SetDeviceInformation(const char* NewDeviceInformation) { - FString VersionString("v2.5.0 ("); + FString VersionString("v3.0.3 ("); VersionString += __DATE__; VersionString += ")"; HardwareVersionInfo.SetString(FStringToChar(VersionString)); @@ -614,7 +614,7 @@ void FMobuLiveLink::UpdateStreamObjects() void FMobuLiveLink::TickCoreTicker() { double CurrentTime = FPlatformTime::Seconds(); - FTicker::GetCoreTicker().Tick(CurrentTime - LastEvaluationTime); + FTSTicker::GetCoreTicker().Tick(CurrentTime - LastEvaluationTime); LastEvaluationTime = CurrentTime; } diff --git a/Source/Private/MobuLiveLinkLayout.cpp b/Source/Private/MobuLiveLinkLayout.cpp index 8d40e18f..3774fc00 100644 --- a/Source/Private/MobuLiveLinkLayout.cpp +++ b/Source/Private/MobuLiveLinkLayout.cpp @@ -665,7 +665,7 @@ void FMobuLiveLinkLayout::EventAddStaticEndpoint(HISender Sender, HKEvent Event) { char NewAddressString[1024] = "0.0.0.0:6666"; - const std::string Description("Enter a new Static Endpoint Address of the PC running UE4."); + const std::string Description("Enter a new Static Endpoint Address of the PC running Unreal Engine."); const std::string FormatHint("\n\nThe entered address was not formatted correctly. The format must match this pattern:\nIpAddress:Port"); int ButtonClicked = 0; bool bTryAgain = false; diff --git a/Source/Private/MobuLiveLinkPluginPrivatePCH.h b/Source/Private/MobuLiveLinkPluginPrivatePCH.h deleted file mode 100644 index 14d21ea0..00000000 --- a/Source/Private/MobuLiveLinkPluginPrivatePCH.h +++ /dev/null @@ -1,3 +0,0 @@ -// Copyright Epic Games, Inc. All Rights Reserved. - -#pragma once diff --git a/Source/Private/MobuLiveLinkUtilities.cpp b/Source/Private/MobuLiveLinkUtilities.cpp index 7cefea7a..8b6f3310 100644 --- a/Source/Private/MobuLiveLinkUtilities.cpp +++ b/Source/Private/MobuLiveLinkUtilities.cpp @@ -1,255 +1,270 @@ -// Copyright Epic Games, Inc. All Rights Reserved. - -#include "MobuLiveLinkUtilities.h" - -const float MobuUtilities::InchesToMillimeters = 25.4f; - -FTransform MobuUtilities::MobuTransformToUnreal(FBMatrix MobuTransfrom) -{ - FBMatrix MobuTransformUnrealSpace; - FBTVector TVector; - FBSVector SVector; - FBQuaternion Quat; - for (int j = 0; j < 4; ++j) - { - if (j == 1) - { - MobuTransformUnrealSpace(j, 0) = -MobuTransfrom(j, 0); - MobuTransformUnrealSpace(j, 1) = MobuTransfrom(j, 1); - MobuTransformUnrealSpace(j, 2) = -MobuTransfrom(j, 2); - MobuTransformUnrealSpace(j, 3) = -MobuTransfrom(j, 3); - } - else - { - MobuTransformUnrealSpace(j, 0) = MobuTransfrom(j, 0); - MobuTransformUnrealSpace(j, 1) = -MobuTransfrom(j, 1); - MobuTransformUnrealSpace(j, 2) = MobuTransfrom(j, 2); - MobuTransformUnrealSpace(j, 3) = MobuTransfrom(j, 3); - } - } - - FBMatrixToTranslation(TVector, MobuTransformUnrealSpace); - FBMatrixToQuaternion(Quat, MobuTransformUnrealSpace); - FBMatrixToScaling(SVector, MobuTransformUnrealSpace); - - FTransform UnrealTransform; - UnrealTransform.SetRotation(FQuat(Quat[0], Quat[1], Quat[2], Quat[3])); - UnrealTransform.SetTranslation(FVector(TVector[0], TVector[1], TVector[2])); - UnrealTransform.SetScale3D(FVector(SVector[0], SVector[1], SVector[2])); - - return UnrealTransform; -} - -FColor MobuUtilities::MobuColorToUnreal(FBColor Color) -{ - FColor Result; - Result.R = FMath::Clamp(Color[0] * 255.0, 0.0, 255.0); - Result.G = FMath::Clamp(Color[1] * 255.0, 0.0, 255.0); - Result.B = FMath::Clamp(Color[2] * 255.0, 0.0, 255.0); - Result.A = 255; - return Result; -} - -FTransform MobuUtilities::UnrealTransformFromModel(FBModel* MobuModel, bool bIsGlobal) -{ - FBMatrix MobuTransform; - FBMatrix MatOffset; - - MobuModel->GetMatrix(MobuTransform, kModelTransformation, bIsGlobal, nullptr); - - // Y-Up Correction - FBRVector RotOffset(90, 0, 0); - FBRotationToMatrix(MatOffset, RotOffset); - FBMatrixMult(MobuTransform, MatOffset, MobuTransform); - - return MobuTransformToUnreal(MobuTransform); -}; - -// Get all properties on a given model that are both Animatable and are of a Type we can stream -TArray MobuUtilities::GetAllAnimatableCurveNames(FBModel* MobuModel, const FString& Prefix) -{ - const int PropertyCount = MobuModel->PropertyList.GetCount(); - - TArray LiveLinkCurves; - // Reserve enough memory for worst case - LiveLinkCurves.Reserve(PropertyCount); - - for (int i = 0; i < PropertyCount; ++i) - { - FBProperty* Property = MobuModel->PropertyList[i]; - if (Property->IsAnimatable()) - { - //Only add supported property - switch (Property->GetPropertyType()) - { - case kFBPT_bool: - case kFBPT_double: - case kFBPT_float: - case kFBPT_enum: - case kFBPT_int: - case kFBPT_int64: - case kFBPT_uint64: - break; - default: - continue; - } - - if (!Prefix.IsEmpty()) - { - LiveLinkCurves.Add(*(Prefix + FString(":") + Property->GetName())); - } - else - { - LiveLinkCurves.Add(Property->GetName()); - } - } - } - return LiveLinkCurves; -} - -TArray MobuUtilities::GetAllAnimatableCurveValues(FBModel* MobuModel) -{ - int PropertyCount = MobuModel->PropertyList.GetCount(); - - TArray LiveLinkCurves; - // Reserve enough memory for worst case - LiveLinkCurves.Reserve(PropertyCount); - - float PropertyValue; - for (int i = 0; i < PropertyCount; ++i) - { - FBProperty* Property = MobuModel->PropertyList[i]; - if (Property->IsAnimatable()) - { - switch (Property->GetPropertyType()) - { - case kFBPT_bool: - { - bool bValue; - Property->GetData(&bValue, sizeof(bValue), nullptr); - PropertyValue = bValue ? 1.0f : 0.0f; - break; - } - case kFBPT_double: - { - double Value; - Property->GetData(&Value, sizeof(Value), nullptr); - PropertyValue = (float)Value; - break; - } - case kFBPT_float: - { - // PropertyValue is a float so retrieve it directly - Property->GetData(&PropertyValue, sizeof(PropertyValue), nullptr); - break; - } - case kFBPT_enum: // Enums are assumed to be ints - case kFBPT_int: - { - int Value; - Property->GetData(&Value, sizeof(Value), nullptr); - PropertyValue = (float)Value; - break; - } - case kFBPT_int64: - { - int64 Value; - Property->GetData(&Value, sizeof(Value), nullptr); - PropertyValue = (float)Value; - break; - } - case kFBPT_uint64: - { - uint64 Value; - Property->GetData(&Value, sizeof(Value), nullptr); - PropertyValue = (float)Value; - break; - } - default: - continue; - } - LiveLinkCurves.Add(PropertyValue); - } - } - return LiveLinkCurves; -} - -FFrameRate MobuUtilities::TimeModeToFrameRate(FBTimeMode TimeMode) -{ - switch (TimeMode) - { - case FBTimeMode::kFBTimeMode1000Frames: - return FFrameRate(1000,1); - case FBTimeMode::kFBTimeMode120Frames: - return FFrameRate(120, 1); - case FBTimeMode::kFBTimeMode100Frames: - return FFrameRate(100, 1); - case FBTimeMode::kFBTimeMode96Frames: - return FFrameRate(96, 1); - case FBTimeMode::kFBTimeMode72Frames: - return FFrameRate(72, 1); - case FBTimeMode::kFBTimeMode60Frames: - return FFrameRate(60, 1); - case FBTimeMode::kFBTimeMode5994Frames: - return FFrameRate(60000, 1001); - case FBTimeMode::kFBTimeMode50Frames: - return FFrameRate(50, 1); - case FBTimeMode::kFBTimeMode48Frames: - return FFrameRate(48, 1); - case FBTimeMode::kFBTimeMode30Frames: - return FFrameRate(30, 1); - case FBTimeMode::kFBTimeMode2997Frames_Drop: - return FFrameRate(30000, 1001); - case FBTimeMode::kFBTimeMode2997Frames: - return FFrameRate(30000, 1001); - case FBTimeMode::kFBTimeMode25Frames: - return FFrameRate(25, 1); - case FBTimeMode::kFBTimeMode24Frames: - return FFrameRate(24, 1); - case FBTimeMode::kFBTimeMode23976Frames: - return FFrameRate(24000, 1001); - case FBTimeMode::kFBTimeModeDefault: - case FBTimeMode::kFBTimeModeCustom: - default: - return FFrameRate(FMath::RoundToInt(FBPlayerControl().GetTransportFpsValue() * 1001), 1001); - } -} - -FQualifiedFrameTime MobuUtilities::GetSceneTimecode(ETimecodeMode TimecodeMode) -{ - FBTimeMode TimeMode = FBPlayerControl().GetTransportFps(); - FFrameRate FrameRate = TimeModeToFrameRate(TimeMode); - FFrameTime FrameTime; - - // Make sure we use the decimal frame time instead of the integer frame number to keep subframes - if (TimecodeMode == ETimecodeMode::TimecodeMode_Local) // Local time (Take time) - { - FBTime MobuTime = FBSystem().LocalTime; - FrameTime = FFrameTime(FrameRate.AsFrameTime(MobuTime.GetSecondDouble())); - } - else if (TimecodeMode == ETimecodeMode::TimecodeMode_System) // System time (PC clock) - { - const FDateTime DateTime = FDateTime::Now(); - const FTimespan Timespan = DateTime.GetTimeOfDay(); - FrameTime = FFrameTime(FrameRate.AsFrameTime(Timespan.GetTotalSeconds())); - } - else if (TimecodeMode == ETimecodeMode::TimecodeMode_Reference) // Reference time (Incoming LTC) - { - FBReferenceTime MobuRefTime; - if (MobuRefTime.Count > 0) - { - FBTime RefTime = MobuRefTime.GetTime(MobuRefTime.ItemIndex, FBTime(0)); - FrameTime = FFrameTime(FrameRate.AsFrameTime(RefTime.GetSecondDouble())); - } - else - { - FBTrace("GetSceneTimecode - No Reference time sources\n"); - } - } - else - { - FBTrace("GetSceneTimecode - Invalid timecode mode\n"); - } - - return FQualifiedFrameTime(FrameTime, FrameRate); +// Copyright Epic Games, Inc. All Rights Reserved. + +#include "MobuLiveLinkUtilities.h" + +const float MobuUtilities::InchesToMillimeters = 25.4f; + +FTransform MobuUtilities::MobuTransformToUnreal(FBMatrix MobuTransfrom) +{ + FBMatrix MobuTransformUnrealSpace; + FBTVector TVector; + FBSVector SVector; + FBQuaternion Quat; + for (int j = 0; j < 4; ++j) + { + if (j == 1) + { + MobuTransformUnrealSpace(j, 0) = -MobuTransfrom(j, 0); + MobuTransformUnrealSpace(j, 1) = MobuTransfrom(j, 1); + MobuTransformUnrealSpace(j, 2) = -MobuTransfrom(j, 2); + MobuTransformUnrealSpace(j, 3) = -MobuTransfrom(j, 3); + } + else + { + MobuTransformUnrealSpace(j, 0) = MobuTransfrom(j, 0); + MobuTransformUnrealSpace(j, 1) = -MobuTransfrom(j, 1); + MobuTransformUnrealSpace(j, 2) = MobuTransfrom(j, 2); + MobuTransformUnrealSpace(j, 3) = MobuTransfrom(j, 3); + } + } + + FBMatrixToTranslation(TVector, MobuTransformUnrealSpace); + FBMatrixToQuaternion(Quat, MobuTransformUnrealSpace); + FBMatrixToScaling(SVector, MobuTransformUnrealSpace); + + FTransform UnrealTransform; + UnrealTransform.SetRotation(FQuat(Quat[0], Quat[1], Quat[2], Quat[3])); + UnrealTransform.SetTranslation(FVector(TVector[0], TVector[1], TVector[2])); + UnrealTransform.SetScale3D(FVector(SVector[0], SVector[1], SVector[2])); + + return UnrealTransform; +} + +FColor MobuUtilities::MobuColorToUnreal(FBColor Color) +{ + FColor Result; + Result.R = FMath::Clamp(Color[0] * 255.0, 0.0, 255.0); + Result.G = FMath::Clamp(Color[1] * 255.0, 0.0, 255.0); + Result.B = FMath::Clamp(Color[2] * 255.0, 0.0, 255.0); + Result.A = 255; + return Result; +} + +FTransform MobuUtilities::UnrealTransformFromModel(FBModel* MobuModel, bool bIsGlobal) +{ + FBMatrix MobuTransform; + FBMatrix MatOffset; + + MobuModel->GetMatrix(MobuTransform, kModelTransformation, bIsGlobal, nullptr); + + // Y-Up Correction + FBRVector RotOffset(90, 0, 0); + FBRotationToMatrix(MatOffset, RotOffset); + FBMatrixMult(MobuTransform, MatOffset, MobuTransform); + + return MobuTransformToUnreal(MobuTransform); +}; + +// Get all properties on a given model that are both Animatable and are of a Type we can stream +TArray MobuUtilities::GetAllAnimatableCurveNames(FBModel* MobuModel, const FString& Prefix) +{ + const int PropertyCount = MobuModel->PropertyList.GetCount(); + + TArray LiveLinkCurves; + // Reserve enough memory for worst case + LiveLinkCurves.Reserve(PropertyCount); + + for (int i = 0; i < PropertyCount; ++i) + { + FBProperty* Property = MobuModel->PropertyList[i]; + if (Property->IsAnimatable()) + { + //Only add supported property + switch (Property->GetPropertyType()) + { + case kFBPT_bool: + case kFBPT_double: + case kFBPT_float: + case kFBPT_enum: + case kFBPT_int: + case kFBPT_int64: + case kFBPT_uint64: + break; + default: + continue; + } + + if (!Prefix.IsEmpty()) + { + LiveLinkCurves.Add(*(Prefix + FString(":") + Property->GetName())); + } + else + { + LiveLinkCurves.Add(Property->GetName()); + } + } + } + return LiveLinkCurves; +} + +TArray MobuUtilities::GetAllAnimatableCurveValues(FBModel* MobuModel) +{ + int PropertyCount = MobuModel->PropertyList.GetCount(); + + TArray LiveLinkCurves; + // Reserve enough memory for worst case + LiveLinkCurves.Reserve(PropertyCount); + + float PropertyValue; + for (int i = 0; i < PropertyCount; ++i) + { + FBProperty* Property = MobuModel->PropertyList[i]; + if (Property->IsAnimatable()) + { + switch (Property->GetPropertyType()) + { + case kFBPT_bool: + { + bool bValue; + Property->GetData(&bValue, sizeof(bValue), nullptr); + PropertyValue = bValue ? 1.0f : 0.0f; + break; + } + case kFBPT_double: + { + double Value; + Property->GetData(&Value, sizeof(Value), nullptr); + PropertyValue = (float)Value; + break; + } + case kFBPT_float: + { + // PropertyValue is a float so retrieve it directly + Property->GetData(&PropertyValue, sizeof(PropertyValue), nullptr); + break; + } + case kFBPT_enum: // Enums are assumed to be ints + case kFBPT_int: + { + int Value; + Property->GetData(&Value, sizeof(Value), nullptr); + PropertyValue = (float)Value; + break; + } + case kFBPT_int64: + { + int64 Value; + Property->GetData(&Value, sizeof(Value), nullptr); + PropertyValue = (float)Value; + break; + } + case kFBPT_uint64: + { + uint64 Value; + Property->GetData(&Value, sizeof(Value), nullptr); + PropertyValue = (float)Value; + break; + } + default: + continue; + } + LiveLinkCurves.Add(PropertyValue); + } + } + return LiveLinkCurves; +} + +FFrameRate MobuUtilities::TimeModeToFrameRate(FBTimeMode TimeMode) +{ + switch (TimeMode) + { + case FBTimeMode::kFBTimeMode1000Frames: + return FFrameRate(1000,1); + case FBTimeMode::kFBTimeMode120Frames: + return FFrameRate(120, 1); + case FBTimeMode::kFBTimeMode100Frames: + return FFrameRate(100, 1); + case FBTimeMode::kFBTimeMode96Frames: + return FFrameRate(96, 1); + case FBTimeMode::kFBTimeMode72Frames: + return FFrameRate(72, 1); + case FBTimeMode::kFBTimeMode60Frames: + return FFrameRate(60, 1); + case FBTimeMode::kFBTimeMode5994Frames: + return FFrameRate(60000, 1001); + case FBTimeMode::kFBTimeMode50Frames: + return FFrameRate(50, 1); + case FBTimeMode::kFBTimeMode48Frames: + return FFrameRate(48, 1); + case FBTimeMode::kFBTimeMode30Frames: + return FFrameRate(30, 1); + case FBTimeMode::kFBTimeMode2997Frames_Drop: + return FFrameRate(30000, 1001); + case FBTimeMode::kFBTimeMode2997Frames: + return FFrameRate(30000, 1001); + case FBTimeMode::kFBTimeMode25Frames: + return FFrameRate(25, 1); + case FBTimeMode::kFBTimeMode24Frames: + return FFrameRate(24, 1); + case FBTimeMode::kFBTimeMode23976Frames: + return FFrameRate(24000, 1001); + case FBTimeMode::kFBTimeModeDefault: + case FBTimeMode::kFBTimeModeCustom: + default: + return FFrameRate(FMath::RoundToInt(FBPlayerControl().GetTransportFpsValue() * 1001), 1001); + } +} + +FQualifiedFrameTime MobuUtilities::GetSceneTimecode(ETimecodeMode TimecodeMode) +{ + FBTimeMode TimeMode = FBPlayerControl().GetTransportFps(); + FFrameRate FrameRate = TimeModeToFrameRate(TimeMode); + FFrameTime FrameTime; + + // Make sure we use the decimal frame time instead of the integer frame number to keep subframes + if (TimecodeMode == ETimecodeMode::TimecodeMode_Local) // Local time (Take time) + { + FBTime MobuTime = FBSystem().LocalTime; + FrameTime = FFrameTime(FrameRate.AsFrameTime(MobuTime.GetSecondDouble())); + } + else if (TimecodeMode == ETimecodeMode::TimecodeMode_System) // System time (PC clock) + { + const FDateTime DateTime = FDateTime::Now(); + const FTimespan Timespan = DateTime.GetTimeOfDay(); + FrameTime = FFrameTime(FrameRate.AsFrameTime(Timespan.GetTotalSeconds())); + } + else if (TimecodeMode == ETimecodeMode::TimecodeMode_Reference) // Reference time (Incoming LTC) + { + FBReferenceTime MobuRefTime; + #if PRODUCT_VERSION >= 2019 + FBArrayTemplate Identifiers; + MobuRefTime.GetUniqueIDList(&Identifiers); + if (Identifiers.GetCount() > 0) + { + FBTime RefTime = MobuRefTime.GetTime(MobuRefTime.CurrentTimeReferenceID, FBTime(0)); + FrameTime = FFrameTime(FrameRate.AsFrameTime(RefTime.GetSecondDouble())); + } + else + { + FBTrace("GetSceneTimecode - No Reference time sources\n"); + } + #else + if (MobuRefTime.Count > 0) + { + FBTime RefTime = MobuRefTime.GetTime(MobuRefTime.ItemIndex, FBTime(0)); + FrameTime = FFrameTime(FrameRate.AsFrameTime(RefTime.GetSecondDouble())); + } + else + { + FBTrace("GetSceneTimecode - No Reference time sources\n"); + } + #endif + + } + else + { + FBTrace("GetSceneTimecode - Invalid timecode mode\n"); + } + + return FQualifiedFrameTime(FrameTime, FrameRate); } \ No newline at end of file diff --git a/Source/StreamObjects/Private/EditorActiveCameraStreamObject.cpp b/Source/StreamObjects/Private/EditorActiveCameraStreamObject.cpp index 1772bc02..c571c0bc 100644 --- a/Source/StreamObjects/Private/EditorActiveCameraStreamObject.cpp +++ b/Source/StreamObjects/Private/EditorActiveCameraStreamObject.cpp @@ -1,125 +1,125 @@ -// Copyright Epic Games, Inc. All Rights Reserved. - -#include "EditorActiveCameraStreamObject.h" -#include "MobuLiveLinkUtilities.h" - -#include "CameraStreamObject.h" -#include "ModelStreamObject.h" - -#include "Roles/LiveLinkCameraRole.h" -#include "Roles/LiveLinkCameraTypes.h" - -FEditorActiveCameraStreamObject::FEditorActiveCameraStreamObject() - : SubjectName("EditorActiveCamera") - , bIsActive(true) - , bSendAnimatable(false) -{ -} - -FEditorActiveCameraStreamObject::~FEditorActiveCameraStreamObject() -{ -} - -const bool FEditorActiveCameraStreamObject::ShouldShowInUI() const -{ - return false; -} - -const FString FEditorActiveCameraStreamObject::GetStreamOptions() const -{ - // Stream options are not valid on Editor camera - return FString(); -}; - -FName FEditorActiveCameraStreamObject::GetSubjectName() const -{ - return SubjectName; -}; - -void FEditorActiveCameraStreamObject::UpdateSubjectName(FName NewSubjectName) -{ - // Subject name is not changeable on the Editor camera -}; - - -int FEditorActiveCameraStreamObject::GetStreamingMode() const -{ - return 0; -}; - -void FEditorActiveCameraStreamObject::UpdateStreamingMode(int NewStreamingMode) -{ - // Streaming mode is not changeable on the Editor camera -}; - - -bool FEditorActiveCameraStreamObject::GetActiveStatus() const -{ - return bIsActive; -}; - -void FEditorActiveCameraStreamObject::UpdateActiveStatus(bool bIsNowActive) -{ - bIsActive = bIsNowActive; -}; - -bool FEditorActiveCameraStreamObject::GetSendAnimatableStatus() const -{ - return bSendAnimatable; -}; - -void FEditorActiveCameraStreamObject::UpdateSendAnimatableStatus(bool bNewSendAnimatable) -{ - if (bSendAnimatable != bNewSendAnimatable) - { - bSendAnimatable = bNewSendAnimatable; - } -}; - -const FBModel* FEditorActiveCameraStreamObject::GetModelPointer() const -{ - return nullptr; -}; - -const FString FEditorActiveCameraStreamObject::GetRootName() const -{ - // Root Name is not valid on Editor camera - return FString(); -} - - -bool FEditorActiveCameraStreamObject::IsValid() const -{ - // Editor camera is always valid - return true; -} - -void FEditorActiveCameraStreamObject::Refresh(const TSharedPtr Provider) -{ - FBSystem System; - const FBCamera* CameraModel = System.Scene->Renderer->CurrentCamera; - - FLiveLinkStaticDataStruct CameraData(FLiveLinkCameraStaticData::StaticStruct()); - FModelStreamObject::UpdateSubjectTransformStaticData(CameraModel, bSendAnimatable, *CameraData.Cast()); - FCameraStreamObject::UpdateSubjectCameraStaticData(CameraModel, *CameraData.Cast()); - Provider->UpdateSubjectStaticData(SubjectName, ULiveLinkCameraRole::StaticClass(), MoveTemp(CameraData)); -} - -void FEditorActiveCameraStreamObject::UpdateSubjectFrame(const TSharedPtr Provider, FLiveLinkWorldTime WorldTime, FQualifiedFrameTime QualifiedFrameTime) -{ - if (!bIsActive) - { - return; - } - - FBSystem System; - const FBCamera* CameraModel = System.Scene->Renderer->CurrentCamera; - - if (CameraModel) - { - FLiveLinkFrameDataStruct CameraData(FLiveLinkCameraFrameData::StaticStruct()); - FModelStreamObject::UpdateSubjectTransformFrameData(CameraModel, bSendAnimatable, WorldTime, QualifiedFrameTime, *CameraData.Cast()); - FCameraStreamObject::UpdateSubjectCameraFrameData(CameraModel, *CameraData.Cast()); - Provider->UpdateSubjectFrameData(SubjectName, MoveTemp(CameraData)); - } +// Copyright Epic Games, Inc. All Rights Reserved. + +#include "EditorActiveCameraStreamObject.h" +#include "MobuLiveLinkUtilities.h" + +#include "CameraStreamObject.h" +#include "ModelStreamObject.h" + +#include "Roles/LiveLinkCameraRole.h" +#include "Roles/LiveLinkCameraTypes.h" + +FEditorActiveCameraStreamObject::FEditorActiveCameraStreamObject() + : SubjectName("EditorActiveCamera") + , bIsActive(true) + , bSendAnimatable(false) +{ +} + +FEditorActiveCameraStreamObject::~FEditorActiveCameraStreamObject() +{ +} + +const bool FEditorActiveCameraStreamObject::ShouldShowInUI() const +{ + return false; +} + +const FString FEditorActiveCameraStreamObject::GetStreamOptions() const +{ + // Stream options are not valid on Editor camera + return FString(); +}; + +FName FEditorActiveCameraStreamObject::GetSubjectName() const +{ + return SubjectName; +}; + +void FEditorActiveCameraStreamObject::UpdateSubjectName(FName NewSubjectName) +{ + // Subject name is not changeable on the Editor camera +}; + + +int FEditorActiveCameraStreamObject::GetStreamingMode() const +{ + return 0; +}; + +void FEditorActiveCameraStreamObject::UpdateStreamingMode(int NewStreamingMode) +{ + // Streaming mode is not changeable on the Editor camera +}; + + +bool FEditorActiveCameraStreamObject::GetActiveStatus() const +{ + return bIsActive; +}; + +void FEditorActiveCameraStreamObject::UpdateActiveStatus(bool bIsNowActive) +{ + bIsActive = bIsNowActive; +}; + +bool FEditorActiveCameraStreamObject::GetSendAnimatableStatus() const +{ + return bSendAnimatable; +}; + +void FEditorActiveCameraStreamObject::UpdateSendAnimatableStatus(bool bNewSendAnimatable) +{ + if (bSendAnimatable != bNewSendAnimatable) + { + bSendAnimatable = bNewSendAnimatable; + } +}; + +const FBModel* FEditorActiveCameraStreamObject::GetModelPointer() const +{ + return nullptr; +}; + +const FString FEditorActiveCameraStreamObject::GetRootName() const +{ + // Root Name is not valid on Editor camera + return FString(); +} + + +bool FEditorActiveCameraStreamObject::IsValid() const +{ + // Editor camera is always valid + return true; +} + +void FEditorActiveCameraStreamObject::Refresh(const TSharedPtr Provider) +{ + FBSystem System; + const FBCamera* CameraModel = System.Scene->Renderer->GetCameraInPane(0); + + FLiveLinkStaticDataStruct CameraData(FLiveLinkCameraStaticData::StaticStruct()); + FModelStreamObject::UpdateSubjectTransformStaticData(CameraModel, bSendAnimatable, *CameraData.Cast()); + FCameraStreamObject::UpdateSubjectCameraStaticData(CameraModel, *CameraData.Cast()); + Provider->UpdateSubjectStaticData(SubjectName, ULiveLinkCameraRole::StaticClass(), MoveTemp(CameraData)); +} + +void FEditorActiveCameraStreamObject::UpdateSubjectFrame(const TSharedPtr Provider, FLiveLinkWorldTime WorldTime, FQualifiedFrameTime QualifiedFrameTime) +{ + if (!bIsActive) + { + return; + } + + FBSystem System; + const FBCamera* CameraModel = System.Scene->Renderer->GetCameraInPane(0); + + if (CameraModel) + { + FLiveLinkFrameDataStruct CameraData(FLiveLinkCameraFrameData::StaticStruct()); + FModelStreamObject::UpdateSubjectTransformFrameData(CameraModel, bSendAnimatable, WorldTime, QualifiedFrameTime, *CameraData.Cast()); + FCameraStreamObject::UpdateSubjectCameraFrameData(CameraModel, *CameraData.Cast()); + Provider->UpdateSubjectFrameData(SubjectName, MoveTemp(CameraData)); + } } \ No newline at end of file