Unity编辑器拓展之十:UI对齐工具

示例图

这里写图片描述

这里写图片描述

开发思路

1、获取选中的UI
2、根据对齐规则修改所选中UI的坐标

代码

UGUIAlign.cs

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

public enum AlignType
{
    Top = 1,
    Left = 2,
    Right = 3,
    Bottom = 4,
    HorizontalCenter = 5,       //水平居中
    VerticalCenter = 6,         //垂直居中
    Horizontal = 7,             //横向分布
    Vertical = 8,               //纵向分布
}

public class UGUIAlign : Editor
{
    [MenuItem("GameObject/UI/Align/Left 【左对齐】")]
    static void AlignLeft()
    {
        Align(AlignType.Left);
    }
    [MenuItem("GameObject/UI/Align/HorizontalCenter 【水平居中】")]
    static void AlignHorizontalCenter()
    {
        Align(AlignType.HorizontalCenter);
    }
    [MenuItem("GameObject/UI/Align/Right 【右对齐】")]
    static void AlignRight()
    {
        Align(AlignType.Right);
    }
    [MenuItem("GameObject/UI/Align/Top 【顶端对齐】")]
    static void AlignTop()
    {
        Align(AlignType.Top);
    }
    [MenuItem("GameObject/UI/Align/VerticalCenter 【垂直居中】")]
    static void AlignVerticalCenter()
    {
        Align(AlignType.VerticalCenter);
    }
    [MenuItem("GameObject/UI/Align/Bottom 【底端对齐】")]
    static void AlignBottom()
    {
        Align(AlignType.Bottom);
    }
    [MenuItem("GameObject/UI/Align/Horizontal 【横向分布】")]
    static void AlignHorizontal()
    {
        Align(AlignType.Horizontal);
    }
    [MenuItem("GameObject/UI/Align/Vertical 【纵向分布】")]
    static void AlignVertical()
    {
        Align(AlignType.Vertical);
    }

    public static void Align(AlignType type)
    {
        List<RectTransform> rects = new List<RectTransform>();
        GameObject[] objects = Selection.gameObjects;
        if (objects != null && objects.Length > 0)
        {
            for (int i = 0; i < objects.Length; i++)
            {
                RectTransform rect = objects[i].GetComponent<RectTransform>();
                if (rect != null)
                    rects.Add(rect);
            }
        }

        if (rects.Count > 1)
        {
            Align(type, rects);
        }
    }

    public static void Align(AlignType type, List<RectTransform> rects)
    {
        RectTransform tenplate = rects[0];
        float w = tenplate.sizeDelta.x * tenplate.lossyScale.x;
        float h = tenplate.sizeDelta.y * tenplate.localScale.y;

        float x = tenplate.position.x - tenplate.pivot.x * w;
        float y = tenplate.position.y - tenplate.pivot.y * h;

        switch (type)
        {
            case AlignType.Top:
                for (int i = 1; i < rects.Count; i++)
                {
                    RectTransform trans = rects[i];
                    float th = trans.sizeDelta.y * trans.localScale.y;
                    Vector3 pos = trans.position;
                    pos.y = y + h - th + trans.pivot.y * th;
                    trans.position = pos;
                }
                break;
            case AlignType.Left:
                for (int i = 1; i < rects.Count; i++)
                {
                    RectTransform trans = rects[i];
                    float tw = trans.sizeDelta.x * trans.lossyScale.x;
                    Vector3 pos = trans.position;
                    pos.x = x + tw * trans.pivot.x;
                    trans.position = pos;
                }
                break;
            case AlignType.Right:
                for (int i = 1; i < rects.Count; i++)
                {
                    RectTransform trans = rects[i];
                    float tw = trans.sizeDelta.x * trans.lossyScale.x;
                    Vector3 pos = trans.position;
                    pos.x = x + w - tw + tw * trans.pivot.x;
                    trans.position = pos;
                }
                break;
            case AlignType.Bottom:
                for (int i = 1; i < rects.Count; i++)
                {
                    RectTransform trans = rects[i];
                    float th = trans.sizeDelta.y * trans.localScale.y;
                    Vector3 pos = trans.position;
                    pos.y = y + th * trans.pivot.y;
                    trans.position = pos;
                }
                break;
            case AlignType.HorizontalCenter:
                for (int i = 1; i < rects.Count; i++)
                {
                    RectTransform trans = rects[i];
                    float tw = trans.sizeDelta.x * trans.lossyScale.x;
                    Vector3 pos = trans.position;
                    pos.x = x + 0.5f * w - 0.5f * tw + tw * trans.pivot.x;
                    trans.position = pos;
                }
                break;
            case AlignType.VerticalCenter:
                for (int i = 1; i < rects.Count; i++)
                {
                    RectTransform trans = rects[i];
                    float th = trans.sizeDelta.y * trans.localScale.y;
                    Vector3 pos = trans.position;
                    pos.y = y + 0.5f * h - 0.5f * th + th * trans.pivot.y;
                    trans.position = pos;
                }
                break;
            case AlignType.Horizontal:
                float minX = GetMinX(rects);
                float maxX = GetMaxX(rects);
                rects.Sort(SortListRectTransformByX);
                float distance = (maxX - minX)/(rects.Count - 1);
                for (int i = 1; i < rects.Count - 1; i++)
                {
                    RectTransform trans = rects[i];
                    Vector3 pos = trans.position;
                    pos.x = minX + i * distance;
                    trans.position = pos;
                }
                break;
            case AlignType.Vertical:
                float minY = GetMinY(rects);
                float maxY = GetMaxY(rects);
                rects.Sort(SortListRectTransformByY);
                float distanceY = (maxY - minY)/(rects.Count - 1);
                for (int i = 1; i < rects.Count - 1; i++)
                {
                    RectTransform trans = rects[i];
                    Vector3 pos = trans.position;
                    pos.y = minY + i*distanceY;
                    trans.position = pos;
                }
                break;
        }
    }

