Files
UnrealEngine/Engine/Source/Editor/AnimationEditorWidgets/Public/SchematicGraphPanel/SSchematicGraphPanel.h
2025-05-18 13:04:45 +08:00

315 lines
13 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#if WITH_EDITOR
#include "SchematicGraphModel.h"
#include "SNodePanel.h"
#include "TickableEditorObject.h"
#include "Framework/Animation/AnimatedAttribute.h"
class SSchematicGraphPanel;
class SSchematicGraphNode;
class ANIMATIONEDITORWIDGETS_API FSchematicGraphNodeDragDropOp : public FDragDropOperation
{
public:
DRAG_DROP_OPERATOR_TYPE(FSchematicGraphNodeDragDropOp, FDragDropOperation)
static TSharedRef<FSchematicGraphNodeDragDropOp> New(TArray<SSchematicGraphNode*> InSchematicGraphNodes, const TArray<FGuid>& InElements);
virtual ~FSchematicGraphNodeDragDropOp() override;
virtual TSharedPtr<SWidget> GetDefaultDecorator() const override;
/** @return true if this drag operation contains property paths */
bool HasElements() const
{
return Elements.Num() > 0;
}
/** @return The property paths from this drag operation */
const TArray<FGuid>& GetElements() const
{
return Elements;
}
/** @return The nodes being dragged */
const TArray<const FSchematicGraphNode*> GetNodes() const;
FString GetJoinedDecoratorLabels() const;
private:
/** Nodes being dragged */
TArray<SSchematicGraphNode*> SchematicGraphNodes;
/** Data for the property paths this item represents */
TArray<FGuid> Elements;
};
class ANIMATIONEDITORWIDGETS_API SSchematicGraphNode : public SNodePanel::SNode
{
public:
typedef TAnimatedAttribute<FVector2d> FVector2dAttribute;
typedef TAnimatedAttribute<float> FFloatAttribute;
typedef TAnimatedAttribute<FLinearColor> FLinearColorAttribute;
DECLARE_DELEGATE_TwoParams(FOnClicked, SSchematicGraphNode*, const FPointerEvent&);
DECLARE_DELEGATE_TwoParams(FOnBeginDrag, SSchematicGraphNode*, const TSharedPtr<FDragDropOperation>&);
DECLARE_DELEGATE_TwoParams(FOnEndDrag, SSchematicGraphNode*, const TSharedPtr<FDragDropOperation>&);
DECLARE_DELEGATE_TwoParams(FOnDrop, SSchematicGraphNode*, const FDragDropEvent&);
SLATE_BEGIN_ARGS(SSchematicGraphNode);
SLATE_ARGUMENT(const FSchematicGraphNode*, NodeData)
SLATE_ARGUMENT(TSharedPtr<FVector2dAttribute>, Position)
SLATE_ARGUMENT(TSharedPtr<FVector2dAttribute>, Size)
SLATE_ARGUMENT(TSharedPtr<FFloatAttribute>, Scale)
SLATE_ATTRIBUTE(bool, EnableAutoScale)
SLATE_ARGUMENT(TArray<TSharedPtr<FLinearColorAttribute>>, LayerColors)
SLATE_ARGUMENT(TFunction<const FSlateBrush*(const FGuid&, int32)>, BrushGetter)
SLATE_EVENT(FOnClicked, OnClicked)
SLATE_EVENT(FOnBeginDrag, OnBeginDrag)
SLATE_EVENT(FOnEndDrag, OnEndDrag)
SLATE_EVENT(FOnDrop, OnDrop)
SLATE_ATTRIBUTE(FText, ToolTipText)
SLATE_END_ARGS()
void Construct(const FArguments& InArgs);
virtual FVector2D ComputeDesiredSize(float LayoutScaleMultiplier) 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 void OnMouseEnter(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override;
virtual void OnMouseLeave(const FPointerEvent& MouseEvent) override;
virtual FReply OnMouseButtonDown(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override;
virtual FReply OnDragOver(const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent) override;
virtual void OnDragLeave(const FDragDropEvent& DragDropEvent) override;
virtual FReply OnDrop(const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent) override;
virtual FReply OnDragDetected(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override;
virtual EVisibility GetNodeVisibility() const;
virtual FVector2f GetPosition2f() const override;
void EnablePositionAnimation(bool bEnabled = true);
const FVector2d& GetOriginalSize() const { return OriginalSize; }
const FSchematicGraphNode* GetNodeData() const { return NodeData.Get(); }
FSchematicGraphNode* GetNodeData() { return NodeData.Get(); }
const FGuid GetGuid() const;
bool IsInteractive() const;
const bool IsBeingDragged() const { return bIsBeingDragged; }
const bool IsFadedOut() const;
private:
bool bIsBeingDragged = false;
static inline const FVector2d DefaultNodeSize = FVector2d(32.0,32.0);
FVector2d OriginalSize = DefaultNodeSize;
TSharedPtr<FSchematicGraphNode> NodeData;
TSharedPtr<FVector2dAttribute> Position;
TOptional<FVector2d> PositionDuringDrag;
TOptional<FVector2d> OffsetDuringDrag;
TSharedPtr<FVector2dAttribute> Size;
TSharedPtr<FFloatAttribute> Scale;
TAttribute<bool> EnableAutoScale;
TOptional<float> AutoScale;
TArray<TSharedPtr<FLinearColorAttribute>> LayerColors;
TFunction<const FSlateBrush*(const FGuid&, int32)> BrushGetter;
FOnClicked OnClickedDelegate;
FOnBeginDrag OnBeginDragDelegate;
FOnEndDrag OnEndDragDelegate;
FOnDrop OnDropDelegate;
SSchematicGraphPanel* SchematicGraphPanel = nullptr;
TSharedPtr<FFloatAttribute> ExpansionCircleFactor;
friend class SSchematicGraphPanel;
friend class FSchematicGraphModel;
};
/** Widget allowing editing of a control rig's structure */
class ANIMATIONEDITORWIDGETS_API SSchematicGraphPanel : public SNodePanel, public FTickableEditorObject
{
public:
using FVector2dAttribute = SSchematicGraphNode::FVector2dAttribute;
using FFloatAttribute = SSchematicGraphNode::FFloatAttribute;
using FLinearColorAttribute = SSchematicGraphNode::FLinearColorAttribute;
DECLARE_DELEGATE_ThreeParams(FOnNodeClicked, SSchematicGraphPanel*, SSchematicGraphNode*, const FPointerEvent&);
DECLARE_DELEGATE_ThreeParams(FOnBeginDrag, SSchematicGraphPanel*, SSchematicGraphNode*, const TSharedPtr<FDragDropOperation>&);
DECLARE_DELEGATE_ThreeParams(FOnEndDrag, SSchematicGraphPanel*, SSchematicGraphNode*, const TSharedPtr<FDragDropOperation>&);
DECLARE_DELEGATE_TwoParams(FOnEnterDrag, SSchematicGraphPanel*, const TSharedPtr<FDragDropOperation>&);
DECLARE_DELEGATE_TwoParams(FOnLeaveDrag, SSchematicGraphPanel*, const TSharedPtr<FDragDropOperation>&);
DECLARE_DELEGATE_ThreeParams(FOnCancelDrag, SSchematicGraphPanel*, SSchematicGraphNode*, const TSharedPtr<FDragDropOperation>&);
DECLARE_DELEGATE_ThreeParams(FOnDrop, SSchematicGraphPanel*, SSchematicGraphNode*, const FDragDropEvent&);
SLATE_BEGIN_ARGS(SSchematicGraphPanel)
{}
SLATE_ARGUMENT(bool, IsOverlay)
SLATE_ARGUMENT_DEPRECATED(FSchematicGraphModel*, GraphData, 5.6, "Please, use GraphDataModel instead.")
SLATE_ARGUMENT(TWeakPtr<FSchematicGraphModel>, GraphDataModel)
SLATE_ARGUMENT(int32, PaddingLeft)
SLATE_ARGUMENT(int32, PaddingRight)
SLATE_ARGUMENT(int32, PaddingTop)
SLATE_ARGUMENT(int32, PaddingBottom)
SLATE_ARGUMENT(int32, PaddingInterNode)
SLATE_EVENT(FOnNodeClicked, OnNodeClicked)
SLATE_EVENT(FOnBeginDrag, OnBeginDrag)
SLATE_EVENT(FOnEndDrag, OnEndDrag)
SLATE_EVENT(FOnEnterDrag, OnEnterDrag)
SLATE_EVENT(FOnLeaveDrag, OnLeaveDrag)
SLATE_EVENT(FOnCancelDrag, OnCancelDrag)
SLATE_EVENT(FOnDrop, OnDrop)
SLATE_END_ARGS()
struct FSchematicLinkWidgetInfo
{
TSharedPtr<FFloatAttribute> Minimum;
TSharedPtr<FFloatAttribute> Maximum;
TSharedPtr<FLinearColorAttribute> Color;
TSharedPtr<FFloatAttribute> Thickness;
};
virtual ~SSchematicGraphPanel() override
{
OnNodeClickedDelegate.Unbind();
OnDropDelegate.Unbind();
}
UE_DEPRECATED(5.6, "SetSchematicGraph with raw pointer has been deprecated, please, use SetSchematicGraphModel with a weak pointer instead.")
void SetSchematicGraph(FSchematicGraphModel* InGraphData) {}
UE_DEPRECATED(5.6, "GetSchematicGraph with raw pointer has been deprecated, please, use GetSchematicGraphModel with a weak pointer instead.")
const FSchematicGraphModel* GetSchematicGraph() const { return nullptr; }
UE_DEPRECATED(5.6, "GetSchematicGraph with raw pointer has been deprecated, please, use GetSchematicGraphModel with a weak pointer instead.")
FSchematicGraphModel* GetSchematicGraph() { return nullptr; }
void SetSchematicGraphModel(TWeakPtr<FSchematicGraphModel> InGraphData);
const TWeakPtr<const FSchematicGraphModel> GetSchematicGraphModel() const { return GraphDataWeak; }
TWeakPtr<FSchematicGraphModel> GetSchematicGraphModel() { return GraphDataWeak; }
void Construct(const FArguments& InArgs);
void RebuildPanel();
void AddNode(const FSchematicGraphNode* InNodeToAdd);
void RemoveNode(const FSchematicGraphNode* InNodeToRemove);
const SSchematicGraphNode* FindNode(const FGuid& InGuid) const;
SSchematicGraphNode* FindNode(const FGuid& InGuid);
void AddLink(const FSchematicGraphLink* InLinkToAdd);
void RemoveLink(const FSchematicGraphLink* InLinkToRemove);
const FSchematicLinkWidgetInfo* FindLink(const FGuid& InGuid) const;
FSchematicLinkWidgetInfo* FindLink(const FGuid& InGuid);
// SNodePanel interface
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 void RemoveAllNodes() override;
virtual FReply OnMouseWheel(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override;
// End of SNodePanel interface
TSharedRef<SSchematicGraphNode> GetChild(int32 ChildIndex) const;
// FTickableEditorObject Interface
virtual TStatId GetStatId() const override;
virtual void Tick(float DeltaTime) override;
virtual void Tick( const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime ) override;
virtual bool IsTickable() const override { return true; }
// End of FTickableEditorObject interface
void ToggleVisibility();
void OnNodeClicked(SSchematicGraphNode* Node, const FPointerEvent& MouseEvent);
void OnBeginDragEvent(SSchematicGraphNode* Node, const TSharedPtr<FDragDropOperation>& InDragDropEvent);
void OnEndDragEvent(SSchematicGraphNode* Node, const TSharedPtr<FDragDropOperation>& InDragDropEvent);
void OnEnterDragEvent(const TSharedPtr<FDragDropOperation>& InDragDropEvent);
void OnLeaveDragEvent(const TSharedPtr<FDragDropOperation>& InDragDropEvent);
void OnCancelDragEvent(SSchematicGraphNode* Node, const TSharedPtr<FDragDropOperation>& InDragDropEvent);
void OnDropEvent(SSchematicGraphNode* Node, const FDragDropEvent& InDragDropEvent);
FReply HandleNodeDragDetected(FGuid Guid, const FGeometry& MyGeometry, const FPointerEvent& MouseEvent);
virtual FVector2d GetPositionForNode(FGuid InNodeGuid) const;
virtual FLinearColor GetColorForNode(FGuid InNodeGuid, int32 InLayerIndex) const;
virtual FText GetToolTipForNode(FGuid InNodeGuid) const;
virtual float GetScaleForNode(FGuid InNodeGuid) const;
void AdjustPositionWithDPIScale(FVector2d& InOutPosition, bool bInverse = false) const;
virtual bool IsAutoGroupingEnabled() const;
virtual float GetAutoGroupingDistance() const;
virtual bool IsAutoScaleEnabledForNode(FGuid InNodeGuid) const;
virtual float GetMinimumLinkDistanceForNode(FGuid InLinkGuid, bool bIncludeScale = true) const;
FOnNodeClicked& OnNodeClicked() { return OnNodeClickedDelegate; }
FOnBeginDrag& OnBeginDrag() { return OnBeginDragDelegate; }
FOnEndDrag& OnEndDrag() { return OnEndDragDelegate; }
FOnEnterDrag& OnEnterDrag() { return OnEnterDragDelegate; }
FOnLeaveDrag& OnLeaveDrag() { return OnLeaveDragDelegate; }
FOnCancelDrag& OnCancelDrag() { return OnCancelDragDelegate; }
FOnDrop& OnAcceptDrop() { return OnDropDelegate; }
const FVector2d& GetNodeLabelOffset() const { return NodeLabelOffset; }
void IncrementNodeLabelOffset(const FVector2d& InOffset);
private:
void UpdatePerNodeCaches(bool bRemoveNodesFromAutoGroups);
void UpdateAutoGroupingForNodes();
void UpdateAutoScalingForNodes();
bool bIsDragDropping = false;
TSharedPtr<FDragDropOperation> DragDropOpFromOutside;
bool bIsOverlay = false;
int32 PaddingLeft = 0;
int32 PaddingRight = 0;
int32 PaddingTop = 0;
int32 PaddingBottom = 0;
int32 PaddingInterNode = 0;
TWeakPtr<FSchematicGraphModel> GraphDataWeak;
FOnNodeClicked OnNodeClickedDelegate;
FOnBeginDrag OnBeginDragDelegate;
FOnEndDrag OnEndDragDelegate;
FOnEnterDrag OnEnterDragDelegate;
FOnLeaveDrag OnLeaveDragDelegate;
FOnCancelDrag OnCancelDragDelegate;
FOnDrop OnDropDelegate;
TMap<FGuid, TSharedPtr<SSchematicGraphNode>> NodeByGuid;
struct FPerNodeCache
{
FPerNodeCache()
: Guid()
, Label()
, bHasParent(false)
, Visibility(ESchematicGraphVisibility::Visible)
, bIsAutoScaling(false)
, Position(FVector2d::ZeroVector)
, Radius(0.0)
{}
FGuid Guid;
FText Label;
bool bHasParent;
ESchematicGraphVisibility::Type Visibility;
bool bIsAutoScaling;
FVector2d Position;
double Radius;
};
TArray<FPerNodeCache> PerNodeCaches;
TMap<FGuid, int32> GuidToNodeCache;
TMap<uint32, FGuid> GroupNodeGuidByHash;
TMap<FGuid, TSharedPtr<FSchematicLinkWidgetInfo>> LinkByGuid;
mutable TMap<FGuid, FVector2d> NodeCenterByGuid;
mutable TArray<FVector2d> NodeCenterByIndex;
mutable TArray<ESchematicGraphVisibility::Type> NodeVisibilityByIndex;
mutable TMap<FGuid, ESchematicGraphVisibility::Type> NodeVisibilityByGuid;
mutable TOptional<FGuid> DropTarget;
mutable TOptional<float> DPIScale;
FVector2d NodeLabelOffset = FVector2d::ZeroVector;
};
#endif