Merge a card refresh (#59)
- **Refactored Card Placement Flow** - Separated card presentation from orchestration logic - Extracted `CornerCardManager` for pending card lifecycle (spawn, shuffle, rebuild) - Extracted `AlbumNavigationService` for book page navigation and zone mapping - Extracted `CardEnlargeController` for backdrop management and card reparenting - Implemented controller pattern (non-MonoBehaviour) for complex logic - Cards now unparent from slots before rebuild to prevent premature destruction - **Improved Corner Card Display** - Fixed cards spawning on top of each other during rebuild - Implemented shuffle-to-front logic (remaining cards occupy slots 0→1→2) - Added smart card selection (prioritizes cards matching current album page) - Pending cards now removed from queue immediately on drag start - Corner cards rebuild after each placement with proper slot reassignment - **Enhanced Album Card Viewing** - Added dramatic scale increase when viewing cards from album slots - Implemented shrink animation when dismissing enlarged cards - Cards transition: `PlacedInSlotState` → `AlbumEnlargedState` → `PlacedInSlotState` - Backdrop shows/hides with card enlarge/shrink cycle - Cards reparent to enlarged container while viewing, return to slot after - **State Machine Improvements** - Added `CardStateNames` constants for type-safe state transitions - Implemented `ICardClickHandler` and `ICardStateDragHandler` interfaces - State transitions now use cached property indices - `BoosterCardContext` separated from `CardContext` for single responsibility - **Code Cleanup** - Identified unused `SlotContainerHelper.cs` (superseded by `CornerCardManager`) - Identified unused `BoosterPackDraggable.canOpenOnDrop` field - Identified unused `AlbumViewPage._previousInputMode` (hardcoded value) - Identified unused `Card.OnPlacedInAlbumSlot` event (no subscribers) Co-authored-by: Michal Pikulski <michal.a.pikulski@gmail.com> Co-authored-by: Michal Pikulski <michal@foolhardyhorizons.com> Reviewed-on: #59
This commit is contained in:
@@ -243,6 +243,10 @@ namespace UI.DragAndDrop.Core
|
||||
|
||||
public virtual void OnDrag(PointerEventData eventData)
|
||||
{
|
||||
// Just ship all this shit when disabled
|
||||
if (!_isDraggingEnabled)
|
||||
return;
|
||||
|
||||
if (!_isDragging)
|
||||
return;
|
||||
|
||||
@@ -269,6 +273,9 @@ namespace UI.DragAndDrop.Core
|
||||
|
||||
public virtual void OnEndDrag(PointerEventData eventData)
|
||||
{
|
||||
if (!_isDraggingEnabled)
|
||||
return;
|
||||
|
||||
if (!_isDragging)
|
||||
return;
|
||||
|
||||
@@ -282,14 +289,7 @@ namespace UI.DragAndDrop.Core
|
||||
if (_canvasGroup != null)
|
||||
_canvasGroup.blocksRaycasts = true;
|
||||
|
||||
// Find closest slot and snap
|
||||
FindAndSnapToSlot();
|
||||
|
||||
// Snap base rotation back to slot rotation (if in a slot)
|
||||
if (_currentSlot != null)
|
||||
{
|
||||
Tween.Rotation(transform, _currentSlot.transform.rotation, 0.3f, 0f, Tween.EaseOutBack);
|
||||
}
|
||||
// No auto-slotting - derived classes handle placement logic via OnDragEndedHook()
|
||||
|
||||
OnDragEnded?.Invoke(this);
|
||||
OnDragEndedHook();
|
||||
@@ -344,70 +344,8 @@ namespace UI.DragAndDrop.Core
|
||||
|
||||
#region Slot Management
|
||||
|
||||
protected virtual void FindAndSnapToSlot()
|
||||
{
|
||||
SlotContainer[] containers = FindObjectsByType<SlotContainer>(FindObjectsSortMode.None);
|
||||
DraggableSlot closestSlot = null;
|
||||
float closestDistance = float.MaxValue;
|
||||
|
||||
// Use RectTransform.position for overlay, transform.position for others
|
||||
Vector3 myPosition = (_canvas != null && _canvas.renderMode == RenderMode.ScreenSpaceOverlay && RectTransform != null)
|
||||
? RectTransform.position
|
||||
: transform.position;
|
||||
|
||||
foreach (var container in containers)
|
||||
{
|
||||
DraggableSlot slot = container.FindClosestSlot(myPosition, this);
|
||||
if (slot != null)
|
||||
{
|
||||
Vector3 slotPosition = slot.RectTransform != null ? slot.RectTransform.position : slot.transform.position;
|
||||
float distance = Vector3.Distance(myPosition, slotPosition);
|
||||
if (distance < closestDistance)
|
||||
{
|
||||
closestDistance = distance;
|
||||
closestSlot = slot;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (closestSlot != null)
|
||||
{
|
||||
// Check if slot is occupied
|
||||
if (closestSlot.IsOccupied && closestSlot.Occupant != this)
|
||||
{
|
||||
// Swap with occupant
|
||||
SwapWithSlot(closestSlot);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Move to empty slot
|
||||
AssignToSlot(closestSlot, true);
|
||||
}
|
||||
}
|
||||
else if (_currentSlot != null)
|
||||
{
|
||||
// Return to current slot if no valid slot found
|
||||
SnapToCurrentSlot();
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void SwapWithSlot(DraggableSlot targetSlot)
|
||||
{
|
||||
DraggableSlot mySlot = _currentSlot;
|
||||
DraggableObject otherObject = targetSlot.Occupant;
|
||||
|
||||
if (otherObject != null)
|
||||
{
|
||||
// Both objects swap slots
|
||||
targetSlot.Vacate();
|
||||
if (mySlot != null)
|
||||
mySlot.Vacate();
|
||||
|
||||
AssignToSlot(targetSlot, true);
|
||||
if (mySlot != null)
|
||||
otherObject.AssignToSlot(mySlot, true);
|
||||
}
|
||||
}
|
||||
// Auto-slotting removed - derived classes (Card, etc.) handle placement via state machines
|
||||
// AssignToSlot() and SnapToSlot() kept for explicit slot assignment
|
||||
|
||||
public virtual void AssignToSlot(DraggableSlot slot, bool animate)
|
||||
{
|
||||
@@ -461,14 +399,6 @@ namespace UI.DragAndDrop.Core
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void SnapToCurrentSlot()
|
||||
{
|
||||
if (_currentSlot != null)
|
||||
{
|
||||
SnapToSlot(_currentSlot);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Selection
|
||||
|
||||
Reference in New Issue
Block a user