From 03a51e53c4873dd72bb829820dd969bfc5176364 Mon Sep 17 00:00:00 2001 From: Arne Kiesewetter Date: Thu, 4 Jun 2026 22:32:02 +0200 Subject: [PATCH] Add a Tooltip Resolver for the ReferenceProxySources on inspector components and fields --- .../Locale/Monkeys/de.json | 5 +- .../Locale/Monkeys/en.json | 5 +- .../Tooltips/ButtonDelegateTooltipResolver.cs | 5 -- .../UI/Tooltips/ButtonTooltips.cs | 9 +-- .../UI/Tooltips/CommentTooltipResolver.cs | 5 -- .../UI/Tooltips/HyperlinkTooltipResolver.cs | 5 -- .../ReferenceProxySourceTooltipResolver.cs | 77 +++++++++++++++++++ .../UI/Tooltips/Tooltip.cs | 6 -- .../UI/Tooltips/TooltipConfig.cs | 1 - .../UI/Tooltips/TooltipManager.cs | 6 -- 10 files changed, 86 insertions(+), 38 deletions(-) create mode 100644 MonkeyLoader.Resonite.Integration/UI/Tooltips/ReferenceProxySourceTooltipResolver.cs diff --git a/MonkeyLoader.Resonite.Integration/Locale/Monkeys/de.json b/MonkeyLoader.Resonite.Integration/Locale/Monkeys/de.json index 40624888..12334dcc 100644 --- a/MonkeyLoader.Resonite.Integration/Locale/Monkeys/de.json +++ b/MonkeyLoader.Resonite.Integration/Locale/Monkeys/de.json @@ -95,7 +95,7 @@ "MonkeyLoader.GamePacks.Resonite.SyncMemberEditorBuilderInjector.Name": "Sync Member Editor Builder Injektor", "MonkeyLoader.GamePacks.Resonite.SyncMemberEditorBuilderInjector.Description": "Versendet die verschiedenen Build Member Editor Events, damit Monkeys die Generierung dieser überschreiben können.", - "MonkeyLoader.GamePacks.Resonite.ButtonDelegateTooltipResolver.Name": "Button Delegate Tooltip Auflöser", + "MonkeyLoader.GamePacks.Resonite.ButtonDelegateTooltipResolver.Name": "Delegate Tooltip Auflöser", "MonkeyLoader.GamePacks.Resonite.ButtonDelegateTooltipResolver.Description": "Wandelt das SyncDelegate Ziel eines Buttons in den Schlüssel für eine Übersetzungsnachricht um, damit diese als Tooltip angezeigt werden kann.", "MonkeyLoader.GamePacks.Resonite.ButtonTooltips.Name": "Button Tooltips", @@ -107,6 +107,9 @@ "MonkeyLoader.GamePacks.Resonite.HyperlinkTooltipResolver.Name": "Hyperlink Tooltip Auflöser", "MonkeyLoader.GamePacks.Resonite.HyperlinkTooltipResolver.Description": "Löst die Anfrage für den Tooltip eines Buttons basierend dem Grund und der URL einer Hyperlink-Komponente auf.
Diese können zu einem weiteren Tooltip für den Button hinzugefügt werden.", + "MonkeyLoader.GamePacks.Resonite.ReferenceProxySourceTooltipResolver.Name": "Referenzproxy Tooltip Auflöser", + "MonkeyLoader.GamePacks.Resonite.ReferenceProxySourceTooltipResolver.Description": "Löst die Anfrage für den Tooltip eines Buttons basierend auf der Zielreferenz einer ReferenceProxySource-Komponent auf.
Used for components and fields in inspectors.", + "MonkeyLoader.GamePacks.Resonite.TooltipManager.Name": "Tooltip Manager", "MonkeyLoader.GamePacks.Resonite.TooltipManager.Description": "Versendet die Tooltip Auflösungsanfragen aus verschiedenen Quellen. Das Tooltipsystem basiert auf dem Tooltippery Mod, der ursprünglich von Psychpsyo erstellt wurde.", diff --git a/MonkeyLoader.Resonite.Integration/Locale/Monkeys/en.json b/MonkeyLoader.Resonite.Integration/Locale/Monkeys/en.json index 78c8b422..f44ccbd9 100644 --- a/MonkeyLoader.Resonite.Integration/Locale/Monkeys/en.json +++ b/MonkeyLoader.Resonite.Integration/Locale/Monkeys/en.json @@ -95,7 +95,7 @@ "MonkeyLoader.GamePacks.Resonite.SyncMemberEditorBuilderInjector.Name": "Sync Member Editor Builder Injector", "MonkeyLoader.GamePacks.Resonite.SyncMemberEditorBuilderInjector.Description": "Sends out the various Build Member Editor events to allow monkeys to override the generation of them.", - "MonkeyLoader.GamePacks.Resonite.ButtonDelegateTooltipResolver.Name": "Button Delegate Tooltip Resolver", + "MonkeyLoader.GamePacks.Resonite.ButtonDelegateTooltipResolver.Name": "Delegate Tooltip Resolver", "MonkeyLoader.GamePacks.Resonite.ButtonDelegateTooltipResolver.Description": "Turns the SyncDelegate targeted by a Button into a locale key to display as a tooltip.", "MonkeyLoader.GamePacks.Resonite.ButtonTooltips.Name": "Button Tooltips", @@ -107,6 +107,9 @@ "MonkeyLoader.GamePacks.Resonite.HyperlinkTooltipResolver.Name": "Hyperlink Tooltip Resolver", "MonkeyLoader.GamePacks.Resonite.HyperlinkTooltipResolver.Description": "Resolves the tooltip for a button based on a Hyperlink component's URL and reason.
They may be added on to another tooltip for the button.", + "MonkeyLoader.GamePacks.Resonite.ReferenceProxySourceTooltipResolver.Name": "Reference Proxy Tooltip Resolver", + "MonkeyLoader.GamePacks.Resonite.ReferenceProxySourceTooltipResolver.Description": "Resolves the tooltip for a button based on a ReferenceProxySource component's target reference.
Used for components and fields in inspectors.", + "MonkeyLoader.GamePacks.Resonite.TooltipManager.Name": "Tooltip Manager", "MonkeyLoader.GamePacks.Resonite.TooltipManager.Description": "Sends out tooltip resolve requests from different sources. The tooltip system is based on the Tooltippery mod originally created by Psychpsyo.", diff --git a/MonkeyLoader.Resonite.Integration/UI/Tooltips/ButtonDelegateTooltipResolver.cs b/MonkeyLoader.Resonite.Integration/UI/Tooltips/ButtonDelegateTooltipResolver.cs index 6eccfa04..486b3996 100644 --- a/MonkeyLoader.Resonite.Integration/UI/Tooltips/ButtonDelegateTooltipResolver.cs +++ b/MonkeyLoader.Resonite.Integration/UI/Tooltips/ButtonDelegateTooltipResolver.cs @@ -2,12 +2,7 @@ using EnumerableToolkit; using FrooxEngine; using FrooxEngine.UIX; -using System; -using System.Collections.Generic; -using System.Linq; using System.Reflection; -using System.Text; -using System.Threading.Tasks; namespace MonkeyLoader.Resonite.UI.Tooltips { diff --git a/MonkeyLoader.Resonite.Integration/UI/Tooltips/ButtonTooltips.cs b/MonkeyLoader.Resonite.Integration/UI/Tooltips/ButtonTooltips.cs index 7201b548..f3a60f76 100644 --- a/MonkeyLoader.Resonite.Integration/UI/Tooltips/ButtonTooltips.cs +++ b/MonkeyLoader.Resonite.Integration/UI/Tooltips/ButtonTooltips.cs @@ -1,13 +1,6 @@ -using Elements.Core; -using FrooxEngine; +using FrooxEngine; using FrooxEngine.UIX; using HarmonyLib; -using MonkeyLoader.Patching; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace MonkeyLoader.Resonite.UI.Tooltips { diff --git a/MonkeyLoader.Resonite.Integration/UI/Tooltips/CommentTooltipResolver.cs b/MonkeyLoader.Resonite.Integration/UI/Tooltips/CommentTooltipResolver.cs index f2ed7ae0..a23cfac0 100644 --- a/MonkeyLoader.Resonite.Integration/UI/Tooltips/CommentTooltipResolver.cs +++ b/MonkeyLoader.Resonite.Integration/UI/Tooltips/CommentTooltipResolver.cs @@ -1,10 +1,5 @@ using FrooxEngine; -using System; -using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace MonkeyLoader.Resonite.UI.Tooltips { diff --git a/MonkeyLoader.Resonite.Integration/UI/Tooltips/HyperlinkTooltipResolver.cs b/MonkeyLoader.Resonite.Integration/UI/Tooltips/HyperlinkTooltipResolver.cs index f29805c7..887e76da 100644 --- a/MonkeyLoader.Resonite.Integration/UI/Tooltips/HyperlinkTooltipResolver.cs +++ b/MonkeyLoader.Resonite.Integration/UI/Tooltips/HyperlinkTooltipResolver.cs @@ -1,11 +1,6 @@ using Elements.Core; using FrooxEngine; -using System; -using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace MonkeyLoader.Resonite.UI.Tooltips { diff --git a/MonkeyLoader.Resonite.Integration/UI/Tooltips/ReferenceProxySourceTooltipResolver.cs b/MonkeyLoader.Resonite.Integration/UI/Tooltips/ReferenceProxySourceTooltipResolver.cs new file mode 100644 index 00000000..7c706186 --- /dev/null +++ b/MonkeyLoader.Resonite.Integration/UI/Tooltips/ReferenceProxySourceTooltipResolver.cs @@ -0,0 +1,77 @@ +using Elements.Core; +using FrooxEngine; +using System.Diagnostics.CodeAnalysis; +using System.Reflection; + +namespace MonkeyLoader.Resonite.UI.Tooltips +{ + internal sealed class ReferenceProxySourceTooltipResolver : ResoniteCancelableEventHandlerMonkey + { + public override bool CanBeDisabled => true; + + public override int Priority => HarmonyLib.Priority.HigherThanNormal + 1; + + public override bool SkipCanceled => true; + + public static bool TryGetTooltipLabel(IButton button, [NotNullWhen(true)] out LocaleString? label) + { + label = null; + + if (button.Slot.GetComponent() is not ReferenceProxySource proxySource) + return false; + + // Slots, Users, (User)Components, SyncObjects themselves + if (proxySource.Reference.Target is Worker targetWorker) + { + label = $"Tooltip.{string.Join('.', GetAllNestedNames(targetWorker.WorkerType).Reverse())}"; + return true; + } + + // Any synchronized data owned by Workers + if (proxySource.Reference.Target is not SyncElement targetElement) + return false; + + var nesting = 0; + + // FieldList are SyncElements with more SyncElements inside + // We want to use the name of the outermost one + // Not sure if there is any deeper nestings than one, but just to be sure... + while (targetElement.Parent is SyncElement parentElement) + { + ++nesting; + targetElement = parentElement; + } + + // Slots, Users, (User)Components, SyncObjects + if (targetElement.FindNearestParent() is not Worker parentWorker) + return false; + + if (parentWorker.GetSyncMemberFieldInfo(targetElement.Name) is not FieldInfo targetField) + return false; + + label = (nesting is 0 + ? $"Tooltip.{string.Join('.', GetAllNestedNames(targetField.DeclaringType!).Reverse())}.{targetElement.Name}" + : $"Tooltip.{string.Join('.', GetAllNestedNames(targetField.DeclaringType!).Reverse())}.{targetElement.Name}.{string.Join('.', Enumerable.Repeat("Item", nesting))}" + ).AsLocaleKey(); + + return true; + } + + protected override void Handle(ResolveTooltipLabelEvent eventData) + { + if (TryGetTooltipLabel(eventData.Button, out var label)) + eventData.Label = label; + } + + private static IEnumerable GetAllNestedNames(Type type) + { + yield return type.Name; + + while (type.IsNested) + { + type = type.DeclaringType!; + yield return type.Name; + } + } + } +} \ No newline at end of file diff --git a/MonkeyLoader.Resonite.Integration/UI/Tooltips/Tooltip.cs b/MonkeyLoader.Resonite.Integration/UI/Tooltips/Tooltip.cs index 93b9a8e6..21114769 100644 --- a/MonkeyLoader.Resonite.Integration/UI/Tooltips/Tooltip.cs +++ b/MonkeyLoader.Resonite.Integration/UI/Tooltips/Tooltip.cs @@ -1,12 +1,6 @@ using Elements.Core; using FrooxEngine; using FrooxEngine.UIX; -using System; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace MonkeyLoader.Resonite.UI.Tooltips { diff --git a/MonkeyLoader.Resonite.Integration/UI/Tooltips/TooltipConfig.cs b/MonkeyLoader.Resonite.Integration/UI/Tooltips/TooltipConfig.cs index c4c3069a..1d6cd5ca 100644 --- a/MonkeyLoader.Resonite.Integration/UI/Tooltips/TooltipConfig.cs +++ b/MonkeyLoader.Resonite.Integration/UI/Tooltips/TooltipConfig.cs @@ -3,7 +3,6 @@ using FrooxEngine; using MonkeyLoader.Configuration; using MonkeyLoader.Resonite.Configuration; -using System; namespace MonkeyLoader.Resonite.UI.Tooltips { diff --git a/MonkeyLoader.Resonite.Integration/UI/Tooltips/TooltipManager.cs b/MonkeyLoader.Resonite.Integration/UI/Tooltips/TooltipManager.cs index 90fa6aa4..9d7e4e3f 100644 --- a/MonkeyLoader.Resonite.Integration/UI/Tooltips/TooltipManager.cs +++ b/MonkeyLoader.Resonite.Integration/UI/Tooltips/TooltipManager.cs @@ -2,13 +2,7 @@ using EnumerableToolkit; using FrooxEngine; using MonkeyLoader.Events; -using System; -using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; namespace MonkeyLoader.Resonite.UI.Tooltips {