using UI.DragAndDrop.Core; using UnityEngine; namespace UI.CardSystem.DragDrop { /// /// Booster pack specific implementation of DraggableObject. /// Manages booster pack behavior and opening logic. /// public class BoosterPackDraggable : DraggableObject { [Header("Booster Pack Settings")] [SerializeField] private bool canOpenOnDrop = true; [SerializeField] private bool canOpenOnDoubleClick = true; [Header("Tap to Open")] [SerializeField] private bool canTapToOpen = true; [SerializeField] private int maxTapsToOpen = 3; [SerializeField] private float tapPulseScale = 1.15f; [SerializeField] private float tapPulseDuration = 0.2f; [SerializeField] private ParticleSystem openingParticleSystem; // ...existing code... public event System.Action OnBoosterOpened; public event System.Action OnTapped; // (booster, currentTap, maxTaps) public event System.Action OnReadyToOpen; // Final tap reached private bool _isOpening; private float _lastClickTime; private int _currentTapCount; public bool IsOpening => _isOpening; public int CurrentTapCount => _currentTapCount; protected override void OnPointerUpHook(bool longPress) { base.OnPointerUpHook(longPress); // Handle tap-to-open logic (only when in slot and not a long press) if (canTapToOpen && !longPress && CurrentSlot != null) { _currentTapCount++; // Pulse effect on tap (scales visual up and back down) if (Visual != null) { // Calculate pulse intensity based on tap progress float tapProgress = _currentTapCount / (float)maxTapsToOpen; float currentPulseScale = 1f + (tapPulseScale - 1f) * (0.5f + tapProgress * 0.5f); // Increases from 1.075 to 1.15 // Save the current scale before pulsing Vector3 baseScale = Visual.transform.localScale; Pixelplacement.Tween.Cancel(Visual.transform.GetInstanceID()); Pixelplacement.Tween.LocalScale(Visual.transform, baseScale * currentPulseScale, tapPulseDuration * 0.5f, 0f, Pixelplacement.Tween.EaseOutBack, completeCallback: () => { // Return to the base scale we had before pulsing Pixelplacement.Tween.LocalScale(Visual.transform, baseScale, tapPulseDuration * 0.5f, 0f, Pixelplacement.Tween.EaseInBack); }); } OnTapped?.Invoke(this, _currentTapCount, maxTapsToOpen); if (_currentTapCount >= maxTapsToOpen) { OnReadyToOpen?.Invoke(this); } return; // Don't process double-click if tap-to-open is active } // ...existing code... if (canOpenOnDoubleClick && !longPress) { float timeSinceLastClick = Time.time - _lastClickTime; if (timeSinceLastClick < 0.3f) // Double click threshold { TriggerOpen(); } _lastClickTime = Time.time; } } protected override void OnDragEndedHook() { base.OnDragEndedHook(); // Optionally trigger open when dropped in specific zones if (canOpenOnDrop) { // Could check if dropped in an "opening zone" // For now, just a placeholder } } /// /// Trigger the booster pack opening animation and logic /// public void TriggerOpen() { if (_isOpening) return; _isOpening = true; // Play particle effect if (openingParticleSystem != null) { openingParticleSystem.Play(); } OnBoosterOpened?.Invoke(this); // The actual opening logic (calling CardSystemManager) should be handled // by the UI page or controller that manages this booster pack // Visual feedback would be handled by the BoosterPackVisual } /// /// Reset the opening state /// public void ResetOpeningState() { _isOpening = false; _currentTapCount = 0; } /// /// Set whether this booster is in the opening slot (disables dragging, enables tapping) /// public void SetInOpeningSlot(bool inSlot) { Debug.Log($"[BoosterPackDraggable] SetInOpeningSlot({inSlot}) called on {name}"); SetDraggingEnabled(!inSlot); // Disable dragging when in opening slot Debug.Log($"[BoosterPackDraggable] SetDraggingEnabled({!inSlot}) called"); canTapToOpen = inSlot; // Enable tap-to-open when in opening slot if (inSlot) { _currentTapCount = 0; // Reset tap counter when placed // Suppress visual effects (idle animations, glow, etc.) when in opening slot // But allow slot tween and tap pulse to still work if (Visual != null) { Visual.SuppressEffects(); // Play one-time placement tween to animate into slot // The visual will follow the parent to its slot position, then lock in place // Get target scale from current slot if it has scale mode Vector3 targetScale = Vector3.one; if (CurrentSlot != null && CurrentSlot.GetComponent() != null) { // Access the slot's occupant scale if it's in Scale mode // For now, use Vector3.one as default targetScale = Vector3.one; } Visual.PlayPlacementTween(0.3f, targetScale); } } else { ResetOpeningState(); // Reset completely when removed // Resume visual effects when removed from opening slot if (Visual != null) { Visual.StopPlacementTween(); // Stop any ongoing placement tween Visual.ResumeEffects(); } } } /// /// Reset tap count (useful when starting a new opening sequence) /// public void ResetTapCount() { _currentTapCount = 0; } /// /// Enable or disable tap-to-open functionality at runtime /// public void SetTapToOpenEnabled(bool enabled) { canTapToOpen = enabled; } } }