Skip to content

Add <icon> to UIToolkit, + picking mode & text outline #128

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jun 29, 2025
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
291 changes: 291 additions & 0 deletions Assets/Material Icons/Material Icons SDF.asset

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions Assets/Material Icons/Material Icons SDF.asset.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Assets/Material Icons/Material Icons.asset
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ MonoBehaviour:
m_EditorClassIdentifier:
Name: Material Icons
FontAsset: {fileID: 11400000, guid: 2d3b5da16a7081c4b9d07980bc7922c7, type: 2}
ToolkitFontAsset: {fileID: 11400000, guid: f6206075b3056fc44a6a93f14f64c615, type: 2}
Codepoints: {fileID: 4900000, guid: d8af46a16a86a264c9638732d5ecc1e4, type: 3}
60 changes: 60 additions & 0 deletions Runtime/Frameworks/UIToolkit/Components/IconComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
using ReactUnity.Styling;
using UnityEngine;
using UnityEngine.UIElements;

namespace ReactUnity.UIToolkit
{
public class IconComponent : UIToolkitComponent<TextElement>, ITextComponent
{
public string Content => Element.text;
public IconSet Set { get; private set; }


public IconComponent(string text, UIToolkitContext context, string tag) : base(context, tag, true)
{
ApplySet(Context.DefaultIconSet);

if (text != null) SetText(text);
}

public void SetText(string text)
{
if(Set != null)
{
Element.text = Set.ConvertTextContent(text);
}
else
{
Element.text = text;
}
}

public override void SetProperty(string property, object value)
{
if (property == "set") ApplySet(value);
else base.SetProperty(property, value);
}

public void ApplySet(object value)
{
if (value == null)
{
Set = Context.DefaultIconSet;
}
else if (value is IconSet i) Set = i;
else
{
var str = value?.ToString();
if (Context.IconSets.TryGetValue(str, out var ic)) Set = ic;
else Set = null;
}

if (Set != null)
{
Element.style.unityFontDefinition = new StyleFontDefinition(Set.ToolkitFontAsset);
SetText(Element.text);

}
}
}
}
2 changes: 2 additions & 0 deletions Runtime/Frameworks/UIToolkit/Components/IconComponent.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 8 additions & 5 deletions Runtime/Frameworks/UIToolkit/Components/UIToolkitComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -152,14 +152,15 @@ protected override void ApplyStylesSelf()
TargetElement.style.letterSpacing = StylingHelpers.GetStyleFloat(computed, StyleProperties.letterSpacing).value;
TargetElement.style.wordSpacing = StylingHelpers.GetStyleFloat(computed, StyleProperties.wordSpacing).value;
#endif
TargetElement.style.unityTextOutlineColor = StylingHelpers.GetStyleColor(computed, StyleProperties.textStrokeColor).value;
TargetElement.style.unityTextOutlineWidth = StylingHelpers.GetStyleFloat(computed, StyleProperties.textStrokeWidth).value;

