(Feat) Add Storage Chests + Item Details Panel

Coffres : AStorageContainer, un UInventoryComponent configure en conteneur,
affiche comme panneau de WBP_InventoryScreen plutot que dans un ecran a lui.
Deplacement unifie par UInventoryComponent::TransferSlot / TransferAllTo.

Panneau de detail : UItemDetailsWidget, pose DANS WBP_Inventory a droite de la
grille. Icone, nom, separation, description, barre d'usure. Il recoit un couple
(inventaire, index) et s'abonne a OnInventoryChanged, donc une charge consommee
sous le curseur se voit.

Une case ne connait plus sa grille : elle diffuse OnHoverChanged. La barre
rapide s'y abonne aussi et relaie par le PlayerController, seul a posseder a la
fois le HUD et l'ecran. Le panneau efface la case qu'on QUITTE et non lui-meme,
sinon passer de la barre a la grille viderait ce qui vient d'etre affiche.

L'ecran allume et eteint le panneau (SetItemDetailsEnabled) : WBP_Inventory
etant instancie deux fois en mode coffre, une case a cocher par instance serait
un bug qui attend qu'on oublie de la decocher.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-01 22:51:24 +02:00
parent d50ef564ba
commit 41d6e6a7f3
50 changed files with 2947 additions and 167 deletions
@@ -8,7 +8,6 @@
#include "Components/TextBlock.h"
#include "Components/Widget.h"
#include "InventoryDragDropOperation.h"
#include "InventoryWidget.h"
#include "ItemDataAsset.h"
void UInventorySlotWidget::NativeConstruct()
@@ -53,31 +52,29 @@ void UInventorySlotWidget::ConfigureAsDragVisual()
SetVisibility(ESlateVisibility::HitTestInvisible);
}
void UInventorySlotWidget::InitSlot(UInventoryComponent* InInventory, int32 InSlotIndex, UInventoryWidget* InOwningGrid)
void UInventorySlotWidget::InitSlot(UInventoryComponent* InInventory, int32 InSlotIndex)
{
OwningInventory = InInventory;
SlotIndex = InSlotIndex;
OwningGrid = InOwningGrid;
}
void UInventorySlotWidget::SetQuickTransferTarget(UInventoryComponent* InTarget)
{
QuickTransferTarget = InTarget;
}
void UInventorySlotWidget::NativeOnMouseEnter(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent)
{
Super::NativeOnMouseEnter(InGeometry, InMouseEvent);
if (OwningGrid.IsValid())
{
OwningGrid->NotifySlotHovered(SlotIndex, true);
}
OnHoverChanged.Broadcast(SlotIndex, true);
}
void UInventorySlotWidget::NativeOnMouseLeave(const FPointerEvent& InMouseEvent)
{
Super::NativeOnMouseLeave(InMouseEvent);
if (OwningGrid.IsValid())
{
OwningGrid->NotifySlotHovered(SlotIndex, false);
}
OnHoverChanged.Broadcast(SlotIndex, false);
}
void UInventorySlotWidget::SetSlot(const FInventorySlot& InSlot)
@@ -142,6 +139,18 @@ void UInventorySlotWidget::SetSlot(const FInventorySlot& InSlot)
FReply UInventorySlotWidget::NativeOnMouseButtonDown(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent)
{
// Clic droit : transfert rapide vers l'inventaire d'en face, quand il y en
// a un. Traite avant le glisser pour que le bouton droit ne demarre jamais
// de DetectDrag -- ce qui laisserait une operation orpheline en cours.
if (!CachedSlot.IsEmpty() && InMouseEvent.GetEffectingButton() == EKeys::RightMouseButton)
{
if (QuickTransferTarget.IsValid() && OwningInventory.IsValid() && SlotIndex != INDEX_NONE)
{
UInventoryComponent::QuickTransferSlot(OwningInventory.Get(), SlotIndex, QuickTransferTarget.Get());
return FReply::Handled();
}
}
if (CachedSlot.IsEmpty() || !InMouseEvent.IsMouseButtonDown(EKeys::LeftMouseButton))
{
return Super::NativeOnMouseButtonDown(InGeometry, InMouseEvent);
@@ -225,15 +234,12 @@ bool UInventorySlotWidget::NativeOnDrop(const FGeometry& InGeometry, const FDrag
return Super::NativeOnDrop(InGeometry, InDragDropEvent, InOperation);
}
// On refuse les transferts entre deux inventaires differents : ce sera le
// jour ou tu ajouteras les coffres, avec ses propres regles.
if (!Payload->SourceInventory.IsValid() || Payload->SourceInventory != OwningInventory)
{
return false;
}
// MoveItemQuantity diffuse OnInventoryChanged, donc la grille se rafraichit
// seule. Une quantite egale a la pile entiere retombe sur le comportement
// complet, echange compris.
return OwningInventory->MoveItemQuantity(Payload->SourceSlotIndex, SlotIndex, Payload->Quantity);
// TransferSlot diffuse OnInventoryChanged des DEUX cotes, donc les grilles
// se rafraichissent seules. Elle gere indifferemment le meme inventaire et
// deux inventaires distincts : glisser vers un coffre, vers la barre rapide
// ou vers la case d'a cote emprunte exactement le meme chemin.
return UInventoryComponent::TransferSlot(
Payload->SourceInventory.Get(), Payload->SourceSlotIndex,
OwningInventory.Get(), SlotIndex,
Payload->Quantity);
}