// 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 New(TArray InSchematicGraphNodes, const TArray& InElements); virtual ~FSchematicGraphNodeDragDropOp() override; virtual TSharedPtr 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& GetElements() const { return Elements; } /** @return The nodes being dragged */ const TArray GetNodes() const; FString GetJoinedDecoratorLabels() const; private: /** Nodes being dragged */ TArray SchematicGraphNodes; /** Data for the property paths this item represents */ TArray Elements; }; class ANIMATIONEDITORWIDGETS_API SSchematicGraphNode : public SNodePanel::SNode { public: typedef TAnimatedAttribute FVector2dAttribute; typedef TAnimatedAttribute FFloatAttribute; typedef TAnimatedAttribute FLinearColorAttribute; DECLARE_DELEGATE_TwoParams(FOnClicked, SSchematicGraphNode*, const FPointerEvent&); DECLARE_DELEGATE_TwoParams(FOnBeginDrag, SSchematicGraphNode*, const TSharedPtr&); DECLARE_DELEGATE_TwoParams(FOnEndDrag, SSchematicGraphNode*, const TSharedPtr&); DECLARE_DELEGATE_TwoParams(FOnDrop, SSchematicGraphNode*, const FDragDropEvent&); SLATE_BEGIN_ARGS(SSchematicGraphNode); SLATE_ARGUMENT(const FSchematicGraphNode*, NodeData) SLATE_ARGUMENT(TSharedPtr, Position) SLATE_ARGUMENT(TSharedPtr, Size) SLATE_ARGUMENT(TSharedPtr, Scale) SLATE_ATTRIBUTE(bool, EnableAutoScale) SLATE_ARGUMENT(TArray>, LayerColors) SLATE_ARGUMENT(TFunction, 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 NodeData; TSharedPtr Position; TOptional PositionDuringDrag; TOptional OffsetDuringDrag; TSharedPtr Size; TSharedPtr Scale; TAttribute EnableAutoScale; TOptional AutoScale; TArray> LayerColors; TFunction BrushGetter; FOnClicked OnClickedDelegate; FOnBeginDrag OnBeginDragDelegate; FOnEndDrag OnEndDragDelegate; FOnDrop OnDropDelegate; SSchematicGraphPanel* SchematicGraphPanel = nullptr; TSharedPtr 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&); DECLARE_DELEGATE_ThreeParams(FOnEndDrag, SSchematicGraphPanel*, SSchematicGraphNode*, const TSharedPtr&); DECLARE_DELEGATE_TwoParams(FOnEnterDrag, SSchematicGraphPanel*, const TSharedPtr&); DECLARE_DELEGATE_TwoParams(FOnLeaveDrag, SSchematicGraphPanel*, const TSharedPtr&); DECLARE_DELEGATE_ThreeParams(FOnCancelDrag, SSchematicGraphPanel*, SSchematicGraphNode*, const TSharedPtr&); 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, 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 Minimum; TSharedPtr Maximum; TSharedPtr Color; TSharedPtr 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 InGraphData); const TWeakPtr GetSchematicGraphModel() const { return GraphDataWeak; } TWeakPtr 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 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& InDragDropEvent); void OnEndDragEvent(SSchematicGraphNode* Node, const TSharedPtr& InDragDropEvent); void OnEnterDragEvent(const TSharedPtr& InDragDropEvent); void OnLeaveDragEvent(const TSharedPtr& InDragDropEvent); void OnCancelDragEvent(SSchematicGraphNode* Node, const TSharedPtr& 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 DragDropOpFromOutside; bool bIsOverlay = false; int32 PaddingLeft = 0; int32 PaddingRight = 0; int32 PaddingTop = 0; int32 PaddingBottom = 0; int32 PaddingInterNode = 0; TWeakPtr GraphDataWeak; FOnNodeClicked OnNodeClickedDelegate; FOnBeginDrag OnBeginDragDelegate; FOnEndDrag OnEndDragDelegate; FOnEnterDrag OnEnterDragDelegate; FOnLeaveDrag OnLeaveDragDelegate; FOnCancelDrag OnCancelDragDelegate; FOnDrop OnDropDelegate; TMap> 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 PerNodeCaches; TMap GuidToNodeCache; TMap GroupNodeGuidByHash; TMap> LinkByGuid; mutable TMap NodeCenterByGuid; mutable TArray NodeCenterByIndex; mutable TArray NodeVisibilityByIndex; mutable TMap NodeVisibilityByGuid; mutable TOptional DropTarget; mutable TOptional DPIScale; FVector2d NodeLabelOffset = FVector2d::ZeroVector; }; #endif