using UnityEngine; using UnityEngine.UI; using System.Collections; using System; namespace UIWidgets { /// /// Progressbar types. /// Determinate - Allow specify Max progress. /// Indeterminate - Indeterminate. /// public enum ProgressbarTypes { Determinate = 0, Indeterminate = 1, } /// /// Progressbar text types. /// None - Don't show text. /// Percent - Show progress in percent. /// Range - Show progress in range. /// public enum ProgressbarTextTypes { None = 0, Percent = 1, Range = 2, } /// /// Progressbar direction. /// Horizontal - Horizontal. /// Vertical - Vertical. /// public enum ProgressbarDirection { Horizontal = 0, Vertical = 1, } /// /// Progressbar. /// http://ilih.ru/images/unity-assets/UIWidgets/ProgressbarDeterminate.png /// http://ilih.ru/images/unity-assets/UIWidgets/ProgressbarIndeterminate.png /// /// // Example of using Progressbar for show instantiating progress. /// /// var bar = GetComponent(); /// bar.Max = 10000; /// for (int i = 0; i < 10000; i++) /// { /// Instantiate(prefab); /// if (i % 100) /// { /// bar.Value = i; /// yield return null;//wait 1 frame /// } /// } /// /// /// [AddComponentMenu("UI/UIWidgets/Progressbar")] public class Progressbar : MonoBehaviour { /// /// Max value of progress. /// [SerializeField] public int Max = 100; [SerializeField] int _value; /// /// Gets or sets the value. /// /// The value. public int Value { get { return _value; } set { if (value > Max) { value = Max; } _value = value; UpdateProgressbar(); } } [SerializeField] ProgressbarDirection Direction = ProgressbarDirection.Horizontal; [SerializeField] ProgressbarTypes type = ProgressbarTypes.Determinate; /// /// Gets or sets the type. /// /// The type. public ProgressbarTypes Type { get { return type; } set { type = value; ToggleType(); } } /// /// The indeterminate bar. /// Use texture type "texture" and set wrap mode = repeat; /// [SerializeField] public RawImage IndeterminateBar; /// /// The determinate bar. /// [SerializeField] public GameObject DeterminateBar; /// /// The empty bar. /// [SerializeField] public Image EmptyBar; /// /// The empty bar text. /// [SerializeField] public Text EmptyBarText; [SerializeField] Image fullBar; /// /// Gets or sets the full bar. /// /// The full bar. public Image FullBar { get { return fullBar; } set { fullBar = value; } } RectTransform FullBarRectTransform { get { return fullBar.transform as RectTransform; } } /// /// The full bar text. /// [SerializeField] public Text FullBarText; /// /// The bar mask. /// [SerializeField] public RectTransform BarMask; [SerializeField] ProgressbarTextTypes textType = ProgressbarTextTypes.None; /// /// Gets or sets the type of the text. /// /// The type of the text. [SerializeField] public ProgressbarTextTypes TextType { get { return textType; } set { textType = value; ToggleTextType(); } } /// /// The speed. /// For Determinate how many seconds past before for changing progress on 1. /// For Indeterminate speed of changing uvRect coordinates. /// [SerializeField] public float Speed = 0.1f; Func textFunc = TextPercent; /// /// Gets or sets the text function. /// /// The text function. public Func TextFunc { get { return textFunc; } set { textFunc = value; UpdateText(); } } /// /// Use unscaled time. /// [SerializeField] public bool UnscaledTime = false; /// /// Gets a value indicating whether this instance is animation run. /// /// true if this instance is animation run; otherwise, false. public bool IsAnimationRun { get; protected set; } /// /// Don't show progress text. /// /// string.Empty /// Progressbar. public static string TextNone(Progressbar bar) { return string.Empty; } /// /// Show progress with percent. /// /// string.Empty /// Progressbar. public static string TextPercent(Progressbar bar) { return string.Format("{0:P0}", (float)bar.Value / bar.Max); } /// /// Show progress with range. /// /// The range. /// Progressbar. public static string TextRange(Progressbar bar) { return string.Format("{0} / {1}", bar.Value, bar.Max); } IEnumerator currentAnimation; /// /// Animate the progressbar to specified targetValue. /// /// Target value. public void Animate(int? targetValue=null) { if (currentAnimation!=null) { StopCoroutine(currentAnimation); } if (Type==ProgressbarTypes.Indeterminate) { currentAnimation = IndeterminateAnimation(); } else { currentAnimation = DeterminateAnimation(targetValue ?? Max); } IsAnimationRun = true; StartCoroutine(currentAnimation); } /// /// Stop animation. /// public void Stop() { if (IsAnimationRun) { StopCoroutine(currentAnimation); IsAnimationRun = false; } } IEnumerator DeterminateAnimation(int targetValue) { if (targetValue > Max) { targetValue = Max; } var delta = targetValue - Value; if (delta!=0) { while (true) { if (delta > 0) { _value += 1; } else { _value -= 1; } UpdateProgressbar(); if (_value==targetValue) { break; } yield return new WaitForSeconds(Speed); } } IsAnimationRun = false; } IEnumerator IndeterminateAnimation() { while (true) { var time = UnscaledTime ? Time.unscaledTime : Time.time; var r = IndeterminateBar.uvRect; if (Direction==ProgressbarDirection.Horizontal) { r.x = (time * Speed) % 1; } else { r.y = (time * Speed) % 1; } IndeterminateBar.uvRect = r; yield return null; } } /// /// Update progressbar. /// public void Refresh() { FullBar = fullBar; ToggleType(); ToggleTextType(); UpdateProgressbar(); } void UpdateProgressbar() { if ((BarMask!=null) && (FullBar!=null)) { var range = (float)Value / (float)Max; BarMask.sizeDelta = (Direction==ProgressbarDirection.Horizontal) ? new Vector2(FullBarRectTransform.rect.width * range, BarMask.sizeDelta.y) : new Vector2(BarMask.sizeDelta.x, FullBarRectTransform.rect.height * range); } UpdateText(); } /// /// Updates the text. /// protected virtual void UpdateText() { var text = textFunc(this); if (FullBarText!=null) { FullBarText.text = text; } if (EmptyBarText!=null) { EmptyBarText.text = text; } } void ToggleType() { bool is_deterimate = (type==ProgressbarTypes.Determinate); if (DeterminateBar!=null) { DeterminateBar.gameObject.SetActive(is_deterimate); } if (IndeterminateBar!=null) { IndeterminateBar.gameObject.SetActive(!is_deterimate); } } void ToggleTextType() { if (TextType==ProgressbarTextTypes.None) { textFunc = TextNone; return ; } if (TextType==ProgressbarTextTypes.Percent) { textFunc = TextPercent; return ; } if (TextType==ProgressbarTextTypes.Range) { textFunc = TextRange; return ; } } } }