From e169c0ebb38217d0aef6328fec869a6b1b7cbd3f Mon Sep 17 00:00:00 2001 From: Arne Kiesewetter Date: Tue, 2 Jun 2026 22:58:42 +0200 Subject: [PATCH 1/3] Use ValueTag instead of ValueField for local action buttons --- .../UI/LocalActionButtonExtensions.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/MonkeyLoader.Resonite.Core/UI/LocalActionButtonExtensions.cs b/MonkeyLoader.Resonite.Core/UI/LocalActionButtonExtensions.cs index bfe31a8..d16598c 100644 --- a/MonkeyLoader.Resonite.Core/UI/LocalActionButtonExtensions.cs +++ b/MonkeyLoader.Resonite.Core/UI/LocalActionButtonExtensions.cs @@ -156,11 +156,11 @@ public static Button LocalActionButton(this UIBuilder builder, IAssetProvider public static TButton WithLocalAction(this TButton button, Action action) where TButton : IButton { - var valueField = button.Slot.AttachComponent>().Value; - valueField.OnValueChange += field => action(button); + var valueTag = button.Slot.AttachComponent>().Value; + valueTag.OnValueChange += field => action(button); var toggle = button.Slot.AttachComponent(); - toggle.TargetValue.Target = valueField; + toggle.TargetValue.Target = valueTag; button.Slot.DestroyWhenLocalUserLeaves(); @@ -183,11 +183,11 @@ public static TButton WithLocalAction(this TButton button, Action(this TButton button, TArgument argument, Action action) where TButton : IButton { - var valueField = button.Slot.AttachComponent>().Value; - valueField.OnValueChange += field => action(button, argument); + var valueTag = button.Slot.AttachComponent>().Value; + valueTag.OnValueChange += field => action(button, argument); var toggle = button.Slot.AttachComponent(); - toggle.TargetValue.Target = valueField; + toggle.TargetValue.Target = valueTag; button.Slot.DestroyWhenLocalUserLeaves(); From c9ec6deb114594246ac253b662e4e4c676f62a2f Mon Sep 17 00:00:00 2001 From: Arne Kiesewetter Date: Tue, 2 Jun 2026 22:59:09 +0200 Subject: [PATCH 2/3] Update Remora.Resonite.Sdk and bump version --- Directory.Build.props | 2 +- global.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index b51cec0..cf340b2 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,6 +1,6 @@ - 0.31.0 + 0.32.0 MonkeyLoader.Resonite True diff --git a/global.json b/global.json index 416004e..75f5aa7 100644 --- a/global.json +++ b/global.json @@ -1,5 +1,5 @@ { "msbuild-sdks": { - "Remora.Resonite.Sdk": "2.1.0" + "Remora.Resonite.Sdk": "2.2.0" } } \ No newline at end of file From 3eeb4a1c8d27069bd2d8bd5940bb8efb4c7165b3 Mon Sep 17 00:00:00 2001 From: Arne Kiesewetter Date: Tue, 2 Jun 2026 22:59:35 +0200 Subject: [PATCH 3/3] Add wiki button to Default Inspector Header Handler and Config --- .../MonkeyLoader.Resonite.Core.csproj | 2 + .../UI/ButtonRefExtensions.cs | 5 - .../UI/LocalActionButtonExtensions.cs | 7 +- .../UI/WikiLinkButtonExtensions.cs | 149 ++++++++++++++++++ .../Locale/Config/de.json | 10 +- .../Locale/Config/en.json | 2 + .../Locale/General/de.json | 5 +- .../Locale/General/en.json | 5 +- .../UI/Inspectors/BuildInspectorEvents.cs | 33 ++++ .../DefaultInspectorHeaderConfig.cs | 29 +++- .../DefaultInspectorHeaderHandler.cs | 25 ++- 11 files changed, 245 insertions(+), 27 deletions(-) create mode 100644 MonkeyLoader.Resonite.Core/UI/WikiLinkButtonExtensions.cs diff --git a/MonkeyLoader.Resonite.Core/MonkeyLoader.Resonite.Core.csproj b/MonkeyLoader.Resonite.Core/MonkeyLoader.Resonite.Core.csproj index d69931c..ff76c55 100644 --- a/MonkeyLoader.Resonite.Core/MonkeyLoader.Resonite.Core.csproj +++ b/MonkeyLoader.Resonite.Core/MonkeyLoader.Resonite.Core.csproj @@ -34,6 +34,8 @@ For mods targetting ML, this library is part of the Resonite Game Pack. + + diff --git a/MonkeyLoader.Resonite.Core/UI/ButtonRefExtensions.cs b/MonkeyLoader.Resonite.Core/UI/ButtonRefExtensions.cs index 1e2bdeb..da5527f 100644 --- a/MonkeyLoader.Resonite.Core/UI/ButtonRefExtensions.cs +++ b/MonkeyLoader.Resonite.Core/UI/ButtonRefExtensions.cs @@ -1,12 +1,7 @@ using Elements.Core; using FrooxEngine; using FrooxEngine.UIX; -using System; -using System.Collections.Generic; -using System.Linq; using System.Runtime.CompilerServices; -using System.Text; -using System.Threading.Tasks; #pragma warning disable CS1572 // XML comment has a param tag, but there is no parameter by that name #pragma warning disable CS1573 // Parameter has no matching param tag in the XML comment (but other parameters do) diff --git a/MonkeyLoader.Resonite.Core/UI/LocalActionButtonExtensions.cs b/MonkeyLoader.Resonite.Core/UI/LocalActionButtonExtensions.cs index d16598c..dae897d 100644 --- a/MonkeyLoader.Resonite.Core/UI/LocalActionButtonExtensions.cs +++ b/MonkeyLoader.Resonite.Core/UI/LocalActionButtonExtensions.cs @@ -1,17 +1,12 @@ using FrooxEngine.UIX; using FrooxEngine; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using Elements.Core; using System.Runtime.CompilerServices; namespace MonkeyLoader.Resonite.UI { /// - /// Contains extension methods to setup locally defined actions for s which are triggerable by anyone. + /// Contains extension methods to setup locally defined actions for s, which are triggerable by anyone. /// /// /// Due to their nature, they will only work while the that creates them hasn't left the session.
diff --git a/MonkeyLoader.Resonite.Core/UI/WikiLinkButtonExtensions.cs b/MonkeyLoader.Resonite.Core/UI/WikiLinkButtonExtensions.cs new file mode 100644 index 0000000..22027ca --- /dev/null +++ b/MonkeyLoader.Resonite.Core/UI/WikiLinkButtonExtensions.cs @@ -0,0 +1,149 @@ +using Elements.Core; +using FrooxEngine; +using FrooxEngine.ProtoFlux; +using ProtoFlux.Core; +using System.Reflection; + +namespace MonkeyLoader.Resonite.UI +{ + /// + /// Contains extension methods to setup s with links to the Resonite Wiki, which are triggerable by anyone. + /// + public static class WikiLinkButtonExtensions + { + private static readonly Dictionary _nameOverrides = new() + { + { "Engine.DynamicVariables.Input", "DynamicVariableInput" }, + { "Engine.DynamicVariables.InputWithEvents", "DynamicVariableInputWithEvents" }, + }; + + internal static LocaleString ComponentLocale { get; set; } + + internal static LocaleString ProtoFluxLocale { get; set; } + + /// + /// Sets up an with a to the given wiki , + /// optionally setting the for opening it. + /// + /// The specific type of the button. + /// The button to set up with a wiki link. + /// The wiki page to link to. + /// The optional reason for opening the link. + /// The unchanged button. + public static TButton WithWikiLink(this TButton button, string page, in LocaleString reason = default) + where TButton : IButton + { + var hyperlink = button.Slot.AttachComponent(); + hyperlink.URL.Value = new Uri($"{button.Slot.Engine.PlatformProfile.Wiki}/{page}"); + hyperlink.Reason.AssignLocaleString(reason); + + return button; + } + + //private static readonly Type _componentType = typeof(Component); + //private static readonly Type _protoFluxNodeType = typeof(ProtoFluxNode); + //public static TButton WithWikiLinkFor(this TButton button, Type workerType) + // where TButton : IButton + //{ + // while (workerType.IsNested) + // workerType = workerType.DeclaringType!; + + // var pagePrefix = workerType.GetCustomAttribute(inherit: true)?.Prefix ?? ""; + + // string wikiPage; + // LocaleString reason; + + // if (workerType.IsAssignableTo(_protoFluxNodeType)) + // { + // var nodeName = node.NodeName; + // var overload = NodeMetadataHelper.GetMetadata(node.NodeType).Overload; + + // if (!string.IsNullOrEmpty(overload)) + // { + // if (_nameOverrides.TryGetValue(overload, out var overrideName)) + // { + // nodeName = overrideName; + // } + // else + // { + // var dotIndex = overload.LastIndexOf('.'); + + // nodeName = dotIndex > 0 ? overload[(dotIndex + 1)..] : nodeName; + // } + // } + + // wikiPage = $"{pagePrefix}{nodeName.Replace(' ', '_')}"; + // reason = ProtoFluxLocale; + // } + // else + // { + // var workerName = worker.WorkerType.Name; + + // // Don't need to remove the `1 on generics - they redirect and may actually be different + // wikiPage = $"{pagePrefix}{workerName}"; + // reason = ComponentLocale; + // } + + // return button + // .WithTooltip(reason) + // .WithWikiLink(wikiPage, reason); + //} + + /// + /// Sets up an with a to the wiki page for the given . + /// + /// + /// This method automatically sets a tooltip and reason for opening the link. + /// + /// The specific type of the button. + /// The button to set up with a wiki link. + /// The worker to the link the wiki page for. + /// The unchanged button. + public static TButton WithWikiLinkFor(this TButton button, IWorker worker) + where TButton : IButton + { + if (worker is ProtoFluxEngineProxy proxy) + worker = proxy.Node.Target ?? worker; + + var pagePrefix = worker.GetType().GetCustomAttribute(inherit: true)?.Prefix ?? ""; + + string wikiPage; + LocaleString reason; + + if (worker is ProtoFluxNode node) + { + var nodeName = node.NodeName; + var overload = NodeMetadataHelper.GetMetadata(node.NodeType).Overload; + + if (!string.IsNullOrEmpty(overload)) + { + if (_nameOverrides.TryGetValue(overload, out var overrideName)) + { + nodeName = overrideName; + } + else + { + var dotIndex = overload.LastIndexOf('.'); + + nodeName = dotIndex > 0 ? overload[(dotIndex + 1)..] : nodeName; + } + } + + wikiPage = $"{pagePrefix}{nodeName.Replace(' ', '_')}"; + reason = ProtoFluxLocale; + } + else + { + var workerName = worker.WorkerType.Name; + + // Don't need to remove the `1 on generics - they redirect and may actually be different + wikiPage = $"{pagePrefix}{workerName}"; + reason = ComponentLocale; + } + + return button + .WithTooltip(reason) + .WithWikiLink(wikiPage, reason); + } + } +} \ No newline at end of file diff --git a/MonkeyLoader.Resonite.Integration/Locale/Config/de.json b/MonkeyLoader.Resonite.Integration/Locale/Config/de.json index 4e35664..00afd48 100644 --- a/MonkeyLoader.Resonite.Integration/Locale/Config/de.json +++ b/MonkeyLoader.Resonite.Integration/Locale/Config/de.json @@ -57,15 +57,17 @@ "MonkeyLoader.GamePacks.Resonite.Config.DefaultInspectorHeader.Name": "Inspektor-Kopfzeile", "MonkeyLoader.GamePacks.Resonite.Config.DefaultInspectorHeader.DestroyOffset.Name": "Löschen Offset", - "MonkeyLoader.GamePacks.Resonite.Config.DefaultInspectorHeader.DestroyOffset.Description": "Das Order Offset des Löschen-Knopfs bei Inspektor-Kopfzeilen. Erlaubter Wert: 0-16 - Höher ist weiter rechts.", + "MonkeyLoader.GamePacks.Resonite.Config.DefaultInspectorHeader.DestroyOffset.Description": "Das Order Offset des Löschen-Knopfs bei Inspektor-Kopfzeilen. Höher ist weiter rechts.", "MonkeyLoader.GamePacks.Resonite.Config.DefaultInspectorHeader.DuplicateOffset.Name": "Duplizieren Offset", - "MonkeyLoader.GamePacks.Resonite.Config.DefaultInspectorHeader.DuplicateOffset.Description": "Das Order Offset des Duplizieren-Knopfs bei Inspektor-Kopfzeilen. Erlaubter Wert: 0-16 - Höher ist weiter rechts.", + "MonkeyLoader.GamePacks.Resonite.Config.DefaultInspectorHeader.DuplicateOffset.Description": "Das Order Offset des Duplizieren-Knopfs bei Inspektor-Kopfzeilen. Höher ist weiter rechts.", "MonkeyLoader.GamePacks.Resonite.Config.DefaultInspectorHeader.OpenContainerOffset.Name": "Container-Öffnen Offset", - "MonkeyLoader.GamePacks.Resonite.Config.DefaultInspectorHeader.OpenContainerOffset.Description": "Das Order Offset des Container-Öffnen-Knopfs bei Inspektor-Kopfzeilen. Erlaubter Wert: 0-16 - Höher ist weiter rechts.", + "MonkeyLoader.GamePacks.Resonite.Config.DefaultInspectorHeader.OpenContainerOffset.Description": "Das Order Offset des Container-Öffnen-Knopfs bei Inspektor-Kopfzeilen. Höher ist weiter rechts.", "MonkeyLoader.GamePacks.Resonite.Config.DefaultInspectorHeader.StartHeaderTextExpanded.Name": "Starte Kopfzeilentext Expandiert", "MonkeyLoader.GamePacks.Resonite.Config.DefaultInspectorHeader.StartHeaderTextExpanded.Description": "Zeigt den Kopfzeilentext in Inspektoren standardmäßig an.", "MonkeyLoader.GamePacks.Resonite.Config.DefaultInspectorHeader.NameOffset.Name": "Name Offset", - "MonkeyLoader.GamePacks.Resonite.Config.DefaultInspectorHeader.NameOffset.Description": "Das Order Offset des Worker-Name-Knopfs bei Inspektor-Kopfzeilen. Erlaubter Wert: 0-16 - Höher ist weiter rechts.", + "MonkeyLoader.GamePacks.Resonite.Config.DefaultInspectorHeader.NameOffset.Description": "Das Order Offset des Worker-Name-Knopfs bei Inspektor-Kopfzeilen. Höher ist weiter rechts.", + "MonkeyLoader.GamePacks.Resonite.Config.DefaultInspectorHeader.WikiLinkOffset.Name": "Wikilink Offset", + "MonkeyLoader.GamePacks.Resonite.Config.DefaultInspectorHeader.WikiLinkOffset.Description": "Das Order Offset des Wikilink-Knopfs bei Inspektor-Kopfzeilen. Höher ist weiter rechts.

Nutzt den konfigurierten Wert der ursprünglichen Wiki Integration Mod als Standardwert, falls vorhanden.", "MonkeyLoader.GamePacks.Resonite.Config.Loading.Name": "Ladevorgang", "MonkeyLoader.GamePacks.Resonite.Config.Loading.HijackLoadProgressIndicator.Name": "Ladefortschrittsanzeige übernehmen", diff --git a/MonkeyLoader.Resonite.Integration/Locale/Config/en.json b/MonkeyLoader.Resonite.Integration/Locale/Config/en.json index caf524b..73ce9a3 100644 --- a/MonkeyLoader.Resonite.Integration/Locale/Config/en.json +++ b/MonkeyLoader.Resonite.Integration/Locale/Config/en.json @@ -66,6 +66,8 @@ "MonkeyLoader.GamePacks.Resonite.Config.DefaultInspectorHeader.StartHeaderTextExpanded.Description": "Shows the inspector header text by default.", "MonkeyLoader.GamePacks.Resonite.Config.DefaultInspectorHeader.NameOffset.Name": "Name Offset", "MonkeyLoader.GamePacks.Resonite.Config.DefaultInspectorHeader.NameOffset.Description": "The Order Offset of the Worker Name button on Inspector Headers. Higher is further right.", + "MonkeyLoader.GamePacks.Resonite.Config.DefaultInspectorHeader.WikiLinkOffset.Name": "Wiki Link Offset", + "MonkeyLoader.GamePacks.Resonite.Config.DefaultInspectorHeader.WikiLinkOffset.Description": "The Order Offset of the Wiki Link button on Inspector Headers. Higher is further right.

Uses the configured value of the original Wiki Integration mod as a default, if available.", "MonkeyLoader.GamePacks.Resonite.Config.Loading.Name": "Loading", "MonkeyLoader.GamePacks.Resonite.Config.Loading.HijackLoadProgressIndicator.Name": "Hijack Load Progress Indicator", diff --git a/MonkeyLoader.Resonite.Integration/Locale/General/de.json b/MonkeyLoader.Resonite.Integration/Locale/General/de.json index 27454b8..27db570 100644 --- a/MonkeyLoader.Resonite.Integration/Locale/General/de.json +++ b/MonkeyLoader.Resonite.Integration/Locale/General/de.json @@ -16,6 +16,9 @@ "MonkeyLoader.GamePacks.Resonite.Tooltip.RefreshFacet": "Aktualisiert diese Facet auf die neueste Version.", "MonkeyLoader.GamePacks.Resonite.Tooltip.OpenHyperlink.Direct": "Versucht einen Hyperlink zu öffnen.

Grund: {reason}
URL: {url}", - "MonkeyLoader.GamePacks.Resonite.Tooltip.OpenHyperlink.WithLabel": "{label}

Grund: {reason}
URL: {url}" + "MonkeyLoader.GamePacks.Resonite.Tooltip.OpenHyperlink.WithLabel": "{label}

Grund: {reason}
URL: {url}", + + "MonkeyLoader.GamePacks.Resonite.Tooltip.WikiHyperlink.Component": "Öffnet den Resonite Wiki Artikel über diese Komponente.", + "MonkeyLoader.GamePacks.Resonite.Tooltip.WikiHyperlink.ProtoFlux": "Öffnet den Resonite Wiki Artikel über diese ProtoFlux Node." } } \ No newline at end of file diff --git a/MonkeyLoader.Resonite.Integration/Locale/General/en.json b/MonkeyLoader.Resonite.Integration/Locale/General/en.json index 37c106c..5f6b82a 100644 --- a/MonkeyLoader.Resonite.Integration/Locale/General/en.json +++ b/MonkeyLoader.Resonite.Integration/Locale/General/en.json @@ -16,6 +16,9 @@ "MonkeyLoader.GamePacks.Resonite.Tooltip.RefreshFacet": "Refreshes this facet to the latest version.", "MonkeyLoader.GamePacks.Resonite.Tooltip.OpenHyperlink.Direct": "Attempts to open a hyperlink.

Reason: {reason}
URL: {url}", - "MonkeyLoader.GamePacks.Resonite.Tooltip.OpenHyperlink.WithLabel": "{label}

Reason: {reason}
URL: {url}" + "MonkeyLoader.GamePacks.Resonite.Tooltip.OpenHyperlink.WithLabel": "{label}

Reason: {reason}
URL: {url}", + + "MonkeyLoader.GamePacks.Resonite.Tooltip.WikiHyperlink.Component": "Opens the Resonite Wiki article about this Component.", + "MonkeyLoader.GamePacks.Resonite.Tooltip.WikiHyperlink.ProtoFlux": "Opens the Resonite Wiki article about this ProtoFlux node." } } \ No newline at end of file diff --git a/MonkeyLoader.Resonite.Integration/UI/Inspectors/BuildInspectorEvents.cs b/MonkeyLoader.Resonite.Integration/UI/Inspectors/BuildInspectorEvents.cs index 78e5fac..d0fa2c4 100644 --- a/MonkeyLoader.Resonite.Integration/UI/Inspectors/BuildInspectorEvents.cs +++ b/MonkeyLoader.Resonite.Integration/UI/Inspectors/BuildInspectorEvents.cs @@ -124,6 +124,11 @@ public sealed class BuildInspectorHeaderEvent : BuildInspectorEvent /// public const string OpenContainerButtonName = "OpenContainer"; + /// + /// The name for the Wiki Link button. + /// + public const string WikiLinkButtonName = "WikiLink"; + /// /// The name for the Worker Name button. /// @@ -149,6 +154,12 @@ public sealed class BuildInspectorHeaderEvent : BuildInspectorEvent /// public bool CreateOpenContainerButton => AllowContainer && !HasOpenContainerButton && Worker.FindNearestParent() != null; + /// + /// Gets whether the inspector header that's currently being build + /// still needs to have a Wiki Link button created. + /// + public bool CreateWikiLinkButton => !HasWikiLinkButton; + /// /// Gets whether the inspector header that's currently being build /// still needs to have a Worker Name button created. @@ -181,24 +192,35 @@ public IButton DuplicateButton /// Gets whether the inspector header that's currently being build /// already has a Destroy button. /// + [MemberNotNullWhen(true, nameof(DestroyButton))] public bool HasDestroyButton => HasButton(DestroyButtonName); /// /// Gets whether the inspector header that's currently being build /// already has a Duplicate button. /// + [MemberNotNullWhen(true, nameof(DuplicateButton))] public bool HasDuplicateButton => HasButton(DuplicateButtonName); /// /// Gets whether the inspector header that's currently being build /// already has an Open Container button. /// + [MemberNotNullWhen(true, nameof(OpenContainerButton))] public bool HasOpenContainerButton => HasButton(OpenContainerButtonName); + /// + /// Gets whether the inspector header that's currently being build + /// already has a Wiki Link button. + /// + [MemberNotNullWhen(true, nameof(WikiLinkButton))] + public bool HasWikiLinkButton => HasButton(WikiLinkButtonName); + /// /// Gets whether the inspector header that's currently being build /// already has a Worker Name button. /// + [MemberNotNullWhen(true, nameof(WorkerNameButton))] public bool HasWorkerNameButton => HasButton(WorkerNameButtonName); /// @@ -212,6 +234,17 @@ public IButton OpenContainerButton set => SetButton(OpenContainerButtonName, value); } + /// + /// Gets the Wiki Link button of the inspector header that's currently being build. + /// + /// The button or null if there is none yet. + [MaybeNull] + public IButton WikiLinkButton + { + get => GetButton(WikiLinkButtonName); + set => SetButton(WikiLinkButtonName, value); + } + /// /// Gets the Worker Name button of the inspector header that's currently being build. /// diff --git a/MonkeyLoader.Resonite.Integration/UI/Inspectors/DefaultInspectorHeaderConfig.cs b/MonkeyLoader.Resonite.Integration/UI/Inspectors/DefaultInspectorHeaderConfig.cs index ab319c4..0f023bf 100644 --- a/MonkeyLoader.Resonite.Integration/UI/Inspectors/DefaultInspectorHeaderConfig.cs +++ b/MonkeyLoader.Resonite.Integration/UI/Inspectors/DefaultInspectorHeaderConfig.cs @@ -1,7 +1,8 @@ -using FrooxEngine; +using Elements.Core; +using FrooxEngine; using MonkeyLoader.Configuration; +using MonkeyLoader.Meta; using MonkeyLoader.Resonite.Configuration; -using System; namespace MonkeyLoader.Resonite.UI.Inspectors { @@ -25,7 +26,7 @@ public sealed class DefaultInspectorHeaderConfig : SingletonConfigSection _openContainerOffset = new("OpenContainerOffset", "The Order Offset of the Open Container button on Inspector Headers. Higher is further right.", () => 4) { OffsetRange, - MakeOffsetRangeShare(10) + MakeOffsetRangeShare(9) }; private readonly DefiningConfigKey _startHeaderTextExpanded = new("StartHeaderTextExpanded", "Whether the inspector header text should be shown by default.", () => true) @@ -33,6 +34,12 @@ public sealed class DefaultInspectorHeaderConfig : SingletonConfigSection(true) }; + private readonly DefiningConfigKey _wikiLinkOffset = new("WikiLinkOffset", "The Order Offset of the Wiki Link button on Inspector Headers. Higher is further right.", GetWikiIntegrationOffsetOrDefault) + { + OffsetRange, + MakeOffsetRangeShare(10) + }; + private readonly DefiningConfigKey _workerNameOffset = new("NameOffset", "The Order Offset of the Worker Name button on Inspector Headers. Higher is further right.", () => 6) { OffsetRange, @@ -71,7 +78,12 @@ public sealed class DefaultInspectorHeaderConfig : SingletonConfigSection StartHeaderTextExpanded => _startHeaderTextExpanded.Components.Get>(); /// - public override Version Version { get; } = new Version(1, 0, 1); + public override Version Version { get; } = new Version(1, 1, 0); + + /// + /// Gets the Order Offset share for the Wiki Link button on Inspector Headers. + /// + public ConfigKeySessionShare WikiLinkOffset => _wikiLinkOffset.Components.Get>(); /// /// Gets the Order Offset share for the Worker Name button on Inspector Headers. @@ -87,6 +99,15 @@ public sealed class DefaultInspectorHeaderConfig : SingletonConfigSection MakeOffsetRangeShare(int defaultValue = default) => new(IntToLong, LongToInt, defaultValue); + private static int GetWikiIntegrationOffsetOrDefault() + { + if (Instance.Config.Owner.Loader.TryGet().ByFullId("WikiIntegration.Config.Buttons.ComponentOffset", out var genericKey) + && genericKey is IDefiningConfigKey offsetKey) + return offsetKey.GetValue(); + + return 10; + } + private static long IntToLong(int value) => value; private static int LongToInt(long value) => (int)value; diff --git a/MonkeyLoader.Resonite.Integration/UI/Inspectors/DefaultInspectorHeaderHandler.cs b/MonkeyLoader.Resonite.Integration/UI/Inspectors/DefaultInspectorHeaderHandler.cs index 87f2a98..f2529fb 100644 --- a/MonkeyLoader.Resonite.Integration/UI/Inspectors/DefaultInspectorHeaderHandler.cs +++ b/MonkeyLoader.Resonite.Integration/UI/Inspectors/DefaultInspectorHeaderHandler.cs @@ -1,11 +1,5 @@ using Elements.Core; using FrooxEngine; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using System.Text; -using System.Threading.Tasks; namespace MonkeyLoader.Resonite.UI.Inspectors { @@ -45,6 +39,17 @@ protected override void Handle(BuildInspectorHeaderEvent eventData) eventData.OpenContainerButton = button; } + if (eventData.CreateWikiLinkButton) + { + var button = Engine.IsAprilFools + ? ui.Button(OfficialAssets.Graphics.Badges.Mentor) + : ui.Button(OfficialAssets.Graphics.Icons.Inspector.Help, RadiantUI_Constants.Sub.CYAN).WithWikiLinkFor(worker); + + ConfigSection.WikiLinkOffset.DriveFromVariable(button.Slot.OrderOffset_Field); + + eventData.WikiLinkButton = button; + } + if (eventData.CreateDuplicateButton) { var button = ui.ButtonRef(OfficialAssets.Graphics.Icons.Inspector.Duplicate, RadiantUI_Constants.Sub.GREEN, eventData.Inspector.OnDuplicateComponentPressed, worker); @@ -62,5 +67,13 @@ protected override void Handle(BuildInspectorHeaderEvent eventData) } } } + + protected override bool OnLoaded() + { + WikiLinkButtonExtensions.ComponentLocale = Mod.GetLocaleString("Tooltip.WikiHyperlink.Component"); + WikiLinkButtonExtensions.ProtoFluxLocale = Mod.GetLocaleString("Tooltip.WikiHyperlink.ProtoFlux"); + + return base.OnLoaded(); + } } } \ No newline at end of file