feat:场景视图添加属性编辑,添加轮廓显示

This commit is contained in:
m0_75251201
2025-11-13 16:24:49 +08:00
parent 9b91218973
commit 8fcbdc5649
95 changed files with 2836 additions and 445 deletions

View File

@@ -1,5 +1,3 @@
using System;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
@@ -9,26 +7,36 @@ namespace SceneView
public class SceneViewPanel : MonoBehaviour, IDragHandler, IBeginDragHandler
{
public const float titleHeight = 50;
private Vector2 shift;
public ScrollRect? scrollRect;
private TreeViewNode? treeViewNode;
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.SizeDelta = CanvasControl.panelSize - new Vector2(0, titleHeight);
scrollConfig.RectConfig.SizeDelta = CanvasControl.panelSize - new Vector2(0, titleHeight);
var scrollRectArr = ControlUtilities.CreateScrollView(transform, scrollConfig);
scrollRect = scrollRectArr.scrollRect;
if (scrollRect == null)
@@ -83,7 +91,7 @@ namespace SceneView
inputConfig.RectConfig.AnchorMax = Vector2.right;
inputConfig.RectConfig.Pivot = new Vector2(0.5f, 1);
inputConfig.RectConfig.SizeDelta = new Vector2(0, titleHeight);
inputConfig.PlaceholderText = "输入搜索对象";
inputConfig.PlaceholderText = "输入对象名称";
var inputObj = ControlUtilities.CreateInputField(transform, inputConfig);
inputObj.inputField.onEndEdit.AddListener(s =>
{
@@ -92,7 +100,7 @@ namespace SceneView
});
Refresh();
// Refresh();
}
private void CreateTitleBar()
@@ -117,10 +125,7 @@ namespace SceneView
titleTextConfig.RectConfig.AnchorMax = Vector2.one;
var titleText = ControlUtilities.CreateText(titleBar, titleTextConfig);
if (titleText == null)
{
Debug.LogError("Failed to create TitleText.");
}
if (titleText == null) Debug.LogError("Failed to create TitleText.");
var refreshButtonConfig = ButtonConfig.Default;
refreshButtonConfig.Text = "刷新";
@@ -143,8 +148,9 @@ namespace SceneView
{
if (treeViewNode)
{
var canvas = FindIncludingHidden(currentAimObj);
if (!canvas)
var canvas = GameObject.Find(currentAimObj);
// var canvas = FindIncludingHidden(currentAimObj);
if (!canvas && !string.IsNullOrEmpty(currentAimObj))
{
Debug.LogError($"{currentAimObj} not found.");
return;
@@ -155,27 +161,16 @@ namespace SceneView
}
}
public void OnDrag(PointerEventData eventData)
{
transform.position = eventData.position + shift;
}
public void OnBeginDrag(PointerEventData eventData)
{
shift = transform.position - new Vector3(eventData.position.x, eventData.position.y);
}
/// <summary>
/// 按名称查找场景中的GameObject包括隐藏非激活对象和DontDestroyOnLoad对象。
/// 此方法会遍历所有当前加载到内存中的GameObject实例。
///
/// **重要提示:**
/// 1. **性能开销较大:** 该方法会遍历所有已加载的GameObject性能开销相对较高。
/// 因此,**不建议在Update、FixedUpdate等帧循环中频繁调用。**
/// 2. **适用场景:** 更适合在初始化、加载场景、调试或不频繁的查找操作中使用
/// 3. **同名对象:** 如果场景中存在多个同名对象,此方法将返回它遇到的第一个匹配项
/// 4. **DontDestroyOnLoad** 自动包含在DontDestroyOnLoad根下的对象。
/// 5. **隐藏对象:** 自动包含Hierarchy中非激活隐藏的对象。
/// 按名称查找场景中的GameObject包括隐藏非激活对象和DontDestroyOnLoad对象。
/// 此方法会遍历所有当前加载到内存中的GameObject实例。
/// **重要提示:**
/// 1. **性能开销较大:** 该方法会遍历所有已加载的GameObject性能开销相对较高。
/// 因此,**不建议在Update、FixedUpdate等帧循环中频繁调用。**
/// 2. **适用场景:** 更适合在初始化、加载场景、调试或不频繁的查找操作中使用。
/// 3. **同名对象:** 如果场景中存在多个同名对象,此方法将返回它遇到的第一个匹配项
/// 4. **DontDestroyOnLoad** 自动包含在DontDestroyOnLoad根下的对象
/// 5. **隐藏对象:** 自动包含Hierarchy中非激活隐藏的对象。
/// </summary>
/// <param name="name">要查找的GameObject的名称。</param>
/// <returns>找到的第一个GameObject如果未找到则返回null。</returns>
@@ -187,34 +182,12 @@ namespace SceneView
Debug.LogWarning("FindIncludingHidden: Provided name is null, empty, or whitespace. Returning null.");
return null;
}
// 2. 获取所有已加载的GameObject
// Resources.FindObjectsOfTypeAll<GameObject>() 是实现需求的关键。
// 它会找到所有当前加载到内存中的GameObject实例不论它们是否激活属于哪个场景包括 DontDestroyOnLoad 场景),
// 甚至可能包括一些编辑器内部使用的隐藏GameObject。
GameObject[] allGameObjects = Resources.FindObjectsOfTypeAll<GameObject>();
// 3. 遍历并比较名称
foreach (GameObject obj in allGameObjects)
{
// Unity中存在许多内部GameObject例如场景视图的相机、光照探头组等
// 它们的hideFlags属性可能被设置为HideInHierarchy、HideAndDontSave等。
// 题目要求“包括隐藏”,并未明确排除这些内部或编辑器对象。
// 因此这里我们采取最宽松的策略只要GameObject的name属性与传入的name匹配就返回。
// 如果未来需要排除特定类型的隐藏对象(例如只查找用户创建的游戏对象),
// 可以根据 obj.scene.name 来过滤 DontDestroyOnLoad 场景中的对象,
// 或者根据 obj.hideFlags 来排除编辑器内部对象。
var allGameObjects = Resources.FindObjectsOfTypeAll<GameObject>();
foreach (var obj in allGameObjects)
if (obj.name == name)
{
return obj; // 4. 返回第一个匹配项
}
}
// 5. 未找到则返回 null
// 通常查找函数在未找到结果时静默返回null是更常见的API行为。
// 调用方可以根据返回值自行决定是否输出日志。
// Debug.LogWarning($"FindIncludingHidden: GameObject with name '{name}' not found. Returning null.");
return null;
}
}
}
}