//--------------------------------------------
// NGUI: HUD Text
// Copyright © 2012 Tasharen Entertainment
//--------------------------------------------
using UnityEngine;
using System.Collections.Generic;
///
/// HUD text creates temporary on-screen text entries that are perfect for damage, effects, and messages.
///
[AddComponentMenu("NGUI/Examples/HUD Text")]
public class HUDText : MonoBehaviour
{
protected class Entry
{
public float time; // Timestamp of when this entry was added
public float stay = 0f; // How long the text will appear to stay stationary on the screen
public float offset = 0f; // How far the object has moved based on time
public float val = 0f; // Optional value (used for damage)
public UILabel label; // Label on the game object
public float scaleTime = 0; // add by chenbin
public float movementStart { get { return time + stay; } }
}
///
/// Sorting comparison function.
///
static int Comparison(Entry a, Entry b)
{
if (a.movementStart < b.movementStart) return -1;
if (a.movementStart > b.movementStart) return 1;
return 0;
}
///
/// Font that will be used to create labels.
///
[HideInInspector]
public string fontName; //add by chenbin
[HideInInspector]
public UIFont font;
///
/// Effect applied to the text.
///
public UILabel.Effect effect = UILabel.Effect.None;
public bool inactiveWhenFinish = false;
public bool gradient = false;
public FontStyle fontStyle = FontStyle.Normal;
public int spacingX = 0;
public bool needAddValue = true;
public bool needQueue = true;
public float scaleOffset = 1;
public float speed = 1;
public float hightOffset = 0;
public AnimationCurve scaleCurve = new AnimationCurve(new Keyframe[] { new Keyframe(0f, 0f), new Keyframe(1f, 1f) });
///
/// Curve used to move entries with time.
///
public AnimationCurve offsetCurve = new AnimationCurve(new Keyframe[] { new Keyframe(0f, 0f), new Keyframe(3f, 40f) });
///
/// Curve used to fade out entries with time.
///
public AnimationCurve alphaCurve = new AnimationCurve(new Keyframe[] { new Keyframe(1f, 1f), new Keyframe(3f, 0.001f) });
List mList = new List();
List mUnused = new List();
int counter = 0;
///
/// Whether some HUD text is visible.
///
public bool isVisible { get { return mList.Count != 0; } }
///
/// Create a new entry, reusing an old entry if necessary.
///
Entry Create()
{
// See if an unused entry can be reused
if (mUnused.Count > 0)
{
Entry ent = mUnused[mUnused.Count - 1];
mUnused.RemoveAt(mUnused.Count - 1);
ent.time = Time.realtimeSinceStartup;
ent.label.depth = NGUITools.CalculateNextDepth(HUDRoot.go) + 10;
//ent.label.gameObject.active = true;
ent.offset = 0f;
ent.scaleTime = 0f;
ent.label.applyGradient = gradient;
ent.label.enabled = false;
ent.label.gameObject.SetActive(true);
mList.Add(ent);
return ent;
}
// New entry
Entry ne = new Entry();
ne.time = Time.realtimeSinceStartup;
ne.label = NGUITools.AddWidget(gameObject);
ne.label.name = counter.ToString();
ne.label.effectStyle = effect;
ne.label.applyGradient = gradient;
ne.label.fontStyle = fontStyle;
ne.label.spacingX = spacingX;
ne.label.bitmapFont = font;
if (font != null)
{
ne.label.fontSize = font.defaultSize;
}
else
{
ne.label.fontSize = 30;
}
// Make it small so that it's invisible to start with
ne.label.cachedTransform.localScale = new Vector3(0.01f, 0.01f, 0.01f);
ne.label.overflowMethod = UILabel.Overflow.ResizeHeight;
ne.label.width = (int)(Screen.width * UIRoot.GetPixelSizeAdjustment(ne.label.gameObject) * 0.65f);
ne.scaleTime = 0f;
mList.Add(ne);
++counter;
return ne;
}
///
/// Delete the specified entry, adding it to the unused list.
///
void Delete(Entry ent)
{
ent.label.enabled = false;
if (inactiveWhenFinish)
{
ent.label.gameObject.SetActive(false);
}
else
{
ent.label.transform.localPosition = new Vector3(0, 10000, 0);
}
mList.Remove(ent);
mUnused.Add(ent);
}
public void init(int num = 1)
{
for (int i = 0; i < num; i++)
{
Entry ne = Create();
mList.Add(ne);
}
int count = mList.Count;
for (int i = 0; i < count; i++)
{
mUnused.Add(mList[i]);
}
mList.Clear();
}
///
/// Add a new scrolling text entry.
///
public UILabel Add(object obj, Color c, float stayDuration, float scaleOffset = 1)
{
if (!enabled) return null;
float time = Time.realtimeSinceStartup;
bool isNumeric = false;
float val = 0f;
this.scaleOffset = scaleOffset;
if (obj is float)
{
isNumeric = true;
val = (float)obj;
}
else if (obj is int)
{
isNumeric = true;
val = (int)obj;
}
else if (obj is double)
{
isNumeric = true;
val = float.Parse(obj.ToString());
} else if (obj is System.Int64)
{
isNumeric = true;
val = float.Parse(obj.ToString());
}
if (isNumeric && needAddValue)
{
if (Mathf.Abs(val) <= 0.0001f) return null;
for (int i = mList.Count; i > 0;)
{
Entry ent = mList[--i];
if (ent.time + 1f < time) continue;
if (ent.val < 0f && val < 0f)
{
ent.val += val;
ent.label.text = Mathf.RoundToInt(ent.val).ToString();
ent.label.fontSize = Mathf.CeilToInt(font.defaultSize * scaleOffset);
return ent.label;
}
else if (ent.val > 0f && val > 0f)
{
ent.val += val;
ent.label.text = Coolape.PStr.begin().a ("+").a (Mathf.RoundToInt(ent.val)).end(); // add by chenbin
//ent.label.text = Mathf.RoundToInt(ent.val).ToString();
ent.label.fontSize = Mathf.CeilToInt(font.defaultSize * scaleOffset);
return ent.label;
}
}
}
// Create a new entry
Entry ne = Create();
ne.stay = stayDuration;
ne.label.color = c;
if (font != null)
{
ne.label.fontSize = Mathf.CeilToInt(font.defaultSize * scaleOffset);
}
else
{
ne.label.fontSize = 30;
}
ne.val = val;
if (isNumeric)
{
ne.label.text = (val < 0f ? Mathf.RoundToInt(ne.val).ToString() : Coolape.PStr.begin().a("+").a(Mathf.RoundToInt(ne.val)).e());
}
else
{
ne.label.text = obj.ToString();
}
ne.scaleTime = ne.scaleTime >= 1 ? 0 : ne.scaleTime; //add by chenbin
// Sort the list
mList.Sort(Comparison);
return ne.label;
}
///
/// Disable all labels when this script gets disabled.
///
void OnDisable()
{
Entry lent = null;
int count = mList.Count;
for (int i = count - 1; i >= 0; i--)
{
lent = mList[i];
if (lent.label != null)
{
Delete(lent);
}
}
}
///
/// Update the position of all labels, as well as update their size and alpha.
///
float time = 0;
Keyframe[] offsets;
Keyframe[] alphas;
float alphaEnd;
float offsetEnd;
float totalEnd;
Entry cellEnt;
float currentTime;
float offset = 0f;
float tmpSize;
// [HideInInspector]
public bool ignoreTimeScale = true;
void Update()
{
time = Time.realtimeSinceStartup;
offsets = offsetCurve.keys;
alphas = alphaCurve.keys;
offsetEnd = offsets[offsets.Length - 1].time;
alphaEnd = alphas[alphas.Length - 1].time;
totalEnd = Mathf.Max(offsetEnd, alphaEnd);
// Adjust alpha and delete old entries
for (int i = mList.Count; i > 0;)
{
cellEnt = mList[--i];
if (cellEnt.stay < 0)
{
//NGUI 2.X
// ent.label.cachedTransform.localScale = new Vector3(font.size, font.size, 1f); //modify by chenbin
//NGUI 3.0
cellEnt.label.cachedTransform.localScale = Vector3.one; // add by chenbin
cellEnt.label.enabled = true;
continue;
}
currentTime = time - cellEnt.movementStart;
cellEnt.offset = offsetCurve.Evaluate(currentTime);
cellEnt.label.alpha = alphaCurve.Evaluate(currentTime);
// Fade the label in by adjusting its size
// float size = font.size * Mathf.Clamp01((time - ent.time) * 4f); // del by chenbin
// float size = Mathf.Clamp01((time - ent.time) * 4f); //add by chenbin
cellEnt.scaleTime += (ignoreTimeScale ? RealTime.deltaTime : Time.deltaTime) * speed;//Time.deltaTime;
cellEnt.scaleTime = cellEnt.scaleTime > 1 ? 1 : cellEnt.scaleTime;
tmpSize = scaleCurve.Evaluate(cellEnt.scaleTime);
cellEnt.label.cachedTransform.localScale = new Vector3(tmpSize, tmpSize, 1f);
// Delete the entry when needed
if (currentTime > totalEnd) Delete(cellEnt);
else cellEnt.label.enabled = true;
}
offset = 0f;
// Move the entries
for (int i = mList.Count; i > 0;)
{
cellEnt = mList[--i];
if (cellEnt.stay < 0) continue;
offset = Mathf.Max(offset, cellEnt.offset);
cellEnt.label.cachedTransform.localPosition = new Vector3(0f, offset, 0f);
if (needQueue)
{
offset += Mathf.Round(cellEnt.label.cachedTransform.localScale.y * cellEnt.label.height + hightOffset); //modify by chenbin
}
}
}
}