Working profiles & Updated HarmonyLinkLib

This commit is contained in:
Jordon Brooks 2024-05-25 00:44:14 +01:00
parent 3f435a284f
commit 15a2622991
Signed by: jordon
GPG key ID: DBD9758CD53E786A
12 changed files with 538 additions and 94 deletions

View file

@ -52,23 +52,22 @@ public class HarmonyLink : ModuleRules
}
);
// 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"));
}
// Platform-specific settings for static libraries
if (Target.Platform == UnrealTargetPlatform.Win64)
{
PublicAdditionalLibraries.Add(Path.Combine(PluginDirectory, "Source/ThirdParty/HarmonyLinkLib/lib/Win64/HarmonyLinkLibStatic.lib"));
PublicDefinitions.Add("HARMONYLINKLIB_STATIC=1");
}
else if (Target.Platform == UnrealTargetPlatform.Linux)
{
PublicAdditionalLibraries.Add(Path.Combine(PluginDirectory, "Source/ThirdParty/HarmonyLinkLib/lib/Linux/libHarmonyLinkLibStatic.a"));
PublicDefinitions.Add("HARMONYLINKLIB_STATIC=1");
}
// 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"));
}
else if (Target.Platform == UnrealTargetPlatform.Mac)
{
PublicAdditionalLibraries.Add(Path.Combine(PluginDirectory, "Source/ThirdParty/HarmonyLinkLib/lib/Mac/libHarmonyLinkLibStatic.a"));
PublicDefinitions.Add("HARMONYLINKLIB_STATIC=1");
}
}
}

View file

@ -11,13 +11,7 @@ bool UHarmonyLinkLibrary::IsWine()
bool UHarmonyLinkLibrary::IsLinux()
{
#if PLATFORM_WINDOWS
return IsWine();
#elif PLATFORM_LINUX
return true;
#else
return false;
#endif
return HarmonyLinkLib::get_is_linux();
}
bool UHarmonyLinkLibrary::IsSteamDeck()

View file

