From 50e383ec3a566535dec1f3e7b9d396d1bc0059e9 Mon Sep 17 00:00:00 2001 From: Nytra <14206961+Nytra@users.noreply.github.com> Date: Tue, 24 Dec 2024 03:24:30 +0000 Subject: [PATCH] Fixup mod setting standalone facets, still not completely working with nullable HasValue --- .../Settings/ConfigSectionSettingsItems.cs | 13 ++++++- .../Settings/ModSettingStandaloneFacet.cs | 39 +++++++++++++++++-- .../FieldExtensions.cs | 18 ++++++--- .../UI/Tooltips/TooltipConfig.cs | 1 + 4 files changed, 60 insertions(+), 11 deletions(-) diff --git a/MonkeyLoader.Resonite.Integration/DataFeeds/Settings/ConfigSectionSettingsItems.cs b/MonkeyLoader.Resonite.Integration/DataFeeds/Settings/ConfigSectionSettingsItems.cs index c137898..e04006d 100644 --- a/MonkeyLoader.Resonite.Integration/DataFeeds/Settings/ConfigSectionSettingsItems.cs +++ b/MonkeyLoader.Resonite.Integration/DataFeeds/Settings/ConfigSectionSettingsItems.cs @@ -196,7 +196,18 @@ private static async IAsyncEnumerable GenerateNullableEnumItemsAsy nullableToggle.InitBase(configKey.FullId + ".HasValue", path, nullableGroupKeys, Mod.GetLocaleString("NullableEnumHasValue.Name")); nullableToggle.InitDescription(configKey.GetLocaleKey("HasValue").AsLocaleKey()); - nullableToggle.InitSetupValue(field => field.SyncWithNullableConfigKeyHasValue(configKey)); + nullableToggle.InitSetupValue(field => + { + var slot = field.FindNearestParent(); + + if (slot.GetComponentInParents() is FeedItemInterface feedItemInterface) + { + // Adding the config key's full id to make it easier to create standalone facets + feedItemInterface.Slot.AttachComponent().Text.Value = configKey.FullId; + } + + field.SyncWithNullableConfigKeyHasValue(configKey); + }); yield return nullableToggle; var enumItems = (IAsyncEnumerable)_generateEnumItemsAsync diff --git a/MonkeyLoader.Resonite.Integration/DataFeeds/Settings/ModSettingStandaloneFacet.cs b/MonkeyLoader.Resonite.Integration/DataFeeds/Settings/ModSettingStandaloneFacet.cs index 68e7257..9c714a6 100644 --- a/MonkeyLoader.Resonite.Integration/DataFeeds/Settings/ModSettingStandaloneFacet.cs +++ b/MonkeyLoader.Resonite.Integration/DataFeeds/Settings/ModSettingStandaloneFacet.cs @@ -1,4 +1,5 @@ -using FrooxEngine; +using Elements.Core; +using FrooxEngine; using FrooxEngine.UIX; using HarmonyLib; using MonkeyLoader.Configuration; @@ -19,11 +20,29 @@ internal sealed class ModSettingStandaloneFacet : ResoniteMonkey GetFeaturePatches() => []; private static IDefiningConfigKey? GetConfigKeyByFullId(string fullId) { + foreach (var gamePack in Mod.Loader.GamePacks) + { + if (fullId.StartsWith(gamePack.Id)) + { + var partialId = fullId.Remove(0, gamePack.Id.Length + 1); + + if (!partialId.StartsWith("Config.")) + partialId = "Config." + partialId; + + Logger.Debug(() => "Partial Id: " + partialId); + if (gamePack.TryGet().ByPartialId(partialId, out var modConfigKey)) + return modConfigKey; + + break; + } + } + if (fullId.StartsWith(Mod.Loader.Id)) { var partialId = fullId.Remove(0, Mod.Loader.Id.Length + 1); @@ -73,8 +92,19 @@ internal sealed class ModSettingStandaloneFacet : ResoniteMonkey(IField field, IDefiningConfigKey key, string? eventLabel) - => ((IField)field).SyncWithConfigKey((IDefiningConfigKey)key, eventLabel); + private static void SyncWithConfigKeyWrapper(IField field, IDefiningConfigKey key, string? eventLabel) where T : unmanaged + { + if (typeof(T) == typeof(bool) && key.ValueType.IsNullable()) + { + //((IField)field).SyncWithNullableConfigKeyHasValue((IDefiningConfigKey)key, eventLabel); + var type = key.ValueType.GetGenericArguments()[0]; + _syncWithNullableConfigKeyHasValueMethod.MakeGenericMethod(type).Invoke(null, [(IField)field, key, eventLabel, true]); + } + else + { + ((IField)field).SyncWithConfigKey(key, eventLabel); + } + } [HarmonyPatch(typeof(Facet), nameof(Facet.OnLoading))] [HarmonyPatchCategory(nameof(ModSettingStandaloneFacet))] @@ -131,7 +161,8 @@ private class UIGrabInstancerPatch [HarmonyPostfix] private static void TryGrabPostfix(UIGrabInstancer __instance, IGrabbable? __result) { - if (!__instance.World.IsUserspace() || __result is not Grabbable + if (!__instance.World.IsUserspace() || + __result is not Grabbable || __result?.Slot.GetComponent() is null || __instance.Slot.GetComponentInParents() is null || __instance.Slot.GetComponentInParents() is null diff --git a/MonkeyLoader.Resonite.Integration/FieldExtensions.cs b/MonkeyLoader.Resonite.Integration/FieldExtensions.cs index fc648c7..50d96a5 100644 --- a/MonkeyLoader.Resonite.Integration/FieldExtensions.cs +++ b/MonkeyLoader.Resonite.Integration/FieldExtensions.cs @@ -1,6 +1,7 @@ using Elements.Core; using FrooxEngine; using MonkeyLoader.Configuration; +using MonkeyLoader.Meta; using MonkeyLoader.Resonite.Configuration; using System; using System.Collections.Generic; @@ -122,6 +123,8 @@ public static Action SyncWithNullableConfigKeyHasValue(this IFie IDefiningConfigKey configKey, string? eventLabel = null, bool allowWriteBack = true) where T : unmanaged { + configKey.FindNearestParent().Logger.Info(() => $"Syncing with nullable config key: {configKey.Id}"); + field.Value = configKey.GetValue().HasValue; eventLabel ??= field.GetWriteBackEventLabel(); @@ -129,6 +132,8 @@ public static Action SyncWithNullableConfigKeyHasValue(this IFie void ParentDestroyedHandler(IDestroyable _) { + configKey.FindNearestParent().Logger.Info(() => $"Parent destroyed: {configKey.Id}"); + parent.Destroyed -= ParentDestroyedHandler; field.Changed -= FieldChangedHandler; @@ -137,19 +142,20 @@ void ParentDestroyedHandler(IDestroyable _) void FieldChangedHandler(IChangeable _) { + configKey.FindNearestParent().Logger.Info(() => $"Field changed: {configKey.Id} {field.Value} {configKey.GetValue().HasValue} {allowWriteBack}"); + T? newValue = field.Value ? default : null; - var keyValue = configKey.GetValue().HasValue; - if (field.Value != keyValue && (!allowWriteBack || !configKey.TrySetValue(newValue, eventLabel))) - field.World.RunSynchronously(() => field.Value = keyValue); + if (field.Value != configKey.GetValue().HasValue && (!allowWriteBack || !configKey.TrySetValue(newValue, eventLabel))) + field.World.RunSynchronously(() => field.Value = configKey.GetValue().HasValue); } void ConfigKeyChangedHandler(object sender, ConfigKeyChangedEventArgs args) { - var keyValue = configKey.GetValue().HasValue; + configKey.FindNearestParent().Logger.Info(() => $"Config key changed: {configKey.Id} {field.Value} {configKey.GetValue().HasValue}"); - if (field.Value != keyValue) - field.World.RunSynchronously(() => field.Value = keyValue); + if (field.Value != configKey.GetValue().HasValue) + field.World.RunSynchronously(() => field.Value = configKey.GetValue().HasValue); } field.Changed += FieldChangedHandler; diff --git a/MonkeyLoader.Resonite.Integration/UI/Tooltips/TooltipConfig.cs b/MonkeyLoader.Resonite.Integration/UI/Tooltips/TooltipConfig.cs index e8eaa14..d010a59 100644 --- a/MonkeyLoader.Resonite.Integration/UI/Tooltips/TooltipConfig.cs +++ b/MonkeyLoader.Resonite.Integration/UI/Tooltips/TooltipConfig.cs @@ -33,6 +33,7 @@ public sealed class TooltipConfig : SingletonConfigSection private static readonly DefiningConfigKey _testKey = new("testKey", "Test key.", () => ShadowType.Soft); private static readonly DefiningConfigKey _testKey3 = new("testKey3", "Test key3.", () => MappingTarget.NONE); private static readonly DefiningConfigKey _testKey2 = new("testKey2", "Test key2.", () => null); + private static readonly DefiningConfigKey _testKey4 = new("testKey4", "Test key4.", () => null); /// /// Gets the background color for tooltips.