From 2415f5df72265afb368d5189b91cbe6242da4e5f Mon Sep 17 00:00:00 2001 From: Grigoriy Date: Mon, 12 Mar 2018 00:30:49 +0300 Subject: First commit --- Source/NVIDIAGfeSDK/NVIDIAGfeSDK.Build.cs | 102 +++ Source/NVIDIAGfeSDK/Private/FNVIDIAGfeSDK.cpp | 237 +++++++ Source/NVIDIAGfeSDK/Private/FNVIDIAGfeSDK.h | 46 ++ Source/NVIDIAGfeSDK/Private/GfeSDKCore.cpp | 65 ++ Source/NVIDIAGfeSDK/Private/GfeSDKHighlights.cpp | 245 ++++++++ Source/NVIDIAGfeSDK/Private/HighLightBlueprint.cpp | 697 +++++++++++++++++++++ .../NVIDIAGfeSDK/Private/NVIDIAGfeSDKPrivatePCH.h | 15 + Source/NVIDIAGfeSDK/Private/TypeTranslation.cpp | 66 ++ Source/NVIDIAGfeSDK/Private/TypeTranslation.h | 63 ++ Source/NVIDIAGfeSDK/Public/GfeSDKCore.h | 27 + Source/NVIDIAGfeSDK/Public/GfeSDKHighlights.h | 33 + Source/NVIDIAGfeSDK/Public/HighLightBlueprint.h | 321 ++++++++++ Source/NVIDIAGfeSDK/Public/INVIDIAGfeSDK.h | 49 ++ Source/NVIDIAGfeSDK/Public/NVIDIAGfeSDKPublicPCH.h | 11 + Source/NVIDIAGfeSDK/Public/NVIDIAGfeSDKTypes.h | 279 +++++++++ 15 files changed, 2256 insertions(+) create mode 100644 Source/NVIDIAGfeSDK/NVIDIAGfeSDK.Build.cs create mode 100644 Source/NVIDIAGfeSDK/Private/FNVIDIAGfeSDK.cpp create mode 100644 Source/NVIDIAGfeSDK/Private/FNVIDIAGfeSDK.h create mode 100644 Source/NVIDIAGfeSDK/Private/GfeSDKCore.cpp create mode 100644 Source/NVIDIAGfeSDK/Private/GfeSDKHighlights.cpp create mode 100644 Source/NVIDIAGfeSDK/Private/HighLightBlueprint.cpp create mode 100644 Source/NVIDIAGfeSDK/Private/NVIDIAGfeSDKPrivatePCH.h create mode 100644 Source/NVIDIAGfeSDK/Private/TypeTranslation.cpp create mode 100644 Source/NVIDIAGfeSDK/Private/TypeTranslation.h create mode 100644 Source/NVIDIAGfeSDK/Public/GfeSDKCore.h create mode 100644 Source/NVIDIAGfeSDK/Public/GfeSDKHighlights.h create mode 100644 Source/NVIDIAGfeSDK/Public/HighLightBlueprint.h create mode 100644 Source/NVIDIAGfeSDK/Public/INVIDIAGfeSDK.h create mode 100644 Source/NVIDIAGfeSDK/Public/NVIDIAGfeSDKPublicPCH.h create mode 100644 Source/NVIDIAGfeSDK/Public/NVIDIAGfeSDKTypes.h (limited to 'Source') diff --git a/Source/NVIDIAGfeSDK/NVIDIAGfeSDK.Build.cs b/Source/NVIDIAGfeSDK/NVIDIAGfeSDK.Build.cs new file mode 100644 index 0000000..30e3125 --- /dev/null +++ b/Source/NVIDIAGfeSDK/NVIDIAGfeSDK.Build.cs @@ -0,0 +1,102 @@ +// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved. + +using System.IO; + +namespace UnrealBuildTool.Rules +{ + public class NVIDIAGfeSDK : ModuleRules + { + private string ModulePath + { + get { return ModuleDirectory; } + } + + private string ThirdPartyPath + { + get { return Path.GetFullPath(Path.Combine(ModulePath, "../../ThirdParty/")); } + } + + private string BinariesPath + { + get { return Path.GetFullPath(Path.Combine(ThirdPartyPath, "NVIDIAGfeSDK", "redist")); } + } + + private string LibraryPath + { + get { return Path.GetFullPath(Path.Combine(ThirdPartyPath, "NVIDIAGfeSDK", "lib")); } + } + + public NVIDIAGfeSDK(ReadOnlyTargetRules Target) : base(Target) + { + PublicIncludePaths.AddRange( + new string[] { + "NVIDIAGfeSDK/Public", + ThirdPartyPath + "NVIDIAGfeSDK/Include", + ThirdPartyPath + "NVIDIAGfeSDK/Include/gfesdk", + // ... add public include paths required here ... + } + ); + + PrivateIncludePaths.AddRange( + new string[] { + "NVIDIAGfeSDK/Private", + //Path.Combine(ThirdPartyPath, "NVIDIAGfeSDK", "Include"), + ThirdPartyPath + "NVIDIAGfeSDK/Include", + ThirdPartyPath + "NVIDIAGfeSDK/Include/gfesdk", + // ... add other private include paths required here ... + } + ); + + PublicDependencyModuleNames.AddRange( + new string[] + { + "Engine", + "Core", + "CoreUObject" + } + ); + + PrivateDependencyModuleNames.AddRange( + new string[] + { + // ... add private dependencies that you statically link with here ... + } + ); + + DynamicallyLoadedModuleNames.AddRange( + new string[] + { + // ... add any modules that your module loads dynamically here ... + } + ); + + LoadNVIDIAGfeSDKLib(Target); + } + + public bool LoadNVIDIAGfeSDKLib(ReadOnlyTargetRules Target) + { + bool isLibrarySupported = false; + + if ((Target.Platform == UnrealTargetPlatform.Win64) || (Target.Platform == UnrealTargetPlatform.Win32)) + { + isLibrarySupported = true; + + string PlatformString = (Target.Platform == UnrealTargetPlatform.Win64) ? "Win64" : "Win32"; + + string DllPath = Path.Combine(BinariesPath, PlatformString); + string LibFullPath = Path.Combine(LibraryPath, PlatformString); + + string DllName = Path.Combine(DllPath, "GfeSDK.dll"); + string LibFilePath = Path.Combine(LibFullPath, "GfeSDK.lib"); + + PublicLibraryPaths.Add(LibFullPath); + PublicAdditionalLibraries.Add("GfeSDK.lib"); + + PublicDelayLoadDLLs.Add("GfeSDK.dll"); + RuntimeDependencies.Add(new RuntimeDependency(DllName)); + } + + return isLibrarySupported; + } + } +} diff --git a/Source/NVIDIAGfeSDK/Private/FNVIDIAGfeSDK.cpp b/Source/NVIDIAGfeSDK/Private/FNVIDIAGfeSDK.cpp new file mode 100644 index 0000000..315cf2d --- /dev/null +++ b/Source/NVIDIAGfeSDK/Private/FNVIDIAGfeSDK.cpp @@ -0,0 +1,237 @@ +/* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA CORPORATION and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA CORPORATION is strictly prohibited. + */ +#include "FNVIDIAGfeSDK.h" +#include "NVIDIAGfeSDKPrivatePCH.h" +#include "Runtime/Core/Public/Misc/Paths.h" +#include "Runtime/Core/Public/Windows/WindowsPlatformProcess.h" +#include "gfesdk/sdk_types.h" + + +#define LOCTEXT_NAMESPACE "NVIDIAGfeSDKPlugin" +#define PLUGIN_VERSION "1.0.0" + +DEFINE_LOG_CATEGORY(LogGfeSDK); + +static void __stdcall LoggingCallback(GfeSDK::NVGSDK_LogLevel level, char const* text) +{ + switch (level) + { + case GfeSDK::NVGSDK_LOG_NONE: + break; + case GfeSDK::NVGSDK_LOG_ERROR: + UE_LOG(LogGfeSDK, Warning, TEXT("%s"), UTF8_TO_TCHAR(text)); + break; + case GfeSDK::NVGSDK_LOG_INFO: + case GfeSDK::NVGSDK_LOG_DEBUG: + case GfeSDK::NVGSDK_LOG_VERBOSE: + default: + UE_LOG(LogGfeSDK, Log, TEXT("%s"), UTF8_TO_TCHAR(text)); + break; + } +} + +void FNVIDIAGfeSDK::StartupModule() +{ +#if PLATFORM_WINDOWS +#if _WIN64 + FString WinDir = TEXT("Win64/"); +#else + FString WinDir = TEXT("Win32/"); +#endif +#else +#error Platform currently unsupported +#endif // PLATFORM_WINDOWS + + // Get the base directory of this plugin + const FString PluginPath = FString(FPaths::EnginePluginsDir()); + + FString RootDllPath = PluginPath / FString::Printf(TEXT("Runtime/NVIDIA/GfeSDK/ThirdParty/NVIDIAGfeSDK/redist/")) / WinDir; + + FPlatformProcess::PushDllDirectory(*RootDllPath); + LibHandle = FPlatformProcess::GetDllHandle(*(RootDllPath + "GfeSDK.dll")); + FPlatformProcess::PopDllDirectory(*RootDllPath); + + if (!LibHandle) + { + UE_LOG(LogTemp, Warning, TEXT("Failed to load GfeSDK library.")); + } + else + { + UE_LOG(LogTemp, Log, TEXT("Using NVIDIAGfeSDKPlugin version %s"), TEXT(PLUGIN_VERSION)); + GfeSDK::AttachLogListener(LoggingCallback); + } +} + +void FNVIDIAGfeSDK::ShutdownModule() +{ + + Release(); + if (LibHandle) + { + FPlatformProcess::FreeDllHandle(LibHandle); + LibHandle = nullptr; + } +} + +static GfeSDK::NVGSDK_LogLevel getLogLevel(ELogVerbosity::Type verbosity) +{ + switch (verbosity) + { + case ELogVerbosity::NoLogging: + return GfeSDK::NVGSDK_LOG_NONE; + case ELogVerbosity::Fatal: + case ELogVerbosity::Error: + case ELogVerbosity::Warning: + return GfeSDK::NVGSDK_LOG_ERROR; + case ELogVerbosity::Display: + return GfeSDK::NVGSDK_LOG_INFO; + case ELogVerbosity::Log: + return GfeSDK::NVGSDK_LOG_DEBUG; + case ELogVerbosity::Verbose: + case ELogVerbosity::VeryVerbose: + return GfeSDK::NVGSDK_LOG_VERBOSE; + default: + return GfeSDK::NVGSDK_LOG_DEBUG; + } +} + +// Controls the log level of GfeSDK's internal logfile +GfeSDK::NVGSDK_RetCode FNVIDIAGfeSDK::SetFileLogLevel(ELogVerbosity::Type Level) +{ + if (!LibHandle) return GfeSDK::NVGSDK_ERR_MODULE_NOT_LOADED; + return GfeSDK::SetFileLogLevel(getLogLevel(Level)); +} + +// Controls the log level of logs that GfeSDK sends to the unreal logfile +GfeSDK::NVGSDK_RetCode FNVIDIAGfeSDK::SetUnrealLogLevel(ELogVerbosity::Type Level) +{ + if (!LibHandle) return GfeSDK::NVGSDK_ERR_MODULE_NOT_LOADED; + return GfeSDK::SetListenerLogLevel(getLogLevel(Level)); +} + +static const EGfeSDKScope ScopeMap[(size_t)EGfeSDKScope::MAX] = { + EGfeSDKScope::Highlights, + EGfeSDKScope::HighlightsRecordVideo, + EGfeSDKScope::HighlightsRecordScreenshot +}; + +static const EGfeSDKPermission PermissionMap[] = { + EGfeSDKPermission::Granted, + EGfeSDKPermission::MustAsk, + EGfeSDKPermission::Denied, + EGfeSDKPermission::Unknown +}; + +void __stdcall OnNotificationCallback(GfeSDK::NVGSDK_NotificationType type, GfeSDK::NVGSDK_Notification const* response, void* context) +{ + FNVIDIAGfeSDK* SDKObject = static_cast(context); + switch (type) + { + case GfeSDK::NVGSDK_NOTIFICATION_PERMISSIONS_CHANGED: + { + FGfeSDKPermissionsChangedData PermissionsChangedData; + + for (size_t i = 0; i < response->permissionsChanged.scopePermissionTableSize; i++) + { + PermissionsChangedData.ScopePermissions.Add(ScopeMap[response->permissionsChanged.scopePermissionTable[i].scope], PermissionMap[response->permissionsChanged.scopePermissionTable[i].permission]); + } + if (SDKObject) + SDKObject->PermissionsChangedDelegate.ExecuteIfBound(PermissionsChangedData); + } + } +} + +EGfeSDKReturnCode FNVIDIAGfeSDK::Create(FGfeSDKCreateInputParams const& InputParams, FGfeSDKCreateResponse& Response) +{ + if (!GFEHandle) + { + GfeSDK::NVGSDK_HANDLE* Handle = nullptr; + + GfeSDK::NVGSDK_CreateInputParams InputParamsCreate; + GfeSDK::NVGSDK_CreateResponse OutputParamsCreate; + + std::string appNameUTF = TCHAR_TO_UTF8(*InputParams.AppName); + + InputParamsCreate.appName = appNameUTF.c_str(); + InputParamsCreate.pollForCallbacks = InputParams.PollForCallbacks; + + std::vector Scopes(InputParams.RequiredScopes.Num()); + + for (size_t i = 0; i cScopePermissionList(Scopes.size()); + OutputParamsCreate.scopePermissionTable = &cScopePermissionList[0]; + OutputParamsCreate.scopePermissionTableSize = Scopes.size(); + + GfeSDK::NVGSDK_RetCode Result = GfeSDK::NVGSDK_Create(&Handle, &InputParamsCreate, &OutputParamsCreate); + + if (GfeSDK::NVGSDK_SUCCEEDED(Result)) + { + GFEHandle = Handle; + Response.VersionMajor = OutputParamsCreate.versionMajor; + Response.VersionMinor = OutputParamsCreate.versionMinor; + Response.NVIDIAGfeVersion = FString(OutputParamsCreate.gfeVersionStr); + + SdkCore.Reset(new FGfeSDKCore(GFEHandle)); + SdkHighlights.Reset(new FGfeSDKHighlights(GFEHandle)); + + for (size_t i = 0; i < OutputParamsCreate.scopePermissionTableSize; i++) + { + Response.ScopePermissions.Add( + TranslateEnum(kScopeSdkToUnreal, OutputParamsCreate.scopePermissionTable[i].scope, EGfeSDKScope::MAX), + TranslateEnum(kPermissionSdkToUnreal, OutputParamsCreate.scopePermissionTable[i].permission, EGfeSDKPermission::MAX)); + } + } + else + { + // clear the response + Response = FGfeSDKCreateResponse(); + UE_LOG(LogGfeSDK, Error, TEXT("Failed to create GfeSDK: %d"), (int)Result); + } + + return TranslateReturnCodeToUnreal(Result); + } + else + { + return TranslateReturnCodeToUnreal(GfeSDK::NVGSDK_RetCode::NVGSDK_SUCCESS); + } + +} + +void FNVIDIAGfeSDK::Release() +{ + if (GFEHandle) + { + NVGSDK_Release(GFEHandle); + GFEHandle = nullptr; + } + SdkHighlights.Reset(); +} + +FGfeSDKCore* FNVIDIAGfeSDK::Core() +{ + return SdkCore.Get(); +} + +FGfeSDKHighlights* FNVIDIAGfeSDK::Highlights() +{ + return SdkHighlights.Get(); +} + +IMPLEMENT_MODULE(FNVIDIAGfeSDK, NVIDIAGfeSDK) + +#undef LOCTEXT_NAMESPACE diff --git a/Source/NVIDIAGfeSDK/Private/FNVIDIAGfeSDK.h b/Source/NVIDIAGfeSDK/Private/FNVIDIAGfeSDK.h new file mode 100644 index 0000000..f021576 --- /dev/null +++ b/Source/NVIDIAGfeSDK/Private/FNVIDIAGfeSDK.h @@ -0,0 +1,46 @@ +/* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA CORPORATION and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA CORPORATION is strictly prohibited. + */ + +#pragma once + +#include "NVIDIAGfeSDKPrivatePCH.h" +#include "../Public/INVIDIAGfeSDK.h" + +namespace GfeSDK { + class Core; + class Highlights; +} + +DECLARE_LOG_CATEGORY_EXTERN(LogGfeSDK, Log, All); + +class FNVIDIAGfeSDK : public INVIDIAGfeSDK +{ +public: + FNVIDIAGfeSDK(): GFEHandle(nullptr) {} + virtual ~FNVIDIAGfeSDK() {} + + virtual void StartupModule() override; + virtual void ShutdownModule() override; + + virtual GfeSDK::NVGSDK_RetCode SetFileLogLevel(ELogVerbosity::Type Level); + virtual GfeSDK::NVGSDK_RetCode SetUnrealLogLevel(ELogVerbosity::Type Level); + + virtual EGfeSDKReturnCode Create(FGfeSDKCreateInputParams const& InputParams, FGfeSDKCreateResponse& Response); + virtual void Release(); + virtual FGfeSDKCore* Core(); + virtual FGfeSDKHighlights* Highlights(); + +private: + void* LibHandle = nullptr; + + TUniquePtr SdkHighlights; + TUniquePtr SdkCore; + // SDK handle for C interface + GfeSDK::NVGSDK_HANDLE* GFEHandle; +}; diff --git a/Source/NVIDIAGfeSDK/Private/GfeSDKCore.cpp b/Source/NVIDIAGfeSDK/Private/GfeSDKCore.cpp new file mode 100644 index 0000000..8abd970 --- /dev/null +++ b/Source/NVIDIAGfeSDK/Private/GfeSDKCore.cpp @@ -0,0 +1,65 @@ +/* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. +* +* NVIDIA CORPORATION and its licensors retain all intellectual property +* and proprietary rights in and to this software, related documentation +* and any modifications thereto. Any use, reproduction, disclosure or +* distribution of this software and related documentation without an express +* license agreement from NVIDIA CORPORATION is strictly prohibited. +*/ +#include "GfeSDKCore.h" + +#include "NVIDIAGfeSDKPrivatePCH.h" + +#define VALIDATE_MODULE_CORE() \ + if (!GFEHandle && Callback) \ + { \ + Callback(GfeSDK::NVGSDK_ERR_MODULE_NOT_LOADED, Context); \ + return; \ + } + +#define VALIDATE_MODULE_CORE_SPECIALIZED() \ + if (!GFEHandle && Callback) \ + { \ + Callback(GfeSDK::NVGSDK_ERR_MODULE_NOT_LOADED, nullptr, Context); \ + return; \ + } + +FGfeSDKCore::FGfeSDKCore(GfeSDK::NVGSDK_HANDLE* GFEHandle_) + : GFEHandle(GFEHandle_) +{ +} + +FGfeSDKCore::~FGfeSDKCore() +{ +} + +void FGfeSDKCore::Poll() +{ + if (GFEHandle) + GfeSDK::NVGSDK_Poll(GFEHandle); +} + +void FGfeSDKCore::RequestPermissionsAsync(FGfeSDKRequestPermissionsParams const& Params, GfeSDK::NVGSDK_EmptyCallback Callback, void* Context) +{ + VALIDATE_MODULE_CORE(); + + std::vector Scopes(Params.Scopes.Num()); + + for (int32 i = 0; i < Params.Scopes.Num(); i++) + { + Scopes[i] = TranslateEnum(kScopeUnrealToSdk, Params.Scopes[i], GfeSDK::NVGSDK_SCOPE_MAX); + } + + GfeSDK::NVGSDK_RequestPermissionsParams cParams; + cParams.scopeTable = const_cast(Scopes.data()); + cParams.scopeTableSize = Scopes.size(); + + GfeSDK::NVGSDK_RequestPermissionsAsync(GFEHandle, &cParams, Callback, Context); +} + +void FGfeSDKCore::GetUILanguageAsync(GfeSDK::NVGSDK_GetUILanguageCallback Callback, void* Context) +{ + VALIDATE_MODULE_CORE_SPECIALIZED(); + + GfeSDK::NVGSDK_GetUILanguageAsync(GFEHandle, Callback, Context); +} diff --git a/Source/NVIDIAGfeSDK/Private/GfeSDKHighlights.cpp b/Source/NVIDIAGfeSDK/Private/GfeSDKHighlights.cpp new file mode 100644 index 0000000..bf24347 --- /dev/null +++ b/Source/NVIDIAGfeSDK/Private/GfeSDKHighlights.cpp @@ -0,0 +1,245 @@ +/* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. +* +* NVIDIA CORPORATION and its licensors retain all intellectual property +* and proprietary rights in and to this software, related documentation +* and any modifications thereto. Any use, reproduction, disclosure or +* distribution of this software and related documentation without an express +* license agreement from NVIDIA CORPORATION is strictly prohibited. +*/ +#include "GfeSDKHighlights.h" +#include "NVIDIAGfeSDKPrivatePCH.h" +#include "Platform.h" + +#define VALIDATE_MODULE_HIGHLIGHTS() \ + if (!GFEHandle && Callback) \ + { \ + Callback(GfeSDK::NVGSDK_ERR_MODULE_NOT_LOADED, Context); \ + return; \ + } + +#define VALIDATE_MODULE_HIGHLIGHTS_SPECIALIZED() \ + if (!GFEHandle && Callback) \ + { \ + Callback(GfeSDK::NVGSDK_ERR_MODULE_NOT_LOADED, nullptr, Context); \ + return; \ + } + +struct LocaleStringPair +{ + std::string localeCode; + std::string localizedString; +}; + +struct LocaleHighlightsList +{ + std::vector Strings; + std::vector Pairs; +}; + +FGfeSDKHighlights::FGfeSDKHighlights(GfeSDK::NVGSDK_HANDLE* Handle) : + GFEHandle(Handle) +{} + +FGfeSDKHighlights::~FGfeSDKHighlights() +{} + +void FGfeSDKHighlights::ConfigureAsync(FGfeSDKHighlightConfigParams const& Params, GfeSDK::NVGSDK_EmptyCallback Callback, void* Context) +{ + VALIDATE_MODULE_HIGHLIGHTS(); + + std::string UTF8DefaultLocale = TCHAR_TO_UTF8(*Params.DefaultLocale); + GfeSDK::NVGSDK_HighlightConfigParams cParams; + cParams.defaultLocale = UTF8DefaultLocale.c_str(); + + // Temporary storages for structure elements required by ConfigureAsync function + std::vector Highlights(Params.HighlightDefinitions.Num()); + // TCHAR_TO_UTF8 shares internal buffer, so its results need to be assigned by copy, not pointer. + std::vector id(Params.HighlightDefinitions.Num()); // Workaround for usage of TCHAR_TO_UTF8. + std::vector LocaleStringPairs(Params.HighlightDefinitions.Num()); + + for (int32 i=0; i cGroupViews(Params.GroupViews.Num()); + std::vector StringCache(Params.GroupViews.Num()); + + for (size_t i = 0; i < cGroupViews.size(); i++) + { + StringCache[i] = TCHAR_TO_UTF8(*Params.GroupViews[i].GroupId); + cGroupViews[i].groupId = StringCache[i].c_str(); + cGroupViews[i].tagsFilter = TranslateBitfieldEnum(kHighlightTypeUnrealToSdk, Params.GroupViews[i].TagsFilter); + cGroupViews[i].significanceFilter = TranslateBitfieldEnum(kHighlightSignificanceUnrealToSdk, Params.GroupViews[i].SignificanceFilter); + } + cParams.groupSummaryTable = cGroupViews.data(); + cParams.groupSummaryTableSize = cGroupViews.size(); + + GfeSDK::NVGSDK_Highlights_OpenSummaryAsync(GFEHandle, &cParams, Callback, Context); +} + +void FGfeSDKHighlights::GetNumberOfHighlightsAsync(FGfeSDKHighlightGroupView const& GroupView, GfeSDK::NVGSDK_Highlights_GetNumberOfHighlightsCallback Callback, void* Context) +{ + VALIDATE_MODULE_HIGHLIGHTS_SPECIALIZED(); + GfeSDK::NVGSDK_GroupView groupView; + std::string gID = TCHAR_TO_UTF8(*GroupView.GroupId); + groupView.groupId = gID.c_str(); + groupView.tagsFilter = TranslateBitfieldEnum(kHighlightTypeUnrealToSdk, GroupView.TagsFilter); + groupView.significanceFilter = TranslateBitfieldEnum(kHighlightSignificanceUnrealToSdk, GroupView.SignificanceFilter); + + GfeSDK::NVGSDK_Highlights_GetNumberOfHighlightsAsync(GFEHandle, &groupView, Callback, Context); +} + +struct SNumHighlightsInfo +{ + volatile bool Ready; + int32 NumberOfHighlights; + + SNumHighlightsInfo(): + Ready(false), + NumberOfHighlights(0) + {} +}; + +void __stdcall OnGetNumberOfHighlightsCallbackBlocking(GfeSDK::NVGSDK_RetCode rt, GfeSDK::NVGSDK_Highlights_NumberOfHighlights const* NumberOfHighlights, void* context) +{ + SNumHighlightsInfo* NCB = static_cast(context); + if (NCB) + { + NCB->NumberOfHighlights = NumberOfHighlights->numberOfHighlights; + NCB->Ready = true; + } +} + +int32 FGfeSDKHighlights::GetNumberOfHighlights(FGfeSDKHighlightGroupView const& GroupView) +{ + SNumHighlightsInfo NCB; + GetNumberOfHighlightsAsync(GroupView, &OnGetNumberOfHighlightsCallbackBlocking, &NCB); + int32 IterationCounter = 0; + // Polling cycle (not sure if this is correct for UE4, if we need a blocking function) + // Wait for 10 seconds and return 0 if time is up + while (!NCB.Ready && (IterationCounter < 1000)) + { + Poll(); + FPlatformProcess::Sleep(0.001f); + IterationCounter++; + } + return NCB.NumberOfHighlights; +} + +void FGfeSDKHighlights::Poll() +{ + if (GFEHandle) + GfeSDK::NVGSDK_Poll(GFEHandle); +} \ No newline at end of file diff --git a/Source/NVIDIAGfeSDK/Private/HighLightBlueprint.cpp b/Source/NVIDIAGfeSDK/Private/HighLightBlueprint.cpp new file mode 100644 index 0000000..c6de5a7 --- /dev/null +++ b/Source/NVIDIAGfeSDK/Private/HighLightBlueprint.cpp @@ -0,0 +1,697 @@ +// 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 "Platform.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); + } +} diff --git a/Source/NVIDIAGfeSDK/Private/NVIDIAGfeSDKPrivatePCH.h b/Source/NVIDIAGfeSDK/Private/NVIDIAGfeSDKPrivatePCH.h new file mode 100644 index 0000000..7c5bfa8 --- /dev/null +++ b/Source/NVIDIAGfeSDK/Private/NVIDIAGfeSDKPrivatePCH.h @@ -0,0 +1,15 @@ +/* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA CORPORATION and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA CORPORATION is strictly prohibited. + */ + +#include "NVIDIAGfeSDKPublicPCH.h" +#include "ModuleManager.h" +#include "FNVIDIAGfeSDK.h" +#include "TypeTranslation.h" +#include +#include diff --git a/Source/NVIDIAGfeSDK/Private/TypeTranslation.cpp b/Source/NVIDIAGfeSDK/Private/TypeTranslation.cpp new file mode 100644 index 0000000..bbd53c4 --- /dev/null +++ b/Source/NVIDIAGfeSDK/Private/TypeTranslation.cpp @@ -0,0 +1,66 @@ +/* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. +* +* NVIDIA CORPORATION and its licensors retain all intellectual property +* and proprietary rights in and to this software, related documentation +* and any modifications thereto. Any use, reproduction, disclosure or +* distribution of this software and related documentation without an express +* license agreement from NVIDIA CORPORATION is strictly prohibited. +*/ +#include "TypeTranslation.h" +#include "NVIDIAGfeSDKPrivatePCH.h" + + + +using namespace GfeSDK; + +std::map kScopeSdkToUnreal = { + { NVGSDK_SCOPE_HIGHLIGHTS, EGfeSDKScope::Highlights }, + { NVGSDK_SCOPE_HIGHLIGHTS_VIDEO, EGfeSDKScope::HighlightsRecordVideo }, + { NVGSDK_SCOPE_HIGHLIGHTS_SCREENSHOT, EGfeSDKScope::HighlightsRecordScreenshot }, + { NVGSDK_SCOPE_MAX, EGfeSDKScope::MAX }, +}; +std::map kScopeUnrealToSdk = InvertMap(kScopeSdkToUnreal); + +std::map kPermissionSdkToUnreal = { + { NVGSDK_PERMISSION_GRANTED, EGfeSDKPermission::Granted }, + { NVGSDK_PERMISSION_DENIED, EGfeSDKPermission::Denied }, + { NVGSDK_PERMISSION_MUST_ASK, EGfeSDKPermission::MustAsk }, + { NVGSDK_PERMISSION_UNKNOWN, EGfeSDKPermission::Unknown }, + { NVGSDK_PERMISSION_MAX, EGfeSDKPermission::MAX } +}; +std::map kPermissionUnrealToSdk = InvertMap(kPermissionSdkToUnreal); + +std::map kHighlightTypeSdkToUnreal = { + { NVGSDK_HIGHLIGHT_TYPE_MILESTONE, EGfeSDKHighlightType::Milestone }, + { NVGSDK_HIGHLIGHT_TYPE_ACHIEVEMENT, EGfeSDKHighlightType::Achievement }, + { NVGSDK_HIGHLIGHT_TYPE_INCIDENT, EGfeSDKHighlightType::Incident }, + { NVGSDK_HIGHLIGHT_TYPE_STATE_CHANGE, EGfeSDKHighlightType::StateChange }, + { NVGSDK_HIGHLIGHT_TYPE_MAX, EGfeSDKHighlightType::MAX } +}; +std::map kHighlightTypeUnrealToSdk = InvertMap(kHighlightTypeSdkToUnreal); + +std::map kHighlightSignificanceSdkToUnreal = { + { NVGSDK_HIGHLIGHT_SIGNIFICANCE_EXTREMELY_BAD, EGfeSDKHighlightSignificance::ExtremelyBad }, + { NVGSDK_HIGHLIGHT_SIGNIFICANCE_VERY_BAD, EGfeSDKHighlightSignificance::VeryBad }, + { NVGSDK_HIGHLIGHT_SIGNIFICANCE_BAD, EGfeSDKHighlightSignificance::Bad }, + { NVGSDK_HIGHLIGHT_SIGNIFICANCE_NEUTRAL, EGfeSDKHighlightSignificance::Neutral }, + { NVGSDK_HIGHLIGHT_SIGNIFICANCE_GOOD, EGfeSDKHighlightSignificance::Good }, + { NVGSDK_HIGHLIGHT_SIGNIFICANCE_VERY_GOOD, EGfeSDKHighlightSignificance::VeryGood }, + { NVGSDK_HIGHLIGHT_SIGNIFICANCE_EXTREMELY_GOOD, EGfeSDKHighlightSignificance::ExtremelyGood }, + { NVGSDK_HIGHLIGHT_SIGNIFICANCE_MAX, EGfeSDKHighlightSignificance::MAX } +}; +std::map kHighlightSignificanceUnrealToSdk = InvertMap(kHighlightSignificanceSdkToUnreal); + +EGfeSDKReturnCode TranslateReturnCodeToUnreal(NVGSDK_RetCode code) +{ + switch (code) + { + case NVGSDK_SUCCESS: return EGfeSDKReturnCode::Success; + case NVGSDK_SUCCESS_VERSION_OLD_SDK: return EGfeSDKReturnCode::SuccessIpcOldSdk; + case NVGSDK_SUCCESS_VERSION_OLD_GFE: return EGfeSDKReturnCode::SuccessIpcOldGfe; + case NVGSDK_ERR_GFE_VERSION: return EGfeSDKReturnCode::ErrorGfeVersion; + case NVGSDK_ERR_SDK_VERSION: return EGfeSDKReturnCode::ErrorSdkVersion; + } + + return (NVGSDK_SUCCEEDED(code) ? EGfeSDKReturnCode::Success : EGfeSDKReturnCode::Error); +} diff --git a/Source/NVIDIAGfeSDK/Private/TypeTranslation.h b/Source/NVIDIAGfeSDK/Private/TypeTranslation.h new file mode 100644 index 0000000..2097c44 --- /dev/null +++ b/Source/NVIDIAGfeSDK/Private/TypeTranslation.h @@ -0,0 +1,63 @@ +/* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. +* +* NVIDIA CORPORATION and its licensors retain all intellectual property +* and proprietary rights in and to this software, related documentation +* and any modifications thereto. Any use, reproduction, disclosure or +* distribution of this software and related documentation without an express +* license agreement from NVIDIA CORPORATION is strictly prohibited. +*/ + +#pragma once + +#include "NVIDIAGfeSDKPrivatePCH.h" + +#include + +extern std::map kScopeSdkToUnreal; +extern std::map kScopeUnrealToSdk; +extern std::map kPermissionSdkToUnreal; +extern std::map kPermissionUnrealToSdk; +extern std::map kHighlightTypeSdkToUnreal; +extern std::map kHighlightTypeUnrealToSdk; +extern std::map kHighlightSignificanceSdkToUnreal; +extern std::map kHighlightSignificanceUnrealToSdk; + +extern EGfeSDKReturnCode TranslateReturnCodeToUnreal(GfeSDK::NVGSDK_RetCode code); + +template +std::map InvertMap(std::map const& map) +{ + std::map result; + for (auto it = map.begin(); it != map.end(); ++it) + { + result[it->second] = it->first; + } + return result; +} + +template +U TranslateEnum(std::map const& map, T const& value, U const& defaultValue) +{ + auto foundIt = map.find(value); + return (foundIt != map.end()) ? foundIt->second : defaultValue; +} + +template +U TranslateBitfieldEnum(std::map const& map, T const& value) +{ + uint32 result = 0x0; + for (size_t i = 0; i < sizeof(T)*8; ++i) + { + uint32 v = (1 << i); + if ((static_cast(value) & v) > 0) + { + auto foundIt = map.find(static_cast(v)); + if (foundIt != map.end()) + { + result |= static_cast(foundIt->second); + } + } + } + + return static_cast(result); +} diff --git a/Source/NVIDIAGfeSDK/Public/GfeSDKCore.h b/Source/NVIDIAGfeSDK/Public/GfeSDKCore.h new file mode 100644 index 0000000..c2100c1 --- /dev/null +++ b/Source/NVIDIAGfeSDK/Public/GfeSDKCore.h @@ -0,0 +1,27 @@ +/* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. +* +* NVIDIA CORPORATION and its licensors retain all intellectual property +* and proprietary rights in and to this software, related documentation +* and any modifications thereto. Any use, reproduction, disclosure or +* distribution of this software and related documentation without an express +* license agreement from NVIDIA CORPORATION is strictly prohibited. +*/ + +#pragma once + +#include "NVIDIAGfeSDKPublicPCH.h" + +class NVIDIAGFESDK_API FGfeSDKCore +{ +public: + FGfeSDKCore(GfeSDK::NVGSDK_HANDLE* GFEHandle_); // Takes ownership + ~FGfeSDKCore(); + + void Poll(); + void RequestPermissionsAsync(FGfeSDKRequestPermissionsParams const& Params, GfeSDK::NVGSDK_EmptyCallback Callback, void* Context); + void GetUILanguageAsync(GfeSDK::NVGSDK_GetUILanguageCallback Callback, void* Context); + + friend class FNVIDIAGfeSDK; +private: + GfeSDK::NVGSDK_HANDLE* GFEHandle; +}; diff --git a/Source/NVIDIAGfeSDK/Public/GfeSDKHighlights.h b/Source/NVIDIAGfeSDK/Public/GfeSDKHighlights.h new file mode 100644 index 0000000..e1e3842 --- /dev/null +++ b/Source/NVIDIAGfeSDK/Public/GfeSDKHighlights.h @@ -0,0 +1,33 @@ +/* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. +* +* NVIDIA CORPORATION and its licensors retain all intellectual property +* and proprietary rights in and to this software, related documentation +* and any modifications thereto. Any use, reproduction, disclosure or +* distribution of this software and related documentation without an express +* license agreement from NVIDIA CORPORATION is strictly prohibited. +*/ + +#pragma once + +#include "NVIDIAGfeSDKPublicPCH.h" +#include "gfesdk/sdk_types.h" + +class NVIDIAGFESDK_API FGfeSDKHighlights +{ +public: + FGfeSDKHighlights(GfeSDK::NVGSDK_HANDLE* Handle); + virtual ~FGfeSDKHighlights(); + + virtual void ConfigureAsync(FGfeSDKHighlightConfigParams const& Params, GfeSDK::NVGSDK_EmptyCallback callback, void* Context); + virtual void GetUserSettingsAsync(GfeSDK::NVGSDK_Highlights_GetUserSettingsCallback Callback, void* Context) const; + virtual void OpenGroupAsync(FGfeSDKHighlightOpenGroupParams const& Params, GfeSDK::NVGSDK_EmptyCallback Callback, void* Context); + virtual void CloseGroupAsync(FGfeSDKHighlightCloseGroupParams const& Params, GfeSDK::NVGSDK_EmptyCallback Callback, void* Context); + virtual void SetScreenshotHighlightAsync(FGfeSDKHighlightScreenshotParams const& Params, GfeSDK::NVGSDK_EmptyCallback Callback, void* Context); + virtual void SetVideoHighlightAsync(FGfeSDKHighlightVideoParams const& Params, GfeSDK::NVGSDK_EmptyCallback Callback, void* Context); + virtual void OpenSummaryAsync(FGfeSDKHighlightSummaryParams const& Params, GfeSDK::NVGSDK_EmptyCallback Callback, void* Context); + virtual void GetNumberOfHighlightsAsync(FGfeSDKHighlightGroupView const& GroupView, GfeSDK::NVGSDK_Highlights_GetNumberOfHighlightsCallback Callback, void* Context); + virtual int32 GetNumberOfHighlights(FGfeSDKHighlightGroupView const& GroupView); + virtual void Poll(); +private: + GfeSDK::NVGSDK_HANDLE* GFEHandle; +}; diff --git a/Source/NVIDIAGfeSDK/Public/HighLightBlueprint.h b/Source/NVIDIAGfeSDK/Public/HighLightBlueprint.h new file mode 100644 index 0000000..46cd053 --- /dev/null +++ b/Source/NVIDIAGfeSDK/Public/HighLightBlueprint.h @@ -0,0 +1,321 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once +#include "NVIDIAGfeSDKPrivatePCH.h" +#include "CoreMinimal.h" +#include "Kismet/BlueprintFunctionLibrary.h" +#include "Kismet/BlueprintAsyncActionBase.h" +#include +#include "NVIDIAGfeSDKTypes.h" +#include "HighLightBlueprint.generated.h" + +//--------------------------------------------------------------------------- + +UCLASS() +class UHighlightsFunctionLibrary : public UBlueprintFunctionLibrary +{ + GENERATED_UCLASS_BODY() +public: + // This function should be called periodically. + // It is used to receive callbacks. + // Can be called in Tick event + UFUNCTION(BlueprintCallable, Category = "Shadowplay Highlights") + static void Poll(); + // This function is for convenience + // It chesks if the permissions to use Video or Screenshots functions are granted + // It returns the actual enumeration values for each function + UFUNCTION(BlueprintCallable, Category = "Shadowplay Highlights") + static void ChekIfHighlightsAvailable(const FGfeSDKCreateResponse& InitProperties, bool &VideoGranted, bool &ScreenshotsGranted, EGfeSDKPermission &Video, EGfeSDKPermission &Screenshots); +}; + + +//--------------------------------------------------------------------------- + +DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnHighlightsCallback); +DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnHighlightsOperationResultCallback, EGfeSDKReturnCode, GfeSdkReturnCode); +DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnHighlightsInitCallback, EGfeSDKReturnCode, GfeSdkReturnCode, FGfeSDKCreateResponse, GfeSdkProperties); +DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnGetNumberOfHighlightsCallback, EGfeSDKReturnCode, GfeSdkReturnCode, int32, NumberOfHighlights); + +UCLASS() +class UInitHighlights : public UBlueprintAsyncActionBase +{ + GENERATED_BODY() +public: + // Called when there is a successful init + UPROPERTY(BlueprintAssignable) + FOnHighlightsInitCallback OnSuccess; + + // Called when there is an unsuccessful init + UPROPERTY(BlueprintAssignable) + FOnHighlightsOperationResultCallback OnFailure; + + // Initializes the Highlights client. Should be called first, all other functions will fail otherwise. Takes the game name and desired Highlights options as an input. + // Requests Highlights permissions to recorde Video or Screenshots according to the input checkboxes + // Use the GFE Request Permissions function if desired permissions are not granted to you. + UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true", WorldContext = "WorldContextObject"), Category = "Shadowplay Highlights") + static UInitHighlights* InitHighlights(UObject* WorldContextObject, const FString InGameName, const bool Video, const bool Screenshots); + + // UBlueprintAsyncActionBase interface + virtual void Activate() override; + // End of UBlueprintAsyncActionBase interface + +private: + FCriticalSection CS; + UObject* WorldContextObject; + FString GameName; + TArray RequestedPermissions; + + // Permissions for Highlights + TMap mLastScopePermissions; + TArray mPermissionsNeeded; + + void Callback(); + void OnPermissionsChanged(FGfeSDKPermissionsChangedData const& PermissionsChangedData); +}; + +//--------------------------------------------------------------------------- + +UCLASS() +class UHighlightsConfigureAsync : public UBlueprintAsyncActionBase +{ + GENERATED_BODY() +public: + // Called when there is a successful query + UPROPERTY(BlueprintAssignable) + FOnHighlightsOperationResultCallback OnSuccess; + + // Called when there is an unsuccessful query + UPROPERTY(BlueprintAssignable) + FOnHighlightsOperationResultCallback OnFailure; + + // Configures the highlights system and defines the highlight types. + // Should be called once in game (or can be called if the highlight type list changed, for example for another game type). + // Should be called after init and before the OpenGroup functions + // Uses Poll function to receive callbacks + UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true", WorldContext = "WorldContextObject"), Category = "Shadowplay Highlights") + static UHighlightsConfigureAsync* HighlightsConfigure(UObject* WorldContextObject, const FGfeSDKHighlightConfigParams& ConfigParams); + + // UBlueprintAsyncActionBase interface + virtual void Activate() override; + // End of UBlueprintAsyncActionBase interface + +private: + UObject* WorldContextObject; + FGfeSDKHighlightConfigParams ConfigParams; + static void __stdcall OnConfigureCallback(GfeSDK::NVGSDK_RetCode rt, void* context); +}; + +//--------------------------------------------------------------------------- + +UCLASS() +class UHighlightsOpenGroupAsync : public UBlueprintAsyncActionBase +{ + GENERATED_BODY() +public: + // Called when there is a successful query + UPROPERTY(BlueprintAssignable) + FOnHighlightsOperationResultCallback OnSuccess; + + // Called when there is an unsuccessful query + UPROPERTY(BlueprintAssignable) + FOnHighlightsOperationResultCallback OnFailure; + + // Opens the group of highlights + // Uses Poll function to receive callbacks + UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true", WorldContext = "WorldContextObject"), Category = "Shadowplay Highlights") + static UHighlightsOpenGroupAsync* HighlightsOpenGroup(UObject* WorldContextObject, const FGfeSDKHighlightOpenGroupParams& Params); + + // UBlueprintAsyncActionBase interface + virtual void Activate() override; + // End of UBlueprintAsyncActionBase interface + +private: + UObject* WorldContextObject; + FGfeSDKHighlightOpenGroupParams Params; + static void __stdcall OnOpenGroupCallback(GfeSDK::NVGSDK_RetCode rt, void* context); +}; + +//--------------------------------------------------------------------------- + +UCLASS() +class UHighlightsCloseGroupAsync : public UBlueprintAsyncActionBase +{ + GENERATED_BODY() +public: + // Called when there is a successful query + UPROPERTY(BlueprintAssignable) + FOnHighlightsOperationResultCallback OnSuccess; + + // Called when there is an unsuccessful query + UPROPERTY(BlueprintAssignable) + FOnHighlightsOperationResultCallback OnFailure; + + // Closes the group of highlights + // Uses Poll function to receive callbacks + UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true", WorldContext = "WorldContextObject"), Category = "Shadowplay Highlights") + static UHighlightsCloseGroupAsync* HighlightsCloseGroup(UObject* WorldContextObject, const FString& GroupId, const bool& DestroyHighlights); + + // UBlueprintAsyncActionBase interface + virtual void Activate() override; + // End of UBlueprintAsyncActionBase interface + +private: + UObject* WorldContextObject; + FGfeSDKHighlightCloseGroupParams Params; + static void __stdcall OnCloseGroupCallback(GfeSDK::NVGSDK_RetCode rt, void* context); +}; + +//--------------------------------------------------------------------------- + +UCLASS() +class UHighlightsSetScreenshotAsync : public UBlueprintAsyncActionBase +{ + GENERATED_BODY() +public: + // Called when there is a successful query + UPROPERTY(BlueprintAssignable) + FOnHighlightsOperationResultCallback OnSuccess; + + // Called when there is an unsuccessful query + UPROPERTY(BlueprintAssignable) + FOnHighlightsOperationResultCallback OnFailure; + + // Takes screenshot of the game + // Uses Poll function to receive callbacks + UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true", WorldContext = "WorldContextObject"), Category = "Shadowplay Highlights") + static UHighlightsSetScreenshotAsync* HighlightsSetScreenshot(UObject* WorldContextObject, const FString& GroupId, const FString& HighlightId); + + // UBlueprintAsyncActionBase interface + virtual void Activate() override; + // End of UBlueprintAsyncActionBase interface + +private: + UObject* WorldContextObject; + FGfeSDKHighlightScreenshotParams Params; + static void __stdcall OnSetScreenshotCallback(GfeSDK::NVGSDK_RetCode rt, void* context); +}; + +//--------------------------------------------------------------------------- + +UCLASS() +class UHighlightsSetVideoAsync : public UBlueprintAsyncActionBase +{ + GENERATED_BODY() +public: + // Called when there is a successful query + UPROPERTY(BlueprintAssignable) + FOnHighlightsOperationResultCallback OnSuccess; + + // Called when there is an unsuccessful query + UPROPERTY(BlueprintAssignable) + FOnHighlightsOperationResultCallback OnFailure; + + // Records the video of the gameplay + // GroupID is the name of the group this highlight is related to + // HighlightID is the name of the Highlight + // StartDelta and EndDelta are the time range in miliseconds from the current moment. + // For example StartDelta can be set to -2000 and EndDelta to 3000 - that corresponds to {get the video of two seconds before this moment and record 3 seconds more from this moment} + // Uses Poll function to receive callbacks + UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true", WorldContext = "WorldContextObject"), Category = "Shadowplay Highlights") + static UHighlightsSetVideoAsync* HighlightsSetVideo(UObject* WorldContextObject, const FString& GroupId, const FString& HighlightId, const int32& StartDelta, const int32& EndDelta); + + // UBlueprintAsyncActionBase interface + virtual void Activate() override; + // End of UBlueprintAsyncActionBase interface + +private: + UObject* WorldContextObject; + FGfeSDKHighlightVideoParams Params; + static void __stdcall OnSetVideoCallback(GfeSDK::NVGSDK_RetCode rt, void* context); +}; + +//--------------------------------------------------------------------------- + +UCLASS() +class UHighlightsSummaryAsync : public UBlueprintAsyncActionBase +{ + GENERATED_BODY() +public: + // Called when there is a successful query + UPROPERTY(BlueprintAssignable) + FOnHighlightsOperationResultCallback OnSuccess; + + // Called when there is an unsuccessful query + UPROPERTY(BlueprintAssignable) + FOnHighlightsOperationResultCallback OnFailure; + + // Shows the Shadowplay Highlights Summary interface + // Uses Poll function to receive callbacks + UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true", WorldContext = "WorldContextObject"), Category = "Shadowplay Highlights") + static UHighlightsSummaryAsync* HighlightsOpenSummary(UObject* WorldContextObject, const FGfeSDKHighlightSummaryParams& Params); + + // UBlueprintAsyncActionBase interface + virtual void Activate() override; + // End of UBlueprintAsyncActionBase interface + +private: + UObject* WorldContextObject; + FGfeSDKHighlightSummaryParams Params; + static void __stdcall OnOpenSummaryCallback(GfeSDK::NVGSDK_RetCode rt, void* context); +}; + +//--------------------------------------------------------------------------- + +UCLASS() +class UHighlightsGetNumberAsync : public UBlueprintAsyncActionBase +{ + GENERATED_BODY() +public: + // Called when there is a successful query + UPROPERTY(BlueprintAssignable) + FOnGetNumberOfHighlightsCallback OnSuccess; + + // Called when there is an unsuccessful query + UPROPERTY(BlueprintAssignable) + FOnHighlightsOperationResultCallback OnFailure; + + // Gets number of highlights recorded according to the specified input filtering values + // Uses Poll function to receive callbacks + UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true", WorldContext = "WorldContextObject"), Category = "Shadowplay Highlights") + static UHighlightsGetNumberAsync* HighlightsGetNumberOfHighlights(UObject* WorldContextObject, const FString& GroupID, const EGfeSDKHighlightType& TagFilter, const EGfeSDKHighlightSignificance& SignificanceFilter); + + // UBlueprintAsyncActionBase interface + virtual void Activate() override; + // End of UBlueprintAsyncActionBase interface + +private: + UObject* WorldContextObject; + FGfeSDKHighlightGroupView Params; + static void __stdcall OnGetNumberCallback(GfeSDK::NVGSDK_RetCode rt, GfeSDK::NVGSDK_Highlights_NumberOfHighlights const* NumberOfHighlights, void* context); +}; + +//--------------------------------------------------------------------------- + +UCLASS() +class URequestPermissionsAsync : public UBlueprintAsyncActionBase +{ + GENERATED_BODY() +public: + // Called when there is a successful query + UPROPERTY(BlueprintAssignable) + FOnHighlightsOperationResultCallback OnSuccess; + + // Called when there is an unsuccessful query + UPROPERTY(BlueprintAssignable) + FOnHighlightsOperationResultCallback OnFailure; + + // Requests permissions to use the specified Shadowplay Highlights features + // Use this function to request the permission if the InitHighlights function failed to grant the desired permissions + // Uses Poll function to receive callbacks + UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true", WorldContext = "WorldContextObject"), Category = "Shadowplay Highlights") + static URequestPermissionsAsync* GFERequestPermissions(UObject* WorldContextObject, const bool Video, const bool Screenshots); + + // UBlueprintAsyncActionBase interface + virtual void Activate() override; + // End of UBlueprintAsyncActionBase interface + +private: + UObject* WorldContextObject; + FGfeSDKRequestPermissionsParams Params; + static void __stdcall OnGetNumberCallback(GfeSDK::NVGSDK_RetCode rt, void* context); +}; \ No newline at end of file diff --git a/Source/NVIDIAGfeSDK/Public/INVIDIAGfeSDK.h b/Source/NVIDIAGfeSDK/Public/INVIDIAGfeSDK.h new file mode 100644 index 0000000..73378ea --- /dev/null +++ b/Source/NVIDIAGfeSDK/Public/INVIDIAGfeSDK.h @@ -0,0 +1,49 @@ +/* Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. +* +* NVIDIA CORPORATION and its licensors retain all intellectual property +* and proprietary rights in and to this software, related documentation +* and any modifications thereto. Any use, reproduction, disclosure or +* distribution of this software and related documentation without an express +* license agreement from NVIDIA CORPORATION is strictly prohibited. +*/ + +#pragma once + +#include "NVIDIAGfeSDKPublicPCH.h" + +class INVIDIAGfeSDK : public IModuleInterface +{ +public: + /** + * Singleton-like access to this module's interface. This is just for convenience! + * Beware of calling this during the shutdown phase, though. Your module might have been unloaded already. + * + * @return Returns singleton instance, loading the module on demand if needed + */ + static inline INVIDIAGfeSDK& Get() + { + return FModuleManager::LoadModuleChecked("NVIDIAGfeSDK"); + } + + /** + * Checks to see if this module is loaded and ready. It is only valid to call Get() if IsAvailable() returns true. + * + * @return True if the module is loaded and ready to use + */ + static inline bool IsAvailable() + { + return FModuleManager::Get().IsModuleLoaded("NVIDIAGfeSDK"); + } + + // Controls the log level of GfeSDK's internal logfile + virtual GfeSDK::NVGSDK_RetCode SetFileLogLevel(ELogVerbosity::Type Level) = 0; + // Controls the log level of logs that GfeSDK sends to the unreal logfile + virtual GfeSDK::NVGSDK_RetCode SetUnrealLogLevel(ELogVerbosity::Type Level) = 0; + + virtual EGfeSDKReturnCode Create(FGfeSDKCreateInputParams const& InputParams, FGfeSDKCreateResponse& Response) = 0; + virtual void Release() = 0; + virtual FGfeSDKCore* Core() = 0; + virtual FGfeSDKHighlights* Highlights() = 0; + + FGfeSDKOnPermissionsChanged PermissionsChangedDelegate; +}; diff --git a/Source/NVIDIAGfeSDK/Public/NVIDIAGfeSDKPublicPCH.h b/Source/NVIDIAGfeSDK/Public/NVIDIAGfeSDKPublicPCH.h new file mode 100644 index 0000000..8b446f7 --- /dev/null +++ b/Source/NVIDIAGfeSDK/Public/NVIDIAGfeSDKPublicPCH.h @@ -0,0 +1,11 @@ +#include "ModuleManager.h" +#include "CoreMinimal.h" +//#include "Engine.h" +#include "UniquePtr.h" + +#include "NVIDIAGfeSDKTypes.h" +#include "GfeSDKCore.h" +#include "GfeSDKHighlights.h" +#include "gfesdk/bindings/cpp/sdk_types_cpp.h" +#include "gfesdk/bindings/cpp/isdk_cpp.h" +#include "gfesdk/bindings/cpp/highlights/ihighlights_cpp.h" diff --git a/Source/NVIDIAGfeSDK/Public/NVIDIAGfeSDKTypes.h b/Source/NVIDIAGfeSDK/Public/NVIDIAGfeSDKTypes.h new file mode 100644 index 0000000..02e3b79 --- /dev/null +++ b/Source/NVIDIAGfeSDK/Public/NVIDIAGfeSDKTypes.h @@ -0,0 +1,279 @@ +#pragma once + +#include "NVIDIAGfeSDKTypes.generated.h" + +UENUM(BlueprintType) +enum class EGfeSDKReturnCode : uint8 +{ + Success = 0, + SuccessIpcOldSdk = 1, + SuccessIpcOldGfe = 2, + Error = 3, + ErrorGfeVersion = 4, + ErrorSdkVersion = 5, + ErrorModuleNotLoaded = 6, + ErrorWrongTimeRangeSet = 7 +}; + +UENUM(BlueprintType) +enum class EGfeSDKScope : uint8 +{ + Highlights = 0, + HighlightsRecordVideo = 1, + HighlightsRecordScreenshot = 2, + MAX = 3 +}; + +UENUM(BlueprintType) +enum class EGfeSDKPermission : uint8 +{ + Granted = 0, + Denied = 1, + MustAsk = 2, + Unknown = 3, + MAX= 4 +}; + +UENUM(BlueprintType) +enum class EGfeSDKHighlightType : uint8 +{ + NONE = 0x00, + Milestone = 0x01, + Achievement = 0x02, + Incident = 0x04, + StateChange = 0x08, + MAX = 0x10 +}; + +// This different from the version in sdk_types.h because +// UE4 only supports 8 bit enums. It must be translated +UENUM(BlueprintType) +enum class EGfeSDKHighlightSignificance : uint8 +{ + NONE = 0x00, + ExtremelyBad = 0x01, + VeryBad = 0x02, + Bad = 0x04, + Neutral = 0x08, + Good = 0x10, + VeryGood = 0x20, + ExtremelyGood = 0x40, + MAX = 0x80 +}; + +USTRUCT(BlueprintType) +struct FGfeSDKCreateInputParams +{ + GENERATED_BODY() + + FGfeSDKCreateInputParams() + { + AppName = TEXT("Undefined"); + PollForCallbacks = false; + } + + UPROPERTY() + FString AppName; + + UPROPERTY() + TArray RequiredScopes; + + UPROPERTY() + bool PollForCallbacks; +}; + +USTRUCT(BlueprintType) +struct FGfeSDKCreateResponse +{ + GENERATED_USTRUCT_BODY() + + FGfeSDKCreateResponse() + { + VersionMajor = -1; + VersionMinor = -1; + NVIDIAGfeVersion = TEXT("Undefined"); + } + + UPROPERTY() + uint16 VersionMajor; + + UPROPERTY() + uint16 VersionMinor; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Shadowplay Highlights") + FString NVIDIAGfeVersion; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Shadowplay Highlights") + TMap ScopePermissions; +}; + +USTRUCT(BlueprintType) +struct FGfeSDKHighlightDefinition +{ + GENERATED_USTRUCT_BODY() + + FGfeSDKHighlightDefinition() + { + UserDefaultInterest = true; + HighlightTags = static_cast(0x0); + Significance = static_cast(0x0); + } + + FGfeSDKHighlightDefinition(FString const& Id_, bool UserDefaultInterest_, EGfeSDKHighlightType Tags_, EGfeSDKHighlightSignificance Sig_, TMap Table_) : + Id(Id_), UserDefaultInterest(UserDefaultInterest_), HighlightTags(Tags_), Significance(Sig_), NameTranslationTable(Table_) {} + // Defines the highlight type name + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Shadowplay Highlights") + FString Id; + // If set to true, the highlight will be recorded, otherwise the Shadowplay will lookup the GFE database and user's options. + // If it's not found there or user switched of the highlihts for this game, it will be treated as irrelevant. + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Shadowplay Highlights") + bool UserDefaultInterest; + // Tag that defines the type of the highlight + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Shadowplay Highlights") + EGfeSDKHighlightType HighlightTags; + // This property defines how good or bad the recorded event is in terms of the gameplay + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Shadowplay Highlights") + EGfeSDKHighlightSignificance Significance; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Shadowplay Highlights") + TMap NameTranslationTable; +}; + +USTRUCT(BlueprintType) +struct FGfeSDKHighlightConfigParams +{ + GENERATED_USTRUCT_BODY() + + FGfeSDKHighlightConfigParams() {} + + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Shadowplay Highlights") + TArray HighlightDefinitions; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Shadowplay Highlights") + FString DefaultLocale; +}; + +USTRUCT(BlueprintType) +struct FGfeSDKRequestPermissionsParams +{ + GENERATED_USTRUCT_BODY() + + FGfeSDKRequestPermissionsParams() {} + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Shadowplay Highlights") + TArray Scopes; +}; + +USTRUCT(BlueprintType) +struct FGfeSDKPermissionsChangedData +{ + GENERATED_USTRUCT_BODY() + + FGfeSDKPermissionsChangedData() {} + + UPROPERTY() + TMap ScopePermissions; +}; + +USTRUCT(BlueprintType) +struct FGfeSDKHighlightOpenGroupParams +{ + GENERATED_USTRUCT_BODY() + + FGfeSDKHighlightOpenGroupParams() {} + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Shadowplay Highlights") + FString GroupId; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Shadowplay Highlights") + TMap GroupDescriptionTranslationTable; +}; + +USTRUCT(BlueprintType) +struct FGfeSDKHighlightCloseGroupParams +{ + GENERATED_USTRUCT_BODY() + + FGfeSDKHighlightCloseGroupParams(): + DestroyHighlights(false) + {} + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Shadowplay Highlights") + FString GroupId; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Shadowplay Highlights") + bool DestroyHighlights; +}; + +USTRUCT(BlueprintType) +struct FGfeSDKHighlightScreenshotParams +{ + GENERATED_USTRUCT_BODY() + + FGfeSDKHighlightScreenshotParams() {} + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Shadowplay Highlights") + FString GroupId; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Shadowplay Highlights") + FString HighlightId; +}; + +USTRUCT(BlueprintType) +struct FGfeSDKHighlightVideoParams +{ + GENERATED_USTRUCT_BODY() + + FGfeSDKHighlightVideoParams() + { + StartDelta = 0; + EndDelta = 0; + } + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Shadowplay Highlights") + FString GroupId; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Shadowplay Highlights") + FString HighlightId; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Shadowplay Highlights") + int32 StartDelta; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Shadowplay Highlights") + int32 EndDelta; +}; + +USTRUCT(BlueprintType) +struct FGfeSDKHighlightGroupView +{ + GENERATED_USTRUCT_BODY() + + FGfeSDKHighlightGroupView() : + TagsFilter(EGfeSDKHighlightType::NONE), + SignificanceFilter(EGfeSDKHighlightSignificance::NONE) + {} + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Shadowplay Highlights") + FString GroupId; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Shadowplay Highlights") + EGfeSDKHighlightType TagsFilter; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Shadowplay Highlights") + EGfeSDKHighlightSignificance SignificanceFilter; +}; + +USTRUCT(BlueprintType) +struct FGfeSDKHighlightSummaryParams +{ + GENERATED_USTRUCT_BODY() + + FGfeSDKHighlightSummaryParams() {} + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Shadowplay Highlights") + TArray GroupViews; +}; + + +DECLARE_DELEGATE_OneParam(FGfeSDKOnPermissionsChanged, FGfeSDKPermissionsChangedData const&); -- cgit v1.2.3