NLDClient-yudde/ProjectNLD/Assets/Code/Scripts/Gameplay/UI/UI_BuyEnergyController.cs

509 lines
15 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/****************************************************
文件Assets/Code/Scripts/Gameplay/UI/UI_BuyEnergyController.cs
作者yuntao-Hu
时间2024/5
描述补充体力UI界面
说明:
*****************************************************/
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.UIElements;
using Button = UnityEngine.UI.Button;
using Image = UnityEngine.UI.Image;
using Toggle = UnityEngine.UI.Toggle;
using ScrollView = PhxhSDK.PhxhScrollView;
using Framework;
using System;
using Gameplay;
using Cysharp.Threading.Tasks;
using UnityEngine.Events;
using System.Threading;
using static UnityEngine.Rendering.DebugUI;
using Gameplay.Net;
using Gameplay.Common;
using cfg.ActorCfg;
using PhxhSDK;
using LeanCloud.Realtime.Internal.Protocol;
using static UI_BuyEnergyController;
public class UI_BuyEnergyController : UIWindow
{
#region enum
/// <summary>
/// 补充体力方式 ( 与窗口内顺序对应 )
/// </summary>
public enum RechargeMethod
{
Recharge_byItem,
Recharge_byCurrency
}//TODO 考虑后续以json方式存储补充体力方式信息
#endregion
#region Temporary_Constant
private const int DEFAULT_USAGE_AMOUNT = 1;//默认使用数目,使用时的最小量
/// <summary>
/// 体力药物品ID
/// </summary>
private const int ENERGY_ITEM_ID = 8;//TODO 体力药物品ID考虑加入globalconfig
private readonly int[] itemIDs = { ENERGY_ITEM_ID, GLConfig.Inst.data.DiamondItemId };//TODO 考虑后续将补充体力方式改为json配置后需要调整传参
#endregion
#region UI GameObj
//UI GameObj
///Auto Gen Start///
public Image Image_BG;
public TMP_Text Text_Title;
public TMP_Text Text_Currency;
public Button Button_Close;
public Image Image_DetailBG;
public TMP_Text Text_Detail;
public Image Image_BtnBar;
public TMP_InputField Text_NumInputField;
public Button Button_Min;
public Image Image_Min;
public TMP_Text Text_Min;
public Button Button_Minus;
public Button Button_Max;
public Image Image_Max;
public TMP_Text Text_Max;
public Button Button_Plus;
public Image Image_ItemBG;
public Image Image_ItemRect;
public Image Image_MovePoint;
public Image Image_Arrow;
public TMP_Text Text_NowCount;
public TMP_Text Text_AfterCount;
public Button Button_Return;
public TMP_Text Text_Return;
public Button Button_Buy;
public TMP_Text Text_Buy;
///Auto Gen End///
private RawImage rawImageGaussianBlurMask;
#endregion
#region class
class MethodButtonObj: UIGameObjectWrapper
{
private GameObject chosenCircle;
private TextMeshProUGUI itemAmountText;
private Image buttonIcon;
//TODO 考虑后续将补充体力方式改为json配置后可能需要调整传参
public MethodButtonObj(GameObject root, int i, int itemID, bool isScaleShow = true) : base(root, i, isScaleShow)
{
chosenCircle = FindObj("ChooseRect");
itemAmountText = GetComponent<TextMeshProUGUI>("ImageCount/TextCount");
buttonIcon = GetComponent<Image>("ItemIcon");
RefreshIcon(itemID);
}
public void BindListener(Action callback)
{
BindButton(GameObject.GetComponent<Button>(), callback);
}
async void RefreshIcon(int itemID)
{
var spritePath = CommonUtils.GetItemPath(itemID);
buttonIcon.sprite = await LoadAssetAsync<Sprite>(spritePath);
}
public void SetChosen(bool isChosen)
{
chosenCircle.SetActive(isChosen);
}
public void SetItemAmount(uint amount)
{
itemAmountText.text = amount.ToString();
}
public void SetActive(bool isActive)
{
GameObject.SetActive(isActive);
}
}
#endregion
#region Button_Listener
public void OnClickClose()
{
CloseWindow();
}
public void OnMinClick()
{
SetUsageAmountAndRefresh(DEFAULT_USAGE_AMOUNT);
}
public void OnMinusClick()
{
if (m_UsageAmount > DEFAULT_USAGE_AMOUNT)
{
m_UsageAmount--;
SetUsageAmountAndRefresh(m_UsageAmount);
}
}
public void OnMaxClick()
{
SetUsageAmountAndRefresh(MaxConsumeAmountWithoutConvert());
}
public void OnPlusClick()
{
if (m_UsageAmount < MaxConsumeAmountWithoutConvert())
{
m_UsageAmount++;
SetUsageAmountAndRefresh(m_UsageAmount);
}
}
public void OnReturnClick()
{
CloseWindow();
}
public void OnBuyClick()
{
if (m_UsageAmount <= MaxConsumeAmountWithoutConvert() && m_UsageAmount > 0)
{
EnergyManager.Instance.BuyEnergy(itemIDs[(int)m_RechargeMethod], (uint)m_UsageAmount);
CloseWindow();
}
else
{
#if UNITY_EDITOR
DebugUtil.Log("购买体力数目超出可选择范围!");
#endif
CommonUtils.ShowMessageTips(CommonUtils.GetLocalizeText("BuyEnergy_failed"));
}
}
#endregion
private List<MethodButtonObj> rechargeMethodButtons = new List<MethodButtonObj>();
private Dictionary<RechargeMethod, uint> storageItemCount = new Dictionary<RechargeMethod, uint>();
private uint m_CurrEnergy;
private int m_UsageAmount;
private RechargeMethod m_RechargeMethod;
/// <summary>
/// 打开购买体力界面
/// </summary>
public static async UniTask<UIWindow> Open()
{
CommonUtils.CaptureScreenshot();
return await UIManager.Instance.OpenWindow(UINameConst.UI_BuyEnergy);
}
// deal with input data
public override void PreLoad(object data = null)
{
}
// Use this for initialization
public override void OnInit()
{
//bind UI GameObj
UI_BuyEnergyBinder.GetComponents(this);
rawImageGaussianBlurMask = GetComponent<RawImage>("GaussianBlurMask");
rawImageGaussianBlurMask.texture = CommonUtils.screenTexture;
GetStorageFromServer();
BindButton();
BindInputFieldListener();
InitEnergyRefreshTimer();
}
/// <summary>
/// 根据体力刷新情况即时更新界面内体力数目显示
/// </summary>
void InitEnergyRefreshTimer()
{
m_CurrEnergy = EnergyManager.Instance.GetNowEnergy();
EventManager.Instance.Register<uint>(EventManager.EventName.ItemChange, OnItemChange);
}
private void OnItemChange(uint itemId)
{
if ((int)itemId != GLConfig.Inst.data.EnergyPointID)
return;
m_CurrEnergy = EnergyManager.Instance.GetNowEnergy();
int consume = EnergyManager.Instance.GetConvertConsumes(itemIDs[(int)m_RechargeMethod], m_UsageAmount);
int recharge = EnergyManager.Instance.GetConvertRecharges(itemIDs[(int)m_RechargeMethod], m_UsageAmount);
RefreshDetailText(consume, recharge);
}
void BindInputFieldListener()
{
Text_NumInputField.onEndEdit.AddListener(SnapInputToStep);
}
/// <summary>
/// 由于货币输入框输入的数值不一定是阶梯值,需要对输入的数值做向下取整到阶梯值
/// </summary>
/// <param name="inputAmount"></param>
void SnapInputToStep(string inputAmount)
{
int parsedValue;
if (int.TryParse(inputAmount, out parsedValue))
{
// 对输入的数据做向下取整到阶梯值
int snappedValue = (int)(parsedValue / EnergyManager.Instance.GetConvertConsumes(itemIDs[(int)m_RechargeMethod]));
if (snappedValue < DEFAULT_USAGE_AMOUNT)
{
snappedValue = DEFAULT_USAGE_AMOUNT;
}
if (snappedValue > MaxConsumeAmountWithoutConvert())
{
snappedValue = MaxConsumeAmountWithoutConvert();
}
m_UsageAmount = snappedValue;
SetUsageAmountAndRefresh(m_UsageAmount);
}
else
{
DebugUtil.LogError("错误输入内容,已舍弃");
SetUsageAmountAndRefresh(m_UsageAmount);
}
}
/// <summary>
/// 注意先初始化storageItemCount字典再绑定按钮
/// </summary>
void BindButton()
{
BindMethodButton();
Button_Buy.onClick.AddListener(OnBuyClick);
Button_Close.onClick.AddListener(OnClickClose);
Button_Min.onClick.AddListener(OnMinClick);
Button_Minus.onClick.AddListener(OnMinusClick);
Button_Max.onClick.AddListener(OnMaxClick);
Button_Plus.onClick.AddListener(OnPlusClick);
Button_Return.onClick.AddListener(OnReturnClick);
}
/// <summary>
/// 注意先初始化storageItemCount字典再绑定补充体力方式选择按钮
/// </summary>
void BindMethodButton()
{
//体力补充方式选择按钮
ScrollView methodButtonView = Image_ItemBG.GetComponentInChildren<ScrollView>();
if (methodButtonView == null)
{
DebugUtil.LogError("体力补充方式按钮列表获取失败!");
return;
}
else
{
GameObject buttonPrefab = null;
foreach (Transform buttonGameObj in methodButtonView.content)
{
buttonGameObj.gameObject.SetActive(false);
if (buttonGameObj.GetComponent<Button>() != null)
buttonPrefab = buttonGameObj.gameObject;
}
for (int i = 0; i < Enum.GetValues(typeof(RechargeMethod)).Length; i++)
{
var methodButton = new MethodButtonObj(buttonPrefab, i, itemIDs[i]);
methodButton.SetActive(true);
rechargeMethodButtons.Add(methodButton);
RechargeMethod method = (RechargeMethod)i;
methodButton.BindListener(() =>
{
if (method != m_RechargeMethod)
OnChooseMethod(method);
});
if (storageItemCount.ContainsKey(method))
methodButton.SetItemAmount(storageItemCount[method]);
else
DebugUtil.LogError("未找到" + method.ToString() + "对应的物品数目检查正确性或是否初始化storage字典");
}
}
}
//invoke when open window
protected override void OnShowWindow(object data = null)
{
//TODO 后续补充体力方式增加后,可能要考虑其他物品
if (isItemRemained(RechargeMethod.Recharge_byItem))
{
OnChooseMethod(RechargeMethod.Recharge_byItem);
}
else
{
HideMethodButton(RechargeMethod.Recharge_byItem);
OnChooseMethod(RechargeMethod.Recharge_byCurrency);
}
SetUsageAmountAndRefresh(amount: DEFAULT_USAGE_AMOUNT);
}
void HideMethodButton(RechargeMethod method)
{
if((int)method < rechargeMethodButtons.Count)
{
rechargeMethodButtons[(int)method].SetActive(false);
}
else
{
DebugUtil.LogError("不存在" + method.ToString() + "对应的按钮!");
}
}
//invoke when reload window
protected override void OnReloadWindow(object data = null)
{
}
//invoke when close window
protected override void OnHideWindow()
{
}
//invoke when destroy
public override void OnRelease()
{
foreach(var btn in rechargeMethodButtons)
{
btn.Dispose();
}
EventManager.Instance.Unregister<uint>(EventManager.EventName.ItemChange, OnItemChange);
base.OnRelease();
}
/// <summary>
/// 初始化补充体力物品数目
/// </summary>
void GetStorageFromServer()
{
//storageItemCount字典查找物品数目为后续扩展
uint m_ItemAmount = Actor.Instance.Item.GetItemCount(ENERGY_ITEM_ID);
if (!storageItemCount.ContainsKey(RechargeMethod.Recharge_byItem))
{
storageItemCount.Add(RechargeMethod.Recharge_byItem, m_ItemAmount);
}
uint m_CurrencyAmount = Actor.Instance.Item.GetItemCount(GLConfig.Inst.data.DiamondItemId);
if (!storageItemCount.ContainsKey(RechargeMethod.Recharge_byCurrency))
{
storageItemCount.Add(RechargeMethod.Recharge_byCurrency, m_CurrencyAmount);
}
}
/// <summary>
/// 体力药是否剩余(可用于判断初始化时的补充体力方式)
/// </summary>
/// <returns></returns>
bool isItemRemained(RechargeMethod method)
{
if (storageItemCount.ContainsKey(method))
return storageItemCount[method] > 0;
else
{
DebugUtil.LogError("未找到" + method.ToString() + "对应的物品数目检查正确性或是否初始化storage字典");
return false;
}
}
/// <summary>
/// 选中补充体力方式Button
/// </summary>
/// <param name="chosenMethod"></param>
void OnChooseMethod(RechargeMethod chosenMethod)
{
MethodButtonObj preChosenButton = rechargeMethodButtons[(int)m_RechargeMethod];
MethodButtonObj curChosenButton = rechargeMethodButtons[(int)chosenMethod];
m_RechargeMethod = chosenMethod;
preChosenButton.SetChosen(false);
curChosenButton.SetChosen(true);
//切换按钮后,重置界面内相关数目显示
SetUsageAmountAndRefresh(amount: DEFAULT_USAGE_AMOUNT);
}
/// <summary>
/// 获取当前选中状态下的最大消耗数目(实际数据需要乘比例转化)
/// </summary>
/// <returns></returns>
int MaxConsumeAmountWithoutConvert()
{
//道具数目限制
uint AmountInStorage = storageItemCount[m_RechargeMethod];
int maxConsumeRate = (int)(AmountInStorage / EnergyManager.Instance.GetConvertConsumes(itemIDs[(int)m_RechargeMethod]));
//体力上限限制
DataItem energyData = TableManager.Instance.Tables.Item.Get(GLConfig.Inst.data.EnergyPointID);
uint energyToMax = (uint)energyData.MaxCount - m_CurrEnergy;
int maxConsumeRateByEnergy = (int)(energyToMax / EnergyManager.Instance.GetConvertRecharges(itemIDs[(int)m_RechargeMethod]));
return Math.Min(maxConsumeRate, maxConsumeRateByEnergy);
}
/// <summary>
/// 设定使用数目,并刷新界面内相关数目显示
/// </summary>
/// <param name="amount"></param>
void SetUsageAmountAndRefresh(int amount)
{
m_UsageAmount = amount;
int consume = EnergyManager.Instance.GetConvertConsumes(itemIDs[(int)m_RechargeMethod], m_UsageAmount);
int recharge = EnergyManager.Instance.GetConvertRecharges(itemIDs[(int)m_RechargeMethod], m_UsageAmount);
RefreshDetailText(consume, recharge);
}
/// <summary>
/// 刷新文字显示
/// </summary>
/// <param name="consume">实际道具消耗显示数</param>
/// <param name="recharge">转化体力数量</param>
void RefreshDetailText(int consume,int recharge)
{
uint curEnergy = m_CurrEnergy;
Text_NumInputField.text = consume.ToString();
Text_NowCount.text = curEnergy.ToString();
Text_AfterCount.text = (curEnergy + recharge).ToString();
//TODO 配置对应消耗物的json数据
DataItem dataItem = TableManager.Instance.Tables.Item.Get(ENERGY_ITEM_ID);
DataItem diamond = TableManager.Instance.Tables.Item.Get(GLConfig.Inst.data.DiamondItemId);
string[] itemNames = { "个" + CommonUtils.GetLocalizeText(dataItem.NameLocal), CommonUtils.GetLocalizeText(diamond.NameLocal) };
Text_Detail.text = CommonUtils.GetLocalizeText("BuyEnergy_tips", consume, itemNames[(int)m_RechargeMethod], recharge);
}
}