| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217 |
- using UnityEngine;
- using UnityEngine.InputSystem;
- using UnityEngine.UIElements;
- /// <summary>
- /// Displays agent information in a popup panel using UI Toolkit
- /// Singleton pattern to ensure only one panel is shown at a time
- /// </summary>
- public class AgentInfoPanel : MonoBehaviour
- {
- private static AgentInfoPanel instance;
- private static UIDocument uiDocument;
- private static VisualElement panelRoot;
- private static AIAgent currentAgent;
- private static AgentGroup currentGroup;
- void Awake()
- {
- if (instance != null && instance != this)
- {
- Destroy(gameObject);
- return;
- }
- instance = this;
- uiDocument = GetComponent<UIDocument>();
- if (uiDocument == null)
- {
- Debug.LogError("AgentInfoPanel: UIDocument component not found!");
- return;
- }
- }
- void OnEnable()
- {
- if (uiDocument == null) return;
- panelRoot = uiDocument.rootVisualElement.Q<VisualElement>("AgentInfoPanelRoot");
- if (panelRoot == null)
- {
- Debug.LogError("AgentInfoPanel: AgentInfoPanelRoot not found in UXML!");
- return;
- }
- // Hide panel initially
- panelRoot.style.display = DisplayStyle.None;
- // Setup close button
- var closeButton = panelRoot.Q<Button>("CloseButton");
- if (closeButton != null)
- {
- closeButton.clicked += HidePanel;
- }
- }
- /// <summary>
- /// Shows agent information in the info panel (solo agent).
- /// </summary>
- public static void ShowAgentInfo(AIAgent agent)
- {
- if (instance == null) { Debug.LogWarning("AgentInfoPanel: Instance not found!"); return; }
- if (agent == null) return;
- currentAgent = agent;
- currentGroup = null;
- instance.DisplayAgentInfo(agent, null);
- }
- /// <summary>
- /// Shows combined group information – called when clicking any member of a group.
- /// </summary>
- public static void ShowGroupInfo(AgentGroup group)
- {
- if (instance == null) { Debug.LogWarning("AgentInfoPanel: Instance not found!"); return; }
- if (group == null) return;
- currentGroup = group;
- currentAgent = group.Leader;
- instance.DisplayAgentInfo(group.Leader, group);
- }
- /// <summary>
- /// Displays agent or group information in the panel.
- /// When group is non-null, shows combined (max) stats and the member roster.
- /// </summary>
- private void DisplayAgentInfo(AIAgent agent, AgentGroup group)
- {
- if (panelRoot == null) return;
- panelRoot.style.display = DisplayStyle.Flex;
- bool isGroup = group != null && group.Size > 1;
- // ---- Header name ----
- var nameLabel = panelRoot.Q<Label>("AgentNameLabel");
- if (nameLabel != null)
- nameLabel.text = isGroup ? $"{agent.AgentName}'s Group" : agent.AgentName;
- // ---- Group banner ----
- var groupBanner = panelRoot.Q<VisualElement>("GroupBanner");
- if (groupBanner != null)
- {
- groupBanner.style.display = isGroup ? DisplayStyle.Flex : DisplayStyle.None;
- if (isGroup)
- {
- var sizeLabel = panelRoot.Q<Label>("GroupSizeLabel");
- if (sizeLabel != null)
- sizeLabel.text = $"Group of {group.Size} (max {AgentGroup.MAX_SIZE})";
- var membersLabel = panelRoot.Q<Label>("GroupMembersLabel");
- if (membersLabel != null)
- membersLabel.text = string.Join(", ", System.Linq.Enumerable.Select(group.Members, m => m.AgentName));
- }
- }
- // ---- Stats section title ----
- var statsTitle = panelRoot.Q<Label>("StatsTitle");
- if (statsTitle != null)
- statsTitle.text = isGroup ? "Combined Stats (best in group)" : "Stats";
- // ---- Stat bars ----
- if (isGroup)
- {
- UpdateStatDisplay("StrengthBar", "StrengthValue", group.CombinedStrength);
- UpdateStatDisplay("SpeedBar", "SpeedValue", group.CombinedSpeed);
- UpdateStatDisplay("MagicBar", "MagicValue", group.CombinedMagic);
- UpdateStatDisplay("DexterityBar", "DexterityValue", group.CombinedDexterity);
- UpdateStatDisplay("IntelligenceBar", "IntelligenceValue", group.CombinedIntelligence);
- UpdateStatDisplay("ConstitutionBar", "ConstitutionValue", group.CombinedConstitution);
- UpdateStatDisplay("HealthBar", "HealthValue", group.CombinedHealth, maxValue: group.Size * 110);
- var totalLabel = panelRoot.Q<Label>("TotalStatsValue");
- if (totalLabel != null)
- totalLabel.text = (group.CombinedStrength + group.CombinedSpeed + group.CombinedMagic
- + group.CombinedDexterity + group.CombinedIntelligence + group.CombinedConstitution).ToString();
- }
- else
- {
- var stats = agent.Stats;
- UpdateStatDisplay("StrengthBar", "StrengthValue", stats.Strength);
- UpdateStatDisplay("SpeedBar", "SpeedValue", stats.Speed);
- UpdateStatDisplay("MagicBar", "MagicValue", stats.Magic);
- UpdateStatDisplay("DexterityBar", "DexterityValue", stats.Dexterity);
- UpdateStatDisplay("IntelligenceBar", "IntelligenceValue", stats.Intelligence);
- UpdateStatDisplay("ConstitutionBar", "ConstitutionValue", stats.Constitution);
- UpdateStatDisplay("HealthBar", "HealthValue", stats.Health, maxValue: 110);
- var totalLabel = panelRoot.Q<Label>("TotalStatsValue");
- if (totalLabel != null)
- totalLabel.text = stats.GetTotalStats().ToString();
- }
- // ---- Status ----
- var statusLabel = panelRoot.Q<Label>("StatusLabel");
- if (statusLabel != null)
- {
- if (isGroup)
- statusLabel.text = $"Travelling together ({group.Size} members)";
- else if (agent.HasReachedGoal)
- statusLabel.text = "✓ Reached Exit";
- else if (agent.KnowsExitLocation)
- statusLabel.text = agent.GroupUpAffinity > 0.5f
- ? "Spotted exit — seeking allies..."
- : "Spotted exit — heading in!";
- else
- statusLabel.text = "Exploring maze...";
- }
- }
- /// <summary>
- /// Updates a stat display (progress bar and label)
- /// </summary>
- private void UpdateStatDisplay(string barName, string labelName, int value, int maxValue = 100)
- {
- var bar = panelRoot.Q<ProgressBar>(barName);
- if (bar != null)
- {
- bar.highValue = maxValue;
- bar.value = value;
- }
- var label = panelRoot.Q<Label>(labelName);
- if (label != null)
- {
- label.text = value.ToString();
- }
- }
- /// <summary>
- /// Hides the info panel
- /// </summary>
- private static void HidePanel()
- {
- if (panelRoot != null)
- {
- panelRoot.style.display = DisplayStyle.None;
- currentAgent = null;
- currentGroup = null;
- }
- }
- /// <summary>
- /// Hides panel when clicking outside of it
- /// </summary>
- void Update()
- {
- if (panelRoot == null || panelRoot.style.display == DisplayStyle.None) return;
- if (Mouse.current.leftButton.wasPressedThisFrame)
- {
- // Check if click is outside the panel
- var clickPos = Input.mousePosition;
- var panelWorldRect = panelRoot.worldBound;
- if (!panelWorldRect.Contains(new Vector2(clickPos.x, Screen.height - clickPos.y)))
- {
- HidePanel();
- }
- }
- }
- }
|