@ -9,7 +9,20 @@
UHarmonyLinkGraphics* UHarmonyLinkGraphics::_INSTANCE = nullptr;
int32 UHarmonyLinkGraphics::_TickRate = 1;
FTimerHandle UHarmonyLinkGraphics::_TickTimerHandle = FTimerHandle();
/**
* @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) },
@ -34,8 +47,7 @@ TMap<FName, TMap<FName, FHLConfigValue>> UHarmonyLinkGraphics::_DefaultSettings
UHarmonyLinkGraphics::UHarmonyLinkGraphics()
{
UE_LOG(LogHarmonyLink, Warning, TEXT("HarmonyLinkGraphics initialized."));
_bAutomaticSwitch = true;
FWorldDelegates::OnPostWorldInitialization.AddUObject(this, &UHarmonyLinkGraphics::OnPostWorldInitialization);
FWorldDelegates::OnPreWorldFinishDestroy.AddUObject(this, &UHarmonyLinkGraphics::OnWorldEnd);
}
@ -50,25 +62,29 @@ void UHarmonyLinkGraphics::LoadConfig(const bool bForceReload)
QUICK_SCOPE_CYCLE_COUNTER(HarmonyLinkGraphics_LoadSettings);
// Load the settings into the map
if (!LoadSettingsFromConfig())
if (!LoadSettingsFromConfig(false))
{
// Retry 2nd time
LoadSettingsFromConfig();
if (!LoadSettingsFromConfig(true))
{
CreateDefaultConfigFile();
// Retry 2nd time
LoadSettingsFromConfig(true);
}
}
DebugPrintProfiles();
}
bool UHarmonyLinkGraphics::LoadSettingsFromConfig()
bool UHarmonyLinkGraphics::LoadSettingsFromConfig(const bool bLoadDefaults)
{
// Load the configuration from the INI file
FConfigFile ConfigFile;
const FString Filename = GetConfigDirectoryFile();
const FString Filename = GetConfigDirectoryFile(bLoadDefaults);
if (!GConfig)
{
UE_LOG(LogHarmonyLink, Error, TEXT("Failed to access GConfig!"))
UE_LOG(LogHarmonyLink, Error, TEXT("Failed to access GConfig!"));
return false;
}
@ -77,6 +93,20 @@ bool UHarmonyLinkGraphics::LoadSettingsFromConfig()
// Load each profile section
bool bLoaded = true;
// Load the _bAutomaticSwitch variable
const FString SectionName = TEXT("HarmonyLink");
const FString KeyName = TEXT("AutomaticProfileSwitch");
if (!GConfig->GetBool(*SectionName, *KeyName, _bAutomaticSwitch, Filename))
{
UE_LOG(LogHarmonyLink, Error, TEXT("Failed to load bAutomaticSwitch from config"));
bLoaded = false;
}
else
{
UE_LOG(LogHarmonyLink, Log, TEXT("Loaded bAutomaticSwitch: %s"), _bAutomaticSwitch ? TEXT("true") : TEXT("false"));
}
for (const TPair<EProfile, FName>& Profile : _ProfileNames)
{
if (!LoadSection(ConfigFile, Profile))
@ -86,7 +116,7 @@ bool UHarmonyLinkGraphics::LoadSettingsFromConfig()
}
}
// Check if all profiles were loaded successfully
// Check if all profiles and settings were loaded successfully
if (bLoaded)
{
UE_LOG(LogHarmonyLink, Log, TEXT("Successfully loaded config file: %s"), *Filename);
@ -95,7 +125,6 @@ bool UHarmonyLinkGraphics::LoadSettingsFromConfig()
}
UE_LOG(LogHarmonyLink, Error, TEXT("Failed to load config file: %s"), *Filename);
CreateDefaultConfigFile();
return false;
}
@ -151,20 +180,17 @@ bool UHarmonyLinkGraphics::LoadSection(const FConfigFile& ConfigFile, const TPai
void UHarmonyLinkGraphics::SaveConfig() const
{
QUICK_SCOPE_CYCLE_COUNTER(HarmonyLinkGraphics_SaveConfig);
for (TPair<EProfile, FSettingsProfile> Profile : _Profiles)
{
SaveSection(Profile.Value);
}
const FString Filename = GetConfigDirectoryFile();
UE_LOG(LogHarmonyLink, Log, TEXT("Flushing file: '%s'"), *Filename);
GConfig->Flush(false, Filename);
Intermal_SaveConfig(false);
}
void UHarmonyLinkGraphics::SetSetting(const EProfile Profile, const FName Setting, const FHLConfigValue Value)
{
// 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);
@ -230,6 +256,12 @@ UHarmonyLinkGraphics* UHarmonyLinkGraphics::GetSettings()
FSettingsProfile UHarmonyLinkGraphics::GetSettingProfile(const EProfile Profile)
{
// 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);
@ -249,7 +281,6 @@ FSettingsProfile UHarmonyLinkGraphics::GetSettingProfile(const EProfile Profile)
}
return *SettingsProfile;
}
EProfile UHarmonyLinkGraphics::GetActiveProfile() const
@ -286,16 +317,35 @@ void UHarmonyLinkGraphics::Init()
LoadConfig();
const FBattery BatteryStatus = UHarmonyLinkLibrary::GetBatteryStatus();
// Enabled for development testing
// At some point I need to implement the ability to fake and emulate these settings to make it easier to test
// BUG: Remove this before release!
if (!BatteryStatus.HasBattery)
if (BatteryStatus.HasBattery)
{
ApplyProfileInternal(EProfile::BATTERY);
}
}
void UHarmonyLinkGraphics::Intermal_SaveConfig(const bool bDefaultConfig) const
{
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(LogHarmonyLink, Log, TEXT("Saving bAutomaticSwitch: %s"), _bAutomaticSwitch ? TEXT("true") : TEXT("false"));
for (const TPair<EProfile, FSettingsProfile>& Profile : _Profiles)
{
SaveSection(Profile.Value, bDefaultConfig);
}
UE_LOG(LogHarmonyLink, Log, TEXT("Flushing file: '%s'"), *Filename);
GConfig->Flush(true, Filename);
}
void UHarmonyLinkGraphics::Tick()
{
Async(EAsyncExecution::Thread, [this]()
@ -347,27 +397,23 @@ void UHarmonyLinkGraphics::CreateDefaultConfigFile()
UE_LOG(LogHarmonyLink, Log, TEXT("Creating default config file."));
LoadDefaults();
SaveConfig();
Intermal_SaveConfig(true);
UE_LOG(LogHarmonyLink, Log, TEXT("Default config file created."));
}
FString UHarmonyLinkGraphics::GetConfigDirectoryFile()
FString UHarmonyLinkGraphics::GetConfigDirectoryFile(const bool bDefaultFolder)
{
FString ConfigFileName = "HarmonyLink.ini"; // Replace with your actual config file name
FString ConfigFileName = bDefaultFolder? "DefaultHarmonyLink.ini" : "HarmonyLink.ini"; // Replace with your actual config file name
#if WITH_EDITOR
return FPaths::Combine(FPaths::ProjectSavedDir(), TEXT("Config"), ConfigFileName);
#else
return FPaths::Combine(FPaths::ProjectConfigDir(), ConfigFileName);
#endif
return FPaths::Combine(bDefaultFolder ? FPaths::ProjectConfigDir() : FPaths::GeneratedConfigDir(), ConfigFileName);
}
void UHarmonyLinkGraphics::SaveSection(FSettingsProfile& SettingsProfile, const bool bFlush)
void UHarmonyLinkGraphics::SaveSection(const FSettingsProfile& SettingsProfile, const bool bDefaultConfig, const bool bFlush)
{
if (GConfig)
{
const FString Filename = GetConfigDirectoryFile();
const FString Filename = GetConfigDirectoryFile(bDefaultConfig);
for (const auto& Setting : SettingsProfile.Settings)
{
FString TypeString;
@ -490,7 +536,7 @@ bool UHarmonyLinkGraphics::ApplyProfileInternal(const EProfile Profile)
void UHarmonyLinkGraphics::OnPostWorldInitialization(UWorld* World, UWorld::InitializationValues IVS)
{
if (!World)
if (!World || !World->IsValidLowLevel())
{
UE_LOG(LogHarmonyLink, Error, TEXT("Failed to Hook into World Initialisation!"))
return;
@ -498,18 +544,29 @@ void UHarmonyLinkGraphics::OnPostWorldInitialization(UWorld* World, UWorld::Init
if (World->IsGameWorld())
{
if (UHarmonyLinkGraphics* Settings = GetSettings())
if (_INSTANCE)
{
if (World->IsPlayInEditor())
FTimerManager* TimerManager = &World->GetTimerManager();
if (!TimerManager)
{
Settings->LoadConfig(true);
UE_LOG(LogHarmonyLink, Error, TEXT("Failed get TimerManager!"))
return;
}
if (!World->GetTimerManager().TimerExists(Settings->_TickTimerHandle) || !World->GetTimerManager().IsTimerActive(Settings->_TickTimerHandle))
if (!TimerManager->TimerExists(_INSTANCE->_TickTimerHandle) || !TimerManager->IsTimerActive(_INSTANCE->_TickTimerHandle))
{
World->GetTimerManager().SetTimer(Settings->_TickTimerHandle, [Settings]
World->GetTimerManager().SetTimer(_INSTANCE->_TickTimerHandle, [&, TimerManager]
{
Settings->Tick();
if (!this)
{
UE_LOG(LogHarmonyLink, Error, TEXT("'This' is destroyed, Clearing timer."))
if (TimerManager)
{
TimerManager->ClearTimer(_TickTimerHandle);
}
return;
}
Tick();
}, _TickRate, true);
}
}
@ -518,7 +575,7 @@ void UHarmonyLinkGraphics::OnPostWorldInitialization(UWorld* World, UWorld::Init
void UHarmonyLinkGraphics::OnWorldEnd(UWorld* World)
{
if (!World)
if (!World || !World->IsValidLowLevel())
{
UE_LOG(LogHarmonyLink, Error, TEXT("World Already destroyed"))
return;
@ -533,10 +590,10 @@ void UHarmonyLinkGraphics::OnWorldEnd(UWorld* World)
DestroySettings();
}
bool UHarmonyLinkGraphics::ApplyProfile(const EProfile Profile, const bool bDisableAuto)
bool UHarmonyLinkGraphics::ApplyProfile(const EProfile Profile, const bool bDisableAutomaticSwitch)
{
// Manual profile change, turn off automatic switching
if (bDisableAuto)
if (bDisableAutomaticSwitch)
{
_bAutomaticSwitch = false;
}

View file

@ -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.
*/

