Files
zahra nikbakht 114a0d681f GraphEditor: ensure the correct LOD is applied to graph node and pins before the first tick.
We rely on the LOD setting of the graph panel to determine the LOD of nodes and pins, but they only get a reference to the panel after their construction, so we need to refresh the LOD once we get a reference to the owning panel from the node. This is only needed before the first tick.
This is a prerequisite to fix the issue of graph nodes disappearing for a frame on undo/redo
#jira UE-187947
#rb Patrick.Boutot

[CL 30514055 by zahra nikbakht in ue5-main branch]
2024-01-09 15:02:34 -05:00

489 lines
18 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "Animation/CurveHandle.h"
#include "Animation/CurveSequence.h"
#include "BlueprintUtilities.h"
#include "Containers/Array.h"
#include "Containers/Map.h"
#include "Containers/Set.h"
#include "Containers/UnrealString.h"
#include "CoreMinimal.h"
#include "EdGraph/EdGraphNodeUtils.h"
#include "GraphEditor.h"
#include "HAL/PlatformMath.h"
#include "Input/Reply.h"
#include "Internationalization/Text.h"
#include "Layout/SlateRect.h"
#include "Layout/Visibility.h"
#include "Math/Color.h"
#include "Math/Vector2D.h"
#include "Misc/Attribute.h"
#include "SNodePanel.h"
#include "SlateFwd.h"
#include "Styling/AppStyle.h"
#include "Styling/ISlateStyle.h"
#include "Styling/SlateColor.h"
#include "Styling/SlateTypes.h"
#include "Templates/SharedPointer.h"
#include "Types/SlateEnums.h"
#include "UObject/NameTypes.h"
#include "UObject/WeakObjectPtr.h"
#include "UObject/WeakObjectPtrTemplates.h"
#include "Widgets/DeclarativeSyntaxSupport.h"
#include "Widgets/Notifications/SErrorText.h"
#include "Widgets/SCompoundWidget.h"
#include "Widgets/SOverlay.h"
#include "Widgets/SWidget.h"
class FActorDragDropOp;
class FDragDropEvent;
class ISlateStyle;
class IToolTip;
class SGraphPanel;
class SGraphPin;
class SInlineEditableTextBlock;
class SLevelOfDetailBranchNode;
class SToolTip;
class SVerticalBox;
class SWidget;
class UEdGraphNode;
class UEdGraphPin;
class UObject;
struct FGeometry;
struct FPointerEvent;
struct FSlateBrush;
/////////////////////////////////////////////////////
// SNodeTitle
class GRAPHEDITOR_API SNodeTitle : public SCompoundWidget
{
public:
SLATE_BEGIN_ARGS(SNodeTitle)
: _StyleSet(&FAppStyle::Get())
, _Style(TEXT("Graph.Node.NodeTitle"))
, _ExtraLineStyle(TEXT("Graph.Node.NodeTitleExtraLines"))
{}
SLATE_ARGUMENT(const ISlateStyle*, StyleSet)
// The style of the text block, which dictates the font, color, and shadow options. Style overrides all other properties!
SLATE_ARGUMENT(FName, Style)
// The style of any additional lines in the the text block
SLATE_ARGUMENT(FName, ExtraLineStyle)
// Title text to display, auto-binds to get the title if not set externally
SLATE_ATTRIBUTE(FText, Text)
SLATE_END_ARGS()
void Construct(const FArguments& InArgs, UEdGraphNode* InNode);
// SWidget interface
virtual void Tick( const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime ) override;
// End of SWidget interface
/** Returns the main title for the node */
FText GetHeadTitle() const;
/** Get the size of this title the last time it was drawn */
FVector2D GetTitleSize() const;
/** Mark the cached title dirty */
void MarkDirty();
protected:
TWeakObjectPtr<UEdGraphNode> GraphNode;
FNodeTextCache NodeTitleCache;
FName ExtraLineStyle;
const ISlateStyle* StyleSet;
/** The cached head title to return */
FText CachedHeadTitle;
/** The title text to use, auto-binds to get the title if not set externally */
TAttribute< FText > TitleText;
/** The cached size of the title */
FVector2D CachedSize;
protected:
// Gets the expected node title
FText GetNodeTitle() const;
// Rebuilds the widget if needed
void RebuildWidget();
};
/////////////////////////////////////////////////////
// SGraphNode
class GRAPHEDITOR_API SGraphNode : public SNodePanel::SNode
{
public:
// SWidget interface
virtual void OnDragEnter( const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent ) override;
virtual void OnDragLeave( const FDragDropEvent& DragDropEvent ) override;
virtual FReply OnDragOver( const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent ) override;
virtual FReply OnDrop( const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent ) override;
virtual FReply OnMouseButtonDown( const FGeometry& MyGeometry, const FPointerEvent& MouseEvent ) override;
virtual FReply OnMouseButtonUp( const FGeometry& MyGeometry, const FPointerEvent& MouseEvent ) override;
virtual FReply OnMouseButtonDoubleClick( const FGeometry& InMyGeometry, const FPointerEvent& InMouseEvent ) override;
virtual TSharedPtr<IToolTip> GetToolTip() override;
virtual void OnToolTipClosing() override;
virtual void Tick( const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime ) override;
// End of SWidget interface
// SNodePanel::SNode interface
virtual void MoveTo( const FVector2D& NewPosition, FNodeSet& NodeFilter, bool bMarkDirty = true ) override;
virtual FVector2D GetPosition() const override;
virtual FString GetNodeComment() const override;
virtual UObject* GetObjectBeingDisplayed() const override;
// End of SNodePanel::SNode interface
/** Set attribute for determining if widget is editable */
void SetIsEditable(TAttribute<bool> InIsEditable);
/** Returns if widget is editable, additionally considers if the owning graph is read only */
virtual bool IsNodeEditable() const;
/** Set event when node is double clicked */
void SetDoubleClickEvent(FSingleNodeEvent InDoubleClickEvent);
/** @param OwnerPanel The GraphPanel that this node belongs to */
virtual void SetOwner( const TSharedRef<SGraphPanel>& OwnerPanel );
/** @return the editable title for a node */
FString GetEditableNodeTitle() const;
/** @return the editable title for a node */
FText GetEditableNodeTitleAsText() const;
/** @return the tint for the node's title image */
FSlateColor GetNodeTitleColor() const;
/** @return the tint for the node's comment */
FSlateColor GetNodeCommentColor() const;
/** @return the tint for the node's main body */
FSlateColor GetNodeBodyColor() const;
/** @return the image brush to use for the node */
virtual const FSlateBrush * GetNodeBodyBrush() const;
/** @return the tint for the node's title icon */
FSlateColor GetNodeTitleIconColor() const;
/** @return the tint for the node's title text */
FLinearColor GetNodeTitleTextColor() const;
/** @return the tooltip to display when over the node */
FText GetNodeTooltip() const;
/** @return the node being observed by this widget*/
UEdGraphNode* GetNodeObj() const;
/** @return the node under the mouse (either this node or one of its children) */
virtual TSharedRef<SGraphNode> GetNodeUnderMouse(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent);
TSharedPtr<SGraphPanel> GetOwnerPanel() const;
/**
* Update this GraphNode to match the data that it is observing
*/
virtual void UpdateGraphNode();
/** Create the widgets for pins on the node */
virtual void CreatePinWidgets();
/** Create a single pin widget */
virtual void CreateStandardPinWidget(UEdGraphPin* Pin);
/**
* Get all the pins found on this node.
*
* @param AllPins The set of pins found on this node.
*/
void GetPins( TSet< TSharedRef<SWidget> >& AllPins ) const;
void GetPins( TArray< TSharedRef<SWidget> >& AllPins ) const;
/**
* Find the pin that is hovered.
*
* @param MyGeometry The geometry of the node
* @param MouseEvent Information about the mouse
*
* @return A pointer to the pin widget hovered in this node, or invalid pointer if none.
*/
virtual TSharedPtr<SGraphPin> GetHoveredPin( const FGeometry& MyGeometry, const FPointerEvent& MouseEvent ) const;
TSharedPtr<SGraphPin> FindWidgetForPin( UEdGraphPin* ThePin ) const;
void PlaySpawnEffect();
/** Given a coordinate in SGraphNode space, return the same coordinate in graph space while taking zoom and panning of the parent graph into account */
FVector2D NodeCoordToGraphCoord( const FVector2D& PanelSpaceCoordinate ) const;
FVector2D GetContentScale() const;
FLinearColor GetColorAndOpacity() const;
FLinearColor GetPinLabelColorAndOpacity() const;
/** Set event when text is committed on the node */
void SetVerifyTextCommitEvent(FOnNodeVerifyTextCommit InOnVerifyTextCommit);
/** Set event when text is committed on the node */
void SetTextCommittedEvent(FOnNodeTextCommitted InDelegate);
/** Set event when the user generates a warning tooltip because a connection was invalid */
void SetDisallowedPinConnectionEvent(SGraphEditor::FOnDisallowedPinConnection InOnDisallowedPinConnection);
/** called to replace this nodes comment text */
virtual void OnCommentTextCommitted(const FText& NewComment, ETextCommit::Type CommitInfo);
/** called when the node's comment bubble is toggled */
virtual void OnCommentBubbleToggled(bool bInCommentBubbleVisible);
/** returns true if a rename is pending on this node */
bool IsRenamePending() const { return bRenameIsPending; }
/** Requests a rename when the node was initially spawned */
virtual void RequestRenameOnSpawn()
{
RequestRename();
}
/** flags node as rename pending if supported */
void RequestRename();
/** Sets node into rename state if supported */
void ApplyRename();
/** return rect of the title area */
virtual FSlateRect GetTitleRect() const;
/** Called from drag drop code when a disallowed connection is hovered */
void NotifyDisallowedPinConnection(const class UEdGraphPin* PinA, const class UEdGraphPin* PinB) const;
/** Gets the unscaled position of the node from the last tick */
FVector2D GetUnscaledPosition() const {return CachedUnscaledPosition;}
/** Returns the current Node LOD or Highest LOD if unable to query */
EGraphRenderingLOD::Type GetCurrentLOD() const;
/** Called when GraphNode changes its error information, may be called when no change has actually occurred: */
virtual void RefreshErrorInfo();
/** Called when ed graph data is cleared, indicating this widget can no longer safely access GraphNode - forwards call to owned pins: */
void InvalidateGraphData();
/** Returns true if the node is hiding its pins */
virtual bool IsHidingPinWidgets() const { return false; }
protected:
SGraphNode();
void PositionThisNodeBetweenOtherNodes(const TMap< UObject*, TSharedRef<SNode> >& NodeToWidgetLookup, UEdGraphNode* PreviousNode, UEdGraphNode* NextNode, float HeightAboveWire) const;
void PositionThisNodeBetweenOtherNodes(const TMap< UObject*, TSharedRef<SNode> >& NodeToWidgetLookup, TSet<UEdGraphNode*>& PreviousNodes, TSet<UEdGraphNode*>& NextNodes, float HeightAboveWire) const;
void PositionThisNodeBetweenOtherNodes(const FVector2D& PrevPos, const FVector2D& NextPos, float HeightAboveWire) const;
/**
* Check whether drag and drop functionality is permitted on the given node
*/
static bool CanAllowInteractionUsingDragDropOp( const UEdGraphNode* GraphNodePtr, const TSharedPtr<FActorDragDropOp>& DragDropOp );
/**
* Function to get error description string
*
* @return string to be displayed as tooltip.
*/
FText GetErrorMsgToolTip() const;
/**
* Add a new pin to this graph node. The pin must be newly created.
*
* @param PinToAdd A new pin to add to this GraphNode.
*/
virtual void AddPin( const TSharedRef<SGraphPin>& PinToAdd );
/** Hook that allows derived classes to supply their own SGraphPin derivatives for any pin. */
virtual TSharedPtr<SGraphPin> CreatePinWidget(UEdGraphPin* Pin) const;
/**
* Override this to provide support for an 'expensive' tooltip widget that is only built on demand
*/
virtual TSharedPtr<SToolTip> GetComplexTooltip() { return NULL; }
// Override this to add widgets below the node and pins
virtual void CreateBelowWidgetControls(TSharedPtr<SVerticalBox> MainBox) {}
// Override this to add widgets below the pins but above advanced view arrow
virtual void CreateBelowPinControls(TSharedPtr<SVerticalBox> MainBox) {}
/** Determines how the node title overflow is handled */
virtual TOptional<ETextOverflowPolicy> GetNameOverflowPolicy() const { return {}; }
/* Helper function to check if node can be renamed */
virtual bool IsNameReadOnly () const;
/** Called when text is being committed to check for validity */
bool OnVerifyNameTextChanged ( const FText& InText, FText& OutErrorMessage );
/* Called when text is committed on the node */
void OnNameTextCommited ( const FText& InText, ETextCommit::Type CommitInfo ) ;
/* Helper function to set the error color for the node */
FSlateColor GetErrorColor() const {return ErrorColor;}
/** Controls wether to show or not the visual warning message */
EVisibility VisualWarningVisibility() const;
/** Function to get a visual warning description string(visual warnings does not break the build) */
FText GetVisualWarningMsgToolTip() const;
/* Helper function to set the error color for the node */
FSlateColor GetVisualWarningColor() const;
/** Helper function to get any error text for the node */
FString GetErrorMessage() const {return ErrorMsg;}
/** Called to set error text on the node */
virtual void UpdateErrorInfo();
/** Set-up the error reporting widget for the node */
void SetupErrorReporting();
// Should we use low-detail node titles?
virtual bool UseLowDetailNodeTitles() const;
public:
// Should we use low-detail pin names?
virtual bool UseLowDetailPinNames() const { return false; }
protected:
/** Return the desired comment bubble color */
virtual FSlateColor GetCommentColor() const { return FLinearColor::White; }
///// ADVANCED VIEW FUNCTIONS /////
/** Create button to show/hide advanced pins */
virtual void CreateAdvancedViewArrow(TSharedPtr<SVerticalBox> MainBox);
/** Returns visibility of AdvancedViewButton */
virtual EVisibility AdvancedViewArrowVisibility() const;
/** Show/hide advanced view */
virtual void OnAdvancedViewChanged( const ECheckBoxState NewCheckedState );
/** hidden == unchecked, shown == checked */
virtual ECheckBoxState IsAdvancedViewChecked() const;
/** Up when shown, down when hidden */
virtual const FSlateBrush* GetAdvancedViewArrow() const;
/** Checks if the node is the only node selected */
bool IsSelectedExclusively() const;
virtual void SetDefaultTitleAreaWidget(TSharedRef<SOverlay> DefaultTitleAreaWidget) {}
virtual TSharedRef<SWidget> CreateTitleWidget(TSharedPtr<SNodeTitle> NodeTitle);
/** Optionally create a widget to dock to the right in the title bar of the node. */
virtual TSharedRef<SWidget> CreateTitleRightWidget();
/** Create the inner node content area, including the left/right pin boxes */
virtual TSharedRef<SWidget> CreateNodeContentArea();
///// ADD PIN BUTTON FUNCTIONS /////
/** Override this to create a button to add pins on the input side of the node */
virtual void CreateInputSideAddButton(TSharedPtr<SVerticalBox> InputBox) {};
/** Override this to create a button to add pins on the output side of the node */
virtual void CreateOutputSideAddButton(TSharedPtr<SVerticalBox> OutputBox) {};
/** Creates widget for an Add pin button, which can then be added to the node */
TSharedRef<SWidget> AddPinButtonContent(FText PinText, FText PinTooltipText, bool bRightSide = true, FString DocumentationExcerpt = FString(), TSharedPtr<SToolTip> CustomTooltip = NULL);
/** Checks whether Add pin button should currently be visible */
virtual EVisibility IsAddPinButtonVisible() const;
/** Callback function executed when Add pin button is clicked */
virtual FReply OnAddPin() {return FReply::Handled();}
/* Populate a meta data tag with information about this graph node */
virtual void PopulateMetaTag(class FGraphNodeMetaData* TagMeta) const;
/** Returns TRUE if the input pin should be hidden from view */
bool ShouldPinBeHidden(const UEdGraphPin* InPin) const;
/** Returns the widget to use for the enabled state of the node */
TSharedPtr<SWidget> GetEnabledStateWidget();
protected:
/** Input pin widgets on this node */
TArray< TSharedRef<SGraphPin> > InputPins;
/** Output pin widgets on this node */
TArray< TSharedRef<SGraphPin> > OutputPins;
/** The GraphPanel within in which this node resides.*/
TWeakPtr<SGraphPanel> OwnerGraphPanelPtr;
/** The GraphNode being observed by this widget */
UEdGraphNode* GraphNode;
/** The area where input pins reside */
TSharedPtr<SVerticalBox> LeftNodeBox;
/** The area where output pins reside */
TSharedPtr<SVerticalBox> RightNodeBox;
/** Used to display the name of the node and allow renaming of the node */
TSharedPtr<SInlineEditableTextBlock> InlineEditableText;
/** Error handling widget */
TSharedPtr<class IErrorReportingWidget> ErrorReporting;
/** Visual Warning handling widget */
TSharedPtr<class IErrorReportingWidget> VisualWarningReporting;
FCurveSequence SpawnAnim;
FCurveHandle ZoomCurve;
FCurveHandle FadeCurve;
/* The margin used by the border containing the title. Can be changed by child classes if necessary.
* The extra padding on the right is for making the color spill stretch well past the node title */
FMargin TitleBorderMargin = FMargin(10.f, 5.f, 30.f, 3.f);
/** Is this node editable */
TAttribute<bool> IsEditable;
FSingleNodeEvent OnDoubleClick;
// Is the current tooltip a complex one that should be dropped when the tooltip is no longer displayed?
bool bProvidedComplexTooltip;
// Is a rename operation pending
bool bRenameIsPending;
/** Called whenever the text on the node is being committed interactively by the user, validates the string for commit */
FOnNodeVerifyTextCommit OnVerifyTextCommit;
/** Called whenever the text on the node is committed interactively by the user */
FOnNodeTextCommitted OnTextCommitted;
/** Called when the user generates a warning tooltip because a connection was invalid */
SGraphEditor::FOnDisallowedPinConnection OnDisallowedPinConnection;
/** Used to report errors on the node */
FString ErrorMsg;
/** Used to set the error color */
FSlateColor ErrorColor;
/** Used to report visual warnings on the node (does not break build) */
FString VisualWarningMsg;
/** Used to set the soft error color */
FSlateColor VisualWarningColor;
/** Caches true position of node */
FVector2D CachedUnscaledPosition;
/** Cached icon color for the node */
FLinearColor IconColor;
/** Cached pointer to graph editor settings */
const class UGraphEditorSettings* Settings;
private:
TSharedPtr<SLevelOfDetailBranchNode> TitleLODBranchNode;
};