I’m implementing drag and drop operations for my inventory menu via c++.
I have it working, but the only problem is that there appears to be a memory leak in my current implementation. I must be forgetting a step once the operation is done to say i’m done with the object?.
My destructor on my UDragDropOperation only gets called once the game is terminated instead of after a Canceled or Sucessful drag drop operation.
So these objects will build up until the end of the game. For what I see, I’m not keeping any strong references to it.
This is my current implementation.
TTWidgetInventorySlot.h
#pragma once
#include "TTWidgetBase.h"
#include "TTWidgetInventoryItem.h"
#include "Blueprint/UserWidget.h"
#include "TTDragDropOperation.h"
#include "CoreMinimal.h"
#include "TTWidgetInventorySlot.generated.h"
UCLASS()
class MYGAME_API UTTWidgetInventorySlot : public UTTWidgetBase
{
GENERATED_BODY()
public:
UPROPERTY(meta = (BindWidget))
UCanvasPanel *CanvasPanelContent;
UPROPERTY(meta = (BindWidget))
UBorder *BorderBackgroundColor;
UPROPERTY(meta = (BindWidget))
UBorder *BorderBackgroundImage;
UPROPERTY(meta = (BindWidget))
UTTWidgetInventoryItem *WidgetInventoryItem;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, category = "UTTWidgetInventorySlot")
TSubclassOf<class UTTDragDropOperation> DragDropOperationType;
protected:
virtual FReply NativeOnMouseButtonDown(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent) override;
virtual FReply NativeOnMouseButtonUp(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent) override;
virtual void NativeOnDragDetected(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent, UDragDropOperation*& OutOperation) override;
virtual bool NativeOnDrop(const FGeometry& InGeometry, const FDragDropEvent& InDragDropEvent, UDragDropOperation* InOperation) override;
virtual void NativeOnDragCancelled(const FDragDropEvent& InDragDropEvent, UDragDropOperation* InOperation) override;
TTWidgetInventorySlot.cpp
#include "TTWidgetInventorySlot.h"
#include "MyGame.h"
// ========================
// Mouse Events
// ========================
FReply UTTWidgetInventorySlot::NativeOnMouseButtonDown(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent)
{
return UWidgetBlueprintLibrary::DetectDragIfPressed(InMouseEvent, this, EKeys::LeftMouseButton).NativeReply;
}
FReply UTTWidgetInventorySlot::NativeOnMouseButtonUp(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent)
{
return Super::NativeOnMouseButtonUp(InGeometry, InMouseEvent);
}
// ========================
// Drag Drop
// ========================
void UTTWidgetInventorySlot::NativeOnDragDetected(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent, UDragDropOperation*& OutOperation)
{
Super::NativeOnDragDetected(InGeometry, InMouseEvent, OutOperation);
if (DragDropOperationType != nullptr)
{
UDragDropOperation *DragDropOperationRaw = UWidgetBlueprintLibrary::CreateDragDropOperation(DragDropOperationType);
UTTDragDropOperation *DragDropOperation = static_cast<UTTDragDropOperation*>(DragDropOperationRaw);
OutOperation = DragDropOperation;
}
}
bool UTTWidgetInventorySlot::NativeOnDrop(const FGeometry& InGeometry, const FDragDropEvent& InDragDropEvent, UDragDropOperation* InOperation)
{
Super::NativeOnDrop(InGeometry, InDragDropEvent, InOperation);
return true;
}
void UTTWidgetInventorySlot::NativeOnDragCancelled(const FDragDropEvent& InDragDropEvent, UDragDropOperation* InOperation)
{
Super::NativeOnDragCancelled(InDragDropEvent, InOperation);
}
UTTDragDropOperation.h
#pragma once
#include "Blueprint/DragDropOperation.h"
#include "CoreMinimal.h"
#include "TTDragDropOperation.generated.h"
UCLASS()
class MYGAME_API UTTDragDropOperation : public UDragDropOperation
{
GENERATED_BODY()
public:
UTTDragDropOperation();
virtual ~UTTDragDropOperation();
};
TTDragDropOperation.cpp
#include "TTDragDropOperation.h"
#include "MyGame.h"
UTTDragDropOperation::UTTDragDropOperation()
{
// Log Contructor
UE_LOG("UTTDragDropOperation::UTTDragDropOperation()");
}
UTTDragDropOperation::~UTTDragDropOperation()
{
// Log Destructor
// This does not get called automatically after a successful drag and drop operation
// It only gets called on all instances once the game is terminated.
UE_LOG("UTTDragDropOperation::~UTTDragDropOperation()");
}