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(); _canvasRt = _canvas != null ? (RectTransform)_canvas.transform : null; } protected virtual void OnEnable() { - if (UIFormManager.Main != null) - UIFormManager.Main.RegisterWindow(this); } protected virtual void OnDisable() { StopAutoHideMonitor(); - if (_windowState == WindowState.EdgeHidden && UIFormManager.Main != null) - UIFormManager.Main.UnregisterEdgeHidden(this); - - if (UIFormManager.Main != null) - { - UIFormManager.Main.UnregisterWindow(this); - UIFormManager.Main.UnregisterEdgeHidden(this); - } + if (_windowState == WindowState.EdgeHidden && _manager != null) + _manager.UnregisterEdgeHidden(_entry); +#if UNITY_EDITOR UnsubscribeEditorUpdate(); +#endif _isHovering = false; } #endregion - #region IUIFormTarget 实现 + #region === 公开 API === - public bool IsActive => isActiveAndEnabled; - - public Rect GetEnterRect() => GetWindowScreenRect(); - public Rect GetExitRect() => GetWindowScreenRect(); - - public void OnPointerEnter() - { - if (m_DebugLogEvents) - Debug.Log($"[UIFormController] 鼠标进入窗口范围: {name}", this); - } - - public void OnPointerExit() - { - if (m_DebugLogEvents) - Debug.Log($"[UIFormController] 鼠标离开窗口范围: {name}", this); - } - - #endregion - - #region === 公开 API(供 UITitleBar 及外部调用) === - - /// 全屏/还原切换 public void ToggleMaximize() { if (IsMaximized) RestoreFromFullscreen(); else MaximizeToFullscreen(); + + if (_entry != null) + _entry.State = _windowState; } - /// 最小化窗口 public void Minimize() { if (_windowState == WindowState.Minimized) return; - if (UIFormManager.Main == null) return; - - UIFormManager.Main.MinimizeWindow(this); + if (_manager == null || _entry == null) return; + _manager.MinimizeWindow(_entry.Id); } - /// 关闭窗口(Destroy GameObject) public void Close() { - if (UIFormManager.Main != null) - UIFormManager.Main.CloseWindow(this); - - if (Application.isPlaying) + if (_manager != null && _entry != null) + _manager.DestroyWindow(_entry.Id); + else if (Application.isPlaying) Destroy(gameObject); - else - DestroyImmediate(gameObject); } - /// 设置边缘吸附开关 - public void SetAutoSnapEnabled(bool enabled) - { - m_EnableAutoSnap = enabled; - } - - /// 设置自动隐藏开关 + public void SetAutoSnapEnabled(bool enabled) => m_EnableAutoSnap = enabled; public void SetAutoHideEnabled(bool enabled) { m_EnableAutoHide = enabled; - if (!enabled && _windowState == WindowState.EdgeHidden) - { - // 关闭自动隐藏 → 还原窗口 SlideInFromEdge(); - } } - /// 设置自动隐藏方向 - public void SetAutoHideDirection(AutoHideDirection direction) + public void SetAutoHideDirection(AutoHideDirection direction) => m_AutoHideDirection = direction; + + /// 置顶窗口 + public void MoveToFront() { - m_AutoHideDirection = direction; + transform.SetAsLastSibling(); } #endregion @@ -250,9 +214,6 @@ namespace XericUI.Form _rectTransform.offsetMax = Vector2.zero; _windowState = WindowState.Maximized; - - if (m_DebugLogEvents) - Debug.Log($"[UIFormController] 窗口全屏: {name}", this); } private void RestoreFromFullscreen() @@ -265,25 +226,27 @@ namespace XericUI.Form _rectTransform.sizeDelta = _saveSize; _windowState = WindowState.Normal; - - if (m_DebugLogEvents) - Debug.Log($"[UIFormController] 窗口还原: {name}", this); } #endregion - #region === 拖拽 === + #region === 拖拽 & 点击聚焦 === + + public void OnPointerDown(PointerEventData eventData) + { + // 点击窗口任意位置 → 置顶 + transform.SetAsLastSibling(); + if (_manager != null && _entry != null) + _manager.MoveToFront(_entry.Id); + } public void OnBeginDrag(PointerEventData eventData) { - if (_windowState == WindowState.EdgeHidden || _windowState == WindowState.Minimized) - return; + if (_windowState == WindowState.EdgeHidden || _windowState == WindowState.Minimized) return; - // 全屏拖拽 → 先还原 if (IsMaximized) { RestoreFromFullscreen(); - // 将窗口移到鼠标附近 _rectTransform.anchoredPosition = eventData.position; } @@ -292,8 +255,7 @@ namespace XericUI.Form public void OnDrag(PointerEventData eventData) { - if (_windowState == WindowState.EdgeHidden || _windowState == WindowState.Minimized) - return; + if (_windowState == WindowState.EdgeHidden || _windowState == WindowState.Minimized) return; _rectTransform.anchoredPosition = eventData.position + _dragOffset; @@ -303,14 +265,10 @@ namespace XericUI.Form public void OnEndDrag(PointerEventData eventData) { - if (_windowState == WindowState.EdgeHidden || _windowState == WindowState.Minimized) - return; + if (_windowState == WindowState.EdgeHidden || _windowState == WindowState.Minimized) return; - // 拖拽结束 → 如果贴边且启用自动隐藏,则触发 if (m_EnableAutoHide && IsSnappedToEdge()) - { AutoHideToEdge(); - } } #endregion @@ -320,54 +278,35 @@ namespace XericUI.Form private void CheckEdgeSnap() { if (_canvasRt == null) return; - Vector2 canvasSize = _canvasRt.rect.size; Vector2 pos = _rectTransform.anchoredPosition; Vector2 size = _rectTransform.rect.size; - bool snapped = false; - - // 左 if (Mathf.Abs(pos.x) < m_SnapThreshold) - { pos.x = 0; - snapped = true; - } - // 右 else if (Mathf.Abs(pos.x + size.x - canvasSize.x) < m_SnapThreshold) - { pos.x = canvasSize.x - size.x; - snapped = true; - } _rectTransform.anchoredPosition = pos; } - /// 检测窗口是否贴边 private bool IsSnappedToEdge() { if (_canvasRt == null) return false; - Vector2 canvasSize = _canvasRt.rect.size; Vector2 pos = _rectTransform.anchoredPosition; Vector2 size = _rectTransform.rect.size; - - return Mathf.Abs(pos.x) < 1f - || Mathf.Abs(pos.x + size.x - canvasSize.x) < 1f; + return Mathf.Abs(pos.x) < 1f || Mathf.Abs(pos.x + size.x - canvasSize.x) < 1f; } - /// 获取最近的边缘方向 public AutoHideDirection GetClosestEdge() { if (_canvasRt == null) return AutoHideDirection.Left; - Vector2 canvasSize = _canvasRt.rect.size; Vector2 pos = _rectTransform.anchoredPosition; Vector2 size = _rectTransform.rect.size; - float distLeft = Mathf.Abs(pos.x); float distRight = Mathf.Abs(pos.x + size.x - canvasSize.x); - return distLeft < distRight ? AutoHideDirection.Left : AutoHideDirection.Right; } @@ -377,8 +316,7 @@ namespace XericUI.Form private void AutoHideToEdge() { - if (_windowState == WindowState.EdgeHidden) return; - if (_canvasRt == null) return; + if (_windowState == WindowState.EdgeHidden || _canvasRt == null) return; Vector2 canvasSize = _canvasRt.rect.size; Vector2 pos = _rectTransform.anchoredPosition; @@ -390,58 +328,40 @@ namespace XericUI.Form if (dir == AutoHideDirection.Left || dir == AutoHideDirection.Right) dir = GetClosestEdge(); - switch (dir) + _edgeHiddenPos = dir switch { - case AutoHideDirection.Left: - _edgeHiddenPos = new Vector2(-size.x, pos.y); - break; - case AutoHideDirection.Right: - _edgeHiddenPos = new Vector2(canvasSize.x, pos.y); - break; - case AutoHideDirection.Down: - _edgeHiddenPos = new Vector2(pos.x, -size.y); - break; - case AutoHideDirection.Up: - _edgeHiddenPos = new Vector2(pos.x, canvasSize.y); - break; - } + AutoHideDirection.Left => new Vector2(-size.x, pos.y), + AutoHideDirection.Right => new Vector2(canvasSize.x, pos.y), + AutoHideDirection.Down => new Vector2(pos.x, -size.y), + AutoHideDirection.Up => new Vector2(pos.x, canvasSize.y), + _ => pos + }; _rectTransform.anchoredPosition = _edgeHiddenPos; _windowState = WindowState.EdgeHidden; - if (UIFormManager.Main != null) - UIFormManager.Main.RegisterEdgeHidden(this, dir); - - if (m_DebugLogEvents) - Debug.Log($"[UIFormController] 自动隐藏 (方向={dir}): {name}", this); + if (_manager != null && _entry != null) + _manager.RegisterEdgeHidden(_entry, dir); } - /// 由 Manager 调用 — 从边缘滑出 public void SlideInFromEdge() { if (_windowState != WindowState.EdgeHidden) return; - StopAutoHideMonitor(); _rectTransform.anchoredPosition = _edgeVisiblePos; _windowState = WindowState.Normal; - if (UIFormManager.Main != null) - UIFormManager.Main.UnregisterEdgeHidden(this); + if (_manager != null) + _manager.UnregisterEdgeHidden(_entry); - // 开始监控鼠标是否离开窗口 _autoHideCoroutine = StartCoroutine(MonitorMouseExit()); - - if (m_DebugLogEvents) - Debug.Log($"[UIFormController] 从边缘滑出: {name}", this); } - /// 监控鼠标是否离开窗口范围,离开则自动隐藏 private IEnumerator MonitorMouseExit() { while (_windowState == WindowState.Normal && m_EnableAutoHide) { yield return null; - Rect screenRect = GetWindowScreenRect(); if (!screenRect.Contains(Input.mousePosition)) { @@ -464,82 +384,29 @@ namespace XericUI.Form #region === 窗口屏幕范围 === - /// 获取窗口自身在屏幕空间中的 Rect public Rect GetWindowScreenRect() { if (_rectTransform == null || _canvas == null) return Rect.zero; - Vector3[] corners = new Vector3[4]; _rectTransform.GetWorldCorners(corners); - Camera cam = _canvas.renderMode == RenderMode.ScreenSpaceOverlay ? null : _canvas.worldCamera; - - Vector2 min = Vector2.positiveInfinity; - Vector2 max = Vector2.negativeInfinity; - + Vector2 min = Vector2.positiveInfinity, max = Vector2.negativeInfinity; for (int i = 0; i < 4; i++) { Vector2 sp = cam != null ? RectTransformUtility.WorldToScreenPoint(cam, corners[i]) : (Vector2)corners[i]; - min = Vector2.Min(min, sp); max = Vector2.Max(max, sp); } - return new Rect(min.x, min.y, max.x - min.x, max.y - min.y); } #endregion - #region === 悬停检测(供 Manager 调用) === - - public bool CheckHover(Vector2 screenPoint) - { - Rect windowRect = GetWindowScreenRect(); - - if (!_isHovering) - { - if (windowRect.Contains(screenPoint)) - { - _isHovering = true; - OnPointerEnter(); - } - } - else - { - if (!windowRect.Contains(screenPoint)) - { - _isHovering = false; - OnPointerExit(); - } - } - - return _isHovering; - } - - public void SimulateEnter() - { - _isHovering = true; - - if (m_DebugLogEvents) - Debug.Log($"[UIFormController] 模拟进入: {name}", this); - } - - public void SimulateExit() - { - _isHovering = false; - - if (m_DebugLogEvents) - Debug.Log($"[UIFormController] 模拟退出: {name}", this); - } - - #endregion - #region 编辑器调试 #if UNITY_EDITOR - [System.NonSerialized] private bool _editorDebugSubscribed; [System.NonSerialized] private Vector2 _editorMouseScreenPos; @@ -559,87 +426,53 @@ namespace XericUI.Form protected virtual void OnValidate() { - if (m_DebugMode) - SubscribeEditorUpdate(); - else - UnsubscribeEditorUpdate(); + if (m_DebugMode) SubscribeEditorUpdate(); + else UnsubscribeEditorUpdate(); } - /// - /// SceneView 重绘回调 — 在 GUI 上下文中获取鼠标屏幕坐标并执行悬停检测。 - /// 使用 GUIUtility.GUIToScreenPoint 将 SceneView 内的 GUI 坐标转为 Unity 屏幕坐标。 - /// private void OnSceneGUI(UnityEditor.SceneView sceneView) { - if (this == null) - { - UnsubscribeEditorUpdate(); - return; - } + if (this == null) { UnsubscribeEditorUpdate(); return; } + if (Application.isPlaying || !m_DebugMode) return; - if (Application.isPlaying) return; - if (!m_DebugMode) return; - - // Event.current.mousePosition 是相对于 SceneView 窗口的 GUI 坐标 - // GUIUtility.GUIToScreenPoint 将其转换为屏幕坐标(左下角为原点) Vector2 guiPos = Event.current.mousePosition; _editorMouseScreenPos = GUIUtility.GUIToScreenPoint(guiPos); - CheckHover(_editorMouseScreenPos); + Rect rect = GetWindowScreenRect(); + _isHovering = rect.Contains(_editorMouseScreenPos); } protected virtual void OnDrawGizmosSelected() { - if (!m_DebugMode) return; - if (_canvas == null) return; - if (_canvasRt == null) return; - + if (!m_DebugMode || _canvas == null || _canvasRt == null) return; Rect screenRect = GetWindowScreenRect(); if (screenRect.width <= 0 || screenRect.height <= 0) return; - // 悬停时高亮边框 Color borderColor = _isHovering ? new Color(0f, 1f, 0f, 0.6f) : new Color(0f, 0.7f, 1f, 0.3f); - Gizmos.color = borderColor; DrawScreenRectOnCanvas(screenRect, borderColor, _canvas, _canvasRt); - - // 边缘吸附阈值可视化 - if (m_EnableAutoSnap) - { - Gizmos.color = new Color(1f, 0.6f, 0f, 0.15f); - DrawScreenRectOnCanvas( - new Rect(screenRect.x + m_SnapThreshold, screenRect.y, - screenRect.width - m_SnapThreshold * 2, screenRect.height), - Gizmos.color, _canvas, _canvasRt); - } } private static void DrawScreenRectOnCanvas(Rect screenRect, Color color, Canvas canvas, RectTransform canvasRt) { if (screenRect.width <= 0 || screenRect.height <= 0) return; - Gizmos.color = color; Camera uiCam = canvas.renderMode == RenderMode.ScreenSpaceOverlay ? null : canvas.worldCamera; - - Vector3 p0 = ScreenToWorldOnCanvas(new Vector3(screenRect.xMin, screenRect.yMin), uiCam, canvasRt); - Vector3 p1 = ScreenToWorldOnCanvas(new Vector3(screenRect.xMax, screenRect.yMin), uiCam, canvasRt); - Vector3 p2 = ScreenToWorldOnCanvas(new Vector3(screenRect.xMax, screenRect.yMax), uiCam, canvasRt); - Vector3 p3 = ScreenToWorldOnCanvas(new Vector3(screenRect.xMin, screenRect.yMax), uiCam, canvasRt); - - Gizmos.DrawLine(p0, p1); - Gizmos.DrawLine(p1, p2); - Gizmos.DrawLine(p2, p3); - Gizmos.DrawLine(p3, p0); + Vector3 p0 = Stw(new Vector3(screenRect.xMin, screenRect.yMin), uiCam, canvasRt); + Vector3 p1 = Stw(new Vector3(screenRect.xMax, screenRect.yMin), uiCam, canvasRt); + Vector3 p2 = Stw(new Vector3(screenRect.xMax, screenRect.yMax), uiCam, canvasRt); + Vector3 p3 = Stw(new Vector3(screenRect.xMin, screenRect.yMax), uiCam, canvasRt); + Gizmos.DrawLine(p0, p1); Gizmos.DrawLine(p1, p2); + Gizmos.DrawLine(p2, p3); Gizmos.DrawLine(p3, p0); } - private static Vector3 ScreenToWorldOnCanvas(Vector3 screenPoint, Camera uiCamera, RectTransform canvasRt) + private static Vector3 Stw(Vector3 sp, Camera cam, RectTransform rt) { - RectTransformUtility.ScreenPointToWorldPointInRectangle(canvasRt, (Vector2)screenPoint, uiCamera, out Vector3 wp); + RectTransformUtility.ScreenPointToWorldPointInRectangle(rt, (Vector2)sp, cam, out Vector3 wp); return wp; } - #endif #endregion diff --git a/Runtime/Form/Controllers/UITaskBar.cs b/Runtime/Form/Controllers/UITaskBar.cs new file mode 100644 index 0000000..4b33c71 --- /dev/null +++ b/Runtime/Form/Controllers/UITaskBar.cs @@ -0,0 +1,91 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace XericUI.Form +{ + /// + /// 任务栏控制器 — 监听 UIFormManager 的窗口创建/销毁/状态变更事件, + /// 动态创建/销毁 UITaskBarItem 图标。 + /// + public class UITaskBar : MonoBehaviour + { + [Header("绑定")] + [SerializeField, Tooltip("窗口管理器引用")] + private UIFormManager m_Manager; + + [SerializeField, Tooltip("任务栏图标项预制体")] + private UITaskBarItem m_ItemPrefab; + + [SerializeField, Tooltip("图标项的父容器")] + private Transform m_ItemsContainer; + + private readonly Dictionary _items = new Dictionary(); + + #region 生命周期 + + private void Start() + { + if (m_Manager == null) + { + Debug.LogError("[UITaskBar] 未绑定 UIFormManager!", this); + return; + } + + m_Manager.OnWindowCreated += OnWindowCreated; + m_Manager.OnWindowDestroyed += OnWindowDestroyed; + m_Manager.OnWindowStateChanged += OnWindowStateChanged; + } + + private void OnDestroy() + { + if (m_Manager != null) + { + m_Manager.OnWindowCreated -= OnWindowCreated; + m_Manager.OnWindowDestroyed -= OnWindowDestroyed; + m_Manager.OnWindowStateChanged -= OnWindowStateChanged; + } + + foreach (var item in _items.Values) + { + if (item != null) + Destroy(item.gameObject); + } + _items.Clear(); + } + + #endregion + + #region 事件回调 + + private void OnWindowCreated(WindowEntry entry) + { + if (entry == null || !entry.ShowInTaskBar) return; + if (m_ItemPrefab == null || m_ItemsContainer == null) return; + + var item = Instantiate(m_ItemPrefab, m_ItemsContainer); + item.Bind(entry, m_Manager); + _items[entry.Id] = item; + } + + private void OnWindowDestroyed(WindowEntry entry) + { + if (entry == null) return; + + if (_items.TryGetValue(entry.Id, out var item)) + { + if (item != null) + Destroy(item.gameObject); + _items.Remove(entry.Id); + } + } + + private void OnWindowStateChanged(WindowEntry entry) + { + if (entry == null) return; + + // 状态变更时触发 Repaint(进度、高亮等由 Item 自己的 Update 处理) + } + + #endregion + } +} diff --git a/Runtime/Form/Controllers/UITaskBar.cs.meta b/Runtime/Form/Controllers/UITaskBar.cs.meta new file mode 100644 index 0000000..abbecb6 --- /dev/null +++ b/Runtime/Form/Controllers/UITaskBar.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 08764fa4decbd8b4b9f16f7236d36baf +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Form/Controllers/UITaskBarItem.cs b/Runtime/Form/Controllers/UITaskBarItem.cs new file mode 100644 index 0000000..c4bbff2 --- /dev/null +++ b/Runtime/Form/Controllers/UITaskBarItem.cs @@ -0,0 +1,108 @@ +using UnityEngine; +using UnityEngine.UI; + +namespace XericUI.Form +{ + /// + /// 任务栏图标项 — 显示单个窗口的图标、标题、进度条和聚焦高亮。 + /// 点击时通过 UIFormManager 切换窗口显示/隐藏并置顶。 + /// + public class UITaskBarItem : MonoBehaviour + { + [Header("控件引用")] + [SerializeField, Tooltip("窗口图标")] + private Image m_Icon; + + [SerializeField, Tooltip("窗口标题文本")] + private Text m_TitleText; + + [SerializeField, Tooltip("进度条 Image(fillAmount)")] + private Image m_ProgressBar; + + [SerializeField, Tooltip("聚焦高亮 Image")] + private Image m_Highlight; + + [SerializeField, Tooltip("按钮组件")] + private Button m_Button; + + private WindowEntry _entry; + private UIFormManager _manager; + + public WindowEntry Entry => _entry; + + #region 初始化 + + public void Bind(WindowEntry entry, UIFormManager manager) + { + _entry = entry; + _manager = manager; + + if (m_Icon != null && entry.Icon != null) + m_Icon.sprite = entry.Icon; + + if (m_Icon != null) + m_Icon.color = entry.TintColor; + + if (m_TitleText != null) + m_TitleText.text = entry.Title; + + if (m_Button != null) + m_Button.onClick.AddListener(OnClick); + + RefreshHighlight(); + RefreshProgress(); + } + + private void OnDestroy() + { + if (m_Button != null) + m_Button.onClick.RemoveListener(OnClick); + } + + #endregion + + #region 交互 + + private void OnClick() + { + if (_entry == null || _manager == null) return; + + _manager.ToggleWindow(_entry.Id); + _manager.MoveToFront(_entry.Id); + } + + #endregion + + #region 每帧同步 + + private void Update() + { + if (_entry == null) return; + + if (m_TitleText != null && m_TitleText.text != _entry.Title) + m_TitleText.text = _entry.Title; + + if (m_Icon != null && m_Icon.color != _entry.TintColor) + m_Icon.color = _entry.TintColor; + + RefreshProgress(); + RefreshHighlight(); + } + + private void RefreshProgress() + { + if (m_ProgressBar == null) return; + m_ProgressBar.fillAmount = _entry.Progress; + m_ProgressBar.gameObject.SetActive(_entry.ShowProgress && _entry.Progress > 0f); + } + + private void RefreshHighlight() + { + if (m_Highlight == null || _manager == null) return; + var focused = _manager.GetFocusedEntry(); + m_Highlight.gameObject.SetActive(focused == _entry); + } + + #endregion + } +} diff --git a/Runtime/Form/Controllers/UITaskBarItem.cs.meta b/Runtime/Form/Controllers/UITaskBarItem.cs.meta new file mode 100644 index 0000000..dc0b6aa --- /dev/null +++ b/Runtime/Form/Controllers/UITaskBarItem.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bf298c8b67bb4d345a69728112b72229 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Form/Controllers/UITitleBar.cs b/Runtime/Form/Controllers/UITitleBar.cs index 52b3b48..e054aea 100644 --- a/Runtime/Form/Controllers/UITitleBar.cs +++ b/Runtime/Form/Controllers/UITitleBar.cs @@ -12,21 +12,23 @@ namespace XericUI.Form { /// /// 窗口标题栏 — 独立子组件,挂载在 UIFormController 的子对象上。 - /// Start 时向上查找父级 UIFormController,绑定按钮事件到其公开 API。 - /// 与窗口完全解耦:Controller 不关心标题栏是否存在。 + /// Start 时向上查找父级 UIFormController,绑定按钮/Toggle 事件到其公开 API。 /// [AddComponentMenu("Xeric UI Vessel/Form/UI Title Bar")] public class UITitleBar : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler { [Header("控件引用")] + [SerializeField, Tooltip("窗口图标")] + private Image m_IconImage; + [SerializeField, Tooltip("标题文本")] private UI_Text m_TitleText; [SerializeField, Tooltip("关闭按钮")] private Button m_CloseButton; - [SerializeField, Tooltip("最大化按钮")] - private Button m_MaximizeButton; + [SerializeField, Tooltip("最大化 Toggle(isOn=全屏)")] + private Toggle m_MaximizeToggle; [SerializeField, Tooltip("最小化按钮")] private Button m_MinimizeButton; @@ -57,9 +59,25 @@ namespace XericUI.Form { if (_controller == null) return; - // 实时同步标题(可能由外部修改) if (m_TitleText != null && m_TitleText.text != _controller.WindowTitle) m_TitleText.text = _controller.WindowTitle; + + // 同步最大化 Toggle 状态 + if (m_MaximizeToggle != null) + { + bool maxed = _controller.IsMaximized; + if (m_MaximizeToggle.isOn != maxed) + m_MaximizeToggle.SetIsOnWithoutNotify(maxed); + } + + // 同步图标 + if (m_IconImage != null && _controller.Entry != null) + { + if (_controller.Entry.Icon != null && m_IconImage.sprite != _controller.Entry.Icon) + m_IconImage.sprite = _controller.Entry.Icon; + if (m_IconImage.color != _controller.Entry.TintColor) + m_IconImage.color = _controller.Entry.TintColor; + } } #region 事件绑定 @@ -69,8 +87,8 @@ namespace XericUI.Form if (m_CloseButton != null) m_CloseButton.onClick.AddListener(() => _controller.Close()); - if (m_MaximizeButton != null) - m_MaximizeButton.onClick.AddListener(() => _controller.ToggleMaximize()); + if (m_MaximizeToggle != null) + m_MaximizeToggle.onValueChanged.AddListener(_ => _controller.ToggleMaximize()); if (m_MinimizeButton != null) m_MinimizeButton.onClick.AddListener(() => _controller.Minimize()); @@ -119,11 +137,21 @@ namespace XericUI.Form if (m_TitleText != null) m_TitleText.text = _controller.WindowTitle; + if (m_MaximizeToggle != null) + m_MaximizeToggle.isOn = _controller.IsMaximized; + if (m_AutoSnapToggle != null) m_AutoSnapToggle.isOn = _controller.AutoSnapEnabled; if (m_AutoHideToggle != null) m_AutoHideToggle.isOn = _controller.AutoHideEnabled; + + // 图标 + if (m_IconImage != null && _controller.Entry != null && _controller.Entry.Icon != null) + { + m_IconImage.sprite = _controller.Entry.Icon; + m_IconImage.color = _controller.Entry.TintColor; + } } #endregion diff --git a/Runtime/Form/UIFormManager.cs b/Runtime/Form/UIFormManager.cs index f02d048..8e19af0 100644 --- a/Runtime/Form/UIFormManager.cs +++ b/Runtime/Form/UIFormManager.cs @@ -4,91 +4,57 @@ using UnityEngine; namespace XericUI.Form { /// - /// UI 窗体管理器 — 窗口管理中心。 - /// 挂载在 Canvas 所在 GameObject 上(或通过代码自动创建), - /// 管理所有窗口的注册、最小化恢复、边缘触发隐藏窗口的显隐调度。 + /// UI 窗体管理器 — 窗口管理中心。挂载在 Canvas 下作为所有窗口的父容器。 + /// 通过 Entry 驱动管理窗口生命周期、层级排序、委托事件发布。 + /// 支持任务栏和边缘触发隐藏窗口。 /// [AddComponentMenu("Xeric UI Vessel/Form/UI Form Manager")] [DefaultExecutionOrder(32000)] public class UIFormManager : MonoBehaviour { [Header("边缘触发")] - [SerializeField, Tooltip("边缘触发区域大小(x=宽度方向,y=高度方向),鼠标进入此区域时触发对应方向隐藏窗口的显示")] + [SerializeField, Tooltip("边缘触发区域大小")] private Vector2 m_EdgeTriggerSize = new Vector2(80, 60); [Header("调试")] [SerializeField, Tooltip("输出事件日志")] private bool m_EnableDebugLog; - #region 静态单例 + #region === 委托事件 === - private static UIFormManager s_Main; + /// 窗口创建 + public event WindowEntryEventHandler OnWindowCreated; - /// 全局单例引用 - public static UIFormManager Main => s_Main; + /// 窗口销毁 + public event WindowEntryEventHandler OnWindowDestroyed; + + /// 窗口状态变更 + public event WindowEntryEventHandler OnWindowStateChanged; + + /// 窗口获得焦点(置顶) + public event WindowEntryEventHandler OnWindowFocused; #endregion - #region 内部状态 + #region === 内部状态 === - // 所有窗口 - private readonly List _windows = new List(); + private readonly Dictionary _entries = new Dictionary(); + private readonly List _orderedEntries = new List(); + private string _focusedEntryId; - // 最小化窗口数据 - private struct MinimizedData + // 边缘隐藏(按方向分组) + private readonly Dictionary> _edgeHidden = new() { - public Vector2 anchoredPosition; - public Vector2 sizeDelta; - public Vector2 anchorMin; - public Vector2 anchorMax; - } - private readonly Dictionary _minimized = new(); - - // 边缘隐藏窗口(按方向分组) - private readonly Dictionary> _edgeHidden = new() - { - { AutoHideDirection.Left, new List() }, - { AutoHideDirection.Right, new List() }, - { AutoHideDirection.Up, new List() }, - { AutoHideDirection.Down, new List() }, + { AutoHideDirection.Left, new List() }, + { AutoHideDirection.Right, new List() }, + { AutoHideDirection.Up, new List() }, + { AutoHideDirection.Down, new List() }, }; - - // 边缘触发状态跟踪(避免重复触发) private AutoHideDirection? _lastEdgeTrigger; #endregion - #region 生命周期 - - protected virtual void Awake() - { - if (s_Main != null && s_Main != this) - { - Debug.LogWarning($"[UIFormManager] 已存在单例,销毁重复实例: {name}", this); - Destroy(this); - return; - } - - s_Main = this; - } - - protected virtual void OnEnable() - { - if (s_Main == null) s_Main = this; - } - - protected virtual void OnDisable() - { - if (s_Main == this) s_Main = null; - } - - protected virtual void OnDestroy() - { - if (s_Main == this) s_Main = null; - _windows.Clear(); - _minimized.Clear(); - foreach (var list in _edgeHidden.Values) list.Clear(); - } + #region === 生命周期 === protected virtual void Update() { @@ -97,64 +63,222 @@ namespace XericUI.Form #endregion - #region === 窗口注册 / 注销 === + #region === 程序化窗口创建 / 销毁 === - public void RegisterWindow(UIFormController window) + /// 程序化创建一个窗口实例并返回其 Entry + public WindowEntry CreateWindow(RectTransform prefab, string title = null, Sprite icon = null) { - if (window == null || _windows.Contains(window)) return; - _windows.Add(window); + if (prefab == null) + { + Debug.LogError("[UIFormManager] CreateWindow: prefab 为空", this); + return null; + } + + var instance = Instantiate(prefab, transform); + instance.name = title ?? prefab.name; + + var controller = instance.GetComponent(); + var entry = new WindowEntry + { + Title = title ?? prefab.name, + Icon = icon, + Prefab = prefab, + Controller = controller, + State = WindowState.Normal, + }; + + if (controller != null) + controller.Entry = entry; + + _entries[entry.Id] = entry; + _orderedEntries.Add(entry); + + MoveToFront(entry.Id); + + NotifyCreated(entry); if (m_EnableDebugLog) - Debug.Log($"[UIFormManager] 注册窗口: {window.name}"); + Debug.Log($"[UIFormManager] 创建窗口: {entry.Title} (ID={entry.Id})"); + + return entry; } - public void UnregisterWindow(UIFormController window) + /// 销毁窗口及其所有子窗口 + public void DestroyWindow(string entryId) { - if (window == null) return; - _windows.Remove(window); - UnregisterEdgeHidden(window); - _minimized.Remove(window); + if (!_entries.TryGetValue(entryId, out var entry)) return; - if (m_EnableDebugLog) - Debug.Log($"[UIFormManager] 注销窗口: {window.name}"); + // 级联关闭子窗口 + CascadeCloseChildren(entry); + + UnregisterEdgeHiddenForEntry(entry); + + _orderedEntries.Remove(entry); + _entries.Remove(entryId); + + if (_focusedEntryId == entryId) + _focusedEntryId = null; + + var controller = entry.Controller; + entry.Controller = null; + + NotifyDestroyed(entry); + + if (controller != null && Application.isPlaying) + Destroy(controller.gameObject); + } + + private void CascadeCloseChildren(WindowEntry entry) + { + for (int i = entry.ChildEntries.Count - 1; i >= 0; i--) + { + var child = entry.ChildEntries[i]; + DestroyWindow(child.Id); + } } #endregion - #region === 边缘隐藏窗口管理 === + #region === 显示控制 === - /// 注册边缘隐藏窗口 - public void RegisterEdgeHidden(UIFormController window, AutoHideDirection direction) + /// 显示窗口并置顶 + public void ShowWindow(string entryId) { - if (window == null) return; + if (!TryGetEntry(entryId, out var entry)) return; + if (entry.Controller == null) return; + entry.Controller.gameObject.SetActive(true); + MoveToFront(entryId); + } + + /// 隐藏窗口 + public void HideWindow(string entryId) + { + if (!TryGetEntry(entryId, out var entry)) return; + if (entry.Controller == null) return; + + entry.Controller.gameObject.SetActive(false); + } + + /// 切换窗口显示/隐藏 + public void ToggleWindow(string entryId) + { + if (!TryGetEntry(entryId, out var entry)) return; + if (entry.Controller == null) return; + + if (entry.State == WindowState.Minimized) + { + RestoreWindow(entryId); + } + else if (entry.Controller.gameObject.activeSelf) + { + MinimizeWindow(entryId); + } + else + { + ShowWindow(entryId); + } + } + + /// 将窗口置顶 + public void MoveToFront(string entryId) + { + if (!TryGetEntry(entryId, out var entry)) return; + if (entry.Controller == null) return; + + entry.Controller.transform.SetAsLastSibling(); + + _orderedEntries.Remove(entry); + _orderedEntries.Add(entry); + + _focusedEntryId = entryId; + + NotifyFocused(entry); + } + + #endregion + + #region === 最小化 / 恢复 === + + /// 最小化窗口 + public void MinimizeWindow(string entryId) + { + if (!TryGetEntry(entryId, out var entry)) return; + if (entry.Controller == null) return; + if (entry.State == WindowState.Minimized) return; + + entry.Controller.gameObject.SetActive(false); + entry.State = WindowState.Minimized; + + NotifyStateChanged(entry); + } + + /// 恢复已最小化的窗口 + public void RestoreWindow(string entryId) + { + if (!TryGetEntry(entryId, out var entry)) return; + if (entry.Controller == null) return; + if (entry.State != WindowState.Minimized) return; + + ShowWindow(entryId); + entry.State = WindowState.Normal; + + NotifyStateChanged(entry); + } + + public void ToggleMaximize(string entryId) + { + if (!TryGetEntry(entryId, out var entry)) return; + if (entry.Controller == null) return; + + entry.Controller.ToggleMaximize(); + NotifyStateChanged(entry); + } + + #endregion + + #region === 查询 === + + public WindowEntry GetEntry(string id) + { + _entries.TryGetValue(id, out var entry); + return entry; + } + + public IReadOnlyList GetAllEntries() => _orderedEntries; + + public WindowEntry GetFocusedEntry() + { + if (string.IsNullOrEmpty(_focusedEntryId)) return null; + return GetEntry(_focusedEntryId); + } + + public int EntryCount => _entries.Count; + + #endregion + + #region === 边缘隐藏 === + + public void RegisterEdgeHidden(WindowEntry entry, AutoHideDirection direction) + { + if (entry == null) return; var list = _edgeHidden[direction]; - if (!list.Contains(window)) - list.Add(window); - - if (m_EnableDebugLog) - Debug.Log($"[UIFormManager] 边缘隐藏注册: {window.name} (方向={direction})"); + if (!list.Contains(entry)) + list.Add(entry); } - /// 注销边缘隐藏窗口 - public void UnregisterEdgeHidden(UIFormController window) + public void UnregisterEdgeHidden(WindowEntry entry) { - if (window == null) return; - + if (entry == null) return; foreach (var list in _edgeHidden.Values) - list.Remove(window); + list.Remove(entry); } - /// 获取指定方向的隐藏窗口列表 - public IReadOnlyList GetEdgeWindows(AutoHideDirection direction) + private void UnregisterEdgeHiddenForEntry(WindowEntry entry) { - return _edgeHidden[direction]; + UnregisterEdgeHidden(entry); } - #endregion - - #region === 边缘触发检测 === - private void CheckEdgeTriggers() { Vector2 mousePos = Input.mousePosition; @@ -167,124 +291,60 @@ namespace XericUI.Form bool topTrigger = mousePos.y > (sh - m_EdgeTriggerSize.y); AutoHideDirection? activeTrigger = null; - if (leftTrigger) activeTrigger = AutoHideDirection.Left; else if (rightTrigger) activeTrigger = AutoHideDirection.Right; else if (bottomTrigger) activeTrigger = AutoHideDirection.Down; else if (topTrigger) activeTrigger = AutoHideDirection.Up; - // 触发进入 → 显示该方向窗口 if (activeTrigger.HasValue && activeTrigger != _lastEdgeTrigger) { ShowEdgeWindows(activeTrigger.Value); } - // 鼠标离开所有边缘触发区 if (!activeTrigger.HasValue) - { _lastEdgeTrigger = null; - } } - /// 显示指定方向的所有边缘隐藏窗口 public void ShowEdgeWindows(AutoHideDirection direction) { _lastEdgeTrigger = direction; - var list = _edgeHidden[direction]; + for (int i = list.Count - 1; i >= 0; i--) { - var window = list[i]; - if (window == null) + var entry = list[i]; + if (entry?.Controller == null) { list.RemoveAt(i); continue; } - - window.SlideInFromEdge(); + entry.Controller.SlideInFromEdge(); } - - if (m_EnableDebugLog && list.Count > 0) - Debug.Log($"[UIFormManager] 边缘触发: 方向={direction}, 显示 {list.Count} 个窗口"); } #endregion - #region === 最小化 / 恢复 === + #region === 内部通知 === - internal void MinimizeWindow(UIFormController window) + private void NotifyCreated(WindowEntry entry) => OnWindowCreated?.Invoke(entry); + private void NotifyDestroyed(WindowEntry entry) => OnWindowDestroyed?.Invoke(entry); + private void NotifyStateChanged(WindowEntry entry) => OnWindowStateChanged?.Invoke(entry); + private void NotifyFocused(WindowEntry entry) => OnWindowFocused?.Invoke(entry); + + #endregion + + #region === 工具 === + + private bool TryGetEntry(string id, out WindowEntry entry) { - if (window == null || _minimized.ContainsKey(window)) return; - - var rt = window.transform as RectTransform; - if (rt == null) return; - - _minimized[window] = new MinimizedData + if (string.IsNullOrEmpty(id)) { - anchoredPosition = rt.anchoredPosition, - sizeDelta = rt.sizeDelta, - anchorMin = rt.anchorMin, - anchorMax = rt.anchorMax, - }; - - window.gameObject.SetActive(false); - - if (m_EnableDebugLog) - Debug.Log($"[UIFormManager] 最小化窗口: {window.name}"); + entry = null; + return false; + } + return _entries.TryGetValue(id, out entry); } - /// 恢复已最小化的窗口 - public void RestoreWindow(UIFormController window) - { - if (window == null || !_minimized.TryGetValue(window, out var data)) return; - - var rt = window.transform as RectTransform; - if (rt == null) return; - - rt.anchorMin = data.anchorMin; - rt.anchorMax = data.anchorMax; - rt.anchoredPosition = data.anchoredPosition; - rt.sizeDelta = data.sizeDelta; - - window.gameObject.SetActive(true); - _minimized.Remove(window); - - if (m_EnableDebugLog) - Debug.Log($"[UIFormManager] 恢复窗口: {window.name}"); - } - - /// 获取所有已最小化的窗口列表 - public IReadOnlyList GetMinimizedWindows() - { - return new List(_minimized.Keys); - } - - #endregion - - #region === 关闭 === - - internal void CloseWindow(UIFormController window) - { - if (window == null) return; - - _windows.Remove(window); - UnregisterEdgeHidden(window); - _minimized.Remove(window); - - if (m_EnableDebugLog) - Debug.Log($"[UIFormManager] 关闭窗口: {window.name}"); - } - - #endregion - - #region === 查询 === - - /// 已注册窗口数量 - public int WindowCount => _windows.Count; - - /// 获取所有已注册窗口 - public IReadOnlyList GetAllWindows() => _windows; - #endregion } } diff --git a/Runtime/Form/WindowEntry.cs b/Runtime/Form/WindowEntry.cs new file mode 100644 index 0000000..1539592 --- /dev/null +++ b/Runtime/Form/WindowEntry.cs @@ -0,0 +1,102 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace XericUI.Form +{ + /// + /// 窗口数据描述对象 — 由 UIFormManager 创建和持有。 + /// 描述一个窗口实例的标识信息、运行时引用、显示状态和层级关系。 + /// + public class WindowEntry + { + #region 基本标识 + + /// 唯一 ID(GUID) + public string Id { get; } + + /// 窗口标题 + public string Title; + + /// 窗口图标(任务栏和标题栏使用) + public Sprite Icon; + + /// 任务栏图标着色 + public Color TintColor = Color.white; + + #endregion + + #region 实例引用 + + /// 运行时窗口实例 + public UIFormController Controller; + + /// 窗口预制体引用 + public RectTransform Prefab; + + #endregion + + #region 显示状态 + + /// 当前窗口状态 + public WindowState State; + + /// 是否在任务栏上显示图标 + public bool ShowInTaskBar = true; + + #endregion + + #region 层级关系 + + /// 父窗口 Entry(关闭父窗口时级联关闭子窗口) + public WindowEntry ParentEntry { get; private set; } + + /// 子窗口 Entry 列表 + public readonly List ChildEntries = new List(); + + /// 添加子窗口依赖 + public void AddChild(WindowEntry child) + { + if (child == null || ChildEntries.Contains(child)) return; + child.ParentEntry = this; + ChildEntries.Add(child); + } + + /// 移除子窗口依赖 + public void RemoveChild(WindowEntry child) + { + if (child == null) return; + child.ParentEntry = null; + ChildEntries.Remove(child); + } + + #endregion + + #region 进度 + + /// 任务栏进度 (0-1) + public float Progress; + + /// 是否在任务栏显示进度条 + public bool ShowProgress; + + #endregion + + #region 构造 + + public WindowEntry(string id) + { + Id = id ?? System.Guid.NewGuid().ToString(); + } + + public WindowEntry() : this(null) { } + + #endregion + } + + #region 委托 + + /// 窗口 Entry 事件委托 + public delegate void WindowEntryEventHandler(WindowEntry entry); + + #endregion +} diff --git a/Runtime/Form/WindowEntry.cs.meta b/Runtime/Form/WindowEntry.cs.meta new file mode 100644 index 0000000..40aa404 --- /dev/null +++ b/Runtime/Form/WindowEntry.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 174c44278748c9a48b2d6600a450f65a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Prefab.meta b/Runtime/Prefab.meta new file mode 100644 index 0000000..cb91269 --- /dev/null +++ b/Runtime/Prefab.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 785b681a65a87f54e9ade90261da6d87 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Prefab/Form.meta b/Runtime/Prefab/Form.meta new file mode 100644 index 0000000..b288ccb --- /dev/null +++ b/Runtime/Prefab/Form.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a7f23b52396c0c840a4f927a3468a0c9 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Prefab/Form/Window Title.prefab b/Runtime/Prefab/Form/Window Title.prefab new file mode 100644 index 0000000..bc565c5 --- /dev/null +++ b/Runtime/Prefab/Form/Window Title.prefab @@ -0,0 +1,1116 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &614364816953327696 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1870072387805421849} + - component: {fileID: 477255177890062157} + - component: {fileID: 5082803898349498006} + m_Layer: 5 + m_Name: Checkmark + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1870072387805421849 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 614364816953327696} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 5104909081225547168} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 20, y: 20} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &477255177890062157 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 614364816953327696} + m_CullTransparentMesh: 1 +--- !u!114 &5082803898349498006 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 614364816953327696} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 21300000, guid: a25c9ab25f90433458e244e933003acf, type: 3} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 10 +--- !u!1 &620690997739468670 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 450102652151164027} + - component: {fileID: 6056125067687973009} + - component: {fileID: 8110723934686815148} + m_Layer: 5 + m_Name: "\u7A97\u53E3\u5316" + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &450102652151164027 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 620690997739468670} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 5104909081225547168} + m_Father: {fileID: 5013155818891949195} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &6056125067687973009 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 620690997739468670} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 9085046f02f69544eb97fd06b6048fe2, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_WrapAround: 0 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 0} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 0.5019608} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_SelectedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_SelectedTrigger: Selected + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 5670686958620600197} + toggleTransition: 1 + graphic: {fileID: 5082803898349498006} + m_Group: {fileID: 0} + onValueChanged: + m_PersistentCalls: + m_Calls: [] + m_IsOn: 0 +--- !u!222 &8110723934686815148 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 620690997739468670} + m_CullTransparentMesh: 1 +--- !u!1 &3497872670259324617 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 3818289831396923672} + - component: {fileID: 9119487109894987971} + - component: {fileID: 5330696047603728753} + m_Layer: 5 + m_Name: Icon + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &3818289831396923672 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3497872670259324617} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 2144800616648419082} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0.5} + m_AnchorMax: {x: 0, y: 0.5} + m_AnchoredPosition: {x: 18, y: 0} + m_SizeDelta: {x: 30, y: 30} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &9119487109894987971 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3497872670259324617} + m_CullTransparentMesh: 1 +--- !u!114 &5330696047603728753 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3497872670259324617} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 21300000, guid: 20c77f777936af142a12f6ea92c70161, type: 3} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!1 &3677843437910568646 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 8232264927106219026} + - component: {fileID: 6080311456184651865} + - component: {fileID: 8119625050836726749} + m_Layer: 5 + m_Name: Image + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &8232264927106219026 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3677843437910568646} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 7882577829573674029} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: -5} + m_SizeDelta: {x: 20, y: 20} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &6080311456184651865 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3677843437910568646} + m_CullTransparentMesh: 1 +--- !u!114 &8119625050836726749 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3677843437910568646} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 21300000, guid: 5d082959ce575d240bb665b1ec42d749, type: 3} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!1 &3742107610793422745 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 5104909081225547168} + - component: {fileID: 7722905847236453224} + - component: {fileID: 5670686958620600197} + m_Layer: 5 + m_Name: Background + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &5104909081225547168 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3742107610793422745} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 6750121449181033628} + - {fileID: 1870072387805421849} + m_Father: {fileID: 450102652151164027} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &7722905847236453224 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3742107610793422745} + m_CullTransparentMesh: 1 +--- !u!114 &5670686958620600197 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3742107610793422745} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 0} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 10 +--- !u!1 &3958647350117642535 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2144800616648419082} + - component: {fileID: 6665024858261367530} + - component: {fileID: 3780672247442027155} + - component: {fileID: 8882792753637816074} + m_Layer: 5 + m_Name: Window Title + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &2144800616648419082 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3958647350117642535} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 3818289831396923672} + - {fileID: 8799390510342556130} + - {fileID: 5013155818891949195} + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 305.6317, y: -134.9267} + m_SizeDelta: {x: 897.2634, y: 36} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &6665024858261367530 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3958647350117642535} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f5e6e4624592b3248a4c65c33cd21d5e, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IconImage: {fileID: 0} + m_TitleText: {fileID: 4632247821145074539} + m_CloseButton: {fileID: 1814331676489454388} + m_MaximizeToggle: {fileID: 0} + m_MinimizeButton: {fileID: 0} + m_AutoSnapToggle: {fileID: 0} + m_AutoHideToggle: {fileID: 0} +--- !u!222 &3780672247442027155 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3958647350117642535} + m_CullTransparentMesh: 1 +--- !u!114 &8882792753637816074 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3958647350117642535} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.25184909, g: 0.53985643, b: 0.8867924, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 0} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!1 &4799328019211172942 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 6508353797821310857} + - component: {fileID: 5233788064537585813} + - component: {fileID: 1756935852519786291} + - component: {fileID: 1814331676489454388} + m_Layer: 5 + m_Name: "\u5173\u95ED" + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &6508353797821310857 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4799328019211172942} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 6166662553715593466} + m_Father: {fileID: 5013155818891949195} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &5233788064537585813 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4799328019211172942} + m_CullTransparentMesh: 1 +--- !u!114 &1756935852519786291 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4799328019211172942} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!114 &1814331676489454388 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4799328019211172942} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 8bdce41790b144b78cce0334f2df1e13, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_WrapAround: 0 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 0, b: 0, a: 0} + m_HighlightedColor: {r: 0.9607843, g: 0, b: 0, a: 0.5019608} + m_PressedColor: {r: 0.78431374, g: 0, b: 0, a: 1} + m_SelectedColor: {r: 0.9607843, g: 0, b: 0, a: 1} + m_DisabledColor: {r: 0.5, g: 0, b: 0, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_SelectedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_SelectedTrigger: Selected + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 1756935852519786291} + m_OnClick: + m_PersistentCalls: + m_Calls: [] + m_text: {fileID: 0} + m_enableTextColorTransition: 0 + m_textTransitionColorMode: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_enableTextContextTransition: 0 + m_textTransitionContextMode: + m_NormalTrigger: button_normal + m_HighlightedTrigger: button_highlight + m_PressedTrigger: button_pressed + m_SelectedTrigger: button_selected + m_DisabledTrigger: button_disabled +--- !u!1 &5488487651960378444 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 8799390510342556130} + - component: {fileID: 6657971757996795133} + - component: {fileID: 4632247821145074539} + m_Layer: 5 + m_Name: Label + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &8799390510342556130 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5488487651960378444} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 2144800616648419082} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 50, y: 0} + m_SizeDelta: {x: -230, y: 0} + m_Pivot: {x: 0, y: 0.5} +--- !u!222 &6657971757996795133 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5488487651960378444} + m_CullTransparentMesh: 1 +--- !u!114 &4632247821145074539 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5488487651960378444} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_text: Window + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: a8c0a683785f3ae4c94b7a2cffb02078, type: 2} + m_sharedMaterial: {fileID: 8804854241636562321, guid: a8c0a683785f3ae4c94b7a2cffb02078, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4294967295 + m_fontColor: {r: 1, g: 1, b: 1, a: 1} + m_enableVertexGradient: 0 + m_colorMode: 3 + m_fontColorGradient: + topLeft: {r: 1, g: 1, b: 1, a: 1} + topRight: {r: 1, g: 1, b: 1, a: 1} + bottomLeft: {r: 1, g: 1, b: 1, a: 1} + bottomRight: {r: 1, g: 1, b: 1, a: 1} + m_fontColorGradientPreset: {fileID: 0} + m_spriteAsset: {fileID: 0} + m_tintAllSprites: 0 + m_StyleSheet: {fileID: 0} + m_TextStyleHashCode: -1183493901 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_fontSize: 20 + m_fontSizeBase: 20 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_HorizontalAlignment: 1 + m_VerticalAlignment: 512 + m_textAlignment: 65535 + m_characterSpacing: 0 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_enableWordWrapping: 0 + m_wordWrappingRatios: 0.4 + m_overflowMode: 1 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_enableKerning: 1 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_IsTextObjectScaleStatic: 0 + m_VertexBufferAutoSizeReduction: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!1 &6195623315818175959 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 5013155818891949195} + - component: {fileID: 251247678512295731} + m_Layer: 5 + m_Name: Group + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &5013155818891949195 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6195623315818175959} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 7882577829573674029} + - {fileID: 450102652151164027} + - {fileID: 6508353797821310857} + m_Father: {fileID: 2144800616648419082} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 1, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 180, y: 0} + m_Pivot: {x: 1, y: 0.5} +--- !u!114 &251247678512295731 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6195623315818175959} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 30649d3a9faa99c48a7b1166b86bf2a0, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_ChildAlignment: 4 + m_Spacing: 0 + m_ChildForceExpandWidth: 1 + m_ChildForceExpandHeight: 1 + m_ChildControlWidth: 1 + m_ChildControlHeight: 1 + m_ChildScaleWidth: 0 + m_ChildScaleHeight: 0 + m_ReverseArrangement: 0 +--- !u!1 &6384657472823953773 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 6750121449181033628} + - component: {fileID: 5754381382532448150} + - component: {fileID: 3103925096648609860} + m_Layer: 5 + m_Name: background + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &6750121449181033628 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6384657472823953773} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 5104909081225547168} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 20, y: 20} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &5754381382532448150 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6384657472823953773} + m_CullTransparentMesh: 1 +--- !u!114 &3103925096648609860 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6384657472823953773} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 21300000, guid: 2c6de31d1cb551b4d92a47d7de33d6c1, type: 3} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 10 +--- !u!1 &7200429100440025092 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 7882577829573674029} + - component: {fileID: 4466830931248569459} + - component: {fileID: 1817156327892665258} + - component: {fileID: 2789864834306041896} + m_Layer: 5 + m_Name: "\u6700\u5C0F\u5316" + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &7882577829573674029 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7200429100440025092} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 8232264927106219026} + m_Father: {fileID: 5013155818891949195} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &4466830931248569459 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7200429100440025092} + m_CullTransparentMesh: 1 +--- !u!114 &1817156327892665258 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7200429100440025092} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!114 &2789864834306041896 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7200429100440025092} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_WrapAround: 0 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 0} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 0.5019608} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_SelectedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_SelectedTrigger: Selected + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 1817156327892665258} + m_OnClick: + m_PersistentCalls: + m_Calls: [] +--- !u!1 &8168484735676085777 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 6166662553715593466} + - component: {fileID: 29321676436556042} + - component: {fileID: 4201270612912276207} + m_Layer: 5 + m_Name: Image + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &6166662553715593466 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8168484735676085777} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 6508353797821310857} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 24, y: 24} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &29321676436556042 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8168484735676085777} + m_CullTransparentMesh: 1 +--- !u!114 &4201270612912276207 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8168484735676085777} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 21300000, guid: cbade0bcfd572a94298ddc62f6bada7a, type: 3} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 diff --git a/Runtime/Prefab/Form/Window Title.prefab.meta b/Runtime/Prefab/Form/Window Title.prefab.meta new file mode 100644 index 0000000..8959e5e --- /dev/null +++ b/Runtime/Prefab/Form/Window Title.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: f1ad7693cfe6cf3448535dce51381df1 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: