Problems with Drag and Drop Operation (Visual Widget)

Raxwell00
Tue, 18 Mar 2025 20:47:35 +0000
C++

Hi! I have an inventory system and im working on a drag & drop system. So the problem is im making a system where if you drag the slot with “Right Mouse Button” you are able to split items and using mouse wheel you increase/decrease the amount to split so the problem is im creating a drag visual widget named InventorySlotDragVisual but it doesn’t execute the nativeonmousewheel. It only executes the nativeonmousewheel function of InventorySlot i managed to get it to work but now it only works if i play with mouse wheel inside the inventory slot as expected.

InventorySlot.cpp

// Fill out your copyright notice in the Description page of Project Settings.


#include "InventorySlot.h"

#include "InventoryItem.h"
#include "Blueprint/WidgetBlueprintLibrary.h"
#include "Blueprint/DragDropOperation.h"
#include "InventoryComponent.h"
#include "Components/TextBlock.h"

void UInventorySlot::InitializeSlot(const FInventoryItem& SlotData,int32 Index,UInventoryComponent* InventoryComponent)

{
   CurrentItemData = SlotData;
   SlotIndex = Index;
   OwningInventory = InventoryComponent;

   if (ItemNameText)
   {
   	if (SlotData.ItemName.IsNone())
   		ItemNameText->SetText(FText::GetEmpty());
   	else
   		ItemNameText->SetText(FText::FromName(SlotData.ItemName));
   }

   if (QuantityText)
   {
   	if (SlotData.Quantity <= 0)
   		QuantityText->SetText(FText::GetEmpty());
   	else
   		QuantityText->SetText(FText::AsNumber(SlotData.Quantity));
   }
}

FReply UInventorySlot::NativeOnMouseButtonDown(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent)
{
   if (CurrentItemData.ItemName.IsNone())
   {
   	return FReply::Unhandled();
   }

   bool bRightDrag = InMouseEvent.IsMouseButtonDown(EKeys::RightMouseButton);
   bIsRightDragActive = bRightDrag;

   if (bRightDrag)
   {
   	return UWidgetBlueprintLibrary::DetectDragIfPressed(InMouseEvent, this, EKeys::RightMouseButton).NativeReply;
   }
   else if (InMouseEvent.IsMouseButtonDown(EKeys::LeftMouseButton))
   {
   	bIsRightDragActive = false;
   	return UWidgetBlueprintLibrary::DetectDragIfPressed(InMouseEvent, this, EKeys::LeftMouseButton).NativeReply;
   }

   return Super::NativeOnMouseButtonDown(InGeometry, InMouseEvent);
}

void UInventorySlot::NativeOnDragDetected(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent, UDragDropOperation*& OutOperation)
{
   UDragDropOperation* DragDropOp = UWidgetBlueprintLibrary::CreateDragDropOperation(UDragDropOperation::StaticClass());
   if (DragDropOp)
   {
   	DragDropOp->Payload = this;
   	if (InventoryDragVisualWidgetClass)
   	{
   		UInventorySlotDragVisual* DragVisual = CreateWidget<UInventorySlotDragVisual>(GetWorld(), InventoryDragVisualWidgetClass);
   		bool bRightDrag = (InMouseEvent.GetEffectingButton() == EKeys::RightMouseButton);
   		DragVisual->bIsRightDrag = bRightDrag;
   		CurrentlyDragging = DragVisual;
   		if (bRightDrag)
   		{
   			DragVisual->TransferAmount = 1;

   		}
   		else
   		{
   			DragVisual->TransferAmount = CurrentItemData.Quantity;
   		}
   		if (DragVisual->TransferAmountText)
   		{
   			DragVisual->TransferAmountText->SetText(FText::AsNumber(DragVisual->TransferAmount));
   		}
   		DragDropOp->DefaultDragVisual = DragVisual;
   	}
   	else
   	{
   		DragDropOp->DefaultDragVisual = this;
   	}
   	OutOperation = DragDropOp;
   }
}

