static void CreateVert(ref Vector2 start, ref Vector2 end, ref BlockInfo <HVertex> vert, ref BlockInfo <int> tris, ref Color32 color, float lineWidth) { float vx = end.x - start.x; float vy = end.y - start.y; float r = Mathf.Sqrt(lineWidth * lineWidth / (vx * vx + vy * vy)); float nx = vx * r; float ny = vy * r; int index = vert.DataCount; unsafe { HVertex *p = vert.Addr; p[index].position.x = start.x + ny; p[index].position.y = start.y - nx; p[index].position.z = 0; p[index].color = color; p[index].picture = 0; index++; p[index].position.x = start.x - ny; p[index].position.y = start.y + nx; p[index].position.z = 0; p[index].color = color; p[index].picture = 0; index++; p[index].position.x = end.x - ny; p[index].position.y = end.y + nx; p[index].position.z = 0; p[index].color = color; p[index].picture = 0; index++; p[index].position.x = end.x + ny; p[index].position.y = end.y - nx; p[index].position.z = 0; p[index].color = color; p[index].picture = 0; } index = vert.DataCount; int t = tris.DataCount; unsafe { int *p = tris.Addr; p[t] = index; t++; p[t] = index + 1; t++; p[t] = index + 3; t++; p[t] = index + 3; t++; p[t] = index + 1; t++; p[t] = index + 2; t++; } vert.DataCount += 4; tris.DataCount += 6; }
/// <summary> /// 创建出线 /// </summary> /// <param name="text">文本实体</param> protected static void CreateOutLine(HText text) { int c = text.vertInfo.DataCount; if (c == 0) { return; } BlockInfo <HVertex> tmp = VertexBuffer.RegNew(c * 5); tmp.DataCount = c * 5; float d = text.OutLine; OutLineVertex(ref tmp, 0, ref text.vertInfo, d, d, ref text.shadowColor); OutLineVertex(ref tmp, c, ref text.vertInfo, d, -d, ref text.shadowColor); OutLineVertex(ref tmp, c * 2, ref text.vertInfo, -d, -d, ref text.shadowColor); OutLineVertex(ref tmp, c * 3, ref text.vertInfo, -d, d, ref text.shadowColor); unsafe { HVertex *tar = tmp.Addr; HVertex *ori = text.vertInfo.Addr; int s = c * 4; for (int i = 0; i < c; i++) { tar[s] = ori[i]; s++; } } text.vertInfo.Release(); text.vertInfo = tmp; if (text.trisInfo.DataCount > 0) { int l = text.trisInfo.DataCount; var tris = trisBuffer.RegNew(l * 5); tris.DataCount = l * 5; OutLineTris(ref tris, 0, ref text.trisInfo, 0); OutLineTris(ref tris, l, ref text.trisInfo, c); OutLineTris(ref tris, l * 2, ref text.trisInfo, c * 2); OutLineTris(ref tris, l * 3, ref text.trisInfo, c * 3); OutLineTris(ref tris, l * 4, ref text.trisInfo, c * 4); text.trisInfo.Release(); text.trisInfo = tris; } if (text.trisInfo2.DataCount > 0) { int l = text.trisInfo2.DataCount; var tris = trisBuffer.RegNew(l * 5); tris.DataCount = l * 5; OutLineTris(ref tris, 0, ref text.trisInfo2, 0); OutLineTris(ref tris, l, ref text.trisInfo2, c); OutLineTris(ref tris, l * 2, ref text.trisInfo2, c * 2); OutLineTris(ref tris, l * 3, ref text.trisInfo2, c * 3); OutLineTris(ref tris, l * 4, ref text.trisInfo2, c * 4); text.trisInfo2.Release(); text.trisInfo2 = tris; } }
static void OutLineVertex(ref BlockInfo <HVertex> buf, int start, ref BlockInfo <HVertex> src, float x, float y, ref Color32 color) { int l = src.DataCount; unsafe { HVertex *tar = buf.Addr; HVertex *ori = src.Addr; for (int i = 0; i < l; i++) { tar[start] = ori[i]; tar[start].position.x += x; tar[start].position.y += y; tar[start].color = color; start++; } } }
unsafe static void AddUV1(HCanvas canvas, int[] ids, HVertex *vertices, int vc, int l) { for (int i = 0; i < l; i++) { switch (ids[i]) { case 0: UV1[i].x = 0; UV1[i].y = 0; break; case 1: UV1[i].x = 0; UV1[i].y = 1; break; case 2: UV1[i].x = 1; UV1[i].y = 0; break; case 3: UV1[i].x = 1; UV1[i].y = 1; break; } } for (int i = 0; i < vc; i++) { int p = vertices[i].picture; if (p < 0 | p > 3) { Debug.LogError("out of index"); } else { canvas.uv1.Add(UV1[p]); } } }
unsafe static void AddUV1(HCanvas canvas, int[] ids, HVertex *vertices, int vc, int l) { for (int i = 0; i < l; i++) { float x = ids[i]; UV1[i].x = x * 0.1f; UV1[i].y = 0; } for (int i = 0; i < vc; i++) { int p = vertices[i].picture; if (p < 0 | p > 3) { Debug.LogError("out of index"); } else { UV1[p].y = vertices[i].fillColor; canvas.uv1.Add(UV1[p]); } } }
/// <summary> /// 添加阴影 /// </summary> /// <param name="graphics"></param> /// <param name="canvas"></param> /// <param name="q"></param> /// <param name="scale"></param> /// <param name="o"></param> /// <param name="clip"></param> static void AddShadow(HGraphics graphics, HCanvas canvas, ref Quaternion q, ref Vector3 scale, ref Vector3 o, ref Vector4 clip, ref Vector2 center, ref Vector2 half) { var vs = canvas.vertex; var vc = vs.Count; int dc = graphics.vertInfo.DataCount; var os = graphics.shadowOffsset; if (dc > 0) { float px = (0.5f - graphics.Pivot.x) * graphics.SizeDelta.x + os.x; float py = (0.5f - graphics.Pivot.y) * graphics.SizeDelta.y + os.y; Vector2 uv2 = Vector2.zero; unsafe { HVertex *vert = graphics.vertInfo.Addr; for (int j = 0; j < dc; j++) { var tp = vert[j].position;//局部顶点 tp.x += px; tp.y += py; var t = q * tp; t.x *= scale.x; t.y *= scale.y; t += o; t.z = 0; uv2.x = (t.x - center.x) / half.x * 0.001f + 0.5f; uv2.y = (t.y - center.y) / half.y * 0.001f + 0.5f; vs.Add(t); canvas.colors.Add(graphics.shadowColor); canvas.uv.Add(vert[j].uv); canvas.uv2.Add(uv2); canvas.uv3.Add(vert[j].uv3); canvas.uv4.Add(vert[j].uv4); } } AddTris(graphics, canvas, vc, dc); } }
static void Batch(HGUIElement[] pipeLine, int index, HCanvas canvas, Vector4 clip) { if (!pipeLine[index].active) { return; } Vector3 o = pipeLine[index].Position; Vector3 scale = pipeLine[index].Scale; Quaternion q = pipeLine[index].Rotation; bool mask = false; var script = pipeLine[index].script; if (script != null) { mask = script.Mask; if (mask)//计算遮挡区域 { float x = script.SizeDelta.x; float y = script.SizeDelta.y; float px = script.Pivot.x; float py = script.Pivot.y; float lx = x * -px; float rx = x + lx; float dy = y * -py; float ty = y + dy; lx *= scale.x; rx *= scale.x; dy *= scale.y; ty *= scale.y; Vector4 v = new Vector4(o.x + lx, o.y + dy, o.x + rx, o.y + ty); v.x += 10000; v.x /= 20000; v.y += 10000; v.y /= 20000; v.z += 10000; v.z /= 20000; v.w += 10000; v.w /= 20000; clip = CutRect(clip, v); } var graphics = script as HGraphics; if (graphics != null)//计算图形 { if (graphics.Shadow) { AddShadow(graphics, canvas, ref q, ref scale, ref o, ref clip); } var vs = canvas.vertex; var vc = vs.Count; int dc = graphics.vertInfo.DataCount; if (dc > 0) { float px = (0.5f - script.Pivot.x) * script.m_sizeDelta.x; float py = (0.5f - script.Pivot.y) * script.m_sizeDelta.y; Vector2 uv2 = Vector2.zero; unsafe { HVertex *hv = graphics.vertInfo.Addr; for (int j = 0; j < dc; j++) { var tp = hv[j].position;//局部顶点 tp.z = 0; tp.x += px; tp.y += py; tp.x *= scale.x; tp.y *= scale.y; var t = q * tp; t += o; t.z = 0; uv2.x = (t.x + 10000) / 20000; uv2.y = (t.y + 10000) / 20000; vs.Add(t); canvas.colors.Add(hv[j].color); canvas.uv.Add(hv[j].uv); canvas.uv2.Add(uv2); canvas.uv3.Add(hv[j].uv3); canvas.uv4.Add(hv[j].uv4); } } if (graphics.tris != null) { int tid = 0; var src = graphics.tris; int len = src.Length; if (len > 0) { for (int k = 0; k < len; k++) { TriBuffer[k] = src[k] + vc; } canvas.MatCollector.CombinationMaterial(graphics, TriBuffer, len, ref tid, ref clip); } AddUV1(canvas, tid, dc); } else if (graphics.trisInfo.DataCount > 0 | graphics.trisInfo2.DataCount > 0) { int l = 0; int tc = graphics.trisInfo.DataCount; if (tc > 0) { unsafe { int *ip = graphics.trisInfo.Addr; for (int k = 0; k < tc; k++) { TriBuffer[k] = ip[k] + vc; } } l = 1; } Arrays[0].Length = tc; int tc2 = graphics.trisInfo2.DataCount; if (tc2 > 0) { int ks = tc; unsafe { int *ip = graphics.trisInfo2.Addr; for (int k = 0; k < tc2; k++) { TriBuffer[ks] = ip[k] + vc; ks++; } } Arrays[1].Start = tc; Arrays[1].Length = tc2; l = 2; } canvas.MatCollector.CombinationMaterial(graphics, TriBuffer, Arrays, IDBuffer, l, ref clip); unsafe { HVertex *hv = graphics.vertInfo.Addr; AddUV1(canvas, IDBuffer, hv, dc, l); } } else { AddUV1(canvas, 0, dc); } } } } int c = pipeLine[index].childCount; int os = pipeLine[index].childOffset; for (int i = 0; i < c; i++) { Batch(pipeLine, os, canvas, clip); os++; } }
/// <summary> /// 添加阴影 /// </summary> /// <param name="graphics"></param> /// <param name="canvas"></param> /// <param name="q"></param> /// <param name="scale"></param> /// <param name="o"></param> /// <param name="clip"></param> static void AddShadow(HGraphics graphics, HCanvas canvas, ref Quaternion q, ref Vector3 scale, ref Vector3 o, ref Vector4 clip) { var vs = canvas.vertex; var vc = vs.Count; int dc = graphics.vertInfo.DataCount; var os = graphics.shadowOffsset; if (dc > 0) { float px = (0.5f - graphics.Pivot.x) * graphics.SizeDelta.x + os.x; float py = (0.5f - graphics.Pivot.y) * graphics.SizeDelta.y + os.y; Vector2 uv2 = Vector2.zero; unsafe { HVertex *vert = graphics.vertInfo.Addr; for (int j = 0; j < dc; j++) { var tp = vert[j].position;//局部顶点 tp.x += px; tp.y += py; var t = q * tp; t.x *= scale.x; t.y *= scale.y; t += o; t.z = 0; uv2.x = (t.x + 10000) / 20000; uv2.y = (t.y + 10000) / 20000; vs.Add(t); canvas.colors.Add(graphics.shadowColor); canvas.uv.Add(vert[j].uv); canvas.uv2.Add(uv2); canvas.uv3.Add(vert[j].uv3); canvas.uv4.Add(vert[j].uv4); } } if (graphics.tris != null) { int tid = 0; var src = graphics.tris; int len = src.Length; if (len > 0) { for (int k = 0; k < len; k++) { TriBuffer[k] = src[k] + vc; } canvas.MatCollector.CombinationMaterial(graphics, TriBuffer, len, ref tid, ref clip); } AddUV1(canvas, tid, dc); } else if (graphics.trisInfo.DataCount > 0 | graphics.trisInfo2.DataCount > 0) { int l = 0; int tc = graphics.trisInfo.DataCount; if (tc > 0) { unsafe { int *ip = graphics.trisInfo.Addr; for (int k = 0; k < tc; k++) { TriBuffer[k] = ip[k] + vc; } } l = 1; } Arrays[0].Length = tc; int tc2 = graphics.trisInfo2.DataCount; if (tc2 > 0) { int ks = tc; unsafe { int *ip = graphics.trisInfo2.Addr; for (int k = 0; k < tc2; k++) { TriBuffer[ks] = ip[k] + vc; ks++; } } Arrays[1].Start = tc; Arrays[1].Length = tc2; l = 2; } canvas.MatCollector.CombinationMaterial(graphics, TriBuffer, Arrays, IDBuffer, l, ref clip); unsafe { HVertex *hv = graphics.vertInfo.Addr; AddUV1(canvas, IDBuffer, hv, dc, l); } } else { AddUV1(canvas, 0, dc); } } }
/// <summary> /// 创建带有表情符的网格 /// </summary> /// <param name="text"></param> protected static void CreateEmojiMesh(HText text) { if (text.TmpVerts.DataCount == 0) { text.vertInfo.DataCount = 0; text.trisInfo.DataCount = 0; text.trisInfo2.DataCount = 0; return; } bufferA.Clear(); bufferB.Clear(); var emojis = text.emojiString.emojis; var str = text.emojiString.FilterString; var verts = text.TmpVerts; int c = verts.DataCount; text.tris = null; if (text.vertInfo.Size == 0) { text.vertInfo = VertexBuffer.RegNew(c); } else if (text.vertInfo.Size <c | text.vertInfo.Size> c + 32) { text.vertInfo.Release(); text.vertInfo = VertexBuffer.RegNew(c); } var emoji = text.emojiString; EmojiInfo info = null; if (emoji.emojis.Count > 0) { info = emoji.emojis[0]; } int index = 0; int e = c / 4; int ac = 0; Color32 col = Color.white; unsafe { HVertex * hv = text.vertInfo.Addr; TextVertex *src = verts.Addr; for (int i = 0; i < e; i++) { int s = i * 4; int ss = ac; int ti = src[s].Index; for (int j = 0; j < 4; j++) { hv[ss].position = src[s].position; hv[ss].color = src[s].color; hv[ss].uv = src[s].uv; hv[ss].uv4.x = 1; hv[ss].uv4.y = 1; hv[ss].picture = 0; s++; ss++; } if (info != null) { if (ti > info.pos) { info = null; for (int j = index; j < emoji.emojis.Count; j++) { if (emoji.emojis[j].pos >= ti) { index = j; info = emoji.emojis[j]; break; } } } ss = ac; if (info != null) { if (ti == info.pos) { AddTris(bufferB, ac); hv[ss].uv = info.uv[0]; hv[ss].color = col; hv[ss].picture = 1; ss++; hv[ss].uv = info.uv[1]; hv[ss].color = col; hv[ss].picture = 1; ss++; hv[ss].uv = info.uv[2]; hv[ss].color = col; hv[ss].picture = 1; ss++; hv[ss].uv = info.uv[3]; hv[ss].color = col; hv[ss].picture = 1; } else { AddTris(bufferA, ac); } } else { AddTris(bufferA, ac); } } else { AddTris(bufferA, ac); } ac += 4; } } text.vertInfo.DataCount = ac; ApplyTris(text); }
static void Batch(HGUIElement[] pipeLine, int index, HCanvas canvas, Vector4 clip, Vector2 center, Vector2 half) { if (!pipeLine[index].active) { return; } Vector3 o = pipeLine[index].Position; Vector3 scale = pipeLine[index].Scale; Quaternion q = pipeLine[index].Rotation; bool mask = false; var script = pipeLine[index].script; if (script != null) { mask = script.Mask; if (mask)//计算遮挡区域 { float x = script.SizeDelta.x; float y = script.SizeDelta.y; float px = script.Pivot.x; float py = script.Pivot.y; float lx = x * -px; float rx = x + lx; float dy = y * -py; float ty = y + dy; lx *= scale.x; rx *= scale.x; dy *= scale.y; ty *= scale.y; Vector4 v = new Vector4(o.x + lx, o.y + dy, o.x + rx, o.y + ty); clip = CutRect(clip, v); half.x = (clip.z - clip.x) * 0.5f; half.y = (clip.w - clip.y) * 0.5f; center.x = half.x + clip.x; center.y = half.y + clip.y; } var graphics = script as HGraphics; if (graphics != null)//计算图形 { if (graphics.Shadow) { AddShadow(graphics, canvas, ref q, ref scale, ref o, ref clip, ref center, ref half); } var vs = canvas.vertex; var vc = vs.Count; int dc = graphics.vertInfo.DataCount; if (dc > 0) { float px = (0.5f - script.Pivot.x) * script.m_sizeDelta.x; float py = (0.5f - script.Pivot.y) * script.m_sizeDelta.y; Vector2 uv2 = Vector2.zero; unsafe { HVertex *hv = graphics.vertInfo.Addr; for (int j = 0; j < dc; j++) { var tp = hv[j].position;//局部顶点 tp.z = 0; tp.x += px; tp.y += py; tp.x *= scale.x; tp.y *= scale.y; var t = q * tp; t += o; t.z = 0; uv2.x = (t.x - center.x) / half.x * 0.001f + 0.5f; uv2.y = (t.y - center.y) / half.y * 0.001f + 0.5f; vs.Add(t); canvas.colors.Add(hv[j].color); canvas.uv.Add(hv[j].uv); canvas.uv2.Add(uv2); canvas.uv3.Add(hv[j].uv3); canvas.uv4.Add(hv[j].uv4); } } AddTris(graphics, canvas, vc, dc); } } } int c = pipeLine[index].childCount; int os = pipeLine[index].childOffset; for (int i = 0; i < c; i++) { Batch(pipeLine, os, canvas, clip, center, half); os++; } }
static void AddTris(HGraphics graphics, HCanvas canvas, int vc, int dc) { int max = vc + dc; if (graphics.tris != null) { int tid = 0; var src = graphics.tris; int len = src.Length; if (len > 0) { for (int k = 0; k < len; k++) { int index = TriBuffer[k] = src[k] + vc; if (index >= max) { Debug.LogError("数组超标"); } } canvas.MatCollector.CombinationMaterial(graphics, graphics.MainTexture, TriBuffer, len, ref tid); } AddUV1(canvas, tid, ref graphics.vertInfo); } else if (graphics.trisInfo.DataCount > 0 | graphics.trisInfo1.DataCount > 0 | graphics.trisInfo2.DataCount > 0) { Arrays[0].Length = 0; Arrays[1].Length = 0; Arrays[2].Length = 0; int l = 0; int tc = graphics.trisInfo.DataCount; if (tc > 0) { unsafe { int *ip = graphics.trisInfo.Addr; for (int k = 0; k < tc; k++) { TriBuffer[k] = ip[k] + vc; } } l = 1; } Arrays[0].Length = tc; int tc2 = graphics.trisInfo1.DataCount; if (tc2 > 0) { int ks = tc; unsafe { int *ip = graphics.trisInfo1.Addr; for (int k = 0; k < tc2; k++) { TriBuffer[ks] = ip[k] + vc; ks++; } } Arrays[1].Start = tc; Arrays[1].Length = tc2; l = 2; } int tc3 = graphics.trisInfo2.DataCount; if (tc3 > 0) { int ks = tc + tc2; unsafe { int *ip = graphics.trisInfo2.Addr; for (int k = 0; k < tc3; k++) { TriBuffer[ks] = ip[k] + vc; ks++; } } Arrays[2].Start = tc + tc2; Arrays[2].Length = tc3; l = 3; } canvas.MatCollector.CombinationMaterial(graphics, TriBuffer, Arrays, IDBuffer, l); unsafe { HVertex *hv = graphics.vertInfo.Addr; AddUV1(canvas, IDBuffer, hv, dc, l); } } else { AddUV1(canvas, 0, ref graphics.vertInfo); } }