mirror of
https://github.com/litruv/TobiiEyetracking.git
synced 2026-07-26 03:36:11 +10:00
Added Tobii from 4.23 + updated
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
/******************************************************************************
|
||||
* Copyright 2017- Tobii Technology AB. All rights reserved.
|
||||
*
|
||||
* @author Temaran | Fredrik Lindh | fredrik.lindh@tobii.com | https://github.com/Temaran
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Slate/SRetainerWidget.h"
|
||||
#include "TobiiGTOMTypes.h"
|
||||
#include "STobiiRadialMenuWidget.h"
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "DisplayDebugHelpers.h"
|
||||
#include "Widgets/Layout/SBox.h"
|
||||
|
||||
class AHUD;
|
||||
class UCanvas;
|
||||
class UTobiiGazeFocusableWidget;
|
||||
|
||||
//This is the underlying slate widget.
|
||||
//WARNING: Please note that we do not support using these directly yet.
|
||||
class TOBIIGTOM_API STobiiGazeFocusableWidget : public SBox
|
||||
{
|
||||
public:
|
||||
SLATE_BEGIN_ARGS(STobiiGazeFocusableWidget)
|
||||
{
|
||||
_Visibility = EVisibility::SelfHitTestInvisible;
|
||||
}
|
||||
SLATE_EVENT(FSimpleDelegate, OnHovered)
|
||||
SLATE_EVENT(FSimpleDelegate, OnUnhovered)
|
||||
|
||||
/************************************************************************/
|
||||
/* From SBox widget */
|
||||
/************************************************************************/
|
||||
//Horizontal alignment of content in the area allotted to the SBox by its parent
|
||||
SLATE_ARGUMENT(EHorizontalAlignment, HAlign)
|
||||
|
||||
//Vertical alignment of content in the area allotted to the SBox by its parent
|
||||
SLATE_ARGUMENT(EVerticalAlignment, VAlign)
|
||||
|
||||
//Padding between the SBox and the content that it presents. Padding affects desired size.
|
||||
SLATE_ATTRIBUTE(FMargin, Padding)
|
||||
|
||||
//The widget content presented by the SBox
|
||||
SLATE_DEFAULT_SLOT(FArguments, Content)
|
||||
SLATE_END_ARGS()
|
||||
|
||||
/************************************************************************/
|
||||
/* Tobii */
|
||||
/************************************************************************/
|
||||
public:
|
||||
TWeakObjectPtr<UTobiiGazeFocusableWidget> UMGWidget;
|
||||
|
||||
STobiiGazeFocusableWidget();
|
||||
void Construct(const FArguments& InArgs);
|
||||
|
||||
float GetCleanUIAlpha() { return CleanUIAlpha; }
|
||||
bool IsHoveredByPointer() { return bIsHovered; }
|
||||
bool HitByGaze();
|
||||
|
||||
void AddExtraCleanUIContainerToPollHitsFrom(STobiiGazeFocusableWidget* CleanUIContainerToPoll, bool PollGazeHits = true, bool PollMouseHits = true);
|
||||
void RemoveExtraCleanUIContainerToPollHitsFrom(STobiiGazeFocusableWidget* CleanUIContainerToStopPolling);
|
||||
|
||||
static STobiiGazeFocusableWidget* TryCastToTobiiGazeFocusable(SWidget* Widget);
|
||||
|
||||
/************************************************************************/
|
||||
/* SBox */
|
||||
/************************************************************************/
|
||||
public:
|
||||
FSimpleDelegate OnHovered;
|
||||
FSimpleDelegate OnUnhovered;
|
||||
|
||||
virtual void Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime) override;
|
||||
virtual int32 OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyClippingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& InWidgetStyle, bool bParentEnabled) const override;
|
||||
virtual void OnMouseEnter(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override;
|
||||
virtual void OnMouseLeave(const FPointerEvent& MouseEvent) override;
|
||||
|
||||
private:
|
||||
struct CleanUIPollingInfo
|
||||
{
|
||||
TWeakPtr<SWidget> CleanUIToPollFrom;
|
||||
bool PollGaze;
|
||||
bool PollPointer;
|
||||
};
|
||||
|
||||
float CleanUIAlpha;
|
||||
|
||||
TArray<CleanUIPollingInfo> CleanUIContainersToPollHitsFrom;
|
||||
};
|
||||
159
Source/TobiiGTOM/Public/GTOMAwareUI/STobiiRadialMenuWidget.h
Normal file
159
Source/TobiiGTOM/Public/GTOMAwareUI/STobiiRadialMenuWidget.h
Normal file
@@ -0,0 +1,159 @@
|
||||
/******************************************************************************
|
||||
* Copyright 2017- Tobii Technology AB. All rights reserved.
|
||||
*
|
||||
* @author Temaran | Fredrik Lindh | fredrik.lindh@tobii.com | https://github.com/Temaran
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "DisplayDebugHelpers.h"
|
||||
#include "Slate/SRetainerWidget.h"
|
||||
#include "Widgets/Layout/SBox.h"
|
||||
|
||||
class FArrangedChildren;
|
||||
class FPaintArgs;
|
||||
class FSlateWindowElementList;
|
||||
|
||||
struct FTobiiRadialMenuPanelRenderData
|
||||
{
|
||||
TArray<FSlateVertex> PanelVertexData;
|
||||
TArray<SlateIndex> PanelIndexData;
|
||||
|
||||
TArray<FSlateVertex> BorderVertexData; //This also contains the PanelVertexData in the end.
|
||||
TArray<SlateIndex> BorderIndexData;
|
||||
};
|
||||
|
||||
//This is the underlying slate widget.
|
||||
class TOBIIGTOM_API STobiiRadialMenuWidget : public SPanel
|
||||
{
|
||||
public:
|
||||
class FSlot : public TSlotBase<FSlot>
|
||||
{
|
||||
public:
|
||||
FSlot& Offset(const TAttribute<FVector2D>& InOffset)
|
||||
{
|
||||
OffsetAttr = InOffset;
|
||||
return *this;
|
||||
}
|
||||
|
||||
FSlot& Scale(const TAttribute<float>& InScale)
|
||||
{
|
||||
ScaleAttr = InScale;
|
||||
return *this;
|
||||
}
|
||||
|
||||
FSlot& Alpha(const TAttribute<float>& InAlpha)
|
||||
{
|
||||
AlphaAttr = InAlpha;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Offset */
|
||||
TAttribute<FVector2D> OffsetAttr;
|
||||
|
||||
/** Scale */
|
||||
TAttribute<float> ScaleAttr;
|
||||
|
||||
/** Alpha */
|
||||
TAttribute<float> AlphaAttr;
|
||||
|
||||
/** Default values for a slot. */
|
||||
FSlot()
|
||||
: TSlotBase<FSlot>()
|
||||
, OffsetAttr(FVector2D(0.0f, 0.0f))
|
||||
, ScaleAttr(1.0f)
|
||||
, AlphaAttr(1.0f)
|
||||
{ }
|
||||
};
|
||||
|
||||
SLATE_BEGIN_ARGS(STobiiRadialMenuWidget)
|
||||
: _UseHardBorder(true)
|
||||
, _BorderColor(FColor(230, 230, 230))
|
||||
, _PanelColor(FColor(70, 70, 70))
|
||||
, _BorderThicknessPx(5.0f)
|
||||
, _SegmentSeparationPx(10.0f)
|
||||
, _AngularDisplacementDeg(0.0f)
|
||||
, _RadiusPx(500.0f)
|
||||
, _VertexCount(360)
|
||||
{
|
||||
_Visibility = EVisibility::SelfHitTestInvisible;
|
||||
}
|
||||
|
||||
SLATE_SUPPORTS_SLOT(STobiiRadialMenuWidget::FSlot)
|
||||
SLATE_ARGUMENT(bool, UseHardBorder)
|
||||
SLATE_ARGUMENT(FColor, BorderColor)
|
||||
SLATE_ARGUMENT(FColor, PanelColor)
|
||||
SLATE_ARGUMENT(float, BorderThicknessPx)
|
||||
SLATE_ARGUMENT(float, SegmentSeparationPx)
|
||||
SLATE_ARGUMENT(float, AngularDisplacementDeg)
|
||||
SLATE_ARGUMENT(float, RadiusPx)
|
||||
SLATE_ARGUMENT(int32, VertexCount)
|
||||
|
||||
SLATE_END_ARGS()
|
||||
|
||||
STobiiRadialMenuWidget();
|
||||
|
||||
void Construct(const FArguments& InArgs);
|
||||
|
||||
static FSlot& Slot()
|
||||
{
|
||||
return *(new FSlot());
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a content slot.
|
||||
*
|
||||
* @return The added slot.
|
||||
*/
|
||||
FSlot& AddSlot()
|
||||
{
|
||||
Invalidate(EInvalidateWidget::Layout);
|
||||
|
||||
STobiiRadialMenuWidget::FSlot& NewSlot = *(new FSlot());
|
||||
this->Children.Add(&NewSlot);
|
||||
return NewSlot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a particular content slot.
|
||||
*
|
||||
* @param SlotWidget The widget in the slot to remove.
|
||||
*/
|
||||
int32 RemoveSlot(const TSharedRef<SWidget>& SlotWidget);
|
||||
|
||||
/**
|
||||
* Removes all slots from the panel.
|
||||
*/
|
||||
void ClearChildren();
|
||||
|
||||
public:
|
||||
// Begin SWidget overrides
|
||||
virtual void OnArrangeChildren(const FGeometry& AllottedGeometry, FArrangedChildren& ArrangedChildren) const override;
|
||||
virtual int32 OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyCullingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& InWidgetStyle, bool bParentEnabled) const override;
|
||||
virtual FChildren* GetChildren() override;
|
||||
// End SWidget overrides
|
||||
|
||||
protected:
|
||||
// Begin SWidget overrides.
|
||||
virtual FVector2D ComputeDesiredSize(float LayoutScaleMultiplier) const override;
|
||||
// End SWidget overrides.
|
||||
|
||||
protected:
|
||||
/** The ConstraintCanvas widget's children. */
|
||||
TPanelChildren<FSlot> Children;
|
||||
|
||||
public:
|
||||
FSlateResourceHandle BrushResourceHandle;
|
||||
bool bUseHardBorder;
|
||||
FColor BorderColor;
|
||||
FColor PanelColor;
|
||||
float BorderThicknessPx;
|
||||
float SegmentSeparationPx;
|
||||
float AngularDisplacementDeg;
|
||||
float RadiusPx;
|
||||
int32 VertexCount;
|
||||
|
||||
private:
|
||||
void GeneratePanelRenderData(const FGeometry& AllottedGeometry, int32 NrChildren, TArray<FTobiiRadialMenuPanelRenderData>& OutChildRenderData) const;
|
||||
};
|
||||
167
Source/TobiiGTOM/Public/GTOMAwareUI/TobiiGazeFocusableWidget.h
Normal file
167
Source/TobiiGTOM/Public/GTOMAwareUI/TobiiGazeFocusableWidget.h
Normal file
@@ -0,0 +1,167 @@
|
||||
/******************************************************************************
|
||||
* Copyright 2017- Tobii Technology AB. All rights reserved.
|
||||
*
|
||||
* @author Temaran | Fredrik Lindh | fredrik.lindh@tobii.com | https://github.com/Temaran
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "TobiiGTOMTypes.h"
|
||||
#include "STobiiGazeFocusableWidget.h"
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "ObjectEditorUtils.h"
|
||||
#include "Components/WidgetComponent.h"
|
||||
#include "Components/SizeBox.h"
|
||||
|
||||
#include "TobiiGazeFocusableWidget.generated.h"
|
||||
|
||||
class UPrimitiveComponent;
|
||||
class UTobiiGazeFocusManagerComponent;
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FWidgetGazeFocusSignature, UTobiiGazeFocusableWidget*, FocusedWidget);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FWidgetHoverSignature, UTobiiGazeFocusableWidget*, FocusedWidget);
|
||||
|
||||
/**
|
||||
* Use this widget to wrap other widgets you want to mark as gaze focusable.
|
||||
* In contrast to gaze focusable components, each widget you want to make focusable needs to be wrapped by its own UTobiiGazeFocusableWidget. There is more info below on why this is the case.
|
||||
* Please note that while this wraps a raw slate widget, we currently do not officially support using the slate widgets directly. Please use the UMG wrapper.
|
||||
*
|
||||
* There are some major differences to how gaze focusable widgets versus components work:
|
||||
* 1. Since widgets don't support tags, widgets can only participate in GTOM by being wrapped by this widget.
|
||||
* 2. Actor component hierarchies can be very rigid since they can be partially constructed in cpp, both by the developer and the engine. This means that designating gaze focusability via component parenting wouldn't be reliable.
|
||||
* 3. It is very common to want to make it so that every primitive component on an actor should contribute to focusing that actor. This is not true for widgets, here it is more common that each individual widget wants to know if it has been individually focused.
|
||||
*
|
||||
* All of these things should help to illustrate why using different models for gaze focus in slate/UMG and actors is to be preferred.
|
||||
*/
|
||||
UCLASS(BlueprintType, Blueprintable, meta = (BlueprintSpawnableComponent, DisplayName= "Tobii Gaze Focusable"))
|
||||
class TOBIIGTOM_API UTobiiGazeFocusableWidget : public USizeBox
|
||||
{
|
||||
GENERATED_UCLASS_BODY()
|
||||
|
||||
/************************************************************************/
|
||||
/* USizeBox */
|
||||
/************************************************************************/
|
||||
public:
|
||||
// UVisual interface
|
||||
virtual void ReleaseSlateResources(bool bReleaseChildren) override;
|
||||
protected:
|
||||
// UWidget interface
|
||||
virtual TSharedRef<SWidget> RebuildWidget() override;
|
||||
|
||||
public:
|
||||
//These are for pointer hovering
|
||||
UPROPERTY(BlueprintAssignable, Category = "Event")
|
||||
FWidgetHoverSignature OnHovered;
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category = "Event")
|
||||
FWidgetHoverSignature OnUnhovered;
|
||||
|
||||
//This function must be called to make the widget participate in GTOM.
|
||||
//WARNING: For screen space widgets, you must do this manually by sending in a nullptr HostWidget! For worldspace widgets, the UTobiiGazeFocusableComponent will do this for you though.
|
||||
UFUNCTION(BlueprintCallable, Category = "Gaze Focus")
|
||||
void RegisterWidgetToGTOM(UWidgetComponent* HostWidget);
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "General")
|
||||
UWidgetComponent* GetWorldSpaceHostWidgetComponent();
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "General")
|
||||
bool IsHoveredByPointer();
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "General")
|
||||
bool IsWorldSpaceWidget();
|
||||
|
||||
/************************************************************************/
|
||||
/* Tobii */
|
||||
/************************************************************************/
|
||||
public:
|
||||
//This will be true if this is the most likely widget to currently have focus irregardless of layer filters.
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Gaze Focus")
|
||||
bool bHasGazeFocus;
|
||||
|
||||
//Set this to false if you want to stop this widget participating in GTOM.
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Gaze Focus")
|
||||
bool bIsGazeFocusable;
|
||||
|
||||
//The gaze focus priority is optional input that you can provide to GTOM. Objects with higher focus priority are more "important" and are therefore more likely to be construed as being in focus. If this is negative, it will not be enforced.
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Gaze Focus")
|
||||
float GazeFocusPriority;
|
||||
|
||||
//If this object is at least this far away from the player, it will not participate in GTOM. If this is less or equal to zero, it will not be enforced.
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Gaze Focus")
|
||||
float MaxFocusDistance;
|
||||
|
||||
//A focus manager can opt to only query a subset of focusables by using a focus layer. If this is empty, the default layer will be used (Either from a gaze focusable component, or the global default).
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Gaze Focus")
|
||||
FString FocusLayer;
|
||||
|
||||
//This delegate will fire when this widget receives user focus
|
||||
UPROPERTY(BlueprintAssignable, Category = "Gaze Focus|Event")
|
||||
FWidgetGazeFocusSignature ReceivedGazeFocus;
|
||||
|
||||
//This delegate will fire when this widget loses user focus
|
||||
UPROPERTY(BlueprintAssignable, Category = "Gaze Focus|Event")
|
||||
FWidgetGazeFocusSignature LostGazeFocus;
|
||||
|
||||
//This will return true if this widget has user focus
|
||||
UFUNCTION(BlueprintPure, Category = "Gaze Focus")
|
||||
bool HasFocus();
|
||||
|
||||
//This will return true if this widget is close enough to the user's gaze to be considered in focus, even though it might not be the object the user is actively focusing on.
|
||||
UFUNCTION(BlueprintPure, Category = "Gaze Focus")
|
||||
bool IsInFocusCollection();
|
||||
|
||||
public:
|
||||
//How should we apply CleanUI?
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "CleanUI")
|
||||
ETobiiCleanUIMode CleanUIMode;
|
||||
|
||||
//If this is larger than 0, CleanUI is currently being suppressed.
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "CleanUI")
|
||||
float TimeCleanUIIsSuppressedForSecs;
|
||||
|
||||
//If you want this cleanUI panel to behave differently from the default governed by CVars you can override properties here. Any negative value will result in the CVar value being used.
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "CleanUI")
|
||||
float CleanUIFadeInTimeSecsOverride;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "CleanUI")
|
||||
float CleanUIFadeOutTimeSecsOverride;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "CleanUI")
|
||||
float CleanUIMinAlphaOverride;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "CleanUI")
|
||||
float CleanUIMaxAlphaOverride;
|
||||
|
||||
//If you have a game where you want this cleanUI widget to fade in on mouse over, set this to true.
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "CleanUI")
|
||||
bool bTriggerCleanUIOnMouseOver;
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "CleanUI")
|
||||
float GetCleanUIAlpha();
|
||||
|
||||
public:
|
||||
//If this widget should fade out when another container is being looked at, use these functions to make that happen. This requires bUseFastHitTesting to be off.
|
||||
UFUNCTION(BlueprintCallable, Category = "Dependent Widgets")
|
||||
void AddGazeFocusableWidgetToPollHitsFrom(UTobiiGazeFocusableWidget* GazeFocusableWidgetToPoll, bool PollGazeHits = true, bool PollMouseHits = true);
|
||||
UFUNCTION(BlueprintCallable, Category = "Dependent Widgets")
|
||||
void RemoveGazeFocusableWidgetToPollHitsFrom(UTobiiGazeFocusableWidget* GazeFocusableWidgetToStopPolling);
|
||||
|
||||
public:
|
||||
STobiiGazeFocusableWidget* GetSlateGazeFocusableWidget();
|
||||
|
||||
virtual void ReceiveFocus();
|
||||
virtual void LoseFocus();
|
||||
|
||||
static TMap<FTobiiFocusableUID, TWeakObjectPtr<UTobiiGazeFocusableWidget>>& GetTobiiScreenSpaceFocusableWidgets();
|
||||
|
||||
public:
|
||||
#if WITH_EDITOR
|
||||
virtual const FText GetPaletteCategory() override;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
//This is set during run time by a UTobiiGazeFocusableComponent if this is a world space widget.
|
||||
TWeakObjectPtr<UWidgetComponent> WorldSpaceHostWidgetComponent;
|
||||
TSharedPtr<class STobiiGazeFocusableWidget> MySlateWidget;
|
||||
|
||||
void SlateHandleHovered();
|
||||
void SlateHandleUnhovered();
|
||||
};
|
||||
166
Source/TobiiGTOM/Public/GTOMAwareUI/TobiiRadialMenuWidget.h
Normal file
166
Source/TobiiGTOM/Public/GTOMAwareUI/TobiiRadialMenuWidget.h
Normal file
@@ -0,0 +1,166 @@
|
||||
/******************************************************************************
|
||||
* Copyright 2017- Tobii Technology AB. All rights reserved.
|
||||
*
|
||||
* @author Temaran | Fredrik Lindh | fredrik.lindh@tobii.com | https://github.com/Temaran
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "TobiiGTOMTypes.h"
|
||||
#include "STobiiRadialMenuWidget.h"
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "ObjectEditorUtils.h"
|
||||
#include "Components/SizeBox.h"
|
||||
#include "Components/WidgetComponent.h"
|
||||
|
||||
#include "TobiiRadialMenuWidget.generated.h"
|
||||
|
||||
UCLASS()
|
||||
class TOBIIGTOM_API UTobiiRadialMenuSlot : public UPanelSlot
|
||||
{
|
||||
GENERATED_UCLASS_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Layout|Radial Menu Slot")
|
||||
FVector2D Offset;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Layout|Radial Menu Slot")
|
||||
float Scale;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Layout|Radial Menu Slot")
|
||||
float Alpha;
|
||||
|
||||
public:
|
||||
#if WITH_EDITOR
|
||||
virtual bool NudgeByDesigner(const FVector2D& NudgeDirection, const TOptional<int32>& GridSnapSize) override;
|
||||
virtual bool DragDropPreviewByDesigner(const FVector2D& LocalCursorPosition, const TOptional<int32>& XGridSnapSize, const TOptional<int32>& YGridSnapSize) override;
|
||||
virtual void SynchronizeFromTemplate(const UPanelSlot* const TemplateSlot) override;
|
||||
#endif //WITH_EDITOR
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Layout|Radial Menu Slot")
|
||||
void SetOffset(FVector2D InOffset);
|
||||
UFUNCTION(BlueprintCallable, Category = "Layout|Radial Menu Slot")
|
||||
FVector2D GetOffset() const;
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Layout|Radial Menu Slot")
|
||||
void SetScale(float InScale);
|
||||
UFUNCTION(BlueprintCallable, Category = "Layout|Radial Menu Slot")
|
||||
float GetScale() const;
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Layout|Radial Menu Slot")
|
||||
void SetAlpha(float InAlpha);
|
||||
UFUNCTION(BlueprintCallable, Category = "Layout|Radial Menu Slot")
|
||||
float GetAlpha() const;
|
||||
|
||||
public:
|
||||
STobiiRadialMenuWidget::FSlot* GetSlateSlot() { return Slot; }
|
||||
void BuildSlot(TSharedRef<STobiiRadialMenuWidget> RadialMenu);
|
||||
|
||||
// UPanelSlot interface
|
||||
virtual void SynchronizeProperties() override;
|
||||
// End of UPanelSlot interface
|
||||
|
||||
virtual void ReleaseSlateResources(bool bReleaseChildren) override;
|
||||
|
||||
#if WITH_EDITOR
|
||||
// UObject interface
|
||||
virtual void PreEditChange(class FEditPropertyChain& PropertyAboutToChange) override;
|
||||
virtual void PostEditChangeChainProperty(struct FPropertyChangedChainEvent& PropertyChangedEvent) override;
|
||||
// End of UObject interface
|
||||
#endif
|
||||
|
||||
private:
|
||||
STobiiRadialMenuWidget::FSlot* Slot;
|
||||
};
|
||||
|
||||
/**
|
||||
*/
|
||||
UCLASS(BlueprintType, Blueprintable, meta = (BlueprintSpawnableComponent, DisplayName= "Tobii Radial Menu"))
|
||||
class TOBIIGTOM_API UTobiiRadialMenuWidget : public UPanelWidget
|
||||
{
|
||||
GENERATED_UCLASS_BODY()
|
||||
|
||||
public:
|
||||
//A hard border will not be blended with the panel, while a soft border will be blended
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Radial Menu")
|
||||
bool bUseHardBorder;
|
||||
//The color of the borders around each panel
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Radial Menu")
|
||||
FColor BorderColor;
|
||||
//The color of the panels themselves
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Radial Menu")
|
||||
FColor PanelColor;
|
||||
//The thickness of the border area
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Radial Menu")
|
||||
float BorderThicknessPx;
|
||||
//The amount of pixels separating each segment
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Radial Menu")
|
||||
float SegmentSeparationPx;
|
||||
//This is how rotated the panel is. Useful if you want another orientation.
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Radial Menu")
|
||||
float AngularDisplacementDeg;
|
||||
//This is the preferred radius. This will inform the desired size of the widget
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Radial Menu")
|
||||
float RadiusPx;
|
||||
//The amount of vertices that will be used for the outside of the circle segments in total.
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Radial Menu")
|
||||
int32 VertexCount;
|
||||
|
||||
public:
|
||||
UFUNCTION(BlueprintCallable, Category = "Radial Menu")
|
||||
void SetUseHardBorder(bool bNewUseHardBorder);
|
||||
UFUNCTION(BlueprintCallable, Category = "Radial Menu")
|
||||
void SetBorderColor(FColor NewBorderColor);
|
||||
UFUNCTION(BlueprintCallable, Category = "Radial Menu")
|
||||
void SetPanelColor(FColor NewPanelColor);
|
||||
UFUNCTION(BlueprintCallable, Category = "Radial Menu")
|
||||
void SetBorderThicknessPx(float NewBorderThicknessPx);
|
||||
UFUNCTION(BlueprintCallable, Category = "Radial Menu")
|
||||
void SetSegmentSeparationPx(float NewSegmentSeparationPx);
|
||||
UFUNCTION(BlueprintCallable, Category = "Radial Menu")
|
||||
void SetAngularDisplacementDeg(float NewAngularDisplacementDeg);
|
||||
UFUNCTION(BlueprintCallable, Category = "Radial Menu")
|
||||
void SetRadiusPx(float NewRadiusPx);
|
||||
UFUNCTION(BlueprintCallable, Category = "Radial Menu")
|
||||
void SetVertexCount(int32 NewVertexCount);
|
||||
|
||||
public:
|
||||
/** */
|
||||
UFUNCTION(BlueprintCallable, Category = "Radial Menu")
|
||||
UTobiiRadialMenuSlot* AddRadialMenuChild(UWidget* Content);
|
||||
|
||||
/** Computes the geometry for a particular slot based on the current geometry of the canvas. */
|
||||
bool GetGeometryForSlot(int32 SlotIndex, FGeometry& ArrangedGeometry) const;
|
||||
bool GetGeometryForSlot(UTobiiRadialMenuSlot* InSlot, FGeometry& ArrangedGeometry) const;
|
||||
|
||||
void ReleaseSlateResources(bool bReleaseChildren) override;
|
||||
|
||||
#if WITH_EDITOR
|
||||
// UWidget interface
|
||||
virtual const FText GetPaletteCategory() override;
|
||||
// End UWidget interface
|
||||
|
||||
// UWidget interface
|
||||
virtual bool LockToPanelOnDrag() const override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// End UWidget interface
|
||||
#endif
|
||||
|
||||
protected:
|
||||
|
||||
// UPanelWidget
|
||||
virtual UClass* GetSlotClass() const override;
|
||||
virtual void OnSlotAdded(UPanelSlot* Slot) override;
|
||||
virtual void OnSlotRemoved(UPanelSlot* Slot) override;
|
||||
// End UPanelWidget
|
||||
|
||||
protected:
|
||||
|
||||
TSharedPtr<class STobiiRadialMenuWidget> MyRadialMenu;
|
||||
|
||||
protected:
|
||||
// UWidget interface
|
||||
virtual TSharedRef<SWidget> RebuildWidget() override;
|
||||
// End of UWidget interface
|
||||
};
|
||||
156
Source/TobiiGTOM/Public/TobiiGTOMBlueprintLibrary.h
Normal file
156
Source/TobiiGTOM/Public/TobiiGTOMBlueprintLibrary.h
Normal file
@@ -0,0 +1,156 @@
|
||||
/******************************************************************************
|
||||
* Copyright 2017- Tobii Technology AB. All rights reserved.
|
||||
*
|
||||
* @author Temaran | Fredrik Lindh | fredrik.lindh@tobii.com | https://github.com/Temaran
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "GTOMAwareUI/TobiiGazeFocusableWidget.h"
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Components/WidgetComponent.h"
|
||||
#include "Components/WidgetInteractionComponent.h"
|
||||
#include "Kismet/BlueprintFunctionLibrary.h"
|
||||
|
||||
#include "TobiiGTOMBlueprintLibrary.generated.h"
|
||||
|
||||
/**
|
||||
* Simplified interface for blueprint use. Only exposes the features most likely to be consumed from BP.
|
||||
*/
|
||||
UCLASS()
|
||||
class TOBIIGTOM_API UTobiiGTOMBlueprintLibrary : public UBlueprintFunctionLibrary
|
||||
{
|
||||
GENERATED_UCLASS_BODY()
|
||||
|
||||
public:
|
||||
/**
|
||||
* Set which player controller should be used for GTOM.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "Tobii GTOM")
|
||||
static void SetGTOMPlayerController(APlayerController* NewGTOMPlayerController);
|
||||
|
||||
/**
|
||||
* Get the component the focus system believes the user is looking at.
|
||||
*/
|
||||
UFUNCTION(BlueprintPure, Category = "Tobii GTOM")
|
||||
static bool GetGazeFocusData(FTobiiGazeFocusData& OutFocusData);
|
||||
|
||||
/**
|
||||
* Get a sorted list of components that the focus system believes the user is looking at.
|
||||
*/
|
||||
UFUNCTION(BlueprintPure, Category = "Tobii GTOM")
|
||||
static bool GetAllGazeFocusData(TArray<FTobiiGazeFocusData>& OutFocusData);
|
||||
|
||||
/**
|
||||
* Get the component the focus system believes the user is looking at. This variant allows you to filter out certain objects in accordance with a filter list.
|
||||
*
|
||||
* @param FocusLayerFilterList These are the filters that will determine what focus data you will receive. The behavior of the filters are controlled by bIsWhiteList.
|
||||
* @param bIsWhiteList This controls how the filters in FocusFilterList are used. If this is true, only focusables with a layer that is in the FocusFilterList will be considered. If this is false, the FocusFilterList will act like a black list, excluding any focusables whos layer can be found in the array.
|
||||
* @param bWantPrimitives If this is true, focus data with valid UPrimitiveComponents will be included in the output results.
|
||||
* @param bWantWidgets If this is true, focus data with valid UWidgets will be included in the output results.
|
||||
* @param OutFocusData Output focus data.
|
||||
*/
|
||||
UFUNCTION(BlueprintPure, Category = "Tobii GTOM")
|
||||
static bool GetFilteredGazeFocusData(const TArray<FName>& FocusLayerFilterList, const bool bIsWhiteList, const bool bWantPrimitives, const bool bWantWidgets, FTobiiGazeFocusData& OutFocusData);
|
||||
|
||||
/**
|
||||
* Get a sorted list of components that the focus system believes the user is looking at. This variant allows you to filter out certain objects in accordance with a filter list.
|
||||
*
|
||||
* @param FocusLayerFilterList These are the filters that will determine what focus data you will receive. The behavior of the filters are controlled by bIsWhiteList.
|
||||
* @param bIsWhiteList This controls how the filters in FocusFilterList are used. If this is true, only focusables with a layer that is in the FocusFilterList will be considered. If this is false, the FocusFilterList will act like a black list, excluding any focusables whos layer can be found in the array.
|
||||
* @param bWantPrimitives If this is true, focus data with valid UPrimitiveComponents will be included in the output results.
|
||||
* @param bWantWidgets If this is true, focus data with valid UWidgets will be included in the output results.
|
||||
* @param OutFocusData Output focus data.
|
||||
*/
|
||||
UFUNCTION(BlueprintPure, Category = "Tobii GTOM")
|
||||
static bool GetAllFilteredGazeFocusData(const TArray<FName>& FocusLayerFilterList, const bool bIsWhiteList, const bool bWantPrimitives, const bool bWantWidgets, TArray<FTobiiGazeFocusData>& OutFocusData);
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* Utils */
|
||||
/************************************************************************/
|
||||
/**
|
||||
* Gets a simple ray hit along combined gaze
|
||||
*/
|
||||
UFUNCTION(BlueprintPure, Category = "Tobii GTOM Utils")
|
||||
static const FHitResult& GetNaiveGazeHit();
|
||||
|
||||
/**
|
||||
* Tests to see whether a primitive component is gaze focusable
|
||||
*/
|
||||
UFUNCTION(BlueprintPure, Category = "Tobii GTOM Utils")
|
||||
static bool IsPrimitiveComponentGazeFocusable(UPrimitiveComponent* PrimitiveComponent);
|
||||
|
||||
/**
|
||||
* Tests to see whether a widget is gaze focusable
|
||||
*/
|
||||
UFUNCTION(BlueprintPure, Category = "Tobii GTOM Utils")
|
||||
static bool IsWidgetGazeFocusable(UWidget* Widget);
|
||||
|
||||
/**
|
||||
* Gets the *untransformed* focus offset for a primitive component.
|
||||
*/
|
||||
UFUNCTION(BlueprintPure, Category = "Tobii GTOM Utils")
|
||||
static bool GetPrimitiveComponentFocusOffset(USceneComponent* Component, FVector& OutFocusOffset);
|
||||
|
||||
/**
|
||||
* Gets the focus point on the primitive.
|
||||
*/
|
||||
UFUNCTION(BlueprintPure, Category = "Tobii GTOM Utils")
|
||||
static bool GetPrimitiveComponentFocusLocation(USceneComponent* Component, FVector& OutFocusLocation);
|
||||
|
||||
/*
|
||||
* This function will traverse a widget tree given a root and add any UTobiiGazeFocusableWidget to the screen space widget collection.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "Tobii GTOM Utils")
|
||||
static void RegisterScreenSpaceGazeFocusableWidgets(UWidget* Root);
|
||||
|
||||
/**
|
||||
* Helper function to simulate gaze focus using a widget interaction component
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "Tobii GTOM Utils")
|
||||
static bool MakeGazeFocusDataForWidgetInteractionComponent(UWidgetInteractionComponent* WidgetInteraction, ECollisionChannel CollisionChannel, FTobiiGazeFocusData& OutGazeFocusData);
|
||||
|
||||
/**
|
||||
* Helper function to simulate gaze focus using a widget interaction component
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "Tobii GTOM Utils")
|
||||
static void EmulateGazeFocusUsingWidgetInteractionComponent(UWidgetInteractionComponent* WidgetInteraction, ECollisionChannel CollisionChannel);
|
||||
|
||||
/**
|
||||
* This function will find the largest possible rectangle that can be inscribed into a given circle.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "Tobii Math Utils Utils")
|
||||
static bool FindLargestInscribedAlignedRect(float CircleSegmentAngleRad, float CircleRadius, FVector2D& LargestInscribedRectSize, float& DistanceToCenter);
|
||||
|
||||
/**
|
||||
* This function will project a local point in a widget hosted by a widget component into world space
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "Tobii Math Utils")
|
||||
static bool TransformWidgetLocalPointToWorld(UWidgetComponent* Component, const FVector2D& LocalWidgetLocation, FVector& OutWorldLocation);
|
||||
|
||||
/**
|
||||
* This function will project a world point to the widget's local space
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "Tobii Math Utils")
|
||||
static bool TransformWorldPointToWidgetLocal(UWidgetComponent* Component, const FVector& WorldLocation, const FVector& WorldDirection, FVector2D& OutLocalWidgetLocation);
|
||||
|
||||
/**
|
||||
* This function will test whether a right angle cone and a sphere intersects. Very useful for world space eye tracking.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "Tobii Math Utils")
|
||||
static bool TestConeSphereIntersection(const FVector& ConeApex, const FVector& ConeDirection, const float ConeAngleDeg, const FVector& SphereCenter, const float SphereRadius);
|
||||
|
||||
/**
|
||||
* This function will test whether a rectangle and a rotated ellipse intersects. Very useful for screen space eye tracking.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "Tobii Math Utils")
|
||||
static bool TestRectEllipseIntersection(const FVector2D& RectangleCenter, const FVector2D& RectangleRightAxis, const FVector2D& RectangleUpAxis, const FVector2D& RectangleExtents, const FVector2D& EllipseCenter, const FVector2D& EllipseRadii, const float& EllipseRotationDeg);
|
||||
|
||||
/**
|
||||
* Get a random point on a circle centered at the origin that is uniformly distributed.
|
||||
*/
|
||||
UFUNCTION(BlueprintPure, Category = "Tobii Math Utils")
|
||||
static FVector2D GetUniformlyDistributedRandomCirclePoint(float CircleRadius);
|
||||
};
|
||||
93
Source/TobiiGTOM/Public/TobiiGTOMTypes.h
Normal file
93
Source/TobiiGTOM/Public/TobiiGTOMTypes.h
Normal file
@@ -0,0 +1,93 @@
|
||||
/******************************************************************************
|
||||
* Copyright 2017- Tobii Technology AB. All rights reserved.
|
||||
*
|
||||
* @author Temaran | Fredrik Lindh | fredrik.lindh@tobii.com | https://github.com/Temaran
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Engine/EngineTypes.h"
|
||||
|
||||
#include "TobiiGTOMTypes.generated.h"
|
||||
|
||||
class UTobiiGazeFocusableWidget;
|
||||
typedef uint32 FTobiiFocusableUID; //Only use this ID type for our focus container types like UTobiiGazeFocusableComponents and UTobiiGazeFocusableWidgets
|
||||
typedef uint32 FEngineFocusableUID; //Only use this for base engine things that can be focused, like UPrimitiveComponents and UWidgets
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FPrimitiveReceivedGazeFocusSignature, UPrimitiveComponent*, FocusedComponent);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FPrimitiveLostGazeFocusSignature, UPrimitiveComponent*, FocusedComponent);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FWidgetReceivedGazeFocusSignature, UTobiiGazeFocusableWidget*, FocusedWidget);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FWidgetLostGazeFocusSignature, UTobiiGazeFocusableWidget*, FocusedWidget);
|
||||
|
||||
UENUM(BlueprintType)
|
||||
enum class ETobiiCleanUIMode : uint8
|
||||
{
|
||||
/** CleanUI is disabled for this widget. */
|
||||
Disabled,
|
||||
|
||||
/** CleanUI will only consider the gaze point for determining alpha, and will ignore nearby widgets. */
|
||||
Normal,
|
||||
|
||||
/** This widget is aware of it's neighbors and only one widget can be faded in at a time. */
|
||||
FocusExclusive,
|
||||
|
||||
/** This widget will still calcualte its CleanUI alpha value, but it will not apply it when calculating its own color. */
|
||||
Silent
|
||||
};
|
||||
|
||||
/**
|
||||
* Information about an object that is being considered when determining user focus.
|
||||
* When utilizing gaze, this is almost always what you should be using as your input data.
|
||||
*/
|
||||
USTRUCT(BlueprintType)
|
||||
struct FTobiiGazeFocusData
|
||||
{
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
public:
|
||||
FTobiiGazeFocusData()
|
||||
: FocusedActor()
|
||||
, FocusedPrimitiveComponent()
|
||||
, FocusedWidget()
|
||||
, LastVisibleWorldLocation(0.0f, 0.0f, 0.0f)
|
||||
, FocusConfidence(0.0f)
|
||||
{}
|
||||
|
||||
//This is the actor that the Focused Primitive Component belongs to.
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Focus Data")
|
||||
TWeakObjectPtr<AActor> FocusedActor;
|
||||
|
||||
//This is the primitive component that is most likely to hold the user's focus.
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Focus Data")
|
||||
TWeakObjectPtr<UPrimitiveComponent> FocusedPrimitiveComponent;
|
||||
|
||||
//This is the primitive component that is most likely to hold the user's focus.
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Focus Data")
|
||||
TWeakObjectPtr<UTobiiGazeFocusableWidget> FocusedWidget;
|
||||
|
||||
//This is the point on the Focused Primitive Component that was last confirmed visible to the user. This is very useful when aligning objects towards a focused object.
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Focus Data")
|
||||
FVector LastVisibleWorldLocation;
|
||||
|
||||
//This is how confident the focus system is that this object is in focus. The object with the highest confidence is not necessarily the object with focus however.
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Focus Data")
|
||||
float FocusConfidence;
|
||||
};
|
||||
|
||||
//This contains the tags that can optionally be used to inform the GTOM system about the primitive component they are attached to. These only exist since we cannot add UPROPERTY's to primitive components without engine modifications.
|
||||
//If you want to override behavior or widgets, please change the relevant properties on the TobiiGazeFocusableWidget since we have full access to that type.
|
||||
class TOBIIGTOM_API FTobiiPrimitiveComponentGazeFocusTags
|
||||
{
|
||||
public:
|
||||
static FName HasGazeFocusTag; //A primitive component with this tag is the primitive component that most likely has focus irregardless of layer filters.
|
||||
static FName GazeFocusableTag; //A primitive component with this tag will participate in GTOM even if the actor owning the primitive doesn't have a GazeFocusableComponent, or if the default for the gaze focusable is off.
|
||||
static FName NotGazeFocusableTag; //A primitive component with this tag will not participate in GTOM even if the actor owning the primitive component has a GazeFocusableComponent.
|
||||
static FString GazeFocusablePriorityTag; //A primitive component with this tag will modify it's priority. Priority is used when only a certain number of focusables can participate in an operation. An example of this is ID buffer based GTOM. This is an argument tag, this means you must provide the value after the tag. Usage example: GazeFocusablePriorityTag 100
|
||||
static FString GazeFocusableMaximumDistanceTag; //A primitive component with this tag and has the GazeFocusableTag will only be considered if the distance between the GTOM source and the component is shorter than the argument part of the tag. Please note that this tag cannot be used to force the GTOM line traces to be longer than default, only exclude the primitive if the distance is longer than this argument. This is an argument tag, this means you must provide the value after the tag. Usage example: GazeFocusableMaximumDistanceTag 10000
|
||||
static FString GazeFocusableLayerTag; //A focus manager can opt to only query a subset of focusables by using a focus layer. A primitive will this tag will only be subject to the layer supplied as the argument. This is an argument tag, this means you must provide the value after the tag. Usage example: GazeFocusableLayerTag Enemies
|
||||
|
||||
static FString PrimitiveFocusOffsetXTag; //If this tag is present, it tells the various systems interacting with gaze focus that the actual focus point is relative to the primitive origin by this amount.
|
||||
static FString PrimitiveFocusOffsetYTag; //If this tag is present, it tells the various systems interacting with gaze focus that the actual focus point is relative to the primitive origin by this amount.
|
||||
static FString PrimitiveFocusOffsetZTag; //If this tag is present, it tells the various systems interacting with gaze focus that the actual focus point is relative to the primitive origin by this amount.
|
||||
};
|
||||
88
Source/TobiiGTOM/Public/TobiiGazeFocusManagerComponent.h
Normal file
88
Source/TobiiGTOM/Public/TobiiGazeFocusManagerComponent.h
Normal file
@@ -0,0 +1,88 @@
|
||||
/******************************************************************************
|
||||
* Copyright 2017- Tobii Technology AB. All rights reserved.
|
||||
*
|
||||
* @author Temaran | Fredrik Lindh | fredrik.lindh@tobii.com | https://github.com/Temaran
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "TobiiGTOMTypes.h"
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Components/ActorComponent.h"
|
||||
#include "Delegates/DelegateCombinations.h"
|
||||
|
||||
#include "TobiiGazeFocusManagerComponent.generated.h"
|
||||
|
||||
/*
|
||||
* Tobii focus managers are an easier way to set up focus layer filters and access the focusables associated with them.
|
||||
* It also offers a way to get notified of changes in gaze focus via events.
|
||||
*/
|
||||
UCLASS(BlueprintType, Blueprintable, meta = (BlueprintSpawnableComponent))
|
||||
class TOBIIGTOM_API UTobiiGazeFocusManagerComponent : public UActorComponent
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UTobiiGazeFocusManagerComponent();
|
||||
|
||||
public:
|
||||
//If this is true, focus data with valid UPrimitiveComponents will be included in the output results.
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Gaze Focus Management")
|
||||
bool bWantPrimitives;
|
||||
|
||||
//If this is true, focus data with valid UWidgets will be included in the output results
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Gaze Focus Management")
|
||||
bool bWantWidgets;
|
||||
|
||||
//This controls how the filters in FocusFilterList are used. If this is true, only focusables with a layer that is in the FocusFilterList will be considered. If this is false, the FocusFilterList will act like a black list, excluding any focusables whos layer can be found in the array.
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Gaze Focus Management")
|
||||
bool bIsWhiteList;
|
||||
|
||||
//These are the filters that will determine what focus data you will receive. The behavior of the filters are controlled by bIsWhiteList.
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Gaze Focus Management")
|
||||
TArray<FName> FocusLayerFilters;
|
||||
|
||||
public:
|
||||
//These functions will notify when gaze focus is lost for this focus manager's filtered set.
|
||||
UPROPERTY(BlueprintAssignable, Category = "Gaze Focus Management")
|
||||
FPrimitiveReceivedGazeFocusSignature OnPrimitiveReceivedGazeFocus;
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category = "Gaze Focus Management")
|
||||
FPrimitiveLostGazeFocusSignature OnPrimitiveLostGazeFocus;
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category = "Gaze Focus Management")
|
||||
FWidgetReceivedGazeFocusSignature OnWidgetReceivedGazeFocus;
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category = "Gaze Focus Management")
|
||||
FWidgetLostGazeFocusSignature OnWidgetLostGazeFocus;
|
||||
|
||||
public:
|
||||
//Get the component the focus system believes the user is looking at, given the filters the focus manager is configured with.
|
||||
UFUNCTION(BlueprintPure, Category = "Gaze Focus Management")
|
||||
void GetBestFilteredPrimitiveComponentFocusData(FTobiiGazeFocusData& OutFocusData) const;
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "Gaze Focus Management")
|
||||
void GetBestFilteredWidgetComponentFocusData(FTobiiGazeFocusData& OutFocusData) const;
|
||||
|
||||
//Get a sorted list of components that the focus system believes the user is looking at, given the filters the focus manager is configured with.
|
||||
UFUNCTION(BlueprintPure, Category = "Gaze Focus Management")
|
||||
void GetAllFilteredFocusData(TArray<FTobiiGazeFocusData>& OutFocusData) const;
|
||||
|
||||
/************************************************************************/
|
||||
/* UActorComponent */
|
||||
/************************************************************************/
|
||||
public:
|
||||
virtual void TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction) override;
|
||||
|
||||
private:
|
||||
TWeakObjectPtr<UPrimitiveComponent> PreviouslyFocusedPrimitiveComponent;
|
||||
TWeakObjectPtr<UTobiiGazeFocusableWidget> PreviouslyFocusedWidget;
|
||||
FTobiiGazeFocusData BestPrimitiveComponentFocusData;
|
||||
FTobiiGazeFocusData BestWidgetFocusData;
|
||||
TArray<FTobiiGazeFocusData> AllFocusData;
|
||||
|
||||
void ResetFocusData();
|
||||
void NotifyPrimitiveComponentGazeFocusReceived(UPrimitiveComponent& PrimitiveComponentToReceiveFocus);
|
||||
void NotifyPrimitiveComponentGazeFocusLost(UPrimitiveComponent& PrimitiveComponentToLoseFocus);
|
||||
};
|
||||
111
Source/TobiiGTOM/Public/TobiiGazeFocusableComponent.h
Normal file
111
Source/TobiiGTOM/Public/TobiiGazeFocusableComponent.h
Normal file
@@ -0,0 +1,111 @@
|
||||
/******************************************************************************
|
||||
* Copyright 2017- Tobii Technology AB. All rights reserved.
|
||||
*
|
||||
* @author Temaran | Fredrik Lindh | fredrik.lindh@tobii.com | https://github.com/Temaran
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "TobiiGazeFocusableWidget.h"
|
||||
#include "TobiiGTOMTypes.h"
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "SceneTypes.h"
|
||||
#include "Components/ActorComponent.h"
|
||||
|
||||
#include "TobiiGazeFocusableComponent.generated.h"
|
||||
|
||||
class UPrimitiveComponent;
|
||||
class UTobiiGazeFocusManagerComponent;
|
||||
|
||||
/**
|
||||
* This component is a helper that can make it easier to setup GTOM, as well as provide an focus event interface for this object.
|
||||
* If you don't use specific tags on your primitive components, the values on this component will be used instead.
|
||||
* This component is REQUIRED for GPU based GTOM.
|
||||
* This component is also REQUIRED for world space widget focus.
|
||||
* This should be placed on the root actor for every component tree. This means that if you have an actor that has a child actor that has primitive components you would like to control, you need to add one of these components to that child actor as well.
|
||||
* Having more than one of these components on one actor is not recommended, as it is unclear which focusable component's values will be used.
|
||||
* If you want world space UI widgets to participate in GTOM, you must attach one of these components to the actor carrying the WidgetComponent(s) to affect
|
||||
*/
|
||||
UCLASS(BlueprintType, Blueprintable, meta = (BlueprintSpawnableComponent))
|
||||
class TOBIIGTOM_API UTobiiGazeFocusableComponent : public UActorComponent
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
//The default value for focusability to be used by all primitives on the same actor as this component. It can be useful to set this to false if you only want a few primitives on the actor to be focusable.
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Default Focus Settings")
|
||||
bool bDefaultIsFocusable;
|
||||
|
||||
//The focus priority is optional input that you can provide to GTOM. Objects with higher focus priority are more "important" and are therefore more likely to be construed as being in focus.
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Default Focus Settings")
|
||||
float DefaultFocusPriority;
|
||||
|
||||
//If this object is at least this far away from the player, it will not participate in GTOM. This will only be in effect if it is greater than zero.
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Default Focus Settings")
|
||||
float DefaultMaxFocusDistance;
|
||||
|
||||
//A developer can opt to only query a subset of focusables by using a focus layer. This is the default layer that will be used if none is set with tags on primitives or on a gazefocusablewidget.
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Default Focus Settings")
|
||||
FName DefaultFocusLayer;
|
||||
|
||||
public:
|
||||
//These functions will notify when gaze focus is lost or gained irregardless of focus layers.
|
||||
UPROPERTY(BlueprintAssignable, Category = "Gaze Focus")
|
||||
FPrimitiveReceivedGazeFocusSignature OnPrimitiveReceivedGazeFocus;
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category = "Gaze Focus")
|
||||
FPrimitiveLostGazeFocusSignature OnPrimitiveLostGazeFocus;
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category = "Gaze Focus")
|
||||
FWidgetReceivedGazeFocusSignature OnWidgetReceivedGazeFocus;
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category = "Gaze Focus")
|
||||
FWidgetLostGazeFocusSignature OnWidgetLostGazeFocus;
|
||||
|
||||
public:
|
||||
UFUNCTION(BlueprintCallable, Category = "CleanUI")
|
||||
void RefreshOwnedWidgets();
|
||||
|
||||
public:
|
||||
UTobiiGazeFocusableComponent();
|
||||
virtual void PrimitiveReceivedGazeFocus(UPrimitiveComponent* FocusedComponent);
|
||||
virtual void PrimitiveLostGazeFocus(UPrimitiveComponent* FocusedComponent);
|
||||
virtual void WidgetReceivedGazeFocus(UTobiiGazeFocusableWidget* FocusedWidget);
|
||||
virtual void WidgetLostGazeFocus(UTobiiGazeFocusableWidget* FocusedWidget);
|
||||
|
||||
const TMap<FTobiiFocusableUID, TWeakObjectPtr<UTobiiGazeFocusableWidget>>& GetAllFocusableWidgets() { return AllFocusableWidgets; }
|
||||
const TArray<TWeakObjectPtr<UTobiiGazeFocusableWidget>>& GetFocusableWidgetsForPrimitiveComponent(UPrimitiveComponent* PrimitiveComponent);
|
||||
|
||||
/************************************************************************/
|
||||
/* UActorComponent */
|
||||
/************************************************************************/
|
||||
public:
|
||||
virtual void BeginPlay() override;
|
||||
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
|
||||
virtual void TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction) override;
|
||||
|
||||
public:
|
||||
static void ClearFocusableComponents();
|
||||
static const TMap<FTobiiFocusableUID, TWeakObjectPtr<UTobiiGazeFocusableComponent>>& GetFocusableComponents();
|
||||
|
||||
static void UpdateGazeFocusPrio(FVector POVActorLocation, int32 MaxNrFocusables);
|
||||
static const TSet<FPrimitiveComponentId>* GetGazeFocusPrioSet();
|
||||
|
||||
static bool IsPrimitiveFocusable(UPrimitiveComponent* Primitive);
|
||||
static bool GetMaxFocusDistanceForPrimitive(UPrimitiveComponent* Primitive, float& OutMaxDistance);
|
||||
static float GetFocusPriorityForPrimitive(UPrimitiveComponent* Primitive);
|
||||
static FName GetFocusLayerForPrimitive(UPrimitiveComponent* Primitive);
|
||||
|
||||
static bool IsWidgetFocusable(UTobiiGazeFocusableWidget* GazeFocusableWidget);
|
||||
static bool GetMaxFocusDistanceForWidget(UTobiiGazeFocusableWidget* GazeFocusableWidget, float& OutMaxDistance);
|
||||
static float GetFocusPriorityForWidget(UTobiiGazeFocusableWidget* GazeFocusableWidget);
|
||||
static FName GetFocusLayerForWidget(UTobiiGazeFocusableWidget* GazeFocusableWidget);
|
||||
|
||||
private:
|
||||
TMap<FTobiiFocusableUID, TWeakObjectPtr<UTobiiGazeFocusableWidget>> AllFocusableWidgets;
|
||||
TMap<FEngineFocusableUID, TArray<TWeakObjectPtr<UTobiiGazeFocusableWidget>>> PrimitiveMap;
|
||||
bool bWidgetsRefreshedOnce;
|
||||
|
||||
void GatherGazeFocusableWidgets(UWidget* Parent, TArray<TWeakObjectPtr<UTobiiGazeFocusableWidget>>& WidgetArray, UWidgetComponent* OptionalHostWidgetComponent);
|
||||
};
|
||||
Reference in New Issue
Block a user