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 手册