RealtimeStyleTransferRuntime/Plugins/GameSettings/Source/Private/GameSetting.cpp

335 lines
8.5 KiB
C++
Raw Normal View History

2022-05-23 18:41:30 +00:00
// Copyright Epic Games, Inc. All Rights Reserved.
#include "GameSetting.h"
#include "Framework/Text/ITextDecorator.h"
#include "Framework/Text/RichTextMarkupProcessing.h"
#include "Templates/UnrealTemplate.h"
#include "Engine/LocalPlayer.h"
#define LOCTEXT_NAMESPACE "GameSetting"
#define UE_CAN_SHOW_SETTINGS_DEBUG_INFO (!UE_BUILD_SHIPPING)
namespace GameSettingsConsoleVars
{
#if UE_CAN_SHOW_SETTINGS_DEBUG_INFO
int32 ShowDebugInfoMode = -1;
static FAutoConsoleVariableRef CVarGameSettingsShowDebugInfo(
TEXT("GameSettings.ShowDebugInfo"),
ShowDebugInfoMode,
TEXT("Should we show the developer name and class as part of dynamic details?\n")
TEXT(" -1: Default (enabled in editor, disabled in -game or cooked builds)\n")
TEXT(" 0: Never show it\n")
TEXT(" 1: Always show it\n")
TEXT("\n")
TEXT(" Note: Shipping builds always disable this"),
ECVF_Default);
#endif
}
//--------------------------------------
// UGameSetting
//--------------------------------------
void UGameSetting::Initialize(ULocalPlayer* InLocalPlayer)
{
// If we've already gotten this local player we're already initialized.
if (LocalPlayer == InLocalPlayer)
{
return;
}
LocalPlayer = InLocalPlayer;
//TODO: GameSettings
//LocalPlayer->OnPlayerLoggedIn().AddUObject(this, &UGameSetting::RefreshEditableState, true);
#if !UE_BUILD_SHIPPING
ensureAlwaysMsgf(DevName != NAME_None, TEXT("You must provide a DevName for the setting."));
ensureAlwaysMsgf(!DisplayName.IsEmpty(), TEXT("You must provide a DisplayName for settings."));
#endif
for (const TSharedRef<FGameSettingEditCondition>& EditCondition : EditConditions)
{
EditCondition->Initialize(LocalPlayer);
}
// If there are any child settings go ahead and initialize them as well.
for (UGameSetting* Setting : GetChildSettings())
{
Setting->Initialize(LocalPlayer);
}
Startup();
}
void UGameSetting::Startup()
{
StartupComplete();
}
void UGameSetting::StartupComplete()
{
ensureMsgf(!bReady, TEXT("StartupComplete called twice."));
if (!bReady)
{
bReady = true;
OnInitialized();
}
}
void UGameSetting::Apply()
{
OnApply();
// Run through any edit conditions and let them know things changed.
for (const TSharedRef<FGameSettingEditCondition>& EditCondition : EditConditions)
{
EditCondition->SettingApplied(LocalPlayer, this);
}
2022-09-13 07:18:28 +00:00
OnSettingAppliedEvent.Broadcast(this);
2022-05-23 18:41:30 +00:00
}
void UGameSetting::OnInitialized()
{
ensureMsgf(bReady, TEXT("OnInitialized called directly instead of via StartupComplete."));
EditableStateCache = ComputeEditableState();
}
void UGameSetting::OnApply()
{
// No-Op by default.
}
UWorld* UGameSetting::GetWorld() const
{
return LocalPlayer ? LocalPlayer->GetWorld() : nullptr;
}
void UGameSetting::SetSettingParent(UGameSetting* InSettingParent)
{
SettingParent = InSettingParent;
}
FGameSettingEditableState UGameSetting::ComputeEditableState() const
{
FGameSettingEditableState EditState;
// Does this setting itself have any special rules?
OnGatherEditState(EditState);
// Run through any edit conditions
for (const TSharedRef<FGameSettingEditCondition>& EditCondition : EditConditions)
{
EditCondition->GatherEditState(LocalPlayer, EditState);
}
return EditState;
}
void UGameSetting::OnGatherEditState(FGameSettingEditableState& InOutEditState) const
{
}
const FString& UGameSetting::GetDescriptionPlainText() const
{
RefreshPlainText();
return AutoGenerated_DescriptionPlainText;
}
void UGameSetting::RefreshPlainText() const
{
//TODO: GameSettings
// TODO NDarnell Settings - Will need to recache if the language changes.
if (bRefreshPlainSearchableText)
{
TArray<FTextLineParseResults> ActualResultsArray;
FString ActualOutput;
FDefaultRichTextMarkupParser::GetStaticInstance()->Process(ActualResultsArray, DescriptionRichText.ToString(), ActualOutput);
AutoGenerated_DescriptionPlainText.Reset();
for (const FTextLineParseResults& Line : ActualResultsArray)
{
for (const FTextRunParseResults& Run : Line.Runs)
{
if (Run.Name.IsEmpty())
{
AutoGenerated_DescriptionPlainText.Append(ActualOutput.Mid(Run.OriginalRange.BeginIndex, Run.OriginalRange.Len()));
}
else if (!Run.ContentRange.IsEmpty())
{
AutoGenerated_DescriptionPlainText.Append(ActualOutput.Mid(Run.ContentRange.BeginIndex, Run.ContentRange.Len()));
}
}
}
bRefreshPlainSearchableText = false;
}
}
void UGameSetting::NotifySettingChanged(EGameSettingChangeReason Reason)
{
OnSettingChanged(Reason);
// Run through any edit conditions and let them know things changed.
for (const TSharedRef<FGameSettingEditCondition>& EditCondition : EditConditions)
{
EditCondition->SettingChanged(LocalPlayer, this, Reason);
}
if (!bOnSettingChangedEventGuard)
{
TGuardValue<bool> Guard(bOnSettingChangedEventGuard, true);
OnSettingChangedEvent.Broadcast(this, Reason);
}
}
void UGameSetting::OnSettingChanged(EGameSettingChangeReason Reason)
{
// No-Op
}
void UGameSetting::AddEditCondition(const TSharedRef<FGameSettingEditCondition>& InEditCondition)
{
EditConditions.Add(InEditCondition);
InEditCondition->OnEditConditionChangedEvent.AddUObject(this, &ThisClass::RefreshEditableState);
}
void UGameSetting::AddEditDependency(UGameSetting* DependencySetting)
{
if (ensure(DependencySetting))
{
DependencySetting->OnSettingChangedEvent.AddUObject(this, &ThisClass::HandleEditDependencyChanged);
DependencySetting->OnSettingEditConditionChangedEvent.AddUObject(this, &ThisClass::HandleEditDependencyChanged);
}
}
void UGameSetting::RefreshEditableState(bool bNotifyEditConditionsChanged)
{
// The LocalPlayer may be destroyed out from under us, if that happens,
// we need to ignore attempts to refresh the editable state.
if (!LocalPlayer)
{
return;
}
//TODO: GameSettings
//// We should wait until the player is fully logged in before trying to refresh settings.
//if (!LocalPlayer->IsLoggedIn())
//{
// return;
//}
if (!bOnEditConditionsChangedEventGuard)
{
TGuardValue<bool> Guard(bOnEditConditionsChangedEventGuard, true);
EditableStateCache = ComputeEditableState();
if (bNotifyEditConditionsChanged)
{
NotifyEditConditionsChanged();
}
}
}
void UGameSetting::NotifyEditConditionsChanged()
{
OnEditConditionsChanged();
OnSettingEditConditionChangedEvent.Broadcast(this);
}
void UGameSetting::OnEditConditionsChanged()
{
}
void UGameSetting::HandleEditDependencyChanged(UGameSetting* DependencySetting)
{
OnDependencyChanged();
RefreshEditableState();
}
void UGameSetting::HandleEditDependencyChanged(UGameSetting* DependencySetting, EGameSettingChangeReason Reason)
{
OnDependencyChanged();
RefreshEditableState();
if (Reason != EGameSettingChangeReason::DependencyChanged)
{
NotifySettingChanged(EGameSettingChangeReason::DependencyChanged);
}
}
void UGameSetting::OnDependencyChanged()
{
}
FText UGameSetting::GetDynamicDetails() const
{
if (!LocalPlayer)
{
return FText::GetEmpty();
}
FText DynamicDetailsText = DynamicDetails.IsBound() ? DynamicDetails.Execute(*LocalPlayer) : FText::GetEmpty();
#if UE_CAN_SHOW_SETTINGS_DEBUG_INFO
if ((GameSettingsConsoleVars::ShowDebugInfoMode == 1) || ((GameSettingsConsoleVars::ShowDebugInfoMode == -1) && GIsEditor))
{
const FString DevSettingDetails = FString::Printf(TEXT("%s<debug>DevName: %s</>\n<debug>Class: %s</>"),
DynamicDetailsText.IsEmpty() ? TEXT("") : TEXT("\n"),
*DevName.ToString(),
*GetClass()->GetName());
DynamicDetailsText = FText::Format(LOCTEXT("DevDynamicDetailsFormat", "{0}{1}"),
DynamicDetailsText,
FText::FromString(DevSettingDetails));
}
#endif
return DynamicDetailsText;
}
FText UGameSetting::GetDynamicDetailsInternal() const
{
return FText::GetEmpty();
}
UGameSetting::FStringCultureCache::FStringCultureCache(TFunction<FString()> InStringGetter)
: Culture(FInternationalization::Get().GetCurrentCulture())
, StringGetter(InStringGetter)
{
StringCache = StringGetter();
}
void UGameSetting::FStringCultureCache::Invalidate()
{
StringCache = StringGetter();
Culture = FInternationalization::Get().GetCurrentCulture();
}
FString UGameSetting::FStringCultureCache::Get() const
{
if (Culture == FInternationalization::Get().GetCurrentCulture())
{
return StringCache;
}
StringCache = StringGetter();
Culture = FInternationalization::Get().GetCurrentCulture();
return StringCache;
}
#undef LOCTEXT_NAMESPACE