diff --git a/Assets/Scripts/FixSystem/PunchType/PunchTapeFavoritesPanel.cs b/Assets/Scripts/FixSystem/PunchType/PunchTapeFavoritesPanel.cs index 1f08fd407..a7e48394d 100644 --- a/Assets/Scripts/FixSystem/PunchType/PunchTapeFavoritesPanel.cs +++ b/Assets/Scripts/FixSystem/PunchType/PunchTapeFavoritesPanel.cs @@ -1,11 +1,11 @@ -using System.Collections.Generic; -using AibisDream.Kit; +using System.Collections.Generic; using DG.Tweening; using UnityEngine; /// /// 打孔带收藏夹视图。侧栏( 上的 RectTransform)做滑入滑出; /// 可选的 仅显隐,与侧栏同开同关。数据来自 。 +/// 固定 3 个槽位,打孔带按顺序放入槽位。 /// namespace AibisDream.FixSystem { @@ -14,8 +14,8 @@ namespace AibisDream.FixSystem private const float PanelSlideDuration = 0.5f; [Header("收藏夹 UI")] - [Tooltip("列表项父节点(Vertical Layout 等)")] - [SerializeField] private Transform punchTapeContent; + [Tooltip("3 个固定槽位,按顺序放置打孔带")] + [SerializeField] private RectTransform[] punchTapeSlots = new RectTransform[3]; [SerializeField] private GameObject punchTapeItemPrefab; @@ -26,19 +26,28 @@ namespace AibisDream.FixSystem [SerializeField] private Vector2 panelHiddenAnchoredPos; [SerializeField] private Vector2 panelVisibleAnchoredPos; - private SimpleObjectPool _rowPool; private readonly Dictionary _rowByTapeKey = new(); + private readonly Dictionary _slotIndexByKey = new(); private PunchTapeManager PunchTapeManager => PunchTapeManager.Instance; private void Start() { - if (punchTapeContent == null) + if (punchTapeSlots == null || punchTapeSlots.Length != 3) { - Debug.LogError("[PunchTapeFavoritesPanel] 未指定 punchTapeContent。", this); + Debug.LogError("[PunchTapeFavoritesPanel] 必须指定 3 个 punchTapeSlots。", this); enabled = false; return; } + for (var i = 0; i < punchTapeSlots.Length; i++) + { + if (punchTapeSlots[i] == null) + { + Debug.LogError($"[PunchTapeFavoritesPanel] punchTapeSlots[{i}] 未指定。", this); + enabled = false; + return; + } + } if (punchTapeItemPrefab == null) { Debug.LogError("[PunchTapeFavoritesPanel] 未指定 punchTapeItemPrefab。", this); @@ -58,53 +67,31 @@ namespace AibisDream.FixSystem punchTapePanel?.DOKill(); - DisposeRowPool(); + ClearAllRows(); _rowByTapeKey.Clear(); + _slotIndexByKey.Clear(); } private void HandleCollectionChanged() => SyncListToData(); - private void DisposeRowPool() + private void ClearAllRows() { - if (_rowPool == null) - return; - - _rowPool.Clear(Destroy); - _rowPool = null; - } - - private void EnsureRowPool() - { - if (_rowPool != null) - return; - - _rowPool = new SimpleObjectPool( - () => - { - var go = Instantiate(punchTapeItemPrefab, punchTapeContent); - go.SetActive(false); - return go; - }, - go => - { - go.SetActive(false); - go.transform.SetParent(punchTapeContent, false); - }); + foreach (var kvp in _rowByTapeKey) + { + if (kvp.Value != null) + Destroy(kvp.Value); + } + _rowByTapeKey.Clear(); + _slotIndexByKey.Clear(); } private void SyncListToData() { - EnsureRowPool(); - var favorites = PunchTapeManager.GetFavorites(); - RemoveRowsNotInFavorites(favorites); - EnsureRowsForFavorites(favorites); - } - private void RemoveRowsNotInFavorites(IReadOnlyList favorites) - { + // 回收不在前 3 个的项 var keepKeys = new HashSet(); - for (var i = 0; i < favorites.Count; i++) + for (var i = 0; i < favorites.Count && i < punchTapeSlots.Length; i++) keepKeys.Add(favorites[i].GetRowKey()); var staleKeys = new List(); @@ -113,35 +100,85 @@ namespace AibisDream.FixSystem if (!keepKeys.Contains(key)) staleKeys.Add(key); } - foreach (var key in staleKeys) { if (_rowByTapeKey.TryGetValue(key, out var go) && go != null) - _rowPool.Recycle(go); + Destroy(go); _rowByTapeKey.Remove(key); } + + // 确保前 3 个槽位有对应项 + for (var i = 0; i < punchTapeSlots.Length; i++) + { + if (i < favorites.Count) + { + var tape = favorites[i]; + var key = tape.GetRowKey(); + _slotIndexByKey[key] = i; + + // 如果该 key 已经在别的槽位,先移过来 + if (_rowByTapeKey.TryGetValue(key, out var existingGo) && existingGo != null) + { + existingGo.transform.SetParent(punchTapeSlots[i], false); + ResetRowRectTransform(existingGo); + existingGo.transform.SetSiblingIndex(i); + } + else + { + var rowGo = Instantiate(punchTapeItemPrefab, punchTapeSlots[i], false); + ResetRowRectTransform(rowGo); + _rowByTapeKey[key] = rowGo; + BindRow(rowGo, tape); + rowGo.SetActive(true); + } + } + else + { + // 清空该槽位上不再需要的项 + ClearSlot(i); + } + } } - private void EnsureRowsForFavorites(IReadOnlyList favorites) + private void ClearSlot(int slotIndex) { - for (var i = 0; i < favorites.Count; i++) - { - var tape = favorites[i]; - var key = tape.GetRowKey(); + var slot = punchTapeSlots[slotIndex]; + if (slot == null || slot.childCount == 0) + return; - if (!_rowByTapeKey.TryGetValue(key, out var rowGo) || rowGo == null) + // 槽位下应该只有一个打孔带子对象 + for (var i = slot.childCount - 1; i >= 0; i--) + { + var child = slot.GetChild(i).gameObject; + if (child == null) continue; + + var item = child.GetComponent(); + if (item != null && item.GetPunchTapeData() != null) { - rowGo = _rowPool.Allocate(); - rowGo.transform.SetParent(punchTapeContent, false); - _rowByTapeKey[key] = rowGo; + var key = item.GetPunchTapeData().GetRowKey(); + _rowByTapeKey.Remove(key); + _slotIndexByKey.Remove(key); } - BindRow(rowGo, tape); - rowGo.SetActive(true); - rowGo.transform.SetSiblingIndex(i); + Destroy(child); } } + private static void ResetRowRectTransform(GameObject rowGo) + { + var rt = rowGo.GetComponent(); + if (rt == null) return; + + rt.anchorMin = Vector2.zero; + rt.anchorMax = Vector2.one; + rt.offsetMin = Vector2.zero; + rt.offsetMax = Vector2.zero; + rt.pivot = new Vector2(0.5f, 0.5f); + rt.anchoredPosition = Vector2.zero; + rt.localRotation = Quaternion.identity; + rt.localScale = Vector3.one; + } + private static void BindRow(GameObject rowGo, PunchTape tape) { var interaction = rowGo.GetComponent(); @@ -156,10 +193,30 @@ namespace AibisDream.FixSystem item.Setup(tape); } + /// + /// 将拖拽回弹的打孔带重新放置到它所属的槽位中。 + /// + public void ReturnToSlot(PunchTapeInteraction interaction) + { + if (interaction == null) return; + + var item = interaction.GetComponent(); + if (item == null) return; + + var tape = item.GetPunchTapeData(); + if (tape == null) return; + + var key = tape.GetRowKey(); + if (_slotIndexByKey.TryGetValue(key, out var slotIndex) && slotIndex >= 0 && slotIndex < punchTapeSlots.Length) + { + interaction.transform.SetParent(punchTapeSlots[slotIndex], false); + ResetRowRectTransform(interaction.gameObject); + } + } + private void ApplyClosedLayout() { punchTapePanel.anchoredPosition = panelHiddenAnchoredPos; - punchTapePanel.gameObject.SetActive(false); } diff --git a/Assets/Scripts/FixSystem/PunchType/PunchTapeInteraction.cs b/Assets/Scripts/FixSystem/PunchType/PunchTapeInteraction.cs index 7c3d03a5e..e71e8e1bd 100644 --- a/Assets/Scripts/FixSystem/PunchType/PunchTapeInteraction.cs +++ b/Assets/Scripts/FixSystem/PunchType/PunchTapeInteraction.cs @@ -10,18 +10,11 @@ namespace AibisDream.FixSystem public class PunchTapeInteraction : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler, IPointerClickHandler, IBeginDragHandler, IDragHandler, IEndDragHandler { - private Transform originalParent; - public Transform OriginalParent => originalParent; private Canvas canvas; [HideInInspector] public bool isFavorited = false; private RectTransform rectTransform; - private Vector2 originalAnchorMin; - private Vector2 originalAnchorMax; - private Vector2 originalOffsetMin; - private Vector2 originalOffsetMax; - private Vector2 originalPivot; private CursorMode cursorMode = CursorMode.Auto; @@ -38,7 +31,6 @@ namespace AibisDream.FixSystem private void OnEnable() { canvas = GetComponentInParent(); - StoreOriginalTransform(); } private void OnDisable() @@ -50,16 +42,6 @@ namespace AibisDream.FixSystem } } - private void StoreOriginalTransform() - { - originalParent = transform.parent; - originalAnchorMin = rectTransform.anchorMin; - originalAnchorMax = rectTransform.anchorMax; - originalOffsetMin = rectTransform.offsetMin; - originalOffsetMax = rectTransform.offsetMax; - originalPivot = rectTransform.pivot; - } - public void OnPointerEnter(PointerEventData eventData) { } @@ -78,6 +60,7 @@ namespace AibisDream.FixSystem if (!isFavorited || isLocked) return; transform.SetParent(canvas.transform, true); + transform.localScale = Vector3.one; transform.SetAsLastSibling(); var cg = GetComponent(); if (cg != null) cg.blocksRaycasts = false; @@ -120,21 +103,15 @@ namespace AibisDream.FixSystem } if (accepted) + { Destroy(gameObject); + } else - ReturnToOriginalPosition(); - } - - public void ReturnToOriginalPosition() - { - isLocked = false; - transform.rotation = Quaternion.Euler(0, 0, 0); - transform.SetParent(originalParent, false); - rectTransform.anchorMin = originalAnchorMin; - rectTransform.anchorMax = originalAnchorMax; - rectTransform.offsetMin = originalOffsetMin; - rectTransform.offsetMax = originalOffsetMax; - rectTransform.pivot = originalPivot; + { + var manager = PunchTapeManager.Instance; + if (manager != null && manager.FavoritesPanel != null) + manager.FavoritesPanel.ReturnToSlot(this); + } } public void SetIsFavorited(bool favorited) diff --git a/Assets/Scripts/FixSystem/PunchType/PunchTapeItem.cs b/Assets/Scripts/FixSystem/PunchType/PunchTapeItem.cs index 9b1174ad9..b5fe6cfab 100644 --- a/Assets/Scripts/FixSystem/PunchType/PunchTapeItem.cs +++ b/Assets/Scripts/FixSystem/PunchType/PunchTapeItem.cs @@ -1,5 +1,4 @@ using UnityEngine; -using TMPro; using UnityEngine.UI; using UnityEngine.Localization.Components; using AibisDream.Framework; @@ -12,17 +11,13 @@ namespace AibisDream.FixSystem public class PunchTapeItem : MonoBehaviour { public Image clueImageUI; - public TMP_Text categoryText; public LocalizeStringEvent nameText; - public GameObject stateText; [HideInInspector] public bool used = false; private PunchTape punchTapeData; - public GameObject finished; - public void Setup(PunchTape punchTape) { punchTapeData = punchTape; @@ -41,11 +36,6 @@ namespace AibisDream.FixSystem if (clueImageUI != null && pt.used) clueImageUI.color = Color.grey; - if (stateText != null) - stateText.SetActive(pt.used); - - if (categoryText != null) - categoryText.text = "分类:" + pt.Category; if (nameText != null) { nameText.StringReference.Arguments = new object[] { LocalizationKit.LocalizeParam(pt.ClueName) }; diff --git a/Assets/Scripts/FixSystem/PunchType/PunchTapeManager.cs b/Assets/Scripts/FixSystem/PunchType/PunchTapeManager.cs index 8479ea3e8..6e09c85f0 100644 --- a/Assets/Scripts/FixSystem/PunchType/PunchTapeManager.cs +++ b/Assets/Scripts/FixSystem/PunchType/PunchTapeManager.cs @@ -15,6 +15,7 @@ namespace AibisDream.FixSystem public GameObject punchTapecluePrefab; [SerializeField] private PunchTapeFavoritesPanel favoritesPanel; + public PunchTapeFavoritesPanel FavoritesPanel => favoritesPanel; [SerializeField] private PunchTapePrinter punchTapePrinter; public PunchTapePrinter PunchTapePrinter => punchTapePrinter;