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#
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);
|
|
}
|
|
}
|
|
}
|