public override void ModifyMesh(VertexHelper vh) { int count = vh.currentVertCount; if (!IsActive() || count == 0) { return; } var vertexList = new List<UIVertex>(); vh.GetUIVertexStream(vertexList); UIVertex uiVertex = new UIVertex(); if (gradientMode == GradientMode.Global) { if (gradientDir == GradientDir.DiagonalLeftToRight || gradientDir == GradientDir.DiagonalRightToLeft) { #if UNITY_EDITOR Debug.LogWarning("Diagonal dir is not supported in Global mode"); #endif gradientDir = GradientDir.Vertical; } float bottomY = gradientDir == GradientDir.Vertical ? vertexList[vertexList.Count - 1].position.y : vertexList[vertexList.Count - 1].position.x; float topY = gradientDir == GradientDir.Vertical ? vertexList[0].position.y : vertexList[0].position.x; float uiElementHeight = topY - bottomY; for (int i = 0; i < count; i++) { vh.PopulateUIVertex(ref uiVertex, i); if (!overwriteAllColor && uiVertex.color != targetGraphic.color) continue; uiVertex.color *= Color.Lerp(vertex2, vertex1, ((gradientDir == GradientDir.Vertical ? uiVertex.position.y : uiVertex.position.x) - bottomY) / uiElementHeight); vh.SetUIVertex(uiVertex, i); } } else { for (int i = 0; i < count; i++) { vh.PopulateUIVertex(ref uiVertex, i); if (!overwriteAllColor && !CompareCarefully(uiVertex.color, targetGraphic.color)) continue; switch (gradientDir) { case GradientDir.Vertical: uiVertex.color *= (i % 4 == 0 || (i - 1) % 4 == 0) ? vertex1 : vertex2; break; case GradientDir.Horizontal: uiVertex.color *= (i % 4 == 0 || (i - 3) % 4 == 0) ? vertex1 : vertex2; break; case GradientDir.DiagonalLeftToRight: uiVertex.color *= (i % 4 == 0) ? vertex1 : ((i - 2) % 4 == 0 ? vertex2 : Color.Lerp(vertex2, vertex1, 0.5f)); break; case GradientDir.DiagonalRightToLeft: uiVertex.color *= ((i - 1) % 4 == 0) ? vertex1 : ((i - 3) % 4 == 0 ? vertex2 : Color.Lerp(vertex2, vertex1, 0.5f)); break; } vh.SetUIVertex(uiVertex, i); } } }
public void PopulateUIVertex(ref UIVertex vertex, int i) { vertex.position = this.m_Positions[i]; vertex.color = this.m_Colors[i]; vertex.uv0 = this.m_Uv0S[i]; vertex.uv1 = this.m_Uv1S[i]; vertex.normal = this.m_Normals[i]; vertex.tangent = this.m_Tangents[i]; }
public void SetUIVertex(UIVertex vertex, int i) { m_Positions[i] = vertex.position; m_Colors[i] = vertex.color; m_Uv0S[i] = vertex.uv0; m_Uv1S[i] = vertex.uv1; m_Normals[i] = vertex.normal; m_Tangents[i] = vertex.tangent; }
public override void ModifyMesh(VertexHelper vh) { UIVertex vertex = new UIVertex(); for (int i = 0; i < vh.currentVertCount; ++i) { vh.PopulateUIVertex(ref vertex, i); vertex.uv1 = new Vector2(vertex.position.x, vertex.position.y); vh.SetUIVertex(vertex, i); } }
/// <summary> /// Adds the position of this <see cref="UIVertex"/> to another <see cref="UIVertex"/>. /// </summary> /// <param name="v1">This <see cref="UIVertex"/>.</param> /// <param name="v2">The other <see cref="UIVertex"/>.</param> /// <returns>The resulting <see cref="UIVertex"/>.</returns> public static UIVertex Add(this UIVertex v1, UIVertex v2) { return new UIVertex { color = v1.color, normal = v1.normal, position = v1.position + v2.position, tangent = v1.tangent, uv0 = v1.uv0 + v2.uv0, uv1 = v1.uv1 + v2.uv1 }; }
/// <summary> /// Creates a new <see cref="UIVertex"/> object from a <c>byte</c> array. /// </summary> /// <param name="data"><c>byte</c> array to parse.</param> /// <param name="type">The map type.</param> /// <param name="version">The version of this lump.</param> /// <returns>The resulting <see cref="UIVertex"/> object.</returns> /// <exception cref="ArgumentNullException"><paramref name="data"/> was null.</exception> /// <exception cref="ArgumentException">This structure is not implemented for the given maptype.</exception> /// <remarks><see cref="UIVertex"/> has no constructor, so the object must be initialized field-by-field. Even if it /// did have a constructor, the way data needs to be read wouldn't allow use of it.</remarks> public static UIVertex CreateVertex(byte[] data, MapType type, int version = 0) { if (data == null) { throw new ArgumentNullException(); } UIVertex result = new UIVertex(); switch (type) { case MapType.MOHAA: case MapType.Quake3: case MapType.CoD: case MapType.CoD2: case MapType.CoD4: case MapType.FAKK: { result.uv0 = new Vector2(BitConverter.ToSingle(data, 12), BitConverter.ToSingle(data, 16)); result.color = Color32Extensions.FromArgb(data[43], data[40], data[41], data[42]); goto case MapType.DMoMaM; } case MapType.Raven: { result.uv0 = new Vector2(BitConverter.ToSingle(data, 12), BitConverter.ToSingle(data, 16)); result.color = Color32Extensions.FromArgb(data[67], data[64], data[65], data[66]); goto case MapType.DMoMaM; } case MapType.STEF2: case MapType.STEF2Demo: { result.uv0 = new Vector2(BitConverter.ToSingle(data, 12), BitConverter.ToSingle(data, 16)); result.color = Color32Extensions.FromArgb(data[35], data[32], data[33], data[34]); goto case MapType.DMoMaM; } case MapType.Quake: case MapType.Nightfire: case MapType.SiN: case MapType.SoF: case MapType.Source17: case MapType.Source18: case MapType.Source19: case MapType.Source20: case MapType.Source21: case MapType.Source22: case MapType.Source23: case MapType.Source27: case MapType.L4D2: case MapType.TacticalInterventionEncrypted: case MapType.Quake2: case MapType.Daikatana: case MapType.Vindictus: case MapType.DMoMaM: { result.position = new Vector3(BitConverter.ToSingle(data, 0), BitConverter.ToSingle(data, 4), BitConverter.ToSingle(data, 8)); break; } default: { throw new ArgumentException("Map type " + type + " isn't supported by the UIVertex class factory."); } } return result; }
protected UIVertex[] SetVbo(Vector2[] vertices, Vector2[] uvs) { UIVertex[] vbo = new UIVertex[4]; for (int i = 0; i < vertices.Length; i++) { var vert = UIVertex.simpleVert; vert.color = color; vert.position = vertices[i]; vert.uv0 = uvs[i]; vbo[i] = vert; } return vbo; }
/// <summary> /// Constructs a new <see cref="MAPPatch"/> object using the supplied string array as data. /// </summary> /// <param name="lines">Data to parse.</param> public MAPPatch(string[] lines) { texture = lines[2]; List<UIVertex> vertices = new List<UIVertex>(9); switch (lines[0]) { case "patchDef3": case "patchDef2": { string[] line = lines[3].Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); dims = new Vector2(Single.Parse(line[1], _format), Single.Parse(line[2], _format)); for (int i = 0; i < dims.x; ++i) { line = lines[i + 5].Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); for (int j = 0; j < dims.y; ++j) { Vector3 point = new Vector3(Single.Parse(line[2 + (j * 7)], _format), Single.Parse(line[3 + (j * 7)], _format), Single.Parse(line[4 + (j * 7)], _format)); Vector2 uv = new Vector2(Single.Parse(line[5 + (j * 7)], _format), Single.Parse(line[6 + (j * 7)], _format)); UIVertex vertex = new UIVertex() { position = point, uv0 = uv }; vertices.Add(vertex); } } break; } case "patchTerrainDef3": { string[] line = lines[3].Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); dims = new Vector2(Single.Parse(line[1], _format), Single.Parse(line[2], _format)); for (int i = 0; i < dims.x; ++i) { line = lines[i + 5].Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); for (int j = 0; j < dims.y; ++j) { Vector3 point = new Vector3(Single.Parse(line[2 + (j * 12)], _format), Single.Parse(line[3 + (j * 12)], _format), Single.Parse(line[4 + (j * 12)], _format)); Vector2 uv = new Vector2(Single.Parse(line[5 + (j * 12)], _format), Single.Parse(line[6 + (j * 12)], _format)); Color32 color = Color32Extensions.FromArgb(Byte.Parse(line[7 + (j * 12)]), Byte.Parse(line[8 + (j * 12)]), Byte.Parse(line[9 + (j * 12)]), Byte.Parse(line[10 + (j * 12)])); UIVertex vertex = new UIVertex() { position = point, uv0 = uv, color = color }; vertices.Add(vertex); } } break; } default: { throw new ArgumentException(string.Format("Unknown patch type {0}! Call a scientist! ", lines[0])); } } }
public override void ModifyMesh(VertexHelper vh) { int count = vh.currentVertCount; if (!IsActive() || count == 0) { return; } for (int index = 0; index < vh.currentVertCount; index++) { UIVertex uiVertex = new UIVertex(); vh.PopulateUIVertex(ref uiVertex, index); uiVertex.position.y += curveForText.Evaluate(rectTrans.rect.width * rectTrans.pivot.x + uiVertex.position.x) * curveMultiplier; vh.SetUIVertex(uiVertex, index); } }
public void ModifyMesh(VertexHelper verts) { RectTransform rt = this.transform as RectTransform; for (int i = 0; i < verts.currentVertCount; ++i) { UIVertex uiVertex = new UIVertex(); verts.PopulateUIVertex(ref uiVertex,i); // Modify positions uiVertex.position = new Vector3( (this.m_Horizontal ? (uiVertex.position.x + (rt.rect.center.x - uiVertex.position.x) * 2) : uiVertex.position.x), (this.m_Veritical ? (uiVertex.position.y + (rt.rect.center.y - uiVertex.position.y) * 2) : uiVertex.position.y), uiVertex.position.z ); // Apply verts.SetUIVertex(uiVertex, i); } }
public override void ModifyMesh(VertexHelper vh) { int count = vh.currentVertCount; if (!IsActive() || count == 0) { return; } var k = 0; var upCount = 0; float progressMax = vh.currentVertCount * 0.5f; for (int index = 0; index < vh.currentVertCount; ++index) { UIVertex uiVertex = new UIVertex(); vh.PopulateUIVertex(ref uiVertex, index); if (k < 2) { var progress = upCount++ - progressMax * 0.5f; uiVertex.position.y += curveForTextUpper.Evaluate((rectTrans.rect.width * rectTrans.pivot.x + uiVertex.position.x) / rectTrans.rect.width) * curveMultiplierUpper; uiVertex.position.x += progress * curveMultiplierX; } else if (k < 4) { uiVertex.position.y += curveForText.Evaluate((rectTrans.rect.width * rectTrans.pivot.x + uiVertex.position.x) / rectTrans.rect.width) * curveMultiplier; } ++k; if (k >= 4) k = 0; vh.SetUIVertex(uiVertex, index); } }
public override void ModifyMesh(VertexHelper vh) { if (! IsActive()) return; int count = vh.currentVertCount; if (!IsActive() || count == 0) { return; } for (int index = 0; index < vh.currentVertCount; index++) { UIVertex uiVertex = new UIVertex(); vh.PopulateUIVertex(ref uiVertex, index); // get x position var x = uiVertex.position.x; // calculate bend based on pivot and radius uiVertex.position.z = -radius * Mathf.Cos(x / radius); uiVertex.position.x = radius * Mathf.Sin(x / radius); vh.SetUIVertex(uiVertex, index); } }
public override void ModifyMesh(VertexHelper vh) { if (!enabled) { return; } var size = widthsize; if (size < text.fontSize) { size = text.fontSize; } var count = vh.currentVertCount / 4; var content = text.text; var length = content.Length; var richtext = text.supportRichText; if (string.IsNullOrWhiteSpace(content)) { return; } int i = 0; if (richtext) { i = GetNextValidIndex(content, i); } float a = size / 2.0f * 1.30f; float b = size * 1.30f; float d = 0; float s = 0; float si = 0; UIVertex v1 = new UIVertex(); UIVertex v2 = new UIVertex(); float linestart = -rectTransform.sizeDelta.x * rectTransform.pivot.x; //顶点索引记录 int vi = 0; char c = '\x0'; for (; i < length && vi < count; ++i) { c = content[i]; if (c == '\n') { if (richtext) { var ni = i + 1; i = GetNextValidIndex(content, ni); if (i >= length) { break; } else if (i == ni) { //非特殊 i -= 1; } } s = 0; continue; } else if (c == ' ') { s += size / 2.0f; continue; } else if (richtext && c == '<') { i = GetNextValidIndex(content, i); if (i >= length) { break; } c = content[i]; } vh.PopulateUIVertex(ref v1, vi * 4 + 0); vh.PopulateUIVertex(ref v2, vi * 4 + 2); d = v2.position.x - v1.position.x; if (d > b) { //字形大小超过文本尺寸时 //可能使用<size>富文本标记 si = d; } else if (uEmuera.Utils.CheckHalfSize(c)) { si = size / 2.0f; } else if (c == ' ') { si = size / 2.0f; } //else if(c == ' ') // si = size; //else if(d < a) // si = size / 2.0f; else { si = size; } var o = s + (si - d) / 2.0f; v1.position.x = linestart + o; v2.position.x = v1.position.x + d; vh.SetUIVertex(v1, vi * 4 + 0); vh.SetUIVertex(v2, vi * 4 + 2); vh.PopulateUIVertex(ref v1, vi * 4 + 3); vh.PopulateUIVertex(ref v2, vi * 4 + 1); v1.position.x = linestart + o; v2.position.x = v1.position.x + d; vh.SetUIVertex(v1, vi * 4 + 3); vh.SetUIVertex(v2, vi * 4 + 1); vi += 1; s += si; } }
void SplitTrianglesAtGradientStops(List <UIVertex> _vertexList, Rect bounds, float zoomOffset, VertexHelper helper) { List <float> stops = FindStops(zoomOffset, bounds); if (stops.Count > 0) { helper.Clear(); int nCount = _vertexList.Count; for (int i = 0; i < nCount; i += 3) { float[] positions = GetPositions(_vertexList, i); List <int> originIndices = new List <int>(3); List <UIVertex> starts = new List <UIVertex>(3); List <UIVertex> ends = new List <UIVertex>(2); for (int s = 0; s < stops.Count; s++) { int initialCount = helper.currentVertCount; bool hadEnds = ends.Count > 0; bool earlyStart = false; // find any start vertices for this stop for (int p = 0; p < 3; p++) { if (!originIndices.Contains(p) && positions[p] < stops[s]) { // make sure the first index crosses the stop int p1 = (p + 1) % 3; var start = _vertexList[p + i]; if (positions[p1] > stops[s]) { originIndices.Insert(0, p); starts.Insert(0, start); earlyStart = true; } else { originIndices.Add(p); starts.Add(start); } } } // bail if all before or after the stop if (originIndices.Count == 0) { continue; } if (originIndices.Count == 3) { break; } // report any start vertices foreach (var start in starts) { helper.AddVert(start); } // make two ends, splitting at the stop ends.Clear(); foreach (int index in originIndices) { int oppositeIndex = (index + 1) % 3; if (positions[oppositeIndex] < stops[s]) { oppositeIndex = (oppositeIndex + 1) % 3; } ends.Add(CreateSplitVertex(_vertexList[index + i], _vertexList[oppositeIndex + i], stops[s])); } if (ends.Count == 1) { int oppositeIndex = (originIndices[0] + 2) % 3; ends.Add(CreateSplitVertex(_vertexList[originIndices[0] + i], _vertexList[oppositeIndex + i], stops[s])); } // report end vertices foreach (var end in ends) { helper.AddVert(end); } // make triangles if (hadEnds) { helper.AddTriangle(initialCount - 2, initialCount, initialCount + 1); helper.AddTriangle(initialCount - 2, initialCount + 1, initialCount - 1); if (starts.Count > 0) { if (earlyStart) { helper.AddTriangle(initialCount - 2, initialCount + 3, initialCount); } else { helper.AddTriangle(initialCount + 1, initialCount + 3, initialCount - 1); } } } else { int vertexCount = helper.currentVertCount; helper.AddTriangle(initialCount, vertexCount - 2, vertexCount - 1); if (starts.Count > 1) { helper.AddTriangle(initialCount, vertexCount - 1, initialCount + 1); } } starts.Clear(); } // clean up after looping through gradient stops if (ends.Count > 0) { // find any final vertices after the gradient stops if (starts.Count == 0) { for (int p = 0; p < 3; p++) { if (!originIndices.Contains(p) && positions[p] > stops[stops.Count - 1]) { int p1 = (p + 1) % 3; UIVertex end = _vertexList[p + i]; if (positions[p1] > stops[stops.Count - 1]) { starts.Insert(0, end); } else { starts.Add(end); } } } } // report final vertices foreach (var start in starts) { helper.AddVert(start); } // make final triangle(s) int vertexCount = helper.currentVertCount; if (starts.Count > 1) { helper.AddTriangle(vertexCount - 4, vertexCount - 2, vertexCount - 1); helper.AddTriangle(vertexCount - 4, vertexCount - 1, vertexCount - 3); } else if (starts.Count > 0) { helper.AddTriangle(vertexCount - 3, vertexCount - 1, vertexCount - 2); } } else { // if the triangle wasn't split, add it as-is helper.AddVert(_vertexList[i]); helper.AddVert(_vertexList[i + 1]); helper.AddVert(_vertexList[i + 2]); int vertexCount = helper.currentVertCount; helper.AddTriangle(vertexCount - 3, vertexCount - 2, vertexCount - 1); } } } }
public override void ModifyMesh(VertexHelper helper) { List <UIVertex> verts = new List <UIVertex>(); helper.GetUIVertexStream(verts); if (!IsActive()) { return; } Text text = GetComponent <Text>(); if (text == null) { Debug.LogWarning("LetterSpacing: Missing Text component"); return; } string[] lines = text.text.Split('\n'); Vector3 pos; float letterOffset = spacing * (float)text.fontSize / 100f; float alignmentFactor = 0; int glyphIdx = 0; switch (text.alignment) { case TextAnchor.LowerLeft: case TextAnchor.MiddleLeft: case TextAnchor.UpperLeft: alignmentFactor = 0f; break; case TextAnchor.LowerCenter: case TextAnchor.MiddleCenter: case TextAnchor.UpperCenter: alignmentFactor = 0.5f; break; case TextAnchor.LowerRight: case TextAnchor.MiddleRight: case TextAnchor.UpperRight: alignmentFactor = 1f; break; } for (int lineIdx = 0; lineIdx < lines.Length; lineIdx++) { string line = lines[lineIdx]; float lineOffset = (line.Length - 1) * letterOffset * alignmentFactor; for (int charIdx = 0; charIdx < line.Length; charIdx++) { int idx1 = glyphIdx * 6 + 0; int idx2 = glyphIdx * 6 + 1; int idx3 = glyphIdx * 6 + 2; int idx4 = glyphIdx * 6 + 3; int idx5 = glyphIdx * 6 + 4; int idx6 = glyphIdx * 6 + 5; // Check for truncated text (doesn't generate verts for all characters) if (idx4 > verts.Count - 1) { return; } UIVertex vert1 = verts[idx1]; UIVertex vert2 = verts[idx2]; UIVertex vert3 = verts[idx3]; UIVertex vert4 = verts[idx4]; UIVertex vert5 = verts[idx5]; UIVertex vert6 = verts[idx6]; pos = Vector3.right * (letterOffset * charIdx - lineOffset); vert1.position += pos; vert2.position += pos; vert3.position += pos; vert4.position += pos; vert5.position += pos; vert6.position += pos; verts[idx1] = vert1; verts[idx2] = vert2; verts[idx3] = vert3; verts[idx4] = vert4; verts[idx5] = vert5; verts[idx6] = vert6; glyphIdx++; } // Offset for carriage return character that still generates verts glyphIdx++; } helper.AddUIVertexTriangleStream(verts); }
protected override void OnPopulateMesh(VertexHelper vh) { if (m_points == null) return; Vector2[] pointsToDraw = m_points; //If Bezier is desired, pick the implementation if (BezierMode != BezierType.None && m_points.Length > 3) { BezierPath bezierPath = new BezierPath(); bezierPath.SetControlPoints(pointsToDraw); bezierPath.SegmentsPerCurve = BezierSegmentsPerCurve; List<Vector2> drawingPoints; switch (BezierMode) { case BezierType.Basic: drawingPoints = bezierPath.GetDrawingPoints0(); break; case BezierType.Improved: drawingPoints = bezierPath.GetDrawingPoints1(); break; default: drawingPoints = bezierPath.GetDrawingPoints2(); break; } pointsToDraw = drawingPoints.ToArray(); } var sizeX = rectTransform.rect.width; var sizeY = rectTransform.rect.height; var offsetX = -rectTransform.pivot.x * rectTransform.rect.width; var offsetY = -rectTransform.pivot.y * rectTransform.rect.height; // don't want to scale based on the size of the rect, so this is switchable now if (!relativeSize) { sizeX = 1; sizeY = 1; } if (UseMargins) { sizeX -= Margin.x; sizeY -= Margin.y; offsetX += Margin.x / 2f; offsetY += Margin.y / 2f; } vh.Clear(); // Generate the quads that make up the wide line var segments = new List<UIVertex[]>(); if (LineList) { for (var i = 1; i < pointsToDraw.Length; i += 2) { var start = pointsToDraw[i - 1]; var end = pointsToDraw[i]; start = new Vector2(start.x * sizeX + offsetX, start.y * sizeY + offsetY); end = new Vector2(end.x * sizeX + offsetX, end.y * sizeY + offsetY); if (LineCaps) { segments.Add(CreateLineCap(start, end, SegmentType.Start)); } segments.Add(CreateLineSegment(start, end, SegmentType.Middle)); if (LineCaps) { segments.Add(CreateLineCap(start, end, SegmentType.End)); } } } else { for (var i = 1; i < pointsToDraw.Length; i++) { var start = pointsToDraw[i - 1]; var end = pointsToDraw[i]; start = new Vector2(start.x * sizeX + offsetX, start.y * sizeY + offsetY); end = new Vector2(end.x * sizeX + offsetX, end.y * sizeY + offsetY); if (LineCaps && i == 1) { segments.Add(CreateLineCap(start, end, SegmentType.Start)); } segments.Add(CreateLineSegment(start, end, SegmentType.Middle)); if (LineCaps && i == pointsToDraw.Length - 1) { segments.Add(CreateLineCap(start, end, SegmentType.End)); } } } // Add the line segments to the vertex helper, creating any joins as needed for (var i = 0; i < segments.Count; i++) { if (!LineList && i < segments.Count - 1) { var vec1 = segments[i][1].position - segments[i][2].position; var vec2 = segments[i + 1][2].position - segments[i + 1][1].position; var angle = Vector2.Angle(vec1, vec2) * Mathf.Deg2Rad; // Positive sign means the line is turning in a 'clockwise' direction var sign = Mathf.Sign(Vector3.Cross(vec1.normalized, vec2.normalized).z); // Calculate the miter point var miterDistance = LineThickness / (2 * Mathf.Tan(angle / 2)); var miterPointA = segments[i][2].position - vec1.normalized * miterDistance * sign; var miterPointB = segments[i][3].position + vec1.normalized * miterDistance * sign; var joinType = LineJoins; if (joinType == JoinType.Miter) { // Make sure we can make a miter join without too many artifacts. if (miterDistance < vec1.magnitude / 2 && miterDistance < vec2.magnitude / 2 && angle > MIN_MITER_JOIN) { segments[i][2].position = miterPointA; segments[i][3].position = miterPointB; segments[i + 1][0].position = miterPointB; segments[i + 1][1].position = miterPointA; } else { joinType = JoinType.Bevel; } } if (joinType == JoinType.Bevel) { if (miterDistance < vec1.magnitude / 2 && miterDistance < vec2.magnitude / 2 && angle > MIN_BEVEL_NICE_JOIN) { if (sign < 0) { segments[i][2].position = miterPointA; segments[i + 1][1].position = miterPointA; } else { segments[i][3].position = miterPointB; segments[i + 1][0].position = miterPointB; } } var join = new UIVertex[] { segments[i][2], segments[i][3], segments[i + 1][0], segments[i + 1][1] }; vh.AddUIVertexQuad(join); } } vh.AddUIVertexQuad(segments[i]); } }
public void ModifyVertices(List <UIVertex> verts) { if (!IsActive()) { return; } Text text = GetComponent <Text>(); string str = text.text; // Artificially insert line breaks for automatic line breaks. IList <UILineInfo> lineInfos = text.cachedTextGenerator.lines; for (int i = lineInfos.Count - 1; i > 0; i--) { // Insert a \n at the location Unity wants to automatically line break. // Also, remove any space before the automatic line break location. str = str.Insert(lineInfos[i].startCharIdx, "\n"); str = str.Remove(lineInfos[i].startCharIdx - 1, 1); } string[] lines = str.Split('\n'); if (text == null) { Debug.LogWarning("LetterSpacing: Missing Text component"); return; } Vector3 pos; float letterOffset = spacing * (float)text.fontSize / 100f; float alignmentFactor = 0; int glyphIdx = 0; // character index from the beginning of the text, including RichText tags and line breaks bool isRichText = useRichText && text.supportRichText; IEnumerator matchedTagCollection = null; // when using RichText this will collect all tags (index, length, value) Match currentMatchedTag = null; switch (text.alignment) { case TextAnchor.LowerLeft: case TextAnchor.MiddleLeft: case TextAnchor.UpperLeft: alignmentFactor = 0f; break; case TextAnchor.LowerCenter: case TextAnchor.MiddleCenter: case TextAnchor.UpperCenter: alignmentFactor = 0.5f; break; case TextAnchor.LowerRight: case TextAnchor.MiddleRight: case TextAnchor.UpperRight: alignmentFactor = 1f; break; } for (int lineIdx = 0; lineIdx < lines.Length; lineIdx++) { string line = lines[lineIdx]; int lineLength = line.Length; if (isRichText) { matchedTagCollection = GetRegexMatchedTagCollection(line, out lineLength); currentMatchedTag = null; if (matchedTagCollection.MoveNext()) { currentMatchedTag = (Match)matchedTagCollection.Current; } } float lineOffset = (lineLength - 1) * letterOffset * alignmentFactor; for (int charIdx = 0, actualCharIndex = 0; charIdx < line.Length; charIdx++, actualCharIndex++) { if (isRichText) { if (currentMatchedTag != null && currentMatchedTag.Index == charIdx) { // skip matched RichText tag charIdx += currentMatchedTag.Length - 1; // -1 because next iteration will increment charIdx actualCharIndex--; // tag is not an actual character, cancel counter increment on this iteration glyphIdx += currentMatchedTag.Length; // glyph index is not incremented in for loop so skip entire length // prepare next tag to detect currentMatchedTag = null; if (matchedTagCollection.MoveNext()) { currentMatchedTag = (Match)matchedTagCollection.Current; } continue; } } int idx1 = glyphIdx * 6 + 0; int idx2 = glyphIdx * 6 + 1; int idx3 = glyphIdx * 6 + 2; int idx4 = glyphIdx * 6 + 3; int idx5 = glyphIdx * 6 + 4; int idx6 = glyphIdx * 6 + 5; // Check for truncated text (doesn't generate verts for all characters) if (idx6 > verts.Count - 1) { return; } UIVertex vert1 = verts[idx1]; UIVertex vert2 = verts[idx2]; UIVertex vert3 = verts[idx3]; UIVertex vert4 = verts[idx4]; UIVertex vert5 = verts[idx5]; UIVertex vert6 = verts[idx6]; pos = Vector3.right * (letterOffset * actualCharIndex - lineOffset); vert1.position += pos; vert2.position += pos; vert3.position += pos; vert4.position += pos; vert5.position += pos; vert6.position += pos; verts[idx1] = vert1; verts[idx2] = vert2; verts[idx3] = vert3; verts[idx4] = vert4; verts[idx5] = vert5; verts[idx6] = vert6; glyphIdx++; } // Offset for carriage return character that still generates verts glyphIdx++; } }
public override void ModifyMesh(VertexHelper vh) { vh.Clear(); innerVertices.Clear(); outterVertices.Clear(); float degreeDelta = (float)(2 * Mathf.PI / segements); int curSegements = (int)(segements * fillPercent); float tw = image.rectTransform.rect.width; float th = image.rectTransform.rect.height; float outerRadius = image.rectTransform.pivot.x * tw; float innerRadius = image.rectTransform.pivot.x * tw - thickness; Vector4 uv = image.overrideSprite != null?DataUtility.GetOuterUV(image.overrideSprite) : Vector4.zero; float uvCenterX = (uv.x + uv.z) * 0.5f; float uvCenterY = (uv.y + uv.w) * 0.5f; float uvScaleX = (uv.z - uv.x) / tw; float uvScaleY = (uv.w - uv.y) / th; float curDegree = 0; UIVertex uiVertex; int verticeCount; int triangleCount; Vector2 curVertice; if (fill) //圆形 { curVertice = Vector2.zero; verticeCount = curSegements + 1; uiVertex = new UIVertex(); uiVertex.color = image.color; uiVertex.position = curVertice; uiVertex.uv0 = new Vector2(curVertice.x * uvScaleX + uvCenterX, curVertice.y * uvScaleY + uvCenterY); vh.AddVert(uiVertex); for (int i = 1; i < verticeCount; i++) { float cosA = Mathf.Cos(curDegree); float sinA = Mathf.Sin(curDegree); curVertice = new Vector2(cosA * outerRadius, sinA * outerRadius); curDegree += degreeDelta; uiVertex = new UIVertex(); uiVertex.color = image.color; uiVertex.position = curVertice; uiVertex.uv0 = new Vector2(curVertice.x * uvScaleX + uvCenterX, curVertice.y * uvScaleY + uvCenterY); vh.AddVert(uiVertex); outterVertices.Add(curVertice); } triangleCount = curSegements * 3; for (int i = 0, vIdx = 1; i < triangleCount - 3; i += 3, vIdx++) { vh.AddTriangle(vIdx, 0, vIdx + 1); } if (fillPercent == 1) { //首尾顶点相连 vh.AddTriangle(verticeCount - 1, 0, 1); } } else//圆环 { verticeCount = curSegements * 2; for (int i = 0; i < verticeCount; i += 2) { float cosA = Mathf.Cos(curDegree); float sinA = Mathf.Sin(curDegree); curDegree += degreeDelta; curVertice = new Vector3(cosA * innerRadius, sinA * innerRadius); uiVertex = new UIVertex(); uiVertex.color = image.color; uiVertex.position = curVertice; uiVertex.uv0 = new Vector2(curVertice.x * uvScaleX + uvCenterX, curVertice.y * uvScaleY + uvCenterY); vh.AddVert(uiVertex); innerVertices.Add(curVertice); curVertice = new Vector3(cosA * outerRadius, sinA * outerRadius); uiVertex = new UIVertex(); uiVertex.color = image.color; uiVertex.position = curVertice; uiVertex.uv0 = new Vector2(curVertice.x * uvScaleX + uvCenterX, curVertice.y * uvScaleY + uvCenterY); vh.AddVert(uiVertex); outterVertices.Add(curVertice); } triangleCount = curSegements * 3 * 2; for (int i = 0, vIdx = 0; i < triangleCount - 6; i += 6, vIdx += 2) { vh.AddTriangle(vIdx + 1, vIdx, vIdx + 3); vh.AddTriangle(vIdx, vIdx + 2, vIdx + 3); } if (fillPercent == 1) { //首尾顶点相连 vh.AddTriangle(verticeCount - 1, verticeCount - 2, 1); vh.AddTriangle(verticeCount - 2, 0, 1); } } }
int _verticesCountWithTag;//带有完整标签的 public override void ModifyMesh(VertexHelper helper) { //Debug.LogError("Modify"); if (!IsActive() || helper.currentVertCount == 0) { return; } _verticesCountWithTag = helper.currentVertCount; if (!_richPrcessed) { ProcessRichTags(_text.text); //_verticesCount = _verticesCountWithTag - tag * 4; } //如果顶点数有变化,说明文本内容有修改,需要清除记录 if (_verticesOriPos != null && _verticesOriPos.Count != helper.currentVertCount) { ClearPosRecord(); } List <UIVertex> vertices = new List <UIVertex>(); helper.GetUIVertexStream(vertices); UIVertex v = new UIVertex(); //记录顶点的初始信息 RecordVerticesInfo(helper, ref v); //处理布局阶段 if (_curStage == Stage.Layout) { RefreshLayout(helper, ref v); //进入下一阶段 PrepareSwitchStage(); } //尝试处理淡入阶段 if (_curStage == Stage.Fadein && fadein_1) { //对每个顶点做相应的处理 ProcessAnim(helper, ref v); } //尝试处理展示阶段 else if (_curStage == Stage.Display && stage_2) { //对每个顶点做相应的处理 ProcessAnim(helper, ref v); } //尝试处理淡出阶段 else if (_curStage == Stage.Fadeout && stage_3) { //对每个顶点做相应的处理 ProcessAnim(helper, ref v); } //else if(_curStage == Stage.End && loop_0) //{ // //Replay(); // PrepareSwitchStage(); //} // else { LayoutDefault(helper, ref v); } //if (_isFadeIn) //{ // //对每个顶点做相应的处理 // ProcessAnim(helper, ref v); //} //else //{ // LayoutDefault(helper, ref v); //} }
private void GenerateFilledSprite(VertexHelper toFill, bool preserveAspect) { toFill.Clear(); if (m_FillAmount < 0.001f) { return; } Vector4 drawingDimensions = GetDrawingDimensions(preserveAspect); Vector4 vector = (!(overrideSprite != null)) ? Vector4.zero : DataUtility.GetOuterUV(overrideSprite); UIVertex simpleVert = UIVertex.simpleVert; simpleVert.color = base.color; float num = vector.x; float num2 = vector.y; float num3 = vector.z; float num4 = vector.w; if (m_FillMethod == FillMethod.Horizontal || m_FillMethod == FillMethod.Vertical) { if (fillMethod == FillMethod.Horizontal) { float num5 = (num3 - num) * m_FillAmount; if (m_FillOrigin == 1) { drawingDimensions.x = drawingDimensions.z - (drawingDimensions.z - drawingDimensions.x) * m_FillAmount; num = num3 - num5; } else { drawingDimensions.z = drawingDimensions.x + (drawingDimensions.z - drawingDimensions.x) * m_FillAmount; num3 = num + num5; } } else if (fillMethod == FillMethod.Vertical) { float num6 = (num4 - num2) * m_FillAmount; if (m_FillOrigin == 1) { drawingDimensions.y = drawingDimensions.w - (drawingDimensions.w - drawingDimensions.y) * m_FillAmount; num2 = num4 - num6; } else { drawingDimensions.w = drawingDimensions.y + (drawingDimensions.w - drawingDimensions.y) * m_FillAmount; num4 = num2 + num6; } } } s_Xy[0] = new Vector2(drawingDimensions.x, drawingDimensions.y); s_Xy[1] = new Vector2(drawingDimensions.x, drawingDimensions.w); s_Xy[2] = new Vector2(drawingDimensions.z, drawingDimensions.w); s_Xy[3] = new Vector2(drawingDimensions.z, drawingDimensions.y); s_Uv[0] = new Vector2(num, num2); s_Uv[1] = new Vector2(num, num4); s_Uv[2] = new Vector2(num3, num4); s_Uv[3] = new Vector2(num3, num2); if (m_FillAmount < 1f && m_FillMethod != 0 && m_FillMethod != FillMethod.Vertical) { if (fillMethod == FillMethod.Radial90) { if (RadialCut(s_Xy, s_Uv, m_FillAmount, m_FillClockwise, m_FillOrigin)) { AddQuad(toFill, s_Xy, base.color, s_Uv); } } else if (fillMethod == FillMethod.Radial180) { for (int i = 0; i < 2; i++) { int num7 = (m_FillOrigin > 1) ? 1 : 0; float t; float t2; float t3; float t4; if (m_FillOrigin == 0 || m_FillOrigin == 2) { t = 0f; t2 = 1f; if (i == num7) { t3 = 0f; t4 = 0.5f; } else { t3 = 0.5f; t4 = 1f; } } else { t3 = 0f; t4 = 1f; if (i == num7) { t = 0.5f; t2 = 1f; } else { t = 0f; t2 = 0.5f; } } s_Xy[0].x = Mathf.Lerp(drawingDimensions.x, drawingDimensions.z, t3); s_Xy[1].x = s_Xy[0].x; s_Xy[2].x = Mathf.Lerp(drawingDimensions.x, drawingDimensions.z, t4); s_Xy[3].x = s_Xy[2].x; s_Xy[0].y = Mathf.Lerp(drawingDimensions.y, drawingDimensions.w, t); s_Xy[1].y = Mathf.Lerp(drawingDimensions.y, drawingDimensions.w, t2); s_Xy[2].y = s_Xy[1].y; s_Xy[3].y = s_Xy[0].y; s_Uv[0].x = Mathf.Lerp(num, num3, t3); s_Uv[1].x = s_Uv[0].x; s_Uv[2].x = Mathf.Lerp(num, num3, t4); s_Uv[3].x = s_Uv[2].x; s_Uv[0].y = Mathf.Lerp(num2, num4, t); s_Uv[1].y = Mathf.Lerp(num2, num4, t2); s_Uv[2].y = s_Uv[1].y; s_Uv[3].y = s_Uv[0].y; float value = (!m_FillClockwise) ? (m_FillAmount * 2f - (float)(1 - i)) : (fillAmount * 2f - (float)i); if (RadialCut(s_Xy, s_Uv, Mathf.Clamp01(value), m_FillClockwise, (i + m_FillOrigin + 3) % 4)) { AddQuad(toFill, s_Xy, base.color, s_Uv); } } } else { if (fillMethod != FillMethod.Radial360) { return; } for (int j = 0; j < 4; j++) { float t5; float t6; if (j < 2) { t5 = 0f; t6 = 0.5f; } else { t5 = 0.5f; t6 = 1f; } float t7; float t8; if (j == 0 || j == 3) { t7 = 0f; t8 = 0.5f; } else { t7 = 0.5f; t8 = 1f; } s_Xy[0].x = Mathf.Lerp(drawingDimensions.x, drawingDimensions.z, t5); s_Xy[1].x = s_Xy[0].x; s_Xy[2].x = Mathf.Lerp(drawingDimensions.x, drawingDimensions.z, t6); s_Xy[3].x = s_Xy[2].x; s_Xy[0].y = Mathf.Lerp(drawingDimensions.y, drawingDimensions.w, t7); s_Xy[1].y = Mathf.Lerp(drawingDimensions.y, drawingDimensions.w, t8); s_Xy[2].y = s_Xy[1].y; s_Xy[3].y = s_Xy[0].y; s_Uv[0].x = Mathf.Lerp(num, num3, t5); s_Uv[1].x = s_Uv[0].x; s_Uv[2].x = Mathf.Lerp(num, num3, t6); s_Uv[3].x = s_Uv[2].x; s_Uv[0].y = Mathf.Lerp(num2, num4, t7); s_Uv[1].y = Mathf.Lerp(num2, num4, t8); s_Uv[2].y = s_Uv[1].y; s_Uv[3].y = s_Uv[0].y; float value2 = (!m_FillClockwise) ? (m_FillAmount * 4f - (float)(3 - (j + m_FillOrigin) % 4)) : (m_FillAmount * 4f - (float)((j + m_FillOrigin) % 4)); if (RadialCut(s_Xy, s_Uv, Mathf.Clamp01(value2), m_FillClockwise, (j + 2) % 4)) { AddQuad(toFill, s_Xy, base.color, s_Uv); } } } } else { AddQuad(toFill, s_Xy, base.color, s_Uv); } }
private void GenerateTiledSprite(VertexHelper toFill) { Vector4 vector; Vector4 vector2; Vector2 vector3; Vector4 a; if (overrideSprite != null) { vector = DataUtility.GetOuterUV(overrideSprite); vector2 = DataUtility.GetInnerUV(overrideSprite); a = overrideSprite.border; vector3 = overrideSprite.rect.size; } else { vector = Vector4.zero; vector2 = Vector4.zero; a = Vector4.zero; vector3 = Vector2.one * 100f; } Rect pixelAdjustedRect = GetPixelAdjustedRect(); float num = (vector3.x - a.x - a.z) / pixelsPerUnit; float num2 = (vector3.y - a.y - a.w) / pixelsPerUnit; a = GetAdjustedBorders(a / pixelsPerUnit, pixelAdjustedRect); Vector2 uvMin = new Vector2(vector2.x, vector2.y); Vector2 vector4 = new Vector2(vector2.z, vector2.w); UIVertex simpleVert = UIVertex.simpleVert; simpleVert.color = base.color; float x = a.x; float num3 = pixelAdjustedRect.width - a.z; float y = a.y; float num4 = pixelAdjustedRect.height - a.w; toFill.Clear(); Vector2 uvMax = vector4; if (num == 0f) { num = num3 - x; } if (num2 == 0f) { num2 = num4 - y; } if (m_FillCenter) { for (float num5 = y; num5 < num4; num5 += num2) { float num6 = num5 + num2; if (num6 > num4) { uvMax.y = uvMin.y + (vector4.y - uvMin.y) * (num4 - num5) / (num6 - num5); num6 = num4; } uvMax.x = vector4.x; for (float num7 = x; num7 < num3; num7 += num) { float num8 = num7 + num; if (num8 > num3) { uvMax.x = uvMin.x + (vector4.x - uvMin.x) * (num3 - num7) / (num8 - num7); num8 = num3; } AddQuad(toFill, new Vector2(num7, num5) + pixelAdjustedRect.position, new Vector2(num8, num6) + pixelAdjustedRect.position, base.color, uvMin, uvMax); } } } if (!hasBorder) { return; } uvMax = vector4; for (float num9 = y; num9 < num4; num9 += num2) { float num10 = num9 + num2; if (num10 > num4) { uvMax.y = uvMin.y + (vector4.y - uvMin.y) * (num4 - num9) / (num10 - num9); num10 = num4; } AddQuad(toFill, new Vector2(0f, num9) + pixelAdjustedRect.position, new Vector2(x, num10) + pixelAdjustedRect.position, base.color, new Vector2(vector.x, uvMin.y), new Vector2(uvMin.x, uvMax.y)); AddQuad(toFill, new Vector2(num3, num9) + pixelAdjustedRect.position, new Vector2(pixelAdjustedRect.width, num10) + pixelAdjustedRect.position, base.color, new Vector2(vector4.x, uvMin.y), new Vector2(vector.z, uvMax.y)); } uvMax = vector4; for (float num11 = x; num11 < num3; num11 += num) { float num12 = num11 + num; if (num12 > num3) { uvMax.x = uvMin.x + (vector4.x - uvMin.x) * (num3 - num11) / (num12 - num11); num12 = num3; } AddQuad(toFill, new Vector2(num11, 0f) + pixelAdjustedRect.position, new Vector2(num12, y) + pixelAdjustedRect.position, base.color, new Vector2(uvMin.x, vector.y), new Vector2(uvMax.x, uvMin.y)); AddQuad(toFill, new Vector2(num11, num4) + pixelAdjustedRect.position, new Vector2(num12, pixelAdjustedRect.height) + pixelAdjustedRect.position, base.color, new Vector2(uvMin.x, vector4.y), new Vector2(uvMax.x, vector.w)); } AddQuad(toFill, new Vector2(0f, 0f) + pixelAdjustedRect.position, new Vector2(x, y) + pixelAdjustedRect.position, base.color, new Vector2(vector.x, vector.y), new Vector2(uvMin.x, uvMin.y)); AddQuad(toFill, new Vector2(num3, 0f) + pixelAdjustedRect.position, new Vector2(pixelAdjustedRect.width, y) + pixelAdjustedRect.position, base.color, new Vector2(vector4.x, vector.y), new Vector2(vector.z, uvMin.y)); AddQuad(toFill, new Vector2(0f, num4) + pixelAdjustedRect.position, new Vector2(x, pixelAdjustedRect.height) + pixelAdjustedRect.position, base.color, new Vector2(vector.x, vector4.y), new Vector2(uvMin.x, vector.w)); AddQuad(toFill, new Vector2(num3, num4) + pixelAdjustedRect.position, new Vector2(pixelAdjustedRect.width, pixelAdjustedRect.height) + pixelAdjustedRect.position, base.color, new Vector2(vector4.x, vector4.y), new Vector2(vector.z, vector.w)); }
/** * @brief TextAniamation 진행에 맞춰 TextUIVertex (Y)위치 값 변경 * @param txtData : text animation info, uiVertex : text UI Vertex */ public override void Apply(TextData txtData, ref UIVertex uiVertex) { uiVertex.position.y *= curve.Evaluate(txtData.Progress); }
public override void ModifyMesh(VertexHelper vh) { if (IsActive()) { var count = vh.currentVertCount; if (count == 0) { return; } var degreeDelta = (float)(2 * Mathf.PI / Segments); var curVertice = Vector2.zero; var curDegree = 0f; var height = graphic.rectTransform.rect.height; var width = graphic.rectTransform.rect.width; var uv = new Vector4(0, 0, 1, 1); var uvCenterX = (uv.x + uv.z) * 0.5f; var uvCenterY = (uv.y + uv.w) * 0.5f; var uvScaleX = (uv.z - uv.x) / width; var uvScaleY = (uv.w - uv.y) / height; var outerRadius = new Vector2(graphic.rectTransform.pivot.x * width, graphic.rectTransform.pivot.y * height); var innerRadius = new Vector2(Mathf.Clamp(outerRadius.x - Thickness, 0, float.MaxValue), Mathf.Clamp(outerRadius.y - Thickness, 0, float.MaxValue)); if (innerRadius == Vector2.zero) { var verticeCount = Segments + 1; var triangleCount = 3 * Segments; var uiVertex = new UIVertex(); uiVertex.color = graphic.color; uiVertex.position = curVertice; uiVertex.uv0 = new Vector2(curVertice.x * uvScaleX + uvCenterX, curVertice.y * uvScaleY + uvCenterY); vh.Clear(); vh.AddVert(uiVertex); for (int i = 1; i < verticeCount; i++) { var cosA = Mathf.Cos(curDegree); var sinA = Mathf.Sin(curDegree); curVertice = new Vector2(cosA * outerRadius.x, sinA * outerRadius.y); uiVertex = new UIVertex(); uiVertex.color = graphic.color; uiVertex.position = curVertice; uiVertex.uv0 = new Vector2(curVertice.x * uvScaleX + uvCenterX, curVertice.y * uvScaleY + uvCenterY); vh.AddVert(uiVertex); curDegree += degreeDelta; } var min = Mathf.FloorToInt(FillAmount.Min * verticeCount); var max = Mathf.FloorToInt(FillAmount.Max * verticeCount); for (int i = 0, j = 1; i < triangleCount - 3; i += 3, j++) { if (min <= j && max >= j + 1) { vh.AddTriangle(j, 0, j + 1); } } if (FillAmount.Max >= 1) { vh.AddTriangle(verticeCount - 1, 0, 1); } } else { var verticeCount = 2 * Segments; var triangleCount = 3 * 2 * Segments; vh.Clear(); for (int i = 0; i < verticeCount; i += 2) { var cosA = Mathf.Cos(curDegree); var sinA = Mathf.Sin(curDegree); curVertice = new Vector3(cosA * innerRadius.x, sinA * innerRadius.y); var uiVertex = new UIVertex(); uiVertex.color = graphic.color; uiVertex.position = curVertice; uiVertex.uv0 = new Vector2(curVertice.x * uvScaleX + uvCenterX, curVertice.y * uvScaleY + uvCenterY); vh.AddVert(uiVertex); curVertice = new Vector3(cosA * outerRadius.x, sinA * outerRadius.y); uiVertex = new UIVertex(); uiVertex.color = graphic.color; uiVertex.position = curVertice; uiVertex.uv0 = new Vector2(curVertice.x * uvScaleX + uvCenterX, curVertice.y * uvScaleY + uvCenterY); vh.AddVert(uiVertex); curDegree += degreeDelta; } var min = Mathf.FloorToInt(FillAmount.Min * verticeCount); var max = Mathf.FloorToInt(FillAmount.Max * verticeCount); for (int i = 0, j = 0; i < triangleCount - 6; i += 6, j += 2) { if (min <= j && max >= j + 3) { vh.AddTriangle(j + 1, j, j + 3); vh.AddTriangle(j, j + 2, j + 3); } } if (FillAmount.Max >= 1) { vh.AddTriangle(verticeCount - 1, verticeCount - 2, 1); vh.AddTriangle(verticeCount - 2, 0, 1); } } } }
protected override void OnPopulateMesh(VertexHelper toFill) { var orignText = m_Text; m_Text = m_OutputText; base.OnPopulateMesh(toFill); m_Text = orignText; UIVertex vert = new UIVertex(); for (var i = 0; i < m_ImagesVertexIndex.Count; i++) { var endIndex = m_ImagesVertexIndex[i]; var rt = m_ImagesPool[i].rectTransform; var size = rt.sizeDelta; if (endIndex < toFill.currentVertCount) { toFill.PopulateUIVertex(ref vert, endIndex); rt.anchoredPosition = new Vector2(vert.position.x + size.x / 2, vert.position.y + size.y / 2); // 抹掉左下角的小黑点 toFill.PopulateUIVertex(ref vert, endIndex - 3); var pos = vert.position; for (int j = endIndex, m = endIndex - 3; j > m; j--) { toFill.PopulateUIVertex(ref vert, endIndex); vert.position = pos; toFill.SetUIVertex(vert, j); } } } if (m_ImagesVertexIndex.Count != 0) { m_ImagesVertexIndex.Clear(); } // 处理超链接包围框 foreach (var hrefInfo in m_HrefInfos) { hrefInfo.boxes.Clear(); if (hrefInfo.startIndex >= toFill.currentVertCount) { continue; } // 将超链接里面的文本顶点索引坐标加入到包围框 toFill.PopulateUIVertex(ref vert, hrefInfo.startIndex); var pos = vert.position; var bounds = new Bounds(pos, Vector3.zero); for (int i = hrefInfo.startIndex, m = hrefInfo.endIndex; i < m; i++) { if (i >= toFill.currentVertCount) { break; } toFill.PopulateUIVertex(ref vert, i); pos = vert.position; if (pos.x < bounds.min.x) // 换行重新添加包围框 { hrefInfo.boxes.Add(new Rect(bounds.min, bounds.size)); bounds = new Bounds(pos, Vector3.zero); } else { bounds.Encapsulate(pos); // 扩展包围框 } } hrefInfo.boxes.Add(new Rect(bounds.min, bounds.size)); } }
override protected void OnPopulateMesh(VertexHelper helper) { // var total = new Stopwatch(); // total.Start(); if (!Mesh || !Mesh.isReadable) { helper.Clear(); return; } int[] triangles = Mesh.triangles; Color[] colors = Mesh.colors; Vector3[] positions = Mesh.vertices; List <int> indices; indices = ListPool <int> .Get(); for (int index = 0; index < triangles.Length; index++) { indices.Add(triangles[index]); } Rect rect; rect = rectTransform.rect; Vector2 scale; scale = Vector2.zero; switch (ScaleMode) { case MeshGraphicScaleMode.None: scale = Vector2.one * PixelsPerUnit; break; case MeshGraphicScaleMode.AspectFill: scale.x = scale.y = Mathf.Max(rect.width / Mesh.bounds.size.x, rect.height / Mesh.bounds.size.y); break; case MeshGraphicScaleMode.AspectFit: scale.x = scale.y = Mathf.Min(rect.width / Mesh.bounds.size.x, rect.height / Mesh.bounds.size.y); break; case MeshGraphicScaleMode.Fill: scale.x = rect.width / Mesh.bounds.size.x; scale.y = rect.height / Mesh.bounds.size.y; break; } Bounds bounds; bounds = Mesh.bounds; bounds.SetMinMax(Vector2.Scale(bounds.min, scale), Vector2.Scale(bounds.max, scale)); Vector2 offset; offset = (Vector2)rect.center; switch (AlignMode) { case MeshGraphicAlignMode.UpperLeft: offset = (Vector2)rect.center - (Vector2)bounds.center; offset.x += (bounds.size.x - rect.width) * 0.5f; offset.y += (bounds.size.y - rect.height) * -0.5f; break; case MeshGraphicAlignMode.UpperCenter: offset = (Vector2)rect.center - (Vector2)bounds.center; offset.y += (bounds.size.y - rect.height) * -0.5f; break; case MeshGraphicAlignMode.UpperRight: offset = (Vector2)rect.center - (Vector2)bounds.center; offset.x += (bounds.size.x - rect.width) * -0.5f; offset.y += (bounds.size.y - rect.height) * -0.5f; break; case MeshGraphicAlignMode.MiddleLeft: offset = (Vector2)rect.center - (Vector2)bounds.center; offset.x += (bounds.size.x - rect.width) * 0.5f; break; case MeshGraphicAlignMode.MiddleCenter: offset = (Vector2)rect.center - (Vector2)bounds.center; break; case MeshGraphicAlignMode.MiddleRight: offset = (Vector2)rect.center - (Vector2)bounds.center; offset.x += (bounds.size.x - rect.width) * -0.5f; break; case MeshGraphicAlignMode.LowerLeft: offset = (Vector2)rect.center - (Vector2)bounds.center; offset.x += (bounds.size.x - rect.width) * 0.5f; offset.y += (bounds.size.y - rect.height) * 0.5f; break; case MeshGraphicAlignMode.LowerCenter: offset = (Vector2)rect.center - (Vector2)bounds.center; offset.y += (bounds.size.y - rect.height) * 0.5f; break; case MeshGraphicAlignMode.LowerRight: offset = (Vector2)rect.center - (Vector2)bounds.center; offset.x += (bounds.size.x - rect.width) * -0.5f; offset.y += (bounds.size.y - rect.height) * 0.5f; break; } List <UIVertex> vertices; vertices = ListPool <UIVertex> .Get(); for (int index = 0; index < positions.Length; index++) { UIVertex vert = UIVertex.simpleVert; vert.position = Vector2.Scale(positions[index], scale) + offset; vert.color = ColorMode == MeshGraphicColorMode.VertexColor ? colors[index] : color; vertices.Add(vert); } helper.Clear(); helper.AddUIVertexStream(vertices, indices); ListPool <int> .Put(indices); ListPool <UIVertex> .Put(vertices); // total.Stop(); // Debug.LogFormat(this, "MeshGraphic.OnPopulateMesh(): {0}ms", total.ElapsedMilliseconds); }
void fillUnderline(List <UIVertex> toFill) #endif { if (null == mCharTextGenerator) { mCharTextGenerator = new TextGenerator(1); } #if UNITY_5_2 || UNITY_5_3_OR_NEWER || UNITY_5_4 m_DisableFontTextureRebuiltCallback = true; #else #endif Vector2 extents = rectTransform.rect.size; TextGenerationSettings settings = GetGenerationSettings(extents); mCharTextGenerator.Populate("_", settings); IList <UIVertex> verts = mCharTextGenerator.verts; if (verts.Count < 4) { return; } Vector2 topUV = (verts[0].uv0 + verts[1].uv0) / 2; Vector2 bottomUV = (verts[2].uv0 + verts[3].uv0) / 2; UIVertex[] temp = new UIVertex[4]; for (int i = 0; i < 4; i++) { temp[i] = verts[i]; if (i < 2) { temp[i].uv0 = topUV; } else { temp[i].uv0 = bottomUV; } } #if UNITY_5_2 || UNITY_5_3_OR_NEWER || UNITY_5_4 float underLineTopY = mCharTextGenerator.lines[0].topY; #else float underLineTopY = mCharTextGenerator.characters[0].cursorPos.y; #endif float offsetTop = verts[0].position.y - underLineTopY; float offsetBottom = verts[3].position.y - underLineTopY; IList <UILineInfo> lines = cachedTextGenerator.lines; TextSegmentFlag segment; int segmentIdx = 0, segmentStartIdx = -1, segmentEndIdx = -1, endIdx = lines.Count - 1; bool start = false; if (null == mUnderlineEdgeCfg) { mUnderlineEdgeCfg = new UnderlineEdgeConfig(); } mUnderlineEdgeCfg.init(toFill, temp, cachedTextGenerator, offsetTop, offsetBottom); for (int i = 0, max = lines.Count; i < max; ++i) { if (segmentIdx == mUnderlineIndexList.Count) { break; } segment = mUnderlineIndexList[segmentIdx]; if (!start && (lines[i].startCharIdx > segment.start || i == endIdx)) { if (!mUnderlineEdgeCfg.setUnderLineStartPos(segment.start, ref segmentStartIdx, i)) { break; } start = true; } if (start && (lines[i].startCharIdx > segment.end || i == endIdx)) { segmentEndIdx = i - (lines[i].startCharIdx > segment.end ? 1 : 0); if (segmentStartIdx == segmentEndIdx) { if (!mUnderlineEdgeCfg.setUnderLineEndPos(segment.end)) { break; } segmentIdx++; start = false; --i; continue; } //start -> start line end int startLineEndCharIdx = lines[segmentStartIdx + 1].startCharIdx - 1; if ('\n' == text[startLineEndCharIdx]) { --startLineEndCharIdx; } if (!mUnderlineEdgeCfg.setUnderLineEndPos(startLineEndCharIdx)) { break; } //for(line start + 1 --> line end - 1) for (int k = segmentStartIdx + 1; k < segmentEndIdx; ++k) { int lineStartCharIdx = lines[k].startCharIdx; //ignore line feed if ('\n' == text[lineStartCharIdx]) { continue; } if (!mUnderlineEdgeCfg.setUnderLineStartPos(lineStartCharIdx, ref k, k)) { break; } int lineEndCharIdx = lines[k + 1].startCharIdx - 1; if ('\n' == text[lineEndCharIdx]) { --lineEndCharIdx; } if (!mUnderlineEdgeCfg.setUnderLineEndPos(lineEndCharIdx)) { break; } } //end line start -> end int endLineStartCharIdx = lines[segmentEndIdx].startCharIdx; if (!mUnderlineEdgeCfg.setUnderLineStartPos(endLineStartCharIdx, ref segmentEndIdx, segmentEndIdx)) { break; } if (!mUnderlineEdgeCfg.setUnderLineEndPos(segment.end)) { break; } segmentIdx++; start = false; --i; continue; } } #if UNITY_5_2 || UNITY_5_3_OR_NEWER || UNITY_5_4 m_DisableFontTextureRebuiltCallback = false; #else #endif }
void Perspective(VertexHelper helper, ref UIVertex v, int i) { int curTextIndex = IndexOffsetByTag(i) >> 2; //float xFactor = CalcCurPerspectiveFactor(curTextIndex, _perspectiveFactor.x); float yFactor = CalcCurPerspectiveFactor(curTextIndex, _perspectiveFactor.y); //float curOff = 0; //if (_verticesCount / 4 % 2 == 0) //{ // curOff = (_verticesCount / 8 - curTextIndex) * _perspectiveFactor; // if (curTextIndex < _verticesCount / 8) // { // curOff = (_verticesCount / 8 - curTextIndex - 1) * _perspectiveFactor + _perspectiveFactor / 2; // } // else // { // curOff = -(curTextIndex - _verticesCount / 8) * _perspectiveFactor - _perspectiveFactor / 2; // } //} //else //{ // curOff = (_verticesCount / 8 - curTextIndex) * _perspectiveFactor; //} if (i % 4 == 0 || i % 4 == 1) { //if (layout == Layout.Normal) //{ v.position.y += _strethFactor; v.position.x += yFactor; //} ////圆形布局需要计算方向 //else //{ // v.position = _verticesOriPos[i] + SampleFromAnimCurve(i) * _animFactor * _verticleYDir[i]; //} } else if (i % 4 == 2) { //v.position.y += _strethFactor; v.position.x += _perspectiveFactor.x; //v.position.x += curOff; //v.position.y += _verticesOriPos[i] + SampleFromAnimCurve(i) * _animFactor * _defaultYDir; } else { v.position.x -= _perspectiveFactor.x; } //if (i % 4 == 0) //{ // //v.position.x += (_verticesCountWithTag - (i - 0.5f))/ _verticesCountWithTag * italicFactor.x; // //v.position.x -= (0.5f - i)/ _verticesCountWithTag * italicFactor.y; //} //else if (i % 4 == 1) //{ // v.position.x += curOff; // //v.position.x += (_verticesCountWithTag - (i + 0.5f)) / _verticesCountWithTag * italicFactor.x; // //v.position.x -= (- 0.5f - i) / _verticesCountWithTag * italicFactor.y; //} //else //{ //v.position = _verticesOriPos[i]; //} }
/// <summary> /// Map position of a vertex to a section of a circle. calculated in canvas's local space /// </summary> UIVertex CurveVertex(UIVertex input, float cylinder_angle, float radius, Vector2 canvasSize) { Vector3 pos = input.position; //calculated in canvas local space version: pos = CanvasToLocal.MultiplyPoint3x4(MyToWorld.MultiplyPoint3x4(pos)); // pos = mySettings.VertexPositionToCurvedCanvas(pos); if (mySettings.Shape == CurvedUISettings.CurvedUIShape.CYLINDER && mySettings.Angle != 0) { float theta = (pos.x / canvasSize.x) * cylinder_angle * Mathf.Deg2Rad; radius += pos.z; // change the radius depending on how far the element is moved in z direction from canvas plane pos.x = Mathf.Sin(theta) * radius; pos.z += Mathf.Cos(theta) * radius - radius; } else if (mySettings.Shape == CurvedUISettings.CurvedUIShape.CYLINDER_VERTICAL && mySettings.Angle != 0) { float theta = (pos.y / canvasSize.y) * cylinder_angle * Mathf.Deg2Rad; radius += pos.z; // change the radius depending on how far the element is moved in z direction from canvas plane pos.y = Mathf.Sin(theta) * radius; pos.z += Mathf.Cos(theta) * radius - radius; } else if (mySettings.Shape == CurvedUISettings.CurvedUIShape.RING) { float angleOffset = 0; float r = pos.y.Remap(canvasSize.y * 0.5f * (mySettings.RingFlipVertical ? 1 : -1), -canvasSize.y * 0.5f * (mySettings.RingFlipVertical ? 1 : -1), mySettings.RingExternalDiameter * (1 - mySettings.RingFill) * 0.5f, mySettings.RingExternalDiameter * 0.5f); float theta = (pos.x / canvasSize.x).Remap(-0.5f, 0.5f, Mathf.PI / 2.0f, cylinder_angle * Mathf.Deg2Rad + Mathf.PI / 2.0f) - angleOffset; pos.x = r * Mathf.Cos(theta); pos.y = r * Mathf.Sin(theta); } else if (mySettings.Shape == CurvedUISettings.CurvedUIShape.SPHERE && mySettings.Angle != 0) { float vangle = mySettings.VerticalAngle; float savedZ = -pos.z; if (mySettings.PreserveAspect) { vangle = cylinder_angle * (canvasSize.y / canvasSize.x); } else { radius = canvasSize.x / 2.0f; if (vangle == 0) { return(input); } } //convert planar coordinates to spherical coordinates float theta = (pos.x / canvasSize.x).Remap(-0.5f, 0.5f, (180 - cylinder_angle) / 2.0f - 90, 180 - (180 - cylinder_angle) / 2.0f - 90); theta *= Mathf.Deg2Rad; float gamma = (pos.y / canvasSize.y).Remap(-0.5f, 0.5f, (180 - vangle) / 2.0f, 180 - (180 - vangle) / 2.0f); gamma *= Mathf.Deg2Rad; pos.z = Mathf.Sin(gamma) * Mathf.Cos(theta) * (radius + savedZ); pos.y = -(radius + savedZ) * Mathf.Cos(gamma); pos.x = Mathf.Sin(gamma) * Mathf.Sin(theta) * (radius + savedZ); if (mySettings.PreserveAspect) { pos.z -= radius; } } //4. write output input.position = MyToLocal.MultiplyPoint3x4(CanvasToWorld.MultiplyPoint3x4(pos)); return(input); }
//刷新布局 void RefreshLayout(VertexHelper helper, ref UIVertex v) { //圆形布局,重新计算顶点位置信息 if (layout == Layout.Circle) { ClearPosRecord(); RecordVerticesInfo(helper, ref v); Vector3 tempCenter = new Vector3(); for (int i = 0; i < _centerPos.Count; i++) { tempCenter += _centerPos[i]; } tempCenter /= _centerPos.Count; _circleCenter = new Vector3(tempCenter.x, tempCenter.y - _radius); _textCenter = new Vector3(tempCenter.x, tempCenter.y); //重新计算每个顶点的布局 for (int i = 0; i < _verticesCountWithTag; i++) { if (!IsValidVertice(i)) { continue; } helper.PopulateUIVertex(ref v, i); CircleLayout(helper, ref v, i); helper.SetUIVertex(v, i); } RecordAfterLayout(helper, ref v); } else if (layout == Layout.Italic) { ClearPosRecord(); RecordVerticesInfo(helper, ref v); //重新计算每个顶点的布局 for (int i = 0; i < _verticesCountWithTag; i++) { if (!IsValidVertice(i)) { continue; } helper.PopulateUIVertex(ref v, i); Italic(helper, ref v, i); helper.SetUIVertex(v, i); } RecordAfterLayout(helper, ref v); } else if (layout == Layout.Perspective) { ClearPosRecord(); RecordVerticesInfo(helper, ref v); //重新计算每个顶点的布局 for (int i = 0; i < _verticesCountWithTag; i++) { if (!IsValidVertice(i)) { continue; } helper.PopulateUIVertex(ref v, i); Perspective(helper, ref v, i); helper.SetUIVertex(v, i); } RecordAfterLayout(helper, ref v); } }
private void PopulateMesh(VertexHelper vh, Vector2[] pointsToDraw) { //If Bezier is desired, pick the implementation if (BezierMode != BezierType.None && BezierMode != BezierType.Catenary && pointsToDraw.Length > 3) { BezierPath bezierPath = new BezierPath(); bezierPath.SetControlPoints(pointsToDraw); bezierPath.SegmentsPerCurve = bezierSegmentsPerCurve; List <Vector2> drawingPoints; switch (BezierMode) { case BezierType.Basic: drawingPoints = bezierPath.GetDrawingPoints0(); break; case BezierType.Improved: drawingPoints = bezierPath.GetDrawingPoints1(); break; default: drawingPoints = bezierPath.GetDrawingPoints2(); break; } pointsToDraw = drawingPoints.ToArray(); } if (BezierMode == BezierType.Catenary && pointsToDraw.Length == 2) { CableCurve cable = new CableCurve(pointsToDraw); cable.slack = Resoloution; cable.steps = BezierSegmentsPerCurve; pointsToDraw = cable.Points(); } if (ImproveResolution != ResolutionMode.None) { pointsToDraw = IncreaseResolution(pointsToDraw); } // scale based on the size of the rect or use absolute, this is switchable var sizeX = !relativeSize ? 1 : rectTransform.rect.width; var sizeY = !relativeSize ? 1 : rectTransform.rect.height; var offsetX = -rectTransform.pivot.x * sizeX; var offsetY = -rectTransform.pivot.y * sizeY; // Generate the quads that make up the wide line var segments = new List <UIVertex[]> (); if (lineList) { for (var i = 1; i < pointsToDraw.Length; i += 2) { var start = pointsToDraw [i - 1]; var end = pointsToDraw [i]; start = new Vector2(start.x * sizeX + offsetX, start.y * sizeY + offsetY); end = new Vector2(end.x * sizeX + offsetX, end.y * sizeY + offsetY); if (lineCaps) { segments.Add(CreateLineCap(start, end, SegmentType.Start)); } segments.Add(CreateLineSegment(start, end, SegmentType.Middle, segments.Count > 1 ? segments[segments.Count - 2] : null)); if (lineCaps) { segments.Add(CreateLineCap(start, end, SegmentType.End)); } } } else { for (var i = 1; i < pointsToDraw.Length; i++) { var start = pointsToDraw [i - 1]; var end = pointsToDraw [i]; start = new Vector2(start.x * sizeX + offsetX, start.y * sizeY + offsetY); end = new Vector2(end.x * sizeX + offsetX, end.y * sizeY + offsetY); if (lineCaps && i == 1) { segments.Add(CreateLineCap(start, end, SegmentType.Start)); } segments.Add(CreateLineSegment(start, end, SegmentType.Middle)); if (lineCaps && i == pointsToDraw.Length - 1) { segments.Add(CreateLineCap(start, end, SegmentType.End)); } } } // Add the line segments to the vertex helper, creating any joins as needed for (var i = 0; i < segments.Count; i++) { if (!lineList && i < segments.Count - 1) { var vec1 = segments [i] [1].position - segments [i] [2].position; var vec2 = segments [i + 1] [2].position - segments [i + 1] [1].position; var angle = Vector2.Angle(vec1, vec2) * Mathf.Deg2Rad; // Positive sign means the line is turning in a 'clockwise' direction var sign = Mathf.Sign(Vector3.Cross(vec1.normalized, vec2.normalized).z); // Calculate the miter point var miterDistance = lineThickness / (2 * Mathf.Tan(angle / 2)); var miterPointA = segments [i] [2].position - vec1.normalized * miterDistance * sign; var miterPointB = segments [i] [3].position + vec1.normalized * miterDistance * sign; var joinType = LineJoins; if (joinType == JoinType.Miter) { // Make sure we can make a miter join without too many artifacts. if (miterDistance < vec1.magnitude / 2 && miterDistance < vec2.magnitude / 2 && angle > MIN_MITER_JOIN) { segments [i] [2].position = miterPointA; segments [i] [3].position = miterPointB; segments [i + 1] [0].position = miterPointB; segments [i + 1] [1].position = miterPointA; } else { joinType = JoinType.Bevel; } } if (joinType == JoinType.Bevel) { if (miterDistance < vec1.magnitude / 2 && miterDistance < vec2.magnitude / 2 && angle > MIN_BEVEL_NICE_JOIN) { if (sign < 0) { segments [i] [2].position = miterPointA; segments [i + 1] [1].position = miterPointA; } else { segments [i] [3].position = miterPointB; segments [i + 1] [0].position = miterPointB; } } var join = new UIVertex[] { segments [i] [2], segments [i] [3], segments [i + 1] [0], segments [i + 1] [1] }; vh.AddUIVertexQuad(join); } } vh.AddUIVertexQuad(segments [i]); } if (vh.currentVertCount > 64000) { Debug.LogError("Max Verticies size is 64000, current mesh vertcies count is [" + vh.currentVertCount + "] - Cannot Draw"); vh.Clear(); return; } }
public override void ModifyMesh(VertexHelper helper) { if (!IsActive() || helper.currentVertCount == 0) { return; } List <UIVertex> _vertexList = new List <UIVertex> (); helper.GetUIVertexStream(_vertexList); int nCount = _vertexList.Count; switch (GradientType) { case Type.Vertical: { float fBottomY = _vertexList[0].position.y; float fTopY = _vertexList[0].position.y; float fYPos = 0f; for (int i = nCount - 1; i >= 1; --i) { fYPos = _vertexList[i].position.y; if (fYPos > fTopY) { fTopY = fYPos; } else if (fYPos < fBottomY) { fBottomY = fYPos; } } float fUIElementHeight = 1f / (fTopY - fBottomY); UIVertex v = new UIVertex(); for (int i = 0; i < helper.currentVertCount; i++) { helper.PopulateUIVertex(ref v, i); v.color = Color32.Lerp(EndColor, StartColor, (v.position.y - fBottomY) * fUIElementHeight - Offset); helper.SetUIVertex(v, i); } } break; case Type.Horizontal: { float fLeftX = _vertexList[0].position.x; float fRightX = _vertexList[0].position.x; float fXPos = 0f; for (int i = nCount - 1; i >= 1; --i) { fXPos = _vertexList[i].position.x; if (fXPos > fRightX) { fRightX = fXPos; } else if (fXPos < fLeftX) { fLeftX = fXPos; } } float fUIElementWidth = 1f / (fRightX - fLeftX); UIVertex v = new UIVertex(); for (int i = 0; i < helper.currentVertCount; i++) { helper.PopulateUIVertex(ref v, i); v.color = Color32.Lerp(EndColor, StartColor, (v.position.x - fLeftX) * fUIElementWidth - Offset); helper.SetUIVertex(v, i); } } break; default: break; } }
protected override void OnPopulateMesh(VertexHelper toFill) { // Vector4 v = GetDrawingDimensions(); // var uv = (overrideSprite != null) ? DataUtility.GetOuterUV(overrideSprite) : Vector4.zero; // print("//?uv"+uv); // var color32 = color; // toFill.Clear(); // toFill.AddVert(new Vector3(v.x, v.y), color32, new Vector2(uv.x, uv.y)); // toFill.AddVert(new Vector3(v.x, v.w), color32, new Vector2(uv.x, uv.w)); // toFill.AddVert(new Vector3(v.z, v.w), color32, new Vector2(uv.z, uv.w)); // toFill.AddVert(new Vector3(v.z, v.y), color32, new Vector2(uv.z, uv.y)); // toFill.AddTriangle(0, 1, 2); // toFill.AddTriangle(2, 3, 0); vertexList = new List <Vector2>(); toFill.Clear(); //Sprite外部UV参数 Vector4 uv = overrideSprite != null?DataUtility.GetOuterUV(overrideSprite) : Vector4.zero; //Vector2[] uvs = overrideSprite.uv; //获取必要的参数 float width = rectTransform.rect.width; float height = rectTransform.rect.height; float uv_width = uv.z - uv.x; float uv_height = uv.w - uv.y; Vector2 uv_centre = new Vector2(uv_width * 0.5f + uv.x, uv_height * 0.5f + uv.y); Vector2 rate = new Vector2(uv_width / width, uv_height / height); //计算半径和弧度 float radius = redius <= 0 ? width / 2 : redius; float radian = (2 * Mathf.PI) / segments; //添加初始点 UIVertex origin = new UIVertex(); var spriteSize = new Vector2(overrideSprite.rect.width, overrideSprite.rect.height); var spritePivot = overrideSprite.pivot / spriteSize; var rectPivot = rectTransform.pivot; Rect r = GetPixelAdjustedRect(); var drawingSize = new Vector2(r.width, r.height); var spriteBoundSize = overrideSprite.bounds.size; var drawOffset = (rectPivot - spritePivot) * drawingSize; Vector2[] vertices = overrideSprite.vertices; Vector2 origin_pos = new Vector2((0.5f - rectTransform.pivot.x) * width, (0.5f - rectTransform.pivot.y) * height);//原点位置 origin.color = color; origin.position = origin_pos; float uv_x = originPos.x * rate.x + uv_centre.x; float uv_y = originPos.y * rate.y + uv_centre.y; origin.uv0 = new Vector2(uv_x, uv_y); toFill.AddVert(origin); //添加其他点 // toFill.AddVert(new Vector3(v.x, v.y), color, new Vector2(uv.x, uv.y)); // toFill.AddVert(new Vector3(v.x, v.w), color, new Vector2(uv.x, uv.w)); // toFill.AddVert(new Vector3(v.z, v.w), color, new Vector2(uv.z, uv.w)); // toFill.AddVert(new Vector3(v.z, v.y), color, new Vector2(uv.z, uv.y)); float total_radian = 0; for (int i = 0; i < segments + 1; i++) { //角度转为弧度 float x = Mathf.Cos(total_radian + MathTool.AngleToRadian(rotation)) * radius; float y = Mathf.Sin(total_radian + MathTool.AngleToRadian(rotation)) * radius; float real_x = x; float real_y = y; // float k = (origin_pos.y - y) / (origin_pos.x - x); // if (x > v.z) // { // real_x = v.z; // real_y = k * (real_x - x) + y; // } // if (x < v.x) // { // real_x = v.x; // real_y = k * (real_x - x) + y; // } // if (y > v.w) // { // real_y = v.w; // real_x = (real_y - y) / k + x; // } // if (y < v.y) // { // real_y = v.y; // real_x = (real_y - y) / k + x; // } total_radian += radian; origin = new UIVertex(); Vector2 other_pos = new Vector2(real_x, real_y) + origin_pos; origin.color = color; origin.position = other_pos; uv_x = ((originPos.x + x) * rate.x + uv_centre.x); uv_y = ((originPos.y + y) * rate.y + uv_centre.y); origin.uv0 = new Vector2(uv_x, uv_y); toFill.AddVert(origin); vertexList.Add(other_pos); } //绘制圆形 for (int i = 1; i <= segments; i++) { toFill.AddTriangle(i, 0, i + 1); } }
/// <summary> /// 纹理 /// </summary> protected string CalculateLayoutOfImage(string richText, out IList <UIVertex> verts) { float fontSize2 = fontSize * 0.5f; float unitsPerPixel = 1f / pixelsPerUnit; Vector2 extents = rectTransform.rect.size; var settings = GetGenerationSettings(extents); settings.verticalOverflow = VerticalWrapMode.Overflow; // Image replace icons.Clear(); Match match = null; StringBuilder builder = new StringBuilder(); while ((match = IconReg.Match(richText)).Success) { IconInfo iconInfo = new IconInfo(); float w = fontSize2, h = fontSize2, pivot = 0f, frame = -1f; string[] sprites = null; string atlas = null, e = null, args = null; Match itemMatch = ItemReg.Match(match.Value); while (itemMatch.Success) { string name = itemMatch.Groups[1].Value; string value = itemMatch.Groups[2].Value; switch (name) { case "frame": //帧率 float.TryParse(value, out frame); break; case "sprite": //纹理 sprites = value.Split('+'); break; case "atlas": //图集 atlas = value; break; case "pivot": //y方向锚点 float.TryParse(value, out pivot); break; case "w": //宽 float.TryParse(value, out w); break; case "h": //高 float.TryParse(value, out h); break; case "event": //事件 e = value; break; case "args": //事件参数 args = value; break; } itemMatch = itemMatch.NextMatch(); } iconInfo.size = new Vector2(w, h); iconInfo.pivot = pivot; iconInfo.frame = frame; iconInfo.atlas = atlas; iconInfo.sprite = sprites; iconInfo.evt = e; iconInfo.args = args; iconInfo.vertice = match.Index * 4; icons.Add(iconInfo); float size = (1f - pivot) * (iconInfo.size.y - fontSize) + fontSize; string replace = string.Format("<size={0}>{1}</size>", size, replaceChar); float spaceWidth = cachedTextGenerator.GetPreferredWidth(replace, settings) * unitsPerPixel; int holderLen = Mathf.CeilToInt(iconInfo.size.x / spaceWidth); if (holderLen < 0) { holderLen = 0; } //占位符 builder.Length = 0; builder.Append(string.Format("<color=#00000000><size={0}>", size)); builder.Append(replaceChar, holderLen); builder.Append("</size></color>"); string holder = builder.ToString(); iconInfo.vlength = holder.Length * 4; //截取 builder.Length = 0; builder.Append(richText, 0, match.Index); builder.Append(holder); builder.Append(richText, match.Index + match.Length, richText.Length - match.Index - match.Length); richText = builder.ToString(); } // Populate characters cachedTextGenerator.Populate(richText, settings); //这里不是直接给verts赋值,而是返回一个副本,避免操作unity内部verts造成顶点泄漏 UIVertex[] ary = new UIVertex[cachedTextGenerator.verts.Count]; cachedTextGenerator.verts.CopyTo(ary, 0); verts = new List <UIVertex>(ary); // Last 4 verts are always a new line... int vertCount = verts.Count - 4; if (vertCount <= 0) { icons.Clear(); SetImageDirty(); preferTextWid = preferTextHei = richText; return(richText); } preferTextWid = richText; // Image wrap check if (horizontalOverflow == HorizontalWrapMode.Wrap) { //水平自动换行 for (int i = 0; i < icons.Count; i++) { IconInfo iconInfo = icons[i]; int vertice = iconInfo.vertice; int vlength = iconInfo.vlength; if (verts[vertice + vlength - 1].position.x < verts[vertice].position.x) { // New line richText = richText.Insert(vertice / 4, "\r\n"); for (int j = i; j < icons.Count; j++) { icons[j].vertice += 8; } //todo:这里也要小心 cachedTextGenerator.Populate(richText, settings); verts = cachedTextGenerator.verts; vertCount = verts.Count - 4; } } } if (verticalOverflow == VerticalWrapMode.Truncate) { //溢出框外的不要 float minY = rectTransform.rect.yMin; while (vertCount > 0 && verts[vertCount - 2].position.y * unitsPerPixel < minY) { verts.RemoveAt(vertCount - 1); verts.RemoveAt(vertCount - 2); verts.RemoveAt(vertCount - 3); verts.RemoveAt(vertCount - 4); vertCount -= 4; } } preferTextHei = richText; // Image position calculation for (int i = icons.Count - 1; i >= 0; i--) { IconInfo iconInfo = icons[i]; int vertice = iconInfo.vertice; if (vertice < vertCount) { UIVertex vert = verts[vertice]; Vector2 vertex = vert.position; vertex *= unitsPerPixel; vertex += new Vector2(iconInfo.size.x * 0.5f, (fontSize2 + iconInfo.size.y * (0.5f - iconInfo.pivot)) * 0.5f); vertex += new Vector2(rectTransform.sizeDelta.x * (rectTransform.pivot.x - 0.5f), rectTransform.sizeDelta.y * (rectTransform.pivot.y - 0.5f)); iconInfo.position = vertex; iconInfo.color = Color.white; if (!string.IsNullOrEmpty(iconInfo.evt)) { Event e = new Event(); e.name = iconInfo.evt; e.args = iconInfo.args; e.rect = new Rect(verts[vertice].position.x * unitsPerPixel, verts[vertice].position.y * unitsPerPixel + (fontSize2 - iconInfo.size.y) * 0.5f, iconInfo.size.x, iconInfo.size.y); eventList.Add(e); } } else { icons.RemoveAt(i); } } // Need re-layout image SetImageDirty(); return(richText); }
/// <summary> /// Modifies the mesh. /// </summary> public override void ModifyMesh(VertexHelper vh) { if (!isActiveAndEnabled) { return; } vh.GetUIVertexStream(tempVerts); vh.Clear(); var count = tempVerts.Count; if (!m_AdvancedMode) { Vector2 uvMask = new Vector2(Packer.ToFloat(0, 0), Packer.ToFloat(1, 1)); // Vertex for (int i = 0; i < count; i++) { UIVertex vt = tempVerts[i]; vt.uv0 = new Vector2(Packer.ToFloat((vt.uv0.x + 0.5f) / 2f, (vt.uv0.y + 0.5f) / 2f), blur); vt.uv1 = uvMask; tempVerts[i] = vt; } vh.AddUIVertexTriangleStream(tempVerts); tempVerts.Clear(); return; } // Bundle int bundleSize = targetGraphic is Text ? 6 : count; Rect posBounds = default(Rect); Rect uvBounds = default(Rect); Vector3 size = default(Vector3); Vector3 tPos = default(Vector3); Vector3 tUV = default(Vector3); for (int i = 0; i < count; i += bundleSize) { // Quadバンドル単位での最大/最小値 GetBounds(tempVerts, i, bundleSize, ref posBounds, ref uvBounds, true); // Pack uv mask. Vector2 uvMask = new Vector2(Packer.ToFloat(uvBounds.xMin, uvBounds.yMin), Packer.ToFloat(uvBounds.xMax, uvBounds.yMax)); // Quad for (int j = 0; j < bundleSize; j += 6) { Vector3 cornerPos1 = tempVerts[i + j + 1].position; Vector3 cornerPos2 = tempVerts[i + j + 4].position; // 外周Quadかどうか. bool hasOuterEdge = (bundleSize == 6) || !posBounds.Contains(cornerPos1) || !posBounds.Contains(cornerPos2); if (hasOuterEdge) { Vector3 cornerUv1 = tempVerts[i + j + 1].uv0; Vector3 cornerUv2 = tempVerts[i + j + 4].uv0; Vector3 centerPos = (cornerPos1 + cornerPos2) / 2; Vector3 centerUV = (cornerUv1 + cornerUv2) / 2; size = (cornerPos1 - cornerPos2); size.x = 1 + (KernelSize - 1) / Mathf.Abs(size.x); size.y = 1 + (KernelSize - 1) / Mathf.Abs(size.y); size.z = 1 + (KernelSize - 1) / Mathf.Abs(size.z); tPos = centerPos - Vector3.Scale(size, centerPos); tUV = centerUV - Vector3.Scale(size, centerUV); } // Vertex for (int k = 0; k < 6; k++) { UIVertex vt = tempVerts[i + j + k]; Vector3 pos = vt.position; Vector2 uv0 = vt.uv0; if (hasOuterEdge && (pos.x < posBounds.xMin || posBounds.xMax < pos.x)) { pos.x = pos.x * size.x + tPos.x; uv0.x = uv0.x * size.x + tUV.x; } if (hasOuterEdge && (pos.y < posBounds.yMin || posBounds.yMax < pos.y)) { pos.y = pos.y * size.y + tPos.y; uv0.y = uv0.y * size.y + tUV.y; } vt.uv0 = new Vector2(Packer.ToFloat((uv0.x + 0.5f) / 2f, (uv0.y + 0.5f) / 2f), blur); vt.position = pos; vt.uv1 = uvMask; tempVerts[i + j + k] = vt; } } } vh.AddUIVertexTriangleStream(tempVerts); tempVerts.Clear(); }
public void AddUIVertexQuad(UIVertex[] verts) { int startIndex = currentVertCount; for (int i = 0; i < 4; i++) AddVert(verts[i].position, verts[i].color, verts[i].uv0, verts[i].uv1, verts[i].normal, verts[i].tangent); AddTriangle(startIndex, startIndex + 1, startIndex + 2); AddTriangle(startIndex + 2, startIndex + 3, startIndex); }
protected override void OnPopulateMesh(VertexHelper toFill) { toFill.Clear(); m_InnerVertices.Clear(); m_OuterVertices.Clear(); float degreeDelta = 2 * Mathf.PI / m_Segments; int curSegements = (int)(m_Segments * m_FillPercent); float tw = rectTransform.rect.width; float th = rectTransform.rect.height; float outerRadius = rectTransform.pivot.x * tw; float innerRadius = rectTransform.pivot.x * tw - m_Thickness; Vector4 uv = overrideSprite != null?DataUtility.GetOuterUV(overrideSprite) : Vector4.zero; float uvCenterX = (uv.x + uv.z) * 0.5f; float uvCenterY = (uv.y + uv.w) * 0.5f; float uvScaleX = (uv.z - uv.x) / tw; float uvScaleY = (uv.w - uv.y) / th; float curDegree = 0; UIVertex uiVertex; int verticeCount; int triangleCount; Vector2 curVertice; if (m_Fill) {// Circle curVertice = Vector2.zero; verticeCount = curSegements + 1; uiVertex = new UIVertex(); uiVertex.color = color; uiVertex.position = curVertice; uiVertex.uv0 = new Vector2(curVertice.x * uvScaleX + uvCenterX, curVertice.y * uvScaleY + uvCenterY); toFill.AddVert(uiVertex); for (int i = 1; i < verticeCount; i++) { float cosA = Mathf.Cos(curDegree); float sinA = Mathf.Sin(curDegree); curVertice = new Vector2(cosA * outerRadius, sinA * outerRadius); curDegree += degreeDelta; uiVertex = new UIVertex(); uiVertex.color = color; uiVertex.position = curVertice; uiVertex.uv0 = new Vector2(curVertice.x * uvScaleX + uvCenterX, curVertice.y * uvScaleY + uvCenterY); toFill.AddVert(uiVertex); m_OuterVertices.Add(curVertice); } triangleCount = curSegements * 3; for (int i = 0, v = 1; i < triangleCount - 3; i += 3, v++) { toFill.AddTriangle(v, 0, v + 1); } if (m_FillPercent == 1f) {// Connect head and tail toFill.AddTriangle(verticeCount - 1, 0, 1); } } else {// Ring verticeCount = curSegements * 2; for (int i = 0; i < verticeCount; i += 2) { float cosA = Mathf.Cos(curDegree); float sinA = Mathf.Sin(curDegree); curDegree += degreeDelta; curVertice = new Vector3(cosA * innerRadius, sinA * innerRadius); uiVertex = new UIVertex(); uiVertex.color = color; uiVertex.position = curVertice; uiVertex.uv0 = new Vector2(curVertice.x * uvScaleX + uvCenterX, curVertice.y * uvScaleY + uvCenterY); toFill.AddVert(uiVertex); m_InnerVertices.Add(curVertice); curVertice = new Vector3(cosA * outerRadius, sinA * outerRadius); uiVertex = new UIVertex(); uiVertex.color = color; uiVertex.position = curVertice; uiVertex.uv0 = new Vector2(curVertice.x * uvScaleX + uvCenterX, curVertice.y * uvScaleY + uvCenterY); toFill.AddVert(uiVertex); m_OuterVertices.Add(curVertice); } triangleCount = curSegements * 3 * 2; for (int i = 0, v = 0; i < triangleCount - 6; i += 6, v += 2) { toFill.AddTriangle(v + 1, v, v + 3); toFill.AddTriangle(v, v + 2, v + 3); } if (m_FillPercent == 1f) {// Connect head and tail toFill.AddTriangle(verticeCount - 1, verticeCount - 2, 1); toFill.AddTriangle(verticeCount - 2, 0, 1); } } }
/// <summary> /// <para>Add a single vertex to the stream.</para> /// </summary> /// <param name="position"></param> /// <param name="color"></param> /// <param name="uv0"></param> /// <param name="uv1"></param> /// <param name="normal"></param> /// <param name="tangent"></param> /// <param name="v"></param> public void AddVert(UIVertex v) { this.AddVert(v.position, v.color, v.uv0, v.uv1, v.normal, v.tangent); }
public override void ModifyMesh(VertexHelper helper) { if (!IsActive() || helper.currentVertCount == 0) { return; } List <UIVertex> _vertexList = new List <UIVertex>(); helper.GetUIVertexStream(_vertexList); int nCount = _vertexList.Count; switch (GradientType) { case Type.Horizontal: case Type.Vertical: { Rect bounds = GetBounds(_vertexList); float min = bounds.xMin; float w = bounds.width; Func <UIVertex, float> GetPosition = v => v.position.x; if (GradientType == Type.Vertical) { min = bounds.yMin; w = bounds.height; GetPosition = v => v.position.y; } float width = 1f / w / Zoom; float zoomOffset = (1 - (1 / Zoom)) * 0.5f; float offset = (Offset * (1 - zoomOffset)) - zoomOffset; if (ModifyVertices) { SplitTrianglesAtGradientStops(_vertexList, bounds, zoomOffset, helper); } UIVertex vertex = new UIVertex(); for (int i = 0; i < helper.currentVertCount; i++) { helper.PopulateUIVertex(ref vertex, i); vertex.color = BlendColor(vertex.color, EffectGradient.Evaluate((GetPosition(vertex) - min) * width - offset)); helper.SetUIVertex(vertex, i); } } break; case Type.Diamond: { Rect bounds = GetBounds(_vertexList); float height = 1f / bounds.height / Zoom; float radius = bounds.center.y / 2f; Vector3 center = (Vector3.right + Vector3.up) * radius + Vector3.forward * _vertexList[0].position.z; if (ModifyVertices) { helper.Clear(); for (int i = 0; i < nCount; i++) { helper.AddVert(_vertexList[i]); } UIVertex centralVertex = new UIVertex(); centralVertex.position = center; centralVertex.normal = _vertexList[0].normal; centralVertex.uv0 = new Vector2(0.5f, 0.5f); centralVertex.color = Color.white; helper.AddVert(centralVertex); for (int i = 1; i < nCount; i++) { helper.AddTriangle(i - 1, i, nCount); } helper.AddTriangle(0, nCount - 1, nCount); } UIVertex vertex = new UIVertex(); for (int i = 0; i < helper.currentVertCount; i++) { helper.PopulateUIVertex(ref vertex, i); vertex.color = BlendColor(vertex.color, EffectGradient.Evaluate( Vector3.Distance(vertex.position, center) * height - Offset)); helper.SetUIVertex(vertex, i); } } break; case Type.Radial: { Rect bounds = GetBounds(_vertexList); float width = 1f / bounds.width / Zoom; float height = 1f / bounds.height / Zoom; if (ModifyVertices) { helper.Clear(); float radiusX = bounds.width / 2f; float radiusY = bounds.height / 2f; UIVertex centralVertex = new UIVertex(); centralVertex.position = Vector3.right * bounds.center.x + Vector3.up * bounds.center.y + Vector3.forward * _vertexList[0].position.z; centralVertex.normal = _vertexList[0].normal; centralVertex.uv0 = new Vector2(0.5f, 0.5f); centralVertex.color = Color.white; int steps = 64; for (int i = 0; i < steps; i++) { UIVertex curVertex = new UIVertex(); float angle = (float)i * 360f / (float)steps; float cosX = Mathf.Cos(Mathf.Deg2Rad * angle); float cosY = Mathf.Sin(Mathf.Deg2Rad * angle); curVertex.position = Vector3.right * cosX * radiusX + Vector3.up * cosY * radiusY + Vector3.forward * _vertexList[0].position.z; curVertex.normal = _vertexList[0].normal; curVertex.uv0 = new Vector2((cosX + 1) * 0.5f, (cosY + 1) * 0.5f); curVertex.color = Color.white; helper.AddVert(curVertex); } helper.AddVert(centralVertex); for (int i = 1; i < steps; i++) { helper.AddTriangle(i - 1, i, steps); } helper.AddTriangle(0, steps - 1, steps); } UIVertex vertex = new UIVertex(); for (int i = 0; i < helper.currentVertCount; i++) { helper.PopulateUIVertex(ref vertex, i); vertex.color = BlendColor(vertex.color, EffectGradient.Evaluate( Mathf.Sqrt( Mathf.Pow(Mathf.Abs(vertex.position.x - bounds.center.x) * width, 2f) + Mathf.Pow(Mathf.Abs(vertex.position.y - bounds.center.y) * height, 2f)) * 2f - Offset)); helper.SetUIVertex(vertex, i); } } break; } }
void AddQuad(List<UIVertex> vbo, UIVertex v, Vector2 posMin, Vector2 posMax, Vector2 uvMin, Vector2 uvMax) { s_VertQuad[0] = new Vector3(posMin.x, posMin.y, 0); s_VertQuad[1] = new Vector3(posMin.x, posMax.y, 0); s_VertQuad[2] = new Vector3(posMax.x, posMax.y, 0); s_VertQuad[3] = new Vector3(posMax.x, posMin.y, 0); s_UVQuad[0] = new Vector2(uvMin.x, uvMin.y); s_UVQuad[1] = new Vector2(uvMin.x, uvMax.y); s_UVQuad[2] = new Vector2(uvMax.x, uvMax.y); s_UVQuad[3] = new Vector2(uvMax.x, uvMin.y); int offset = (int)rotate; for (int i = 0; i < 4; i++) { v.position = s_VertQuad[i]; v.uv0 = s_UVQuad[(i + offset) % 4]; vbo.Add(v); } }
/// <summary> /// Add a single vertex to the stream. /// </summary> /// <param name="v">The vertex to add</param> public void AddVert(UIVertex v) { AddVert(v.position, v.color, v.uv0, v.uv1, v.normal, v.tangent); }
public override void ModifyMesh(VertexHelper vh) { if (!IsActive()) { return; } int vertCount = vh.currentVertCount; if (vertCount < 2) { return; } if (colors.Count == 0) { return; } _vertexList.Clear(); for (var i = 0; i < vertCount; i++) { var vertex = new UIVertex(); vh.PopulateUIVertex(ref vertex, i); _vertexList.Add(vertex); } float start = Mathf.Infinity; float end = Mathf.NegativeInfinity; // 遍历所有顶点,获取首尾顶点 for (int i = 0; i < vertCount; i++) { float val = 0; if (gradientDirection == GradientDirection.VERTICAL) { val = _vertexList[i].position.y; } else { val = _vertexList[i].position.x; } if (val > end) { end = val; } else if (val < start) { start = val; } } // 首尾距离 float totalDist = end - start; if (totalDist == 0) { return; } // 遍历所有顶点上色 for (int i = 0; i < vertCount; i++) { UIVertex uiVertex = _vertexList[i]; if (colors.Count == 1) { uiVertex.color = colors[0]; } else { Color32 startColor = Color.white; Color32 endColor = Color.white; float step = totalDist / (colors.Count - 1); float passed = 0; if (gradientDirection == GradientDirection.VERTICAL) { passed = uiVertex.position.y - start; } else { passed = uiVertex.position.x - start; } int stepIdx = (int)(passed / step); if (stepIdx >= colors.Count - 1) { startColor = endColor = colors[colors.Count - 1]; } else { startColor = colors[stepIdx]; endColor = colors[stepIdx + 1]; } float remain = passed - stepIdx * step; uiVertex.color = Color32.Lerp(startColor, endColor, remain / step); } vh.SetUIVertex(uiVertex, i); } }
public override void ModifyMesh(VertexHelper mesh) { if (!IsActive() || Localization.currentLanguage == "ar" || Localization.currentLanguage == "fa") { return; } _Mesh = mesh; if (_Rebuild || _Vtx == null) { _Vtx = new List <int>(); for (int i = 0; i < _Mesh.currentVertCount; i++) { bool ok = true; UIVertex uv1 = new UIVertex(); _Mesh.PopulateUIVertex(ref uv1, i); if (i < _Mesh.currentVertCount - 1) { UIVertex uv2 = new UIVertex(); _Mesh.PopulateUIVertex(ref uv2, i + 1); if (uv1.position == uv2.position) { ok = false; } } if (ok && i > 0) { UIVertex uv2 = new UIVertex(); _Mesh.PopulateUIVertex(ref uv2, i - 1); if (uv1.position == uv2.position) { ok = false; } } if (ok) { _Vtx.Add(i); } } } int index = 0; for (int i = 0; i < _Vtx.Count; i++) { UIVertex uv = new UIVertex(); _Mesh.PopulateUIVertex(ref uv, _Vtx[i]); Color32 color = uv.color; if (index < (int)(charsPerSecond * (_Timer - delay)) * 4) { color.a = 255; } else { color.a = 0; } uv.color = color; _Mesh.SetUIVertex(uv, _Vtx[i]); index++; } }
/// <summary> /// <para>Add a quad to the stream.</para> /// </summary> /// <param name="verts">4 Vertices representing the quad.</param> public void AddUIVertexQuad(UIVertex[] verts) { int currentVertCount = this.currentVertCount; for (int index = 0; index < 4; ++index) this.AddVert(verts[index].position, verts[index].color, verts[index].uv0, verts[index].uv1, verts[index].normal, verts[index].tangent); this.AddTriangle(currentVertCount, currentVertCount + 1, currentVertCount + 2); this.AddTriangle(currentVertCount + 2, currentVertCount + 3, currentVertCount); }
public override void ModifyMesh(VertexHelper helper) { if (!IsActive() || helper.currentVertCount == 0) { return; } List <UIVertex> _vertexList = new List <UIVertex>(); helper.GetUIVertexStream(_vertexList); int nCount = _vertexList.Count; switch (GradientType) { case Type.Horizontal: { float left = _vertexList[0].position.x; float right = _vertexList[0].position.x; float x = 0f; for (int i = nCount - 1; i >= 1; --i) { x = _vertexList[i].position.x; if (x > right) { right = x; } else if (x < left) { left = x; } } float width = 1f / (right - left); UIVertex vertex = new UIVertex(); for (int i = 0; i < helper.currentVertCount; i++) { helper.PopulateUIVertex(ref vertex, i); vertex.color = BlendColor(vertex.color, EffectGradient.Evaluate((vertex.position.x - left) * width - Offset)); helper.SetUIVertex(vertex, i); } } break; case Type.Vertical: { float bottom = _vertexList[0].position.y; float top = _vertexList[0].position.y; float y = 0f; for (int i = nCount - 1; i >= 1; --i) { y = _vertexList[i].position.y; if (y > top) { top = y; } else if (y < bottom) { bottom = y; } } float height = 1f / (top - bottom); UIVertex vertex = new UIVertex(); for (int i = 0; i < helper.currentVertCount; i++) { helper.PopulateUIVertex(ref vertex, i); vertex.color = BlendColor(vertex.color, EffectGradient.Evaluate((vertex.position.y - bottom) * height - Offset)); helper.SetUIVertex(vertex, i); } } break; case Type.Diamond: { float bottom = _vertexList[0].position.y; float top = _vertexList[0].position.y; float y = 0f; for (int i = nCount - 1; i >= 1; --i) { y = _vertexList[i].position.y; if (y > top) { top = y; } else if (y < bottom) { bottom = y; } } float height = 1f / (top - bottom); helper.Clear(); for (int i = 0; i < nCount; i++) { helper.AddVert(_vertexList[i]); } float center = (bottom + top) / 2f; UIVertex centralVertex = new UIVertex(); centralVertex.position = (Vector3.right + Vector3.up) * center + Vector3.forward * _vertexList[0].position.z; centralVertex.normal = _vertexList[0].normal; centralVertex.color = Color.white; helper.AddVert(centralVertex); for (int i = 1; i < nCount; i++) { helper.AddTriangle(i - 1, i, nCount); } helper.AddTriangle(0, nCount - 1, nCount); UIVertex vertex = new UIVertex(); for (int i = 0; i < helper.currentVertCount; i++) { helper.PopulateUIVertex(ref vertex, i); vertex.color = BlendColor(vertex.color, EffectGradient.Evaluate( Vector3.Distance(vertex.position, centralVertex.position) * height - Offset)); helper.SetUIVertex(vertex, i); } } break; case Type.Radial: { float left = _vertexList[0].position.x; float right = _vertexList[0].position.x; float bottom = _vertexList[0].position.y; float top = _vertexList[0].position.y; float x = 0f; float y = 0f; for (int i = nCount - 1; i >= 1; --i) { x = _vertexList[i].position.x; if (x > right) { right = x; } else if (x < left) { left = x; } y = _vertexList[i].position.y; if (y > top) { top = y; } else if (y < bottom) { bottom = y; } } float width = 1f / (right - left); float height = 1f / (top - bottom); helper.Clear(); float centerX = (right + left) / 2f; float centerY = (bottom + top) / 2f; float radiusX = (right - left) / 2f; float radiusY = (top - bottom) / 2f; UIVertex centralVertex = new UIVertex(); centralVertex.position = Vector3.right * centerX + Vector3.up * centerY + Vector3.forward * _vertexList[0].position.z; centralVertex.normal = _vertexList[0].normal; centralVertex.color = Color.white; int steps = 64; for (int i = 0; i < steps; i++) { UIVertex curVertex = new UIVertex(); float angle = (float)i * 360f / (float)steps; float curX = Mathf.Cos(Mathf.Deg2Rad * angle) * radiusX; float curY = Mathf.Sin(Mathf.Deg2Rad * angle) * radiusY; curVertex.position = Vector3.right * curX + Vector3.up * curY + Vector3.forward * _vertexList[0].position.z; curVertex.normal = _vertexList[0].normal; curVertex.color = Color.white; helper.AddVert(curVertex); } helper.AddVert(centralVertex); for (int i = 1; i < steps; i++) { helper.AddTriangle(i - 1, i, steps); } helper.AddTriangle(0, steps - 1, steps); UIVertex vertex = new UIVertex(); for (int i = 0; i < helper.currentVertCount; i++) { helper.PopulateUIVertex(ref vertex, i); vertex.color = BlendColor(vertex.color, EffectGradient.Evaluate( Mathf.Sqrt( Mathf.Pow(Mathf.Abs(vertex.position.x - centerX) * width, 2f) + Mathf.Pow(Mathf.Abs(vertex.position.y - centerY) * height, 2f)) * 2f - Offset)); helper.SetUIVertex(vertex, i); } } break; } }
void AddQuad(List<UIVertex> vbo, UIVertex v, Vector2 posMin, Vector2 posMax, Vector2 uvMin, Vector2 uvMax) { v.position = new Vector3(posMin.x, posMin.y, 0); v.uv0 = new Vector2(uvMin.x, uvMin.y); vbo.Add(v); v.position = new Vector3(posMin.x, posMax.y, 0); v.uv0 = new Vector2(uvMin.x, uvMax.y); vbo.Add(v); v.position = new Vector3(posMax.x, posMax.y, 0); v.uv0 = new Vector2(uvMax.x, uvMax.y); vbo.Add(v); v.position = new Vector3(posMax.x, posMin.y, 0); v.uv0 = new Vector2(uvMax.x, uvMin.y); vbo.Add(v); }
void GenerateFilledSprite(VertexHelper toFill, bool preserveAspect) { toFill.Clear(); if (m_FillAmount < 0.001f) { return; } Vector4 v = GetDrawingDimensions(preserveAspect); Vector4 outer = activeSprite != null?Sprites.DataUtility.GetOuterUV(activeSprite) : Vector4.zero; UIVertex uiv = UIVertex.simpleVert; uiv.color = color; float tx0 = outer.x; float ty0 = outer.y; float tx1 = outer.z; float ty1 = outer.w; // Horizontal and vertical filled sprites are simple -- just end the Image prematurely if (m_FillMethod == FillMethod.Horizontal || m_FillMethod == FillMethod.Vertical) { if (fillMethod == FillMethod.Horizontal) { float fill = (tx1 - tx0) * m_FillAmount; if (m_FillOrigin == 1) { v.x = v.z - (v.z - v.x) * m_FillAmount; tx0 = tx1 - fill; } else { v.z = v.x + (v.z - v.x) * m_FillAmount; tx1 = tx0 + fill; } } else if (fillMethod == FillMethod.Vertical) { float fill = (ty1 - ty0) * m_FillAmount; if (m_FillOrigin == 1) { v.y = v.w - (v.w - v.y) * m_FillAmount; ty0 = ty1 - fill; } else { v.w = v.y + (v.w - v.y) * m_FillAmount; ty1 = ty0 + fill; } } } s_Xy[0] = new Vector2(v.x, v.y); s_Xy[1] = new Vector2(v.x, v.w); s_Xy[2] = new Vector2(v.z, v.w); s_Xy[3] = new Vector2(v.z, v.y); s_Uv[0] = new Vector2(tx0, ty0); s_Uv[1] = new Vector2(tx0, ty1); s_Uv[2] = new Vector2(tx1, ty1); s_Uv[3] = new Vector2(tx1, ty0); { if (m_FillAmount < 1f && m_FillMethod != FillMethod.Horizontal && m_FillMethod != FillMethod.Vertical) { if (fillMethod == FillMethod.Radial90) { if (RadialCut(s_Xy, s_Uv, m_FillAmount, m_FillClockwise, m_FillOrigin)) { AddQuad(toFill, s_Xy, color, s_Uv); } } else if (fillMethod == FillMethod.Radial180) { for (int side = 0; side < 2; ++side) { float fx0, fx1, fy0, fy1; int even = m_FillOrigin > 1 ? 1 : 0; if (m_FillOrigin == 0 || m_FillOrigin == 2) { fy0 = 0f; fy1 = 1f; if (side == even) { fx0 = 0f; fx1 = 0.5f; } else { fx0 = 0.5f; fx1 = 1f; } } else { fx0 = 0f; fx1 = 1f; if (side == even) { fy0 = 0.5f; fy1 = 1f; } else { fy0 = 0f; fy1 = 0.5f; } } s_Xy[0].x = Mathf.Lerp(v.x, v.z, fx0); s_Xy[1].x = s_Xy[0].x; s_Xy[2].x = Mathf.Lerp(v.x, v.z, fx1); s_Xy[3].x = s_Xy[2].x; s_Xy[0].y = Mathf.Lerp(v.y, v.w, fy0); s_Xy[1].y = Mathf.Lerp(v.y, v.w, fy1); s_Xy[2].y = s_Xy[1].y; s_Xy[3].y = s_Xy[0].y; s_Uv[0].x = Mathf.Lerp(tx0, tx1, fx0); s_Uv[1].x = s_Uv[0].x; s_Uv[2].x = Mathf.Lerp(tx0, tx1, fx1); s_Uv[3].x = s_Uv[2].x; s_Uv[0].y = Mathf.Lerp(ty0, ty1, fy0); s_Uv[1].y = Mathf.Lerp(ty0, ty1, fy1); s_Uv[2].y = s_Uv[1].y; s_Uv[3].y = s_Uv[0].y; float val = m_FillClockwise ? fillAmount * 2f - side : m_FillAmount * 2f - (1 - side); if (RadialCut(s_Xy, s_Uv, Mathf.Clamp01(val), m_FillClockwise, ((side + m_FillOrigin + 3) % 4))) { AddQuad(toFill, s_Xy, color, s_Uv); } } } else if (fillMethod == FillMethod.Radial360) { for (int corner = 0; corner < 4; ++corner) { float fx0, fx1, fy0, fy1; if (corner < 2) { fx0 = 0f; fx1 = 0.5f; } else { fx0 = 0.5f; fx1 = 1f; } if (corner == 0 || corner == 3) { fy0 = 0f; fy1 = 0.5f; } else { fy0 = 0.5f; fy1 = 1f; } s_Xy[0].x = Mathf.Lerp(v.x, v.z, fx0); s_Xy[1].x = s_Xy[0].x; s_Xy[2].x = Mathf.Lerp(v.x, v.z, fx1); s_Xy[3].x = s_Xy[2].x; s_Xy[0].y = Mathf.Lerp(v.y, v.w, fy0); s_Xy[1].y = Mathf.Lerp(v.y, v.w, fy1); s_Xy[2].y = s_Xy[1].y; s_Xy[3].y = s_Xy[0].y; s_Uv[0].x = Mathf.Lerp(tx0, tx1, fx0); s_Uv[1].x = s_Uv[0].x; s_Uv[2].x = Mathf.Lerp(tx0, tx1, fx1); s_Uv[3].x = s_Uv[2].x; s_Uv[0].y = Mathf.Lerp(ty0, ty1, fy0); s_Uv[1].y = Mathf.Lerp(ty0, ty1, fy1); s_Uv[2].y = s_Uv[1].y; s_Uv[3].y = s_Uv[0].y; float val = m_FillClockwise ? m_FillAmount * 4f - ((corner + m_FillOrigin) % 4) : m_FillAmount * 4f - (3 - ((corner + m_FillOrigin) % 4)); if (RadialCut(s_Xy, s_Uv, Mathf.Clamp01(val), m_FillClockwise, ((corner + 2) % 4))) { AddQuad(toFill, s_Xy, color, s_Uv); } } } } else { AddQuad(toFill, s_Xy, color, s_Uv); } } }
public override void ModifyVertices(List <UIVertex> verts) { if (!this.IsActive()) { return; } string[] lines = this.GetLines(); Vector3 pos; float letterOffset = this.spacing * (float)this.text.fontSize / 100f; float alignmentFactor = 0; int glyphIdx = 0; switch (this.text.alignment) { case TextAnchor.LowerLeft: case TextAnchor.MiddleLeft: case TextAnchor.UpperLeft: alignmentFactor = 0f; break; case TextAnchor.LowerCenter: case TextAnchor.MiddleCenter: case TextAnchor.UpperCenter: alignmentFactor = 0.5f; break; case TextAnchor.LowerRight: case TextAnchor.MiddleRight: case TextAnchor.UpperRight: alignmentFactor = 1f; break; } for (int lineIdx = 0; lineIdx < lines.Length; lineIdx++) { string line = lines[lineIdx]; float lineOffset = (line.Length - 1) * letterOffset * alignmentFactor; for (int charIdx = 0; charIdx < line.Length; charIdx++) { int idx1 = glyphIdx * 4 + 0; int idx2 = glyphIdx * 4 + 1; int idx3 = glyphIdx * 4 + 2; int idx4 = glyphIdx * 4 + 3; // Check for truncated text (doesn't generate verts for all characters) if (idx4 > verts.Count - 1) { return; } UIVertex vert1 = verts[idx1]; UIVertex vert2 = verts[idx2]; UIVertex vert3 = verts[idx3]; UIVertex vert4 = verts[idx4]; pos = Vector3.right * (letterOffset * charIdx - lineOffset); vert1.position += pos; vert2.position += pos; vert3.position += pos; vert4.position += pos; verts[idx1] = vert1; verts[idx2] = vert2; verts[idx3] = vert3; verts[idx4] = vert4; glyphIdx++; } // Offset for carriage return character that still generates verts glyphIdx++; } }
/// <summary> /// 绘制模型 /// </summary> /// <param name="toFill"></param> protected override void OnPopulateMesh(VertexHelper toFill) { // base.OnPopulateMesh(toFill); if (font == null) { return; } // We don't care if we the font Texture changes while we are doing our Update. // The end result of cachedTextGenerator will be valid for this instance. // Otherwise we can get issues like Case 619238. m_DisableFontTextureRebuiltCallback = true; Vector2 extents = rectTransform.rect.size; var settings = GetGenerationSettings(extents); cachedTextGenerator.Populate(m_OutputText, settings); Rect inputRect = rectTransform.rect; // get the text alignment anchor point for the text in local space Vector2 textAnchorPivot = GetTextAnchorPivot(alignment); Vector2 refPoint = Vector2.zero; refPoint.x = (textAnchorPivot.x == 1 ? inputRect.xMax : inputRect.xMin); refPoint.y = (textAnchorPivot.y == 0 ? inputRect.yMin : inputRect.yMax); // Determine fraction of pixel to offset text mesh. Vector2 roundingOffset = PixelAdjustPoint(refPoint) - refPoint; // Apply the offset to the vertices IList <UIVertex> verts = cachedTextGenerator.verts; float unitsPerPixel = 1 / pixelsPerUnit; //Last 4 verts are always a new line... int vertCount = verts.Count - 4; toFill.Clear(); //清楚乱码 for (int i = 0; i < m_AnimSpiteTag.Count; i++) { if (m_AnimSpiteTag[i].Length > 0) { //UGUIText不支持<quad/>标签,表现为乱码,我这里将他的uv全设置为0,清除乱码 for (int m = m_AnimSpiteTag[i][0].index * 4; m < m_AnimSpiteTag[i][0].index * 4 + 4; m++) { UIVertex tempVertex = verts[m]; tempVertex.uv0 = Vector2.zero; verts[m] = tempVertex; } } } //计算标签 其实应该计算偏移值后 再计算标签的值 算了 后面再继续改吧 // CalcQuadTag(verts); if (roundingOffset != Vector2.zero) { for (int i = 0; i < vertCount; ++i) { int tempVertsIndex = i & 3; m_TempVerts[tempVertsIndex] = verts[i]; m_TempVerts[tempVertsIndex].position *= unitsPerPixel; m_TempVerts[tempVertsIndex].position.x += roundingOffset.x; m_TempVerts[tempVertsIndex].position.y += roundingOffset.y; if (tempVertsIndex == 3) { toFill.AddUIVertexQuad(m_TempVerts); } } } else { for (int i = 0; i < vertCount; ++i) { int tempVertsIndex = i & 3; m_TempVerts[tempVertsIndex] = verts[i]; m_TempVerts[tempVertsIndex].position *= unitsPerPixel; if (tempVertsIndex == 3) { toFill.AddUIVertexQuad(m_TempVerts); } } } //计算标签 计算偏移值后 再计算标签的值 List <UIVertex> vertsTemp = new List <UIVertex>(); for (int i = 0; i < vertCount; i++) { UIVertex tempVer = new UIVertex(); toFill.PopulateUIVertex(ref tempVer, i); vertsTemp.Add(tempVer); } CalcQuadTag(vertsTemp); m_DisableFontTextureRebuiltCallback = false; //更新绘制图片信息 if (m_SGManager != null) { m_SGManager.UpdateSpriteInfor(); } //DrawSprite(); #region 处理超链接的包围盒 // 处理超链接包围框 UIVertex vert = new UIVertex(); foreach (var hrefInfo in m_HrefInfos) { hrefInfo.boxes.Clear(); if (hrefInfo.startIndex >= toFill.currentVertCount) { continue; } // 将超链接里面的文本顶点索引坐标加入到包围框 toFill.PopulateUIVertex(ref vert, hrefInfo.startIndex); var pos = vert.position; var bounds = new Bounds(pos, Vector3.zero); for (int i = hrefInfo.startIndex, m = hrefInfo.endIndex; i < m; i++) { if (i >= toFill.currentVertCount) { break; } toFill.PopulateUIVertex(ref vert, i); pos = vert.position; if (pos.x < bounds.min.x) // 换行重新添加包围框 { hrefInfo.boxes.Add(new Rect(bounds.min, bounds.size)); bounds = new Bounds(pos, Vector3.zero); } else { bounds.Encapsulate(pos); // 扩展包围框 } } hrefInfo.boxes.Add(new Rect(bounds.min, bounds.size)); } #endregion }