Changing caret style (inside a TextField)?

Another user had a similar issue recently, but with the Selection Color. The selector he’s using should work for the cursor color. Let me know if it helps, otherwise I think you should log a but for it.

Link to other thread .

I tried the uss selector of the thread but it doesn’t work. I tried several other ones and I do see it appearing in the UI Toolkit Debugger but it’s not showing any difference unfortunately. I’ll reproduce it in a sample model and report it as a bug.

1 Like

Composed a script based on the advices from here, maybe will come handy to someone
It’s an extended TextField with blinking caret and some properties exposed

using UnityEngine.UIElements;

namespace LOL.UI
{
    /// <summary>
    /// Text field with blinking caret.
    /// <list type="bullet">
    ///     <listheader>Exposed UXML properties</listheader>
    ///     <item>blink-interval (in ms)</item>
    ///     <item>blink-enable (if true, caret blinks)</item>
    ///     <item>blink-style (uss style which applies to caret on blink)</item>
    /// </list>
    /// </summary>
    public class BlinkingTextField : TextField
    {
        private readonly IVisualElementScheduledItem _blink;

        private long _blinkInterval = 500;
        private bool _isBlinkEnabled = true;
        private string _blinkStyle = "cursor-transparent";

        /// <summary>
        /// Caret blink interval in ms.
        /// </summary>
        public long BlinkInterval
        {
            get => _blinkInterval;
            set
            {
                _blinkInterval = value;
                _blink?.Every(_blinkInterval);
            }
        }

        /// <summary>
        /// Caret uss style applied on blink.
        /// </summary>
        public string BlinkStyle { get => _blinkStyle; set => _blinkStyle = value; }

        /// <summary>
        /// If true, caret blinks.
        /// </summary>
        public bool BlinkEnable
        {
            get => _isBlinkEnabled;
            set
            {
                if (_isBlinkEnabled == value)
                    return;

                _isBlinkEnabled = value;

                if (!_isBlinkEnabled)
                {
                    if (IsFocused)
                        _blink?.Pause();

                    if (ClassListContains(_blinkStyle))
                        RemoveFromClassList(_blinkStyle);
                }
                else if (IsFocused)
                {
                    _blink?.Resume();
                }
            }
        }

        /// <summary>
        /// Returns true if active input.
        /// </summary>
        public bool IsFocused => focusController?.focusedElement == this;

        public BlinkingTextField()
        {
            RegisterCallback<FocusEvent>(OnFocus);
            RegisterCallback<BlurEvent>(OnInputEnded);

            _blink = schedule.Execute(() =>
            {
                if (ClassListContains(_blinkStyle))
                    RemoveFromClassList(_blinkStyle);
                else
                    AddToClassList(_blinkStyle);
            }).Every(_blinkInterval);

            _blink.Pause();
        }

        private void OnFocus(FocusEvent evt)
        {
            if (!_isBlinkEnabled)
                return;

            _blink.Resume();
        }

        private void OnInputEnded(BlurEvent evt)
        {
            _blink.Pause();
        }

        public new class UxmlFactory : UxmlFactory<BlinkingTextField, BlinkingUxmlTraits>
        {
        }

        [UnityEngine.Scripting.Preserve]
        public class BlinkingUxmlTraits : UxmlTraits
        {
            private readonly UxmlLongAttributeDescription _blinkInterval = new() { name = "blink-interval", use = UxmlAttributeDescription.Use.Optional, defaultValue = 500 };
            private readonly UxmlBoolAttributeDescription _blinkEnable = new() { name = "blink-enable", use = UxmlAttributeDescription.Use.Optional, defaultValue = true };
            private readonly UxmlStringAttributeDescription _blinkStyle = new() { name = "blink-style", use = UxmlAttributeDescription.Use.Optional, defaultValue = "cursor-transparent" };

            public override void Init(VisualElement ve, IUxmlAttributes bag, CreationContext cc)
            {
                base.Init(ve, bag, cc);
                ((BlinkingTextField)ve).BlinkInterval = _blinkInterval.GetValueFromBag(bag, cc);
                ((BlinkingTextField)ve).BlinkEnable = _blinkEnable.GetValueFromBag(bag, cc);
                ((BlinkingTextField)ve).BlinkStyle = _blinkStyle.GetValueFromBag(bag, cc);
            }
        }
    }
}

And the styles would be:

.unity-text-field {
    --unity-cursor-color:#FFFFFF;
}

.cursor-transparent {
    --unity-cursor-color: rgba(0, 0, 0, 0);
}

.cursor-red {
    --unity-cursor-color: red;
}
2 Likes

Which Unity Version do you use?
I had something similar, but since unity 2022.2. my version did not work anymore. I think the problem was that the Textfield is only repainted, when the user types something.

It’s 2022.3.5
hmm, never faced issues with that script yet. Not sure, sometimes it requires to postpone executions to redraw something, I had a case where I had to schedule executions one after another

1 Like

In this version my code seams to work again :slight_smile:

1 Like

Just as an fyi, this was broken in 2022.2, until it was fixed in 2022.2.19, see release notes Unity 2022.2.19.

1 Like

Now how do i can change caret color with 2022.3.10f1 , release note at 2022.3.10f1 has no more supported with --unity-cursor-color and textEdition.cursorColor not effective anymore

1 Like

Adding
.unity-text-field {
–unity-cursor-color:#00FF00;
}
to my uss file worked for me.
(Unity 2023.2.5f1)

2 Likes

Thanks this is great! Could we animate / smooth the blink in some way?

I’ve tried every approach here. Nothing helps. I use unity 6000.0.33
Even accessing from code doesn’t work.

_document.rootVisualElement.Q<TextField>().textSelection.cursorColor = Color.white;

I have very simple layout and I’ve checked that I get right one TextField (which is the only in hierarchy but who knows)

So is it even an option to bit such a simple case when I have changed background color on TextField and I need different color for caret???

UPD: editing USS manually works finally, but not from code

.unity-text-field {
    --unity-cursor-color:#FFFFFF;
}

.cursor-transparent {
    --unity-cursor-color: rgba(0, 0, 0, 0);
}