Add automatic profile switching #1
44 changed files with 2026 additions and 238 deletions
|
@ -2,7 +2,7 @@
|
|||
"FileVersion": 3,
|
||||
"Version": 1,
|
||||
"VersionName": "1.0",
|
||||
"FriendlyName": "HarmonyLink",
|
||||
"FriendlyName": "HarmonyLinkUE",
|
||||
"Description": "Revolutionize handheld gaming with adaptive game settings. Optimize graphics and gameplay experience based on real-time system metrics. Open-source project empowering developers to enhance games on portable devices",
|
||||
"Category": "Handheld",
|
||||
"CreatedBy": "Jordon Brooks",
|
||||
|
@ -10,16 +10,24 @@
|
|||
"DocsURL": "https://github.com/Jordonbc/HarmonyLink",
|
||||
"MarketplaceURL": "com.epicgames.launcher://ue/marketplace/product/92fd511971274d1f955abb7197485041",
|
||||
"SupportURL": "",
|
||||
"CanContainContent": true,
|
||||
"CanContainContent": false,
|
||||
"IsBetaVersion": false,
|
||||
"IsExperimentalVersion": false,
|
||||
"Installed": false,
|
||||
"Modules": [
|
||||
{
|
||||
"Name": "HarmonyLink",
|
||||
"Name": "HarmonyLinkUE",
|
||||
"Type": "Runtime",
|
||||
"LoadingPhase": "Default",
|
||||
"WhitelistPlatforms": ["Win64", "Linux"]
|
||||
"LoadingPhase": "PreDefault",
|
||||
"WhitelistPlatforms": [
|
||||
"Win64",
|
||||
"Linux"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "HarmonyLinkSettings",
|
||||
"Type": "Runtime",
|
||||
"LoadingPhase": "Default"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,72 +0,0 @@
|
|||
// Copyright (C) 2024 Jordon Brooks
|
||||
|
||||
using UnrealBuildTool;
|
||||
using System.IO;
|
||||
|
||||
public class HarmonyLink : ModuleRules
|
||||
{
|
||||
public HarmonyLink(ReadOnlyTargetRules Target) : base(Target)
|
||||
{
|
||||
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
|
||||
|
||||
PublicIncludePaths.AddRange(
|
||||
new string[] {
|
||||
// ... add public include paths required here ...
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
PrivateIncludePaths.AddRange(
|
||||
new string[] {
|
||||
// ... add other private include paths required here ...
|
||||
"ThirdParty/HarmonyLinkLib/include"
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
PublicDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"Core",
|
||||
"CoreUObject",
|
||||
"Engine",
|
||||
// ... add other public dependencies that you statically link with here ...
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
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 ...
|
||||
}
|
||||
);
|
||||
|
||||
// Platform-specific settings
|
||||
if (Target.Platform == UnrealTargetPlatform.Win64)
|
||||
{
|
||||
PublicAdditionalLibraries.Add(Path.Combine(PluginDirectory, "Source/ThirdParty/HarmonyLinkLib/bin/Win64/HarmonyLinkLib.lib"));
|
||||
RuntimeDependencies.Add("$(BinaryOutputDir)/HarmonyLinkLib.dll", Path.Combine(PluginDirectory, "Source/ThirdParty/HarmonyLinkLib/bin/Win64/HarmonyLinkLib.dll"));
|
||||
}
|
||||
else if (Target.Platform == UnrealTargetPlatform.Linux)
|
||||
{
|
||||
PublicAdditionalLibraries.Add(Path.Combine(PluginDirectory, "Source/ThirdParty/HarmonyLinkLib/bin/Linux/libHarmonyLinkLib.so"));
|
||||
RuntimeDependencies.Add("$(BinaryOutputDir)/libHarmonyLinkLib.so", Path.Combine(PluginDirectory, "Source/ThirdParty/HarmonyLinkLib/bin/Linux/libHarmonyLinkLib.so"));
|
||||
}
|
||||
|
||||
// I shall include this if anyone wishes to provide Mac binaries of HarmonyLink but these are not included by default as I don't own one.
|
||||
else if (Target.Platform == UnrealTargetPlatform.Mac)
|
||||
{
|
||||
PublicAdditionalLibraries.Add(Path.Combine(PluginDirectory, "Source/ThirdParty/HarmonyLinkLib/bin/Mac/HarmonyLinkLib.dylib"));
|
||||
RuntimeDependencies.Add("$(BinaryOutputDir)/HarmonyLinkLib.dylib", Path.Combine(PluginDirectory, "Source/ThirdParty/HarmonyLinkLib/bin/Mac/HarmonyLinkLib.dylib"));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
// Copyright (C) 2024 Jordon Brooks
|
||||
|
||||
#include "HarmonyLink.h"
|
||||
#include "Modules/ModuleManager.h"
|
||||
|
||||
#define LOCTEXT_NAMESPACE "FHarmonyLinkModule"
|
||||
|
||||
void FHarmonyLinkModule::StartupModule()
|
||||
{
|
||||
}
|
||||
|
||||
void FHarmonyLinkModule::ShutdownModule()
|
||||
{
|
||||
}
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
|
||||
IMPLEMENT_MODULE(FHarmonyLinkModule, HarmonyLink)
|
|
@ -1,46 +0,0 @@
|
|||
// Copyright (C) 2024 Jordon Brooks
|
||||
|
||||
#include "HarmonyLinkLibrary.h"
|
||||
|
||||
#include <HarmonyLinkLib.h>
|
||||
|
||||
bool UHarmonyLinkLibrary::IsWine()
|
||||
{
|
||||
return HarmonyLinkLib::get_is_wine();
|
||||
}
|
||||
|
||||
bool UHarmonyLinkLibrary::IsLinux()
|
||||
{
|
||||
#if PLATFORM_WINDOWS
|
||||
return IsWine();
|
||||
#elif PLATFORM_LINUX
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool UHarmonyLinkLibrary::IsSteamDeck()
|
||||
{
|
||||
return GetDeviceInfo().Device == EDeviceEnum::STEAM_DECK;
|
||||
}
|
||||
|
||||
FCPUInfo UHarmonyLinkLibrary::GetCPUInfo()
|
||||
{
|
||||
return FCPUInfo(HarmonyLinkLib::get_cpu_info());
|
||||
}
|
||||
|
||||
FDevice UHarmonyLinkLibrary::GetDeviceInfo()
|
||||
{
|
||||
return FDevice(HarmonyLinkLib::get_device_info());
|
||||
}
|
||||
|
||||
FOSVerInfo UHarmonyLinkLibrary::GetOSInfo()
|
||||
{
|
||||
return FOSVerInfo(HarmonyLinkLib::get_os_version());
|
||||
}
|
||||
|
||||
FBattery UHarmonyLinkLibrary::GetBatteryStatus()
|
||||
{
|
||||
return FBattery(HarmonyLinkLib::get_battery_status());
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
// Copyright (C) 2024 Jordon Brooks
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
|
||||
#include "Structs/Battery.h"
|
||||
#include "Structs/CPUInfo.h"
|
||||
#include "Structs/Device.h"
|
||||
#include "Structs/OSVerInfo.h"
|
||||
|
||||
#include "Kismet/BlueprintFunctionLibrary.h"
|
||||
#include "HarmonyLinkLibrary.generated.h"
|
||||
|
||||
/**
|
||||
* Library of static functions for accessing various system information, particularly for the HarmonyLink project.
|
||||
*/
|
||||
UCLASS()
|
||||
class HARMONYLINK_API UHarmonyLinkLibrary : public UBlueprintFunctionLibrary
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
// Checks if the game is running under Wine.
|
||||
UFUNCTION(BlueprintCallable, Category="HarmonyLink")
|
||||
static bool IsWine();
|
||||
|
||||
// Checks if the operating system is Linux.
|
||||
UFUNCTION(BlueprintCallable, Category="HarmonyLink")
|
||||
static bool IsLinux();
|
||||
|
||||
// Checks if the game is running on a Steam Deck.
|
||||
UFUNCTION(BlueprintCallable, Category="HarmonyLink")
|
||||
static bool IsSteamDeck();
|
||||
|
||||
// Retrieves information about the CPU of the current device.
|
||||
UFUNCTION(BlueprintCallable, Category="HarmonyLink")
|
||||
static FCPUInfo GetCPUInfo();
|
||||
|
||||
// Retrieves information about the current device.
|
||||
UFUNCTION(BlueprintCallable, Category="HarmonyLink")
|
||||
static FDevice GetDeviceInfo();
|
||||
|
||||
// Retrieves information about the operating system of the current device.
|
||||
UFUNCTION(BlueprintCallable, Category="HarmonyLink")
|
||||
static FOSVerInfo GetOSInfo();
|
||||
|
||||
// Retrieves the current battery status of the device.
|
||||
UFUNCTION(BlueprintCallable, Category="HarmonyLink")
|
||||
static FBattery GetBatteryStatus();
|
||||
};
|
26
Source/HarmonyLinkSettings/HarmonyLinkSettings.Build.cs
Normal file
26
Source/HarmonyLinkSettings/HarmonyLinkSettings.Build.cs
Normal file
|
@ -0,0 +1,26 @@
|
|||
using UnrealBuildTool;
|
||||
|
||||
public class HarmonyLinkSettings : ModuleRules
|
||||
{
|
||||
public HarmonyLinkSettings(ReadOnlyTargetRules Target) : base(Target)
|
||||
{
|
||||
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
|
||||
|
||||
PublicDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"Core",
|
||||
}
|
||||
);
|
||||
|
||||
PrivateDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"CoreUObject",
|
||||
"Engine",
|
||||
|
||||
"HarmonyLinkUE"
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
22
Source/HarmonyLinkSettings/Private/HarmonyLinkSettings.cpp
Normal file
22
Source/HarmonyLinkSettings/Private/HarmonyLinkSettings.cpp
Normal file
|
@ -0,0 +1,22 @@
|
|||
#include "HarmonyLinkSettings.h"
|
||||
|
||||
#include "Objects/HarmonyLinkGraphics.h"
|
||||
|
||||
#define LOCTEXT_NAMESPACE "FHarmonyLinkSettingsModule"
|
||||
|
||||
DEFINE_LOG_CATEGORY(LogHarmonyLinkSettings);
|
||||
|
||||
void FHarmonyLinkSettingsModule::StartupModule()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void FHarmonyLinkSettingsModule::ShutdownModule()
|
||||
{
|
||||
// Ensure we safely destroy our singleton instance
|
||||
UHarmonyLinkGraphics::DestroySettings();
|
||||
}
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
|
||||
IMPLEMENT_MODULE(FHarmonyLinkSettingsModule, HarmonyLinkSettings)
|
|
@ -0,0 +1,798 @@
|
|||
// Copyright (C) 2024 Jordon Brooks
|
||||
|
||||
|
||||
#include "Objects/HarmonyLinkGraphics.h"
|
||||
#include "ComponentRecreateRenderStateContext.h"
|
||||
#include "HarmonyLinkSettings.h"
|
||||
#include "HarmonyLinkLibrary.h"
|
||||
#include "GameFramework/GameUserSettings.h"
|
||||
#include "Kismet/GameplayStatics.h"
|
||||
|
||||
UHarmonyLinkGraphics* UHarmonyLinkGraphics::_INSTANCE = nullptr;
|
||||
int32 UHarmonyLinkGraphics::_TickRate = 1;
|
||||
FTimerHandle UHarmonyLinkGraphics::_TickTimerHandle = FTimerHandle();
|
||||
TSharedPtr<FConfigFile> UHarmonyLinkGraphics::_ConfigFile = nullptr;
|
||||
bool UHarmonyLinkGraphics::_bAutomaticSwitch = false;
|
||||
int32 UHarmonyLinkGraphics::_LastBatteryPercentage = 0;
|
||||
EProfile UHarmonyLinkGraphics::_ActiveProfile = EProfile::NONE;
|
||||
TMap<EProfile, FSettingsProfile> UHarmonyLinkGraphics::_Profiles = TMap<EProfile, FSettingsProfile>();
|
||||
|
||||
TMap<EProfile, FName> UHarmonyLinkGraphics::_ProfileNames =
|
||||
{
|
||||
{EProfile::BATTERY, "Battery"},
|
||||
{EProfile::CHARGING, "Charging"},
|
||||
{EProfile::DOCKED, "Docked"},
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Default graphics settings for different power states in HarmonyLink.
|
||||
*
|
||||
* This map defines the default configuration values for various graphics settings based on the power state of the device.
|
||||
* The outer map's key is the power state (e.g., "Battery", "Charging", "Docked").
|
||||
* The inner map contains key-value pairs where the key is the setting name and the value is the corresponding configuration value.
|
||||
*
|
||||
* Power States:
|
||||
* - "Battery": Settings for when the device is running on battery power.
|
||||
* - "Charging": Settings for when the device is charging.
|
||||
* - "Docked": Settings for when the device is docked.
|
||||
*/
|
||||
TMap<FName, TMap<FName, FHLConfigValue>> UHarmonyLinkGraphics::_DefaultSettings = {
|
||||
{ "Battery", {
|
||||
// { TEXT("r.ReflectionMethod"), FHLConfigValue(0) },
|
||||
// { TEXT("r.DynamicGlobalIlluminationMethod"), FHLConfigValue(2) },
|
||||
// { TEXT("r.Shadow.Virtual.Enable"), FHLConfigValue(0) },
|
||||
// { TEXT("r.ScreenPercentage"), FHLConfigValue(50) },
|
||||
}},
|
||||
{ "Charging", {
|
||||
// { TEXT("r.ReflectionMethod"), FHLConfigValue(2) },
|
||||
// { TEXT("r.DynamicGlobalIlluminationMethod"), FHLConfigValue(2) },
|
||||
// { TEXT("r.Shadow.Virtual.Enable"), FHLConfigValue(1) },
|
||||
// { TEXT("r.ScreenPercentage"), FHLConfigValue(100) },
|
||||
}},
|
||||
{ "Docked", {
|
||||
// { TEXT("r.ReflectionMethod"), FHLConfigValue(2) },
|
||||
// { TEXT("r.DynamicGlobalIlluminationMethod"), FHLConfigValue(2) },
|
||||
// { TEXT("r.Shadow.Virtual.Enable"), FHLConfigValue(1) },
|
||||
// { TEXT("r.ScreenPercentage"), FHLConfigValue(100) },
|
||||
}}
|
||||
};
|
||||
|
||||
UHarmonyLinkGraphics::~UHarmonyLinkGraphics()
|
||||
{
|
||||
UE_LOG(LogHarmonyLinkSettings, Verbose, TEXT("~UHarmonyLinkGraphics called."));
|
||||
FWorldDelegates::OnPostWorldInitialization.RemoveAll(this);
|
||||
FWorldDelegates::OnPreWorldFinishDestroy.RemoveAll(this);
|
||||
}
|
||||
|
||||
void UHarmonyLinkGraphics::LoadConfig(const bool bForceReload)
|
||||
{
|
||||
UE_LOG(LogHarmonyLinkSettings, Verbose, TEXT("LoadConfig called."));
|
||||
QUICK_SCOPE_CYCLE_COUNTER(HarmonyLinkGraphics_LoadSettings);
|
||||
|
||||
// Load the settings into the map
|
||||
FConfigFile* _ = GetConfig();
|
||||
|
||||
DebugPrintProfiles();
|
||||
}
|
||||
|
||||
bool UHarmonyLinkGraphics::LoadSettingsFromConfig(FConfigFile* ConfigFile) const
|
||||
{
|
||||
UE_LOG(LogHarmonyLinkSettings, Verbose, TEXT("LoadSettingsFromConfig called."));
|
||||
//const FString Filename = "HarmonyLink"; //GetConfigDirectoryFile(bLoadDefaults);
|
||||
|
||||
// Load each profile section
|
||||
bool bLoaded = true;
|
||||
|
||||
// Load the _bAutomaticSwitch variable
|
||||
const FString SectionName = TEXT("HarmonyLink");
|
||||
const FString KeyName = TEXT("AutomaticProfileSwitch");
|
||||
|
||||
if (!ConfigFile->GetBool(*SectionName, *KeyName, _bAutomaticSwitch))
|
||||
{
|
||||
UE_LOG(LogHarmonyLinkSettings, Error, TEXT("Failed to load bAutomaticSwitch from config"));
|
||||
bLoaded = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(LogHarmonyLinkSettings, Log, TEXT("Loaded bAutomaticSwitch: %s"), _bAutomaticSwitch ? TEXT("true") : TEXT("false"));
|
||||
}
|
||||
|
||||
for (const TPair<EProfile, FName>& Profile : _ProfileNames)
|
||||
{
|
||||
if (!LoadSection(ConfigFile, Profile))
|
||||
{
|
||||
UE_LOG(LogHarmonyLinkSettings, Error, TEXT("Failed to load section: '%s'"), *Profile.Value.ToString());
|
||||
bLoaded = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if all profiles and settings were loaded successfully
|
||||
if (bLoaded)
|
||||
{
|
||||
UE_LOG(LogHarmonyLinkSettings, Log, TEXT("Successfully loaded config."));
|
||||
return true;
|
||||
}
|
||||
|
||||
UE_LOG(LogHarmonyLinkSettings, Error, TEXT("Failed to load config file."));
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UHarmonyLinkGraphics::LoadSection(FConfigFile* ConfigFile, const TPair<EProfile, FName> Profile)
|
||||
{
|
||||
UE_LOG(LogHarmonyLinkSettings, Verbose, TEXT("LoadSection called."));
|
||||
if (!ensureMsgf(ConfigFile, TEXT("ConfigFile is nullptr!"))) return false;
|
||||
|
||||
const FName& SectionName = Profile.Value;
|
||||
const EProfile ProfileKey = Profile.Key;
|
||||
|
||||
const FConfigSection* Section = nullptr;
|
||||
|
||||
|
||||
#if (ENGINE_MAJOR_VERSION >= 5)
|
||||
Section = ConfigFile->FindSection(*SectionName.ToString());
|
||||
#elif (ENGINE_MAJOR_VERSION == 4) && (ENGINE_MINOR_VERSION >= 27)
|
||||
Section = ConfigFile->FindOrAddSection(*SectionName.ToString());
|
||||
#else
|
||||
#error "Unsupported Unreal Engine version"
|
||||
#endif
|
||||
|
||||
if (Section)
|
||||
{
|
||||
FSettingsProfile& SettingsProfile = _Profiles.FindOrAdd(ProfileKey);
|
||||
SettingsProfile.SectionName = SectionName;
|
||||
SettingsProfile.Settings.Empty(); // Clear previous settings
|
||||
|
||||
for (const auto& ValueIt : *Section)
|
||||
{
|
||||
FString ValueString = ValueIt.Value.GetValue();
|
||||
FString Value, Type;
|
||||
|
||||
// Parse the Value and Type from the string
|
||||
if (ValueString.Split(TEXT(", Type="), &Value, &Type))
|
||||
{
|
||||
Value = Value.RightChop(7); // Remove "(Value=" prefix
|
||||
Type = Type.LeftChop(1); // Remove ")" suffix
|
||||
|
||||
if (Type == "int")
|
||||
{
|
||||
const int32 IntValue = FCString::Atoi(*Value);
|
||||
SettingsProfile.Settings.Add(ValueIt.Key, FHLConfigValue(IntValue));
|
||||
}
|
||||
else if (Type == "float")
|
||||
{
|
||||
const float FloatValue = FCString::Atof(*Value);
|
||||
SettingsProfile.Settings.Add(ValueIt.Key, FHLConfigValue(FloatValue));
|
||||
}
|
||||
else if (Type == "bool")
|
||||
{
|
||||
const bool BoolValue = Value == "true";
|
||||
SettingsProfile.Settings.Add(ValueIt.Key, FHLConfigValue(BoolValue));
|
||||
}
|
||||
else if (Type == "string")
|
||||
{
|
||||
SettingsProfile.Settings.Add(ValueIt.Key, FHLConfigValue(Value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void UHarmonyLinkGraphics::SaveConfig() const
|
||||
{
|
||||
UE_LOG(LogHarmonyLinkSettings, Verbose, TEXT("SaveConfig called."));
|
||||
Intermal_SaveConfig(false);
|
||||
}
|
||||
|
||||
void UHarmonyLinkGraphics::SetSetting(const EProfile Profile, const FName Setting, const FHLConfigValue& Value)
|
||||
{
|
||||
UE_LOG(LogHarmonyLinkSettings, Verbose, TEXT("SetSetting called."));
|
||||
// Ignore if HarmonyLinkSettings is disabled
|
||||
if (Profile == EProfile::NONE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Find the profile name associated with the given EProfile
|
||||
const FName* ProfileName = _ProfileNames.Find(Profile);
|
||||
|
||||
if (!ProfileName)
|
||||
{
|
||||
UE_LOG(LogHarmonyLinkSettings, Error, TEXT("Profile not found."));
|
||||
return;
|
||||
}
|
||||
|
||||
FString TypeString;
|
||||
FString ValueString;
|
||||
|
||||
switch (Value.GetType())
|
||||
{
|
||||
case EConfigValueType::Int:
|
||||
ValueString = FString::FromInt(Value.GetValue<int32>());
|
||||
TypeString = TEXT("int");
|
||||
break;
|
||||
case EConfigValueType::Float:
|
||||
ValueString = FString::SanitizeFloat(Value.GetValue<float>());
|
||||
TypeString = TEXT("float");
|
||||
break;
|
||||
case EConfigValueType::Bool:
|
||||
ValueString = Value.GetValue<bool>() ? TEXT("True") : TEXT("False");
|
||||
TypeString = TEXT("bool");
|
||||
break;
|
||||
case EConfigValueType::String:
|
||||
ValueString = Value.GetValue<FString>();
|
||||
TypeString = TEXT("string");
|
||||
break;
|
||||
}
|
||||
|
||||
UE_LOG(LogHarmonyLinkSettings, Log, TEXT("Applying '%s': Value='%s', Type='%s' to profile '%s'."), *Setting.ToString(), *TypeString, *ValueString, *ProfileName->ToString());
|
||||
|
||||
// Find the settings associated with the profile
|
||||
FSettingsProfile* SettingsProfile = _Profiles.Find(Profile);
|
||||
|
||||
if (!SettingsProfile)
|
||||
{
|
||||
UE_LOG(LogHarmonyLinkSettings, Error, TEXT("No settings found for profile %s."), *ProfileName->ToString());
|
||||
return;
|
||||
}
|
||||
|
||||
SettingsProfile->Settings.FindOrAdd(Setting) = Value;
|
||||
}
|
||||
|
||||
|
||||
UHarmonyLinkGraphics* UHarmonyLinkGraphics::GetSettings()
|
||||
{
|
||||
UE_LOG(LogHarmonyLinkSettings, VeryVerbose, TEXT("GetSettings called."));
|
||||
// Check if we already initialised
|
||||
if (_INSTANCE)
|
||||
{
|
||||
return _INSTANCE;
|
||||
}
|
||||
|
||||
// Proceed to create a new singleton instance
|
||||
_INSTANCE = NewObject<UHarmonyLinkGraphics>();
|
||||
_INSTANCE->Init();
|
||||
|
||||
return _INSTANCE;
|
||||
}
|
||||
|
||||
FSettingsProfile UHarmonyLinkGraphics::GetSettingProfile(const EProfile Profile)
|
||||
{
|
||||
UE_LOG(LogHarmonyLinkSettings, Verbose, TEXT("GetSettingProfile called."));
|
||||
// Ignore if HarmonyLinkSettings is disabled
|
||||
if (Profile == EProfile::NONE)
|
||||
{
|
||||
return FSettingsProfile();
|
||||
}
|
||||
|
||||
// Find the profile name associated with the given EProfile
|
||||
const FName* ProfileName = _ProfileNames.Find(Profile);
|
||||
|
||||
if (!ProfileName)
|
||||
{
|
||||
UE_LOG(LogHarmonyLinkSettings, Error, TEXT("Profile not found."));
|
||||
return FSettingsProfile();
|
||||
}
|
||||
|
||||
// Find the settings associated with the profile
|
||||
FSettingsProfile* SettingsProfile = _Profiles.Find(Profile);
|
||||
|
||||
if (!SettingsProfile)
|
||||
{
|
||||
UE_LOG(LogHarmonyLinkSettings, Error, TEXT("No settings found for profile %s."), *ProfileName->ToString());
|
||||
return FSettingsProfile();
|
||||
}
|
||||
|
||||
return *SettingsProfile;
|
||||
}
|
||||
|
||||
EProfile UHarmonyLinkGraphics::GetActiveProfile() const
|
||||
{
|
||||
UE_LOG(LogHarmonyLinkSettings, Verbose, TEXT("GetActiveProfile called."));
|
||||
return _ActiveProfile;
|
||||
}
|
||||
|
||||
void UHarmonyLinkGraphics::SetAutomaticSwitching(const bool bAutomaticSwitch)
|
||||
{
|
||||
UE_LOG(LogHarmonyLinkSettings, Verbose, TEXT("SetAutomaticSwitching called."));
|
||||
_bAutomaticSwitch = bAutomaticSwitch;
|
||||
OnAutomaticSwitchChanged.Broadcast(_bAutomaticSwitch);
|
||||
}
|
||||
|
||||
bool UHarmonyLinkGraphics::GetAutomaticSwitching() const
|
||||
{
|
||||
UE_LOG(LogHarmonyLinkSettings, Verbose, TEXT("GetAutomaticSwitching called."));
|
||||
return _bAutomaticSwitch;
|
||||
}
|
||||
|
||||
void UHarmonyLinkGraphics::DestroySettings()
|
||||
{
|
||||
UE_LOG(LogHarmonyLinkSettings, Log, TEXT("DestroySettings called."));
|
||||
if (_INSTANCE)
|
||||
{
|
||||
UE_LOG(LogHarmonyLinkSettings, Log, TEXT("Destroying UHarmonyLinkGraphics."))
|
||||
FWorldDelegates::OnPostWorldInitialization.RemoveAll(_INSTANCE);
|
||||
FWorldDelegates::OnPreWorldFinishDestroy.RemoveAll(_INSTANCE);
|
||||
_INSTANCE->RemoveFromRoot();
|
||||
|
||||
#if (ENGINE_MAJOR_VERSION >= 5)
|
||||
_INSTANCE->MarkAsGarbage(); // For UE 5.0 and above
|
||||
#elif (ENGINE_MAJOR_VERSION == 4) && (ENGINE_MINOR_VERSION >= 27)
|
||||
_INSTANCE->MarkPendingKill(); // For UE 4.27 and above
|
||||
#else
|
||||
#error "Unsupported Unreal Engine version"
|
||||
#endif
|
||||
|
||||
_INSTANCE = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void UHarmonyLinkGraphics::Init()
|
||||
{
|
||||
UE_LOG(LogHarmonyLinkSettings, Warning, TEXT("HarmonyLinkGraphics initialized."));
|
||||
if (_INSTANCE != this)
|
||||
{
|
||||
if (_INSTANCE)
|
||||
{
|
||||
DestroySettings();
|
||||
}
|
||||
|
||||
_INSTANCE = this;
|
||||
}
|
||||
|
||||
AddToRoot();
|
||||
|
||||
FWorldDelegates::OnPostWorldInitialization.AddStatic(&UHarmonyLinkGraphics::OnPostWorldInitialization);
|
||||
FWorldDelegates::OnPreWorldFinishDestroy.AddStatic(&UHarmonyLinkGraphics::OnWorldEnd);
|
||||
|
||||
UE_LOG(LogHarmonyLinkSettings, Log, TEXT("Init called."));
|
||||
|
||||
if (!UHarmonyLinkLibrary::IsInitialised())
|
||||
{
|
||||
UE_LOG(LogHarmonyLinkSettings, Fatal, TEXT("Failed to initialise HarmonyLinkLib!"));
|
||||
return;
|
||||
}
|
||||
|
||||
LoadConfig();
|
||||
|
||||
const FBattery BatteryStatus = UHarmonyLinkLibrary::GetBatteryStatus();
|
||||
|
||||
if (BatteryStatus.HasBattery)
|
||||
{
|
||||
if (BatteryStatus.IsACConnected)
|
||||
{
|
||||
ApplyProfileInternal(EProfile::BATTERY);
|
||||
}
|
||||
else
|
||||
{
|
||||
ApplyProfileInternal(EProfile::CHARGING);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UHarmonyLinkGraphics::Intermal_SaveConfig(const bool bDefaultConfig) const
|
||||
{
|
||||
UE_LOG(LogHarmonyLinkSettings, Log, TEXT("Intermal_SaveConfig called."));
|
||||
QUICK_SCOPE_CYCLE_COUNTER(HarmonyLinkGraphics_SaveConfig);
|
||||
|
||||
const FString Filename = GetConfigDirectoryFile(bDefaultConfig);
|
||||
const FString SectionName = TEXT("HarmonyLink");
|
||||
const FString KeyName = TEXT("AutomaticProfileSwitch");
|
||||
|
||||
// Save the _bAutomaticSwitch variable
|
||||
GConfig->SetBool(*SectionName, *KeyName, _bAutomaticSwitch, Filename);
|
||||
|
||||
UE_LOG(LogHarmonyLinkSettings, Log, TEXT("Saving bAutomaticSwitch: %s"), _bAutomaticSwitch ? TEXT("true") : TEXT("false"));
|
||||
|
||||
for (const TPair<EProfile, FSettingsProfile>& Profile : _Profiles)
|
||||
{
|
||||
SaveSection(Profile.Value, bDefaultConfig);
|
||||
}
|
||||
|
||||
UE_LOG(LogHarmonyLinkSettings, Log, TEXT("Flushing file: '%s'"), *Filename);
|
||||
GetConfig()->Dirty = true;
|
||||
// You'd think that Write would actually write something but for some
|
||||
// reason even if it outputs a success the file doesn't actually get created.
|
||||
// For this reason, Flush seems to work for now.
|
||||
//GetConfig()->Write(Filename);
|
||||
GConfig->Flush(true, Filename);
|
||||
}
|
||||
|
||||
void UHarmonyLinkGraphics::Tick()
|
||||
{
|
||||
UE_LOG(LogHarmonyLinkSettings, VeryVerbose, TEXT("Tick called."));
|
||||
const FBattery BatteryStatus = UHarmonyLinkLibrary::GetBatteryStatus();
|
||||
|
||||
if (BatteryStatus.BatteryPercent != _LastBatteryPercentage)
|
||||
{
|
||||
// Ensure thread-safe broadcasting
|
||||
OnBatteryLevelChanged.Broadcast(BatteryStatus.BatteryPercent);
|
||||
}
|
||||
|
||||
if (!_bAutomaticSwitch)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (BatteryStatus.HasBattery)
|
||||
{
|
||||
if (BatteryStatus.IsACConnected)
|
||||
{
|
||||
if (_ActiveProfile != EProfile::CHARGING)
|
||||
{
|
||||
ApplyProfileInternal(EProfile::CHARGING);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_ActiveProfile != EProfile::BATTERY)
|
||||
{
|
||||
ApplyProfileInternal(EProfile::BATTERY);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UHarmonyLinkGraphics::CreateDefaultConfigFile() const
|
||||
{
|
||||
UE_LOG(LogHarmonyLinkSettings, Log, TEXT("CreateDefaultConfigFile called."));
|
||||
UE_LOG(LogHarmonyLinkSettings, Log, TEXT("Creating default config file."));
|
||||
|
||||
LoadDefaults();
|
||||
Intermal_SaveConfig(true);
|
||||
|
||||
UE_LOG(LogHarmonyLinkSettings, Log, TEXT("Default config file created."));
|
||||
}
|
||||
|
||||
FString UHarmonyLinkGraphics::GetConfigDirectoryFile(const bool bDefaultFolder)
|
||||
{
|
||||
UE_LOG(LogHarmonyLinkSettings, Log, TEXT("GetConfigDirectoryFile called."));
|
||||
FString ConfigFileName = bDefaultFolder ? TEXT("DefaultHarmonyLink.ini") : TEXT("HarmonyLink.ini");
|
||||
|
||||
FString ConfigDirectory = bDefaultFolder ? FPaths::ProjectConfigDir() : FPaths::Combine(FPaths::GeneratedConfigDir(), UGameplayStatics::GetPlatformName());
|
||||
|
||||
return FPaths::Combine(ConfigDirectory, ConfigFileName);
|
||||
}
|
||||
|
||||
void UHarmonyLinkGraphics::SaveSection(const FSettingsProfile& SettingsProfile, const bool bDefaultConfig, const bool bFlush) const
|
||||
{
|
||||
UE_LOG(LogHarmonyLinkSettings, Log, TEXT("SaveSection called."));
|
||||
if (GConfig)
|
||||
{
|
||||
const FString Filename = GetConfigDirectoryFile(bDefaultConfig);
|
||||
for (const auto& Setting : SettingsProfile.Settings)
|
||||
{
|
||||
FString TypeString;
|
||||
FString ValueString;
|
||||
|
||||
switch (Setting.Value.GetType())
|
||||
{
|
||||
case EConfigValueType::Int:
|
||||
ValueString = FString::FromInt(Setting.Value.GetValue<int32>());
|
||||
TypeString = TEXT("int");
|
||||
break;
|
||||
case EConfigValueType::Float:
|
||||
ValueString = FString::SanitizeFloat(Setting.Value.GetValue<float>());
|
||||
TypeString = TEXT("float");
|
||||
break;
|
||||
case EConfigValueType::Bool:
|
||||
ValueString = Setting.Value.GetValue<bool>() ? TEXT("True") : TEXT("False");
|
||||
TypeString = TEXT("bool");
|
||||
break;
|
||||
case EConfigValueType::String:
|
||||
ValueString = Setting.Value.GetValue<FString>();
|
||||
TypeString = TEXT("string");
|
||||
break;
|
||||
}
|
||||
|
||||
const FString ConfigValue = FString::Printf(TEXT("(Value=%s, Type=%s)"), *ValueString, *TypeString);
|
||||
GConfig->SetString(*SettingsProfile.SectionName.ToString(), *Setting.Key.ToString(), *ConfigValue, Filename);
|
||||
}
|
||||
|
||||
UE_LOG(LogHarmonyLinkSettings, Log, TEXT("Saving config file: '%s'"), *Filename);
|
||||
if (bFlush)
|
||||
{
|
||||
UE_LOG(LogHarmonyLinkSettings, Log, TEXT("Flushing file: '%s'"), *Filename);
|
||||
GConfig->Flush(false, Filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UHarmonyLinkGraphics::LoadDefaults() const
|
||||
{
|
||||
UE_LOG(LogHarmonyLinkSettings, Log, TEXT("LoadDefaults called."));
|
||||
|
||||
_Profiles.Reset();
|
||||
|
||||
// Iterate over ProfileNames to create default settings
|
||||
for (const TPair<EProfile, FName>& Profile : _ProfileNames)
|
||||
{
|
||||
FSettingsProfile NewProfileSettings;
|
||||
NewProfileSettings.SectionName = Profile.Value;
|
||||
|
||||
if (const TMap<FName, FHLConfigValue>* Settings = _DefaultSettings.Find(Profile.Value))
|
||||
{
|
||||
NewProfileSettings.Settings = *Settings;
|
||||
}
|
||||
|
||||
_Profiles.Add(Profile.Key, NewProfileSettings);
|
||||
}
|
||||
}
|
||||
|
||||
bool UHarmonyLinkGraphics::ApplyProfileInternal(const EProfile Profile)
|
||||
{
|
||||
UE_LOG(LogHarmonyLinkSettings, Log, TEXT("ApplyProfileInternal called."));
|
||||
// If the profile is None, revert to the original user game settings
|
||||
if (Profile == EProfile::NONE)
|
||||
{
|
||||
UE_LOG(LogHarmonyLinkSettings, Log, TEXT("Reverting to original user game settings."));
|
||||
|
||||
if (UGameUserSettings* UserSettings = GEngine->GetGameUserSettings())
|
||||
{
|
||||
UserSettings->LoadSettings(true);
|
||||
UserSettings->ApplySettings(true);
|
||||
_ActiveProfile = EProfile::NONE;
|
||||
OnProfileChanged.Broadcast(_ActiveProfile);
|
||||
UE_LOG(LogHarmonyLinkSettings, Log, TEXT("Original user game settings applied."));
|
||||
return true;
|
||||
}
|
||||
|
||||
UE_LOG(LogHarmonyLinkSettings, Warning, TEXT("Failed to get user game settings."));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Find the profile name associated with the given EProfile
|
||||
const FName* ProfileName = _ProfileNames.Find(Profile);
|
||||
|
||||
if (!ProfileName)
|
||||
{
|
||||
UE_LOG(LogHarmonyLinkSettings, Error, TEXT("Profile not found."));
|
||||
return false;
|
||||
}
|
||||
|
||||
UE_LOG(LogHarmonyLinkSettings, Log, TEXT("Applying profile %s."), *ProfileName->ToString());
|
||||
|
||||
// Find the settings associated with the profile
|
||||
FSettingsProfile* SettingsProfile = _Profiles.Find(Profile);
|
||||
|
||||
if (!SettingsProfile)
|
||||
{
|
||||
UE_LOG(LogHarmonyLinkSettings, Warning, TEXT("No settings found for profile %s."), *ProfileName->ToString());
|
||||
return false;
|
||||
}
|
||||
|
||||
{
|
||||
FGlobalComponentRecreateRenderStateContext Context;
|
||||
|
||||
// Example of applying settings (actual application depends on your implementation)
|
||||
for (const TPair<FName, FHLConfigValue>& Setting : SettingsProfile->Settings)
|
||||
{
|
||||
// Example of logging each setting being applied
|
||||
UE_LOG(LogHarmonyLinkSettings, Log, TEXT("Patching CVar override: %s = %s"),
|
||||
*Setting.Key.ToString(), *Setting.Value.ToString());
|
||||
|
||||
ApplySetting(Setting);
|
||||
}
|
||||
}
|
||||
|
||||
_ActiveProfile = Profile;
|
||||
OnProfileChanged.Broadcast(_ActiveProfile);
|
||||
return true;
|
||||
}
|
||||
|
||||
void UHarmonyLinkGraphics::OnPostWorldInitialization(UWorld* World, UWorld::InitializationValues IVS)
|
||||
{
|
||||
UE_LOG(LogHarmonyLinkSettings, Log, TEXT("OnPostWorldInitialization called."));
|
||||
if (!World || !World->IsValidLowLevel())
|
||||
{
|
||||
UE_LOG(LogHarmonyLinkSettings, Error, TEXT("Failed to Hook into World Initialisation!"))
|
||||
return;
|
||||
}
|
||||
|
||||
if (World->IsGameWorld())
|
||||
{
|
||||
if (IsValid(GetSettings()))
|
||||
{
|
||||
FTimerManager* TimerManager = &World->GetTimerManager();
|
||||
if (!TimerManager)
|
||||
{
|
||||
UE_LOG(LogHarmonyLinkSettings, Error, TEXT("Failed get TimerManager!"))
|
||||
return;
|
||||
}
|
||||
|
||||
if (!TimerManager->TimerExists(_TickTimerHandle) || !TimerManager->IsTimerActive(_TickTimerHandle))
|
||||
{
|
||||
|
||||
World->GetTimerManager().SetTimer(_TickTimerHandle, [TimerManager]
|
||||
{
|
||||
if (!GetSettings())
|
||||
{
|
||||
UE_LOG(LogHarmonyLinkSettings, Error, TEXT("'This' is destroyed, Clearing timer."))
|
||||
if (TimerManager)
|
||||
{
|
||||
TimerManager->ClearTimer(_TickTimerHandle);
|
||||
}
|
||||
return;
|
||||
}
|
||||
GetSettings()->Tick();
|
||||
}, _TickRate, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(LogHarmonyLinkSettings, Error, TEXT("Error: Timer already exists."));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(LogHarmonyLinkSettings, Error, TEXT("'This' is nullptr!"));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//UE_LOG(LogHarmonyLink, Error, TEXT("Failed to bring up tick!"));
|
||||
}
|
||||
}
|
||||
|
||||
void UHarmonyLinkGraphics::OnWorldEnd(UWorld* World)
|
||||
{
|
||||
UE_LOG(LogHarmonyLinkSettings, Log, TEXT("OnWorldEnd(UWorld* World) called."));
|
||||
if (!World)
|
||||
{
|
||||
UE_LOG(LogHarmonyLinkSettings, Error, TEXT("World Already destroyed"))
|
||||
return;
|
||||
}
|
||||
|
||||
if (!World->IsGameWorld())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(World->GetTimerManager().TimerExists(_TickTimerHandle))
|
||||
{
|
||||
World->GetTimerManager().ClearTimer(_TickTimerHandle);
|
||||
}
|
||||
|
||||
// Ensure we safely destroy our singleton instance
|
||||
DestroySettings();
|
||||
}
|
||||
|
||||
bool UHarmonyLinkGraphics::ApplyProfile(const EProfile Profile, const bool bDisableAutomaticSwitch)
|
||||
{
|
||||
UE_LOG(LogHarmonyLinkSettings, Log, TEXT("Applying Profile."));
|
||||
// Manual profile change, turn off automatic switching
|
||||
if (bDisableAutomaticSwitch)
|
||||
{
|
||||
_bAutomaticSwitch = false;
|
||||
}
|
||||
|
||||
return ApplyProfileInternal(Profile);
|
||||
}
|
||||
|
||||
void UHarmonyLinkGraphics::ApplySetting(const TPair<FName, FHLConfigValue>& Setting)
|
||||
{
|
||||
UE_LOG(LogHarmonyLinkSettings, Log, TEXT("Applying settings."));
|
||||
// Apply the setting based on the key (CVar)
|
||||
IConsoleManager& ConsoleManager = IConsoleManager::Get();
|
||||
IConsoleVariable* CVar = ConsoleManager.FindConsoleVariable(*Setting.Key.ToString());
|
||||
|
||||
if (CVar)
|
||||
{
|
||||
switch (Setting.Value.GetType())
|
||||
{
|
||||
case EConfigValueType::Bool:
|
||||
CVar->Set(Setting.Value.GetValue<bool>(), ECVF_SetByGameSetting);
|
||||
break;
|
||||
|
||||
case EConfigValueType::Float:
|
||||
CVar->Set(Setting.Value.GetValue<float>(), ECVF_SetByGameSetting);
|
||||
break;
|
||||
|
||||
case EConfigValueType::Int:
|
||||
CVar->Set(Setting.Value.GetValue<int32>(), ECVF_SetByGameSetting);
|
||||
break;
|
||||
|
||||
default:
|
||||
UE_LOG(LogHarmonyLinkSettings, Warning, TEXT("Unsupported value type for setting: %s"), *Setting.Key.ToString());
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(LogHarmonyLinkSettings, Warning, TEXT("Console variable not found: %s"), *Setting.Key.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
void UHarmonyLinkGraphics::DebugPrintProfiles() const
|
||||
{
|
||||
UE_LOG(LogHarmonyLinkSettings, Log, TEXT("DebugPrintProfiles started."));
|
||||
|
||||
for (TPair<EProfile, FSettingsProfile> Profile : _Profiles)
|
||||
{
|
||||
PrintDebugSection(Profile.Value);
|
||||
}
|
||||
|
||||
UE_LOG(LogHarmonyLinkSettings, Log, TEXT("DebugPrintProfiles completed."));
|
||||
}
|
||||
|
||||
FConfigFile* UHarmonyLinkGraphics::GetConfig() const
|
||||
{
|
||||
UE_LOG(LogHarmonyLinkSettings, Verbose, TEXT("GetConfig Called."));
|
||||
if (_ConfigFile)
|
||||
{
|
||||
return _ConfigFile.Get();
|
||||
}
|
||||
|
||||
FConfigFile* ConfigFile = GConfig->Find(GetConfigDirectoryFile(false), false);
|
||||
|
||||
if (!ConfigFile)
|
||||
{
|
||||
UE_LOG(LogHarmonyLinkSettings, Warning, TEXT("Config file not found, attempting to read DefaultHarmonyLink.ini."));
|
||||
// Look in ProjectFolder->Config->DefaultHarmonyLink.ini
|
||||
ConfigFile = GConfig->Find(GetConfigDirectoryFile(true), true);
|
||||
}
|
||||
|
||||
/*if (!ConfigFile)
|
||||
{
|
||||
CreateDefaultConfigFile();
|
||||
ConfigFile = GConfig->Find(GetConfigDirectoryFile(true), true);
|
||||
}*/
|
||||
|
||||
if (ConfigFile)
|
||||
{
|
||||
UE_LOG(LogHarmonyLinkSettings, Verbose, TEXT("Setting up config."));
|
||||
ConfigFile->Name = "HarmonyLink";
|
||||
LoadSettingsFromConfig(ConfigFile);
|
||||
_ConfigFile = MakeShareable(ConfigFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(LogHarmonyLinkSettings, Error, TEXT("Failed to make config variable!"))
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return _ConfigFile.Get();
|
||||
}
|
||||
|
||||
void UHarmonyLinkGraphics::PrintDebugSection(FSettingsProfile& SettingsProfile)
|
||||
{
|
||||
UE_LOG(LogHarmonyLinkSettings, Warning, TEXT("[%s]"), *SettingsProfile.SectionName.ToString());
|
||||
|
||||
for (const auto& Setting : SettingsProfile.Settings)
|
||||
{
|
||||
FString ValueString;
|
||||
FString TypeString;
|
||||
|
||||
switch (Setting.Value.GetType())
|
||||
{
|
||||
case EConfigValueType::Int:
|
||||
ValueString = FString::FromInt(Setting.Value.GetValue<int32>());
|
||||
TypeString = TEXT("int");
|
||||
break;
|
||||
case EConfigValueType::Float:
|
||||
ValueString = FString::SanitizeFloat(Setting.Value.GetValue<float>());
|
||||
TypeString = TEXT("float");
|
||||
break;
|
||||
case EConfigValueType::Bool:
|
||||
ValueString = Setting.Value.GetValue<bool>() ? TEXT("true") : TEXT("false");
|
||||
TypeString = TEXT("bool");
|
||||
break;
|
||||
case EConfigValueType::String:
|
||||
ValueString = Setting.Value.GetValue<FString>();
|
||||
TypeString = TEXT("string");
|
||||
break;
|
||||
}
|
||||
|
||||
UE_LOG(LogHarmonyLinkSettings, Warning, TEXT("Key: %s = V=%s, T=%s "), *Setting.Key.ToString(), *ValueString, *TypeString);
|
||||
}
|
||||
}
|
||||
|
||||
void UHarmonyLinkGraphics::ResetInstance()
|
||||
{
|
||||
UE_LOG(LogHarmonyLinkSettings, Log, TEXT("Resetting instance."));
|
||||
_INSTANCE->DestroySettings();
|
||||
GetSettings();
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
// Copyright (C) 2024 Jordon Brooks
|
||||
|
||||
#include "Structs/HLConfigValue.h"
|
18
Source/HarmonyLinkSettings/Public/Enums/Profile.h
Normal file
18
Source/HarmonyLinkSettings/Public/Enums/Profile.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
// Copyright (C) 2024 Jordon Brooks
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Profile.generated.h"
|
||||
|
||||
/*
|
||||
* Enum representing different operating system platforms.
|
||||
*/
|
||||
UENUM(BlueprintType)
|
||||
enum class EProfile : uint8
|
||||
{
|
||||
NONE = 0 UMETA(DisplayName = "NONE"),
|
||||
BATTERY UMETA(DisplayName = "BATTERY"),
|
||||
CHARGING UMETA(DisplayName = "CHARGING"),
|
||||
DOCKED UMETA(DisplayName = "DOCKED"),
|
||||
};
|
13
Source/HarmonyLinkSettings/Public/HarmonyLinkSettings.h
Normal file
13
Source/HarmonyLinkSettings/Public/HarmonyLinkSettings.h
Normal file
|
@ -0,0 +1,13 @@
|
|||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Modules/ModuleManager.h"
|
||||
|
||||
DECLARE_LOG_CATEGORY_EXTERN(LogHarmonyLinkSettings, Log, All);
|
||||
|
||||
class FHarmonyLinkSettingsModule : public IModuleInterface
|
||||
{
|
||||
public:
|
||||
virtual void StartupModule() override;
|
||||
virtual void ShutdownModule() override;
|
||||
};
|
499
Source/HarmonyLinkSettings/Public/Objects/HarmonyLinkGraphics.h
Normal file
499
Source/HarmonyLinkSettings/Public/Objects/HarmonyLinkGraphics.h
Normal file
|
@ -0,0 +1,499 @@
|
|||
// Copyright (C) 2024 Jordon Brooks
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Enums/Profile.h"
|
||||
#include "Structs/SettingsProfile.h"
|
||||
|
||||
#include "Kismet/BlueprintFunctionLibrary.h"
|
||||
#include "HarmonyLinkGraphics.generated.h"
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnProfileChanged, EProfile, Profile);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnAutomaticSwitchChanged, bool, bAutomaticSwich);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnBatteryLevelChanged, int32, BatteryPercent);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS(Blueprintable, config="HarmonyLink")
|
||||
class HARMONYLINKSETTINGS_API UHarmonyLinkGraphics : public UBlueprintFunctionLibrary
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
virtual ~UHarmonyLinkGraphics() override;
|
||||
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FOnProfileChanged OnProfileChanged;
|
||||
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FOnAutomaticSwitchChanged OnAutomaticSwitchChanged;
|
||||
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FOnBatteryLevelChanged OnBatteryLevelChanged;
|
||||
|
||||
/**
|
||||
* @brief Loads the graphics configuration settings.
|
||||
*
|
||||
* This function loads the graphics settings into the appropriate map. If the initial loading attempt fails,
|
||||
* it retries a second time. The settings are loaded using the `LoadSettingsFromConfig` method.
|
||||
* After loading the settings, the function prints debug information about the profiles.
|
||||
*
|
||||
* @param bForceReload Indicates whether to force reload the settings. Defaults to false.
|
||||
*
|
||||
* @note This function uses the QUICK_SCOPE_CYCLE_COUNTER macro for performance profiling.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category="HarmonyLink Settings")
|
||||
void LoadConfig(const bool bForceReload = false);
|
||||
|
||||
/**
|
||||
* @brief Saves the current graphics configuration settings to the configuration file.
|
||||
*
|
||||
* This function iterates through all profiles and saves their settings to the configuration file.
|
||||
* Additionally, it saves the `_bAutomaticSwitch` variable to the configuration file and flushes the changes.
|
||||
*
|
||||
* @details
|
||||
* - Uses the QUICK_SCOPE_CYCLE_COUNTER macro for performance profiling.
|
||||
* - Iterates through the `_Profiles` map and calls `SaveSection` for each profile to save its settings.
|
||||
* - Saves the `_bAutomaticSwitch` variable under the "HarmonyLink" section with the key "AutomaticProfileSwitch".
|
||||
* - Logs the status of `_bAutomaticSwitch` and flushes the configuration file to ensure all changes are written.
|
||||
*
|
||||
* @note Uses UE_LOG for logging the save process and status messages.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category="HarmonyLink Settings")
|
||||
void SaveConfig() const;
|
||||
|
||||
/**
|
||||
* @brief Sets a specific configuration value for a given profile.
|
||||
*
|
||||
* This function updates a setting for a specified profile with a new value. It handles various data types (int, float, bool, string)
|
||||
* and logs the process. If the profile or settings cannot be found, it logs an error message.
|
||||
*
|
||||
* @param Profile The profile identifier for which the setting is to be updated.
|
||||
* @param Setting The name of the setting to update.
|
||||
* @param Value The new value to set for the specified setting.
|
||||
*
|
||||
* @details
|
||||
* - Finds the profile name associated with the given `EProfile`.
|
||||
* - Determines the type of the value and converts it to a string.
|
||||
* - Logs the application of the setting with its value and type.
|
||||
* - Finds the settings profile associated with the given profile.
|
||||
* - Updates the setting with the new value or adds it if it does not exist.
|
||||
*
|
||||
* @note Uses UE_LOG for logging the update process and any errors.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category="HarmonyLink Settings")
|
||||
void SetSetting(EProfile Profile, FName Setting, const FHLConfigValue& Value);
|
||||
|
||||
/**
|
||||
* @brief Applies the specified graphics profile.
|
||||
*
|
||||
* This function applies the given graphics profile. If automatic profile switching is enabled, it can be disabled by setting the `bDisableAutomaticSwitch` parameter to true.
|
||||
*
|
||||
* @param Profile The profile to apply.
|
||||
* @param bDisableAutomaticSwitch Indicates whether to disable automatic profile switching. Defaults to true.
|
||||
* @return bool Returns true if the profile was successfully applied; false otherwise.
|
||||
*
|
||||
* @details
|
||||
* - If `bDisableAutomaticSwitch` is true, sets `_bAutomaticSwitch` to false to disable automatic profile switching.
|
||||
* - Calls `ApplyProfileInternal` to apply the specified profile.
|
||||
* - Returns the result of `ApplyProfileInternal`.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category="HarmonyLink Settings")
|
||||
bool ApplyProfile(EProfile Profile, const bool bDisableAutomaticSwitch = true);
|
||||
|
||||
/**
|
||||
* @brief Retrieves the singleton instance of the UHarmonyLinkGraphics settings.
|
||||
*
|
||||
* This function returns the singleton instance of the `UHarmonyLinkGraphics` class. If the instance has not been
|
||||
* initialized, it creates a new instance, adds it to the root to prevent garbage collection, initializes it, and
|
||||
* then returns the instance.
|
||||
*
|
||||
* @return UHarmonyLinkGraphics* The singleton instance of the `UHarmonyLinkGraphics` class.
|
||||
*
|
||||
* @details
|
||||
* - Checks if the singleton instance (`_INSTANCE`) is already initialized.
|
||||
* - If not, creates a new instance using `NewObject<UHarmonyLinkGraphics>`.
|
||||
* - Adds the new instance to the root to prevent it from being garbage collected.
|
||||
* - Calls the `Init` function on the new instance to perform any necessary initialization.
|
||||
* - Returns the singleton instance.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category="HarmonyLink Settings")
|
||||
static UHarmonyLinkGraphics* GetSettings();
|
||||
|
||||
/**
|
||||
* @brief Retrieves the settings profile for a specified profile.
|
||||
*
|
||||
* This function returns the settings profile associated with the given `EProfile`. If the profile name or the settings
|
||||
* cannot be found, it logs an error message and returns an empty `FSettingsProfile`.
|
||||
*
|
||||
* @param Profile The profile identifier for which the settings profile is to be retrieved.
|
||||
* @return FSettingsProfile The settings profile associated with the specified profile. If the profile is not found, returns an empty `FSettingsProfile`.
|
||||
*
|
||||
* @details
|
||||
* - Finds the profile name associated with the given `EProfile`.
|
||||
* - Logs an error and returns an empty `FSettingsProfile` if the profile name is not found.
|
||||
* - Finds the settings profile associated with the profile.
|
||||
* - Logs an error and returns an empty `FSettingsProfile` if the settings profile is not found.
|
||||
* - Returns the settings profile if found.
|
||||
*
|
||||
* @note Uses UE_LOG for logging errors.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, BlueprintPure, Category="HarmonyLink Settings")
|
||||
FSettingsProfile GetSettingProfile(const EProfile Profile);
|
||||
|
||||
/**
|
||||
* @brief Retrieves the currently active profile.
|
||||
*
|
||||
* This function returns the currently active profile of the `UHarmonyLinkGraphics` settings.
|
||||
*
|
||||
* @return EProfile The currently active profile.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category="HarmonyLink Settings")
|
||||
EProfile GetActiveProfile() const;
|
||||
|
||||
/**
|
||||
* @brief Sets the automatic profile switching state.
|
||||
*
|
||||
* This function updates the automatic profile switching setting and broadcasts the change.
|
||||
*
|
||||
* @param bAutomaticSwitch Indicates whether automatic profile switching should be enabled (true) or disabled (false).
|
||||
*
|
||||
* @details
|
||||
* - Updates the `_bAutomaticSwitch` member variable with the new value.
|
||||
* - Broadcasts the change to any listeners using the `OnAutomaticSwitchChanged` delegate.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category="HarmonyLink Settings")
|
||||
void SetAutomaticSwitching(const bool bAutomaticSwitch);
|
||||
|
||||
/**
|
||||
* @brief Retrieves the current state of automatic profile switching.
|
||||
*
|
||||
* This function returns the state of the automatic profile switching setting.
|
||||
*
|
||||
* @return bool True if automatic profile switching is enabled; false otherwise.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category="HarmonyLink Settings")
|
||||
bool GetAutomaticSwitching() const;
|
||||
|
||||
/**
|
||||
* @brief Destroys the singleton instance of the UHarmonyLinkGraphics settings.
|
||||
*
|
||||
* This function safely destroys the singleton instance of the `UHarmonyLinkGraphics` class by removing it from root,
|
||||
* marking it as garbage for cleanup, and setting the instance pointer to null.
|
||||
*
|
||||
* @details
|
||||
* - Checks if the singleton instance (`_INSTANCE`) exists.
|
||||
* - Logs the destruction of the `UHarmonyLinkGraphics` instance.
|
||||
* - Removes all delegate bindings from `_INSTANCE`.
|
||||
* - Removes `_INSTANCE` from the root to allow garbage collection.
|
||||
* - Marks `_INSTANCE` as garbage to enable cleanup.
|
||||
* - Sets `_INSTANCE` to null.
|
||||
*
|
||||
* @note Uses UE_LOG for logging the destruction process.
|
||||
*/
|
||||
static void DestroySettings();
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Initializes the UHarmonyLinkGraphics settings.
|
||||
*
|
||||
* This function initializes the `UHarmonyLinkGraphics` settings by loading the configuration and applying the
|
||||
* appropriate profile based on the battery status.
|
||||
*
|
||||
* @details
|
||||
* - Calls `LoadConfig` to load the configuration settings.
|
||||
* - Retrieves the current battery status using `UHarmonyLinkLibrary::GetBatteryStatus`.
|
||||
* - If the device has a battery, applies the `BATTERY` profile by calling `ApplyProfileInternal`.
|
||||
*/
|
||||
void Init();
|
||||
|
||||
void Intermal_SaveConfig(const bool bDefaultConfig) const;
|
||||
|
||||
/**
|
||||
* @brief Periodically checks and updates the battery status and profile settings.
|
||||
*
|
||||
* This function is executed based on a timer determined by `_TickRate`. It asynchronously checks the current battery status
|
||||
* and updates the battery percentage and profile settings as needed. If the battery percentage has changed, it broadcasts
|
||||
* this change. If automatic profile switching is enabled, it applies the appropriate profile based on the AC connection status.
|
||||
*
|
||||
* @details
|
||||
* - Runs asynchronously on a separate thread to fetch the current battery status using `UHarmonyLinkLibrary::GetBatteryStatus`.
|
||||
* - If the battery percentage has changed, broadcasts the new battery percentage in a thread-safe manner.
|
||||
* - If automatic profile switching (`_bAutomaticSwitch`) is disabled, exits the function.
|
||||
* - If the device has a battery:
|
||||
* - Checks the AC connection status and applies the `CHARGING` profile if connected to AC.
|
||||
* - Applies the `BATTERY` profile if not connected to AC.
|
||||
* - Ensures all profile applications and broadcasts are executed on the main thread for thread safety.
|
||||
*
|
||||
* @note Uses UE_LOG for logging and `Async` for asynchronous execution.
|
||||
*/
|
||||
void Tick();
|
||||
|
||||
/**
|
||||
* @brief Creates a default configuration file.
|
||||
*
|
||||
* This function creates a default configuration file by loading the default settings and then saving them to the config file.
|
||||
*
|
||||
* @details
|
||||
* - Logs the start of the default configuration file creation process.
|
||||
* - Calls `LoadDefaults` to load the default settings into the configuration.
|
||||
* - Calls `SaveConfig` to save the default settings to the configuration file.
|
||||
* - Logs the completion of the default configuration file creation process.
|
||||
*
|
||||
* @note Uses UE_LOG for logging the creation process.
|
||||
*/
|
||||
void CreateDefaultConfigFile() const;
|
||||
|
||||
/**
|
||||
* @brief Retrieves the path to the configuration file.
|
||||
*
|
||||
* This function constructs and returns the full path to the configuration file used by the `UHarmonyLinkGraphics` settings.
|
||||
*
|
||||
* @return FString The full path to the configuration file.
|
||||
*
|
||||
* @details
|
||||
* - Defines the configuration file name as "HarmonyLink.ini".
|
||||
* - Combines the generated config directory path with the configuration file name to form the full path.
|
||||
* - Returns the full path to the configuration file.
|
||||
*/
|
||||
static FString GetConfigDirectoryFile(const bool bDefaultFolder);
|
||||
|
||||
/**
|
||||
* @brief Loads the settings from the configuration file.
|
||||
*
|
||||
* This function loads the graphics settings from an INI configuration file into the appropriate structures.
|
||||
* It attempts to load each profile section and the automatic switch setting. If any section fails to load,
|
||||
* it logs an error message and indicates failure. If loading is successful, it logs a success message.
|
||||
*
|
||||
* @return true if the settings were successfully loaded; false otherwise.
|
||||
*
|
||||
* @details
|
||||
* - Loads the configuration file specified by `GetConfigDirectoryFile`.
|
||||
* - Iterates over the `_ProfileNames` to load each profile section.
|
||||
* - Loads the `_bAutomaticSwitch` variable from the config.
|
||||
* - If loading fails, it attempts to create a default configuration file.
|
||||
*
|
||||
* @note Uses UE_LOG for logging errors and success messages.
|
||||
*/
|
||||
bool LoadSettingsFromConfig(FConfigFile* ConfigFile) const;
|
||||
|
||||
/**
|
||||
* @brief Loads a specific section from the configuration file into a settings profile.
|
||||
*
|
||||
* This function extracts settings from a specified section of the configuration file and stores them in the corresponding profile.
|
||||
* It handles different data types (int, float, bool, string) and parses them accordingly. If the section is found and loaded successfully,
|
||||
* the settings are added to the profile's settings map.
|
||||
*
|
||||
* @param ConfigFile The configuration file from which to load the section.
|
||||
* @param Profile The profile key-value pair containing the profile enum and the section name.
|
||||
* @return true if the section was found and loaded successfully; false otherwise.
|
||||
*
|
||||
* @details
|
||||
* - Finds the section in the configuration file using the section name from the profile.
|
||||
* - Clears any previous settings in the profile.
|
||||
* - Iterates through the settings in the section, parsing the value and type, and adds them to the profile's settings map.
|
||||
*
|
||||
* @note The function handles settings of types int, float, bool, and string.
|
||||
*/
|
||||
static bool LoadSection(FConfigFile* ConfigFile, const TPair<EProfile, FName> Profile);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Saves the settings of a given profile section to the configuration file.
|
||||
*
|
||||
* This function saves the settings of a specified profile section to the configuration file. It handles various data types
|
||||
* (int, float, bool, string) and formats them accordingly before saving. If the `bFlush` parameter is true, the configuration
|
||||
* file is flushed to ensure all changes are written to disk.
|
||||
*
|
||||
* @param SettingsProfile The settings profile to be saved.
|
||||
* @param bFlush Indicates whether to flush the configuration file after saving. Defaults to false.
|
||||
*
|
||||
* @details
|
||||
* - Checks if the global configuration object (`GConfig`) is available.
|
||||
* - Constructs the full path to the configuration file using `GetConfigDirectoryFile`.
|
||||
* - Iterates through the settings in the provided `SettingsProfile`.
|
||||
* - Determines the type and value of each setting and formats them as strings.
|
||||
* - Sets the formatted string in the configuration file for each setting.
|
||||
* - Logs the save operation.
|
||||
* - If `bFlush` is true, flushes the configuration file to ensure all changes are written.
|
||||
*
|
||||
* @note Uses UE_LOG for logging the save and flush operations.
|
||||
*/
|
||||
void SaveSection(const FSettingsProfile& SettingsProfile, const bool bDefaultConfig, const bool bFlush = false) const;
|
||||
|
||||
/**
|
||||
* @brief Loads the default settings into the profiles.
|
||||
*
|
||||
* This function resets the current profiles and loads the default settings into the profiles. It iterates over the profile names
|
||||
* and assigns the default settings to each profile.
|
||||
*
|
||||
* @details
|
||||
* - Logs the start of the `LoadDefaults` process.
|
||||
* - Resets the `_Profiles` map to clear any existing settings.
|
||||
* - Iterates over `_ProfileNames` to create default settings for each profile.
|
||||
* - For each profile, initializes a `FSettingsProfile` with the section name.
|
||||
* - If default settings are found for the profile in `_DefaultSettings`, assigns these settings to the profile.
|
||||
* - Adds the newly created profile settings to `_Profiles`.
|
||||
*
|
||||
* @note Uses UE_LOG for logging the start of the default settings loading process.
|
||||
*/
|
||||
void LoadDefaults() const;
|
||||
|
||||
/**
|
||||
* @brief Applies the specified graphics profile internally.
|
||||
*
|
||||
* This function applies the given graphics profile by either reverting to the original user game settings or
|
||||
* applying the settings associated with the specified profile.
|
||||
*
|
||||
* @param Profile The profile to apply. If the profile is `EProfile::NONE`, the function reverts to the original user game settings.
|
||||
* @return bool Returns true if the profile was successfully applied; false otherwise.
|
||||
*
|
||||
* @details
|
||||
* - If the `Profile` is `EProfile::NONE`:
|
||||
* - Logs a message indicating reversion to original user game settings.
|
||||
* - Retrieves the user game settings and applies them.
|
||||
* - Sets `_ActiveProfile` to `EProfile::NONE` and broadcasts the profile change.
|
||||
* - Returns true if successful, false otherwise.
|
||||
* - Finds the profile name associated with the given `EProfile`.
|
||||
* - Logs an error and returns false if the profile name is not found.
|
||||
* - Logs a message indicating the profile being applied.
|
||||
* - Finds the settings associated with the profile.
|
||||
* - Logs a warning and returns false if the settings profile is not found.
|
||||
* - Creates a render state context for applying settings.
|
||||
* - Iterates through each setting in the profile and applies it using `ApplySetting`.
|
||||
* - Sets `_ActiveProfile` to the specified profile and broadcasts the profile change.
|
||||
* - Returns true indicating the profile was successfully applied.
|
||||
*
|
||||
* @note Uses UE_LOG for logging messages, warnings, and errors. Uses `OnProfileChanged` to broadcast profile changes.
|
||||
*/
|
||||
bool ApplyProfileInternal(EProfile Profile);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Handles actions to be performed after the world initialization.
|
||||
*
|
||||
* This function hooks into the world initialization process to set up the `UHarmonyLinkGraphics` settings.
|
||||
* It checks if the world is valid and is a game world, then initializes or reloads the settings as necessary and sets up a timer for periodic updates.
|
||||
*
|
||||
* @param World The world that has just been initialized.
|
||||
* @param IVS Initialization values for the world.
|
||||
*
|
||||
* @details
|
||||
* - Checks if the `World` pointer is valid. Logs an error and returns if the world is invalid.
|
||||
* - If the world is a game world:
|
||||
* - Retrieves the singleton settings instance using `GetSettings`.
|
||||
* - If the world is a play-in-editor world, reloads the settings configuration by calling `LoadConfig` with `bForceReload` set to true.
|
||||
* - Checks if the tick timer is already set or active. If not, sets a timer to call the `Tick` function at intervals specified by `_TickRate`.
|
||||
*
|
||||
* @note Uses UE_LOG for logging errors and informational messages.
|
||||
*/
|
||||
static void OnPostWorldInitialization(UWorld* World, UWorld::InitializationValues IVS);
|
||||
|
||||
/**
|
||||
* @brief Handles actions to be performed when the world ends.
|
||||
*
|
||||
* This function is called when the world is about to be destroyed. It clears the tick timer and safely destroys the singleton instance of the `UHarmonyLinkGraphics` settings.
|
||||
*
|
||||
* @param World The world that is ending.
|
||||
*
|
||||
* @details
|
||||
* - Checks if the `World` pointer is valid. Logs an error and returns if the world is already destroyed.
|
||||
* - If the tick timer exists, clears the timer using the world's timer manager.
|
||||
* - Calls `DestroySettings` to safely destroy the singleton instance of `UHarmonyLinkGraphics`.
|
||||
*
|
||||
* @note Uses UE_LOG for logging errors and informational messages.
|
||||
*/
|
||||
static void OnWorldEnd(UWorld* World);
|
||||
|
||||
/**
|
||||
* @brief Resets the singleton instance of the UHarmonyLinkGraphics settings.
|
||||
*
|
||||
* This function resets the singleton instance by destroying the current instance and creating a new one.
|
||||
*
|
||||
* @details
|
||||
* - Calls `DestroySettings` on the current instance to safely destroy it.
|
||||
* - Calls `GetSettings` to create and initialize a new singleton instance.
|
||||
*/
|
||||
static void ResetInstance();
|
||||
|
||||
/**
|
||||
* @brief Applies a specific configuration setting to the console variable.
|
||||
*
|
||||
* This function applies the given configuration setting to the corresponding console variable (CVar) based on its key. It supports different data types such as bool, float, and int.
|
||||
*
|
||||
* @param Setting The key-value pair representing the setting to apply. The key is the name of the console variable, and the value is the configuration value.
|
||||
*
|
||||
* @details
|
||||
* - Uses the console manager to find the console variable associated with the given setting key.
|
||||
* - Depending on the type of the configuration value, sets the console variable to the corresponding value.
|
||||
* - If the console variable is not found, logs a warning message.
|
||||
* - If the value type is unsupported, logs a warning message.
|
||||
*
|
||||
* @note Uses UE_LOG for logging warnings about unsupported value types or missing console variables.
|
||||
*/
|
||||
static void ApplySetting(const TPair<FName, FHLConfigValue>& Setting);
|
||||
|
||||
/**
|
||||
* @brief Prints debug information for all profiles.
|
||||
*
|
||||
* This function logs the debug information for all profiles stored in `_Profiles`. It iterates through each profile and calls `PrintDebugSection` to print the details.
|
||||
*
|
||||
* @details
|
||||
* - Logs the start of the `DebugPrintProfiles` process.
|
||||
* - Iterates over each profile in the `_Profiles` map.
|
||||
* - Calls `PrintDebugSection` for each profile to print its details.
|
||||
* - Logs the completion of the `DebugPrintProfiles` process.
|
||||
*
|
||||
* @note Uses UE_LOG for logging the start and completion of the debug print process.
|
||||
*/
|
||||
void DebugPrintProfiles() const;
|
||||
|
||||
FConfigFile* GetConfig() const;
|
||||
|
||||
/**
|
||||
* @brief Prints debug information for a specific settings profile.
|
||||
*
|
||||
* This function logs the debug information for a given settings profile, including the section name and each setting's key, value, and type.
|
||||
*
|
||||
* @param SettingsProfile The settings profile to print debug information for.
|
||||
*
|
||||
* @details
|
||||
* - Logs the section name of the `SettingsProfile`.
|
||||
* - Iterates through each setting in the `SettingsProfile`.
|
||||
* - Depending on the type of each setting, converts the value to a string and logs the key, value, and type.
|
||||
*
|
||||
* @note Uses UE_LOG for logging the section name and settings details.
|
||||
*/
|
||||
static void PrintDebugSection(FSettingsProfile& SettingsProfile);
|
||||
|
||||
// Indicates whether automatic profile switching is enabled.
|
||||
static bool _bAutomaticSwitch;
|
||||
|
||||
// Stores the last recorded battery percentage.
|
||||
static int32 _LastBatteryPercentage;
|
||||
|
||||
// The rate at which to query HarmonyLinkLib for hardware info.
|
||||
static int32 _TickRate;
|
||||
|
||||
// Timer handle for managing the periodic tick function.
|
||||
static FTimerHandle _TickTimerHandle;
|
||||
|
||||
// The currently active profile.
|
||||
static EProfile _ActiveProfile;
|
||||
|
||||
// Maps profile enums to their corresponding names.
|
||||
static TMap<EProfile, FName> _ProfileNames;
|
||||
|
||||
// Stores the settings profiles.
|
||||
static TMap<EProfile, FSettingsProfile> _Profiles;
|
||||
|
||||
static TSharedPtr<FConfigFile> _ConfigFile;
|
||||
|
||||
// The default settings for profiles.
|
||||
static TMap<FName, TMap<FName, FHLConfigValue>> _DefaultSettings;
|
||||
|
||||
// Singleton instance of UHarmonyLinkGraphics.
|
||||
static UHarmonyLinkGraphics* _INSTANCE;
|
||||
};
|
158
Source/HarmonyLinkSettings/Public/Structs/HLConfigValue.h
Normal file
158
Source/HarmonyLinkSettings/Public/Structs/HLConfigValue.h
Normal file
|
@ -0,0 +1,158 @@
|
|||
// Copyright (C) 2024 Jordon Brooks
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "HLConfigValue.generated.h"
|
||||
|
||||
UENUM(BlueprintType)
|
||||
enum class EConfigValueType : uint8
|
||||
{
|
||||
Int,
|
||||
Float,
|
||||
Bool,
|
||||
String
|
||||
};
|
||||
|
||||
/**
|
||||
* Note: In Blueprints, all values will be visible, but only the value corresponding to the 'Type' will be used.
|
||||
*/
|
||||
USTRUCT(BlueprintType)
|
||||
struct FHLConfigValue
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
private:
|
||||
// Allow Blueprint access to these private variables
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ConfigValue", meta = (AllowPrivateAccess = "true"))
|
||||
EConfigValueType Type;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ConfigValue", meta = (AllowPrivateAccess = "true", EditCondition = "Type == EConfigValueType::Int", EditConditionHides))
|
||||
int32 IntValue;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ConfigValue", meta = (AllowPrivateAccess = "true", EditCondition = "Type == EConfigValueType::Float", EditConditionHides))
|
||||
float FloatValue;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ConfigValue", meta = (AllowPrivateAccess = "true", EditCondition = "Type == EConfigValueType::Bool", EditConditionHides))
|
||||
bool BoolValue;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ConfigValue", meta = (AllowPrivateAccess = "true", EditCondition = "Type == EConfigValueType::String", EditConditionHides))
|
||||
FString StringValue;
|
||||
|
||||
public:
|
||||
FHLConfigValue() : Type(EConfigValueType::String), IntValue(0), FloatValue(0.0f), BoolValue(false), StringValue(TEXT("")) {}
|
||||
|
||||
FHLConfigValue(int32 Value) : Type(EConfigValueType::Int), IntValue(Value), FloatValue(0.0f), BoolValue(false), StringValue(TEXT("")) {}
|
||||
|
||||
FHLConfigValue(float Value) : Type(EConfigValueType::Float), IntValue(0), FloatValue(Value), BoolValue(false), StringValue(TEXT("")) {}
|
||||
|
||||
FHLConfigValue(bool Value) : Type(EConfigValueType::Bool), IntValue(0), FloatValue(0.0f), BoolValue(Value), StringValue(TEXT("")) {}
|
||||
|
||||
FHLConfigValue(const FString& Value) : Type(EConfigValueType::String), IntValue(0), FloatValue(0.0f), BoolValue(false), StringValue(Value) {}
|
||||
|
||||
FString ToString() const
|
||||
{
|
||||
switch (Type)
|
||||
{
|
||||
case EConfigValueType::Int:
|
||||
return FString::Printf(TEXT("Int: %d"), IntValue);
|
||||
case EConfigValueType::Float:
|
||||
return FString::Printf(TEXT("Float: %f"), FloatValue);
|
||||
case EConfigValueType::Bool:
|
||||
return BoolValue ? TEXT("Bool: true") : TEXT("Bool: false");
|
||||
case EConfigValueType::String:
|
||||
return FString::Printf(TEXT("String: %s"), *StringValue);
|
||||
default:
|
||||
return TEXT("Unknown Type");
|
||||
}
|
||||
}
|
||||
|
||||
EConfigValueType GetType() const
|
||||
{
|
||||
return Type;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T GetValue() const;
|
||||
|
||||
// Equality operators
|
||||
bool operator==(const FHLConfigValue& Other) const
|
||||
{
|
||||
if (Type != Other.Type)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (Type)
|
||||
{
|
||||
case EConfigValueType::Int:
|
||||
return IntValue == Other.IntValue;
|
||||
case EConfigValueType::Float:
|
||||
return FloatValue == Other.FloatValue;
|
||||
case EConfigValueType::Bool:
|
||||
return BoolValue == Other.BoolValue;
|
||||
case EConfigValueType::String:
|
||||
return StringValue == Other.StringValue;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool operator!=(const FHLConfigValue& Other) const
|
||||
{
|
||||
return !(*this == Other);
|
||||
}
|
||||
};
|
||||
|
||||
// Specializations of the templated getter
|
||||
template<>
|
||||
inline int32 FHLConfigValue::GetValue<int32>() const
|
||||
{
|
||||
ensure(Type == EConfigValueType::Int);
|
||||
return IntValue;
|
||||
}
|
||||
|
||||
template<>
|
||||
inline float FHLConfigValue::GetValue<float>() const
|
||||
{
|
||||
ensure(Type == EConfigValueType::Float);
|
||||
return FloatValue;
|
||||
}
|
||||
|
||||
template<>
|
||||
inline bool FHLConfigValue::GetValue<bool>() const
|
||||
{
|
||||
ensure(Type == EConfigValueType::Bool);
|
||||
return BoolValue;
|
||||
}
|
||||
|
||||
template<>
|
||||
inline FString FHLConfigValue::GetValue<FString>() const
|
||||
{
|
||||
ensure(Type == EConfigValueType::String);
|
||||
return StringValue;
|
||||
}
|
||||
|
||||
// Hash function
|
||||
FORCEINLINE uint32 GetTypeHash(const FHLConfigValue& Value)
|
||||
{
|
||||
uint32 Hash = GetTypeHash(Value.GetType());
|
||||
|
||||
switch (Value.GetType())
|
||||
{
|
||||
case EConfigValueType::Int:
|
||||
Hash = HashCombine(Hash, GetTypeHash(Value.GetValue<int32>()));
|
||||
break;
|
||||
case EConfigValueType::Float:
|
||||
Hash = HashCombine(Hash, GetTypeHash(Value.GetValue<float>()));
|
||||
break;
|
||||
case EConfigValueType::Bool:
|
||||
Hash = HashCombine(Hash, GetTypeHash(Value.GetValue<bool>()));
|
||||
break;
|
||||
case EConfigValueType::String:
|
||||
Hash = HashCombine(Hash, GetTypeHash(Value.GetValue<FString>()));
|
||||
break;
|
||||
}
|
||||
|
||||
return Hash;
|
||||
}
|
45
Source/HarmonyLinkSettings/Public/Structs/SettingsProfile.h
Normal file
45
Source/HarmonyLinkSettings/Public/Structs/SettingsProfile.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
// Copyright (C) 2024 Jordon Brooks
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "HLConfigValue.h"
|
||||
|
||||
#include "SettingsProfile.generated.h"
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FSettingsProfile
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Settings")
|
||||
FName SectionName;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Settings")
|
||||
TMap<FName, FHLConfigValue> Settings;
|
||||
|
||||
// Equality operators
|
||||
bool operator==(const FSettingsProfile& Other) const
|
||||
{
|
||||
return SectionName == Other.SectionName && Settings.OrderIndependentCompareEqual(Other.Settings);
|
||||
}
|
||||
|
||||
bool operator!=(const FSettingsProfile& Other) const
|
||||
{
|
||||
return !(*this == Other);
|
||||
}
|
||||
};
|
||||
|
||||
// Hash function
|
||||
FORCEINLINE uint32 GetTypeHash(const FSettingsProfile& Profile)
|
||||
{
|
||||
uint32 Hash = GetTypeHash(Profile.SectionName);
|
||||
|
||||
for (const auto& Pair : Profile.Settings)
|
||||
{
|
||||
Hash = HashCombine(Hash, GetTypeHash(Pair.Key));
|
||||
Hash = HashCombine(Hash, GetTypeHash(Pair.Value));
|
||||
}
|
||||
|
||||
return Hash;
|
||||
}
|
49
Source/HarmonyLinkUE/HarmonyLinkUE.Build.cs
Normal file
49
Source/HarmonyLinkUE/HarmonyLinkUE.Build.cs
Normal file
|
@ -0,0 +1,49 @@
|
|||
// Copyright (C) 2024 Jordon Brooks
|
||||
|
||||
using UnrealBuildTool;
|
||||
using System.IO;
|
||||
|
||||
public class HarmonyLinkUE : ModuleRules
|
||||
{
|
||||
public HarmonyLinkUE(ReadOnlyTargetRules Target) : base(Target)
|
||||
{
|
||||
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
|
||||
|
||||
//IWYUSupport = IWYUSupport.Full;
|
||||
|
||||
PublicIncludePaths.AddRange(
|
||||
new string[] {
|
||||
// ... add public include paths required here ...
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
PrivateIncludePaths.AddRange(
|
||||
new string[] {
|
||||
// ... add other private include paths required here ...
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
PublicDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"Core",
|
||||
"CoreUObject",
|
||||
"Engine",
|
||||
|
||||
"HarmonyLinkLib",
|
||||
// ... add other public dependencies that you statically link with here ...
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
PrivateDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
// ... add private dependencies that you statically link with here ...
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
}
|
107
Source/HarmonyLinkUE/Private/HarmonyLinkLibrary.cpp
Normal file
107
Source/HarmonyLinkUE/Private/HarmonyLinkLibrary.cpp
Normal file
|
@ -0,0 +1,107 @@
|
|||
// Copyright (C) 2024 Jordon Brooks
|
||||
|
||||
#include "HarmonyLinkLibrary.h"
|
||||
#include "HarmonyLinkUE.h"
|
||||
|
||||
#include "HarmonyLinkLib.h"
|
||||
|
||||
bool UHarmonyLinkLibrary::bIsWineCached = false;
|
||||
bool UHarmonyLinkLibrary::bIsLinuxCached = false;
|
||||
bool UHarmonyLinkLibrary::bIsSteamDeckCached = false;
|
||||
bool UHarmonyLinkLibrary::bCPUInfoCached = false;
|
||||
bool UHarmonyLinkLibrary::bDeviceInfoCached = false;
|
||||
bool UHarmonyLinkLibrary::bOSInfoCached = false;
|
||||
|
||||
bool UHarmonyLinkLibrary::bIsWine = false;
|
||||
bool UHarmonyLinkLibrary::bIsLinux = false;
|
||||
bool UHarmonyLinkLibrary::bIsSteamDeck = false;
|
||||
|
||||
FCPUInfo UHarmonyLinkLibrary::CachedCPUInfo = FCPUInfo();
|
||||
FDevice UHarmonyLinkLibrary::CachedDeviceInfo = FDevice();
|
||||
FOSVerInfo UHarmonyLinkLibrary::CachedOSInfo = FOSVerInfo();
|
||||
|
||||
bool UHarmonyLinkLibrary::bIsInitialised = false;
|
||||
|
||||
UHarmonyLinkLibrary::UHarmonyLinkLibrary()
|
||||
{
|
||||
bIsInitialised = HarmonyLinkLib::HL_Init();
|
||||
|
||||
if (!bIsInitialised)
|
||||
{
|
||||
UE_LOG(LogHarmonyLink, Fatal, TEXT("Failed to initialise HarmonyLinkLib!"));
|
||||
return;
|
||||
}
|
||||
|
||||
UE_LOG(LogHarmonyLink, Log, TEXT("HarmonyLinkLib Initialised!"));
|
||||
}
|
||||
|
||||
bool UHarmonyLinkLibrary::IsInitialised()
|
||||
{
|
||||
return bIsInitialised;
|
||||
}
|
||||
|
||||
bool UHarmonyLinkLibrary::IsWine(bool bForce)
|
||||
{
|
||||
if (!bIsWineCached || bForce)
|
||||
{
|
||||
bIsWine = HarmonyLinkLib::get_is_wine();
|
||||
bIsWineCached = true;
|
||||
}
|
||||
return bIsWine;
|
||||
}
|
||||
|
||||
bool UHarmonyLinkLibrary::IsLinux(bool bForce)
|
||||
{
|
||||
if (!bIsLinuxCached || bForce)
|
||||
{
|
||||
bIsLinux = HarmonyLinkLib::get_is_linux();
|
||||
bIsLinuxCached = true;
|
||||
}
|
||||
return bIsLinux;
|
||||
}
|
||||
|
||||
bool UHarmonyLinkLibrary::IsSteamDeck(bool bForce)
|
||||
{
|
||||
if (!bIsSteamDeckCached || bForce)
|
||||
{
|
||||
bIsSteamDeck = GetDeviceInfo().Device == EDevice::STEAM_DECK;
|
||||
bIsSteamDeckCached = true;
|
||||
}
|
||||
return bIsSteamDeck;
|
||||
}
|
||||
|
||||
FCPUInfo UHarmonyLinkLibrary::GetCPUInfo(bool bForce)
|
||||
{
|
||||
if (!bCPUInfoCached || bForce)
|
||||
{
|
||||
CachedCPUInfo = FCPUInfo(HarmonyLinkLib::get_cpu_info());
|
||||
bCPUInfoCached = true;
|
||||
}
|
||||
|
||||
return CachedCPUInfo;
|
||||
}
|
||||
|
||||
FDevice UHarmonyLinkLibrary::GetDeviceInfo(bool bForce)
|
||||
{
|
||||
if (!bDeviceInfoCached || bForce)
|
||||
{
|
||||
CachedDeviceInfo = FDevice(HarmonyLinkLib::get_device_info());
|
||||
bDeviceInfoCached = true;
|
||||
}
|
||||
return CachedDeviceInfo;
|
||||
}
|
||||
|
||||
FOSVerInfo UHarmonyLinkLibrary::GetOSInfo(bool bForce)
|
||||
{
|
||||
if (!bOSInfoCached || bForce)
|
||||
{
|
||||
CachedOSInfo = FOSVerInfo(HarmonyLinkLib::get_os_version());
|
||||
bOSInfoCached = true;
|
||||
}
|
||||
return CachedOSInfo;
|
||||
}
|
||||
|
||||
FBattery UHarmonyLinkLibrary::GetBatteryStatus()
|
||||
{
|
||||
return FBattery(HarmonyLinkLib::get_battery_status());
|
||||
}
|
22
Source/HarmonyLinkUE/Private/HarmonyLinkUE.cpp
Normal file
22
Source/HarmonyLinkUE/Private/HarmonyLinkUE.cpp
Normal file
|
@ -0,0 +1,22 @@
|
|||
// Copyright (C) 2024 Jordon Brooks
|
||||
|
||||
#include "HarmonyLinkUE.h"
|
||||
#include "Modules/ModuleManager.h"
|
||||
|
||||
#define LOCTEXT_NAMESPACE "FHarmonyLinkUEModule"
|
||||
|
||||
DEFINE_LOG_CATEGORY(LogHarmonyLink);
|
||||
|
||||
void FHarmonyLinkUEModule::StartupModule()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void FHarmonyLinkUEModule::ShutdownModule()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
|
||||
IMPLEMENT_MODULE(FHarmonyLinkUEModule, HarmonyLinkUE)
|
|
@ -11,11 +11,6 @@ FCPUInfo::FCPUInfo(HarmonyLinkLib::FCPUInfo* cpu_info)
|
|||
PhysicalCores = cpu_info->Physical_Cores;
|
||||
LogicalCores = cpu_info->Logical_Cores;
|
||||
|
||||
for (const HarmonyLinkLib::FString& Flag : cpu_info->Flags)
|
||||
{
|
||||
Flags.Add(Flag.c_str());
|
||||
}
|
||||
|
||||
cpu_info->free();
|
||||
}
|
||||
else
|
|
@ -19,20 +19,20 @@ FDevice::FDevice(HarmonyLinkLib::FDevice* oldDevice)
|
|||
}
|
||||
}
|
||||
|
||||
EDeviceEnum FDevice::Convert(HarmonyLinkLib::EDevice Device)
|
||||
EDevice FDevice::Convert(HarmonyLinkLib::EDevice Device)
|
||||
{
|
||||
switch (Device)
|
||||
{
|
||||
case HarmonyLinkLib::EDevice::DESKTOP:
|
||||
return EDeviceEnum::DESKTOP;
|
||||
return EDevice::DESKTOP;
|
||||
case HarmonyLinkLib::EDevice::LAPTOP:
|
||||
return EDeviceEnum::LAPTOP;
|
||||
return EDevice::LAPTOP;
|
||||
case HarmonyLinkLib::EDevice::HANDHELD:
|
||||
return EDeviceEnum::HANDHELD;
|
||||
return EDevice::HANDHELD;
|
||||
case HarmonyLinkLib::EDevice::STEAM_DECK:
|
||||
return EDeviceEnum::STEAM_DECK;
|
||||
return EDevice::STEAM_DECK;
|
||||
default:
|
||||
return EDeviceEnum::DESKTOP;
|
||||
return EDevice::DESKTOP;
|
||||
}
|
||||
}
|
||||
|
|
@ -9,7 +9,7 @@
|
|||
* Enum representing different operating system platforms.
|
||||
*/
|
||||
UENUM(BlueprintType)
|
||||
enum class EDeviceEnum : uint8
|
||||
enum class EDevice : uint8
|
||||
{
|
||||
DESKTOP UMETA(DisplayName = "Desktop"),
|
||||
LAPTOP UMETA(DisplayName = "Laptop"),
|
|
@ -5,6 +5,9 @@
|
|||
#include "CoreMinimal.h"
|
||||
#include "Platform.generated.h"
|
||||
|
||||
// Undefine the LINUX macro to avoid conflicts with the enum definition.
|
||||
#undef LINUX
|
||||
|
||||
/*
|
||||
* Enum representing different operating system platforms.
|
||||
*/
|
75
Source/HarmonyLinkUE/Public/HarmonyLinkLibrary.h
Normal file
75
Source/HarmonyLinkUE/Public/HarmonyLinkLibrary.h
Normal file
|
@ -0,0 +1,75 @@
|
|||
// Copyright (C) 2024 Jordon Brooks
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
|
||||
#include "Structs/Battery.h"
|
||||
#include "Structs/CPUInfo.h"
|
||||
#include "Structs/Device.h"
|
||||
#include "Structs/OSVerInfo.h"
|
||||
|
||||
#include "Kismet/BlueprintFunctionLibrary.h"
|
||||
#include "HarmonyLinkLibrary.generated.h"
|
||||
|
||||
/**
|
||||
* Library of static functions for accessing various system information, particularly for the HarmonyLink project.
|
||||
*/
|
||||
UCLASS()
|
||||
class HARMONYLINKUE_API UHarmonyLinkLibrary : public UBlueprintFunctionLibrary
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UHarmonyLinkLibrary();
|
||||
|
||||
// IsInitialised
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category="HarmonyLink")
|
||||
static bool IsInitialised();
|
||||
|
||||
// Checks if the game is running under Wine.
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category="HarmonyLink")
|
||||
static bool IsWine(bool bForce = false);
|
||||
|
||||
// Checks if the operating system is Linux.
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category="HarmonyLink")
|
||||
static bool IsLinux(bool bForce = false);
|
||||
|
||||
// Checks if the game is running on a Steam Deck.
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category="HarmonyLink")
|
||||
static bool IsSteamDeck(bool bForce = false);
|
||||
|
||||
// Retrieves information about the CPU of the current device.
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category="HarmonyLink")
|
||||
static FCPUInfo GetCPUInfo(bool bForce = false);
|
||||
|
||||
// Retrieves information about the current device.
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category="HarmonyLink")
|
||||
static FDevice GetDeviceInfo(bool bForce = false);
|
||||
|
||||
// Retrieves information about the operating system of the current device.
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category="HarmonyLink")
|
||||
static FOSVerInfo GetOSInfo(bool bForce = false);
|
||||
|
||||
// Retrieves the current battery status of the device.
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category="HarmonyLink")
|
||||
static FBattery GetBatteryStatus();
|
||||
|
||||
private:
|
||||
static bool bIsWineCached;
|
||||
static bool bIsWine;
|
||||
static bool bIsLinuxCached;
|
||||
static bool bIsLinux;
|
||||
static bool bIsSteamDeckCached;
|
||||
static bool bIsSteamDeck;
|
||||
|
||||
static bool bCPUInfoCached;
|
||||
static bool bDeviceInfoCached;
|
||||
static bool bOSInfoCached;
|
||||
|
||||
static FCPUInfo CachedCPUInfo;
|
||||
static FDevice CachedDeviceInfo;
|
||||
static FOSVerInfo CachedOSInfo;
|
||||
|
||||
static bool bIsInitialised;
|
||||
};
|
|
@ -4,7 +4,9 @@
|
|||
|
||||
#include "Modules/ModuleManager.h"
|
||||
|
||||
class FHarmonyLinkModule : public IModuleInterface
|
||||
DECLARE_LOG_CATEGORY_EXTERN(LogHarmonyLink, All, All);
|
||||
|
||||
class FHarmonyLinkUEModule : public IModuleInterface
|
||||
{
|
||||
public:
|
||||
|
|
@ -1,9 +1,10 @@
|
|||
// Copyright (C) 2024 Jordon Brooks
|
||||
#pragma once
|
||||
|
||||
#include <HarmonyLinkLib.h>
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
|
||||
#include "Structs/FBattery.h"
|
||||
|
||||
#include "Battery.generated.h"
|
||||
|
||||
/*
|
|
@ -2,9 +2,10 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <HarmonyLinkLib.h>
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
|
||||
#include "Structs/FCPUInfo.h"
|
||||
|
||||
#include "CPUInfo.generated.h"
|
||||
|
||||
/*
|
||||
|
@ -33,10 +34,6 @@ struct FCPUInfo
|
|||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="HarmonyLink")
|
||||
int32 LogicalCores = 0;
|
||||
|
||||
// A set of flags representing various features or capabilities of the CPU.
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="HarmonyLink")
|
||||
TSet<FString> Flags;
|
||||
|
||||
// Constructor that initializes the struct with information from an external CPU info source.
|
||||
// @param cpu_info Pointer to an external FCPUInfo structure to copy data from.
|
||||
FCPUInfo(HarmonyLinkLib::FCPUInfo* cpu_info);
|
|
@ -5,7 +5,8 @@
|
|||
#include "CoreMinimal.h"
|
||||
#include "Enums/DeviceEnum.h"
|
||||
#include "Enums/Platform.h"
|
||||
#include <Structs/FDevice.h>
|
||||
|
||||
#include "Structs/FDevice.h"
|
||||
|
||||
#include "Device.generated.h"
|
||||
|
||||
|
@ -25,7 +26,7 @@ struct FDevice
|
|||
|
||||
// The type of the device.
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category="HarmonyLink")
|
||||
EDeviceEnum Device = EDeviceEnum::DESKTOP;
|
||||
EDevice Device = EDevice::DESKTOP;
|
||||
|
||||
// Constructor that initializes the struct with information from an external source.
|
||||
// @param oldDevice Pointer to an external FDevice structure to copy data from.
|
||||
|
@ -35,7 +36,7 @@ private:
|
|||
// Converts an external device enum to the internal EDeviceEnum type.
|
||||
// @param Device External device enum to convert.
|
||||
// @returns Converted EDeviceEnum value.
|
||||
static EDeviceEnum Convert(HarmonyLinkLib::EDevice Device);
|
||||
static EDevice Convert(HarmonyLinkLib::EDevice Device);
|
||||
|
||||
// Converts an external platform enum to the internal EPlatform type.
|
||||
// @param Platform External platform enum to convert.
|
|
@ -2,7 +2,8 @@
|
|||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include <HarmonyLinkLib.h>
|
||||
|
||||
#include "Structs/FOSVerInfo.h"
|
||||
|
||||
#include "OSVerInfo.generated.h"
|
||||
|
72
Source/ThirdParty/HarmonyLinkLib/HarmonyLinkLib.Build.cs
vendored
Normal file
72
Source/ThirdParty/HarmonyLinkLib/HarmonyLinkLib.Build.cs
vendored
Normal file
|
@ -0,0 +1,72 @@
|
|||
// Copyright (C) 2024 Jordon Brooks
|
||||
|
||||
using UnrealBuildTool;
|
||||
using System.IO;
|
||||
using Internal;
|
||||
|
||||
public class HarmonyLinkLib : ModuleRules
|
||||
{
|
||||
public HarmonyLinkLib(ReadOnlyTargetRules Target) : base(Target)
|
||||
{
|
||||
//Console.WriteLine("Building HarmonyLinkLib");
|
||||
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
|
||||
|
||||
Type = ModuleType.External;
|
||||
|
||||
// Add the standard library
|
||||
//bUseRTTI = true;
|
||||
//bEnableExceptions = true;
|
||||
|
||||
// Optionally, if you need C++17 features
|
||||
//CppStandard = CppStandardVersion.Cpp17;
|
||||
|
||||
string includePath = Path.Combine(ModuleDirectory, "include");
|
||||
//Console.WriteLine("Include Path: " + includePath);
|
||||
PublicIncludePaths.Add(includePath);
|
||||
|
||||
string platformString = Target.Platform.ToString();
|
||||
if (Target.Platform == UnrealTargetPlatform.Win64)
|
||||
{
|
||||
PublicDefinitions.Add("HARMONYLINKLIB_STATIC=1");
|
||||
PublicDefinitions.Add("BUILD_WINDOWS=1");
|
||||
string libpath = Path.Combine(ModuleDirectory, "lib", platformString, "HarmonyLinkLibStatic.lib");
|
||||
|
||||
PublicAdditionalLibraries.Add(libpath);
|
||||
|
||||
//string dllPath = Path.Combine(ModuleDirectory, "bin", platformString, "HarmonyLinkLibShared.dll");
|
||||
//string dllTargetPath = "$(TargetOutputDir)/HarmonyLinkLibShared.dll";
|
||||
|
||||
//Console.WriteLine("DLL Path: " + dllPath);
|
||||
//RuntimeDependencies.Add(dllTargetPath, dllPath);
|
||||
|
||||
//PublicDelayLoadDLLs.Add("HarmonyLinkLibShared.dll");
|
||||
}
|
||||
else if (Target.Platform == UnrealTargetPlatform.Linux)
|
||||
{
|
||||
PublicDefinitions.Add("HARMONYLINKLIB_STATIC=1");
|
||||
//Console.WriteLine("Building Linux");
|
||||
PublicDefinitions.Add("BUILD_LINUX=1");
|
||||
string dllPath = Path.Combine(ModuleDirectory, "lib", platformString, "libHarmonyLinkLibStatic_clang++.a");
|
||||
//string dllTargetPath = "$(TargetOutputDir)/libHarmonyLinkLibShared.so";
|
||||
//Console.WriteLine("Library Path: " + libPath);
|
||||
PublicAdditionalLibraries.Add(dllPath);
|
||||
|
||||
// Ensure the proper linking of standard C++ libraries
|
||||
//PublicSystemLibraries.Add("stdc++");
|
||||
//PublicSystemLibraries.Add("c++abi");
|
||||
//PublicSystemLibraries.Add("m"); // Math library
|
||||
//PublicSystemLibraries.Add("pthread"); // POSIX threads library
|
||||
|
||||
// Add the C++ standard library explicitly if needed
|
||||
PublicSystemLibraries.Add("c++");
|
||||
|
||||
// Ensure linking with libc and other necessary libraries
|
||||
//PublicSystemLibraries.Add("dl"); // Dynamic linking loader
|
||||
//PublicSystemLibraries.Add("rt"); // Real-time library
|
||||
|
||||
// Add any other libraries that might be needed
|
||||
//PublicSystemLibraries.Add("gcc_s"); // GCC support library
|
||||
//PublicSystemLibraries.Add("gcc"); // GCC compiler support library
|
||||
}
|
||||
}
|
||||
}
|
BIN
Source/ThirdParty/HarmonyLinkLib/bin/Linux/libHarmonyLinkLib.so
(Stored with Git LFS)
vendored
BIN
Source/ThirdParty/HarmonyLinkLib/bin/Linux/libHarmonyLinkLib.so
(Stored with Git LFS)
vendored
Binary file not shown.
BIN
Source/ThirdParty/HarmonyLinkLib/bin/Linux/libHarmonyLinkLibShared.so
(Stored with Git LFS)
vendored
Normal file
BIN
Source/ThirdParty/HarmonyLinkLib/bin/Linux/libHarmonyLinkLibShared.so
(Stored with Git LFS)
vendored
Normal file
Binary file not shown.
BIN
Source/ThirdParty/HarmonyLinkLib/bin/Win64/HarmonyLinkLib.dll
(Stored with Git LFS)
vendored
BIN
Source/ThirdParty/HarmonyLinkLib/bin/Win64/HarmonyLinkLib.dll
(Stored with Git LFS)
vendored
Binary file not shown.
BIN
Source/ThirdParty/HarmonyLinkLib/bin/Win64/HarmonyLinkLib.lib
(Stored with Git LFS)
vendored
BIN
Source/ThirdParty/HarmonyLinkLib/bin/Win64/HarmonyLinkLib.lib
(Stored with Git LFS)
vendored
Binary file not shown.
BIN
Source/ThirdParty/HarmonyLinkLib/bin/Win64/HarmonyLinkLibShared.dll
(Stored with Git LFS)
vendored
Normal file
BIN
Source/ThirdParty/HarmonyLinkLib/bin/Win64/HarmonyLinkLibShared.dll
(Stored with Git LFS)
vendored
Normal file
Binary file not shown.
22
Source/ThirdParty/HarmonyLinkLib/include/Core.h
vendored
22
Source/ThirdParty/HarmonyLinkLib/include/Core.h
vendored
|
@ -15,12 +15,24 @@
|
|||
#pragma once
|
||||
|
||||
// Use a preprocessor definition to switch between export and import declarations
|
||||
#ifdef _WIN32
|
||||
#ifdef HARMONYLINKLIB_EXPORTS
|
||||
#define HARMONYLINKLIB_API __declspec(dllexport)
|
||||
#ifdef BUILD_WINDOWS
|
||||
#ifdef HARMONYLINKLIB_STATIC
|
||||
#define HARMONYLINKLIB_API
|
||||
#else
|
||||
#define HARMONYLINKLIB_API __declspec(dllimport)
|
||||
#ifdef HARMONYLINKLIB_SHARED
|
||||
#define HARMONYLINKLIB_API __declspec(dllexport)
|
||||
#else
|
||||
#define HARMONYLINKLIB_API __declspec(dllimport)
|
||||
#endif
|
||||
#endif
|
||||
#else
|
||||
#define HARMONYLINKLIB_API
|
||||
#ifdef HARMONYLINKLIB_SHARED
|
||||
#ifdef __clang__
|
||||
#define HARMONYLINKLIB_API __attribute__((visibility("default")))
|
||||
#else
|
||||
#define HARMONYLINKLIB_API
|
||||
#endif
|
||||
#else
|
||||
#define HARMONYLINKLIB_API
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -14,6 +14,9 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
// Undefine the LINUX macro to avoid conflicts with the enum definition.
|
||||
#undef LINUX
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
// Enum class for representing different types of devices
|
||||
|
@ -21,6 +24,7 @@ namespace HarmonyLinkLib
|
|||
{
|
||||
enum class EDevice : uint8_t
|
||||
{
|
||||
UNKNOWN,
|
||||
DESKTOP,
|
||||
LAPTOP,
|
||||
HANDHELD,
|
||||
|
|
|
@ -21,6 +21,7 @@ namespace HarmonyLinkLib
|
|||
{
|
||||
enum class EPlatform : uint8_t
|
||||
{
|
||||
UNKNOWN,
|
||||
WINDOWS,
|
||||
LINUX,
|
||||
MAC,
|
||||
|
|
29
Source/ThirdParty/HarmonyLinkLib/include/Enums/ESteamDeck.h
vendored
Normal file
29
Source/ThirdParty/HarmonyLinkLib/include/Enums/ESteamDeck.h
vendored
Normal file
|
@ -0,0 +1,29 @@
|
|||
// Copyright (c) 2024 Jordon Brooks
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
// Enum class for representing different types of devices
|
||||
namespace HarmonyLinkLib
|
||||
{
|
||||
enum class ESteamDeck : uint8_t
|
||||
{
|
||||
NONE, // Device is not a steam deck
|
||||
UNKNOWN, // Device is a steam deck but model cannot be determined
|
||||
LCD,
|
||||
OLED,
|
||||
};
|
||||
}
|
|
@ -44,13 +44,19 @@ class IPlatformUtilities;
|
|||
|
||||
namespace HarmonyLinkLib
|
||||
{
|
||||
extern "C" HARMONYLINKLIB_API bool get_is_wine();
|
||||
HARMONYLINKLIB_API bool HL_Init();
|
||||
|
||||
extern "C" HARMONYLINKLIB_API FCPUInfo* get_cpu_info();
|
||||
HARMONYLINKLIB_API bool get_is_wine();
|
||||
|
||||
extern "C" HARMONYLINKLIB_API FDevice* get_device_info();
|
||||
HARMONYLINKLIB_API bool get_is_linux();
|
||||
|
||||
extern "C" HARMONYLINKLIB_API FOSVerInfo* get_os_version();
|
||||
HARMONYLINKLIB_API bool get_is_docked();
|
||||
|
||||
HARMONYLINKLIB_API FCPUInfo* get_cpu_info();
|
||||
|
||||
HARMONYLINKLIB_API FDevice* get_device_info();
|
||||
|
||||
HARMONYLINKLIB_API FOSVerInfo* get_os_version();
|
||||
|
||||
extern "C" HARMONYLINKLIB_API FBattery* get_battery_status();
|
||||
HARMONYLINKLIB_API FBattery* get_battery_status();
|
||||
}
|
||||
|
|
|
@ -18,13 +18,15 @@
|
|||
|
||||
#include "Enums/EDevice.h"
|
||||
#include "Enums/EPlatform.h"
|
||||
#include "Enums/ESteamDeck.h"
|
||||
|
||||
namespace HarmonyLinkLib
|
||||
{
|
||||
// Struct to represent a specific device with both platform and device type
|
||||
struct FDevice : HarmonyLinkStruct
|
||||
{
|
||||
EPlatform platform;
|
||||
EDevice device;
|
||||
EPlatform platform = EPlatform::UNKNOWN;
|
||||
EDevice device = EDevice::UNKNOWN;
|
||||
ESteamDeck steam_deck_model = ESteamDeck::NONE;
|
||||
};
|
||||
}
|
||||
|
|
BIN
Source/ThirdParty/HarmonyLinkLib/lib/Linux/libHarmonyLinkLibStatic.a
(Stored with Git LFS)
vendored
Normal file
BIN
Source/ThirdParty/HarmonyLinkLib/lib/Linux/libHarmonyLinkLibStatic.a
(Stored with Git LFS)
vendored
Normal file
Binary file not shown.
BIN
Source/ThirdParty/HarmonyLinkLib/lib/Linux/libHarmonyLinkLibStatic_clang++.a
(Stored with Git LFS)
vendored
Normal file
BIN
Source/ThirdParty/HarmonyLinkLib/lib/Linux/libHarmonyLinkLibStatic_clang++.a
(Stored with Git LFS)
vendored
Normal file
Binary file not shown.
BIN
Source/ThirdParty/HarmonyLinkLib/lib/Win64/HarmonyLinkLibStatic.lib
(Stored with Git LFS)
vendored
Normal file
BIN
Source/ThirdParty/HarmonyLinkLib/lib/Win64/HarmonyLinkLibStatic.lib
(Stored with Git LFS)
vendored
Normal file
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue