Hi, I want to make a `FileNameTextField` or `FileNameManipulator` that restrict input so that user can only enter a file name friendly string. My first try was to simply make a manipulator and stopping KeyDown event propagation if the character was invalid. That simply didn't affect TextField value. The second attempt looked like this: Code (CSharp): public class FileNameField : TextValueField<string> { public FileNameField(): base(null, -1, new FileNameInput()) { } public override void ApplyInputDeviceDelta(Vector3 delta, DeltaSpeed speed, string startValue) { } protected override string StringToValue(string str) => str; protected override string ValueToString(string value) => value; class FileNameInput : TextValueInput { protected override string allowedCharacters => "test"; public override void ApplyInputDeviceDelta(Vector3 delta, DeltaSpeed speed, string startValue) { } protected override string ValueToString(string value) => value; } } It did filter the characters but started to throw `NotSupportedException: Specified method is not supported` every time I typed character. Also, I think that doing this by manipulator would be a much cleaner approach. So, what is the proper way to do this?
This is it: Spoiler: Log NotSupportedException: Specified method is not supported. UnityEngine.UIElements.TextInputBaseField`1+TextInputBase[TValueType].StringToValue (System.String str) (at /Users/builduser/buildslave/unity/build/Modules/UIElements/Controls/TextInputFieldBase.cs:242) UnityEditor.UIElements.TextValueField`1+TextValueInput[TValueType].StringToValue (System.String str) (at /Users/builduser/buildslave/unity/build/Editor/Mono/UIElements/Controls/TextValueField.cs:133) UnityEngine.UIElements.TextInputBaseField`1+TextInputBase[TValueType].UpdateValueFromText () (at /Users/builduser/buildslave/unity/build/Modules/UIElements/Controls/TextInputFieldBase.cs:247) UnityEditor.UIElements.TextValueField`1+TextValueInput[TValueType].ExecuteDefaultActionAtTarget (UnityEngine.UIElements.EventBase evt) (at /Users/builduser/buildslave/unity/build/Editor/Mono/UIElements/Controls/TextValueField.cs:173) UnityEngine.UIElements.CallbackEventHandler.HandleEvent (UnityEngine.UIElements.EventBase evt) (at /Users/builduser/buildslave/unity/build/Modules/UIElements/Events/EventHandler.cs:106) UnityEngine.UIElements.EventDispatchUtilities.PropagateEvent (UnityEngine.UIElements.EventBase evt) (at /Users/builduser/buildslave/unity/build/Modules/UIElements/Events/IEventDispatchingStrategy.cs:95) UnityEngine.UIElements.KeyboardEventDispatchingStrategy.DispatchEvent (UnityEngine.UIElements.EventBase evt, UnityEngine.UIElements.IPanel panel) (at /Users/builduser/buildslave/unity/build/Modules/UIElements/Events/KeyboardEventDispatchingStrategy.cs:30) UnityEngine.UIElements.EventDispatcher.ProcessEvent (UnityEngine.UIElements.EventBase evt, UnityEngine.UIElements.IPanel panel) (at /Users/builduser/buildslave/unity/build/Modules/UIElements/EventDispatcher.cs:277) UnityEngine.UIElements.EventDispatcher.Dispatch (UnityEngine.UIElements.EventBase evt, UnityEngine.UIElements.IPanel panel, UnityEngine.UIElements.DispatchMode dispatchMode) (at /Users/builduser/buildslave/unity/build/Modules/UIElements/EventDispatcher.cs:159) UnityEngine.UIElements.BaseVisualElementPanel.SendEvent (UnityEngine.UIElements.EventBase e, UnityEngine.UIElements.DispatchMode dispatchMode) (at /Users/builduser/buildslave/unity/build/Modules/UIElements/Panel.cs:245) UnityEngine.UIElements.UIElementsUtility.DoDispatch (UnityEngine.UIElements.BaseVisualElementPanel panel) (at /Users/builduser/buildslave/unity/build/Modules/UIElements/UIElementsUtility.bindings.cs:359) UnityEngine.UIElements.UIElementsUtility.ProcessEvent (System.Int32 instanceID, System.IntPtr nativeEventPtr) (at /Users/builduser/buildslave/unity/build/Modules/UIElements/UIElementsUtility.bindings.cs:154) UnityEngine.GUIUtility.ProcessEvent (System.Int32 instanceID, System.IntPtr nativeEventPtr) (at /Users/builduser/buildslave/unity/build/Modules/IMGUI/GUIUtility.cs:179)
Thanks Jonathan, I was hoping for someone to hint a solution that doesn't depends on TextValueField but for now this works. For anyone interested this is the working snippet: Code (CSharp): public class FileNameField : TextValueField<string> { public FileNameField() : base(null, -1, new FileNameInput()) { } public override void ApplyInputDeviceDelta(Vector3 delta, DeltaSpeed speed, string startValue) { } protected override string StringToValue(string str) => str; protected override string ValueToString(string value) => value; class FileNameInput : TextValueInput { private readonly string _allowedChars; protected override string allowedCharacters => _allowedChars; public FileNameInput() { _allowedChars = new string(Enumerable.Range(char.MinValue, char.MaxValue) .Select(c => (char)c) .Where(c => !char.IsControl(c)) .Except(Path.GetInvalidFileNameChars()) .ToArray()); } public override void ApplyInputDeviceDelta(Vector3 delta, DeltaSpeed speed, string startValue) { } protected override string ValueToString(string value) => value; protected override string StringToValue(string str) => str; } }