Files
AppleHillsProduction/docs/cards_wip/card_dragdrop_integration_summary.md

292 lines
8.8 KiB
Markdown
Raw Normal View History

2025-11-12 14:39:38 +01:00
# Card Drag/Drop Integration - Refactor Summary
## What Was Changed
### ✅ **Files Modified:**
1. **Card.cs** - Now inherits from `DraggableObject`
- Added drag event hooks (`OnDragStartedHook`, `OnDragEndedHook`)
- Added setup methods for different flows (booster, album placement, album slot)
- Changed `Awake()` to `Initialize()` to match DraggableObject pattern
2. **CardDraggingState.cs** - Simplified to visual-only
- Removed position update methods (handled by DraggableObject base)
- Kept scale animation for visual feedback
- Removed redundant methods (`UpdateDragPosition`, `OnDroppedInSlot`, etc.)
### ✅ **Files Moved to DEPRECATED:**
- `CardDraggable.cs``DEPRECATED/` (redundant wrapper)
- `CardDraggableVisual.cs``DEPRECATED/` (tied to old system)
- `FlippableCard.cs``DEPRECATED/` (old card implementation)
**Note:** AlbumCardPlacementDraggable.cs remains in DragDrop/ for now (used by album corner cards)
---
## How It Works Now
### **Card.cs Inheritance Chain:**
```
Card → DraggableObject → MonoBehaviour
```
Card now has all DraggableObject capabilities:
- ✅ Drag/drop detection (OnBeginDrag, OnDrag, OnEndDrag)
- ✅ Slot detection and snapping
- ✅ Pointer events (OnPointerEnter, OnPointerExit, etc.)
- ✅ Enable/disable dragging via `SetDraggingEnabled(bool)`
### **Drag Event Flow:**
```
1. Player starts dragging card
2. DraggableObject.OnBeginDrag() fires
3. Calls Card.OnDragStartedHook()
4. Card transitions to DraggingState
5. DraggingState.OnEnterState() scales card up (visual feedback)
6. Player drags (DraggableObject handles position updates)
7. Player releases drag
8. DraggableObject.OnEndDrag() fires
9. DraggableObject finds closest slot
10. Calls Card.OnDragEndedHook()
11. Card checks if dropped in AlbumCardSlot:
- YES → Transition to PlacedInSlotState
- NO → Transition to RevealedState
```
---
## Setup Methods
### **For Booster Opening Flow:**
```csharp
card.SetupForBoosterReveal(cardData, isNew: true);
// - Starts in IdleState
// - Dragging DISABLED (booster cards can't be dragged)
```
### **For Album Placement Flow:**
```csharp
card.SetupForAlbumPlacement(cardData);
// - Starts in RevealedState
// - Dragging ENABLED (can drag to album slots)
```
### **For Cards Already in Album:**
```csharp
card.SetupForAlbumSlot(cardData, albumSlot);
// - Starts in PlacedInSlotState
// - Dragging DISABLED (can't drag out of album)
```
---
## Integration with Existing Drag/Drop System
### **Works with AlbumCardSlot:**
```csharp
// AlbumCardSlot.cs doesn't need changes!
// It expects DraggableObject, and Card now IS a DraggableObject
public class AlbumCardSlot : DraggableSlot
{
public bool CanAccept(DraggableObject draggable)
{
// Works with Card because Card inherits from DraggableObject
if (draggable is Card card)
{
return CanAcceptCard(card.CardData);
}
return false;
}
}
```
### **No Visual Component Needed:**
- DraggableObject can optionally use a DraggableVisual child
- Card doesn't need one - the state machine handles all visuals
- Card itself IS the visual representation
---
## State Machine Integration
### **States that interact with drag system:**
1. **RevealedState** - Card waits here, dragging enabled
- Player can click to flip (if corner card)
- Player can drag to album slot (if placement card)
2. **DraggingState** - Visual feedback during drag
- Scales card up (1.1x by default)
- DraggableObject handles actual drag movement
3. **PlacedInSlotState** - Card placed in album
- Dragging disabled
- Can be clicked to enlarge
---
## Benefits
### **Cleaner Architecture:**
- ✅ No wrapper scripts needed (Card, CardDraggable, CardDraggableVisual → Just Card)
- ✅ Drag capability at top level (Card manages it directly)
- ✅ States handle visuals only (DraggingState shows scale, not position)
- ✅ Separation of concerns (drag logic ≠ visual logic)
### **Reuses Generic Base:**
- ✅ DraggableObject does all heavy lifting (snapping, slot detection, events)
- ✅ No card-specific drag code duplication
- ✅ Works with existing SlotContainer, DraggableSlot system
### **Backward Compatible:**
- ✅ Old files moved to DEPRECATED/ (not deleted)
- ✅ AlbumCardPlacementDraggable still exists for old corner cards
- ✅ Can migrate gradually (new Card works alongside old FlippableCard)
---
## Testing Checklist
### **Booster Opening Flow:**
- [ ] Cards spawn in center (not draggable)
- [ ] Click card → flips → enlarges
- [ ] Tap enlarged card → shrinks to revealed state
- [ ] Try dragging card → should be blocked (dragging disabled)
### **Album Placement Flow:**
- [ ] Cards spawn in corner (draggable)
- [ ] Click card → flips → shows which card it is
- [ ] Card enters RevealedState (draggable)
- [ ] Drag card → enters DraggingState (scales up)
- [ ] Drop in valid AlbumCardSlot → PlacedInSlotState
- [ ] Drop outside slot → returns to RevealedState
- [ ] Card in slot is NOT draggable
### **Album Slot Interaction:**
- [ ] Click card in slot → AlbumEnlargedState
- [ ] Tap enlarged card → shrinks back to PlacedInSlotState
- [ ] Card cannot be dragged out of slot
---
## Migration Path for Old Code
### **Current State:**
- ✅ New Card.cs works with drag/drop
- ✅ Old FlippableCard.cs in DEPRECATED/ (still compiles)
- ✅ Old AlbumCardPlacementDraggable.cs still in DragDrop/ (for corner cards)
### **Next Steps:**
1. Update BoosterOpeningPage to use new Card.SetupForBoosterReveal()
2. Update AlbumViewPage corner cards to use Card.SetupForAlbumPlacement()
3. Test both flows thoroughly
4. Once stable, delete DEPRECATED/ folder
---
## Example Usage
### **BoosterOpeningPage.cs (New):**
```csharp
// Spawn booster cards (NOT draggable)
Card card = Instantiate(cardPrefab);
card.SetupForBoosterReveal(cardData, isNew: isNewCard);
card.Context.IsClickable = true;
// Subscribe to events
card.Context.OnFlipComplete += OnCardFlipComplete;
card.Context.OnCardInteractionComplete += OnCardComplete;
```
### **AlbumViewPage.cs (New - Corner Cards):**
```csharp
// Spawn unrevealed corner card (DRAGGABLE)
Card card = Instantiate(cardPrefab);
card.SetupForAlbumPlacement(cardData);
// Card can now be dragged to matching album slot
// When dropped, automatically transitions to PlacedInSlotState
```
### **AlbumViewPage.cs (New - Already Placed):**
```csharp
// Card already in album slot (NOT draggable)
Card card = Instantiate(cardPrefab, albumSlot.transform);
card.SetupForAlbumSlot(cardData, albumSlot);
// Card can be clicked to enlarge, but not dragged out
```
---
## Technical Notes
### **Why Card inherits from DraggableObject:**
- **Single Responsibility:** Card manages its own drag capability
- **No Wrappers:** Simpler prefab structure (no CardDraggable wrapper)
- **Polymorphism:** AlbumCardSlot accepts DraggableObject, Card IS a DraggableObject
- **Event Integration:** DraggableObject events trigger state transitions
### **Why DraggingState is visual-only:**
- **DraggableObject handles movement:** OnDrag() updates transform.position automatically
- **State shows feedback:** Scaling up indicates "I'm being dragged"
- **Clean separation:** Drag logic (base class) vs visual feedback (state)
### **Why SetDraggingEnabled():**
- **Booster cards:** Should never be draggable (opens in place)
- **Corner cards:** Should be draggable (placement flow)
- **Album cards:** Should NOT be draggable once placed (locked in slot)
- **Runtime control:** Can enable/disable per card instance
---
## Files Structure After Refactor
```
CardSystem/
├─ Card.cs ← NOW inherits from DraggableObject
├─ CardContext.cs
├─ CardAnimator.cs
├─ ProgressBarController.cs
├─ StateMachine/
│ ├─ States/
│ │ ├─ CardDraggingState.cs ← Simplified (visual-only)
│ │ ├─ CardRevealedState.cs ← Drag starts from here
│ │ ├─ CardPlacedInSlotState.cs ← Drag ends here (if valid slot)
│ │ └─ [other states...]
├─ DragDrop/
│ ├─ AlbumCardSlot.cs ← Works with Card (DraggableObject)
│ └─ AlbumCardPlacementDraggable.cs ← OLD system, for corner cards
└─ DEPRECATED/ ✨ NEW
├─ CardDraggable.cs ← Moved
├─ CardDraggableVisual.cs ← Moved
└─ FlippableCard.cs ← Moved
```
---
## Summary
**Card.cs now inherits from DraggableObject** - Owns drag capability
**Drag events trigger state transitions** - OnDragStarted → DraggingState
**DraggingState is visual-only** - Shows scale feedback
**Setup methods control dragging** - Enable/disable per flow
**Backward compatible** - Old files in DEPRECATED/
**Works with existing slots** - AlbumCardSlot unchanged
**Cleaner architecture** - No wrappers, states handle visuals
**Status: Drag/Drop integration complete! Ready for testing and migration.**