using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; namespace BrewMonster.Scripts.Task.UI { public class TaskTreeView : MonoBehaviour, IRefreshLayout { [SerializeField] private TaskTreeViewItem m_pTreeItemPrefab_Deep1; [SerializeField] private TaskTreeViewItem m_pTreeItemPrefab_Deep2; [SerializeField] private TaskTreeViewItem m_pTreeItemPrefab_Deep3; [Header("DEBUG")] [SerializeField] private TaskTreeViewItem _currentSelectedItem = null; [SerializeField] private TaskTreeViewItem[] m_aTreeViewItems; private void Start() { EventBus.Subscribe(evt => { SetSelectedItem(evt.Data); }); } public void SetItemData(TaskTreeViewItem item, uint taskType) { item.SetItemData(taskType); } public uint GetItemData(TaskTreeViewItem item) { if (item == null) return 0; return item.GetItemData(); } public TaskTreeViewItem GetNextSiblingItem(TaskTreeViewItem item) { if (m_aTreeViewItems == null) { m_aTreeViewItems = GetComponentsInChildren(true); } for (int i = 0; i < m_aTreeViewItems.Length - 1; i++) { if (m_aTreeViewItems[i] == item) { return m_aTreeViewItems[i + 1]; } } return null; } public TaskTreeViewItem InsertItem(string text, TaskTreeViewItem pParent, TaskTreeViewItem pAfter) { //caculate treelevel first int treeLevel = pParent != null ? pParent.GetTreeLevel() + 1 : 0; // Create a new item GameObject and component TaskTreeViewItem pItem = null; switch (treeLevel) { case 0: pItem = Instantiate(m_pTreeItemPrefab_Deep1); break; case 1: pItem = Instantiate(m_pTreeItemPrefab_Deep2); break; default: pItem = Instantiate(m_pTreeItemPrefab_Deep3); break; } if(pParent != null) { pParent.SetLastItem(false); } pItem.SetLastItem(true); GameObject go = pItem.gameObject; // go.name = $"Task_{}"; if (pItem == null) return null; // Parent: root (this) if null; otherwise under given parent item var parentTransform = (pParent != null ? pParent.transform : this.transform); go.transform.SetParent(parentTransform, false); // Set sibling position: after specific item if provided; otherwise append to end if (pAfter != null && pAfter.transform.parent == parentTransform) { int afterIndex = pAfter.transform.GetSiblingIndex(); go.transform.SetSiblingIndex(afterIndex + 1); } else { go.transform.SetAsLastSibling(); } // Optionally set label text if a TMP_Text is attached under the item (not required here) // var label = go.GetComponentInChildren(true); // if (label != null) label.text = text ?? string.Empty; pItem.SetItemText(text); pItem.SetTreeLevel(treeLevel); // Refresh local cache of items m_aTreeViewItems = GetComponentsInChildren(true); // pParent.RefreshLayout(); if(pParent) pParent.SetExpand(false); // Collapse parent to show new item only when expanded return pItem; } public void DeleteAllItems() { List childrenCopy = new(); foreach (Transform child in transform) { // Destroy(child.GetComponent()); childrenCopy.Add(child); } foreach (var child in childrenCopy) { child.SetParent(null); Destroy(child.gameObject); } m_aTreeViewItems = null; // m_aTreeViewItems = GetComponentsInChildren(true); _currentSelectedItem = null; } public TaskTreeViewItem GetItemByData(uint taskType) { if (m_aTreeViewItems == null) { m_aTreeViewItems = new TaskTreeViewItem[this.transform.childCount]; m_aTreeViewItems = GetComponentsInChildren(true); } foreach (var item in m_aTreeViewItems) { if (item.GetItemData() == taskType) { return item; } } return null; } public TaskTreeViewItem GetFirstChild() { return transform.childCount == 0 ? null : transform.GetChild(0).GetComponent(); } public TaskTreeViewItem GetSelectedItem() { return _currentSelectedItem; } void SetSelectedItem(uint idItem) { _currentSelectedItem = GetItemByData(idItem); Debug.Log($"[TaskTreeView] SetSelectedItem: {idItem}"); } public void RefreshLayout() { var parent = GetComponent(); // Force Unity to rebuild layout immediately parent.ForceUpdateRectTransforms(); LayoutRebuilder.ForceRebuildLayoutImmediate(parent); } } }