using System.Collections.Generic;
using UnityEngine;
namespace FairyGUI
{
///
///
///
public sealed class VertexBuffer
{
///
///
///
public Rect contentRect;
///
///
///
public Rect uvRect;
///
///
///
public Color32 vertexColor;
///
///
///
public Vector2 textureSize;
///
///
///
public readonly List vertices;
///
///
///
public readonly List colors;
///
///
///
public readonly List uvs;
///
///
///
public readonly List uvs2;
///
///
///
public readonly List triangles;
static public Vector2[] NormalizedUV = new Vector2[] {
new Vector2(0, 0), new Vector2(0, 1), new Vector2(1, 1), new Vector2(1, 0) };
static public Vector2[] NormalizedPosition = new Vector2[] {
new Vector2(0, 1), new Vector2(0, 0), new Vector2(1, 0), new Vector2(1, 1) };
internal bool _alphaInVertexColor;
internal bool _isArbitraryQuad;
static Stack _pool = new Stack();
///
///
///
///
public static VertexBuffer Begin()
{
if (_pool.Count > 0)
{
VertexBuffer inst = _pool.Pop();
inst.Clear();
return inst;
}
else
return new VertexBuffer();
}
///
///
///
///
public static VertexBuffer Begin(VertexBuffer source)
{
VertexBuffer vb = Begin();
vb.contentRect = source.contentRect;
vb.uvRect = source.uvRect;
vb.vertexColor = source.vertexColor;
vb.textureSize = source.textureSize;
return vb;
}
private VertexBuffer()
{
vertices = new List();
colors = new List();
uvs = new List();
uvs2 = new List();
triangles = new List();
}
///
///
///
public void End()
{
_pool.Push(this);
}
///
///
///
public void Clear()
{
vertices.Clear();
colors.Clear();
uvs.Clear();
uvs2.Clear();
triangles.Clear();
_isArbitraryQuad = false;
_alphaInVertexColor = false;
}
///
///
///
public int currentVertCount
{
get
{
return vertices.Count;
}
}
///
///
///
///
public void AddVert(Vector3 position)
{
position.y = -position.y;
vertices.Add(position);
colors.Add(vertexColor);
if (vertexColor.a != 255)
_alphaInVertexColor = true;
uvs.Add(new Vector2(
Mathf.Lerp(uvRect.xMin, uvRect.xMax, (position.x - contentRect.xMin) / contentRect.width),
Mathf.Lerp(uvRect.yMax, uvRect.yMin, (-position.y - contentRect.yMin) / contentRect.height)));
}
///
///
///
///
///
public void AddVert(Vector3 position, Color32 color)
{
position.y = -position.y;
vertices.Add(position);
colors.Add(color);
if (color.a != 255)
_alphaInVertexColor = true;
uvs.Add(new Vector2(
Mathf.Lerp(uvRect.xMin, uvRect.xMax, (position.x - contentRect.xMin) / contentRect.width),
Mathf.Lerp(uvRect.yMax, uvRect.yMin, (-position.y - contentRect.yMin) / contentRect.height)));
}
///
///
///
///
///
///
public void AddVert(Vector3 position, Color32 color, Vector2 uv)
{
position.y = -position.y;
vertices.Add(position);
uvs.Add(new Vector2(uv.x, uv.y));
colors.Add(color);
if (color.a != 255)
_alphaInVertexColor = true;
}
///
///
/// 1---2
/// | / |
/// 0---3
///
///
public void AddQuad(Rect vertRect)
{
AddVert(new Vector3(vertRect.xMin, vertRect.yMax, 0f));
AddVert(new Vector3(vertRect.xMin, vertRect.yMin, 0f));
AddVert(new Vector3(vertRect.xMax, vertRect.yMin, 0f));
AddVert(new Vector3(vertRect.xMax, vertRect.yMax, 0f));
}
///
///
///
///
///
public void AddQuad(Rect vertRect, Color32 color)
{
AddVert(new Vector3(vertRect.xMin, vertRect.yMax, 0f), color);
AddVert(new Vector3(vertRect.xMin, vertRect.yMin, 0f), color);
AddVert(new Vector3(vertRect.xMax, vertRect.yMin, 0f), color);
AddVert(new Vector3(vertRect.xMax, vertRect.yMax, 0f), color);
}
///
///
///
///
///
///
public void AddQuad(Rect vertRect, Color32 color, Rect uvRect)
{
vertices.Add(new Vector3(vertRect.xMin, -vertRect.yMax, 0f));
vertices.Add(new Vector3(vertRect.xMin, -vertRect.yMin, 0f));
vertices.Add(new Vector3(vertRect.xMax, -vertRect.yMin, 0f));
vertices.Add(new Vector3(vertRect.xMax, -vertRect.yMax, 0f));
uvs.Add(new Vector2(uvRect.xMin, uvRect.yMin));
uvs.Add(new Vector2(uvRect.xMin, uvRect.yMax));
uvs.Add(new Vector2(uvRect.xMax, uvRect.yMax));
uvs.Add(new Vector2(uvRect.xMax, uvRect.yMin));
colors.Add(color);
colors.Add(color);
colors.Add(color);
colors.Add(color);
if (color.a != 255)
_alphaInVertexColor = true;
}
static List helperV4List = new List(4) { Vector4.zero, Vector4.zero, Vector4.zero, Vector4.zero };
internal List FixUVForArbitraryQuad()
{
//ref1 http://www.reedbeta.com/blog/quadrilateral-interpolation-part-1/
//ref2 https://bitlush.com/blog/arbitrary-quadrilaterals-in-opengl-es-2-0
Vector4 qq = Vector4.one;
Vector2 a = vertices[2] - vertices[0];
Vector2 b = vertices[1] - vertices[3];
Vector2 c = vertices[0] - vertices[3];
float cross = a.x * b.y - a.y * b.x;
if (cross != 0)
{
float s = (a.x * c.y - a.y * c.x) / cross;
if (s > 0 && s < 1)
{
float t = (b.x * c.y - b.y * c.x) / cross;
if (t > 0 && t < 1)
{
qq.x = 1 / (1 - t);
qq.y = 1 / s;
qq.z = 1 / t;
qq.w = 1 / (1 - s);
}
}
}
for (int i = 0; i < 4; i++)
{
Vector4 v = uvs[i];
float q = qq[i];
v.x *= q;
v.y *= q;
v.w = q;
helperV4List[i] = v;
}
return helperV4List;
}
///
///
///
///
///
///
public void RepeatColors(Color32[] value, int startIndex, int count)
{
int len = Mathf.Min(startIndex + count, vertices.Count);
int colorCount = value.Length;
int k = 0;
for (int i = startIndex; i < len; i++)
{
Color32 c = value[(k++) % colorCount];
colors[i] = c;
if (c.a != 255)
_alphaInVertexColor = true;
}
}
///
///
///
///
///
///
public void AddTriangle(int idx0, int idx1, int idx2)
{
triangles.Add(idx0);
triangles.Add(idx1);
triangles.Add(idx2);
}
///
///
///
///
///
public void AddTriangles(int[] idxList, int startVertexIndex = 0)
{
if (startVertexIndex != 0)
{
if (startVertexIndex < 0)
startVertexIndex = vertices.Count + startVertexIndex;
int cnt = idxList.Length;
for (int i = 0; i < cnt; i++)
triangles.Add(idxList[i] + startVertexIndex);
}
else
triangles.AddRange(idxList);
}
///
///
///
///
public void AddTriangles(int startVertexIndex = 0)
{
int cnt = vertices.Count;
if (startVertexIndex < 0)
startVertexIndex = cnt + startVertexIndex;
for (int i = startVertexIndex; i < cnt; i += 4)
{
triangles.Add(i);
triangles.Add(i + 1);
triangles.Add(i + 2);
triangles.Add(i + 2);
triangles.Add(i + 3);
triangles.Add(i);
}
}
///
///
///
///
///
public Vector3 GetPosition(int index)
{
if (index < 0)
index = vertices.Count + index;
Vector3 vec = vertices[index];
vec.y = -vec.y;
return vec;
}
///
///
///
///
///
///
public Vector2 GetUVAtPosition(Vector2 position, bool usePercent)
{
if (usePercent)
{
return new Vector2(Mathf.Lerp(uvRect.xMin, uvRect.xMax, position.x),
Mathf.Lerp(uvRect.yMax, uvRect.yMin, position.y));
}
else
return new Vector2(Mathf.Lerp(uvRect.xMin, uvRect.xMax, (position.x - contentRect.xMin) / contentRect.width),
Mathf.Lerp(uvRect.yMax, uvRect.yMin, (position.y - contentRect.yMin) / contentRect.height));
}
///
///
///
///
public void Append(VertexBuffer vb)
{
int len = vertices.Count;
vertices.AddRange(vb.vertices);
uvs.AddRange(vb.uvs);
uvs2.AddRange(vb.uvs2);
colors.AddRange(vb.colors);
if (len != 0)
{
int len1 = vb.triangles.Count;
for (int i = 0; i < len1; i++)
triangles.Add(vb.triangles[i] + len);
}
else
triangles.AddRange(vb.triangles);
if (vb._alphaInVertexColor)
_alphaInVertexColor = true;
}
///
///
///
///
public void Insert(VertexBuffer vb)
{
vertices.InsertRange(0, vb.vertices);
uvs.InsertRange(0, vb.uvs);
uvs2.InsertRange(0, vb.uvs2);
colors.InsertRange(0, vb.colors);
int len = triangles.Count;
if (len != 0)
{
int len1 = vb.vertices.Count;
for (int i = 0; i < len; i++)
triangles[i] += len1;
}
triangles.InsertRange(0, vb.triangles);
if (vb._alphaInVertexColor)
_alphaInVertexColor = true;
}
}
}