【工作筆記】U3D 新手引導高亮顯示某一區域,新增圓角高亮區

在一張圖裏摳個洞出來,可以仿照Image的Sliced模式來做

public class ImageWithHole : Image
{
	public Vector2 Center = Vector2.zero;
	public float Height = 200;
	public float Width = 100;

	static readonly Vector2[] s_VertScratch = new Vector2[4];
	static readonly Vector2[] s_UVScratch = new Vector2[4];

	protected override void OnPopulateMesh(VertexHelper toFill)
	{
		Vector4 outer, inner, padding;
		if (sprite != null)
		{
			outer = UnityEngine.Sprites.DataUtility.GetOuterUV(sprite);
			inner = UnityEngine.Sprites.DataUtility.GetInnerUV(sprite);
			padding = UnityEngine.Sprites.DataUtility.GetPadding(sprite);
		}
		else
		{
			outer = Vector4.zero;
			inner = Vector4.zero;
			padding = Vector4.zero;
		}

		Rect rect = GetPixelAdjustedRect();
		padding = padding / pixelsPerUnit;

		s_VertScratch[0] = new Vector2(padding.x, padding.y);
		s_VertScratch[3] = new Vector2(rect.width - padding.z, rect.height - padding.w);
		s_VertScratch[0].x += rect.x;
		s_VertScratch[0].y += rect.y;
		s_VertScratch[3].x += rect.x;
		s_VertScratch[3].y += rect.y;

		s_VertScratch[1].x = Center.x - Width / 2;
		s_VertScratch[1].y = Center.y - Height / 2;
		s_VertScratch[2].x = Center.x + Width / 2;
		s_VertScratch[2].y = Center.y + Height / 2;

		s_UVScratch[0] = new Vector2(outer.x, outer.y);
		s_UVScratch[1] = new Vector2(inner.x, inner.y);
		s_UVScratch[2] = new Vector2(inner.z, inner.w);
		s_UVScratch[3] = new Vector2(outer.z, outer.w);
		toFill.Clear();
		for (int x = 0; x < 3; ++x)
		{
			int x2 = x + 1;
			for (int y = 0; y < 3; ++y)
			{
				if (x == 1 && y == 1)
					continue;
				int y2 = y + 1;
				AddQuad(toFill,
					new Vector2(s_VertScratch[x].x, s_VertScratch[y].y),
					new Vector2(s_VertScratch[x2].x, s_VertScratch[y2].y),
					color,
					new Vector2(s_UVScratch[x].x, s_UVScratch[y].y),
					new Vector2(s_UVScratch[x2].x, s_UVScratch[y2].y));
			}
		}
	}

	private Vector4 GetAdjustedBorders(Vector4 border, Rect adjustedRect)
	{
		Rect originalRect = rectTransform.rect;

		for (int axis = 0; axis <= 1; axis++)
		{
			float borderScaleRatio;
			if (originalRect.size[axis] != 0)
			{
				borderScaleRatio = adjustedRect.size[axis] / originalRect.size[axis];
				border[axis] *= borderScaleRatio;
				border[axis + 2] *= borderScaleRatio;
			}
			float combinedBorders = border[axis] + border[axis + 2];
			if (adjustedRect.size[axis] < combinedBorders && combinedBorders != 0)
			{
				borderScaleRatio = adjustedRect.size[axis] / combinedBorders;
				border[axis] *= borderScaleRatio;
				border[axis + 2] *= borderScaleRatio;
			}
		}
		return border;
	}

	static void AddQuad(VertexHelper vertexHelper, Vector2 posMin, Vector2 posMax, Color32 color, Vector2 uvMin, Vector2 uvMax)
	{
		int startIndex = vertexHelper.currentVertCount;
		vertexHelper.AddVert(new Vector3(posMin.x, posMin.y, 0), color, new Vector2(uvMin.x, uvMin.y));
		vertexHelper.AddVert(new Vector3(posMin.x, posMax.y, 0), color, new Vector2(uvMin.x, uvMax.y));
		vertexHelper.AddVert(new Vector3(posMax.x, posMax.y, 0), color, new Vector2(uvMax.x, uvMax.y));
		vertexHelper.AddVert(new Vector3(posMax.x, posMin.y, 0), color, new Vector2(uvMax.x, uvMin.y));

		vertexHelper.AddTriangle(startIndex, startIndex + 1, startIndex + 2);
		vertexHelper.AddTriangle(startIndex + 2, startIndex + 3, startIndex);
	}
}

