using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class DragDropBaseClass : MonoBehaviour, IEndDragHandler, IDragHandler, IBeginDragHandler
{
public bool dragOnSurfaces = true;
public GameObject m_DraggingIcon;
internal RectTransform m_DraggingPlane;
public void OnEndDrag(PointerEventData eventData)
{
if (m_DraggingIcon != null)
{
Destroy(m_DraggingIcon);
Image img = transform.GetComponent<Image>();
img.color = new Color(img.color.r, img.color.g, img.color.b, 1f);
}
}
public void OnDrag(PointerEventData data)
{
if (m_DraggingIcon != null)
SetDraggedPosition(data);
}
public virtual void OnBeginDrag(PointerEventData eventData)
{
var canvas = FindInParents<Canvas>(gameObject);
if (canvas == null)
return;
Image img = transform.GetComponent<Image>();
img.color = new Color(img.color.r, img.color.g, img.color.b, 0.2f);
// We have clicked something that can be dragged.
// What we want to do is create an icon for this.
m_DraggingIcon = new GameObject("icon");
m_DraggingIcon.transform.SetParent(canvas.transform, false);
m_DraggingIcon.transform.SetAsLastSibling();
m_DraggingIcon.AddComponent<CanvasGroup>();
m_DraggingIcon.GetComponent<CanvasGroup>().blocksRaycasts = false;
var image = m_DraggingIcon.AddComponent<Image>();
image.sprite = GetComponent<Image>().sprite;
if (dragOnSurfaces)
m_DraggingPlane = transform as RectTransform;
else
m_DraggingPlane = canvas.transform as RectTransform;
SetDraggedPosition(eventData);
}
private void SetDraggedPosition(PointerEventData data)
{
if (dragOnSurfaces && data.pointerEnter != null && data.pointerEnter.transform as RectTransform != null)
m_DraggingPlane = data.pointerEnter.transform as RectTransform;
var rt = m_DraggingIcon.GetComponent<RectTransform>();
Vector3 globalMousePos;
if (RectTransformUtility.ScreenPointToWorldPointInRectangle(m_DraggingPlane, data.position, data.pressEventCamera, out globalMousePos))
{
rt.position = globalMousePos;
rt.rotation = m_DraggingPlane.rotation;
}
}
private T FindInParents<T>(GameObject go) where T : Component
{
if (go == null) return null;
var comp = go.GetComponent<T>();
if (comp != null)
return comp;
Transform t = go.transform.parent;
while (t != null && comp == null)
{
comp = t.gameObject.GetComponent<T>();
t = t.parent;
}
return comp;
}
}
using ORKFramework;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
public class InventoryDrag : DragDropBaseClass
{
public IInventoryShortcut inventoryItem = null;
public override void OnBeginDrag(PointerEventData eventData)
{
// don't drag if this is an empty slot
if (inventoryItem == null)
return;
base.OnBeginDrag(eventData);
}
}
using ORKFramework;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class InventoryControl : MonoBehaviour
{
private Combatant playerCombatant;
[Tooltip("The game object prefab that will be created for every inventory item")]
[SerializeField]
private GameObject prefab;
void Start()
{
StartCoroutine(GetPlayer());
}
private IEnumerator GetPlayer()
{
do
{
playerCombatant = ORK.Game.ActiveGroup.Leader;
yield return null;
}
while (this.playerCombatant == null);
PopulateInventory();
}
public void PopulateInventory()
{
if (playerCombatant != null)
{
List<IInventoryShortcut> inventory = new List<IInventoryShortcut>();
// determine at THIS point what we actually want to see, items, weapons, armor, ALL?
playerCombatant.Inventory.GetAll(false, false, true, true, true, false, false, false, -1, false, ref inventory);
// clear the inventory and populate with the new inventory
clearScrollView();
GameObject newObj;
int numberToCreate = 0;
if (ORK.InventorySettings.limit)
numberToCreate = Convert.ToInt32(ORK.InventorySettings.limitValue.value);
else
numberToCreate = inventory.Count;
for (int i = 0; i < numberToCreate; i++)
{
// Create new instances of our prefab until we've created as many as we specified
newObj = (GameObject)Instantiate(prefab, transform);
if (inventory.Count > i)
{
Texture tex = inventory[i].GetIcon();
Transform trItem = newObj.transform.Find("InventoryItem");
Image img = trItem.GetComponent<Image>();
((InventoryDrag)trItem.GetComponent<InventoryDrag>()).inventoryItem = inventory[i];
img.sprite = Sprite.Create(tex as Texture2D, new Rect(0, 0, tex.width, tex.height), new Vector2(.5f, .5f));
img.color = new Color(img.color.r, img.color.g, img.color.b, 1);
}
else
{
// here we are creating a blank border image with no inventrory item inside
Image img = newObj.transform.Find("InventoryItem").GetComponent<Image>();
img.color = new Color(img.color.r, img.color.g, img.color.b, 0); // make transparent
}
}
}
}
private void clearScrollView()
{
foreach (Transform child in transform)
{
Destroy(child.gameObject);
}
}
}
using ORKFramework;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using ORKEnums;
public class EquipDrag : DragDropBaseClass, IDropHandler
{
[Tooltip("ORK Framework Equipment slot ID")]
[SerializeField]
private int equipmentSlotID;
private Combatant playerCombatant;
public InventoryControl controller;
public Image borderImage;
public Image equipmentImage;
void Start()
{
StartCoroutine(GetPlayer());
}
private IEnumerator GetPlayer()
{
do
{
playerCombatant = ORK.Game.ActiveGroup.Leader;
yield return null;
}
while (this.playerCombatant == null);
displayEquipmentSlot();
}
private void displayEquipmentSlot()
{
if (playerCombatant.Equipment[(int)equipmentSlotID].Available)
{
this.gameObject.SetActive(true);
if (!playerCombatant.Equipment[(int)equipmentSlotID].Equipped)
{
borderImage.color = new Color(borderImage.color.r, borderImage.color.g, borderImage.color.b, 1);
equipmentImage.color = new Color(equipmentImage.color.r, equipmentImage.color.g, equipmentImage.color.b, 0);
}
else
{
// display this image
borderImage.color = new Color(borderImage.color.r, borderImage.color.g, borderImage.color.b, 1);
equipmentImage.color = new Color(equipmentImage.color.r, equipmentImage.color.g, equipmentImage.color.b, 1);
Texture tex = playerCombatant.Equipment[(int)equipmentSlotID].Equipment.GetIcon();
equipmentImage.sprite = Sprite.Create(tex as Texture2D, new Rect(0, 0, tex.width, tex.height), new Vector2(.5f, .5f));
}
}
else
{
// hide it
borderImage.color = new Color(borderImage.color.r, borderImage.color.g, borderImage.color.b, 0);
equipmentImage.color = new Color(equipmentImage.color.r, equipmentImage.color.g, equipmentImage.color.b, 0);
this.gameObject.SetActive(false);
}
}
public void OnDrop(PointerEventData eventData)
{
if (eventData.pointerDrag != null)
{
InventoryDrag itemScript = ((InventoryDrag)eventData.pointerDrag.GetComponent<InventoryDrag>());
if (itemScript != null && playerCombatant.Equipment[(int)equipmentSlotID].Available && !playerCombatant.Equipment[(int)equipmentSlotID].IsBlocked)
{
if (itemScript.inventoryItem != null)
{
if (itemScript.inventoryItem is ItemShortcut)
{
//; we can't actually *equip* items so we can ignore this (for the moment)
}
else if (itemScript.inventoryItem is EquipShortcut)
{
EquipShortcut eshort = (EquipShortcut)itemScript.inventoryItem;
if (eshort.CanEquip(playerCombatant))
{
playerCombatant.Equipment.Equip((int)equipmentSlotID, eshort, playerCombatant, playerCombatant, true);
playerCombatant.Status.ResetStatus(true);
}
}
}
}
if (itemScript != null && itemScript.m_DraggingIcon != null)
Destroy(itemScript.m_DraggingIcon);
displayEquipmentSlot();
if (controller != null) controller.PopulateInventory();
}
}
public override void OnBeginDrag(PointerEventData eventData)
{
// don't drag if this is an empty slot
if (!playerCombatant.Equipment[(int)equipmentSlotID].Equipped)
{
return;
}
base.OnBeginDrag(eventData);
}
}
It looks like you're new here. If you want to get involved, click one of these buttons!
If you're enjoying my products, updates and support, please consider supporting me on patreon.com!
Also, I added bool variable to base class for checking when item actually dragged. All over changes was mostly cosmetic. Everything dragged, dropped, equipped and unequipped now :)
Great you caught the ResetSatus thing, I hadn't noticed anything since I am still working on various GUI interfaces and not actually *using* any of them in anger yet :)
I'll have to add add that to my code too!
public static InventoryManager instance = null;
void Awake()
{
instance = this;
}
You can make your UI modular. One manager will enable them or disable. Instances can use OnEnable instead of Awake to initialize.
And they can be accessed each other by InventoryManager.instance (as exemple) without need using Find or direct links. Only tricky thing here is to enable them in particular order to avoid Null References.
At the moment I am throwing mud at the walls and see what sticks. Just implemented the new Unity Input System (Preview) to fire the Ork shortcuts so the user can change key bindings in game. No idea how to get into the ORK KeyControls stuff properly but what I have works. Part of the implementation of a Diablo/Torchlight mouse click system attack system.
Maybe singletons would be a way to go with this....
You could work with something like this.
Singleton base class
using UnityEngine;
/// <summary>
/// Inherit from this base class to create a singleton.
/// e.g. public class MyClassName : Singleton<MyClassName> {}
/// </summary>
public class Singleton<T> : MonoBehaviour where T : MonoBehaviour
{
// Check to see if we're about to be destroyed.
private static bool m_ShuttingDown = false;
private static object m_Lock = new object();
private static T m_Instance;
/// <summary>
/// Access singleton instance through this propriety.
/// </summary>
public static T Instance
{
get
{
if (m_ShuttingDown)
{
Debug.LogWarning("[Singleton] Instance '" + typeof(T) +
"' already destroyed. Returning null.");
return null;
}
lock (m_Lock)
{
if (m_Instance == null)
{
// Search for existing instance.
m_Instance = (T)FindObjectOfType(typeof(T));
// Create new instance if one doesn't already exist.
if (m_Instance == null)
{
// Need to create a new GameObject to attach the singleton to.
var singletonObject = new GameObject();
m_Instance = singletonObject.AddComponent<T>();
singletonObject.name = typeof(T).ToString() + " (Singleton)";
// Make instance persistent.
DontDestroyOnLoad(singletonObject);
}
}
return m_Instance;
}
}
}
private void OnApplicationQuit()
{
m_ShuttingDown = true;
}
private void OnDestroy()
{
m_ShuttingDown = true;
}
}
Implemented in a GameControl singleton:
using ORKFramework;
using System.Collections;
public class GameControlSingleton : Singleton<GameControlSingleton>
{
// (Optional) Prevent non-singleton constructor use.
protected GameControlSingleton() { }
public Combatant PlayerCombatant { get; set; }
public string ExampleString = "String contents";
void Start()
{
StartCoroutine(GetPlayer());
}
private IEnumerator GetPlayer()
{
do
{
PlayerCombatant = ORK.Game.ActiveGroup.Leader;
yield return null;
}
while (this.PlayerCombatant == null);
}
}
That class can contain LOTS of code and properties and be used elsewhere in the game for other purposes (see the Example string for example)
Note:
- To access the properties of the singleton you use GameControlSingleton.Instance.PlayerCombatant
or GameControlSingleton.Instance.ExampleString
- The first time you call the singleton this way it is instantiated so the PlayerCombatant will be NULL
- The second time assuming the co-routine worked, PlayerCombatant will return the player
Obviously lots of ways to change this and use it.
I am in debt again! Hope it will help others too :)
That code, like my drag and drop stuff, is an end result of several of other peoples tutorials and research and bits I fiddled with, can't take too much credit for it.
@Talairina Have you solved any related problems?
According to the main context, is it impossible to implement functions such as slot movement and item sorting in the inventory?