using System.Collections.Generic; using MelonLoader; using UnityEngine.UIElements; namespace ADOFAIRenderer.Data { public class IntegerInputValidator { private struct FieldEntry { public List Limits; public bool Optional; } private readonly VisualElement _rootVisualElement; private readonly Dictionary _fields = new(); public IntegerInputValidator(VisualElement rootVisualElement) { _rootVisualElement = rootVisualElement; } /// /// Registers one or more s for the field with the given name. /// Multiple limits can be added to the same field — they are all checked in order. /// /// The name of the IntegerField in the UXML. /// /// If true, the field is allowed to be empty. Limits are only enforced when a value is present. /// /// The limits to apply. public IntegerInputValidator AddLimits(string fieldName, bool optional, params IntegerLimit[] limits) { if (!_fields.TryGetValue(fieldName, out var entry)) { entry = new FieldEntry { Limits = new List(), Optional = optional }; } entry.Optional = optional; entry.Limits.AddRange(limits); _fields[fieldName] = entry; return this; } /// /// Shorthand for required (non-optional) fields. public IntegerInputValidator AddLimits(string fieldName, params IntegerLimit[] limits) { return AddLimits(fieldName, false, limits); } /// /// Queries all registered fields from the root VisualElement and /// registers value-changed callbacks that rollback invalid values. /// public void SetupValidation() { foreach (var kvp in _fields) { var fieldName = kvp.Key; var entry = kvp.Value; var field = _rootVisualElement.Q(fieldName); if (field == null) { Melon.Logger.Warning( $"IntegerField '{fieldName}'을(를) 찾을 수 없습니다. 유효성 검사를 건너뜁니다."); continue; } var limits = entry.Limits; var optional = entry.Optional; field.RegisterValueChangedCallback(evt => { // Optional fields allow empty input — skip validation when cleared if (optional && string.IsNullOrEmpty(field.text)) { return; } foreach (var limit in limits) { if (!limit.Validate(evt.newValue, out _)) { field.SetValueWithoutNotify(evt.previousValue); return; } } }); } } } }