// Fill out your copyright notice in the Description page of Project Settings. #include "HighLightBlueprint.h" #include "NVIDIAGfeSDKPrivatePCH.h" #include "FNVIDIAGfeSDK.h" #include "NVIDIAGfeSDKTypes.h" #include "CoreMinimal.h" #include "Runtime/CoreUObject/Public/UObject/Package.h" #include #include template static FORCEINLINE FString EnumToString(const FString& Name, TEnum Value) { const UEnum* enumPtr = FindObject(ANY_PACKAGE, *Name, true); if (!enumPtr) { return FString("Invalid"); } return enumPtr->GetNameByValue((int64)Value).ToString(); } class CGFEHighlights { public: CGFEHighlights(FString AppName) { static const EGfeSDKScope kRequiredScopes[] = { EGfeSDKScope::Highlights, EGfeSDKScope::HighlightsRecordScreenshot, EGfeSDKScope::HighlightsRecordVideo }; INVIDIAGfeSDK::Get().SetFileLogLevel(ELogVerbosity::Verbose); INVIDIAGfeSDK::Get().SetUnrealLogLevel(ELogVerbosity::Display); INVIDIAGfeSDK::Get().PermissionsChangedDelegate.BindRaw(this, &CGFEHighlights::OnPermissionsChanged); FGfeSDKCreateInputParams InParams; InParams.AppName = *AppName; InParams.RequiredScopes.Append(kRequiredScopes, sizeof(kRequiredScopes) / sizeof(EGfeSDKScope)); InParams.PollForCallbacks = true; FGfeSDKCreateResponse OutParams; EGfeSDKReturnCode ret = INVIDIAGfeSDK::Get().Create(InParams, OutParams); if (ret == EGfeSDKReturnCode::Success) { // We have successfully initialized the SDK and passed the version check } else if (ret == EGfeSDKReturnCode::SuccessIpcOldSdk) { // We have successfully initialized the SDK. We are running an older version of the GFESDK // as compared to the installed GFE, but are still ok UE_LOG(LogTemp, Log, TEXT("We are running an older version of the GFESDK. Backend Version %d.%d GFE version %s"), OutParams.VersionMajor, OutParams.VersionMinor, *OutParams.NVIDIAGfeVersion); } else if (ret == EGfeSDKReturnCode::SuccessIpcOldGfe) { // We have successfully initialized the SDK, but the installed version of GFE is older. // Older functionality will still work, but game should check the returned Version to // see if the required functionality is present in the older version. UE_LOG(LogTemp, Log, TEXT("We have successfully initialized the SDK, but the installed version of GFE is older. Backend Version %d.%d GFE version %s"), OutParams.VersionMajor, OutParams.VersionMinor, *OutParams.NVIDIAGfeVersion); } else if (ret == EGfeSDKReturnCode::ErrorGfeVersion) { // The installed GFE is too old to continue. User must download newer GFE. UE_LOG(LogTemp, Warning, TEXT("The installed GFE is too old to continue. User must download newer GFE.")); } else if (ret == EGfeSDKReturnCode::ErrorSdkVersion) { // This version of the GfeSDK is too old to continue. Game needs to distribute newer version. // This is UNLIKELY UE_LOG(LogTemp, Warning, TEXT("This version of the GfeSDK is too old to continue. Game needs to distribute newer version.")); } else if (ret == EGfeSDKReturnCode::Error) { UE_LOG(LogTemp, Warning, TEXT("Failed to connect to GfeSDK backend")); return; } if (ret >= EGfeSDKReturnCode::Error) { UE_LOG(LogTemp, Log, TEXT("FAILED to connect with GfeSDK. Backend Version %d.%d GFE version %s"), OutParams.VersionMajor, OutParams.VersionMinor, *OutParams.NVIDIAGfeVersion); } else { UE_LOG(LogTemp, Log, TEXT("Connected with GfeSDK. Backend Version %d.%d GFE version %s"), OutParams.VersionMajor, OutParams.VersionMinor, *OutParams.NVIDIAGfeVersion); } mPermissionsNeeded.Empty(); for (auto& ScopePermission : OutParams.ScopePermissions) { UE_LOG(LogTemp, Log, TEXT("Required Scope %s has permission %s"), *EnumToString("EGfeSDKScope", ScopePermission.Key), *EnumToString("EGfeSDKPermission", ScopePermission.Value)); if (ScopePermission.Value == EGfeSDKPermission::MustAsk) { mPermissionsNeeded.Add(ScopePermission.Key); } } } ~CGFEHighlights() { INVIDIAGfeSDK::Get().Release(); } protected: TMap mLastScopePermissions; TArray mPermissionsNeeded; void OnPermissionsChanged(FGfeSDKPermissionsChangedData const& PermissionsChangedData) { UE_LOG(LogTemp, Log, TEXT("Permissions Changed notification")); for (auto& ScopePermission : PermissionsChangedData.ScopePermissions) { UE_LOG(LogTemp, Log, TEXT("Scope %s now has permission %s"), *EnumToString("EGfeSDKScope", ScopePermission.Key), *EnumToString("EGfeSDKPermission", ScopePermission.Value)); if (ScopePermission.Value == EGfeSDKPermission::MustAsk) { mPermissionsNeeded.Add(ScopePermission.Key); } } mLastScopePermissions = PermissionsChangedData.ScopePermissions; } }; //--------------------------------------------------------------------------- inline EGfeSDKReturnCode ConvertRetCode(GfeSDK::NVGSDK_RetCode rt) { switch (rt) { case GfeSDK::NVGSDK_SUCCESS: return EGfeSDKReturnCode::Success; case GfeSDK::NVGSDK_SUCCESS_VERSION_OLD_SDK: return EGfeSDKReturnCode::SuccessIpcOldSdk; case GfeSDK::NVGSDK_SUCCESS_VERSION_OLD_GFE: return EGfeSDKReturnCode::SuccessIpcOldGfe; case GfeSDK::NVGSDK_ERR_GFE_VERSION: return EGfeSDKReturnCode::ErrorGfeVersion; case GfeSDK::NVGSDK_ERR_SDK_VERSION: return EGfeSDKReturnCode::ErrorSdkVersion; case GfeSDK::NVGSDK_ERR_MODULE_NOT_LOADED: return EGfeSDKReturnCode::ErrorModuleNotLoaded; default: return EGfeSDKReturnCode::Error; } } //--------------------------------------------------------------------------- //--------- Polling from function library ----------------------------------- //--------------------------------------------------------------------------- UHighlightsFunctionLibrary::UHighlightsFunctionLibrary(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer) { } //--------------------------------------------------------------------------- void UHighlightsFunctionLibrary::Poll() { FGfeSDKHighlights* HiL = INVIDIAGfeSDK::Get().Highlights(); if (HiL) { HiL->Poll(); } } void UHighlightsFunctionLibrary::ChekIfHighlightsAvailable(const FGfeSDKCreateResponse& InitProperties, bool &VideoGranted, bool &ScreenshotsGranted, EGfeSDKPermission &Video, EGfeSDKPermission &Screenshots) { const EGfeSDKPermission* H = InitProperties.ScopePermissions.Find(EGfeSDKScope::Highlights); VideoGranted = false; ScreenshotsGranted = false; Video = EGfeSDKPermission::Denied; Screenshots = EGfeSDKPermission::Denied; if (H && (*H) == EGfeSDKPermission::Granted) { const EGfeSDKPermission* V = InitProperties.ScopePermissions.Find(EGfeSDKScope::HighlightsRecordVideo); if (V) { Video = (*V); if (Video == EGfeSDKPermission::Granted) VideoGranted = true; } const EGfeSDKPermission* S = InitProperties.ScopePermissions.Find(EGfeSDKScope::HighlightsRecordScreenshot); if (S) { Screenshots = (*S); if (Screenshots == EGfeSDKPermission::Granted) ScreenshotsGranted = true; } } } //--------------------------------------------------------------------------- //----------- Initialization class event ------------------------------------ //--------------------------------------------------------------------------- UInitHighlights* UInitHighlights::InitHighlights(UObject* WorldContextObject, const FString InGameName, const bool Video, const bool Screenshots) { UInitHighlights* Proxy = NewObject(); Proxy->GameName = InGameName; Proxy->RequestedPermissions.Empty(); Proxy->RequestedPermissions.Add(EGfeSDKScope::Highlights); if (Video) Proxy->RequestedPermissions.Add(EGfeSDKScope::HighlightsRecordVideo); if (Screenshots) Proxy->RequestedPermissions.Add(EGfeSDKScope::HighlightsRecordScreenshot); Proxy->WorldContextObject = WorldContextObject; return Proxy; } //--------------------------------------------------------------------------- void UInitHighlights::Activate() { INVIDIAGfeSDK::Get().SetFileLogLevel(ELogVerbosity::Verbose); INVIDIAGfeSDK::Get().SetUnrealLogLevel(ELogVerbosity::Display); INVIDIAGfeSDK::Get().PermissionsChangedDelegate.BindUObject(this, &UInitHighlights::OnPermissionsChanged); FGfeSDKCreateInputParams InParams; InParams.AppName = *GameName; InParams.RequiredScopes = RequestedPermissions; InParams.PollForCallbacks = true; FGfeSDKCreateResponse OutParams; EGfeSDKReturnCode ret = INVIDIAGfeSDK::Get().Create(InParams, OutParams); if (ret == EGfeSDKReturnCode::Success) { // We have successfully initialized the SDK and passed the version check } else if (ret == EGfeSDKReturnCode::SuccessIpcOldSdk) { // We have successfully initialized the SDK. We are running an older version of the GFESDK // as compared to the installed GFE, but are still ok /*FFrame::KismetExecutionMessage(*FString::Printf(TEXT("We are running an older version of the GFESDK. Backend Version %d.%d GFE version %s"), OutParams.VersionMajor, OutParams.VersionMinor, *OutParams.NVIDIAGfeVersion), ELogVerbosity::Warning);*/ } else if (ret == EGfeSDKReturnCode::SuccessIpcOldGfe) { // We have successfully initialized the SDK, but the installed version of GFE is older. // Older functionality will still work, but game should check the returned Version to // see if the required functionality is present in the older version. /*UE_LOG(LogTemp, Log, TEXT("We have successfully initialized the SDK, but the installed version of GFE is older. Backend Version %d.%d GFE version %s"), OutParams.VersionMajor, OutParams.VersionMinor, *OutParams.NVIDIAGfeVersion);*/ } else if (ret == EGfeSDKReturnCode::ErrorGfeVersion) { // The installed GFE is too old to continue. User must download newer GFE. //UE_LOG(LogTemp, Warning, TEXT("The installed GFE is too old to continue. User must download newer GFE.")); FFrame::KismetExecutionMessage(*FString::Printf(TEXT("The installed GFE is too old to continue. User must download newer GFE.")), ELogVerbosity::Error); } else if (ret == EGfeSDKReturnCode::ErrorSdkVersion) { // This version of the GfeSDK is too old to continue. Game needs to distribute newer version. // This is UNLIKELY FFrame::KismetExecutionMessage(*FString::Printf(TEXT("This version of the GfeSDK is too old to continue. Game needs to distribute newer version.")), ELogVerbosity::Error); } else if (ret == EGfeSDKReturnCode::Error) { //UE_LOG(LogTemp, Warning, TEXT("Failed to connect to GfeSDK backend")); return; } mPermissionsNeeded.Empty(); for (auto& ScopePermission : OutParams.ScopePermissions) { /*UE_LOG(LogTemp, Log, TEXT("Required Scope %s has permission %s"), *EnumToString("EGfeSDKScope", ScopePermission.Key), *EnumToString("EGfeSDKPermission", ScopePermission.Value));*/ if (ScopePermission.Value == EGfeSDKPermission::MustAsk) { mPermissionsNeeded.Add(ScopePermission.Key); } } if (ret >= EGfeSDKReturnCode::Error) { OnFailure.Broadcast(ret); UE_LOG(LogTemp, Log, TEXT("FAILED to connect with GfeSDK. Backend Version %d.%d GFE version %s"), OutParams.VersionMajor, OutParams.VersionMinor, *OutParams.NVIDIAGfeVersion); } else { OnSuccess.Broadcast(ret, OutParams); UE_LOG(LogTemp, Log, TEXT("Connected with GfeSDK. Backend Version %d.%d GFE version %s"), OutParams.VersionMajor, OutParams.VersionMinor, *OutParams.NVIDIAGfeVersion); } } //--------------------------------------------------------------------------- void UInitHighlights::Callback() { } //--------------------------------------------------------------------------- void UInitHighlights::OnPermissionsChanged(FGfeSDKPermissionsChangedData const& PermissionsChangedData) { UE_LOG(LogTemp, Log, TEXT("Permissions Changed notification")); for (auto& ScopePermission : PermissionsChangedData.ScopePermissions) { UE_LOG(LogTemp, Log, TEXT("Scope %s now has permission %s"), *EnumToString("EGfeSDKScope", ScopePermission.Key), *EnumToString("EGfeSDKPermission", ScopePermission.Value)); if (ScopePermission.Value == EGfeSDKPermission::MustAsk) { mPermissionsNeeded.Add(ScopePermission.Key); } } mLastScopePermissions = PermissionsChangedData.ScopePermissions; } //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- UHighlightsConfigureAsync* UHighlightsConfigureAsync::HighlightsConfigure(UObject* WorldContextObject, const FGfeSDKHighlightConfigParams& ConfigParams) { UHighlightsConfigureAsync* Proxy = NewObject(); Proxy->WorldContextObject = WorldContextObject; Proxy->ConfigParams = ConfigParams; return Proxy; } //--------------------------------------------------------------------------- void __stdcall UHighlightsConfigureAsync::OnConfigureCallback(GfeSDK::NVGSDK_RetCode rt, void* context) { UHighlightsConfigureAsync* Th = static_cast(context); if (Th) { if (NVGSDK_SUCCEEDED(rt)) { Th->OnSuccess.Broadcast(ConvertRetCode(rt)); } else { Th->OnFailure.Broadcast(ConvertRetCode(rt)); } } } void UHighlightsConfigureAsync::Activate() { FGfeSDKHighlights* HiL = INVIDIAGfeSDK::Get().Highlights(); if (HiL) { HiL->ConfigureAsync(ConfigParams, &OnConfigureCallback, this); } else { OnFailure.Broadcast(EGfeSDKReturnCode::ErrorModuleNotLoaded); } } //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- UHighlightsOpenGroupAsync* UHighlightsOpenGroupAsync::HighlightsOpenGroup(UObject* WorldContextObject, const FGfeSDKHighlightOpenGroupParams& Params) { UHighlightsOpenGroupAsync* Proxy = NewObject(); Proxy->WorldContextObject = WorldContextObject; Proxy->Params = Params; return Proxy; } //--------------------------------------------------------------------------- void __stdcall UHighlightsOpenGroupAsync::OnOpenGroupCallback(GfeSDK::NVGSDK_RetCode rt, void* context) { UHighlightsOpenGroupAsync* Th = static_cast(context); if (Th) { if (NVGSDK_SUCCEEDED(rt)) { Th->OnSuccess.Broadcast(ConvertRetCode(rt)); } else { Th->OnFailure.Broadcast(ConvertRetCode(rt)); } } } void UHighlightsOpenGroupAsync::Activate() { FGfeSDKHighlights* HiL = INVIDIAGfeSDK::Get().Highlights(); if (HiL) { HiL->OpenGroupAsync(Params, &OnOpenGroupCallback, this); } else { OnFailure.Broadcast(EGfeSDKReturnCode::ErrorModuleNotLoaded); } } //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- UHighlightsCloseGroupAsync* UHighlightsCloseGroupAsync::HighlightsCloseGroup(UObject* WorldContextObject, const FString& GroupId, const bool& DestroyHighlights) { UHighlightsCloseGroupAsync* Proxy = NewObject(); Proxy->WorldContextObject = WorldContextObject; Proxy->Params.GroupId = GroupId; Proxy->Params.DestroyHighlights = DestroyHighlights; return Proxy; } //--------------------------------------------------------------------------- void __stdcall UHighlightsCloseGroupAsync::OnCloseGroupCallback(GfeSDK::NVGSDK_RetCode rt, void* context) { UHighlightsCloseGroupAsync* Th = static_cast(context); if (Th) { if (NVGSDK_SUCCEEDED(rt)) { Th->OnSuccess.Broadcast(ConvertRetCode(rt)); } else { Th->OnFailure.Broadcast(ConvertRetCode(rt)); } } } void UHighlightsCloseGroupAsync::Activate() { FGfeSDKHighlights* HiL = INVIDIAGfeSDK::Get().Highlights(); if (HiL) { HiL->CloseGroupAsync(Params, &OnCloseGroupCallback, this); } else { OnFailure.Broadcast(EGfeSDKReturnCode::ErrorModuleNotLoaded); } } //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- UHighlightsSetScreenshotAsync* UHighlightsSetScreenshotAsync::HighlightsSetScreenshot(UObject* WorldContextObject, const FString& GroupId, const FString& HighlightId) { UHighlightsSetScreenshotAsync* Proxy = NewObject(); Proxy->WorldContextObject = WorldContextObject; Proxy->Params.GroupId = GroupId; Proxy->Params.HighlightId = HighlightId; return Proxy; } //--------------------------------------------------------------------------- void __stdcall UHighlightsSetScreenshotAsync::OnSetScreenshotCallback(GfeSDK::NVGSDK_RetCode rt, void* context) { UHighlightsSetScreenshotAsync* Th = static_cast(context); if (Th) { if (NVGSDK_SUCCEEDED(rt)) { Th->OnSuccess.Broadcast(ConvertRetCode(rt)); } else { Th->OnFailure.Broadcast(ConvertRetCode(rt)); } } } void UHighlightsSetScreenshotAsync::Activate() { FGfeSDKHighlights* HiL = INVIDIAGfeSDK::Get().Highlights(); if (HiL) { HiL->SetScreenshotHighlightAsync(Params, &OnSetScreenshotCallback, this); } else { OnFailure.Broadcast(EGfeSDKReturnCode::ErrorModuleNotLoaded); } } //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- UHighlightsSetVideoAsync* UHighlightsSetVideoAsync::HighlightsSetVideo(UObject* WorldContextObject, const FString& GroupId, const FString& HighlightId, const int32& StartDelta, const int32& EndDelta) { UHighlightsSetVideoAsync* Proxy = NewObject(); Proxy->WorldContextObject = WorldContextObject; Proxy->Params.GroupId = GroupId; Proxy->Params.HighlightId = HighlightId; Proxy->Params.StartDelta = StartDelta; Proxy->Params.EndDelta = EndDelta; return Proxy; } //--------------------------------------------------------------------------- void __stdcall UHighlightsSetVideoAsync::OnSetVideoCallback(GfeSDK::NVGSDK_RetCode rt, void* context) { UHighlightsSetVideoAsync* Th = static_cast(context); if (Th) { if (NVGSDK_SUCCEEDED(rt)) { Th->OnSuccess.Broadcast(ConvertRetCode(rt)); } else { Th->OnFailure.Broadcast(ConvertRetCode(rt)); } } } void UHighlightsSetVideoAsync::Activate() { FGfeSDKHighlights* HiL = INVIDIAGfeSDK::Get().Highlights(); if (HiL) { if (Params.EndDelta <= Params.StartDelta) { OnFailure.Broadcast(EGfeSDKReturnCode::ErrorWrongTimeRangeSet); } else { HiL->SetVideoHighlightAsync(Params, &OnSetVideoCallback, this); } } else { OnFailure.Broadcast(EGfeSDKReturnCode::ErrorModuleNotLoaded); } } //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- UHighlightsSummaryAsync* UHighlightsSummaryAsync::HighlightsOpenSummary(UObject* WorldContextObject, const FGfeSDKHighlightSummaryParams& Params) { UHighlightsSummaryAsync* Proxy = NewObject(); Proxy->WorldContextObject = WorldContextObject; Proxy->Params = Params; return Proxy; } //--------------------------------------------------------------------------- void __stdcall UHighlightsSummaryAsync::OnOpenSummaryCallback(GfeSDK::NVGSDK_RetCode rt, void* context) { UHighlightsSummaryAsync* Th = static_cast(context); if (Th) { if (NVGSDK_SUCCEEDED(rt)) { Th->OnSuccess.Broadcast(ConvertRetCode(rt)); } else { Th->OnFailure.Broadcast(ConvertRetCode(rt)); } } } void UHighlightsSummaryAsync::Activate() { FGfeSDKHighlights* HiL = INVIDIAGfeSDK::Get().Highlights(); if (HiL) { HiL->OpenSummaryAsync(Params, &OnOpenSummaryCallback, this); } else { OnFailure.Broadcast(EGfeSDKReturnCode::ErrorModuleNotLoaded); } } //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- UHighlightsGetNumberAsync* UHighlightsGetNumberAsync::HighlightsGetNumberOfHighlights(UObject* WorldContextObject, const FString& GroupID, const EGfeSDKHighlightType& TagFilter, const EGfeSDKHighlightSignificance& SignificanceFilter) { UHighlightsGetNumberAsync* Proxy = NewObject(); Proxy->WorldContextObject = WorldContextObject; Proxy->Params.GroupId = GroupID; Proxy->Params.TagsFilter = TagFilter; Proxy->Params.SignificanceFilter = SignificanceFilter; return Proxy; } //--------------------------------------------------------------------------- void __stdcall UHighlightsGetNumberAsync::OnGetNumberCallback(GfeSDK::NVGSDK_RetCode rt, GfeSDK::NVGSDK_Highlights_NumberOfHighlights const* NumberOfHighlights, void* context) { UHighlightsGetNumberAsync* Th = static_cast(context); if (Th) { if (NVGSDK_SUCCEEDED(rt)) { Th->OnSuccess.Broadcast(ConvertRetCode(rt), NumberOfHighlights->numberOfHighlights); } else { Th->OnFailure.Broadcast(ConvertRetCode(rt)); } } } void UHighlightsGetNumberAsync::Activate() { FGfeSDKHighlights* HiL = INVIDIAGfeSDK::Get().Highlights(); if (HiL) { HiL->GetNumberOfHighlightsAsync(Params, &OnGetNumberCallback, this); } else { OnFailure.Broadcast(EGfeSDKReturnCode::ErrorModuleNotLoaded); } } //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- URequestPermissionsAsync* URequestPermissionsAsync::GFERequestPermissions(UObject* WorldContextObject, const bool Video, const bool Screenshots) { URequestPermissionsAsync* Proxy = NewObject(); Proxy->WorldContextObject = WorldContextObject; Proxy->Params.Scopes.Empty(); Proxy->Params.Scopes.Add(EGfeSDKScope::Highlights); if (Video) Proxy->Params.Scopes.Add(EGfeSDKScope::HighlightsRecordVideo); if (Screenshots) Proxy->Params.Scopes.Add(EGfeSDKScope::HighlightsRecordScreenshot); return Proxy; } //--------------------------------------------------------------------------- void __stdcall URequestPermissionsAsync::OnGetNumberCallback(GfeSDK::NVGSDK_RetCode rt, void* context) { URequestPermissionsAsync* Th = static_cast(context); if (Th) { if (NVGSDK_SUCCEEDED(rt)) { Th->OnSuccess.Broadcast(ConvertRetCode(rt)); } else { Th->OnFailure.Broadcast(ConvertRetCode(rt)); } } } void URequestPermissionsAsync::Activate() { FGfeSDKCore* Core = INVIDIAGfeSDK::Get().Core(); if (Core) { Core->RequestPermissionsAsync(Params, &OnGetNumberCallback, this); } else { OnFailure.Broadcast(EGfeSDKReturnCode::ErrorModuleNotLoaded); } }