internal static void MakeText(TextCore.MeshInfo meshInfo, Vector2 offset, AllocMeshData meshAlloc) { int vertexCount = LimitTextVertices(meshInfo.vertexCount); int quadCount = vertexCount / 4; var mesh = meshAlloc.Allocate((uint)(quadCount * 4), (uint)(quadCount * 6)); for (int q = 0, v = 0, i = 0; q < quadCount; ++q, v += 4, i += 6) { mesh.SetNextVertex(ConvertTextVertexToUIRVertex(meshInfo, v + 0, offset)); mesh.SetNextVertex(ConvertTextVertexToUIRVertex(meshInfo, v + 1, offset)); mesh.SetNextVertex(ConvertTextVertexToUIRVertex(meshInfo, v + 2, offset)); mesh.SetNextVertex(ConvertTextVertexToUIRVertex(meshInfo, v + 3, offset)); mesh.SetNextIndex((UInt16)(v + 0)); mesh.SetNextIndex((UInt16)(v + 1)); mesh.SetNextIndex((UInt16)(v + 2)); mesh.SetNextIndex((UInt16)(v + 2)); mesh.SetNextIndex((UInt16)(v + 3)); mesh.SetNextIndex((UInt16)(v + 0)); } }
internal static void MakeSolidRect(MeshGenerationContextUtils.RectangleParams rectParams, float posZ, AllocMeshData meshAlloc) { if (!rectParams.HasRadius(Tessellation.kEpsilon)) { MakeQuad(rectParams.rect, Rect.zero, rectParams.color, posZ, meshAlloc); } else { Tessellation.TessellateRect(rectParams, posZ, meshAlloc, false); } }
internal static void MakeVectorGraphicsStretchBackground(Vertex[] svgVertices, UInt16[] svgIndices, float svgWidth, float svgHeight, Rect targetRect, Rect sourceUV, ScaleMode scaleMode, Color tint, int settingIndexOffset, AllocMeshData meshAlloc, out int finalVertexCount, out int finalIndexCount) { // Determine position offset and scale according to scale mode Vector2 svgSubRectSize = new Vector2(svgWidth * sourceUV.width, svgHeight * sourceUV.height); Vector2 svgSubRectOffset = new Vector2(sourceUV.xMin * svgWidth, sourceUV.yMin * svgHeight); Rect svgSubRect = new Rect(svgSubRectOffset, svgSubRectSize); bool isSubRect = sourceUV.xMin != 0 || sourceUV.yMin != 0 || sourceUV.width != 1 || sourceUV.height != 1; float srcAspect = svgSubRectSize.x / svgSubRectSize.y; float destAspect = targetRect.width / targetRect.height; Vector2 posOffset, posScale; switch (scaleMode) { case ScaleMode.StretchToFill: posOffset = new Vector2(0, 0); posScale.x = targetRect.width / svgSubRectSize.x; posScale.y = targetRect.height / svgSubRectSize.y; break; case ScaleMode.ScaleAndCrop: // ScaleAndCrop keeps the content centered to follow the same behavior as textures posOffset = new Vector2(0, 0); if (destAspect > srcAspect) { // Fill on x and crop top/bottom sides posScale.x = posScale.y = targetRect.width / svgSubRectSize.x; var height = targetRect.height / posScale.y; float offset = svgSubRect.height / 2.0f - height / 2.0f; posOffset.y -= offset * posScale.y; svgSubRect.y += offset; svgSubRect.height = height; isSubRect = true; } else if (destAspect < srcAspect) { // Fill on y and crop left/right sides posScale.x = posScale.y = targetRect.height / svgSubRectSize.y; var width = targetRect.width / posScale.x; float offset = svgSubRect.width / 2.0f - width / 2.0f; posOffset.x -= offset * posScale.x; svgSubRect.x += offset; svgSubRect.width = width; isSubRect = true; } else { posScale.x = posScale.y = targetRect.width / svgSubRectSize.x; // Just scale, cropping is not involved } break; case ScaleMode.ScaleToFit: if (destAspect > srcAspect) { // Fill on y and offset on x posScale.x = posScale.y = targetRect.height / svgSubRectSize.y; posOffset.x = (targetRect.width - svgSubRectSize.x * posScale.x) * 0.5f; posOffset.y = 0; } else { // Fill on x and offset on y posScale.x = posScale.y = targetRect.width / svgSubRectSize.x; posOffset.x = 0; posOffset.y = (targetRect.height - svgSubRectSize.y * posScale.y) * 0.5f; } break; default: throw new NotImplementedException(); } s_VectorGraphicsStretch.Begin(); posOffset -= svgSubRectOffset * posScale; int newVertexCount = svgVertices.Length; int newIndexCount = svgIndices.Length; ClipCounts cc = new ClipCounts(); Vector4 svgSubRectMinMax = Vector4.zero; if (isSubRect) { if (svgSubRect.width <= 0 || svgSubRect.height <= 0) { finalVertexCount = finalIndexCount = 0; s_VectorGraphicsStretch.End(); return; // Totally clipped } svgSubRectMinMax = new Vector4(svgSubRect.xMin, svgSubRect.yMin, svgSubRect.xMax, svgSubRect.yMax); cc = UpperBoundApproximateRectClippingResults(svgVertices, svgIndices, svgSubRectMinMax); // We never kill vertices, just triangles.. so the clipper will only cause growth in the vertex count newVertexCount += cc.clippedTriangles * 6; // 6 new vertices per clipped triangle newIndexCount += cc.addedTriangles * 3; newIndexCount -= cc.degenerateTriangles * 3; // We will not add the indices of degenerate triangles, so discount them } var mwd = meshAlloc.alloc((uint)newVertexCount, (uint)newIndexCount, ref meshAlloc); // Copy indices straight. If clipping is involved, perform clipping. This will fill all the indices // as well as register some new vertices at the end of the original set of vertices if (isSubRect) { RectClip(svgVertices, svgIndices, svgSubRectMinMax, mwd, cc, ref newVertexCount); } else { mwd.SetAllIndices(svgIndices); } // Transform all original vertices, vertices generated by clipping will use those directly var uvRegion = mwd.uvRegion; int vertsCount = svgVertices.Length; for (int i = 0; i < vertsCount; i++) { var v = svgVertices[i]; v.position.x = v.position.x * posScale.x + posOffset.x; v.position.y = v.position.y * posScale.y + posOffset.y; v.uv.x = v.uv.x * uvRegion.width + uvRegion.xMin; v.uv.y = v.uv.y * uvRegion.height + uvRegion.yMin; v.tint *= tint; uint settingIndex = (uint)(((v.opacityPageSVGSettingIndex.b << 8) | v.opacityPageSVGSettingIndex.a) + settingIndexOffset); v.opacityPageSVGSettingIndex.b = (byte)(settingIndex >> 8); v.opacityPageSVGSettingIndex.a = (byte)settingIndex; mwd.SetNextVertex(v); } // Transform newely generated vertices as well (if any) for (int i = vertsCount; i < newVertexCount; i++) { var v = mwd.m_Vertices[i]; v.position.x = v.position.x * posScale.x + posOffset.x; v.position.y = v.position.y * posScale.y + posOffset.y; v.uv.x = v.uv.x * uvRegion.width + uvRegion.xMin; v.uv.y = v.uv.y * uvRegion.height + uvRegion.yMin; v.tint *= tint; uint settingIndex = (uint)(((v.opacityPageSVGSettingIndex.b << 8) | v.opacityPageSVGSettingIndex.a) + settingIndexOffset); v.opacityPageSVGSettingIndex.b = (byte)(settingIndex >> 8); v.opacityPageSVGSettingIndex.a = (byte)settingIndex; mwd.m_Vertices[i] = v; } finalVertexCount = mwd.vertexCount; finalIndexCount = mwd.indexCount; s_VectorGraphicsStretch.End(); }
internal static void MakeBorder(MeshGenerationContextUtils.BorderParams borderParams, float posZ, AllocMeshData meshAlloc) { Tessellation.TessellateBorder(borderParams, posZ, meshAlloc); }
internal static void MakeVectorGraphics(MeshGenerationContextUtils.RectangleParams rectParams, int settingIndexOffset, AllocMeshData meshAlloc, out int finalVertexCount, out int finalIndexCount) { var vi = rectParams.vectorImage; Debug.Assert(vi != null); finalVertexCount = 0; finalIndexCount = 0; // Convert the VectorImage's serializable vertices to Vertex instances int vertexCount = vi.vertices.Length; var vertices = new Vertex[vertexCount]; for (int i = 0; i < vertexCount; ++i) { var v = vi.vertices[i]; vertices[i] = new Vertex() { position = v.position, tint = v.tint, uv = v.uv, opacityPageSVGSettingIndex = new Color32(0, 0, (byte)(v.settingIndex >> 8), (byte)v.settingIndex) }; } if (rectParams.leftSlice <= Mathf.Epsilon && rectParams.topSlice <= Mathf.Epsilon && rectParams.rightSlice <= Mathf.Epsilon && rectParams.bottomSlice <= Mathf.Epsilon) { MeshBuilder.MakeVectorGraphicsStretchBackground(vertices, vi.indices, vi.size.x, vi.size.y, rectParams.rect, rectParams.uv, rectParams.scaleMode, rectParams.color, settingIndexOffset, meshAlloc, out finalVertexCount, out finalIndexCount); } else { var sliceLTRB = new Vector4(rectParams.leftSlice, rectParams.topSlice, rectParams.rightSlice, rectParams.bottomSlice); MeshBuilder.MakeVectorGraphics9SliceBackground(vertices, vi.indices, vi.size.x, vi.size.y, rectParams.rect, sliceLTRB, true, rectParams.color, settingIndexOffset, meshAlloc); } }
internal static void MakeSlicedQuad(ref MeshGenerationContextUtils.RectangleParams rectParams, float posZ, AllocMeshData meshAlloc) { var mesh = meshAlloc.Allocate(16, 9 * 6); float pixelsPerPoint = 1; var texture2D = rectParams.texture as Texture2D; if (texture2D != null) { pixelsPerPoint = texture2D.pixelsPerPoint; } float texWidth = rectParams.texture.width; float texHeight = rectParams.texture.height; float uConversion = pixelsPerPoint / texWidth; float vConversion = pixelsPerPoint / texHeight; float leftSlice = Mathf.Max(0.0f, rectParams.leftSlice); float rightSlice = Mathf.Max(0.0f, rectParams.rightSlice); float bottomSlice = Mathf.Max(0.0f, rectParams.bottomSlice); float topSlice = Mathf.Max(0.0f, rectParams.topSlice); // Clamp UVs in the [0,1] range float uvLeftSlice = Mathf.Clamp(leftSlice * uConversion, 0.0f, 1.0f); float uvRightSlice = Mathf.Clamp(rightSlice * uConversion, 0.0f, 1.0f); float uvBottomSlice = Mathf.Clamp(bottomSlice * vConversion, 0.0f, 1.0f); float uvTopslice = Mathf.Clamp(topSlice * vConversion, 0.0f, 1.0f); k_TexCoordSlicesX[0] = rectParams.uv.min.x; k_TexCoordSlicesX[1] = rectParams.uv.min.x + uvLeftSlice; k_TexCoordSlicesX[2] = rectParams.uv.max.x - uvRightSlice; k_TexCoordSlicesX[3] = rectParams.uv.max.x; k_TexCoordSlicesY[0] = rectParams.uv.max.y; k_TexCoordSlicesY[1] = rectParams.uv.max.y - uvBottomSlice; k_TexCoordSlicesY[2] = rectParams.uv.min.y + uvTopslice; k_TexCoordSlicesY[3] = rectParams.uv.min.y; var uvRegion = mesh.uvRegion; for (int i = 0; i < 4; i++) { k_TexCoordSlicesX[i] = k_TexCoordSlicesX[i] * uvRegion.width + uvRegion.xMin; k_TexCoordSlicesY[i] = (rectParams.uv.min.y + rectParams.uv.max.y - k_TexCoordSlicesY[i]) * uvRegion.height + uvRegion.yMin; } // Prevent overlapping slices float sliceWidth = (leftSlice + rightSlice); if (sliceWidth > rectParams.rect.width) { float rescale = rectParams.rect.width / sliceWidth; leftSlice *= rescale; rightSlice *= rescale; } float sliceHeight = (bottomSlice + topSlice); if (sliceHeight > rectParams.rect.height) { float rescale = rectParams.rect.height / sliceHeight; bottomSlice *= rescale; topSlice *= rescale; } k_PositionSlicesX[0] = rectParams.rect.x; k_PositionSlicesX[1] = rectParams.rect.x + leftSlice; k_PositionSlicesX[2] = rectParams.rect.xMax - rightSlice; k_PositionSlicesX[3] = rectParams.rect.xMax; k_PositionSlicesY[0] = rectParams.rect.yMax; k_PositionSlicesY[1] = rectParams.rect.yMax - bottomSlice; k_PositionSlicesY[2] = rectParams.rect.y + topSlice; k_PositionSlicesY[3] = rectParams.rect.y; for (int i = 0; i < 16; ++i) { int x = i % 4; int y = i / 4; mesh.SetNextVertex(new Vertex() { position = new Vector3(k_PositionSlicesX[x], k_PositionSlicesY[y], posZ), uv = new Vector2(k_TexCoordSlicesX[x], k_TexCoordSlicesY[y]), tint = rectParams.color }); } mesh.SetAllIndices(slicedQuadIndices); }
private static void MakeQuad(Rect rcPosition, Rect rcTexCoord, Color color, float posZ, AllocMeshData meshAlloc) { var mesh = meshAlloc.Allocate(4, 6); float x0 = rcPosition.x; float x3 = rcPosition.xMax; float y0 = rcPosition.yMax; float y3 = rcPosition.y; var uvRegion = mesh.uvRegion; float u0 = rcTexCoord.x * uvRegion.width + uvRegion.xMin; float u3 = rcTexCoord.xMax * uvRegion.width + uvRegion.xMin; float v0 = rcTexCoord.y * uvRegion.height + uvRegion.yMin; float v3 = rcTexCoord.yMax * uvRegion.height + uvRegion.yMin; mesh.SetNextVertex(new Vertex() { position = new Vector3(x0, y0, posZ), tint = color, uv = new Vector2(u0, v0) }); mesh.SetNextVertex(new Vertex() { position = new Vector3(x3, y0, posZ), tint = color, uv = new Vector2(u3, v0) }); mesh.SetNextVertex(new Vertex() { position = new Vector3(x0, y3, posZ), tint = color, uv = new Vector2(u0, v3) }); mesh.SetNextVertex(new Vertex() { position = new Vector3(x3, y3, posZ), tint = color, uv = new Vector2(u3, v3) }); mesh.SetNextIndex(0); mesh.SetNextIndex(1); mesh.SetNextIndex(2); mesh.SetNextIndex(1); mesh.SetNextIndex(3); mesh.SetNextIndex(2); }
internal static void MakeRect(RectStylePainterParameters rectParams, float posZ, AllocMeshData meshAlloc) { if (IsSimpleRect(rectParams.border)) { MakeQuad(rectParams.rect, Rect.zero, rectParams.color, posZ, VertexFlags.IsSolid, meshAlloc); } else { UIRTessellation.TessellateBorderedRect(rectParams.rect, Rect.zero, rectParams.color, rectParams.border, posZ, VertexFlags.IsSolid, meshAlloc); } }
internal static void MakeVectorGraphics(MeshGenerationContextUtils.RectangleParams rectParams, int settingIndexOffset, AllocMeshData meshAlloc, out int finalVertexCount, out int finalIndexCount) { var vi = rectParams.vectorImage; Debug.Assert(vi != null); finalVertexCount = 0; finalIndexCount = 0; if (rectParams.leftSlice <= Mathf.Epsilon && rectParams.topSlice <= Mathf.Epsilon && rectParams.rightSlice <= Mathf.Epsilon && rectParams.bottomSlice <= Mathf.Epsilon) { MeshBuilder.MakeVectorGraphicsStretchBackground(vi.vertices, vi.indices, vi.size.x, vi.size.y, rectParams.rect, rectParams.uv, rectParams.scaleMode, rectParams.color, settingIndexOffset, meshAlloc, out finalVertexCount, out finalIndexCount); } else { var sliceLTRB = new Vector4(rectParams.leftSlice, rectParams.topSlice, rectParams.rightSlice, rectParams.bottomSlice); MeshBuilder.MakeVectorGraphics9SliceBackground(vi.vertices, vi.indices, vi.size.x, vi.size.y, rectParams.rect, sliceLTRB, true, rectParams.color, settingIndexOffset, meshAlloc); } }
private static void MakeSlicedQuad(ref MeshGenerationContextUtils.RectangleParams rectParams, float posZ, VertexFlags vertexFlags, AllocMeshData meshAlloc) { var mesh = meshAlloc(16, 9 * 6); float pixelsPerPoint = 1; var texture2D = rectParams.texture as Texture2D; if (texture2D != null) { pixelsPerPoint = texture2D.pixelsPerPoint; } // The following offsets are in texels (not normalized). float uvSliceLeft = rectParams.leftSlice * pixelsPerPoint; float uvSliceTop = rectParams.topSlice * pixelsPerPoint; float uvSliceRight = rectParams.rightSlice * pixelsPerPoint; float uvSliceBottom = rectParams.bottomSlice * pixelsPerPoint; // When an atlas is used, relative coordinates must not be used. bool isAtlassed = vertexFlags == VertexFlags.IsAtlasTexturedPoint || vertexFlags == VertexFlags.IsAtlasTexturedBilinear; float uConversion = isAtlassed ? 1 : 1f / rectParams.texture.width; float vConversion = isAtlassed ? 1 : 1f / rectParams.texture.height; k_TexCoordSlicesX[0] = rectParams.uv.min.x; k_TexCoordSlicesX[1] = rectParams.uv.min.x + uvSliceLeft * uConversion; k_TexCoordSlicesX[2] = rectParams.uv.max.x - uvSliceRight * uConversion; k_TexCoordSlicesX[3] = rectParams.uv.max.x; k_TexCoordSlicesY[0] = rectParams.uv.max.y; k_TexCoordSlicesY[1] = rectParams.uv.max.y - uvSliceBottom * vConversion; k_TexCoordSlicesY[2] = rectParams.uv.min.y + uvSliceTop * vConversion; k_TexCoordSlicesY[3] = rectParams.uv.min.y; k_PositionSlicesX[0] = rectParams.rect.x; k_PositionSlicesX[1] = rectParams.rect.x + rectParams.leftSlice; k_PositionSlicesX[2] = rectParams.rect.xMax - rectParams.rightSlice; k_PositionSlicesX[3] = rectParams.rect.xMax; k_PositionSlicesY[0] = rectParams.rect.yMax; k_PositionSlicesY[1] = rectParams.rect.yMax - rectParams.bottomSlice; k_PositionSlicesY[2] = rectParams.rect.y + rectParams.topSlice; k_PositionSlicesY[3] = rectParams.rect.y; for (int i = 0; i < 16; ++i) { int x = i % 4; int y = i / 4; mesh.vertices[i] = new Vertex() { position = new Vector3(k_PositionSlicesX[x], k_PositionSlicesY[y], posZ), uv = new Vector2(k_TexCoordSlicesX[x], rectParams.uv.min.y + rectParams.uv.max.y - k_TexCoordSlicesY[y]), tint = rectParams.color, flags = (float)vertexFlags }; } mesh.indices.CopyFrom(slicedQuadIndices); }
private static void MakeQuad(Rect rcPosition, Rect rcTexCoord, Color color, float posZ, VertexFlags vertexFlags, AllocMeshData meshAlloc) { float x0 = rcPosition.x; float x3 = rcPosition.xMax; float y0 = rcPosition.yMax; float y3 = rcPosition.y; float u0 = rcTexCoord.x; float u3 = rcTexCoord.xMax; float v0 = rcTexCoord.y; float v3 = rcTexCoord.yMax; var mesh = meshAlloc(4, 6); mesh.vertices[0] = new Vertex() { position = new Vector3(x0, y0, posZ), tint = color, uv = new Vector2(u0, v0), flags = (float)vertexFlags }; mesh.vertices[1] = new Vertex() { position = new Vector3(x3, y0, posZ), tint = color, uv = new Vector2(u3, v0), flags = (float)vertexFlags }; mesh.vertices[2] = new Vertex() { position = new Vector3(x0, y3, posZ), tint = color, uv = new Vector2(u0, v3), flags = (float)vertexFlags }; mesh.vertices[3] = new Vertex() { position = new Vector3(x3, y3, posZ), tint = color, uv = new Vector2(u3, v3), flags = (float)vertexFlags }; mesh.indices[0] = 0; mesh.indices[1] = 1; mesh.indices[2] = 2; mesh.indices[3] = 1; mesh.indices[4] = 3; mesh.indices[5] = 2; }
internal static void MakeText(NativeArray <TextVertex> uiVertices, Vector2 offset, AllocMeshData meshAlloc) { int vertexCount = LimitTextVertices(uiVertices.Length); int quadCount = vertexCount / 4; var mesh = meshAlloc.Allocate((uint)(quadCount * 4), (uint)(quadCount * 6)); for (int q = 0, v = 0; q < quadCount; ++q, v += 4) { mesh.SetNextVertex(ConvertTextVertexToUIRVertex(uiVertices[v + 0], offset)); mesh.SetNextVertex(ConvertTextVertexToUIRVertex(uiVertices[v + 1], offset)); mesh.SetNextVertex(ConvertTextVertexToUIRVertex(uiVertices[v + 2], offset)); mesh.SetNextVertex(ConvertTextVertexToUIRVertex(uiVertices[v + 3], offset)); mesh.SetNextIndex((UInt16)(v + 0)); mesh.SetNextIndex((UInt16)(v + 1)); mesh.SetNextIndex((UInt16)(v + 2)); mesh.SetNextIndex((UInt16)(v + 2)); mesh.SetNextIndex((UInt16)(v + 3)); mesh.SetNextIndex((UInt16)(v + 0)); } }
private static void MakeSlicedQuad(ref MeshGenerationContextUtils.RectangleParams rectParams, float posZ, AllocMeshData meshAlloc) { var mesh = meshAlloc.Allocate(16, 9 * 6); float pixelsPerPoint = 1; var texture2D = rectParams.texture as Texture2D; if (texture2D != null) { pixelsPerPoint = texture2D.pixelsPerPoint; } float uConversion = pixelsPerPoint / rectParams.texture.width; float vConversion = pixelsPerPoint / rectParams.texture.height; k_TexCoordSlicesX[0] = rectParams.uv.min.x; k_TexCoordSlicesX[1] = rectParams.uv.min.x + rectParams.leftSlice * uConversion; k_TexCoordSlicesX[2] = rectParams.uv.max.x - rectParams.rightSlice * uConversion; k_TexCoordSlicesX[3] = rectParams.uv.max.x; k_TexCoordSlicesY[0] = rectParams.uv.max.y; k_TexCoordSlicesY[1] = rectParams.uv.max.y - rectParams.bottomSlice * vConversion; k_TexCoordSlicesY[2] = rectParams.uv.min.y + rectParams.topSlice * vConversion; k_TexCoordSlicesY[3] = rectParams.uv.min.y; var uvRegion = mesh.uvRegion; for (int i = 0; i < 4; i++) { k_TexCoordSlicesX[i] = k_TexCoordSlicesX[i] * uvRegion.width + uvRegion.xMin; k_TexCoordSlicesY[i] = (rectParams.uv.min.y + rectParams.uv.max.y - k_TexCoordSlicesY[i]) * uvRegion.height + uvRegion.yMin; } k_PositionSlicesX[0] = rectParams.rect.x; k_PositionSlicesX[1] = rectParams.rect.x + rectParams.leftSlice; k_PositionSlicesX[2] = rectParams.rect.xMax - rectParams.rightSlice; k_PositionSlicesX[3] = rectParams.rect.xMax; k_PositionSlicesY[0] = rectParams.rect.yMax; k_PositionSlicesY[1] = rectParams.rect.yMax - rectParams.bottomSlice; k_PositionSlicesY[2] = rectParams.rect.y + rectParams.topSlice; k_PositionSlicesY[3] = rectParams.rect.y; for (int i = 0; i < 16; ++i) { int x = i % 4; int y = i / 4; mesh.SetNextVertex(new Vertex() { position = new Vector3(k_PositionSlicesX[x], k_PositionSlicesY[y], posZ), uv = new Vector2(k_TexCoordSlicesX[x], k_TexCoordSlicesY[y]), tint = rectParams.color }); } mesh.SetAllIndices(slicedQuadIndices); }
internal static void MakeTexture(TextureStylePainterParameters textureParams, float posZ, VertexFlags vertexFlags, AllocMeshData meshAlloc) { if (textureParams.sliceLeft <= Mathf.Epsilon && textureParams.sliceTop <= Mathf.Epsilon && textureParams.sliceRight <= Mathf.Epsilon && textureParams.sliceBottom <= Mathf.Epsilon) { if (IsSimpleRect(textureParams.border)) { MakeQuad(textureParams.rect, textureParams.uv, textureParams.color, posZ, vertexFlags, meshAlloc); } else { UIRTessellation.TessellateBorderedRect(textureParams.rect, textureParams.uv, textureParams.color, textureParams.border, posZ, vertexFlags, meshAlloc); } } else { MakeSlicedQuad(textureParams, posZ, vertexFlags, meshAlloc); } }
internal static void MakeTexturedRect(MeshGenerationContextUtils.RectangleParams rectParams, float posZ, AllocMeshData meshAlloc) { if (rectParams.leftSlice <= Mathf.Epsilon && rectParams.topSlice <= Mathf.Epsilon && rectParams.rightSlice <= Mathf.Epsilon && rectParams.bottomSlice <= Mathf.Epsilon) { if (!rectParams.HasRadius(Tessellation.kEpsilon)) { MakeQuad(rectParams.rect, rectParams.uv, rectParams.color, posZ, meshAlloc); } else { Tessellation.TessellateRect(rectParams, posZ, meshAlloc, true); } } else if (rectParams.texture == null) { MakeQuad(rectParams.rect, rectParams.uv, rectParams.color, posZ, meshAlloc); } else { MakeSlicedQuad(ref rectParams, posZ, meshAlloc); } }
internal static void MakeText(NativeArray <TextVertex> uiVertices, Vector2 offset, AllocMeshData meshAlloc) { int quadCount = uiVertices.Length / 4; if (quadCount > k_MaxTextQuadCount) { Debug.LogError("MakeTextMeshHandle: text is too long and generates too many vertices"); quadCount = k_MaxTextQuadCount; } var mesh = meshAlloc.Allocate((uint)(quadCount * 4), (uint)(quadCount * 6)); for (int q = 0, v = 0; q < quadCount; ++q, v += 4) { mesh.SetNextVertex(ConvertTextVertexToUIRVertex(uiVertices[v + 0], offset)); mesh.SetNextVertex(ConvertTextVertexToUIRVertex(uiVertices[v + 1], offset)); mesh.SetNextVertex(ConvertTextVertexToUIRVertex(uiVertices[v + 2], offset)); mesh.SetNextVertex(ConvertTextVertexToUIRVertex(uiVertices[v + 3], offset)); mesh.SetNextIndex((UInt16)(v + 0)); mesh.SetNextIndex((UInt16)(v + 2)); mesh.SetNextIndex((UInt16)(v + 1)); mesh.SetNextIndex((UInt16)(v + 2)); mesh.SetNextIndex((UInt16)(v + 0)); mesh.SetNextIndex((UInt16)(v + 3)); } }
private static void MakeVectorGraphics9SliceBackground(Vertex[] svgVertices, UInt16[] svgIndices, float svgWidth, float svgHeight, Rect targetRect, Vector4 sliceLTRB, bool stretch, Color tint, int settingIndexOffset, AllocMeshData meshAlloc) { var mwd = meshAlloc.alloc((uint)svgVertices.Length, (uint)svgIndices.Length, ref meshAlloc); mwd.SetAllIndices(svgIndices); if (!stretch) { throw new NotImplementedException("Support for repeating 9-slices is not done yet"); } s_VectorGraphics9Slice.Begin(); var uvRegion = mwd.uvRegion; int vertsCount = svgVertices.Length; Vector2 sliceInvSize = new Vector2(1.0f / (svgWidth - sliceLTRB.z - sliceLTRB.x), 1.0f / (svgHeight - sliceLTRB.w - sliceLTRB.y)); Vector2 stretchAmount = new Vector2(targetRect.width - svgWidth, targetRect.height - svgHeight); for (int i = 0; i < vertsCount; i++) { var v = svgVertices[i]; Vector2 skinWeight; skinWeight.x = Mathf.Clamp01((v.position.x - sliceLTRB.x) * sliceInvSize.x); skinWeight.y = Mathf.Clamp01((v.position.y - sliceLTRB.y) * sliceInvSize.y); v.position.x += skinWeight.x * stretchAmount.x; v.position.y += skinWeight.y * stretchAmount.y; v.uv.x = v.uv.x * uvRegion.width + uvRegion.xMin; v.uv.y = v.uv.y * uvRegion.height + uvRegion.yMin; v.tint *= tint; uint settingIndex = (uint)(((v.opacityPageSVGSettingIndex.b << 8) | v.opacityPageSVGSettingIndex.a) + settingIndexOffset); v.opacityPageSVGSettingIndex.b = (byte)(settingIndex >> 8); v.opacityPageSVGSettingIndex.a = (byte)settingIndex; mwd.SetNextVertex(v); } s_VectorGraphics9Slice.End(); }
private static void MakeSlicedQuad(TextureStylePainterParameters texParams, float posZ, VertexFlags vertexFlags, AllocMeshData meshAlloc) { var texture = texParams.texture; if (texture == null) { // Early exit without slicing. MakeQuad(texParams.rect, texParams.uv, texParams.color, posZ, vertexFlags, meshAlloc); return; } var mesh = meshAlloc(16, 9 * 6); float pixelsPerPoint = 1; var texture2D = texParams.texture as Texture2D; if (texture2D != null) { pixelsPerPoint = texture2D.pixelsPerPoint; } // The following offsets are in texels (not normalized). float uvSliceLeft = texParams.sliceLeft * pixelsPerPoint; float uvSliceTop = texParams.sliceTop * pixelsPerPoint; float uvSliceRight = texParams.sliceRight * pixelsPerPoint; float uvSliceBottom = texParams.sliceBottom * pixelsPerPoint; // When an atlas is used, relative coordinates must not be used. bool isAtlassed = vertexFlags == VertexFlags.IsTextured; float uConversion = isAtlassed ? 1 : 1f / texture.width; float vConversion = isAtlassed ? 1 : 1f / texture.height; k_TexCoordSlicesX[0] = texParams.uv.min.x; k_TexCoordSlicesX[1] = texParams.uv.min.x + uvSliceLeft * uConversion; k_TexCoordSlicesX[2] = texParams.uv.max.x - uvSliceRight * uConversion; k_TexCoordSlicesX[3] = texParams.uv.max.x; k_TexCoordSlicesY[0] = texParams.uv.max.y; k_TexCoordSlicesY[1] = texParams.uv.max.y - uvSliceBottom * vConversion; k_TexCoordSlicesY[2] = texParams.uv.min.y + uvSliceTop * vConversion; k_TexCoordSlicesY[3] = texParams.uv.min.y; k_PositionSlicesX[0] = texParams.rect.x; k_PositionSlicesX[1] = texParams.rect.x + texParams.sliceLeft; k_PositionSlicesX[2] = texParams.rect.xMax - texParams.sliceRight; k_PositionSlicesX[3] = texParams.rect.xMax; k_PositionSlicesY[0] = texParams.rect.yMax; k_PositionSlicesY[1] = texParams.rect.yMax - texParams.sliceBottom; k_PositionSlicesY[2] = texParams.rect.y + texParams.sliceTop; k_PositionSlicesY[3] = texParams.rect.y; for (int i = 0; i < 16; ++i) { int x = i % 4; int y = i / 4; mesh.vertices[i] = new Vertex() { position = new Vector3(k_PositionSlicesX[x], k_PositionSlicesY[y], posZ), uv = new Vector2(k_TexCoordSlicesX[x], texParams.uv.min.y + texParams.uv.max.y - k_TexCoordSlicesY[y]), tint = texParams.color, flags = (float)vertexFlags }; } mesh.indices.CopyFrom(slicedQuadIndices); }