I've been trying to develop an UI item dragging and dropping system for the past few days and make it as flexible as possible (it's being developed using Unity 3D although that's not exactly relevant to my problem). Here's the code before I get to explaining exactly what the issue is:
public class ItemHandler<ItemType> : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler, IHoverHandler where ItemType : Item {
public ItemType item { get; protected set; }
...
}
public abstract class SlotHandler<ItemType> : MonoBehaviour, IDropHandler where ItemType : Item {
...
public ItemHandler<ItemType> itemHandler { get; protected set; }
...
public void OnDrop(PointerEventData eventData) {
// Retrieve the slots
SlotHandler<Item> originalSlotHandler = ItemManager.draggedItemParent.GetComponent<SlotHandler<Item>>();
SlotHandler<ItemType> destinationSlotHandler = this;
// Retrieve the handlers from their items
ItemHandler<Item> originalItemHandler = originalSlotHandler.itemObject != null ? originalSlotHandler.itemObject.GetComponent<ItemHandler<Item>>() : null;
ItemHandler<ItemType> destinationItemHandler = destinationSlotHandler.itemObject != null ? destinationSlotHandler.itemObject.GetComponent<ItemHandler<ItemType>>() : null;
// Add the original item to the destination slot
bool canAddToDestination = originalSlotHandler is SlotHandler<ItemType> || originalSlotHandler is SlotHandler<Item>;
bool canRemoveFromOrigin = originalSlotHandler is SlotHandler<ItemType> || destinationSlotHandler is SlotHandler<Item>;
// Swap the items
if(canAddToDestination == true && canRemoveFromOrigin == true) {
// Remove the old items
originalSlotHandler.RemoveItem();
destinationSlotHandler.RemoveItem();
// Add the new items
originalSlotHandler.AddItem(destinationItemHandler);
destinationSlotHandler.AddItem(originalItemHandler);
...
}
...
}
public virtual void AddItem(ItemHandler<ItemType> itemHandler) {
this.itemHandler = itemHandler;
}
}
The idea behind this is to have ItemHandler of a given type (e.g. ItemHandler< Gem >, ItemHandler< Weapon > etc.) and then only allow them to be dropped into SlotHandlers of the same type OR of the same base type.
- ItemHandler< Gem > goes into SlotHandler< Gem > and SlotHandler< Item >.
- ItemHandler< Weapon > goes into SlotHandler< Weapon > and SlotHandler< Item >.
I tried doing things this way because I want to limit in which slots I'm able to drop specific items.
The problem comes from the fact that I have to take into account a specific type of slot, SlotHandler< Item > (the Item class you see in the code snippet which is the base class for all Items). The inventory slots should be able to hold every type of item.
Now, since ItemHandler< Gem > isn't a subclass of ItemHandler< Item > (or any other derived type of Item) this won't work. Now you might say why not just store Item instead of storing a Generic ItemType? I would but the idea here is to derive SlotHandler and have specific behaviour in each sub-class (dropping items into different types of slots should do different things).
I think I understand why this won't work the way I'm trying to do it but I can't find a solution I feel comfortable with so I thought I'd try and ask for some help. Sorry If I'm not being clear enough with the problem, please let me know if I should clear something up.
Thanks in advance for any help trying to solve my problem!