setup equipment ui
This commit is contained in:
@@ -1 +1,8 @@
|
||||
#include "GameLayoutWidget.h"
|
||||
#include "Widgets/CommonActivatableWidgetContainer.h"
|
||||
#include "Inventory/InventoryScreenWidget.h"
|
||||
|
||||
void UGameLayoutWidget::OpenInventory()
|
||||
{
|
||||
InventoryScreenWidget = WidgetStack->AddWidget<UInventoryScreenWidget>(InventoryScreenWidgetClass);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "CommonUserWidget.h"
|
||||
#include "GameLayoutWidget.generated.h"
|
||||
|
||||
class UInventoryScreenWidget;
|
||||
class UHUDWidget;
|
||||
class UCommonActivatableWidgetStack;
|
||||
|
||||
@@ -17,4 +18,13 @@ class NAKEDDESIRE_API UGameLayoutWidget : public UCommonUserWidget
|
||||
|
||||
UPROPERTY(meta = (BindWidget))
|
||||
TObjectPtr<UHUDWidget> HUD;
|
||||
|
||||
UPROPERTY(EditDefaultsOnly, Category = "UI")
|
||||
TSubclassOf<UInventoryScreenWidget> InventoryScreenWidgetClass;
|
||||
|
||||
UPROPERTY()
|
||||
TObjectPtr<UInventoryScreenWidget> InventoryScreenWidget;
|
||||
|
||||
public:
|
||||
void OpenInventory();
|
||||
};
|
||||
|
||||
@@ -2,3 +2,63 @@
|
||||
|
||||
|
||||
#include "EquipmentPanelWidget.h"
|
||||
|
||||
#include "EquipmentSlotWidget.h"
|
||||
|
||||
void UEquipmentPanelWidget::NativeConstruct()
|
||||
{
|
||||
Super::NativeConstruct();
|
||||
|
||||
InitSlotTypes();
|
||||
|
||||
const TArray<UEquipmentSlotWidget*> AllSlots = {
|
||||
NipplesSlot, AnalSlot, VaginaSlot,
|
||||
HeadSlot, NeckSlot, FaceSlot, EyesSlot,
|
||||
BodysuitSlot, TopSlot, BottomSlot,
|
||||
UnderwearTopSlot, UnderwearBottomSlot,
|
||||
SocksSlot, FootwearSlot, OuterwearSlot,
|
||||
WristRestraintSlot, AnkleRestraintSlot, NeckRestraintSlot
|
||||
};
|
||||
|
||||
for (UEquipmentSlotWidget* Slot : AllSlots)
|
||||
{
|
||||
if (Slot)
|
||||
{
|
||||
Slot->OnEquipmentSlotClicked.BindUObject(this, &UEquipmentPanelWidget::HandleSlotClicked);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UEquipmentPanelWidget::NativePreConstruct()
|
||||
{
|
||||
Super::NativePreConstruct();
|
||||
|
||||
InitSlotTypes();
|
||||
}
|
||||
|
||||
void UEquipmentPanelWidget::HandleSlotClicked(UEquipmentSlotWidget* SlotWidget)
|
||||
{
|
||||
OnSlotClicked.ExecuteIfBound(SlotWidget);
|
||||
}
|
||||
|
||||
void UEquipmentPanelWidget::InitSlotTypes()
|
||||
{
|
||||
if (NipplesSlot) NipplesSlot->SetSlotType(EClothingSlotType::Nipples);
|
||||
if (AnalSlot) AnalSlot->SetSlotType(EClothingSlotType::Anal);
|
||||
if (VaginaSlot) VaginaSlot->SetSlotType(EClothingSlotType::Vagina);
|
||||
if (HeadSlot) HeadSlot->SetSlotType(EClothingSlotType::Head);
|
||||
if (NeckSlot) NeckSlot->SetSlotType(EClothingSlotType::Neck);
|
||||
if (FaceSlot) FaceSlot->SetSlotType(EClothingSlotType::Face);
|
||||
if (EyesSlot) EyesSlot->SetSlotType(EClothingSlotType::Eyes);
|
||||
if (BodysuitSlot) BodysuitSlot->SetSlotType(EClothingSlotType::Bodysuit);
|
||||
if (TopSlot) TopSlot->SetSlotType(EClothingSlotType::Top);
|
||||
if (BottomSlot) BottomSlot->SetSlotType(EClothingSlotType::Bottom);
|
||||
if (UnderwearTopSlot) UnderwearTopSlot->SetSlotType(EClothingSlotType::UnderwearTop);
|
||||
if (UnderwearBottomSlot) UnderwearBottomSlot->SetSlotType(EClothingSlotType::UnderwearBottom);
|
||||
if (SocksSlot) SocksSlot->SetSlotType(EClothingSlotType::Socks);
|
||||
if (FootwearSlot) FootwearSlot->SetSlotType(EClothingSlotType::Footwear);
|
||||
if (OuterwearSlot) OuterwearSlot->SetSlotType(EClothingSlotType::Outerwear);
|
||||
if (WristRestraintSlot) WristRestraintSlot->SetSlotType(EClothingSlotType::WristRestraint);
|
||||
if (AnkleRestraintSlot) AnkleRestraintSlot->SetSlotType(EClothingSlotType::AnkleRestraint);
|
||||
if (NeckRestraintSlot) NeckRestraintSlot->SetSlotType(EClothingSlotType::NeckRestraint);
|
||||
}
|
||||
|
||||
@@ -6,11 +6,76 @@
|
||||
#include "CommonUserWidget.h"
|
||||
#include "EquipmentPanelWidget.generated.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
class UEquipmentSlotWidget;
|
||||
|
||||
UCLASS(Abstract)
|
||||
class NAKEDDESIRE_API UEquipmentPanelWidget : public UCommonUserWidget
|
||||
{
|
||||
GENERATED_BODY()
|
||||
};
|
||||
|
||||
public:
|
||||
DECLARE_DELEGATE_OneParam(FOnSlotClicked, UEquipmentSlotWidget*);
|
||||
FOnSlotClicked OnSlotClicked;
|
||||
|
||||
protected:
|
||||
virtual void NativeConstruct() override;
|
||||
virtual void NativePreConstruct() override;
|
||||
|
||||
private:
|
||||
UPROPERTY(meta = (BindWidgetOptional))
|
||||
TObjectPtr<UEquipmentSlotWidget> NipplesSlot;
|
||||
|
||||
UPROPERTY(meta = (BindWidgetOptional))
|
||||
TObjectPtr<UEquipmentSlotWidget> AnalSlot;
|
||||
|
||||
UPROPERTY(meta = (BindWidgetOptional))
|
||||
TObjectPtr<UEquipmentSlotWidget> VaginaSlot;
|
||||
|
||||
UPROPERTY(meta = (BindWidgetOptional))
|
||||
TObjectPtr<UEquipmentSlotWidget> HeadSlot;
|
||||
|
||||
UPROPERTY(meta = (BindWidgetOptional))
|
||||
TObjectPtr<UEquipmentSlotWidget> NeckSlot;
|
||||
|
||||
UPROPERTY(meta = (BindWidgetOptional))
|
||||
TObjectPtr<UEquipmentSlotWidget> FaceSlot;
|
||||
|
||||
UPROPERTY(meta = (BindWidgetOptional))
|
||||
TObjectPtr<UEquipmentSlotWidget> EyesSlot;
|
||||
|
||||
UPROPERTY(meta = (BindWidgetOptional))
|
||||
TObjectPtr<UEquipmentSlotWidget> BodysuitSlot;
|
||||
|
||||
UPROPERTY(meta = (BindWidgetOptional))
|
||||
TObjectPtr<UEquipmentSlotWidget> TopSlot;
|
||||
|
||||
UPROPERTY(meta = (BindWidgetOptional))
|
||||
TObjectPtr<UEquipmentSlotWidget> BottomSlot;
|
||||
|
||||
UPROPERTY(meta = (BindWidgetOptional))
|
||||
TObjectPtr<UEquipmentSlotWidget> UnderwearTopSlot;
|
||||
|
||||
UPROPERTY(meta = (BindWidgetOptional))
|
||||
TObjectPtr<UEquipmentSlotWidget> UnderwearBottomSlot;
|
||||
|
||||
UPROPERTY(meta = (BindWidgetOptional))
|
||||
TObjectPtr<UEquipmentSlotWidget> SocksSlot;
|
||||
|
||||
UPROPERTY(meta = (BindWidgetOptional))
|
||||
TObjectPtr<UEquipmentSlotWidget> FootwearSlot;
|
||||
|
||||
UPROPERTY(meta = (BindWidgetOptional))
|
||||
TObjectPtr<UEquipmentSlotWidget> OuterwearSlot;
|
||||
|
||||
UPROPERTY(meta = (BindWidgetOptional))
|
||||
TObjectPtr<UEquipmentSlotWidget> WristRestraintSlot;
|
||||
|
||||
UPROPERTY(meta = (BindWidgetOptional))
|
||||
TObjectPtr<UEquipmentSlotWidget> AnkleRestraintSlot;
|
||||
|
||||
UPROPERTY(meta = (BindWidgetOptional))
|
||||
TObjectPtr<UEquipmentSlotWidget> NeckRestraintSlot;
|
||||
|
||||
void HandleSlotClicked(UEquipmentSlotWidget* SlotWidget);
|
||||
void InitSlotTypes();
|
||||
};
|
||||
@@ -0,0 +1,29 @@
|
||||
// © 2025 Naked People Team. All Rights Reserved.
|
||||
|
||||
|
||||
#include "EquipmentSlotMenuWidget.h"
|
||||
|
||||
#include "Components/Button.h"
|
||||
#include "Kismet/GameplayStatics.h"
|
||||
#include "NakedDesire/Clothing/ClothingManager.h"
|
||||
#include "NakedDesire/Player/NakedDesireCharacter.h"
|
||||
|
||||
void UEquipmentSlotMenuWidget::Init(const EClothingSlotType InSlotType)
|
||||
{
|
||||
SlotType = InSlotType;
|
||||
}
|
||||
|
||||
void UEquipmentSlotMenuWidget::NativeConstruct()
|
||||
{
|
||||
Super::NativeConstruct();
|
||||
|
||||
Player = Cast<ANakedDesireCharacter>(UGameplayStatics::GetPlayerCharacter(GetWorld(), 0));
|
||||
|
||||
DropClothingBtn->OnClicked.AddUniqueDynamic(this, &UEquipmentSlotMenuWidget::OnDropClothingClicked);
|
||||
}
|
||||
|
||||
void UEquipmentSlotMenuWidget::OnDropClothingClicked()
|
||||
{
|
||||
Player->ClothingManager->DropClothing(SlotType);
|
||||
OnActionPerformed.Broadcast();
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
// © 2025 Naked People Team. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "CommonUserWidget.h"
|
||||
#include "NakedDesire/Clothing/ClothingSlotType.h"
|
||||
#include "EquipmentSlotMenuWidget.generated.h"
|
||||
|
||||
class ANakedDesireCharacter;
|
||||
class UButton;
|
||||
|
||||
UCLASS(Abstract)
|
||||
class NAKEDDESIRE_API UEquipmentSlotMenuWidget : public UCommonUserWidget
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
void Init(EClothingSlotType InSlotType);
|
||||
|
||||
EClothingSlotType GetSlotType() const { return SlotType; }
|
||||
|
||||
DECLARE_MULTICAST_DELEGATE(FOnActionPerformed);
|
||||
FOnActionPerformed OnActionPerformed;
|
||||
|
||||
protected:
|
||||
virtual void NativeConstruct() override;
|
||||
|
||||
private:
|
||||
UPROPERTY(meta = (BindWidget))
|
||||
TObjectPtr<UButton> DropClothingBtn;
|
||||
|
||||
UPROPERTY()
|
||||
TObjectPtr<ANakedDesireCharacter> Player;
|
||||
|
||||
UPROPERTY()
|
||||
EClothingSlotType SlotType;
|
||||
|
||||
UFUNCTION()
|
||||
void OnDropClothingClicked();
|
||||
};
|
||||
@@ -2,34 +2,88 @@
|
||||
|
||||
|
||||
#include "EquipmentSlotWidget.h"
|
||||
#include "Kismet/GameplayStatics.h"
|
||||
#include "NakedDesire/Clothing/ClothingItem.h"
|
||||
#include "NakedDesire/Clothing/ClothingItemInstance.h"
|
||||
#include "NakedDesire/Clothing/ClothingManager.h"
|
||||
#include "NakedDesire/Clothing/ClothingSlotsData.h"
|
||||
#include "NakedDesire/Player/NakedDesireCharacter.h"
|
||||
|
||||
void UEquipmentSlotWidget::SetItem(UClothingItemInstance* InItem)
|
||||
{
|
||||
ClothingItemInstance = InItem;
|
||||
|
||||
IconImage->SetBrushFromTexture(InItem->GetClothingItem()->Icon);
|
||||
IconImage->SetVisibility(ESlateVisibility::SelfHitTestInvisible);
|
||||
SetIsEnabled(true);
|
||||
}
|
||||
|
||||
void UEquipmentSlotWidget::ClearItem()
|
||||
{
|
||||
ClothingItemInstance = nullptr;
|
||||
|
||||
IconImage->SetBrushFromTexture(nullptr);
|
||||
IconImage->SetVisibility(ESlateVisibility::Hidden);
|
||||
SetIsEnabled(false);
|
||||
}
|
||||
|
||||
void UEquipmentSlotWidget::NativeOnClicked()
|
||||
{
|
||||
Super::NativeOnClicked();
|
||||
|
||||
OnEquipmentSlotClicked.ExecuteIfBound(this);
|
||||
}
|
||||
|
||||
void UEquipmentSlotWidget::NativePreConstruct()
|
||||
{
|
||||
Super::NativePreConstruct();
|
||||
|
||||
// if (!ClothingSlotsData->Slots.Contains(SlotType))
|
||||
// return;
|
||||
|
||||
// FClothingSlotData& SlotData = ClothingSlotsData->Slots[SlotType];
|
||||
// PlaceholderImage->SetBrushFromTexture(&SlotData.Icon);
|
||||
InitSlotVisuals();
|
||||
}
|
||||
|
||||
void UEquipmentSlotWidget::OnClothingEquip(UClothingItemInstance* InClothingItemInstance)
|
||||
{
|
||||
if (InClothingItemInstance->GetClothingItem()->SlotType != SlotType)
|
||||
return;
|
||||
|
||||
SetItem(InClothingItemInstance);
|
||||
}
|
||||
|
||||
void UEquipmentSlotWidget::OnClothingUnequip(UClothingItemInstance* InClothingItemInstance)
|
||||
{
|
||||
if (InClothingItemInstance->GetClothingItem()->SlotType != SlotType)
|
||||
return;
|
||||
|
||||
ClearItem();
|
||||
}
|
||||
|
||||
void UEquipmentSlotWidget::InitSlotVisuals()
|
||||
{
|
||||
if (!ClothingSlotsData)
|
||||
return;
|
||||
|
||||
const FClothingSlotData& SlotData = ClothingSlotsData->Slots[SlotType];
|
||||
PlaceholderImage->SetBrushFromTexture(SlotData.Icon);
|
||||
}
|
||||
|
||||
void UEquipmentSlotWidget::SetSlotType(const EClothingSlotType InSlotType)
|
||||
{
|
||||
SlotType = InSlotType;
|
||||
|
||||
InitSlotVisuals();
|
||||
}
|
||||
|
||||
void UEquipmentSlotWidget::NativeConstruct()
|
||||
{
|
||||
Super::NativeConstruct();
|
||||
|
||||
const ANakedDesireCharacter* Player = Cast<ANakedDesireCharacter>(UGameplayStatics::GetPlayerCharacter(GetWorld(), 0));
|
||||
|
||||
Player->ClothingManager->OnClothingEquip.AddUniqueDynamic(this, &UEquipmentSlotWidget::OnClothingEquip);
|
||||
Player->ClothingManager->OnClothingUnequip.AddUniqueDynamic(this, &UEquipmentSlotWidget::OnClothingUnequip);
|
||||
|
||||
if (UClothingItemInstance* Item = Player->ClothingManager->GetSlotClothing(SlotType))
|
||||
SetItem(Item);
|
||||
else
|
||||
ClearItem();
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
#include "NakedDesire/Clothing/ClothingSlotType.h"
|
||||
#include "EquipmentSlotWidget.generated.h"
|
||||
|
||||
class UEquipmentSlotMenuWidget;
|
||||
class ANakedDesireCharacter;
|
||||
class UClothingSlotsData;
|
||||
class UClothingItemInstance;
|
||||
|
||||
@@ -19,6 +21,14 @@ class NAKEDDESIRE_API UEquipmentSlotWidget : public UCommonButtonBase
|
||||
public:
|
||||
void SetItem(UClothingItemInstance* InItem);
|
||||
void ClearItem();
|
||||
|
||||
EClothingSlotType GetSlotType() const { return SlotType; }
|
||||
void SetSlotType(EClothingSlotType InSlotType);
|
||||
|
||||
virtual void NativeConstruct() override;
|
||||
|
||||
DECLARE_DELEGATE_OneParam(FOnEquipmentSlotClicked, UEquipmentSlotWidget* EquipmentSLotWidget)
|
||||
FOnEquipmentSlotClicked OnEquipmentSlotClicked;
|
||||
|
||||
protected:
|
||||
virtual void NativeOnClicked() override;
|
||||
@@ -39,4 +49,12 @@ private:
|
||||
|
||||
UPROPERTY()
|
||||
EClothingSlotType SlotType = EClothingSlotType::Anal;
|
||||
|
||||
UFUNCTION()
|
||||
void OnClothingEquip(UClothingItemInstance* InClothingItemInstance);
|
||||
|
||||
UFUNCTION()
|
||||
void OnClothingUnequip(UClothingItemInstance* InClothingItemInstance);
|
||||
|
||||
void InitSlotVisuals();
|
||||
};
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS()
|
||||
UCLASS(Abstract)
|
||||
class NAKEDDESIRE_API UInventoryPanelWidget : public UCommonUserWidget
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
@@ -1 +1,87 @@
|
||||
#include "InventoryScreenWidget.h"
|
||||
|
||||
#include "Components/Button.h"
|
||||
#include "Components/CanvasPanel.h"
|
||||
#include "Components/CanvasPanelSlot.h"
|
||||
#include "EquipmentPanelWidget.h"
|
||||
#include "EquipmentSlotMenuWidget.h"
|
||||
#include "EquipmentSlotWidget.h"
|
||||
|
||||
void UInventoryScreenWidget::NativeOnActivated()
|
||||
{
|
||||
Super::NativeOnActivated();
|
||||
|
||||
if (!EquipmentSlotMenuWidget && EquipmentSlotMenuWidgetClass)
|
||||
{
|
||||
// Place the dynamic menu in the same canvas that hosts the blocker.
|
||||
// The blocker must live in a UCanvasPanel that spans the area where
|
||||
// outside clicks should be captured (typically the screen root canvas).
|
||||
if (UCanvasPanel* MenuCanvas = Cast<UCanvasPanel>(MenuBlocker->GetParent()))
|
||||
{
|
||||
EquipmentSlotMenuWidget = CreateWidget<UEquipmentSlotMenuWidget>(this, EquipmentSlotMenuWidgetClass);
|
||||
if (UCanvasPanelSlot* CanvasSlot = Cast<UCanvasPanelSlot>(MenuCanvas->AddChild(EquipmentSlotMenuWidget)))
|
||||
{
|
||||
CanvasSlot->SetAutoSize(true);
|
||||
CanvasSlot->SetAnchors(FAnchors(0.f, 0.f));
|
||||
// Render above the blocker so menu clicks aren't eaten by it.
|
||||
CanvasSlot->SetZOrder(1);
|
||||
}
|
||||
|
||||
EquipmentSlotMenuWidget->OnActionPerformed.AddUObject(this, &UInventoryScreenWidget::CloseMenu);
|
||||
}
|
||||
|
||||
EquipmentPanelWidget->OnSlotClicked.BindUObject(this, &UInventoryScreenWidget::HandleSlotClicked);
|
||||
MenuBlocker->OnClicked.AddUniqueDynamic(this, &UInventoryScreenWidget::CloseMenu);
|
||||
}
|
||||
|
||||
CloseMenu();
|
||||
}
|
||||
|
||||
void UInventoryScreenWidget::NativeOnDeactivated()
|
||||
{
|
||||
Super::NativeOnDeactivated();
|
||||
|
||||
CloseMenu();
|
||||
}
|
||||
|
||||
void UInventoryScreenWidget::HandleSlotClicked(UEquipmentSlotWidget* SlotWidget)
|
||||
{
|
||||
if (!EquipmentSlotMenuWidget || !SlotWidget)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const bool bMenuOpen = EquipmentSlotMenuWidget->GetVisibility() != ESlateVisibility::Collapsed;
|
||||
if (bMenuOpen && EquipmentSlotMenuWidget->GetSlotType() == SlotWidget->GetSlotType())
|
||||
{
|
||||
CloseMenu();
|
||||
return;
|
||||
}
|
||||
|
||||
EquipmentSlotMenuWidget->Init(SlotWidget->GetSlotType());
|
||||
|
||||
if (UCanvasPanelSlot* MenuSlot = Cast<UCanvasPanelSlot>(EquipmentSlotMenuWidget->Slot))
|
||||
{
|
||||
if (UCanvasPanel* MenuCanvas = Cast<UCanvasPanel>(MenuBlocker->GetParent()))
|
||||
{
|
||||
const FGeometry& SlotGeom = SlotWidget->GetCachedGeometry();
|
||||
const FVector2D AbsPos = SlotGeom.GetAbsolutePosition() + FVector2D(SlotGeom.GetAbsoluteSize().X, 0.f);
|
||||
MenuSlot->SetPosition(MenuCanvas->GetCachedGeometry().AbsoluteToLocal(AbsPos));
|
||||
}
|
||||
}
|
||||
|
||||
MenuBlocker->SetVisibility(ESlateVisibility::Visible);
|
||||
EquipmentSlotMenuWidget->SetVisibility(ESlateVisibility::Visible);
|
||||
}
|
||||
|
||||
void UInventoryScreenWidget::CloseMenu()
|
||||
{
|
||||
if (EquipmentSlotMenuWidget)
|
||||
{
|
||||
EquipmentSlotMenuWidget->SetVisibility(ESlateVisibility::Collapsed);
|
||||
}
|
||||
if (MenuBlocker)
|
||||
{
|
||||
MenuBlocker->SetVisibility(ESlateVisibility::Collapsed);
|
||||
}
|
||||
}
|
||||
@@ -4,8 +4,35 @@
|
||||
#include "CommonActivatableWidget.h"
|
||||
#include "InventoryScreenWidget.generated.h"
|
||||
|
||||
UCLASS()
|
||||
class UButton;
|
||||
class UEquipmentPanelWidget;
|
||||
class UEquipmentSlotMenuWidget;
|
||||
class UEquipmentSlotWidget;
|
||||
|
||||
UCLASS(Abstract)
|
||||
class NAKEDDESIRE_API UInventoryScreenWidget : public UCommonActivatableWidget
|
||||
{
|
||||
GENERATED_BODY()
|
||||
};
|
||||
|
||||
UPROPERTY(EditDefaultsOnly, Category = "UI")
|
||||
TSubclassOf<UEquipmentSlotMenuWidget> EquipmentSlotMenuWidgetClass;
|
||||
|
||||
UPROPERTY()
|
||||
TObjectPtr<UEquipmentSlotMenuWidget> EquipmentSlotMenuWidget;
|
||||
|
||||
UPROPERTY(meta = (BindWidget))
|
||||
TObjectPtr<UEquipmentPanelWidget> EquipmentPanelWidget;
|
||||
|
||||
UPROPERTY(meta = (BindWidget))
|
||||
TObjectPtr<UButton> MenuBlocker;
|
||||
|
||||
protected:
|
||||
virtual void NativeOnActivated() override;
|
||||
virtual void NativeOnDeactivated() override;
|
||||
|
||||
private:
|
||||
void HandleSlotClicked(UEquipmentSlotWidget* SlotWidget);
|
||||
|
||||
UFUNCTION()
|
||||
void CloseMenu();
|
||||
};
|
||||
Reference in New Issue
Block a user