From 7290bbab1e5ed563361bcacc974437e6775abb63 Mon Sep 17 00:00:00 2001
From: Ding Yuntian <1491671119@qq.com>
Date: Wed, 15 Apr 2026 22:22:30 +0800
Subject: [PATCH] =?UTF-8?q?feat(fix-system):=20=E6=89=93=E5=AD=94=E5=B8=A6?=
=?UTF-8?q?=E6=94=B6=E8=97=8F=E5=A4=B9=E6=94=B9=E4=B8=BA=E5=9B=BA=E5=AE=9A?=
=?UTF-8?q?3=E6=A7=BD=E4=BD=8D=E5=B8=83=E5=B1=80?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../PunchType/PunchTapeFavoritesPanel.cs | 169 ++++++++++++------
.../PunchType/PunchTapeInteraction.cs | 39 +---
.../FixSystem/PunchType/PunchTapeItem.cs | 10 --
.../FixSystem/PunchType/PunchTapeManager.cs | 1 +
4 files changed, 122 insertions(+), 97 deletions(-)
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