Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@
It should follow the format major.minor.patch (semantic versioning). If you publish your mod
as a library to NuGet, this version will also be used as the package version.
-->
<Version>0.3.0</Version>
<Version>0.4.0</Version>
</PropertyGroup>
</Project>
20 changes: 16 additions & 4 deletions Elements/ChoiceElement.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public class ChoiceElement<T> : SelectableValueElement<T>
/// <summary>
/// Construct a ChoiceElement with the given label text, model, and description text.
/// </summary>
public ChoiceElement(string label, IChoiceModel<T> model, string description = "")
public ChoiceElement(LocalizedText label, IChoiceModel<T> model, LocalizedText description)
: base(
MenuPrefabs.Get().NewTextChoiceContainer(out var menuOptionHorizontal),
menuOptionHorizontal,
Expand All @@ -36,17 +36,29 @@ public ChoiceElement(string label, IChoiceModel<T> model, string description = "

OnValueChanged += _ => custom.UpdateText();

LabelText.text = label;
DescriptionText.text = description;
LabelText.LocalizedText = label;
DescriptionText.LocalizedText = description;
custom.UpdateText();
}

/// <summary>
/// Construct a ChoiceElement with the given label and model.
/// </summary>
public ChoiceElement(LocalizedText label, IChoiceModel<T> model)
: this(label, model, "") { }

/// <summary>
/// Shortcut for building a ChoiceElement from a finite list of values.
/// </summary>
public ChoiceElement(string label, List<T> items, string description = "")
public ChoiceElement(LocalizedText label, List<T> items, LocalizedText description)
: this(label, ChoiceModels.ForValues(items), description) { }

/// <summary>
/// Shortcut for building a ChoiceElement from a finite list of values.
/// </summary>
public ChoiceElement(LocalizedText label, List<T> items)
: this(label, ChoiceModels.ForValues(items), "") { }

/// <summary>
/// The value holder and model underlying this choice element.
/// </summary>
Expand Down
18 changes: 9 additions & 9 deletions Elements/DynamicDescriptionChoiceElement.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,17 @@ public class DynamicDescriptionChoiceElement<T> : ChoiceElement<T>
{
internal const string RIGHT_DESCRIPTION_NAME = "ModMenu-Right Description";

/// <inheritdoc cref="ChoiceElement{T}.ChoiceElement(string, IChoiceModel{T}, string)"/>
/// <inheritdoc cref="ChoiceElement{T}.ChoiceElement(LocalizedText, IChoiceModel{T}, LocalizedText)"/>
public DynamicDescriptionChoiceElement(
string label,
LocalizedText label,
IChoiceModel<T> model,
string description,
string rightDescription
LocalizedText description,
LocalizedText rightDescription
)
: base(label, model, description)
{
RightText = SetupRightDescription(DescriptionText, ChoiceText);
RightText.text = rightDescription;
RightText.LocalizedText = rightDescription;
}

/// <summary>
Expand All @@ -40,14 +40,14 @@ string rightDescription
/// <param name="description"></param>
/// <param name="getRightDescription">Function used to determine the description below the choice.</param>
public DynamicDescriptionChoiceElement(
string label,
LocalizedText label,
IChoiceModel<T> model,
string description,
Func<T, string> getRightDescription
LocalizedText description,
Func<T, LocalizedText> getRightDescription
)
: this(label, model, description, getRightDescription(model.Value))
{
model.OnValueChanged += value => RightText.text = getRightDescription(value);
model.OnValueChanged += value => RightText.LocalizedText = getRightDescription(value);
}

/// <summary>
Expand Down
6 changes: 3 additions & 3 deletions Elements/KeyBindElement.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public class KeyBindElement : SelectableValueElement<KeyCode>
/// <summary>
/// Construct a KeyBindElement with a custom model.
/// </summary>
public KeyBindElement(string label, IValueModel<KeyCode> model)
public KeyBindElement(LocalizedText label, IValueModel<KeyCode> model)
: base(
MenuPrefabs.Get().NewKeyBindContainer(out var customMappableKey),
customMappableKey,
Expand All @@ -27,13 +27,13 @@ public KeyBindElement(string label, IValueModel<KeyCode> model)
KeyBindText = customMappableKey.KeymapText!;
KeyBindImage = customMappableKey.KeymapImage!;

LabelText.text = label;
LabelText.LocalizedText = label;
}

/// <summary>
/// Construct a KeyBindElement with a default model that accepts any KeyCode.
/// </summary>
public KeyBindElement(string label)
public KeyBindElement(LocalizedText label)
: this(label, new ValueModel<KeyCode>(KeyCode.A)) { }

/// <summary>
Expand Down
62 changes: 62 additions & 0 deletions Elements/LocalizedText.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
using TeamCherry.Localization;

namespace Silksong.ModMenu.Elements;

/// <summary>
/// Wrapper class for either text that supports localization, or raw text which does not.
/// </summary>
public class LocalizedText
{
private readonly TeamCherry.Localization.LocalisedString localisedString;
private readonly string rawText;

private LocalizedText(LocalisedString localisedString, string rawText)
{
this.localisedString = localisedString;
this.rawText = rawText;
}

/// <summary>
/// Get the readable text represented by this object.
/// </summary>
public string Text =>
localisedString.IsEmpty
? rawText
: Language.Get(localisedString.Key, localisedString.Sheet);

/// <summary>
/// Returns true if this object has localization support.
/// </summary>
public bool IsLocalized => !localisedString.IsEmpty;

/// <summary>
/// Returns the localized identifier for this object, which may be empty.
/// </summary>
public LocalisedString Localized => localisedString;

/// <summary>
/// Represents localized text with the given key and an empty sheet title.
/// </summary>
public static LocalizedText Key(string languageKey) => new(new("", languageKey), "");

/// <summary>
/// Represents localized text with the given key.
/// </summary>
public static LocalizedText Key(LocalisedString localisedString) => new(localisedString, "");

/// <summary>
/// Represents text with no localization that always renders to the given value.
/// </summary>
public static LocalizedText Raw(string rawText) => new(new(), rawText);

/// <summary>
/// Implicit conversion for raw text to un-localized LocalizedText.
/// </summary>
public static implicit operator LocalizedText(string rawText) => Raw(rawText);

/// <summary>
/// Implicit conversion from a LocalisedString.
/// </summary>
public static implicit operator LocalizedText(LocalisedString localisedString) =>
Key(localisedString);
}
46 changes: 46 additions & 0 deletions Elements/LocalizedTextExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
using UnityEngine.UI;

namespace Silksong.ModMenu.Elements;

/// <summary>
/// Helper methods for working with LocalizedText.
/// </summary>
public static class LocalizedTextExtensions
{
extension(Text self)
{
/// <summary>
/// Helper field to set localized text on a Text component.
/// </summary>
public LocalizedText LocalizedText
{
get
{
if (self.TryGetComponent<AutoLocalizeTextUI>(out var auto) && !auto.text.IsEmpty)
return auto.text;
else
return self.text;
}
set
{
if (value.IsLocalized)
{
if (!self.TryGetComponent<AutoLocalizeTextUI>(out var auto))
{
auto = self.gameObject.AddComponent<AutoLocalizeTextUI>();
auto.textField = self;
}

auto.text = value.Localized;
auto.RefreshTextFromLocalization();
}
else
{
if (self.TryGetComponent<AutoLocalizeTextUI>(out var auto))
UnityEngine.Object.Destroy(auto);
self.text = value.Text;
}
}
}
}
}
8 changes: 4 additions & 4 deletions Elements/SliderElement.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ public class SliderElement<T> : SelectableValueElement<T>
/// </summary>
/// <param name="label">The label text for the slider.</param>
/// <param name="model">The model for the domain range and underlying value.</param>
public SliderElement(string label, SliderModel<T> model)
public SliderElement(LocalizedText label, SliderModel<T> model)
: base(MenuPrefabs.Get().NewSliderContainer(out var slider), slider, model)
{
Container.name = label;
Container.name = label.Text;

Slider = slider;
var sliderObj = Slider.gameObject;
Expand Down Expand Up @@ -57,7 +57,7 @@ public SliderElement(string label, SliderModel<T> model)
}
});

