#nullable enable using System; using UnityEngine; using UnityEngine.UIElements; namespace UVC.UIToolkit { /// /// 프로그레스 바 컴포넌트. /// Unity ProgressBar를 래핑하여 커스텀 스타일을 적용합니다. /// /// /// C# 코드에서 사용: /// /// // 기본 프로그레스 바 /// var progressBar = new UTKProgressBar(); /// progressBar.title = "다운로드 중..."; /// progressBar.MinValue = 0; /// progressBar.MaxValue = 100; /// progressBar.Value = 50; /// /// // 값 표시 설정 /// progressBar.ShowValue = true; /// progressBar.ShowPercentage = true; /// /// // 무한 로딩 (불확정 상태) /// progressBar.IsIndeterminate = true; /// /// // 변형 스타일 /// progressBar.Variant = UTKProgressBar.ProgressBarVariant.Success; /// /// UXML에서 사용: /// /// /// /// /// /// /// /// /// /// /// /// /// [UxmlElement] public partial class UTKProgressBar : ProgressBar, IDisposable { #region Constants private const string USS_PATH = "UIToolkit/Slider/UTKProgressBar"; #endregion #region Fields private bool _disposed; private bool _showValue = true; private bool _showPercentage = true; private bool _isIndeterminate; private ProgressBarVariant _variant = ProgressBarVariant.Default; #endregion #region Properties /// 현재 값 public float Value { get => value; set => SetValue(value); } /// 최소값 public float MinValue { get => lowValue; set { lowValue = value; UpdateValueLabel(); } } /// 최대값 public float MaxValue { get => highValue; set { highValue = value; UpdateValueLabel(); } } /// 값 표시 여부 [UxmlAttribute("show-value")] public bool ShowValue { get => _showValue; set { _showValue = value; UpdateValueLabel(); } } /// 퍼센트로 표시 여부 [UxmlAttribute("show-percentage")] public bool ShowPercentage { get => _showPercentage; set { _showPercentage = value; UpdateValueLabel(); } } /// 불확정 상태 (애니메이션) [UxmlAttribute("is-indeterminate")] public bool IsIndeterminate { get => _isIndeterminate; set { _isIndeterminate = value; EnableInClassList("utk-progress--indeterminate", value); UpdateValueLabel(); } } /// 스타일 변형 [UxmlAttribute("variant")] public ProgressBarVariant Variant { get => _variant; set { _variant = value; UpdateVariant(); } } #endregion #region Enums public enum ProgressBarVariant { Default, Success, Warning, Error } #endregion #region Constructor public UTKProgressBar() : base() { UTKThemeManager.Instance.ApplyThemeToElement(this); var uss = Resources.Load(USS_PATH); if (uss != null) { styleSheets.Add(uss); } SetupStyles(); SubscribeToThemeChanges(); } public UTKProgressBar(string text, float value = 0f, float maxValue = 100f) : this() { title = text; highValue = maxValue; SetValue(value); } #endregion #region Setup private void SetupStyles() { AddToClassList("utk-progress"); UpdateVariant(); UpdateValueLabel(); } private void SubscribeToThemeChanges() { UTKThemeManager.Instance.OnThemeChanged += OnThemeChanged; RegisterCallback(_ => { UTKThemeManager.Instance.OnThemeChanged -= OnThemeChanged; }); } private void OnThemeChanged(UTKTheme theme) { UTKThemeManager.Instance.ApplyThemeToElement(this); } #endregion #region Methods /// /// 값 설정 /// public void SetValue(float newValue) { value = Mathf.Clamp(newValue, lowValue, highValue); UpdateValueLabel(); } private void UpdateValueLabel() { if (_isIndeterminate || !_showValue) { title = title?.Split(' ')[0] ?? ""; return; } string baseTitle = title?.Split(' ')[0] ?? ""; if (_showPercentage) { float range = highValue - lowValue; float percent = range > 0 ? (value - lowValue) / range * 100 : 0; title = string.IsNullOrEmpty(baseTitle) ? $"{percent:F0}%" : $"{baseTitle} {percent:F0}%"; } else { title = string.IsNullOrEmpty(baseTitle) ? $"{value:F0}/{highValue:F0}" : $"{baseTitle} {value:F0}/{highValue:F0}"; } } private void UpdateVariant() { RemoveFromClassList("utk-progress--default"); RemoveFromClassList("utk-progress--success"); RemoveFromClassList("utk-progress--warning"); RemoveFromClassList("utk-progress--error"); var variantClass = _variant switch { ProgressBarVariant.Success => "utk-progress--success", ProgressBarVariant.Warning => "utk-progress--warning", ProgressBarVariant.Error => "utk-progress--error", _ => "utk-progress--default" }; AddToClassList(variantClass); } #endregion #region IDisposable public void Dispose() { if (_disposed) return; _disposed = true; UTKThemeManager.Instance.OnThemeChanged -= OnThemeChanged; } #endregion } }