Files
UnrealEngine/Engine/Source/Editor/ComponentVisualizers/Public/SplineComponentVisualizer.h
Brandyn / Techy fcc1b09210 init
2026-04-04 15:40:51 -05:00

715 lines
25 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "ComponentVisualizer.h"
#include "Components/SplineComponent.h"
#include "Containers/Array.h"
#include "Containers/Set.h"
#include "Containers/UnrealString.h"
#include "CoreMinimal.h"
#include "Engine/EngineBaseTypes.h"
#include "GenericPlatform/ICursor.h"
#include "HitProxies.h"
#include "InputCoreTypes.h"
#include "Math/Axis.h"
#include "Math/Box.h"
#include "Math/InterpCurvePoint.h"
#include "Math/Matrix.h"
#include "Math/Quat.h"
#include "Math/Rotator.h"
#include "Math/UnrealMathSSE.h"
#include "Math/Vector.h"
#include "Misc/AssertionMacros.h"
#include "SplineDetailsProvider.h"
#include "Templates/SharedPointer.h"
#include "UObject/GCObject.h"
#include "UObject/Object.h"
#include "UObject/ObjectMacros.h"
#include "UObject/UObjectGlobals.h"
#include "Features/IModularFeature.h"
#include "PrimitiveDrawInterface.h"
#include "SplineComponentVisualizer.generated.h"
#define UE_API COMPONENTVISUALIZERS_API
class AActor;
class FCanvas;
class FEditorViewportClient;
class FMenuBuilder;
class FPrimitiveDrawInterface;
class FProperty;
class FSceneView;
class FUICommandList;
class FViewport;
class SSplineGeneratorPanel;
class SWidget;
class SWindow;
class UActorComponent;
class USplineComponent;
class USplineMetadata;
struct FConvexVolume;
struct FViewportClick;
namespace UE::SplineComponentVisualizer
{
struct FPDICache
{
struct FRenderableLine
{
FRenderableLine()
: Start(ForceInitToZero)
, End(ForceInitToZero)
, Color(ForceInitToZero)
, DepthPriority(SDPG_World)
, Thickness(0.0f)
, DepthBias(0.0f)
{}
FRenderableLine(const FVector& InStart, const FVector& InEnd, const FColor& InColor, const ESceneDepthPriorityGroup InDepthPriority = SDPG_World, const float InThickness = 0.0f, const float InDepthBias = 0.0f)
: Start(InStart)
, End(InEnd)
, Color(InColor)
, DepthPriority(InDepthPriority)
, Thickness(InThickness)
, DepthBias(InDepthBias)
{}
void Draw(FPrimitiveDrawInterface* PDI) const
{
PDI->DrawLine(Start, End, Color, static_cast<uint8>(DepthPriority), Thickness, DepthBias);
}
FVector Start;
FVector End;
FColor Color;
ESceneDepthPriorityGroup DepthPriority;
float Thickness;
float DepthBias;
};
struct FRenderablePoint
{
FRenderablePoint()
: Position(ForceInitToZero)
, Color(ForceInitToZero)
, Size(0.f)
, DepthPriority(SDPG_World)
{}
FRenderablePoint(const FVector& InPosition, const FColor& InColor, const float InSize, const ESceneDepthPriorityGroup InDepthPriority = SDPG_World)
: Position(InPosition)
, Color(InColor)
, Size(InSize)
, DepthPriority(InDepthPriority)
{}
void Draw(FPrimitiveDrawInterface* PDI) const
{
PDI->DrawPoint(Position, Color, Size, static_cast<uint8>(DepthPriority));
}
FVector Position;
FColor Color;
float Size;
ESceneDepthPriorityGroup DepthPriority;
};
template <typename ElementType>
struct TElementBatch
{
TArray<ElementType> Elements;
TFunction<HHitProxy*()> AllocHitProxyFunc = []() -> HHitProxy* { return nullptr; };
void Draw(FPrimitiveDrawInterface* PDI) const
{
PDI->SetHitProxy(AllocateHitProxy());
for (const ElementType& Element : Elements) { Element.Draw(PDI); }
PDI->SetHitProxy(nullptr);
}
private:
HHitProxy* AllocateHitProxy() const
{
return AllocHitProxyFunc
? AllocHitProxyFunc()
: nullptr;
}
};
using FLineBatch = TElementBatch<FRenderableLine>;
using FPointBatch = TElementBatch<FRenderablePoint>;
void Reset()
{
LineBatches.Reset();
PointBatches.Reset();
}
void Draw(FPrimitiveDrawInterface* PDI) const
{
for (const FLineBatch& Batch : LineBatches) { Batch.Draw(PDI); }
for (const FPointBatch& Batch : PointBatches) { Batch.Draw(PDI); }
}
void AddBatch(FLineBatch&& LineBatch)
{
LineBatches.Add(MoveTemp(LineBatch));
LineBatch.Elements.Reset();
}
void AddBatch(FPointBatch&& PointBatch)
{
PointBatches.Add(MoveTemp(PointBatch));
PointBatch.Elements.Reset();
}
TArray<FLineBatch> LineBatches;
TArray<FPointBatch> PointBatches;
bool bDirty = true;
};
}
/** Tangent handle selection modes. */
UENUM()
enum class ESelectedTangentHandle
{
None,
Leave,
Arrive
};
/** Selection state data that will be captured by scoped transactions.*/
UCLASS(MinimalAPI, Transient)
class USplineComponentVisualizerSelectionState : public UObject
{
GENERATED_BODY()
public:
/** Checks LastKeyIndexSelected is valid given the number of splint points and returns its value. */
UE_API int32 GetVerifiedLastKeyIndexSelected(const int32 InNumSplinePoints) const;
/** Checks TangentHandle and TangentHandleType are valid and sets relevant output parameters. */
UE_API void GetVerifiedSelectedTangentHandle(const int32 InNumSplinePoints, int32& OutSelectedTangentHandle, ESelectedTangentHandle& OutSelectedTangentHandleType) const;
const FComponentPropertyPath GetSplinePropertyPath() const { return SplinePropertyPath; }
void SetSplinePropertyPath(const FComponentPropertyPath& InSplinePropertyPath) { SplinePropertyPath = InSplinePropertyPath; }
const TSet<int32>& GetSelectedKeys() const { return SelectedKeys; }
TSet<int32>& ModifySelectedKeys() { return SelectedKeys; }
int32 GetLastKeyIndexSelected() const { return LastKeyIndexSelected; }
void SetLastKeyIndexSelected(const int32 InLastKeyIndexSelected) { LastKeyIndexSelected = InLastKeyIndexSelected; }
int32 GetSelectedSegmentIndex() const { return SelectedSegmentIndex; }
void SetSelectedSegmentIndex(const int32 InSelectedSegmentIndex) { SelectedSegmentIndex = InSelectedSegmentIndex; }
int32 GetSelectedTangentHandle() const { return SelectedTangentHandle; }
void SetSelectedTangentHandle(const int32 InSelectedTangentHandle) { SelectedTangentHandle = InSelectedTangentHandle; }
int32 GetSelectedAttributeIndex() const { return SelectedAttributeIndex; }
FName GetSelectedAttributeName() const { return SelectedAttributeName; }
void SetSelectedAttribute(const int32 InSelectedAttributeIndex = INDEX_NONE, const FName& InSelectedAttributeName = NAME_None)
{
if (InSelectedAttributeIndex != INDEX_NONE)
{
// if we actually select an attribute point, don't persist other selection.
ClearSelectedKeys(); // necessary? maybe...
}
SelectedAttributeIndex = InSelectedAttributeIndex;
SelectedAttributeName = InSelectedAttributeName;
}
ESelectedTangentHandle GetSelectedTangentHandleType() const { return SelectedTangentHandleType; }
void SetSelectedTangentHandleType(const ESelectedTangentHandle InSelectedTangentHandle) { SelectedTangentHandleType = InSelectedTangentHandle; }
FVector GetSelectedSplinePosition() const { return SelectedSplinePosition; }
void SetSelectedSplinePosition(const FVector& InSelectedSplinePosition) { SelectedSplinePosition = InSelectedSplinePosition; }
FQuat GetCachedRotation() const { return CachedRotation; }
void SetCachedRotation(const FQuat& InCachedRotation) { CachedRotation = InCachedRotation; }
UE_API void Reset();
UE_API void ClearSelectedKeys();
UE_API void ClearSelectedSegmentIndex();
UE_API void ClearSelectedTangentHandle();
void ClearSelectedAttribute() { SetSelectedAttribute(); }
UE_API bool IsSplinePointSelected(const int32 InIndex) const;
protected:
/** Property path from the parent actor to the component */
UPROPERTY()
FComponentPropertyPath SplinePropertyPath;
/** Indices of keys we have selected */
UPROPERTY()
TSet<int32> SelectedKeys;
/** Index of the last key we selected */
UPROPERTY()
int32 LastKeyIndexSelected = INDEX_NONE;
/** Index of segment we have selected */
UPROPERTY()
int32 SelectedSegmentIndex = INDEX_NONE;
/** Index of tangent handle we have selected */
UPROPERTY()
int32 SelectedTangentHandle = INDEX_NONE;
/** The type of the selected tangent handle */
UPROPERTY()
ESelectedTangentHandle SelectedTangentHandleType = ESelectedTangentHandle::None;
/** Index of attribute handle we have selected */
UPROPERTY()
int32 SelectedAttributeIndex = INDEX_NONE;
UPROPERTY()
FName SelectedAttributeName = NAME_None;
/** Position on spline we have selected */
UPROPERTY()
FVector SelectedSplinePosition;
/** Cached rotation for this point */
UPROPERTY()
FQuat CachedRotation;
};
/** Base class for clickable spline editing proxies */
struct HSplineVisProxy : public HComponentVisProxy
{
DECLARE_HIT_PROXY( UE_API );
HSplineVisProxy(const UActorComponent* InComponent)
: HComponentVisProxy(InComponent, HPP_Wireframe)
{}
virtual EMouseCursor::Type GetMouseCursor() override
{
return EMouseCursor::CardinalCross;
}
};
/** Proxy for a spline key */
struct HSplineKeyProxy : public HSplineVisProxy
{
DECLARE_HIT_PROXY( UE_API );
HSplineKeyProxy(const UActorComponent* InComponent, int32 InKeyIndex)
: HSplineVisProxy(InComponent)
, KeyIndex(InKeyIndex)
{}
int32 KeyIndex;
virtual EMouseCursor::Type GetMouseCursor() override
{
return EMouseCursor::CardinalCross;
}
};
/** Proxy for spline attribute key (as opposed to a positional control point) */
struct HSplineAttributeKeyProxy : public HSplineVisProxy
{
DECLARE_HIT_PROXY( UE_API );
HSplineAttributeKeyProxy(const UActorComponent* InComponent, int32 InKeyIndex)
: HSplineVisProxy(InComponent)
, KeyIndex(InKeyIndex)
{}
int32 KeyIndex;
virtual EMouseCursor::Type GetMouseCursor() override
{
return EMouseCursor::CardinalCross;
}
};
/** Proxy for a spline segment */
struct HSplineSegmentProxy : public HSplineVisProxy
{
DECLARE_HIT_PROXY( UE_API );
HSplineSegmentProxy(const UActorComponent* InComponent, int32 InSegmentIndex)
: HSplineVisProxy(InComponent)
, SegmentIndex(InSegmentIndex)
{}
int32 SegmentIndex;
virtual EMouseCursor::Type GetMouseCursor() override
{
return EMouseCursor::CardinalCross;
}
};
/** Proxy for a tangent handle */
struct HSplineTangentHandleProxy : public HSplineVisProxy
{
DECLARE_HIT_PROXY( UE_API );
HSplineTangentHandleProxy(const UActorComponent* InComponent, int32 InKeyIndex, bool bInArriveTangent)
: HSplineVisProxy(InComponent)
, KeyIndex(InKeyIndex)
, bArriveTangent(bInArriveTangent)
{}
int32 KeyIndex;
bool bArriveTangent;
virtual EMouseCursor::Type GetMouseCursor() override
{
return EMouseCursor::CardinalCross;
}
};
/** Accepted modes for snapping points. */
enum class ESplineComponentSnapMode
{
Snap,
AlignToTangent,
AlignPerpendicularToTangent
};
/** SplineComponent visualizer/edit functionality */
class FSplineComponentVisualizer : public FComponentVisualizer, public FGCObject
PRAGMA_DISABLE_INTERNAL_WARNINGS
, public ISplineDetailsProvider
PRAGMA_DISABLE_INTERNAL_WARNINGS
{
using FPDICache = UE::SplineComponentVisualizer::FPDICache;
public:
UE_API FSplineComponentVisualizer();
UE_API virtual ~FSplineComponentVisualizer();
//~ Begin FComponentVisualizer Interface
UE_API virtual void OnRegister() override;
UE_API virtual bool ShouldShowForSelectedSubcomponents(const UActorComponent* Component) override;
UE_API virtual void DrawVisualization(const UActorComponent* Component, const FSceneView* View, FPrimitiveDrawInterface* PDI) override;
UE_API virtual bool VisProxyHandleClick(FEditorViewportClient* InViewportClient, HComponentVisProxy* VisProxy, const FViewportClick& Click) override;
/** Draw HUD on viewport for the supplied component */
UE_API virtual void DrawVisualizationHUD(const UActorComponent* Component, const FViewport* Viewport, const FSceneView* View, FCanvas* Canvas) override;
UE_API virtual void EndEditing() override;
UE_API virtual bool GetWidgetLocation(const FEditorViewportClient* ViewportClient, FVector& OutLocation) const override;
UE_API virtual bool GetCustomInputCoordinateSystem(const FEditorViewportClient* ViewportClient, FMatrix& OutMatrix) const override;
UE_API virtual bool HandleInputDelta(FEditorViewportClient* ViewportClient, FViewport* Viewport, FVector& DeltaTranslate, FRotator& DeltaRotate, FVector& DeltaScale) override;
UE_API virtual bool HandleInputKey(FEditorViewportClient* ViewportClient, FViewport* Viewport, FKey Key, EInputEvent Event) override;
/** Handle click modified by Alt, Ctrl and/or Shift. The input HitProxy may not be on this component. */
UE_API virtual bool HandleModifiedClick(FEditorViewportClient* InViewportClient, HHitProxy* HitProxy, const FViewportClick& Click) override;
/** Handle box select input */
UE_API virtual bool HandleBoxSelect(const FBox& InBox, FEditorViewportClient* InViewportClient, FViewport* InViewport) override;
/** Handle frustum select input */
UE_API virtual bool HandleFrustumSelect(const FConvexVolume& InFrustum, FEditorViewportClient* InViewportClient, FViewport* InViewport) override;
/** Return whether focus on selection should focus on bounding box defined by active visualizer */
UE_API virtual bool HasFocusOnSelectionBoundingBox(FBox& OutBoundingBox) override;
/** Pass snap input to active visualizer */
UE_API virtual bool HandleSnapTo(const bool bInAlign, const bool bInUseLineTrace, const bool bInUseBounds, const bool bInUsePivot, AActor* InDestination) override;
/** Gets called when the mouse tracking has stopped (dragging behavior) */
UE_API virtual void TrackingStopped(FEditorViewportClient* InViewportClient, bool bInDidMove) override;
/** Get currently edited component, this is needed to reset the active visualizer after undo/redo */
UE_API virtual UActorComponent* GetEditedComponent() const override;
UE_API virtual TSharedPtr<SWidget> GenerateContextMenu() const override;
UE_API virtual bool IsVisualizingArchetype() const override;
//~ End FComponentVisualizer Interface
/** Add menu sections to the context menu */
UE_API virtual void GenerateContextMenuSections(FMenuBuilder& InMenuBuilder) const;
/** Get the spline component we are currently editing */
UE_API virtual USplineComponent* GetEditedSplineComponent() const override;
const virtual TSet<int32>& GetSelectedKeys() const override { check(SelectionState); return SelectionState->GetSelectedKeys(); }
/** Select first or last spline point, returns true if the spline component being edited has changed */
UE_API virtual bool HandleSelectFirstLastSplinePoint(USplineComponent* InSplineComponent, bool bFirstPoint) override;
UE_API virtual void HandleSelectPrevNextSplinePoint(bool bNext, bool bAddToSelection) override;
/** Select all spline points, , returns true if the spline component being edited has changed */
UE_API virtual bool HandleSelectAllSplinePoints(USplineComponent* InSplineComponent) override;
/** Select next or prev spline point, loops when last point is currently selected */
UE_API void OnSelectPrevNextSplinePoint(bool bNextPoint, bool bAddToSelection);
/** Sets the new cached rotation on the visualizer */
UE_API virtual void SetCachedRotation(const FQuat& NewRotation) override;
protected:
/** Determine if any selected key index is out of range (perhaps because something external has modified the spline) */
UE_API bool IsAnySelectedKeyIndexOutOfRange(const USplineComponent* Comp) const;
/** Whether a single spline key is currently selected */
UE_API bool IsSingleKeySelected() const;
/** Whether a multiple spline keys are currently selected */
UE_API bool AreMultipleKeysSelected() const;
/** Whether any keys are currently selected */
UE_API bool AreKeysSelected() const;
/** Select spline point at specified index */
UE_API void SelectSplinePoint(int32 SelectIndex, bool bAddToSelection);
/** Transforms selected tangent by given translation */
UE_API bool TransformSelectedTangent(EPropertyChangeType::Type InPropertyChangeType, const FVector& InDeltaTranslate);
/** Transforms selected tangent by given translate, rotate and scale */
UE_API bool TransformSelectedKeys(EPropertyChangeType::Type InPropertyChangeType, const FVector& InDeltaTranslate, const FRotator& InDeltaRotate = FRotator::ZeroRotator, const FVector& InDeltaScale = FVector::ZeroVector);
/** Transforms selected attribute by given translation */
UE_API bool TransformSelectedAttribute(EPropertyChangeType::Type InPropertyChangeType, const FVector& InDeltaTranslate);
/** Update the key selection state of the visualizer */
UE_API virtual void ChangeSelectionState(int32 Index, bool bIsCtrlHeld);
/** Alt-drag: duplicates the selected spline key */
UE_API virtual bool DuplicateKeyForAltDrag(const FVector& InDrag);
/** Alt-drag: updates duplicated selected spline key */
UE_API virtual bool UpdateDuplicateKeyForAltDrag(const FVector& InDrag);
/** Return spline data for point on spline closest to input point */
UE_API virtual float FindNearest(const FVector& InLocalPos, int32 InSegmentStartIndex, FVector& OutSplinePos, FVector& OutSplineTangent) const;
/** Split segment using given world position */
UE_API virtual void SplitSegment(const FVector& InWorldPos, int32 InSegmentIndex, bool bCopyFromSegmentBeginIndex = true);
/** Update split segment based on drag offset */
UE_API virtual void UpdateSplitSegment(const FVector& InDrag);
/** Add segment to beginning or end of spline */
UE_API virtual void AddSegment(const FVector& InWorldPos, bool bAppend);
/** Add segment to beginning or end of spline */
UE_API virtual void UpdateAddSegment(const FVector& InWorldPos);
/** Alt-drag: duplicates the selected spline key */
UE_API virtual void ResetAllowDuplication();
/** Snapping: snap keys to axis position of last selected key */
UE_API virtual void SnapKeysToLastSelectedAxisPosition(const EAxis::Type InAxis, TArray<int32> InSnapKeys);
/** Snapping: snap key to selected actor */
UE_API virtual void SnapKeyToActor(const AActor* InActor, const ESplineComponentSnapMode SnapMode);
/** Snapping: generic method for snapping selected keys to given transform */
UE_API virtual void SnapKeyToTransform(const ESplineComponentSnapMode InSnapMode,
const FVector& InWorldPos,
const FVector& InWorldUpVector,
const FVector& InWorldForwardVector,
const FVector& InScale,
const USplineMetadata* InCopySplineMetadata = nullptr,
const int32 InCopySplineMetadataKey = 0);
/** Snapping: set snap to actor temporary mode */
UE_API virtual void SetSnapToActorMode(const bool bInIsSnappingToActor, const ESplineComponentSnapMode InSnapMode = ESplineComponentSnapMode::Snap);
/** Snapping: get snap to actor temporary mode */
UE_API virtual bool GetSnapToActorMode(ESplineComponentSnapMode& OutSnapMode) const;
/** Reset temporary modes after inputs are handled. */
UE_API virtual void ResetTempModes();
/** Updates the component and selected properties if the component has changed */
UE_API const USplineComponent* UpdateSelectedSplineComponent(HComponentVisProxy* VisProxy);
UE_API void OnDeleteKey();
UE_API bool CanDeleteKey() const;
/** Duplicates selected spline keys in place */
UE_API void OnDuplicateKey();
UE_API bool IsKeySelectionValid() const;
UE_API void OnAddKeyToSegment();
UE_API bool CanAddKeyToSegment() const;
UE_API void OnSnapKeyToNearestSplinePoint(ESplineComponentSnapMode InSnapMode);
UE_API void OnSnapKeyToActor(const ESplineComponentSnapMode InSnapMode);
UE_API void OnSnapAllToAxis(EAxis::Type InAxis);
UE_API void OnSnapSelectedToAxis(EAxis::Type InAxis);
UE_API void OnStraightenKey(int32 Direction);
UE_API void StraightenKey(int32 KeyToStraighten, int32 KeyToStraightenToward);
UE_API void OnToggleSnapTangentAdjustment();
UE_API bool IsSnapTangentAdjustment() const;
UE_API void OnLockAxis(EAxis::Type InAxis);
UE_API bool IsLockAxisSet(EAxis::Type InAxis) const;
UE_API void OnResetToAutomaticTangent(EInterpCurveMode Mode);
UE_API bool CanResetToAutomaticTangent(EInterpCurveMode Mode) const;
UE_API void OnSetKeyType(EInterpCurveMode Mode);
UE_API bool IsKeyTypeSet(EInterpCurveMode Mode) const;
UE_API void OnSetVisualizeRollAndScale();
UE_API bool IsVisualizingRollAndScale() const;
UE_API void OnSetDiscontinuousSpline();
UE_API bool IsDiscontinuousSpline() const;
UE_API void OnToggleClosedLoop();
UE_API bool IsClosedLoop() const;
UE_API void OnResetToDefault();
UE_API bool CanResetToDefault() const;
UE_API void OnAddAttributeKey();
UE_API bool CanAddAttributeKey() const;
UE_API void OnDeleteAttributeKey();
UE_API bool CanDeleteAttributeKey() const;
/** Select first or last spline point */
UE_API void OnSelectFirstLastSplinePoint(bool bFirstPoint);
/** Select all spline points, if no spline points selected yet the currently edited spline component will be set as well */
UE_API void OnSelectAllSplinePoints();
UE_API bool CanSelectSplinePoints() const;
/** Generate the submenu containing available selection actions */
UE_API void GenerateSelectSplinePointsSubMenu(FMenuBuilder& MenuBuilder) const;
/** Generate the submenu containing the available point types */
UE_API void GenerateSplinePointTypeSubMenu(FMenuBuilder& MenuBuilder) const;
/** Generate the submenu containing the available auto tangent types */
UE_API void GenerateTangentTypeSubMenu(FMenuBuilder& MenuBuilder) const;
/** Generate the submenu containing the available snap/align actions */
UE_API void GenerateSnapAlignSubMenu(FMenuBuilder& MenuBuilder) const;
/** Generate the submenu containing the lock axis types */
UE_API void GenerateLockAxisSubMenu(FMenuBuilder& MenuBuilder) const;
/** Extends the provided MenuBuilder with an Attribute section */
UE_API void GenerateAttributeMenuSection(FMenuBuilder& InMenuBuilder) const;
/** Generate the channel creator/selector widget. */
UE_API TSharedPtr<SWidget> GenerateChannelWidget() const;
UE_API TSharedPtr<SWidget> GenerateChannelCreatorWidget() const;
UE_API TSharedPtr<SWidget> GenerateChannelSelectorWidget() const;
/** Generate the attribute editor widget. */
UE_API TSharedPtr<SWidget> GenerateAttributeEditorWidget() const;
/** Helper function to set edited component we are currently editing */
UE_API void SetEditedSplineComponent(const USplineComponent* InSplineComponent);
UE_API void CreateSplineGeneratorPanel();
UE_API void OnDeselectedInEditor(TObjectPtr<USplineComponent> SplineComponent);
UE_API bool ShouldUseForSpline(const USplineComponent* SplineComponent) const override;
UE_API void ActivateVisualization() override;
UE_API bool IsEnabledForSpline(const USplineComponent* InSplineComponent) const;
// FGCObject interface
UE_API virtual void AddReferencedObjects(FReferenceCollector& Collector);
virtual FString GetReferencerName() const override
{
return TEXT("FSplineComponentVisualizer");
}
// End of FGCObject interface
/** Output log commands */
TSharedPtr<FUICommandList> SplineComponentVisualizerActions;
/** Current selection state */
TObjectPtr<USplineComponentVisualizerSelectionState> SelectionState;
/** Whether we currently allow duplication when dragging */
bool bAllowDuplication;
/** Alt-drag: True when in process of duplicating a spline key. */
bool bDuplicatingSplineKey;
/** Alt-drag: True when in process of adding end segment. */
bool bUpdatingAddSegment;
/** Alt-drag: Delays duplicating control point to accumulate sufficient drag input offset. */
uint32 DuplicateDelay;
/** Alt-drag: Accumulates delayed drag offset. */
FVector DuplicateDelayAccumulatedDrag;
/** Alt-drag: Cached segment parameter for split segment at new control point */
float DuplicateCacheSplitSegmentParam;
/** Axis to fix when adding new spline points. Uses the value of the currently
selected spline point's X, Y, or Z value when fix is not equal to none. */
EAxis::Type AddKeyLockedAxis;
/** Snap: True when in process of snapping to actor which needs to be Ctrl-Selected. */
bool bIsSnappingToActor;
/** Snap: Snap to actor mode. */
ESplineComponentSnapMode SnapToActorMode;
UE_DEPRECATED(5.7, "SplineCurvesProperty is deprecated, please use SplineProperties.")
FProperty* SplineCurvesProperty;
/** The set of properties to mark as dirty when manipulating the target spline component. */
TArray<FProperty*> SplineProperties;
FDelegateHandle DeselectedInEditorDelegateHandle;
void UpdateSharedAttributeNames() const
{
if (const USplineComponent* SplineComp = GetEditedSplineComponent())
{
SharedAttributeNames.Empty();
SharedAttributeNames.Add(MakeShared<FName>(NAME_None));
Algo::Transform(SplineComp->GetFloatPropertyChannels(), SharedAttributeNames, [](const FName& Name)
{
return MakeShared<FName>(Name);
});
}
}
mutable TArray<TSharedPtr<FName>> SharedAttributeNames;
private:
mutable TMap<TWeakObjectPtr<const USplineComponent>, FPDICache> PDICache;
void DirtyPDICache(const USplineComponent* SplineComp);
void UpdatePDICache(const USplineComponent* SplineComp);
TSharedPtr<SSplineGeneratorPanel> SplineGeneratorPanel;
static UE_API TWeakPtr<SWindow> WeakExistingWindow;
};
/** This class could be changed or removed without deprecation, use at your own risk. */
class UE_INTERNAL ISplineComponentVisualizerSuppressor;
PRAGMA_DISABLE_INTERNAL_WARNINGS
/** Allows implements to suppress the visualizer (disabling rendering, input capture, etc.) for a particular spline component. */
class ISplineComponentVisualizerSuppressor : public IModularFeature
{
public:
virtual ~ISplineComponentVisualizerSuppressor() = default;
static FName GetModularFeatureName() { return FName(TEXT("SplineComponentVisualizerSuppressor")); }
virtual bool ShouldSuppress(const USplineComponent* SplineComponent) const = 0;
};
PRAGMA_ENABLE_INTERNAL_WARNINGS
#undef UE_API