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 ;
}
}
}
}