bool UInventorySlot::NativeOnDrop(const FGeometry& InGeometry, const FDragDropEvent& InDragDropEvent, UDragDropOperation* InOperation)
{
   if (InOperation && InOperation->Payload)
   {
       UInventorySlot* SourceSlot = Cast<UInventorySlot>(InOperation->Payload);
       if (SourceSlot && SourceSlot != this && OwningInventory)
       {
           int32 TransferQty = 0;
           if (SourceSlot->bIsRightDragActive)
           {
               UInventorySlotDragVisual* DragVisual = Cast<UInventorySlotDragVisual>(InOperation->DefaultDragVisual);
               if (DragVisual)
               {
                   TransferQty = DragVisual->TransferAmount;
               }
               else
               {
                   TransferQty = 1;
               }
           }
           else
           {
               TransferQty = SourceSlot->CurrentItemData.Quantity;
           }

           if (CurrentItemData.ItemName.IsNone())
           {
               OwningInventory->PartialTransferItem(SourceSlot->SlotIndex, SlotIndex, TransferQty);
               SourceSlot->bIsRightDragActive = false;
               return true;
           }
           else if (CurrentItemData.ItemName == SourceSlot->CurrentItemData.ItemName)
           {
               if (CurrentItemData.Quantity < CurrentItemData.MaxStack)
               {
                   OwningInventory->MergePartialItems(SourceSlot->SlotIndex, SlotIndex, TransferQty);
                   SourceSlot->bIsRightDragActive = false;
                   return true;
               }
               else
               {
                   OwningInventory->SwapItems(SourceSlot->SlotIndex, SlotIndex);
                   SourceSlot->bIsRightDragActive = false;
                   return true;
               }
           }
           else
           {
               OwningInventory->SwapItems(SourceSlot->SlotIndex, SlotIndex);
               SourceSlot->bIsRightDragActive = false;
               return true;
           }
       }
   }
   return Super::NativeOnDrop(InGeometry, InDragDropEvent, InOperation);
}

FReply UInventorySlot::NativeOnMouseWheel(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent)
{
   GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Green, FString::Printf(TEXT("bIsRightDragActive: %d, CurrentlyDragging: %p"), bIsRightDragActive, CurrentlyDragging));

   if (bIsRightDragActive && CurrentlyDragging)
   {
   	GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, "InventorySlot::NativeOnMouseWheel");
   	int32 Delta = InMouseEvent.GetWheelDelta();
   	CurrentlyDragging->TransferAmount = FMath::Clamp(CurrentlyDragging->TransferAmount + Delta, 1, CurrentItemData.Quantity);

   	if (CurrentlyDragging->TransferAmountText)
   	{
   		CurrentlyDragging->TransferAmountText->SetText(FText::AsNumber(CurrentlyDragging->TransferAmount));
   	}

   	return FReply::Handled();
   }
   return Super::NativeOnMouseWheel(InGeometry, InMouseEvent);
}

InventorySlotDragVisual.cpp

#include "InventorySlotDragVisuaL.h"
#include "Components/TextBlock.h"


void UInventorySlotDragVisual::NativeConstruct()
{
	Super::NativeConstruct();
	this->SetKeyboardFocus();

	if (APlayerController* PC = GetOwningPlayer())
	{
		FInputModeUIOnly InputMode;
		InputMode.SetWidgetToFocus(this->TakeWidget());
		PC->SetInputMode(InputMode);
	}
}

FReply UInventorySlotDragVisual::NativeOnMouseWheel(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent)
{
	int32 Delta = InMouseEvent.GetWheelDelta();
	GEngine->AddOnScreenDebugMessage(-1, 2.f, FColor::Blue, FString::Printf(TEXT("TransferAmount: %d"), TransferAmount));
	if (bIsRightDrag)
	{
		TransferAmount = FMath::Clamp(TransferAmount + Delta, 1, 100);
	}

	if (TransferAmountText)
	{
		TransferAmountText->SetText(FText::AsNumber(TransferAmount));
		if (GEngine)
		{
			GEngine->AddOnScreenDebugMessage(-1, 2.f, FColor::Green, FString::Printf(TEXT("TransferAmount: %d"), TransferAmount));
		}
	}
	else
	{
		if (GEngine)
		{
			GEngine->AddOnScreenDebugMessage(-1, 2.f, FColor::Red, TEXT("TransferAmountText is null!"));
		}
	}

	OnTransferAmountUpdated(TransferAmount);

	return FReply::Handled();
}

1 post - 1 participant