LabelText.text = label;
LabelText.LocalizedText = label;
UpdateValueText();
}

Expand Down Expand Up @@ -95,5 +95,5 @@ public override void SetFontSizes(FontSizes fontSizes)
ValueText.fontSize = fontSizes.SliderSize();
}

private void UpdateValueText() => ValueText.text = SliderModel.DisplayString();
private void UpdateValueText() => ValueText.LocalizedText = SliderModel.DisplayString();
}
6 changes: 3 additions & 3 deletions Elements/TextButton.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ public class TextButton : SelectableElement
/// <summary>
/// Construct a text button with the given text.
/// </summary>
public TextButton(string text)
public TextButton(LocalizedText text)
: base(MenuPrefabs.Get().NewTextButtonContainer(out var menuButton), menuButton)
{
Container.name = text;
Container.name = text.Text;

MenuButton = menuButton;
MenuButton
Expand All @@ -35,7 +35,7 @@ public TextButton(string text)
MenuButton.buttonType = MenuButton.MenuButtonType.Activate;

ButtonText = menuButton.gameObject.FindChild("Menu Button Text")!.GetComponent<Text>();
ButtonText.text = text;
ButtonText.LocalizedText = text;
}

/// <summary>
Expand Down
12 changes: 9 additions & 3 deletions Elements/TextInput.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public class TextInput<T> : SelectableValueElement<T>
/// <summary>
/// Construct a basic text input.
/// </summary>
public TextInput(string label, ITextModel<T> model, string description = "")
public TextInput(LocalizedText label, ITextModel<T> model, LocalizedText description)
: base(MenuPrefabs.Get().NewTextInputContainer(out var inputField), inputField, model)
{
TextModel = model;
Expand All @@ -40,15 +40,21 @@ public TextInput(string label, ITextModel<T> model, string description = "")

OnTextValueChanged += value => InputField.text = value;

LabelText.text = label;
DescriptionText.text = description;
LabelText.LocalizedText = label;
DescriptionText.LocalizedText = description;

if (intTypes.Contains(typeof(T)))
InputField.contentType = InputField.ContentType.IntegerNumber;
else if (floatTypes.Contains(typeof(T)))
InputField.contentType = InputField.ContentType.DecimalNumber;
}