View file

@ -33,81 +33,468 @@ public:
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, 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 bDisableAuto = true);
bool ApplyProfile(EProfile Profile, const bool bDisableAutomaticSwitch = true);
/** Returns the game local machine settings (resolution, windowing mode, scalability settings, etc...) */
/**
* @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, 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, 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();
static FString GetConfigDirectoryFile();
bool LoadSettingsFromConfig();
/**
* @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(const bool bLoadDefaults);
/**
* @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.
*/
bool LoadSection(const FConfigFile& ConfigFile, const TPair<EProfile, FName> Profile);
static void SaveSection(FSettingsProfile& SettingsProfile, const bool bFlush = false);
/**
* @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.
*/
static void SaveSection(const FSettingsProfile& SettingsProfile, const bool bDefaultConfig, const bool bFlush = false);
/**
* @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();
/**
* @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.
*/
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.
*/
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();
// Note: Turning off HarmonyLink Settings requires game restart
/**
* @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);
// Debugging
/**
* @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;
/**
* @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);
uint8 _bAutomaticSwitch :1;
// Indicates whether automatic profile switching is enabled.
bool _bAutomaticSwitch = false;
// Stores the last recorded battery percentage.
int32 _LastBatteryPercentage = 0;
// How many times to query HarmonyLinkLib for hardware info
// The rate at which to query HarmonyLinkLib for hardware info.
static int32 _TickRate;
FTimerHandle _TickTimerHandle;
// Timer handle for managing the periodic tick function.
static FTimerHandle _TickTimerHandle;
// The currently active profile.
EProfile _ActiveProfile = EProfile::NONE;
// Maps profile enums to their corresponding names.
TMap<EProfile, FName> _ProfileNames = {
{EProfile::BATTERY, "Battery"},
{EProfile::CHARGING, "Charging"},
{EProfile::DOCKED, "Docked"},
};
// Stores the settings profiles.
TMap<EProfile, FSettingsProfile> _Profiles;
// The default settings for profiles.
static TMap<FName, TMap<FName, FHLConfigValue>> _DefaultSettings;
// Singleton instance of UHarmonyLinkGraphics.
static UHarmonyLinkGraphics* _INSTANCE;
};

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -16,10 +16,14 @@
// Use a preprocessor definition to switch between export and import declarations
#ifdef _WIN32
#ifdef HARMONYLINKLIB_EXPORTS
#define HARMONYLINKLIB_API __declspec(dllexport)
#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

View file

@ -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

BIN
Source/ThirdParty/HarmonyLinkLib/lib/Linux/libHarmonyLinkLibStatic.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

Binary file not shown.