if (computed.HasValue(StyleProperties.backgroundImage))
{
var bg = computed.backgroundImage?.Get(0);

TargetElement.style.backgroundImage = null;
bg?.ResolveImage(Context, TargetElement.layout.size, tx =>
{
bg?.ResolveImage(Context, TargetElement.layout.size, tx => {
if (bg != ComputedStyle.backgroundImage?.Get(0)) return;
TargetElement.style.backgroundImage = tx?.Texture;
});
Expand All @@ -186,8 +187,7 @@ protected override void ApplyStylesSelf()

if (computed.HasValue(StyleProperties.fontFamily))
{
if (computed.fontFamily != null) computed.fontFamily?.Get(Context, x =>
{
if (computed.fontFamily != null) computed.fontFamily?.Get(Context, x => {
if (x?.Font != null)
{
TargetElement.style.unityFont = x.Font;
Expand All @@ -196,7 +196,8 @@ protected override void ApplyStylesSelf()
#endif
}
#if REACT_TMP
else if (x?.TmpFontAsset != null) {
else if (x?.TmpFontAsset != null)
{
TargetElement.style.unityFont = x?.TmpFontAsset?.sourceFontFile;
#if REACT_TEXTCORE
TargetElement.style.unityFontDefinition = FontDefinition.FromFont(x?.TmpFontAsset?.sourceFontFile);
Expand Down Expand Up @@ -293,6 +294,8 @@ protected override void ApplyStylesSelf()
#endif
}
else TargetElement.transform.position = translate;

TargetElement.pickingMode = computed.pointerEvents == PointerEvents.None ? PickingMode.Ignore : PickingMode.Position;
}

protected override void DestroySelf()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#if UNITY_2021_2_OR_NEWER
using System.Collections.Generic;
using ReactUnity.Scheduling;
using ReactUnity.Styling;
using ReactUnity.Styling.Rules;
using UnityEngine;
using UnityEngine.UIElements;
Expand All @@ -11,6 +13,8 @@ namespace ReactUnity.UIToolkit
public class ReactRendererUIToolkit : ReactRendererBase
{
public VisualElement Root => GetComponent<UIDocument>()?.rootVisualElement;
public IconSet DefaultIconSet;
public List<IconSet> IconSets;

protected override void ClearRoot()
{
Expand All @@ -27,6 +31,8 @@ protected override ReactContext CreateContext(ScriptSource script)
Timer = Timer ?? UnscaledTimer.Instance,
MediaProvider = MediaProvider,
OnRestart = () => Render(),
IconSets = IconSets,
DefaultIconSet = DefaultIconSet,
OnAudioPlayback = PlayAudio,
EngineType = EngineType,
Debug = AdvancedOptions.DebugMode != DebugMode.None,
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 20 additions & 0 deletions Runtime/Frameworks/UIToolkit/General/UIToolkitContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ public class UIToolkitContext : ReactContext
public VisualElement HostElement;
public Action<AudioClip, float, float> OnAudioPlayback;
public override bool CalculatesLayout => false;

public List<IconSet> IconSets;
public IconSet DefaultIconSet;
}

public static Func<string, string, UIToolkitContext, IUIToolkitComponent<VisualElement>> defaultCreator =
Expand Down Expand Up @@ -42,6 +45,7 @@ public static Dictionary<string, Func<string, string, UIToolkitContext, IReactCo
{ "style", (tag, text, context) => new Styling.StyleComponent(context, tag, text) },
{ "script", (tag, text, context) => new Scripting.ScriptComponent(context, tag, text) },
{ "html", (tag, text, context) => new Html.HtmlComponent(context, tag) },
{ "icon", (tag, text, context) => new IconComponent(text, context, tag) },
#if UNITY_2020_1_OR_NEWER
{ "helpbox", (tag, text, context) => new UIToolkitComponent<HelpBox>(context, tag) }, // TODO
#endif
Expand Down Expand Up @@ -69,6 +73,10 @@ public static Dictionary<string, Func<string, string, UIToolkitContext, IReactCo
{ "hover", typeof(HoverStateHandler) },
};

public IconSet DefaultIconSet { get; }
public Dictionary<string, IconSet> IconSets { get; } = new Dictionary<string, IconSet>() { };


private Action<AudioClip, float, float> OnAudioPlayback = null;

public VisualElement HostElement { get; }
Expand All @@ -77,6 +85,18 @@ public UIToolkitContext(Options options) : base(options)
{
OnAudioPlayback = options.OnAudioPlayback;
HostElement = options.HostElement;

if (options.IconSets != null)
{
if (options.IconSets.Count > 0) IconSets["default"] = options.IconSets[0];
foreach (var ic in options.IconSets) IconSets[ic.Name] = ic;
}

DefaultIconSet = options.DefaultIconSet;
if (DefaultIconSet == null)
{
if (IconSets.TryGetValue("default", out var def)) DefaultIconSet = def;
}
}

public virtual void Initialize()
Expand Down
3 changes: 3 additions & 0 deletions Runtime/Styling/IconSet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ namespace ReactUnity.Styling
public class IconSet : ScriptableObject
{
public string Name;
[Tooltip("For UGUI Use")]
public TMPro.TMP_FontAsset FontAsset;
[Tooltip("For UIToolkit Use")]
public UnityEngine.TextCore.Text.FontAsset ToolkitFontAsset;
public TextAsset Codepoints;

[NonSerialized]
Expand Down