diff --git a/Runtime/XTable/Rendering/Component/TableRenderer.cs b/Runtime/XTable/Rendering/Component/TableRenderer.cs index bbfba69..42cbb7a 100644 --- a/Runtime/XTable/Rendering/Component/TableRenderer.cs +++ b/Runtime/XTable/Rendering/Component/TableRenderer.cs @@ -27,6 +27,7 @@ namespace XericUI.XTable.Rendering.Component public Dictionary<(int, int), GameObject> ActivePrefabMap; public float CellPadding; public XTableConfig Config; + public XericUIActionTable SelectionTable; public int StartRow; public int StartCol; @@ -62,12 +63,13 @@ namespace XericUI.XTable.Rendering.Component { if (m_BackgroundGo == null) { - m_BackgroundGo = new GameObject("_TableBackground", typeof(RectTransform), typeof(CanvasRenderer), typeof(Image)); + m_BackgroundGo = new GameObject("_TableBackground", typeof(RectTransform), typeof(CanvasRenderer), typeof(Image), typeof(XTableSelectionInput)); m_BackgroundGo.hideFlags = HideFlags.DontSave | HideFlags.HideInHierarchy; m_BackgroundGo.transform.SetParent(m_Parent, false); m_BackgroundGo.transform.SetAsFirstSibling(); var image = m_BackgroundGo.GetComponent(); - image.raycastTarget = false; + image.raycastTarget = true; + m_BackgroundGo.GetComponent().Configure(SelectionTable); image.color = GetStyleColor?.Invoke(styleNamespace, XericUIActionTable.STYLE_CELL_BG_COLOR, XericUIActionTable.BG_COLOR_FALLBACK) ?? XericUIActionTable.BG_COLOR_FALLBACK; } diff --git a/Runtime/XTable/Rendering/Component/XTableSelectionInput.cs b/Runtime/XTable/Rendering/Component/XTableSelectionInput.cs new file mode 100644 index 0000000..573b197 --- /dev/null +++ b/Runtime/XTable/Rendering/Component/XTableSelectionInput.cs @@ -0,0 +1,39 @@ +using UnityEngine; +using UnityEngine.EventSystems; + +namespace XericUI.XTable.Rendering.Component +{ + [RequireComponent(typeof(RectTransform))] + internal sealed class XTableSelectionInput : MonoBehaviour, IPointerDownHandler, IDragHandler, IPointerUpHandler, IEndDragHandler + { + private XericUIActionTable m_Table; + private bool m_Dragging; + + internal void Configure(XericUIActionTable table) => m_Table = table; + + public void OnPointerDown(PointerEventData eventData) + { + if (m_Table == null || !m_Table.TryGetCellFromScreenPoint((RectTransform)transform, eventData.position, + eventData.pressEventCamera, true, out int row, out int col)) return; + m_Dragging = true; + m_Table.BeginSelection(row, col); + } + + public void OnDrag(PointerEventData eventData) + { + if (!m_Dragging || m_Table == null) return; + m_Table.UpdateSelectionDrag((RectTransform)transform, eventData.position, eventData.pressEventCamera); + } + + public void OnPointerUp(PointerEventData eventData) => EndSelection(); + public void OnEndDrag(PointerEventData eventData) => EndSelection(); + private void OnDisable() => EndSelection(); + + private void EndSelection() + { + if (!m_Dragging) return; + m_Dragging = false; + m_Table?.EndSelection(); + } + } +} diff --git a/Runtime/XTable/Rendering/Component/XTableSelectionInput.cs.meta b/Runtime/XTable/Rendering/Component/XTableSelectionInput.cs.meta new file mode 100644 index 0000000..9a86486 --- /dev/null +++ b/Runtime/XTable/Rendering/Component/XTableSelectionInput.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7ec3998ca9451274896072bf17af699b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/XTable/Rendering/Component/XTableSelectionOverlay.cs b/Runtime/XTable/Rendering/Component/XTableSelectionOverlay.cs index 0f4da45..dff91dc 100644 --- a/Runtime/XTable/Rendering/Component/XTableSelectionOverlay.cs +++ b/Runtime/XTable/Rendering/Component/XTableSelectionOverlay.cs @@ -1,14 +1,12 @@ -using System.Collections.Generic; using UnityEngine; -using UnityEngine.EventSystems; using UnityEngine.UI; using XericLibrary.Runtime.MacroLibrary; namespace XericUI.XTable.Rendering.Component { - /// 单个渲染层的固定框选输入与视觉覆盖层。 + /// 单个渲染层的固定选区视觉覆盖层。 [RequireComponent(typeof(RectTransform), typeof(Image))] - public sealed class XTableSelectionOverlay : MonoBehaviour, IPointerDownHandler, IDragHandler, IPointerUpHandler, IEndDragHandler + public sealed class XTableSelectionOverlay : MonoBehaviour { private XericUIActionTable m_Table; private Image m_Fill; @@ -16,15 +14,6 @@ namespace XericUI.XTable.Rendering.Component private int m_RowEnd; private int m_ColStart; private int m_ColEnd; - private bool m_Dragging; - - #region debug-point selection-overlay-config - private void DebugReport(string point, string details) - { - if (Application.isPlaying) - Debug.Log($"[XTableSelection] {point} object={name}; {details}", this); - } - #endregion public void Configure(XericUIActionTable table, int rowStart, int rowEnd, int colStart, int colEnd) { @@ -42,7 +31,6 @@ namespace XericUI.XTable.Rendering.Component rt.sizeDelta = region.size; EnsureVisuals(); RefreshVisual(); - DebugReport("overlay-config", $"region={m_RowStart},{m_RowEnd},{m_ColStart},{m_ColEnd};rect={rt.rect};position={rt.anchoredPosition};parent={transform.parent?.name};sibling={transform.GetSiblingIndex()}"); } public void RefreshVisual() @@ -73,88 +61,33 @@ namespace XericUI.XTable.Rendering.Component m_Fill.gameObject.SetActive(true); } - #region debug-point selection-overlay-input - public void OnPointerDown(PointerEventData eventData) - { - int row = -1; - int col = -1; - bool hit = TryGetCellFromOverlayPoint(eventData.position, eventData.pressEventCamera, out row, out col); - DebugReport("pointer-down", $"hit={hit};row={row};col={col};position={eventData.position};rect={transform.RectTransform().rect};dragHandler={eventData.pointerDrag?.name};pressHandler={eventData.pointerPress?.name}"); - if (!hit) - return; - m_Dragging = true; - m_Table.BeginSelection(row, col); - eventData.Use(); - } - - public void OnDrag(PointerEventData eventData) - { - if (!m_Dragging || m_Table == null) - { - DebugReport("drag-ignored", $"dragging={m_Dragging};table={m_Table != null};dragHandler={eventData.pointerDrag?.name}"); - return; - } - bool hit = TryGetCellFromOverlayPoint(eventData.position, eventData.pressEventCamera, out int row, out int col); - DebugReport("drag", $"hit={hit};row={row};col={col};position={eventData.position};dragHandler={eventData.pointerDrag?.name}"); - if (hit) - m_Table.UpdateSelectionDragToCell(row, col); - eventData.Use(); - } - - public void OnPointerUp(PointerEventData eventData) - { - EndDrag(); - eventData.Use(); - } - - public void OnEndDrag(PointerEventData eventData) => EndDrag(); - #endregion - - private void Update() - { - if (!Application.isPlaying || !Input.GetMouseButtonDown(0) || EventSystem.current == null) return; - var data = new PointerEventData(EventSystem.current) { position = Input.mousePosition }; - var results = new List(); - EventSystem.current.RaycastAll(data, results); - string hits = string.Empty; - for (int i = 0; i < results.Count && i < 5; i++) - hits += $"{i}:{results[i].gameObject.name}/{results[i].module.GetType().Name} "; - DebugReport("raycast", $"mouse={Input.mousePosition};hits={hits}"); - } - - private void OnDisable() => EndDrag(); - private void OnDestroy() => EndDrag(); - - private void EndDrag() - { - if (!m_Dragging) return; - m_Dragging = false; - m_Table?.EndSelection(); - } - - private bool TryGetCellFromOverlayPoint(Vector2 screenPoint, Camera eventCamera, out int row, out int col) - { - row = col = -1; - if (m_Table == null || !RectTransformUtility.ScreenPointToLocalPointInRectangle(transform.RectTransform(), screenPoint, eventCamera, out Vector2 local)) - return false; - Rect region = m_Table.GetTableRect(m_RowStart, m_RowEnd, m_ColStart, m_ColEnd); - return m_Table.TryGetCellFromTablePoint(new Vector2(region.x + local.x, region.y - local.y), true, out row, out col); - } - private void EnsureVisuals() { var input = GetComponent(); input.color = Color.clear; - input.raycastTarget = true; + input.raycastTarget = false; + for (int i = transform.childCount - 1; i >= 0; i--) + { + Transform child = transform.GetChild(i); + if (child.name != "_SelectionRect") continue; + Image image = child.GetComponent(); + if (m_Fill == null && image != null) + { + m_Fill = image; + m_Fill.raycastTarget = false; + var outline = child.GetComponent(); + if (outline != null) Destroy(outline); + continue; + } + if (Application.isPlaying) Destroy(child.gameObject); + else DestroyImmediate(child.gameObject); + } if (m_Fill != null) return; - var go = new GameObject("_SelectionRect", typeof(RectTransform), typeof(CanvasRenderer), typeof(Image), typeof(Outline)); + var go = new GameObject("_SelectionRect", typeof(RectTransform), typeof(CanvasRenderer), typeof(Image)); go.hideFlags = HideFlags.DontSave | HideFlags.HideInHierarchy; go.transform.SetParent(transform, false); m_Fill = go.GetComponent(); m_Fill.raycastTarget = false; - var outline = go.GetComponent(); - outline.effectColor = new Color(0.2f, 0.55f, 1f, 1f); - outline.effectDistance = new Vector2(1f, -1f); var rt = m_Fill.rectTransform; rt.anchorMin = new Vector2(0, 1); rt.anchorMax = new Vector2(0, 1); diff --git a/Runtime/XTable/Rendering/Component/XericUIActionTable.Freeze.cs b/Runtime/XTable/Rendering/Component/XericUIActionTable.Freeze.cs index 14ca5b2..dba47b2 100644 --- a/Runtime/XTable/Rendering/Component/XericUIActionTable.Freeze.cs +++ b/Runtime/XTable/Rendering/Component/XericUIActionTable.Freeze.cs @@ -56,6 +56,7 @@ namespace XericUI.XTable.Rendering.Component PrefabPool = m_PrefabPool, CellPadding = CellPadding, Config = Config, + SelectionTable = this, GetStyleColor = (ns, path, fallback) => GetStyleColor(ns, path, fallback), GetStyleInt = (ns, path, fallback) => GetStyleInt(ns, path, fallback), GetStyleFontAsset = (ns, path) => GetStyleFontAsset(ns, path), diff --git a/Runtime/XTable/Rendering/Component/XericUIActionTable.RendererFilter.cs b/Runtime/XTable/Rendering/Component/XericUIActionTable.RendererFilter.cs index 1963a4f..91187b3 100644 --- a/Runtime/XTable/Rendering/Component/XericUIActionTable.RendererFilter.cs +++ b/Runtime/XTable/Rendering/Component/XericUIActionTable.RendererFilter.cs @@ -405,7 +405,7 @@ namespace XericUI.XTable.Rendering.Component if (m_BackgroundRenderer != null) return; var backgroundGo = new GameObject("_TableBackground", - typeof(RectTransform), typeof(CanvasRenderer), typeof(XTableBackgroundRenderer)); + typeof(RectTransform), typeof(CanvasRenderer), typeof(XTableBackgroundRenderer), typeof(XTableSelectionInput)); backgroundGo.hideFlags = HideFlags.DontSave | HideFlags.HideInHierarchy; backgroundGo.transform.SetParent(ContentTransform, false); backgroundGo.transform.SetAsFirstSibling(); @@ -418,7 +418,8 @@ namespace XericUI.XTable.Rendering.Component backgroundRt.sizeDelta = new Vector2(m_TotalWidth, m_TotalHeight); m_BackgroundRenderer = backgroundGo.GetComponent(); - m_BackgroundRenderer.raycastTarget = false; + m_BackgroundRenderer.raycastTarget = true; + backgroundGo.GetComponent().Configure(this); UpdateBackground(); }