Files

194 lines
4.8 KiB
C++

// Fill out your copyright notice in the Description page of Project Settings.
#include "HotbarWidget.h"
#include "Components/HorizontalBox.h"
#include "Components/HorizontalBoxSlot.h"
#include "FpsPlayer.h"
#include "GameFramework/PlayerController.h"
#include "InventoryComponent.h"
#include "InventorySlotWidget.h"
void UHotbarWidget::NativeConstruct()
{
Super::NativeConstruct();
BindToOwningPawn();
}
void UHotbarWidget::BindToOwningPawn()
{
UInventoryComponent* NewInventory = ResolveInventory();
if (BoundInventory.Get() == NewInventory)
{
return;
}
if (BoundInventory.IsValid())
{
BoundInventory->OnInventoryChanged.RemoveDynamic(this, &UHotbarWidget::HandleInventoryChanged);
BoundInventory->OnSelectedHotbarSlotChanged.RemoveDynamic(this, &UHotbarWidget::HandleSelectionChanged);
}
BoundInventory = NewInventory;
if (BoundInventory.IsValid())
{
BoundInventory->OnInventoryChanged.AddDynamic(this, &UHotbarWidget::HandleInventoryChanged);
BoundInventory->OnSelectedHotbarSlotChanged.AddDynamic(this, &UHotbarWidget::HandleSelectionChanged);
}
else
{
UE_LOG(LogTemp, Warning, TEXT("UHotbarWidget : aucun UInventoryComponent trouve sur le pawn possede."));
}
// Les cases memorisent l'ancien composant : on les recree.
for (UInventorySlotWidget* SlotWidget : SlotWidgets)
{
if (SlotWidget)
{
SlotWidget->RemoveFromParent();
}
}
SlotWidgets.Reset();
Refresh();
}
void UHotbarWidget::NativeDestruct()
{
if (BoundInventory.IsValid())
{
BoundInventory->OnInventoryChanged.RemoveDynamic(this, &UHotbarWidget::HandleInventoryChanged);
BoundInventory->OnSelectedHotbarSlotChanged.RemoveDynamic(this, &UHotbarWidget::HandleSelectionChanged);
}
BoundInventory.Reset();
Super::NativeDestruct();
}
UInventoryComponent* UHotbarWidget::ResolveInventory() const
{
const APlayerController* OwningController = GetOwningPlayer();
AFpsPlayer* Player = OwningController ? Cast<AFpsPlayer>(OwningController->GetPawn()) : nullptr;
return Player ? Player->GetInventoryComponent() : nullptr;
}
void UHotbarWidget::HandleInventoryChanged()
{
Refresh();
}
void UHotbarWidget::SetQuickTransferTarget(UInventoryComponent* InTarget)
{
QuickTransferTarget = InTarget;
for (UInventorySlotWidget* SlotWidget : SlotWidgets)
{
if (SlotWidget)
{
SlotWidget->SetQuickTransferTarget(InTarget);
}
}
}
void UHotbarWidget::HandleSelectionChanged(int32 NewIndex)
{
// Seule la surbrillance bouge : inutile de repousser tout le contenu.
for (int32 Index = 0; Index < SlotWidgets.Num(); ++Index)
{
if (SlotWidgets[Index])
{
SlotWidgets[Index]->SetSelected(Index == NewIndex);
}
}
}
void UHotbarWidget::HandleSlotHovered(int32 SlotIndex, bool bHovered)
{
OnSlotHovered.Broadcast(BoundInventory.Get(), SlotIndex, bHovered);
}
void UHotbarWidget::Refresh()
{
if (!SlotContainer)
{
UE_LOG(LogTemp, Warning, TEXT("UHotbarWidget::Refresh : SlotContainer est nul. Le widget nomme 'SlotContainer' manque dans le Blueprint."));
return;
}
if (!BoundInventory.IsValid())
{
return;
}
const TArray<FInventorySlot>& Slots = BoundInventory->GetSlots();
const int32 Count = BoundInventory->GetHotbarSlotCount();
RebuildSlots(Count);
const int32 Selected = BoundInventory->GetSelectedHotbarIndex();
for (int32 Index = 0; Index < SlotWidgets.Num(); ++Index)
{
if (!SlotWidgets[Index] || !Slots.IsValidIndex(Index))
{
continue;
}
SlotWidgets[Index]->SetSlot(Slots[Index]);
SlotWidgets[Index]->SetSelected(Index == Selected);
}
}
void UHotbarWidget::RebuildSlots(int32 DesiredCount)
{
if (SlotWidgets.Num() == DesiredCount)
{
return;
}
if (!SlotWidgetClass)
{
UE_LOG(LogTemp, Warning, TEXT("UHotbarWidget : SlotWidgetClass n'est pas assignee, la barre restera vide."));
return;
}
while (SlotWidgets.Num() > DesiredCount)
{
const int32 Last = SlotWidgets.Num() - 1;
if (SlotWidgets[Last])
{
SlotWidgets[Last]->RemoveFromParent();
}
SlotWidgets.RemoveAt(Last);
}
while (SlotWidgets.Num() < DesiredCount)
{
UInventorySlotWidget* NewSlot = CreateWidget<UInventorySlotWidget>(this, SlotWidgetClass);
if (!NewSlot)
{
UE_LOG(LogTemp, Error, TEXT("UHotbarWidget : impossible de creer une case a partir de %s. Recompile ce Widget Blueprint."),
*GetNameSafe(SlotWidgetClass));
break;
}
const int32 Index = SlotWidgets.Num();
// Meme indexation que la grille : la case 0 de la barre EST le slot 0
// de l'inventaire. C'est ce qui rend le glisser-deposer entre les deux
// gratuit -- ils manipulent le meme tableau.
NewSlot->InitSlot(BoundInventory.Get(), Index);
NewSlot->OnHoverChanged.AddDynamic(this, &UHotbarWidget::HandleSlotHovered);
NewSlot->SetQuickTransferTarget(QuickTransferTarget.Get());
if (UHorizontalBoxSlot* BoxSlot = SlotContainer->AddChildToHorizontalBox(NewSlot))
{
BoxSlot->SetPadding(FMargin(SlotPadding));
}
SlotWidgets.Add(NewSlot);
}
}