ActiveFightsUIPanel.cs 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. using UnityEngine;
  2. using UnityEngine.UIElements;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. /// <summary>
  6. /// Displays active fights in the UI with zoom buttons
  7. /// Shows runner vs monster fights, sorted by fight intensity (participants in room)
  8. /// </summary>
  9. public class ActiveFightsUIPanel : MonoBehaviour
  10. {
  11. [Header("Settings")]
  12. [SerializeField] private float updateInterval = 0.5f;
  13. private VisualElement root;
  14. private VisualElement fightsList;
  15. private Dictionary<string, VisualElement> fightEntries = new();
  16. private float lastUpdateTime = 0f;
  17. void Start()
  18. {
  19. InitializeUI();
  20. }
  21. private void InitializeUI()
  22. {
  23. // Find or create UIDocument
  24. var uiDocument = FindAnyObjectByType<UIDocument>();
  25. if (uiDocument == null)
  26. {
  27. var docGO = new GameObject("UIDocument");
  28. uiDocument = docGO.AddComponent<UIDocument>();
  29. }
  30. root = uiDocument.rootVisualElement;
  31. // Create the fights panel container
  32. var panelContainer = new VisualElement();
  33. panelContainer.name = "ActiveFightsPanel";
  34. panelContainer.style.position = Position.Absolute;
  35. panelContainer.style.left = 20; // Left side instead of right
  36. panelContainer.style.top = 20;
  37. panelContainer.style.width = 350;
  38. // Limit height so the list scrolls instead of growing off-screen
  39. panelContainer.style.maxHeight = new StyleLength(new Length(85, LengthUnit.Percent));
  40. panelContainer.style.backgroundColor = new Color(0.1f, 0.1f, 0.1f, 0.8f);
  41. panelContainer.style.borderBottomLeftRadius = 5;
  42. panelContainer.style.borderBottomRightRadius = 5;
  43. panelContainer.style.borderTopLeftRadius = 5;
  44. panelContainer.style.borderTopRightRadius = 5;
  45. panelContainer.style.paddingBottom = 10;
  46. panelContainer.style.paddingTop = 10;
  47. panelContainer.style.paddingLeft = 10;
  48. panelContainer.style.paddingRight = 10;
  49. panelContainer.style.flexDirection = FlexDirection.Column;
  50. // Title
  51. var title = new Label("Active Fights");
  52. title.style.fontSize = 16;
  53. title.style.color = Color.white;
  54. title.style.marginBottom = 10;
  55. title.style.unityFontStyleAndWeight = FontStyle.Bold;
  56. title.style.flexShrink = 0;
  57. panelContainer.Add(title);
  58. // Scrollable container so the list doesn't overflow the screen
  59. var scrollView = new ScrollView(ScrollViewMode.Vertical);
  60. scrollView.name = "FightsScrollView";
  61. scrollView.style.flexGrow = 1;
  62. scrollView.style.flexShrink = 1;
  63. scrollView.horizontalScrollerVisibility = ScrollerVisibility.Hidden;
  64. scrollView.verticalScrollerVisibility = ScrollerVisibility.Auto;
  65. // Fights list container (lives inside the ScrollView)
  66. fightsList = new VisualElement();
  67. fightsList.name = "FightsList";
  68. fightsList.style.flexDirection = FlexDirection.Column;
  69. scrollView.Add(fightsList);
  70. panelContainer.Add(scrollView);
  71. root.Add(panelContainer);
  72. }
  73. void Update()
  74. {
  75. if (FightTracker.Instance == null) return;
  76. if (fightsList == null) return;
  77. if (Time.time - lastUpdateTime < updateInterval) return;
  78. lastUpdateTime = Time.time;
  79. RefreshFightsList();
  80. }
  81. /// <summary>
  82. /// Updates the list of displayed fights
  83. /// </summary>
  84. private void RefreshFightsList()
  85. {
  86. var fights = FightTracker.Instance.GetDisplayFights();
  87. var currentFightIds = new HashSet<string>();
  88. // Update or create entries for current fights
  89. foreach (var fight in fights)
  90. {
  91. string fightId = $"{fight.runnerId}_{fight.monster.GetHashCode()}";
  92. currentFightIds.Add(fightId);
  93. if (fightEntries.ContainsKey(fightId))
  94. {
  95. // Update existing entry
  96. UpdateFightEntry(fightEntries[fightId], fight);
  97. }
  98. else
  99. {
  100. // Create new entry
  101. var entryElement = CreateFightEntry(fight, fightId);
  102. fightEntries[fightId] = entryElement;
  103. fightsList.Add(entryElement);
  104. }
  105. }
  106. // Remove entries for fights that are no longer active
  107. var entriesToRemove = fightEntries.Keys.Where(id => !currentFightIds.Contains(id)).ToList();
  108. foreach (var id in entriesToRemove)
  109. {
  110. if (fightEntries[id] != null)
  111. {
  112. fightEntries[id].RemoveFromHierarchy();
  113. }
  114. fightEntries.Remove(id);
  115. }
  116. }
  117. /// <summary>
  118. /// Creates a single fight entry UI element
  119. /// </summary>
  120. private VisualElement CreateFightEntry(FightData fight, string fightId)
  121. {
  122. var entryContainer = new VisualElement();
  123. entryContainer.name = $"FightEntry_{fightId}";
  124. entryContainer.style.flexDirection = FlexDirection.Row;
  125. entryContainer.style.backgroundColor = new Color(0.2f, 0.2f, 0.2f, 0.9f);
  126. entryContainer.style.borderBottomLeftRadius = 3;
  127. entryContainer.style.borderBottomRightRadius = 3;
  128. entryContainer.style.borderTopLeftRadius = 3;
  129. entryContainer.style.borderTopRightRadius = 3;
  130. entryContainer.style.paddingBottom = 5;
  131. entryContainer.style.paddingTop = 5;
  132. entryContainer.style.paddingLeft = 8;
  133. entryContainer.style.paddingRight = 8;
  134. entryContainer.style.marginBottom = 5;
  135. entryContainer.style.alignItems = Align.Center;
  136. // Status indicator
  137. var statusDot = new VisualElement();
  138. statusDot.style.width = 12;
  139. statusDot.style.height = 12;
  140. statusDot.style.borderBottomLeftRadius = 6;
  141. statusDot.style.borderBottomRightRadius = 6;
  142. statusDot.style.borderTopLeftRadius = 6;
  143. statusDot.style.borderTopRightRadius = 6;
  144. statusDot.style.backgroundColor = fight.isActive ? Color.red : new Color(1f, 0.5f, 0f);
  145. statusDot.style.marginRight = 8;
  146. entryContainer.Add(statusDot);
  147. // Fight text
  148. var fightText = new Label(fight.GetDisplayText());
  149. fightText.style.color = Color.white;
  150. fightText.style.fontSize = 12;
  151. fightText.style.flexGrow = 1;
  152. entryContainer.Add(fightText);
  153. // Zoom button
  154. var zoomButton = new Button(() => ZoomToFight(fight));
  155. zoomButton.text = "Zoom";
  156. zoomButton.style.width = 60;
  157. zoomButton.style.height = 25;
  158. zoomButton.style.backgroundColor = new Color(0.2f, 0.5f, 0.9f, 0.9f);
  159. zoomButton.style.color = Color.white;
  160. zoomButton.style.fontSize = 11;
  161. zoomButton.style.marginLeft = 8;
  162. entryContainer.Add(zoomButton);
  163. return entryContainer;
  164. }
  165. /// <summary>
  166. /// Updates an existing fight entry
  167. /// </summary>
  168. private void UpdateFightEntry(VisualElement entryElement, FightData fight)
  169. {
  170. if (entryElement == null) return;
  171. // Update status dot color
  172. var statusDot = entryElement.Q<VisualElement>(null, "unity-content-container")?.Children().FirstOrDefault() as VisualElement;
  173. if (statusDot != null)
  174. {
  175. statusDot.style.backgroundColor = fight.isActive ? Color.red : new Color(1f, 0.5f, 0f);
  176. }
  177. }
  178. /// <summary>
  179. /// Zooms the camera to the room where the fight is happening
  180. /// </summary>
  181. private void ZoomToFight(FightData fight)
  182. {
  183. var cameraController = FindAnyObjectByType<MazeCameraController>();
  184. if (cameraController != null)
  185. {
  186. cameraController.ZoomToRoom(fight.room, 1.3f, 0.5f);
  187. }
  188. }
  189. }