GuildTycoon/Assets/_/Features/UI/Runtime/Adventurers/AdventurersPanel.cs

153 lines
5.2 KiB
C#

using System.Collections.Generic;
using EventSystem.Runtime;
using Adventurer.Runtime;
using Core.Runtime;
using Quests.Runtime;
using TMPro;
using UnityEngine;
namespace GameUI.Runtime
{
public class AdventurersPanel : BasePanel
{
#region Unity API
void OnEnable()
{
AdventurerSignals.OnPortraitCaptured += OnPortraitCapturedHandler;
AdventurerSignals.OnRefresh += DisplayAdventurers;
}
private void Start()
{
foreach (var txt in GetComponentsInChildren<TMP_Text>())
{
txt.text = LocalizationSystem.Instance.GetLocalizedText(txt.text);
}
DisplayAdventurers();
}
private void OnDisable()
{
AdventurerSignals.OnPortraitCaptured -= OnPortraitCapturedHandler;
AdventurerSignals.OnRefresh -= DisplayAdventurers;
}
#endregion
#region Utils
void OnPortraitCapturedHandler(AdventurerClass adventurer, Sprite portrait)
{
foreach (Transform child in _heroesPanel.transform)
{
AdventurerCardUI card = child.GetComponent<AdventurerCardUI>();
if (card != null && card.Adventurer == adventurer)
{
card.SetPortrait(portrait);
break;
}
}
}
void DisplayAdventurers()
{
// Build a lookup of existing cards by their Adventurer instance
Dictionary<AdventurerClass, AdventurerCardUI> existing = new Dictionary<AdventurerClass, AdventurerCardUI>();
List<AdventurerCardUI> orphaned = new List<AdventurerCardUI>();
foreach (Transform child in _heroesPanel.transform)
{
AdventurerCardUI card = child.GetComponent<AdventurerCardUI>();
if (card != null && card.Adventurer != null)
{
if (!existing.ContainsKey(card.Adventurer))
existing.Add(card.Adventurer, card);
else
orphaned.Add(card); // duplicate safety
}
else if (card != null)
{
orphaned.Add(card);
}
}
List<AdventurerClass> filtered = FilterAdventurers(_sort);
// Reuse or create cards to match the filtered list and order
HashSet<AdventurerCardUI> used = new HashSet<AdventurerCardUI>();
for (int i = 0; i < filtered.Count; i++)
{
AdventurerClass adv = filtered[i];
AdventurerCardUI card;
if (existing.TryGetValue(adv, out card))
{
// Refresh textual data and availability indicators without touching portrait
card.setup(adv);
card.transform.SetSiblingIndex(i);
}
else
{
GameObject cardAdventurerGO = Instantiate(_adventurerPrefab, _heroesPanel.transform);
cardAdventurerGO.transform.SetSiblingIndex(i);
card = cardAdventurerGO.GetComponent<AdventurerCardUI>();
if (card != null)
{
card.setup(adv);
}
}
if (card != null)
used.Add(card);
}
// Remove cards that are no longer needed (not part of filtered) or orphaned
foreach (Transform child in _heroesPanel.transform)
{
AdventurerCardUI card = child.GetComponent<AdventurerCardUI>();
if (card != null && !used.Contains(card))
{
Destroy(child.gameObject);
}
}
// Cleanup any explicit orphaned duplicates detected earlier
foreach (var card in orphaned)
{
if (card != null && !used.Contains(card))
{
Destroy(card.gameObject);
}
}
}
List<AdventurerClass> FilterAdventurers(AdventurerSortEnum sortType)
{
List<AdventurerClass> allAdventurers = GetFact<List<AdventurerClass>>("my_adventurers");
switch (sortType)
{
case AdventurerSortEnum.Available:
return allAdventurers.FindAll(a => a.IsAvailable);
case AdventurerSortEnum.NotAvailable:
return allAdventurers.FindAll(a => !a.IsAvailable);
case AdventurerSortEnum.AssignedToQuest:
return QuestClass.GetAdventurersFromId(QuestManager.Instance.AssignedAdventurers);
case AdventurerSortEnum.None:
return allAdventurers;
default:
return allAdventurers;
}
}
#endregion
#region Privates and Protected
[SerializeField] GameObject _adventurerPrefab;
[SerializeField] GameObject _heroesPanel;
[SerializeField] AdventurerSortEnum _sort;
#endregion
}
}