Files
test/Assets/Scripts/CECUIManager.cs
T
2025-12-29 16:56:42 +07:00

269 lines
8.2 KiB
C#

using System;
using System.Collections.Generic;
using BrewMonster;
using BrewMonster.Network;
using BrewMonster.UI;
using UnityEngine;
using UnityEngine.UI;
public class CECUIManager : MonoSingleton<CECUIManager>
{
[SerializeField] private Transform uiRoot; // nơi chứa UI được spawn (Canvas hoặc Transform)
[SerializeField] private List<GameObject> uiPrefabs; // drag các prefab UI vào đây
private readonly Dictionary<System.Type, GameObject> _spawnedUIs = new();
[SerializeField] private HUDNPC npsUI;
[SerializeField] private int currentTargetNPCID;
CECGameUIMan gameUI;
AUIManager aUIManager;
[SerializeField] private DialogScriptTableObject dialogResouce;
[SerializeField] private Canvas canvasDlg;
[SerializeField] private CdlgQuickBar cDlgQuickBar;
[SerializeField] private Button skillButton;
[SerializeField] private Button btnSecondClick; // Button for second-click action (attack/move to NPC)
protected override void Awake()
{
base.Awake();
EventBus.Subscribe<CECHostPlayer.NPCINFO>(ShowUINPC);
EventBus.Subscribe<NPCDiedEvent>(TryHideUINPC);
gameUI = new CECGameUIMan();
gameUI.SetDependency(dialogResouce, canvasDlg);
gameUI.Init();
// Wire up second-click button / 连接第二次点击按钮
if (btnSecondClick != null)
{
btnSecondClick.onClick.AddListener(OnSecondClickButtonClicked);
}
}
private void OnDestroy()
{
EventBus.Unsubscribe<CECHostPlayer.NPCINFO>(ShowUINPC);
EventBus.Unsubscribe<NPCDiedEvent>(TryHideUINPC);
}
private void ShowUINPC(CECHostPlayer.NPCINFO obj)
{
npsUI.gameObject.SetActive(true);
npsUI.SetText($"{obj.CurrentHealth}/{obj.MaxHealth}", obj.Name, "");
npsUI.SetHealthImage((float)obj.CurrentHealth / (float)obj.MaxHealth);
currentTargetNPCID = obj.IDNPC;
}
public void SetSkillButton()
{
}
public CdlgQuickBar GetCDlgQuickBar()
{
return cDlgQuickBar;
}
private void TryHideUINPC(NPCDiedEvent obj)
{
if (obj.NPCID != currentTargetNPCID) return;
npsUI.gameObject.SetActive(false);
}
/// <summary>
/// Show UI by name of component ("DlgTask", "EC_InventoryUI")
/// </summary>
/// <param name="componentName">name of component ("DlgTask", "EC_InventoryUI")</param>
public void ShowUI(string componentName)
{
if (string.IsNullOrEmpty(componentName) || canvasDlg == null)
{
if (canvasDlg == null) Debug.LogError("canvasDlg chưa được gán");
return;
}
GetInGameUIMan().GetDialog(componentName).Show(true);
return;
var type = FindTypeByName(componentName);
if (TryShowCachedUI(type)) return;
if (FindUIByName(componentName, type)) return;
if (FindUIByType(type)) return;
Debug.LogWarning($"Không tìm thấy UI {componentName} đã spawn trong canvasDlg. Type found: {(type != null ? type.FullName : "null")}");
}
private System.Type FindTypeByName(string componentName)
{
string[] namespacePrefixes = {
"", // No namespace
"BrewMonster.Scripts.Task.UI.",
"BrewMonster.UI.",
"BrewMonster.Scripts.UI.",
"BrewMonster."
};
// Try with common namespace prefixes
foreach (var prefix in namespacePrefixes)
{
string fullTypeName = string.IsNullOrEmpty(prefix) ? componentName : prefix + componentName;
var type = System.Type.GetType(fullTypeName);
if (type != null) return type;
}
// Search in all assemblies
foreach (var assembly in System.AppDomain.CurrentDomain.GetAssemblies())
{
var type = assembly.GetType(componentName);
if (type != null) return type;
foreach (var prefix in namespacePrefixes)
{
if (string.IsNullOrEmpty(prefix)) continue;
type = assembly.GetType(prefix + componentName);
if (type != null) return type;
}
}
return null;
}
private bool TryShowCachedUI(System.Type type)
{
if (type != null && _spawnedUIs.TryGetValue(type, out var uiGo))
{
uiGo.SetActive(true);
return true;
}
return false;
}
private bool FindUIByName(string componentName, System.Type type)
{
for (int i = 0; i < canvasDlg.transform.childCount; i++)
{
var child = canvasDlg.transform.GetChild(i);
if (!child.name.Contains(componentName) && child.name != componentName) continue;
if (type != null)
{
var foundComponent = child.GetComponentInChildren(type, true);
if (foundComponent != null)
{
ActivateAndCacheUI(foundComponent.gameObject, type);
return true;
}
}
ActivateAndCacheUI(child.gameObject, type);
return true;
}
return false;
}
private bool FindUIByType(System.Type type)
{
if (type == null) return false;
var foundComponent = canvasDlg.GetComponentInChildren(type, true);
if (foundComponent != null)
{
ActivateAndCacheUI(foundComponent.gameObject, type);
return true;
}
return false;
}
private void ActivateAndCacheUI(GameObject uiGameObject, System.Type type)
{
uiGameObject.SetActive(true);
if (type != null) _spawnedUIs[type] = uiGameObject;
}
/// <summary>
/// Ẩn UI (disable thay vì destroy)
/// </summary>
public void HideUI<T>() where T : Component
{
var type = typeof(T);
if (_spawnedUIs.TryGetValue(type, out var uiGo))
{
uiGo.SetActive(false);
}
}
/// <summary>
/// Kiểm tra UI có đang active không
/// </summary>
public bool IsUIActive<T>() where T : Component
{
var type = typeof(T);
return _spawnedUIs.TryGetValue(type, out var uiGo) && uiGo.activeSelf;
}
/// <summary>
/// Ẩn tất cả UI hiện tại
/// </summary>
public void HideAll()
{
foreach (var kv in _spawnedUIs)
{
kv.Value.SetActive(false);
}
}
public CECGameUIMan GetInGameUIMan()
{
if (gameUI == null)
{
gameUI = new CECGameUIMan();
gameUI.SetDependency(dialogResouce, canvasDlg);
gameUI.Init();
}
return gameUI;
}
/// <summary>
/// Get the current target NPC ID (same as stored from NPCINFO event)
/// </summary>
public int GetCurrentTargetNPCID()
{
return currentTargetNPCID;
}
//todo: change this code to other place
private int slot = 0;
public void OnClickedWaveHand()
{
if (EC_Game.GetGameRun().GetPoseCmdShortcuts() == null)
{
EC_Game.GetGameRun().StartGame(0, Vector3.zero);
}
CECShortcut pSC = EC_Game.GetGameRun().GetPoseCmdShortcuts().GetShortcut(slot);
if (pSC != null) // && pObjSrc->GetDataPtr("ptr_CECShortcut") == pSC
{
// a_LogOutput(1, "[Dat Emote] ptr_CECShortcut");
pSC.Execute();
}
}
/// <summary>
/// Handle second-click button click - triggers attack or move to NPC / 处理第二次点击按钮 - 触发攻击或移动到NPC
/// Uses OnMsgLBtnClick with selected target to reuse existing logic / 使用OnMsgLBtnClick和选中的目标来重用现有逻辑
/// </summary>
private void OnSecondClickButtonClicked()
{
CECHostPlayer hostPlayer = EC_Game.GetGameRun()?.GetHostPlayer();
if (hostPlayer != null)
{
int selectedTarget = hostPlayer.GetSelectedTarget();
if (selectedTarget != 0)
{
// Call OnMsgLBtnClick with the selected target to simulate second click / 使用选中的目标调用OnMsgLBtnClick以模拟第二次点击
hostPlayer.OnMsgLBtnClick(selectedTarget);
}
}
}
}