2014-03-14 14:13:41 -04:00
// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
# include "GraphEditorCommon.h"
# include "NodeFactory.h"
# include "TokenizedMessage.h"
# include "Editor/UnrealEd/Public/DragAndDrop/ActorDragDropGraphEdOp.h"
# include "Editor/UnrealEd/Public/DragAndDrop/AssetDragDropOp.h"
# include "Editor/Persona/Public/BoneDragDropOp.h"
# include "Editor/UnrealEd/Public/Kismet2/BlueprintEditorUtils.h"
# include "SLevelOfDetailBranchNode.h"
# include "IDocumentation.h"
/////////////////////////////////////////////////////
// SNodeTitle
void SNodeTitle : : Construct ( const FArguments & InArgs , UEdGraphNode * InNode )
{
GraphNode = InNode ;
ExtraLineStyle = InArgs . _ExtraLineStyle ;
// If the user set the text, use it, otherwise use the node title by default
if ( InArgs . _Text . IsSet ( ) )
{
TitleText = InArgs . _Text ;
}
else
{
2014-04-23 18:30:37 -04:00
TitleText = TAttribute < FText > ( this , & SNodeTitle : : GetNodeTitle ) ;
2014-03-14 14:13:41 -04:00
}
2014-04-23 18:30:37 -04:00
CachedTitle = TitleText . Get ( ) ;
2014-03-14 14:13:41 -04:00
RebuildWidget ( ) ;
}
void SNodeTitle : : Tick ( const FGeometry & AllottedGeometry , const double InCurrentTime , const float InDeltaTime )
{
SCompoundWidget : : Tick ( AllottedGeometry , InCurrentTime , InDeltaTime ) ;
// Checks to see if the cached string is valid, and if not, updates it.
2014-04-23 19:34:38 -04:00
if ( TitleText . Get ( ) . CompareTo ( CachedTitle ) ! = 0 )
2014-03-14 14:13:41 -04:00
{
2014-04-23 18:30:37 -04:00
CachedTitle = TitleText . Get ( ) ;
2014-03-14 14:13:41 -04:00
RebuildWidget ( ) ;
}
}
2014-04-23 18:30:37 -04:00
FText SNodeTitle : : GetNodeTitle ( ) const
2014-03-14 14:13:41 -04:00
{
return ( GraphNode ! = NULL )
? GraphNode - > GetNodeTitle ( ENodeTitleType : : FullTitle )
2014-04-23 18:30:37 -04:00
: NSLOCTEXT ( " GraphEditor " , " NullNode " , " Null Node " ) ;
2014-03-14 14:13:41 -04:00
}
FText SNodeTitle : : GetHeadTitle ( ) const
{
2014-05-15 17:34:14 -04:00
return GraphNode - > bCanRenameNode ? GraphNode - > GetNodeTitle ( ENodeTitleType : : EditableTitle ) : CachedHeadTitle ;
2014-03-14 14:13:41 -04:00
}
void SNodeTitle : : RebuildWidget ( )
{
// Create the box to contain the lines
TSharedPtr < SVerticalBox > VerticalBox ;
this - > ChildSlot
[
SAssignNew ( VerticalBox , SVerticalBox )
] ;
// Break the title into lines
TArray < FString > Lines ;
2014-04-23 18:30:37 -04:00
CachedTitle . ToString ( ) . ParseIntoArray ( & Lines , TEXT ( " \n " ) , false ) ;
2014-03-14 14:13:41 -04:00
if ( Lines . Num ( ) )
{
CachedHeadTitle = FText : : FromString ( Lines [ 0 ] ) ;
}
// Make a separate widget for each line, using a less obvious style for subsequent lines
for ( int32 Index = 1 ; Index < Lines . Num ( ) ; + + Index )
{
VerticalBox - > AddSlot ( )
. AutoHeight ( )
[
SNew ( STextBlock )
. TextStyle ( FEditorStyle : : Get ( ) , ExtraLineStyle )
. Text ( Lines [ Index ] )
] ;
}
}
/////////////////////////////////////////////////////
// SGraphNode
// Check whether drag and drop functionality is permitted on the given node
bool SGraphNode : : CanAllowInteractionUsingDragDropOp ( const UEdGraphNode * GraphNodePtr , const TSharedPtr < FActorDragDropOp > & DragDropOp )
{
bool bReturn = false ;
//Allow interaction only if this node is a literal type object.
//Only change actor reference if a single actor reference is dragged from the outliner.
if ( GraphNodePtr - > IsA ( UK2Node_Literal : : StaticClass ( ) ) & & DragDropOp - > Actors . Num ( ) = = 1 )
{
bReturn = true ;
}
return bReturn ;
}
void SGraphNode : : SetIsEditable ( TAttribute < bool > InIsEditable )
{
IsEditable = InIsEditable ;
}
2014-06-18 05:04:59 -04:00
bool SGraphNode : : IsNodeEditable ( ) const
{
bool bReadOnly = OwnerGraphPanelPtr . IsValid ( ) ? OwnerGraphPanelPtr . Pin ( ) - > IsGraphEditable ( ) : false ;
return IsEditable . Get ( ) & & ! bReadOnly ;
}
2014-03-14 14:13:41 -04:00
/** Set event when node is double clicked */
void SGraphNode : : SetDoubleClickEvent ( FSingleNodeEvent InDoubleClickEvent )
{
OnDoubleClick = InDoubleClickEvent ;
}
void SGraphNode : : SetVerifyTextCommitEvent ( FOnNodeVerifyTextCommit InOnVerifyTextCommit )
{
OnVerifyTextCommit = InOnVerifyTextCommit ;
}
void SGraphNode : : SetTextCommittedEvent ( FOnNodeTextCommitted InOnTextCommitted )
{
OnTextCommitted = InOnTextCommitted ;
}
void SGraphNode : : SetDisallowedPinConnectionEvent ( SGraphEditor : : FOnDisallowedPinConnection InOnDisallowedPinConnection )
{
OnDisallowedPinConnection = InOnDisallowedPinConnection ;
}
void SGraphNode : : OnDragEnter ( const FGeometry & MyGeometry , const FDragDropEvent & DragDropEvent )
{
2014-04-23 18:00:50 -04:00
TSharedPtr < FDragDropOperation > Operation = DragDropEvent . GetOperation ( ) ;
if ( ! Operation . IsValid ( ) )
{
return ;
}
2014-03-14 14:13:41 -04:00
// Is someone dragging a connection?
2014-04-23 18:00:50 -04:00
if ( Operation - > IsOfType < FGraphEditorDragDropAction > ( ) )
2014-03-14 14:13:41 -04:00
{
// Inform the Drag and Drop operation that we are hovering over this pin.
2014-04-23 18:00:50 -04:00
TSharedPtr < FGraphEditorDragDropAction > DragConnectionOp = StaticCastSharedPtr < FGraphEditorDragDropAction > ( Operation ) ;
2014-03-14 14:13:41 -04:00
DragConnectionOp - > SetHoveredNode ( SharedThis ( this ) ) ;
}
2014-04-23 18:00:50 -04:00
else if ( Operation - > IsOfType < FActorDragDropGraphEdOp > ( ) )
2014-03-14 14:13:41 -04:00
{
2014-04-23 18:00:50 -04:00
TSharedPtr < FActorDragDropGraphEdOp > DragConnectionOp = StaticCastSharedPtr < FActorDragDropGraphEdOp > ( Operation ) ;
2014-03-14 14:13:41 -04:00
if ( GraphNode - > IsA ( UK2Node_Literal : : StaticClass ( ) ) )
{
//Show tool tip only if a single actor is dragged
if ( DragConnectionOp - > Actors . Num ( ) = = 1 )
{
UK2Node_Literal * LiteralNode = CastChecked < UK2Node_Literal > ( GraphNode ) ;
//Check whether this node is already referencing the same actor dragged from outliner
if ( LiteralNode - > GetObjectRef ( ) ! = DragConnectionOp - > Actors [ 0 ] . Get ( ) )
{
DragConnectionOp - > SetToolTip ( FActorDragDropGraphEdOp : : ToolTip_Compatible ) ;
}
}
else
{
//For more that one actor dragged on to a literal node, show tooltip as incompatible
DragConnectionOp - > SetToolTip ( FActorDragDropGraphEdOp : : ToolTip_MultipleSelection_Incompatible ) ;
}
}
else
{
DragConnectionOp - > SetToolTip ( ( DragConnectionOp - > Actors . Num ( ) = = 1 ) ? FActorDragDropGraphEdOp : : ToolTip_Incompatible : FActorDragDropGraphEdOp : : ToolTip_MultipleSelection_Incompatible ) ;
}
}
2014-04-23 18:00:50 -04:00
else if ( Operation - > IsOfType < FBoneDragDropOp > ( ) )
2014-03-14 14:13:41 -04:00
{
//@TODO: A2REMOVAL: No support for A3 nodes handling this drag-drop op yet!
}
}
void SGraphNode : : OnDragLeave ( const FDragDropEvent & DragDropEvent )
{
2014-04-23 18:00:50 -04:00
TSharedPtr < FDragDropOperation > Operation = DragDropEvent . GetOperation ( ) ;
if ( ! Operation . IsValid ( ) )
{
return ;
}
2014-03-14 14:13:41 -04:00
// Is someone dragging a connection?
2014-04-23 18:00:50 -04:00
if ( Operation - > IsOfType < FGraphEditorDragDropAction > ( ) )
2014-03-14 14:13:41 -04:00
{
// Inform the Drag and Drop operation that we are not hovering any pins
2014-04-23 18:00:50 -04:00
TSharedPtr < FGraphEditorDragDropAction > DragConnectionOp = StaticCastSharedPtr < FGraphEditorDragDropAction > ( Operation ) ;
2014-03-14 14:13:41 -04:00
DragConnectionOp - > SetHoveredNode ( TSharedPtr < SGraphNode > ( NULL ) ) ;
}
2014-04-23 18:00:50 -04:00
else if ( Operation - > IsOfType < FActorDragDropGraphEdOp > ( ) )
2014-03-14 14:13:41 -04:00
{
//Default tool tip
2014-04-23 18:00:50 -04:00
TSharedPtr < FActorDragDropGraphEdOp > DragConnectionOp = StaticCastSharedPtr < FActorDragDropGraphEdOp > ( Operation ) ;
2014-03-14 14:13:41 -04:00
DragConnectionOp - > ResetToDefaultToolTip ( ) ;
}
2014-04-23 18:00:50 -04:00
else if ( Operation - > IsOfType < FAssetDragDropOp > ( ) )
2014-03-14 14:13:41 -04:00
{
2014-04-23 18:00:50 -04:00
TSharedPtr < FAssetDragDropOp > AssetOp = StaticCastSharedPtr < FAssetDragDropOp > ( Operation ) ;
2014-03-14 14:13:41 -04:00
AssetOp - > ResetToDefaultToolTip ( ) ;
}
2014-04-23 18:00:50 -04:00
else if ( Operation - > IsOfType < FBoneDragDropOp > ( ) )
2014-03-14 14:13:41 -04:00
{
//@TODO: A2REMOVAL: No support for A3 nodes handling this drag-drop op yet!
}
}
FReply SGraphNode : : OnDragOver ( const FGeometry & MyGeometry , const FDragDropEvent & DragDropEvent )
{
2014-04-23 18:00:50 -04:00
TSharedPtr < FAssetDragDropOp > AssetOp = DragDropEvent . GetOperationAs < FAssetDragDropOp > ( ) ;
if ( AssetOp . IsValid ( ) )
2014-03-14 14:13:41 -04:00
{
if ( GraphNode ! = NULL & & GraphNode - > GetSchema ( ) ! = NULL )
{
bool bOkIcon = false ;
FString TooltipText ;
GraphNode - > GetSchema ( ) - > GetAssetsNodeHoverMessage ( AssetOp - > AssetData , GraphNode , TooltipText , bOkIcon ) ;
2014-06-18 05:04:59 -04:00
bool bReadOnly = OwnerGraphPanelPtr . IsValid ( ) ? ! OwnerGraphPanelPtr . Pin ( ) - > IsGraphEditable ( ) : false ;
bOkIcon = bReadOnly ? false : bOkIcon ;
2014-03-14 14:13:41 -04:00
const FSlateBrush * TooltipIcon = bOkIcon ? FEditorStyle : : GetBrush ( TEXT ( " Graph.ConnectorFeedback.OK " ) ) : FEditorStyle : : GetBrush ( TEXT ( " Graph.ConnectorFeedback.Error " ) ) ; ;
2014-04-23 17:55:20 -04:00
AssetOp - > SetToolTip ( FText : : FromString ( TooltipText ) , TooltipIcon ) ;
2014-03-14 14:13:41 -04:00
}
return FReply : : Handled ( ) ;
}
return FReply : : Unhandled ( ) ;
}
/** Given a coordinate in SGraphPanel space (i.e. panel widget space), return the same coordinate in graph space while taking zoom and panning into account */
FVector2D SGraphNode : : NodeCoordToGraphCoord ( const FVector2D & NodeSpaceCoordinate ) const
{
TSharedPtr < SGraphPanel > OwnerCanvas = OwnerGraphPanelPtr . Pin ( ) ;
if ( OwnerCanvas . IsValid ( ) )
{
//@TODO: NodeSpaceCoordinate != PanelCoordinate
FVector2D PanelSpaceCoordinate = NodeSpaceCoordinate ;
return OwnerCanvas - > PanelCoordToGraphCoord ( PanelSpaceCoordinate ) ;
}
else
{
return FVector2D : : ZeroVector ;
}
}
FReply SGraphNode : : OnDrop ( const FGeometry & MyGeometry , const FDragDropEvent & DragDropEvent )
{
2014-06-18 05:04:59 -04:00
bool bReadOnly = OwnerGraphPanelPtr . IsValid ( ) ? ! OwnerGraphPanelPtr . Pin ( ) - > IsGraphEditable ( ) : false ;
2014-04-23 18:00:50 -04:00
TSharedPtr < FDragDropOperation > Operation = DragDropEvent . GetOperation ( ) ;
2014-06-18 05:04:59 -04:00
if ( ! Operation . IsValid ( ) | | bReadOnly )
2014-03-14 14:13:41 -04:00
{
2014-04-23 18:00:50 -04:00
return FReply : : Unhandled ( ) ;
}
// Is someone dropping a connection onto this node?
if ( Operation - > IsOfType < FGraphEditorDragDropAction > ( ) )
{
TSharedPtr < FGraphEditorDragDropAction > DragConnectionOp = StaticCastSharedPtr < FGraphEditorDragDropAction > ( Operation ) ;
2014-03-14 14:13:41 -04:00
const FVector2D NodeAddPosition = NodeCoordToGraphCoord ( MyGeometry . AbsoluteToLocal ( DragDropEvent . GetScreenSpacePosition ( ) ) ) ;
FReply Result = DragConnectionOp - > DroppedOnNode ( DragDropEvent . GetScreenSpacePosition ( ) , NodeAddPosition ) ;
if ( Result . IsEventHandled ( ) & & ( GraphNode ! = NULL ) )
{
GraphNode - > GetGraph ( ) - > NotifyGraphChanged ( ) ;
}
return Result ;
}
2014-04-23 18:00:50 -04:00
else if ( Operation - > IsOfType < FActorDragDropGraphEdOp > ( ) )
2014-03-14 14:13:41 -04:00
{
2014-04-23 18:00:50 -04:00
TSharedPtr < FActorDragDropGraphEdOp > DragConnectionOp = StaticCastSharedPtr < FActorDragDropGraphEdOp > ( Operation ) ;
2014-03-14 14:13:41 -04:00
if ( CanAllowInteractionUsingDragDropOp ( GraphNode , DragConnectionOp ) )
{
UK2Node_Literal * LiteralNode = CastChecked < UK2Node_Literal > ( GraphNode ) ;
//Check whether this node is already referencing the same actor
if ( LiteralNode - > GetObjectRef ( ) ! = DragConnectionOp - > Actors [ 0 ] . Get ( ) )
{
//Replace literal node's object reference
LiteralNode - > SetObjectRef ( DragConnectionOp - > Actors [ 0 ] . Get ( ) ) ;
UBlueprint * Blueprint = FBlueprintEditorUtils : : FindBlueprintForGraphChecked ( CastChecked < UEdGraph > ( GraphNode - > GetOuter ( ) ) ) ;
FBlueprintEditorUtils : : MarkBlueprintAsModified ( Blueprint ) ;
}
}
return FReply : : Handled ( ) ;
}
2014-04-23 18:00:50 -04:00
else if ( Operation - > IsOfType < FAssetDragDropOp > ( ) )
2014-03-14 14:13:41 -04:00
{
UEdGraphNode * Node = GetNodeObj ( ) ;
if ( Node ! = NULL & & Node - > GetSchema ( ) ! = NULL )
{
2014-04-23 18:00:50 -04:00
TSharedPtr < FAssetDragDropOp > AssetOp = StaticCastSharedPtr < FAssetDragDropOp > ( Operation ) ;
2014-03-14 14:13:41 -04:00
Node - > GetSchema ( ) - > DroppedAssetsOnNode ( AssetOp - > AssetData , DragDropEvent . GetScreenSpacePosition ( ) , Node ) ;
}
return FReply : : Handled ( ) ;
}
2014-04-23 18:00:50 -04:00
else if ( Operation - > IsOfType < FBoneDragDropOp > ( ) )
2014-03-14 14:13:41 -04:00
{
//@TODO: A2REMOVAL: No support for A3 nodes handling this drag-drop op yet!
}
return FReply : : Unhandled ( ) ;
}
/**
* The system calls this method to notify the widget that a mouse button was pressed within it . This event is bubbled .
*
* @ param MyGeometry The Geometry of the widget receiving the event
* @ param MouseEvent Information about the input event
*
* @ return Whether the event was handled along with possible requests for the system to take action .
*/
FReply SGraphNode : : OnMouseButtonDown ( const FGeometry & MyGeometry , const FPointerEvent & MouseEvent )
{
return FReply : : Unhandled ( ) ;
}
// The system calls this method to notify the widget that a mouse button was release within it. This event is bubbled.
FReply SGraphNode : : OnMouseButtonUp ( const FGeometry & MyGeometry , const FPointerEvent & MouseEvent )
{
return FReply : : Unhandled ( ) ;
}
// Called when a mouse button is double clicked. Override this in derived classes
FReply SGraphNode : : OnMouseButtonDoubleClick ( const FGeometry & InMyGeometry , const FPointerEvent & InMouseEvent )
{
2014-04-02 18:09:23 -04:00
if ( InMouseEvent . IsMouseButtonDown ( EKeys : : LeftMouseButton ) )
{
OnDoubleClick . ExecuteIfBound ( GraphNode ) ;
return FReply : : Handled ( ) ;
}
return FReply : : Unhandled ( ) ;
2014-03-14 14:13:41 -04:00
}
Slate: Refactored core Slate implementation into SlateCore module in preparation for UMG.
Other Updates:
- The WidgetReflector is now in its own module as well. It will be converted to a plug-in later.
- The Public API of both Slate and SlateCore has largely been reorganized for better discoverabilty. More cleanup work is needed.
- Added a lot of missing API documentation and fixed existing ones. More and better documentation is needed.
- Removed dead code, fixed a couple things I stubled upon, and conformed to coding guidelines (NULL vs nullptr, line breaks, etc.)
Upgrade Notes:
- The Slate Remote Server is currently disabled - will be re-enabled shortly!
- If your module previously had a module dependency to 'Slate', it now also needs a PrivateModuleDependency to 'SlateCore' in its Build.cs file.
- If your module exposes in any of its Public header files types that are now declared in SlateCore, it needs a PublicModuleDependency to 'SlateCore'
- The ToolTip property type on SWidget has changed from SToolTip to IToolTip; change local variables to TSharedPtr<IToolTip> instead of TSharedPtr<SToolTip> where needed
- IToolTip is not a widget. If you need access to the actual widget that represents the tool tip, use IToolTip::AsWidget(); If you need access to the tool tip's content, use IToolTip::GetContentWidget()
Troubleshooting:
- After syncing to this changelist you may have to clean your /Engine/Intermediate/Build/ directory and rebuild your entire project
- If in your project you are getting linker errors for unresolved types that are now declared in SlateCore, you may be missing a dependency to 'SlateCore'
- If in the Engine code you are getting linker errors for unresolved types that are now declared in SlateCore, you may need to rebuild the entire Engine
[CL 2057118 by Max Preussner in Main branch]
2014-04-26 15:07:24 -04:00
TSharedPtr < IToolTip > SGraphNode : : GetToolTip ( )
2014-03-14 14:13:41 -04:00
{
Slate: Refactored core Slate implementation into SlateCore module in preparation for UMG.
Other Updates:
- The WidgetReflector is now in its own module as well. It will be converted to a plug-in later.
- The Public API of both Slate and SlateCore has largely been reorganized for better discoverabilty. More cleanup work is needed.
- Added a lot of missing API documentation and fixed existing ones. More and better documentation is needed.
- Removed dead code, fixed a couple things I stubled upon, and conformed to coding guidelines (NULL vs nullptr, line breaks, etc.)
Upgrade Notes:
- The Slate Remote Server is currently disabled - will be re-enabled shortly!
- If your module previously had a module dependency to 'Slate', it now also needs a PrivateModuleDependency to 'SlateCore' in its Build.cs file.
- If your module exposes in any of its Public header files types that are now declared in SlateCore, it needs a PublicModuleDependency to 'SlateCore'
- The ToolTip property type on SWidget has changed from SToolTip to IToolTip; change local variables to TSharedPtr<IToolTip> instead of TSharedPtr<SToolTip> where needed
- IToolTip is not a widget. If you need access to the actual widget that represents the tool tip, use IToolTip::AsWidget(); If you need access to the tool tip's content, use IToolTip::GetContentWidget()
Troubleshooting:
- After syncing to this changelist you may have to clean your /Engine/Intermediate/Build/ directory and rebuild your entire project
- If in your project you are getting linker errors for unresolved types that are now declared in SlateCore, you may be missing a dependency to 'SlateCore'
- If in the Engine code you are getting linker errors for unresolved types that are now declared in SlateCore, you may need to rebuild the entire Engine
[CL 2057118 by Max Preussner in Main branch]
2014-04-26 15:07:24 -04:00
TSharedPtr < IToolTip > CurrentTooltip = SWidget : : GetToolTip ( ) ;
2014-03-14 14:13:41 -04:00
if ( ! CurrentTooltip . IsValid ( ) )
{
TSharedPtr < SToolTip > ComplexTooltip = GetComplexTooltip ( ) ;
if ( ComplexTooltip . IsValid ( ) )
{
SetToolTip ( ComplexTooltip ) ;
bProvidedComplexTooltip = true ;
}
}
return SWidget : : GetToolTip ( ) ;
}
void SGraphNode : : OnToolTipClosing ( )
{
if ( bProvidedComplexTooltip )
{
SetToolTip ( NULL ) ;
bProvidedComplexTooltip = false ;
}
}
void SGraphNode : : Tick ( const FGeometry & AllottedGeometry , const double InCurrentTime , const float InDeltaTime )
{
CachedUnscaledPosition = AllottedGeometry . AbsolutePosition / AllottedGeometry . Scale ;
SNodePanel : : SNode : : Tick ( AllottedGeometry , InCurrentTime , InDeltaTime ) ;
}
bool SGraphNode : : IsSelectedExclusively ( ) const
{
TSharedPtr < SGraphPanel > OwnerPanel = OwnerGraphPanelPtr . Pin ( ) ;
if ( ! OwnerPanel - > HasKeyboardFocus ( ) | | OwnerPanel - > SelectionManager . GetSelectedNodes ( ) . Num ( ) > 1 )
{
return false ;
}
return OwnerPanel - > SelectionManager . IsNodeSelected ( GraphNode ) ;
}
/** @param OwnerPanel The GraphPanel that this node belongs to */
void SGraphNode : : SetOwner ( const TSharedRef < SGraphPanel > & OwnerPanel )
{
check ( ! OwnerGraphPanelPtr . IsValid ( ) ) ;
OwnerGraphPanelPtr = OwnerPanel ;
GraphNode - > NodeWidget = SharedThis ( this ) ;
/*Once we have an owner, and if hide Unused pins is enabled, we need to remake our pins to drop the hidden ones*/
if ( OwnerGraphPanelPtr . Pin ( ) - > GetPinVisibility ( ) ! = SGraphEditor : : Pin_Show
& & LeftNodeBox . IsValid ( )
& & RightNodeBox . IsValid ( ) )
{
this - > LeftNodeBox - > ClearChildren ( ) ;
this - > RightNodeBox - > ClearChildren ( ) ;
CreatePinWidgets ( ) ;
}
}
/** @param NewPosition The Node should be relocated to this position in the graph panel */
2014-05-06 04:45:44 -04:00
void SGraphNode : : MoveTo ( const FVector2D & NewPosition , FNodeSet & NodeFilter )
2014-03-14 14:13:41 -04:00
{
2014-05-06 04:45:44 -04:00
if ( ! NodeFilter . Find ( SharedThis ( this ) ) )
2014-03-14 14:13:41 -04:00
{
2014-05-06 04:45:44 -04:00
if ( GraphNode & & ! RequiresSecondPassLayout ( ) )
2014-03-14 14:13:41 -04:00
{
2014-05-06 04:45:44 -04:00
NodeFilter . Add ( SharedThis ( this ) ) ;
2014-04-02 18:09:23 -04:00
GraphNode - > Modify ( ) ;
2014-03-14 14:13:41 -04:00
GraphNode - > NodePosX = NewPosition . X ;
GraphNode - > NodePosY = NewPosition . Y ;
}
}
}
/** @return the Node's position within the graph */
FVector2D SGraphNode : : GetPosition ( ) const
{
return FVector2D ( GraphNode - > NodePosX , GraphNode - > NodePosY ) ;
}
FString SGraphNode : : GetEditableNodeTitle ( ) const
{
if ( GraphNode ! = NULL )
{
// Trying to catch a non-reproducible crash in this function
check ( GraphNode - > IsValidLowLevel ( ) ) ;
}
if ( GraphNode )
{
2014-04-23 18:30:37 -04:00
return GraphNode - > GetNodeTitle ( ENodeTitleType : : EditableTitle ) . ToString ( ) ;
2014-03-14 14:13:41 -04:00
}
return NSLOCTEXT ( " GraphEditor " , " NullNode " , " Null Node " ) . ToString ( ) ;
// Get the portion of the node that is actually editable text (may be a subsection of the title, or something else entirely)
return ( GraphNode ! = NULL )
2014-04-23 18:30:37 -04:00
? GraphNode - > GetNodeTitle ( ENodeTitleType : : EditableTitle ) . ToString ( )
2014-03-14 14:13:41 -04:00
: NSLOCTEXT ( " GraphEditor " , " NullNode " , " Null Node " ) . ToString ( ) ;
}
FText SGraphNode : : GetEditableNodeTitleAsText ( ) const
{
FString NewString = GetEditableNodeTitle ( ) ;
return FText : : FromString ( NewString ) ;
}
FString SGraphNode : : GetNodeComment ( ) const
{
return GetNodeObj ( ) - > NodeComment ;
}
UObject * SGraphNode : : GetObjectBeingDisplayed ( ) const
{
return GetNodeObj ( ) ;
}
FSlateColor SGraphNode : : GetNodeTitleColor ( ) const
{
FLinearColor NodeTitleColor = GraphNode - > IsDeprecated ( ) ? FLinearColor : : Red : GetNodeObj ( ) - > GetNodeTitleColor ( ) ;
NodeTitleColor . A = FadeCurve . GetLerp ( ) ;
return NodeTitleColor ;
}
FSlateColor SGraphNode : : GetNodeCommentColor ( ) const
{
return GetNodeObj ( ) - > GetNodeCommentColor ( ) ;
}
/** @return the tooltip to display when over the node */
FText SGraphNode : : GetNodeTooltip ( ) const
{
if ( GraphNode ! = NULL )
{
2014-04-23 18:30:37 -04:00
// Display the native title of the node when alt is held
if ( FSlateApplication : : Get ( ) . GetModifierKeys ( ) . IsAltDown ( ) )
{
return FText : : FromString ( GraphNode - > GetNodeNativeTitle ( ENodeTitleType : : ListView ) ) ;
}
2014-03-14 14:13:41 -04:00
FText TooltipText = FText : : FromString ( GraphNode - > GetTooltip ( ) ) ;
if ( UEdGraph * Graph = GraphNode - > GetGraph ( ) )
{
// If the node resides in an intermediate graph, show the UObject name for debug purposes
if ( Graph - > HasAnyFlags ( RF_Transient ) )
{
2014-04-23 18:30:37 -04:00
FFormatNamedArguments Args ;
Args . Add ( TEXT ( " NodeName " ) , FText : : FromString ( GraphNode - > GetName ( ) ) ) ;
Args . Add ( TEXT ( " TooltipText " ) , TooltipText ) ;
TooltipText = FText : : Format ( NSLOCTEXT ( " GraphEditor " , " GraphNodeTooltip " , " {NodeName} \n \n {TooltipText} " ) , Args ) ;
2014-03-14 14:13:41 -04:00
}
}
if ( TooltipText . IsEmpty ( ) )
{
2014-04-23 18:30:37 -04:00
TooltipText = GraphNode - > GetNodeTitle ( ENodeTitleType : : FullTitle ) ;
2014-03-14 14:13:41 -04:00
}
return TooltipText ;
}
else
{
return NSLOCTEXT ( " GraphEditor " , " InvalidGraphNode " , " <Invalid graph node> " ) ;
}
}
/** @return the node being observed by this widget*/
UEdGraphNode * SGraphNode : : GetNodeObj ( ) const
{
return GraphNode ;
}
TSharedPtr < SGraphPanel > SGraphNode : : GetOwnerPanel ( ) const
{
return OwnerGraphPanelPtr . Pin ( ) ;
}
void SGraphNode : : UpdateErrorInfo ( )
{
//Check for node errors/warnings
if ( GraphNode - > bHasCompilerMessage )
{
if ( GraphNode - > ErrorType < = EMessageSeverity : : Error )
{
ErrorMsg = FString ( TEXT ( " ERROR! " ) ) ;
ErrorColor = FEditorStyle : : GetColor ( " ErrorReporting.BackgroundColor " ) ;
}
else if ( GraphNode - > ErrorType < = EMessageSeverity : : Warning )
{
ErrorMsg = FString ( TEXT ( " WARNING! " ) ) ;
ErrorColor = FEditorStyle : : GetColor ( " ErrorReporting.WarningBackgroundColor " ) ;
}
else
{
ErrorMsg = FString ( TEXT ( " NOTE " ) ) ;
ErrorColor = FEditorStyle : : GetColor ( " InfoReporting.BackgroundColor " ) ;
}
}
else
{
ErrorColor = FLinearColor ( 0 , 0 , 0 ) ;
ErrorMsg . Empty ( ) ;
}
}
TSharedPtr < SWidget > SGraphNode : : SetupErrorReporting ( )
{
TSharedPtr < SErrorText > ErrorText ;
UpdateErrorInfo ( ) ;
// generate widget
SAssignNew ( ErrorText , SErrorText )
. BackgroundColor ( this , & SGraphNode : : GetErrorColor )
. ToolTipText ( this , & SGraphNode : : GetErrorMsgToolTip ) ;
ErrorReporting = ErrorText ;
ErrorReporting - > SetError ( ErrorMsg ) ;
return ErrorText ;
}
TSharedRef < SWidget > SGraphNode : : CreateTitleWidget ( TSharedPtr < SNodeTitle > NodeTitle )
{
return SAssignNew ( InlineEditableText , SInlineEditableTextBlock )
. Style ( FEditorStyle : : Get ( ) , " Graph.Node.NodeTitleInlineEditableText " )
. Text ( NodeTitle . Get ( ) , & SNodeTitle : : GetHeadTitle )
. OnVerifyTextChanged ( this , & SGraphNode : : OnVerifyNameTextChanged )
. OnTextCommitted ( this , & SGraphNode : : OnNameTextCommited )
. IsReadOnly ( this , & SGraphNode : : IsNameReadOnly )
. IsSelected ( this , & SGraphNode : : IsSelectedExclusively ) ;
}
/**
* Update this GraphNode to match the data that it is observing
*/
BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
void SGraphNode : : UpdateGraphNode ( )
{
InputPins . Empty ( ) ;
OutputPins . Empty ( ) ;
// Reset variables that are going to be exposed, in case we are refreshing an already setup node.
RightNodeBox . Reset ( ) ;
LeftNodeBox . Reset ( ) ;
//
// ______________________
// | TITLE AREA |
// +-------+------+-------+
// | (>) L | | R (>) |
// | (>) E | | I (>) |
// | (>) F | | G (>) |
// | (>) T | | H (>) |
// | | | T (>) |
// |_______|______|_______|
//
TSharedPtr < SVerticalBox > MainVerticalBox ;
TSharedPtr < SWidget > ErrorText = SetupErrorReporting ( ) ;
TSharedPtr < SNodeTitle > NodeTitle = SNew ( SNodeTitle , GraphNode ) ;
// Get node icon
FLinearColor IconColor = FLinearColor : : White ;
const FSlateBrush * IconBrush = NULL ;
if ( GraphNode ! = NULL & & GraphNode - > ShowPaletteIconOnNode ( ) )
{
IconBrush = FEditorStyle : : GetBrush ( GraphNode - > GetPaletteIcon ( IconColor ) ) ;
}
TSharedRef < SOverlay > DefaultTitleAreaWidget =
SNew ( SOverlay )
+ SOverlay : : Slot ( )
[
SNew ( SImage )
. Image ( FEditorStyle : : GetBrush ( " Graph.Node.TitleGloss " ) )
]
+ SOverlay : : Slot ( )
. HAlign ( HAlign_Left )
. VAlign ( VAlign_Center )
[
SNew ( SBorder )
. BorderImage ( FEditorStyle : : GetBrush ( " Graph.Node.ColorSpill " ) )
// The extra margin on the right
// is for making the color spill stretch well past the node title
. Padding ( FMargin ( 10 , 5 , 30 , 3 ) )
. BorderBackgroundColor ( this , & SGraphNode : : GetNodeTitleColor )
[
SNew ( SHorizontalBox )
+ SHorizontalBox : : Slot ( )
. VAlign ( VAlign_Top )
. Padding ( FMargin ( 0.f , 0.f , 4.f , 0.f ) )
. AutoWidth ( )
[
SNew ( SImage )
. Image ( IconBrush )
. ColorAndOpacity ( IconColor )
]
+ SHorizontalBox : : Slot ( )
[
SNew ( SVerticalBox )
+ SVerticalBox : : Slot ( )
. AutoHeight ( )
[
CreateTitleWidget ( NodeTitle )
]
+ SVerticalBox : : Slot ( )
. AutoHeight ( )
[
NodeTitle . ToSharedRef ( )
]
]
]
]
+ SOverlay : : Slot ( )
. VAlign ( VAlign_Top )
[
SNew ( SBorder )
. Visibility ( EVisibility : : HitTestInvisible )
. BorderImage ( FEditorStyle : : GetBrush ( " Graph.Node.TitleHighlight " ) )
[
SNew ( SSpacer )
. Size ( FVector2D ( 20 , 20 ) )
]
] ;
SetDefaultTitleAreaWidget ( DefaultTitleAreaWidget ) ;
TSharedRef < SWidget > TitleAreaWidget =
SNew ( SLevelOfDetailBranchNode )
. UseLowDetailSlot ( this , & SGraphNode : : UseLowDetailNodeTitles )
. LowDetail ( )
[
SNew ( SBorder )
. BorderImage ( FEditorStyle : : GetBrush ( " Graph.Node.ColorSpill " ) )
. Padding ( FMargin ( 75.0f , 22.0f ) ) // Saving enough space for a 'typical' title so the transition isn't quite so abrupt
. BorderBackgroundColor ( this , & SGraphNode : : GetNodeTitleColor )
]
. HighDetail ( )
[
DefaultTitleAreaWidget
] ;
if ( ! SWidget : : GetToolTip ( ) . IsValid ( ) )
{
TSharedRef < SToolTip > DefaultToolTip = IDocumentation : : Get ( ) - > CreateToolTip ( TAttribute < FText > ( this , & SGraphNode : : GetNodeTooltip ) , NULL , GraphNode - > GetDocumentationLink ( ) , GraphNode - > GetDocumentationExcerptName ( ) ) ;
SetToolTip ( DefaultToolTip ) ;
}
TSharedPtr < SVerticalBox > InnerVerticalBox ;
this - > ContentScale . Bind ( this , & SGraphNode : : GetContentScale ) ;
this - > ChildSlot
. HAlign ( HAlign_Center )
. VAlign ( VAlign_Center )
[
SAssignNew ( MainVerticalBox , SVerticalBox )
+ SVerticalBox : : Slot ( )
. AutoHeight ( )
[
SNew ( SBorder )
. BorderImage ( FEditorStyle : : GetBrush ( " Graph.Node.Body " ) )
. Padding ( 0 )
[
SAssignNew ( InnerVerticalBox , SVerticalBox )
+ SVerticalBox : : Slot ( )
. AutoHeight ( )
. HAlign ( HAlign_Fill )
. VAlign ( VAlign_Top )
[
TitleAreaWidget
]
+ SVerticalBox : : Slot ( )
. AutoHeight ( )
. Padding ( 1.0f )
[
ErrorText - > AsShared ( )
]
+ SVerticalBox : : Slot ( )
. AutoHeight ( )
. HAlign ( HAlign_Fill )
. VAlign ( VAlign_Top )
[
CreateNodeContentArea ( )
]
]
]
] ;
CreateBelowWidgetControls ( MainVerticalBox ) ;
CreatePinWidgets ( ) ;
2014-04-02 18:09:23 -04:00
CreateInputSideAddButton ( LeftNodeBox ) ;
CreateOutputSideAddButton ( RightNodeBox ) ;
2014-03-14 14:13:41 -04:00
CreateBelowPinControls ( InnerVerticalBox ) ;
CreateAdvancedViewArrow ( InnerVerticalBox ) ;
}
END_SLATE_FUNCTION_BUILD_OPTIMIZATION
TSharedRef < SWidget > SGraphNode : : CreateNodeContentArea ( )
{
// NODE CONTENT AREA
return SNew ( SBorder )
. BorderImage ( FEditorStyle : : GetBrush ( " NoBorder " ) )
. HAlign ( HAlign_Fill )
. VAlign ( VAlign_Fill )
. Padding ( FMargin ( 0 , 3 ) )
[
SNew ( SHorizontalBox )
+ SHorizontalBox : : Slot ( )
. HAlign ( HAlign_Left )
. FillWidth ( 1.0f )
[
// LEFT
SAssignNew ( LeftNodeBox , SVerticalBox )
]
+ SHorizontalBox : : Slot ( )
. AutoWidth ( )
. HAlign ( HAlign_Right )
[
// RIGHT
SAssignNew ( RightNodeBox , SVerticalBox )
]
] ;
}
/** Returns visibility of AdvancedViewButton */
EVisibility SGraphNode : : AdvancedViewArrowVisibility ( ) const
{
const bool bShowAdvancedViewArrow = GraphNode & & ( ENodeAdvancedPins : : NoPins ! = GraphNode - > AdvancedPinDisplay ) ;
return bShowAdvancedViewArrow ? EVisibility : : Visible : EVisibility : : Collapsed ;
}
void SGraphNode : : OnAdvancedViewChanged ( const ESlateCheckBoxState : : Type NewCheckedState )
{
if ( GraphNode & & ( ENodeAdvancedPins : : NoPins ! = GraphNode - > AdvancedPinDisplay ) )
{
const bool bAdvancedPinsHidden = ( NewCheckedState ! = ESlateCheckBoxState : : Checked ) ;
GraphNode - > AdvancedPinDisplay = bAdvancedPinsHidden ? ENodeAdvancedPins : : Hidden : ENodeAdvancedPins : : Shown ;
}
}
ESlateCheckBoxState : : Type SGraphNode : : IsAdvancedViewChecked ( ) const
{
const bool bAdvancedPinsHidden = GraphNode & & ( ENodeAdvancedPins : : Hidden = = GraphNode - > AdvancedPinDisplay ) ;
return bAdvancedPinsHidden ? ESlateCheckBoxState : : Unchecked : ESlateCheckBoxState : : Checked ;
}
const FSlateBrush * SGraphNode : : GetAdvancedViewArrow ( ) const
{
const bool bAdvancedPinsHidden = GraphNode & & ( ENodeAdvancedPins : : Hidden = = GraphNode - > AdvancedPinDisplay ) ;
return FEditorStyle : : GetBrush ( bAdvancedPinsHidden ? TEXT ( " Kismet.TitleBarEditor.ArrowDown " ) : TEXT ( " Kismet.TitleBarEditor.ArrowUp " ) ) ;
}
/** Create widget to show/hide advanced pins */
void SGraphNode : : CreateAdvancedViewArrow ( TSharedPtr < SVerticalBox > MainBox )
{
const bool bHidePins = OwnerGraphPanelPtr . IsValid ( ) & & ( OwnerGraphPanelPtr . Pin ( ) - > GetPinVisibility ( ) ! = SGraphEditor : : Pin_Show ) ;
const bool bAnyAdvancedPin = GraphNode & & ( ENodeAdvancedPins : : NoPins ! = GraphNode - > AdvancedPinDisplay ) ;
if ( ! bHidePins & & GraphNode & & MainBox . IsValid ( ) )
{
MainBox - > AddSlot ( )
. AutoHeight ( )
. HAlign ( HAlign_Fill )
. VAlign ( VAlign_Top )
. Padding ( 3 , 0 , 3 , 3 )
[
SNew ( SCheckBox )
. Visibility ( this , & SGraphNode : : AdvancedViewArrowVisibility )
. OnCheckStateChanged ( this , & SGraphNode : : OnAdvancedViewChanged )
. IsChecked ( this , & SGraphNode : : IsAdvancedViewChecked )
. Cursor ( EMouseCursor : : Default )
. Style ( FEditorStyle : : Get ( ) , " Graph.Node.AdvancedView " )
[
SNew ( SHorizontalBox )
+ SHorizontalBox : : Slot ( )
. VAlign ( VAlign_Center )
. HAlign ( HAlign_Center )
[
SNew ( SImage )
. Image ( this , & SGraphNode : : GetAdvancedViewArrow )
]
]
] ;
}
}
void SGraphNode : : CreateStandardPinWidget ( UEdGraphPin * CurPin )
{
const UEdGraphSchema_K2 * K2Schema = Cast < const UEdGraphSchema_K2 > ( GraphNode - > GetSchema ( ) ) ;
bool bHideNoConnectionPins = false ;
bool bHideNoConnectionNoDefaultPins = false ;
// Not allowed to hide exec pins
const bool bCanHidePin = ( K2Schema & & ( CurPin - > PinType . PinCategory ! = K2Schema - > PC_Exec ) ) ;
if ( OwnerGraphPanelPtr . IsValid ( ) & & bCanHidePin )
{
bHideNoConnectionPins = OwnerGraphPanelPtr . Pin ( ) - > GetPinVisibility ( ) = = SGraphEditor : : Pin_HideNoConnection ;
bHideNoConnectionNoDefaultPins = OwnerGraphPanelPtr . Pin ( ) - > GetPinVisibility ( ) = = SGraphEditor : : Pin_HideNoConnectionNoDefault ;
}
const bool bIsOutputPin = CurPin - > Direction = = EGPD_Output ;
const bool bPinHasDefaultValue = ! CurPin - > DefaultValue . IsEmpty ( ) | | ( CurPin - > DefaultObject ! = NULL ) ;
const bool bIsSelfTarget = K2Schema & & ( CurPin - > PinType . PinCategory = = K2Schema - > PC_Object ) & & ( CurPin - > PinName = = K2Schema - > PN_Self ) ;
const bool bPinHasValidDefault = ! bIsOutputPin & & ( bPinHasDefaultValue | | bIsSelfTarget ) ;
const bool bPinHasConections = CurPin - > LinkedTo . Num ( ) > 0 ;
const bool bPinDesiresToBeHidden = CurPin - > bHidden | | ( bHideNoConnectionPins & & ! bPinHasConections ) | | ( bHideNoConnectionNoDefaultPins & & ! bPinHasConections & & ! bPinHasValidDefault ) ;
// No matter how strong the desire, a pin with connections can never be hidden!
const bool bShowPin = ! bPinDesiresToBeHidden | | bPinHasConections ;
if ( bShowPin )
{
TSharedPtr < SGraphPin > NewPin = CreatePinWidget ( CurPin ) ;
check ( NewPin . IsValid ( ) ) ;
NewPin - > SetIsEditable ( IsEditable ) ;
this - > AddPin ( NewPin . ToSharedRef ( ) ) ;
}
}
void SGraphNode : : CreatePinWidgets ( )
{
// Create Pin widgets for each of the pins.
for ( int32 PinIndex = 0 ; PinIndex < GraphNode - > Pins . Num ( ) ; + + PinIndex )
{
UEdGraphPin * CurPin = GraphNode - > Pins [ PinIndex ] ;
CreateStandardPinWidget ( CurPin ) ;
}
}
TSharedPtr < SGraphPin > SGraphNode : : CreatePinWidget ( UEdGraphPin * Pin ) const
{
return FNodeFactory : : CreatePinWidget ( Pin ) ;
}
/**
* Add a new pin to this graph node . The pin must be newly created .
*
* @ param PinToAdd A new pin to add to this GraphNode .
*/
void SGraphNode : : AddPin ( const TSharedRef < SGraphPin > & PinToAdd )
{
PinToAdd - > SetOwner ( SharedThis ( this ) ) ;
const UEdGraphPin * PinObj = PinToAdd - > GetPinObj ( ) ;
const bool bAdvancedParameter = PinObj & & PinObj - > bAdvancedView ;
if ( bAdvancedParameter )
{
PinToAdd - > SetVisibility ( TAttribute < EVisibility > ( PinToAdd , & SGraphPin : : IsPinVisibleAsAdvanced ) ) ;
}
if ( PinToAdd - > GetDirection ( ) = = EEdGraphPinDirection : : EGPD_Input )
{
LeftNodeBox - > AddSlot ( )
. AutoHeight ( )
. HAlign ( HAlign_Left )
. VAlign ( VAlign_Center )
. Padding ( 10 , 4 )
[
PinToAdd
] ;
InputPins . Add ( PinToAdd ) ;
}
else // Direction == EEdGraphPinDirection::EGPD_Output
{
RightNodeBox - > AddSlot ( )
. AutoHeight ( )
. HAlign ( HAlign_Right )
. VAlign ( VAlign_Center )
. Padding ( 10 , 4 )
[
PinToAdd
] ;
OutputPins . Add ( PinToAdd ) ;
}
}
/**
* Get all the pins found on this node .
*
* @ param AllPins The set of pins found on this node .
*/
void SGraphNode : : GetPins ( TSet < TSharedRef < SWidget > > & AllPins ) const
{
for ( int32 PinIndex = 0 ; PinIndex < this - > InputPins . Num ( ) ; + + PinIndex )
{
AllPins . Add ( InputPins [ PinIndex ] ) ;
}
for ( int32 PinIndex = 0 ; PinIndex < this - > OutputPins . Num ( ) ; + + PinIndex )
{
AllPins . Add ( OutputPins [ PinIndex ] ) ;
}
}
void SGraphNode : : GetPins ( TArray < TSharedRef < SWidget > > & AllPins ) const
{
for ( int32 PinIndex = 0 ; PinIndex < this - > InputPins . Num ( ) ; + + PinIndex )
{
AllPins . Add ( InputPins [ PinIndex ] ) ;
}
for ( int32 PinIndex = 0 ; PinIndex < this - > OutputPins . Num ( ) ; + + PinIndex )
{
AllPins . Add ( OutputPins [ PinIndex ] ) ;
}
}
TSharedPtr < SGraphPin > SGraphNode : : GetHoveredPin ( const FGeometry & MyGeometry , const FPointerEvent & MouseEvent ) const
{
// We just need to find the one WidgetToFind among our descendants.
TSet < TSharedRef < SWidget > > MyPins ;
{
GetPins ( MyPins ) ;
}
TMap < TSharedRef < SWidget > , FArrangedWidget > Result ;
FindChildGeometries ( MyGeometry , MyPins , Result ) ;
if ( Result . Num ( ) > 0 )
{
FArrangedChildren ArrangedPins ( EVisibility : : Visible ) ;
Result . GenerateValueArray ( ArrangedPins . GetInternalArray ( ) ) ;
int32 HoveredPinIndex = SWidget : : FindChildUnderMouse ( ArrangedPins , MouseEvent ) ;
if ( HoveredPinIndex ! = INDEX_NONE )
{
return StaticCastSharedRef < SGraphPin > ( ArrangedPins ( HoveredPinIndex ) . Widget ) ;
}
}
return TSharedPtr < SGraphPin > ( ) ;
}
TSharedPtr < SGraphPin > SGraphNode : : FindWidgetForPin ( UEdGraphPin * ThePin ) const
{
// Search input or output pins?
const TArray < TSharedRef < SGraphPin > > & PinsToSearch = ( ThePin - > Direction = = EGPD_Input ) ? InputPins : OutputPins ;
// Actually search for the widget
for ( int32 PinIndex = 0 ; PinIndex < PinsToSearch . Num ( ) ; + + PinIndex )
{
if ( PinsToSearch [ PinIndex ] - > GetPinObj ( ) = = ThePin )
{
return PinsToSearch [ PinIndex ] ;
}
}
return TSharedPtr < SGraphPin > ( NULL ) ;
}
void SGraphNode : : PlaySpawnEffect ( )
{
SpawnAnim . Play ( ) ;
}
FVector2D SGraphNode : : GetContentScale ( ) const
{
const float CurZoomValue = ZoomCurve . GetLerp ( ) ;
return FVector2D ( CurZoomValue , CurZoomValue ) ;
}
FLinearColor SGraphNode : : GetColorAndOpacity ( ) const
{
return FLinearColor ( 1 , 1 , 1 , FadeCurve . GetLerp ( ) ) ;
}
FLinearColor SGraphNode : : GetPinLabelColorAndOpacity ( ) const
{
return FLinearColor ( 0 , 0 , 0 , FadeCurve . GetLerp ( ) ) ;
}
SGraphNode : : SGraphNode ( )
: bProvidedComplexTooltip ( false )
, ErrorColor ( FLinearColor : : White )
, bRenameIsPending ( false )
, CachedUnscaledPosition ( FVector2D : : ZeroVector )
{
// Set up animation
{
ZoomCurve = SpawnAnim . AddCurve ( 0 , 0.1f ) ;
FadeCurve = SpawnAnim . AddCurve ( 0.15f , 0.15f ) ;
SpawnAnim . JumpToEnd ( ) ;
}
}
void SGraphNode : : PositionThisNodeBetweenOtherNodes ( const TMap < UObject * , TSharedRef < SNode > > & NodeToWidgetLookup , UEdGraphNode * PreviousNode , UEdGraphNode * NextNode , float HeightAboveWire ) const
{
if ( ( PreviousNode ! = NULL ) & & ( NextNode ! = NULL ) )
{
TSet < UEdGraphNode * > PrevNodes ;
PrevNodes . Add ( PreviousNode ) ;
TSet < UEdGraphNode * > NextNodes ;
NextNodes . Add ( NextNode ) ;
PositionThisNodeBetweenOtherNodes ( NodeToWidgetLookup , PrevNodes , NextNodes , HeightAboveWire ) ;
}
}
void SGraphNode : : PositionThisNodeBetweenOtherNodes ( const TMap < UObject * , TSharedRef < SNode > > & NodeToWidgetLookup , TSet < UEdGraphNode * > & PreviousNodes , TSet < UEdGraphNode * > & NextNodes , float HeightAboveWire ) const
{
// Find the previous position centroid
FVector2D PrevPos ( 0.0f , 0.0f ) ;
for ( auto NodeIt = PreviousNodes . CreateConstIterator ( ) ; NodeIt ; + + NodeIt )
{
UEdGraphNode * PreviousNode = * NodeIt ;
const FVector2D CornerPos ( PreviousNode - > NodePosX , PreviousNode - > NodePosY ) ;
PrevPos + = CornerPos + NodeToWidgetLookup . FindChecked ( PreviousNode ) - > GetDesiredSize ( ) * 0.5f ;
}
// Find the next position centroid
FVector2D NextPos ( 0.0f , 0.0f ) ;
for ( auto NodeIt = NextNodes . CreateConstIterator ( ) ; NodeIt ; + + NodeIt )
{
UEdGraphNode * NextNode = * NodeIt ;
const FVector2D CornerPos ( NextNode - > NodePosX , NextNode - > NodePosY ) ;
NextPos + = CornerPos + NodeToWidgetLookup . FindChecked ( NextNode ) - > GetDesiredSize ( ) * 0.5f ;
}
PositionThisNodeBetweenOtherNodes ( PrevPos , NextPos , HeightAboveWire ) ;
}
void SGraphNode : : PositionThisNodeBetweenOtherNodes ( const FVector2D & PrevPos , const FVector2D & NextPos , float HeightAboveWire ) const
{
const FVector2D DesiredSize = GetDesiredSize ( ) ;
FVector2D DeltaPos ( NextPos - PrevPos ) ;
if ( DeltaPos . IsNearlyZero ( ) )
{
DeltaPos = FVector2D ( 10.0f , 0.0f ) ;
}
const FVector2D Normal = FVector2D ( DeltaPos . Y , - DeltaPos . X ) . SafeNormal ( ) ;
const FVector2D SlidingCapsuleBias = FVector2D : : ZeroVector ; //(0.5f * FMath::Sin(Normal.X * (float)HALF_PI) * DesiredSize.X, 0.0f);
const FVector2D NewCenter = PrevPos + ( 0.5f * DeltaPos ) + ( HeightAboveWire * Normal ) + SlidingCapsuleBias ;
// Now we need to adjust the new center by the node size and zoom factor
const FVector2D NewCorner = NewCenter - ( 0.5f * DesiredSize ) ;
GraphNode - > NodePosX = NewCorner . X ;
GraphNode - > NodePosY = NewCorner . Y ;
}
FString SGraphNode : : GetErrorMsgToolTip ( ) const
{
return GraphNode - > ErrorMsg ;
}
bool SGraphNode : : ShouldScaleNodeComment ( ) const
{
return true ;
}
bool SGraphNode : : IsNameReadOnly ( ) const
{
return ! GraphNode - > bCanRenameNode ;
}
2014-05-15 17:34:14 -04:00
bool SGraphNode : : OnVerifyNameTextChanged ( const FText & InText , FText & OutErrorMessage )
2014-03-14 14:13:41 -04:00
{
bool bValid ( true ) ;
2014-05-15 17:34:14 -04:00
if ( ( GetEditableNodeTitle ( ) ! = InText . ToString ( ) ) & & OnVerifyTextCommit . IsBound ( ) )
2014-03-14 14:13:41 -04:00
{
bValid = OnVerifyTextCommit . Execute ( InText , GraphNode ) ;
}
OutErrorMessage = FText : : FromString ( TEXT ( " Error " ) ) ;
//UpdateErrorInfo();
//ErrorReporting->SetError(ErrorMsg);
return bValid ;
}
2014-05-15 17:34:14 -04:00
void SGraphNode : : OnNameTextCommited ( const FText & InText , ETextCommit : : Type CommitInfo )
2014-03-14 14:13:41 -04:00
{
OnTextCommitted . ExecuteIfBound ( InText , CommitInfo , GraphNode ) ;
UpdateErrorInfo ( ) ;
2014-05-15 17:34:14 -04:00
if ( ErrorReporting . IsValid ( ) )
{
ErrorReporting - > SetError ( ErrorMsg ) ;
}
2014-03-14 14:13:41 -04:00
}
void SGraphNode : : RequestRename ( )
{
if ( ( GraphNode ! = NULL ) & & GraphNode - > bCanRenameNode )
{
bRenameIsPending = true ;
}
}
void SGraphNode : : ApplyRename ( )
{
if ( bRenameIsPending )
{
bRenameIsPending = false ;
InlineEditableText - > EnterEditingMode ( ) ;
}
}
FSlateRect SGraphNode : : GetTitleRect ( ) const
{
const FVector2D NodePosition = GetPosition ( ) ;
const FVector2D NodeSize = GraphNode ? InlineEditableText - > GetDesiredSize ( ) : GetDesiredSize ( ) ;
return FSlateRect ( NodePosition . X , NodePosition . Y + NodeSize . Y , NodePosition . X + NodeSize . X , NodePosition . Y ) ;
}
void SGraphNode : : NotifyDisallowedPinConnection ( const UEdGraphPin * PinA , const UEdGraphPin * PinB ) const
{
OnDisallowedPinConnection . ExecuteIfBound ( PinA , PinB ) ;
}
bool SGraphNode : : UseLowDetailNodeTitles ( ) const
{
if ( const SGraphPanel * MyOwnerPanel = GetOwnerPanel ( ) . Get ( ) )
{
return ( MyOwnerPanel - > GetCurrentLOD ( ) < = EGraphRenderingLOD : : LowestDetail ) & & ! InlineEditableText - > IsInEditMode ( ) ;
}
else
{
return false ;
}
}
2014-04-02 18:09:23 -04:00
TSharedRef < SWidget > SGraphNode : : AddPinButtonContent ( FText PinText , FText PinTooltipText , bool bRightSide , FString DocumentationExcerpt , TSharedPtr < SToolTip > CustomTooltip )
{
TSharedPtr < SWidget > ButtonContent ;
if ( bRightSide )
{
SAssignNew ( ButtonContent , SHorizontalBox )
+ SHorizontalBox : : Slot ( )
. AutoWidth ( )
. HAlign ( HAlign_Left )
[
SNew ( STextBlock )
. Text ( PinText )
. ColorAndOpacity ( FLinearColor : : White )
]
+ SHorizontalBox : : Slot ( )
. AutoWidth ( )
. VAlign ( VAlign_Center )
. Padding ( 7 , 0 , 0 , 0 )
[
SNew ( SImage )
. Image ( FEditorStyle : : GetBrush ( TEXT ( " PropertyWindow.Button_AddToArray " ) ) )
] ;
}
else
{
SAssignNew ( ButtonContent , SHorizontalBox )
+ SHorizontalBox : : Slot ( )
. AutoWidth ( )
. VAlign ( VAlign_Center )
. Padding ( 0 , 0 , 7 , 0 )
[
SNew ( SImage )
. Image ( FEditorStyle : : GetBrush ( TEXT ( " PropertyWindow.Button_AddToArray " ) ) )
]
+ SHorizontalBox : : Slot ( )
. AutoWidth ( )
. HAlign ( HAlign_Left )
[
SNew ( STextBlock )
. Text ( PinText )
. ColorAndOpacity ( FLinearColor : : White )
] ;
}
TSharedPtr < SToolTip > Tooltip ;
if ( CustomTooltip . IsValid ( ) )
{
Tooltip = CustomTooltip ;
}
else if ( ! DocumentationExcerpt . IsEmpty ( ) )
{
Tooltip = IDocumentation : : Get ( ) - > CreateToolTip ( PinTooltipText , NULL , GraphNode - > GetDocumentationLink ( ) , DocumentationExcerpt ) ;
}
TSharedRef < SButton > AddPinButton = SNew ( SButton )
. ContentPadding ( 0.0f )
. ButtonStyle ( FEditorStyle : : Get ( ) , " NoBorder " )
. OnClicked ( this , & SGraphNode : : OnAddPin )
. ToolTipText ( PinTooltipText )
. ToolTip ( Tooltip )
. Visibility ( this , & SGraphNode : : IsAddPinButtonVisible )
[
ButtonContent . ToSharedRef ( )
] ;
AddPinButton - > SetCursor ( EMouseCursor : : Hand ) ;
return AddPinButton ;
}
EVisibility SGraphNode : : IsAddPinButtonVisible ( ) const
{
bool bIsHidden = false ;
auto OwnerGraphPanel = OwnerGraphPanelPtr . Pin ( ) ;
if ( OwnerGraphPanel . IsValid ( ) )
{
bIsHidden | = ( SGraphEditor : : EPinVisibility : : Pin_Show ! = OwnerGraphPanel - > GetPinVisibility ( ) ) ;
bIsHidden | = ( OwnerGraphPanel - > GetCurrentLOD ( ) < = EGraphRenderingLOD : : LowDetail ) ;
}
return bIsHidden ? EVisibility : : Collapsed : EVisibility : : Visible ;
}