(Feat) add crafting discovery + notification + inventory tool tips

This commit is contained in:
2026-07-09 17:44:52 +02:00
parent c6830fa7a4
commit faa061cced
454 changed files with 2445 additions and 229 deletions
@@ -19,6 +19,7 @@ namespace Ashwild.UI
private int totalQuantity;
private float hideTimer;
private bool isHiding;
private bool isDiscovery;
private Tweener fadeTween;
private Tweener slideTween;
@@ -30,6 +31,9 @@ namespace Ashwild.UI
// A notification is either a gain (+) or a loss (-); merging only happens within the same direction.
public bool IsGain => totalQuantity >= 0;
// A discovery notification (icon + name + "NEW" badge) never merges with a gain/loss one.
public bool IsDiscovery => isDiscovery;
public void Initialize(ItemData item, int signedQuantity, Color numberColor, float displayDuration, float slideInDuration, Ease slideInEase)
{
itemData = item;
@@ -49,6 +53,34 @@ namespace Ashwild.UI
fadeTween = canvasGroup.DOFade(1f, slideInDuration).SetEase(Ease.OutQuad);
}
/// <summary>
/// Sets up a discovery notification: an icon and name (of the unlocked recipe) with a fixed
/// badge (e.g. "NEW") in the number slot, tinted with the caller-chosen colour. It carries no
/// quantity and never merges, so it reads as a one-time "recipe unlocked" cue.
/// </summary>
public void InitializeDiscovery(Sprite icon, string displayName, string badgeText, Color badgeColor, float displayDuration, float slideInDuration)
{
itemData = null;
isDiscovery = true;
hideTimer = displayDuration;
isHiding = false;
if (iconImage != null)
iconImage.sprite = icon;
if (labelText != null)
labelText.text = displayName;
if (numberText != null)
{
numberText.text = badgeText;
numberText.color = badgeColor;
}
canvasGroup.alpha = 0f;
fadeTween = canvasGroup.DOFade(1f, slideInDuration).SetEase(Ease.OutQuad);
}
public void AddQuantity(int signedAmount, float displayDuration)
{
totalQuantity += signedAmount;
+33 -1
View File
@@ -30,6 +30,11 @@ namespace Ashwild.UI
[SerializeField] private Color gainColor = new Color(0.45f, 1f, 0.45f); // picked up / added
[SerializeField] private Color lossColor = new Color(1f, 0.45f, 0.45f); // dropped / consumed
[Header("Discovery")]
[Tooltip("Badge shown in the number slot when a new item/recipe is discovered.")]
[SerializeField] private string discoveryLabel = "NEW";
[SerializeField] private Color discoveryColor = new Color(1f, 0.85f, 0.3f);
private readonly List<NotificationItemUI> activeNotifications = new List<NotificationItemUI>();
private void OnEnable()
@@ -37,6 +42,7 @@ namespace Ashwild.UI
PlayerEvents.ItemAdded += OnItemAdded;
PlayerEvents.ItemDropped += OnItemDropped;
PlayerEvents.ItemConsumed += OnItemConsumed;
PlayerEvents.RecipeDiscovered += OnRecipeDiscovered;
PlayerEvents.FoodPlacedToCook += OnItemSpent;
PlayerEvents.FuelAdded += OnItemSpent;
}
@@ -46,6 +52,7 @@ namespace Ashwild.UI
PlayerEvents.ItemAdded -= OnItemAdded;
PlayerEvents.ItemDropped -= OnItemDropped;
PlayerEvents.ItemConsumed -= OnItemConsumed;
PlayerEvents.RecipeDiscovered -= OnRecipeDiscovered;
PlayerEvents.FoodPlacedToCook -= OnItemSpent;
PlayerEvents.FuelAdded -= OnItemSpent;
}
@@ -53,6 +60,7 @@ namespace Ashwild.UI
private void OnItemAdded(ItemData item, int quantity) => Push(item, quantity);
private void OnItemDropped(ItemData item, int quantity) => Push(item, -quantity);
private void OnItemConsumed(ItemData item) => Push(item, -1);
private void OnRecipeDiscovered(Sprite icon, string recipeName) => PushDiscovery(icon, recipeName);
// Food placed on a cooking station or fuel fed to it both leave the inventory by one.
private void OnItemSpent(ItemData item) => Push(item, -1);
@@ -69,7 +77,8 @@ namespace Ashwild.UI
// Merge only with a notification for the same item AND same direction
for (int i = 0; i < activeNotifications.Count; i++)
{
if (activeNotifications[i] != null && activeNotifications[i].ItemData == item
if (activeNotifications[i] != null && !activeNotifications[i].IsDiscovery
&& activeNotifications[i].ItemData == item
&& activeNotifications[i].IsGain == gain)
{
activeNotifications[i].AddQuantity(signedQuantity, displayDuration);
@@ -94,6 +103,29 @@ namespace Ashwild.UI
activeNotifications.Add(notification);
}
/// <summary>
/// Pushes a one-time "NEW" notification for a newly unlocked recipe: its result icon and name
/// with the configured badge in the discovery colour. Never merges with anything.
/// </summary>
private void PushDiscovery(Sprite icon, string recipeName)
{
activeNotifications.RemoveAll(n => n == null);
GameObject go = Instantiate(notificationPrefab, container);
NotificationItemUI notification = go.GetComponent<NotificationItemUI>();
float targetY = startOffsetY + activeNotifications.Count * (notificationHeight + spacing);
RectTransform rt = notification.RectTransform;
rt.anchoredPosition = new Vector2(0f, targetY - 30f);
notification.InitializeDiscovery(icon, recipeName, discoveryLabel, discoveryColor, displayDuration, slideInDuration);
rt.DOAnchorPosY(targetY, slideInDuration).SetEase(slideInEase);
activeNotifications.Add(notification);
}
private void LateUpdate()
{
// Clean up destroyed notifications and reposition remaining ones