using System; using TMPro; using UnityEngine; using UnityEngine.UI; namespace NotificationSamples.Demo { /// /// UI list item for buying an inventory item. /// public class BuyInventoryItem : MonoBehaviour { [SerializeField] protected TextMeshProUGUI titleLabel; [SerializeField] protected TextMeshProUGUI timeLabel; [SerializeField] protected TextMeshProUGUI costLabel; [SerializeField] protected Image icon; [SerializeField] protected Button buyButton; [SerializeField] protected Image progressImage; // Fired when the buy button is pressed. private Action bought; // When the last bought item will be delivered. private DateTime? deliveryTime; // Initial time remaining for the delivery of the last bought item. private float initialTimeRemaining; // The last currency received from the game controller. private int currency; /// /// Title to show in the notification. /// public string Title => titleLabel.text; /// /// Description to show in the notification. /// public string Description { get; private set; } /// /// Fire notification after this amount of minutes. /// public float Minutes { get; set; } /// /// The item's cost. /// public int Cost { get; set; } /// /// The item data linked to this UI item. /// public InventoryItemData ItemData { get; private set; } /// /// Initialise the item with the specified settings. /// public void Initialise(InventoryItemData itemData, Action buyAction) { ItemData = itemData; titleLabel.text = itemData.Title; Minutes = itemData.InitialCreationTime; Description = itemData.Description; Cost = itemData.InitialCost; icon.sprite = itemData.Icon; bought = buyAction; deliveryTime = null; progressImage.fillAmount = 0.0f; UpdateControls(); } /// /// Called when the buy button is clicked. /// public void OnBuy() { bought?.Invoke(this); } /// /// Called when buying an item was successful. /// public void OnBuySuccess(DateTime boughtDeliveryTime) { deliveryTime = boughtDeliveryTime; initialTimeRemaining = GetTimeRemaining(); buyButton.interactable = false; UpdateControls(); } /// /// Update UI controls. /// public void UpdateControls() { if (deliveryTime != null) { // Do not update the labels (i.e. show the old values until the item is delivered). return; } costLabel.text = Cost.ToString("N0"); timeLabel.text = $"Takes {Minutes:F1} minute(s)"; } /// /// Called when the game's currency total changed. /// public void OnCurrencyChanged(int newCurrency) { currency = newCurrency; UpdateBuyButton(); } /// /// Called when an item was delivered. /// public void OnDeliveredItem(InventoryItemData itemData) { if (itemData == ItemData) { UpdateBuyButton(); } } // Time remaining until the last bought item is delivered. private float GetTimeRemaining() { if (deliveryTime == null) { return 0.0f; } TimeSpan timeSpan = deliveryTime.Value - DateTime.Now; return Mathf.Max((float)timeSpan.TotalSeconds, 0.0f); } private void Update() { UpdateProgress(); } // Determine if the buy button should be interactable. private void UpdateBuyButton() { buyButton.interactable = currency >= Cost && GetTimeRemaining() <= 0.0f; } // Update an item's delivery progress, and update the progress bar. private void UpdateProgress() { if (deliveryTime == null) { return; } float timeRemaining = GetTimeRemaining(); if (timeRemaining > 0.0f) { progressImage.fillAmount = 1.0f - Mathf.Clamp01(timeRemaining / initialTimeRemaining); return; } progressImage.fillAmount = 0.0f; deliveryTime = null; UpdateControls(); } } }