Files
DuckovMods/SceneView/SceneViewPanel.cs
2025-11-18 18:45:14 +08:00

194 lines
8.3 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
namespace SceneView
{
public class SceneViewPanel : MonoBehaviour, IDragHandler, IBeginDragHandler
{
public const float titleHeight = 50;
public ScrollRect? scrollRect;
public string currentAimObj;
private Vector2 shift;
private TreeViewNode? treeViewNode;
private void Start()
{
currentAimObj = CanvasControl.ShowAim;
CreateUI();
}
public void OnBeginDrag(PointerEventData eventData)
{
shift = transform.position - new Vector3(eventData.position.x, eventData.position.y);
}
public void OnDrag(PointerEventData eventData)
{
transform.position = eventData.position + shift;
}
private void CreateUI()
{
CreateTitleBar();
var scrollConfig = ScrollViewConfig.Default;
scrollConfig.Horizontal = true;
scrollConfig.RectConfig.SizeDelta = CanvasControl.panelSize - new Vector2(0, titleHeight);
var scrollRectArr = ControlUtilities.CreateScrollView(transform, scrollConfig);
scrollRect = scrollRectArr.scrollRect;
if (scrollRect == null)
{
Debug.LogError("Failed to create ScrollView.");
return;
}
var scrollRectRectTransform = scrollRect.GetComponent<RectTransform>();
if (scrollRectRectTransform == null)
{
Debug.LogError("Failed to get RectTransform for ScrollView.");
return;
}
scrollRectRectTransform.anchorMin = new Vector2(0, 0);
scrollRectRectTransform.anchorMax = new Vector2(1, 1);
scrollRectRectTransform.offsetMin = Vector2.zero;
scrollRectRectTransform.offsetMax = new Vector2(0, -titleHeight);
var content = scrollRect.content.gameObject;
if (content == null)
{
Debug.LogError("Failed to get content for ScrollView.");
return;
}
// var contentRectTransform = content.GetComponent<RectTransform>();
// contentRectTransform.anchorMin = Vector2.up;
// contentRectTransform.anchorMax = Vector2.one;
// contentRectTransform.sizeDelta = Vector2.zero;
// contentRectTransform.offsetMin = Vector2.zero;
// contentRectTransform.offsetMax = new Vector2(0, 0);
// var root = new GameObject("root");
// root.AddComponent<RectTransform>();
// root.transform.SetParent(content.transform, false);
treeViewNode = content.AddComponent<TreeViewNode>();
// treeViewNode.UpdateHeight();
// var vLayout = content.AddComponent<VerticalLayoutGroup>();
// vLayout.padding = new RectOffset(2, 2, 2, 2);
// vLayout.spacing = 5;
// vLayout.childControlWidth = true;
// vLayout.childControlHeight = false;
// var size= content.AddComponent<ContentSizeFitter>();
// size.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
// size.horizontalFit = ContentSizeFitter.FitMode.Unconstrained;
var inputConfig = InputFieldConfig.Default;
inputConfig.RectConfig.AnchorMin = Vector2.zero;
inputConfig.RectConfig.AnchorMax = Vector2.right;
inputConfig.RectConfig.Pivot = new Vector2(0.5f, 1);
inputConfig.RectConfig.SizeDelta = new Vector2(0, titleHeight);
inputConfig.PlaceholderText = "输入对象名称";
var inputObj = ControlUtilities.CreateInputField(transform, inputConfig);
inputObj.inputField.onEndEdit.AddListener(s =>
{
currentAimObj = s;
Refresh();
});
// Refresh();
}
private void CreateTitleBar()
{
var titleBar = new GameObject("TitleBar").AddComponent<RectTransform>();
titleBar.transform.SetParent(transform, false);
if (titleBar == null)
{
Debug.LogError("Failed to create TitleBar RectTransform.");
return;
}
titleBar.anchorMin = new Vector2(0, 1);
titleBar.anchorMax = new Vector2(1, 1);
titleBar.pivot = new Vector2(0.5f, 1);
titleBar.sizeDelta = new Vector2(0, titleHeight);
titleBar.anchoredPosition = Vector2.zero;
var titleTextConfig = TextConfig.Default;
titleTextConfig.Text = "场景视图";
titleTextConfig.RectConfig.AnchorMin = Vector2.zero;
titleTextConfig.RectConfig.AnchorMax = Vector2.one;
var titleText = ControlUtilities.CreateText(titleBar, titleTextConfig);
if (titleText == null) Debug.LogError("Failed to create TitleText.");
var refreshButtonConfig = ButtonConfig.Default;
refreshButtonConfig.Text = "刷新";
refreshButtonConfig.BackgroundColor = Color.yellow;
refreshButtonConfig.RectConfig.SizeDelta = new Vector2(60, 40);
refreshButtonConfig.RectConfig.AnchoredPosition = new Vector2(35, -25);
var refreshButton = ControlUtilities.CreateButton(titleBar, refreshButtonConfig, Refresh);
var closeButtonConfig = ButtonConfig.Default;
closeButtonConfig.Text = "X";
closeButtonConfig.BackgroundColor = Color.red;
closeButtonConfig.RectConfig.AnchorMax = Vector2.one;
closeButtonConfig.RectConfig.AnchorMin = Vector2.one;
closeButtonConfig.RectConfig.SizeDelta = new Vector2(30, 30);
closeButtonConfig.RectConfig.AnchoredPosition = new Vector2(-25, -25);
ControlUtilities.CreateButton(titleBar, closeButtonConfig, () => gameObject.SetActive(false));
}
public void Refresh()
{
if (treeViewNode)
{
var canvas = GameObject.Find(currentAimObj);
// var canvas = FindIncludingHidden(currentAimObj);
if (!canvas && !string.IsNullOrEmpty(currentAimObj))
{
Debug.LogError($"{currentAimObj} not found.");
return;
}
treeViewNode.ClearChildNodes();
StartCoroutine(treeViewNode.InitializeNode(canvas));
// StartCoroutine(treeViewNode.DisplayGameObjectStructureCoroutine(canvas));
// treeViewNode.DisplayGameObjectStructure(canvas);
}
}
/// <summary>
/// 按名称查找场景中的GameObject包括隐藏非激活对象和DontDestroyOnLoad对象。
/// 此方法会遍历所有当前加载到内存中的GameObject实例。
/// **重要提示:**
/// 1. **性能开销较大:** 该方法会遍历所有已加载的GameObject性能开销相对较高。
/// 因此,**不建议在Update、FixedUpdate等帧循环中频繁调用。**
/// 2. **适用场景:** 更适合在初始化、加载场景、调试或不频繁的查找操作中使用。
/// 3. **同名对象:** 如果场景中存在多个同名对象,此方法将返回它遇到的第一个匹配项。
/// 4. **DontDestroyOnLoad** 自动包含在DontDestroyOnLoad根下的对象。
/// 5. **隐藏对象:** 自动包含Hierarchy中非激活隐藏的对象。
/// </summary>
/// <param name="name">要查找的GameObject的名称。</param>
/// <returns>找到的第一个GameObject如果未找到则返回null。</returns>
public static GameObject FindIncludingHidden(string name)
{
// 1. 验证名称 - 处理null, empty, 或只包含空白字符的名称
if (string.IsNullOrWhiteSpace(name))
{
Debug.LogWarning("FindIncludingHidden: Provided name is null, empty, or whitespace. Returning null.");
return null;
}
var allGameObjects = Resources.FindObjectsOfTypeAll<GameObject>();
foreach (var obj in allGameObjects)
if (obj.name == name)
return obj; // 4. 返回第一个匹配项
return null;
}
}
}