You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

172 lines
3.1 KiB
C#

using UnityEngine;
using System;
using System.Collections.Generic;
namespace Projectiles.UI
{
public class UIList : UIListBase<UIListItem, MonoBehaviour>
{
}
public abstract class UIListBase<TListItem, RContent> : UIBehaviour
where TListItem: UIListItemBase<RContent>
where RContent: MonoBehaviour
{
// PUBLIC MEMBERS
public event Action<int, RContent> UpdateContent;
public event Action<int> SelectionChanged;
public int Selection { get { return _selection; } set { SetSelection(value, false); } }
public int Count => _dataCount;
// PRIVATE MEMBERS
[SerializeField]
private bool _allowSelection = true;
[SerializeField]
private bool _allowDeselection = true;
[SerializeField]
private TListItem _itemInstance;
private List<TListItem> _items = new List<TListItem>(32);
private int _dataCount;
private int _selection = -1;
// PUBLIC METHODS
public void Refresh(int dataCount, bool notifySelection = true)
{
_dataCount = dataCount;
UpdateItems();
if (_selection >= _dataCount)
{
SetSelection(_allowDeselection == false && _dataCount > 0 ? 0 : -1, notifySelection, true);
}
else if(_selection < 0 && _allowDeselection == false && _dataCount > 0)
{
SetSelection(0, notifySelection, true);
}
else
{
SetSelection(_selection, false, true);
}
}
public void Clear(bool destroyItems = true)
{
_dataCount = 0;
if (destroyItems == true)
{
_itemInstance.SetActive(false);
for (int i = 1; i < _items.Count; i++)
{
Destroy(_items[i].gameObject);
}
_items.Clear();
}
else
{
UpdateItems();
}
if (_selection >= 0)
{
SetSelection(-1, true);
}
}
// MONOBEHAVIOR
protected void Awake()
{
if (_dataCount == 0)
{
_itemInstance.SetActive(false);
}
}
// PRIVATE METHODS
private void SetSelection(int selection, bool notify, bool force = false)
{
if (_allowSelection == false)
return;
if (selection >= _dataCount)
return;
if (selection == _selection && force == false)
return;
if (selection < 0)
{
selection = -1;
}
_selection = selection;
for (int i = 0; i < _dataCount; i++)
{
var item = _items[i];
item.IsSelected = item.Id == _selection;
}
if (notify == true)
{
SelectionChanged?.Invoke(_selection);
}
}
private void UpdateItems()
{
bool selectable = _itemInstance.IsSelectable;
var parent = _itemInstance.transform.parent;
for (int i = _items.Count; i < _dataCount; i++)
{
var newItem = i == 0 ? _itemInstance : Instantiate(_itemInstance, parent);
newItem.Id = i;
if (selectable == true)
{
newItem.Clicked -= OnItemClicked;
newItem.Clicked += OnItemClicked;
}
_items.Add(newItem);
}
for (int i = 0; i < _items.Count; i++)
{
var item = _items[i];
if (i < _dataCount)
{
UpdateContent?.Invoke(i, item.Content);
item.SetActive(true);
}
else
{
item.SetActive(false);
}
}
}
private void OnItemClicked(int id)
{
if (id == _selection && _allowDeselection == false)
return;
SetSelection(id == _selection ? -1 : id, true);
}
}
}