Unity编辑器拓展之十九:NGUI UISprite预览图Preview拓展

本文介绍了一个NGUI UISprite预览图的拓展功能,实现了在UIAtlas上直接选择Sprite,简化了选择流程。文章详细展示了如何修改UISpriteInspector脚本来实现新的预览效果,包括左右双视图展示AtlasTexture和Sprite,以及通过鼠标点击选择Sprite的具体实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

博客迁移

个人博客站点,欢迎访问,www.jiingfengji.tech

NGUI UISprite预览图Preview拓展

功能说明

1、拓展UISprite的Preview视图,同时显示UIAtlas Texture和Sprite
2、支持在UIAtlas上直接点选Sprite
3、无需打开Atlas选择框和Sprite选择框两步操作

Gif示意图

这里写图片描述

逻辑介绍

1、找到UISpriteInspector脚本,其脚本的OnPreView函数逻辑,源码如下:

public override void OnPreviewGUI (Rect rect, GUIStyle background)
{
	UISprite sprite = target as UISprite;
	if (sprite == null || !sprite.isValid) return;
	Texture2D tex = sprite.mainTexture as Texture2D;
	if (tex == null) return;
	UISpriteData sd = sprite.atlas.GetSprite(sprite.spriteName);
	NGUIEditorTools.DrawSprite(tex, rect, sd, sprite.color);
}

其中NGUIEditorTools.DrawSprite函数负责绘制Sprite,包括背景、border line、out line、size label等,如下图所示:

2、PreView区域为左右两边,分别绘制Atlas Texture和Sprite,并且Atlas Texture在绘制时依然采用sprite的绘制样式,底图背景 + 黑色轮廓,再次基础上使用的Sprite采用绿色轮廓

public override void OnPreviewGUI (Rect rect, GUIStyle background)
{
	UISprite sprite = target as UISprite;
	if (sprite == null || !sprite.isValid) return;
	Texture2D tex = sprite.mainTexture as Texture2D;
	if (tex == null) return;
	float interval = 10f;
	float width = (rect.width - interval) / 2;
	Rect leftRect = new Rect(rect.x,rect.y,width,rect.height);
	Rect rightRect = new Rect(rect.x + width + interval,rect.y,width,rect.height);
	UISpriteData sd = sprite.atlas.GetSprite(sprite.spriteName);
	NGUIEditorTools.DrawAtlas(tex,leftRect,sd);	
	NGUIEditorTools.DrawSprite(tex, rightRect, sd, sprite.color);
}
	static public void DrawAtlas(Texture2D tex,Rect drawRect,UISpriteData sprite)
	{
		if (!tex) return;

		// Create the texture rectangle that is centered inside rect.
		Rect outerRect = drawRect;
		outerRect.width = tex.width;
		outerRect.height = tex.height;
		
		if (tex.width > 0)
		{
			float f = drawRect.width / outerRect.width;
			outerRect.width *= f;
			outerRect.height *= f;
		}

		if (drawRect.height > outerRect.height)
		{
			outerRect.y += (drawRect.height - outerRect.height) * 0.5f;
		}
		else if (outerRect.height > drawRect.height)
		{
			float f = drawRect.height / outerRect.height;
			outerRect.width *= f;
			outerRect.height *= f;
		}

		if (drawRect.width > outerRect.width) outerRect.x += (drawRect.width - outerRect.width) * 0.5f;

		// Draw the background
		NGUIEditorTools.DrawTiledTexture(outerRect, NGUIEditorTools.backdropTexture);

		Handles.color = Color.black;
		Handles.DrawLine(new Vector3(outerRect.xMin, outerRect.yMin), new Vector3(outerRect.xMin, outerRect.yMax));
		Handles.DrawLine(new Vector3(outerRect.xMax, outerRect.yMin), new Vector3(outerRect.xMax, outerRect.yMax));
		Handles.DrawLine(new Vector3(outerRect.xMin, outerRect.yMin), new Vector3(outerRect.xMax, outerRect.yMin));
		Handles.DrawLine(new Vector3(outerRect.xMin, outerRect.yMax), new Vector3(outerRect.xMax, outerRect.yMax));
		
		if(sprite != null)
		{
			Handles.color = Color.green;
			Rect spriteOutlineRect = outerRect;
			float r = outerRect.width / tex.width;
			spriteOutlineRect.x = outerRect.xMin + sprite.x * r;
			spriteOutlineRect.y = outerRect.yMin + sprite.y * r;
			spriteOutlineRect.width = sprite.width * r;
			spriteOutlineRect.height = sprite.height * r;
			Handles.DrawLine(new Vector3(spriteOutlineRect.xMin, spriteOutlineRect.yMin), new Vector3(spriteOutlineRect.xMin, spriteOutlineRect.yMax));
			Handles.DrawLine(new Vector3(spriteOutlineRect.xMax, spriteOutlineRect.yMin), new Vector3(spriteOutlineRect.xMax, spriteOutlineRect.yMax));
			Handles.DrawLine(new Vector3(spriteOutlineRect.xMin, spriteOutlineRect.yMin), new Vector3(spriteOutlineRect.xMax, spriteOutlineRect.yMin));
			Handles.DrawLine(new Vector3(spriteOutlineRect.xMin, spriteOutlineRect.yMax), new Vector3(spriteOutlineRect.xMax, spriteOutlineRect.yMax));
		}

		Rect uv = new Rect(0, 0, tex.width, tex.height);
		uv = NGUIMath.ConvertToTexCoords(uv, tex.width, tex.height);
		GUI.DrawTextureWithTexCoords(outerRect, tex, uv, true);
		
		// Sprite size label
		string text = string.Format("Atlas Size: {0}x{1}", Mathf.RoundToInt(tex.width), Mathf.RoundToInt(tex.height));
        EditorGUI.DropShadowLabel(GUILayoutUtility.GetRect(Screen.width, 18f), text);
	}

