using System; using System.Collections.Generic; using System.Linq; using Jovian.EncounterSystem; using UnityEditor; using UnityEditor.UIElements; using UnityEngine; using UnityEngine.UIElements; namespace Jovian.EncounterSystem.Editor { /// Browser for every encounter across all tables. Search + kind filter + detail pane. Quest chains render as a tree rooted at the first step. public class EncounterBrowserWindow : EditorWindow { private const string AllKinds = "All"; private class Record { public EncounterTable table; public int index; public IEncounter encounter; public int depth; public bool IsTableHeader => encounter == null; } private static readonly Color[] DepthColors = { new(0.35f, 0.55f, 0.85f), // depth 0 — table headers (blue) new(0.90f, 0.90f, 0.90f), // depth 1 — encounters under table (neutral) new(0.70f, 0.90f, 0.55f), // depth 2 — chain step 1 (green) new(0.95f, 0.80f, 0.45f), // depth 3 — chain step 2 (amber) new(0.85f, 0.65f, 0.90f) // depth 4+ — deeper chain (violet) }; private readonly List allRecords = new(); private string searchText = string.Empty; private string kindFilter = AllKinds; private readonly Dictionary> issuesByEncounter = new(); private TreeView treeView; private VisualElement detailPane; private ToolbarMenu kindDropdown; private VisualElement statusBanner; [MenuItem("Jovian/Encounters/Encounter Browser")] public static void Open() { var window = GetWindow("Encounters"); window.minSize = new Vector2(640, 360); } private void CreateGUI() { BuildToolbar(); BuildSplit(); Refresh(); } private void BuildToolbar() { var toolbar = new Toolbar(); var search = new ToolbarSearchField(); search.style.flexGrow = 1f; search.RegisterValueChangedCallback(evt => { searchText = evt.newValue ?? string.Empty; ApplyFilter(); }); toolbar.Add(search); kindDropdown = new ToolbarMenu { text = $"Kind: {AllKinds}" }; foreach(var choice in GetKindChoices()) { var captured = choice; kindDropdown.menu.AppendAction(captured, _ => { kindFilter = captured; kindDropdown.text = $"Kind: {captured}"; ApplyFilter(); }); } toolbar.Add(kindDropdown); var refreshButton = new ToolbarButton(Refresh) { text = "Refresh" }; toolbar.Add(refreshButton); rootVisualElement.Add(toolbar); } private void BuildSplit() { statusBanner = new VisualElement { style = { paddingLeft = 10, paddingRight = 10, paddingTop = 8, paddingBottom = 8, marginBottom = 2, flexDirection = FlexDirection.Column, backgroundColor = new StyleColor(new Color(0.85f, 0.4f, 0.15f, 0.35f)), display = DisplayStyle.None } }; rootVisualElement.Add(statusBanner); var split = new VisualElement { style = { flexDirection = FlexDirection.Row, flexGrow = 1f } }; rootVisualElement.Add(split); treeView = new TreeView { makeItem = MakeRow, bindItem = BindRow, fixedItemHeight = 22, selectionType = SelectionType.Single }; treeView.selectionChanged += OnSelectionChanged; treeView.style.width = 280; treeView.style.flexShrink = 0f; treeView.style.borderRightWidth = 1; treeView.style.borderRightColor = new StyleColor(new Color(0f, 0f, 0f, 0.4f)); split.Add(treeView); detailPane = new ScrollView(ScrollViewMode.Vertical) { style = { paddingLeft = 8, paddingTop = 8, paddingRight = 8, flexGrow = 1f } }; ShowEmptyDetail(); split.Add(detailPane); } private static VisualElement MakeRow() { var row = new VisualElement { style = { flexDirection = FlexDirection.Row, alignItems = Align.Center, paddingLeft = 6, paddingRight = 6, height = 22, flexGrow = 1f, flexShrink = 0f } }; var badge = new VisualElement { name = "issue-badge", style = { width = 8, height = 8, marginRight = 6, borderTopLeftRadius = 4, borderTopRightRadius = 4, borderBottomLeftRadius = 4, borderBottomRightRadius = 4, visibility = Visibility.Hidden } }; row.Add(badge); var label = new Label { name = "row-label", style = { flexGrow = 1f, unityTextAlign = TextAnchor.MiddleLeft } }; row.Add(label); var selectButton = new Button { name = "select-button", text = "Select", style = { marginLeft = 4, marginRight = 0, paddingLeft = 6, paddingRight = 6, display = DisplayStyle.None } }; row.Add(selectButton); return row; } private void BindRow(VisualElement element, int index) { var record = treeView.GetItemDataForIndex(index); var label = element.Q