/// <summary>
/// Construct a basic text input with no description.
/// </summary>
public TextInput(LocalizedText label, ITextModel<T> model)
: this(label, model, "") { }

/// <summary>
/// The value holder and model underlying this choice element.
/// </summary>
Expand Down
6 changes: 3 additions & 3 deletions Elements/TextLabel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ public class TextLabel : MenuElement
/// <summary>
/// Construct a label with the given text contents.
/// </summary>
public TextLabel(string text)
public TextLabel(LocalizedText text)
: base(MenuPrefabs.Get().NewTextLabel())
{
Container.name = text;
Container.name = text.Text;
Text = Container.GetComponent<Text>();
Text.text = text;
Text.LocalizedText = text;
}

/// <summary>
Expand Down
3 changes: 2 additions & 1 deletion Internal/CustomMenuOptionHorizontal.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using MonoDetour;
using MonoDetour.DetourTypes;
using MonoDetour.HookGen;
using Silksong.ModMenu.Elements;
using Silksong.ModMenu.Models;
using UnityEngine;
using UnityEngine.EventSystems;
Expand All @@ -27,7 +28,7 @@ internal void UpdateText()
if (orig == null)
return;

orig.optionText.text = Model?.DisplayString() ?? "???";
orig.optionText.LocalizedText = Model?.DisplayString() ?? "???";
if (orig.optionText.TryGetComponent<FixVerticalAlign>(out var align))
align.AlignText();
}
Expand Down
3 changes: 2 additions & 1 deletion Models/AbstractValueModel.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using Silksong.ModMenu.Elements;

namespace Silksong.ModMenu.Models;

Expand Down Expand Up @@ -57,5 +58,5 @@ public T Value
}

/// <inheritdoc/>
public virtual string DisplayString() => $"{GetValue()}";
public virtual LocalizedText DisplayString() => $"{GetValue()}";
}
6 changes: 4 additions & 2 deletions Models/Delegates.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
namespace Silksong.ModMenu.Models;
using Silksong.ModMenu.Elements;

namespace Silksong.ModMenu.Models;

/// <summary>
/// Converts 'item' to string with the additional context of an associated index, most likely within a list.
/// </summary>
public delegate string IndexedToString<T>(int index, T item);
public delegate LocalizedText IndexedToString<T>(int index, T item);
6 changes: 4 additions & 2 deletions Models/IDisplayable.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
namespace Silksong.ModMenu.Models;
using Silksong.ModMenu.Elements;

namespace Silksong.ModMenu.Models;

/// <summary>
/// Base interface for all models which ultimately display a string to represent the chosen value.
Expand All @@ -8,5 +10,5 @@ public interface IDisplayable
/// <summary>
/// The UI string to display for this entity.
/// </summary>
string DisplayString();
LocalizedText DisplayString();
}
Loading