(Feat) Customisation de personnage -- donnees et montage

Lot 2 du chantier : le corps du lot precedent devient assemblable. Tete,
coiffure, sourcils, barbe et moustache sont montes en leader pose sur le
mesh du Character, et les couleurs sont posees sur des MID.

FCharacterAppearance tient en 11 octets : des INDEX et jamais des chemins
d'assets. Un chemin couterait une chaine a chaque replication, alors qu'un
index tient dans un octet et se VALIDE contre le catalogue -- un client ne
peut donc pas demander un asset arbitraire.

Le corps se monte depuis une LISTE de meshes meme si elle n'a qu'une case.
Le pack livre exprès SKM_BodyA_torso, _arms, _legs_01/02/03 pour qu'une
armure puisse eteindre les segments qu'elle recouvre : le jour venu la case
0 devient SKM_BodyA_empty et les huit segments suivent, sans que ce code
change. Un pointeur unique imposerait de tout reprendre au premier plastron.

Trois pieges rencontres, aucun visible depuis le code :

- Les UFUNCTION(Exec) d'un UActorComponent ne sont JAMAIS appelees. La
  chaine de routage (UPlayer::Exec) interroge le monde, le PlayerInput, le
  controller, le pawn, le HUD, le GameMode, le CheatManager, le GameState et
  le camera manager -- jamais les composants, AActor ne surchargeant pas
  ProcessConsoleExec. Et rien ne proteste. D'ou EmberPart / EmberColor /
  EmberAppearanceDump posees sur AFpsPlayer, qui delegue.

- L'ordre des slots de materiau varie d'un mesh a l'autre : sur
  SKM_HeadA_01 l'Element 0 est celui des YEUX et le 1 celui de la peau. Les
  six tetes venant de deux packs, on cherche le slot par son NOM et on ne
  pose rien si aucun ne correspond -- ecraser le slot de la peau repeint le
  visage entier de la couleur des yeux.

- Un nom de parametre materiau se lit dans le Material INSTANCE, pas dans
  les chaines du master : M_Head_Base contient « Skin Base color » mais le
  parametre expose s'appelle « Skin ». D'ou des UPROPERTY de catalogue
  plutot que des constantes, pour corriger sans recompiler.

Body B reste a remplir dans DA_CharacterParts, avec son ABP_PlayerBody_B et
sans barbes ni moustaches -- le pack n'en livre pas, et une liste vide se
comporte deja comme NoPart.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-08 18:48:37 +02:00
parent 6d22ae561e
commit 5ba5fbfebf
10 changed files with 1378 additions and 2 deletions
+44
View File
@@ -9,6 +9,7 @@
class APickupItem;
class UAnimMontage;
class UCameraComponent;
class UCharacterAppearanceComponent;
class UCraftingComponent;
class UHeadBobComponent;
class UInputAction;
@@ -122,6 +123,37 @@ public:
UFUNCTION(BlueprintPure, Category = "Survie")
USurvivalStatsComponent* GetSurvivalStats() const { return SurvivalStats; }
UFUNCTION(BlueprintPure, Category = "Apparence")
UCharacterAppearanceComponent* GetAppearanceComponent() const { return AppearanceComponent; }
// ------------------------------------------------------------------
// Commandes console d'apparence
//
// Elles vivent ICI et non sur UCharacterAppearanceComponent, ou leur place
// serait pourtant plus naturelle : la chaine de routage des commandes
// (UPlayer::Exec, dans Player.cpp) interroge le monde, le PlayerInput, le
// controller, le PAWN, le HUD, le GameMode, le CheatManager, le GameState
// et le camera manager -- jamais les composants, AActor ne surchargeant pas
// ProcessConsoleExec pour les parcourir. Une UFUNCTION(Exec) posee sur un
// composant est silencieusement ignoree, sans le moindre message.
//
// Le pawn est le maillon le plus proche du composant dans cette chaine,
// d'ou ces trois delegations d'une ligne. Elles disparaitront le jour ou
// l'ecran de customisation existera.
// ------------------------------------------------------------------
/** `EmberPart hair 3` -- body, head, hair, eyebrows, beard, mustache, eyes. */
UFUNCTION(Exec, Category = "Apparence")
void EmberPart(const FString& Part, int32 Index);
/** `EmberColor skin 2` -- skin, hair, eye, underwear. Index dans la palette. */
UFUNCTION(Exec, Category = "Apparence")
void EmberColor(const FString& Part, int32 ColorIndex);
/** Ecrit l'apparence courante et le nombre d'options de chaque categorie. */
UFUNCTION(Exec, Category = "Apparence")
void EmberAppearanceDump();
/** Sert a l'UI pour afficher la vraie touche mappee, plutot qu'un "E" ecrit en dur. */
UFUNCTION(BlueprintPure, Category = "Input")
const UInputAction* GetInteractAction() const { return InteractAction; }
@@ -276,6 +308,18 @@ protected:
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Survie")
TObjectPtr<USurvivalStatsComponent> SurvivalStats;
/**
* Monte la tete, les cheveux, la barbe et les couleurs sur le mesh 3e
* personne.
*
* Sur le pawn et non sur le controller, alors que l'apparence, elle, vivra
* sur le PlayerState : ce composant ne STOCKE rien, il assemble un corps.
* Or c'est le corps qui meurt et reapparait, et un nouveau pawn doit se
* remonter tout seul.
*/
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Apparence")
TObjectPtr<UCharacterAppearanceComponent> AppearanceComponent;
// ------------------------------------------------------------------
// Enhanced Input : assets à assigner dans le Blueprint
// ------------------------------------------------------------------