Tanoda
DragAndDropCell.cs
Go to the documentation of this file.
1using UnityEngine;
2using UnityEngine.UI;
4using System.Collections;
5using System;
6
10[RequireComponent(typeof(Image))]
11public class DragAndDropCell : MonoBehaviour, IDropHandler
12{
13 public enum CellType // Cell types
14 {
15 Swap, // Items will be swapped between any cells
16 DropOnly, // Item will be dropped into cell
17 DragOnly // Item will be dragged from this cell
18 }
19
20 public enum TriggerType // Types of drag and drop events
21 {
22 DropRequest, // Request for item drop from one cell to another
23 DropEventEnd, // Drop event completed
24 ItemAdded, // Item manualy added into cell
25 ItemWillBeDestroyed // Called just before item will be destroyed
26 }
27
28 public class DropEventDescriptor // Info about item's drop event
29 {
30 public TriggerType triggerType; // Type of drag and drop trigger
31 public DragAndDropCell sourceCell; // From this cell item was dragged
32 public DragAndDropCell destinationCell; // Into this cell item was dropped
33 public DragAndDropItem item; // Dropped item
34 public bool permission; // Decision need to be made on request
35 }
36
37 [Tooltip("Functional type of this cell")]
38 public CellType cellType = CellType.Swap; // Special type of this cell
39 [Tooltip("Sprite color for empty cell")]
40 public Color empty = new Color(); // Sprite color for empty cell
41 [Tooltip("Sprite color for filled cell")]
42 public Color full = new Color(); // Sprite color for filled cell
43 [Tooltip("This cell has unlimited amount of items")]
44 public bool unlimitedSource = false; // Item from this cell will be cloned on drag start
45
46 public bool ignoreColor = false;
47
48 private DragAndDropItem myDadItem; // Item of this DaD cell
49
50 void OnEnable()
51 {
52 DragAndDropItem.OnItemDragStartEvent += OnAnyItemDragStart; // Handle any item drag start
53 DragAndDropItem.OnItemDragEndEvent += OnAnyItemDragEnd; // Handle any item drag end
55 StartCoroutine(LateOnEnabled());
56 }
57
58 IEnumerator LateOnEnabled()
59 {
60 yield return new WaitForEndOfFrame();
62 }
63
64 void OnDisable()
65 {
66 DragAndDropItem.OnItemDragStartEvent -= OnAnyItemDragStart;
67 DragAndDropItem.OnItemDragEndEvent -= OnAnyItemDragEnd;
68 StopAllCoroutines(); // Stop all coroutines if there is any
69 }
70
75 private void OnAnyItemDragStart(DragAndDropItem item)
76 {
78 if (myDadItem != null)
79 {
80 myDadItem.MakeRaycast(false); // Disable item's raycast for correct drop handling
81 if (myDadItem == item) // If item dragged from this cell
82 {
83 // Check cell's type
84 switch (cellType)
85 {
86 case CellType.DropOnly:
87 DragAndDropItem.icon.SetActive(false); // Item can not be dragged. Hide icon
88 break;
89 }
90 }
91 }
92 }
93
98 private void OnAnyItemDragEnd(DragAndDropItem item)
99 {
100 UpdateMyItem();
101 if (myDadItem != null)
102 {
103 myDadItem.MakeRaycast(true); // Enable item's raycast
104 }
106 }
107
112 public void OnDrop(PointerEventData data)
113 {
114 if (DragAndDropItem.icon != null)
115 {
118 if (DragAndDropItem.icon.activeSelf == true) // If icon inactive do not need to drop item into cell
119 {
120 if ((item != null) && (sourceCell != this))
121 {
123 switch (cellType) // Check this cell's type
124 {
125 case CellType.Swap: // Item in destination cell can be swapped
126 UpdateMyItem();
127 switch (sourceCell.cellType)
128 {
129 case CellType.Swap: // Item in source cell can be swapped
130 // Fill event descriptor
131 desc.item = item;
132 desc.sourceCell = sourceCell;
133 desc.destinationCell = this;
134 SendRequest(desc); // Send drop request
135 StartCoroutine(NotifyOnDragEnd(desc)); // Send notification after drop will be finished
136 if (desc.permission == true) // If drop permitted by application
137 {
138 if (myDadItem != null) // If destination cell has item
139 {
140 // Fill event descriptor
141 DropEventDescriptor descAutoswap = new DropEventDescriptor();
142 descAutoswap.item = myDadItem;
143 descAutoswap.sourceCell = this;
144 descAutoswap.destinationCell = sourceCell;
145 SendRequest(descAutoswap); // Send drop request
146 StartCoroutine(NotifyOnDragEnd(descAutoswap)); // Send notification after drop will be finished
147 if (descAutoswap.permission == true) // If drop permitted by application
148 {
149 SwapItems(sourceCell, this); // Swap items between cells
150 }
151 else
152 {
153 PlaceItem(item); // Delete old item and place dropped item into this cell
154 }
155 }
156 else
157 {
158 PlaceItem(item); // Place dropped item into this empty cell
159 }
160 }
161 break;
162 default: // Item in source cell can not be swapped
163 // Fill event descriptor
164 desc.item = item;
165 desc.sourceCell = sourceCell;
166 desc.destinationCell = this;
167 SendRequest(desc); // Send drop request
168 StartCoroutine(NotifyOnDragEnd(desc)); // Send notification after drop will be finished
169 if (desc.permission == true) // If drop permitted by application
170 {
171 PlaceItem(item); // Place dropped item into this cell
172 }
173 break;
174 }
175 break;
176 case CellType.DropOnly: // Item only can be dropped into destination cell
177 // Fill event descriptor
178 desc.item = item;
179 desc.sourceCell = sourceCell;
180 desc.destinationCell = this;
181 SendRequest(desc); // Send drop request
182 StartCoroutine(NotifyOnDragEnd(desc)); // Send notification after drop will be finished
183 if (desc.permission == true) // If drop permitted by application
184 {
185 PlaceItem(item); // Place dropped item in this cell
186 }
187 break;
188 default:
189 break;
190 }
191 }
192 }
193 //if (item != null)
194 //{
195 //if (item.GetComponentInParent<DragAndDropCell>() == null) // If item have no cell after drop
196 //{
197 //Destroy(item.gameObject); // Destroy it
198 //}
199 //}
200 UpdateMyItem();
202 //sourceCell.UpdateMyItem();
203 //sourceCell.UpdateBackgroundState();
204 }
205 }
206
211 private void PlaceItem(DragAndDropItem item)
212 {
213 if (item != null)
214 {
215 DestroyItem(); // Remove current item from this cell
216 myDadItem = null;
217 DragAndDropCell cell = item.GetComponentInParent<DragAndDropCell>();
218 if (cell != null)
219 {
220 if (cell.unlimitedSource == true)
221 {
222 string itemName = item.name;
223 item = Instantiate(item); // Clone item from source cell
224 item.name = itemName;
225 }
226 }
227 item.transform.SetParent(transform, false);
228 item.transform.localPosition = Vector3.zero;
229 item.MakeRaycast(true);
230 myDadItem = item;
231 }
233 }
234
238 private void DestroyItem()
239 {
240 UpdateMyItem();
241 if (myDadItem != null)
242 {
243 DropEventDescriptor desc = new DropEventDescriptor();
244 // Fill event descriptor
245 desc.triggerType = TriggerType.ItemWillBeDestroyed;
246 desc.item = myDadItem;
247 desc.sourceCell = this;
248 desc.destinationCell = this;
249 SendNotification(desc); // Notify application about item destruction
250 if (myDadItem != null)
251 {
252 Destroy(myDadItem.gameObject);
253 }
254 }
255 myDadItem = null;
257 }
258
263 private void SendNotification(DropEventDescriptor desc)
264 {
265 if (desc != null)
266 {
267 // Send message with DragAndDrop info to parents GameObjects
268 gameObject.SendMessageUpwards("OnSimpleDragAndDropEvent", desc, SendMessageOptions.DontRequireReceiver);
269 }
270 }
271
277 private bool SendRequest(DropEventDescriptor desc)
278 {
279 bool result = false;
280 if (desc != null)
281 {
282 desc.triggerType = TriggerType.DropRequest;
283 desc.permission = true;
284 SendNotification(desc);
285 result = desc.permission;
286 }
287 return result;
288 }
289
295 private IEnumerator NotifyOnDragEnd(DropEventDescriptor desc)
296 {
297 // Wait end of drag operation
298 while (DragAndDropItem.draggedItem != null)
299 {
300 yield return new WaitForEndOfFrame();
301 }
302 desc.triggerType = TriggerType.DropEventEnd;
303 SendNotification(desc);
304 }
305
311 {
312 if (ignoreColor)
313 return;
314
315 Image bg = GetComponent<Image>();
316 if (bg != null)
317 {
318 bg.color = myDadItem != null ? full : empty;
319 }
320 }
321
325 public void UpdateMyItem()
326 {
327 myDadItem = GetComponentInChildren<DragAndDropItem>();
328 }
329
335 {
336 return myDadItem;
337 }
338
343 public void AddItem(DragAndDropItem newItem)
344 {
345 if (newItem != null)
346 {
347 PlaceItem(newItem);
349 // Fill event descriptor
350 desc.triggerType = TriggerType.ItemAdded;
351 desc.item = newItem;
352 desc.sourceCell = this;
353 desc.destinationCell = this;
354 SendNotification(desc);
355 }
356 }
357
361 public void RemoveItem()
362 {
363 DestroyItem();
364 }
365
371 public void SwapItems(DragAndDropCell firstCell, DragAndDropCell secondCell)
372 {
373 if ((firstCell != null) && (secondCell != null))
374 {
375 DragAndDropItem firstItem = firstCell.GetItem(); // Get item from first cell
376 DragAndDropItem secondItem = secondCell.GetItem(); // Get item from second cell
377 // Swap items
378 if (firstItem != null)
379 {
380 firstItem.transform.SetParent(secondCell.transform, false);
381 firstItem.transform.localPosition = Vector3.zero;
382 firstItem.MakeRaycast(true);
383 }
384 if (secondItem != null)
385 {
386 secondItem.transform.SetParent(firstCell.transform, false);
387 secondItem.transform.localPosition = Vector3.zero;
388 secondItem.MakeRaycast(true);
389 }
390 // Update states
391 firstCell.UpdateMyItem();
392 secondCell.UpdateMyItem();
393 firstCell.UpdateBackgroundState();
394 secondCell.UpdateBackgroundState();
395 }
396 }
397
398 public static implicit operator DragAndDropCell(DragAndDropRawCell v)
399 {
400 var dndc = new DragAndDropCell
401 {
402 cellType = v.cellType,
403 empty = v.empty,
404 full = v.full,
407 myDadItem = v.myDadItem
408 };
409 return dndc;
410 }
411}
System.Drawing.Image Image
Definition: TestScript.cs:37
UnityEngine.Color Color
Definition: TestScript.cs:32
Every item's cell must contain this script
void SwapItems(DragAndDropCell firstCell, DragAndDropCell secondCell)
Swap items between two cells
void AddItem(DragAndDropItem newItem)
Manualy add item into this cell
void OnDrop(PointerEventData data)
Item is dropped in this cell
void UpdateBackgroundState()
Change cell's sprite color on item put/remove.
DragAndDropItem GetItem()
Get item from this cell
void RemoveItem()
Manualy delete item from this cell
void UpdateMyItem()
Updates my item
Drag and Drop item.
static DragEvent OnItemDragEndEvent
static DragAndDropCell sourceCell
static DragAndDropItem draggedItem
void MakeRaycast(bool condition)
Enable item's raycast.
static GameObject icon
static DragEvent OnItemDragStartEvent
Every item's cell must contain this script