From 774f27410aa5fe6c8321c06125361362e0237b62 Mon Sep 17 00:00:00 2001 From: Michal Pikulski Date: Thu, 6 Nov 2025 19:31:33 +0100 Subject: [PATCH] Working drag, tap, open sequence, looking pretty OK --- .../Boosters/BoosterOpeningPage.prefab | 357 +----------------- .../UI/CardSystem/BoosterOpeningPage.cs | 324 ++++++++++------ .../CardSystem/DragDrop/BoosterPackVisual.cs | 8 +- .../UI/DragAndDrop/Core/DraggableObject.cs | 5 + .../UI/DragAndDrop/Core/SlotContainer.cs | 8 + 5 files changed, 239 insertions(+), 463 deletions(-) diff --git a/Assets/Prefabs/UI/CardsSystem/Boosters/BoosterOpeningPage.prefab b/Assets/Prefabs/UI/CardsSystem/Boosters/BoosterOpeningPage.prefab index 49855c6a..72e6ac33 100644 --- a/Assets/Prefabs/UI/CardsSystem/Boosters/BoosterOpeningPage.prefab +++ b/Assets/Prefabs/UI/CardsSystem/Boosters/BoosterOpeningPage.prefab @@ -72,10 +72,7 @@ MonoBehaviour: transitionDuration: 0.3 canvasGroup: {fileID: 7671014600744692184} closeButton: {fileID: 9195578165816196696} - boosterPackInstances: - - {fileID: 705840642806816058} - - {fileID: 2278032343563919548} - - {fileID: 5022511008917093447} + boosterPackPrefab: {fileID: 1439929750438628637, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} bottomRightSlots: {fileID: 415627682025321105} centerOpeningSlot: {fileID: 3371630871680769077} cardDisplayContainer: {fileID: 4830022034953347571} @@ -641,10 +638,7 @@ PrefabInstance: objectReference: {fileID: 0} m_RemovedComponents: [] m_RemovedGameObjects: [] - m_AddedGameObjects: - - targetCorrespondingSourceObject: {fileID: 4310919426181576387, guid: 561f7c561a416e54e9bf1c2af2f3f4ef, type: 3} - insertIndex: -1 - addedObject: {fileID: 106385575138511979} + m_AddedGameObjects: [] m_AddedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: 561f7c561a416e54e9bf1c2af2f3f4ef, type: 3} --- !u!224 &3723208489285683019 stripped @@ -652,121 +646,6 @@ RectTransform: m_CorrespondingSourceObject: {fileID: 4310919426181576387, guid: 561f7c561a416e54e9bf1c2af2f3f4ef, type: 3} m_PrefabInstance: {fileID: 610246570171281800} m_PrefabAsset: {fileID: 0} ---- !u!1001 &893571048183901601 -PrefabInstance: - m_ObjectHideFlags: 0 - serializedVersion: 2 - m_Modification: - serializedVersion: 3 - m_TransformParent: {fileID: 1313588858854015996} - m_Modifications: - - target: {fileID: 1439929750438628637, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_Name - value: BoosterPackPrefab3 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_Pivot.x - value: 0.5 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_Pivot.y - value: 0.5 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_AnchorMax.x - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_AnchorMax.y - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_AnchorMin.x - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_AnchorMin.y - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_SizeDelta.x - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_SizeDelta.y - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_LocalScale.x - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_LocalScale.y - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_LocalPosition.x - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_LocalPosition.y - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_LocalPosition.z - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_LocalRotation.w - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_LocalRotation.x - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_LocalRotation.y - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_LocalRotation.z - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_AnchoredPosition.x - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_AnchoredPosition.y - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_LocalEulerAnglesHint.x - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_LocalEulerAnglesHint.y - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_LocalEulerAnglesHint.z - value: 0 - objectReference: {fileID: 0} - m_RemovedComponents: [] - m_RemovedGameObjects: [] - m_AddedGameObjects: [] - m_AddedComponents: [] - m_SourcePrefab: {fileID: 100100000, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} ---- !u!224 &1670660734182863341 stripped -RectTransform: - m_CorrespondingSourceObject: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - m_PrefabInstance: {fileID: 893571048183901601} - m_PrefabAsset: {fileID: 0} ---- !u!1 &2278032343563919548 stripped -GameObject: - m_CorrespondingSourceObject: {fileID: 1439929750438628637, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - m_PrefabInstance: {fileID: 893571048183901601} - m_PrefabAsset: {fileID: 0} --- !u!1001 &1867557053725785213 PrefabInstance: m_ObjectHideFlags: 0 @@ -877,10 +756,7 @@ PrefabInstance: objectReference: {fileID: 0} m_RemovedComponents: [] m_RemovedGameObjects: [] - m_AddedGameObjects: - - targetCorrespondingSourceObject: {fileID: 4310919426181576387, guid: 561f7c561a416e54e9bf1c2af2f3f4ef, type: 3} - insertIndex: -1 - addedObject: {fileID: 5548954158011133206} + m_AddedGameObjects: [] m_AddedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: 561f7c561a416e54e9bf1c2af2f3f4ef, type: 3} --- !u!224 &2466164304475032254 stripped @@ -888,113 +764,6 @@ RectTransform: m_CorrespondingSourceObject: {fileID: 4310919426181576387, guid: 561f7c561a416e54e9bf1c2af2f3f4ef, type: 3} m_PrefabInstance: {fileID: 1867557053725785213} m_PrefabAsset: {fileID: 0} ---- !u!1001 &1887023816125829159 -PrefabInstance: - m_ObjectHideFlags: 0 - serializedVersion: 2 - m_Modification: - serializedVersion: 3 - m_TransformParent: {fileID: 3723208489285683019} - m_Modifications: - - target: {fileID: 1439929750438628637, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_Name - value: BoosterPackPrefab2 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_Pivot.x - value: 0.5 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_Pivot.y - value: 0.5 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_AnchorMax.x - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_AnchorMax.y - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_AnchorMin.x - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_AnchorMin.y - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_SizeDelta.x - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_SizeDelta.y - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_LocalPosition.x - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_LocalPosition.y - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_LocalPosition.z - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_LocalRotation.w - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_LocalRotation.x - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_LocalRotation.y - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_LocalRotation.z - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_AnchoredPosition.x - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_AnchoredPosition.y - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_LocalEulerAnglesHint.x - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_LocalEulerAnglesHint.y - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_LocalEulerAnglesHint.z - value: 0 - objectReference: {fileID: 0} - m_RemovedComponents: [] - m_RemovedGameObjects: [] - m_AddedGameObjects: [] - m_AddedComponents: [] - m_SourcePrefab: {fileID: 100100000, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} ---- !u!224 &106385575138511979 stripped -RectTransform: - m_CorrespondingSourceObject: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - m_PrefabInstance: {fileID: 1887023816125829159} - m_PrefabAsset: {fileID: 0} ---- !u!1 &705840642806816058 stripped -GameObject: - m_CorrespondingSourceObject: {fileID: 1439929750438628637, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - m_PrefabInstance: {fileID: 1887023816125829159} - m_PrefabAsset: {fileID: 0} --- !u!1001 &3020147864556123455 PrefabInstance: m_ObjectHideFlags: 0 @@ -1097,10 +866,7 @@ PrefabInstance: objectReference: {fileID: 0} m_RemovedComponents: [] m_RemovedGameObjects: [] - m_AddedGameObjects: - - targetCorrespondingSourceObject: {fileID: 4310919426181576387, guid: 561f7c561a416e54e9bf1c2af2f3f4ef, type: 3} - insertIndex: -1 - addedObject: {fileID: 1670660734182863341} + m_AddedGameObjects: [] m_AddedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: 561f7c561a416e54e9bf1c2af2f3f4ef, type: 3} --- !u!224 &1313588858854015996 stripped @@ -1218,121 +984,6 @@ RectTransform: m_CorrespondingSourceObject: {fileID: 793761934373733976, guid: a04075d06f231594292595e90a69cbb1, type: 3} m_PrefabInstance: {fileID: 5916465061944119399} m_PrefabAsset: {fileID: 0} ---- !u!1001 &6217258165417062746 -PrefabInstance: - m_ObjectHideFlags: 0 - serializedVersion: 2 - m_Modification: - serializedVersion: 3 - m_TransformParent: {fileID: 2466164304475032254} - m_Modifications: - - target: {fileID: 1439929750438628637, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_Name - value: BoosterPackPrefab1 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_Pivot.x - value: 0.5 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_Pivot.y - value: 0.5 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_AnchorMax.x - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_AnchorMax.y - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_AnchorMin.x - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_AnchorMin.y - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_SizeDelta.x - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_SizeDelta.y - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_LocalScale.x - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_LocalScale.y - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_LocalPosition.x - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_LocalPosition.y - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_LocalPosition.z - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_LocalRotation.w - value: 1 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_LocalRotation.x - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_LocalRotation.y - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_LocalRotation.z - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_AnchoredPosition.x - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_AnchoredPosition.y - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_LocalEulerAnglesHint.x - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_LocalEulerAnglesHint.y - value: 0 - objectReference: {fileID: 0} - - target: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - propertyPath: m_LocalEulerAnglesHint.z - value: 0 - objectReference: {fileID: 0} - m_RemovedComponents: [] - m_RemovedGameObjects: [] - m_AddedGameObjects: [] - m_AddedComponents: [] - m_SourcePrefab: {fileID: 100100000, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} ---- !u!1 &5022511008917093447 stripped -GameObject: - m_CorrespondingSourceObject: {fileID: 1439929750438628637, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - m_PrefabInstance: {fileID: 6217258165417062746} - m_PrefabAsset: {fileID: 0} ---- !u!224 &5548954158011133206 stripped -RectTransform: - m_CorrespondingSourceObject: {fileID: 1966378914653314124, guid: cff5eaa9e8cc26a439e7b36345916468, type: 3} - m_PrefabInstance: {fileID: 6217258165417062746} - m_PrefabAsset: {fileID: 0} --- !u!1001 &8252956905557640428 PrefabInstance: m_ObjectHideFlags: 0 diff --git a/Assets/Scripts/UI/CardSystem/BoosterOpeningPage.cs b/Assets/Scripts/UI/CardSystem/BoosterOpeningPage.cs index 7a53e85e..352f302a 100644 --- a/Assets/Scripts/UI/CardSystem/BoosterOpeningPage.cs +++ b/Assets/Scripts/UI/CardSystem/BoosterOpeningPage.cs @@ -25,8 +25,8 @@ namespace UI.CardSystem [SerializeField] private Button closeButton; [Header("Booster Management")] - [SerializeField] private GameObject[] boosterPackInstances; // Booster prefabs/instances - [SerializeField] private SlotContainer bottomRightSlots; // Holds waiting boosters + [SerializeField] private GameObject boosterPackPrefab; // Prefab to instantiate new boosters + [SerializeField] private SlotContainer bottomRightSlots; // Holds waiting boosters (max 3) [SerializeField] private DraggableSlot centerOpeningSlot; // Where booster goes to open [Header("Card Display")] @@ -41,10 +41,12 @@ namespace UI.CardSystem private int _availableBoosterCount; private BoosterPackDraggable _currentBoosterInCenter; + private List _activeBoostersInSlots = new List(); private List _currentRevealedCards = new List(); private CardData[] _currentCardData; private int _revealedCardCount; private bool _isProcessingOpening; + private const int MAX_VISIBLE_BOOSTERS = 3; private void Awake() { @@ -75,6 +77,7 @@ namespace UI.CardSystem if (centerOpeningSlot != null) { centerOpeningSlot.OnOccupied -= OnBoosterPlacedInCenter; + centerOpeningSlot.OnVacated -= OnBoosterRemovedFromCenter; } // Unsubscribe from booster events @@ -116,71 +119,38 @@ namespace UI.CardSystem { Debug.Log($"[BoosterOpeningPage] InitializeBoosterDisplay called with {_availableBoosterCount} boosters available"); - if (boosterPackInstances == null || boosterPackInstances.Length == 0) + if (boosterPackPrefab == null) { - Debug.LogWarning("BoosterOpeningPage: No booster pack instances assigned!"); + Debug.LogWarning("BoosterOpeningPage: No booster pack prefab assigned!"); return; } - // Calculate how many boosters to show (capped by array size) - int visibleCount = Mathf.Min(_availableBoosterCount, boosterPackInstances.Length); - - Debug.Log($"[BoosterOpeningPage] Will show {visibleCount} boosters out of {boosterPackInstances.Length} instances"); - - // Show/hide boosters and assign to slots - for (int i = 0; i < boosterPackInstances.Length; i++) + if (bottomRightSlots == null || bottomRightSlots.SlotCount == 0) { - if (boosterPackInstances[i] == null) continue; - - bool shouldShow = i < visibleCount; - Debug.Log($"[BoosterOpeningPage] Booster {i} ({boosterPackInstances[i].name}): shouldShow={shouldShow}, position={boosterPackInstances[i].transform.position}"); - - boosterPackInstances[i].SetActive(shouldShow); - - if (shouldShow) - { - // Get the booster draggable component - BoosterPackDraggable booster = boosterPackInstances[i].GetComponent(); - if (booster != null) - { - // Reset state - booster.ResetTapCount(); - booster.SetTapToOpenEnabled(false); // Disable tap-to-open until in center - - // Subscribe to events - booster.OnReadyToOpen += OnBoosterReadyToOpen; - - // Assign to bottom-right slot if slots available - if (bottomRightSlots != null && i < bottomRightSlots.SlotCount) - { - DraggableSlot slot = bottomRightSlots.GetSlotAtIndex(i); - if (slot != null) - { - Debug.Log($"[BoosterOpeningPage] Assigning booster {i} to slot {slot.name} at {slot.transform.position}"); - booster.AssignToSlot(slot, false); - } - else - { - Debug.LogWarning($"[BoosterOpeningPage] Slot {i} is null in bottomRightSlots!"); - } - } - else - { - Debug.LogWarning($"[BoosterOpeningPage] No slot available for booster {i}. bottomRightSlots={bottomRightSlots}, SlotCount={bottomRightSlots?.SlotCount}"); - } - } - else - { - Debug.LogWarning($"[BoosterOpeningPage] Booster {i} has no BoosterPackDraggable component!"); - } - } + Debug.LogWarning("BoosterOpeningPage: No slots available!"); + return; + } + + // Clear any existing boosters + _activeBoostersInSlots.Clear(); + + // Calculate how many boosters to show (max 3, or available count, whichever is lower) + int visibleCount = Mathf.Min(_availableBoosterCount, MAX_VISIBLE_BOOSTERS); + + Debug.Log($"[BoosterOpeningPage] Will spawn {visibleCount} boosters"); + + // Spawn boosters and assign to slots + for (int i = 0; i < visibleCount; i++) + { + SpawnBoosterInSlot(i); } // Subscribe to center slot events if (centerOpeningSlot != null) { centerOpeningSlot.OnOccupied += OnBoosterPlacedInCenter; - Debug.Log($"[BoosterOpeningPage] Subscribed to center slot {centerOpeningSlot.name} at {centerOpeningSlot.transform.position}"); + centerOpeningSlot.OnVacated += OnBoosterRemovedFromCenter; + Debug.Log($"[BoosterOpeningPage] Subscribed to center slot events"); } else { @@ -188,6 +158,137 @@ namespace UI.CardSystem } } + /// + /// Spawn a new booster and place it in the specified slot index + /// + private void SpawnBoosterInSlot(int slotIndex) + { + if (slotIndex >= bottomRightSlots.SlotCount) + { + Debug.LogWarning($"[BoosterOpeningPage] Slot index {slotIndex} out of range!"); + return; + } + + DraggableSlot slot = bottomRightSlots.GetSlotAtIndex(slotIndex); + if (slot == null) + { + Debug.LogWarning($"[BoosterOpeningPage] Slot {slotIndex} is null!"); + return; + } + + // Instantiate booster + GameObject boosterObj = Instantiate(boosterPackPrefab, slot.transform); + BoosterPackDraggable booster = boosterObj.GetComponent(); + + if (booster != null) + { + // Reset state + booster.ResetTapCount(); + booster.SetTapToOpenEnabled(false); + + // Subscribe to events + booster.OnReadyToOpen += OnBoosterReadyToOpen; + + // Assign to slot with animation + booster.AssignToSlot(slot, true); + + // Track it + _activeBoostersInSlots.Add(booster); + + Debug.Log($"[BoosterOpeningPage] Spawned booster in slot {slotIndex}"); + } + else + { + Debug.LogWarning($"[BoosterOpeningPage] Spawned booster has no BoosterPackDraggable component!"); + Destroy(boosterObj); + } + } + + /// + /// Remove and destroy the booster from the specified slot + /// + private void RemoveBoosterFromSlot(int slotIndex) + { + if (slotIndex >= _activeBoostersInSlots.Count) + return; + + BoosterPackDraggable booster = _activeBoostersInSlots[slotIndex]; + if (booster != null) + { + // Unsubscribe from events + booster.OnReadyToOpen -= OnBoosterReadyToOpen; + + // Animate out and destroy + Transform boosterTransform = booster.transform; + Tween.LocalScale(boosterTransform, Vector3.zero, 0.3f, 0f, Tween.EaseInBack, + completeCallback: () => + { + if (booster != null && booster.gameObject != null) + { + Destroy(booster.gameObject); + } + }); + + // Remove from slot + if (booster.CurrentSlot != null) + { + booster.CurrentSlot.Vacate(); + } + + Debug.Log($"[BoosterOpeningPage] Removed booster from slot {slotIndex}"); + } + + _activeBoostersInSlots.RemoveAt(slotIndex); + } + + /// + /// Update visible boosters based on available count + /// + private void UpdateVisibleBoosters() + { + int targetCount = Mathf.Min(_availableBoosterCount, MAX_VISIBLE_BOOSTERS); + + // Remove excess boosters (from the end) + while (_activeBoostersInSlots.Count > targetCount) + { + int lastIndex = _activeBoostersInSlots.Count - 1; + RemoveBoosterFromSlot(lastIndex); + } + + Debug.Log($"[BoosterOpeningPage] Updated visible boosters: {_activeBoostersInSlots.Count}/{targetCount}"); + } + + /// + /// Try to spawn a new booster to maintain up to 3 visible + /// Pass decrementCount=true when called after placing a booster in center slot + /// (accounts for the booster that will be consumed) + /// + private void TrySpawnNewBooster(bool decrementCount = false) + { + // Can we spawn more boosters? + if (_activeBoostersInSlots.Count >= MAX_VISIBLE_BOOSTERS) + return; // Already at max + + // Use decremented count if this is called after placing in center + // (the booster in center will be consumed, so we check against count - 1) + int effectiveCount = decrementCount ? _availableBoosterCount - 1 : _availableBoosterCount; + + if (_activeBoostersInSlots.Count >= effectiveCount) + return; // No more boosters available + + // Find first available slot + for (int i = 0; i < MAX_VISIBLE_BOOSTERS; i++) + { + DraggableSlot slot = bottomRightSlots.GetSlotAtIndex(i); + if (slot != null && !slot.IsOccupied) + { + SpawnBoosterInSlot(i); + Debug.Log($"[BoosterOpeningPage] Spawned new booster in slot {i}"); + break; + } + } + } + /// /// Handle when a booster is placed in the center opening slot /// @@ -198,17 +299,46 @@ namespace UI.CardSystem _currentBoosterInCenter = booster; - // Lock the slot so it can't be dragged out - centerOpeningSlot.SetLocked(true); + // Remove from active slots list + _activeBoostersInSlots.Remove(booster); + // Lock the slot so it can't be dragged out + Debug.Log($"[BoosterOpeningPage] Locking center slot. IsLocked before: {centerOpeningSlot.IsLocked}"); + centerOpeningSlot.SetLocked(true); + Debug.Log($"[BoosterOpeningPage] IsLocked after: {centerOpeningSlot.IsLocked}"); + // Configure booster for opening (disables drag, enables tapping, resets tap count) + Debug.Log($"[BoosterOpeningPage] Calling SetInOpeningSlot(true) on booster"); booster.SetInOpeningSlot(true); // Subscribe to tap events for visual feedback booster.OnTapped += OnBoosterTapped; booster.OnReadyToOpen += OnBoosterReadyToOpen; - Debug.Log($"[BoosterOpeningPage] Booster placed in center, ready for {booster.CurrentTapCount} taps"); + // Try to spawn a new booster to maintain 3 visible + // Use decrementCount=true because this booster will be consumed + TrySpawnNewBooster(decrementCount: true); + + Debug.Log($"[BoosterOpeningPage] Booster placed in center, ready for taps. Active boosters in slots: {_activeBoostersInSlots.Count}"); + } + + /// + /// Handle when a booster is removed from the center opening slot + /// + private void OnBoosterRemovedFromCenter(DraggableObject draggable) + { + BoosterPackDraggable booster = draggable as BoosterPackDraggable; + if (booster == null) return; + + // If it's being removed back to a corner slot, add it back to tracking + if (booster.CurrentSlot != null && bottomRightSlots.HasSlot(booster.CurrentSlot)) + { + _activeBoostersInSlots.Add(booster); + booster.SetInOpeningSlot(false); + } + + _currentBoosterInCenter = null; + Debug.Log($"[BoosterOpeningPage] Booster removed from center"); } private void OnBoosterTapped(BoosterPackDraggable booster, int currentTaps, int maxTaps) @@ -275,21 +405,19 @@ namespace UI.CardSystem // Animate booster disappearing yield return StartCoroutine(AnimateBoosterDisappear(booster)); + // Decrement available count + _availableBoosterCount--; + + // Update visible boosters (remove from end if we drop below thresholds) + UpdateVisibleBoosters(); + // Show card backs SpawnCardBacks(_currentCardData.Length); // Wait for player to reveal all cards yield return StartCoroutine(WaitForCardReveals()); - // Check if more boosters available - _availableBoosterCount--; - - if (_availableBoosterCount > 0) - { - // Show next booster - yield return StartCoroutine(ShowNextBooster()); - } - else + if (_availableBoosterCount <= 0) { // No more boosters, auto-close page yield return new WaitForSeconds(1f); @@ -327,7 +455,7 @@ namespace UI.CardSystem // Destroy the booster Destroy(booster.gameObject); _currentBoosterInCenter = null; - + // Unlock center slot centerOpeningSlot.SetLocked(false); } @@ -437,40 +565,6 @@ namespace UI.CardSystem yield return new WaitForSeconds(0.5f); } - /// - /// Show the next booster pack - /// - private IEnumerator ShowNextBooster() - { - // Find the next inactive booster and activate it - for (int i = 0; i < boosterPackInstances.Length; i++) - { - if (boosterPackInstances[i] != null && !boosterPackInstances[i].activeSelf) - { - boosterPackInstances[i].SetActive(true); - - BoosterPackDraggable booster = boosterPackInstances[i].GetComponent(); - if (booster != null) - { - booster.ResetTapCount(); - booster.SetTapToOpenEnabled(false); - booster.OnReadyToOpen += OnBoosterReadyToOpen; - - // Assign to first available slot - DraggableSlot slot = bottomRightSlots?.GetAvailableSlots().FirstOrDefault(); - if (slot != null) - { - booster.AssignToSlot(slot, true); - } - } - - break; - } - } - - yield return null; - } - /// /// Clean up the page when hidden /// @@ -478,6 +572,14 @@ namespace UI.CardSystem { UnsubscribeFromAllBoosters(); + // Destroy all active boosters + foreach (var booster in _activeBoostersInSlots.ToList()) + { + if (booster != null && booster.gameObject != null) + Destroy(booster.gameObject); + } + _activeBoostersInSlots.Clear(); + // Clear any remaining cards foreach (GameObject card in _currentRevealedCards) { @@ -495,18 +597,22 @@ namespace UI.CardSystem /// private void UnsubscribeFromAllBoosters() { - if (boosterPackInstances == null) return; - - foreach (GameObject boosterObj in boosterPackInstances) + // Unsubscribe from active boosters in slots + foreach (var booster in _activeBoostersInSlots) { - if (boosterObj == null) continue; - - BoosterPackDraggable booster = boosterObj.GetComponent(); if (booster != null) { booster.OnReadyToOpen -= OnBoosterReadyToOpen; + booster.OnTapped -= OnBoosterTapped; } } + + // Unsubscribe from center booster + if (_currentBoosterInCenter != null) + { + _currentBoosterInCenter.OnReadyToOpen -= OnBoosterReadyToOpen; + _currentBoosterInCenter.OnTapped -= OnBoosterTapped; + } } protected override void DoTransitionIn(System.Action onComplete) diff --git a/Assets/Scripts/UI/CardSystem/DragDrop/BoosterPackVisual.cs b/Assets/Scripts/UI/CardSystem/DragDrop/BoosterPackVisual.cs index a2ec3492..f97cbe1f 100644 --- a/Assets/Scripts/UI/CardSystem/DragDrop/BoosterPackVisual.cs +++ b/Assets/Scripts/UI/CardSystem/DragDrop/BoosterPackVisual.cs @@ -246,7 +246,13 @@ namespace UI.CardSystem.DragDrop protected override void HandleDragEnded(DraggableObject draggable) { - // Don't call base if effects are suppressed (in opening slot) + // ALWAYS reset canvas sorting, even when effects are suppressed + if (canvas != null) + { + canvas.overrideSorting = false; + } + + // Skip other drag end effects if suppressed (in opening slot) if (_effectsSuppressed) return; diff --git a/Assets/Scripts/UI/DragAndDrop/Core/DraggableObject.cs b/Assets/Scripts/UI/DragAndDrop/Core/DraggableObject.cs index be85b873..d4cb7fea 100644 --- a/Assets/Scripts/UI/DragAndDrop/Core/DraggableObject.cs +++ b/Assets/Scripts/UI/DragAndDrop/Core/DraggableObject.cs @@ -445,6 +445,11 @@ namespace UI.DragAndDrop.Core if (RectTransform != null) { + // Pop-in animation: start slightly scaled down, then bounce to normal + Vector3 startScale = transform.localScale * 0.8f; + transform.localScale = startScale; + Tween.LocalScale(transform, Vector3.one, snapDuration, 0f, Tween.EaseOutBack); + Tween.LocalPosition(RectTransform, targetLocalPos, snapDuration, 0f, Tween.EaseOutBack); Tween.LocalRotation(transform, Quaternion.identity, snapDuration, 0f, Tween.EaseOutBack); } diff --git a/Assets/Scripts/UI/DragAndDrop/Core/SlotContainer.cs b/Assets/Scripts/UI/DragAndDrop/Core/SlotContainer.cs index df429ab7..e615036f 100644 --- a/Assets/Scripts/UI/DragAndDrop/Core/SlotContainer.cs +++ b/Assets/Scripts/UI/DragAndDrop/Core/SlotContainer.cs @@ -153,6 +153,14 @@ namespace UI.DragAndDrop.Core return _slots[index]; } + /// + /// Check if this container contains the specified slot + /// + public bool HasSlot(DraggableSlot slot) + { + return _slots.Contains(slot); + } + /// /// Update the layout of all slots based on layout type ///