2025-09-24 11:24:38 +05:00

203 lines
3.8 KiB
C#

using System.Collections.Generic;
using UnityEngine;
using DG.Tweening;
using System.Collections;
namespace TPSBR.UI
{
public interface IFeedData
{
}
public struct KillFeedData : IFeedData
{
public string Killer;
public string Victim;
public bool IsHeadshot;
public EHitType DamageType;
public bool KillerIsLocal;
public bool VictimIsLocal;
}
public struct JoinedLeftFeedData : IFeedData
{
public string Nickname;
public bool Joined;
}
public struct EliminationFeedData : IFeedData
{
public string Nickname;
public bool IsLocal;
}
public struct AnnouncementFeedData : IFeedData
{
public string Announcement;
public Color Color;
}
public class UIKillFeed : UIWidget
{
// PRIVATE MEMBERS
[SerializeField]
private float _minVisibilityTime;
[SerializeField]
private float _maxVisibilityTime;
[SerializeField]
private float _moveTime = 0.3f;
private UIKillFeedItem[] _items;
private Vector3[] _originalPositions;
private int _maxFeeds;
private Coroutine _moveRoutine;
private List<UIKillFeedItem> _itemsPool = new List<UIKillFeedItem>(16);
private List<UIKillFeedItem> _visibleFeeds = new List<UIKillFeedItem>(16);
private List<IFeedData> _pendingFeeds = new List<IFeedData>(16);
// PUBLIC METHODS
public void ShowFeed(IFeedData data)
{
_pendingFeeds.Add(data);
}
public void HideAll()
{
for (int i = 0; i < _maxFeeds; i++)
{
_items[i].SetActive(false);
}
_visibleFeeds.Clear();
_pendingFeeds.Clear();
_itemsPool.AddRange(_items);
_moveRoutine = null;
}
// UIWidget
protected override void OnInitialize()
{
base.OnInitialize();
_items = GetComponentsInChildren<UIKillFeedItem>();
_maxFeeds = _items.Length;
_itemsPool = new List<UIKillFeedItem>(_items);
_originalPositions = new Vector3[_maxFeeds];
for (int i = 0; i < _maxFeeds; i++)
{
var position = _items[i].transform.position;
position.x /= Screen.width;
position.y /= Screen.height;
_originalPositions[i] = position;
}
}
protected override void OnVisible()
{
base.OnVisible();
HideAll();
}
protected override void OnTick()
{
base.OnTick();
if (_moveRoutine != null)
return; // Do not add or remove feeds when moving
int visibleFeeds = _visibleFeeds.Count;
if (_pendingFeeds.Count > 0)
{
if (visibleFeeds == _maxFeeds)
{
if (_visibleFeeds[0].VisibilityTime < _minVisibilityTime)
return;
HideFeedItem(0);
return;
}
ShowFeedItem(_pendingFeeds[0]);
_pendingFeeds.RemoveAt(0);
return;
}
if (visibleFeeds > 0)
{
if (_visibleFeeds[0].VisibilityTime >= _maxVisibilityTime)
{
HideFeedItem(0);
}
}
}
// PRIVATE METHODS
private void ShowFeedItem(IFeedData data)
{
int poolIndex = _itemsPool.Count - 1;
var item = _itemsPool[poolIndex];
_itemsPool.RemoveAt(poolIndex);
_visibleFeeds.Add(item);
item.SetData(data);
item.RectTransform.position = GetPosition(_visibleFeeds.Count - 1);
item.SetActive(true);
}
private void HideFeedItem(int index)
{
var feedItem = _visibleFeeds[index];
feedItem.SetActive(false);
_visibleFeeds.RemoveAt(index);
_itemsPool.Add(feedItem);
if (_visibleFeeds.Count > 0)
{
_moveRoutine = StartCoroutine(MoveFeeds_Coroutine());
}
}
private IEnumerator MoveFeeds_Coroutine()
{
for (int i = 0; i < _visibleFeeds.Count; i++)
{
var feedItem = _visibleFeeds[i];
DOTween.Kill(feedItem);
_visibleFeeds[i].RectTransform.DOMove(GetPosition(i), _moveTime);
}
yield return new WaitForSeconds(_moveTime);
_moveRoutine = null;
}
private Vector3 GetPosition(int index)
{
var position = _originalPositions[index];
position.x *= Screen.width;
position.y *= Screen.height;
return position;
}
}
}