锚点窗口改为了使用集合,一次性可以添加多个窗口
This commit is contained in:
@@ -1,17 +1,18 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace XericUI.VisualForm
|
||||
{
|
||||
/// <summary>
|
||||
/// 中间窗口状态类 - 管理锚点窗口和锚点坞之间的中间产物。
|
||||
/// 负责窗口实例的生命周期管理、坐标脏标记和屏幕定位。
|
||||
/// 负责所有窗口条目的实例生命周期管理、坐标脏标记和屏幕定位。
|
||||
/// 使用对象池管理,避免频繁创建销毁。
|
||||
///
|
||||
/// 生命周期:
|
||||
/// OnStart - 从对象池取出时调用(初始化/复用)
|
||||
/// OnEnable - 锚点激活时调用(脏更新触发)
|
||||
/// OnDisable- 锚点隐藏时调用(脏更新触发)
|
||||
/// OnEnd - 回收到对象池时调用(清理/回收)
|
||||
/// OnStart - 从对象池取出时调用(初始化/复用,解析所有窗口条目)
|
||||
/// OnEnable - 锚点激活时调用(脏更新触发,激活所有启用条目)
|
||||
/// OnDisable- 锚点隐藏时调用(脏更新触发,隐藏所有条目)
|
||||
/// OnEnd - 回收到对象池时调用(清理/回收所有条目实例)
|
||||
/// </summary>
|
||||
public class WindowState
|
||||
{
|
||||
@@ -26,34 +27,10 @@ namespace XericUI.VisualForm
|
||||
public AnchorDock Dock { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 原始窗口对象(来自AnchorWindow的引用)
|
||||
/// 窗口条目列表(来自AnchorWindow的WindowEntries的运行时副本)
|
||||
/// 每个条目维护自己的实例、偏移量和激活状态
|
||||
/// </summary>
|
||||
private GameObject _windowObject;
|
||||
|
||||
/// <summary>
|
||||
/// 实例化的窗口对象(如果是预制体则为此实例,否则为_windowObject本身)
|
||||
/// </summary>
|
||||
private GameObject _instance;
|
||||
|
||||
/// <summary>
|
||||
/// 是否为预制体
|
||||
/// </summary>
|
||||
private bool _isPrefab;
|
||||
|
||||
/// <summary>
|
||||
/// 是否为预制体(公开属性)
|
||||
/// </summary>
|
||||
public bool IsPrefab => _isPrefab;
|
||||
|
||||
/// <summary>
|
||||
/// 窗口实例对象(预制体实例化后的对象,或子项中已有的对象)
|
||||
/// </summary>
|
||||
public GameObject WindowInstance => _instance;
|
||||
|
||||
/// <summary>
|
||||
/// 上帧锚点世界坐标
|
||||
/// </summary>
|
||||
public Vector3 LastWorldPosition => _lastPosition;
|
||||
public List<WindowEntry> Entries { get; private set; } = new List<WindowEntry>();
|
||||
|
||||
/// <summary>
|
||||
/// 当前是否处于激活状态
|
||||
@@ -65,6 +42,11 @@ namespace XericUI.VisualForm
|
||||
/// </summary>
|
||||
public bool CoordinateDirty { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 上帧锚点世界坐标
|
||||
/// </summary>
|
||||
public Vector3 LastWorldPosition => _lastPosition;
|
||||
|
||||
/// <summary>
|
||||
/// 上帧世界坐标(用于比较变化量)
|
||||
/// </summary>
|
||||
@@ -75,8 +57,6 @@ namespace XericUI.VisualForm
|
||||
/// <summary>
|
||||
/// 从对象池取出时的初始化(Start事件)
|
||||
/// </summary>
|
||||
/// <param name="anchor">关联的锚点</param>
|
||||
/// <param name="dock">关联的锚点坞</param>
|
||||
public void OnStart(WorldAnchor anchor, AnchorDock dock)
|
||||
{
|
||||
ResetState();
|
||||
@@ -84,8 +64,8 @@ namespace XericUI.VisualForm
|
||||
Anchor = anchor;
|
||||
Dock = dock;
|
||||
|
||||
// 解析窗口实例(原型对象或预制体实例化)
|
||||
ResolveWindowInstance();
|
||||
// 解析所有窗口条目(原型对象或预制体实例化)
|
||||
ResolveWindowEntries();
|
||||
|
||||
// 初始化位置记录
|
||||
if (anchor != null)
|
||||
@@ -93,38 +73,42 @@ namespace XericUI.VisualForm
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 解析窗口实例:自动判断窗口对象是原型(已在子项中)还是预制体,并完成实例获取或创建。
|
||||
/// 如果锚点是AnchorWindow且携带窗口对象,则根据是否在坞子项中决定处理方向:
|
||||
/// - 在子项中 → 直接使用该对象作为实例(原型模式)
|
||||
/// - 不在子项中 → 从WindowPool获取或实例化预制体
|
||||
/// 如果锚点不是AnchorWindow或无窗口对象,则不创建实例。
|
||||
/// 解析所有窗口条目:遍历AnchorWindow的WindowEntries,
|
||||
/// 为每个条目判断窗口对象是原型还是预制体,并完成实例获取或创建。
|
||||
/// </summary>
|
||||
public void ResolveWindowInstance()
|
||||
public void ResolveWindowEntries()
|
||||
{
|
||||
if (Dock == null || Anchor == null) return;
|
||||
|
||||
var anchorWindow = Anchor as AnchorWindow;
|
||||
if (anchorWindow == null || anchorWindow.WindowObject == null)
|
||||
if (anchorWindow == null || anchorWindow.WindowEntries.Count == 0)
|
||||
return;
|
||||
|
||||
_windowObject = anchorWindow.WindowObject;
|
||||
Entries.Clear();
|
||||
|
||||
// 通过锚点坞的哈希检查窗口对象是否在子项中
|
||||
_isPrefab = !Dock.IsChildObject(_windowObject);
|
||||
|
||||
if (_isPrefab)
|
||||
foreach (var srcEntry in anchorWindow.WindowEntries)
|
||||
{
|
||||
// 预制体:从对象池获取或创建实例,挂到坞下
|
||||
_instance = WindowPool.Get(_windowObject, Dock.transform);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 原型:已在子项中的实例对象,直接引用
|
||||
_instance = _windowObject;
|
||||
}
|
||||
if (srcEntry == null || srcEntry.WindowObject == null)
|
||||
continue;
|
||||
|
||||
// 同步标记到AnchorWindow
|
||||
anchorWindow.IsPrefab = _isPrefab;
|
||||
var entry = srcEntry; // 直接复用WindowEntry引用,运行时状态写回
|
||||
|
||||
// 通过锚点坞的哈希检查窗口对象是否在子项中
|
||||
entry.IsPrefab = !Dock.IsChildObject(entry.WindowObject);
|
||||
|
||||
if (entry.IsPrefab)
|
||||
{
|
||||
// 预制体:从对象池获取或创建实例,挂到坞下
|
||||
entry.Instance = WindowPool.Get(entry.WindowObject, Dock.transform);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 原型:已在子项中的实例对象,直接引用
|
||||
entry.Instance = entry.WindowObject;
|
||||
}
|
||||
|
||||
Entries.Add(entry);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -134,12 +118,16 @@ namespace XericUI.VisualForm
|
||||
{
|
||||
IsEnabled = true;
|
||||
|
||||
// 如果实例尚不存在(如纯WorldAnchor没有窗口对象),尝试解析
|
||||
if (_instance == null)
|
||||
ResolveWindowInstance();
|
||||
// 确保窗口条目已解析
|
||||
if (Entries.Count == 0)
|
||||
ResolveWindowEntries();
|
||||
|
||||
if (_instance != null)
|
||||
_instance.SetActive(true);
|
||||
// 激活所有启用的条目实例
|
||||
foreach (var entry in Entries)
|
||||
{
|
||||
if (entry.Instance != null && entry.Enabled)
|
||||
entry.Instance.SetActive(true);
|
||||
}
|
||||
|
||||
// 激活时强制标记坐标脏,确保下一帧更新位置
|
||||
CoordinateDirty = true;
|
||||
@@ -152,8 +140,11 @@ namespace XericUI.VisualForm
|
||||
{
|
||||
IsEnabled = false;
|
||||
|
||||
if (_instance != null)
|
||||
_instance.SetActive(false);
|
||||
foreach (var entry in Entries)
|
||||
{
|
||||
if (entry.Instance != null)
|
||||
entry.Instance.SetActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -161,12 +152,17 @@ namespace XericUI.VisualForm
|
||||
/// </summary>
|
||||
public void OnEnd()
|
||||
{
|
||||
// 回收预制体实例到对象池
|
||||
if (_isPrefab && _instance != null)
|
||||
// 回收所有预制体实例到对象池
|
||||
foreach (var entry in Entries)
|
||||
{
|
||||
WindowPool.Release(_windowObject, _instance);
|
||||
if (entry.IsPrefab && entry.Instance != null)
|
||||
WindowPool.Release(entry.WindowObject, entry.Instance);
|
||||
|
||||
entry.Instance = null;
|
||||
entry.IsPrefab = false;
|
||||
}
|
||||
|
||||
Entries.Clear();
|
||||
ResetState();
|
||||
}
|
||||
|
||||
@@ -181,9 +177,6 @@ namespace XericUI.VisualForm
|
||||
{
|
||||
Anchor = null;
|
||||
Dock = null;
|
||||
_windowObject = null;
|
||||
_instance = null;
|
||||
_isPrefab = false;
|
||||
IsEnabled = false;
|
||||
CoordinateDirty = false;
|
||||
_lastPosition = Vector3.zero;
|
||||
@@ -193,7 +186,6 @@ namespace XericUI.VisualForm
|
||||
/// 检查锚点坐标是否发生变化,超过阈值则标记脏
|
||||
/// 由锚点坞在每帧调用
|
||||
/// </summary>
|
||||
/// <param name="threshold">变化阈值</param>
|
||||
public void CheckPositionDirty(float threshold)
|
||||
{
|
||||
if (Anchor == null) return;
|
||||
@@ -207,18 +199,30 @@ namespace XericUI.VisualForm
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前需要定位的Transform目标(实例化的窗口对象或锚点自身)
|
||||
/// 获取第一个有效窗口条目的Transform(兼容旧API)
|
||||
/// </summary>
|
||||
/// <returns>目标Transform</returns>
|
||||
public Transform GetTargetTransform()
|
||||
{
|
||||
if (_instance != null)
|
||||
return _instance.transform;
|
||||
foreach (var entry in Entries)
|
||||
{
|
||||
if (entry.Instance != null)
|
||||
return entry.Instance.transform;
|
||||
}
|
||||
if (Anchor != null)
|
||||
return Anchor.CachedTransform;
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取所有需要定位的Transform
|
||||
/// </summary>
|
||||
public IEnumerable<Transform> GetAllTargetTransforms()
|
||||
{
|
||||
foreach (var entry in Entries)
|
||||
if (entry.Instance != null)
|
||||
yield return entry.Instance.transform;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user