JingFengJi
for me
FRIENDS
llcat

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

2018-08-10

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;
}

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

Author: Mr.Ding

Link: https://jingfengji.github.io/2018/08/10/Unity编辑器拓展之十九:NGUI UISprite预览图Preview拓展/

Copyright: All articles in this blog are licensed under CC BY-NC-SA 3.0 unless stating additionally.

< PreviousPost
Unity编辑器拓展之二十:拓展Unity模块,打造私人工具库(一)
NextPost >
常用软件集锦
CATALOG
  1. 1. NGUI UISprite预览图Preview拓展
    1. 1.1. 功能说明
    2. 1.2. Gif示意图
    3. 1.3. 逻辑介绍