Following up on this. I made the jump to 4.13 and now I’m using Widget Interaction Components to do all of my interaction. New WidgetPassThrough material option worked great. Thanks for that tip.
The problem I ran into with the Widget Interaction Components is that they do their own line tracing.
I had already set up a custom collision channel, and placed my Widget Component in that channel, per your suggestion.
DefaultEngine.ini:
+DefaultChannelResponses=(Channel=ECC_GameTraceChannel2,Name="Menu",DefaultResponse=ECR_Ignore,bTraceType=False,bStaticObject=False)
Then I simply made a new c++ class from WidgetInteractionComponent.cpp and overrided its PerformTrace function with my own.
MyWidgetInteractionComponent.cpp
#include “UnifiedPlatform.h”
#include “MyWidgetInteractionComponent.h”
bool UMyWidgetInteractionComponent::PerformTrace(FHitResult& HitResult)
{
switch (InteractionSource)
{
case EWidgetInteractionSource::World:
{
const FVector WorldLocation = GetComponentLocation();
const FTransform WorldTransform = GetComponentTransform();
const FVector Direction = WorldTransform.GetUnitAxis(EAxis::X);
TArray<UPrimitiveComponent*> PrimitiveChildren;
GetRelatedComponentsToIgnoreInAutomaticHitTesting(PrimitiveChildren);
FCollisionQueryParams Params = FCollisionQueryParams::DefaultQueryParam;
Params.AddIgnoredComponents(PrimitiveChildren);
FCollisionObjectQueryParams Everything(FCollisionObjectQueryParams::AllObjects);
return GetWorld()->LineTraceSingleByObjectType(HitResult, WorldLocation, WorldLocation + (Direction * InteractionDistance), FCollisionObjectQueryParams(ECollisionChannel::ECC_GameTraceChannel2), Params);
}
case EWidgetInteractionSource::Mouse:
case EWidgetInteractionSource::CenterScreen:
{
TArray<UPrimitiveComponent*> PrimitiveChildren;
GetRelatedComponentsToIgnoreInAutomaticHitTesting(PrimitiveChildren);
FCollisionQueryParams Params = FCollisionQueryParams::DefaultQueryParam;
Params.AddIgnoredComponents(PrimitiveChildren);
APlayerController* PlayerController = GetWorld()->GetFirstPlayerController();
ULocalPlayer* LocalPlayer = PlayerController->GetLocalPlayer();
bool bHit = false;
if (LocalPlayer && LocalPlayer->ViewportClient)
{
if (InteractionSource == EWidgetInteractionSource::Mouse)
{
FVector2D MousePosition;
if (LocalPlayer->ViewportClient->GetMousePosition(MousePosition))
{
bHit = PlayerController->GetHitResultAtScreenPosition(MousePosition, ECC_Visibility, Params, HitResult);
}
}
else if (InteractionSource == EWidgetInteractionSource::CenterScreen)
{
FVector2D ViewportSize;
LocalPlayer->ViewportClient->GetViewportSize(ViewportSize);
bHit = PlayerController->GetHitResultAtScreenPosition(ViewportSize * 0.5f, ECC_Visibility, Params, HitResult);
}
// Don't allow infinite distance hit testing.
if (bHit)
{
if (HitResult.Distance > InteractionDistance)
{
HitResult = FHitResult();
bHit = false;
}
}
}
return bHit;
}
case EWidgetInteractionSource::Custom:
{
HitResult = CustomHitResult;
return HitResult.bBlockingHit;
}
}
return false;
}
MyWidgetInteractionComponent.h
#pragma once
#include "Components/WidgetInteractionComponent.h"
#include "MyWidgetInteractionComponent.generated.h"
/**
*
*/
UCLASS(ClassGroup = Experimental, meta = (BlueprintSpawnableComponent, DevelopmentStatus = Experimental))
class UNIFIEDPLATFORM_API UMyWidgetInteractionComponent : public UWidgetInteractionComponent
{
GENERATED_BODY()
protected:
/** Performs the trace and gets the hit result under the specified InteractionSource */
virtual bool PerformTrace(FHitResult& HitResult);
};
Now everything works perfectly. My depth perception goes haywire when I get within inches of a wall and open up the menu, that’s floating 6 feet away, but I can live with that.
][1]