Administrator
发布于 2024-08-27 / 2 阅读
0
0

UI工具代码|父物件对齐子物件,并添加快捷键

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

public class UICommonTool : Editor
{
    [MenuItem("GameObject/UI/工具/适应子物体大小   Ctrl+Alt+Q %&Q", priority = 10000)]
    public static void AutoSizeDelayByChilds()
    {
        var curTrans = (Selection.activeObject as GameObject)?.GetComponent<RectTransform>(); 


        if (object.ReferenceEquals(curTrans, null) || curTrans.childCount <= 0) return;

        Camera curCamera = null;
        Canvas curCanvas = null;
        Transform parentTran = curTrans;  //获取位置
        do
        {
            var canvas = parentTran.GetComponent<Canvas>();
            if (canvas != null)
            {
                curCanvas = canvas;
                curCamera = canvas.worldCamera;
            }
            parentTran = parentTran.parent;
        } while (parentTran != null && object.ReferenceEquals(curCamera, null));


        if (object.ReferenceEquals(curCamera, null))
        {
            var ojs = Resources.FindObjectsOfTypeAll(typeof(Camera)) as Camera[];

            for (int i = 0; i < ojs.Length || object.ReferenceEquals(curCamera, null); i++)
            {
                var item = ojs[i];
                if ((item.cullingMask & (1 << LayerMask.NameToLayer("UI"))) != 0)
                {
                    curCamera = item;
                }
            }
        }
        else
        {
            Debug.Log($"{curCamera.name}");
        }

        if (object.ReferenceEquals(curCamera, null)) return;

        bool Continue = true;
        List<GameObject> pingList = new();

        for (var i = 0; i < curTrans.childCount; i++)
        {
            var item = curTrans.GetChild(i).GetComponent<RectTransform>();
            if (item.pivot != Vector2.one * 0.5f || (item.anchorMin != item.anchorMax) || (item.anchorMax != Vector2.one * 0.5f))
            {
                Continue = false;
                UnityEditor.EditorGUIUtility.PingObject(item.gameObject);
                pingList.Add(item.gameObject);
            }
        }


        if (!Continue)
        {
            Selection.activeObject = null;
            Selection.objects = pingList.ToArray();
            return;
        }
        var cacheParent = curTrans.parent;
        var cachePos = curTrans.anchoredPosition;
        var cacheAnchorsMin = curTrans.anchorMin;
        var cacheAnchorsMax = curTrans.anchorMax;
        var cachePivot = curTrans.pivot;

        //Undo.RegisterCompleteObjectUndo()
        //这里把对象放到了撤销栈上了
        Undo.RegisterCompleteObjectUndo(curTrans, "Rect Transform");
        Debug.Log("curTrans="+(string)curTrans.name) ;
        //curTrans.SetParent(curCanvas.transform);
        Undo.SetTransformParent(curTrans.transform, curCanvas.transform, "Rect Transform");
        Debug.Log("curCanvas=" + curCanvas.name);

        curTrans.anchorMin = curTrans.anchorMax = Vector2.one * 0.5f;
        curTrans.pivot = Vector2.one * 0.5f;
        curTrans.anchoredPosition3D = Vector3.zero;

        var childsRect = new List<RectTransform>(curTrans.GetComponentsInChildren<RectTransform>());
        Vector2 maxPoint = Vector2.one * float.MinValue;
        Vector2 minPoint = Vector2.zero * float.MaxValue;
        //子物体也放到了撤销栈上
        /*
         将对象状态存储在撤销堆栈上。
         如果执行了撤销操作,那么在调用这一函数后对对象所做的任何更改都将被撤销,并且该对象将恢复到记录的状态。
         无法使用这一函数恢复变换组件父项的更改.
         */
        Undo.RegisterCompleteObjectUndo(childsRect.ToArray(), "LocalSacle Transform");
        foreach(var s in childsRect.ToArray())
        {
            Debug.Log(s.name);
        }
        //Debug.Log(childsRect.ToArray().name);
        // 设置大小
        foreach (var item in childsRect)
        {
            if (item == curTrans || !item.gameObject.activeInHierarchy) continue;
            var tempItem = item;
            Vector2 curPos = curCanvas.transform.InverseTransformPoint(item.position);
            var min = curPos - item.rect.size * item.pivot;
            var max = min + item.rect.size;


            minPoint = new Vector2(
                Mathf.Min(minPoint.x, min.x),
                Mathf.Min(minPoint.y, min.y)
                );

            maxPoint = new Vector2(
                Mathf.Max(maxPoint.x, max.x),
                Mathf.Max(maxPoint.y, max.y)
                );
        }

        var deltaSize = maxPoint - minPoint;



        var centerPoint = minPoint + deltaSize * 0.5f;

        // 设置子节点位置
        Vector2 thisPos = curCanvas.transform.InverseTransformPoint(curTrans.position);
        var moveInterval = thisPos - centerPoint;

        for (int i = 0; i < curTrans.childCount; i++)
        {
            var tran = curTrans.GetChild(i).GetComponent<RectTransform>();

            tran.anchoredPosition += moveInterval;
        }

        var tranCentre = (Vector2.one * 0.5f - cachePivot) * (deltaSize - curTrans.sizeDelta);
        //这里更新了父节点吗?
       // curTrans.SetParent(cacheParent);
        Undo.SetTransformParent(curTrans.transform, cacheParent.transform, "Rect Transform");

        curTrans.sizeDelta = deltaSize;
        curTrans.pivot = cachePivot;
        curTrans.anchorMin = cacheAnchorsMin;
        curTrans.anchorMax = cacheAnchorsMax;
        var num = new Vector2(cachePivot.x % 1, cachePivot.y % 1);
        curTrans.anchoredPosition = cachePos - moveInterval - tranCentre;
        //curTrans.anchoredPosition = cachePos - num * 2 * moveInterval
        //    + (Vector2.one - num * 2) * deltaSize * (cachePivot - Vector2.one * 0.5f) * 2;
        //curTrans.anchoredPosition += deltaSize * (cachePivot - Vector2.one * 0.5f);
        //curTrans.anchoredPosition += (cachePivot - Vector2.one * 0.5f) * deltaSize;


        //EditorUtility.SetDirty(curTrans);
    }

}

使 UI 元素适应其内容的大小 - Unity 手册


评论