Merge pull request 'feature/fix-ui' (#170) from feature/fix-ui into develop

Reviewed-on: https://git.pthub.vn/Unity/perfect-world-unity/pulls/170
This commit is contained in:
hainh
2026-02-26 07:34:46 +00:00
9 changed files with 15856 additions and 6 deletions
@@ -49,3 +49,5 @@ MonoBehaviour:
prefab: {fileID: 1126053271199039253, guid: 526d462bd8c87b74c9e461e80d028cb2, type: 3}
- id: DlgPlayerOptions
prefab: {fileID: 1813565726936289741, guid: a0e02be030755ab4a917523764fe4eef, type: 3}
- id: DlgPetHatch
prefab: {fileID: 3120870614492201289, guid: eaebf3351c396754fb983e0d5ba83e9a, type: 3}
@@ -771,7 +771,11 @@ namespace BrewMonster.Scripts.Managers
if (eventTrigger == null)
eventTrigger = button.gameObject.AddComponent<EventTrigger>();
eventTrigger.triggers.Clear();
eventTrigger.triggers.RemoveAll(e =>
e.eventID == EventTriggerType.BeginDrag ||
e.eventID == EventTriggerType.Drag ||
e.eventID == EventTriggerType.EndDrag ||
e.eventID == EventTriggerType.Drop);
void AddEvent(EventTriggerType type, UnityEngine.Events.UnityAction<BaseEventData> action)
{
@@ -378,6 +378,12 @@ namespace PerfectWorld.Scripts.Managers
Debug.Log("[THN]GetFollowPetDesc. This is not implemented yet.");
return "";
}
public PET_EGG_ESSENCE GetDBEssence()
{
return m_pDBEssence;
}
private string GetEvolutionPetDesc(bool bRepair)
{
Debug.Log("[THN]GetEvolutionPetDesc. This is not implemented yet.");
@@ -171,8 +171,6 @@ public class CECNPCServer : CECNPC
if (idTask <= 0 || !pTask.HasTask(idTask))
continue;
BMLogger.Log($"[UpdateCurTaskIcon] Check IN task {idTask}, HasTask={pTask.HasTask(idTask)}, CanFinish={pTask.CanFinishTask((idTask))}");
var pTaskTemp = pTaskMan.GetTaskTemplByID(idTask);
if (pTaskTemp == null)
continue;
@@ -184,7 +182,6 @@ public class CECNPCServer : CECNPC
if (pTaskTemp.IsKeyTask())
{
m_TaskIcon = IconTaskType.QI_IN_K;
BMLogger.Log($"[UpdateCurTaskIcon] Set icon QI_IN_K for task {idTask}");
_needUpdateTaskIcon = true;
return;
}
@@ -230,7 +227,6 @@ public class CECNPCServer : CECNPC
else if ((taskFlag & TASK_COMPLETE_TYPE1) != 0)
m_TaskIcon = IconTaskType.QI_IN_TYPE1;
BMLogger.Log($"[UpdateCurTaskIcon] Set complete icon {m_TaskIcon}");
_needUpdateTaskIcon = true;
return;
}
@@ -2377,10 +2377,12 @@ namespace BrewMonster.UI
}
else if (iService == CDLGNPC.CDLGNPC_PETHATCH && (pEssence?.combined_services & 0x200) != 0)
{
Show(false);
//Show(false);
// TO DO: fix later
//GetGameUIMan().m_pDlgInventory.Show(true);
//GetGameUIMan().m_pDlgPetHatch.Show(true);
var dlgPetHatch = GetGameUIMan().GetDialog("DlgPetHatch");
dlgPetHatch.Show(true);
return;
}
else if (iService == CDLGNPC.CDLGNPC_PETREC && (pEssence?.combined_services & 0x400) != 0)
@@ -0,0 +1,561 @@
using BrewMonster.Assets.PerfectWorld.Scripts.UI;
using BrewMonster.Common;
using BrewMonster.Managers;
using BrewMonster.Scripts;
using BrewMonster.Scripts.Managers;
using CSNetwork.GPDataType;
using Cysharp.Threading.Tasks.Triggers;
using PerfectWorld.Scripts.Managers;
using System;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
namespace BrewMonster.UI
{
public class DlgPetHatch : AUIDialog
{
[Header("Component")]
[SerializeField] private TextMeshProUGUI m_pTxtName;
[SerializeField] private TextMeshProUGUI m_pTxtGold;
[SerializeField] private Image m_pImg_Item;
[SerializeField] private GameObject m_pTxtBindTip;
[Header("Buttons")]
[SerializeField] private Button m_btnConfirm;
[SerializeField] private Button m_btnCancel;
[SerializeField] private Button m_btnClose;
[Header("Defautl Icon")]
[SerializeField] private Sprite m_defaultIcon;
private int m_nSlot = 1;
private EC_IvtrPetEgg m_pCurrentEgg = null;
private float m_doubleClickTime = 1f;
private Dictionary<int, float> m_lastClickTime = new Dictionary<int, float>();
public override void Awake()
{
base.Awake();
RegisterDrop(m_pImg_Item.transform, OnDropEgg);
RegisterClick(m_pImg_Item.transform, OnClickEggSlot);
if (m_btnConfirm != null)
m_btnConfirm.onClick.AddListener(OnCommandConfirm);
if (m_btnCancel != null)
m_btnCancel.onClick.AddListener(OnCommandCancel);
if (m_btnClose != null)
m_btnClose.onClick.AddListener(OnCommandCancel);
}
public override void OnEnable()
{
base.OnEnable();
ClearEgg();
RegisterInventoryDoubleClick();
}
public override void OnDisable()
{
base.OnDisable();
RestoreInventoryColor();
UnregisterInventoryDoubleClick();
}
public override void Show(bool value)
{
base.Show(value);
if (value)
{
OnShowDialog();
}
}
private void OnShowDialog()
{
ClearEgg();
}
#region Double-Click Support
private void RegisterInventoryDoubleClick()
{
var inventoryUI = FindFirstObjectByType<EC_InventoryUI>();
if (inventoryUI == null)
{
return;
}
var field = typeof(EC_InventoryUI)
.GetField("inventoryPackButtons", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
if (field == null)
{
return;
}
var buttons = field.GetValue(inventoryUI) as List<Button>;
if (buttons == null || buttons.Count == 0)
{
return;
}
for (int i = 0; i < buttons.Count; i++)
{
if (buttons[i] != null)
{
RegisterDoubleClickOnButton(buttons[i], i);
}
}
}
private void UnregisterInventoryDoubleClick()
{
var inventoryUI = FindFirstObjectByType<EC_InventoryUI>();
if(inventoryUI == null)
{
return;
}
var field = typeof(EC_InventoryUI)
.GetField("inventoryPackButtons", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
if (field == null)
return;
var buttons = field.GetValue(inventoryUI) as List<Button>;
if (buttons == null)
return;
foreach (var btn in buttons)
{
if (btn != null)
{
var trigger = btn.GetComponent<EventTrigger>();
if (trigger != null)
{
trigger.triggers.RemoveAll(e =>
e.eventID == EventTriggerType.PointerClick &&
e.callback.GetPersistentEventCount() > 0);
}
}
}
}
private void RegisterDoubleClickOnButton(Button button, int slotIndex)
{
if (button == null)
return;
var trigger = button.GetComponent<EventTrigger>();
if (trigger == null)
trigger = button.gameObject.AddComponent<EventTrigger>();
var entry = new EventTrigger.Entry
{
eventID = EventTriggerType.PointerClick
};
entry.callback.AddListener((data) =>
{
OnInventoryButtonClick(slotIndex, (PointerEventData)data);
});
trigger.triggers.Add(entry);
}
private void OnInventoryButtonClick(int slotIndex, PointerEventData eventData)
{
float currentTime = Time.unscaledTime;
if (m_lastClickTime.ContainsKey(slotIndex))
{
float timeSinceLastClick = currentTime - m_lastClickTime[slotIndex];
if (timeSinceLastClick <= m_doubleClickTime)
{
OnInventoryItemDoubleClick(slotIndex);
m_lastClickTime.Remove(slotIndex);
return;
}
}
m_lastClickTime[slotIndex] = currentTime;
}
private void OnInventoryItemDoubleClick(int slotIndex)
{
var host = CECGameRun.Instance?.GetHostPlayer();
if (host == null)
{
return;
}
var inv = host.GetInventory(0);
if (inv == null)
{
return;
}
var item = inv.GetItem(slotIndex, false);
if (item == null)
{
return;
}
if (item.GetClassID() != (int)EC_IvtrItem.InventoryClassId.ICID_PETEGG)
{
return;
}
EC_IvtrItem detailedItem = EC_IvtrItem.CreateItem(item.m_tid, item.m_expire_date, item.m_iCount);
if (item.Content != null && item.Content.Length > 0)
{
detailedItem.SetItemInfo(item.Content, item.Content.Length);
}
else
{
detailedItem.GetDetailDataFromLocal();
}
EC_IvtrPetEgg petEgg = detailedItem as EC_IvtrPetEgg;
if (petEgg == null)
{
return;
}
SetEggInternal(petEgg, slotIndex);
}
private void SetEggInternal(EC_IvtrPetEgg petEgg, int slotIndex)
{
if(petEgg == null)
return;
if (m_nSlot >= 0)
{
var previousBtn = FindInventoryButtonBySlot(m_nSlot);
SetInventorySlotGray(previousBtn, false);
}
if(m_pCurrentEgg != null)
m_pCurrentEgg.Freeze(false);
m_pCurrentEgg = petEgg;
m_nSlot = slotIndex;
petEgg.Freeze(true);
UpdateEggUI(petEgg);
var btn = FindInventoryButtonBySlot(slotIndex);
SetInventorySlotGray(btn, true);
}
#endregion
private void RegisterDrop(Transform target, Action<PointerEventData> callback)
{
if (target == null)
return;
var trigger = target.GetComponent<EventTrigger>();
if(trigger == null)
trigger = target.gameObject.AddComponent<EventTrigger>();
var existingDrop = trigger.triggers.Find(e => e.eventID == EventTriggerType.Drop);
if(existingDrop != null)
trigger.triggers.Remove(existingDrop);
var entry = new EventTrigger.Entry
{
eventID = EventTriggerType.Drop
};
entry.callback.AddListener((data) => { callback((PointerEventData)data); });
trigger.triggers.Add(entry);
}
private void RegisterClick(Transform target, Action<PointerEventData> callback)
{
if (target == null)
return;
var trigger = target.GetComponent<EventTrigger>();
if (trigger == null)
trigger = target.gameObject.AddComponent<EventTrigger>();
var existingClick = trigger.triggers.Find(e => e.eventID == EventTriggerType.PointerClick);
if (existingClick != null)
trigger.triggers.Remove(existingClick);
var entry = new EventTrigger.Entry
{
eventID = EventTriggerType.PointerClick
};
entry.callback.AddListener((data) => { callback((PointerEventData)data); });
trigger.triggers.Add(entry);
}
private void OnClickEggSlot(PointerEventData eventData)
{
if (m_pCurrentEgg != null)
{
ReturnItemToInventory(m_nSlot);
ClearEgg();
}
}
private void OnDropEgg(PointerEventData eventData)
{
if (eventData.pointerDrag == null)
return;
var btn = eventData.pointerDrag.GetComponent<Button>();
if(btn == null)
return;
int slotIndex = btn.transform.GetSiblingIndex();
var item = GetItemFromDrag(eventData);
if (item == null)
return;
if(item.GetClassID() != (int)EC_IvtrItem.InventoryClassId.ICID_PETEGG)
{
return;
}
EC_IvtrItem detailedItem = EC_IvtrItem.CreateItem(item.m_tid, item.m_expire_date, item.m_iCount);
if(item.Content != null && item.Content.Length > 0)
{
detailedItem.SetItemInfo(item.Content, item.Content.Length);
}
else
{
detailedItem.GetDetailDataFromLocal();
}
EC_IvtrPetEgg petEgg = detailedItem as EC_IvtrPetEgg;
if(petEgg == null)
{
return;
}
if (m_nSlot >= 0)
{
var previosBtn = FindInventoryButtonBySlot(m_nSlot);
SetInventorySlotGray(previosBtn, false);
}
if(m_pCurrentEgg != null)
m_pCurrentEgg.Freeze(false);
m_pCurrentEgg = petEgg;
m_nSlot = slotIndex;
petEgg.Freeze(true);
UpdateEggUI(petEgg);
SetInventorySlotGray(btn, true);
}
private EC_IvtrItem GetItemFromDrag(PointerEventData eventData)
{
if (eventData.pointerDrag == null)
return null;
var btn = eventData.pointerDrag.GetComponent<Button>();
if(btn == null)
return null;
int slotIndex = btn.transform.GetSiblingIndex();
var host = CECGameRun.Instance?.GetHostPlayer();
if(host == null)
return null;
var inv = host.GetInventory(0);
if (inv == null)
return null;
return inv.GetItem(slotIndex, false);
}
private Button FindInventoryButtonBySlot(int slot)
{
var inventoryUI = FindFirstObjectByType<EC_InventoryUI>();
if(inventoryUI == null)
return null;
var field = typeof(EC_InventoryUI)
.GetField("inventoryPackButtons", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
if(field == null)
return null;
var list = field.GetValue(inventoryUI) as System.Collections.Generic.List<Button>;
if(list == null || slot < 0 || slot >= list.Count)
return null;
return list[slot];
}
private void SetInventorySlotGray(Button btn, bool gray)
{
if (btn == null)
return;
var img = btn.GetComponent<Image>();
if (img == null)
return;
img.color = gray ? Color.gray : Color.white;
}
private void SetSlotIcon(Image slot, EC_IvtrItem item)
{
if (slot == null || item == null)
{
BMLogger.LogWarning("DlgPetHatch: SetSlotIcon - slot or item is null");
return;
}
var sprite = EC_IvtrItemUtils.Instance.ResolveItemIconSprite(item.m_tid);
if (sprite == null)
{
BMLogger.LogWarning($"DlgPetHatch: No sprite found for item tid: {item.m_tid}");
return;
}
BMLogger.Log($"DlgPetHatch: Setting icon for {item.GetName()}");
slot.sprite = sprite;
slot.enabled = true;
slot.color = Color.white;
slot.SetNativeSize();
}
private void ClearSlotIcon(Image slot)
{
if (slot == null)
return;
slot.sprite = m_defaultIcon;
slot.enabled = m_defaultIcon != null;
}
private void ReturnItemToInventory(int slotIndex)
{
if (slotIndex < 0)
return;
var btn = FindInventoryButtonBySlot(slotIndex);
SetInventorySlotGray(btn, false);
}
private void RestoreInventoryColor()
{
if (m_nSlot >= 0)
{
var btn = FindInventoryButtonBySlot(m_nSlot);
SetInventorySlotGray(btn, false);
}
}
private void UpdateEggUI(EC_IvtrPetEgg pEgg)
{
if(pEgg == null)
return;
if (m_pTxtBindTip != null)
{
bool isBound = (pEgg.GetProcType() & (int)EC_IvtrItem.ProcType.PROC_BIND) != 0;
m_pTxtBindTip.SetActive(isBound);
if (isBound)
{
BMLogger.Log("DlgPetHatch: Pet egg is bound - displaying warning");
}
}
if(m_pTxtName != null)
{
m_pTxtName.text = pEgg.GetName();
}
if (m_pTxtGold != null)
{
try
{
var essence = pEgg.GetDBEssence();
if (essence.id != 0)
{
m_pTxtGold.SetText(essence.money_hatched.ToString());
}
else
{
m_pTxtGold.SetText("0");
}
}
catch (Exception ex)
{
BMLogger.LogError($"DlgPetHatch: Failed to get essence data for pet egg - {ex.Message}");
m_pTxtGold.SetText("0");
}
}
SetSlotIcon(m_pImg_Item, pEgg);
}
private void ClearEgg()
{
if(m_pTxtBindTip != null)
m_pTxtBindTip.SetActive(false);
if (m_pCurrentEgg != null)
{
m_pCurrentEgg.Freeze(false);
m_pCurrentEgg = null;
}
ClearSlotIcon(m_pImg_Item);
if (m_pTxtName != null)
m_pTxtName.text = "___";
if(m_pTxtGold != null)
m_pTxtGold.text = "0";
m_nSlot = -1;
}
private void OnCommandConfirm()
{
//TODO: Send hatch command to server with m_pCurrentEgg
}
private void OnCommandCancel()
{
ClearEgg();
GetGameUIMan().EndNPCService();
Show(false);
GetHostPlayer().GetPack(InventoryConst.IVTRTYPE_PACK).UnfreezeAllItems();
}
public void SetEgg(EC_IvtrItem pItem, int nSlot)
{
if (pItem == null || !(pItem is EC_IvtrPetEgg))
return;
ClearEgg();
EC_IvtrPetEgg petEgg = (EC_IvtrPetEgg)pItem;
m_pCurrentEgg = petEgg;
m_nSlot = nSlot;
petEgg.Freeze(true);
UpdateEggUI(petEgg);
var btn = FindInventoryButtonBySlot(nSlot);
SetInventorySlotGray(btn, true);
}
private void OnDestroy()
{
ClearEgg();
RestoreInventoryColor();
}
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: d8447ff1f4a24bf4d9de247feb0d1f5f
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: eaebf3351c396754fb983e0d5ba83e9a
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant: