/Project/Assets/Scripts/ThirdParty/NGUI/Scripts/UI/UIFilledSprite.cs
https://bitbucket.org/adiq94/villageposition · C# · 466 lines · 360 code · 64 blank · 42 comment · 63 complexity · f605dc271b75743d88dde679032823b3 MD5 · raw file
- //----------------------------------------------
- // NGUI: Next-Gen UI kit
- // Copyright � 2011-2012 Tasharen Entertainment
- //----------------------------------------------
- using UnityEngine;
- using System.Collections.Generic;
- /// <summary>
- /// Similar to a regular UISprite, but lets you only display a part of it. Great for progress bars, sliders, timers, etc.
- /// </summary>
- [ExecuteInEditMode]
- [AddComponentMenu("NGUI/UI/Sprite (Filled)")]
- public class UIFilledSprite : UISprite
- {
- public enum FillDirection
- {
- Horizontal,
- Vertical,
- Radial90,
- Radial180,
- Radial360,
- }
- [HideInInspector][SerializeField] FillDirection mFillDirection = FillDirection.Radial360;
- [HideInInspector][SerializeField] float mFillAmount = 1.0f;
- [HideInInspector][SerializeField] bool mInvert = false;
- /// <summary>
- /// Direction of the cut procedure.
- /// </summary>
- public FillDirection fillDirection
- {
- get
- {
- return mFillDirection;
- }
- set
- {
- if (mFillDirection != value)
- {
- mFillDirection = value;
- mChanged = true;
- }
- }
- }
- /// <summary>
- /// Amount of the sprite shown. 0-1 range with 0 being nothing shown, and 1 being the full sprite.
- /// </summary>
- public float fillAmount
- {
- get
- {
- return mFillAmount;
- }
- set
- {
- float val = Mathf.Clamp01(value);
- if (mFillAmount != val)
- {
- mFillAmount = val;
- mChanged = true;
- }
- }
- }
- /// <summary>
- /// Whether the sprite should be filled in the opposite direction.
- /// </summary>
- public bool invert
- {
- get
- {
- return mInvert;
- }
- set
- {
- if (mInvert != value)
- {
- mInvert = value;
- mChanged = true;
- }
- }
- }
- /// <summary>
- /// Adjust the specified quad, making it be radially filled instead.
- /// </summary>
- bool AdjustRadial (Vector2[] xy, Vector2[] uv, float fill, bool invert)
- {
- // Nothing to fill
- if (fill < 0.001f) return false;
- // Nothing to adjust
- if (!invert && fill > 0.999f) return true;
- // Convert 0-1 value into 0 to 90 degrees angle in radians
- float angle = Mathf.Clamp01(fill);
- if (!invert) angle = 1f - angle;
- angle *= 90f * Mathf.Deg2Rad;
- // Calculate the effective X and Y factors
- float fx = Mathf.Sin(angle);
- float fy = Mathf.Cos(angle);
- // Normalize the result, so it's projected onto the side of the rectangle
- if (fx > fy)
- {
- fy *= 1f / fx;
- fx = 1f;
- if (!invert)
- {
- xy[0].y = Mathf.Lerp(xy[2].y, xy[0].y, fy);
- xy[3].y = xy[0].y;
- uv[0].y = Mathf.Lerp(uv[2].y, uv[0].y, fy);
- uv[3].y = uv[0].y;
- }
- }
- else if (fy > fx)
- {
- fx *= 1f / fy;
- fy = 1f;
- if (invert)
- {
- xy[0].x = Mathf.Lerp(xy[2].x, xy[0].x, fx);
- xy[1].x = xy[0].x;
- uv[0].x = Mathf.Lerp(uv[2].x, uv[0].x, fx);
- uv[1].x = uv[0].x;
- }
- }
- else
- {
- fx = 1f;
- fy = 1f;
- }
- if (invert)
- {
- xy[1].y = Mathf.Lerp(xy[2].y, xy[0].y, fy);
- uv[1].y = Mathf.Lerp(uv[2].y, uv[0].y, fy);
- }
- else
- {
- xy[3].x = Mathf.Lerp(xy[2].x, xy[0].x, fx);
- uv[3].x = Mathf.Lerp(uv[2].x, uv[0].x, fx);
- }
- return true;
- }
- /// <summary>
- /// Helper function that copies the contents of the array, rotated by the specified offset.
- /// </summary>
- void Rotate (Vector2[] v, int offset)
- {
- for (int i = 0; i < offset; ++i)
- {
- Vector2 v0 = new Vector2(v[3].x, v[3].y);
- v[3].x = v[2].y;
- v[3].y = v[2].x;
- v[2].x = v[1].y;
- v[2].y = v[1].x;
- v[1].x = v[0].y;
- v[1].y = v[0].x;
- v[0].x = v0.y;
- v[0].y = v0.x;
- }
- }
- /// <summary>
- /// Virtual function called by the UIScreen that fills the buffers.
- /// </summary>
- #if UNITY_3_5_4
- override public void OnFill (BetterList<Vector3> verts, BetterList<Vector2> uvs, BetterList<Color> cols)
- #else
- override public void OnFill (BetterList<Vector3> verts, BetterList<Vector2> uvs, BetterList<Color32> cols)
- #endif
- {
- float x0 = 0f;
- float y0 = 0f;
- float x1 = 1f;
- float y1 = -1f;
- float u0 = mOuterUV.xMin;
- float v0 = mOuterUV.yMin;
- float u1 = mOuterUV.xMax;
- float v1 = mOuterUV.yMax;
- // Horizontal and vertical filled sprites are simple -- just end the sprite prematurely
- if (mFillDirection == FillDirection.Horizontal || mFillDirection == FillDirection.Vertical)
- {
- float du = (u1 - u0) * mFillAmount;
- float dv = (v1 - v0) * mFillAmount;
- if (fillDirection == FillDirection.Horizontal)
- {
- if (mInvert)
- {
- x0 = (1f - mFillAmount);
- u0 = u1 - du;
- }
- else
- {
- x1 *= mFillAmount;
- u1 = u0 + du;
- }
- }
- else if (fillDirection == FillDirection.Vertical)
- {
- if (mInvert)
- {
- y1 *= mFillAmount;
- v0 = v1 - dv;
- }
- else
- {
- y0 = -(1f - mFillAmount);
- v1 = v0 + dv;
- }
- }
- }
- // Starting quad for the sprite
- Vector2[] xy = new Vector2[4];
- Vector2[] uv = new Vector2[4];
- xy[0] = new Vector2(x1, y0);
- xy[1] = new Vector2(x1, y1);
- xy[2] = new Vector2(x0, y1);
- xy[3] = new Vector2(x0, y0);
- uv[0] = new Vector2(u1, v1);
- uv[1] = new Vector2(u1, v0);
- uv[2] = new Vector2(u0, v0);
- uv[3] = new Vector2(u0, v1);
- Color colF = color;
- colF.a *= mPanel.alpha;
- #if UNITY_3_5_4
- Color col = atlas.premultipliedAlpha ? NGUITools.ApplyPMA(colF) : colF;
- #else
- Color32 col = atlas.premultipliedAlpha ? NGUITools.ApplyPMA(colF) : colF;
- #endif
- if (fillDirection == FillDirection.Radial90)
- {
- // Adjust the quad radially, and if 'false' is returned (it's not visible), just exit
- if (!AdjustRadial(xy, uv, mFillAmount, mInvert)) return;
- }
- else if (fillDirection == FillDirection.Radial180)
- {
- // Working in 0-1 coordinates is easier
- Vector2[] oxy = new Vector2[4];
- Vector2[] ouv = new Vector2[4];
- for (int i = 0; i < 2; ++i)
- {
- oxy[0] = new Vector2(0f, 0f);
- oxy[1] = new Vector2(0f, 1f);
- oxy[2] = new Vector2(1f, 1f);
- oxy[3] = new Vector2(1f, 0f);
- ouv[0] = new Vector2(0f, 0f);
- ouv[1] = new Vector2(0f, 1f);
- ouv[2] = new Vector2(1f, 1f);
- ouv[3] = new Vector2(1f, 0f);
- // Each half must be rotated 90 degrees clockwise in order for it to fill properly
- if (mInvert)
- {
- if (i > 0)
- {
- Rotate(oxy, i);
- Rotate(ouv, i);
- }
- }
- else if (i < 1)
- {
- Rotate(oxy, 1 - i);
- Rotate(ouv, 1 - i);
- }
- // Each half must fill in only a part of the space
- float x, y;
- if (i == 1)
- {
- x = mInvert ? 0.5f : 1f;
- y = mInvert ? 1f : 0.5f;
- }
- else
- {
- x = mInvert ? 1f : 0.5f;
- y = mInvert ? 0.5f : 1f;
- }
- oxy[1].y = Mathf.Lerp(x, y, oxy[1].y);
- oxy[2].y = Mathf.Lerp(x, y, oxy[2].y);
- ouv[1].y = Mathf.Lerp(x, y, ouv[1].y);
- ouv[2].y = Mathf.Lerp(x, y, ouv[2].y);
- float amount = (mFillAmount) * 2 - i;
- bool odd = (i % 2) == 1;
- if (AdjustRadial(oxy, ouv, amount, !odd))
- {
- if (mInvert) odd = !odd;
- // Add every other side in reverse order so they don't come out backface-culled due to rotation
- if (odd)
- {
- for (int b = 0; b < 4; ++b)
- {
- x = Mathf.Lerp(xy[0].x, xy[2].x, oxy[b].x);
- y = Mathf.Lerp(xy[0].y, xy[2].y, oxy[b].y);
- float u = Mathf.Lerp(uv[0].x, uv[2].x, ouv[b].x);
- float v = Mathf.Lerp(uv[0].y, uv[2].y, ouv[b].y);
- verts.Add(new Vector3(x, y, 0f));
- uvs.Add(new Vector2(u, v));
- cols.Add(col);
- }
- }
- else
- {
- for (int b = 3; b > -1; --b)
- {
- x = Mathf.Lerp(xy[0].x, xy[2].x, oxy[b].x);
- y = Mathf.Lerp(xy[0].y, xy[2].y, oxy[b].y);
- float u = Mathf.Lerp(uv[0].x, uv[2].x, ouv[b].x);
- float v = Mathf.Lerp(uv[0].y, uv[2].y, ouv[b].y);
- verts.Add(new Vector3(x, y, 0f));
- uvs.Add(new Vector2(u, v));
- cols.Add(col);
- }
- }
- }
- }
- return;
- }
- else if (fillDirection == FillDirection.Radial360)
- {
- float[] matrix = new float[]
- {
- // x0 y0 x1 y1
- 0.5f, 1f, 0f, 0.5f, // quadrant 0
- 0.5f, 1f, 0.5f, 1f, // quadrant 1
- 0f, 0.5f, 0.5f, 1f, // quadrant 2
- 0f, 0.5f, 0f, 0.5f, // quadrant 3
- };
- Vector2[] oxy = new Vector2[4];
- Vector2[] ouv = new Vector2[4];
- for (int i = 0; i < 4; ++i)
- {
- oxy[0] = new Vector2(0f, 0f);
- oxy[1] = new Vector2(0f, 1f);
- oxy[2] = new Vector2(1f, 1f);
- oxy[3] = new Vector2(1f, 0f);
- ouv[0] = new Vector2(0f, 0f);
- ouv[1] = new Vector2(0f, 1f);
- ouv[2] = new Vector2(1f, 1f);
- ouv[3] = new Vector2(1f, 0f);
- // Each quadrant must be rotated 90 degrees clockwise in order for it to fill properly
- if (mInvert)
- {
- if (i > 0)
- {
- Rotate(oxy, i);
- Rotate(ouv, i);
- }
- }
- else if (i < 3)
- {
- Rotate(oxy, 3 - i);
- Rotate(ouv, 3 - i);
- }
- // Each quadrant must fill in only a quarter of the space
- for (int b = 0; b < 4; ++b)
- {
- int index = (mInvert) ? (3 - i) * 4 : i * 4;
- float fx0 = matrix[index];
- float fy0 = matrix[index + 1];
- float fx1 = matrix[index + 2];
- float fy1 = matrix[index + 3];
- oxy[b].x = Mathf.Lerp(fx0, fy0, oxy[b].x);
- oxy[b].y = Mathf.Lerp(fx1, fy1, oxy[b].y);
- ouv[b].x = Mathf.Lerp(fx0, fy0, ouv[b].x);
- ouv[b].y = Mathf.Lerp(fx1, fy1, ouv[b].y);
- }
- float amount = (mFillAmount) * 4 - i;
- bool odd = (i % 2) == 1;
- if (AdjustRadial(oxy, ouv, amount, !odd))
- {
- if (mInvert) odd = !odd;
- // Add every other side in reverse order so they don't come out backface-culled due to rotation
- if (odd)
- {
- for (int b = 0; b < 4; ++b)
- {
- float x = Mathf.Lerp(xy[0].x, xy[2].x, oxy[b].x);
- float y = Mathf.Lerp(xy[0].y, xy[2].y, oxy[b].y);
- float u = Mathf.Lerp(uv[0].x, uv[2].x, ouv[b].x);
- float v = Mathf.Lerp(uv[0].y, uv[2].y, ouv[b].y);
- verts.Add(new Vector3(x, y, 0f));
- uvs.Add(new Vector2(u, v));
- cols.Add(col);
- }
- }
- else
- {
- for (int b = 3; b > -1; --b)
- {
- float x = Mathf.Lerp(xy[0].x, xy[2].x, oxy[b].x);
- float y = Mathf.Lerp(xy[0].y, xy[2].y, oxy[b].y);
- float u = Mathf.Lerp(uv[0].x, uv[2].x, ouv[b].x);
- float v = Mathf.Lerp(uv[0].y, uv[2].y, ouv[b].y);
- verts.Add(new Vector3(x, y, 0f));
- uvs.Add(new Vector2(u, v));
- cols.Add(col);
- }
- }
- }
- }
- return;
- }
- // Fill the buffer with the quad for the sprite
- for (int i = 0; i < 4; ++i)
- {
- verts.Add(xy[i]);
- uvs.Add(uv[i]);
- cols.Add(col);
- }
- }
- }