(Feat) Add footsteps
This commit is contained in:
@@ -0,0 +1,193 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Blueprint/UserWidget.h"
|
||||
#include "CharacterAppearanceTypes.h"
|
||||
#include "CharacterPreviewActor.h"
|
||||
#include "CharacterCustomizationWidget.generated.h"
|
||||
|
||||
class ACharacterPreviewActor;
|
||||
class UButton;
|
||||
class UCharacterPartsDataAsset;
|
||||
class UCustomizationCategoryWidget;
|
||||
class UCustomizationOptionWidget;
|
||||
class UPanelWidget;
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnCustomizationConfirmed);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnCustomizationCancelled);
|
||||
|
||||
/**
|
||||
* Ce que le joueur peut regler, dans l'ordre d'affichage de la colonne.
|
||||
*
|
||||
* Pieces et couleurs sont dans le MEME enum : ce sont onze rangees de la meme
|
||||
* colonne, et les distinguer par deux listes obligerait a dessiner deux fois la
|
||||
* meme chose. La difference ne vit que dans BuildOptions, qui remplit la grille
|
||||
* de vignettes ou de pastilles selon le cas.
|
||||
*/
|
||||
UENUM(BlueprintType)
|
||||
enum class ECustomizationCategory : uint8
|
||||
{
|
||||
Body,
|
||||
Head,
|
||||
Hair,
|
||||
Eyebrows,
|
||||
Beard,
|
||||
Mustache,
|
||||
Eyes,
|
||||
SkinColor,
|
||||
HairColor,
|
||||
EyeColor,
|
||||
UnderwearColor,
|
||||
|
||||
Count UMETA(Hidden)
|
||||
};
|
||||
|
||||
/**
|
||||
* L'ecran de customisation : la colonne de reglages a gauche, le personnage a
|
||||
* droite.
|
||||
*
|
||||
* Le widget ne monte rien lui-meme -- il pousse une FCharacterAppearance sur
|
||||
* ACharacterPreviewActor et lit le catalogue pour savoir quoi proposer. C'est
|
||||
* le meme partage des roles que partout ailleurs dans le projet : l'interface
|
||||
* affiche et demande, le systeme decide.
|
||||
*
|
||||
* Classe Abstract : on cree un WBP_CharacterCustomization qui en herite.
|
||||
*/
|
||||
UCLASS(Abstract)
|
||||
class SURVIVAL_PROJET_API UCharacterCustomizationWidget : public UUserWidget
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UCharacterCustomizationWidget(const FObjectInitializer& ObjectInitializer);
|
||||
|
||||
virtual void NativeOnInitialized() override;
|
||||
virtual void NativeConstruct() override;
|
||||
|
||||
/**
|
||||
* Echap = Retour, comme le bouton.
|
||||
*
|
||||
* Obligatoire ici et pas seulement confortable : dans la map du menu, le
|
||||
* controller ne binde AUCUNE action d'input. Tout Echap qui fonctionne passe
|
||||
* donc par le NativeOnKeyDown d'un widget -- il n'y a pas d'autre chemin.
|
||||
*/
|
||||
virtual FReply NativeOnKeyDown(const FGeometry& InGeometry, const FKeyEvent& InKeyEvent) override;
|
||||
|
||||
/** Le joueur valide : l'ecran a fini, l'apparence est dans GetAppearance(). */
|
||||
UPROPERTY(BlueprintAssignable, Category = "Customization")
|
||||
FOnCustomizationConfirmed OnConfirmed;
|
||||
|
||||
/** Le joueur renonce : rien n'a ete valide, on rend la main au menu. */
|
||||
UPROPERTY(BlueprintAssignable, Category = "Customization")
|
||||
FOnCustomizationCancelled OnCancelled;
|
||||
|
||||
/**
|
||||
* Branche l'ecran sur son mannequin et son point de depart.
|
||||
*
|
||||
* A appeler AVANT d'ajouter le widget au viewport : NativeConstruct
|
||||
* reconstruit les listes, et il les batirait vides sans catalogue.
|
||||
*
|
||||
* Surtout PAS nommee Initialize : UUserWidget en a deja une, virtuelle, et
|
||||
* une surcharge de signature differente la masquerait au lieu de la
|
||||
* surcharger (C4263/C4264). Meme famille de piege que les membres nommes
|
||||
* Player ou Slot dans une classe derivee du moteur.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "Customization")
|
||||
void SetupCustomization(ACharacterPreviewActor* InPreview, const FCharacterAppearance& InAppearance);
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "Customization")
|
||||
const FCharacterAppearance& GetAppearance() const { return Appearance; }
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Le catalogue. Assigne-lui le meme DA_CharacterParts que BP_FpsPlayer.
|
||||
*
|
||||
* Sur le widget et pas pris sur le mannequin : l'ecran doit pouvoir batir
|
||||
* ses listes meme si le mannequin manque encore, et un catalogue different
|
||||
* des deux cotes se verrait immediatement a l'ecran.
|
||||
*/
|
||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Customization")
|
||||
TObjectPtr<UCharacterPartsDataAsset> Catalog;
|
||||
|
||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Customization")
|
||||
TSubclassOf<UCustomizationCategoryWidget> CategoryWidgetClass;
|
||||
|
||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Customization")
|
||||
TSubclassOf<UCustomizationOptionWidget> OptionWidgetClass;
|
||||
|
||||
/** La colonne des categories. Un Vertical Box nomme exactement ainsi. */
|
||||
UPROPERTY(meta = (BindWidget))
|
||||
TObjectPtr<UPanelWidget> CategoryList;
|
||||
|
||||
/** La grille d'options. Un Wrap Box va tres bien. */
|
||||
UPROPERTY(meta = (BindWidget))
|
||||
TObjectPtr<UPanelWidget> OptionGrid;
|
||||
|
||||
/** Valide et lance la partie. */
|
||||
UPROPERTY(meta = (BindWidget))
|
||||
TObjectPtr<UButton> PlayButton;
|
||||
|
||||
/** Retour au menu principal, sans rien valider. */
|
||||
UPROPERTY(meta = (BindWidget))
|
||||
TObjectPtr<UButton> BackButton;
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Rotation du personnage au clic-glisser
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
virtual FReply NativeOnMouseButtonDown(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent) override;
|
||||
virtual FReply NativeOnMouseButtonUp(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent) override;
|
||||
virtual FReply NativeOnMouseMove(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent) override;
|
||||
|
||||
private:
|
||||
/** Reconstruit la colonne de gauche. Une seule fois, les categories sont fixes. */
|
||||
void BuildCategories();
|
||||
|
||||
/** Reconstruit la grille selon la categorie active. */
|
||||
void BuildOptions();
|
||||
|
||||
/** Repose l'apparence sur le mannequin et rafraichit la selection affichee. */
|
||||
void RefreshPreview();
|
||||
|
||||
/** Encadre la case qui porte le choix courant, efface les autres. */
|
||||
void RefreshSelection();
|
||||
|
||||
/** L'index courant dans la categorie active, pour l'encadrement. */
|
||||
int32 GetCurrentIndexForCategory(ECustomizationCategory Category) const;
|
||||
|
||||
/** Ecrit un choix dans l'apparence. Le seul endroit qui la modifie. */
|
||||
void SetIndexForCategory(ECustomizationCategory Category, int32 NewIndex);
|
||||
|
||||
/** Combien d'options a proposer, catalogue en main. */
|
||||
int32 GetOptionCountForCategory(ECustomizationCategory Category) const;
|
||||
|
||||
UFUNCTION()
|
||||
void HandleCategoryClicked(int32 CategoryIndex);
|
||||
|
||||
UFUNCTION()
|
||||
void HandleOptionClicked(int32 OptionIndex);
|
||||
|
||||
UFUNCTION()
|
||||
void HandlePlayClicked();
|
||||
|
||||
UFUNCTION()
|
||||
void HandleBackClicked();
|
||||
|
||||
UPROPERTY(Transient)
|
||||
TObjectPtr<ACharacterPreviewActor> Preview;
|
||||
|
||||
UPROPERTY(Transient)
|
||||
TArray<TObjectPtr<UCustomizationCategoryWidget>> CategoryWidgets;
|
||||
|
||||
UPROPERTY(Transient)
|
||||
TArray<TObjectPtr<UCustomizationOptionWidget>> OptionWidgets;
|
||||
|
||||
FCharacterAppearance Appearance;
|
||||
|
||||
ECustomizationCategory ActiveCategory = ECustomizationCategory::Body;
|
||||
|
||||
/** Vrai entre l'appui et le relachement, pendant qu'on fait tourner. */
|
||||
bool bDragging = false;
|
||||
};
|
||||
Reference in New Issue
Block a user