2022-05-23 18:41:30 +00:00
// Copyright Epic Games, Inc. All Rights Reserved.
# pragma once
# include "AsyncMixin.h"
# include "Blueprint/UserWidgetPool.h"
2022-09-13 07:18:28 +00:00
# include "Containers/Array.h"
# include "Containers/UnrealString.h"
# include "Engine/LocalPlayer.h"
# include "HAL/Platform.h"
# include "Layout/Children.h"
# include "Layout/Geometry.h"
# include "Layout/Visibility.h"
# include "Math/Vector2D.h"
# include "Misc/Attribute.h"
# include "Misc/Optional.h"
# include "SlotBase.h"
# include "Templates/SharedPointer.h"
# include "Types/SlateEnums.h"
# include "UObject/GCObject.h"
# include "UObject/WeakObjectPtr.h"
# include "UObject/WeakObjectPtrTemplates.h"
# include "Widgets/DeclarativeSyntaxSupport.h"
# include "Widgets/SPanel.h"
# include "Widgets/SWidget.h"
2022-05-23 18:41:30 +00:00
2022-09-13 07:18:28 +00:00
class FActiveTimerHandle ;
2022-05-23 18:41:30 +00:00
class FArrangedChildren ;
2022-09-13 07:18:28 +00:00
class FChildren ;
class FPaintArgs ;
class FReferenceCollector ;
class FSlateRect ;
class FSlateWindowElementList ;
class FWidgetStyle ;
class UIndicatorDescriptor ;
2022-05-23 18:41:30 +00:00
class ULyraIndicatorManagerComponent ;
2022-09-13 07:18:28 +00:00
struct FSlateBrush ;
2022-05-23 18:41:30 +00:00
class SActorCanvas : public SPanel , public FAsyncMixin , public FGCObject
{
public :
/** ActorCanvas-specific slot class */
class FSlot : public TSlotBase < FSlot >
{
public :
FSlot ( UIndicatorDescriptor * InIndicator )
: TSlotBase < FSlot > ( )
, Indicator ( InIndicator )
, ScreenPosition ( FVector2D : : ZeroVector )
, Depth ( 0 )
, Priority ( 0.f )
, bIsIndicatorVisible ( true )
, bInFrontOfCamera ( true )
, bHasValidScreenPosition ( false )
, bDirty ( true )
, bWasIndicatorClamped ( false )
, bWasIndicatorClampedStatusChanged ( false )
{
}
SLATE_SLOT_BEGIN_ARGS ( FSlot , TSlotBase < FSlot > )
SLATE_SLOT_END_ARGS ( )
using TSlotBase < FSlot > : : Construct ;
bool GetIsIndicatorVisible ( ) const { return bIsIndicatorVisible ; }
void SetIsIndicatorVisible ( bool bVisible )
{
if ( bIsIndicatorVisible ! = bVisible )
{
bIsIndicatorVisible = bVisible ;
bDirty = true ;
}
RefreshVisibility ( ) ;
}
FVector2D GetScreenPosition ( ) const { return ScreenPosition ; }
void SetScreenPosition ( FVector2D InScreenPosition )
{
if ( ScreenPosition ! = InScreenPosition )
{
ScreenPosition = InScreenPosition ;
bDirty = true ;
}
}
double GetDepth ( ) const { return Depth ; }
void SetDepth ( double InDepth )
{
if ( Depth ! = InDepth )
{
Depth = InDepth ;
bDirty = true ;
}
}
int32 GetPriority ( ) const { return Priority ; }
void SetPriority ( int32 InPriority )
{
if ( Priority ! = InPriority )
{
Priority = InPriority ;
bDirty = true ;
}
}
bool GetInFrontOfCamera ( ) const { return bInFrontOfCamera ; }
void SetInFrontOfCamera ( bool bInFront )
{
if ( bInFrontOfCamera ! = bInFront )
{
bInFrontOfCamera = bInFront ;
bDirty = true ;
}
RefreshVisibility ( ) ;
}
bool HasValidScreenPosition ( ) const { return bHasValidScreenPosition ; }
void SetHasValidScreenPosition ( bool bValidScreenPosition )
{
if ( bHasValidScreenPosition ! = bValidScreenPosition )
{
bHasValidScreenPosition = bValidScreenPosition ;
bDirty = true ;
}
RefreshVisibility ( ) ;
}
bool bIsDirty ( ) const { return bDirty ; }
void ClearDirtyFlag ( )
{
bDirty = false ;
}
bool WasIndicatorClamped ( ) const { return bWasIndicatorClamped ; }
void SetWasIndicatorClamped ( bool bWasClamped ) const
{
if ( bWasClamped ! = bWasIndicatorClamped )
{
bWasIndicatorClamped = bWasClamped ;
bWasIndicatorClampedStatusChanged = true ;
}
}
bool WasIndicatorClampedStatusChanged ( ) const { return bWasIndicatorClampedStatusChanged ; }
void ClearIndicatorClampedStatusChangedFlag ( )
{
bWasIndicatorClampedStatusChanged = false ;
}
private :
void RefreshVisibility ( )
{
const bool bIsVisible = bIsIndicatorVisible & & bHasValidScreenPosition ;
GetWidget ( ) - > SetVisibility ( bIsVisible ? EVisibility : : SelfHitTestInvisible : EVisibility : : Collapsed ) ;
}
//Kept Alive by SActorCanvas::AddReferencedObjects
UIndicatorDescriptor * Indicator ;
FVector2D ScreenPosition ;
double Depth ;
int32 Priority ;
uint8 bIsIndicatorVisible : 1 ;
uint8 bInFrontOfCamera : 1 ;
uint8 bHasValidScreenPosition : 1 ;
uint8 bDirty : 1 ;
/**
* Cached & frame - deferred value of whether the indicator was visually screen clamped last frame or not ;
* Semi - hacky mutable implementation as it is cached during a const paint operation
*/
mutable uint8 bWasIndicatorClamped : 1 ;
mutable uint8 bWasIndicatorClampedStatusChanged : 1 ;
friend class SActorCanvas ;
} ;
/** ActorCanvas-specific slot class */
class FArrowSlot : public TSlotBase < FArrowSlot >
{
} ;
/** Begin the arguments for this slate widget */
SLATE_BEGIN_ARGS ( SActorCanvas ) {
_Visibility = EVisibility : : HitTestInvisible ;
}
/** Indicates that we have a slot that this widget supports */
SLATE_SLOT_ARGUMENT ( SActorCanvas : : FSlot , Slots )
/** This always goes at the end */
SLATE_END_ARGS ( )
SActorCanvas ( )
: CanvasChildren ( this )
, ArrowChildren ( this )
, AllChildren ( this )
{
AllChildren . AddChildren ( CanvasChildren ) ;
AllChildren . AddChildren ( ArrowChildren ) ;
}
void Construct ( const FArguments & InArgs , const FLocalPlayerContext & InCtx , const FSlateBrush * ActorCanvasArrowBrush ) ;
// SWidget Interface
virtual void OnArrangeChildren ( const FGeometry & AllottedGeometry , FArrangedChildren & ArrangedChildren ) const override ;
virtual FVector2D ComputeDesiredSize ( float ) const override { return FVector2D : : ZeroVector ; }
virtual FChildren * GetChildren ( ) override { return & AllChildren ; }
virtual int32 OnPaint ( const FPaintArgs & Args , const FGeometry & AllottedGeometry , const FSlateRect & MyCullingRect , FSlateWindowElementList & OutDrawElements , int32 LayerId , const FWidgetStyle & InWidgetStyle , bool bParentEnabled ) const ;
// End SWidget
void SetDrawElementsInOrder ( bool bInDrawElementsInOrder ) { bDrawElementsInOrder = bInDrawElementsInOrder ; }
virtual FString GetReferencerName ( ) const override ;
virtual void AddReferencedObjects ( FReferenceCollector & Collector ) override ;
private :
void OnIndicatorAdded ( UIndicatorDescriptor * Indicator ) ;
void OnIndicatorRemoved ( UIndicatorDescriptor * Indicator ) ;
void AddIndicatorForEntry ( UIndicatorDescriptor * Indicator ) ;
void RemoveIndicatorForEntry ( UIndicatorDescriptor * Indicator ) ;
using FScopedWidgetSlotArguments = TPanelChildren < FSlot > : : FScopedWidgetSlotArguments ;
FScopedWidgetSlotArguments AddActorSlot ( UIndicatorDescriptor * Indicator ) ;
int32 RemoveActorSlot ( const TSharedRef < SWidget > & SlotWidget ) ;
void SetShowAnyIndicators ( bool bIndicators ) ;
EActiveTimerReturnType UpdateCanvas ( double InCurrentTime , float InDeltaTime ) ;
/** Helper function for calculating the offset */
void GetOffsetAndSize ( const UIndicatorDescriptor * Indicator ,
FVector2D & OutSize ,
FVector2D & OutOffset ,
FVector2D & OutPaddingMin ,
FVector2D & OutPaddingMax ) const ;
void UpdateActiveTimer ( ) ;
private :
TArray < UIndicatorDescriptor * > AllIndicators ;
TArray < UIndicatorDescriptor * > InactiveIndicators ;
FLocalPlayerContext LocalPlayerContext ;
TWeakObjectPtr < ULyraIndicatorManagerComponent > IndicatorComponentPtr ;
/** All the slots in this canvas */
TPanelChildren < FSlot > CanvasChildren ;
mutable TPanelChildren < FArrowSlot > ArrowChildren ;
FCombinedChildren AllChildren ;
FUserWidgetPool IndicatorPool ;
const FSlateBrush * ActorCanvasArrowBrush = nullptr ;
mutable int32 NextArrowIndex = 0 ;
mutable int32 ArrowIndexLastUpdate = 0 ;
/** Whether to draw elements in the order they were added to canvas. Note: Enabling this will disable batching and will cause a greater number of drawcalls */
bool bDrawElementsInOrder = false ;
bool bShowAnyIndicators = false ;
mutable TOptional < FGeometry > OptionalPaintGeometry ;
TSharedPtr < FActiveTimerHandle > TickHandle ;
} ;