using BrewMonster.Network; using CSNetwork; using System.Collections.Generic; using TMPro; using UnityEngine; using UnityEngine.UI; namespace BrewMonster.UI { public class AUIDialog : MonoBehaviour { protected Dictionary m_StringTable = new Dictionary(); protected bool m_bShow = false; protected string m_strDataName = ""; protected string m_strDataPtrName = ""; protected uint m_dwData; protected object m_pvData; protected AUIManager m_pAUIManager = null; protected string m_szName; private bool m_bUpdateRenderTarget = false; [SerializeField] TextMeshProUGUI skillNameText; [SerializeField] Image imageProgress; [SerializeField] Button btnCancel; public virtual void Show(bool value) { gameObject.SetActive(value); m_bShow = value; OnShowDialogue(); } public virtual void ShowForPlayer(int characterId) { } public string GetName() { return m_szName; } public bool SetName(string pszName) { m_szName = pszName; if (m_pAUIManager == null) return false; // Will be registered when SetAUIManager is called if (m_pAUIManager.m_DlgName.ContainsKey(pszName)) return false; //m_pAUIManager.m_DlgName.Remove(m_szName); m_pAUIManager.m_DlgName[m_szName] = this; return true; } public void SetData(uint dwData, string strName = "") { m_strDataName = strName; m_dwData = dwData; } public uint GetData() { return m_dwData; } public object GetDataPtr(string strName) { //if (0 != m_pvData && strName != m_strDataPtrName) // AUI_ReportError(__LINE__, 1, "AUIDialog::GetDataPtr(), data name not match"); return m_pvData; } public bool IsShow() { return m_bShow; } public void SetDataPtr(object pvData, string strName) { m_strDataPtrName = strName; m_pvData = pvData; } public TextMeshProUGUI GetSkillNameText() { return skillNameText; } public CECGameUIMan GetGameUIMan() { return EC_Game.GetGameRun().GetUIManager().GetInGameUIMan(); } public Image GetProgressImage() { return imageProgress; } public CECHostPlayer GetHostPlayer() { return EC_Game.GetGameRun().GetHostPlayer(); } public string GetStringFromTable(int idString) { CECGameUIMan gameUIMan = EC_Game.GetGameRun().GetUIManager().GetInGameUIMan(); string str = gameUIMan.GetStringFromAuiDialogTable(idString); if (str == null) { return gameUIMan.GetStringFromTable(idString); } return str; } /// /// Format a string table entry that may still use printf-style placeholders (e.g. "%d", "%s"). /// This converts printf-style placeholders into C# string.Format placeholders ("{0}", "{1}", ...). /// protected string FormatFromTable(int idString, params object[] args) { return FormatPrintf(GetStringFromTable(idString), args); } /// /// Convert/format printf-style strings (e.g. "ID:%d Name:%s") with C# args. /// Supports common specifiers and keeps "%%" as a literal percent. /// public static string FormatPrintf(string formatStr, params object[] args) { if (string.IsNullOrEmpty(formatStr)) return formatStr; var sb = new System.Text.StringBuilder(); int paramIndex = 0; for (int i = 0; i < formatStr.Length; i++) { if (formatStr[i] == '%' && i + 1 < formatStr.Length) { // "%%" -> literal '%' if (formatStr[i + 1] == '%') { sb.Append('%'); i++; continue; } int startPos = i; int j = i + 1; // Parse flags (skip; best-effort) bool hasMinus = false; bool hasZero = false; bool hasPlus = false; while (j < formatStr.Length) { char c = formatStr[j]; if (c == '-') { hasMinus = true; j++; } else if (c == '0') { hasZero = true; j++; } else if (c == '+') { hasPlus = true; j++; } else { break; } } // Parse width int width = 0; int widthStart = j; while (j < formatStr.Length && char.IsDigit(formatStr[j])) j++; if (j > widthStart) int.TryParse(formatStr.Substring(widthStart, j - widthStart), out width); // Parse precision (e.g. ".2") int precision = -1; if (j < formatStr.Length && formatStr[j] == '.') { j++; int precStart = j; while (j < formatStr.Length && char.IsDigit(formatStr[j])) j++; if (j > precStart) int.TryParse(formatStr.Substring(precStart, j - precStart), out precision); } // Final type char if (j >= formatStr.Length) { sb.Append('%'); continue; } char typeChar = formatStr[j]; bool recognized = typeChar == 'd' || typeChar == 'i' || typeChar == 'u' || typeChar == 's' || typeChar == 'c' || typeChar == 'f' || typeChar == 'F' || typeChar == 'e' || typeChar == 'E' || typeChar == 'g' || typeChar == 'G'; if (!recognized) { // Not a recognized printf placeholder: keep original char(s) sb.Append(formatStr[startPos]); continue; } // Build C# placeholder, preserving common width/precision behavior (best-effort). string csharpFormatSpec = string.Empty; // Alignment for width: left/right if (width > 0 && (typeChar == 'd' || typeChar == 'i' || typeChar == 'u' || typeChar == 's' || typeChar == 'c')) { // C# alignment: {0,10} right-aligned; {0,-10} left-aligned int align = hasMinus ? -width : width; csharpFormatSpec = $",{align}"; } // Precision for float: %.2f -> {0:F2} if (precision >= 0 && (typeChar == 'f' || typeChar == 'F' || typeChar == 'e' || typeChar == 'E' || typeChar == 'g' || typeChar == 'G')) { string floatFmt = (typeChar == 'e' || typeChar == 'E') ? $"E{precision}" : (typeChar == 'g' || typeChar == 'G') ? $"G{precision}" : $"F{precision}"; if (csharpFormatSpec.StartsWith(",")) csharpFormatSpec += $":{floatFmt}"; else csharpFormatSpec = $":{floatFmt}"; } // %+d -> show sign (best-effort) if (hasPlus && (typeChar == 'd' || typeChar == 'i') && string.IsNullOrEmpty(csharpFormatSpec)) { csharpFormatSpec = ":+0;-0"; } // %0Nd -> zero-padded integers (best-effort) if (hasZero && width > 0 && (typeChar == 'd' || typeChar == 'i' || typeChar == 'u')) { if (!csharpFormatSpec.StartsWith(",")) csharpFormatSpec = $":D{width}"; } if (!string.IsNullOrEmpty(csharpFormatSpec)) { if (csharpFormatSpec.StartsWith(",") || csharpFormatSpec.StartsWith(":")) sb.Append($"{{{paramIndex}{csharpFormatSpec}}}"); else sb.Append($"{{{paramIndex}:{csharpFormatSpec}}}"); } else { sb.Append($"{{{paramIndex}}}"); } paramIndex++; i = j; // skip the full specifier } else { sb.Append(formatStr[i]); } } // Convert-only: callers that do string.Format(fmt, ...) themselves must not pass args here. // 仅转换:调用方自己 string.Format(fmt, …) 时不要传 args。 if (args == null || args.Length == 0) return sb.ToString(); try { return string.Format(sb.ToString(), args); } catch (System.FormatException) { Debug.LogWarning($"[AUIDialog] FormatPrintf failed for string: {formatStr}, expected {paramIndex} args, got {args?.Length ?? 0}"); return formatStr; } } public AUIManager GetAUIManager() { return m_pAUIManager; } public void SetAUIManager(AUIManager pAUIManager) { m_pAUIManager = pAUIManager; // Register dialog name if it was set before manager was assigned if (m_pAUIManager != null && !string.IsNullOrEmpty(m_szName) && !m_pAUIManager.m_DlgName.ContainsKey(m_szName)) { m_pAUIManager.m_DlgName[m_szName] = this; } } public virtual void OnEnable() { } public virtual void OnDisable() { } public virtual void Awake() { m_szName = "Dialog_"; if(btnCancel != null) { btnCancel.onClick.RemoveAllListeners(); btnCancel.onClick.AddListener(OnClickBtnCancel); } } public virtual void Start() { } public virtual void Update() { Render(); } public virtual void OnShowDialogue() { } public virtual bool Render() { return false; } public virtual void Release() { m_StringTable.Clear(); m_strDataName = ""; m_strDataPtrName = ""; m_dwData = 0; m_pvData = null; m_szName = ""; } /// Override in dialogs that support attribute-point reset (e.g. DlgCharacter). No-op by default. public virtual void ResetPoints() { } public virtual void UpdateRenderTarget() { m_bUpdateRenderTarget = true; } public bool NeedRenderTargetUpdate() { return m_bUpdateRenderTarget; } public void ResetRenderTargetFlag() { m_bUpdateRenderTarget = false; } public virtual void CloseDialogue() { CECUIManager.Instance.HideCurrentUIInStack(); } public void OnClickBtnCancel() { EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_PRESSCANCEL, MANAGER_INDEX.MAN_PLAYER, 0); } } }