// Fill out your copyright notice in the Description page of Project Settings. #include "CharacterPartsDataAsset.h" namespace { /** * Rendue par GetParts quand la categorie n'existe pas, pour que l'appelant * n'ait jamais a tester un pointeur. * * Le nom porte le prefixe du fichier : le build unity concatene les .cpp du * module et un namespace anonyme n'isole plus rien. Une constante nommee * "EmptyParts" tout court finirait par entrer en collision -- invisible en * build incremental, elle ne sortirait qu'au premier -Rebuild. */ const TArray CharacterPartsEmptyList; /** Borne un index de piece OBLIGATOIRE : hors bornes, on retombe sur 0. */ void ClampRequiredIndex(uint8& Index, int32 Count) { if (Count <= 0 || Index >= Count) { Index = 0; } } /** Borne un index de piece FACULTATIVE : hors bornes, on retire la piece. */ void ClampOptionalIndex(uint8& Index, int32 Count) { if (Index == FCharacterAppearance::NoPart) { return; } if (Count <= 0 || Index >= Count) { Index = FCharacterAppearance::NoPart; } } } const FCharacterBodySet* UCharacterPartsDataAsset::GetBodySet(ECharacterBodyType BodyType) const { const int32 Index = static_cast(BodyType); return BodySets.IsValidIndex(Index) ? &BodySets[Index] : nullptr; } const TArray& UCharacterPartsDataAsset::GetParts(ECharacterBodyType BodyType, ECharacterPartCategory Category) const { const FCharacterBodySet* Set = GetBodySet(BodyType); if (!Set) { return CharacterPartsEmptyList; } switch (Category) { case ECharacterPartCategory::Head: return Set->Heads; case ECharacterPartCategory::Hair: return Set->Hairstyles; case ECharacterPartCategory::Eyebrows: return Set->Eyebrows; case ECharacterPartCategory::Beard: return Set->Beards; case ECharacterPartCategory::Mustache: return Set->Mustaches; default: return CharacterPartsEmptyList; } } int32 UCharacterPartsDataAsset::GetPartCount(ECharacterBodyType BodyType, ECharacterPartCategory Category) const { return GetParts(BodyType, Category).Num(); } void UCharacterPartsDataAsset::Sanitize(FCharacterAppearance& InOut) const { // La silhouette d'abord : tout le reste est indexe DANS son jeu de pieces, // donc la borner apres ne servirait a rien. if (static_cast(InOut.BodyType) >= BodySets.Num()) { InOut.BodyType = ECharacterBodyType::BodyA; } ClampRequiredIndex(InOut.HeadIndex, GetPartCount(InOut.BodyType, ECharacterPartCategory::Head)); ClampRequiredIndex(InOut.EyebrowsIndex, GetPartCount(InOut.BodyType, ECharacterPartCategory::Eyebrows)); // Cheveux, barbe et moustache sont facultatifs : un crane rase est un choix, // pas une erreur. ClampOptionalIndex(InOut.HairIndex, GetPartCount(InOut.BodyType, ECharacterPartCategory::Hair)); ClampOptionalIndex(InOut.BeardIndex, GetPartCount(InOut.BodyType, ECharacterPartCategory::Beard)); ClampOptionalIndex(InOut.MustacheIndex, GetPartCount(InOut.BodyType, ECharacterPartCategory::Mustache)); ClampRequiredIndex(InOut.EyesIndex, EyeMaterials.Num()); ClampRequiredIndex(InOut.SkinColorIndex, SkinColors.Num()); ClampRequiredIndex(InOut.HairColorIndex, HairColors.Num()); ClampRequiredIndex(InOut.EyeColorIndex, EyeColors.Num()); ClampRequiredIndex(InOut.UnderwearColorIndex, UnderwearColors.Num()); }