2019-12-27 09:26:59 -05:00
|
|
|
// Copyright Epic Games, Inc. All Rights Reserved.
|
2019-10-01 20:41:42 -04:00
|
|
|
|
2021-03-08 14:35:06 -04:00
|
|
|
#pragma once
|
|
|
|
|
|
2020-01-27 20:11:15 -05:00
|
|
|
#include "CoreMinimal.h"
|
2019-10-01 20:41:42 -04:00
|
|
|
#include "BaseBehaviors/BehaviorTargetInterfaces.h"
|
2020-10-22 19:19:16 -04:00
|
|
|
#include "ToolSceneQueriesUtil.h"
|
2022-04-02 01:04:02 -04:00
|
|
|
#include "Engine/HitResult.h"
|
2019-10-01 20:41:42 -04:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* BehaviorTarget to do world raycast selection from a click
|
|
|
|
|
* Currently used to click-select reference planes in the world
|
|
|
|
|
*/
|
|
|
|
|
class FSelectClickedAction : public IClickBehaviorTarget
|
|
|
|
|
{
|
2019-12-19 18:07:47 -05:00
|
|
|
FInputRayHit DoRayCast(const FInputDeviceRay& ClickPos, bool callbackOnHit)
|
2019-10-01 20:41:42 -04:00
|
|
|
{
|
|
|
|
|
FHitResult Result;
|
2021-12-09 14:46:09 -05:00
|
|
|
const TArray<const UPrimitiveComponent*>* IgnoreComponents = VisibleComponentsToIgnore.Num() == 0 ? nullptr : &VisibleComponentsToIgnore;
|
|
|
|
|
const TArray<const UPrimitiveComponent*>* InvisibleComponentsToInclude = InvisibleComponentsToHitTest.Num() == 0 ? nullptr : &InvisibleComponentsToHitTest;
|
|
|
|
|
bool bHitWorld = (SnapManager != nullptr) ?
|
|
|
|
|
ToolSceneQueriesUtil::FindNearestVisibleObjectHit(SnapManager, Result, ClickPos.WorldRay, IgnoreComponents, InvisibleComponentsToInclude) :
|
|
|
|
|
ToolSceneQueriesUtil::FindNearestVisibleObjectHit(World, Result, ClickPos.WorldRay, IgnoreComponents, InvisibleComponentsToInclude);
|
2020-10-29 13:38:15 -04:00
|
|
|
|
2019-10-01 20:41:42 -04:00
|
|
|
if (callbackOnHit && bHitWorld && OnClickedPositionFunc != nullptr)
|
|
|
|
|
{
|
|
|
|
|
OnClickedPositionFunc(Result);
|
|
|
|
|
}
|
2019-12-19 18:07:47 -05:00
|
|
|
return (bHitWorld) ? FInputRayHit(Result.Distance) : FInputRayHit();
|
2019-10-01 20:41:42 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public:
|
2021-12-09 14:46:09 -05:00
|
|
|
USceneSnappingManager* SnapManager = nullptr;
|
|
|
|
|
UWorld* World = nullptr;
|
2019-10-01 20:41:42 -04:00
|
|
|
TFunction<void(const FHitResult&)> OnClickedPositionFunc = nullptr;
|
2020-01-27 20:11:15 -05:00
|
|
|
TUniqueFunction<bool()> ExternalCanClickPredicate = nullptr;
|
2019-10-01 20:41:42 -04:00
|
|
|
|
2020-10-29 13:38:15 -04:00
|
|
|
// These lists can be used to modify which components are hit tested when doing a ray cast.
|
|
|
|
|
// By default, all visible components are hit tested.
|
2021-01-14 19:07:52 -04:00
|
|
|
TArray<const UPrimitiveComponent*> VisibleComponentsToIgnore;
|
|
|
|
|
TArray<const UPrimitiveComponent*> InvisibleComponentsToHitTest;
|
2020-10-29 13:38:15 -04:00
|
|
|
|
2020-03-09 13:20:07 -04:00
|
|
|
// can alternately track shift modifier, however client must register this modifier w/ behavior
|
|
|
|
|
static const int ShiftModifier = 1;
|
|
|
|
|
bool bShiftModifierToggle = false;
|
|
|
|
|
|
2019-12-19 18:07:47 -05:00
|
|
|
virtual FInputRayHit IsHitByClick(const FInputDeviceRay& ClickPos) override
|
2019-10-01 20:41:42 -04:00
|
|
|
{
|
2020-01-27 20:11:15 -05:00
|
|
|
if (ExternalCanClickPredicate && ExternalCanClickPredicate() == false)
|
|
|
|
|
{
|
|
|
|
|
return FInputRayHit();
|
|
|
|
|
}
|
2019-10-01 20:41:42 -04:00
|
|
|
return DoRayCast(ClickPos, false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual void OnClicked(const FInputDeviceRay& ClickPos) override
|
|
|
|
|
{
|
|
|
|
|
DoRayCast(ClickPos, true);
|
|
|
|
|
}
|
2020-03-09 13:20:07 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
virtual void OnUpdateModifierState(int ModifierID, bool bIsOn)
|
|
|
|
|
{
|
|
|
|
|
if (ModifierID == ShiftModifier)
|
|
|
|
|
{
|
|
|
|
|
bShiftModifierToggle = bIsOn;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-01 20:41:42 -04:00
|
|
|
};
|