    private static int SortListRectTransformByX(RectTransform r1, RectTransform r2)
    {
        float w = r1.sizeDelta.x * r1.lossyScale.x;
        float x1 = r1.position.x - r1.pivot.x * w;
        w = r2.sizeDelta.x * r2.lossyScale.x;
        float x2 = r2.position.x - r2.pivot.x * w;
        if (x1 >= x2)
            return 1;
        else
            return -1;
    }

    private static int SortListRectTransformByY(RectTransform r1, RectTransform r2)
    {
        float w = r1.sizeDelta.y * r1.lossyScale.y;
        float y1 = r1.position.y - r1.pivot.y * w;
        w = r2.sizeDelta.y * r2.lossyScale.y;
        float y2 = r2.position.y - r2.pivot.y * w;
        if (y1 >= y2)
            return 1;
        else
            return -1;
    }

    private static float GetMinX(List<RectTransform> rects)
    {
        if (null == rects || rects.Count == 0)
            return 0;
        RectTransform tenplate = rects[0];
        float minx = tenplate.position.x;
        float tempX = 0;
        for (int i = 1; i < rects.Count; i++)
        {
            tempX = rects[i].position.x;
            if (tempX < minx)
                minx = tempX;
        }
        return minx;
    }

    private static float GetMaxX(List<RectTransform> rects)
    {
        if (null == rects || rects.Count == 0)
            return 0;
        RectTransform tenplate = rects[0];
        float maxX = tenplate.position.x;
        float tempX = 0;
        for (int i = 1; i < rects.Count; i++)
        {
            tempX = rects[i].position.x;
            if (tempX > maxX)
                maxX = tempX;
        }
        return maxX;
    }

    private static float GetMinY(List<RectTransform> rects)
    {
        if (null == rects || rects.Count == 0)
            return 0;
        RectTransform tenplate = rects[0];
        float minY = tenplate.position.y;
        float tempX = 0;
        for (int i = 1; i < rects.Count; i++)
        {
            tempX = rects[i].position.y;
            if (tempX < minY)
                minY = tempX;
        }
        return minY;
    }

    private static float GetMaxY(List<RectTransform> rects)
    {
        if (null == rects || rects.Count == 0)
            return 0;
        RectTransform tenplate = rects[0];
        float maxY = tenplate.position.y;
        float tempX = 0;
        for (int i = 1; i < rects.Count; i++)
        {
            tempX = rects[i].position.y;
            if (tempX > maxY)
                maxY = tempX;
        }
        return maxY;
    }
}

UGUIAlignWindow.cs

为了操作更加便捷,提供一个EditorWindow类

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

public class UGUIAlignWindow : EditorWindow
{
    private Dictionary<AlignType,Texture> alignTexture = new Dictionary<AlignType, Texture>(); 
    void OnEnable()
    {
        Texture leftTexture = Resources.Load<Texture>("Textures/Left");
        Texture horizontalCenterTexture = Resources.Load<Texture>("Textures/HorizontalCenter");
        Texture rightTexture = Resources.Load<Texture>("Textures/Right");
        Texture topTexture = Resources.Load<Texture>("Textures/Top");
        Texture verticalCenterTexture = Resources.Load<Texture>("Textures/VerticalCenter");
        Texture bottomTexture = Resources.Load<Texture>("Textures/Bottom");
        Texture horizontalTexture = Resources.Load<Texture>("Textures/Horizontal");
        Texture verticalTexture = Resources.Load<Texture>("Textures/Vertical");
        alignTexture.Add(AlignType.Left, leftTexture);
        alignTexture.Add(AlignType.HorizontalCenter, horizontalCenterTexture);
        alignTexture.Add(AlignType.Right, rightTexture);
        alignTexture.Add(AlignType.Top, topTexture);
        alignTexture.Add(AlignType.VerticalCenter, verticalCenterTexture);
        alignTexture.Add(AlignType.Bottom, bottomTexture);
        alignTexture.Add(AlignType.Horizontal, horizontalTexture);
        alignTexture.Add(AlignType.Vertical, verticalTexture);
    }

    [MenuItem("UGUIAlign/Align")]
    public static UGUIAlignWindow GetWindow()
    {
        var window = GetWindow<UGUIAlignWindow>();
        window.titleContent = new GUIContent("UGUI Align");
        window.Focus();
        window.Repaint();
        return window;
    }

    void OnGUI()
    {
        GUILayout.BeginHorizontal();
        GUILayout.BeginVertical();
        for (int i = (int)AlignType.Top; i <= (int)AlignType.Vertical; i++)
        {
            if (GUILayout.Button(alignTexture[(AlignType)i], "LargeButton"))
            {
                UGUIAlign.Align((AlignType)i);
            }
            if (i%3 == 0)
            {
                GUILayout.EndVertical();
                GUILayout.BeginVertical();
            }
        }
        GUILayout.EndVertical();
        GUILayout.EndHorizontal();
    }
}

对齐图片资源

这里写图片描述

Code下载

https://github.com/JingFengJi/UGUIAlign

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

猜你喜欢

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