Some checks failed
Gitea Actions Demo / Explore-Gitea-Actions (push) Has been cancelled
- добавлена новая система призов: PrizeBase, PrizeType, PrizeDatabase, LevelPrizeConfig и реализации для hopper, QR-кода, отсутствия приза и стойки с призом - добавлена конфигурация призов уровней через `prizes.json` и связанная логика загрузки/обработки в менеджерах игры - расширен UI главного меню и настроек уровней: добавлены LevelSettingsModal, LevelPrizeSettingsModal, QRCodeModal и PrizeStandModal - обновлена навигация модальных окон и связанный UI-код: ModalManager, MainMenu, RulesModal, PauseMenu, PrizeErrorDisplay, UIRowPointer и WinBannerController - доработаны настройки и генерация UI-элементов: обновлены SettingsDatabase, SettingsUIGenerator, SettingUIItem, ValueSelectorRow и editor drawer для настроек - обновлены и добавлены UI-prefab'ы для кнопок, строк настроек, панели групп и кнопки настроек уровня - обновлены сцены `MainMenu` и `Level UI` под новый флоу настройки уровней, выбора призов и отображения модалок - добавлены файлы лаунчера в `StreamingAssets`, включая `RRLauncher.exe`, служебные meta-файлы и документацию - улучшено логирование через FileLogger и удален устаревший код лицензирования - удалены больше неиспользуемые файлы: `Licensing.cs`, `SteppedSlider.cs` и recovery-сцены
231 lines
8.8 KiB
C#
231 lines
8.8 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using UnityEngine;
|
||
|
||
namespace RR.Common.Settings
|
||
{
|
||
public enum SettingValueType
|
||
{
|
||
Bool,
|
||
Int,
|
||
Float,
|
||
String,
|
||
Button, // Кнопка - не хранит значение, только вызывает действие
|
||
OptionPicker // Выбор из списка опций (enum-like)
|
||
}
|
||
|
||
public enum ApplyTarget
|
||
{
|
||
None,
|
||
Audio // Применить к звуку через AudioManager (музыка или эффекты)
|
||
}
|
||
|
||
public enum AudioTargetType
|
||
{
|
||
Music, // Музыка
|
||
Sfx // Звуковые эффекты
|
||
}
|
||
|
||
public enum IntDisplayFormat
|
||
{
|
||
Slider, // Обычный слайдер
|
||
ValueSelector // Выбор значения (со стрелками или дропдауном)
|
||
}
|
||
|
||
public enum FloatDisplayFormat
|
||
{
|
||
Slider, // Обычный слайдер
|
||
ValueSelector // Выбор значения (со стрелками)
|
||
}
|
||
|
||
[Serializable]
|
||
public struct SettingValue
|
||
{
|
||
public SettingValueType type;
|
||
public bool b;
|
||
public int i;
|
||
public float f;
|
||
public string s;
|
||
|
||
public static SettingValue Bool(bool v) => new() { type = SettingValueType.Bool, b = v };
|
||
public static SettingValue Int(int v) => new() { type = SettingValueType.Int, i = v };
|
||
public static SettingValue Float(float v) => new() { type = SettingValueType.Float, f = v };
|
||
public static SettingValue String(string v) => new() { type = SettingValueType.String, s = v };
|
||
|
||
/// <summary>
|
||
/// Создает компактную версию для сериализации (только нужные поля)
|
||
/// </summary>
|
||
public SettingValueCompact ToCompact()
|
||
{
|
||
return new SettingValueCompact
|
||
{
|
||
type = (int)type,
|
||
value = type switch
|
||
{
|
||
SettingValueType.Bool => b ? "1" : "0",
|
||
SettingValueType.Int => i.ToString(),
|
||
SettingValueType.Float => f.ToString("F6"),
|
||
SettingValueType.String => s ?? "",
|
||
_ => ""
|
||
}
|
||
};
|
||
}
|
||
|
||
/// <summary>
|
||
/// Создает SettingValue из компактной версии
|
||
/// </summary>
|
||
public static SettingValue FromCompact(SettingValueCompact compact)
|
||
{
|
||
var type = (SettingValueType)compact.type;
|
||
return type switch
|
||
{
|
||
SettingValueType.Bool => Bool(compact.value == "1"),
|
||
SettingValueType.Int => Int(int.TryParse(compact.value, out int i) ? i : 0),
|
||
SettingValueType.Float => Float(float.TryParse(compact.value, out float f) ? f : 0f),
|
||
SettingValueType.String => String(compact.value ?? ""),
|
||
_ => default
|
||
};
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Компактная версия SettingValue для сериализации (экономит место в JSON)
|
||
/// </summary>
|
||
[Serializable]
|
||
public struct SettingValueCompact
|
||
{
|
||
public int type;
|
||
public string value;
|
||
}
|
||
|
||
[Serializable]
|
||
public class SettingEntry
|
||
{
|
||
public string key;
|
||
public string displayName;
|
||
[TextArea] public string description;
|
||
public string group = "General";
|
||
|
||
[Tooltip("Показывать ли настройку в UI меню настроек")]
|
||
public bool shownInSettings = true;
|
||
|
||
[Tooltip("Доступна ли настройка для изменения извне (через API/файл)")]
|
||
public bool exposed = false;
|
||
|
||
public SettingValueType valueType;
|
||
|
||
// Defaults
|
||
public bool defaultBool = true;
|
||
public int defaultInt = 0;
|
||
public float defaultFloat = 1f;
|
||
public string defaultString = "";
|
||
|
||
// Ranges (used for Int/Float)
|
||
public int minInt = 0;
|
||
public int maxInt = 10;
|
||
|
||
[Tooltip("Формат отображения для Int (слайдер или выбор значения)")]
|
||
public IntDisplayFormat intDisplayFormat = IntDisplayFormat.Slider;
|
||
|
||
[Tooltip("Шаг для выбора значения Int (используется только для ValueSelector)")]
|
||
public int intStep = 1;
|
||
|
||
public float minFloat = 0f;
|
||
public float maxFloat = 1f;
|
||
|
||
[Tooltip("Отображать float значение как проценты (0-100%)")]
|
||
public bool displayAsPercentage = false;
|
||
|
||
[Tooltip("Формат отображения для Float (слайдер или выбор значения)")]
|
||
public FloatDisplayFormat floatDisplayFormat = FloatDisplayFormat.Slider;
|
||
|
||
[Tooltip("Шаг для выбора значения Float (используется только для ValueSelector)")]
|
||
public float floatStep = 0.1f;
|
||
|
||
public ApplyTarget applyTarget = ApplyTarget.None;
|
||
|
||
// Audio params (используется только для ApplyTarget.Audio)
|
||
[Tooltip("Тип звука: музыка или звуковые эффекты")]
|
||
public AudioTargetType audioTargetType = AudioTargetType.Music;
|
||
|
||
// Button params (для типа Button)
|
||
[Tooltip("Текст на кнопке (если не задан displayName)")]
|
||
public string buttonText;
|
||
|
||
[Tooltip("Дополнительные данные для кнопки (URL, имя сцены и т.д.)")]
|
||
public string buttonData;
|
||
|
||
[Tooltip("Цвет кнопки")]
|
||
public Color buttonColor = Color.white;
|
||
|
||
[Tooltip("Текстура/спрайт кнопки")]
|
||
public Sprite buttonSprite;
|
||
|
||
// OptionPicker params (для типа OptionPicker)
|
||
[Tooltip("Список вариантов выбора")]
|
||
public List<string> options;
|
||
|
||
[Tooltip("Индекс варианта по умолчанию")]
|
||
public int defaultOptionIndex;
|
||
|
||
public SettingValue DefaultValue => valueType switch
|
||
{
|
||
SettingValueType.Bool => SettingValue.Bool(defaultBool),
|
||
SettingValueType.Int => SettingValue.Int(defaultInt),
|
||
SettingValueType.Float => SettingValue.Float(defaultFloat),
|
||
SettingValueType.String => SettingValue.String(defaultString ?? ""),
|
||
SettingValueType.Button => default, // Кнопки не хранят значение
|
||
SettingValueType.OptionPicker => SettingValue.Int(options != null && options.Count > 0
|
||
? Mathf.Clamp(defaultOptionIndex, 0, options.Count - 1)
|
||
: 0),
|
||
_ => default
|
||
};
|
||
|
||
public SettingValue Sanitize(SettingValue v)
|
||
{
|
||
if (v.type != valueType) return DefaultValue;
|
||
|
||
// защита от кривых min/max
|
||
int iMin = Mathf.Min(minInt, maxInt);
|
||
int iMax = Mathf.Max(minInt, maxInt);
|
||
float fMin = Mathf.Min(minFloat, maxFloat);
|
||
float fMax = Mathf.Max(minFloat, maxFloat);
|
||
|
||
return valueType switch
|
||
{
|
||
SettingValueType.Bool => SettingValue.Bool(v.b),
|
||
SettingValueType.Int => SettingValue.Int(Mathf.Clamp(v.i, iMin, iMax)),
|
||
SettingValueType.Float => SettingValue.Float(Mathf.Clamp(v.f, fMin, fMax)),
|
||
SettingValueType.String => SettingValue.String(v.s ?? ""),
|
||
SettingValueType.Button => default,
|
||
SettingValueType.OptionPicker => SettingValue.Int(options != null && options.Count > 0
|
||
? Mathf.Clamp(v.i, 0, options.Count - 1)
|
||
: 0),
|
||
_ => DefaultValue
|
||
};
|
||
}
|
||
}
|
||
|
||
[CreateAssetMenu(menuName = "Settings/Database")]
|
||
public class SettingsDatabase : ScriptableObject
|
||
{
|
||
public List<SettingEntry> entries = new();
|
||
|
||
public SettingEntry Find(string key)
|
||
=> entries.Find(e => string.Equals(e.key, key, StringComparison.Ordinal));
|
||
|
||
private void OnValidate()
|
||
{
|
||
var set = new HashSet<string>();
|
||
foreach (var e in entries)
|
||
{
|
||
if (e == null) continue;
|
||
|
||
if (string.IsNullOrWhiteSpace(e.key))
|
||
Debug.LogWarning($"[SettingsDatabase] Empty key in {name}", this);
|
||
else if (!set.Add(e.key))
|
||
Debug.LogWarning($"[SettingsDatabase] Duplicate key '{e.key}' in {name}", this);
|
||
}
|
||
}
|
||
}
|
||
} |