Download

How do I respond to Drag and Mouse Down events on the same widget?

I have a simple inventory system which pops up from the side of the screen. I want the player to be able to drag items out of the inventory and drop them over other objects in the world. I also need a single click on the inventory items to start an item examination mode.

I’ve put my code for the mouse down and drag detected functions below. The DragDetected fires as expected but I don’t know the correct way to do something else (the PlayerCharacter-> line) if drag WASN’T detected. Can someone point me in the right direction please?

FReply UPGInventoryItemWidget::NativeOnMouseButtonDown(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent)
{
	// Check whether a drag action was initiated with any of our "Interact" action mappings.
	auto InteractMappingDragged = GetPlayerContext().GetPlayerController()->PlayerInput->ActionMappings.FindByPredicate(
		[InMouseEvent](auto& Mapping)
	{
		return Mapping.ActionName == FName("Interact")
			&& Mapping.Key == InMouseEvent.GetEffectingButton();
	});

	if (InteractMappingDragged)
	{
		// Do this if dragged.
		return UWidgetBlueprintLibrary::DetectDragIfPressed(InMouseEvent, this, InMouseEvent.GetEffectingButton()).NativeReply;
	}
	else
	{
		// Do this if just clicked but not dragged.
		PlayerCharacter->ExamineActorFromInventory(InventoryItem->GetOwner());
		return Super::NativeOnMouseButtonDown(InGeometry, InMouseEvent);
	}
}

void UPGInventoryItemWidget::NativeOnDragDetected(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent,
	UDragDropOperation*& OutOperation)
{
	UE_LOG(LogPGUI, Warning, TEXT("Drag detected"));

	Super::NativeOnDragDetected(InGeometry, InMouseEvent, OutOperation);
}

In the mean time I’ve implemented a ■■■■■■ hack which works well enough: At the start of NativeOnMouseButtonDown I start a timer which runs for 150ms. This is a “waiting for drag” delay. If a drag starts before the timer runs out, NativeOnDragDetected clears the timer. Otherwise, a new callback method handles what would be normal mouse down event.

It works well enough for now but it’s rather ugly and I’d love to know of a more clean way to do this. Surely it’s common to want to respond to a click or click-and-drag differently on the same object?