TeamOverviewSetup.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  1. using UnityEngine;
  2. using UnityEngine.UIElements;
  3. /// <summary>
  4. /// Setup script to create and configure the TeamOverview UI system.
  5. /// This creates a separate UI GameObject specifically for the team overview panel.
  6. /// </summary>
  7. public class TeamOverviewSetup : MonoBehaviour
  8. {
  9. [Header("Setup Options")]
  10. public bool autoSetupOnStart = true;
  11. public bool showDebugLogs = true;
  12. [Header("UI Assets")]
  13. [SerializeField] private VisualTreeAsset teamOverviewUXML;
  14. [SerializeField] private StyleSheet teamOverviewStyleSheet;
  15. void Start()
  16. {
  17. if (autoSetupOnStart)
  18. {
  19. SetupTeamOverview();
  20. }
  21. }
  22. [ContextMenu("Setup Team Overview UI")]
  23. public void SetupTeamOverview()
  24. {
  25. if (!Application.isPlaying)
  26. {
  27. Debug.LogWarning("⚠️ TeamOverviewSetup: Please run this setup during Play Mode!");
  28. return;
  29. }
  30. // Check if TeamOverview already exists
  31. var existingOverview = FindFirstObjectByType<TeamOverviewController>();
  32. if (existingOverview != null)
  33. {
  34. if (showDebugLogs)
  35. {
  36. Debug.Log("📋 TeamOverview already exists, skipping setup");
  37. }
  38. return;
  39. }
  40. // Try to load UXML asset if not assigned
  41. if (teamOverviewUXML == null)
  42. {
  43. teamOverviewUXML = Resources.Load<VisualTreeAsset>("UI/MapScene/TeamOverview");
  44. if (teamOverviewUXML == null)
  45. {
  46. #if UNITY_EDITOR
  47. // Try alternative paths (Editor only)
  48. teamOverviewUXML = UnityEditor.AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/UI/MapScene/TeamOverview.uxml");
  49. #endif
  50. }
  51. }
  52. if (teamOverviewUXML == null)
  53. {
  54. Debug.LogError("❌ TeamOverview.uxml not found! Please assign it in the inspector.");
  55. return;
  56. }
  57. // Create TeamOverview GameObject
  58. GameObject teamOverviewObject = new GameObject("TeamOverviewUI");
  59. teamOverviewObject.transform.SetParent(transform);
  60. // Add UIDocument component
  61. UIDocument uiDocument = teamOverviewObject.AddComponent<UIDocument>();
  62. uiDocument.visualTreeAsset = teamOverviewUXML;
  63. // Find and assign Panel Settings from existing UI
  64. var existingUI = GameObject.Find("TravelUI")?.GetComponent<UIDocument>();
  65. if (existingUI?.panelSettings != null)
  66. {
  67. uiDocument.panelSettings = existingUI.panelSettings;
  68. if (showDebugLogs)
  69. {
  70. Debug.Log("✅ Panel Settings assigned from TravelUI");
  71. }
  72. }
  73. else
  74. {
  75. // Try to find any PanelSettings asset
  76. #if UNITY_EDITOR
  77. var panelSettings = UnityEditor.AssetDatabase.FindAssets("t:PanelSettings");
  78. if (panelSettings.Length > 0)
  79. {
  80. var path = UnityEditor.AssetDatabase.GUIDToAssetPath(panelSettings[0]);
  81. var settings = UnityEditor.AssetDatabase.LoadAssetAtPath<UnityEngine.UIElements.PanelSettings>(path);
  82. uiDocument.panelSettings = settings;
  83. if (showDebugLogs)
  84. {
  85. Debug.Log($"✅ Panel Settings auto-assigned: {settings.name}");
  86. }
  87. }
  88. #endif
  89. }
  90. // Add style sheet if available (the UXML file should reference it automatically)
  91. if (teamOverviewStyleSheet != null && showDebugLogs)
  92. {
  93. Debug.Log("ℹ️ Style sheet will be loaded automatically from UXML reference");
  94. }
  95. // Set up the UI to appear on the right side with appropriate priority
  96. uiDocument.sortingOrder = 5; // Lower than combat popups but higher than map UI
  97. // Add TeamOverviewController
  98. TeamOverviewController controller = teamOverviewObject.AddComponent<TeamOverviewController>();
  99. controller.showDebugLogs = showDebugLogs;
  100. // Ensure the UI root doesn't block other UI elements
  101. StartCoroutine(ConfigureUIEventHandling(uiDocument));
  102. // Position the UI panel on the right side
  103. StartCoroutine(PositionTeamOverview(uiDocument));
  104. // Ensure TravelEventUI exists for travel events
  105. EnsureTravelEventUI();
  106. // Ensure player object exists for MapMaker2
  107. EnsurePlayerObject();
  108. // Ensure combat popups have highest priority
  109. EnsureCombatPopupPriority();
  110. if (showDebugLogs)
  111. {
  112. Debug.Log("✅ TeamOverview UI created and configured!");
  113. }
  114. }
  115. private System.Collections.IEnumerator PositionTeamOverview(UIDocument uiDocument)
  116. {
  117. // Wait a frame for the UI to initialize
  118. yield return null;
  119. var root = uiDocument.rootVisualElement;
  120. var teamPanel = root.Q("TeamOverviewPanel");
  121. if (teamPanel != null)
  122. {
  123. // Position the panel on the right side of the screen
  124. teamPanel.style.position = Position.Absolute;
  125. teamPanel.style.right = 10;
  126. teamPanel.style.top = 10;
  127. teamPanel.style.width = 300;
  128. teamPanel.style.height = Length.Percent(80);
  129. // Make sure it's visible
  130. teamPanel.style.display = DisplayStyle.Flex;
  131. // Add TravelUI-style click blocking overlay
  132. AddClickBlockingOverlay(root);
  133. if (showDebugLogs)
  134. {
  135. Debug.Log("📍 TeamOverview positioned on right side with click blocking overlay");
  136. }
  137. }
  138. }
  139. private void AddClickBlockingOverlay(VisualElement root)
  140. {
  141. // Create a click blocker similar to TravelUI
  142. var clickBlocker = new VisualElement();
  143. clickBlocker.name = "ClickBlocker";
  144. clickBlocker.AddToClassList("click-blocker");
  145. // Position as first child (behind everything else)
  146. root.Insert(0, clickBlocker);
  147. // Block all mouse events
  148. clickBlocker.RegisterCallback<ClickEvent>(evt =>
  149. {
  150. evt.StopPropagation();
  151. });
  152. clickBlocker.RegisterCallback<MouseDownEvent>(evt =>
  153. {
  154. evt.StopPropagation();
  155. });
  156. clickBlocker.RegisterCallback<MouseUpEvent>(evt =>
  157. {
  158. evt.StopPropagation();
  159. });
  160. }
  161. private System.Collections.IEnumerator ConfigureUIEventHandling(UIDocument uiDocument)
  162. {
  163. // Wait a frame for the UI to initialize
  164. yield return null;
  165. var root = uiDocument.rootVisualElement;
  166. if (root != null)
  167. {
  168. // Ensure root doesn't block other UI - set to ignore picking
  169. root.pickingMode = PickingMode.Ignore;
  170. if (showDebugLogs)
  171. {
  172. Debug.Log("✅ TeamOverview root configured to not interfere with other UI");
  173. }
  174. }
  175. }
  176. /// <summary>
  177. /// Ensures TravelEventUI exists in the scene to prevent warnings
  178. /// </summary>
  179. private void EnsureTravelEventUI()
  180. {
  181. var existingEventUI = FindFirstObjectByType<TravelEventUI>();
  182. if (existingEventUI == null)
  183. {
  184. // Create a simple TravelEventUI GameObject
  185. GameObject eventUIObject = new GameObject("TravelEventUI");
  186. eventUIObject.transform.SetParent(transform);
  187. var travelEventUI = eventUIObject.AddComponent<TravelEventUI>();
  188. if (showDebugLogs)
  189. {
  190. Debug.Log("✅ TravelEventUI created to handle travel event messages");
  191. }
  192. }
  193. else if (showDebugLogs)
  194. {
  195. Debug.Log("ℹ️ TravelEventUI already exists");
  196. }
  197. }
  198. /// <summary>
  199. /// Ensures a basic player object exists for MapMaker2
  200. /// </summary>
  201. private void EnsurePlayerObject()
  202. {
  203. // Check if a player object exists
  204. var player = GameObject.FindWithTag("Player");
  205. if (player == null)
  206. {
  207. // Try to find any object that might be the player/team
  208. var teamPlacement = FindFirstObjectByType<SimpleTeamPlacement>();
  209. if (teamPlacement != null)
  210. {
  211. // Tag the team placement as Player if it exists
  212. teamPlacement.gameObject.tag = "Player";
  213. if (showDebugLogs)
  214. {
  215. Debug.Log("✅ Tagged SimpleTeamPlacement as Player for MapMaker2");
  216. }
  217. }
  218. else
  219. {
  220. // Create a simple player marker
  221. GameObject playerMarker = new GameObject("PlayerMarker");
  222. playerMarker.tag = "Player";
  223. if (showDebugLogs)
  224. {
  225. Debug.Log("✅ Created basic Player object for MapMaker2");
  226. }
  227. }
  228. }
  229. else if (showDebugLogs)
  230. {
  231. Debug.Log("ℹ️ Player object already exists");
  232. }
  233. }
  234. /// <summary>
  235. /// Ensures combat popups have the highest UI priority to prevent black squares
  236. /// </summary>
  237. private void EnsureCombatPopupPriority()
  238. {
  239. // Find combat popup UI documents and ensure they have highest sorting order
  240. var combatPopup = FindFirstObjectByType<CombatEventPopup>();
  241. if (combatPopup != null)
  242. {
  243. var popupUIDocument = combatPopup.GetComponent<UIDocument>();
  244. if (popupUIDocument != null)
  245. {
  246. popupUIDocument.sortingOrder = 100; // Highest priority
  247. if (showDebugLogs)
  248. {
  249. Debug.Log("✅ CombatEventPopup sortingOrder set to 100 (highest priority)");
  250. }
  251. }
  252. }
  253. var combatPopupUXML = FindFirstObjectByType<CombatEventPopupUXML>();
  254. if (combatPopupUXML != null)
  255. {
  256. var popupUIDocument = combatPopupUXML.GetComponent<UIDocument>();
  257. if (popupUIDocument != null)
  258. {
  259. popupUIDocument.sortingOrder = 100; // Highest priority
  260. if (showDebugLogs)
  261. {
  262. Debug.Log("✅ CombatEventPopupUXML sortingOrder set to 100 (highest priority)");
  263. }
  264. }
  265. }
  266. if (showDebugLogs && combatPopup == null && combatPopupUXML == null)
  267. {
  268. Debug.Log("ℹ️ No combat popup components found - will be configured when created");
  269. }
  270. }
  271. [ContextMenu("Remove Team Overview")]
  272. public void RemoveTeamOverview()
  273. {
  274. var existingOverview = FindFirstObjectByType<TeamOverviewController>();
  275. if (existingOverview != null)
  276. {
  277. DestroyImmediate(existingOverview.gameObject);
  278. Debug.Log("🗑️ TeamOverview removed");
  279. }
  280. else
  281. {
  282. Debug.Log("ℹ️ No TeamOverview found to remove");
  283. }
  284. }
  285. [ContextMenu("Test Team Overview")]
  286. public void TestTeamOverview()
  287. {
  288. var controller = FindFirstObjectByType<TeamOverviewController>();
  289. if (controller != null)
  290. {
  291. controller.TestShowTeamOverview();
  292. }
  293. else
  294. {
  295. Debug.LogWarning("⚠️ No TeamOverviewController found! Run setup first.");
  296. }
  297. }
  298. [ContextMenu("Fix UI Layering Issues")]
  299. public void FixUILayering()
  300. {
  301. Debug.Log("🔧 Fixing UI layering issues...");
  302. // Set correct sorting orders for all UI systems
  303. var teamOverview = FindFirstObjectByType<TeamOverviewController>()?.GetComponent<UIDocument>();
  304. if (teamOverview != null)
  305. {
  306. teamOverview.sortingOrder = 5;
  307. Debug.Log("✅ TeamOverview sortingOrder: 5");
  308. }
  309. var travelUI = GameObject.Find("TravelUI")?.GetComponent<UIDocument>();
  310. if (travelUI != null)
  311. {
  312. travelUI.sortingOrder = 3;
  313. Debug.Log("✅ TravelUI sortingOrder: 3");
  314. }
  315. var combatPopup = FindFirstObjectByType<CombatEventPopup>()?.GetComponent<UIDocument>();
  316. if (combatPopup != null)
  317. {
  318. combatPopup.sortingOrder = 100;
  319. Debug.Log("✅ CombatEventPopup sortingOrder: 100");
  320. }
  321. var combatPopupUXML = FindFirstObjectByType<CombatEventPopupUXML>()?.GetComponent<UIDocument>();
  322. if (combatPopupUXML != null)
  323. {
  324. combatPopupUXML.sortingOrder = 100;
  325. Debug.Log("✅ CombatEventPopupUXML sortingOrder: 100");
  326. }
  327. Debug.Log("🎯 UI layering fixed! Combat popups should now appear on top.");
  328. }
  329. }