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

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_26999509/article/details/81570904

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

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

猜你喜欢

转载自blog.csdn.net/qq_26999509/article/details/81570904