Files
test/Assets/PerfectWorld/Scripts/UI/ShopDetailPanel.cs
2025-12-09 16:37:16 +07:00

443 lines
14 KiB
C#

using BrewMonster.Network;
using NUnit.Framework;
using System;
using System.Collections.Generic;
using TMPro;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.UI;
public class ShopDetailPanel : MonoBehaviour
{
[Header("UI Components")]
public TextMeshProUGUI itemNameText;
public TextMeshProUGUI itemDescriptionText;
public Image itemIconImage;
public TextMeshProUGUI itemPriceText;
public TextMeshProUGUI itemQuantityText;
public TextMeshProUGUI itemGiftText;
[Header("Buy Options")]
public Button[] buyOptionButtons; // Up to 4 buy options
public TextMeshProUGUI[] buyOptionPriceTexts;
public TextMeshProUGUI[] buyOptionStatusTexts;
[Header("Action Buttons")]
public Button buyButton;
public Button closeButton;
private GShopItem currentItem;
private ShopUIManager shopManager;
void Start()
{
SetupEventListeners();
}
void SetupEventListeners()
{
if (buyButton != null)
buyButton.onClick.AddListener(OnBuyClicked);
if (closeButton != null)
closeButton.onClick.AddListener(OnCloseClicked);
// Setup buy option buttons
for (int i = 0; i < buyOptionButtons.Length; i++)
{
int optionIndex = i; // Capture for closure
if (buyOptionButtons[i] != null)
{
buyOptionButtons[i].onClick.AddListener(() => OnBuyOptionSelected(optionIndex));
}
}
}
public void SetupDetailPanel(GShopItem item, ShopUIManager manager)
{
Debug.Log($"[ShopDetailPanel] SetupDetailPanel called with item ID: {item.id}, Name: '{item.name}', Icon: '{item.icon}'");
currentItem = item;
shopManager = manager;
UpdateDisplay();
}
void UpdateDisplay()
{
Debug.Log($"[ShopDetailPanel] UpdateDisplay called for item ID: {currentItem.id}");
if (currentItem.id == 0)
{
Debug.LogWarning("[ShopDetailPanel] Current item ID is 0, skipping display update");
return;
}
// Set basic item info
if (itemNameText != null)
itemNameText.text = currentItem.name;
if (itemDescriptionText != null)
{
RemoveCaretColor(itemDescriptionText.text = ConvertColorCodeOfText(currentItem.desc));
}
if (itemQuantityText != null)
itemQuantityText.text = $"Quantity: {currentItem.num}";
// Load icon
Debug.Log($"[ShopDetailPanel] About to load icon. itemIconImage is null: {itemIconImage == null}");
Debug.Log($"[ShopDetailPanel] Current item icon field: '{currentItem.icon}'");
if (itemPriceText != null)
{
itemPriceText.text = currentItem.buy[0].price.ToString();
LayoutRebuilder.ForceRebuildLayoutImmediate(itemPriceText.transform as RectTransform);
}
if (itemIconImage != null)
{
LoadItemIcon(itemIconImage, currentItem.icon);
}
else
{
Debug.LogError("[ShopDetailPanel] itemIconImage is null! Make sure it's assigned in the inspector.");
}
// Update buy options
UpdateBuyOptions();
// Update gift info
UpdateGiftInfo();
}
struct ColorText
{
public string hex;
public string content;
}
private string ConvertColorCodeOfText(string input)
{
/*string returnValue = "";
List<ColorText> colorTexts = new List<ColorText>();
ColorText currentColorText = new ColorText();
currentColorText.hex = "ffffff";
currentColorText.content = "";
for (int i = 0; i < input.Length; i++)
{
if (input[i] == '^' && i + 6 < input.Length)
{
// Store the current segment before changing color
colorTexts.Add(currentColorText);
// Start a new color segment
currentColorText = new ColorText();
currentColorText.hex = input.Substring(i + 1, 6);
currentColorText.content = "";
i += 6;
}
else
{
currentColorText.content += input[i];
}
}
foreach ( var ct in colorTexts)
{
if (ct.hex.ToLower() != "ffffff")
{
returnValue += $"<color=#{ct.hex}>{ct.content}</color>";
}
else
{
returnValue += ct.content;
}
Debug.Log($"[ShopDetailPanel] Processed ColorText: Hex='{ct.hex}', Content='{ct.content}'");
}
return returnValue;*/
if (string.IsNullOrEmpty(input))
return input;
input = input.Replace("\\r\\n", "\n");
input = input.Replace("\\r", "\n");
input = input.Replace("\\n", "\n");
input = input.Replace("\r\n", "\n");
input = input.Replace("\r", "\n");
input = input.Replace("\n", "\n");
System.Text.StringBuilder sb = new System.Text. StringBuilder();
for (int i = 0; i < input.Length; i++)
{
if (input[i] == '^' && i + 6 < input.Length)
{
string hex = input.Substring(i + 1, 6);
if (hex.ToLower() != "ffffff")
{
sb.Append($"<color=#{hex}>");
}
i += 6;
}
else
{
sb.Append(input[i]);
}
}
sb.Append("</color>");
return sb.ToString();
}
public static string RemoveCaretColor(string input)
{
return System.Text.RegularExpressions.Regex.Replace(input, @"\^[0-9a-fA-F]{6}", "");
}
void UpdateBuyOptions()
{
for (int i = 0; i < buyOptionButtons.Length && i < currentItem.buy.Length; i++)
{
var buyOption = currentItem.buy[i];
// Show/hide buy option based on price
bool hasValidPrice = buyOption.price > 0;
if (buyOptionButtons[i] != null)
{
buyOptionButtons[i].gameObject.SetActive(hasValidPrice);
}
if (hasValidPrice)
{
// Set price text
if (i < buyOptionPriceTexts.Length && buyOptionPriceTexts[i] != null)
{
buyOptionPriceTexts[i].text = buyOption.price.ToString();
}
// Set status text
if (i < buyOptionStatusTexts.Length && buyOptionStatusTexts[i] != null)
{
string statusText = GetStatusText(buyOption.status);
buyOptionStatusTexts[i].text = statusText;
}
}
}
}
string GetStatusText(uint status)
{
switch (status)
{
case 0: return "";
case 1: return "HOT";
case 2: return "NEW";
case 3: return "RECOMMENDED";
case 4: return "10% OFF";
case 5: return "20% OFF";
case 6: return "30% OFF";
case 7: return "40% OFF";
case 8: return "50% OFF";
case 9: return "60% OFF";
case 10: return "70% OFF";
case 11: return "80% OFF";
case 12: return "90% OFF";
case 13: return "SOLD OUT";
default: return "";
}
}
void UpdateGiftInfo()
{
if (itemGiftText != null)
{
if (currentItem.idGift > 0)
{
itemGiftText.text = $"Gift: {currentItem.giftNum}x (ID: {currentItem.idGift})";
itemGiftText.gameObject.SetActive(true);
}
else
{
itemGiftText.gameObject.SetActive(false);
}
}
}
void LoadItemIcon(Image iconImage, string itemIcon)
{
Debug.Log($"[ShopDetailPanel] LoadItemIcon called with itemIcon: '{itemIcon}'");
if (string.IsNullOrEmpty(itemIcon))
{
Debug.LogWarning("[ShopDetailPanel] Item icon path is null or empty");
return;
}
// Extract filename from path (e.g., "surfaces/.../... .dds" -> "... .dds")
string fileName = ExtractFileNameFromPath(itemIcon);
Debug.Log($"[ShopDetailPanel] Extracted filename: '{fileName}' from path: '{itemIcon}'");
// Load sprite from DDSAtlas using the same system as inventory items
Sprite iconSprite = LoadSpriteFromDDSAtlas(fileName);
if (iconSprite != null)
{
iconImage.sprite = iconSprite;
Debug.Log($"[ShopDetailPanel] Successfully loaded icon: {fileName}");
}
else
{
Debug.LogWarning($"[ShopDetailPanel] Failed to load icon from DDSAtlas: {fileName}");
iconImage.sprite = null;
}
}
private string ExtractFileNameFromPath(string iconPath)
{
if (string.IsNullOrEmpty(iconPath))
return string.Empty;
try
{
// Replace backslashes with forward slashes for consistency
string normalizedPath = iconPath.Replace('\\', '/');
// Get the filename from the path
string fileName = System.IO.Path.GetFileName(normalizedPath);
if (string.IsNullOrEmpty(fileName))
fileName = normalizedPath;
// Remove extension (.dds/.tga/.png) to get the sprite name
string spriteName = System.IO.Path.GetFileNameWithoutExtension(fileName);
if (string.IsNullOrEmpty(spriteName))
spriteName = fileName;
return spriteName.Trim();
}
catch (System.Exception ex)
{
Debug.LogError($"Error extracting filename from path '{iconPath}': {ex.Message}");
return string.Empty;
}
}
private Sprite LoadSpriteFromDDSAtlas(string spriteName)
{
Debug.Log($"[ShopDetailPanel] LoadSpriteFromDDSAtlas called with spriteName: '{spriteName}'");
if (string.IsNullOrEmpty(spriteName))
{
Debug.LogWarning("[ShopDetailPanel] Sprite name is null or empty");
return null;
}
try
{
// Load the DDSAtlas sprites if not already loaded
var atlasSprites = UnityEngine.Resources.LoadAll<Sprite>("UI/MallItemImg/DDSAtlas");
Debug.Log($"[ShopDetailPanel] Loaded {atlasSprites?.Length ?? 0} sprites from Resources/UI/MallItemImg/DDSAtlas");
if (atlasSprites == null || atlasSprites.Length == 0)
{
Debug.LogWarning("[ShopDetailPanel] Failed to load DDSAtlas sprites from Resources/UI/MallItemImg/DDSAtlas");
return null;
}
// Log first few sprite names for debugging
for (int i = 0; i < Mathf.Min(5, atlasSprites.Length); i++)
{
if (atlasSprites[i] != null)
{
Debug.Log($"[ShopDetailPanel] Atlas sprite {i}: '{atlasSprites[i].name}'");
}
}
// Try to find sprite by exact name match (case insensitive)
foreach (var sprite in atlasSprites)
{
if (sprite != null && string.Equals(sprite.name, spriteName, System.StringComparison.OrdinalIgnoreCase))
{
Debug.Log($"[ShopDetailPanel] Found exact match for sprite: '{spriteName}'");
return sprite;
}
}
// Try lowercase/uppercase variants as fallback
foreach (var sprite in atlasSprites)
{
if (sprite != null && (string.Equals(sprite.name, spriteName.ToLowerInvariant(), System.StringComparison.OrdinalIgnoreCase) ||
string.Equals(sprite.name, spriteName.ToUpperInvariant(), System.StringComparison.OrdinalIgnoreCase)))
{
Debug.Log($"[ShopDetailPanel] Found case variant match for sprite: '{spriteName}'");
return sprite;
}
}
Debug.LogWarning($"[ShopDetailPanel] Sprite '{spriteName}' not found in DDSAtlas. Available sprites: {string.Join(", ", System.Array.ConvertAll(atlasSprites, s => s?.name ?? "null"))}");
return null;
}
catch (System.Exception ex)
{
Debug.LogError($"[ShopDetailPanel] Error loading sprite '{spriteName}' from DDSAtlas: {ex.Message}");
return null;
}
}
void OnBuyOptionSelected(int optionIndex)
{
if (currentItem.buy == null || optionIndex >= currentItem.buy.Length)
return;
var selectedOption = currentItem.buy[optionIndex];
if (selectedOption.price > 0 && selectedOption.status != 13) // Not sold out
{
// TODO: Implement purchase with specific buy option
Debug.Log($"Selected buy option {optionIndex}: Price={selectedOption.price}, Status={selectedOption.status}");
// Update main price display
if (itemPriceText != null)
itemPriceText.text = $"Price: {selectedOption.price}";
}
}
void OnBuyClicked()
{
// TODO: Implement purchase logic
Debug.Log($"Attempting to buy item: ID {currentItem.id} (Index: {currentItem.itemIndex})");
UnityGameSession.Instance.RequestMallShopping(1, Convert.ToInt32(currentItem.id), currentItem.itemIndex, 0);
// Close panel after purchase attempt
OnCloseClicked();
}
void OnCloseClicked()
{
gameObject.SetActive(false);
}
void OnDestroy()
{
// Clean up event listeners
if (buyButton != null)
buyButton.onClick.RemoveListener(OnBuyClicked);
if (closeButton != null)
closeButton.onClick.RemoveListener(OnCloseClicked);
for (int i = 0; i < buyOptionButtons.Length; i++)
{
if (buyOptionButtons[i] != null)
{
int optionIndex = i; // Capture for closure
buyOptionButtons[i].onClick.RemoveListener(() => OnBuyOptionSelected(optionIndex));
}
}
}
}