348 lines
10 KiB
C#
348 lines
10 KiB
C#
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using UnityEngine.UI;
|
|
using TMPro;
|
|
|
|
public class ShopUIManager : MonoBehaviour
|
|
{
|
|
[Header("Shop Data")]
|
|
public GShopLoader shopLoader;
|
|
|
|
[Header("UI Panels")]
|
|
public GameObject shopMainPanel;
|
|
public GameObject shopDetailPanel;
|
|
|
|
[Header("Item Display")]
|
|
public Transform itemContainer; // Parent for item panels
|
|
public GameObject itemPanelPrefab; // Prefab for individual item panels
|
|
|
|
[Header("Object Pooling")]
|
|
public ItemPanelPool itemPanelPool; // Object pool for item panels
|
|
public bool useObjectPooling = true;
|
|
|
|
[Header("Category Buttons")]
|
|
public Button[] categoryButtons; // 6 buttons for categories
|
|
|
|
[Header("Detail Panel Components")]
|
|
public TextMeshProUGUI detailItemName;
|
|
public TextMeshProUGUI detailItemDescription;
|
|
public Image detailItemIcon;
|
|
public TextMeshProUGUI detailItemPrice;
|
|
public TextMeshProUGUI detailItemQuantity;
|
|
public Button buyButton;
|
|
public Button closeDetailButton;
|
|
|
|
[Header("Main Panel Components")]
|
|
public Button closeShopButton;
|
|
|
|
private List<GameObject> currentItemPanels = new List<GameObject>();
|
|
private GShopItem selectedItem;
|
|
private int currentCategory = 0; // 0-5 for the 6 merged categories
|
|
|
|
void Start()
|
|
{
|
|
InitializeUI();
|
|
SetupEventListeners();
|
|
InitializePool();
|
|
}
|
|
|
|
void InitializePool()
|
|
{
|
|
if (useObjectPooling && itemPanelPool == null)
|
|
{
|
|
// Auto-create pool if not assigned
|
|
GameObject poolObj = new GameObject("ItemPanelPool");
|
|
poolObj.transform.SetParent(transform);
|
|
itemPanelPool = poolObj.AddComponent<ItemPanelPool>();
|
|
itemPanelPool.itemPanelPrefab = itemPanelPrefab;
|
|
}
|
|
}
|
|
|
|
void InitializeUI()
|
|
{
|
|
// Initially hide panels
|
|
if (shopMainPanel != null)
|
|
shopMainPanel.SetActive(false);
|
|
if (shopDetailPanel != null)
|
|
shopDetailPanel.SetActive(false);
|
|
}
|
|
|
|
void SetupEventListeners()
|
|
{
|
|
// Setup category buttons
|
|
for (int i = 0; i < categoryButtons.Length && i < 6; i++)
|
|
{
|
|
int categoryIndex = i; // Capture for closure
|
|
categoryButtons[i].onClick.AddListener(() => OnCategorySelected(categoryIndex));
|
|
}
|
|
|
|
// Setup detail panel buttons
|
|
if (buyButton != null)
|
|
buyButton.onClick.AddListener(OnBuyItem);
|
|
if (closeDetailButton != null)
|
|
closeDetailButton.onClick.AddListener(CloseDetailPanel);
|
|
|
|
// Setup main panel close button
|
|
if (closeShopButton != null)
|
|
closeShopButton.onClick.AddListener(CloseShop);
|
|
}
|
|
|
|
public void OpenShop()
|
|
{
|
|
if (shopMainPanel != null)
|
|
{
|
|
shopMainPanel.SetActive(true);
|
|
RefreshShopDisplay();
|
|
}
|
|
}
|
|
|
|
public void CloseShop()
|
|
{
|
|
if (shopMainPanel != null)
|
|
shopMainPanel.SetActive(false);
|
|
if (shopDetailPanel != null)
|
|
shopDetailPanel.SetActive(false);
|
|
}
|
|
|
|
void OnCategorySelected(int categoryIndex)
|
|
{
|
|
if (categoryIndex == currentCategory)
|
|
return;
|
|
|
|
float startTime = Time.realtimeSinceStartup;
|
|
|
|
currentCategory = categoryIndex;
|
|
RefreshShopDisplay();
|
|
|
|
// Update button states
|
|
for (int i = 0; i < categoryButtons.Length; i++)
|
|
{
|
|
if (categoryButtons[i] != null)
|
|
{
|
|
categoryButtons[i].interactable = (i != categoryIndex);
|
|
}
|
|
}
|
|
|
|
// Log performance
|
|
float switchTime = Time.realtimeSinceStartup - startTime;
|
|
|
|
Debug.Log($"Category switch to {categoryIndex} completed in {switchTime * 1000f:F2}ms");
|
|
}
|
|
|
|
public void RefreshShopDisplay()
|
|
{
|
|
// Return all current panels to pool
|
|
ReturnAllPanelsToPool();
|
|
|
|
if (shopLoader == null || shopLoader.primaryShop == null)
|
|
{
|
|
Debug.LogWarning("ShopLoader or primary shop data not available");
|
|
return;
|
|
}
|
|
|
|
// Get items for current category
|
|
List<GShopItem> categoryItems = GetItemsForCategory(currentCategory);
|
|
|
|
// Create item panels using pooling
|
|
foreach (GShopItem item in categoryItems)
|
|
{
|
|
CreateItemPanelFromPool(item);
|
|
}
|
|
}
|
|
|
|
List<GShopItem> GetItemsForCategory(int categoryIndex)
|
|
{
|
|
List<GShopItem> items = new List<GShopItem>();
|
|
|
|
if (shopLoader.primaryShop.items == null)
|
|
return items;
|
|
|
|
foreach (GShopItem item in shopLoader.primaryShop.items)
|
|
{
|
|
if (IsItemInCategory(item, categoryIndex))
|
|
{
|
|
items.Add(item);
|
|
}
|
|
}
|
|
|
|
return items;
|
|
}
|
|
|
|
bool IsItemInCategory(GShopItem item, int categoryIndex)
|
|
{
|
|
// Category mapping: 0=1, 1=2, 2=3+4+5, 3=6, 4=7, 5=8
|
|
switch (categoryIndex)
|
|
{
|
|
case 0: return item.mainType == 0; // Category 1
|
|
case 1: return item.mainType == 1; // Category 2
|
|
case 2: return item.mainType >= 2 && item.mainType <= 4; // Categories 3, 4, 5 merged
|
|
case 3: return item.mainType == 5; // Category 6
|
|
case 4: return item.mainType == 6; // Category 7
|
|
case 5: return item.mainType == 7; // Category 8
|
|
default: return false;
|
|
}
|
|
}
|
|
|
|
void CreateItemPanelFromPool(GShopItem item)
|
|
{
|
|
GameObject itemPanel = null;
|
|
|
|
if (useObjectPooling && itemPanelPool != null)
|
|
{
|
|
// Get panel from pool
|
|
itemPanel = itemPanelPool.GetPanel();
|
|
}
|
|
else
|
|
{
|
|
// Fallback to instantiate if pooling disabled
|
|
if (itemPanelPrefab != null && itemContainer != null)
|
|
{
|
|
itemPanel = Instantiate(itemPanelPrefab, itemContainer);
|
|
}
|
|
}
|
|
|
|
if (itemPanel != null && itemContainer != null)
|
|
{
|
|
// Set parent and position
|
|
itemPanel.transform.SetParent(itemContainer);
|
|
itemPanel.transform.localScale = Vector3.one;
|
|
|
|
// Setup the panel
|
|
ShopItemPanel itemPanelScript = itemPanel.GetComponent<ShopItemPanel>();
|
|
if (itemPanelScript != null)
|
|
{
|
|
itemPanelScript.SetupItem(item, this);
|
|
}
|
|
|
|
currentItemPanels.Add(itemPanel);
|
|
}
|
|
}
|
|
|
|
void ReturnAllPanelsToPool()
|
|
{
|
|
if (useObjectPooling && itemPanelPool != null)
|
|
{
|
|
// Return all panels to pool
|
|
foreach (GameObject panel in currentItemPanels)
|
|
{
|
|
if (panel != null)
|
|
{
|
|
itemPanelPool.ReturnPanel(panel);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Destroy panels if not using pooling
|
|
foreach (GameObject panel in currentItemPanels)
|
|
{
|
|
if (panel != null)
|
|
Destroy(panel);
|
|
}
|
|
}
|
|
|
|
currentItemPanels.Clear();
|
|
}
|
|
|
|
public void ShowItemDetail(GShopItem item)
|
|
{
|
|
selectedItem = item;
|
|
Debug.Log($"$ Local ID of selected item: {item.localId}");
|
|
if (shopDetailPanel != null)
|
|
{
|
|
shopDetailPanel.SetActive(true);
|
|
|
|
// Get the ShopDetailPanel component and call its SetupDetailPanel method
|
|
ShopDetailPanel detailPanelScript = shopDetailPanel.GetComponent<ShopDetailPanel>();
|
|
if (detailPanelScript != null)
|
|
{
|
|
detailPanelScript.SetupDetailPanel(item, this);
|
|
}
|
|
else
|
|
{
|
|
Debug.LogError("ShopDetailPanel script not found on shopDetailPanel GameObject!");
|
|
// Fallback to the old method
|
|
UpdateDetailPanel(item);
|
|
}
|
|
}
|
|
}
|
|
|
|
void UpdateDetailPanel(GShopItem item)
|
|
{
|
|
if (detailItemName != null)
|
|
detailItemName.text = item.name;
|
|
|
|
if (detailItemDescription != null)
|
|
detailItemDescription.text = item.desc;
|
|
|
|
if (detailItemQuantity != null)
|
|
detailItemQuantity.text = $"Quantity: {item.num}";
|
|
|
|
// Find the best buy option (first non-zero price)
|
|
uint bestPrice = 0;
|
|
for (int i = 0; i < item.buy.Length; i++)
|
|
{
|
|
if (item.buy[i].price > 0)
|
|
{
|
|
bestPrice = item.buy[i].price;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (detailItemPrice != null)
|
|
detailItemPrice.text = $"Price: {bestPrice}";
|
|
|
|
// Load icon based on item name (you'll need to implement icon loading)
|
|
if (detailItemIcon != null)
|
|
{
|
|
LoadItemIcon(detailItemIcon, item.name);
|
|
}
|
|
}
|
|
|
|
void LoadItemIcon(Image iconImage, string itemName)
|
|
{
|
|
// TODO: Implement icon loading based on item name
|
|
// This is where you'd load the appropriate icon sprite
|
|
// For now, we'll leave it empty for you to implement
|
|
Debug.Log($"Loading icon for item: {itemName}");
|
|
}
|
|
|
|
void CloseDetailPanel()
|
|
{
|
|
if (shopDetailPanel != null)
|
|
shopDetailPanel.SetActive(false);
|
|
}
|
|
|
|
void OnBuyItem()
|
|
{
|
|
if (selectedItem.id == 0)
|
|
return;
|
|
|
|
// TODO: Implement purchase logic
|
|
Debug.Log($"Attempting to buy item: {selectedItem.name} (ID: {selectedItem.id})");
|
|
|
|
// Close detail panel after purchase attempt
|
|
CloseDetailPanel();
|
|
}
|
|
|
|
void OnDestroy()
|
|
{
|
|
// Clean up pooled objects
|
|
if (useObjectPooling && itemPanelPool != null)
|
|
{
|
|
itemPanelPool.ReturnAllPanels();
|
|
}
|
|
else
|
|
{
|
|
// Fallback cleanup
|
|
foreach (GameObject panel in currentItemPanels)
|
|
{
|
|
if (panel != null)
|
|
Destroy(panel);
|
|
}
|
|
}
|
|
|
|
currentItemPanels.Clear();
|
|
}
|
|
}
|