上個效果圖:

 

以上效果只摳了直角四邊形,顯然活潑跳躍的策劃很不滿足,於是要求我做個能圓角的,這樣可以契合圓角UI,於是就有了以下代碼:

public float Radius = 0;
[Range(1, 20)]
public int TriangleNum = 0;

private void RoundRect(VertexHelper vh)
{
	var color32 = color;
	Vector4 v = new Vector4(
		-Width / 2,
		-Height / 2,
		Width / 2,
		Height / 2
	);
	Vector4 uv = overrideSprite != null ? UnityEngine.Sprites.DataUtility.GetOuterUV(overrideSprite) : Vector4.zero;
	float tw = v.z - v.x;
	float th = v.w - v.y;
	float uvScaleX = (uv.z - uv.x) / tw;
	float uvScaleY = (uv.w - uv.y) / th;
	float uvCenterX = (uv.x + uv.z) * 0.5f;
	float uvCenterY = (uv.y + uv.w) * 0.5f;
	//對radius的值做限制,必須在0-較小的邊的1/2的範圍內
	float radius = Radius;
	if (radius > (v.z - v.x) / 2)
		radius = (v.z - v.x) / 2;
	if (radius > (v.w - v.y) / 2)
		radius = (v.w - v.y) / 2;
	if (radius < 0)
		radius = 0;

	float pos0 = 0;
	float pos1 = 0;

	//開始構造四個角
	List<Vector2> vCenterList = new List<Vector2>();
	List<int> vCenterVertList = new List<int>();

	//右上角的圓心
	pos0 = v.z - radius + Center.x;
	pos1 = v.w - radius + Center.y;
	vCenterList.Add(new Vector2(pos0, pos1));
	vCenterVertList.Add(25);

	//左上角的圓心
	pos0 = v.x + radius + Center.x;
	pos1 = v.w - radius + Center.y;
	vCenterList.Add(new Vector2(pos0, pos1));
	vCenterVertList.Add(6);

	//左下角的圓心
	//左上角的圓心
	pos0 = v.x + radius + Center.x;
	pos1 = v.y + radius + Center.y;
	vCenterList.Add(new Vector2(pos0, pos1));
	vCenterVertList.Add(2);

	//右下角的圓心
	pos0 = v.z - radius + Center.x;
	pos1 = v.y + radius + Center.y;
	vCenterList.Add(new Vector2(pos0, pos1));
	vCenterVertList.Add(14);

	//每個三角形的頂角
	float degreeDelta = (float)(Mathf.PI / 2 / TriangleNum);
	//當前的角度
	float curDegree = 0;

	for (int i = 0; i < vCenterVertList.Count; i++)
	{
		int preVertNum = vh.currentVertCount;
		for (int j = 0; j <= TriangleNum; j++)
		{
			float cosA = Mathf.Cos(curDegree);
			float sinA = Mathf.Sin(curDegree);
			pos0 = vCenterList[i].x + cosA * radius;
			pos1 = vCenterList[i].y + sinA * radius;
			Vector3 vPosition = new Vector3(pos0, pos1);
			Vector2 uvPosition = new Vector2(pos0 * uvScaleX + uvCenterX, pos1 * uvScaleY + uvCenterY);
			vh.AddVert(vPosition, color32, uvPosition);
			curDegree += degreeDelta;
		}
		curDegree -= degreeDelta;
		for (int j = 0; j <= TriangleNum - 1; j++)
		{
			vh.AddTriangle(vCenterVertList[i], preVertNum + j + 1, preVertNum + j);
		}
	}
}

這段加上以後,可以玩新花樣:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章