锚点窗口改为了使用集合,一次性可以添加多个窗口

This commit is contained in:
2026-06-12 14:28:48 +08:00
parent b2d82a054a
commit 856c395819
5 changed files with 219 additions and 159 deletions
+47 -72
View File
@@ -1,59 +1,50 @@
using System.Collections.Generic;
using UnityEngine;
namespace XericUI.VisualForm
{
/// <summary>
/// 锚点窗口 - WorldAnchor的子类,持有UI窗口对象的引用。
/// 锚点窗口 - WorldAnchor的子类,持有一组UI窗口条目的引用。
/// 每个条目包含窗口对象、屏幕偏移量和激活状态,支持一个锚点同时生成多个定位窗口。
/// 窗口对象可以是实际的场景对象,也可以是预制体。
/// 如果窗口锚点坞在子项中找不到对应对象,则视为预制体,需要通过实例化方法创建。
/// </summary>
[AddComponentMenu("Xeric UI Vessel/AnchorWindow/AnchorWindow")]
public class AnchorWindow : WorldAnchor
{
[Header("窗口配置")]
[SerializeField, Tooltip("UI窗口对象(可以是子项中的实例或预制体资源)")]
private GameObject m_WindowObject;
[SerializeField, Tooltip("启用UI显示开关")]
private bool m_EnableUI = true;
[Header("窗口条目")]
[SerializeField, Tooltip("窗口对象集合,每个条目可独立配置偏移和启用状态")]
private List<WindowEntry> m_WindowEntries = new List<WindowEntry>();
/// <summary>
/// 窗口对象引用(可以是实例或预制体)
/// 窗口条目列表
/// </summary>
public GameObject WindowObject
{
get => m_WindowObject;
set => m_WindowObject = value;
}
public List<WindowEntry> WindowEntries => m_WindowEntries;
/// <summary>
/// UI启用开关,设为false时窗口实例将被隐藏
/// 当前生效的窗口条目数(过滤掉WindowObject为null的条目)
/// </summary>
public bool EnableUI
public int ValidEntryCount
{
get => m_EnableUI;
set
get
{
if (m_EnableUI == value) return;
m_EnableUI = value;
ApplyUIState();
int count = 0;
foreach (var entry in m_WindowEntries)
if (entry != null && entry.WindowObject != null)
count++;
return count;
}
}
/// <summary>
/// 判断窗口对象是否为预制体(不在锚点坞的子项中则为预制体)
/// 此标记由WindowState在初始化时设置
/// </summary>
[System.NonSerialized]
public bool IsPrefab;
/// <summary>
/// 获取当前有效的窗口Transform(实例或自身)
/// 获取第一个有效窗口对象的Transform(兼容旧API)
/// </summary>
public Transform GetWindowTransform()
{
if (m_WindowObject != null)
return m_WindowObject.transform;
foreach (var entry in m_WindowEntries)
{
if (entry != null && entry.WindowObject != null)
return entry.WindowObject.transform;
}
return transform;
}
@@ -62,52 +53,58 @@ namespace XericUI.VisualForm
/// <summary>
/// 从所属锚点坞获取自己的中间窗口状态类
/// </summary>
/// <returns>WindowState实例,不存在则返回null</returns>
public WindowState GetWindowState()
{
if (TargetDock == null)
return null;
if (TargetDock == null) return null;
return TargetDock.GetWindowState(this);
}
/// <summary>
/// 获取窗口实例对象(预制体实例化后的对象,或子项中已有的对象)
/// 获取第一个有效窗口的实例对象
/// </summary>
/// <returns>窗口GameObject实例</returns>
public GameObject GetWindowInstance()
{
var state = GetWindowState();
return state?.WindowInstance;
if (state == null || state.Entries == null || state.Entries.Count == 0)
return null;
return state.Entries[0].Instance;
}
/// <summary>
/// 获取窗口当前的屏幕坐标(容器内本地坐标)
/// 获取所有窗口实例对象
/// </summary>
public List<GameObject> GetAllWindowInstances()
{
var result = new List<GameObject>();
var state = GetWindowState();
if (state == null || state.Entries == null) return result;
foreach (var e in state.Entries)
if (e.Instance != null)
result.Add(e.Instance);
return result;
}
/// <summary>
/// 获取第一个窗口当前的屏幕坐标(容器内本地坐标)
/// </summary>
/// <returns>屏幕本地坐标</returns>
public Vector2 GetScreenPosition()
{
var state = GetWindowState();
if (state == null) return Vector2.zero;
var instance = state.WindowInstance;
var instance = GetWindowInstance();
if (instance == null) return Vector2.zero;
var rt = instance.transform as RectTransform;
if (rt != null)
return rt.localPosition;
if (rt != null) return rt.localPosition;
return instance.transform.localPosition;
}
/// <summary>
/// 获取锚点当前的世界坐标
/// </summary>
/// <returns>世界坐标</returns>
public Vector3 GetWorldPosition()
{
var state = GetWindowState();
if (state != null)
return state.LastWorldPosition;
if (state != null) return state.LastWorldPosition;
return CachedTransform.position;
}
@@ -117,29 +114,7 @@ namespace XericUI.VisualForm
public bool IsWindowActive()
{
var state = GetWindowState();
if (state == null) return false;
return state.IsEnabled && m_EnableUI;
}
#endregion
#region 内部方法
/// <summary>
/// 将UI开关状态应用到窗口实例
/// </summary>
private void ApplyUIState()
{
var state = GetWindowState();
if (state == null) return;
var instance = state.WindowInstance;
if (instance == null) return;
if (m_EnableUI && state.IsEnabled)
instance.SetActive(true);
else
instance.SetActive(false);
return state != null && state.IsEnabled;
}
#endregion