using UnityEngine; using UnityEngine.UIElements; using System.Collections.Generic; using System.Linq; /// /// Displays active fights in the UI with zoom buttons /// Shows runner vs monster fights, sorted by fight intensity (participants in room) /// public class ActiveFightsUIPanel : MonoBehaviour { [Header("Settings")] [SerializeField] private float updateInterval = 0.5f; private VisualElement root; private VisualElement fightsList; private Dictionary fightEntries = new(); private float lastUpdateTime = 0f; void Start() { InitializeUI(); } private void InitializeUI() { // Find or create UIDocument var uiDocument = FindAnyObjectByType(); if (uiDocument == null) { var docGO = new GameObject("UIDocument"); uiDocument = docGO.AddComponent(); } root = uiDocument.rootVisualElement; // Create the fights panel container var panelContainer = new VisualElement(); panelContainer.name = "ActiveFightsPanel"; panelContainer.style.position = Position.Absolute; panelContainer.style.left = 20; // Left side instead of right panelContainer.style.top = 20; panelContainer.style.width = 350; // Limit height so the list scrolls instead of growing off-screen panelContainer.style.maxHeight = new StyleLength(new Length(85, LengthUnit.Percent)); panelContainer.style.backgroundColor = new Color(0.1f, 0.1f, 0.1f, 0.8f); panelContainer.style.borderBottomLeftRadius = 5; panelContainer.style.borderBottomRightRadius = 5; panelContainer.style.borderTopLeftRadius = 5; panelContainer.style.borderTopRightRadius = 5; panelContainer.style.paddingBottom = 10; panelContainer.style.paddingTop = 10; panelContainer.style.paddingLeft = 10; panelContainer.style.paddingRight = 10; panelContainer.style.flexDirection = FlexDirection.Column; // Title var title = new Label("Active Fights"); title.style.fontSize = 16; title.style.color = Color.white; title.style.marginBottom = 10; title.style.unityFontStyleAndWeight = FontStyle.Bold; title.style.flexShrink = 0; panelContainer.Add(title); // Scrollable container so the list doesn't overflow the screen var scrollView = new ScrollView(ScrollViewMode.Vertical); scrollView.name = "FightsScrollView"; scrollView.style.flexGrow = 1; scrollView.style.flexShrink = 1; scrollView.horizontalScrollerVisibility = ScrollerVisibility.Hidden; scrollView.verticalScrollerVisibility = ScrollerVisibility.Auto; // Fights list container (lives inside the ScrollView) fightsList = new VisualElement(); fightsList.name = "FightsList"; fightsList.style.flexDirection = FlexDirection.Column; scrollView.Add(fightsList); panelContainer.Add(scrollView); root.Add(panelContainer); } void Update() { if (FightTracker.Instance == null) return; if (fightsList == null) return; if (Time.time - lastUpdateTime < updateInterval) return; lastUpdateTime = Time.time; RefreshFightsList(); } /// /// Updates the list of displayed fights /// private void RefreshFightsList() { var fights = FightTracker.Instance.GetDisplayFights(); var currentFightIds = new HashSet(); // Update or create entries for current fights foreach (var fight in fights) { string fightId = $"{fight.runnerId}_{fight.monster.GetHashCode()}"; currentFightIds.Add(fightId); if (fightEntries.ContainsKey(fightId)) { // Update existing entry UpdateFightEntry(fightEntries[fightId], fight); } else { // Create new entry var entryElement = CreateFightEntry(fight, fightId); fightEntries[fightId] = entryElement; fightsList.Add(entryElement); } } // Remove entries for fights that are no longer active var entriesToRemove = fightEntries.Keys.Where(id => !currentFightIds.Contains(id)).ToList(); foreach (var id in entriesToRemove) { if (fightEntries[id] != null) { fightEntries[id].RemoveFromHierarchy(); } fightEntries.Remove(id); } } /// /// Creates a single fight entry UI element /// private VisualElement CreateFightEntry(FightData fight, string fightId) { var entryContainer = new VisualElement(); entryContainer.name = $"FightEntry_{fightId}"; entryContainer.style.flexDirection = FlexDirection.Row; entryContainer.style.backgroundColor = new Color(0.2f, 0.2f, 0.2f, 0.9f); entryContainer.style.borderBottomLeftRadius = 3; entryContainer.style.borderBottomRightRadius = 3; entryContainer.style.borderTopLeftRadius = 3; entryContainer.style.borderTopRightRadius = 3; entryContainer.style.paddingBottom = 5; entryContainer.style.paddingTop = 5; entryContainer.style.paddingLeft = 8; entryContainer.style.paddingRight = 8; entryContainer.style.marginBottom = 5; entryContainer.style.alignItems = Align.Center; // Status indicator var statusDot = new VisualElement(); statusDot.style.width = 12; statusDot.style.height = 12; statusDot.style.borderBottomLeftRadius = 6; statusDot.style.borderBottomRightRadius = 6; statusDot.style.borderTopLeftRadius = 6; statusDot.style.borderTopRightRadius = 6; statusDot.style.backgroundColor = fight.isActive ? Color.red : new Color(1f, 0.5f, 0f); statusDot.style.marginRight = 8; entryContainer.Add(statusDot); // Fight text var fightText = new Label(fight.GetDisplayText()); fightText.style.color = Color.white; fightText.style.fontSize = 12; fightText.style.flexGrow = 1; entryContainer.Add(fightText); // Zoom button var zoomButton = new Button(() => ZoomToFight(fight)); zoomButton.text = "Zoom"; zoomButton.style.width = 60; zoomButton.style.height = 25; zoomButton.style.backgroundColor = new Color(0.2f, 0.5f, 0.9f, 0.9f); zoomButton.style.color = Color.white; zoomButton.style.fontSize = 11; zoomButton.style.marginLeft = 8; entryContainer.Add(zoomButton); return entryContainer; } /// /// Updates an existing fight entry /// private void UpdateFightEntry(VisualElement entryElement, FightData fight) { if (entryElement == null) return; // Update status dot color var statusDot = entryElement.Q(null, "unity-content-container")?.Children().FirstOrDefault() as VisualElement; if (statusDot != null) { statusDot.style.backgroundColor = fight.isActive ? Color.red : new Color(1f, 0.5f, 0f); } } /// /// Zooms the camera to the room where the fight is happening /// private void ZoomToFight(FightData fight) { var cameraController = FindAnyObjectByType(); if (cameraController != null) { cameraController.ZoomToRoom(fight.room, 1.3f, 0.5f); } } }