为UGUI的Image提供图片翻转功能

僤鯓⒐⒋嵵緔 提交于 2020-03-17 00:31:48

使用了NGUI多年,最终还是转入UGUI门下,刚一上手就发现了一个小问题,没找到图片翻转功能。网上查阅一番,确实没有,那么只好自己造轮子了。

既然两个UI工具开发者相同,那么代码应该也类似,打开我心爱的Rider编辑器(至于为什么又用回Rider,因为它足够强),随便写个Image的变量定义,然后跳转到声明处,Image类源码就展现出来了,不用切源码项目看源码,真香!

先说一下翻转图片的做法原理,一个Image其实就是一个模型片,普通模式的Image就是由4个顶点2个三角形组成的(当然九宫格等模式会复杂喝多)。如果需要左右翻转,我们可以左右翻转所有顶点(翻过来显示背面),也可以左右翻转所有顶点的UV(仅限顶点对称的情况下,比如九宫格就不合适)。所以翻转顶点就是我们要做的事情,我们来看代码。

有源码就是好,很快就锁定了方法OnPopulateMesh(),长成这样还是个override,必定有妖异:

/// <summary>
/// Update the UI renderer mesh.
/// </summary>
protected override void OnPopulateMesh(VertexHelper toFill)
{
	if (activeSprite == null)
	{
		base.OnPopulateMesh(toFill);
		return;
	}

	switch (type)
	{
		case Type.Simple:
			if (!useSpriteMesh)
				GenerateSimpleSprite(toFill, m_PreserveAspect);
			else
				GenerateSprite(toFill, m_PreserveAspect);
			break;
		case Type.Sliced:
			GenerateSlicedSprite(toFill);
			break;
		case Type.Tiled:
			GenerateTiledSprite(toFill);
			break;
		case Type.Filled:
			GenerateFilledSprite(toFill, m_PreserveAspect);
			break;
	}
}

这个方法干了什么事情呢,就是根据图片类型,把传进来的VertexHelper填入完整的顶点数据,包括每个顶点的位置、顶点色、UV、法线、切线,以及三角形序列,然后再送回去。我们只要在这一步完成后,把所有的顶点位置翻转一下,就可以实现图片翻转了。

下面我们就创建一个 Image2 类,它继承了Image,并重写了OnPopulateMesh(),下面贴完整代码:

using UnityEngine;
using UnityEngine.UI;

public class Image2 : Image
{
	/// <summary>
	/// 是否水平翻转
	/// </summary>
	public bool FlipHorizontal
	{
		get { return flipHor; }
		set
		{
			flipHor = value;
			UpdateGeometry();
		}
	}
	/// <summary>
	/// 是否垂直翻转
	/// </summary>
	public bool FlipVertical
	{
		get { return flipVer; }
		set
		{
			flipVer = value;
			UpdateGeometry();
		}
	}

	[SerializeField]
	protected bool flipHor;
	[SerializeField]
	protected bool flipVer;

	protected override void OnPopulateMesh(VertexHelper toFill)
	{
		base.OnPopulateMesh(toFill);

		if (flipHor || flipVer)
		{
			Vector2 rectCenter = rectTransform.rect.center;

			int vertCount = toFill.currentVertCount;
			for (int i = 0; i < vertCount; i++)
			{
				UIVertex uiVertex = new UIVertex();
				toFill.PopulateUIVertex(ref uiVertex, i);

				Vector3 pos = uiVertex.position;
				uiVertex.position = new Vector3(
					flipHor ? (pos.x + (rectCenter.x - pos.x) * 2) : pos.x,
					flipVer ? (pos.y + (rectCenter.y - pos.y) * 2) : pos.y,
					pos.z);

				toFill.SetUIVertex(uiVertex, i);
			}
		}
	}
}

代码简单明了,再贴一个Editor类:

using UnityEngine;
using UnityEngine.UI;
using UnityEditor;
using UnityEditor.UI;

[CustomEditor(typeof(Image2))]
public class Image2Editor : ImageEditor
{
	public new Image2 target;

	private SerializedProperty _spFlipHor;
	private SerializedProperty _spFlipVer;
	private GUIContent _gcFlipHor;
	private GUIContent _gcFlipVer;

	protected override void OnEnable()
	{
		base.OnEnable();

		target = base.target as Image2;

		_spFlipHor = serializedObject.FindProperty("flipHor");
		_spFlipVer = serializedObject.FindProperty("flipVer");
		_gcFlipHor = EditorGUIUtility.TrTextContent("水平翻转", null);
		_gcFlipVer = EditorGUIUtility.TrTextContent("垂直翻转", null);
	}

	public override void OnInspectorGUI()
	{
		base.OnInspectorGUI();

		EditorGUILayout.PropertyField(_spFlipHor, _gcFlipHor);
		EditorGUILayout.PropertyField(_spFlipVer, _gcFlipVer);

		if (GUI.changed)
		{
			EditorUtility.SetDirty(target);
		}
		serializedObject.ApplyModifiedProperties();
	}
}

只要创建一个物体,添加Image2组件即可,监视窗口UI如下,多了2个翻转Toggle:

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!