This commit is contained in:
2026-05-17 22:44:49 +03:00
commit 26fedadcd8
9071 changed files with 44364 additions and 0 deletions
@@ -0,0 +1,4 @@
// © 2025 Naked People Team. All Rights Reserved.
#include "ClothingItem.h"
@@ -0,0 +1,49 @@
// © 2025 Naked People Team. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "ClothingSlotType.h"
#include "Engine/DataAsset.h"
#include "NakedDesire/Player/PrivateBodyPartType.h"
#include "ClothingItem.generated.h"
/**
*
*/
UCLASS(BlueprintType)
class NAKEDDESIRE_API UClothingItem : public UPrimaryDataAsset
{
GENERATED_BODY()
public:
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
FText Name;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
UTexture2D* Icon;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
EClothingSlotType SlotType;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
USkeletalMesh* SkeletalMesh;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
TMap<FName, UMaterialInstance*> Materials;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
UStaticMesh* StaticMesh;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
int BasePrice;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
TArray<EPrivateBodyPartType> CoveredBodyParts;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, meta = (EditCondition = "SlotType == EClothingSlotType::Shoes", Category = "Shoes"))
float ShoesOffset = 0.0f;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
bool UseLeaderPose = false;
};
@@ -0,0 +1,25 @@
// © 2025 Naked People Team. All Rights Reserved.
#include "ClothingItemData.h"
#include "../SaveGame/ClothingItemSaveData.h"
FClothingItemSaveData UClothingItemData::ToSaveData() const
{
FClothingItemSaveData SaveData;
SaveData.ClothingItem = Info;
return SaveData;
}
UClothingItemData* UClothingItemData::CreateFromSaveData(const FClothingItemSaveData& SaveData)
{
UClothingItem* ClothingItem = SaveData.ClothingItem.LoadSynchronous();
UClothingItemData* ClothingItemData = NewObject<UClothingItemData>();
ClothingItemData->Info = ClothingItem;
return ClothingItemData;
}
@@ -0,0 +1,27 @@
// © 2025 Naked People Team. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "ClothingItem.h"
#include "ClothingItemData.generated.h"
struct FClothingItemSaveData;
/**
*
*/
UCLASS(EditInlineNew, BlueprintType)
class NAKEDDESIRE_API UClothingItemData : public UObject
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadOnly, EditDefaultsOnly)
UClothingItem* Info = nullptr;
UFUNCTION(BlueprintCallable)
FClothingItemSaveData ToSaveData() const;
UFUNCTION(BlueprintCallable)
static UClothingItemData* CreateFromSaveData(const FClothingItemSaveData& SaveData);
};
@@ -0,0 +1,5 @@
// © 2025 Naked People Team. All Rights Reserved.
#include "ClothingList.h"
@@ -0,0 +1,22 @@
// © 2025 Naked People Team. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "Engine/DataAsset.h"
#include "ClothingList.generated.h"
class UClothingItemData;
/**
*
*/
UCLASS()
class NAKEDDESIRE_API UClothingList : public UPrimaryDataAsset
{
GENERATED_BODY()
public:
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Instanced)
TArray<UClothingItemData*> ClothingItems;
};
@@ -0,0 +1,186 @@
// © 2025 Naked People Team. All Rights Reserved.
#include "ClothingManager.h"
#include "ClothingItemData.h"
#include "GameFramework/Character.h"
#include "NakedDesire/SaveGame/GlobalSaveGameData.h"
UClothingManager::UClothingManager()
{
PrimaryComponentTick.bCanEverTick = false;
}
bool UClothingManager::IsBodyTypeExposed(const EPrivateBodyPartType PrivateBodyPartType)
{
for (const auto& ClothingSlot : ClothingSlots)
{
if (ClothingSlot.ClothingData && ClothingSlot.ClothingData->Info->CoveredBodyParts.Contains(PrivateBodyPartType))
{
return false;
}
}
return true;
}
bool UClothingManager::GetClothingSlotData(const EClothingSlotType ClothingSlotType, FClothingSlotData& OutClothingSlotData)
{
for (const auto& ClothingSlot : ClothingSlots)
{
if (ClothingSlot.ClothingSlotType == ClothingSlotType)
{
OutClothingSlotData = ClothingSlot;
return true;
}
}
return false;
}
void UClothingManager::SetClothingSlotItem(const EClothingSlotType ClothingSlotType, UClothingItemData* ClothingItem)
{
for (FClothingSlotData& ClothingSlot : ClothingSlots)
{
if (ClothingSlot.ClothingSlotType == ClothingSlotType)
{
ClothingSlot.ClothingData = ClothingItem;
}
}
}
TArray<UClothingItemData*> UClothingManager::GetEquippedClothing()
{
TArray<UClothingItemData*> EquippedClothingItems;
for (FClothingSlotData ClothingSlot : ClothingSlots)
{
if (ClothingSlot.ClothingData)
{
EquippedClothingItems.Add(ClothingSlot.ClothingData);
}
}
return EquippedClothingItems;
}
void UClothingManager::HydrateClothing(UGlobalSaveGameData* SaveGameData)
{
for (const FClothingItemSaveData& ClothingItemSaveData : SaveGameData->PlayerClothing)
{
UClothingItemData* ClothingItemData = UClothingItemData::CreateFromSaveData(ClothingItemSaveData);
PutOnClothing(ClothingItemData);
}
}
float UClothingManager::GetHeelHeight()
{
if (FClothingSlotData ClothingSlotData; GetClothingSlotData(EClothingSlotType::Shoes, ClothingSlotData))
{
if (ClothingSlotData.ClothingData)
{
return ClothingSlotData.ClothingData->Info->ShoesOffset;
}
}
return 0;
}
void UClothingManager::PutOnClothing(UClothingItemData* ClothingData)
{
if (!ClothingData)
{
return;
}
const EClothingSlotType ClothingSlotType = ClothingData->Info->SlotType;
FClothingSlotData ClothingSlotData;
GetClothingSlotData(ClothingSlotType, ClothingSlotData);
ClothingSlotData.MeshComponent->SetSkeletalMesh(ClothingData->Info->SkeletalMesh);
if (!ClothingData->Info->Materials.IsEmpty())
{
for (const TPair<FName, UMaterialInstance*>& Material : ClothingData->Info->Materials)
{
ClothingSlotData.MeshComponent->SetMaterialByName(Material.Key, Material.Value);
}
}
SetClothingSlotItem(ClothingSlotType, ClothingData);
if (ClothingData->Info->UseLeaderPose)
{
ClothingSlotData.MeshComponent->SetLeaderPoseComponent(Cast<ACharacter>(GetOwner())->GetMesh());
}
OnClothingEquip.Broadcast(ClothingData);
}
void UClothingManager::TakeClothing(UClothingItemData* ClothingData)
{
if (!ClothingData->Info)
{
return;
}
FClothingSlotData ClothingSlotData;
GetClothingSlotData(ClothingData->Info->SlotType, ClothingSlotData);
if (ClothingSlotData.ClothingData->Info)
{
DropClothing(ClothingData->Info->SlotType);
}
ClothingSlotData.ClothingData = ClothingData;
PutOnClothing(ClothingData);
}
UClothingItemData* UClothingManager::RemoveClothing(const EClothingSlotType ClothingSlotType)
{
FClothingSlotData ClothingSlotData;
if (!GetClothingSlotData(ClothingSlotType, ClothingSlotData) || !ClothingSlotData.ClothingData)
{
UE_LOG(LogTemp, Error, TEXT("Couldn't find clothing slot"));
return nullptr;
}
UClothingItemData* ClothingData = ClothingSlotData.ClothingData;
SetClothingSlotItem(ClothingSlotType, nullptr);
USkeletalMeshComponent* MeshComponent = ClothingSlotData.MeshComponent;
MeshComponent->SetSkeletalMesh(nullptr);
if (ClothingData->Info->UseLeaderPose)
{
ClothingSlotData.MeshComponent->SetLeaderPoseComponent(nullptr);
}
OnClothingUnequip.Broadcast(ClothingData);
return ClothingData;
}
void UClothingManager::DropClothing(const EClothingSlotType ClothingType)
{
const UClothingItemData* ClothingData = RemoveClothing(ClothingType);
if (!ClothingData)
{
return;
}
OnClothingDropped.Broadcast(ClothingData);
}
bool UClothingManager::IsClothingTypeOn(const EClothingSlotType ClothingType)
{
FClothingSlotData ClothingSlotData;
GetClothingSlotData(ClothingType, ClothingSlotData);
const bool IsTypeOn = ClothingSlotData.ClothingData != nullptr;
return IsTypeOn;
}
bool UClothingManager::IsPartiallyNaked()
{
return IsBodyTypeExposed(EPrivateBodyPartType::BackBottom) || IsBodyTypeExposed(EPrivateBodyPartType::FrontBottom) || IsBodyTypeExposed(EPrivateBodyPartType::FrontTop);
}
@@ -0,0 +1,79 @@
// © 2025 Naked People Team. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "ClothingSlotData.h"
#include "Components/ActorComponent.h"
#include "NakedDesire/Player/PrivateBodyPartType.h"
#include "ClothingManager.generated.h"
// TODO: Check clothing colors
class UGlobalSaveGameData;
class AClothingPickup;
class UClothingItemData;
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnClothingChangeSignature, const UClothingItemData*, ClothingData);
UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class NAKEDDESIRE_API UClothingManager : public UActorComponent
{
GENERATED_BODY()
public:
UClothingManager();
UPROPERTY(BlueprintReadWrite, Category = "Clothing Manager|Clothing")
USkeletalMeshComponent* RootMesh = nullptr;
UPROPERTY(BlueprintReadWrite, Category = "Clothing Manager|Clothing")
TArray<FClothingSlotData> ClothingSlots;
UPROPERTY(BlueprintAssignable)
FOnClothingChangeSignature OnClothingEquip;
UPROPERTY(BlueprintAssignable)
FOnClothingChangeSignature OnClothingUnequip;
UPROPERTY(BlueprintAssignable)
FOnClothingChangeSignature OnClothingDropped;
UFUNCTION(BlueprintCallable)
void PutOnClothing(UClothingItemData* ClothingData);
UFUNCTION(BlueprintCallable)
void DropClothing(const EClothingSlotType ClothingType);
UFUNCTION(BlueprintCallable)
bool IsClothingTypeOn(const EClothingSlotType ClothingType);
UFUNCTION(BlueprintCallable)
bool IsPartiallyNaked();
UFUNCTION(BlueprintCallable)
bool IsBodyTypeExposed(EPrivateBodyPartType PrivateBodyPartType);
UFUNCTION(BlueprintCallable)
void TakeClothing(UClothingItemData* ClothingData);
UFUNCTION(BlueprintCallable)
UClothingItemData* RemoveClothing(EClothingSlotType ClothingSlotType);
UFUNCTION(BlueprintCallable)
bool GetClothingSlotData(EClothingSlotType ClothingSlotType, FClothingSlotData& OutClothingSlotData);
UFUNCTION(BlueprintCallable)
void SetClothingSlotItem(const EClothingSlotType ClothingSlotType, UClothingItemData* ClothingItem);
UFUNCTION(BlueprintCallable)
TArray<UClothingItemData*> GetEquippedClothing();
void HydrateClothing(UGlobalSaveGameData* SaveGameData);
UFUNCTION(BlueprintPure)
float GetHeelHeight();
};
@@ -0,0 +1,45 @@
// © 2025 Naked People Team. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "ClothingSlotType.h"
#include "ClothingSlotData.generated.h"
enum class EClothingSlotType : uint8;
class UClothingItemData;
/**
*
*/
USTRUCT(BlueprintType)
struct NAKEDDESIRE_API FClothingSlotData
{
GENERATED_BODY()
FClothingSlotData()
: MeshComponent(nullptr), ClothingSlotType(EClothingSlotType::Anal), ClothingData(nullptr), Name(FText::GetEmpty())
{
}
FClothingSlotData(USkeletalMeshComponent* MeshComponent, const EClothingSlotType ClothingSlotType, UClothingItemData* ClothingData, const FText& Name)
{
this->MeshComponent = MeshComponent;
this->ClothingSlotType = ClothingSlotType;
this->ClothingData = ClothingData;
this->Name = Name;
}
UPROPERTY(BlueprintReadWrite, Category = "Clothing")
USkeletalMeshComponent* MeshComponent = nullptr;
UPROPERTY(BlueprintReadWrite, Category = "Clothing")
EClothingSlotType ClothingSlotType = EClothingSlotType::Anal;
UPROPERTY(BlueprintReadWrite, Category = "Clothing")
UClothingItemData* ClothingData = nullptr;
UPROPERTY(BlueprintReadWrite, Category = "Clothing")
FText Name = FText::GetEmpty();
};
@@ -0,0 +1,27 @@
// © 2025 Naked People Team. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
/**
*
*/
UENUM(BlueprintType)
enum class EClothingSlotType : uint8
{
Nipples,
Anal,
Vagina,
Head,
Neck,
Face,
Eyes,
Body,
Top,
Bottom,
Bra,
Panties,
Socks,
Shoes,
};
@@ -0,0 +1,14 @@
// © 2025 Naked People Team. All Rights Reserved.
#pragma once
#include "ClothingSlotWidgetData.generated.h"
USTRUCT(BlueprintType)
struct NAKEDDESIRE_API FClothingSlotWidgetData
{
GENERATED_BODY()
UPROPERTY(EditDefaultsOnly)
UTexture2D* PlaceholderIcon = nullptr;
};
@@ -0,0 +1,5 @@
// © 2025 Naked People Team. All Rights Reserved.
#include "ClothingSlotWidgetsInfo.h"
@@ -0,0 +1,22 @@
// © 2025 Naked People Team. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "ClothingSlotWidgetData.h"
#include "ClothingSlotType.h"
#include "Engine/DataAsset.h"
#include "ClothingSlotWidgetsInfo.generated.h"
/**
*
*/
UCLASS()
class NAKEDDESIRE_API UClothingSlotInfo : public UPrimaryDataAsset
{
GENERATED_BODY()
public:
UPROPERTY(EditDefaultsOnly)
TMap<EClothingSlotType, FClothingSlotWidgetData> ClothingSlotsData;
};