using System;
using System.Collections.Generic;
using UnityEngine;
namespace DanroJump.Settings
{
///
/// Предпочитаемый способ отображения настройки в сервисном UI.
///
public enum ServiceSettingDisplayMode
{
Auto,
Toggle,
Slider,
Stepper,
TextInput,
Button,
OptionPicker
}
///
/// Описание одной сервисной настройки: ключ, UI-метаданные, тип, дефолт и ограничения.
///
[Serializable]
public sealed class ServiceSettingDefinition
{
[SerializeField] private string key;
[SerializeField] private string displayName;
[SerializeField] [TextArea] private string description;
[SerializeField] private string group = "General";
[SerializeField] private bool shownInServiceMenu = true;
[SerializeField] private bool exposedForExternalChanges;
[SerializeField] private ServiceSettingValueType valueType;
[SerializeField] private ServiceSettingDisplayMode displayMode = ServiceSettingDisplayMode.Auto;
[Header("Default values")]
[SerializeField] private bool defaultBool = true;
[SerializeField] private int defaultInt;
[SerializeField] private float defaultFloat = 1f;
[SerializeField] private string defaultString = "";
[SerializeField] private int defaultOptionIndex;
[Header("Ranges")]
[SerializeField] private int minInt;
[SerializeField] private int maxInt = 10;
[SerializeField] private int intStep = 1;
[SerializeField] private float minFloat;
[SerializeField] private float maxFloat = 1f;
[SerializeField] private float floatStep = 0.1f;
[SerializeField] private bool displayFloatAsPercentage;
[Header("Options")]
[SerializeField] private List options = new();
[Header("Button")]
[SerializeField] private string buttonText;
[SerializeField] private string buttonData;
[SerializeField] private Color buttonColor = Color.white;
[SerializeField] private Sprite buttonSprite;
///
/// Уникальный ключ настройки.
///
public string Key => key;
///
/// Название настройки для сервисного UI.
///
public string DisplayName => displayName;
///
/// Описание настройки для подсказок обслуживающему персоналу.
///
public string Description => description;
///
/// Группа настройки в сервисном меню.
///
public string Group => group;
///
/// Показывать ли настройку в сервисном меню.
///
public bool ShownInServiceMenu => shownInServiceMenu;
///
/// Можно ли менять настройку через внешний JSON.
///
public bool ExposedForExternalChanges => exposedForExternalChanges;
///
/// Тип значения настройки.
///
public ServiceSettingValueType ValueType => valueType;
///
/// Предпочитаемый вид UI-контрола для настройки.
///
public ServiceSettingDisplayMode DisplayMode => displayMode;
///
/// Минимальное int-значение с защитой от перепутанных границ.
///
public int MinInt => Mathf.Min(minInt, maxInt);
///
/// Максимальное int-значение с защитой от перепутанных границ.
///
public int MaxInt => Mathf.Max(minInt, maxInt);
///
/// Шаг изменения int-значения.
///
public int IntStep => Mathf.Max(1, intStep);
///
/// Минимальное float-значение с защитой от перепутанных границ.
///
public float MinFloat => Mathf.Min(minFloat, maxFloat);
///
/// Максимальное float-значение с защитой от перепутанных границ.
///
public float MaxFloat => Mathf.Max(minFloat, maxFloat);
///
/// Шаг изменения float-значения.
///
public float FloatStep => Mathf.Max(0.0001f, floatStep);
///
/// Отображать ли float-значение как проценты.
///
public bool DisplayFloatAsPercentage => displayFloatAsPercentage;
///
/// Список вариантов для option-настройки.
///
public IReadOnlyList Options => options;
///
/// Текст кнопки действия. Если не задан, UI использует название настройки.
///
public string ButtonText => buttonText;
///
/// Дополнительные данные кнопки: URL, имя окна, идентификатор команды или другая payload-строка.
///
public string ButtonData => buttonData;
///
/// Цвет кнопки действия, перенесенный из legacy-базы.
///
public Color ButtonColor => buttonColor;
///
/// Опциональный спрайт кнопки действия.
///
public Sprite ButtonSprite => buttonSprite;
///
/// Значение по умолчанию, собранное из полей под выбранный тип.
///
public ServiceSettingValue DefaultValue => valueType switch
{
ServiceSettingValueType.Bool => ServiceSettingValue.Bool(defaultBool),
ServiceSettingValueType.Int => ServiceSettingValue.Int(defaultInt),
ServiceSettingValueType.Float => ServiceSettingValue.Float(defaultFloat),
ServiceSettingValueType.String => ServiceSettingValue.String(defaultString),
ServiceSettingValueType.Button => ServiceSettingValue.Button(),
ServiceSettingValueType.Option => ServiceSettingValue.Option(GetDefaultOptionIndex()),
_ => default
};
///
/// Приводит входное значение к типу и диапазонам настройки.
///
public ServiceSettingValue Sanitize(ServiceSettingValue value)
{
if (valueType == ServiceSettingValueType.Button)
{
return ServiceSettingValue.Button();
}
if (value.type != valueType && !(valueType == ServiceSettingValueType.Option && value.type == ServiceSettingValueType.Int))
{
return Sanitize(DefaultValue);
}
return valueType switch
{
ServiceSettingValueType.Bool => ServiceSettingValue.Bool(value.boolValue),
ServiceSettingValueType.Int => ServiceSettingValue.Int(Mathf.Clamp(value.intValue, MinInt, MaxInt)),
ServiceSettingValueType.Float => ServiceSettingValue.Float(Mathf.Clamp(value.floatValue, MinFloat, MaxFloat)),
ServiceSettingValueType.String => ServiceSettingValue.String(value.stringValue),
ServiceSettingValueType.Option => ServiceSettingValue.Option(SanitizeOptionIndex(value.intValue)),
_ => DefaultValue
};
}
///
/// Возвращает безопасный индекс варианта по умолчанию.
///
private int GetDefaultOptionIndex()
{
return SanitizeOptionIndex(defaultOptionIndex);
}
///
/// Ограничивает option-index доступным диапазоном.
///
private int SanitizeOptionIndex(int index)
{
return options is { Count: > 0 } ? Mathf.Clamp(index, 0, options.Count - 1) : 0;
}
}
}