# 🎨 SlotContainer Custom Layout Guide ## 📋 Overview The `SlotContainer` has a **Custom** layout mode that's perfect for artistic, hand-authored slot positions! When you select `Custom`, the SlotContainer **doesn't automatically position your slots** - it lets you manually position them however you want. --- ## 🎯 How Custom Layout Works ### **What Happens When Layout = Custom:** Looking at the code: ```csharp public void UpdateLayout() { if (layoutType == LayoutType.Custom) { OnLayoutChanged?.Invoke(); // Just fires the event return; // Doesn't reposition anything! } // Other layouts (Horizontal, Vertical, Grid) reposition slots here... } ``` **Key Point:** Custom layout means **"Don't touch my slot positions!"** The SlotContainer still: - ✅ Registers your slots - ✅ Finds closest slot when dragging - ✅ Manages slot occupancy - ✅ Fires events But it **does NOT:** - ❌ Automatically position slots - ❌ Apply spacing - ❌ Center slots - ❌ Use curves or grids --- ## 🛠️ Setting Up Custom Layout (Step-by-Step) ### **Method 1: Hand-Author in Scene (Recommended)** This is the easiest and most visual approach: 1. **Create SlotContainer:** ``` BottomRightContainer └── [Add Component: SlotContainer] ``` 2. **Set Layout Type:** - Layout Type: `Custom` - Auto Register Children: ✓ (keep this checked) 3. **Create Slot Children:** ``` BottomRightContainer ├── Slot_0 (DraggableSlot) ├── Slot_1 (DraggableSlot) ├── Slot_2 (DraggableSlot) └── Slot_3 (DraggableSlot) ``` 4. **Position Slots Manually in Scene View:** - Select `Slot_0` - Drag it to artistic position (e.g., X=-150, Y=200) - Select `Slot_1` - Drag it to artistic position (e.g., X=50, Y=150) - Select `Slot_2` - Drag it to artistic position (e.g., X=-200, Y=50) - Etc. 5. **Done!** Your slots stay exactly where you put them. --- ### **Method 2: Script Positions (For Procedural Scatter)** If you want some randomness or code-controlled positions: ```csharp using UnityEngine; using UI.DragAndDrop.Core; public class CustomSlotPositioner : MonoBehaviour { [SerializeField] private SlotContainer slotContainer; [SerializeField] private Vector2[] handAuthoredPositions; private void Start() { PositionSlots(); } private void PositionSlots() { var slots = slotContainer.Slots; for (int i = 0; i < slots.Count && i < handAuthoredPositions.Length; i++) { if (slots[i].RectTransform != null) { slots[i].RectTransform.anchoredPosition = handAuthoredPositions[i]; } } } } ``` Then in Inspector: - Hand Authored Positions (Array): - Element 0: (-150, 200) - Element 1: (50, 150) - Element 2: (-200, 50) - Etc. --- ### **Method 3: Subscribe to OnLayoutChanged Event** For advanced custom positioning logic: ```csharp using UnityEngine; using UI.DragAndDrop.Core; public class ArtisticSlotLayout : MonoBehaviour { [SerializeField] private SlotContainer slotContainer; [SerializeField] private float scatterRadius = 200f; [SerializeField] private bool useRandomSeed = true; [SerializeField] private int seed = 42; private void Awake() { if (slotContainer != null) { slotContainer.OnLayoutChanged += ApplyCustomLayout; } } private void OnDestroy() { if (slotContainer != null) { slotContainer.OnLayoutChanged -= ApplyCustomLayout; } } private void ApplyCustomLayout() { if (useRandomSeed) Random.InitState(seed); var slots = slotContainer.Slots; for (int i = 0; i < slots.Count; i++) { if (slots[i].RectTransform != null) { // Scattered circular layout float angle = Random.Range(0f, 360f); float distance = Random.Range(0f, scatterRadius); float x = Mathf.Cos(angle * Mathf.Deg2Rad) * distance; float y = Mathf.Sin(angle * Mathf.Deg2Rad) * distance; slots[i].RectTransform.anchoredPosition = new Vector2(x, y); // Optional: Random rotation for extra artistic flair slots[i].RectTransform.rotation = Quaternion.Euler(0, 0, Random.Range(-15f, 15f)); } } } } ``` --- ## 🎨 Example: Artistic Scattered Boosters ### **Scenario:** 3 booster slots scattered artistically in bottom-right **Setup:** ``` BottomRightContainer (SlotContainer - Custom Layout) ├── Slot_0 (DraggableSlot) │ └── Position: (-180, 220) │ └── Rotation: (0, 0, -5) ← Slight tilt left ├── Slot_1 (DraggableSlot) │ └── Position: (40, 180) │ └── Rotation: (0, 0, 8) ← Slight tilt right └── Slot_2 (DraggableSlot) └── Position: (-220, 80) └── Rotation: (0, 0, -3) ← Slight tilt left ``` **Visual Result:** ``` [Slot_0] ← Tilted left, higher [Slot_1] ← Tilted right, middle [Slot_2] ← Tilted left, lower ``` --- ## ⚙️ Custom Layout Inspector Settings When you select **Custom** layout type, these settings are **ignored**: - ❌ Spacing (not used) - ❌ Center Slots (not used) - ❌ Use Curve Layout (not used) - ❌ Position Curve (not used) - ❌ Curve Height (not used) These settings **still work**: - ✅ Auto Register Children (still registers your slots) - ✅ OnSlotAdded/OnSlotRemoved events (still fire) - ✅ OnLayoutChanged event (fires when UpdateLayout is called) --- ## 🎯 Best Practices for Custom Layout ### **1. Use Scene View for Positioning** - Easiest and most visual - See results immediately - Adjust in real-time ### **2. Add Visual Guides** - Create a background image showing your intended layout - Position slots over the image - Delete/hide the guide after ### **3. Use Gizmos for Visualization** ```csharp private void OnDrawGizmos() { if (slotContainer == null || slotContainer.Slots == null) return; Gizmos.color = Color.yellow; foreach (var slot in slotContainer.Slots) { if (slot != null) { Gizmos.DrawWireSphere(slot.transform.position, 50f); } } } ``` ### **4. Consider Spacing** - Even with artistic scatter, avoid overlapping slots - Leave enough space for hover/selection effects - Test with different screen sizes ### **5. Save Positions in Prefab** - Once you're happy with positions, save to prefab - Ensures consistency across scenes --- ## 🔄 Combining Custom with Other Layouts You can switch layout types at runtime: ```csharp public class DynamicLayoutSwitcher : MonoBehaviour { [SerializeField] private SlotContainer slotContainer; public void SwitchToScattered() { // Save current positions Vector2[] savedPositions = new Vector2[slotContainer.SlotCount]; for (int i = 0; i < slotContainer.SlotCount; i++) { savedPositions[i] = slotContainer.GetSlotAtIndex(i).RectTransform.anchoredPosition; } // Switch to custom // Note: You'd need to expose layoutType or use reflection // For now, this is just conceptual } } ``` --- ## 📋 Quick Setup Checklist For your bottom-right booster slots: 1. **Create Container:** ``` BottomRightContainer └── Layout Type: Custom └── Auto Register Children: ✓ ``` 2. **Create 3 Slot Children:** ``` Slot_0, Slot_1, Slot_2 └── Each has DraggableSlot component ``` 3. **Position Each Slot:** - Use Scene View - Click and drag to artistic positions - Optional: Add slight rotation (Z-axis) 4. **Test:** - Drag boosters to slots - Verify they snap correctly - Adjust positions as needed 5. **Save to Prefab:** - Once happy, save BoosterOpeningPage prefab - Positions are preserved --- ## 💡 Creative Ideas ### **Scattered Stack:** ``` Slot_0: (-200, 250) Rotation: -8° Slot_1: (-180, 220) Rotation: 3° Slot_2: (-210, 195) Rotation: -5° ``` → Looks like a messy pile of cards! ### **Arc Formation:** ``` Slot_0: (-180, 200) Rotation: -15° Slot_1: (0, 220) Rotation: 0° Slot_2: (180, 200) Rotation: 15° ``` → Gentle arc, like cards in hand ### **Diagonal Cascade:** ``` Slot_0: (-150, 250) Rotation: -10° Slot_1: (-50, 180) Rotation: -5° Slot_2: (50, 110) Rotation: 0° ``` → Diagonal waterfall effect --- ## 🐛 Troubleshooting Custom Layout **Problem: Slots keep resetting position** → Make sure Layout Type = `Custom` → Check if something is calling `UpdateLayout()` with a different type **Problem: Slots don't register** → Ensure Auto Register Children = ✓ → Verify slots are direct children of SlotContainer **Problem: Can't drag boosters to slots** → Check DraggableSlot configuration (Filter By Type, etc.) → Verify slots aren't locked **Problem: Positions lost on scene reload** → Save to prefab! → Check if positions are being set in Awake/Start --- ## 📝 Summary **Custom Layout = Full Manual Control!** - ✅ Position slots anywhere you want - ✅ Add rotation for artistic flair - ✅ No automatic repositioning - ✅ Perfect for hand-authored layouts - ✅ Still gets all SlotContainer benefits (registration, finding, events) **Recommended Workflow:** 1. Set Layout Type = Custom 2. Create slot children 3. Position visually in Scene View 4. Test drag-and-drop 5. Adjust as needed 6. Save to prefab --- 🎨 **Now go create some beautiful, artistic slot layouts!** 🎨