Files
DepthsOfGreed/Assets/Scripts/HandbookUI/HandbookIndexController.cs
T
2026-10-14 01:45:35 +02:00

151 lines
6.7 KiB
C#

using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
namespace DepthsOfGreed.HandbookUI
{
public sealed class HandbookIndexController : MonoBehaviour
{
public HandbookTowerEntry SelectedEntry { get; private set; }
public int VisibleEntryCount => currentFilter == 2 ? 0 : entries.Count;
public ScrollRect ListScroll => scroll;
private ScrollRect scroll;
private Button[] filters;
private readonly List<HandbookTowerEntry> entries = new List<HandbookTowerEntry>();
private readonly List<Button> rows = new List<Button>();
private TMP_Text detailName, description, emptyMessage;
private Image detailIcon;
private Sprite placeholder;
private Color placeholderColor;
private int currentFilter;
public void Initialize(HandbookTowerCatalog catalog)
{
scroll = transform.Find("IndexLeft/EntryScrollView").GetComponent<ScrollRect>();
filters = new[] {
transform.Find("IndexLeft/FilterBar/Filter_All").GetComponent<Button>(),
transform.Find("IndexLeft/FilterBar/Filter_Towers").GetComponent<Button>(),
transform.Find("IndexLeft/FilterBar/Filter_Enemies").GetComponent<Button>()
};
detailName = transform.Find("IndexRight/DetailNameText").GetComponent<TMP_Text>();
description = transform.Find("IndexRight/DetailDescriptionText").GetComponent<TMP_Text>();
detailIcon = transform.Find("IndexRight/DetailIcon").GetComponent<Image>();
placeholder = detailIcon.sprite;
placeholderColor = detailIcon.color;
var template = scroll.content.GetChild(0).GetComponent<Button>();
if (catalog && catalog.towers != null)
foreach (var entry in catalog.towers)
{
if (!entry) continue;
int index = entries.Count;
entries.Add(entry);
var row = Instantiate(template, scroll.content);
row.name = "IndexEntry_" + entry.id;
row.gameObject.SetActive(true);
row.image.color = Color.white;
var label = row.transform.Find("NameText").GetComponent<TMP_Text>();
label.text = entry.displayName;
label.color = Color.black;
label.raycastTarget = false;
label.enableAutoSizing = true;
label.fontSizeMin = 16;
label.fontSizeMax = 24;
var icon = row.transform.Find("Icon").GetComponent<Image>();
if (entry.icon) { icon.sprite = entry.icon; icon.color = Color.white; }
icon.preserveAspect = true;
icon.raycastTarget = false;
row.onClick.RemoveAllListeners();
row.onClick.AddListener(() => SelectEntry(index));
rows.Add(row);
}
template.gameObject.SetActive(false);
var empty = new GameObject("EmptyListMessage", typeof(RectTransform), typeof(TextMeshProUGUI), typeof(LayoutElement));
empty.transform.SetParent(scroll.content, false);
emptyMessage = empty.GetComponent<TMP_Text>();
emptyMessage.font = description.font;
emptyMessage.fontSize = 22;
emptyMessage.color = new Color(0.3f, 0.3f, 0.3f);
emptyMessage.alignment = TextAlignmentOptions.MidlineLeft;
emptyMessage.raycastTarget = false;
empty.GetComponent<LayoutElement>().preferredHeight = 70;
for (int i = 0; i < filters.Length; i++)
{
int index = i;
filters[i].onClick.AddListener(() => SelectFilter(index));
}
ResetForEntry();
}
public void ResetForEntry()
{
SelectFilter(0, true);
}
public void SelectFilter(int index, bool force = false)
{
if (index < 0 || index > 2 || (!force && currentFilter == index)) return;
currentFilter = index;
foreach (var row in rows) row.gameObject.SetActive(index != 2);
bool empty = index == 2 || rows.Count == 0;
emptyMessage.gameObject.SetActive(empty);
emptyMessage.text = index == 2 ? "Noch keine Gegner-Einträge" : "Noch keine Einträge";
for (int i = 0; i < filters.Length; i++)
{
filters[i].image.color = Color.white;
var colors = filters[i].colors;
colors.normalColor = i == index ? new Color(1, 0.72f, 0.2f) : new Color(0.82f, 0.82f, 0.82f);
colors.highlightedColor = i == index ? new Color(1, 0.82f, 0.4f) : Color.white;
colors.selectedColor = colors.normalColor;
filters[i].colors = colors;
}
ClearSelection();
ResetScroll();
}
public void SelectEntry(int index)
{
if (currentFilter == 2 || index < 0 || index >= entries.Count) return;
SelectedEntry = entries[index];
detailName.text = SelectedEntry.displayName;
description.text = SelectedEntry.description;
detailIcon.gameObject.SetActive(true);
detailIcon.sprite = SelectedEntry.icon ? SelectedEntry.icon : placeholder;
detailIcon.color = SelectedEntry.icon ? Color.white : placeholderColor;
detailIcon.preserveAspect = true;
RefreshSelectionColors();
}
public void ClearSelection()
{
SelectedEntry = null;
detailIcon.gameObject.SetActive(false);
detailName.text = "";
description.text = "Wähle links einen Eintrag aus.";
RefreshSelectionColors();
}
private void RefreshSelectionColors()
{
for (int i = 0; i < rows.Count; i++)
{
bool selected = entries[i] == SelectedEntry;
var colors = rows[i].colors;
colors.normalColor = selected ? new Color(0.58f, 0.58f, 0.58f) : new Color(0.86f, 0.86f, 0.86f);
colors.highlightedColor = selected ? new Color(0.64f, 0.64f, 0.64f) : new Color(0.94f, 0.94f, 0.94f);
colors.selectedColor = colors.normalColor;
rows[i].colors = colors;
}
}
public void ResetScroll()
{
scroll.StopMovement();
Canvas.ForceUpdateCanvases();
LayoutRebuilder.ForceRebuildLayoutImmediate(scroll.content);
scroll.verticalNormalizedPosition = 1f;
}
}
}