(Feat) Add Craft Systeme

This commit is contained in:
2026-07-30 23:08:33 +02:00
parent 9b5ad7c8a4
commit 3f3ae1f5fa
57 changed files with 2276 additions and 127 deletions
@@ -14,7 +14,7 @@
#include "InputCoreTypes.h"
#include "InventoryComponent.h"
#include "InteractionPromptWidget.h"
#include "InventoryWidget.h"
#include "InventoryScreenWidget.h"
#include "Kismet/GameplayStatics.h"
#include "PauseMenuWidget.h"
#include "ScreenFadeComponent.h"
@@ -104,7 +104,7 @@ void AFpsPlayerController::OnPossess(APawn* InPawn)
if (Crosshair) { /* pas d'abonnement */ }
if (InteractionPrompt) { InteractionPrompt->BindToOwningPawn(); }
if (Hotbar) { Hotbar->BindToOwningPawn(); }
if (InventoryWidget) { InventoryWidget->BindToOwningPawn(); }
if (InventoryScreen) { InventoryScreen->BindToOwningPawn(); }
if (SurvivalStatsWidget) { SurvivalStatsWidget->BindToOwningPawn(); }
if (AFpsPlayer* PlayerPawn = Cast<AFpsPlayer>(InPawn))
@@ -173,6 +173,11 @@ void AFpsPlayerController::SetupInputComponent()
Input->BindAction(ToggleInventoryAction, ETriggerEvent::Started, this, &AFpsPlayerController::ToggleInventory);
}
if (ToggleCraftingAction)
{
Input->BindAction(ToggleCraftingAction, ETriggerEvent::Started, this, &AFpsPlayerController::ToggleCrafting);
}
if (DropItemAction)
{
Input->BindAction(DropItemAction, ETriggerEvent::Started, this, &AFpsPlayerController::DropHoveredItem);
@@ -236,14 +241,39 @@ void AFpsPlayerController::HandleHotbarScroll(const FInputActionValue& Value)
}
}
void AFpsPlayerController::DropHoveredItem()
void AFpsPlayerController::HandleInventoryTabChanged(bool bInventoryTabActive)
{
if (!bInventoryOpen || !InventoryWidget)
bCraftingTabActive = !bInventoryTabActive;
UpdateHotbarVisibility();
}
void AFpsPlayerController::UpdateHotbarVisibility()
{
if (!Hotbar)
{
return;
}
const int32 SlotIndex = InventoryWidget->GetHoveredSlotIndex();
// La barre rapide reste affichee sur l'onglet Inventaire : elle en fait
// partie, on y glisse des objets. Elle n'a en revanche aucun sens sous la
// page de craft, ou elle ne ferait qu'encombrer.
// Surtout pas "bHidden" : AActor en a deja un, le masquer donne une erreur
// de compilation (C4458) plutot qu'un simple avertissement.
const bool bHideHotbar = bInventoryOpen && bCraftingTabActive;
Hotbar->SetVisibility(bHideHotbar ? ESlateVisibility::Collapsed : HotbarDefaultVisibility);
}
void AFpsPlayerController::DropHoveredItem()
{
if (!bInventoryOpen || !InventoryScreen)
{
return;
}
// Renvoie INDEX_NONE quand l'onglet Fabrication est affiche : la touche ne
// doit pas agir sur une case cachee derriere la grille de craft.
const int32 SlotIndex = InventoryScreen->GetHoveredSlotIndex();
if (SlotIndex == INDEX_NONE)
{
return;
@@ -316,27 +346,35 @@ void AFpsPlayerController::CreateHudWidgets()
Hotbar = CreateWidget<UHotbarWidget>(this, HotbarClass);
if (Hotbar)
{
// Relevee avant tout masquage : c'est la valeur a laquelle on
// reviendra en quittant l'onglet Fabrication.
HotbarDefaultVisibility = Hotbar->GetVisibility();
Hotbar->AddToViewport(ZOrderHotbar);
}
}
if (!InventoryWidget)
if (!InventoryScreen)
{
if (InventoryClass)
if (InventoryScreenClass)
{
InventoryWidget = CreateWidget<UInventoryWidget>(this, InventoryClass);
if (InventoryWidget)
InventoryScreen = CreateWidget<UInventoryScreenWidget>(this, InventoryScreenClass);
if (InventoryScreen)
{
InventoryWidget->AddToViewport(ZOrderInventory);
// Cree des le depart pour que son abonnement au delegue soit
// actif, mais cache : ainsi il reste a jour meme ferme, et
// l'ouverture est instantanee.
InventoryWidget->SetVisibility(ESlateVisibility::Collapsed);
// Abonnement AVANT l'ajout au viewport : c'est lui qui declenche
// NativeConstruct, donc la premiere diffusion d'onglet. S'abonner
// apres, on la manquerait.
InventoryScreen->OnTabChanged.AddDynamic(this, &AFpsPlayerController::HandleInventoryTabChanged);
InventoryScreen->AddToViewport(ZOrderInventory);
// Cree des le depart pour que les abonnements de ses deux pages
// soient actifs, mais cache : ainsi l'ecran reste a jour meme
// ferme, et l'ouverture est instantanee.
InventoryScreen->SetVisibility(ESlateVisibility::Collapsed);
}
}
else
{
UE_LOG(LogTemp, Warning, TEXT("AFpsPlayerController : InventoryClass n'est pas assignee, l'inventaire ne s'ouvrira pas."));
UE_LOG(LogTemp, Warning, TEXT("AFpsPlayerController : InventoryScreenClass n'est pas assignee, l'inventaire ne s'ouvrira pas."));
}
}
@@ -362,14 +400,73 @@ void AFpsPlayerController::CreateHudWidgets()
void AFpsPlayerController::ToggleInventory()
{
if (!InventoryWidget)
// Tab veut dire "ouvre mon sac". Rouvrir sur l'onglet Fabrication parce
// qu'on l'avait laisse la serait une surprise a chaque fois.
SetInventoryScreenOpen(!bInventoryOpen, /*bShowCraftingTab=*/false);
}
void AFpsPlayerController::ToggleCrafting()
{
// Deja sur l'onglet Fabrication : la meme touche referme, comme Tab le fait
// pour l'inventaire. Depuis l'onglet Inventaire, elle bascule sans fermer --
// c'est le geste attendu quand on cherche quoi construire avec ce qu'on vient
// de ramasser.
if (bInventoryOpen && bCraftingTabActive)
{
SetInventoryScreenOpen(false, /*bShowCraftingTab=*/false);
return;
}
SetInventoryScreenOpen(true, /*bShowCraftingTab=*/true);
}
void AFpsPlayerController::SetInventoryScreenOpen(bool bOpen, bool bShowCraftingTab)
{
if (!InventoryScreen)
{
return;
}
bInventoryOpen = !bInventoryOpen;
// Ecran deja ouvert : on ne fait que changer d'onglet. Repasser par le mode
// d'input serait au mieux inutile, au pire nuisible -- SetIgnoreLookInput
// gere un compteur qu'un appel en trop desequilibrerait durablement.
if (bOpen && bInventoryOpen)
{
if (bShowCraftingTab)
{
InventoryScreen->ShowCraftingTab();
}
else
{
InventoryScreen->ShowInventoryTab();
}
return;
}
InventoryWidget->SetVisibility(bInventoryOpen ? ESlateVisibility::Visible : ESlateVisibility::Collapsed);
if (bOpen == bInventoryOpen)
{
return;
}
bInventoryOpen = bOpen;
if (bInventoryOpen)
{
if (bShowCraftingTab)
{
InventoryScreen->ShowCraftingTab();
}
else
{
InventoryScreen->ShowInventoryTab();
}
}
InventoryScreen->SetVisibility(bInventoryOpen ? ESlateVisibility::Visible : ESlateVisibility::Collapsed);
// Fermer l'ecran doit toujours rendre la barre, meme si on l'avait laissee
// sur l'onglet Fabrication.
UpdateHotbarVisibility();
AFpsPlayer* PlayerPawn = Cast<AFpsPlayer>(GetPawn());
@@ -693,10 +790,10 @@ void AFpsPlayerController::EndPlay(const EEndPlayReason::Type EndPlayReason)
PauseMenu = nullptr;
}
if (InventoryWidget)
if (InventoryScreen)
{
InventoryWidget->RemoveFromParent();
InventoryWidget = nullptr;
InventoryScreen->RemoveFromParent();
InventoryScreen = nullptr;
}
if (InteractionPrompt)