diff --git a/Binaries/Win64/UnrealEditor-SettingsWidgetConstructor.dll b/Binaries/Win64/UnrealEditor-SettingsWidgetConstructor.dll
index 9ea4320..3386516 100644
Binary files a/Binaries/Win64/UnrealEditor-SettingsWidgetConstructor.dll and b/Binaries/Win64/UnrealEditor-SettingsWidgetConstructor.dll differ
diff --git a/Binaries/Win64/UnrealEditor-SettingsWidgetConstructor.pdb b/Binaries/Win64/UnrealEditor-SettingsWidgetConstructor.pdb
index 0495de0..72c175b 100644
Binary files a/Binaries/Win64/UnrealEditor-SettingsWidgetConstructor.pdb and b/Binaries/Win64/UnrealEditor-SettingsWidgetConstructor.pdb differ
diff --git a/Binaries/Win64/UnrealEditor-SettingsWidgetConstructorEditor.dll b/Binaries/Win64/UnrealEditor-SettingsWidgetConstructorEditor.dll
index 9091c7f..9d6f036 100644
Binary files a/Binaries/Win64/UnrealEditor-SettingsWidgetConstructorEditor.dll and b/Binaries/Win64/UnrealEditor-SettingsWidgetConstructorEditor.dll differ
diff --git a/Binaries/Win64/UnrealEditor-SettingsWidgetConstructorEditor.pdb b/Binaries/Win64/UnrealEditor-SettingsWidgetConstructorEditor.pdb
index f8456e2..434aee7 100644
Binary files a/Binaries/Win64/UnrealEditor-SettingsWidgetConstructorEditor.pdb and b/Binaries/Win64/UnrealEditor-SettingsWidgetConstructorEditor.pdb differ
diff --git a/Binaries/Win64/UnrealEditor.modules b/Binaries/Win64/UnrealEditor.modules
index 7583808..f50e933 100644
--- a/Binaries/Win64/UnrealEditor.modules
+++ b/Binaries/Win64/UnrealEditor.modules
@@ -1,5 +1,5 @@
{
- "BuildId": "25360045",
+ "BuildId": "27405482",
"Modules":
{
"SettingsWidgetConstructor": "UnrealEditor-SettingsWidgetConstructor.dll",
diff --git a/Config/BaseSettingsDataTable.json b/Config/BaseSettingsDataTable.json
index 6f2e468..c200fa9 100644
--- a/Config/BaseSettingsDataTable.json
+++ b/Config/BaseSettingsDataTable.json
@@ -10,7 +10,7 @@
{
"TagName": "Settings.TextLine"
},
- "StaticContext":
+ "Owner":
{
"FunctionClass": "None",
"FunctionName": "None"
@@ -25,7 +25,7 @@
"FunctionClass": "None",
"FunctionName": "None"
},
- "Caption": "NSLOCTEXT(\"[F67605FD4FE1D83F0EC04D97554FA9A9]\", \"B1FD8AB64A187ECF1AF534A23B1EB4B9\", \"SETTINGS\")",
+ "Caption": "NSLOCTEXT(\"[B300B6BE227CC798280E67264B750EDE]\", \"9B5F34484FB5155A7E20C0B96B5D76AB\", \"SETTINGS\")",
"Tooltip": "NSLOCTEXT(\"Core\", \"None\", \"None\")",
"Padding":
{
@@ -40,6 +40,10 @@
{
"GameplayTags": [],
"ParentTags": []
+ },
+ "ShowNextToSettingOverride":
+ {
+ "TagName": "None"
}
},
"Button":
@@ -94,23 +98,23 @@
{
"TagName": "Settings.Combobox"
},
- "StaticContext":
+ "Owner":
{
- "FunctionClass": "None",
- "FunctionName": "None"
+ "FunctionClass": "/Script/CoreUObject.Class'/Script/SettingsWidgetConstructor.SettingsUtilsLibrary'",
+ "FunctionName": "GetGameUserSettings"
},
"Setter":
{
- "FunctionClass": "None",
- "FunctionName": "None"
+ "FunctionClass": "/Script/CoreUObject.Class'/Script/Engine.GameUserSettings'",
+ "FunctionName": "SetOverallScalabilityLevel"
},
"Getter":
{
- "FunctionClass": "None",
- "FunctionName": "None"
+ "FunctionClass": "/Script/CoreUObject.Class'/Script/Engine.GameUserSettings'",
+ "FunctionName": "GetOverallScalabilityLevel"
},
- "Caption": "NSLOCTEXT(\"[F67605FD4FE1D83F0EC04D97554FA9A9]\", \"C5758D8D4760AC9C55185480331D72DB\", \"Overall Quality\")",
- "Tooltip": "NSLOCTEXT(\"[F67605FD4FE1D83F0EC04D97554FA9A9]\", \"67193396456DFF30A0D91E85F3A0A62D\", \"Choose the overall quality level\")",
+ "Caption": "NSLOCTEXT(\"[B300B6BE227CC798280E67264B750EDE]\", \"3D05344D4AC20700809DC9B76E80BC28\", \"Overall Quality\")",
+ "Tooltip": "NSLOCTEXT(\"[B300B6BE227CC798280E67264B750EDE]\", \"9F345551422A4511C85D2B8E8D740C23\", \"Choose the overall quality level\")",
"Padding":
{
"Left": 0,
@@ -124,6 +128,10 @@
{
"GameplayTags": [],
"ParentTags": []
+ },
+ "ShowNextToSettingOverride":
+ {
+ "TagName": "None"
}
},
"Button":
@@ -147,12 +155,11 @@
"FunctionName": "None"
},
"Members": [
- "NSLOCTEXT(\"[F67605FD4FE1D83F0EC04D97554FA9A9]\", \"4BD5AC644E575D63EA6A51BAE630502E\", \"Custom\")",
- "NSLOCTEXT(\"[F67605FD4FE1D83F0EC04D97554FA9A9]\", \"9A1037DA4D94CD073C1A48A4E72533DB\", \"Low\")",
- "NSLOCTEXT(\"[F67605FD4FE1D83F0EC04D97554FA9A9]\", \"74DF82A24FD955EB28D2508AE0D01227\", \"Medium\")",
- "NSLOCTEXT(\"[F67605FD4FE1D83F0EC04D97554FA9A9]\", \"CE3E2FCE45CCF68724AEB2AAE98A46AA\", \"High\")",
- "NSLOCTEXT(\"[F67605FD4FE1D83F0EC04D97554FA9A9]\", \"402F856C457B291C5F3FC09F9136E9F8\", \"Very High\")",
- "NSLOCTEXT(\"[F67605FD4FE1D83F0EC04D97554FA9A9]\", \"BDDAE76445B3279B1F40D498D16C0C24\", \"Ultra\")"
+ "NSLOCTEXT(\"[B300B6BE227CC798280E67264B750EDE]\", \"CCA672154B5FEA29315F3EADAEF2019F\", \"Low\")",
+ "NSLOCTEXT(\"[B300B6BE227CC798280E67264B750EDE]\", \"3D9EECC54A0F8310659B85A3B3F7BB19\", \"Medium\")",
+ "NSLOCTEXT(\"[B300B6BE227CC798280E67264B750EDE]\", \"455615594854614F98882F94A79F65B1\", \"High\")",
+ "NSLOCTEXT(\"[B300B6BE227CC798280E67264B750EDE]\", \"80910DF74E3E587682422488BCBBD7A3\", \"Epic\")",
+ "NSLOCTEXT(\"[B300B6BE227CC798280E67264B750EDE]\", \"213FC09D4F9042E4C7F73BAE9D693D75\", \"Cinematic\")"
],
"TextJustify": "Center"
},
@@ -175,33 +182,33 @@
}
},
{
- "Name": "Settings.Slider",
+ "Name": "Settings.Checkbox",
"SettingsPicker":
{
- "SettingsType": "Slider",
+ "SettingsType": "Checkbox",
"PrimaryData":
{
"Tag":
{
- "TagName": "Settings.Slider"
+ "TagName": "Settings.Checkbox"
},
- "StaticContext":
+ "Owner":
{
- "FunctionClass": "None",
- "FunctionName": "None"
+ "FunctionClass": "/Script/CoreUObject.Class'/Script/SettingsWidgetConstructor.SettingsUtilsLibrary'",
+ "FunctionName": "GetGameUserSettings"
},
"Setter":
{
- "FunctionClass": "None",
- "FunctionName": "None"
+ "FunctionClass": "/Script/CoreUObject.Class'/Script/Engine.GameUserSettings'",
+ "FunctionName": "SetVSyncEnabled"
},
"Getter":
{
- "FunctionClass": "None",
- "FunctionName": "None"
+ "FunctionClass": "/Script/CoreUObject.Class'/Script/Engine.GameUserSettings'",
+ "FunctionName": "IsVSyncEnabled"
},
- "Caption": "NSLOCTEXT(\"[F67605FD4FE1D83F0EC04D97554FA9A9]\", \"FDDC03E84D349EAC5743FEB1C9E6B87D\", \"Music Volume\")",
- "Tooltip": "NSLOCTEXT(\"[F67605FD4FE1D83F0EC04D97554FA9A9]\", \"3EC174FB4DEA3029A69CEEA9C382A9DD\", \"Set the sound volume for the background music\")",
+ "Caption": "NSLOCTEXT(\"[B300B6BE227CC798280E67264B750EDE]\", \"4B34951E482BBA92506C3D8A3054B05B\", \"V-Sync\")",
+ "Tooltip": "NSLOCTEXT(\"[B300B6BE227CC798280E67264B750EDE]\", \"69E51E954CA7C3F7A9DB57A88A5B8BBA\", \"Check to enable the V-Sync\")",
"Padding":
{
"Left": 0,
@@ -215,6 +222,10 @@
{
"GameplayTags": [],
"ParentTags": []
+ },
+ "ShowNextToSettingOverride":
+ {
+ "TagName": "None"
}
},
"Button":
@@ -259,17 +270,17 @@
}
},
{
- "Name": "Settings.Checkbox",
+ "Name": "Settings.UserInput",
"SettingsPicker":
{
- "SettingsType": "Checkbox",
+ "SettingsType": "UserInput",
"PrimaryData":
{
"Tag":
{
- "TagName": "Settings.Checkbox"
+ "TagName": "Settings.UserInput"
},
- "StaticContext":
+ "Owner":
{
"FunctionClass": "None",
"FunctionName": "None"
@@ -284,8 +295,8 @@
"FunctionClass": "None",
"FunctionName": "None"
},
- "Caption": "NSLOCTEXT(\"[F67605FD4FE1D83F0EC04D97554FA9A9]\", \"30E1B9914168CFDFD022ACAAF72408A2\", \"Fullscreen\")",
- "Tooltip": "NSLOCTEXT(\"[F67605FD4FE1D83F0EC04D97554FA9A9]\", \"D4DAAF084A3BE24A202DE68898F1E2E5\", \"Check to enable the fullscreen mode\")",
+ "Caption": "NSLOCTEXT(\"[B300B6BE227CC798280E67264B750EDE]\", \"27AF3120412B8FDA02FE3F951893C245\", \"Player Name\")",
+ "Tooltip": "NSLOCTEXT(\"[B300B6BE227CC798280E67264B750EDE]\", \"002E379E4E5144B9BB5A128E98C49EDD\", \"Enter your nickname\")",
"Padding":
{
"Left": 0,
@@ -294,11 +305,15 @@
"Bottom": 15
},
"LineHeight": 48,
- "bStartOnNextColumn": false,
+ "bStartOnNextColumn": true,
"SettingsToUpdate":
{
"GameplayTags": [],
"ParentTags": []
+ },
+ "ShowNextToSettingOverride":
+ {
+ "TagName": "None"
}
},
"Button":
@@ -334,7 +349,7 @@
},
"UserInput":
{
- "MaxCharactersNumber": 0
+ "MaxCharactersNumber": 16
},
"CustomWidget":
{
@@ -343,17 +358,17 @@
}
},
{
- "Name": "Settings.UserInput",
+ "Name": "Settings.Slider",
"SettingsPicker":
{
- "SettingsType": "UserInput",
+ "SettingsType": "Slider",
"PrimaryData":
{
"Tag":
{
- "TagName": "Settings.UserInput"
+ "TagName": "Settings.Slider"
},
- "StaticContext":
+ "Owner":
{
"FunctionClass": "None",
"FunctionName": "None"
@@ -368,8 +383,8 @@
"FunctionClass": "None",
"FunctionName": "None"
},
- "Caption": "NSLOCTEXT(\"[F67605FD4FE1D83F0EC04D97554FA9A9]\", \"0A4D44494F98A414FFD6F399B8C3DAFE\", \"Player Name\")",
- "Tooltip": "NSLOCTEXT(\"[F67605FD4FE1D83F0EC04D97554FA9A9]\", \"91BCE84A4CF9B58F61A9C8BB16663DB5\", \"Enter your nickname\")",
+ "Caption": "NSLOCTEXT(\"[B300B6BE227CC798280E67264B750EDE]\", \"B93D9EA548CA0CFCED454784E1FD16D4\", \"Player Name Scale\")",
+ "Tooltip": "NSLOCTEXT(\"[B300B6BE227CC798280E67264B750EDE]\", \"921CAF0148DA0D735D5A358549AF2F1C\", \"Set the Player Scale Scale\")",
"Padding":
{
"Left": 0,
@@ -378,11 +393,15 @@
"Bottom": 15
},
"LineHeight": 48,
- "bStartOnNextColumn": true,
+ "bStartOnNextColumn": false,
"SettingsToUpdate":
{
"GameplayTags": [],
"ParentTags": []
+ },
+ "ShowNextToSettingOverride":
+ {
+ "TagName": "None"
}
},
"Button":
@@ -418,7 +437,7 @@
},
"UserInput":
{
- "MaxCharactersNumber": 8
+ "MaxCharactersNumber": 0
},
"CustomWidget":
{
@@ -437,23 +456,23 @@
{
"TagName": "Settings.Button"
},
- "StaticContext":
+ "Owner":
{
- "FunctionClass": "None",
- "FunctionName": "None"
+ "FunctionClass": "/Script/CoreUObject.Class'/Script/SettingsWidgetConstructor.SettingsUtilsLibrary'",
+ "FunctionName": "GetSettingsWidget"
},
"Setter":
{
- "FunctionClass": "None",
- "FunctionName": "None"
+ "FunctionClass": "/Script/CoreUObject.Class'/Script/SettingsWidgetConstructor.SettingsWidget'",
+ "FunctionName": "SaveSettings"
},
"Getter":
{
"FunctionClass": "None",
"FunctionName": "None"
},
- "Caption": "NSLOCTEXT(\"[F67605FD4FE1D83F0EC04D97554FA9A9]\", \"CFC97B654007D0E10720D4B425844586\", \"Back\")",
- "Tooltip": "NSLOCTEXT(\"[F67605FD4FE1D83F0EC04D97554FA9A9]\", \"A31C26AB4E3A28D6819DC4A4D7EFA70D\", \"Return back to the main menu\")",
+ "Caption": "NSLOCTEXT(\"[B300B6BE227CC798280E67264B750EDE]\", \"2F0E1E0E4E3EC020E6020FB66C005751\", \"Apply\")",
+ "Tooltip": "NSLOCTEXT(\"[B300B6BE227CC798280E67264B750EDE]\", \"BFD2A32B4EDE7484E5AA3499437BB3D7\", \"Apply and save all settings to config\")",
"Padding":
{
"Left": 0,
@@ -467,6 +486,10 @@
{
"GameplayTags": [],
"ParentTags": []
+ },
+ "ShowNextToSettingOverride":
+ {
+ "TagName": "None"
}
},
"Button":
@@ -510,4 +533,4 @@
}
}
}
-]
+]
\ No newline at end of file
diff --git a/Config/BaseSettingsWidgetConstructor.ini b/Config/BaseSettingsWidgetConstructor.ini
index 2c521b3..6bc0ac6 100644
--- a/Config/BaseSettingsWidgetConstructor.ini
+++ b/Config/BaseSettingsWidgetConstructor.ini
@@ -3,6 +3,7 @@ SettingsWidgetClassInternal=WidgetBlueprintGeneratedClass'/SettingsWidgetConstru
[/Script/SettingsWidgetConstructor.SettingsDataAsset]
SettingsDataTableInternal=
+SettingsDataRegistryInternal=/SettingsWidgetConstructor/Data/DR_SettingsDataTables.DR_SettingsDataTables
ButtonClassInternal=WidgetBlueprintGeneratedClass'/SettingsWidgetConstructor/Subwidgets/WBP_SettingsButton.WBP_SettingsButton_C'
CheckboxClassInternal=WidgetBlueprintGeneratedClass'/SettingsWidgetConstructor/Subwidgets/WBP_SettingsCheckBox.WBP_SettingsCheckBox_C'
ComboboxClassInternal=WidgetBlueprintGeneratedClass'/SettingsWidgetConstructor/Subwidgets/WBP_SettingsCombobox.WBP_SettingsCombobox_C'
@@ -10,6 +11,7 @@ SliderClassInternal=WidgetBlueprintGeneratedClass'/SettingsWidgetConstructor/Sub
TextLineClassInternal=WidgetBlueprintGeneratedClass'/SettingsWidgetConstructor/Subwidgets/WBP_SettingsTextLine.WBP_SettingsTextLine_C'
UserInputClassInternal=WidgetBlueprintGeneratedClass'/SettingsWidgetConstructor/Subwidgets/WBP_SettingsTextInput.WBP_SettingsTextInput_C'
bAutoConstructInternal=True
+bAutoFocusOnOpenInternal=True
SettingsPercentSizeInternal=(X=0.600000,Y=0.400000)
SettingsPaddingInternal=(Left=50.000000,Top=50.000000,Right=50.000000,Bottom=50.000000)
ScrollboxPercentHeightInternal=1.000000
diff --git a/Content/Data/DR_SettingsDataTables.uasset b/Content/Data/DR_SettingsDataTables.uasset
new file mode 100644
index 0000000..0942d35
Binary files /dev/null and b/Content/Data/DR_SettingsDataTables.uasset differ
diff --git a/Content/WBP_SettingsWidgetConstructor.uasset b/Content/WBP_SettingsWidgetConstructor.uasset
index 2519a5d..13c2864 100644
Binary files a/Content/WBP_SettingsWidgetConstructor.uasset and b/Content/WBP_SettingsWidgetConstructor.uasset differ
diff --git a/README.md b/README.md
index 7ea43ef..243224c 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@ Settings Widget Constructor is a handy plugin for Unreal Engine 5 that lets you
![Settings UI](https://user-images.githubusercontent.com/20540872/147825296-ce7d33da-dfda-4757-b070-bfd08f700134.jpg)
-
+
## 📚 Documentation
@@ -17,12 +17,21 @@ Check out our [Release](https://github.com/JanSeliv/SettingsWidgetConstructor/re
Also, explore this [game project repository](https://github.com/JanSeliv/Bomber) to view the Settings Widget Constructor in action.
## 📅 Changelog
+#### 2023-10-12
+- Updated to **Unreal Engine 5.3**
+- Added **multiple Settings Data Tables** support ([see doc](https://docs.google.com/document/d/1IXnOqrgaXTClP-0cIo28a9f6GHc9N1BCgTNnMk-X9VQ/edit#heading=h.cix3vjszb2vm)).
+- Implemented **Deferred Bindings**: now Getters and Setters are automatically rebound for failed settings.
+- Added **Blueprint Function Library** support to allow any its blueprint function to be used as an _Owner_ in a setting row.
#### 2023-05-26
- 🎉 Initial public release on Unreal Engine 5.2
## 📫 Feedback & Contribution
-This is an open-source project and we encourage you to contribute. If you encounter any bugs, or if you have any feature requests, please file an issue in the GitHub repository.
+Feedback and contributions from the community are highly appreciated!
+
+If you'd like to contribute, please fork the project and create a pull request targeting the `develop` branch.
+
+If you've found a bug or have an idea for a new feature, please open a new issue on GitHub. Thank you!
## 📜 License
diff --git a/SettingsWidgetConstructor.uplugin b/SettingsWidgetConstructor.uplugin
index fd9fd14..e315d22 100644
--- a/SettingsWidgetConstructor.uplugin
+++ b/SettingsWidgetConstructor.uplugin
@@ -10,7 +10,7 @@
"DocsURL": "",
"MarketplaceURL": "",
"SupportURL": "mailto:janseliw@gmail.com",
- "EngineVersion": "5.2.0",
+ "EngineVersion": "5.3.0",
"EnabledByDefault": true,
"CanContainContent": true,
"IsBetaVersion": false,
@@ -31,6 +31,10 @@
{
"Name": "GameplayTagsEditor",
"Enabled": true
+ },
+ {
+ "Name": "DataRegistry",
+ "Enabled": true
}
]
}
diff --git a/Source/SettingsWidgetConstructor/Private/Data/SettingArchetypesData.cpp b/Source/SettingsWidgetConstructor/Private/Data/SettingArchetypesData.cpp
new file mode 100644
index 0000000..21c2781
--- /dev/null
+++ b/Source/SettingsWidgetConstructor/Private/Data/SettingArchetypesData.cpp
@@ -0,0 +1,265 @@
+// Copyright (c) Yevhenii Selivanov
+
+#include "Data/SettingArchetypesData.h"
+//---
+#include "Data/SettingsDataAsset.h"
+#include "Data/SettingTag.h"
+#include "UI/SettingSubWidget.h"
+#include "UI/SettingsWidget.h"
+//---
+#include UE_INLINE_GENERATED_CPP_BY_NAME(SettingArchetypesData)
+
+/*********************************************************************************************
+ * FSettingsButton
+ ********************************************************************************************* */
+
+// Returns the sub-widget class of this setting type
+TSubclassOf FSettingsButton::GetSubWidgetClass() const
+{
+ return USettingsDataAsset::Get().GetButtonClass();
+}
+
+// Calls the Set function of the Settings Widget of this setting type
+void FSettingsButton::SetSettingValue(USettingsWidget& SettingsWidget, const FSettingTag& Tag, const FString& Value)
+{
+ SettingsWidget.SetSettingButtonPressed(Tag);
+}
+
+// Calls the Bind function of the Settings Widget of this setting type
+void FSettingsButton::BindSetting(USettingsWidget& SettingsWidget, const FSettingsPrimary& PrimaryData)
+{
+ SettingsWidget.BindButton(PrimaryData, *this);
+}
+
+// Calls the Add function of the Settings Widget of this setting type
+void FSettingsButton::AddSetting(USettingsWidget& SettingsWidget, const FSettingsPrimary& PrimaryData)
+{
+ SettingsWidget.AddButton(PrimaryData, *this);
+}
+
+/*********************************************************************************************
+ * FSettingsCheckbox
+ ********************************************************************************************* */
+
+// Returns the sub-widget class of this setting type
+TSubclassOf FSettingsCheckbox::GetSubWidgetClass() const
+{
+ return USettingsDataAsset::Get().GetCheckboxClass();
+}
+
+// Calls the Get function of the Settings Widget of this setting type
+void FSettingsCheckbox::GetSettingValue(const USettingsWidget& SettingsWidget, const FSettingTag& Tag, FString& OutResult) const
+{
+ const bool Value = SettingsWidget.GetCheckboxValue(Tag);
+ OutResult = Value ? TEXT("true") : TEXT("false");
+}
+
+// Calls the Set function of the Settings Widget of this setting type
+void FSettingsCheckbox::SetSettingValue(USettingsWidget& SettingsWidget, const FSettingTag& Tag, const FString& Value)
+{
+ const bool NewValue = Value.ToBool();
+ SettingsWidget.SetSettingCheckbox(Tag, NewValue);
+}
+
+// Calls the Bind function of the Settings Widget of this setting type
+void FSettingsCheckbox::BindSetting(USettingsWidget& SettingsWidget, const FSettingsPrimary& PrimaryData)
+{
+ SettingsWidget.BindCheckbox(PrimaryData, *this);
+}
+
+// Calls the Add function of the Settings Widget of this setting type
+void FSettingsCheckbox::AddSetting(USettingsWidget& SettingsWidget, const FSettingsPrimary& InOutPrimaryData)
+{
+ SettingsWidget.AddCheckbox(InOutPrimaryData, *this);
+}
+
+/*********************************************************************************************
+ * FSettingsCombobox
+ ********************************************************************************************* */
+
+// Returns the sub-widget class of this setting type
+TSubclassOf FSettingsCombobox::GetSubWidgetClass() const
+{
+ return USettingsDataAsset::Get().GetComboboxClass();
+}
+
+// Calls the Get function of the Settings Widget of this setting type
+void FSettingsCombobox::GetSettingValue(const USettingsWidget& SettingsWidget, const FSettingTag& Tag, FString& OutResult) const
+{
+ const int32 Value = SettingsWidget.GetComboboxIndex(Tag);
+ OutResult = FString::Printf(TEXT("%d"), Value);
+}
+
+// Calls the Set function of the Settings Widget of this setting type
+void FSettingsCombobox::SetSettingValue(USettingsWidget& SettingsWidget, const FSettingTag& Tag, const FString& Value)
+{
+ if (Value.IsNumeric())
+ {
+ const int32 NewValue = FCString::Atoi(*Value);
+ SettingsWidget.SetSettingComboboxIndex(Tag, NewValue);
+ }
+ else
+ {
+ static const FString Delimiter = TEXT(",");
+ TArray SeparatedStrings;
+ Value.ParseIntoArray(SeparatedStrings, *Delimiter);
+
+ TArray NewMembers;
+ NewMembers.Reserve(SeparatedStrings.Num());
+ for (FString& StringIt : SeparatedStrings)
+ {
+ NewMembers.Emplace(FText::FromString(MoveTemp(StringIt)));
+ }
+ SettingsWidget.SetSettingComboboxMembers(Tag, NewMembers);
+ }
+}
+
+// Calls the Bind function of the Settings Widget of this setting type
+void FSettingsCombobox::BindSetting(USettingsWidget& SettingsWidget, const FSettingsPrimary& PrimaryData)
+{
+ SettingsWidget.BindCombobox(PrimaryData, *this);
+}
+
+// Calls the Add function of the Settings Widget of this setting type
+void FSettingsCombobox::AddSetting(USettingsWidget& SettingsWidget, const FSettingsPrimary& InOutPrimaryData)
+{
+ SettingsWidget.AddCombobox(InOutPrimaryData, *this);
+}
+
+/*********************************************************************************************
+ * FSettingsSlider
+ ********************************************************************************************* */
+
+// Returns the sub-widget class of this setting type
+TSubclassOf FSettingsSlider::GetSubWidgetClass() const
+{
+ return USettingsDataAsset::Get().GetSliderClass();
+}
+
+// Calls the Get function of the Settings Widget of this setting type
+void FSettingsSlider::GetSettingValue(const USettingsWidget& SettingsWidget, const FSettingTag& Tag, FString& OutResult) const
+{
+ const double Value = SettingsWidget.GetSliderValue(Tag);
+ OutResult = FString::Printf(TEXT("%f"), Value);
+}
+
+// Calls the Set function of the Settings Widget of this setting type
+void FSettingsSlider::SetSettingValue(USettingsWidget& SettingsWidget, const FSettingTag& Tag, const FString& Value)
+{
+ const double NewValue = FCString::Atod(*Value);
+ SettingsWidget.SetSettingSlider(Tag, NewValue);
+}
+
+// Calls the Bind function of the Settings Widget of this setting type
+void FSettingsSlider::BindSetting(USettingsWidget& SettingsWidget, const FSettingsPrimary& PrimaryData)
+{
+ SettingsWidget.BindSlider(PrimaryData, *this);
+}
+
+// Calls the Add function of the Settings Widget of this setting type
+void FSettingsSlider::AddSetting(USettingsWidget& SettingsWidget, const FSettingsPrimary& InOutPrimaryData)
+{
+ SettingsWidget.AddSlider(InOutPrimaryData, *this);
+}
+
+/*********************************************************************************************
+ * FSettingsTextLine
+ ********************************************************************************************* */
+
+// Returns the sub-widget class of this setting type
+TSubclassOf FSettingsTextLine::GetSubWidgetClass() const
+{
+ return USettingsDataAsset::Get().GetTextLineClass();
+}
+
+// Calls the Get function of the Settings Widget of this setting type
+void FSettingsTextLine::GetSettingValue(const USettingsWidget& SettingsWidget, const FSettingTag& Tag, FString& OutResult) const
+{
+ FText OutText;
+ SettingsWidget.GetTextLineValue(Tag, OutText);
+ OutResult = OutText.ToString();
+}
+
+// Calls the Set function of the Settings Widget of this setting type
+void FSettingsTextLine::SetSettingValue(USettingsWidget& SettingsWidget, const FSettingTag& Tag, const FString& Value)
+{
+ const FText NewValue = FText::FromString(Value);
+ SettingsWidget.SetSettingTextLine(Tag, NewValue);
+}
+
+// Calls the Bind function of the Settings Widget of this setting type
+void FSettingsTextLine::BindSetting(USettingsWidget& SettingsWidget, const FSettingsPrimary& PrimaryData)
+{
+ SettingsWidget.BindTextLine(PrimaryData, *this);
+}
+
+// Calls the Add function of the Settings Widget of this setting type
+void FSettingsTextLine::AddSetting(USettingsWidget& SettingsWidget, const FSettingsPrimary& InOutPrimaryData)
+{
+ SettingsWidget.AddTextLine(InOutPrimaryData, *this);
+}
+
+/*********************************************************************************************
+ * FSettingsUserInput
+ ********************************************************************************************* */
+
+// Returns the sub-widget class of this setting type
+TSubclassOf FSettingsUserInput::GetSubWidgetClass() const
+{
+ return USettingsDataAsset::Get().GetUserInputClass();
+}
+
+// Calls the Get function of the Settings Widget of this setting type
+void FSettingsUserInput::GetSettingValue(const USettingsWidget& SettingsWidget, const FSettingTag& Tag, FString& OutResult) const
+{
+ const FName Value = SettingsWidget.GetUserInputValue(Tag);
+ OutResult = Value.ToString();
+}
+
+// Calls the Set function of the Settings Widget of this setting type
+void FSettingsUserInput::SetSettingValue(USettingsWidget& SettingsWidget, const FSettingTag& Tag, const FString& Value)
+{
+ const FName NewValue = *Value;
+ SettingsWidget.SetSettingUserInput(Tag, NewValue);
+}
+
+// Calls the Bind function of the Settings Widget of this setting type
+void FSettingsUserInput::BindSetting(USettingsWidget& SettingsWidget, const FSettingsPrimary& PrimaryData)
+{
+ SettingsWidget.BindUserInput(PrimaryData, *this);
+}
+
+// Calls the Add function of the Settings Widget of this setting type
+void FSettingsUserInput::AddSetting(USettingsWidget& SettingsWidget, const FSettingsPrimary& InOutPrimaryData)
+{
+ SettingsWidget.AddUserInput(InOutPrimaryData, *this);
+}
+
+/*********************************************************************************************
+ * FSettingsCustomWidget
+ ********************************************************************************************* */
+
+// Returns the sub-widget class of this setting type
+TSubclassOf FSettingsCustomWidget::GetSubWidgetClass() const
+{
+ return CustomWidgetClass;
+}
+
+// Calls the Get function of the Settings Widget of this setting type
+void FSettingsCustomWidget::GetSettingValue(const USettingsWidget& SettingsWidget, const FSettingTag& Tag, FString& OutResult) const
+{
+ const TSoftObjectPtr CustomWidget = SettingsWidget.GetCustomWidget(Tag);
+ OutResult = CustomWidget.IsValid() ? CustomWidget.ToSoftObjectPath().ToString() : TEXT("");
+}
+
+// Calls the Bind function of the Settings Widget of this setting type
+void FSettingsCustomWidget::BindSetting(USettingsWidget& SettingsWidget, const FSettingsPrimary& PrimaryData)
+{
+ SettingsWidget.BindCustomWidget(PrimaryData, *this);
+}
+
+// Calls the Add function of the Settings Widget of this setting type
+void FSettingsCustomWidget::AddSetting(USettingsWidget& SettingsWidget, const FSettingsPrimary& InOutPrimaryData)
+{
+ SettingsWidget.AddCustomWidget(InOutPrimaryData, *this);
+}
diff --git a/Source/SettingsWidgetConstructor/Private/Data/SettingTag.cpp b/Source/SettingsWidgetConstructor/Private/Data/SettingTag.cpp
index e52347a..eeeede2 100644
--- a/Source/SettingsWidgetConstructor/Private/Data/SettingTag.cpp
+++ b/Source/SettingsWidgetConstructor/Private/Data/SettingTag.cpp
@@ -2,7 +2,7 @@
#include "Data/SettingTag.h"
//---
-#include "GameplayTags/Classes/GameplayTagsManager.h"
+#include "GameplayTagsManager.h"
//---
#include UE_INLINE_GENERATED_CPP_BY_NAME(SettingTag)
diff --git a/Source/SettingsWidgetConstructor/Private/Data/SettingsDataAsset.cpp b/Source/SettingsWidgetConstructor/Private/Data/SettingsDataAsset.cpp
new file mode 100644
index 0000000..7eaceba
--- /dev/null
+++ b/Source/SettingsWidgetConstructor/Private/Data/SettingsDataAsset.cpp
@@ -0,0 +1,57 @@
+// Copyright (c) Yevhenii Selivanov
+
+#include "Data/SettingsDataAsset.h"
+//---
+#include "Data/SettingsDataTable.h"
+#include "MyUtilsLibraries/SettingsUtilsLibrary.h"
+//---
+#include UE_INLINE_GENERATED_CPP_BY_NAME(SettingsDataAsset)
+
+// Returns the data table, it has to be set manually
+const USettingsDataTable* USettingsDataAsset::GetSettingsDataTable() const
+{
+ return SettingsDataTableInternal.LoadSynchronous();
+}
+
+// Returns the Settings Data Registry asset, is automatically set by default to which 'Settings Data Table' is added by itself
+const UDataRegistry* USettingsDataAsset::GetSettingsDataRegistry() const
+{
+ return SettingsDataRegistryInternal.LoadSynchronous();
+}
+
+// Overrides post init to register Settings Data Table by default on startup
+void USettingsDataAsset::PostInitProperties()
+{
+ Super::PostInitProperties();
+
+ if (!GEngine || !GEngine->IsInitialized())
+ {
+ FCoreDelegates::OnPostEngineInit.AddUObject(this, &ThisClass::OnPostEngineInit);
+ }
+ else
+ {
+ OnPostEngineInit();
+ }
+}
+
+// Is called once Engine is initialized, so we can register Settings Data Table by default on startup
+void USettingsDataAsset::OnPostEngineInit()
+{
+ USettingsUtilsLibrary::RegisterDataTable(SettingsDataTableInternal);
+}
+
+#if WITH_EDITOR
+// Overrides property change events to handle picking Settings Data Table
+void USettingsDataAsset::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
+{
+ Super::PostEditChangeProperty(PropertyChangedEvent);
+
+ static const FName PropertyName = GET_MEMBER_NAME_CHECKED(USettingsDataAsset, SettingsDataTableInternal);
+ const FProperty* Property = PropertyChangedEvent.Property;
+ if (Property && Property->GetFName() == PropertyName)
+ {
+ // The Settings Data Table has been changed, so we have to register it
+ USettingsUtilsLibrary::RegisterDataTable(SettingsDataTableInternal);
+ }
+}
+#endif // WITH_EDITOR
diff --git a/Source/SettingsWidgetConstructor/Private/Data/SettingsDataTable.cpp b/Source/SettingsWidgetConstructor/Private/Data/SettingsDataTable.cpp
index 3cfb6ed..88d2eea 100644
--- a/Source/SettingsWidgetConstructor/Private/Data/SettingsDataTable.cpp
+++ b/Source/SettingsWidgetConstructor/Private/Data/SettingsDataTable.cpp
@@ -2,6 +2,8 @@
#include "Data/SettingsDataTable.h"
//---
+#include "Data/SettingsRow.h"
+//---
#if WITH_EDITOR
#include "DataTableEditorUtils.h" // FDataTableEditorUtils::RenameRow
#endif
diff --git a/Source/SettingsWidgetConstructor/Private/Data/SettingsRow.cpp b/Source/SettingsWidgetConstructor/Private/Data/SettingsRow.cpp
index 3a550ee..c2df7a1 100644
--- a/Source/SettingsWidgetConstructor/Private/Data/SettingsRow.cpp
+++ b/Source/SettingsWidgetConstructor/Private/Data/SettingsRow.cpp
@@ -16,11 +16,22 @@ bool FSettingsPrimary::operator==(const FSettingsPrimary& Other) const
return GetTypeHash(*this) == GetTypeHash(Other);
}
+// Is executed to obtain holding object
+UObject* FSettingsPrimary::GetSettingOwner(const UObject* WorldContext) const
+{
+ if (OwnerFunc.IsBound())
+ {
+ return OwnerFunc.Execute(WorldContext);
+ }
+
+ return nullptr;
+}
+
// Creates a hash value
uint32 GetTypeHash(const FSettingsPrimary& Other)
{
const uint32 TagHash = GetTypeHash(Other.Tag);
- const uint32 ObjectContextHash = GetTypeHash(Other.StaticContext);
+ const uint32 ObjectContextHash = GetTypeHash(Other.Owner);
const uint32 SetterHash = GetTypeHash(Other.Setter);
const uint32 GetterHash = GetTypeHash(Other.Getter);
const uint32 CaptionHash = GetTypeHash(Other.Caption.ToString());
@@ -32,22 +43,21 @@ uint32 GetTypeHash(const FSettingsPrimary& Other)
const uint32 LineHeightHash = GetTypeHash(Other.LineHeight);
const uint32 StartOnNextColumnHash = GetTypeHash(Other.bStartOnNextColumn);
const uint32 SettingsToUpdateHash = GetTypeHash(Other.SettingsToUpdate.ToStringSimple());
- return HashCombine(HashCombine(HashCombine(HashCombine(HashCombine(HashCombine(HashCombine(HashCombine(HashCombine(HashCombine(HashCombine(HashCombine(
- TagHash, ObjectContextHash), SetterHash), GetterHash), CaptionHash), TooltipHash), PaddingLeftHash), PaddingTopHash), PaddingRightHash), PaddingBottomHash), LineHeightHash), StartOnNextColumnHash), SettingsToUpdateHash);
+ return HashCombine(HashCombine(HashCombine(HashCombine(HashCombine(HashCombine(HashCombine(HashCombine(HashCombine(HashCombine(HashCombine(HashCombine(TagHash, ObjectContextHash), SetterHash), GetterHash), CaptionHash), TooltipHash), PaddingLeftHash), PaddingTopHash), PaddingRightHash), PaddingBottomHash), LineHeightHash), StartOnNextColumnHash), SettingsToUpdateHash);
}
// Returns the pointer to one of the chosen in-game type
-const FSettingsDataBase* FSettingsPicker::GetChosenSettingsData() const
+FSettingsDataBase* FSettingsPicker::GetChosenSettingsData() const
{
- const FSettingsDataBase* FoundSetting = nullptr;
if (!SettingsType.IsNone())
{
static const UScriptStruct* const& SettingsPickerStruct = StaticStruct();
const FProperty* FoundProperty = SettingsPickerStruct ? SettingsPickerStruct->FindPropertyByName(SettingsType) : nullptr;
const FStructProperty* FoundStructProperty = CastField(FoundProperty);
- FoundSetting = FoundStructProperty ? FoundStructProperty->ContainerPtrToValuePtr(this, 0) : nullptr;
+ const FSettingsDataBase* FoundSetting = FoundStructProperty ? FoundStructProperty->ContainerPtrToValuePtr(this, 0) : nullptr;
+ return const_cast(FoundSetting);
}
- return FoundSetting;
+ return nullptr;
}
// Compares for equality
diff --git a/Source/SettingsWidgetConstructor/Private/FunctionPickerData/FunctionPicker.cpp b/Source/SettingsWidgetConstructor/Private/FunctionPickerData/FunctionPicker.cpp
index 579daac..ca5a456 100644
--- a/Source/SettingsWidgetConstructor/Private/FunctionPickerData/FunctionPicker.cpp
+++ b/Source/SettingsWidgetConstructor/Private/FunctionPickerData/FunctionPicker.cpp
@@ -8,7 +8,7 @@ const FSWCFunctionPicker FSWCFunctionPicker::Empty = FSWCFunctionPicker();
// Custom constructor to set all members values
FSWCFunctionPicker::FSWCFunctionPicker(UClass* InFunctionClass, FName InFunctionName)
: FunctionClass(InFunctionClass)
- , FunctionName(InFunctionName) {}
+ , FunctionName(InFunctionName) {}
// Returns the function pointer based on set data to this structure
UFunction* FSWCFunctionPicker::GetFunction() const
@@ -19,7 +19,7 @@ UFunction* FSWCFunctionPicker::GetFunction() const
}
if (FunctionClass
- && !FunctionName.IsNone())
+ && !FunctionName.IsNone())
{
UFunction* FoundFunction = FunctionClass->FindFunctionByName(FunctionName, EIncludeSuperFlag::ExcludeSuper);
CachedFunctionInternal = FoundFunction;
@@ -29,11 +29,10 @@ UFunction* FSWCFunctionPicker::GetFunction() const
return nullptr;
}
-// Compares for equality
-bool FSWCFunctionPicker::operator==(const FSWCFunctionPicker& Other) const
+// Returns string in text format: Class::Function
+FString FSWCFunctionPicker::ToDisplayString() const
{
- return Other.FunctionClass->IsChildOf(this->FunctionClass)
- && Other.FunctionName == this->FunctionName;
+ return IsValid() ? FString::Printf(TEXT("%s::%s"), *FunctionClass->GetName(), *FunctionName.ToString()) : FString();
}
// Creates a hash value
diff --git a/Source/SettingsWidgetConstructor/Private/FunctionPickerData/SWCFunctionPicker.h b/Source/SettingsWidgetConstructor/Private/FunctionPickerData/SWCFunctionPicker.h
index 40454e8..af57189 100644
--- a/Source/SettingsWidgetConstructor/Private/FunctionPickerData/SWCFunctionPicker.h
+++ b/Source/SettingsWidgetConstructor/Private/FunctionPickerData/SWCFunctionPicker.h
@@ -21,7 +21,7 @@
*
* Example:
* UPROPERTY(EditDefaultsOnly, meta = (FunctionSetterTemplate = "/Script/FunctionPicker.FunctionPickerTemplate::OnSetMembers__DelegateSignature"))
- * FFunctionPicker SetMembers = FFunctionPicker::Empty;
+ * FSWCFunctionPicker SetMembers = FSWCFunctionPicker::Empty;
*/
USTRUCT(BlueprintType)
struct SETTINGSWIDGETCONSTRUCTOR_API FSWCFunctionPicker
@@ -38,26 +38,35 @@ struct SETTINGSWIDGETCONSTRUCTOR_API FSWCFunctionPicker
FSWCFunctionPicker(UClass* InFunctionClass, FName InFunctionName);
/** The class where function can be found. */
- UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, meta = (DisplayName = "Class"))
+ UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, meta = (DisplayName = "Class", AllowAbstract, ShowOnlyInnerProperties))
TObjectPtr FunctionClass = nullptr;
/** The function name to choose for specified class.*/
- UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, meta = (DisplayName = "Function"))
+ UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, meta = (DisplayName = "Function", ShowOnlyInnerProperties))
FName FunctionName = NAME_None;
/** Returns true if is valid. */
- FORCEINLINE bool IsValid() const { return !(*this == Empty); }
+ FORCEINLINE bool IsValid() const { return FunctionClass && !FunctionName.IsNone(); }
/** Returns the function pointer based on set data to this structure. */
UFunction* GetFunction() const;
+ /** Returns string in text format: Class::Function. */
+ FString ToDisplayString() const;
+
/** Compares for equality.
* @param Other The other object being compared. */
- bool operator==(const FSWCFunctionPicker& Other) const;
+ FORCEINLINE bool operator==(const FSWCFunctionPicker& Other) const { return GetTypeHash(*this) == GetTypeHash(Other); }
/** Creates a hash value.
* @param Other the other object to create a hash value for. */
- friend uint32 GetTypeHash(const FSWCFunctionPicker& Other);
+ friend SETTINGSWIDGETCONSTRUCTOR_API uint32 GetTypeHash(const FSWCFunctionPicker& Other);
+
+ /** bool operator */
+ FORCEINLINE operator bool() const { return IsValid(); }
+
+ /** FName operator */
+ FORCEINLINE operator FName() const { return FunctionName; }
protected:
/** Contains cached function ptr for performance reasons. */
diff --git a/Source/SettingsWidgetConstructor/Private/FunctionPickerData/SWCFunctionPickerTemplate.h b/Source/SettingsWidgetConstructor/Private/FunctionPickerData/SWCFunctionPickerTemplate.h
index 7009592..80e7d0e 100644
--- a/Source/SettingsWidgetConstructor/Private/FunctionPickerData/SWCFunctionPickerTemplate.h
+++ b/Source/SettingsWidgetConstructor/Private/FunctionPickerData/SWCFunctionPickerTemplate.h
@@ -9,7 +9,7 @@
/**
* Delegates wrapper that are used as templates for FFunctionPicker properties.
* Has to have reflection to allow find its members by FFunctionPickerCustomization:
- * UFunctionPickerTemplate::StaticClass()->FindFunctionByName("OnStaticContext__DelegateSignature");
+ * UFunctionPickerTemplate::StaticClass()->FindFunctionByName("OnGetterObject__DelegateSignature");
* DECLARE_DYNAMIC_DELEGATE can't be declared under USTRUCT
*/
UCLASS(Abstract, Const, Transient)
@@ -18,7 +18,7 @@ class USWCFunctionPickerTemplate : public UObject
GENERATED_BODY()
public:
- DECLARE_DYNAMIC_DELEGATE_RetVal(UObject*, FOnStaticContext);
+ DECLARE_DYNAMIC_DELEGATE_RetVal_OneParam(UObject*, FOnGetterObject, const UObject*, WorldContext);
DECLARE_DYNAMIC_DELEGATE(FOnButtonPressed);
@@ -45,4 +45,4 @@ class USWCFunctionPickerTemplate : public UObject
DECLARE_DYNAMIC_DELEGATE_OneParam(FOnGetMembers, TArray&, OutParam);
DECLARE_DYNAMIC_DELEGATE_RetVal(FName, FOnGetterName);
-};
\ No newline at end of file
+};
diff --git a/Source/SettingsWidgetConstructor/Private/MyUtilsLibraries/SettingsUtilsLibrary.cpp b/Source/SettingsWidgetConstructor/Private/MyUtilsLibraries/SettingsUtilsLibrary.cpp
new file mode 100644
index 0000000..aa92a7a
--- /dev/null
+++ b/Source/SettingsWidgetConstructor/Private/MyUtilsLibraries/SettingsUtilsLibrary.cpp
@@ -0,0 +1,191 @@
+// Copyright (c) Yevhenii Selivanov
+
+#include "MyUtilsLibraries/SettingsUtilsLibrary.h"
+//---
+#include "MyUtilsLibraries/SWCWidgetUtilsLibrary.h"
+#include "GameFramework/GameUserSettings.h"
+#include "UI/SettingsWidget.h"
+#include "Data/SettingsDataAsset.h"
+#include "Data/SettingsDataTable.h"
+#include "Data/SettingsRow.h"
+//---
+#include "Engine/Engine.h"
+#include "Engine/World.h"
+#include "DataRegistrySource_DataTable.h"
+#include "DataRegistrySubsystem.h"
+//---
+#include UE_INLINE_GENERATED_CPP_BY_NAME(SettingsUtilsLibrary)
+
+// Returns the Settings widget from viewport
+USettingsWidget* USettingsUtilsLibrary::GetSettingsWidget(const UObject* WorldContextObject)
+{
+ UWorld* World = GEngine ? GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull) : nullptr;
+ return FSWCWidgetUtilsLibrary::FindWidgetOfClass(World);
+}
+
+// Returns the Game User Settings object
+UGameUserSettings* USettingsUtilsLibrary::GetGameUserSettings(const UObject* OptionalWorldContext/* = nullptr*/)
+{
+ return GEngine ? GEngine->GetGameUserSettings() : nullptr;
+}
+
+// Returns all Settings Rows from project's Settings Data Table and all other additional Data Tables from 'SettingsDataTable' Data Registry
+void USettingsUtilsLibrary::GetAllSettingRows(TMap& OutSettingRows)
+{
+ if (!OutSettingRows.IsEmpty())
+ {
+ OutSettingRows.Empty();
+ }
+
+ TSet OutDataTables;
+ GetAllSettingDataTables(OutDataTables);
+
+ if (!ensureMsgf(!OutDataTables.IsEmpty(), TEXT("ASSERT: [%i] %s:\n'Settings Data Table' is not set in the 'Project Settings', can't retrieve any settings!"), __LINE__, *FString(__FUNCTION__)))
+ {
+ return;
+ }
+
+ /**
+ * Sort Setting Rows based on the FSettingsPrimary::ShowNextToSettingOverride property.
+ * All the next settings after ShowNextToSettingOverride in the same table will be also shown next to it.
+ * Sort is needed since setting can be shown based on another setting in different Settings Data Table, so we want to fix the order.
+ */
+
+ TArray OrderedSettings;
+ TMap> OverrideBlocks;
+
+ // Collect settings and override blocks
+ for (const USettingsDataTable* TableIt : OutDataTables)
+ {
+ checkf(TableIt, TEXT("ERROR: [%i] %s:\n'TableIt' is null!"), __LINE__, *FString(__FUNCTION__));
+
+ TMap TableRows;
+ TableIt->GetSettingRows(TableRows);
+
+ TArray CurrentOverrideBlock;
+ FSettingTag CurrentOverrideTag;
+
+ for (const TTuple& Pair : TableRows)
+ {
+ const FSettingsRow& Row = Pair.Value;
+ const FSettingTag& OverrideTag = Row.SettingsPicker.PrimaryData.ShowNextToSettingOverride;
+
+ if (OverrideTag.IsValid())
+ {
+ // Store the previous block if any, then start a new block
+ if (CurrentOverrideBlock.Num() > 0)
+ {
+ OverrideBlocks.Emplace(CurrentOverrideTag, MoveTemp(CurrentOverrideBlock));
+ }
+ CurrentOverrideBlock.Empty();
+ CurrentOverrideTag = OverrideTag;
+ }
+
+ if (CurrentOverrideTag.IsValid())
+ {
+ CurrentOverrideBlock.Emplace(Row);
+ }
+ else
+ {
+ OrderedSettings.Emplace(Row);
+ }
+ }
+
+ // Add the last block if any
+ if (CurrentOverrideBlock.Num() > 0)
+ {
+ OverrideBlocks.Emplace(CurrentOverrideTag, MoveTemp(CurrentOverrideBlock));
+ }
+ }
+
+ // Build the final map, handling the override blocks
+ for (const FSettingsRow& Row : OrderedSettings)
+ {
+ const FName Tag = Row.SettingsPicker.PrimaryData.Tag.GetTagName();
+ OutSettingRows.Add(Tag, Row);
+
+ // Check if there's an override block for this tag
+ const FSettingTag SettingTag = Row.SettingsPicker.PrimaryData.Tag;
+ TArray* OverrideBlock = OverrideBlocks.Find(SettingTag);
+ if (OverrideBlock)
+ {
+ // Add the override block next to the current setting
+ for (const FSettingsRow& OverrideRow : *OverrideBlock)
+ {
+ const FName OverrideTag = OverrideRow.SettingsPicker.PrimaryData.Tag.GetTagName();
+ OutSettingRows.Add(OverrideTag, OverrideRow);
+ }
+ }
+ }
+}
+
+/*********************************************************************************************
+ * Multiple Data Tables support
+ ********************************************************************************************* */
+
+// Registers the Settings Data Table with the Data Registry
+void USettingsUtilsLibrary::RegisterDataTable(const TSoftObjectPtr SettingsDataTable)
+{
+ UDataRegistrySubsystem* DataRegistrySubsystem = UDataRegistrySubsystem::Get();
+ checkf(DataRegistrySubsystem, TEXT("ERROR: [%i] %s:\n'DataRegistrySubsystem' is null!"), __LINE__, *FString(__FUNCTION__));
+
+ const TSoftObjectPtr& SettingsDataRegistry = USettingsDataAsset::Get().GetSettingsDataRegistrySoft();
+ if (ensureMsgf(!SettingsDataRegistry.IsNull(), TEXT("ASSERT: 'SettingsDataRegistry' is null, it has to be set automatically, something went wrong!")))
+ {
+ // Initialize the Settings Data Registry
+ DataRegistrySubsystem->LoadRegistryPath(SettingsDataRegistry.ToSoftObjectPath());
+ }
+
+ // If set, add the Settings Data Table to the Settings Data Registry
+ const FSoftObjectPath DataTablePath = SettingsDataTable.ToSoftObjectPath();
+ if (!DataTablePath.IsNull())
+ {
+ TMap> AssetMap;
+ static const FDataRegistryType RegistryToAddTo{TEXT("SettingsDataTable")};
+ TArray& AssetList = AssetMap.Add(RegistryToAddTo);
+ AssetList.Emplace(DataTablePath);
+ DataRegistrySubsystem->PreregisterSpecificAssets(AssetMap);
+ }
+}
+
+// Returns all Settings Data Tables added to 'SettingsDataTable' Data Registry
+void USettingsUtilsLibrary::GetAllSettingDataTables(TSet& OutDataTables)
+{
+ if (!OutDataTables.IsEmpty())
+ {
+ OutDataTables.Empty();
+ }
+
+ const UDataRegistry* SettingsDataRegistry = USettingsDataAsset::Get().GetSettingsDataRegistry();
+ if (!ensureMsgf(SettingsDataRegistry, TEXT("ASSERT: 'SettingsDataRegistry' is not loaded, can't retrieve any settings!")))
+ {
+ return;
+ }
+
+ const UScriptStruct* SettingStruct = FSettingsRow::StaticStruct();
+ TMap OutItemMap;
+ SettingsDataRegistry->GetAllCachedItems(OutItemMap, SettingStruct);
+
+ // Obtain all Settings Data Tables from the registry
+ for (const TTuple& ItemIt : OutItemMap)
+ {
+ FDataRegistryLookup Lookup;
+ SettingsDataRegistry->ResolveDataRegistryId(/*out*/Lookup, ItemIt.Key);
+
+ FName ResolvedName;
+ constexpr int32 LookupIndex = 0;
+ UDataRegistrySource* LookupSource = SettingsDataRegistry->LookupSource(ResolvedName, Lookup, LookupIndex);
+
+ const UDataRegistrySource_DataTable* DataTableSource = Cast(LookupSource);
+ if (!DataTableSource || DataTableSource->SourceTable.IsNull())
+ {
+ continue;
+ }
+
+ const USettingsDataTable* DataTable = Cast(DataTableSource->SourceTable.LoadSynchronous());
+ if (ensureMsgf(DataTable, TEXT("ASSERT: [%i] %s:\nNext Settings Data Table is found, but can't be loaded: %s"), __LINE__, *FString(__FUNCTION__), *DataTableSource->SourceTable.GetAssetName()))
+ {
+ OutDataTables.Add(DataTable);
+ }
+ }
+}
diff --git a/Source/SettingsWidgetConstructor/Private/UI/SettingSubWidget.cpp b/Source/SettingsWidgetConstructor/Private/UI/SettingSubWidget.cpp
index 1082f15..536f4bd 100644
--- a/Source/SettingsWidgetConstructor/Private/UI/SettingSubWidget.cpp
+++ b/Source/SettingsWidgetConstructor/Private/UI/SettingSubWidget.cpp
@@ -14,6 +14,7 @@
#include "Components/Slider.h"
#include "Components/TextBlock.h"
#include "Widgets/Input/SButton.h"
+#include "Widgets/Input/SComboBox.h"
#include "Widgets/Input/SEditableTextBox.h"
#include "Widgets/Input/SSlider.h"
//---
diff --git a/Source/SettingsWidgetConstructor/Private/UI/SettingsWidget.cpp b/Source/SettingsWidgetConstructor/Private/UI/SettingsWidget.cpp
index 97b179d..e88dae0 100644
--- a/Source/SettingsWidgetConstructor/Private/UI/SettingsWidget.cpp
+++ b/Source/SettingsWidgetConstructor/Private/UI/SettingsWidget.cpp
@@ -2,16 +2,20 @@
#include "UI/SettingsWidget.h"
//---
+#include "Data/SettingsDataAsset.h"
+#include "MyUtilsLibraries/SettingsUtilsLibrary.h"
+#include "UI/SettingSubWidget.h"
+//---
#include "Blueprint/WidgetLayoutLibrary.h"
#include "Components/SizeBox.h"
#include "GameFramework/GameUserSettings.h"
//---
-#include "Data/SettingsDataAsset.h"
-#include "Data/SettingsDataTable.h"
-#include "UI/SettingSubWidget.h"
-//---
#include UE_INLINE_GENERATED_CPP_BY_NAME(SettingsWidget)
+/* ---------------------------------------------------
+ * Public functions
+ * --------------------------------------------------- */
+
// Try to find the setting row
const FSettingsPicker& USettingsWidget::FindSettingRow(FName PotentialTagName) const
{
@@ -56,7 +60,7 @@ void USettingsWidget::SaveSettings()
for (const TTuple& RowIt : SettingsTableRowsInternal)
{
- if (UObject* ContextObject = RowIt.Value.PrimaryData.StaticContextObject.Get())
+ if (UObject* ContextObject = RowIt.Value.PrimaryData.GetSettingOwner(this))
{
ContextObject->SaveConfig();
}
@@ -66,7 +70,7 @@ void USettingsWidget::SaveSettings()
// Apply all current settings on device
void USettingsWidget::ApplySettings()
{
- UGameUserSettings* GameUserSettings = GEngine->GetGameUserSettings();
+ UGameUserSettings* GameUserSettings = USettingsUtilsLibrary::GetGameUserSettings();
if (!GameUserSettings)
{
return;
@@ -100,38 +104,24 @@ void USettingsWidget::UpdateSettings(const FGameplayTagContainer& SettingsToUpda
continue;
}
- const FSettingsDataBase* ChosenData = Setting.GetChosenSettingsData();
+ FSettingsDataBase* ChosenData = Setting.GetChosenSettingsData();
if (!ChosenData)
{
continue;
}
- if (ChosenData == &Setting.Checkbox)
- {
- const bool NewValue = GetCheckboxValue(SettingTag);
- SetSettingCheckbox(SettingTag, NewValue);
- }
- else if (ChosenData == &Setting.Combobox)
- {
- const int32 NewValue = GetComboboxIndex(SettingTag);
- SetSettingComboboxIndex(SettingTag, NewValue);
- }
- else if (ChosenData == &Setting.Slider)
- {
- const double NewValue = GetSliderValue(SettingTag);
- SetSettingSlider(SettingTag, NewValue);
- }
- else if (ChosenData == &Setting.TextLine)
- {
- FText NewValue = TEXT_NONE;
- GetTextLineValue(SettingTag, /*Out*/NewValue);
- SetSettingTextLine(SettingTag, NewValue);
- }
- else if (ChosenData == &Setting.UserInput)
+ UObject* Owner = Setting.PrimaryData.GetSettingOwner(this);
+ if (!Owner)
{
- const FName NewValue = GetUserInputValue(SettingTag);
- SetSettingUserInput(SettingTag, NewValue);
+ continue;
}
+
+ // Obtain the latest value from configs and set it
+ Owner->LoadConfig();
+
+ FString Result;
+ ChosenData->GetSettingValue(*this, SettingTag, /*Out*/Result);
+ ChosenData->SetSettingValue(*this, SettingTag, Result);
}
}
@@ -151,6 +141,10 @@ const FSettingTag& USettingsWidget::GetTagByFunction(const FSettingFunctionPicke
return FSettingTag::EmptySettingTag;
}
+/* ---------------------------------------------------
+ * Setters by setting types
+ * --------------------------------------------------- */
+
// Set value to the option by tag
void USettingsWidget::SetSettingValue(FName TagName, const FString& Value)
{
@@ -160,65 +154,45 @@ void USettingsWidget::SetSettingValue(FName TagName, const FString& Value)
return;
}
- const FSettingsDataBase* ChosenData = FoundRow.GetChosenSettingsData();
+ FSettingsDataBase* ChosenData = FoundRow.GetChosenSettingsData();
if (!ChosenData)
{
return;
}
const FSettingTag& Tag = FoundRow.PrimaryData.Tag;
- if (!Tag.IsValid())
- {
- return;
- }
-
- if (ChosenData == &FoundRow.Button)
- {
- SetSettingButtonPressed(Tag);
- }
- else if (ChosenData == &FoundRow.Checkbox)
- {
- const bool NewValue = Value.ToBool();
- SetSettingCheckbox(Tag, NewValue);
- }
- else if (ChosenData == &FoundRow.Combobox)
- {
- if (Value.IsNumeric())
- {
- const int32 NewValue = FCString::Atoi(*Value);
- SetSettingComboboxIndex(Tag, NewValue);
- }
- else
- {
- static const FString Delimiter = TEXT(",");
- TArray SeparatedStrings;
- Value.ParseIntoArray(SeparatedStrings, *Delimiter);
-
- TArray NewMembers;
- NewMembers.Reserve(SeparatedStrings.Num());
- for (FString& StringIt : SeparatedStrings)
- {
- NewMembers.Emplace(FText::FromString(MoveTemp(StringIt)));
- }
- SetSettingComboboxMembers(Tag, NewMembers);
- }
- }
- else if (ChosenData == &FoundRow.Slider)
- {
- const double NewValue = FCString::Atod(*Value);
- SetSettingSlider(Tag, NewValue);
- }
- else if (ChosenData == &FoundRow.TextLine)
- {
- const FText NewValue = FText::FromString(Value);
- SetSettingTextLine(Tag, NewValue);
- }
- else if (ChosenData == &FoundRow.UserInput)
- {
- const FName NewValue = *Value;
- SetSettingUserInput(Tag, NewValue);
- }
-}
+ if (Tag.IsValid())
+ {
+ ChosenData->SetSettingValue(*this, Tag, Value);
+ }
+}
+
+/** Executes the common pattern of setting a value, executing if bound, and updating the settings.
+ * @param Tag The tag used to find the setting row.
+ * @param DataMember The member that holds the desired value.
+ * @param MemberValue The specific member to set the value to.
+ * @param Value The new value to set.
+ * @param SetterExpression The expression to update the setter delegate. */
+#define SET_SETTING_VALUE(Tag, DataMember, MemberValue, Value, SetterExpression) \
+ do { \
+ if (!Tag.IsValid()) \
+ { \
+ return; \
+ } \
+ FSettingsPicker* FoundRowPtr = SettingsTableRowsInternal.Find(Tag.GetTagName());\
+ if (!FoundRowPtr) \
+ { \
+ return; \
+ } \
+ auto& Data = FoundRowPtr->DataMember; \
+ if (Data.MemberValue == Value) \
+ { \
+ return; \
+ } \
+ Data.MemberValue = Value; \
+ Data.SetterExpression.ExecuteIfBound(Value); \
+ UpdateSettings(FoundRowPtr->PrimaryData.SettingsToUpdate); \
+ } while (0)
// Press button
void USettingsWidget::SetSettingButtonPressed(const FSettingTag& ButtonTag)
@@ -244,26 +218,7 @@ void USettingsWidget::SetSettingButtonPressed(const FSettingTag& ButtonTag)
// Toggle checkbox
void USettingsWidget::SetSettingCheckbox(const FSettingTag& CheckboxTag, bool InValue)
{
- if (!CheckboxTag.IsValid())
- {
- return;
- }
-
- FSettingsPicker* SettingsRowPtr = SettingsTableRowsInternal.Find(CheckboxTag.GetTagName());
- if (!SettingsRowPtr)
- {
- return;
- }
-
- bool& bIsSetRef = SettingsRowPtr->Checkbox.bIsSet;
- if (bIsSetRef == InValue)
- {
- return;
- }
-
- bIsSetRef = InValue;
- SettingsRowPtr->Checkbox.OnSetterBool.ExecuteIfBound(InValue);
- UpdateSettings(SettingsRowPtr->PrimaryData.SettingsToUpdate);
+ SET_SETTING_VALUE(CheckboxTag, Checkbox, bIsSet, InValue, OnSetterBool);
// BP implementation
SetCheckbox(CheckboxTag, InValue);
@@ -273,32 +228,12 @@ void USettingsWidget::SetSettingCheckbox(const FSettingTag& CheckboxTag, bool In
// Set chosen member index for a combobox
void USettingsWidget::SetSettingComboboxIndex(const FSettingTag& ComboboxTag, int32 InValue)
{
- if (!ComboboxTag.IsValid())
- {
- return;
- }
-
if (InValue == INDEX_NONE)
{
return;
}
- FSettingsPicker* SettingsRowPtr = SettingsTableRowsInternal.Find(ComboboxTag.GetTagName());
- if (!SettingsRowPtr)
- {
- return;
- }
-
- FSettingsPicker& SettingsRowRef = *SettingsRowPtr;
- int32& ChosenMemberIndexRef = SettingsRowRef.Combobox.ChosenMemberIndex;
- if (ChosenMemberIndexRef == InValue)
- {
- return;
- }
-
- ChosenMemberIndexRef = InValue;
- SettingsRowRef.Combobox.OnSetterInt.ExecuteIfBound(InValue);
- UpdateSettings(SettingsRowRef.PrimaryData.SettingsToUpdate);
+ SET_SETTING_VALUE(ComboboxTag, Combobox, ChosenMemberIndex, InValue, OnSetterInt);
// BP implementation
SetComboboxIndex(ComboboxTag, InValue);
@@ -328,29 +263,10 @@ void USettingsWidget::SetSettingComboboxMembers(const FSettingTag& ComboboxTag,
// Set current value for a slider
void USettingsWidget::SetSettingSlider(const FSettingTag& SliderTag, double InValue)
{
- if (!SliderTag.IsValid())
- {
- return;
- }
-
- FSettingsPicker* SettingsRowPtr = SettingsTableRowsInternal.Find(SliderTag.GetTagName());
- if (!SettingsRowPtr)
- {
- return;
- }
-
static constexpr double MinValue = 0.0;
static constexpr float MaxValue = 1.0;
const double NewValue = FMath::Clamp(InValue, MinValue, MaxValue);
- double& ChosenValueRef = SettingsRowPtr->Slider.ChosenValue;
- if (ChosenValueRef == NewValue)
- {
- return;
- }
-
- ChosenValueRef = NewValue;
- SettingsRowPtr->Slider.OnSetterFloat.ExecuteIfBound(InValue);
- UpdateSettings(SettingsRowPtr->PrimaryData.SettingsToUpdate);
+ SET_SETTING_VALUE(SliderTag, Slider, ChosenValue, NewValue, OnSetterFloat);
// BP implementation
SetSlider(SliderTag, InValue);
@@ -456,136 +372,86 @@ void USettingsWidget::SetSettingCustomWidget(const FSettingTag& CustomWidgetTag,
UpdateSettings(SettingsRowPtr->PrimaryData.SettingsToUpdate);
}
+/* ---------------------------------------------------
+ * Getters by setting types
+ * --------------------------------------------------- */
+
+/** Retrieve a specific setting row using a given tag.
+ * @param Tag The tag used to find the setting row.
+ * @param DataMember The member that holds the desired value. */
+#define GET_SETTING_ROW(Tag, DataMember) \
+ const FSettingsPicker& FoundRow = GetSettingRow(Tag); \
+ if (!FoundRow.IsValid()) { return; } \
+ const auto& Data = FoundRow.DataMember;
+
+/** Executes the common pattern of getting a value from a data structure.
+ * @param Tag The tag used to find the setting row.
+ * @param DataMember The member that holds the desired value.
+ * @param ValueType The type of value to retrieve.
+ * @param ValueExpression The expression to retrieve the value.
+ * @param GetterExpression The expression to retrieve the getter delegate.
+ * @param DefaultValue The default value to return if no value is found. */
+#define GET_SETTING_VALUE(Tag, DataMember, ValueType, ValueExpression, GetterExpression, DefaultValue) \
+ { \
+ const FSettingsPicker& FoundRow = GetSettingRow(Tag); \
+ ValueType Value = DefaultValue; \
+ if (FoundRow.IsValid()) \
+ { \
+ const auto& Data = FoundRow.DataMember; \
+ Value = ValueExpression; \
+ const auto& Getter = GetterExpression; \
+ if (Getter.IsBound()) \
+ { \
+ Value = Getter.Execute(); \
+ } \
+ } \
+ return Value; \
+ }
+
// Returns is a checkbox toggled
bool USettingsWidget::GetCheckboxValue(const FSettingTag& CheckboxTag) const
{
- if (!CheckboxTag.IsValid())
- {
- return false;
- }
-
- const FSettingsPicker& FoundRow = GetSettingRow(CheckboxTag);
- bool Value = false;
- if (FoundRow.IsValid())
- {
- const FSettingsCheckbox& Data = FoundRow.Checkbox;
- Value = Data.bIsSet;
-
- const USettingFunctionTemplate::FOnGetterBool& Getter = Data.OnGetterBool;
- if (Getter.IsBound())
- {
- Value = Getter.Execute();
- }
- }
- return Value;
+ GET_SETTING_VALUE(CheckboxTag, Checkbox, bool, Data.bIsSet, Data.OnGetterBool, false);
}
// Returns chosen member index of a combobox
int32 USettingsWidget::GetComboboxIndex(const FSettingTag& ComboboxTag) const
{
- const FSettingsPicker& FoundRow = GetSettingRow(ComboboxTag);
- int32 Value = false;
- if (FoundRow.IsValid())
- {
- const FSettingsCombobox& Data = FoundRow.Combobox;
- Value = Data.ChosenMemberIndex;
-
- const USettingFunctionTemplate::FOnGetterInt& Getter = Data.OnGetterInt;
- if (Getter.IsBound())
- {
- Value = Getter.Execute();
- }
- }
- return Value;
+ GET_SETTING_VALUE(ComboboxTag, Combobox, int32, Data.ChosenMemberIndex, Data.OnGetterInt, 0);
}
// Get all members of a combobox
void USettingsWidget::GetComboboxMembers(const FSettingTag& ComboboxTag, TArray& OutMembers) const
{
- const FSettingsPicker& FoundRow = GetSettingRow(ComboboxTag);
- if (FoundRow.IsValid())
- {
- const FSettingsCombobox& Data = FoundRow.Combobox;
- OutMembers = Data.Members;
-
- const USettingFunctionTemplate::FOnGetMembers& Getter = Data.OnGetMembers;
- if (Getter.IsBound())
- {
- Getter.Execute(OutMembers);
- }
- }
+ GET_SETTING_ROW(ComboboxTag, Combobox)
+ OutMembers = Data.Members;
+ Data.OnGetMembers.ExecuteIfBound(OutMembers);
}
// Get current value of a slider [0...1]
double USettingsWidget::GetSliderValue(const FSettingTag& SliderTag) const
{
- const FSettingsPicker& FoundRow = GetSettingRow(SliderTag);
- double Value = 0.0;
- if (FoundRow.IsValid())
- {
- const FSettingsSlider& Data = FoundRow.Slider;
- Value = Data.ChosenValue;
-
- const USettingFunctionTemplate::FOnGetterFloat& Getter = Data.OnGetterFloat;
- if (Getter.IsBound())
- {
- Value = Getter.Execute();
- }
- }
- return Value;
+ GET_SETTING_VALUE(SliderTag, Slider, double, Data.ChosenValue, Data.OnGetterFloat, 0.f);
}
// Get current text of a simple text widget
void USettingsWidget::GetTextLineValue(const FSettingTag& TextLineTag, FText& OutText) const
{
- const FSettingsPicker& FoundRow = GetSettingRow(TextLineTag);
- if (FoundRow.IsValid())
- {
- OutText = FoundRow.PrimaryData.Caption;
-
- const USettingFunctionTemplate::FOnGetterText& Getter = FoundRow.TextLine.OnGetterText;
- if (Getter.IsBound())
- {
- Getter.Execute(OutText);
- }
- }
+ GET_SETTING_ROW(TextLineTag, PrimaryData)
+ OutText = Data.Caption;
+ FoundRow.TextLine.OnGetterText.ExecuteIfBound(OutText);
}
// Get current input name of the text input
FName USettingsWidget::GetUserInputValue(const FSettingTag& UserInputTag) const
{
- const FSettingsPicker& FoundRow = GetSettingRow(UserInputTag);
- FName Value = NAME_None;
- if (FoundRow.IsValid())
- {
- const FSettingsUserInput& Data = FoundRow.UserInput;
- Value = Data.UserInput;
-
- const USettingFunctionTemplate::FOnGetterName& Getter = Data.OnGetterName;
- if (Getter.IsBound())
- {
- Value = Getter.Execute();
- }
- }
- return Value;
+ GET_SETTING_VALUE(UserInputTag, UserInput, FName, Data.UserInput, Data.OnGetterName, NAME_None);
}
// Get custom widget of the setting by specified tag
USettingCustomWidget* USettingsWidget::GetCustomWidget(const FSettingTag& CustomWidgetTag) const
{
- const FSettingsPicker& FoundRow = GetSettingRow(CustomWidgetTag);
- USettingCustomWidget* CustomWidget = nullptr;
- if (FoundRow.IsValid())
- {
- CustomWidget = Cast(FoundRow.PrimaryData.SettingSubWidget.Get());
-
- const USettingFunctionTemplate::FOnGetterWidget& Getter = FoundRow.CustomWidget.OnGetterWidget;
- if (Getter.IsBound())
- {
- CustomWidget = Getter.Execute();
- }
- }
- return CustomWidget;
+ GET_SETTING_VALUE(CustomWidgetTag, CustomWidget, USettingCustomWidget*, Cast(FoundRow.PrimaryData.SettingSubWidget.Get()), Data.OnGetterWidget, nullptr);
}
// Get setting widget object by specified tag
@@ -595,6 +461,10 @@ USettingSubWidget* USettingsWidget::GetSettingSubWidget(const FSettingTag& Setti
return PrimaryData.IsValid() ? PrimaryData.SettingSubWidget.Get() : nullptr;
}
+/* ---------------------------------------------------
+ * Style
+ * --------------------------------------------------- */
+
// Returns the size of the Settings widget on the screen
FVector2D USettingsWidget::GetSettingsSize() const
{
@@ -649,7 +519,6 @@ FVector2D USettingsWidget::GetSubWidgetsSize(int32 SectionsBitmask) const
return SubWidgetsHeight;
}
-
// Returns the height of a setting scrollbox on the screen
float USettingsWidget::GetScrollBoxHeight() const
{
@@ -679,7 +548,7 @@ float USettingsWidget::GetScrollBoxHeight() const
}
// Is blueprint-event called that returns the style brush by specified button state
-FSlateBrush USettingsWidget::GetButtonBrush(ESettingsButtonState State) const
+FSlateBrush USettingsWidget::GetButtonBrush(ESettingsButtonState State)
{
const USettingsDataAsset& SettingsDataAsset = USettingsDataAsset::Get();
const FMiscThemeData& MiscThemeData = SettingsDataAsset.GetMiscThemeData();
@@ -711,6 +580,10 @@ FSlateBrush USettingsWidget::GetButtonBrush(ESettingsButtonState State) const
return SlateBrush;
}
+/* ---------------------------------------------------
+ * Protected functions
+ * --------------------------------------------------- */
+
// Called after the underlying slate widget is constructed
void USettingsWidget::NativeConstruct()
{
@@ -720,6 +593,8 @@ void USettingsWidget::NativeConstruct()
{
TryConstructSettings();
}
+
+ TryFocusOnUI();
}
// Is called right after the game was started and windows size is set to construct settings
@@ -747,24 +622,24 @@ void USettingsWidget::ConstructSettings()
// BP implementation to cache some data before creating subwidgets
OnConstructSettings();
+ FGameplayTagContainer AddedSettings;
for (TTuple& RowIt : SettingsTableRowsInternal)
{
- AddSetting(RowIt.Value);
+ FSettingsPicker& SettingRef = RowIt.Value;
+ BindSetting(SettingRef);
+ AddSetting(SettingRef);
+ AddedSettings.AddTag(SettingRef.PrimaryData.Tag);
}
+ UpdateSettings(AddedSettings);
+
UpdateScrollBoxesHeight();
}
void USettingsWidget::UpdateSettingsTableRows()
{
- const USettingsDataTable* SettingsDataTable = USettingsDataAsset::Get().GetSettingsDataTable();
- if (!ensureMsgf(SettingsDataTable, TEXT("ASSERT: 'SettingsDataTable' is not valid")))
- {
- return;
- }
-
TMap SettingRows;
- SettingsDataTable->GetSettingRows(/*Out*/SettingRows);
+ USettingsUtilsLibrary::GetAllSettingRows(/*Out*/SettingRows);
if (!ensureMsgf(!SettingRows.IsEmpty(), TEXT("ASSERT: 'SettingRows' are empty")))
{
return;
@@ -797,26 +672,31 @@ void USettingsWidget::OnToggleSettings(bool bIsVisible)
}
// Bind and set static object delegate
-void USettingsWidget::TryBindStaticContext(FSettingsPrimary& Primary)
+bool USettingsWidget::TryBindOwner(FSettingsPrimary& Primary)
{
- UObject* FoundContextObj = nullptr;
- if (UFunction* FunctionPtr = Primary.StaticContext.GetFunction())
+ const UObject* FoundContextObj = nullptr;
+ const FSettingFunctionPicker& Owner = Primary.Owner;
+ if (Owner.IsValid())
{
- FunctionPtr->ProcessEvent(FunctionPtr, /*Out*/&FoundContextObj);
+ Primary.OwnerFunc.BindUFunction(Owner.FunctionClass->GetDefaultObject(), Owner.FunctionName);
+ FoundContextObj = Primary.GetSettingOwner(this);
}
if (!FoundContextObj)
{
- return;
- }
+ if (Owner.IsValid())
+ {
+ // Static context function is set, but returning object is null,
+ // most likely such object is not initialized yet,
+ // defer binding to try to rebind it later
+ DeferredBindingsInternal.AddTag(Primary.Tag);
+ }
- Primary.StaticContextObject = FoundContextObj;
+ return false;
+ }
const UClass* ContextClass = FoundContextObj->GetClass();
- if (!ensureMsgf(ContextClass, TEXT("ASSERT: 'ContextClass' is not valid")))
- {
- return;
- }
+ checkf(ContextClass, TEXT("ERROR: [%i] %s:\n'ContextClass' is null!"), __LINE__, *FString(__FUNCTION__));
// Cache all functions that are contained in returned object
for (TFieldIterator It(ContextClass, EFieldIteratorFlags::IncludeSuper); It; ++It)
@@ -830,9 +710,11 @@ void USettingsWidget::TryBindStaticContext(FSettingsPrimary& Primary)
const FName FunctionNameIt = FunctionIt->GetFName();
if (!FunctionNameIt.IsNone())
{
- Primary.StaticContextFunctionList.Emplace(FunctionNameIt);
+ Primary.OwnerFunctionList.Emplace(FunctionNameIt);
}
}
+
+ return true;
}
// Creates new widget based on specified setting class and sets it to specified primary data
@@ -921,10 +803,14 @@ void USettingsWidget::OpenSettings()
TryConstructSettings();
+ TryRebindDeferredContexts();
+
SetVisibility(ESlateVisibility::Visible);
OnToggleSettings(true);
+ TryFocusOnUI();
+
OnOpenSettings();
}
@@ -960,226 +846,178 @@ void USettingsWidget::ToggleSettings()
}
}
-// Add setting on UI.
-void USettingsWidget::AddSetting(FSettingsPicker& Setting)
+// Is called on opening to focus the widget on UI if allowed
+void USettingsWidget::TryFocusOnUI()
{
- const FSettingsDataBase* ChosenData = Setting.GetChosenSettingsData();
- if (!ChosenData)
+ if (!USettingsDataAsset::Get().IsAutoFocusOnOpen())
{
return;
}
- FSettingsPrimary& PrimaryData = Setting.PrimaryData;
- TryBindStaticContext(PrimaryData);
-
- if (Setting.PrimaryData.bStartOnNextColumn)
- {
- StartNextColumn();
- }
-
- if (ChosenData == &Setting.Button)
- {
- AddSettingButton(PrimaryData, Setting.Button);
- }
- else if (ChosenData == &Setting.Checkbox)
- {
- AddSettingCheckbox(PrimaryData, Setting.Checkbox);
- }
- else if (ChosenData == &Setting.Combobox)
- {
- AddSettingCombobox(PrimaryData, Setting.Combobox);
- }
- else if (ChosenData == &Setting.Slider)
- {
- AddSettingSlider(PrimaryData, Setting.Slider);
- }
- else if (ChosenData == &Setting.TextLine)
+ APlayerController* PlayerController = GetOwningPlayer();
+ if (!ensureMsgf(PlayerController, TEXT("ASSERT: [%i] %s:\n'PlayerController' is not valid!"), __LINE__, *FString(__FUNCTION__)))
{
- AddSettingTextLine(PrimaryData, Setting.TextLine);
- }
- else if (ChosenData == &Setting.UserInput)
- {
- AddSettingUserInput(PrimaryData, Setting.UserInput);
- }
- else if (ChosenData == &Setting.CustomWidget)
- {
- AddSettingCustomWidget(PrimaryData, Setting.CustomWidget);
+ return;
}
- UpdateSettings(FGameplayTagContainer(PrimaryData.Tag));
+ static const FInputModeGameAndUI GameAndUI{};
+ PlayerController->SetInputMode(GameAndUI);
+ PlayerController->SetShowMouseCursor(true);
+ PlayerController->bEnableClickEvents = true;
+ PlayerController->bEnableMouseOverEvents = true;
}
-// Add button on UI
-void USettingsWidget::AddSettingButton(FSettingsPrimary& Primary, FSettingsButton& Data)
+/* ---------------------------------------------------
+ * Bind by setting types
+ * --------------------------------------------------- */
+
+// Bind setting to specified Get/Set delegates, so both methods will be called
+bool USettingsWidget::BindSetting(FSettingsPicker& Setting)
{
- const TSubclassOf ButtonClass = USettingsDataAsset::Get().GetButtonClass();
- CreateSettingSubWidget(Primary, ButtonClass);
+ FSettingsDataBase* ChosenData = Setting.GetChosenSettingsData();
+ if (!ChosenData)
+ {
+ return false;
+ }
- if (UObject* StaticContextObject = Primary.StaticContextObject.Get())
+ if (TryBindOwner(Setting.PrimaryData))
{
- const FName SetterFunctionName = Primary.Setter.FunctionName;
- if (Primary.StaticContextFunctionList.Contains(SetterFunctionName))
- {
- Data.OnButtonPressed.BindUFunction(StaticContextObject, SetterFunctionName);
- }
+ ChosenData->BindSetting(*this, Setting.PrimaryData);
+ return true;
}
- AddButton(Primary, Data);
+ return false;
}
-// Add checkbox on UI
-void USettingsWidget::AddSettingCheckbox(FSettingsPrimary& Primary, FSettingsCheckbox& Data)
-{
- const TSubclassOf CheckboxClass = USettingsDataAsset::Get().GetCheckboxClass();
- CreateSettingSubWidget(Primary, CheckboxClass);
+/**
+ * Macro to create and bind a UI widget.
+ * @param Primary Primary settings for the widget
+ * @param Data Data structure containing widget properties
+ * @param GetterFunction The getter function to bind
+ * @param SetterFunction The setter function to bind
+ * @param AdditionalFunctionCalls Any additional function calls needed for specific widgets
+ */
+#define BIND_SETTING(Primary, Data, GetterFunction, SetterFunction) \
+ do \
+ { \
+ if (UObject* OwnerObject = Primary.GetSettingOwner(this)) \
+ { \
+ const FName GetterFunctionName = Primary.Getter.FunctionName; \
+ if (Primary.OwnerFunctionList.Contains(GetterFunctionName)) \
+ { \
+ Data.GetterFunction.BindUFunction(OwnerObject, GetterFunctionName); \
+ } \
+ const FName SetterFunctionName = Primary.Setter.FunctionName; \
+ if (Primary.OwnerFunctionList.Contains(SetterFunctionName)) \
+ { \
+ Data.SetterFunction.BindUFunction(OwnerObject, SetterFunctionName); \
+ } \
+ } \
+ } while (0)
- if (UObject* StaticContextObject = Primary.StaticContextObject.Get())
- {
- const FName GetterFunctionName = Primary.Getter.FunctionName;
- if (Primary.StaticContextFunctionList.Contains(GetterFunctionName))
- {
- Data.OnGetterBool.BindUFunction(StaticContextObject, GetterFunctionName);
- }
-
- const FName SetterFunctionName = Primary.Setter.FunctionName;
- if (Primary.StaticContextFunctionList.Contains(SetterFunctionName))
- {
- Data.OnSetterBool.BindUFunction(StaticContextObject, SetterFunctionName);
- }
- }
+// Bind button to own Get/Set delegates
+void USettingsWidget::BindButton(const FSettingsPrimary& Primary, FSettingsButton& Data)
+{
+ BIND_SETTING(Primary, Data, OnButtonPressed, OnButtonPressed);
+}
- AddCheckbox(Primary, Data);
+// Bind checkbox to own Get/Set delegates
+void USettingsWidget::BindCheckbox(const FSettingsPrimary& Primary, FSettingsCheckbox& Data)
+{
+ BIND_SETTING(Primary, Data, OnGetterBool, OnSetterBool);
}
-// Add combobox on UI
-void USettingsWidget::AddSettingCombobox(FSettingsPrimary& Primary, FSettingsCombobox& Data)
+// Bind combobox to own Get/Set delegates
+void USettingsWidget::BindCombobox(const FSettingsPrimary& Primary, FSettingsCombobox& Data)
{
- const TSubclassOf ComboboxClass = USettingsDataAsset::Get().GetComboboxClass();
- CreateSettingSubWidget(Primary, ComboboxClass);
+ BIND_SETTING(Primary, Data, OnGetterInt, OnSetterInt);
- if (UObject* StaticContextObject = Primary.StaticContextObject.Get())
+ if (UObject* OwnerObject = Primary.GetSettingOwner(this))
{
const FName GetMembersFunctionName = Data.GetMembers.FunctionName;
- if (Primary.StaticContextFunctionList.Contains(GetMembersFunctionName))
+ if (Primary.OwnerFunctionList.Contains(GetMembersFunctionName))
{
- Data.OnGetMembers.BindUFunction(StaticContextObject, GetMembersFunctionName);
+ Data.OnGetMembers.BindUFunction(OwnerObject, GetMembersFunctionName);
Data.OnGetMembers.ExecuteIfBound(Data.Members);
}
const FName SetMembersFunctionName = Data.SetMembers.FunctionName;
- if (Primary.StaticContextFunctionList.Contains(SetMembersFunctionName))
+ if (Primary.OwnerFunctionList.Contains(SetMembersFunctionName))
{
- Data.OnSetMembers.BindUFunction(StaticContextObject, SetMembersFunctionName);
+ Data.OnSetMembers.BindUFunction(OwnerObject, SetMembersFunctionName);
Data.OnSetMembers.ExecuteIfBound(Data.Members);
}
-
- const FName GetterFunctionName = Primary.Getter.FunctionName;
- if (Primary.StaticContextFunctionList.Contains(GetterFunctionName))
- {
- Data.OnGetterInt.BindUFunction(StaticContextObject, GetterFunctionName);
- }
-
- const FName SetterFunctionName = Primary.Setter.FunctionName;
- if (Primary.StaticContextFunctionList.Contains(SetterFunctionName))
- {
- Data.OnSetterInt.BindUFunction(StaticContextObject, SetterFunctionName);
- }
}
-
- AddCombobox(Primary, Data);
}
-// Add slider on UI
-void USettingsWidget::AddSettingSlider(FSettingsPrimary& Primary, FSettingsSlider& Data)
+// Bind slider to own Get/Set delegates
+void USettingsWidget::BindSlider(const FSettingsPrimary& Primary, FSettingsSlider& Data)
{
- const TSubclassOf& SliderClass = USettingsDataAsset::Get().GetSliderClass();
- CreateSettingSubWidget(Primary, SliderClass);
-
- if (UObject* StaticContextObject = Primary.StaticContextObject.Get())
- {
- const FName GetterFunctionName = Primary.Getter.FunctionName;
- if (Primary.StaticContextFunctionList.Contains(GetterFunctionName))
- {
- Data.OnGetterFloat.BindUFunction(StaticContextObject, GetterFunctionName);
- }
+ BIND_SETTING(Primary, Data, OnGetterFloat, OnSetterFloat);
+}
- const FName SetterFunctionName = Primary.Setter.FunctionName;
- if (Primary.StaticContextFunctionList.Contains(SetterFunctionName))
- {
- Data.OnSetterFloat.BindUFunction(StaticContextObject, SetterFunctionName);
- }
- }
+// Bind simple text to own Get/Set delegates
+void USettingsWidget::BindTextLine(const FSettingsPrimary& Primary, FSettingsTextLine& Data)
+{
+ BIND_SETTING(Primary, Data, OnGetterText, OnSetterText);
+}
- AddSlider(Primary, Data);
+// Bind text input to own Get/Set delegates
+void USettingsWidget::BindUserInput(const FSettingsPrimary& Primary, FSettingsUserInput& Data)
+{
+ BIND_SETTING(Primary, Data, OnGetterName, OnSetterName);
}
-// Add simple text on UI
-void USettingsWidget::AddSettingTextLine(FSettingsPrimary& Primary, FSettingsTextLine& Data)
+// Bind custom widget to own Get/Set delegates
+void USettingsWidget::BindCustomWidget(const FSettingsPrimary& Primary, FSettingsCustomWidget& Data)
{
- const TSubclassOf& TextLineClass = USettingsDataAsset::Get().GetTextLineClass();
- CreateSettingSubWidget(Primary, TextLineClass);
+ BIND_SETTING(Primary, Data, OnGetterWidget, OnSetterWidget);
+}
- if (UObject* StaticContextObject = Primary.StaticContextObject.Get())
+// Attempts to rebind those Settings that failed to bind their Getter/Setter functions on initial construct
+void USettingsWidget::TryRebindDeferredContexts()
+{
+ if (DeferredBindingsInternal.IsEmpty())
{
- const FName GetterFunctionName = Primary.Getter.FunctionName;
- if (Primary.StaticContextFunctionList.Contains(GetterFunctionName))
- {
- Data.OnGetterText.BindUFunction(StaticContextObject, GetterFunctionName);
- }
+ // Nothing to rebind, we are done
+ return;
+ }
- const FName SetterFunctionName = Primary.Setter.FunctionName;
- if (Primary.StaticContextFunctionList.Contains(SetterFunctionName))
+ FGameplayTagContainer ReboundSettings;
+ for (const FGameplayTag& TagIt : DeferredBindingsInternal)
+ {
+ FSettingsPicker* FoundRowPtr = TagIt.IsValid() ? SettingsTableRowsInternal.Find(TagIt.GetTagName()) : nullptr;
+ if (FoundRowPtr
+ && BindSetting(*FoundRowPtr))
{
- Data.OnSetterText.BindUFunction(StaticContextObject, SetterFunctionName);
+ ReboundSettings.AddTagFast(TagIt);
}
}
- AddTextLine(Primary, Data);
+ if (!ReboundSettings.IsEmpty())
+ {
+ // Some settings were successfully rebound, remove them from the deferred list and update them
+ DeferredBindingsInternal.RemoveTags(ReboundSettings);
+ UpdateSettings(ReboundSettings);
+ }
}
-// Add text input on UI
-void USettingsWidget::AddSettingUserInput(FSettingsPrimary& Primary, FSettingsUserInput& Data)
+// Add setting on UI.
+void USettingsWidget::AddSetting(FSettingsPicker& Setting)
{
- const TSubclassOf& UserInputClass = USettingsDataAsset::Get().GetUserInputClass();
- CreateSettingSubWidget(Primary, UserInputClass);
-
- if (UObject* StaticContextObject = Primary.StaticContextObject.Get())
+ FSettingsDataBase* ChosenData = Setting.GetChosenSettingsData();
+ if (!ChosenData)
{
- const FName GetterFunctionName = Primary.Getter.FunctionName;
- if (Primary.StaticContextFunctionList.Contains(GetterFunctionName))
- {
- Data.OnGetterName.BindUFunction(StaticContextObject, GetterFunctionName);
- }
-
- const FName SetterFunctionName = Primary.Setter.FunctionName;
- if (Primary.StaticContextFunctionList.Contains(SetterFunctionName))
- {
- Data.OnSetterName.BindUFunction(StaticContextObject, SetterFunctionName);
- }
+ return;
}
- AddUserInput(Primary, Data);
-}
-
-// Add custom widget on UI
-void USettingsWidget::AddSettingCustomWidget(FSettingsPrimary& Primary, FSettingsCustomWidget& Data)
-{
- CreateSettingSubWidget(Primary, Data.CustomWidgetClass);
+ FSettingsPrimary& PrimaryData = Setting.PrimaryData;
- if (UObject* StaticContextObject = Primary.StaticContextObject.Get())
+ if (Setting.PrimaryData.bStartOnNextColumn)
{
- const FName GetterFunctionName = Primary.Getter.FunctionName;
- if (Primary.StaticContextFunctionList.Contains(GetterFunctionName))
- {
- Data.OnGetterWidget.BindUFunction(StaticContextObject, GetterFunctionName);
- }
-
- const FName SetterFunctionName = Primary.Setter.FunctionName;
- if (Primary.StaticContextFunctionList.Contains(SetterFunctionName))
- {
- Data.OnSetterWidget.BindUFunction(StaticContextObject, SetterFunctionName);
- }
+ StartNextColumn();
}
- AddCustomWidget(Primary, Data);
+ CreateSettingSubWidget(PrimaryData, ChosenData->GetSubWidgetClass());
+ ChosenData->AddSetting(*this, PrimaryData);
}
diff --git a/Source/SettingsWidgetConstructor/Public/Data/SettingArchetypesData.h b/Source/SettingsWidgetConstructor/Public/Data/SettingArchetypesData.h
index acbad7e..ed829ad 100644
--- a/Source/SettingsWidgetConstructor/Public/Data/SettingArchetypesData.h
+++ b/Source/SettingsWidgetConstructor/Public/Data/SettingArchetypesData.h
@@ -9,6 +9,12 @@
//---
#include "SettingArchetypesData.generated.h"
+struct FSettingTag;
+struct FSettingsPrimary;
+
+class USettingsWidget;
+class USettingSubWidget;
+
/**
* The base archetype of any setting.
* Properties of child archetypes are used by Settings Picker select a setting.
@@ -18,10 +24,36 @@
* @see FFunctionPicker
*/
USTRUCT(BlueprintType, meta = (
- FunctionContextTemplate = "/Script/SettingsWidgetConstructor.SettingFunctionTemplate::OnStaticContext__DelegateSignature"))
+ FunctionContextTemplate = "/Script/SettingsWidgetConstructor.SettingFunctionTemplate::OnGetterObject__DelegateSignature"))
struct SETTINGSWIDGETCONSTRUCTOR_API FSettingsDataBase
{
GENERATED_BODY()
+
+ virtual ~FSettingsDataBase() = default;
+
+ /*********************************************************************************************
+ * Base methods to override
+ *
+ * Since FSettingsPicker contains many types of settings, base methods are used to call them indirectly:
+ * FSettingsPicker& Setting == ... ;
+ * FSettingsDataBase* ChosenData = Setting.GetChosenSettingsData();
+ * ChosenData-> ... ; // call any of the following methods
+ ********************************************************************************************* */
+
+ /** Base method to get the sub-widget class of this setting type. */
+ virtual TSubclassOf GetSubWidgetClass() const PURE_VIRTUAL(FSettingsDataBase::GetSubWidgetClass, return nullptr;);
+
+ /** Base method to get the setting value, where appropriate Getter of Settings Widget will be called. */
+ virtual void GetSettingValue(const USettingsWidget& SettingsWidget, const FSettingTag& Tag, FString& OutResult) const PURE_VIRTUAL(FSettingsDataBase::GetSettingValue,);
+
+ /** Base method to set the setting value, where string value will be converted to the setting type and appropriate Setter of Settings Widget will be called. */
+ virtual void SetSettingValue(USettingsWidget& SettingsWidget, const FSettingTag& Tag, const FString& Value) PURE_VIRTUAL(FSettingsDataBase::SetSettingValue,);
+
+ /** Base method to Bind setting to specified in table Get/Set delegates, so both methods will be called. */
+ virtual void BindSetting(USettingsWidget& SettingsWidget, const FSettingsPrimary& InOutPrimaryData) PURE_VIRTUAL(FSettingsDataBase::BindSetting,);
+
+ /** Base method to add the setting to the Settings Widget, where appropriate Add method of Settings Widget will be called. */
+ virtual void AddSetting(USettingsWidget& SettingsWidget, const FSettingsPrimary& InOutPrimaryData) PURE_VIRTUAL(FSettingsDataBase::AddSetting,);
};
/**
@@ -33,6 +65,10 @@ struct SETTINGSWIDGETCONSTRUCTOR_API FSettingsButton : public FSettingsDataBase
{
GENERATED_BODY()
+ /*********************************************************************************************
+ * Data
+ ********************************************************************************************* */
+
/** Either Header, Content, or Footer. */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
EMyVerticalAlignment VerticalAlignment = EMyVerticalAlignment::Content;
@@ -41,8 +77,31 @@ struct SETTINGSWIDGETCONSTRUCTOR_API FSettingsButton : public FSettingsDataBase
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
TEnumAsByte HorizontalAlignment = HAlign_Fill;
+ /*********************************************************************************************
+ * Bindings
+ ********************************************************************************************* */
+
/** Cached bound delegate, is executed on pressing this button. */
USettingFunctionTemplate::FOnButtonPressed OnButtonPressed;
+
+ /*********************************************************************************************
+ * Overrides
+ ********************************************************************************************* */
+
+ /** Returns the sub-widget class of this setting type. */
+ virtual TSubclassOf GetSubWidgetClass() const override;
+
+ /** Calls the Get function of the Settings Widget of this setting type. */
+ virtual void GetSettingValue(const USettingsWidget& SettingsWidget, const FSettingTag& Tag, FString& OutResult) const override { OutResult = FString(TEXT("")); }
+
+ /** Calls the Set function of the Settings Widget of this setting type. */
+ virtual void SetSettingValue(USettingsWidget& SettingsWidget, const FSettingTag& Tag, const FString& Value) override;
+
+ /** Calls the Bind function of the Settings Widget of this setting type. */
+ virtual void BindSetting(USettingsWidget& SettingsWidget, const FSettingsPrimary& PrimaryData) override;
+
+ /** Calls the Add function of the Settings Widget of this setting type. */
+ virtual void AddSetting(USettingsWidget& SettingsWidget, const FSettingsPrimary& PrimaryData) override;
};
/**
@@ -55,14 +114,41 @@ struct SETTINGSWIDGETCONSTRUCTOR_API FSettingsCheckbox : public FSettingsDataBas
{
GENERATED_BODY()
+ /*********************************************************************************************
+ * Data
+ ********************************************************************************************* */
+
/** The cached current checkbox state. */
bool bIsSet = false;
+ /*********************************************************************************************
+ * Bindings
+ ********************************************************************************************* */
+
/** The cached bound delegate, is executed to get the current checkbox state. */
USettingFunctionTemplate::FOnGetterBool OnGetterBool;
/** The cached bound delegate, is executed to set the current checkbox state. */
USettingFunctionTemplate::FOnSetterBool OnSetterBool;
+
+ /*********************************************************************************************
+ * Overrides
+ ********************************************************************************************* */
+
+ /** Returns the sub-widget class of this setting type. */
+ virtual TSubclassOf GetSubWidgetClass() const override;
+
+ /** Calls the Get function of the Settings Widget of this setting type. */
+ virtual void GetSettingValue(const USettingsWidget& SettingsWidget, const FSettingTag& Tag, FString& OutResult) const override;
+
+ /** Calls the Set function of the Settings Widget of this setting type. */
+ virtual void SetSettingValue(USettingsWidget& SettingsWidget, const FSettingTag& Tag, const FString& Value) override;
+
+ /** Calls the Bind function of the Settings Widget of this setting type. */
+ virtual void BindSetting(USettingsWidget& SettingsWidget, const FSettingsPrimary& PrimaryData) override;
+
+ /** Calls the Add function of the Settings Widget of this setting type. */
+ virtual void AddSetting(USettingsWidget& SettingsWidget, const FSettingsPrimary& InOutPrimaryData) override;
};
/**
@@ -75,6 +161,10 @@ struct SETTINGSWIDGETCONSTRUCTOR_API FSettingsCombobox : public FSettingsDataBas
{
GENERATED_BODY()
+ /*********************************************************************************************
+ * Data
+ ********************************************************************************************* */
+
/** The Setter function to be called to set all combobox members. */
UPROPERTY(EditDefaultsOnly, meta = (FunctionSetterTemplate = "/Script/SettingsWidgetConstructor.SettingFunctionTemplate::OnSetMembers__DelegateSignature"))
FSettingFunctionPicker SetMembers = FSettingFunctionPicker::EmptySettingFunction;
@@ -94,6 +184,10 @@ struct SETTINGSWIDGETCONSTRUCTOR_API FSettingsCombobox : public FSettingsDataBas
/** The cached chosen member index. */
int32 ChosenMemberIndex = INDEX_NONE;
+ /*********************************************************************************************
+ * Bindings
+ ********************************************************************************************* */
+
/** The cached bound delegate, is executed to get the chosen member index. */
USettingFunctionTemplate::FOnGetterInt OnGetterInt;
@@ -105,6 +199,25 @@ struct SETTINGSWIDGETCONSTRUCTOR_API FSettingsCombobox : public FSettingsDataBas
/** The cached bound delegate, is executed to set all combobox members. */
USettingFunctionTemplate::FOnSetMembers OnSetMembers;
+
+ /*********************************************************************************************
+ * Overrides
+ ********************************************************************************************* */
+
+ /** Returns the sub-widget class of this setting type. */
+ virtual TSubclassOf GetSubWidgetClass() const override;
+
+ /** Calls the Get function of the Settings Widget of this setting type. */
+ virtual void GetSettingValue(const USettingsWidget& SettingsWidget, const FSettingTag& Tag, FString& OutResult) const override;
+
+ /** Calls the Set function of the Settings Widget of this setting type. */
+ virtual void SetSettingValue(USettingsWidget& SettingsWidget, const FSettingTag& Tag, const FString& Value) override;
+
+ /** Calls the Bind function of the Settings Widget of this setting type. */
+ virtual void BindSetting(USettingsWidget& SettingsWidget, const FSettingsPrimary& PrimaryData) override;
+
+ /** Calls the Add function of the Settings Widget of this setting type. */
+ virtual void AddSetting(USettingsWidget& SettingsWidget, const FSettingsPrimary& InOutPrimaryData) override;
};
/**
@@ -117,14 +230,41 @@ struct SETTINGSWIDGETCONSTRUCTOR_API FSettingsSlider : public FSettingsDataBase
{
GENERATED_BODY()
+ /*********************************************************************************************
+ * Data
+ ********************************************************************************************* */
+
/** Cached slider value (0..1). */
double ChosenValue = INDEX_NONE;
+ /*********************************************************************************************
+ * Bindings
+ ********************************************************************************************* */
+
/** The cached bound delegate, is executed to get the current slider value. */
USettingFunctionTemplate::FOnGetterFloat OnGetterFloat;
/** The cached bound delegate, is executed to set the current slider value. */
USettingFunctionTemplate::FOnSetterFloat OnSetterFloat;
+
+ /*********************************************************************************************
+ * Overrides
+ ********************************************************************************************* */
+
+ /** Returns the sub-widget class of this setting type. */
+ virtual TSubclassOf GetSubWidgetClass() const override;
+
+ /** Calls the Get function of the Settings Widget of this setting type. */
+ virtual void GetSettingValue(const USettingsWidget& SettingsWidget, const FSettingTag& Tag, FString& OutResult) const override;
+
+ /** Calls the Set function of the Settings Widget of this setting type. */
+ virtual void SetSettingValue(USettingsWidget& SettingsWidget, const FSettingTag& Tag, const FString& Value) override;
+
+ /** Calls the Bind function of the Settings Widget of this setting type. */
+ virtual void BindSetting(USettingsWidget& SettingsWidget, const FSettingsPrimary& PrimaryData) override;
+
+ /** Calls the Add function of the Settings Widget of this setting type. */
+ virtual void AddSetting(USettingsWidget& SettingsWidget, const FSettingsPrimary& InOutPrimaryData) override;
};
/**
@@ -137,6 +277,10 @@ struct SETTINGSWIDGETCONSTRUCTOR_API FSettingsTextLine : public FSettingsDataBas
{
GENERATED_BODY()
+ /*********************************************************************************************
+ * Data
+ ********************************************************************************************* */
+
/** Either Header, Content, or Footer. */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
EMyVerticalAlignment VerticalAlignment = EMyVerticalAlignment::Content;
@@ -145,11 +289,34 @@ struct SETTINGSWIDGETCONSTRUCTOR_API FSettingsTextLine : public FSettingsDataBas
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
TEnumAsByte HorizontalAlignment = HAlign_Fill;
+ /*********************************************************************************************
+ * Bindings
+ ********************************************************************************************* */
+
/** The cached bound delegate, is executed to set the text caption. */
USettingFunctionTemplate::FOnGetterText OnGetterText;
/** The cached bound delegate, is executed to get the text caption. */
USettingFunctionTemplate::FOnSetterText OnSetterText;
+
+ /*********************************************************************************************
+ * Overrides
+ ********************************************************************************************* */
+
+ /** Returns the sub-widget class of this setting type. */
+ virtual TSubclassOf GetSubWidgetClass() const override;
+
+ /** Calls the Get function of the Settings Widget of this setting type. */
+ virtual void GetSettingValue(const USettingsWidget& SettingsWidget, const FSettingTag& Tag, FString& OutResult) const override;
+
+ /** Calls the Set function of the Settings Widget of this setting type. */
+ virtual void SetSettingValue(USettingsWidget& SettingsWidget, const FSettingTag& Tag, const FString& Value) override;
+
+ /** Calls the Bind function of the Settings Widget of this setting type. */
+ virtual void BindSetting(USettingsWidget& SettingsWidget, const FSettingsPrimary& PrimaryData) override;
+
+ /** Calls the Add function of the Settings Widget of this setting type. */
+ virtual void AddSetting(USettingsWidget& SettingsWidget, const FSettingsPrimary& InOutPrimaryData) override;
};
/**
@@ -162,6 +329,10 @@ struct SETTINGSWIDGETCONSTRUCTOR_API FSettingsUserInput : public FSettingsDataBa
{
GENERATED_BODY()
+ /*********************************************************************************************
+ * Data
+ ********************************************************************************************* */
+
/** The maximal length of the player input that is allowed to type.
* Set 0 to do not limit number of characters. */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
@@ -170,11 +341,34 @@ struct SETTINGSWIDGETCONSTRUCTOR_API FSettingsUserInput : public FSettingsDataBa
/** The cached text shown left of the input box. */
FName UserInput = NAME_None;
+ /*********************************************************************************************
+ * Bindings
+ ********************************************************************************************* */
+
/** The cached bound delegate, is executed to set the input text. */
USettingFunctionTemplate::FOnGetterName OnGetterName;
/** The cached bound delegate, is executed to get the input text. */
USettingFunctionTemplate::FOnSetterName OnSetterName;
+
+ /*********************************************************************************************
+ * Overrides
+ ********************************************************************************************* */
+
+ /** Returns the sub-widget class of this setting type. */
+ virtual TSubclassOf GetSubWidgetClass() const override;
+
+ /** Calls the Get function of the Settings Widget of this setting type. */
+ virtual void GetSettingValue(const USettingsWidget& SettingsWidget, const FSettingTag& Tag, FString& OutResult) const override;
+
+ /** Calls the Set function of the Settings Widget of this setting type. */
+ virtual void SetSettingValue(USettingsWidget& SettingsWidget, const FSettingTag& Tag, const FString& Value) override;
+
+ /** Calls the Bind function of the Settings Widget of this setting type. */
+ virtual void BindSetting(USettingsWidget& SettingsWidget, const FSettingsPrimary& PrimaryData) override;
+
+ /** Calls the Add function of the Settings Widget of this setting type. */
+ virtual void AddSetting(USettingsWidget& SettingsWidget, const FSettingsPrimary& InOutPrimaryData) override;
};
/**
@@ -187,13 +381,40 @@ struct SETTINGSWIDGETCONSTRUCTOR_API FSettingsCustomWidget : public FSettingsDat
{
GENERATED_BODY()
+ /*********************************************************************************************
+ * Data
+ ********************************************************************************************* */
+
/** Contains created custom widget of the setting. */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, meta = (ShowOnlyInnerProperties))
TSubclassOf CustomWidgetClass = nullptr;
+ /*********************************************************************************************
+ * Bindings
+ ********************************************************************************************* */
+
/** The cached bound delegate, is executed to set the custom widget. */
USettingFunctionTemplate::FOnGetterWidget OnGetterWidget;
/** The cached bound delegate, is executed to get the custom widget. */
USettingFunctionTemplate::FOnSetterWidget OnSetterWidget;
+
+ /*********************************************************************************************
+ * Overrides
+ ********************************************************************************************* */
+
+ /** Returns the sub-widget class of this setting type. */
+ virtual TSubclassOf GetSubWidgetClass() const override;
+
+ /** Calls the Get function of the Settings Widget of this setting type. */
+ virtual void GetSettingValue(const USettingsWidget& SettingsWidget, const FSettingTag& Tag, FString& OutResult) const override;
+
+ /** Calls the Set function of the Settings Widget of this setting type. */
+ virtual void SetSettingValue(USettingsWidget& SettingsWidget, const FSettingTag& Tag, const FString& Value) override {}
+
+ /** Calls the Bind function of the Settings Widget of this setting type. */
+ virtual void BindSetting(USettingsWidget& SettingsWidget, const FSettingsPrimary& PrimaryData) override;
+
+ /** Calls the Add function of the Settings Widget of this setting type. */
+ virtual void AddSetting(USettingsWidget& SettingsWidget, const FSettingsPrimary& InOutPrimaryData) override;
};
diff --git a/Source/SettingsWidgetConstructor/Public/Data/SettingsDataAsset.h b/Source/SettingsWidgetConstructor/Public/Data/SettingsDataAsset.h
index 6ceedef..b2b1b31 100644
--- a/Source/SettingsWidgetConstructor/Public/Data/SettingsDataAsset.h
+++ b/Source/SettingsWidgetConstructor/Public/Data/SettingsDataAsset.h
@@ -4,11 +4,13 @@
#include "Engine/DeveloperSettings.h"
//---
-#include "Data/SettingsDataTable.h"
#include "Data/SettingsThemeData.h"
//---
#include "SettingsDataAsset.generated.h"
+class USettingsDataTable;
+class UDataRegistry;
+
/**
* Contains common settings data of the Constructor Widget plugin.
* Is set up in 'Project Settings' -> "Plugins" -> "Settings Widget Constructor".
@@ -18,6 +20,9 @@ class SETTINGSWIDGETCONSTRUCTOR_API USettingsDataAsset : public UDeveloperSettin
{
GENERATED_BODY()
+ /*********************************************************************************************
+ * Getters
+ ********************************************************************************************* */
public:
/** Returns Project Settings Data of the Settings Widget Constructor plugin. */
static const FORCEINLINE USettingsDataAsset& Get() { return *GetDefault(); }
@@ -32,9 +37,9 @@ class SETTINGSWIDGETCONSTRUCTOR_API USettingsDataAsset : public UDeveloperSettin
/** Gets the category for the settings, some high level grouping like, Editor, Engine, Game...etc. */
virtual FName GetCategoryName() const override { return TEXT("Plugins"); }
- /** Returns the data table. */
+ /** Returns the project's main Settings Data Table, it has to be set manually. */
UFUNCTION(BlueprintPure, Category = "Settings Widget Constructor")
- FORCEINLINE USettingsDataTable* GetSettingsDataTable() const { return SettingsDataTableInternal.LoadSynchronous(); }
+ const USettingsDataTable* GetSettingsDataTable() const;
/** Returns the sub-widget of Button settings. */
UFUNCTION(BlueprintPure, Category = "Settings Widget Constructor")
@@ -64,6 +69,10 @@ class SETTINGSWIDGETCONSTRUCTOR_API USettingsDataAsset : public UDeveloperSettin
UFUNCTION(BlueprintPure, Category = "Settings Widget Constructor")
FORCEINLINE bool IsAutoConstruct() const { return bAutoConstructInternal; }
+ /** Returns true if should automatically focus the Settings Widget on UI each time it is opened. */
+ UFUNCTION(BlueprintPure, Category = "Settings Widget Constructor")
+ FORCEINLINE bool IsAutoFocusOnOpen() const { return bAutoFocusOnOpenInternal; }
+
/** Returns the width and height of the settings widget in percentages of an entire screen. */
UFUNCTION(BlueprintPure, Category = "Settings Widget Constructor")
const FORCEINLINE FVector2D& GetSettingsPercentSize() const { return SettingsPercentSizeInternal; }
@@ -108,10 +117,18 @@ class SETTINGSWIDGETCONSTRUCTOR_API USettingsDataAsset : public UDeveloperSettin
UFUNCTION(BlueprintPure, Category = "Settings Widget Constructor")
const FORCEINLINE FMiscThemeData& GetMiscThemeData() const { return MiscThemeDataInternal; }
+ /** Returns the Settings Data Registry asset, is automatically set by default to which 'Settings Data Table' is added by itself. */
+ UFUNCTION(BlueprintPure, Category = "Settings Widget Constructor")
+ const UDataRegistry* GetSettingsDataRegistry() const;
+ const TSoftObjectPtr& GetSettingsDataRegistrySoft() const { return SettingsDataRegistryInternal; }
+
+ /*********************************************************************************************
+ * Protected properties
+ ********************************************************************************************* */
protected:
- /** The data table with all settings, is config property. */
+ /** The project's main Settings Data Table, is config property and has to be set manually. */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Config, Category = "Settings Widget Constructor", meta = (BlueprintProtected, DisplayName = "Settings Data Table", ShowOnlyInnerProperties))
- TSoftObjectPtr SettingsDataTableInternal;
+ TSoftObjectPtr SettingsDataTableInternal;
/** The sub-widget class of Button settings, is config property. */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Config, Category = "Settings Widget Constructor", meta = (BlueprintProtected, DisplayName = "Button Class", ShowOnlyInnerProperties))
@@ -141,6 +158,10 @@ class SETTINGSWIDGETCONSTRUCTOR_API USettingsDataAsset : public UDeveloperSettin
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Config, Category = "Settings Widget Constructor", meta = (BlueprintProtected, DisplayName = "Auto Construct", ShowOnlyInnerProperties))
bool bAutoConstructInternal;
+ /** If true, the Setting Widget will be automatically focused on UI each time it is opened. */
+ UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Config, Category = "Settings Widget Constructor", meta = (BlueprintProtected, DisplayName = "Auto Focus On Open", ShowOnlyInnerProperties))
+ bool bAutoFocusOnOpenInternal;
+
/** The width and height of the settings widget in percentages of an entire screen. Is clamped between 0 and 1, is config property. */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Config, Category = "Settings Widget Constructor", meta = (BlueprintProtected, DisplayName = "Settings Percent Size", ClampMin = "0", ClampMax = "1", ShowOnlyInnerProperties))
FVector2D SettingsPercentSizeInternal;
@@ -184,4 +205,23 @@ class SETTINGSWIDGETCONSTRUCTOR_API USettingsDataAsset : public UDeveloperSettin
/** The misc theme data, is config property. */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Config, Category = "Settings Widget Constructor", meta = (BlueprintProtected, DisplayName = "Misc Theme Data"))
FMiscThemeData MiscThemeDataInternal;
+
+ /** The Settings Data Registry asset, is automatically set by default to which 'Settings Data Table' is added by itself. */
+ UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Config, Category = "Settings Widget Constructor", meta = (BlueprintProtected, DisplayName = "Settings Data Registry", ShowOnlyInnerProperties))
+ TSoftObjectPtr SettingsDataRegistryInternal;
+
+ /*********************************************************************************************
+ * Internal
+ ********************************************************************************************* */
+protected:
+ /** Overrides post init to register Settings Data Table by default on startup. */
+ virtual void PostInitProperties() override;
+
+ /** Is called once Engine is initialized, so we can register Settings Data Table by default on startup. */
+ void OnPostEngineInit();
+
+#if WITH_EDITOR
+ /** Overrides property change events to handle picking Settings Data Table. */
+ virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override;
+#endif
};
diff --git a/Source/SettingsWidgetConstructor/Public/Data/SettingsDataTable.h b/Source/SettingsWidgetConstructor/Public/Data/SettingsDataTable.h
index a764eed..c7845a6 100644
--- a/Source/SettingsWidgetConstructor/Public/Data/SettingsDataTable.h
+++ b/Source/SettingsWidgetConstructor/Public/Data/SettingsDataTable.h
@@ -4,8 +4,6 @@
#include "SettingsWidgetConstructor/Private/MyDataTable/SWCMyDataTable.h"
//---
-#include "Data/SettingsRow.h"
-//---
#include "SettingsDataTable.generated.h"
/**
@@ -24,7 +22,7 @@ class SETTINGSWIDGETCONSTRUCTOR_API USettingsDataTable : public USWCMyDataTable
/** Returns the table rows.
* @see USettingsDataAsset::SettingsDataTableInternal */
UFUNCTION(BlueprintCallable, Category = "Settings Widget Constructor")
- void GetSettingRows(TMap& OutRows) const { GetRows(OutRows); }
+ void GetSettingRows(TMap& OutRows) const { GetRows(OutRows); }
protected:
#if WITH_EDITOR
diff --git a/Source/SettingsWidgetConstructor/Public/Data/SettingsRow.h b/Source/SettingsWidgetConstructor/Public/Data/SettingsRow.h
index 5325e27..e462fd2 100644
--- a/Source/SettingsWidgetConstructor/Public/Data/SettingsRow.h
+++ b/Source/SettingsWidgetConstructor/Public/Data/SettingsRow.h
@@ -18,7 +18,7 @@
* ╚═══╦FSettingsPicker
* ╠═══╦FSettingsPrimary
* ║ ╠════FSettingTag
- * ║ ╚════FSettingFunctionPicker (StaticContext, Setter, Getter)
+ * ║ ╚════FSettingFunctionPicker (Owner, Setter, Getter)
* ╚════FSettingsDataBase
*/
@@ -41,24 +41,24 @@ struct SETTINGSWIDGETCONSTRUCTOR_API FSettingsPrimary
/** The static function to obtain object to call Setters and Getters.
* The FunctionContextTemplate meta will contain a name of one UFunctionPickerTemplate delegate. */
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (FunctionContextTemplate))
- FSettingFunctionPicker StaticContext = FSettingFunctionPicker::EmptySettingFunction;
+ FSettingFunctionPicker Owner = FSettingFunctionPicker::EmptySettingFunction;
- /** The Setter function to be called to set the setting value for the Static Context object.
+ /** The Setter function to be called to set the setting value for the Owner object.
* The FunctionSetterTemplate meta will contain a name of one UFunctionPickerTemplate delegate. */
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (FunctionSetterTemplate))
FSettingFunctionPicker Setter = FSettingFunctionPicker::EmptySettingFunction;
- /** The Getter function to be called to get the setting value from the Static Context object.
+ /** The Getter function to be called to get the setting value from the Owner object.
* The FunctionGetterTemplate meta will contain a name of one UFunctionPickerTemplate delegate. */
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (FunctionGetterTemplate))
FSettingFunctionPicker Getter = FSettingFunctionPicker::EmptySettingFunction;
/** The setting name. */
- UPROPERTY(EditAnywhere, BlueprintReadWrite)
+ UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (MultiLine = "true"))
FText Caption = TEXT_NONE;
/** The description to be shown as tooltip. */
- UPROPERTY(EditAnywhere, BlueprintReadWrite)
+ UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (MultiLine = "true"))
FText Tooltip = TEXT_NONE;
/** The padding of this setting. */
@@ -77,14 +77,18 @@ struct SETTINGSWIDGETCONSTRUCTOR_API FSettingsPrimary
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (Categories = "Settings"))
FGameplayTagContainer SettingsToUpdate = FGameplayTagContainer::EmptyContainer;
+ /** If set, it will override own position to be shown after specified setting.
+ * Is useful when should be shown after setting that is created in another Settings Data Table.
+ * All the next settings after ShowNextToSettingOverride in the same table will be also shown next to it.
+ * @see 'Data Registr'y category of 'Settings Data Asset'. */
+ UPROPERTY(EditAnywhere, BlueprintReadWrite)
+ FSettingTag ShowNextToSettingOverride = FSettingTag::EmptySettingTag;
+
/** Created widget of the chosen setting (button, checkbox, combobox, slider, text line, user input). */
TWeakObjectPtr SettingSubWidget = nullptr;
- /** The cached object obtained from the Static Context function. */
- TWeakObjectPtr StaticContextObject = nullptr;
-
- /** Contains all cached functions of the Static Context object. */
- TArray StaticContextFunctionList;
+ /** Contains all cached functions of the Owner object. */
+ TArray OwnerFunctionList;
/** Returns true if is valid. */
FORCEINLINE bool IsValid() const { return Tag.IsValid(); }
@@ -96,6 +100,17 @@ struct SETTINGSWIDGETCONSTRUCTOR_API FSettingsPrimary
/** Creates a hash value.
* @param Other the other object to create a hash value for. */
friend SETTINGSWIDGETCONSTRUCTOR_API uint32 GetTypeHash(const FSettingsPrimary& Other);
+
+ /*********************************************************************************************
+ * Setting Owner
+ * Is living object that contains specific Setter and Getter functions.
+ ********************************************************************************************* */
+public:
+ /** Is executed to obtain holding object. */
+ UObject* GetSettingOwner(const UObject* WorldContext) const;
+
+ /** The cached bound delegate that returns holding object. */
+ USettingFunctionTemplate::FOnGetterObject OwnerFunc;
};
/**
@@ -152,7 +167,7 @@ struct SETTINGSWIDGETCONSTRUCTOR_API FSettingsPicker
/** Returns the pointer to one of the chosen in-game type.
* It searches the member property of this struct by a value of SettingsType.
* @see FSettingsPicker::SettingsType */
- const FSettingsDataBase* GetChosenSettingsData() const;
+ FSettingsDataBase* GetChosenSettingsData() const;
/** Returns true if row is valid. */
FORCEINLINE bool IsValid() const { return !(*this == Empty); }
diff --git a/Source/SettingsWidgetConstructor/Public/MyUtilsLibraries/SettingsUtilsLibrary.h b/Source/SettingsWidgetConstructor/Public/MyUtilsLibraries/SettingsUtilsLibrary.h
new file mode 100644
index 0000000..d4340bb
--- /dev/null
+++ b/Source/SettingsWidgetConstructor/Public/MyUtilsLibraries/SettingsUtilsLibrary.h
@@ -0,0 +1,45 @@
+// Copyright (c) Yevhenii Selivanov
+
+#pragma once
+
+#include "Kismet/BlueprintFunctionLibrary.h"
+//---
+#include "SettingsUtilsLibrary.generated.h"
+
+/**
+ * The common functions library for Settings Widget Constructor.
+ */
+UCLASS()
+class SETTINGSWIDGETCONSTRUCTOR_API USettingsUtilsLibrary : public UBlueprintFunctionLibrary
+{
+ GENERATED_BODY()
+
+public:
+ /** Returns the Settings widget from viewport. */
+ UFUNCTION(BlueprintPure, Category = "Settings Widget Constructor", meta = (WorldContext = "WorldContextObject"))
+ static class USettingsWidget* GetSettingsWidget(const UObject* WorldContextObject);
+
+ /** Returns the Game User Settings object. */
+ UFUNCTION(BlueprintPure, Category = "Settings Widget Constructor", meta = (WorldContext = "OptionalWorldContext"))
+ static class UGameUserSettings* GetGameUserSettings(const UObject* OptionalWorldContext = nullptr);
+
+ /** Returns all Settings Rows from project's Settings Data Table and all other additional Data Tables from 'SettingsDataTable' Data Registry.
+ * Note: Is expensive function, prefer to cache the result once! */
+ UFUNCTION(BlueprintPure, Category = "Settings Widget Constructor")
+ static void GetAllSettingRows(TMap& OutSettingRows);
+
+ /*********************************************************************************************
+ * Multiple Data Tables support
+ * Allows to register additional Settings Data Tables if needed
+ * https://docs.google.com/document/d/1IXnOqrgaXTClP-0cIo28a9f6GHc9N1BCgTNnMk-X9VQ
+ ********************************************************************************************* */
+public:
+ /** Registers given Settings Data Table to the Settings Data Registry. Alternatively Game Feature Action can be used to register it.
+ * It's automatically called on startup for the 'Settings Data Table' set in the Project Settings.
+ * Can be called manually to register additional Settings Data Tables. */
+ UFUNCTION(BlueprintCallable, Category = "C++")
+ static void RegisterDataTable(const TSoftObjectPtr SettingsDataTable);
+
+ /** Returns all Settings Data Tables added to 'SettingsDataTable' Data Registry including Project's one. */
+ static void GetAllSettingDataTables(TSet& OutDataTables);
+};
diff --git a/Source/SettingsWidgetConstructor/Public/UI/SettingSubWidget.h b/Source/SettingsWidgetConstructor/Public/UI/SettingSubWidget.h
index 3c3e5ef..7002545 100644
--- a/Source/SettingsWidgetConstructor/Public/UI/SettingSubWidget.h
+++ b/Source/SettingsWidgetConstructor/Public/UI/SettingSubWidget.h
@@ -5,7 +5,6 @@
#include "Blueprint/UserWidget.h"
//---
#include "Data/SettingsRow.h"
-#include "Widgets/Input/SComboBox.h"
//---
#include "SettingSubWidget.generated.h"
@@ -149,6 +148,9 @@ class SETTINGSWIDGETCONSTRUCTOR_API USettingCheckbox : public USettingSubWidget
void OnCheckStateChanged(bool bIsChecked);
};
+template
+class SComboBox;
+
/**
* The sub-widget of Combobox settings.
*/
diff --git a/Source/SettingsWidgetConstructor/Public/UI/SettingsWidget.h b/Source/SettingsWidgetConstructor/Public/UI/SettingsWidget.h
index bd3886a..592a017 100644
--- a/Source/SettingsWidgetConstructor/Public/UI/SettingsWidget.h
+++ b/Source/SettingsWidgetConstructor/Public/UI/SettingsWidget.h
@@ -17,11 +17,10 @@ class SETTINGSWIDGETCONSTRUCTOR_API USettingsWidget : public UUserWidget
{
GENERATED_BODY()
-public:
/* ---------------------------------------------------
* Public properties
* --------------------------------------------------- */
-
+public:
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnToggledSettings, bool, bIsVisible);
/** Is called to notify listeners the Settings widget is opened or closed. */
@@ -31,7 +30,7 @@ class SETTINGSWIDGETCONSTRUCTOR_API USettingsWidget : public UUserWidget
/* ---------------------------------------------------
* Public functions
* --------------------------------------------------- */
-
+public:
/** Constructs settings if viewport is ready otherwise wait until viewport become initialized. */
UFUNCTION(BlueprintCallable, Category = "Settings Widget Constructor")
void TryConstructSettings();
@@ -56,6 +55,10 @@ class SETTINGSWIDGETCONSTRUCTOR_API USettingsWidget : public UUserWidget
UFUNCTION(BlueprintCallable, Category = "Settings Widget Constructor")
void ToggleSettings();
+ /** Is called on opening to focus the widget on UI if allowed. */
+ UFUNCTION(BlueprintCallable, Category = "Settings Widget Constructor")
+ void TryFocusOnUI();
+
/** Returns true when this widget is fully constructed and ready to be used. */
UFUNCTION(BlueprintPure, Category = "C++")
FORCEINLINE bool IsSettingsWidgetConstructed() const { return SettingsTableRowsInternal.Num() > 0; }
@@ -100,7 +103,7 @@ class SETTINGSWIDGETCONSTRUCTOR_API USettingsWidget : public UUserWidget
/* ---------------------------------------------------
* Style
* --------------------------------------------------- */
-
+public:
/** Returns the size of the Settings widget on the screen. */
UFUNCTION(BlueprintPure, Category = "Settings Widget Constructor")
FVector2D GetSettingsSize() const;
@@ -116,12 +119,12 @@ class SETTINGSWIDGETCONSTRUCTOR_API USettingsWidget : public UUserWidget
/** Is blueprint-event called that returns the style brush by specified button state. */
UFUNCTION(BlueprintPure, Category = "Settings Widget Constructor|Style")
- FSlateBrush GetButtonBrush(ESettingsButtonState State) const;
+ static FSlateBrush GetButtonBrush(ESettingsButtonState State);
/* ---------------------------------------------------
* Setters by setting types
* --------------------------------------------------- */
-
+public:
/**
* Set value to the option by tag.
* Common function to set setting of an any type by the string.
@@ -177,7 +180,7 @@ class SETTINGSWIDGETCONSTRUCTOR_API USettingsWidget : public UUserWidget
/* ---------------------------------------------------
* Getters by setting types
* --------------------------------------------------- */
-
+public:
/** Returns is a checkbox toggled. */
UFUNCTION(BlueprintPure, Category = "Settings Widget Constructor|Getters", meta = (AutoCreateRefTerm = "CheckboxTag"))
bool GetCheckboxValue(const FSettingTag& CheckboxTag) const;
@@ -214,7 +217,7 @@ class SETTINGSWIDGETCONSTRUCTOR_API USettingsWidget : public UUserWidget
/* ---------------------------------------------------
* Protected properties
* --------------------------------------------------- */
-
+protected:
/** Contains all settings. */
UPROPERTY(VisibleDefaultsOnly, BlueprintReadOnly, Transient, Category = "Settings Widget Constructor", meta = (BlueprintProtected, DisplayName = "Settings Table Rows"))
TMap SettingsTableRowsInternal;
@@ -231,10 +234,15 @@ class SETTINGSWIDGETCONSTRUCTOR_API USettingsWidget : public UUserWidget
UPROPERTY(VisibleDefaultsOnly, BlueprintReadOnly, Transient, Category = "Settings Widget Constructor", meta = (BlueprintProtected, DisplayName = "Setting ScrollBoxes"))
TArray> SettingScrollBoxesInternal;
+ /** Contains all Setting tags that failed to bind their Getter/Setter functions on initial construct, so it's stored to be rebound later.
+ * @see USettingsWidget::TryRebindDeferredContexts */
+ UPROPERTY(VisibleInstanceOnly, BlueprintReadWrite, Transient, Category = "Settings Widget Constructor", meta = (BlueprintProtected, DisplayName = "DeferredBindings"))
+ FGameplayTagContainer DeferredBindingsInternal;
+
/* ---------------------------------------------------
* Bound widget properties
* --------------------------------------------------- */
-
+protected:
/** The section in the top margin of Settings, usually contains a title. */
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "Settings Widget Constructor|Widgets", meta = (BlueprintProtected, BindWidget))
TObjectPtr HeaderVerticalBox = nullptr;
@@ -250,7 +258,7 @@ class SETTINGSWIDGETCONSTRUCTOR_API USettingsWidget : public UUserWidget
/* ---------------------------------------------------
* Protected functions
* --------------------------------------------------- */
-
+protected:
/** Called after the underlying slate widget is constructed.
* May be called multiple times due to adding and removing from the hierarchy. */
virtual void NativeConstruct() override;
@@ -271,11 +279,6 @@ class SETTINGSWIDGETCONSTRUCTOR_API USettingsWidget : public UUserWidget
UFUNCTION(BlueprintCallable, Category = "Settings Widget Constructor", meta = (BlueprintProtected))
void OnToggleSettings(bool bIsVisible);
- /** Bind and set static object delegate.
- * @see FSettingsPrimary::OnStaticContext */
- UFUNCTION(BlueprintCallable, Category = "Settings Widget Constructor", meta = (BlueprintProtected))
- void TryBindStaticContext(UPARAM(ref)FSettingsPrimary& Primary);
-
/** Starts adding settings on the next column. */
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Settings Widget Constructor", meta = (BlueprintProtected))
void StartNextColumn();
@@ -285,9 +288,56 @@ class SETTINGSWIDGETCONSTRUCTOR_API USettingsWidget : public UUserWidget
void UpdateScrollBoxesHeight();
/* ---------------------------------------------------
- * Add by setting types
+ * Bind by setting types
* --------------------------------------------------- */
+public:
+ /** Bind setting to specified in table Get/Set delegates, so both methods will be called. */
+ UFUNCTION(BlueprintCallable, Category = "Settings Widget Constructor", meta = (BlueprintProtected))
+ bool BindSetting(UPARAM(ref)FSettingsPicker& Setting);
+
+ /** Bind button to own Get/Set delegates. */
+ UFUNCTION(BlueprintCallable, Category = "Settings Widget Constructor|Binders", meta = (BlueprintProtected, AutoCreateRefTerm = "Primary,Data"))
+ void BindButton(const FSettingsPrimary& Primary, FSettingsButton& Data);
+
+ /** Bind checkbox to own Get/Set delegates. */
+ UFUNCTION(BlueprintCallable, Category = "Settings Widget Constructor|Binders", meta = (BlueprintProtected, AutoCreateRefTerm = "Primary,Data"))
+ void BindCheckbox(const FSettingsPrimary& Primary, FSettingsCheckbox& Data);
+
+ /** Bind combobox to own Get/Set delegates. */
+ UFUNCTION(BlueprintCallable, Category = "Settings Widget Constructor|Binders", meta = (BlueprintProtected, AutoCreateRefTerm = "Primary,Data"))
+ void BindCombobox(const FSettingsPrimary& Primary, FSettingsCombobox& Data);
+
+ /** Bind slider to own Get/Set delegates. */
+ UFUNCTION(BlueprintCallable, Category = "Settings Widget Constructor|Binders", meta = (BlueprintProtected, AutoCreateRefTerm = "Primary,Data"))
+ void BindSlider(const FSettingsPrimary& Primary, FSettingsSlider& Data);
+
+ /** Bind simple text to own Get/Set delegates. */
+ UFUNCTION(BlueprintCallable, Category = "Settings Widget Constructor|Binders", meta = (BlueprintProtected, AutoCreateRefTerm = "Primary,Data"))
+ void BindTextLine(const FSettingsPrimary& Primary, FSettingsTextLine& Data);
+
+ /** Bind text input to own Get/Set delegates. */
+ UFUNCTION(BlueprintCallable, Category = "Settings Widget Constructor|Binders", meta = (BlueprintProtected, AutoCreateRefTerm = "Primary,Data"))
+ void BindUserInput(const FSettingsPrimary& Primary, FSettingsUserInput& Data);
+
+ /** Bind custom widget to own Get/Set delegates. */
+ UFUNCTION(BlueprintCallable, Category = "Settings Widget Constructor|Binders", meta = (BlueprintProtected, AutoCreateRefTerm = "Primary,Data"))
+ void BindCustomWidget(const FSettingsPrimary& Primary, FSettingsCustomWidget& Data);
+
+protected:
+ /** Bind and set static object delegate.
+ * @see FSettingsPrimary::OwnerFunc */
+ UFUNCTION(BlueprintCallable, Category = "Settings Widget Constructor", meta = (BlueprintProtected))
+ bool TryBindOwner(UPARAM(ref)FSettingsPrimary& Primary);
+ /** Attempts to rebind those Settings that failed to bind their Getter/Setter functions on initial construct.
+ * @see USettingsWidget::DeferredBindingsInternal */
+ UFUNCTION(BlueprintCallable, Category = "Settings Widget Constructor", meta = (BlueprintProtected))
+ void TryRebindDeferredContexts();
+
+ /* ---------------------------------------------------
+ * Add by setting types
+ * --------------------------------------------------- */
+public:
/** Add setting on UI. */
UFUNCTION(BlueprintCallable, Category = "Settings Widget Constructor|Adders", meta = (BlueprintProtected))
void AddSetting(UPARAM(ref)FSettingsPicker& Setting);
@@ -295,59 +345,54 @@ class SETTINGSWIDGETCONSTRUCTOR_API USettingsWidget : public UUserWidget
/** Add button on UI. */
UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, Category = "Settings Widget Constructor|Adders", meta = (BlueprintProtected, AutoCreateRefTerm = "Primary,Data"))
void AddButton(const FSettingsPrimary& Primary, const FSettingsButton& Data);
- void AddSettingButton(FSettingsPrimary& Primary, FSettingsButton& Data);
/** Add checkbox on UI. */
UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, Category = "Settings Widget Constructor|Adders", meta = (BlueprintProtected, AutoCreateRefTerm = "Primary,Data"))
void AddCheckbox(const FSettingsPrimary& Primary, const FSettingsCheckbox& Data);
- void AddSettingCheckbox(FSettingsPrimary& Primary, FSettingsCheckbox& Data);
/** Add combobox on UI. */
UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, Category = "Settings Widget Constructor|Adders", meta = (BlueprintProtected, AutoCreateRefTerm = "Primary,Data"))
void AddCombobox(const FSettingsPrimary& Primary, const FSettingsCombobox& Data);
- void AddSettingCombobox(FSettingsPrimary& Primary, FSettingsCombobox& Data);
/** Add slider on UI. */
UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, Category = "Settings Widget Constructor|Adders", meta = (BlueprintProtected, AutoCreateRefTerm = "Primary,Data"))
void AddSlider(const FSettingsPrimary& Primary, const FSettingsSlider& Data);
- void AddSettingSlider(FSettingsPrimary& Primary, FSettingsSlider& Data);
/** Add simple text on UI. */
UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, Category = "Settings Widget Constructor|Adders", meta = (BlueprintProtected, AutoCreateRefTerm = "Primary,Data"))
void AddTextLine(const FSettingsPrimary& Primary, const FSettingsTextLine& Data);
- void AddSettingTextLine(FSettingsPrimary& Primary, FSettingsTextLine& Data);
/** Add text input on UI. */
UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, Category = "Settings Widget Constructor|Adders", meta = (BlueprintProtected, AutoCreateRefTerm = "Primary,Data"))
void AddUserInput(const FSettingsPrimary& Primary, const FSettingsUserInput& Data);
- void AddSettingUserInput(FSettingsPrimary& Primary, FSettingsUserInput& Data);
/** Add custom widget on UI. */
UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, Category = "Settings Widget Constructor|Adders", meta = (BlueprintProtected, AutoCreateRefTerm = "Primary,Data"))
void AddCustomWidget(const FSettingsPrimary& Primary, const FSettingsCustomWidget& Data);
- void AddSettingCustomWidget(FSettingsPrimary& Primary, FSettingsCustomWidget& Data);
/* ---------------------------------------------------
* Blueprint implementable setters
+ *
+ * Don't call these functions directly, use 'Set Setting X' functions instead.
* --------------------------------------------------- */
-
+protected:
/** Internal blueprint function to toggle checkbox. */
- UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, Category = "Settings Widget Constructor|Setters", meta = (BlueprintProtected, AutoCreateRefTerm = "CheckboxTag"))
+ UFUNCTION(BlueprintImplementableEvent, Category = "Settings Widget Constructor|Setters", meta = (BlueprintProtected, AutoCreateRefTerm = "CheckboxTag"))
void SetCheckbox(const FSettingTag& CheckboxTag, bool InValue);
/** Internal blueprint function to set chosen member index for a combobox. */
- UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, Category = "Settings Widget Constructor|Setters", meta = (BlueprintProtected, AutoCreateRefTerm = "ComboboxTag"))
+ UFUNCTION(BlueprintImplementableEvent, Category = "Settings Widget Constructor|Setters", meta = (BlueprintProtected, AutoCreateRefTerm = "ComboboxTag"))
void SetComboboxIndex(const FSettingTag& ComboboxTag, int32 InValue);
/** Internal blueprint function to set new members for a combobox. */
- UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, Category = "Settings Widget Constructor|Setters", meta = (BlueprintProtected, AutoCreateRefTerm = "ComboboxTag,InValue"))
+ UFUNCTION(BlueprintImplementableEvent, Category = "Settings Widget Constructor|Setters", meta = (BlueprintProtected, AutoCreateRefTerm = "ComboboxTag,InValue"))
void SetComboboxMembers(const FSettingTag& ComboboxTag, const TArray& InValue);
/** Internal blueprint function to set current value for a slider [0...1]. */
- UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, Category = "Settings Widget Constructor|Setters", meta = (BlueprintProtected, AutoCreateRefTerm = "SliderTag"))
+ UFUNCTION(BlueprintImplementableEvent, Category = "Settings Widget Constructor|Setters", meta = (BlueprintProtected, AutoCreateRefTerm = "SliderTag"))
void SetSlider(const FSettingTag& SliderTag, float InValue);
/** Internal blueprint function to set new text for an input box. */
- UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, Category = "Settings Widget Constructor|Setters", meta = (BlueprintProtected, AutoCreateRefTerm = "UserInputTag"))
+ UFUNCTION(BlueprintImplementableEvent, Category = "Settings Widget Constructor|Setters", meta = (BlueprintProtected, AutoCreateRefTerm = "UserInputTag"))
void SetUserInput(const FSettingTag& UserInputTag, FName InValue);
};
diff --git a/Source/SettingsWidgetConstructor/SettingsWidgetConstructor.Build.cs b/Source/SettingsWidgetConstructor/SettingsWidgetConstructor.Build.cs
index 76e54fa..4461a0a 100644
--- a/Source/SettingsWidgetConstructor/SettingsWidgetConstructor.Build.cs
+++ b/Source/SettingsWidgetConstructor/SettingsWidgetConstructor.Build.cs
@@ -8,7 +8,8 @@ public SettingsWidgetConstructor(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
CppStandard = CppStandardVersion.Latest;
-
+ bEnableNonInlinedGenCppWarnings = true;
+
PublicDependencyModuleNames.AddRange(new[]
{
"Core"
@@ -21,6 +22,7 @@ public SettingsWidgetConstructor(ReadOnlyTargetRules Target) : base(Target)
PrivateDependencyModuleNames.AddRange(new[]
{
"CoreUObject", "Engine", "Slate", "SlateCore" // Core
+ , "DataRegistry" // Multiple Data Tables support
}
);
diff --git a/Source/SettingsWidgetConstructorEditor/Private/FunctionPickerType/FunctionPickerCustomization.cpp b/Source/SettingsWidgetConstructorEditor/Private/FunctionPickerType/FunctionPickerCustomization.cpp
index 07c22a0..489a2f7 100644
--- a/Source/SettingsWidgetConstructorEditor/Private/FunctionPickerType/FunctionPickerCustomization.cpp
+++ b/Source/SettingsWidgetConstructorEditor/Private/FunctionPickerType/FunctionPickerCustomization.cpp
@@ -213,7 +213,7 @@ bool FFunctionPickerCustomization::IsSignatureCompatible(const UFunction* Functi
return true;
}
- if (!A || !B) //one of properties is null
+ if (!A || !B)
{
return false;
}
@@ -230,14 +230,18 @@ bool FFunctionPickerCustomization::IsSignatureCompatible(const UFunction* Functi
if (!A->SameType(B)) // A->GetClass() == B->GetClass()
{
- // That part is implemented: if is return param with the same flags
+ // --- That part is implemented: if is return param with the same flags
// Will return true for any derived UObject
- if (A->PropertyFlags & B->PropertyFlags & CPF_ReturnParm
- && A->IsA(B->GetClass()))
+
+ if (!(A->PropertyFlags & B->PropertyFlags & CPF_OutParm))
{
- return true;
+ return false;
+ }
+
+ if (!A->IsA() || !B->IsA())
+ {
+ return false;
}
- return false;
}
return true;
@@ -261,7 +265,12 @@ bool FFunctionPickerCustomization::IsSignatureCompatible(const UFunction* Functi
// Check the flags as well
const uint64 PropertyMash = PropA->PropertyFlags ^ PropB->PropertyFlags;
- if (!ArePropertiesTheSame(PropA, PropB) || ((PropertyMash & ~IgnoreFlags) != 0))
+ if ((PropertyMash & ~IgnoreFlags) != 0)
+ {
+ return false;
+ }
+
+ if (!ArePropertiesTheSame(PropA, PropB))
{
// Type mismatch between an argument of A and B
return false;
diff --git a/Source/SettingsWidgetConstructorEditor/Private/MyAssets/AssetTypeActions_MyDataTable.cpp b/Source/SettingsWidgetConstructorEditor/Private/MyAssets/AssetTypeActions_MyDataTable.cpp
index 4fef3ce..7e9bc83 100644
--- a/Source/SettingsWidgetConstructorEditor/Private/MyAssets/AssetTypeActions_MyDataTable.cpp
+++ b/Source/SettingsWidgetConstructorEditor/Private/MyAssets/AssetTypeActions_MyDataTable.cpp
@@ -103,17 +103,16 @@ void FAssetTypeActions_MyDataTable::OpenAssetEditor(const TArray& InOb
{
FTextBuilder DataTablesListText;
DataTablesListText.Indent();
- for (UDataTable* Table : InvalidDataTables)
+ for (const UDataTable* Table : InvalidDataTables)
{
const FTopLevelAssetPath ResolvedRowStructName = Table->GetRowStructPathName();
DataTablesListText.AppendLineFormat(LOCTEXT("DataTable_MissingRowStructListEntry", "* {0} (Row Structure: {1})"), FText::FromString(Table->GetName()), FText::FromString(ResolvedRowStructName.ToString()));
}
- FText Title = LOCTEXT("DataTable_MissingRowStructTitle", "Continue?");
const EAppReturnType::Type DlgResult = FMessageDialog::Open(
EAppMsgType::YesNoCancel,
FText::Format(LOCTEXT("DataTable_MissingRowStructMsg", "The following Data Tables are missing their row structure and will not be editable.\n\n{0}\n\nDo you want to open these data tables?"), DataTablesListText.ToText()),
- &Title
+ LOCTEXT("DataTable_MissingRowStructTitle", "Continue?")
);
switch (DlgResult)
diff --git a/Source/SettingsWidgetConstructorEditor/Public/SettingsPickerCustomization.h b/Source/SettingsWidgetConstructorEditor/Public/SettingsPickerCustomization.h
index 853b1dc..7f66181 100644
--- a/Source/SettingsWidgetConstructorEditor/Public/SettingsPickerCustomization.h
+++ b/Source/SettingsWidgetConstructorEditor/Public/SettingsPickerCustomization.h
@@ -65,7 +65,7 @@ class SETTINGSWIDGETCONSTRUCTOREDITOR_API FSettingsPickerCustomization : public
/** Contains property to by meta.
* MetaName: SettingsFunctionContextTemplate, SettingsFunctionSetterTemplate, SettingsFunctionGetterTemplate.
- * SettingsFunctionProperty: FSettingsPicker::StaticContext, FSettingsPicker::Setter, FSettingsPicker::Getter, */
+ * SettingsFunctionProperty: FSettingsPicker::Owner, FSettingsPicker::Setter, FSettingsPicker::Getter, */
TMap SettingsFunctionProperties;
/** Pointer to the FSettingsDataBase struct. */
diff --git a/Source/SettingsWidgetConstructorEditor/SettingsWidgetConstructorEditor.Build.cs b/Source/SettingsWidgetConstructorEditor/SettingsWidgetConstructorEditor.Build.cs
index 30076a4..6cee28e 100644
--- a/Source/SettingsWidgetConstructorEditor/SettingsWidgetConstructorEditor.Build.cs
+++ b/Source/SettingsWidgetConstructorEditor/SettingsWidgetConstructorEditor.Build.cs
@@ -8,7 +8,8 @@ public SettingsWidgetConstructorEditor(ReadOnlyTargetRules Target) : base(Target
{
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
CppStandard = CppStandardVersion.Latest;
-
+ bEnableNonInlinedGenCppWarnings = true;
+
PublicDependencyModuleNames.AddRange(new[]
{
"Core"