From ff666d8987666dcb41840f22c3ec8d358c47b76b Mon Sep 17 00:00:00 2001 From: HPsaucii Date: Sun, 13 Apr 2025 14:20:50 +0000 Subject: [PATCH 1/7] Add support for empty titles --- SettingsLib/.steam.props | 99 +++++++++++++++++++ .../Settings/UI/CollapsibleSettingUI.cs | 27 +++-- .../Settings/UI/DynamicSettingListUI.cs | 27 +++-- SettingsLib/SettingsLib.csproj | 37 ++----- 4 files changed, 144 insertions(+), 46 deletions(-) create mode 100644 SettingsLib/.steam.props diff --git a/SettingsLib/.steam.props b/SettingsLib/.steam.props new file mode 100644 index 0000000..962a933 --- /dev/null +++ b/SettingsLib/.steam.props @@ -0,0 +1,99 @@ + + + + + + <_SteamRegPath>HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Valve\Steam + $([MSBuild]::GetRegistryValueFromView('$(_SteamRegPath)', 'InstallPath', null, RegistryView.Registry32)) + + + + $([MSBuild]::NormalizePath('$(SteamInstallPathFromRegistry)', 'steamapps')) + + + + + $([MSBuild]::NormalizePath('C:', 'Program Files (x86)', 'Steam', 'steamapps')) + + + + $(HOME)/.steam/steam/steamapps + + + 1796470 + 3408901301 + 3462196533 + + false + false + + + + + $([System.Text.RegularExpressions.Regex]::Replace('$(SteamDir)', '^\s+|\s+$', '')) + $([MSBuild]::NormalizePath('$(CleanSteamDir)', 'libraryfolders.vdf')) + + + + + true + false + + + + + + + + + + + + + $([System.Text.RegularExpressions.Regex]::Match('$(LibraryFileContent)', '.*"path"\s+"([^"]+)".*"$(HasteAppId)"\s+').Groups[1].Value) + + + $(LibraryPathMatch) + $([System.Text.RegularExpressions.Regex]::Match('$(LibraryFileContent)', '.*"path"\s+"([^"]+)"').Groups[1].Value) + + + $([MSBuild]::NormalizePath('$(SteamLibraryPath)', 'steamapps', 'common', 'Haste')) + $([MSBuild]::NormalizePath('$(HasteDir)', 'Haste_Data', 'Managed')) + $([MSBuild]::NormalizePath('$(SteamLibraryPath)', 'steamapps', 'workshop', 'content', '$(HasteAppId)')) + $([MSBuild]::NormalizePath('$(WorkshopDir)', '$(HarmonyWorkshopId)', '0Harmony.dll')) + $([MSBuild]::NormalizePath('$(WorkshopDir)', '$(SettingsLibWorkshopId)', 'SettingsLib.dll')) + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/SettingsLib/Settings/UI/CollapsibleSettingUI.cs b/SettingsLib/Settings/UI/CollapsibleSettingUI.cs index dbbfefd..92a2b08 100644 --- a/SettingsLib/Settings/UI/CollapsibleSettingUI.cs +++ b/SettingsLib/Settings/UI/CollapsibleSettingUI.cs @@ -1,6 +1,7 @@ using TMPro; using UnityEngine; using UnityEngine.UI; +using UnityEngine.Localization; using Zorro.Core; using Zorro.Localization; using Zorro.Settings; @@ -119,18 +120,26 @@ private void AddSettingBlock(Setting setting, ISettingHandler settingHandler) { var block = UnityEngine.Object.Instantiate(settingObject, transform); - AddSettingTitle(setting, block.transform); - AddSetting(setting, block.transform, settingHandler); - } - - private void AddSettingTitle(Setting setting, Transform transform) - { + LocalizedString titleText = null!; if (setting is IExposedSetting exposedSetting) { - transform - .GetComponentInChildren() - ?.SetString(exposedSetting.GetDisplayName()); + titleText = exposedSetting.GetDisplayName(); } + + // Find the title child object (it's the first child based on SetUpSettingObject) + var titleChildTransform = block.transform.GetChild(0); + + // If the title is empty, destroy the title object. Otherwise, set its text. + if (titleText == null || titleText.IsEmpty) + { + UnityEngine.Object.Destroy(titleChildTransform.gameObject); + } + else + { + titleChildTransform.GetComponentInChildren()?.SetString(titleText); + } + + AddSetting(setting, block.transform, settingHandler); } private void AddSetting(Setting setting, Transform transform, ISettingHandler settingHandler) diff --git a/SettingsLib/Settings/UI/DynamicSettingListUI.cs b/SettingsLib/Settings/UI/DynamicSettingListUI.cs index fa9a03f..a75f0c3 100644 --- a/SettingsLib/Settings/UI/DynamicSettingListUI.cs +++ b/SettingsLib/Settings/UI/DynamicSettingListUI.cs @@ -1,6 +1,7 @@ using TMPro; using UnityEngine; using UnityEngine.UI; +using UnityEngine.Localization; using Zorro.Localization; using Zorro.Settings; @@ -113,18 +114,26 @@ private void AddSettingBlock(Setting setting, ISettingHandler settingHandler) { var block = UnityEngine.Object.Instantiate(settingObject, transform); - AddSettingTitle(setting, block.transform); - AddSetting(setting, block.transform, settingHandler); - } - - private void AddSettingTitle(Setting setting, Transform transform) - { + LocalizedString titleText = null!; if (setting is IExposedSetting exposedSetting) { - transform - .GetComponentInChildren() - ?.SetString(exposedSetting.GetDisplayName()); + titleText = exposedSetting.GetDisplayName(); + } + + // Find the title child object (it's the first child based on SetUpSettingObject) + var titleChildTransform = block.transform.GetChild(0); + + // If the title is empty, destroy the title object. Otherwise, set its text. + if (titleText == null || titleText.IsEmpty) + { + UnityEngine.Object.Destroy(titleChildTransform.gameObject); + } + else + { + titleChildTransform.GetComponentInChildren()?.SetString(titleText); } + + AddSetting(setting, block.transform, settingHandler); } private void AddSetting(Setting setting, Transform transform, ISettingHandler settingHandler) diff --git a/SettingsLib/SettingsLib.csproj b/SettingsLib/SettingsLib.csproj index df977db..a103288 100644 --- a/SettingsLib/SettingsLib.csproj +++ b/SettingsLib/SettingsLib.csproj @@ -1,29 +1,10 @@ - - - - netstandard2.1 - enable - enable - latest - C:\Program Files (x86)\Steam\steamapps\common\Haste\Haste_Data\Managed\*.dll - - - true - - false - - none - - true - - - - - - - - - + + + + + netstandard2.1 + enable + enable + latest + From b0333fc1c235d16b6a76f50e4b78ecbdbfdc50ac Mon Sep 17 00:00:00 2001 From: HPsaucii Date: Sun, 13 Apr 2025 15:05:16 +0000 Subject: [PATCH 2/7] Add support for advanced toggle logic --- SettingsLib/Settings/CollapsibleSetting.cs | 5 +++++ SettingsLib/Settings/UI/CollapsibleSettingUI.cs | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/SettingsLib/Settings/CollapsibleSetting.cs b/SettingsLib/Settings/CollapsibleSetting.cs index 449bc96..85a5833 100644 --- a/SettingsLib/Settings/CollapsibleSetting.cs +++ b/SettingsLib/Settings/CollapsibleSetting.cs @@ -23,6 +23,11 @@ public virtual List GetSettings() return settings; } + public virtual bool OnToggled() + { + return false; + } + public override void ApplyValue() { foreach (Setting setting in GetSettings()) diff --git a/SettingsLib/Settings/UI/CollapsibleSettingUI.cs b/SettingsLib/Settings/UI/CollapsibleSettingUI.cs index 92a2b08..ce1fa99 100644 --- a/SettingsLib/Settings/UI/CollapsibleSettingUI.cs +++ b/SettingsLib/Settings/UI/CollapsibleSettingUI.cs @@ -12,6 +12,7 @@ public class CollapsibleSettingUI : SettingInputUICell { // Track expanded state private bool _expanded = false; + private CollapsibleSetting? _collapsibleSetting; private GameObject titleObject = new GameObject("SettingTitle"); private GameObject settingObject = new GameObject("SettingCell"); private string collapseButtonText @@ -30,6 +31,8 @@ public override void Setup(Setting setting, ISettingHandler settingHandler) { if (setting is CollapsibleSetting group) { + _collapsibleSetting = group; + ApplyEnclosingStyling(); AddCollapseButton(); @@ -61,6 +64,8 @@ private void AddCollapseButton() private void OnToggled() { + if (_collapsibleSetting != null && _collapsibleSetting.OnToggled()) + return; _expanded = !_expanded; SetVisibility(); } From e52aec3ef4b4b7aee40730ee79a0a66bb0e4a37c Mon Sep 17 00:00:00 2001 From: HPsaucii Date: Sun, 13 Apr 2025 15:22:21 +0000 Subject: [PATCH 3/7] Revert install detection --- SettingsLib/.steam.props | 99 ---------------------------------- SettingsLib/SettingsLib.csproj | 37 +++++++++---- 2 files changed, 28 insertions(+), 108 deletions(-) delete mode 100644 SettingsLib/.steam.props diff --git a/SettingsLib/.steam.props b/SettingsLib/.steam.props deleted file mode 100644 index 962a933..0000000 --- a/SettingsLib/.steam.props +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - <_SteamRegPath>HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Valve\Steam - $([MSBuild]::GetRegistryValueFromView('$(_SteamRegPath)', 'InstallPath', null, RegistryView.Registry32)) - - - - $([MSBuild]::NormalizePath('$(SteamInstallPathFromRegistry)', 'steamapps')) - - - - - $([MSBuild]::NormalizePath('C:', 'Program Files (x86)', 'Steam', 'steamapps')) - - - - $(HOME)/.steam/steam/steamapps - - - 1796470 - 3408901301 - 3462196533 - - false - false - - - - - $([System.Text.RegularExpressions.Regex]::Replace('$(SteamDir)', '^\s+|\s+$', '')) - $([MSBuild]::NormalizePath('$(CleanSteamDir)', 'libraryfolders.vdf')) - - - - - true - false - - - - - - - - - - - - - $([System.Text.RegularExpressions.Regex]::Match('$(LibraryFileContent)', '.*"path"\s+"([^"]+)".*"$(HasteAppId)"\s+').Groups[1].Value) - - - $(LibraryPathMatch) - $([System.Text.RegularExpressions.Regex]::Match('$(LibraryFileContent)', '.*"path"\s+"([^"]+)"').Groups[1].Value) - - - $([MSBuild]::NormalizePath('$(SteamLibraryPath)', 'steamapps', 'common', 'Haste')) - $([MSBuild]::NormalizePath('$(HasteDir)', 'Haste_Data', 'Managed')) - $([MSBuild]::NormalizePath('$(SteamLibraryPath)', 'steamapps', 'workshop', 'content', '$(HasteAppId)')) - $([MSBuild]::NormalizePath('$(WorkshopDir)', '$(HarmonyWorkshopId)', '0Harmony.dll')) - $([MSBuild]::NormalizePath('$(WorkshopDir)', '$(SettingsLibWorkshopId)', 'SettingsLib.dll')) - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/SettingsLib/SettingsLib.csproj b/SettingsLib/SettingsLib.csproj index a103288..df977db 100644 --- a/SettingsLib/SettingsLib.csproj +++ b/SettingsLib/SettingsLib.csproj @@ -1,10 +1,29 @@ - - - - - netstandard2.1 - enable - enable - latest - + + + + netstandard2.1 + enable + enable + latest + C:\Program Files (x86)\Steam\steamapps\common\Haste\Haste_Data\Managed\*.dll + + + true + + false + + none + + true + + + + + + + + + From 132feb6eb550a1483403005d940be23de4a2206e Mon Sep 17 00:00:00 2001 From: HPsaucii Date: Mon, 14 Apr 2025 08:26:32 +0000 Subject: [PATCH 4/7] Fix formatting --- SettingsLib/Settings/CollapsibleSetting.cs | 8 ++++---- SettingsLib/Settings/UI/CollapsibleSettingUI.cs | 10 +++++----- SettingsLib/Settings/UI/DynamicSettingListUI.cs | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/SettingsLib/Settings/CollapsibleSetting.cs b/SettingsLib/Settings/CollapsibleSetting.cs index 85a5833..fc45f10 100644 --- a/SettingsLib/Settings/CollapsibleSetting.cs +++ b/SettingsLib/Settings/CollapsibleSetting.cs @@ -23,10 +23,10 @@ public virtual List GetSettings() return settings; } - public virtual bool OnToggled() - { - return false; - } + public virtual bool OnToggled() + { + return false; + } public override void ApplyValue() { diff --git a/SettingsLib/Settings/UI/CollapsibleSettingUI.cs b/SettingsLib/Settings/UI/CollapsibleSettingUI.cs index ce1fa99..4189539 100644 --- a/SettingsLib/Settings/UI/CollapsibleSettingUI.cs +++ b/SettingsLib/Settings/UI/CollapsibleSettingUI.cs @@ -1,7 +1,7 @@ using TMPro; using UnityEngine; -using UnityEngine.UI; using UnityEngine.Localization; +using UnityEngine.UI; using Zorro.Core; using Zorro.Localization; using Zorro.Settings; @@ -12,7 +12,7 @@ public class CollapsibleSettingUI : SettingInputUICell { // Track expanded state private bool _expanded = false; - private CollapsibleSetting? _collapsibleSetting; + private CollapsibleSetting? _collapsibleSetting; private GameObject titleObject = new GameObject("SettingTitle"); private GameObject settingObject = new GameObject("SettingCell"); private string collapseButtonText @@ -31,7 +31,7 @@ public override void Setup(Setting setting, ISettingHandler settingHandler) { if (setting is CollapsibleSetting group) { - _collapsibleSetting = group; + _collapsibleSetting = group; ApplyEnclosingStyling(); AddCollapseButton(); @@ -64,8 +64,8 @@ private void AddCollapseButton() private void OnToggled() { - if (_collapsibleSetting != null && _collapsibleSetting.OnToggled()) - return; + if (_collapsibleSetting != null && _collapsibleSetting.OnToggled()) + return; _expanded = !_expanded; SetVisibility(); } diff --git a/SettingsLib/Settings/UI/DynamicSettingListUI.cs b/SettingsLib/Settings/UI/DynamicSettingListUI.cs index a75f0c3..d7c49ef 100644 --- a/SettingsLib/Settings/UI/DynamicSettingListUI.cs +++ b/SettingsLib/Settings/UI/DynamicSettingListUI.cs @@ -1,7 +1,7 @@ using TMPro; using UnityEngine; -using UnityEngine.UI; using UnityEngine.Localization; +using UnityEngine.UI; using Zorro.Localization; using Zorro.Settings; From cf23dac5fbd04062add4f9c0bab901e22c3f3a71 Mon Sep 17 00:00:00 2001 From: HPsaucii Date: Mon, 14 Apr 2025 08:53:21 +0000 Subject: [PATCH 5/7] Refactor optional titles --- .../Settings/UI/CollapsibleSettingUI.cs | 314 +++++++++--------- .../Settings/UI/DynamicSettingListUI.cs | 283 ++++++++-------- 2 files changed, 299 insertions(+), 298 deletions(-) diff --git a/SettingsLib/Settings/UI/CollapsibleSettingUI.cs b/SettingsLib/Settings/UI/CollapsibleSettingUI.cs index 4189539..d84eef5 100644 --- a/SettingsLib/Settings/UI/CollapsibleSettingUI.cs +++ b/SettingsLib/Settings/UI/CollapsibleSettingUI.cs @@ -6,194 +6,200 @@ using Zorro.Localization; using Zorro.Settings; -namespace SettingsLib.Settings.UI; - -public class CollapsibleSettingUI : SettingInputUICell +namespace SettingsLib.Settings.UI { - // Track expanded state - private bool _expanded = false; - private CollapsibleSetting? _collapsibleSetting; - private GameObject titleObject = new GameObject("SettingTitle"); - private GameObject settingObject = new GameObject("SettingCell"); - private string collapseButtonText + public class CollapsibleSettingUI : SettingInputUICell { - get => _expanded ? "▼ Collapse" : "► Expand"; - } + // Track expanded state + private bool _expanded = false; + private CollapsibleSetting? _collapsibleSetting; - public CollapsibleSettingUI() - : base() - { - SetUpTitleObject(); - SetUpSettingObject(); - } + // We no longer have a persistent titleObject; we create title objects on demand. + private GameObject settingObject = new GameObject("SettingCell"); + private string collapseButtonText => _expanded ? "▼ Collapse" : "► Expand"; - public override void Setup(Setting setting, ISettingHandler settingHandler) - { - if (setting is CollapsibleSetting group) + public CollapsibleSettingUI() + : base() { - _collapsibleSetting = group; - - ApplyEnclosingStyling(); - AddCollapseButton(); - - // Run setup for all settings, except non-shown conditionals - foreach (var subsetting in group.GetSettings()) - if (!(subsetting is IConditionalSetting conditional) || conditional.CanShow()) - AddSettingBlock(subsetting, settingHandler); - - SetVisibility(); + // Removed SetUpTitleObject call – title objects are now created as needed. + SetUpSettingObject(); } - } - private void AddCollapseButton() - { - var ui = UnityEngine.Object.Instantiate( - SingletonAsset.Instance.ButtonSettingCell, - transform - ); - ui.AddComponent().preferredHeight = 55; - var buttonUI = ui.GetComponent(); - buttonUI.Label.text = collapseButtonText; - buttonUI.Button.onClick.AddListener(() => + public override void Setup(Setting setting, ISettingHandler settingHandler) { - OnToggled(); - buttonUI.Label.text = collapseButtonText; - }); - ui.AddComponent().verticalFit = ContentSizeFitter.FitMode.PreferredSize; - } - - private void OnToggled() - { - if (_collapsibleSetting != null && _collapsibleSetting.OnToggled()) - return; - _expanded = !_expanded; - SetVisibility(); - } + if (setting is CollapsibleSetting group) + { + _collapsibleSetting = group; + + ApplyEnclosingStyling(); + AddCollapseButton(); + + // Run setup for all settings, except non-shown conditionals. + foreach (var subsetting in group.GetSettings()) + { + if (!(subsetting is IConditionalSetting conditional) || conditional.CanShow()) + { + AddSettingBlock(subsetting, settingHandler); + } + } + SetVisibility(); + } + } - private void SetVisibility() - { - // Skip the first child, as it is the collapse button. - for (var i = 1; i < transform.childCount; i++) + private void AddCollapseButton() { - var child = transform.GetChild(i); - child.gameObject.SetActive(_expanded); + var ui = UnityEngine.Object.Instantiate( + SingletonAsset.Instance.ButtonSettingCell, + transform + ); + ui.AddComponent().preferredHeight = 55; + var buttonUI = ui.GetComponent(); + buttonUI.Label.text = collapseButtonText; + buttonUI.Button.onClick.AddListener(() => + { + OnToggled(); + buttonUI.Label.text = collapseButtonText; + }); + ui.AddComponent().verticalFit = ContentSizeFitter + .FitMode + .PreferredSize; } - // Trigger all ContentSizeFitters - gameObject.SendMessageUpwards("SetLayoutHorizontal"); - gameObject.SendMessageUpwards("SetLayoutVertical"); - } - private void ApplyEnclosingStyling() - { - // Only run for a top-level CollapsibleSettingUICell - if (!transform.parent.parent.gameObject.TryGetComponent(out var comp)) + private void OnToggled() { - return; + if (_collapsibleSetting != null && _collapsibleSetting.OnToggled()) + return; + _expanded = !_expanded; + SetVisibility(); } - // Make the top level setting box's background and text ignore the Layout - int idx = transform.parent.GetSiblingIndex(); - for (int i = 0; i < transform.parent.parent.childCount; i++) + private void SetVisibility() { - if (i == idx) - continue; - var child = transform.parent.parent.GetChild(i); - child.gameObject.AddComponent().ignoreLayout = true; + // Skip the first child (collapse button) when toggling visibility. + for (var i = 1; i < transform.childCount; i++) + { + var child = transform.GetChild(i); + child.gameObject.SetActive(_expanded); + } + // Trigger a layout update. + gameObject.SendMessageUpwards("SetLayoutHorizontal"); + gameObject.SendMessageUpwards("SetLayoutVertical"); } - // Breaks without this - transform.parent.gameObject.AddComponent(); - - MakeSettingBoxAdaptable(); - } + private void ApplyEnclosingStyling() + { + // Only run for a top-level CollapsibleSettingUICell. + if (!transform.parent.parent.gameObject.TryGetComponent(out var comp)) + { + return; + } - private void MakeSettingBoxAdaptable() - { - // Make the setting box as tall as necessary - var vlg = transform.parent.parent.gameObject.AddComponent(); - vlg.childControlWidth = false; - vlg.spacing = 10; - vlg.childAlignment = TextAnchor.MiddleRight; - // Give the bounding box some breathing room - vlg.padding.top = 15; - vlg.padding.bottom = 15; - transform.parent.parent.gameObject.AddComponent().verticalFit = - ContentSizeFitter.FitMode.PreferredSize; - } + // Make the top-level setting box's background and text ignore the layout. + int idx = transform.parent.GetSiblingIndex(); + for (int i = 0; i < transform.parent.parent.childCount; i++) + { + if (i == idx) + continue; + var child = transform.parent.parent.GetChild(i); + child.gameObject.AddComponent().ignoreLayout = true; + } - private void AddSettingBlock(Setting setting, ISettingHandler settingHandler) - { - var block = UnityEngine.Object.Instantiate(settingObject, transform); + // This is needed to force a layout. + transform.parent.gameObject.AddComponent(); - LocalizedString titleText = null!; - if (setting is IExposedSetting exposedSetting) - { - titleText = exposedSetting.GetDisplayName(); + MakeSettingBoxAdaptable(); } - // Find the title child object (it's the first child based on SetUpSettingObject) - var titleChildTransform = block.transform.GetChild(0); - - // If the title is empty, destroy the title object. Otherwise, set its text. - if (titleText == null || titleText.IsEmpty) + private void MakeSettingBoxAdaptable() { - UnityEngine.Object.Destroy(titleChildTransform.gameObject); + // Make the setting box as tall as necessary. + var vlg = transform.parent.parent.gameObject.AddComponent(); + vlg.childControlWidth = false; + vlg.spacing = 10; + vlg.childAlignment = TextAnchor.MiddleRight; + // Give the bounding box some breathing room. + vlg.padding.top = 15; + vlg.padding.bottom = 15; + transform.parent.parent.gameObject.AddComponent().verticalFit = + ContentSizeFitter.FitMode.PreferredSize; } - else + + /// + /// Adds a new setting block. If a title exists, it is added here. + /// + private void AddSettingBlock(Setting setting, ISettingHandler settingHandler) { - titleChildTransform.GetComponentInChildren()?.SetString(titleText); - } + var block = UnityEngine.Object.Instantiate(settingObject, transform); - AddSetting(setting, block.transform, settingHandler); - } + // Check if the setting has a title. + LocalizedString? titleText = null; + if (setting is IExposedSetting exposedSetting) + { + titleText = exposedSetting.GetDisplayName(); + } - private void AddSetting(Setting setting, Transform transform, ISettingHandler settingHandler) - { - var ui = UnityEngine.Object.Instantiate(setting.GetSettingUICell(), transform); + // Only add a title if it is non-null and non-empty. + if (titleText != null && !titleText.IsEmpty) + { + AddSettingTitle(titleText, block.transform); + } - // Give the field a height so it doesn't get destroyed by the layout - var layoutElement = ui.GetComponent(); - if (layoutElement is null) - { - layoutElement = ui.AddComponent(); + AddSetting(setting, block.transform, settingHandler); } - if (layoutElement.preferredHeight == -1 && layoutElement is LayoutElement elem) + + /// + /// Instantiates a title object and attaches it to the given parent. + /// + private void AddSettingTitle(LocalizedString titleText, Transform parentTransform) { - elem.preferredHeight = setting switch - { - ButtonSetting set => 55, - _ => 35, - }; + var titleObj = new GameObject("SettingTitle"); + titleObj.transform.SetParent(parentTransform, false); + var textMesh = titleObj.AddComponent(); + textMesh.enableAutoSizing = true; + textMesh.alignment = TextAlignmentOptions.Center; + var localizeUIText = titleObj.AddComponent(); + localizeUIText.SetString(titleText); + var layout = titleObj.AddComponent(); + layout.preferredHeight = 20; } - ui.GetComponent().Setup(setting, settingHandler); - } - - private void SetUpTitleObject() - { - var textMesh = titleObject.AddComponent(); - textMesh.enableAutoSizing = true; - textMesh.alignment = TextAlignmentOptions.Center; - var text = titleObject.AddComponent(); - text.String = null; - var layout = titleObject.AddComponent(); - layout.preferredHeight = 20; - - UnityEngine.Object.DontDestroyOnLoad(titleObject); - } - - private void SetUpSettingObject() - { - titleObject.transform.SetParent(settingObject.transform, false); + private void AddSetting( + Setting setting, + Transform transform, + ISettingHandler settingHandler + ) + { + var ui = UnityEngine.Object.Instantiate(setting.GetSettingUICell(), transform); - var layout = settingObject.AddComponent(); - // Little breathing room - layout.spacing = 2; - layout.padding.top = 13; - settingObject.AddComponent().verticalFit = ContentSizeFitter - .FitMode - .PreferredSize; + // Ensure the element retains a preferred height so it isn’t collapsed by the layout. + var layoutElement = ui.GetComponent(); + if (layoutElement is null) + { + layoutElement = ui.AddComponent(); + } + if (layoutElement.preferredHeight == -1 && layoutElement is LayoutElement elem) + { + elem.preferredHeight = setting switch + { + ButtonSetting set => 55, + _ => 35, + }; + } + + ui.GetComponent().Setup(setting, settingHandler); + } - UnityEngine.Object.DontDestroyOnLoad(settingObject); + private void SetUpSettingObject() + { + var layout = settingObject.AddComponent(); + // Add a little breathing room. + layout.spacing = 2; + layout.padding.top = 13; + settingObject.AddComponent().verticalFit = ContentSizeFitter + .FitMode + .PreferredSize; + + UnityEngine.Object.DontDestroyOnLoad(settingObject); + } } } diff --git a/SettingsLib/Settings/UI/DynamicSettingListUI.cs b/SettingsLib/Settings/UI/DynamicSettingListUI.cs index d7c49ef..ea75126 100644 --- a/SettingsLib/Settings/UI/DynamicSettingListUI.cs +++ b/SettingsLib/Settings/UI/DynamicSettingListUI.cs @@ -5,184 +5,179 @@ using Zorro.Localization; using Zorro.Settings; -namespace SettingsLib.Settings.UI; - -public class DynamicSettingListUI : SettingInputUICell +namespace SettingsLib.Settings.UI { - // Track expanded state - private bool _expanded = false; - private GameObject titleObject = new GameObject("SettingTitle"); - private GameObject settingObject = new GameObject("SettingCell"); - private DynamicSettingList? _setting; - private ISettingHandler _settingHandler = GameHandler.Instance.SettingsHandler; - private string collapseButtonText - { - get => _expanded ? "▼ Collapse" : "► Expand"; - } - - public DynamicSettingListUI() - : base() - { - SetUpTitleObject(); - SetUpSettingObject(); - } - - public override void Setup(Setting setting, ISettingHandler settingHandler) + public class DynamicSettingListUI : SettingInputUICell { - if (setting is DynamicSettingList dynamicSetting) + // Track expanded state + private bool _expanded = false; + private GameObject settingObject = new GameObject("SettingCell"); + private DynamicSettingList? _setting; + private ISettingHandler _settingHandler = GameHandler.Instance.SettingsHandler; + private string collapseButtonText { + _expanded ? "▼ Collapse" : "► Expand"; + } + + public DynamicSettingListUI() + : base() { - ApplyEnclosingStyling(); - - _setting = dynamicSetting; - _setting.SetUIElement(this); - _settingHandler = settingHandler; - AddChildren(); + // No longer pre-create a title object. + SetUpSettingObject(); } - } - public void RefreshList() - { - RemoveChildren(); - AddChildren(); - - // Trigger all ContentSizeFitters - LayoutRebuilder.ForceRebuildLayoutImmediate(GetComponent()); + public override void Setup(Setting setting, ISettingHandler settingHandler) + { + if (setting is DynamicSettingList dynamicSetting) + { + ApplyEnclosingStyling(); - gameObject.SendMessageUpwards("SetLayoutHorizontal"); - gameObject.SendMessageUpwards("SetLayoutVertical"); - } + _setting = dynamicSetting; + _setting.SetUIElement(this); + _settingHandler = settingHandler; + AddChildren(); + } + } - private void RemoveChildren() - { - for (var i = 0; i < transform.childCount; i++) + public void RefreshList() { - var child = transform.GetChild(i); - UnityEngine.Object.Destroy(child.gameObject); - } - } + RemoveChildren(); + AddChildren(); - private void AddChildren() - { - if (_setting == null) - return; + // Trigger all ContentSizeFitters + LayoutRebuilder.ForceRebuildLayoutImmediate(GetComponent()); - // Run setup for all settings, except non-shown conditionals - foreach (var subsetting in _setting.GetSettings()) - if (!(subsetting is IConditionalSetting conditional) || conditional.CanShow()) - AddSettingBlock(subsetting, _settingHandler); - } + gameObject.SendMessageUpwards("SetLayoutHorizontal"); + gameObject.SendMessageUpwards("SetLayoutVertical"); + } - private void ApplyEnclosingStyling() - { - // Only run for a top-level DynamicSettingListUICell - if (!transform.parent.parent.gameObject.TryGetComponent(out var comp)) + private void RemoveChildren() { - return; + for (var i = 0; i < transform.childCount; i++) + { + var child = transform.GetChild(i); + UnityEngine.Object.Destroy(child.gameObject); + } } - // Make the top level setting box's background and text ignore the Layout - int idx = transform.parent.GetSiblingIndex(); - for (int i = 0; i < transform.parent.parent.childCount; i++) + private void AddChildren() { - if (i == idx) - continue; - var child = transform.parent.parent.GetChild(i); - child.gameObject.AddComponent().ignoreLayout = true; + if (_setting == null) + return; + + // Run setup for all settings, except non-shown conditionals. + foreach (var subsetting in _setting.GetSettings()) + { + if (!(subsetting is IConditionalSetting conditional) || conditional.CanShow()) + AddSettingBlock(subsetting, _settingHandler); + } } - // Breaks without this - transform.parent.gameObject.AddComponent(); + private void ApplyEnclosingStyling() + { + // Only run for a top-level DynamicSettingListUI. + if (!transform.parent.parent.gameObject.TryGetComponent(out var comp)) + { + return; + } - MakeSettingBoxAdaptable(); - } + // Make the top level setting box's background and text ignore the layout. + int idx = transform.parent.GetSiblingIndex(); + for (int i = 0; i < transform.parent.parent.childCount; i++) + { + if (i == idx) + continue; + var child = transform.parent.parent.GetChild(i); + child.gameObject.AddComponent().ignoreLayout = true; + } - private void MakeSettingBoxAdaptable() - { - // Make the setting box as tall as necessary - var vlg = transform.parent.parent.gameObject.AddComponent(); - vlg.childControlWidth = false; - vlg.spacing = 10; - vlg.childAlignment = TextAnchor.MiddleRight; - // Give the bounding box some breathing room - vlg.padding.top = 15; - vlg.padding.bottom = 15; - transform.parent.parent.gameObject.AddComponent().verticalFit = - ContentSizeFitter.FitMode.PreferredSize; - } + // This is required to force the layout. + transform.parent.gameObject.AddComponent(); - private void AddSettingBlock(Setting setting, ISettingHandler settingHandler) - { - var block = UnityEngine.Object.Instantiate(settingObject, transform); + MakeSettingBoxAdaptable(); + } - LocalizedString titleText = null!; - if (setting is IExposedSetting exposedSetting) + private void MakeSettingBoxAdaptable() { - titleText = exposedSetting.GetDisplayName(); + // Make the setting box as tall as necessary. + var vlg = transform.parent.parent.gameObject.AddComponent(); + vlg.childControlWidth = false; + vlg.spacing = 10; + vlg.childAlignment = TextAnchor.MiddleRight; + // Give the bounding box some breathing room. + vlg.padding.top = 15; + vlg.padding.bottom = 15; + transform.parent.parent.gameObject.AddComponent().verticalFit = + ContentSizeFitter.FitMode.PreferredSize; } - // Find the title child object (it's the first child based on SetUpSettingObject) - var titleChildTransform = block.transform.GetChild(0); - - // If the title is empty, destroy the title object. Otherwise, set its text. - if (titleText == null || titleText.IsEmpty) + private void AddSettingBlock(Setting setting, ISettingHandler settingHandler) { - UnityEngine.Object.Destroy(titleChildTransform.gameObject); + // Instantiate a new container using settingObject as template. + var block = UnityEngine.Object.Instantiate(settingObject, transform); + + // Check if the setting defines a title. + if (setting is IExposedSetting exposedSetting) + { + LocalizedString titleText = exposedSetting.GetDisplayName(); + if (titleText != null && !titleText.IsEmpty) + { + AddSettingTitle(titleText, block.transform); + } + } + + AddSetting(setting, block.transform, settingHandler); } - else + + private void AddSettingTitle(LocalizedString titleText, Transform parentTransform) { - titleChildTransform.GetComponentInChildren()?.SetString(titleText); - } + var titleObj = new GameObject("SettingTitle"); + titleObj.transform.SetParent(parentTransform, false); - AddSetting(setting, block.transform, settingHandler); - } + var textMesh = titleObj.AddComponent(); + textMesh.enableAutoSizing = true; + textMesh.alignment = TextAlignmentOptions.Center; - private void AddSetting(Setting setting, Transform transform, ISettingHandler settingHandler) - { - var ui = UnityEngine.Object.Instantiate(setting.GetSettingUICell(), transform); + var localizeUIText = titleObj.AddComponent(); + localizeUIText.SetString(titleText); - // Give the field a height so it doesn't get destroyed by the layout - var layoutElement = ui.GetComponent(); - if (layoutElement is null) - { - layoutElement = ui.AddComponent(); + var layout = titleObj.AddComponent(); + layout.preferredHeight = 20; } - if (layoutElement.preferredHeight == -1 && layoutElement is LayoutElement elem) + + private void AddSetting(Setting setting, Transform parent, ISettingHandler settingHandler) { - elem.preferredHeight = setting switch + var ui = UnityEngine.Object.Instantiate(setting.GetSettingUICell(), parent); + + // Ensure the element gets a preferred height so it isn’t collapsed by the + // layout. + var layoutElement = ui.GetComponent(); + if (layoutElement is null) + { + layoutElement = ui.AddComponent(); + } + if (layoutElement.preferredHeight == -1 && layoutElement is LayoutElement elem) { - ButtonSetting set => 55, - _ => 35, - }; + elem.preferredHeight = setting switch + { + ButtonSetting set => 55, + _ => 35, + }; + } + + ui.GetComponent().Setup(setting, settingHandler); } - ui.GetComponent().Setup(setting, settingHandler); - } - - private void SetUpTitleObject() - { - var textMesh = titleObject.AddComponent(); - textMesh.enableAutoSizing = true; - textMesh.alignment = TextAlignmentOptions.Center; - var text = titleObject.AddComponent(); - text.String = null; - var layout = titleObject.AddComponent(); - layout.preferredHeight = 20; - - UnityEngine.Object.DontDestroyOnLoad(titleObject); - } - - private void SetUpSettingObject() - { - titleObject.transform.SetParent(settingObject.transform, false); - - var layout = settingObject.AddComponent(); - // Little breathing room - layout.spacing = 2; - layout.padding.top = 13; - settingObject.AddComponent().verticalFit = ContentSizeFitter - .FitMode - .PreferredSize; - - UnityEngine.Object.DontDestroyOnLoad(settingObject); + private void SetUpSettingObject() + { + var layout = settingObject.AddComponent(); + // Little breathing room. + layout.spacing = 2; + layout.padding.top = 13; + settingObject.AddComponent().verticalFit = ContentSizeFitter + .FitMode + .PreferredSize; + + UnityEngine.Object.DontDestroyOnLoad(settingObject); + } } } From 3b999182ca24b48d2474d5d44a056261784a6655 Mon Sep 17 00:00:00 2001 From: HPsaucii Date: Mon, 14 Apr 2025 09:10:11 +0000 Subject: [PATCH 6/7] Refactor advanced toggling --- SettingsLib/Settings/CollapsibleSetting.cs | 5 +---- SettingsLib/Settings/UI/CollapsibleSettingUI.cs | 3 +-- SettingsLib/Settings/UI/DynamicSettingListUI.cs | 5 +---- 3 files changed, 3 insertions(+), 10 deletions(-) diff --git a/SettingsLib/Settings/CollapsibleSetting.cs b/SettingsLib/Settings/CollapsibleSetting.cs index fc45f10..b37b6a9 100644 --- a/SettingsLib/Settings/CollapsibleSetting.cs +++ b/SettingsLib/Settings/CollapsibleSetting.cs @@ -23,10 +23,7 @@ public virtual List GetSettings() return settings; } - public virtual bool OnToggled() - { - return false; - } + public virtual void OnToggled(bool IsExpanded) { } public override void ApplyValue() { diff --git a/SettingsLib/Settings/UI/CollapsibleSettingUI.cs b/SettingsLib/Settings/UI/CollapsibleSettingUI.cs index d84eef5..084e07f 100644 --- a/SettingsLib/Settings/UI/CollapsibleSettingUI.cs +++ b/SettingsLib/Settings/UI/CollapsibleSettingUI.cs @@ -67,10 +67,9 @@ private void AddCollapseButton() private void OnToggled() { - if (_collapsibleSetting != null && _collapsibleSetting.OnToggled()) - return; _expanded = !_expanded; SetVisibility(); + _collapsibleSetting?.OnToggled(_expanded); } private void SetVisibility() diff --git a/SettingsLib/Settings/UI/DynamicSettingListUI.cs b/SettingsLib/Settings/UI/DynamicSettingListUI.cs index ea75126..bd3a53b 100644 --- a/SettingsLib/Settings/UI/DynamicSettingListUI.cs +++ b/SettingsLib/Settings/UI/DynamicSettingListUI.cs @@ -14,14 +14,11 @@ public class DynamicSettingListUI : SettingInputUICell private GameObject settingObject = new GameObject("SettingCell"); private DynamicSettingList? _setting; private ISettingHandler _settingHandler = GameHandler.Instance.SettingsHandler; - private string collapseButtonText { - _expanded ? "▼ Collapse" : "► Expand"; - } + private string collapseButtonText => _expanded ? "▼ Collapse" : "► Expand"; public DynamicSettingListUI() : base() { - // No longer pre-create a title object. SetUpSettingObject(); } From 95f0345b11871b91596f913235d4f9adccbe8b8f Mon Sep 17 00:00:00 2001 From: HPsaucii Date: Mon, 14 Apr 2025 09:53:08 +0000 Subject: [PATCH 7/7] Revert block-scoped namespaces --- .../Settings/UI/CollapsibleSettingUI.cs | 301 +++++++++--------- .../Settings/UI/DynamicSettingListUI.cs | 267 ++++++++-------- 2 files changed, 280 insertions(+), 288 deletions(-) diff --git a/SettingsLib/Settings/UI/CollapsibleSettingUI.cs b/SettingsLib/Settings/UI/CollapsibleSettingUI.cs index 084e07f..727aede 100644 --- a/SettingsLib/Settings/UI/CollapsibleSettingUI.cs +++ b/SettingsLib/Settings/UI/CollapsibleSettingUI.cs @@ -6,199 +6,192 @@ using Zorro.Localization; using Zorro.Settings; -namespace SettingsLib.Settings.UI +namespace SettingsLib.Settings.UI; + +public class CollapsibleSettingUI : SettingInputUICell { - public class CollapsibleSettingUI : SettingInputUICell - { - // Track expanded state - private bool _expanded = false; - private CollapsibleSetting? _collapsibleSetting; + // Track expanded state + private bool _expanded = false; + private CollapsibleSetting? _collapsibleSetting; - // We no longer have a persistent titleObject; we create title objects on demand. - private GameObject settingObject = new GameObject("SettingCell"); - private string collapseButtonText => _expanded ? "▼ Collapse" : "► Expand"; + // We no longer have a persistent titleObject; we create title objects on demand. + private GameObject settingObject = new GameObject("SettingCell"); + private string collapseButtonText => _expanded ? "▼ Collapse" : "► Expand"; - public CollapsibleSettingUI() - : base() - { - // Removed SetUpTitleObject call – title objects are now created as needed. - SetUpSettingObject(); - } + public CollapsibleSettingUI() + : base() + { + // Removed SetUpTitleObject call – title objects are now created as needed. + SetUpSettingObject(); + } - public override void Setup(Setting setting, ISettingHandler settingHandler) + public override void Setup(Setting setting, ISettingHandler settingHandler) + { + if (setting is CollapsibleSetting group) { - if (setting is CollapsibleSetting group) - { - _collapsibleSetting = group; + _collapsibleSetting = group; - ApplyEnclosingStyling(); - AddCollapseButton(); + ApplyEnclosingStyling(); + AddCollapseButton(); - // Run setup for all settings, except non-shown conditionals. - foreach (var subsetting in group.GetSettings()) + // Run setup for all settings, except non-shown conditionals. + foreach (var subsetting in group.GetSettings()) + { + if (!(subsetting is IConditionalSetting conditional) || conditional.CanShow()) { - if (!(subsetting is IConditionalSetting conditional) || conditional.CanShow()) - { - AddSettingBlock(subsetting, settingHandler); - } + AddSettingBlock(subsetting, settingHandler); } - SetVisibility(); } + SetVisibility(); } + } - private void AddCollapseButton() + private void AddCollapseButton() + { + var ui = UnityEngine.Object.Instantiate( + SingletonAsset.Instance.ButtonSettingCell, + transform + ); + ui.AddComponent().preferredHeight = 55; + var buttonUI = ui.GetComponent(); + buttonUI.Label.text = collapseButtonText; + buttonUI.Button.onClick.AddListener(() => { - var ui = UnityEngine.Object.Instantiate( - SingletonAsset.Instance.ButtonSettingCell, - transform - ); - ui.AddComponent().preferredHeight = 55; - var buttonUI = ui.GetComponent(); + OnToggled(); buttonUI.Label.text = collapseButtonText; - buttonUI.Button.onClick.AddListener(() => - { - OnToggled(); - buttonUI.Label.text = collapseButtonText; - }); - ui.AddComponent().verticalFit = ContentSizeFitter - .FitMode - .PreferredSize; - } + }); + ui.AddComponent().verticalFit = ContentSizeFitter.FitMode.PreferredSize; + } - private void OnToggled() + private void OnToggled() + { + _expanded = !_expanded; + SetVisibility(); + _collapsibleSetting?.OnToggled(_expanded); + } + + private void SetVisibility() + { + // Skip the first child (collapse button) when toggling visibility. + for (var i = 1; i < transform.childCount; i++) { - _expanded = !_expanded; - SetVisibility(); - _collapsibleSetting?.OnToggled(_expanded); + var child = transform.GetChild(i); + child.gameObject.SetActive(_expanded); } + // Trigger a layout update. + gameObject.SendMessageUpwards("SetLayoutHorizontal"); + gameObject.SendMessageUpwards("SetLayoutVertical"); + } - private void SetVisibility() + private void ApplyEnclosingStyling() + { + // Only run for a top-level CollapsibleSettingUICell. + if (!transform.parent.parent.gameObject.TryGetComponent(out var comp)) { - // Skip the first child (collapse button) when toggling visibility. - for (var i = 1; i < transform.childCount; i++) - { - var child = transform.GetChild(i); - child.gameObject.SetActive(_expanded); - } - // Trigger a layout update. - gameObject.SendMessageUpwards("SetLayoutHorizontal"); - gameObject.SendMessageUpwards("SetLayoutVertical"); + return; } - private void ApplyEnclosingStyling() + // Make the top-level setting box's background and text ignore the layout. + int idx = transform.parent.GetSiblingIndex(); + for (int i = 0; i < transform.parent.parent.childCount; i++) { - // Only run for a top-level CollapsibleSettingUICell. - if (!transform.parent.parent.gameObject.TryGetComponent(out var comp)) - { - return; - } + if (i == idx) + continue; + var child = transform.parent.parent.GetChild(i); + child.gameObject.AddComponent().ignoreLayout = true; + } - // Make the top-level setting box's background and text ignore the layout. - int idx = transform.parent.GetSiblingIndex(); - for (int i = 0; i < transform.parent.parent.childCount; i++) - { - if (i == idx) - continue; - var child = transform.parent.parent.GetChild(i); - child.gameObject.AddComponent().ignoreLayout = true; - } + // This is needed to force a layout. + transform.parent.gameObject.AddComponent(); - // This is needed to force a layout. - transform.parent.gameObject.AddComponent(); + MakeSettingBoxAdaptable(); + } - MakeSettingBoxAdaptable(); - } + private void MakeSettingBoxAdaptable() + { + // Make the setting box as tall as necessary. + var vlg = transform.parent.parent.gameObject.AddComponent(); + vlg.childControlWidth = false; + vlg.spacing = 10; + vlg.childAlignment = TextAnchor.MiddleRight; + // Give the bounding box some breathing room. + vlg.padding.top = 15; + vlg.padding.bottom = 15; + transform.parent.parent.gameObject.AddComponent().verticalFit = + ContentSizeFitter.FitMode.PreferredSize; + } - private void MakeSettingBoxAdaptable() + /// + /// Adds a new setting block. If a title exists, it is added here. + /// + private void AddSettingBlock(Setting setting, ISettingHandler settingHandler) + { + var block = UnityEngine.Object.Instantiate(settingObject, transform); + + // Check if the setting has a title. + LocalizedString? titleText = null; + if (setting is IExposedSetting exposedSetting) { - // Make the setting box as tall as necessary. - var vlg = transform.parent.parent.gameObject.AddComponent(); - vlg.childControlWidth = false; - vlg.spacing = 10; - vlg.childAlignment = TextAnchor.MiddleRight; - // Give the bounding box some breathing room. - vlg.padding.top = 15; - vlg.padding.bottom = 15; - transform.parent.parent.gameObject.AddComponent().verticalFit = - ContentSizeFitter.FitMode.PreferredSize; + titleText = exposedSetting.GetDisplayName(); } - /// - /// Adds a new setting block. If a title exists, it is added here. - /// - private void AddSettingBlock(Setting setting, ISettingHandler settingHandler) + // Only add a title if it is non-null and non-empty. + if (titleText != null && !titleText.IsEmpty) { - var block = UnityEngine.Object.Instantiate(settingObject, transform); + AddSettingTitle(titleText, block.transform); + } - // Check if the setting has a title. - LocalizedString? titleText = null; - if (setting is IExposedSetting exposedSetting) - { - titleText = exposedSetting.GetDisplayName(); - } + AddSetting(setting, block.transform, settingHandler); + } - // Only add a title if it is non-null and non-empty. - if (titleText != null && !titleText.IsEmpty) - { - AddSettingTitle(titleText, block.transform); - } + /// + /// Instantiates a title object and attaches it to the given parent. + /// + private void AddSettingTitle(LocalizedString titleText, Transform parentTransform) + { + var titleObj = new GameObject("SettingTitle"); + titleObj.transform.SetParent(parentTransform, false); + var textMesh = titleObj.AddComponent(); + textMesh.enableAutoSizing = true; + textMesh.alignment = TextAlignmentOptions.Center; + var localizeUIText = titleObj.AddComponent(); + localizeUIText.SetString(titleText); + var layout = titleObj.AddComponent(); + layout.preferredHeight = 20; + } - AddSetting(setting, block.transform, settingHandler); - } + private void AddSetting(Setting setting, Transform transform, ISettingHandler settingHandler) + { + var ui = UnityEngine.Object.Instantiate(setting.GetSettingUICell(), transform); - /// - /// Instantiates a title object and attaches it to the given parent. - /// - private void AddSettingTitle(LocalizedString titleText, Transform parentTransform) + // Ensure the element retains a preferred height so it isn’t collapsed by the layout. + var layoutElement = ui.GetComponent(); + if (layoutElement is null) { - var titleObj = new GameObject("SettingTitle"); - titleObj.transform.SetParent(parentTransform, false); - var textMesh = titleObj.AddComponent(); - textMesh.enableAutoSizing = true; - textMesh.alignment = TextAlignmentOptions.Center; - var localizeUIText = titleObj.AddComponent(); - localizeUIText.SetString(titleText); - var layout = titleObj.AddComponent(); - layout.preferredHeight = 20; + layoutElement = ui.AddComponent(); } - - private void AddSetting( - Setting setting, - Transform transform, - ISettingHandler settingHandler - ) + if (layoutElement.preferredHeight == -1 && layoutElement is LayoutElement elem) { - var ui = UnityEngine.Object.Instantiate(setting.GetSettingUICell(), transform); - - // Ensure the element retains a preferred height so it isn’t collapsed by the layout. - var layoutElement = ui.GetComponent(); - if (layoutElement is null) + elem.preferredHeight = setting switch { - layoutElement = ui.AddComponent(); - } - if (layoutElement.preferredHeight == -1 && layoutElement is LayoutElement elem) - { - elem.preferredHeight = setting switch - { - ButtonSetting set => 55, - _ => 35, - }; - } - - ui.GetComponent().Setup(setting, settingHandler); + ButtonSetting set => 55, + _ => 35, + }; } - private void SetUpSettingObject() - { - var layout = settingObject.AddComponent(); - // Add a little breathing room. - layout.spacing = 2; - layout.padding.top = 13; - settingObject.AddComponent().verticalFit = ContentSizeFitter - .FitMode - .PreferredSize; - - UnityEngine.Object.DontDestroyOnLoad(settingObject); - } + ui.GetComponent().Setup(setting, settingHandler); + } + + private void SetUpSettingObject() + { + var layout = settingObject.AddComponent(); + // Add a little breathing room. + layout.spacing = 2; + layout.padding.top = 13; + settingObject.AddComponent().verticalFit = ContentSizeFitter + .FitMode + .PreferredSize; + + UnityEngine.Object.DontDestroyOnLoad(settingObject); } } diff --git a/SettingsLib/Settings/UI/DynamicSettingListUI.cs b/SettingsLib/Settings/UI/DynamicSettingListUI.cs index bd3a53b..9ae2ba6 100644 --- a/SettingsLib/Settings/UI/DynamicSettingListUI.cs +++ b/SettingsLib/Settings/UI/DynamicSettingListUI.cs @@ -5,176 +5,175 @@ using Zorro.Localization; using Zorro.Settings; -namespace SettingsLib.Settings.UI +namespace SettingsLib.Settings.UI; + +public class DynamicSettingListUI : SettingInputUICell { - public class DynamicSettingListUI : SettingInputUICell + // Track expanded state + private bool _expanded = false; + private GameObject settingObject = new GameObject("SettingCell"); + private DynamicSettingList? _setting; + private ISettingHandler _settingHandler = GameHandler.Instance.SettingsHandler; + private string collapseButtonText => _expanded ? "▼ Collapse" : "► Expand"; + + public DynamicSettingListUI() + : base() { - // Track expanded state - private bool _expanded = false; - private GameObject settingObject = new GameObject("SettingCell"); - private DynamicSettingList? _setting; - private ISettingHandler _settingHandler = GameHandler.Instance.SettingsHandler; - private string collapseButtonText => _expanded ? "▼ Collapse" : "► Expand"; - - public DynamicSettingListUI() - : base() - { - SetUpSettingObject(); - } + SetUpSettingObject(); + } - public override void Setup(Setting setting, ISettingHandler settingHandler) + public override void Setup(Setting setting, ISettingHandler settingHandler) + { + if (setting is DynamicSettingList dynamicSetting) { - if (setting is DynamicSettingList dynamicSetting) - { - ApplyEnclosingStyling(); + ApplyEnclosingStyling(); - _setting = dynamicSetting; - _setting.SetUIElement(this); - _settingHandler = settingHandler; - AddChildren(); - } + _setting = dynamicSetting; + _setting.SetUIElement(this); + _settingHandler = settingHandler; + AddChildren(); } + } - public void RefreshList() - { - RemoveChildren(); - AddChildren(); + public void RefreshList() + { + RemoveChildren(); + AddChildren(); - // Trigger all ContentSizeFitters - LayoutRebuilder.ForceRebuildLayoutImmediate(GetComponent()); + // Trigger all ContentSizeFitters + LayoutRebuilder.ForceRebuildLayoutImmediate(GetComponent()); - gameObject.SendMessageUpwards("SetLayoutHorizontal"); - gameObject.SendMessageUpwards("SetLayoutVertical"); - } + gameObject.SendMessageUpwards("SetLayoutHorizontal"); + gameObject.SendMessageUpwards("SetLayoutVertical"); + } - private void RemoveChildren() + private void RemoveChildren() + { + for (var i = 0; i < transform.childCount; i++) { - for (var i = 0; i < transform.childCount; i++) - { - var child = transform.GetChild(i); - UnityEngine.Object.Destroy(child.gameObject); - } + var child = transform.GetChild(i); + UnityEngine.Object.Destroy(child.gameObject); } + } - private void AddChildren() + private void AddChildren() + { + if (_setting == null) + return; + + // Run setup for all settings, except non-shown conditionals. + foreach (var subsetting in _setting.GetSettings()) { - if (_setting == null) - return; + if (!(subsetting is IConditionalSetting conditional) || conditional.CanShow()) + AddSettingBlock(subsetting, _settingHandler); + } + } - // Run setup for all settings, except non-shown conditionals. - foreach (var subsetting in _setting.GetSettings()) - { - if (!(subsetting is IConditionalSetting conditional) || conditional.CanShow()) - AddSettingBlock(subsetting, _settingHandler); - } + private void ApplyEnclosingStyling() + { + // Only run for a top-level DynamicSettingListUI. + if (!transform.parent.parent.gameObject.TryGetComponent(out var comp)) + { + return; } - private void ApplyEnclosingStyling() + // Make the top level setting box's background and text ignore the layout. + int idx = transform.parent.GetSiblingIndex(); + for (int i = 0; i < transform.parent.parent.childCount; i++) { - // Only run for a top-level DynamicSettingListUI. - if (!transform.parent.parent.gameObject.TryGetComponent(out var comp)) - { - return; - } + if (i == idx) + continue; + var child = transform.parent.parent.GetChild(i); + child.gameObject.AddComponent().ignoreLayout = true; + } - // Make the top level setting box's background and text ignore the layout. - int idx = transform.parent.GetSiblingIndex(); - for (int i = 0; i < transform.parent.parent.childCount; i++) - { - if (i == idx) - continue; - var child = transform.parent.parent.GetChild(i); - child.gameObject.AddComponent().ignoreLayout = true; - } + // This is required to force the layout. + transform.parent.gameObject.AddComponent(); - // This is required to force the layout. - transform.parent.gameObject.AddComponent(); + MakeSettingBoxAdaptable(); + } - MakeSettingBoxAdaptable(); - } + private void MakeSettingBoxAdaptable() + { + // Make the setting box as tall as necessary. + var vlg = transform.parent.parent.gameObject.AddComponent(); + vlg.childControlWidth = false; + vlg.spacing = 10; + vlg.childAlignment = TextAnchor.MiddleRight; + // Give the bounding box some breathing room. + vlg.padding.top = 15; + vlg.padding.bottom = 15; + transform.parent.parent.gameObject.AddComponent().verticalFit = + ContentSizeFitter.FitMode.PreferredSize; + } - private void MakeSettingBoxAdaptable() - { - // Make the setting box as tall as necessary. - var vlg = transform.parent.parent.gameObject.AddComponent(); - vlg.childControlWidth = false; - vlg.spacing = 10; - vlg.childAlignment = TextAnchor.MiddleRight; - // Give the bounding box some breathing room. - vlg.padding.top = 15; - vlg.padding.bottom = 15; - transform.parent.parent.gameObject.AddComponent().verticalFit = - ContentSizeFitter.FitMode.PreferredSize; - } + private void AddSettingBlock(Setting setting, ISettingHandler settingHandler) + { + // Instantiate a new container using settingObject as template. + var block = UnityEngine.Object.Instantiate(settingObject, transform); - private void AddSettingBlock(Setting setting, ISettingHandler settingHandler) + // Check if the setting defines a title. + if (setting is IExposedSetting exposedSetting) { - // Instantiate a new container using settingObject as template. - var block = UnityEngine.Object.Instantiate(settingObject, transform); - - // Check if the setting defines a title. - if (setting is IExposedSetting exposedSetting) + LocalizedString titleText = exposedSetting.GetDisplayName(); + if (titleText != null && !titleText.IsEmpty) { - LocalizedString titleText = exposedSetting.GetDisplayName(); - if (titleText != null && !titleText.IsEmpty) - { - AddSettingTitle(titleText, block.transform); - } + AddSettingTitle(titleText, block.transform); } - - AddSetting(setting, block.transform, settingHandler); } - private void AddSettingTitle(LocalizedString titleText, Transform parentTransform) - { - var titleObj = new GameObject("SettingTitle"); - titleObj.transform.SetParent(parentTransform, false); + AddSetting(setting, block.transform, settingHandler); + } - var textMesh = titleObj.AddComponent(); - textMesh.enableAutoSizing = true; - textMesh.alignment = TextAlignmentOptions.Center; + private void AddSettingTitle(LocalizedString titleText, Transform parentTransform) + { + var titleObj = new GameObject("SettingTitle"); + titleObj.transform.SetParent(parentTransform, false); - var localizeUIText = titleObj.AddComponent(); - localizeUIText.SetString(titleText); + var textMesh = titleObj.AddComponent(); + textMesh.enableAutoSizing = true; + textMesh.alignment = TextAlignmentOptions.Center; - var layout = titleObj.AddComponent(); - layout.preferredHeight = 20; - } + var localizeUIText = titleObj.AddComponent(); + localizeUIText.SetString(titleText); - private void AddSetting(Setting setting, Transform parent, ISettingHandler settingHandler) - { - var ui = UnityEngine.Object.Instantiate(setting.GetSettingUICell(), parent); + var layout = titleObj.AddComponent(); + layout.preferredHeight = 20; + } - // Ensure the element gets a preferred height so it isn’t collapsed by the - // layout. - var layoutElement = ui.GetComponent(); - if (layoutElement is null) - { - layoutElement = ui.AddComponent(); - } - if (layoutElement.preferredHeight == -1 && layoutElement is LayoutElement elem) - { - elem.preferredHeight = setting switch - { - ButtonSetting set => 55, - _ => 35, - }; - } + private void AddSetting(Setting setting, Transform parent, ISettingHandler settingHandler) + { + var ui = UnityEngine.Object.Instantiate(setting.GetSettingUICell(), parent); - ui.GetComponent().Setup(setting, settingHandler); + // Ensure the element gets a preferred height so it isn’t collapsed by the + // layout. + var layoutElement = ui.GetComponent(); + if (layoutElement is null) + { + layoutElement = ui.AddComponent(); } - - private void SetUpSettingObject() + if (layoutElement.preferredHeight == -1 && layoutElement is LayoutElement elem) { - var layout = settingObject.AddComponent(); - // Little breathing room. - layout.spacing = 2; - layout.padding.top = 13; - settingObject.AddComponent().verticalFit = ContentSizeFitter - .FitMode - .PreferredSize; - - UnityEngine.Object.DontDestroyOnLoad(settingObject); + elem.preferredHeight = setting switch + { + ButtonSetting set => 55, + _ => 35, + }; } + + ui.GetComponent().Setup(setting, settingHandler); + } + + private void SetUpSettingObject() + { + var layout = settingObject.AddComponent(); + // Little breathing room. + layout.spacing = 2; + layout.padding.top = 13; + settingObject.AddComponent().verticalFit = ContentSizeFitter + .FitMode + .PreferredSize; + + UnityEngine.Object.DontDestroyOnLoad(settingObject); } }