示意图如下:
这里写图片描述

3、点选功能实现

	public override void OnPreviewGUI (Rect rect, GUIStyle background)
	{
		UISprite sprite = target as UISprite;
		if (sprite == null || !sprite.isValid) return;

		Texture2D tex = sprite.mainTexture as Texture2D;
		if (tex == null) return;
		float interval = 10f;
		float width = (rect.width - interval) / 2;
		Rect leftRect = new Rect(rect.x,rect.y,width,rect.height);
		Rect rightRect = new Rect(rect.x + width + interval,rect.y,width,rect.height);
		UISpriteData sd = sprite.atlas.GetSprite(sprite.spriteName);
		NGUIEditorTools.DrawAtlas(tex,leftRect,sd);
		
		NGUIEditorTools.DrawSprite(tex, rightRect, sd, sprite.color);

		//点选图片
		Event e = Event.current;
		if(e.type == EventType.MouseDown)
		{
			//下面函数通过点击的坐标,和texture、texture draw rect等信息计算出被点选的sprite
			UISpriteData click = NGUIEditorTools.GetUISpriteData(tex,sprite.atlas,leftRect,e.mousePosition);
			if(click != null)
			{
				sprite.spriteName = click.name;
				EditorUtility.SetDirty(sprite);
			}
		}
	}
	//获取sprite在preview中的区域
	static public Rect GetAreaInPreview(Texture2D tex,Rect drawRect,UISpriteData sprite)
	{
		// Create the texture rectangle that is centered inside rect.
		Rect outerRect = drawRect;
		outerRect.width = tex.width;
		outerRect.height = tex.height;
		
		if (tex.width > 0)
		{
			float f = drawRect.width / outerRect.width;
			outerRect.width *= f;
			outerRect.height *= f;
		}

		if (drawRect.height > outerRect.height)
		{
			outerRect.y += (drawRect.height - outerRect.height) * 0.5f;
		}
		else if (outerRect.height > drawRect.height)
		{
			float f = drawRect.height / outerRect.height;
			outerRect.width *= f;
			outerRect.height *= f;
		}

		if (drawRect.width > outerRect.width) outerRect.x += (drawRect.width - outerRect.width) * 0.5f;

		Rect spriteOutlineRect = outerRect;
		float r = outerRect.width / tex.width;
		spriteOutlineRect.x = outerRect.xMin + sprite.x * r;
		spriteOutlineRect.y = outerRect.yMin + sprite.y * r;
		spriteOutlineRect.width = sprite.width * r;
		spriteOutlineRect.height = sprite.height * r;

		return spriteOutlineRect;
	}
	//根据点击的坐标,循环遍历出哪个Sprite的Area包含了该pos即可
	static public UISpriteData GetUISpriteData(Texture2D tex, UIAtlas atlas,Rect drawRect,Vector2 pos)
	{
		List<UISpriteData> sprites = atlas.spriteList;
		if(sprites == null || sprites.Count <= 0) return null;
		for (int i = 0; i < sprites.Count; i++)
		{
			UISpriteData sprite = sprites[i];
			Rect area = GetAreaInPreview(tex,drawRect,sprite);
			if(area.Contains(pos))
			{
				return sprite;
			}
		}
		return null;
	}

以上知识分享,如有错误,欢迎指出,共同学习,共同进步。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值