diff --git a/Directory.Build.props b/Directory.Build.props
index 2b86539e..875e9add 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -1,6 +1,6 @@
- 0.29.0
+ 0.30.0MonkeyLoader.ResoniteTrue
diff --git a/MonkeyLoader.GamePacks.Resonite.sln b/MonkeyLoader.GamePacks.Resonite.sln
index b2643c29..d9ee7d40 100644
--- a/MonkeyLoader.GamePacks.Resonite.sln
+++ b/MonkeyLoader.GamePacks.Resonite.sln
@@ -32,6 +32,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{
.github\workflows\publish.yml = .github\workflows\publish.yml
EndProjectSection
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MonkeyLoader.Resonite.Core", "MonkeyLoader.Resonite.Core\MonkeyLoader.Resonite.Core.csproj", "{1DD99E73-5628-4400-84B3-D175B03A99C5}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -54,6 +56,10 @@ Global
{E5612DD7-954D-43A8-A0F0-F51E3144A994}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E5612DD7-954D-43A8-A0F0-F51E3144A994}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E5612DD7-954D-43A8-A0F0-F51E3144A994}.Release|Any CPU.Build.0 = Release|Any CPU
+ {1DD99E73-5628-4400-84B3-D175B03A99C5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1DD99E73-5628-4400-84B3-D175B03A99C5}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1DD99E73-5628-4400-84B3-D175B03A99C5}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1DD99E73-5628-4400-84B3-D175B03A99C5}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/MonkeyLoader.Resonite.Integration/DestroyOnUserLeaveExtensions.cs b/MonkeyLoader.Resonite.Core/DestroyOnUserLeaveExtensions.cs
similarity index 92%
rename from MonkeyLoader.Resonite.Integration/DestroyOnUserLeaveExtensions.cs
rename to MonkeyLoader.Resonite.Core/DestroyOnUserLeaveExtensions.cs
index 7a0bb66f..6639bb87 100644
--- a/MonkeyLoader.Resonite.Integration/DestroyOnUserLeaveExtensions.cs
+++ b/MonkeyLoader.Resonite.Core/DestroyOnUserLeaveExtensions.cs
@@ -1,5 +1,6 @@
using FrooxEngine;
using System.Linq;
+using System.Runtime.CompilerServices;
namespace MonkeyLoader.Resonite
{
@@ -7,6 +8,7 @@ namespace MonkeyLoader.Resonite
/// Contains an extension method to add components targeting
/// the local user to mod additions that rely on the local user being there to work.
///
+ [TypeForwardedFrom("MonkeyLoader.Resonite.Integration")]
public static class DestroyOnUserLeaveExtensions
{
///
diff --git a/MonkeyLoader.Resonite.Integration/DynamicVariableExtensions.cs b/MonkeyLoader.Resonite.Core/DynamicVariableExtensions.cs
similarity index 97%
rename from MonkeyLoader.Resonite.Integration/DynamicVariableExtensions.cs
rename to MonkeyLoader.Resonite.Core/DynamicVariableExtensions.cs
index 8a86cdc3..57f61202 100644
--- a/MonkeyLoader.Resonite.Integration/DynamicVariableExtensions.cs
+++ b/MonkeyLoader.Resonite.Core/DynamicVariableExtensions.cs
@@ -6,6 +6,7 @@
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
+using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
@@ -15,6 +16,7 @@ namespace MonkeyLoader.Resonite
/// Contains extension methods related to s
/// and their variables.
///
+ [TypeForwardedFrom("MonkeyLoader.Resonite.Integration")]
public static class DynamicVariableExtensions
{
//public static DynamicReference CreateReferenceVariable(this SyncRef syncRef, string name, bool overrideOnLink = false, bool persistent = true)
@@ -121,7 +123,7 @@ public static IEnumerable GetAvailableSpaces(this Slot slo
/// All full Dynamic Variable identities that apply to this that the given can be assigned to.
///
public static IEnumerable GetAvailableVariableIdentities(this Slot slot, Type type)
- => slot.GetAvailableSpaces().SelectMany(space => space.GetVariableIdentities(type)).ToArray();
+ => [.. slot.GetAvailableSpaces().SelectMany(space => space.GetVariableIdentities(type))];
///
/// Gets all full Dynamic Variable
@@ -133,7 +135,7 @@ public static IEnumerable GetAvailableVariableIdentitie
/// All full Dynamic Variable identities that apply to this that have the given .
///
public static IEnumerable GetAvailableVariableIdentities(this Slot slot, string name)
- => slot.GetAvailableSpaces().SelectMany(space => space.GetVariableIdentities(name)).ToArray();
+ => [.. slot.GetAvailableSpaces().SelectMany(space => space.GetVariableIdentities(name))];
///
/// Gets all full Dynamic Variable
@@ -144,7 +146,7 @@ public static IEnumerable GetAvailableVariableIdentitie
/// All full Dynamic Variable identities that apply to this that can be assigned to.
///
public static IEnumerable GetAvailableVariableIdentities(this Slot slot)
- => slot.GetAvailableSpaces().SelectMany(GetVariableIdentities).ToArray();
+ => [.. slot.GetAvailableSpaces().SelectMany(GetVariableIdentities)];
///
/// Gets all full Dynamic Variable
@@ -161,7 +163,7 @@ public static IEnumerable GetAvailableVariableIdentitie
/// The to find all applicable full Dynamic Variable identities for.
/// All full Dynamic Variable identities that apply to this .
public static IEnumerable GetAvailableVariableIdentities(this Slot slot)
- => slot.GetAvailableSpaces().SelectMany(GetVariableIdentities).ToArray();
+ => [.. slot.GetAvailableSpaces().SelectMany(GetVariableIdentities)];
///
/// Gets the of this
@@ -337,7 +339,7 @@ public static IEnumerable GetVariableIdentities(this
/// The type that must be assignable to the variables.
/// All full Dynamic Variable identities associated with this that the given can be assigned to.
public static IEnumerable GetVariableIdentities(this DynamicVariableSpace space, Type type)
- => space.GetVariableIdentities().Where(id => id.Type.IsAssignableFrom(type)).ToArray();
+ => [.. space.GetVariableIdentities().Where(id => id.Type.IsAssignableFrom(type))];
///
/// Gets all full Dynamic Variable identities
@@ -348,7 +350,7 @@ public static IEnumerable GetVariableIdentities(this Dy
/// The name that the variable identities must have.
/// All full Dynamic Variable identities associated with this that have the given .
public static IEnumerable GetVariableIdentities(this DynamicVariableSpace space, string name)
- => space.GetVariableIdentities().Where(id => id.Name == name).ToArray();
+ => [.. space.GetVariableIdentities().Where(id => id.Name == name)];
//public static DynamicField? CreateVariable(this IField field, string name, bool overrideOnLink = false, bool persistent = true)
//{
diff --git a/MonkeyLoader.Resonite.Integration/DynamicVariableIdentity.cs b/MonkeyLoader.Resonite.Core/DynamicVariableIdentity.cs
similarity index 82%
rename from MonkeyLoader.Resonite.Integration/DynamicVariableIdentity.cs
rename to MonkeyLoader.Resonite.Core/DynamicVariableIdentity.cs
index 935b1d69..29920049 100644
--- a/MonkeyLoader.Resonite.Integration/DynamicVariableIdentity.cs
+++ b/MonkeyLoader.Resonite.Core/DynamicVariableIdentity.cs
@@ -1,14 +1,17 @@
using FrooxEngine;
using System;
using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.CompilerServices;
using System.Text;
namespace MonkeyLoader.Resonite
{
///
- /// Fully describes the identity of a Dynamic Variable based on itsn Type,
+ /// Fully describes the identity of a Dynamic Variable based on its Type,
/// Name, and the Space it's a part of.
///
+ [TypeForwardedFrom("MonkeyLoader.Resonite.Integration")]
public readonly struct DynamicVariableIdentity : IEquatable
{
///
@@ -83,6 +86,22 @@ public override readonly int GetHashCode()
///
public override readonly string ToString()
- => $"Dynamic Variable {Name} of Type {Type.CompactDescription()} on {Space.GetReferenceLabel()}";
+ => $"Dynamic Variable {Name} of Type {CompactDescription(Type)} on {Space.GetReferenceLabel()}";
+
+ ///
+ /// Gets a compact, human-readable description of a type.
+ ///
+ /// The type to format.
+ /// The human-readable description of the type.
+ private static string CompactDescription(Type type)
+ {
+ if (type is null)
+ return "null";
+
+ if (type.IsGenericType)
+ return $"{type.Name}<{string.Join(", ", type.GetGenericArguments().Select(CompactDescription))}>";
+
+ return type.Name;
+ }
}
}
\ No newline at end of file
diff --git a/MonkeyLoader.Resonite.Core/FieldExtensions.cs b/MonkeyLoader.Resonite.Core/FieldExtensions.cs
new file mode 100644
index 00000000..9d0e5a84
--- /dev/null
+++ b/MonkeyLoader.Resonite.Core/FieldExtensions.cs
@@ -0,0 +1,36 @@
+using FrooxEngine;
+using System;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+using System.Text;
+
+namespace MonkeyLoader.Resonite
+{
+ ///
+ /// Contains extension methods for fields
+ /// and other world elements
+ ///
+ [TypeForwardedFrom("MonkeyLoader.Resonite.Integration")]
+ public static class FieldExtensions
+ {
+ ///
+ /// Creates a label describing the reference as a would.
+ ///
+ /// The reference to label.
+ /// A label for the reference if it is not null; otherwise, <i>null</i>.
+ public static string GetReferenceLabel(this IWorldElement? target)
+ {
+ if (target is null)
+ return "null";
+
+ if (target is Slot targetSlot)
+ return $"{targetSlot.Name} ({target.ReferenceID})";
+
+ var component = target.FindNearestParent();
+ var slot = component?.Slot ?? target.FindNearestParent();
+
+ var arg = (component is not null && component != target) ? ("on " + component.Name + " on " + slot.Name) : ((slot is null) ? "" : ("on " + slot.Name));
+ return (target is not SyncElement syncElement) ? $"{target.Name ?? target.GetType().Name} {arg} ({target.ReferenceID})" : $"{syncElement.NameWithPath} {arg} ({target.ReferenceID})";
+ }
+ }
+}
\ No newline at end of file
diff --git a/MonkeyLoader.Resonite.Core/KeyedComponentHelper.cs b/MonkeyLoader.Resonite.Core/KeyedComponentHelper.cs
new file mode 100644
index 00000000..6cd22f42
--- /dev/null
+++ b/MonkeyLoader.Resonite.Core/KeyedComponentHelper.cs
@@ -0,0 +1,102 @@
+using FrooxEngine;
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.Runtime.CompilerServices;
+
+namespace MonkeyLoader.Resonite
+{
+ ///
+ /// Contains extension methods to deal with keyed
+ /// s in s.
+ ///
+ [TypeForwardedFrom("MonkeyLoader.Resonite.Integration")]
+ public static class KeyedComponentHelper
+ {
+ ///
+ /// Gets or creates
+ /// a keyed component, based on the situation and parameters.
+ ///
+ /// The existing or newly created component.
+ ///
+ /// When an incompatible component is associated with the given
+ /// and was .
+ ///
+ ///
+ public static T GetKeyedComponentOrCreate(this Slot slot, string key, Action? onCreated = null,
+ int version = 0, bool replaceExisting = false, bool updateExisting = false)
+ where T : Component, new()
+ {
+ if (!slot.TryGetKeyedComponentOrCreate(key, out var component, onCreated, version, replaceExisting, updateExisting))
+ throw new InvalidOperationException("An incompatible component is stored under the key " + key + $"\nExisting: {component}");
+
+ return component;
+ }
+
+ ///
+ /// Tries to get or create
+ /// a keyed component, based on the situation and parameters.
+ ///
+ ///
+ /// This behavior was adapted from .
+ ///
+ /// Consider that these component-associations will be saved with the .
+ /// Make sure that this is really necessary for what you're attempting to do.
+ ///
+ /// The type of the component to get or create.
+ /// The slot to attach the component to when necessary.
+ /// The unique key (to) associate(d) with the component.
+ ///
+ /// The component associated with the given if this call returns ;
+ /// otherwise, when an incompatible component is associated with it
+ /// and was .
+ ///
+ ///
+ /// The optional configuration action to call when the component had to be created,
+ /// or when its saved version is lower than the given number.
+ ///
+ /// The version number to associate with the component after this call.
+ /// Whether to replace a different component associated with the given with this one.
+ ///
+ /// Whether to call even if the component already exists.
+ /// If the given number is greater than zero and the saved version is lower, this will always be done.
+ ///
+ /// if the keyed component was found or created; otherwise, .
+ public static bool TryGetKeyedComponentOrCreate(this Slot slot, string key, [NotNullWhen(true)] out T? component,
+ Action? onCreated = null, int version = 0, bool replaceExisting = false, bool updateExisting = false)
+ where T : Component, new()
+ {
+ var keyedComponent = slot.World.KeyOwner(key);
+
+ if (keyedComponent is not null)
+ {
+ if (keyedComponent is T typedComponent)
+ {
+ if (version > 0 && slot.World.KeyVersion(key) < version)
+ {
+ updateExisting = true;
+ slot.World.RequestKey(typedComponent, key, version, false);
+ }
+
+ if (updateExisting)
+ onCreated?.Invoke(typedComponent);
+
+ component = typedComponent;
+ return true;
+ }
+
+ if (!replaceExisting)
+ {
+ component = null;
+ return false;
+ }
+ }
+
+ component = slot.AttachComponent();
+
+ slot.World.RequestKey(component, key, version, false);
+ onCreated?.Invoke(component);
+
+ return true;
+ }
+ }
+}
\ No newline at end of file
diff --git a/MonkeyLoader.Resonite.Core/MonkeyLoader.Resonite.Core.csproj b/MonkeyLoader.Resonite.Core/MonkeyLoader.Resonite.Core.csproj
new file mode 100644
index 00000000..b1da2398
--- /dev/null
+++ b/MonkeyLoader.Resonite.Core/MonkeyLoader.Resonite.Core.csproj
@@ -0,0 +1,39 @@
+
+
+ library
+ false
+ true
+
+
+
+ MonkeyLoader.GamePacks.Resonite.Core
+ Resonite Game Pack Core
+ Banane9
+ This package provides the non-ML specific helpers for modding the game Resonite, which uses FrooxEngine.
+It contains many useful features for the Developers of mods and their Users alike.
+
+This package is only intended for use with non-ML mods.
+For mods targetting ML, this library is part of the Resonite Game Pack.
+ mod;mods;modding;mod;loader;monkeyloader;resonite;tools;tool;toolkit;helper;helpers;standalone
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/MonkeyLoader.Resonite.Core/README.md b/MonkeyLoader.Resonite.Core/README.md
new file mode 100644
index 00000000..2bc5b13a
--- /dev/null
+++ b/MonkeyLoader.Resonite.Core/README.md
@@ -0,0 +1,8 @@
+Resonite Game Pack Toolkit
+==========================
+
+This package provides the non-ML specific helpers for modding the game [Resonite](https://resonite.com/), which uses FrooxEngine.
+It contains many useful features for the Developers of mods and their Users alike.
+
+This package is only intended for use with non-ML mods.
+For mods targetting ML, this library is part of the Resonite Game Pack.
\ No newline at end of file
diff --git a/MonkeyLoader.Resonite.Core/UI/ButtonRefExtensions.cs b/MonkeyLoader.Resonite.Core/UI/ButtonRefExtensions.cs
new file mode 100644
index 00000000..1e2bdebe
--- /dev/null
+++ b/MonkeyLoader.Resonite.Core/UI/ButtonRefExtensions.cs
@@ -0,0 +1,138 @@
+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)
+
+namespace MonkeyLoader.Resonite.UI
+{
+ ///
+ /// Contains extension methods that simplify
+ /// the creation of s with s.
+ ///
+ [TypeForwardedFrom("MonkeyLoader.Resonite.Integration")]
+ public static class ButtonRefExtensions
+ {
+ ///
+ public static Button ButtonRef(this UIBuilder builder, in LocaleString text,
+ ButtonEventHandler callback, T argument, float doublePressDelay = 0)
+ where T : class, IWorldElement
+ => builder.Button(text).WithRefRelay(callback, argument, doublePressDelay);
+
+ ///
+ /// Creates a with text and adds
+ /// a to it using the given parameters.
+ ///
+ ///
+ public static Button ButtonRef(this UIBuilder builder, in LocaleString text, in colorX? buttonTint,
+ ButtonEventHandler callback, T argument, float doublePressDelay = 0)
+ where T : class, IWorldElement
+ => builder.Button(text, buttonTint).WithRefRelay(callback, argument, doublePressDelay);
+
+ ///
+ public static Button ButtonRef(this UIBuilder builder, Uri spriteUrl, in LocaleString text,
+ ButtonEventHandler callback, T argument, float doublePressDelay = 0)
+ where T : class, IWorldElement
+ => builder.Button(spriteUrl, text).WithRefRelay(callback, argument, doublePressDelay);
+
+ ///
+ public static Button ButtonRef(this UIBuilder builder, Uri spriteUrl, in LocaleString text, in colorX? buttonTint, in colorX spriteTint,
+ ButtonEventHandler callback, T argument, float doublePressDelay = 0)
+ where T : class, IWorldElement
+ => builder.Button(spriteUrl, text, buttonTint, spriteTint).WithRefRelay(callback, argument, doublePressDelay);
+
+ ///
+ public static Button ButtonRef(this UIBuilder builder, Uri spriteUrl,
+ ButtonEventHandler callback, T argument, float doublePressDelay = 0)
+ where T : class, IWorldElement
+ => builder.Button(spriteUrl).WithRefRelay(callback, argument, doublePressDelay);
+
+ ///
+ public static Button ButtonRef(this UIBuilder builder, Uri spriteUrl, in colorX? buttonTint,
+ ButtonEventHandler callback, T argument, float doublePressDelay = 0)
+ where T : class, IWorldElement
+ => builder.Button(spriteUrl, in buttonTint).WithRefRelay(callback, argument, doublePressDelay);
+
+ ///
+ /// Creates a with a sprite and adds
+ /// a to it using the given parameters.
+ ///
+ ///
+ public static Button ButtonRef(this UIBuilder builder, Uri spriteUrl, in colorX? buttonTint, in colorX spriteTint,
+ ButtonEventHandler callback, T argument, float doublePressDelay = 0)
+ where T : class, IWorldElement
+ => builder.Button(spriteUrl, in buttonTint, in spriteTint).WithRefRelay(callback, argument, doublePressDelay);
+
+ ///
+ public static Button ButtonRef(this UIBuilder builder, IAssetProvider sprite, in LocaleString text,
+ ButtonEventHandler callback, T argument, float doublePressDelay = 0)
+ where T : class, IWorldElement
+ => builder.Button(sprite, text).WithRefRelay(callback, argument, doublePressDelay);
+
+ ///
+ public static Button ButtonRef(this UIBuilder builder, IAssetProvider sprite, in colorX? buttonTint, in colorX spriteTint,
+ ButtonEventHandler callback, T argument, float doublePressDelay = 0)
+ where T : class, IWorldElement
+ => builder.Button(sprite, in buttonTint, in spriteTint).WithRefRelay(callback, argument, doublePressDelay);
+
+ ///
+ /// Creates a with a sprite and text, and adds
+ /// a to it using the given parameters.
+ ///
+ /// The type of the reference argument.
+ /// The builder to use for creating the button.
+ /// The url for the sprite displayed on the button.
+ /// The sprite displayed on the button.
+ /// The tint of the sprite.
+ /// The background color of the button.
+ /// The text displayed on the button.
+ /// The ratio of the button to use for the sprite.
+ /// The ratio of the button to keep as space between sprite and text. The sprite and text ratios are decreased by half of it.
+ ///
+ public static Button ButtonRef(this UIBuilder builder, IAssetProvider sprite, in colorX spriteTint, in LocaleString text,
+ ButtonEventHandler callback, T argument, float doublePressDelay = 0, float buttonTextSplit = .33333f, float buttonTextSplitGap = .05f)
+ where T : class, IWorldElement
+ => builder.Button(sprite, in spriteTint, text, buttonTextSplit, buttonTextSplitGap).WithRefRelay(callback, argument, doublePressDelay);
+
+ ///
+ [Obsolete("Use WithRefRelay instead.")]
+ public static TButton SetupRefRelay(this TButton button,
+ ButtonEventHandler callback, TArgument argument, float doublePressDelay = 0)
+ where TButton : IButton
+ where TArgument : class, IWorldElement
+ => button.WithRefRelay(callback, argument, doublePressDelay);
+
+ ///
+ /// Creates a with the given parameters for this button.
+ ///
+ /// The specific type of the button.
+ /// The type of the reference argument.
+ /// The button to set up with a .
+ /// The ButtonPressed handler for the created relay.
+ /// The Argument for the created relay.
+ /// The DoublePressDelay for the created relay.
+ /// The unchanged button.
+ public static TButton WithRefRelay(this TButton button,
+ ButtonEventHandler callback, TArgument argument, float doublePressDelay = 0)
+ where TButton : IButton
+ where TArgument : class, IWorldElement
+ {
+ var relay = button.Slot.AttachComponent>();
+ relay.DoublePressDelay.Value = doublePressDelay;
+ relay.ButtonPressed.Target = callback;
+ relay.Argument.Target = argument;
+
+ return button;
+ }
+ }
+}
+
+#pragma warning restore CS1572 // XML comment has a param tag, but there is no parameter by that name
+#pragma warning restore CS1573 // Parameter has no matching param tag in the XML comment (but other parameters do)
\ No newline at end of file
diff --git a/MonkeyLoader.Resonite.Integration/UI/CanvasExtensions.cs b/MonkeyLoader.Resonite.Core/UI/CanvasExtensions.cs
similarity index 97%
rename from MonkeyLoader.Resonite.Integration/UI/CanvasExtensions.cs
rename to MonkeyLoader.Resonite.Core/UI/CanvasExtensions.cs
index dfdb6849..e518f743 100644
--- a/MonkeyLoader.Resonite.Integration/UI/CanvasExtensions.cs
+++ b/MonkeyLoader.Resonite.Core/UI/CanvasExtensions.cs
@@ -3,6 +3,7 @@
using FrooxEngine.UIX;
using System;
using System.Collections.Generic;
+using System.Runtime.CompilerServices;
using System.Text;
namespace MonkeyLoader.Resonite.UI
@@ -11,6 +12,7 @@ namespace MonkeyLoader.Resonite.UI
/// Contains helpful methods to deal with UIX es,
/// their s, and related types.
///
+ [TypeForwardedFrom("MonkeyLoader.Resonite.Integration")]
public static class CanvasExtensions
{
///
diff --git a/MonkeyLoader.Resonite.Core/UI/LocalActionButtonExtensions.cs b/MonkeyLoader.Resonite.Core/UI/LocalActionButtonExtensions.cs
new file mode 100644
index 00000000..bfe31a8a
--- /dev/null
+++ b/MonkeyLoader.Resonite.Core/UI/LocalActionButtonExtensions.cs
@@ -0,0 +1,298 @@
+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.
+ ///
+ ///
+ /// Due to their nature, they will only work while the that creates them hasn't left the session.
+ /// As such, they will be destroyed when the local user leaves, and won't be saved either (by marking them non-persistent).
+ ///
+ [TypeForwardedFrom("MonkeyLoader.Resonite.Integration")]
+ public static class LocalActionButtonExtensions
+ {
+ ///
+ /// The prefix that a 's text must have to define a tooltip label.
+ ///
+ public const string CommentTextPrefix = "TooltipperyLabel:";
+
+ internal static RegisterLabelForButtonFunc? RegisterLabelForButton { get; set; }
+
+ ///
+ public static Button LocalActionButton(this UIBuilder builder, in LocaleString text, Action
+ [TypeForwardedFrom("MonkeyLoader.Resonite.Integration")]
public readonly struct NineSlice
{
///
diff --git a/MonkeyLoader.Resonite.Integration/UI/RadiantUIStyleExtensions.cs b/MonkeyLoader.Resonite.Core/UI/RadiantUIStyleExtensions.cs
similarity index 95%
rename from MonkeyLoader.Resonite.Integration/UI/RadiantUIStyleExtensions.cs
rename to MonkeyLoader.Resonite.Core/UI/RadiantUIStyleExtensions.cs
index e132cc19..b03e4c8e 100644
--- a/MonkeyLoader.Resonite.Integration/UI/RadiantUIStyleExtensions.cs
+++ b/MonkeyLoader.Resonite.Core/UI/RadiantUIStyleExtensions.cs
@@ -2,6 +2,7 @@
using FrooxEngine.UIX;
using System;
using System.Collections.Generic;
+using System.Runtime.CompilerServices;
using System.Text;
namespace MonkeyLoader.Resonite.UI
@@ -9,6 +10,7 @@ namespace MonkeyLoader.Resonite.UI
///
/// Contains extension method versions of methods.
///
+ [TypeForwardedFrom("MonkeyLoader.Resonite.Integration")]
public static class RadiantUIStyleExtensions
{
///
diff --git a/MonkeyLoader.Resonite.Integration/UI/Slices.cs b/MonkeyLoader.Resonite.Core/UI/Slices.cs
similarity index 97%
rename from MonkeyLoader.Resonite.Integration/UI/Slices.cs
rename to MonkeyLoader.Resonite.Core/UI/Slices.cs
index 6444cbd3..df45e15e 100644
--- a/MonkeyLoader.Resonite.Integration/UI/Slices.cs
+++ b/MonkeyLoader.Resonite.Core/UI/Slices.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
@@ -12,8 +13,39 @@ namespace MonkeyLoader.Resonite.UI
///
/// Use with: using static MonkeyLoader.Resonite.UI.Slices;
///
+ [TypeForwardedFrom("MonkeyLoader.Resonite.Integration")]
public static class Slices
{
+ ///
+ /// Alias for .
+ ///
+ public const Vertical Bottom = Vertical.Bottom;
+
+ ///
+ /// Alias for .
+ ///
+ public const Horizontal Center = Horizontal.Center;
+
+ ///
+ /// Alias for .
+ ///
+ public const Horizontal Left = Horizontal.Left;
+
+ ///
+ /// Alias for .
+ ///
+ public const Vertical Middle = Vertical.Middle;
+
+ ///
+ /// Alias for .
+ ///
+ public const Horizontal Right = Horizontal.Right;
+
+ ///
+ /// Alias for .
+ ///
+ public const Vertical Top = Vertical.Top;
+
///
/// Contains more "fluent" definitions for first half / third.
///
@@ -46,36 +78,6 @@ public static class Second
public const Third Third = Slices.Third.Second;
}
- ///
- /// Alias for .
- ///
- public const Vertical Top = Vertical.Top;
-
- ///
- /// Alias for .
- ///
- public const Vertical Bottom = Vertical.Bottom;
-
- ///
- /// Alias for .
- ///
- public const Vertical Middle = Vertical.Middle;
-
- ///
- /// Alias for .
- ///
- public const Horizontal Left = Horizontal.Left;
-
- ///
- /// Alias for .
- ///
- public const Horizontal Right = Horizontal.Right;
-
- ///
- /// Alias for .
- ///
- public const Horizontal Center = Horizontal.Center;
-
///
/// Distinguishes halfs.
///
@@ -92,6 +94,27 @@ public enum Half
Second
}
+ ///
+ /// Distinguishes horizontal slices.
+ ///
+ public enum Horizontal
+ {
+ ///
+ /// The 1st horizontal slice.
+ ///
+ Left,
+
+ ///
+ /// The 2nd horizontal slice.
+ ///
+ Center,
+
+ ///
+ /// The 3rd horizontal slice.
+ ///
+ Right
+ }
+
///
/// Distinguishes thirds.
///
@@ -133,26 +156,5 @@ public enum Vertical
///
Top
}
-
- ///
- /// Distinguishes horizontal slices.
- ///
- public enum Horizontal
- {
- ///
- /// The 1st horizontal slice.
- ///
- Left,
-
- ///
- /// The 2nd horizontal slice.
- ///
- Center,
-
- ///
- /// The 3rd horizontal slice.
- ///
- Right
- }
}
}
\ No newline at end of file
diff --git a/MonkeyLoader.Resonite.Integration/UI/UIXExtensions.cs b/MonkeyLoader.Resonite.Core/UI/UIXExtensions.cs
similarity index 94%
rename from MonkeyLoader.Resonite.Integration/UI/UIXExtensions.cs
rename to MonkeyLoader.Resonite.Core/UI/UIXExtensions.cs
index 4fd34811..c58e918b 100644
--- a/MonkeyLoader.Resonite.Integration/UI/UIXExtensions.cs
+++ b/MonkeyLoader.Resonite.Core/UI/UIXExtensions.cs
@@ -1,6 +1,7 @@
using FrooxEngine.UIX;
using System;
using System.Collections.Generic;
+using System.Runtime.CompilerServices;
using System.Text;
namespace MonkeyLoader.Resonite.UI
@@ -8,6 +9,7 @@ namespace MonkeyLoader.Resonite.UI
///
/// Contains miscellaneous extension methods for UIX types that couldn't be categorized further.
///
+ [TypeForwardedFrom("MonkeyLoader.Resonite.Integration")]
public static class UIXExtensions
{
///
diff --git a/MonkeyLoader.Resonite.Integration/DataFeeds/Settings/ModSettingStandaloneFacet.cs b/MonkeyLoader.Resonite.Integration/DataFeeds/Settings/ModSettingStandaloneFacet.cs
index 7684bfda..73b4480a 100644
--- a/MonkeyLoader.Resonite.Integration/DataFeeds/Settings/ModSettingStandaloneFacet.cs
+++ b/MonkeyLoader.Resonite.Integration/DataFeeds/Settings/ModSettingStandaloneFacet.cs
@@ -19,8 +19,8 @@ internal sealed class ModSettingStandaloneFacet : ResoniteMonkey Authors { get; } = ["Nytra"];
diff --git a/MonkeyLoader.Resonite.Integration/FieldExtensions.cs b/MonkeyLoader.Resonite.Integration/FieldConfigKeySyncExtensions.cs
similarity index 91%
rename from MonkeyLoader.Resonite.Integration/FieldExtensions.cs
rename to MonkeyLoader.Resonite.Integration/FieldConfigKeySyncExtensions.cs
index c33f8848..efdc29dd 100644
--- a/MonkeyLoader.Resonite.Integration/FieldExtensions.cs
+++ b/MonkeyLoader.Resonite.Integration/FieldConfigKeySyncExtensions.cs
@@ -1,20 +1,15 @@
-using Elements.Core;
-using FrooxEngine;
+using FrooxEngine;
using MonkeyLoader.Configuration;
using MonkeyLoader.Resonite.Configuration;
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
namespace MonkeyLoader.Resonite
{
///
/// Contains extension methods for fields
- /// and other world elements
+ /// that allow syncing them with s.
///
- public static class FieldExtensions
+ public static class FieldConfigKeySyncExtensions
{
///
/// The prefix for the SetValue
@@ -26,26 +21,6 @@ public static class FieldExtensions
///
public const string WriteBackPrefix = "SyncedField.WriteBack";
- ///
- /// Creates a label describing the reference as a would.
- ///
- /// The reference to label.
- /// A label for the reference if it is not null; otherwise, <i>null</i>.
- public static string GetReferenceLabel(this IWorldElement? target)
- {
- if (target is null)
- return "null";
-
- if (target is Slot targetSlot)
- return $"{targetSlot.Name} ({target.ReferenceID})";
-
- var component = target.FindNearestParent();
- var slot = component?.Slot ?? target.FindNearestParent();
-
- var arg = (component is not null && component != target) ? ("on " + component.Name + " on " + slot.Name) : ((slot is null) ? "" : ("on " + slot.Name));
- return (target is not SyncElement syncElement) ? $"{target.Name ?? target.GetType().Name} {arg} ({target.ReferenceID})" : $"{syncElement.NameWithPath} {arg} ({target.ReferenceID})";
- }
-
///
/// Synchronizes the 's Value with that of the .
///
diff --git a/MonkeyLoader.Resonite.Integration/MonkeyLoader.Resonite.Integration.csproj b/MonkeyLoader.Resonite.Integration/MonkeyLoader.Resonite.Integration.csproj
index becfaefb..7e1aae87 100644
--- a/MonkeyLoader.Resonite.Integration/MonkeyLoader.Resonite.Integration.csproj
+++ b/MonkeyLoader.Resonite.Integration/MonkeyLoader.Resonite.Integration.csproj
@@ -6,11 +6,11 @@
MonkeyLoader.GamePacks.ResoniteResonite Game Pack
- Banane9, Nytra
+ Banane9;NytraThis Game Pack for MonkeyLoader provides basic hooks for modding the game Resonite, which uses FrooxEngine.
It provides hooks for the beginning of initialization, when initialization is done, and when the game shuts down.
Additionally it contains many useful features for Users and Developers alike.
- mod; mods; modding; mod; loader; monkeyloader; resonite; integration
+ mod;mods;modding;mod;loader;monkeyloader;resonite;integration;tools;tool;toolkit;helper;helpers$(TargetsForTfmSpecificContentInPackage);AddExtraFilesToPackage
@@ -23,6 +23,7 @@ Additionally it contains many useful features for Users and Developers alike.
+
@@ -51,6 +52,7 @@ Additionally it contains many useful features for Users and Developers alike.
-
+
+
\ No newline at end of file
diff --git a/MonkeyLoader.Resonite.Integration/MovedTypes.cs b/MonkeyLoader.Resonite.Integration/MovedTypes.cs
new file mode 100644
index 00000000..a46fb296
--- /dev/null
+++ b/MonkeyLoader.Resonite.Integration/MovedTypes.cs
@@ -0,0 +1,19 @@
+using MonkeyLoader.Resonite;
+using MonkeyLoader.Resonite.UI;
+using System.Runtime.CompilerServices;
+
+// MonkeyLoader.Resonite forwards
+[assembly: TypeForwardedTo(typeof(DestroyOnUserLeaveExtensions))]
+[assembly: TypeForwardedTo(typeof(DynamicVariableExtensions))]
+[assembly: TypeForwardedTo(typeof(DynamicVariableIdentity))]
+[assembly: TypeForwardedTo(typeof(FieldExtensions))]
+[assembly: TypeForwardedTo(typeof(KeyedComponentHelper))]
+
+// MonkeyLoader.Resonite.UI forwards
+[assembly: TypeForwardedTo(typeof(ButtonRefExtensions))]
+[assembly: TypeForwardedTo(typeof(CanvasExtensions))]
+[assembly: TypeForwardedTo(typeof(LocalActionButtonExtensions))]
+[assembly: TypeForwardedTo(typeof(RadiantUIStyleExtensions))]
+[assembly: TypeForwardedTo(typeof(UIXExtensions))]
+[assembly: TypeForwardedTo(typeof(NineSlice))]
+[assembly: TypeForwardedTo(typeof(Slices))]
\ No newline at end of file
diff --git a/MonkeyLoader.Resonite.Integration/SharedComponentHelper.cs b/MonkeyLoader.Resonite.Integration/SharedComponentHelper.cs
deleted file mode 100644
index dbe3d022..00000000
--- a/MonkeyLoader.Resonite.Integration/SharedComponentHelper.cs
+++ /dev/null
@@ -1,46 +0,0 @@
-using FrooxEngine;
-using MonkeyLoader.Resonite.Configuration;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace MonkeyLoader.Resonite
-{
- public static class SharedComponentHelper
- {
- public static T GetSharedComponentOrCreate(this Slot slot, string sharedKey, Action onCreate,
- int version = 0, bool replaceExisting = false, bool updateExisting = false) where T : Component, new()
- {
- var component = slot.World.KeyOwner(sharedKey);
-
- if (component is not null)
- {
- if (component is T typedComponent)
- {
- if (version > 0 && slot.World.KeyVersion(sharedKey) < version)
- {
- updateExisting = true;
- slot.World.RequestKey(typedComponent, sharedKey, version, false);
- }
-
- if (updateExisting)
- onCreate(typedComponent);
-
- return typedComponent;
- }
-
- if (!replaceExisting)
- throw new Exception("An incompatible component is stored under the key " + sharedKey + $"\nExisting: {component}");
- }
-
- var attachedComponent = slot.AttachComponent();
- onCreate(attachedComponent);
-
- slot.World.RequestKey(attachedComponent, sharedKey, version, false);
-
- return attachedComponent;
- }
- }
-}
\ No newline at end of file
diff --git a/MonkeyLoader.Resonite.Integration/UI/ButtonRefExtensions.cs b/MonkeyLoader.Resonite.Integration/UI/ButtonRefExtensions.cs
deleted file mode 100644
index ea3635ee..00000000
--- a/MonkeyLoader.Resonite.Integration/UI/ButtonRefExtensions.cs
+++ /dev/null
@@ -1,72 +0,0 @@
-using Elements.Core;
-using FrooxEngine;
-using FrooxEngine.UIX;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace MonkeyLoader.Resonite.UI
-{
- public static class ButtonRefExtensions
- {
- public static Button ButtonRef(this UIBuilder ui, Uri spriteUrl, in colorX? buttonTint,
- ButtonEventHandler callback, T argument, float doublePressDelay = 0)
- where T : class, IWorldElement
- => ui.Button(spriteUrl, in buttonTint).SetupRefRelay(callback, argument, doublePressDelay);
-
- public static Button ButtonRef(this UIBuilder ui, Uri spriteUrl, in colorX? buttonTint, in colorX spriteTint,
- ButtonEventHandler callback, T argument, float doublePressDelay = 0)
- where T : class, IWorldElement
- => ui.Button(spriteUrl, in buttonTint, in spriteTint).SetupRefRelay(callback, argument, doublePressDelay);
-
- public static Button ButtonRef(this UIBuilder ui, Uri spriteUrl,
- ButtonEventHandler callback, T argument, float doublePressDelay = 0)
- where T : class, IWorldElement
- => ui.Button(spriteUrl).SetupRefRelay(callback, argument, doublePressDelay);
-
- public static Button ButtonRef(this UIBuilder ui, IAssetProvider sprite, LocaleString text,
- ButtonEventHandler callback, T argument, float doublePressDelay = 0)
- where T : class, IWorldElement
- => ui.Button(sprite, text).SetupRefRelay(callback, argument, doublePressDelay);
-
- public static Button ButtonRef(this UIBuilder ui, IAssetProvider sprite, in colorX spriteTint, LocaleString text,
- ButtonEventHandler callback, T argument, float doublePressDelay = 0, float buttonTextSplit = .33333f, float buttonTextSplitGap = .05f)
- where T : class, IWorldElement
- => ui.Button(sprite, in spriteTint, text, buttonTextSplit, buttonTextSplitGap).SetupRefRelay(callback, argument, doublePressDelay);
-
- public static Button ButtonRef(this UIBuilder ui, IAssetProvider sprite, in colorX? buttonTint, in colorX spriteTint,
- ButtonEventHandler callback, T argument, float doublePressDelay = 0)
- where T : class, IWorldElement
- => ui.Button(sprite, in buttonTint, in spriteTint).SetupRefRelay(callback, argument, doublePressDelay);
-
- public static Button ButtonRef(this UIBuilder ui, Uri icon, LocaleString text,
- ButtonEventHandler callback, T argument, float doublePressDelay = 0)
- where T : class, IWorldElement
- => ui.Button(icon, text).SetupRefRelay(callback, argument, doublePressDelay);
-
- public static Button ButtonRef(this UIBuilder ui, LocaleString text, in colorX? buttonTint,
- ButtonEventHandler callback, T argument, float doublePressDelay = 0)
- where T : class, IWorldElement
- => ui.Button(text, buttonTint).SetupRefRelay(callback, argument, doublePressDelay);
-
- public static Button ButtonRef(this UIBuilder ui, Uri icon, LocaleString text, in colorX? buttonTint, in colorX spriteTint,
- ButtonEventHandler callback, T argument, float doublePressDelay = 0)
- where T : class, IWorldElement
- => ui.Button(icon, text, buttonTint, spriteTint).SetupRefRelay(callback, argument, doublePressDelay);
-
- public static TButton SetupRefRelay(this TButton button,
- ButtonEventHandler callback, TArgument argument, float doublePressDelay = 0)
- where TButton : IButton
- where TArgument : class, IWorldElement
- {
- var relay = button.Slot.AttachComponent>();
- relay.DoublePressDelay.Value = doublePressDelay;
- relay.ButtonPressed.Target = callback;
- relay.Argument.Target = argument;
-
- return button;
- }
- }
-}
\ No newline at end of file
diff --git a/MonkeyLoader.Resonite.Integration/UI/LocalActionButtonExtensions.cs b/MonkeyLoader.Resonite.Integration/UI/LocalActionButtonExtensions.cs
deleted file mode 100644
index 08ea0a73..00000000
--- a/MonkeyLoader.Resonite.Integration/UI/LocalActionButtonExtensions.cs
+++ /dev/null
@@ -1,310 +0,0 @@
-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 MonkeyLoader.Resonite.UI.Tooltips;
-
-namespace MonkeyLoader.Resonite.UI
-{
- ///
- /// 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.
- /// As such, they will be destroyed when the local user leaves, and won't be saved either (marking it non-persistent).
- ///
- public static class LocalActionButtonExtensions
- {
- ///
- /// Creates a using the given and .
- /// The will be triggerable by anyone, as long as the creating hasn't left the session.
- /// As such, it will be destroyed when the local user leaves, and won't be saved either (marking it non-persistent).
- ///
- /// The builder to use for creating the button.
- /// The text displayed on the button.
- /// The action to run when pressed.
- /// The button created by the .
- public static Button LocalActionButton(this UIBuilder builder, in LocaleString text, Action action)
- => builder.Button(text).WithLocalAction(action);
-
- ///
- /// Creates a using the given and .
- /// The will be triggerable by anyone, as long as the creating hasn't left the session.
- /// As such, it will be destroyed when the local user leaves, and won't be saved either (marking it non-persistent).
- ///
- /// The builder to use for creating the button.
- /// The icon displayed on the button.
- /// The action to run when pressed.
- /// The button created by the .
- public static Button LocalActionButton(this UIBuilder builder, Uri icon, Action action)
- => builder.Button(icon).WithLocalAction(action);
-
- ///
- /// Creates a using the given ,
- /// and .
- /// The will be triggerable by anyone, as long as the creating hasn't left the session.
- /// As such, it will be destroyed when the local user leaves, and won't be saved either (marking it non-persistent).
- ///
- /// The builder to use for creating the button.
- /// The icon displayed on the button.
- /// The text displayed on the button.
- /// The action to run when pressed.
- /// The button created by the .
- public static Button LocalActionButton(this UIBuilder builder, Uri icon, LocaleString text, Action action)
- => builder.Button(icon, text).WithLocalAction(action);
-
- ///
- /// Creates a using the given ,
- /// , tints and .
- /// The will be triggerable by anyone, as long as the creating hasn't left the session.
- /// As such, it will be destroyed when the local user leaves, and won't be saved either (marking it non-persistent).
- ///
- /// The builder to use for creating the button.
- /// The icon displayed on the button.
- /// The text displayed on the button.
- /// The background color of the button.
- /// The tint of the icon.
- /// The action to run when pressed.
- /// The button created by the .
- public static Button LocalActionButton(this UIBuilder builder, Uri icon, LocaleString text,
- in colorX tint, in colorX spriteTint, Action action)
- => builder.Button(icon, text, tint, spriteTint).WithLocalAction(action);
-
- ///
- /// Creates a using the given and with an extra .
- /// The will be triggerable by anyone, as long as the creating hasn't left the session.
- /// As such, it will be destroyed when the local user leaves, and won't be saved either (marking it non-persistent).
- ///
- /// The type of the extra argument to pass to the action.
- /// The builder to use for creating the button.
- /// The text displayed on the button.
- /// The action to run when pressed.
- /// The extra argument to pass to the action when this button is pressed.
- /// The button created by the .
- public static Button LocalActionButton(this UIBuilder builder, in LocaleString text, Action action, T argument)
- => builder.Button(text).WithLocalAction(argument, action);
-
- ///
- /// Creates a using the given and with an extra .
- /// The will be triggerable by anyone, as long as the creating hasn't left the session.
- /// As such, it will be destroyed when the local user leaves, and won't be saved either (marking it non-persistent).
- ///
- /// The type of the extra argument to pass to the action.
- /// The builder to use for creating the button.
- /// The icon displayed on the button.
- /// The action to run when pressed.
- /// The extra argument to pass to the action when this button is pressed.
- /// The button created by the .
- public static Button LocalActionButton(this UIBuilder builder, Uri icon, Action action, T argument)
- => builder.Button(icon).WithLocalAction(argument, action);
-
- ///
- /// Creates a using the given ,
- /// and with an extra .
- /// The will be triggerable by anyone, as long as the creating hasn't left the session.
- /// As such, it will be destroyed when the local user leaves, and won't be saved either (marking it non-persistent).
- ///
- /// The type of the extra argument to pass to the action.
- /// The builder to use for creating the button.
- /// The icon displayed on the button.
- /// The text displayed on the button.
- /// The action to run when pressed.
- /// The extra argument to pass to the action when this button is pressed.
- /// The button created by the .
- public static Button LocalActionButton(this UIBuilder builder, Uri icon, LocaleString text, Action action, T argument)
- => builder.Button(icon, text).WithLocalAction(argument, action);
-
- ///
- /// Creates a using the given ,
- /// , tints and with an extra .
- /// The will be triggerable by anyone, as long as the creating hasn't left the session.
- /// As such, it will be destroyed when the local user leaves, and won't be saved either (marking it non-persistent).
- ///
- /// The type of the extra argument to pass to the action.
- /// The builder to use for creating the button.
- /// The icon displayed on the button.
- /// The text displayed on the button.
- /// The background color of the button.
- /// The tint of the icon.
- /// The action to run when pressed.
- /// The extra argument to pass to the action when this button is pressed.
- /// The button created by the .
- public static Button LocalActionButton(this UIBuilder builder, Uri icon, LocaleString text,
- in colorX tint, in colorX spriteTint, Action action, T argument)
- => builder.Button(icon, text, tint, spriteTint).WithLocalAction(argument, action);
-
- ///
- /// Sets up an with the given and extra .
- /// The will be triggerable by anyone, as long as the creating hasn't left the session.
- /// As such, it will be destroyed when the local user leaves, and won't be saved either (marking it non-persistent).
- ///
- /// The specific type of the button.
- /// The type of the extra argument to pass to the action.
- /// The button to set up with an action.
- /// The extra argument to pass to the action when this button is pressed.
- /// The action to run when pressed.
- /// The unchanged button.
- [Obsolete("Use WithLocalAction instead.")]
- public static TButton SetupLocalAction(this TButton button, TArgument argument, Action action)
- where TButton : IButton
- => button.WithLocalAction(argument, action);
-
- ///
- /// Sets up an with the given .
- /// The will be triggerable by anyone, as long as the creating hasn't left the session.
- /// As such, it will be destroyed when the local user leaves, and won't be saved either (marking it non-persistent).
- ///
- /// The specific type of the button.
- /// The button to set up with an action.
- /// The action to run when pressed.
- /// The unchanged button.
- [Obsolete("Use WithLocalAction instead.")]
- public static TButton SetupLocalAction(this TButton button, Action action)
- where TButton : IButton
- => button.WithLocalAction(action);
-
- ///
- /// Sets up an with the given .
- /// The will be triggerable by anyone, as long as the creating hasn't left the session.
- /// As such, it will be destroyed when the local user leaves, and won't be saved either (marking it non-persistent).
- ///
- /// The specific type of the button.
- /// The button to set up with an action.
- /// The action to run when pressed.
- /// The unchanged button.
- public static TButton WithLocalAction(this TButton button, Action action)
- where TButton : IButton
- {
- var valueField = button.Slot.AttachComponent>().Value;
- valueField.OnValueChange += field => action(button);
-
- var toggle = button.Slot.AttachComponent();
- toggle.TargetValue.Target = valueField;
-
- button.Slot.DestroyWhenLocalUserLeaves();
-
- return button;
- }
-
- ///
- /// Sets up an with the given and extra .
- /// The will be triggerable by anyone, as long as the creating hasn't left the session.
- /// As such, it will be destroyed when the local user leaves, and won't be saved either (marking it non-persistent).
- ///
- /// The specific type of the button.
- /// The type of the extra argument to pass to the action.
- /// The button to set up with an action.
- /// The extra argument to pass to the action when this button is pressed.
- /// The action to run when pressed.
- /// The unchanged button.
- public static TButton WithLocalAction(this TButton button, TArgument argument, Action action)
- where TButton : IButton
- {
- var valueField = button.Slot.AttachComponent>().Value;
- valueField.OnValueChange += field => action(button, argument);
-
- var toggle = button.Slot.AttachComponent();
- toggle.TargetValue.Target = valueField;
-
- button.Slot.DestroyWhenLocalUserLeaves();
-
- return button;
- }
-
- ///
- /// Sets up a local-only with the given as a tooltip
- /// by registering it with the .
- ///
- ///
- /// This is the preferred overload to support localization on local-only buttons.
- /// If a non-locale-key is passed in, the bare string is used as the label.
- ///
- /// The specific type of the button.
- /// The local-only button to set up with a tooltip.
- /// The localized label to display as a tooltip.
- /// The unchanged button.
- /// When the button is not local to the user.
- public static TButton WithLocalTooltip(this TButton button, LocaleString label)
- where TButton : IButton
- {
- if (!button.Slot.IsLocalElement && !button.World.IsUserspace())
- throw new InvalidOperationException("The button to label must be on a local slot or in userspace!");
-
- TooltipManager.RegisterLabelForButton(button, label);
- return button;
- }
-
- ///
- /// Sets up an with the given label as a tooltip.
- ///
- ///
- /// Prefer using the overload taking a to support localization.
- ///
- /// The specific type of the button.
- /// The button to set up with a tooltip.
- /// The label to display as a tooltip.
- /// The unchanged button.
- public static TButton WithTooltip(this TButton button, string label)
- where TButton : IButton
- {
- var comment = button.Slot.AttachComponent();
- comment.Text.Value = CommentTooltipResolver.CommentTextPrefix + label;
-
- TooltipManager.RegisterLabelForButton(button, label);
-
- return button;
- }
-
- ///
- /// Sets up an with the given as a tooltip.
- ///
- ///
- /// This is the preferred overload to support localization.
- /// If a non-locale-key is passed in, the string overload is used.
- ///
- /// The specific type of the button.
- /// The button to set up with a tooltip.
- /// The localized label to display as a tooltip.
- /// The unchanged button.
- public static TButton WithTooltip(this TButton button, LocaleString label)
- where TButton : IButton
- {
- if (!label.isLocaleKey)
- return button.WithTooltip(label.content);
-
- TooltipManager.RegisterLabelForButton(button, label);
-
- return button.WithTooltip(field => field.AssignLocaleString(label));
- }
-
- ///
- /// Sets up an with a
- /// which concatenates the tooltip prefix and as many strings as necessary for .
- ///
- ///
- /// Primarily a helper method for the overload.
- /// Try to keep localization in mind (i.e. by using
- /// to set up fields).
- ///
- /// The specific type of the button.
- /// The button to set up with a tooltip.
- /// Actions to set up additional string fields to be concatenated together.
- /// The unchanged button.
- public static TButton WithTooltip(this TButton button, params Action>[] setupFields)
- where TButton : IButton
- {
- var stringConcat = button.Slot.AttachComponent();
- stringConcat.Strings.Add(CommentTooltipResolver.CommentTextPrefix);
-
- var comment = button.Slot.AttachComponent();
- stringConcat.TargetString.Target = comment.Text;
-
- foreach (var setupField in setupFields)
- setupField(stringConcat.Strings.Add());
-
- return button;
- }
- }
-}
\ No newline at end of file
diff --git a/MonkeyLoader.Resonite.Integration/UI/Tooltips/CommentTooltipResolver.cs b/MonkeyLoader.Resonite.Integration/UI/Tooltips/CommentTooltipResolver.cs
index 51468917..f2ed7ae0 100644
--- a/MonkeyLoader.Resonite.Integration/UI/Tooltips/CommentTooltipResolver.cs
+++ b/MonkeyLoader.Resonite.Integration/UI/Tooltips/CommentTooltipResolver.cs
@@ -21,7 +21,7 @@ public sealed class CommentTooltipResolver : ResoniteCancelableEventHandlerMonke
///
/// The prefix that a 's text must have to define a tooltip label.
///
- public const string CommentTextPrefix = "TooltipperyLabel:";
+ public const string CommentTextPrefix = LocalActionButtonExtensions.CommentTextPrefix;
///
public override bool CanBeDisabled => true;
diff --git a/MonkeyLoader.Resonite.Integration/UI/Tooltips/TooltipManager.cs b/MonkeyLoader.Resonite.Integration/UI/Tooltips/TooltipManager.cs
index 236bde4e..90fa6aa4 100644
--- a/MonkeyLoader.Resonite.Integration/UI/Tooltips/TooltipManager.cs
+++ b/MonkeyLoader.Resonite.Integration/UI/Tooltips/TooltipManager.cs
@@ -96,9 +96,7 @@ public static Tooltip MakeTooltip(IButton button, Slot parent, in float3 localPo
/// Registers a label for the given undestroyed button,
/// if it doesn't already have one.
///
- /// The undestroyed button to register a label for.
- /// The label to register for the button.
- /// true if the label was registered for the button; otherwise, false.
+ ///
public static bool RegisterLabelForButton(IButton button, in LocaleString label)
{
if (button.FilterWorldElement() is null || _labelsByButton.ContainsKey(button))
@@ -310,6 +308,7 @@ protected override void Handle(ResolveTooltipLabelEvent eventData)
protected override bool OnEngineReady()
{
Mod.RegisterEventSource(this);
+ LocalActionButtonExtensions.RegisterLabelForButton = RegisterLabelForButton;
return base.OnEngineReady();
}