diff --git a/Content/UI/HUD/W_HUD.uasset b/Content/UI/HUD/W_HUD.uasset index 18f83e20..11cea7dc 100644 --- a/Content/UI/HUD/W_HUD.uasset +++ b/Content/UI/HUD/W_HUD.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b05fa9217649a2b49ce433c1dc7c6aeaaf5ebb9b3cee644afddac95c3e2a1966 -size 27305 +oid sha256:df406d25fa438cbbbc568a27d340b7d476829bab4744539d922c796d020b0e9e +size 24359 diff --git a/Source/NakedDesire/Clothing/ClothingManager.cpp b/Source/NakedDesire/Clothing/ClothingManager.cpp index 1b462e5a..c05395ff 100644 --- a/Source/NakedDesire/Clothing/ClothingManager.cpp +++ b/Source/NakedDesire/Clothing/ClothingManager.cpp @@ -81,37 +81,6 @@ float UClothingManager::GetHeelHeight() return Footwear->GetClothingItemDefinition()->ShoesOffset; } -USkeletalMeshComponent* UClothingManager::GetMeshComponent(const EClothingSlotType SlotType) const -{ - const ANakedDesireCharacter* Player = Cast(GetOwner()); - if (!Player) - { - return nullptr; - } - switch (SlotType) - { - case EClothingSlotType::Nipples: return Player->NipplesMeshComponent; - case EClothingSlotType::Anal: return Player->AnalMeshComponent; - case EClothingSlotType::Vagina: return Player->VaginaMeshComponent; - case EClothingSlotType::Head: return Player->HeadMeshComponent; - case EClothingSlotType::Neck: return Player->NeckMeshComponent; - case EClothingSlotType::Face: return Player->FaceMeshComponent; - case EClothingSlotType::Eyes: return Player->EyesMeshComponent; - case EClothingSlotType::Bodysuit: return Player->BodySuitMeshComponent; - case EClothingSlotType::Top: return Player->TopMeshComponent; - case EClothingSlotType::Bottom: return Player->BottomMeshComponent; - case EClothingSlotType::UnderwearTop: return Player->UnderwearTopMeshComponent; - case EClothingSlotType::UnderwearBottom:return Player->UnderwearBottomMeshComponent; - case EClothingSlotType::Socks: return Player->SocksMeshComponent; - case EClothingSlotType::Footwear: return Player->FootwearMeshComponent; - case EClothingSlotType::Outerwear: return Player->OuterwearMeshComponent; - case EClothingSlotType::WristRestraint: return Player->WristRestraintMeshComponent; - case EClothingSlotType::AnkleRestraint: return Player->AnkleRestraintMeshComponent; - case EClothingSlotType::NeckRestraint: return Player->NeckRestraintMeshComponent; - default: return nullptr; - } -} - void UClothingManager::SpawnClothingPickup(UClothingItemInstance* ItemInstance) { if (!ItemPickupActor) @@ -139,22 +108,8 @@ void UClothingManager::PutOnClothing(UClothingItemInstance* ClothingItemInstance return; const EClothingSlotType ClothingSlotType = ClothingItemInstance->GetClothingItemDefinition()->SlotType; - - USkeletalMeshComponent* MeshComponent = GetMeshComponent(ClothingSlotType); - MeshComponent->SetSkeletalMesh(ClothingItemInstance->GetClothingItemDefinition()->SkeletalMesh); - if (!ClothingItemInstance->GetClothingItemDefinition()->Materials.IsEmpty()) - { - for (const TPair& Material : ClothingItemInstance->GetClothingItemDefinition()->Materials) - { - MeshComponent->SetMaterialByName(Material.Key, Material.Value); - } - } SetClothingSlotItem(ClothingSlotType, ClothingItemInstance); - if (ClothingItemInstance->GetClothingItemDefinition()->UseLeaderPose) - { - MeshComponent->SetLeaderPoseComponent(Cast(GetOwner())->GetMesh()); - } const UClothingItemDefinition* ClothingItem = ClothingItemInstance->GetClothingItemDefinition(); if (ClothingItem->SlotType == EClothingSlotType::Bodysuit) @@ -200,14 +155,6 @@ UClothingItemInstance* UClothingManager::RemoveClothing(const EClothingSlotType SetClothingSlotItem(ClothingSlotType, nullptr); - USkeletalMeshComponent* MeshComponent = GetMeshComponent(ClothingSlotType); - MeshComponent->SetSkeletalMesh(nullptr); - - if (ExistingItem->GetClothingItemDefinition()->UseLeaderPose) - { - MeshComponent->SetLeaderPoseComponent(nullptr); - } - OnClothingUnequip.Broadcast(ExistingItem); USaveSubsystem* SaveSubsystem = UGameplayStatics::GetGameInstance(GetWorld())->GetSubsystem(); diff --git a/Source/NakedDesire/Clothing/ClothingManager.h b/Source/NakedDesire/Clothing/ClothingManager.h index 84c61dff..b44cbfe9 100644 --- a/Source/NakedDesire/Clothing/ClothingManager.h +++ b/Source/NakedDesire/Clothing/ClothingManager.h @@ -53,7 +53,6 @@ public: float GetHeelHeight(); private: - USkeletalMeshComponent* GetMeshComponent(EClothingSlotType SlotType) const; void SpawnClothingPickup(UClothingItemInstance* ItemInstance); UPROPERTY() diff --git a/Source/NakedDesire/Clothing/ClothingVisualsComponent.cpp b/Source/NakedDesire/Clothing/ClothingVisualsComponent.cpp new file mode 100644 index 00000000..31c57c8b --- /dev/null +++ b/Source/NakedDesire/Clothing/ClothingVisualsComponent.cpp @@ -0,0 +1,98 @@ +// © 2025 Naked People Team. All Rights Reserved. + + +#include "ClothingVisualsComponent.h" + +#include "ClothingItemDefinition.h" +#include "ClothingItemInstance.h" +#include "ClothingManager.h" +#include "Components/SkeletalMeshComponent.h" +#include "Materials/MaterialInstance.h" + +UClothingVisualsComponent::UClothingVisualsComponent() +{ + PrimaryComponentTick.bCanEverTick = false; +} + +void UClothingVisualsComponent::Initialize(USkeletalMeshComponent* InBodyMesh, UClothingManager* InClothingManager) +{ + BodyMesh = InBodyMesh; + ClothingManager = InClothingManager; + + if (!ClothingManager) + return; + + ClothingManager->OnClothingEquip.AddUniqueDynamic(this, &UClothingVisualsComponent::HandleClothingEquip); + ClothingManager->OnClothingUnequip.AddUniqueDynamic(this, &UClothingVisualsComponent::HandleClothingUnequip); + + for (const UClothingItemInstance* Equipped : ClothingManager->GetEquippedClothing()) + { + Apply(Equipped); + } +} + +void UClothingVisualsComponent::Apply(const UClothingItemInstance* ClothingItemInstance) +{ + if (!ClothingItemInstance) + return; + + const UClothingItemDefinition* Definition = ClothingItemInstance->GetClothingItemDefinition(); + if (!Definition) + return; + + USkeletalMeshComponent* SlotMesh = GetOrCreateSlotMesh(Definition->SlotType); + if (!SlotMesh) + return; + + SlotMesh->SetSkeletalMesh(Definition->SkeletalMesh); + + if (Definition->UseLeaderPose) + { + SlotMesh->SetLeaderPoseComponent(BodyMesh); + } + + for (const TPair& Material : Definition->Materials) + { + SlotMesh->SetMaterialByName(Material.Key, Material.Value); + } +} + +void UClothingVisualsComponent::ClearSlot(EClothingSlotType SlotType) +{ + if (const TObjectPtr* Found = SlotMeshes.Find(SlotType)) + { + (*Found)->SetLeaderPoseComponent(nullptr); + (*Found)->SetSkeletalMesh(nullptr); + } +} + +void UClothingVisualsComponent::HandleClothingEquip(UClothingItemInstance* ClothingItemInstance) +{ + Apply(ClothingItemInstance); +} + +void UClothingVisualsComponent::HandleClothingUnequip(UClothingItemInstance* ClothingItemInstance) +{ + if (ClothingItemInstance && ClothingItemInstance->GetClothingItemDefinition()) + { + ClearSlot(ClothingItemInstance->GetClothingItemDefinition()->SlotType); + } +} + +USkeletalMeshComponent* UClothingVisualsComponent::GetOrCreateSlotMesh(EClothingSlotType SlotType) +{ + if (const TObjectPtr* Found = SlotMeshes.Find(SlotType)) + { + return *Found; + } + + if (!BodyMesh) + return nullptr; + + const FName ComponentName = *FString::Printf(TEXT("ClothingSlotMesh_%d"), static_cast(SlotType)); + USkeletalMeshComponent* SlotMesh = NewObject(GetOwner(), ComponentName); + SlotMesh->SetupAttachment(BodyMesh); + SlotMesh->RegisterComponent(); + SlotMeshes.Add(SlotType, SlotMesh); + return SlotMesh; +} \ No newline at end of file diff --git a/Source/NakedDesire/Clothing/ClothingVisualsComponent.h b/Source/NakedDesire/Clothing/ClothingVisualsComponent.h new file mode 100644 index 00000000..c5dd315d --- /dev/null +++ b/Source/NakedDesire/Clothing/ClothingVisualsComponent.h @@ -0,0 +1,56 @@ +// © 2025 Naked People Team. All Rights Reserved. + +#pragma once + +#include "CoreMinimal.h" +#include "Components/ActorComponent.h" +#include "ClothingSlotType.h" +#include "ClothingVisualsComponent.generated.h" + +class UClothingManager; +class UClothingItemInstance; +class USkeletalMeshComponent; + +/** + * Renders equipped clothing by lazily spawning one skeletal mesh component per + * occupied slot, parented to a target body mesh. Reacts to a UClothingManager's + * equip/unequip events, so the character, mirror impostor, and cinematic double + * share one implementation instead of hand-maintained per-slot components. + */ +UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) +class NAKEDDESIRE_API UClothingVisualsComponent : public UActorComponent +{ + GENERATED_BODY() + +public: + UClothingVisualsComponent(); + + /** + * Bind to a clothing manager and a body mesh (the leader-pose source and + * attach parent for spawned slot meshes), then apply the current equipped set. + * Call after the manager has hydrated (e.g. owning actor's BeginPlay). + */ + void Initialize(USkeletalMeshComponent* InBodyMesh, UClothingManager* InClothingManager); + + void Apply(const UClothingItemInstance* ClothingItemInstance); + void ClearSlot(EClothingSlotType SlotType); + +private: + UFUNCTION() + void HandleClothingEquip(UClothingItemInstance* ClothingItemInstance); + + UFUNCTION() + void HandleClothingUnequip(UClothingItemInstance* ClothingItemInstance); + + /** Returns the slot's mesh component, creating + attaching it on first use. */ + USkeletalMeshComponent* GetOrCreateSlotMesh(EClothingSlotType SlotType); + + UPROPERTY() + TObjectPtr BodyMesh; + + UPROPERTY() + TObjectPtr ClothingManager; + + UPROPERTY() + TMap> SlotMeshes; +}; \ No newline at end of file diff --git a/Source/NakedDesire/Player/NakedDesireCharacter.cpp b/Source/NakedDesire/Player/NakedDesireCharacter.cpp index 6d368d11..858a2152 100644 --- a/Source/NakedDesire/Player/NakedDesireCharacter.cpp +++ b/Source/NakedDesire/Player/NakedDesireCharacter.cpp @@ -12,6 +12,7 @@ #include "NakedDesire/Censorship/CensorshipComponent.h" #include "NakedDesire/Clothing/ClothingItemDefinition.h" #include "NakedDesire/Clothing/ClothingItemInstance.h" +#include "NakedDesire/Clothing/ClothingVisualsComponent.h" #include "NakedDesire/Global/Constants.h" #include "NakedDesire/Global/NakedDesireHUD.h" #include "NakedDesire/Global/NakedDesireUserSettings.h" @@ -33,42 +34,7 @@ ANakedDesireCharacter::ANakedDesireCharacter() StatsManager = CreateDefaultSubobject("Stats Manager"); MissionsManager = CreateDefaultSubobject("Missions Manager"); - NipplesMeshComponent = CreateDefaultSubobject("Nipples"); - NipplesMeshComponent->SetupAttachment(GetMesh()); - AnalMeshComponent = CreateDefaultSubobject("Anal"); - AnalMeshComponent->SetupAttachment(GetMesh()); - VaginaMeshComponent = CreateDefaultSubobject("Vagina"); - VaginaMeshComponent->SetupAttachment(GetMesh()); - HeadMeshComponent = CreateDefaultSubobject("Head"); - HeadMeshComponent->SetupAttachment(GetMesh()); - NeckMeshComponent = CreateDefaultSubobject("Neck"); - NeckMeshComponent->SetupAttachment(GetMesh()); - FaceMeshComponent = CreateDefaultSubobject("Face"); - FaceMeshComponent->SetupAttachment(GetMesh()); - EyesMeshComponent = CreateDefaultSubobject("Eyes"); - EyesMeshComponent->SetupAttachment(GetMesh()); - BodySuitMeshComponent = CreateDefaultSubobject("Body Suit"); - BodySuitMeshComponent->SetupAttachment(GetMesh()); - TopMeshComponent = CreateDefaultSubobject("Top"); - TopMeshComponent->SetupAttachment(GetMesh()); - BottomMeshComponent = CreateDefaultSubobject("Bottom"); - BottomMeshComponent->SetupAttachment(GetMesh()); - UnderwearTopMeshComponent = CreateDefaultSubobject("Underwear Top"); - UnderwearTopMeshComponent->SetupAttachment(GetMesh()); - UnderwearBottomMeshComponent = CreateDefaultSubobject("Underwear Bottom"); - UnderwearBottomMeshComponent->SetupAttachment(GetMesh()); - SocksMeshComponent = CreateDefaultSubobject("Socks"); - SocksMeshComponent->SetupAttachment(GetMesh()); - FootwearMeshComponent = CreateDefaultSubobject("Footwear"); - FootwearMeshComponent->SetupAttachment(GetMesh()); - OuterwearMeshComponent = CreateDefaultSubobject("Outerwear"); - OuterwearMeshComponent->SetupAttachment(GetMesh()); - WristRestraintMeshComponent = CreateDefaultSubobject("Wrist Restraint"); - WristRestraintMeshComponent->SetupAttachment(GetMesh()); - AnkleRestraintMeshComponent = CreateDefaultSubobject("Ankle Restraint"); - AnkleRestraintMeshComponent->SetupAttachment(GetMesh()); - NeckRestraintMeshComponent = CreateDefaultSubobject("Neck Restraint"); - NeckRestraintMeshComponent->SetupAttachment(GetMesh()); + ClothingVisualsComponent = CreateDefaultSubobject(TEXT("Clothing Visuals Component")); BoobLCensorship = CreateDefaultSubobject(TEXT("Boob L Censorship")); BoobLCensorship->SetupAttachment(GetMesh(), FName(TEXT("boob_l"))); @@ -157,7 +123,8 @@ void ANakedDesireCharacter::BeginPlay() StimuliSourceComponent->RegisterWithPerceptionSystem(); // Initialize after Super::BeginPlay so clothing hydration has populated the - // equipped set; the component recomputes censorship from that final state. + // equipped set; both components sync from that final state. + ClothingVisualsComponent->Initialize(GetMesh(), ClothingManager); CensorshipComponent->Initialize(ClothingManager, BoobLCensorship, BoobRCensorship, VaginaCensorship, AnalCensorship); HUD = Cast(UGameplayStatics::GetPlayerController(GetWorld(), 0)->GetHUD()); diff --git a/Source/NakedDesire/Player/NakedDesireCharacter.h b/Source/NakedDesire/Player/NakedDesireCharacter.h index 6524a239..36374dfa 100644 --- a/Source/NakedDesire/Player/NakedDesireCharacter.h +++ b/Source/NakedDesire/Player/NakedDesireCharacter.h @@ -19,6 +19,7 @@ class UClothingItemInstance; class UClothingSlotsData; class UAIPerceptionStimuliSourceComponent; class UClothingManager; +class UClothingVisualsComponent; class UCensorshipComponent; class UStatsManager; class UMissionsManager; @@ -57,60 +58,9 @@ public: UPROPERTY(EditDefaultsOnly, Category = "Input") UInputAction* InteractAction; - // Clothing + // Clothing slot meshes are spawned per equipped slot at runtime by ClothingVisualsComponent. UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Clothing") - USkeletalMeshComponent* NipplesMeshComponent; - - UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Clothing") - USkeletalMeshComponent* AnalMeshComponent; - - UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Clothing") - USkeletalMeshComponent* VaginaMeshComponent; - - UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Clothing") - USkeletalMeshComponent* HeadMeshComponent; - - UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Clothing") - USkeletalMeshComponent* NeckMeshComponent; - - UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Clothing") - USkeletalMeshComponent* FaceMeshComponent; - - UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Clothing") - USkeletalMeshComponent* EyesMeshComponent; - - UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Clothing") - USkeletalMeshComponent* BodySuitMeshComponent; - - UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Clothing") - USkeletalMeshComponent* TopMeshComponent; - - UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Clothing") - USkeletalMeshComponent* BottomMeshComponent; - - UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Clothing") - USkeletalMeshComponent* UnderwearTopMeshComponent; - - UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Clothing") - USkeletalMeshComponent* UnderwearBottomMeshComponent; - - UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Clothing") - USkeletalMeshComponent* SocksMeshComponent; - - UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Clothing") - USkeletalMeshComponent* FootwearMeshComponent; - - UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Clothing") - USkeletalMeshComponent* OuterwearMeshComponent; - - UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Clothing") - USkeletalMeshComponent* WristRestraintMeshComponent; - - UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Clothing") - USkeletalMeshComponent* AnkleRestraintMeshComponent; - - UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Clothing") - USkeletalMeshComponent* NeckRestraintMeshComponent; + UClothingVisualsComponent* ClothingVisualsComponent; UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Censorship") UStaticMeshComponent* BoobLCensorship; diff --git a/Source/NakedDesire/Player/PlayerCinematic.cpp b/Source/NakedDesire/Player/PlayerCinematic.cpp index d0b5b968..b947a8e0 100644 --- a/Source/NakedDesire/Player/PlayerCinematic.cpp +++ b/Source/NakedDesire/Player/PlayerCinematic.cpp @@ -1,44 +1,16 @@ -#include "PlayerCinematic.h" +#include "PlayerCinematic.h" + #include "NakedDesireCharacter.h" #include "Kismet/GameplayStatics.h" -#include "NakedDesire/Clothing/ClothingItemDefinition.h" -#include "NakedDesire/Clothing/ClothingItemInstance.h" #include "NakedDesire/Clothing/ClothingManager.h" +#include "NakedDesire/Clothing/ClothingVisualsComponent.h" -// Sets default values APlayerCinematic::APlayerCinematic() { PrimaryActorTick.bCanEverTick = false; - - NipplesMeshComponent = CreateDefaultSubobject(TEXT("Nipples")); - NipplesMeshComponent->SetupAttachment(GetMesh()); - AnalMeshComponent = CreateDefaultSubobject(TEXT("Anal")); - AnalMeshComponent->SetupAttachment(GetMesh()); - VaginaMeshComponent = CreateDefaultSubobject(TEXT("Vagina")); - VaginaMeshComponent->SetupAttachment(GetMesh()); - HeadMeshComponent = CreateDefaultSubobject(TEXT("Head")); - HeadMeshComponent->SetupAttachment(GetMesh()); - NeckMeshComponent = CreateDefaultSubobject(TEXT("Neck")); - NeckMeshComponent->SetupAttachment(GetMesh()); - FaceMeshComponent = CreateDefaultSubobject(TEXT("Face")); - FaceMeshComponent->SetupAttachment(GetMesh()); - EyesMeshComponent = CreateDefaultSubobject(TEXT("Eyes")); - EyesMeshComponent->SetupAttachment(GetMesh()); - BodyMeshComponent = CreateDefaultSubobject(TEXT("Body")); - BodyMeshComponent->SetupAttachment(GetMesh()); - TopMeshComponent = CreateDefaultSubobject(TEXT("Top")); - TopMeshComponent->SetupAttachment(GetMesh()); - BottomMeshComponent = CreateDefaultSubobject(TEXT("Bottom")); - BottomMeshComponent->SetupAttachment(GetMesh()); - BraMeshComponent = CreateDefaultSubobject(TEXT("Bra")); - BraMeshComponent->SetupAttachment(GetMesh()); - PantiesMeshComponent = CreateDefaultSubobject(TEXT("Panties")); - PantiesMeshComponent->SetupAttachment(GetMesh()); - SocksMeshComponent = CreateDefaultSubobject(TEXT("Socks")); - SocksMeshComponent->SetupAttachment(GetMesh()); - ShoesMeshComponent = CreateDefaultSubobject(TEXT("Shoes")); - ShoesMeshComponent->SetupAttachment(GetMesh()); + + ClothingVisualsComponent = CreateDefaultSubobject(TEXT("Clothing Visuals Component")); } void APlayerCinematic::BeginPlay() @@ -51,83 +23,5 @@ void APlayerCinematic::BeginPlay() return; } - Player->ClothingManager->OnClothingEquip.AddUniqueDynamic(this, &APlayerCinematic::OnClothingEquip); - Player->ClothingManager->OnClothingUnequip.AddUniqueDynamic(this, &APlayerCinematic::OnClothingUnequip); - - for (const UClothingItemInstance* ClothingItemInstance : Player->ClothingManager->GetEquippedClothing()) - { - EquipClothing(ClothingItemInstance); - } -} - -void APlayerCinematic::OnClothingEquip(UClothingItemInstance* ClothingItemInstance) -{ - EquipClothing(ClothingItemInstance); -} - -void APlayerCinematic::OnClothingUnequip(UClothingItemInstance* ClothingItemInstance) -{ - UnequipClothing(ClothingItemInstance); -} - -USkeletalMeshComponent* APlayerCinematic::GetMeshByType(const EClothingSlotType SlotType) const -{ - switch (SlotType) - { - case EClothingSlotType::Nipples: - return NipplesMeshComponent; - case EClothingSlotType::Anal: - return AnalMeshComponent; - case EClothingSlotType::Vagina: - return VaginaMeshComponent; - case EClothingSlotType::Head: - return HeadMeshComponent; - case EClothingSlotType::Neck: - return NeckMeshComponent; - case EClothingSlotType::Face: - return FaceMeshComponent; - case EClothingSlotType::Eyes: - return EyesMeshComponent; - case EClothingSlotType::Bodysuit: - return BodyMeshComponent; - case EClothingSlotType::Top: - return TopMeshComponent; - case EClothingSlotType::Bottom: - return BottomMeshComponent; - case EClothingSlotType::UnderwearTop: - return BraMeshComponent; - case EClothingSlotType::UnderwearBottom: - return PantiesMeshComponent; - case EClothingSlotType::Socks: - return SocksMeshComponent; - case EClothingSlotType::Footwear: - return ShoesMeshComponent; - default: - return NipplesMeshComponent; - } -} - -void APlayerCinematic::EquipClothing(const UClothingItemInstance* ClothingItemInstance) -{ - USkeletalMeshComponent* MeshComponent = GetMeshByType(ClothingItemInstance->GetClothingItemDefinition()->SlotType); - MeshComponent->SetSkeletalMesh(ClothingItemInstance->GetClothingItemDefinition()->SkeletalMesh); - if (ClothingItemInstance->GetClothingItemDefinition()->UseLeaderPose) - { - MeshComponent->SetLeaderPoseComponent(GetMesh()); - } - - if (!ClothingItemInstance->GetClothingItemDefinition()->Materials.IsEmpty()) - { - for (const TPair& Material : ClothingItemInstance->GetClothingItemDefinition()->Materials) - { - MeshComponent->SetMaterialByName(Material.Key, Material.Value); - } - } -} - -void APlayerCinematic::UnequipClothing(const UClothingItemInstance* ClothingItemInstance) -{ - USkeletalMeshComponent* MeshComponent = GetMeshByType(ClothingItemInstance->GetClothingItemDefinition()->SlotType); - MeshComponent->SetSkeletalMesh(nullptr); - MeshComponent->SetLeaderPoseComponent(nullptr); -} + ClothingVisualsComponent->Initialize(GetMesh(), Player->ClothingManager); +} \ No newline at end of file diff --git a/Source/NakedDesire/Player/PlayerCinematic.h b/Source/NakedDesire/Player/PlayerCinematic.h index 477dff10..af98d31a 100644 --- a/Source/NakedDesire/Player/PlayerCinematic.h +++ b/Source/NakedDesire/Player/PlayerCinematic.h @@ -1,12 +1,11 @@ -#pragma once +#pragma once #include "CoreMinimal.h" #include "GameFramework/Character.h" -#include "NakedDesire/Clothing/ClothingSlotType.h" #include "PlayerCinematic.generated.h" -class UClothingItemInstance; class ANakedDesireCharacter; +class UClothingVisualsComponent; UCLASS() class NAKEDDESIRE_API APlayerCinematic : public ACharacter @@ -14,63 +13,13 @@ class NAKEDDESIRE_API APlayerCinematic : public ACharacter GENERATED_BODY() UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, meta = (AllowPrivateAccess = true), Category = "Clothing") - USkeletalMeshComponent* NipplesMeshComponent; - - UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, meta = (AllowPrivateAccess = true), Category = "Clothing") - USkeletalMeshComponent* AnalMeshComponent; - - UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, meta = (AllowPrivateAccess = true), Category = "Clothing") - USkeletalMeshComponent* VaginaMeshComponent; - - UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, meta = (AllowPrivateAccess = true), Category = "Clothing") - USkeletalMeshComponent* HeadMeshComponent; - - UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, meta = (AllowPrivateAccess = true), Category = "Clothing") - USkeletalMeshComponent* NeckMeshComponent; - - UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, meta = (AllowPrivateAccess = true), Category = "Clothing") - USkeletalMeshComponent* FaceMeshComponent; - - UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, meta = (AllowPrivateAccess = true), Category = "Clothing") - USkeletalMeshComponent* EyesMeshComponent; - - UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, meta = (AllowPrivateAccess = true), Category = "Clothing") - USkeletalMeshComponent* BodyMeshComponent; - - UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, meta = (AllowPrivateAccess = true), Category = "Clothing") - USkeletalMeshComponent* TopMeshComponent; - - UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, meta = (AllowPrivateAccess = true), Category = "Clothing") - USkeletalMeshComponent* BottomMeshComponent; - - UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, meta = (AllowPrivateAccess = true), Category = "Clothing") - USkeletalMeshComponent* BraMeshComponent; - - UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, meta = (AllowPrivateAccess = true), Category = "Clothing") - USkeletalMeshComponent* PantiesMeshComponent; - - UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, meta = (AllowPrivateAccess = true), Category = "Clothing") - USkeletalMeshComponent* SocksMeshComponent; - - UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, meta = (AllowPrivateAccess = true), Category = "Clothing") - USkeletalMeshComponent* ShoesMeshComponent; + UClothingVisualsComponent* ClothingVisualsComponent; UPROPERTY() ANakedDesireCharacter* Player; public: APlayerCinematic(); - - virtual void BeginPlay() override; -private: - UFUNCTION() - void OnClothingEquip(UClothingItemInstance* ClothingItemInstance); - - UFUNCTION() - void OnClothingUnequip(UClothingItemInstance* ClothingItemInstance); - - USkeletalMeshComponent* GetMeshByType(const EClothingSlotType SlotType) const; - void EquipClothing(const UClothingItemInstance* ClothingItemInstance); - void UnequipClothing(const UClothingItemInstance* ClothingItemInstance); -}; + virtual void BeginPlay() override; +}; \ No newline at end of file diff --git a/Source/NakedDesire/Player/PlayerImpostor.cpp b/Source/NakedDesire/Player/PlayerImpostor.cpp index 04337d77..b3f62f2d 100644 --- a/Source/NakedDesire/Player/PlayerImpostor.cpp +++ b/Source/NakedDesire/Player/PlayerImpostor.cpp @@ -1,9 +1,9 @@ -#include "PlayerImpostor.h" +#include "PlayerImpostor.h" + #include "NakedDesireCharacter.h" #include "Kismet/GameplayStatics.h" -#include "NakedDesire/Clothing/ClothingItemDefinition.h" -#include "NakedDesire/Clothing/ClothingItemInstance.h" #include "NakedDesire/Clothing/ClothingManager.h" +#include "NakedDesire/Clothing/ClothingVisualsComponent.h" APlayerImpostor::APlayerImpostor() @@ -16,44 +16,7 @@ APlayerImpostor::APlayerImpostor() Mesh = CreateDefaultSubobject(TEXT("RootMesh")); Mesh->SetupAttachment(RootComponent); - NipplesMeshComponent = CreateDefaultSubobject(TEXT("Nipples")); - NipplesMeshComponent->SetupAttachment(GetMesh()); - AnalMeshComponent = CreateDefaultSubobject(TEXT("Anal")); - AnalMeshComponent->SetupAttachment(GetMesh()); - VaginaMeshComponent = CreateDefaultSubobject(TEXT("Vagina")); - VaginaMeshComponent->SetupAttachment(GetMesh()); - HeadMeshComponent = CreateDefaultSubobject(TEXT("Head")); - HeadMeshComponent->SetupAttachment(GetMesh()); - NeckMeshComponent = CreateDefaultSubobject(TEXT("Neck")); - NeckMeshComponent->SetupAttachment(GetMesh()); - FaceMeshComponent = CreateDefaultSubobject(TEXT("Face")); - FaceMeshComponent->SetupAttachment(GetMesh()); - EyesMeshComponent = CreateDefaultSubobject(TEXT("Eyes")); - EyesMeshComponent->SetupAttachment(GetMesh()); - BodyMeshComponent = CreateDefaultSubobject(TEXT("Body")); - BodyMeshComponent->SetupAttachment(GetMesh()); - TopMeshComponent = CreateDefaultSubobject(TEXT("Top")); - TopMeshComponent->SetupAttachment(GetMesh()); - BottomMeshComponent = CreateDefaultSubobject(TEXT("Bottom")); - BottomMeshComponent->SetupAttachment(GetMesh()); - BraMeshComponent = CreateDefaultSubobject(TEXT("Bra")); - BraMeshComponent->SetupAttachment(GetMesh()); - PantiesMeshComponent = CreateDefaultSubobject(TEXT("Panties")); - PantiesMeshComponent->SetupAttachment(GetMesh()); - SocksMeshComponent = CreateDefaultSubobject(TEXT("Socks")); - SocksMeshComponent->SetupAttachment(GetMesh()); - ShoesMeshComponent = CreateDefaultSubobject(TEXT("Shoes")); - ShoesMeshComponent->SetupAttachment(GetMesh()); -} - -void APlayerImpostor::OnClothingEquip(UClothingItemInstance* ClothingItemInstance) -{ - EquipClothing(ClothingItemInstance); -} - -void APlayerImpostor::OnClothingUnequip(UClothingItemInstance* ClothingItemInstance) -{ - UnequipClothing(ClothingItemInstance); + ClothingVisualsComponent = CreateDefaultSubobject(TEXT("Clothing Visuals Component")); } void APlayerImpostor::BeginPlay() @@ -66,73 +29,5 @@ void APlayerImpostor::BeginPlay() return; } - Player->ClothingManager->OnClothingEquip.AddUniqueDynamic(this, &APlayerImpostor::OnClothingEquip); - Player->ClothingManager->OnClothingUnequip.AddUniqueDynamic(this, &APlayerImpostor::OnClothingUnequip); - - for (const UClothingItemInstance* ClothingItemInstance : Player->ClothingManager->GetEquippedClothing()) - { - EquipClothing(ClothingItemInstance); - } -} - -USkeletalMeshComponent* APlayerImpostor::GetMeshByType(const EClothingSlotType SlotType) const -{ - switch (SlotType) - { - case EClothingSlotType::Nipples: - return NipplesMeshComponent; - case EClothingSlotType::Anal: - return AnalMeshComponent; - case EClothingSlotType::Vagina: - return VaginaMeshComponent; - case EClothingSlotType::Head: - return HeadMeshComponent; - case EClothingSlotType::Neck: - return NeckMeshComponent; - case EClothingSlotType::Face: - return FaceMeshComponent; - case EClothingSlotType::Eyes: - return EyesMeshComponent; - case EClothingSlotType::Bodysuit: - return BodyMeshComponent; - case EClothingSlotType::Top: - return TopMeshComponent; - case EClothingSlotType::Bottom: - return BottomMeshComponent; - case EClothingSlotType::UnderwearTop: - return BraMeshComponent; - case EClothingSlotType::UnderwearBottom: - return PantiesMeshComponent; - case EClothingSlotType::Socks: - return SocksMeshComponent; - case EClothingSlotType::Footwear: - return ShoesMeshComponent; - default: - return NipplesMeshComponent; - } -} - -void APlayerImpostor::EquipClothing(const UClothingItemInstance* ClothingItemInstance) -{ - USkeletalMeshComponent* MeshComponent = GetMeshByType(ClothingItemInstance->GetClothingItemDefinition()->SlotType); - MeshComponent->SetSkeletalMesh(ClothingItemInstance->GetClothingItemDefinition()->SkeletalMesh); - if (ClothingItemInstance->GetClothingItemDefinition()->UseLeaderPose) - { - MeshComponent->SetLeaderPoseComponent(GetMesh()); - } - - if (!ClothingItemInstance->GetClothingItemDefinition()->Materials.IsEmpty()) - { - for (const TPair& Material : ClothingItemInstance->GetClothingItemDefinition()->Materials) - { - MeshComponent->SetMaterialByName(Material.Key, Material.Value); - } - } -} - -void APlayerImpostor::UnequipClothing(const UClothingItemInstance* ClothingItemInstance) -{ - USkeletalMeshComponent* MeshComponent = GetMeshByType(ClothingItemInstance->GetClothingItemDefinition()->SlotType); - MeshComponent->SetSkeletalMesh(nullptr); - MeshComponent->SetLeaderPoseComponent(nullptr); -} + ClothingVisualsComponent->Initialize(GetMesh(), Player->ClothingManager); +} \ No newline at end of file diff --git a/Source/NakedDesire/Player/PlayerImpostor.h b/Source/NakedDesire/Player/PlayerImpostor.h index 12215454..561d0043 100644 --- a/Source/NakedDesire/Player/PlayerImpostor.h +++ b/Source/NakedDesire/Player/PlayerImpostor.h @@ -1,12 +1,11 @@ -#pragma once +#pragma once #include "CoreMinimal.h" -#include "GameFramework/Actor.h" -#include "NakedDesire/Clothing/ClothingSlotType.h" +#include "GameFramework/Pawn.h" #include "PlayerImpostor.generated.h" -class UClothingItemInstance; class ANakedDesireCharacter; +class UClothingVisualsComponent; UCLASS() class NAKEDDESIRE_API APlayerImpostor : public APawn @@ -20,46 +19,7 @@ class NAKEDDESIRE_API APlayerImpostor : public APawn USkeletalMeshComponent* Mesh; UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, meta = (AllowPrivateAccess = true), Category = "Clothing") - USkeletalMeshComponent* NipplesMeshComponent; - - UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, meta = (AllowPrivateAccess = true), Category = "Clothing") - USkeletalMeshComponent* AnalMeshComponent; - - UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, meta = (AllowPrivateAccess = true), Category = "Clothing") - USkeletalMeshComponent* VaginaMeshComponent; - - UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, meta = (AllowPrivateAccess = true), Category = "Clothing") - USkeletalMeshComponent* HeadMeshComponent; - - UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, meta = (AllowPrivateAccess = true), Category = "Clothing") - USkeletalMeshComponent* NeckMeshComponent; - - UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, meta = (AllowPrivateAccess = true), Category = "Clothing") - USkeletalMeshComponent* FaceMeshComponent; - - UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, meta = (AllowPrivateAccess = true), Category = "Clothing") - USkeletalMeshComponent* EyesMeshComponent; - - UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, meta = (AllowPrivateAccess = true), Category = "Clothing") - USkeletalMeshComponent* BodyMeshComponent; - - UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, meta = (AllowPrivateAccess = true), Category = "Clothing") - USkeletalMeshComponent* TopMeshComponent; - - UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, meta = (AllowPrivateAccess = true), Category = "Clothing") - USkeletalMeshComponent* BottomMeshComponent; - - UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, meta = (AllowPrivateAccess = true), Category = "Clothing") - USkeletalMeshComponent* BraMeshComponent; - - UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, meta = (AllowPrivateAccess = true), Category = "Clothing") - USkeletalMeshComponent* PantiesMeshComponent; - - UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, meta = (AllowPrivateAccess = true), Category = "Clothing") - USkeletalMeshComponent* SocksMeshComponent; - - UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, meta = (AllowPrivateAccess = true), Category = "Clothing") - USkeletalMeshComponent* ShoesMeshComponent; + UClothingVisualsComponent* ClothingVisualsComponent; UPROPERTY() ANakedDesireCharacter* Player; @@ -70,14 +30,5 @@ public: virtual void BeginPlay() override; private: - UFUNCTION() - void OnClothingEquip(UClothingItemInstance* ClothingItemInstance); - - UFUNCTION() - void OnClothingUnequip(UClothingItemInstance* ClothingItemInstance); - - USkeletalMeshComponent* GetMesh() const { return Mesh; }; - USkeletalMeshComponent* GetMeshByType(const EClothingSlotType SlotType) const; - void EquipClothing(const UClothingItemInstance* ClothingItemInstance); - void UnequipClothing(const UClothingItemInstance* ClothingItemInstance); -}; + USkeletalMeshComponent* GetMesh() const { return Mesh; } +}; \ No newline at end of file