Files
2025-10-21 16:55:22 +07:00

170 lines
6.6 KiB
C#

using System;
using System.Text;
using System.Text.RegularExpressions;
using UnityEngine;
using TMPro;
namespace PerfectWorld.Scripts.Common
{
/// <summary>
/// Utility class for formatting text with special characters and color codes
/// Handles Perfect World's custom text formatting system
/// </summary>
public static class EC_TextFormatter
{
/// <summary>
/// Format text for TextMeshPro components with rich text support
/// </summary>
/// <param name="text">Raw text with formatting codes</param>
/// <returns>Formatted text for TextMeshPro</returns>
public static string FormatForTextMeshPro(string text)
{
if (string.IsNullOrEmpty(text))
return string.Empty;
StringBuilder result = new StringBuilder(text);
// Handle line breaks (\r)
result.Replace("\\r", "\n");
// Handle color codes (^RRGGBB format)
string processedText = ProcessColorCodes(result);
return processedText;
}
/// <summary>
/// Format text for legacy Text components (limited rich text support)
/// </summary>
/// <param name="text">Raw text with formatting codes</param>
/// <returns>Formatted text for legacy Text</returns>
public static string FormatForLegacyText(string text)
{
if (string.IsNullOrEmpty(text))
return string.Empty;
StringBuilder result = new StringBuilder(text);
// Handle line breaks (\r)
result.Replace("\\r", "\n");
// Handle color codes (^RRGGBB format) - convert to Unity's rich text format
string processedText = ProcessColorCodesForLegacy(result);
return processedText;
}
/// <summary>
/// Process color codes for TextMeshPro (supports hex colors directly)
/// </summary>
private static string ProcessColorCodes(StringBuilder text)
{
// Pattern to match color codes: ^ followed by 6 hex characters
string pattern = @"\^([0-9A-Fa-f]{6})";
return Regex.Replace(text.ToString(), pattern, match =>
{
string hexColor = match.Groups[1].Value;
return $"<color=#{hexColor}>";
}, RegexOptions.None);
}
/// <summary>
/// Process color codes for legacy Text (convert to Unity rich text format)
/// </summary>
private static string ProcessColorCodesForLegacy(StringBuilder text)
{
// Pattern to match color codes: ^ followed by 6 hex characters
string pattern = @"\^([0-9A-Fa-f]{6})";
return Regex.Replace(text.ToString(), pattern, match =>
{
string hexColor = match.Groups[1].Value;
// Convert hex to Unity color format
Color color = HexToColor(hexColor);
return $"<color=#{ColorUtility.ToHtmlStringRGB(color)}>";
}, RegexOptions.None);
}
/// <summary>
/// Convert hex color string to Unity Color
/// </summary>
/// <param name="hex">Hex color string (e.g., "ffcb4a")</param>
/// <returns>Unity Color object</returns>
private static Color HexToColor(string hex)
{
if (hex.Length != 6)
return Color.white;
try
{
int r = Convert.ToInt32(hex.Substring(0, 2), 16);
int g = Convert.ToInt32(hex.Substring(2, 2), 16);
int b = Convert.ToInt32(hex.Substring(4, 2), 16);
return new Color(r / 255f, g / 255f, b / 255f, 1f);
}
catch
{
return Color.white;
}
}
/// <summary>
/// Apply formatted text to a TextMeshPro component
/// </summary>
/// <param name="textComponent">TextMeshPro component</param>
/// <param name="rawText">Raw text with formatting codes</param>
public static void SetFormattedText(TMPro.TextMeshProUGUI textComponent, string rawText)
{
if (textComponent == null)
return;
textComponent.text = FormatForTextMeshPro(rawText);
}
/// <summary>
/// Apply formatted text to a legacy Text component
/// </summary>
/// <param name="textComponent">Legacy Text component</param>
/// <param name="rawText">Raw text with formatting codes</param>
public static void SetFormattedText(UnityEngine.UI.Text textComponent, string rawText)
{
if (textComponent == null)
return;
textComponent.text = FormatForLegacyText(rawText);
}
/// <summary>
/// Get formatted text for display (auto-detects best format)
/// </summary>
/// <param name="rawText">Raw text with formatting codes</param>
/// <param name="preferTextMeshPro">Whether to prefer TextMeshPro formatting</param>
/// <returns>Formatted text</returns>
public static string GetFormattedText(string rawText, bool preferTextMeshPro = true)
{
if (preferTextMeshPro)
return FormatForTextMeshPro(rawText);
else
return FormatForLegacyText(rawText);
}
/// <summary>
/// Test method to demonstrate formatting with the provided example
/// </summary>
public static void TestFormatting()
{
string testText = @"^ffcb4aTương truyền mang chiếc chuông này, muốn tới nơi nào, chỉ cần lắc nhẹ là sẽ tới.\r^5998FFĐể vật phẩm này trong túi đồ, khi tìm Di chuyển tiến hành di chuyển, chỉ cần kích vào điểm di chuyển trên bản đồ\rsẽ đến thẳng được địa điểm đó. Phí trung chuyển sẽ bị khấu trừ ít.\r^00ffffCó thời hạn trong một tuần, sau một tuần sẽ biến mất.";
Debug.Log("=== Text Formatting Test ===");
Debug.Log("Original Text:");
Debug.Log(testText);
Debug.Log("\nFormatted for TextMeshPro:");
Debug.Log(FormatForTextMeshPro(testText));
Debug.Log("\nFormatted for Legacy Text:");
Debug.Log(FormatForLegacyText(testText));
}
}
}