From 0c3b79b22b223355c412989ec1febed9a955f7b2 Mon Sep 17 00:00:00 2001
From: lrc <571244399@qq.com>
Date: Sun, 26 Jul 2026 16:49:32 +0800
Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E7=AA=97=E5=8F=A3=E4=BB=BB?=
=?UTF-8?q?=E5=8A=A1=E6=A0=8F=E5=8A=9F=E8=83=BD=EF=BC=8C=E6=B7=BB=E5=8A=A0?=
=?UTF-8?q?=E7=AA=97=E5=8F=A3=E7=9A=84=E7=AE=A1=E7=90=86=E5=8A=9F=E8=83=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Editor/Form/UIFormControllerEditor.cs | 68 +-
Editor/Form/UITaskBarEditor.cs | 40 +
Editor/Form/UITaskBarEditor.cs.meta | 11 +
Editor/Form/UITitleBarEditor.cs | 14 +-
Runtime/Form/Controllers/UIFormController.cs | 343 ++---
Runtime/Form/Controllers/UITaskBar.cs | 91 ++
Runtime/Form/Controllers/UITaskBar.cs.meta | 11 +
Runtime/Form/Controllers/UITaskBarItem.cs | 108 ++
.../Form/Controllers/UITaskBarItem.cs.meta | 11 +
Runtime/Form/Controllers/UITitleBar.cs | 42 +-
Runtime/Form/UIFormManager.cs | 414 +++---
Runtime/Form/WindowEntry.cs | 102 ++
Runtime/Form/WindowEntry.cs.meta | 11 +
Runtime/Prefab.meta | 8 +
Runtime/Prefab/Form.meta | 8 +
Runtime/Prefab/Form/Window Title.prefab | 1116 +++++++++++++++++
Runtime/Prefab/Form/Window Title.prefab.meta | 7 +
17 files changed, 1905 insertions(+), 500 deletions(-)
create mode 100644 Editor/Form/UITaskBarEditor.cs
create mode 100644 Editor/Form/UITaskBarEditor.cs.meta
create mode 100644 Runtime/Form/Controllers/UITaskBar.cs
create mode 100644 Runtime/Form/Controllers/UITaskBar.cs.meta
create mode 100644 Runtime/Form/Controllers/UITaskBarItem.cs
create mode 100644 Runtime/Form/Controllers/UITaskBarItem.cs.meta
create mode 100644 Runtime/Form/WindowEntry.cs
create mode 100644 Runtime/Form/WindowEntry.cs.meta
create mode 100644 Runtime/Prefab.meta
create mode 100644 Runtime/Prefab/Form.meta
create mode 100644 Runtime/Prefab/Form/Window Title.prefab
create mode 100644 Runtime/Prefab/Form/Window Title.prefab.meta
diff --git a/Editor/Form/UIFormControllerEditor.cs b/Editor/Form/UIFormControllerEditor.cs
index fb99b95..aa64846 100644
--- a/Editor/Form/UIFormControllerEditor.cs
+++ b/Editor/Form/UIFormControllerEditor.cs
@@ -1,5 +1,6 @@
using UnityEditor;
using UnityEngine;
+using XericUI.Form;
namespace XericUIEditor.Form
{
@@ -24,8 +25,6 @@ namespace XericUIEditor.Form
serializedObject.ApplyModifiedProperties();
}
- #region 基本设置
-
private void DrawBasicSection()
{
EditorGUILayout.LabelField("窗口基本设置", EditorStyles.boldLabel);
@@ -33,10 +32,6 @@ namespace XericUIEditor.Form
EditorGUILayout.Space();
}
- #endregion
-
- #region 边缘行为
-
private void DrawEdgeSection()
{
EditorGUILayout.LabelField("边缘吸附", EditorStyles.boldLabel);
@@ -58,10 +53,6 @@ namespace XericUIEditor.Form
EditorGUILayout.Space();
}
- #endregion
-
- #region 调试与测试
-
private void DrawDebugSection()
{
EditorGUILayout.LabelField("调试", EditorStyles.boldLabel);
@@ -72,74 +63,49 @@ namespace XericUIEditor.Form
// 当前状态
EditorGUILayout.LabelField("当前状态", EditorStyles.boldLabel);
-
var state = _controller.CurrentState;
- Color stateColor;
- string stateText;
-
- switch (state)
+ Color stateColor = state switch
{
- case XericUI.Form.WindowState.Normal:
- stateColor = Color.white;
- stateText = "● 窗口化 (Normal)";
- break;
- case XericUI.Form.WindowState.Maximized:
- stateColor = Color.green;
- stateText = "■ 全屏 (Maximized)";
- break;
- case XericUI.Form.WindowState.Minimized:
- stateColor = Color.gray;
- stateText = "○ 最小化 (Minimized)";
- break;
- case XericUI.Form.WindowState.EdgeHidden:
- stateColor = new Color(1f, 0.6f, 0f);
- stateText = "◄ 边缘隐藏 (Edge Hidden)";
- break;
- default:
- stateColor = Color.white;
- stateText = state.ToString();
- break;
- }
+ XericUI.Form.WindowState.Normal => Color.white,
+ XericUI.Form.WindowState.Maximized => Color.green,
+ XericUI.Form.WindowState.Minimized => Color.gray,
+ XericUI.Form.WindowState.EdgeHidden => new Color(1f, 0.6f, 0f),
+ _ => Color.white
+ };
+ var entries = _controller.Manager?.GetAllEntries();
+ WindowEntry entry = _controller.Entry;
+ string extra = entry != null ? $" | ID={entry.Id}" : "";
GUI.color = stateColor;
- EditorGUILayout.LabelField(stateText, EditorStyles.miniBoldLabel);
+ EditorGUILayout.LabelField($"{state}{extra}", EditorStyles.miniBoldLabel);
GUI.color = Color.white;
EditorGUILayout.Space();
- // 手动测试按钮
+ // 手动测试
EditorGUILayout.LabelField("手动测试", EditorStyles.boldLabel);
-
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("全屏/还原"))
{
_controller.ToggleMaximize();
SceneView.RepaintAll();
}
- if (GUILayout.Button("模拟进入"))
+ if (GUILayout.Button("置顶 (Focus)"))
{
- _controller.SimulateEnter();
- SceneView.RepaintAll();
- }
- if (GUILayout.Button("模拟退出"))
- {
- _controller.SimulateExit();
+ _controller.MoveToFront();
SceneView.RepaintAll();
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space();
- // 调试提示
if (!Application.isPlaying && _controller.DebugMode)
{
EditorGUILayout.HelpBox(
- "调试模式已启用 — 在 SceneView 中移动鼠标即可预览。\n" +
- "蓝色边框 = 窗口范围 | 绿色 = 鼠标悬停中 | 橙色 = 吸附阈值范围",
+ "调试模式已启用 — SceneView 中移动鼠标实时预览。\n" +
+ "蓝色边框=窗口范围 | 绿色=鼠标悬停中",
MessageType.Info);
}
}
-
- #endregion
}
}
diff --git a/Editor/Form/UITaskBarEditor.cs b/Editor/Form/UITaskBarEditor.cs
new file mode 100644
index 0000000..472072e
--- /dev/null
+++ b/Editor/Form/UITaskBarEditor.cs
@@ -0,0 +1,40 @@
+using UnityEditor;
+using UnityEngine;
+
+namespace XericUIEditor.Form
+{
+ [CustomEditor(typeof(XericUI.Form.UITaskBar))]
+ public class UITaskBarEditor : Editor
+ {
+ public override void OnInspectorGUI()
+ {
+ serializedObject.Update();
+
+ EditorGUILayout.LabelField("任务栏绑定", EditorStyles.boldLabel);
+ EditorGUILayout.PropertyField(serializedObject.FindProperty("m_Manager"), new GUIContent("窗口管理器 (Manager)"));
+ EditorGUILayout.PropertyField(serializedObject.FindProperty("m_ItemPrefab"), new GUIContent("图标预制体 (Item Prefab)"));
+ EditorGUILayout.PropertyField(serializedObject.FindProperty("m_ItemsContainer"), new GUIContent("图标容器 (Container)"));
+
+ serializedObject.ApplyModifiedProperties();
+ }
+ }
+
+ [CustomEditor(typeof(XericUI.Form.UITaskBarItem))]
+ public class UITaskBarItemEditor : Editor
+ {
+ public override void OnInspectorGUI()
+ {
+ serializedObject.Update();
+
+ EditorGUILayout.LabelField("任务栏图标项控件", EditorStyles.boldLabel);
+
+ EditorGUILayout.PropertyField(serializedObject.FindProperty("m_Icon"), new GUIContent("图标 (Icon)"));
+ EditorGUILayout.PropertyField(serializedObject.FindProperty("m_TitleText"), new GUIContent("标题文本 (Title)"));
+ EditorGUILayout.PropertyField(serializedObject.FindProperty("m_ProgressBar"), new GUIContent("进度条 (Progress Bar)"));
+ EditorGUILayout.PropertyField(serializedObject.FindProperty("m_Highlight"), new GUIContent("聚焦高亮 (Highlight)"));
+ EditorGUILayout.PropertyField(serializedObject.FindProperty("m_Button"), new GUIContent("按钮 (Button)"));
+
+ serializedObject.ApplyModifiedProperties();
+ }
+ }
+}
diff --git a/Editor/Form/UITaskBarEditor.cs.meta b/Editor/Form/UITaskBarEditor.cs.meta
new file mode 100644
index 0000000..d0f6a15
--- /dev/null
+++ b/Editor/Form/UITaskBarEditor.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 0dfbe31f222f10a4883ad6016cdad32b
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/Form/UITitleBarEditor.cs b/Editor/Form/UITitleBarEditor.cs
index e458dd0..3c07fd8 100644
--- a/Editor/Form/UITitleBarEditor.cs
+++ b/Editor/Form/UITitleBarEditor.cs
@@ -6,26 +6,20 @@ namespace XericUIEditor.Form
[CustomEditor(typeof(XericUI.Form.UITitleBar))]
public class UITitleBarEditor : Editor
{
- private XericUI.Form.UITitleBar _titleBar;
-
- private void OnEnable()
- {
- _titleBar = (XericUI.Form.UITitleBar)target;
- }
-
public override void OnInspectorGUI()
{
serializedObject.Update();
EditorGUILayout.LabelField("标题栏控件引用", EditorStyles.boldLabel);
EditorGUILayout.HelpBox(
- "将标题栏下的子控件拖入下方槽位即可。\n" +
- "UITitleBar 会在 Start 时自动向上查找父级的 UIFormController 并绑定事件。",
+ "将标题栏下的子控件拖入下方槽位。\n" +
+ "UITitleBar 在 Start 时向上查找父级 UIFormController 并绑定事件。",
MessageType.Info);
+ EditorGUILayout.PropertyField(serializedObject.FindProperty("m_IconImage"), new GUIContent("窗口图标 (Icon Image)"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("m_TitleText"), new GUIContent("标题文本 (Title Text)"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("m_CloseButton"), new GUIContent("关闭按钮 (Close)"));
- EditorGUILayout.PropertyField(serializedObject.FindProperty("m_MaximizeButton"), new GUIContent("最大化按钮 (Maximize)"));
+ EditorGUILayout.PropertyField(serializedObject.FindProperty("m_MaximizeToggle"), new GUIContent("最大化 Toggle (Maximize)"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("m_MinimizeButton"), new GUIContent("最小化按钮 (Minimize)"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("m_AutoSnapToggle"), new GUIContent("吸附开关 (Auto Snap)"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("m_AutoHideToggle"), new GUIContent("隐藏开关 (Auto Hide)"));
diff --git a/Runtime/Form/Controllers/UIFormController.cs b/Runtime/Form/Controllers/UIFormController.cs
index 7ba8998..f5f00d2 100644
--- a/Runtime/Form/Controllers/UIFormController.cs
+++ b/Runtime/Form/Controllers/UIFormController.cs
@@ -7,7 +7,6 @@ namespace XericUI.Form
{
#region 枚举与结构体
- /// 范围坐标空间枚举
public enum FormRangeSpace
{
RelativeOffset,
@@ -22,7 +21,7 @@ namespace XericUI.Form
[Tooltip("坐标空间")]
public FormRangeSpace space;
- [Tooltip("范围定义。\nRelativeOffset: x,y=像素偏移; w,h=像素宽高(0=用参考尺寸)\nCanvasLocal: Canvas局部坐标\nAnchorToSelf: x,y=锚点0-1; w,h=尺寸比例0-1\nAnchorToCanvas: x,y=锚点0-1; w,h=尺寸比例0-1")]
+ [Tooltip("范围定义")]
public Rect rect;
}
@@ -30,31 +29,31 @@ namespace XericUI.Form
///
/// UI 窗体控制器 — 挂载到窗口根 GameObject 上,自身即为完整窗口。
- /// 支持全屏/还原、边缘吸附、自动隐藏、拖拽移动。
- /// 标题栏功能由独立的 UITitleBar 子组件提供,Controller 只提供公开 API。
+ /// 支持全屏/还原、边缘吸附、自动隐藏、拖拽移动、置顶。
+ /// 通过 WindowEntry 与 Manager 通信。
///
[AddComponentMenu("Xeric UI Vessel/Form/UI Form Controller")]
[RequireComponent(typeof(RectTransform))]
- public class UIFormController : MonoBehaviour, IUIFormTarget, IBeginDragHandler, IDragHandler, IEndDragHandler
+ public class UIFormController : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler, IPointerDownHandler
{
#region 序列化字段
[Header("窗口基本设置")]
- [SerializeField, Tooltip("窗口标题,供外部读取")]
+ [SerializeField, Tooltip("窗口标题")]
private string m_WindowTitle = "Window";
[Header("边缘吸附")]
- [SerializeField, Tooltip("是否启用边缘自动吸附")]
+ [SerializeField, Tooltip("启用边缘自动吸附")]
private bool m_EnableAutoSnap = true;
- [SerializeField, Tooltip("吸附阈值(像素),窗口距边缘小于此值时自动贴边")]
+ [SerializeField, Tooltip("吸附阈值(像素)")]
private float m_SnapThreshold = 8f;
[Header("自动隐藏")]
- [SerializeField, Tooltip("是否启用自动隐藏(贴边后滑出屏幕)")]
+ [SerializeField, Tooltip("启用自动隐藏")]
private bool m_EnableAutoHide;
- [SerializeField, Tooltip("自动隐藏的滑动方向")]
+ [SerializeField, Tooltip("自动隐藏滑动方向")]
private AutoHideDirection m_AutoHideDirection = AutoHideDirection.Left;
[Header("调试")]
@@ -69,28 +68,29 @@ namespace XericUI.Form
#region 公开属性
public string WindowTitle => m_WindowTitle;
-
- /// 是否处于全屏状态
public bool IsMaximized => _windowState == WindowState.Maximized;
-
- /// 是否处于边缘隐藏状态
public bool IsEdgeHidden => _windowState == WindowState.EdgeHidden;
-
- /// 当前窗口状态
public WindowState CurrentState => _windowState;
-
- /// 自动吸附是否开启
public bool AutoSnapEnabled => m_EnableAutoSnap;
-
- /// 自动隐藏是否开启
public bool AutoHideEnabled => m_EnableAutoHide;
-
- /// 自动隐藏方向
public AutoHideDirection HideDirection => m_AutoHideDirection;
-
- /// 编辑器调试模式
public bool DebugMode => m_DebugMode;
+ /// 窗口数据 Entry(由 Manager 在 CreateWindow 时注入)
+ public WindowEntry Entry
+ {
+ get => _entry;
+ set
+ {
+ _entry = value;
+ if (_entry != null)
+ m_WindowTitle = _entry.Title;
+ }
+ }
+
+ /// 父级 Manager 引用
+ public UIFormManager Manager => _manager;
+
#endregion
#region 内部状态
@@ -98,13 +98,15 @@ namespace XericUI.Form
private RectTransform _rectTransform;
private Canvas _canvas;
private RectTransform _canvasRt;
+ private UIFormManager _manager;
+ private WindowEntry _entry;
private WindowState _windowState = WindowState.Normal;
// 拖拽
private Vector2 _dragOffset;
- // 全屏还原数据
+ // 全屏还原
private Vector2 _savePos;
private Vector2 _saveSize;
private Vector2 _saveAnchorMin;
@@ -125,110 +127,72 @@ namespace XericUI.Form
protected virtual void Awake()
{
_rectTransform = (RectTransform)transform;
+ _manager = GetComponentInParent();
_canvas = GetComponentInParent