2020-12-14 08:58:12 -04:00
// Copyright Epic Games, Inc. All Rights Reserved.
# include "ControlRigGraphDetails.h"
# include "Widgets/SWidget.h"
# include "DetailLayoutBuilder.h"
# include "DetailCategoryBuilder.h"
# include "DetailWidgetRow.h"
# include "IDetailChildrenBuilder.h"
# include "EditorStyleSet.h"
# include "SPinTypeSelector.h"
# include "Widgets/Input/SButton.h"
2021-03-03 14:44:58 -04:00
# include "Widgets/Input/SCheckBox.h"
2020-12-14 08:58:12 -04:00
# include "Widgets/Text/STextBlock.h"
2021-01-27 05:06:20 -04:00
# include "Widgets/Colors/SColorPicker.h"
# include "Widgets/Text/SInlineEditableTextBlock.h"
2021-06-08 12:10:13 -04:00
# include "Widgets/Text/SMultiLineEditableText.h"
2020-12-14 08:58:12 -04:00
# include "PropertyCustomizationHelpers.h"
# include "NodeFactory.h"
# include "Graph/ControlRigGraphNode.h"
# include "ControlRig.h"
# include "RigVMCore/RigVMExternalVariable.h"
# include "Kismet2/BlueprintEditorUtils.h"
2021-06-16 08:03:04 -04:00
# include "Graph/ControlRigGraphSchema.h"
2021-06-21 04:52:59 -04:00
# include "EditorCategoryUtils.h"
2021-08-05 11:08:05 -04:00
# include "IPropertyUtilities.h"
2021-11-03 07:53:40 -04:00
# include "Graph/SControlRigGraphPinVariableBinding.h"
2020-12-14 08:58:12 -04:00
# define LOCTEXT_NAMESPACE "ControlRigGraphDetails"
2021-01-14 15:00:40 -04:00
FControlRigArgumentGroupLayout : : FControlRigArgumentGroupLayout (
URigVMGraph * InGraph ,
UControlRigBlueprint * InBlueprint ,
2021-11-23 04:59:08 -05:00
TWeakPtr < IControlRigEditor > InEditor ,
2021-01-14 15:00:40 -04:00
bool bInputs )
2020-12-14 08:58:12 -04:00
: GraphPtr ( InGraph )
, ControlRigBlueprintPtr ( InBlueprint )
2021-11-23 04:59:08 -05:00
, ControlRigEditorPtr ( InEditor )
2020-12-14 08:58:12 -04:00
, bIsInputGroup ( bInputs )
{
if ( ControlRigBlueprintPtr . IsValid ( ) )
{
ControlRigBlueprintPtr . Get ( ) - > OnModified ( ) . AddRaw ( this , & FControlRigArgumentGroupLayout : : HandleModifiedEvent ) ;
}
}
FControlRigArgumentGroupLayout : : ~ FControlRigArgumentGroupLayout ( )
{
if ( ControlRigBlueprintPtr . IsValid ( ) )
{
ControlRigBlueprintPtr . Get ( ) - > OnModified ( ) . RemoveAll ( this ) ;
}
}
void FControlRigArgumentGroupLayout : : GenerateChildContent ( IDetailChildrenBuilder & ChildrenBuilder )
{
bool WasContentAdded = false ;
if ( GraphPtr . IsValid ( ) )
{
URigVMGraph * Graph = GraphPtr . Get ( ) ;
if ( URigVMLibraryNode * LibraryNode = Cast < URigVMLibraryNode > ( Graph - > GetOuter ( ) ) )
{
for ( URigVMPin * Pin : LibraryNode - > GetPins ( ) )
{
if ( ( bIsInputGroup & & ( Pin - > GetDirection ( ) = = ERigVMPinDirection : : Input | | Pin - > GetDirection ( ) = = ERigVMPinDirection : : IO ) ) | |
( ! bIsInputGroup & & ( Pin - > GetDirection ( ) = = ERigVMPinDirection : : Output | | Pin - > GetDirection ( ) = = ERigVMPinDirection : : IO ) ) )
{
TSharedRef < class FControlRigArgumentLayout > ControlRigArgumentLayout = MakeShareable ( new FControlRigArgumentLayout (
Pin ,
Graph ,
2021-11-23 04:59:08 -05:00
ControlRigBlueprintPtr . Get ( ) ,
ControlRigEditorPtr
2021-01-14 15:00:40 -04:00
) ) ;
2020-12-14 08:58:12 -04:00
ChildrenBuilder . AddCustomBuilder ( ControlRigArgumentLayout ) ;
WasContentAdded = true ;
}
}
}
}
if ( ! WasContentAdded )
{
// Add a text widget to let the user know to hit the + icon to add parameters.
ChildrenBuilder . AddCustomRow ( FText : : GetEmpty ( ) ) . WholeRowContent ( )
. MaxDesiredWidth ( 980.f )
[
SNew ( SHorizontalBox )
+ SHorizontalBox : : Slot ( )
. VAlign ( VAlign_Center )
. Padding ( 0.0f , 0.0f , 4.0f , 0.0f )
. AutoWidth ( )
[
SNew ( STextBlock )
. Text ( LOCTEXT ( " NoArgumentsAddedForControlRig " , " Please press the + icon above to add parameters " ) )
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
]
] ;
}
}
void FControlRigArgumentGroupLayout : : HandleModifiedEvent ( ERigVMGraphNotifType InNotifType , URigVMGraph * InGraph , UObject * InSubject )
{
if ( ! GraphPtr . IsValid ( ) )
{
return ;
}
URigVMGraph * Graph = GraphPtr . Get ( ) ;
URigVMLibraryNode * LibraryNode = Cast < URigVMLibraryNode > ( Graph - > GetOuter ( ) ) ;
if ( LibraryNode = = nullptr )
{
return ;
}
switch ( InNotifType )
{
case ERigVMGraphNotifType : : PinAdded :
case ERigVMGraphNotifType : : PinRemoved :
2021-01-21 04:38:23 -04:00
case ERigVMGraphNotifType : : PinIndexChanged :
2021-12-02 11:44:22 -05:00
case ERigVMGraphNotifType : : PinTypeChanged :
2020-12-14 08:58:12 -04:00
{
URigVMPin * Pin = CastChecked < URigVMPin > ( InSubject ) ;
if ( Pin - > GetNode ( ) = = LibraryNode )
{
OnRebuildChildren . ExecuteIfBound ( ) ;
}
break ;
}
default :
{
break ;
}
}
}
2021-12-02 11:44:22 -05:00
class FControlRigArgumentPinTypeSelectorFilter : public IPinTypeSelectorFilter
{
public :
FControlRigArgumentPinTypeSelectorFilter ( TWeakPtr < IControlRigEditor > InControlRigEditor , TWeakObjectPtr < URigVMGraph > InGraph )
: ControlRigEditorPtr ( InControlRigEditor ) , GraphPtr ( InGraph )
{
}
virtual bool ShouldShowPinTypeTreeItem ( FPinTypeTreeItem InItem ) const override
{
if ( ! InItem . IsValid ( ) )
{
return false ;
}
// Only allow an execute context pin if the graph doesnt have one already
FString CPPType ;
UObject * CPPTypeObject = nullptr ;
RigVMTypeUtils : : CPPTypeFromPinType ( InItem . Get ( ) - > GetPinType ( false ) , CPPType , & CPPTypeObject ) ;
if ( UScriptStruct * ScriptStruct = Cast < UScriptStruct > ( CPPTypeObject ) )
{
if ( ScriptStruct - > IsChildOf ( FRigVMExecuteContext : : StaticStruct ( ) ) )
{
if ( GraphPtr . IsValid ( ) )
{
if ( URigVMFunctionEntryNode * EntryNode = GraphPtr . Get ( ) - > GetEntryNode ( ) )
{
for ( URigVMPin * Pin : EntryNode - > GetPins ( ) )
{
if ( Pin - > IsExecuteContext ( ) )
{
return false ;
}
}
}
}
}
}
if ( ControlRigEditorPtr . IsValid ( ) )
{
if ( ControlRigEditorPtr . Pin ( ) - > GetImportedPinTypeSelectorFilter ( ) . IsValid ( ) )
{
return ControlRigEditorPtr . Pin ( ) - > GetImportedPinTypeSelectorFilter ( ) - > ShouldShowPinTypeTreeItem ( InItem ) ;
}
}
return false ;
}
private :
TWeakPtr < IControlRigEditor > ControlRigEditorPtr ;
TWeakObjectPtr < URigVMGraph > GraphPtr ;
} ;
2020-12-14 08:58:12 -04:00
void FControlRigArgumentLayout : : GenerateHeaderRowContent ( FDetailWidgetRow & NodeRow )
{
2021-06-16 08:03:04 -04:00
const UEdGraphSchema * Schema = GetDefault < UControlRigGraphSchema > ( ) ;
2020-12-14 08:58:12 -04:00
ETypeTreeFilter TypeTreeFilter = ETypeTreeFilter : : None ;
TypeTreeFilter | = ETypeTreeFilter : : AllowExec ;
2021-11-23 04:59:08 -05:00
TSharedPtr < IPinTypeSelectorFilter > CustomPinTypeFilter ;
if ( ControlRigEditorPtr . IsValid ( ) )
{
2021-12-02 11:44:22 -05:00
CustomPinTypeFilter = MakeShared < FControlRigArgumentPinTypeSelectorFilter > ( ControlRigEditorPtr , GraphPtr ) ;
2021-11-23 04:59:08 -05:00
}
2020-12-14 08:58:12 -04:00
NodeRow
2021-01-14 15:00:40 -04:00
. NameContent ( )
[
SNew ( SHorizontalBox )
+ SHorizontalBox : : Slot ( )
2021-06-16 08:03:04 -04:00
. FillWidth ( 1 )
. VAlign ( VAlign_Center )
[
SAssignNew ( ArgumentNameWidget , SEditableTextBox )
. Text ( this , & FControlRigArgumentLayout : : OnGetArgNameText )
. OnTextCommitted ( this , & FControlRigArgumentLayout : : OnArgNameTextCommitted )
. ToolTipText ( this , & FControlRigArgumentLayout : : OnGetArgToolTipText )
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
. IsEnabled ( ! ShouldPinBeReadOnly ( ) )
2021-09-15 10:41:20 -04:00
. OnVerifyTextChanged_Lambda ( [ & ] ( const FText & InNewText , FText & OutErrorMessage ) - > bool
{
if ( InNewText . IsEmpty ( ) )
{
OutErrorMessage = LOCTEXT ( " ArgumentNameEmpty " , " Cannot have an argument with an emtpy string name. " ) ;
return false ;
}
else if ( InNewText . ToString ( ) . Len ( ) > = NAME_SIZE )
{
OutErrorMessage = LOCTEXT ( " ArgumentNameTooLong " , " Name of argument is too long. " ) ;
return false ;
}
2021-09-27 11:50:32 -04:00
EValidatorResult Result = NameValidator . IsValid ( InNewText . ToString ( ) , false ) ;
OutErrorMessage = INameValidatorInterface : : GetErrorText ( InNewText . ToString ( ) , Result ) ;
return Result = = EValidatorResult : : Ok | | Result = = EValidatorResult : : ExistingName ;
2021-09-15 10:41:20 -04:00
} )
2021-06-16 08:03:04 -04:00
]
2021-01-14 15:00:40 -04:00
]
2021-06-16 08:03:04 -04:00
. ValueContent ( )
2021-01-14 15:00:40 -04:00
. MaxDesiredWidth ( 980.f )
[
SNew ( SHorizontalBox )
+ SHorizontalBox : : Slot ( )
2021-06-16 08:03:04 -04:00
. VAlign ( VAlign_Center )
. Padding ( 0.0f , 0.0f , 4.0f , 0.0f )
. AutoWidth ( )
[
SNew ( SPinTypeSelector , FGetPinTypeTree : : CreateUObject ( GetDefault < UEdGraphSchema_K2 > ( ) , & UEdGraphSchema_K2 : : GetVariableTypeTree ) )
. TargetPinType ( this , & FControlRigArgumentLayout : : OnGetPinInfo )
. OnPinTypePreChanged ( this , & FControlRigArgumentLayout : : OnPrePinInfoChange )
. OnPinTypeChanged ( this , & FControlRigArgumentLayout : : PinInfoChanged )
. Schema ( Schema )
. TypeTreeFilter ( TypeTreeFilter )
. bAllowArrays ( ! ShouldPinBeReadOnly ( ) )
. IsEnabled ( ! ShouldPinBeReadOnly ( true ) )
2021-11-23 04:59:08 -05:00
. CustomFilter ( CustomPinTypeFilter )
2021-06-16 08:03:04 -04:00
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
]
+ SHorizontalBox : : Slot ( )
. AutoWidth ( )
[
SNew ( SButton )
. ButtonStyle ( FAppStyle : : Get ( ) , TEXT ( " SimpleButton " ) )
. ContentPadding ( 0 )
. IsEnabled ( ! IsPinEditingReadOnly ( ) )
. OnClicked ( this , & FControlRigArgumentLayout : : OnArgMoveUp )
. ToolTipText ( LOCTEXT ( " FunctionArgDetailsArgMoveUpTooltip " , " Move this parameter up in the list. " ) )
[
SNew ( SImage )
. Image ( FEditorStyle : : GetBrush ( " Icons.ChevronUp " ) )
. ColorAndOpacity ( FSlateColor : : UseForeground ( ) )
]
]
+ SHorizontalBox : : Slot ( )
. AutoWidth ( )
. Padding ( 2 , 0 )
[
SNew ( SButton )
. ButtonStyle ( FAppStyle : : Get ( ) , TEXT ( " SimpleButton " ) )
. ContentPadding ( 0 )
. IsEnabled ( ! IsPinEditingReadOnly ( ) )
. OnClicked ( this , & FControlRigArgumentLayout : : OnArgMoveDown )
. ToolTipText ( LOCTEXT ( " FunctionArgDetailsArgMoveDownTooltip " , " Move this parameter down in the list. " ) )
[
SNew ( SImage )
. Image ( FEditorStyle : : GetBrush ( " Icons.ChevronDown " ) )
. ColorAndOpacity ( FSlateColor : : UseForeground ( ) )
]
]
+ SHorizontalBox : : Slot ( )
. HAlign ( HAlign_Right )
. VAlign ( VAlign_Center )
. Padding ( 10 , 0 , 0 , 0 )
. AutoWidth ( )
[
PropertyCustomizationHelpers : : MakeClearButton ( FSimpleDelegate : : CreateSP ( this , & FControlRigArgumentLayout : : OnRemoveClicked ) , LOCTEXT ( " FunctionArgDetailsClearTooltip " , " Remove this parameter. " ) , ! IsPinEditingReadOnly ( ) )
]
2021-01-14 15:00:40 -04:00
] ;
2020-12-14 08:58:12 -04:00
}
void FControlRigArgumentLayout : : GenerateChildContent ( IDetailChildrenBuilder & ChildrenBuilder )
{
2021-01-14 15:00:40 -04:00
// we don't show defaults here - we rely on a SControlRigGraphNode widget in the top of the details
2020-12-14 08:58:12 -04:00
}
void FControlRigArgumentLayout : : OnRemoveClicked ( )
{
if ( PinPtr . IsValid ( ) & & ControlRigBlueprintPtr . IsValid ( ) )
{
URigVMPin * Pin = PinPtr . Get ( ) ;
UControlRigBlueprint * Blueprint = ControlRigBlueprintPtr . Get ( ) ;
if ( URigVMLibraryNode * LibraryNode = Cast < URigVMLibraryNode > ( Pin - > GetNode ( ) ) )
{
if ( URigVMController * Controller = Blueprint - > GetController ( LibraryNode - > GetContainedGraph ( ) ) )
{
2021-07-19 06:35:29 -04:00
Controller - > RemoveExposedPin ( Pin - > GetFName ( ) , true , true ) ;
2020-12-14 08:58:12 -04:00
}
}
}
}
FReply FControlRigArgumentLayout : : OnArgMoveUp ( )
{
2021-01-21 04:38:23 -04:00
if ( PinPtr . IsValid ( ) & & ControlRigBlueprintPtr . IsValid ( ) )
2020-12-14 08:58:12 -04:00
{
2021-01-21 04:38:23 -04:00
URigVMPin * Pin = PinPtr . Get ( ) ;
UControlRigBlueprint * Blueprint = ControlRigBlueprintPtr . Get ( ) ;
if ( URigVMLibraryNode * LibraryNode = Cast < URigVMLibraryNode > ( Pin - > GetNode ( ) ) )
2020-12-14 08:58:12 -04:00
{
2021-01-21 04:38:23 -04:00
if ( URigVMController * Controller = Blueprint - > GetController ( LibraryNode - > GetContainedGraph ( ) ) )
2020-12-14 08:58:12 -04:00
{
2021-09-27 11:33:19 -04:00
bool bIsInput = Pin - > GetDirection ( ) = = ERigVMPinDirection : : Input | | Pin - > GetDirection ( ) = = ERigVMPinDirection : : IO ;
int32 NewPinIndex = Pin - > GetPinIndex ( ) - 1 ;
while ( NewPinIndex ! = INDEX_NONE )
{
URigVMPin * OtherPin = LibraryNode - > GetPins ( ) [ NewPinIndex ] ;
if ( bIsInput )
{
if ( OtherPin - > GetDirection ( ) = = ERigVMPinDirection : : Input | | OtherPin - > GetDirection ( ) = = ERigVMPinDirection : : IO )
{
break ;
}
}
else
{
if ( OtherPin - > GetDirection ( ) = = ERigVMPinDirection : : Output | | OtherPin - > GetDirection ( ) = = ERigVMPinDirection : : IO )
{
break ;
}
}
- - NewPinIndex ;
}
if ( NewPinIndex ! = INDEX_NONE )
{
Controller - > SetExposedPinIndex ( Pin - > GetFName ( ) , NewPinIndex , true , true ) ;
}
2021-01-21 04:38:23 -04:00
return FReply : : Handled ( ) ;
2020-12-14 08:58:12 -04:00
}
}
}
2021-01-21 04:38:23 -04:00
return FReply : : Unhandled ( ) ;
2020-12-14 08:58:12 -04:00
}
FReply FControlRigArgumentLayout : : OnArgMoveDown ( )
{
2021-01-21 04:38:23 -04:00
if ( PinPtr . IsValid ( ) & & ControlRigBlueprintPtr . IsValid ( ) )
2020-12-14 08:58:12 -04:00
{
2021-01-21 04:38:23 -04:00
URigVMPin * Pin = PinPtr . Get ( ) ;
UControlRigBlueprint * Blueprint = ControlRigBlueprintPtr . Get ( ) ;
if ( URigVMLibraryNode * LibraryNode = Cast < URigVMLibraryNode > ( Pin - > GetNode ( ) ) )
2020-12-14 08:58:12 -04:00
{
2021-01-21 04:38:23 -04:00
if ( URigVMController * Controller = Blueprint - > GetController ( LibraryNode - > GetContainedGraph ( ) ) )
2020-12-14 08:58:12 -04:00
{
2021-09-27 11:33:19 -04:00
bool bIsInput = Pin - > GetDirection ( ) = = ERigVMPinDirection : : Input | | Pin - > GetDirection ( ) = = ERigVMPinDirection : : IO ;
int32 NewPinIndex = Pin - > GetPinIndex ( ) + 1 ;
while ( NewPinIndex < LibraryNode - > GetPins ( ) . Num ( ) )
{
URigVMPin * OtherPin = LibraryNode - > GetPins ( ) [ NewPinIndex ] ;
if ( bIsInput )
{
if ( OtherPin - > GetDirection ( ) = = ERigVMPinDirection : : Input | | OtherPin - > GetDirection ( ) = = ERigVMPinDirection : : IO )
{
break ;
}
}
else
{
if ( OtherPin - > GetDirection ( ) = = ERigVMPinDirection : : Output | | OtherPin - > GetDirection ( ) = = ERigVMPinDirection : : IO )
{
break ;
}
}
+ + NewPinIndex ;
}
if ( NewPinIndex < LibraryNode - > GetPins ( ) . Num ( ) )
{
Controller - > SetExposedPinIndex ( Pin - > GetFName ( ) , NewPinIndex , true , true ) ;
}
2021-01-21 04:38:23 -04:00
return FReply : : Handled ( ) ;
2020-12-14 08:58:12 -04:00
}
}
}
2021-01-21 04:38:23 -04:00
return FReply : : Unhandled ( ) ;
2020-12-14 08:58:12 -04:00
}
bool FControlRigArgumentLayout : : ShouldPinBeReadOnly ( bool bIsEditingPinType /* = false*/ ) const
{
2021-01-14 15:00:40 -04:00
return IsPinEditingReadOnly ( bIsEditingPinType ) ;
2020-12-14 08:58:12 -04:00
}
bool FControlRigArgumentLayout : : IsPinEditingReadOnly ( bool bIsEditingPinType /* = false*/ ) const
{
2021-01-14 15:00:40 -04:00
/*
2020-12-14 08:58:12 -04:00
if ( PinPtr . IsValid ( ) )
{
return PinPtr . Get ( ) - > IsExecuteContext ( ) ;
}
2021-01-14 15:00:40 -04:00
*/
2020-12-14 08:58:12 -04:00
return false ;
}
FText FControlRigArgumentLayout : : OnGetArgNameText ( ) const
{
if ( PinPtr . IsValid ( ) )
{
return FText : : FromName ( PinPtr . Get ( ) - > GetFName ( ) ) ;
}
return FText ( ) ;
}
FText FControlRigArgumentLayout : : OnGetArgToolTipText ( ) const
{
return OnGetArgNameText ( ) ; // for now since we don't have tooltips
}
void FControlRigArgumentLayout : : OnArgNameTextCommitted ( const FText & NewText , ETextCommit : : Type InTextCommit )
{
if ( ! NewText . IsEmpty ( ) & & PinPtr . IsValid ( ) & & ControlRigBlueprintPtr . IsValid ( ) & & ! ShouldPinBeReadOnly ( ) )
{
URigVMPin * Pin = PinPtr . Get ( ) ;
UControlRigBlueprint * Blueprint = ControlRigBlueprintPtr . Get ( ) ;
if ( URigVMLibraryNode * LibraryNode = Cast < URigVMLibraryNode > ( Pin - > GetNode ( ) ) )
{
if ( URigVMController * Controller = Blueprint - > GetController ( LibraryNode - > GetContainedGraph ( ) ) )
{
const FString & NewName = NewText . ToString ( ) ;
2021-07-19 06:35:29 -04:00
Controller - > RenameExposedPin ( Pin - > GetFName ( ) , * NewName , true , true ) ;
2020-12-14 08:58:12 -04:00
}
}
}
}
FEdGraphPinType FControlRigArgumentLayout : : OnGetPinInfo ( ) const
{
if ( PinPtr . IsValid ( ) )
{
return UControlRigGraphNode : : GetPinTypeForModelPin ( PinPtr . Get ( ) ) ;
}
return FEdGraphPinType ( ) ;
}
void FControlRigArgumentLayout : : PinInfoChanged ( const FEdGraphPinType & PinType )
{
if ( PinPtr . IsValid ( ) & & ControlRigBlueprintPtr . IsValid ( ) & & FBlueprintEditorUtils : : IsPinTypeValid ( PinType ) )
{
URigVMPin * Pin = PinPtr . Get ( ) ;
UControlRigBlueprint * Blueprint = ControlRigBlueprintPtr . Get ( ) ;
if ( URigVMLibraryNode * LibraryNode = Cast < URigVMLibraryNode > ( Pin - > GetNode ( ) ) )
{
if ( URigVMController * Controller = Blueprint - > GetController ( LibraryNode - > GetContainedGraph ( ) ) )
{
2021-12-02 11:44:22 -05:00
FString CPPType ;
2020-12-14 08:58:12 -04:00
FName CPPTypeObjectName = NAME_None ;
2021-12-02 11:44:22 -05:00
RigVMTypeUtils : : CPPTypeFromPinType ( PinType , CPPType , CPPTypeObjectName ) ;
2021-05-25 06:55:47 -04:00
bool bSetupUndoRedo = true ;
2021-09-27 11:50:32 -04:00
Controller - > ChangeExposedPinType ( Pin - > GetFName ( ) , CPPType , CPPTypeObjectName , bSetupUndoRedo , false , true ) ;
2021-05-25 06:55:47 -04:00
// If the controller has identified this as a bulk change, it has not added the actions to the action stack
// We need to disable the transaction from the UI as well to keep them synced
if ( ! bSetupUndoRedo )
{
GEditor - > CancelTransaction ( 0 ) ;
}
2020-12-14 08:58:12 -04:00
}
}
}
}
void FControlRigArgumentLayout : : OnPrePinInfoChange ( const FEdGraphPinType & PinType )
{
// not needed for Control Rig
}
2021-01-14 15:00:40 -04:00
FControlRigArgumentDefaultNode : : FControlRigArgumentDefaultNode (
URigVMGraph * InGraph ,
UControlRigBlueprint * InBlueprint
)
: GraphPtr ( InGraph )
, ControlRigBlueprintPtr ( InBlueprint )
{
if ( GraphPtr . IsValid ( ) & & ControlRigBlueprintPtr . IsValid ( ) )
{
ControlRigBlueprintPtr . Get ( ) - > OnModified ( ) . AddRaw ( this , & FControlRigArgumentDefaultNode : : HandleModifiedEvent ) ;
if ( URigVMLibraryNode * LibraryNode = Cast < URigVMLibraryNode > ( GraphPtr - > GetOuter ( ) ) )
{
if ( UControlRigGraph * RigGraph = Cast < UControlRigGraph > ( ControlRigBlueprintPtr - > GetEdGraph ( LibraryNode - > GetGraph ( ) ) ) )
{
GraphChangedDelegateHandle = RigGraph - > AddOnGraphChangedHandler (
FOnGraphChanged : : FDelegate : : CreateRaw ( this , & FControlRigArgumentDefaultNode : : OnGraphChanged )
) ;
}
}
}
}
FControlRigArgumentDefaultNode : : ~ FControlRigArgumentDefaultNode ( )
{
if ( GraphPtr . IsValid ( ) & & ControlRigBlueprintPtr . IsValid ( ) )
{
ControlRigBlueprintPtr . Get ( ) - > OnModified ( ) . RemoveAll ( this ) ;
if ( URigVMLibraryNode * LibraryNode = Cast < URigVMLibraryNode > ( GraphPtr - > GetOuter ( ) ) )
{
if ( UControlRigGraph * RigGraph = Cast < UControlRigGraph > ( ControlRigBlueprintPtr - > GetEdGraph ( LibraryNode - > GetGraph ( ) ) ) )
{
if ( GraphChangedDelegateHandle . IsValid ( ) )
{
RigGraph - > RemoveOnGraphChangedHandler ( GraphChangedDelegateHandle ) ;
}
}
}
}
}
void FControlRigArgumentDefaultNode : : GenerateChildContent ( IDetailChildrenBuilder & ChildrenBuilder )
{
if ( ! GraphPtr . IsValid ( ) | | ! ControlRigBlueprintPtr . IsValid ( ) )
{
return ;
}
UControlRigBlueprint * Blueprint = ControlRigBlueprintPtr . Get ( ) ;
URigVMGraph * Graph = GraphPtr . Get ( ) ;
UControlRigGraphNode * ControlRigGraphNode = nullptr ;
if ( URigVMLibraryNode * LibraryNode = Cast < URigVMLibraryNode > ( Graph - > GetOuter ( ) ) )
{
if ( UControlRigGraph * RigGraph = Cast < UControlRigGraph > ( Blueprint - > GetEdGraph ( LibraryNode - > GetGraph ( ) ) ) )
{
ControlRigGraphNode = Cast < UControlRigGraphNode > ( RigGraph - > FindNodeForModelNodeName ( LibraryNode - > GetFName ( ) ) ) ;
}
}
if ( ControlRigGraphNode = = nullptr )
{
return ;
}
ChildrenBuilder . AddCustomRow ( FText : : GetEmpty ( ) )
. WholeRowContent ( )
. MaxDesiredWidth ( 980.f )
[
SAssignNew ( OwnedNodeWidget , SControlRigGraphNode ) . GraphNodeObj ( ControlRigGraphNode )
] ;
2021-10-29 08:03:06 -04:00
OwnedNodeWidget - > SetIsEditable ( true ) ;
TArray < TSharedRef < SWidget > > Pins ;
OwnedNodeWidget - > GetPins ( Pins ) ;
for ( TSharedRef < SWidget > Pin : Pins )
{
TSharedRef < SGraphPin > SPin = StaticCastSharedRef < SGraphPin > ( Pin ) ;
SPin - > GetPinObj ( ) - > bNotConnectable = true ;
}
2021-01-14 15:00:40 -04:00
}
void FControlRigArgumentDefaultNode : : OnGraphChanged ( const FEdGraphEditAction & InAction )
{
2021-01-19 04:57:43 -04:00
if ( GraphPtr . IsValid ( ) & & ControlRigBlueprintPtr . IsValid ( ) )
{
OnRebuildChildren . ExecuteIfBound ( ) ;
}
2021-01-14 15:00:40 -04:00
}
void FControlRigArgumentDefaultNode : : HandleModifiedEvent ( ERigVMGraphNotifType InNotifType , URigVMGraph * InGraph , UObject * InSubject )
{
if ( ! GraphPtr . IsValid ( ) )
{
return ;
}
URigVMGraph * Graph = GraphPtr . Get ( ) ;
URigVMLibraryNode * LibraryNode = Cast < URigVMLibraryNode > ( Graph - > GetOuter ( ) ) ;
if ( LibraryNode = = nullptr )
{
return ;
}
if ( LibraryNode - > GetGraph ( ) ! = InGraph )
{
return ;
}
switch ( InNotifType )
{
case ERigVMGraphNotifType : : PinAdded :
case ERigVMGraphNotifType : : PinRemoved :
case ERigVMGraphNotifType : : PinTypeChanged :
2021-01-21 04:38:23 -04:00
case ERigVMGraphNotifType : : PinIndexChanged :
2021-01-14 15:00:40 -04:00
case ERigVMGraphNotifType : : PinRenamed :
{
URigVMPin * Pin = CastChecked < URigVMPin > ( InSubject ) ;
if ( Pin - > GetNode ( ) = = LibraryNode )
{
OnRebuildChildren . ExecuteIfBound ( ) ;
}
break ;
}
case ERigVMGraphNotifType : : NodeRenamed :
2021-01-27 05:06:20 -04:00
case ERigVMGraphNotifType : : NodeColorChanged :
2021-01-14 15:00:40 -04:00
{
URigVMNode * Node = CastChecked < URigVMNode > ( InSubject ) ;
if ( Node = = LibraryNode )
{
OnRebuildChildren . ExecuteIfBound ( ) ;
}
break ;
}
default :
{
break ;
}
}
}
2020-12-14 08:58:12 -04:00
TSharedPtr < IDetailCustomization > FControlRigGraphDetails : : MakeInstance ( TSharedPtr < IBlueprintEditor > InBlueprintEditor )
{
const TArray < UObject * > * Objects = ( InBlueprintEditor . IsValid ( ) ? InBlueprintEditor - > GetObjectsCurrentlyBeingEdited ( ) : nullptr ) ;
if ( Objects & & Objects - > Num ( ) = = 1 )
{
if ( UControlRigBlueprint * ControlRigBlueprint = Cast < UControlRigBlueprint > ( ( * Objects ) [ 0 ] ) )
{
return MakeShareable ( new FControlRigGraphDetails ( StaticCastSharedPtr < IControlRigEditor > ( InBlueprintEditor ) , ControlRigBlueprint ) ) ;
}
}
return nullptr ;
}
void FControlRigGraphDetails : : CustomizeDetails ( IDetailLayoutBuilder & DetailLayout )
{
2021-01-27 05:06:20 -04:00
bIsPickingColor = false ;
2020-12-14 08:58:12 -04:00
TArray < TWeakObjectPtr < UObject > > Objects ;
DetailLayout . GetObjectsBeingCustomized ( Objects ) ;
GraphPtr = CastChecked < UControlRigGraph > ( Objects [ 0 ] . Get ( ) ) ;
UControlRigGraph * Graph = GraphPtr . Get ( ) ;
UControlRigBlueprint * Blueprint = ControlRigBlueprintPtr . Get ( ) ;
URigVMGraph * Model = nullptr ;
URigVMController * Controller = nullptr ;
if ( Blueprint )
{
Model = Blueprint - > GetModel ( Graph ) ;
Controller = Blueprint - > GetController ( Model ) ;
}
if ( Blueprint = = nullptr | | Model = = nullptr | | Controller = = nullptr )
{
IDetailCategoryBuilder & Category = DetailLayout . EditCategory ( " Graph " , LOCTEXT ( " FunctionDetailsGraph " , " Graph " ) ) ;
Category . AddCustomRow ( FText : : GetEmpty ( ) )
[
SNew ( STextBlock )
. Text ( LOCTEXT ( " GraphPresentButNotEditable " , " Graph is not editable. " ) )
] ;
return ;
}
if ( Model - > IsTopLevelGraph ( ) )
{
IDetailCategoryBuilder & Category = DetailLayout . EditCategory ( " Graph " , LOCTEXT ( " FunctionDetailsGraph " , " Graph " ) ) ;
Category . AddCustomRow ( FText : : GetEmpty ( ) )
[
SNew ( STextBlock )
. Text ( LOCTEXT ( " GraphIsTopLevelGraph " , " Top-level Graphs are not editable. " ) )
] ;
return ;
}
IDetailCategoryBuilder & InputsCategory = DetailLayout . EditCategory ( " Inputs " , LOCTEXT ( " FunctionDetailsInputs " , " Inputs " ) ) ;
2021-01-14 15:00:40 -04:00
TSharedRef < FControlRigArgumentGroupLayout > InputArgumentGroup = MakeShareable ( new FControlRigArgumentGroupLayout (
Model ,
2021-11-23 04:59:08 -05:00
Blueprint ,
ControlRigEditorPtr ,
2021-01-14 15:00:40 -04:00
true ) ) ;
2020-12-14 08:58:12 -04:00
InputsCategory . AddCustomBuilder ( InputArgumentGroup ) ;
TSharedRef < SHorizontalBox > InputsHeaderContentWidget = SNew ( SHorizontalBox ) ;
InputsHeaderContentWidget - > AddSlot ( )
. HAlign ( HAlign_Right )
[
SNew ( SButton )
. ButtonStyle ( FEditorStyle : : Get ( ) , " SimpleButton " )
. ContentPadding ( FMargin ( 1 , 0 ) )
. OnClicked ( this , & FControlRigGraphDetails : : OnAddNewInputClicked )
. Visibility ( this , & FControlRigGraphDetails : : GetAddNewInputOutputVisibility )
. HAlign ( HAlign_Right )
. ToolTipText ( LOCTEXT ( " FunctionNewInputArgTooltip " , " Create a new input argument " ) )
. VAlign ( VAlign_Center )
. AddMetaData < FTagMetaData > ( FTagMetaData ( TEXT ( " FunctionNewInputArg " ) ) )
. IsEnabled ( this , & FControlRigGraphDetails : : IsAddNewInputOutputEnabled )
[
SNew ( SImage )
. Image ( FAppStyle : : Get ( ) . GetBrush ( " Icons.PlusCircle " ) )
. ColorAndOpacity ( FSlateColor : : UseForeground ( ) )
]
] ;
InputsCategory . HeaderContent ( InputsHeaderContentWidget ) ;
IDetailCategoryBuilder & OutputsCategory = DetailLayout . EditCategory ( " Outputs " , LOCTEXT ( " FunctionDetailsOutputs " , " Outputs " ) ) ;
2021-01-14 15:00:40 -04:00
TSharedRef < FControlRigArgumentGroupLayout > OutputArgumentGroup = MakeShareable ( new FControlRigArgumentGroupLayout (
Model ,
2021-11-23 04:59:08 -05:00
Blueprint ,
ControlRigEditorPtr ,
2021-01-14 15:00:40 -04:00
false ) ) ;
2020-12-14 08:58:12 -04:00
OutputsCategory . AddCustomBuilder ( OutputArgumentGroup ) ;
TSharedRef < SHorizontalBox > OutputsHeaderContentWidget = SNew ( SHorizontalBox ) ;
OutputsHeaderContentWidget - > AddSlot ( )
. HAlign ( HAlign_Right )
[
SNew ( SButton )
. ButtonStyle ( FEditorStyle : : Get ( ) , " SimpleButton " )
. ContentPadding ( FMargin ( 1 , 0 ) )
. OnClicked ( this , & FControlRigGraphDetails : : OnAddNewOutputClicked )
. Visibility ( this , & FControlRigGraphDetails : : GetAddNewInputOutputVisibility )
. HAlign ( HAlign_Right )
. ToolTipText ( LOCTEXT ( " FunctionNewOutputArgTooltip " , " Create a new output argument " ) )
. VAlign ( VAlign_Center )
. AddMetaData < FTagMetaData > ( FTagMetaData ( TEXT ( " FunctionNewOutputArg " ) ) )
. IsEnabled ( this , & FControlRigGraphDetails : : IsAddNewInputOutputEnabled )
[
SNew ( SImage )
. Image ( FAppStyle : : Get ( ) . GetBrush ( " Icons.PlusCircle " ) )
. ColorAndOpacity ( FSlateColor : : UseForeground ( ) )
]
] ;
OutputsCategory . HeaderContent ( OutputsHeaderContentWidget ) ;
2021-01-14 15:00:40 -04:00
2021-01-27 05:06:20 -04:00
IDetailCategoryBuilder & SettingsCategory = DetailLayout . EditCategory ( " NodeSettings " , LOCTEXT ( " FunctionDetailsNodeSettings " , " Node Settings " ) ) ;
bool bIsFunction = false ;
if ( Model )
{
if ( URigVMLibraryNode * LibraryNode = Cast < URigVMLibraryNode > ( Model - > GetOuter ( ) ) )
{
bIsFunction = LibraryNode - > GetGraph ( ) - > IsA < URigVMFunctionLibrary > ( ) ;
}
}
if ( bIsFunction )
{
// node category
SettingsCategory . AddCustomRow ( FText : : GetEmpty ( ) )
. NameContent ( )
[
SNew ( STextBlock )
. Text ( FText : : FromString ( TEXT ( " Category " ) ) )
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
]
. ValueContent ( )
[
SNew ( SEditableTextBox )
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
. Text ( this , & FControlRigGraphDetails : : GetNodeCategory )
. OnTextCommitted ( this , & FControlRigGraphDetails : : SetNodeCategory )
2021-06-21 04:52:59 -04:00
. OnVerifyTextChanged_Lambda ( [ & ] ( const FText & InNewText , FText & OutErrorMessage ) - > bool
{
const FText NewText = FEditorCategoryUtils : : GetCategoryDisplayString ( InNewText ) ;
2021-09-27 10:16:28 -04:00
if ( NewText . ToString ( ) . Len ( ) > = NAME_SIZE )
2021-09-15 10:41:20 -04:00
{
OutErrorMessage = LOCTEXT ( " CategoryTooLong " , " Name of category is too long. " ) ;
return false ;
}
2021-06-21 04:52:59 -04:00
if ( ControlRigBlueprintPtr . IsValid ( ) )
{
if ( NewText . EqualTo ( FText : : FromString ( ControlRigBlueprintPtr . Get ( ) - > GetName ( ) ) ) )
{
OutErrorMessage = LOCTEXT ( " CategoryEqualsBlueprintName " , " Cannot add a category with the same name as the blueprint. " ) ;
return false ;
}
}
return true ;
} )
2021-01-27 05:06:20 -04:00
] ;
// node keywords
SettingsCategory . AddCustomRow ( FText : : GetEmpty ( ) )
. NameContent ( )
[
SNew ( STextBlock )
. Text ( FText : : FromString ( TEXT ( " Keywords " ) ) )
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
]
. ValueContent ( )
[
SNew ( SEditableTextBox )
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
. Text ( this , & FControlRigGraphDetails : : GetNodeKeywords )
. OnTextCommitted ( this , & FControlRigGraphDetails : : SetNodeKeywords )
] ;
2021-03-03 14:44:58 -04:00
2021-06-08 12:10:13 -04:00
// description
SettingsCategory . AddCustomRow ( FText : : GetEmpty ( ) )
. NameContent ( )
[
SNew ( STextBlock )
. Text ( FText : : FromString ( TEXT ( " Description " ) ) )
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
]
. ValueContent ( )
[
SNew ( SMultiLineEditableText )
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
. Text ( this , & FControlRigGraphDetails : : GetNodeDescription )
. OnTextCommitted ( this , & FControlRigGraphDetails : : SetNodeDescription )
] ;
2021-03-03 14:44:58 -04:00
if ( AccessSpecifierStrings . IsEmpty ( ) )
{
AccessSpecifierStrings . Add ( TSharedPtr < FString > ( new FString ( TEXT ( " Public " ) ) ) ) ;
AccessSpecifierStrings . Add ( TSharedPtr < FString > ( new FString ( TEXT ( " Private " ) ) ) ) ;
}
// access specifier
SettingsCategory . AddCustomRow ( LOCTEXT ( " AccessSpecifier " , " Access Specifier " ) )
. NameContent ( )
[
SNew ( STextBlock )
. Text ( LOCTEXT ( " AccessSpecifier " , " Access Specifier " ) )
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
]
. ValueContent ( )
[
SNew ( SComboButton )
. ContentPadding ( 0 )
. ButtonContent ( )
[
SNew ( STextBlock )
. Text ( this , & FControlRigGraphDetails : : GetCurrentAccessSpecifierName )
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
]
. MenuContent ( )
[
SNew ( SListView < TSharedPtr < FString > > )
. ListItemsSource ( & AccessSpecifierStrings )
. OnGenerateRow ( this , & FControlRigGraphDetails : : HandleGenerateRowAccessSpecifier )
. OnSelectionChanged ( this , & FControlRigGraphDetails : : OnAccessSpecifierSelected )
]
] ;
2021-01-27 05:06:20 -04:00
}
// node color
SettingsCategory . AddCustomRow ( FText : : GetEmpty ( ) )
. NameContent ( )
[
SNew ( STextBlock )
. Text ( FText : : FromString ( TEXT ( " Color " ) ) )
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
]
. ValueContent ( )
[
SNew ( SButton )
. ButtonStyle ( FEditorStyle : : Get ( ) , " Menu.Button " )
. OnClicked ( this , & FControlRigGraphDetails : : OnNodeColorClicked )
[
SAssignNew ( ColorBlock , SColorBlock )
. Color ( this , & FControlRigGraphDetails : : GetNodeColor )
. Size ( FVector2D ( 77 , 16 ) )
]
] ;
2021-01-14 15:00:40 -04:00
IDetailCategoryBuilder & DefaultsCategory = DetailLayout . EditCategory ( " NodeDefaults " , LOCTEXT ( " FunctionDetailsNodeDefaults " , " Node Defaults " ) ) ;
TSharedRef < FControlRigArgumentDefaultNode > DefaultsArgumentNode = MakeShareable ( new FControlRigArgumentDefaultNode (
Model ,
Blueprint ) ) ;
DefaultsCategory . AddCustomBuilder ( DefaultsArgumentNode ) ;
2020-12-14 08:58:12 -04:00
}
bool FControlRigGraphDetails : : IsAddNewInputOutputEnabled ( ) const
{
return true ;
}
EVisibility FControlRigGraphDetails : : GetAddNewInputOutputVisibility ( ) const
{
return EVisibility : : Visible ;
}
FReply FControlRigGraphDetails : : OnAddNewInputClicked ( )
{
if ( GraphPtr . IsValid ( ) & & ControlRigBlueprintPtr . IsValid ( ) )
{
UControlRigBlueprint * Blueprint = ControlRigBlueprintPtr . Get ( ) ;
URigVMGraph * Model = Blueprint - > GetModel ( GraphPtr . Get ( ) ) ;
if ( URigVMController * Controller = Blueprint - > GetController ( Model ) )
{
FName ArgumentName = TEXT ( " Argument " ) ;
FString CPPType = TEXT ( " bool " ) ;
FName CPPTypeObjectPath = NAME_None ;
FString DefaultValue = TEXT ( " False " ) ;
2021-01-25 12:13:27 -04:00
if ( URigVMLibraryNode * LibraryNode = Cast < URigVMLibraryNode > ( Model - > GetOuter ( ) ) )
{
if ( LibraryNode - > GetPins ( ) . Num ( ) > 0 )
{
URigVMPin * LastPin = LibraryNode - > GetPins ( ) . Last ( ) ;
if ( ! LastPin - > IsExecuteContext ( ) )
{
ArgumentName = LastPin - > GetFName ( ) ;
CPPType = LastPin - > GetCPPType ( ) ;
if ( LastPin - > GetCPPTypeObject ( ) )
{
CPPTypeObjectPath = * LastPin - > GetCPPTypeObject ( ) - > GetPathName ( ) ;
}
DefaultValue = LastPin - > GetDefaultValue ( ) ;
}
}
}
2020-12-14 08:58:12 -04:00
2021-07-19 06:35:29 -04:00
Controller - > AddExposedPin ( ArgumentName , ERigVMPinDirection : : Input , CPPType , CPPTypeObjectPath , DefaultValue , true , true ) ;
2020-12-14 08:58:12 -04:00
}
}
return FReply : : Unhandled ( ) ;
}
FReply FControlRigGraphDetails : : OnAddNewOutputClicked ( )
{
if ( GraphPtr . IsValid ( ) & & ControlRigBlueprintPtr . IsValid ( ) )
{
UControlRigBlueprint * Blueprint = ControlRigBlueprintPtr . Get ( ) ;
URigVMGraph * Model = Blueprint - > GetModel ( GraphPtr . Get ( ) ) ;
if ( URigVMController * Controller = Blueprint - > GetController ( Model ) )
{
FName ArgumentName = TEXT ( " Argument " ) ;
FString CPPType = TEXT ( " bool " ) ;
FName CPPTypeObjectPath = NAME_None ;
FString DefaultValue = TEXT ( " False " ) ;
// todo: base decisions on types on last argument
2021-07-19 06:35:29 -04:00
Controller - > AddExposedPin ( ArgumentName , ERigVMPinDirection : : Output , CPPType , CPPTypeObjectPath , DefaultValue , true , true ) ;
2020-12-14 08:58:12 -04:00
}
}
return FReply : : Unhandled ( ) ;
}
2021-01-27 05:06:20 -04:00
FText FControlRigGraphDetails : : GetNodeCategory ( ) const
{
if ( GraphPtr . IsValid ( ) & & ControlRigBlueprintPtr . IsValid ( ) )
{
UControlRigBlueprint * Blueprint = ControlRigBlueprintPtr . Get ( ) ;
if ( URigVMGraph * Model = Blueprint - > GetModel ( GraphPtr . Get ( ) ) )
{
if ( URigVMCollapseNode * OuterNode = Cast < URigVMCollapseNode > ( Model - > GetOuter ( ) ) )
{
return FText : : FromString ( OuterNode - > GetNodeCategory ( ) ) ;
}
}
}
return FText ( ) ;
}
void FControlRigGraphDetails : : SetNodeCategory ( const FText & InNewText , ETextCommit : : Type InCommitType )
{
2021-09-07 10:19:44 -04:00
if ( InCommitType = = ETextCommit : : OnCleared )
{
return ;
}
2021-01-27 05:06:20 -04:00
if ( GraphPtr . IsValid ( ) & & ControlRigBlueprintPtr . IsValid ( ) )
{
UControlRigBlueprint * Blueprint = ControlRigBlueprintPtr . Get ( ) ;
if ( URigVMGraph * Model = Blueprint - > GetModel ( GraphPtr . Get ( ) ) )
{
if ( URigVMCollapseNode * OuterNode = Cast < URigVMCollapseNode > ( Model - > GetOuter ( ) ) )
{
if ( URigVMController * Controller = Blueprint - > GetOrCreateController ( OuterNode - > GetGraph ( ) ) )
{
2021-07-19 06:35:29 -04:00
Controller - > SetNodeCategory ( OuterNode , InNewText . ToString ( ) , true , false , true ) ;
2021-01-27 05:06:20 -04:00
}
}
}
}
}
FText FControlRigGraphDetails : : GetNodeKeywords ( ) const
{
if ( GraphPtr . IsValid ( ) & & ControlRigBlueprintPtr . IsValid ( ) )
{
UControlRigBlueprint * Blueprint = ControlRigBlueprintPtr . Get ( ) ;
if ( URigVMGraph * Model = Blueprint - > GetModel ( GraphPtr . Get ( ) ) )
{
if ( URigVMCollapseNode * OuterNode = Cast < URigVMCollapseNode > ( Model - > GetOuter ( ) ) )
{
return FText : : FromString ( OuterNode - > GetNodeKeywords ( ) ) ;
}
}
}
return FText ( ) ;
}
void FControlRigGraphDetails : : SetNodeKeywords ( const FText & InNewText , ETextCommit : : Type InCommitType )
{
2021-09-07 10:19:44 -04:00
if ( InCommitType = = ETextCommit : : OnCleared )
{
return ;
}
2021-01-27 05:06:20 -04:00
if ( GraphPtr . IsValid ( ) & & ControlRigBlueprintPtr . IsValid ( ) )
{
UControlRigBlueprint * Blueprint = ControlRigBlueprintPtr . Get ( ) ;
if ( URigVMGraph * Model = Blueprint - > GetModel ( GraphPtr . Get ( ) ) )
{
if ( URigVMCollapseNode * OuterNode = Cast < URigVMCollapseNode > ( Model - > GetOuter ( ) ) )
{
if ( URigVMController * Controller = Blueprint - > GetOrCreateController ( OuterNode - > GetGraph ( ) ) )
{
2021-07-19 06:35:29 -04:00
Controller - > SetNodeKeywords ( OuterNode , InNewText . ToString ( ) , true , false , true ) ;
2021-01-27 05:06:20 -04:00
}
}
}
}
}
2021-06-08 12:10:13 -04:00
FText FControlRigGraphDetails : : GetNodeDescription ( ) const
{
if ( GraphPtr . IsValid ( ) & & ControlRigBlueprintPtr . IsValid ( ) )
{
UControlRigBlueprint * Blueprint = ControlRigBlueprintPtr . Get ( ) ;
if ( URigVMGraph * Model = Blueprint - > GetModel ( GraphPtr . Get ( ) ) )
{
if ( URigVMCollapseNode * OuterNode = Cast < URigVMCollapseNode > ( Model - > GetOuter ( ) ) )
{
return FText : : FromString ( OuterNode - > GetNodeDescription ( ) ) ;
}
}
}
return FText ( ) ;
}
void FControlRigGraphDetails : : SetNodeDescription ( const FText & InNewText , ETextCommit : : Type InCommitType )
{
2021-09-07 10:19:44 -04:00
if ( InCommitType = = ETextCommit : : OnCleared )
{
return ;
}
2021-06-08 12:10:13 -04:00
if ( GraphPtr . IsValid ( ) & & ControlRigBlueprintPtr . IsValid ( ) )
{
UControlRigBlueprint * Blueprint = ControlRigBlueprintPtr . Get ( ) ;
if ( URigVMGraph * Model = Blueprint - > GetModel ( GraphPtr . Get ( ) ) )
{
if ( URigVMCollapseNode * OuterNode = Cast < URigVMCollapseNode > ( Model - > GetOuter ( ) ) )
{
if ( URigVMController * Controller = Blueprint - > GetOrCreateController ( OuterNode - > GetGraph ( ) ) )
{
2021-07-19 06:35:29 -04:00
Controller - > SetNodeDescription ( OuterNode , InNewText . ToString ( ) , true , false , true ) ;
2021-06-08 12:10:13 -04:00
}
}
}
}
}
2021-01-27 05:06:20 -04:00
FLinearColor FControlRigGraphDetails : : GetNodeColor ( ) const
{
if ( GraphPtr . IsValid ( ) & & ControlRigBlueprintPtr . IsValid ( ) )
{
UControlRigBlueprint * Blueprint = ControlRigBlueprintPtr . Get ( ) ;
if ( URigVMGraph * Model = Blueprint - > GetModel ( GraphPtr . Get ( ) ) )
{
if ( URigVMCollapseNode * OuterNode = Cast < URigVMCollapseNode > ( Model - > GetOuter ( ) ) )
{
return OuterNode - > GetNodeColor ( ) ;
}
}
}
return FLinearColor : : White ;
}
void FControlRigGraphDetails : : SetNodeColor ( FLinearColor InColor , bool bSetupUndoRedo )
{
TargetColor = InColor ;
if ( GraphPtr . IsValid ( ) & & ControlRigBlueprintPtr . IsValid ( ) )
{
UControlRigBlueprint * Blueprint = ControlRigBlueprintPtr . Get ( ) ;
if ( URigVMGraph * Model = Blueprint - > GetModel ( GraphPtr . Get ( ) ) )
{
if ( URigVMCollapseNode * OuterNode = Cast < URigVMCollapseNode > ( Model - > GetOuter ( ) ) )
{
if ( URigVMController * Controller = Blueprint - > GetOrCreateController ( OuterNode - > GetGraph ( ) ) )
{
2021-07-19 06:35:29 -04:00
Controller - > SetNodeColor ( OuterNode , TargetColor , bSetupUndoRedo , bIsPickingColor , true ) ;
2021-01-27 05:06:20 -04:00
}
}
}
}
}
void FControlRigGraphDetails : : OnNodeColorBegin ( )
{
bIsPickingColor = true ;
}
void FControlRigGraphDetails : : OnNodeColorEnd ( )
{
bIsPickingColor = false ;
}
void FControlRigGraphDetails : : OnNodeColorCancelled ( FLinearColor OriginalColor )
{
SetNodeColor ( OriginalColor , true ) ;
}
FReply FControlRigGraphDetails : : OnNodeColorClicked ( )
{
TargetColor = GetNodeColor ( ) ;
TargetColors . Reset ( ) ;
TargetColors . Add ( & TargetColor ) ;
FColorPickerArgs PickerArgs ;
PickerArgs . ParentWidget = ColorBlock ;
PickerArgs . bUseAlpha = false ;
PickerArgs . DisplayGamma = false ;
PickerArgs . InitialColorOverride = TargetColor ;
PickerArgs . LinearColorArray = & TargetColors ;
PickerArgs . OnInteractivePickBegin = FSimpleDelegate : : CreateSP ( this , & FControlRigGraphDetails : : OnNodeColorBegin ) ;
PickerArgs . OnInteractivePickEnd = FSimpleDelegate : : CreateSP ( this , & FControlRigGraphDetails : : OnNodeColorEnd ) ;
PickerArgs . OnColorCommitted = FOnLinearColorValueChanged : : CreateSP ( this , & FControlRigGraphDetails : : SetNodeColor , true ) ;
PickerArgs . OnColorPickerCancelled = FOnColorPickerCancelled : : CreateSP ( this , & FControlRigGraphDetails : : OnNodeColorCancelled ) ;
OpenColorPicker ( PickerArgs ) ;
return FReply : : Handled ( ) ;
}
2021-03-03 14:44:58 -04:00
TArray < TSharedPtr < FString > > FControlRigGraphDetails : : AccessSpecifierStrings ;
FText FControlRigGraphDetails : : GetCurrentAccessSpecifierName ( ) const
{
if ( ControlRigBlueprintPtr . IsValid ( ) & & GraphPtr . IsValid ( ) )
{
UControlRigGraph * Graph = GraphPtr . Get ( ) ;
UControlRigBlueprint * ControlRigBlueprint = ControlRigBlueprintPtr . Get ( ) ;
const FControlRigPublicFunctionData ExpectedFunctionData = Graph - > GetPublicFunctionData ( ) ;
2021-03-10 05:52:25 -04:00
if ( ControlRigBlueprint - > IsFunctionPublic ( ExpectedFunctionData . Name ) )
2021-03-03 14:44:58 -04:00
{
2021-03-10 05:52:25 -04:00
return FText : : FromString ( * AccessSpecifierStrings [ 0 ] . Get ( ) ) ; // public
2021-03-03 14:44:58 -04:00
}
}
return FText : : FromString ( * AccessSpecifierStrings [ 1 ] . Get ( ) ) ; // private
}
void FControlRigGraphDetails : : OnAccessSpecifierSelected ( TSharedPtr < FString > SpecifierName , ESelectInfo : : Type SelectInfo )
{
if ( ControlRigBlueprintPtr . IsValid ( ) & & GraphPtr . IsValid ( ) )
{
UControlRigGraph * Graph = GraphPtr . Get ( ) ;
UControlRigBlueprint * ControlRigBlueprint = ControlRigBlueprintPtr . Get ( ) ;
2021-03-10 05:52:25 -04:00
const FControlRigPublicFunctionData ExpectedFunctionData = Graph - > GetPublicFunctionData ( ) ;
2021-03-03 14:44:58 -04:00
if ( SpecifierName - > Equals ( TEXT ( " Private " ) ) )
{
2021-03-10 05:52:25 -04:00
ControlRigBlueprint - > MarkFunctionPublic ( ExpectedFunctionData . Name , false ) ;
2021-03-03 14:44:58 -04:00
}
else
{
2021-03-10 05:52:25 -04:00
ControlRigBlueprint - > MarkFunctionPublic ( ExpectedFunctionData . Name , true ) ;
2021-03-03 14:44:58 -04:00
}
}
}
TSharedRef < ITableRow > FControlRigGraphDetails : : HandleGenerateRowAccessSpecifier ( TSharedPtr < FString > SpecifierName , const TSharedRef < STableViewBase > & OwnerTable )
{
return SNew ( STableRow < TSharedPtr < FString > > , OwnerTable )
. Content ( )
[
SNew ( STextBlock )
. Text ( FText : : FromString ( * SpecifierName . Get ( ) ) )
] ;
}
2021-08-05 11:08:05 -04:00
# if !UE_RIGVM_UCLASS_BASED_STORAGE_DISABLED
TSharedRef < IDetailCustomization > FControlRigWrappedNodeDetails : : MakeInstance ( )
{
return MakeShareable ( new FControlRigWrappedNodeDetails ) ;
}
void FControlRigWrappedNodeDetails : : CustomizeDetails ( IDetailLayoutBuilder & DetailLayout )
{
TArray < TWeakObjectPtr < UObject > > Objects ;
DetailLayout . GetObjectsBeingCustomized ( Objects ) ;
TArray < UDetailsViewWrapperObject * > Wrappers ;
TArray < URigVMNode * > Nodes ;
for ( const TWeakObjectPtr < UObject > & Object : Objects )
{
UDetailsViewWrapperObject * Wrapper = CastChecked < UDetailsViewWrapperObject > ( Object ) ;
Wrappers . Add ( Wrapper ) ;
URigVMNode * Node = Wrapper - > GetTypedOuter < URigVMNode > ( ) ;
if ( Node = = nullptr )
{
return ;
}
Nodes . Add ( Node ) ;
}
UDetailsViewWrapperObject * FirstWrapper = Wrappers [ 0 ] ;
URigVMNode * FirstNode = Nodes [ 0 ] ;
TArray < FName > Categories ;
DetailLayout . GetCategoryNames ( Categories ) ;
2021-11-11 11:47:13 -05:00
if ( Categories . IsEmpty ( ) )
{
return ;
}
2021-08-05 11:08:05 -04:00
IDetailCategoryBuilder & DefaultsCategory = DetailLayout . EditCategory ( Categories [ 0 ] ) ;
2021-11-03 07:53:40 -04:00
UControlRigBlueprint * Blueprint = FirstNode - > GetTypedOuter < UControlRigBlueprint > ( ) ;
if ( Blueprint = = nullptr )
{
return ;
}
2021-08-05 11:08:05 -04:00
for ( URigVMPin * Pin : FirstNode - > GetPins ( ) )
{
bool bHasAnyInputLink = false ;
for ( URigVMNode * EachNode : Nodes )
{
if ( URigVMPin * EachPin = EachNode - > FindPin ( Pin - > GetName ( ) ) )
{
if ( EachPin - > GetSourceLinks ( true ) . Num ( ) > 0 )
{
bHasAnyInputLink = true ;
break ;
}
}
}
2021-11-11 11:47:13 -05:00
TSharedPtr < IPropertyHandle > PinHandle = DetailLayout . GetProperty ( Pin - > GetFName ( ) ) ;
2021-08-05 11:08:05 -04:00
if ( PinHandle . IsValid ( ) )
{
static const TCHAR DisabledFormat [ ] = TEXT ( " %s \n \n Note: Editing disabled since pin has an input link. " ) ;
2021-11-03 07:53:40 -04:00
if ( Pin - > IsBoundToVariable ( ) )
{
DefaultsCategory . AddCustomRow ( FText : : FromName ( Pin - > GetDisplayName ( ) ) )
. NameContent ( )
[
PinHandle - > CreatePropertyNameWidget ( )
]
. ValueContent ( )
[
SNew ( SControlRigVariableBinding )
. ModelPin ( Pin )
. Blueprint ( Blueprint )
] ;
}
else
{
DefaultsCategory . AddProperty ( PinHandle )
. DisplayName ( FText : : FromName ( Pin - > GetDisplayName ( ) ) )
. IsEnabled ( ! bHasAnyInputLink )
. ToolTip ( FText : : FromString ( FString : : Printf ( DisabledFormat , * Pin - > GetToolTipText ( ) . ToString ( ) ) ) ) ;
}
2021-08-05 11:08:05 -04:00
}
}
if ( Objects . Num ( ) > 1 )
{
return ;
}
UControlRig * DebuggedRig = Cast < UControlRig > ( Blueprint - > GetObjectBeingDebugged ( ) ) ;
if ( DebuggedRig = = nullptr )
{
return ;
}
URigVM * VM = DebuggedRig - > GetVM ( ) ;
if ( VM = = nullptr )
{
return ;
}
TSharedPtr < FRigVMParserAST > AST = FirstNode - > GetGraph ( ) - > GetRuntimeAST ( Blueprint - > VMCompileSettings . ASTSettings , false ) ;
if ( ! AST . IsValid ( ) )
{
return ;
}
FRigVMByteCode & ByteCode = VM - > GetByteCode ( ) ;
if ( ByteCode . GetFirstInstructionIndexForSubject ( FirstNode ) = = INDEX_NONE )
{
return ;
}
IDetailCategoryBuilder & DebugCategory = DetailLayout . EditCategory ( " DebugLiveValues " , LOCTEXT ( " DebugLiveValues " , " Inspect Live Values " ) , ECategoryPriority : : Uncommon ) ;
DebugCategory . InitiallyCollapsed ( true ) ;
for ( URigVMPin * Pin : FirstNode - > GetPins ( ) )
{
// only show hidden pins in debug mode
if ( Pin - > GetDirection ( ) = = ERigVMPinDirection : : Hidden )
{
if ( ! DebuggedRig - > IsInDebugMode ( ) )
{
continue ;
}
}
URigVMPin * SourcePin = Pin ;
if ( Blueprint - > VMCompileSettings . ASTSettings . bFoldAssignments )
{
do
{
2021-08-17 09:34:19 -04:00
TArray < URigVMPin * > SourcePins = SourcePin - > GetLinkedSourcePins ( false ) ;
2021-08-05 11:08:05 -04:00
if ( SourcePins . Num ( ) > 0 )
{
SourcePin = SourcePins [ 0 ] ;
}
else
{
break ;
}
}
while ( SourcePin - > GetNode ( ) - > IsA < URigVMRerouteNode > ( ) ) ;
}
TArray < const FRigVMExprAST * > Expressions = AST - > GetExpressionsForSubject ( SourcePin ) ;
if ( Expressions . Num ( ) = = 0 & & SourcePin ! = Pin )
{
SourcePin = Pin ;
Expressions = AST - > GetExpressionsForSubject ( Pin ) ;
}
bool bHasVar = false ;
for ( const FRigVMExprAST * Expression : Expressions )
{
if ( Expression - > IsA ( FRigVMExprAST : : EType : : Literal ) )
{
continue ;
}
else if ( Expression - > IsA ( FRigVMExprAST : : EType : : Var ) )
{
bHasVar = true ;
break ;
}
}
TArray < const FRigVMExprAST * > FilteredExpressions ;
for ( const FRigVMExprAST * Expression : Expressions )
{
if ( Expression - > IsA ( FRigVMExprAST : : EType : : Literal ) )
{
if ( bHasVar )
{
continue ;
}
FilteredExpressions . Add ( Expression ) ;
}
else if ( Expression - > IsA ( FRigVMExprAST : : EType : : Var ) )
{
FilteredExpressions . Add ( Expression ) ;
}
else if ( Expression - > IsA ( FRigVMExprAST : : EType : : CachedValue ) )
{
const FRigVMCachedValueExprAST * CachedValueExpr = Expression - > To < FRigVMCachedValueExprAST > ( ) ;
FilteredExpressions . Add ( CachedValueExpr - > GetVarExpr ( ) ) ;
}
}
bool bAddedProperty = false ;
int32 SuffixIndex = 1 ;
FString NameSuffix ;
TArray < FRigVMOperand > KnownOperands ;
for ( const FRigVMExprAST * Expression : FilteredExpressions )
{
const FRigVMVarExprAST * VarExpr = Expression - > To < FRigVMVarExprAST > ( ) ;
FString PinHash = URigVMCompiler : : GetPinHash ( SourcePin , VarExpr , false ) ;
const FRigVMOperand * Operand = Blueprint - > PinToOperandMap . Find ( PinHash ) ;
if ( Operand )
{
if ( Operand - > GetRegisterOffset ( ) ! = INDEX_NONE )
{
continue ;
}
if ( KnownOperands . Contains ( * Operand ) )
{
continue ;
}
2021-08-05 19:30:58 -04:00
const FProperty * Property = nullptr ;
2021-08-05 11:08:05 -04:00
TArray < UObject * > ExternalObjects ;
2021-08-05 19:30:58 -04:00
if ( Operand - > GetMemoryType ( ) = = ERigVMMemoryType : : External )
{
if ( ! VM - > GetExternalVariables ( ) . IsValidIndex ( Operand - > GetRegisterIndex ( ) ) )
{
continue ;
}
ExternalObjects . Add ( DebuggedRig ) ;
Property = VM - > GetExternalVariables ( ) [ Operand - > GetRegisterIndex ( ) ] . Property ;
}
else
{
URigVMMemoryStorage * Memory = VM - > GetMemoryByType ( Operand - > GetMemoryType ( ) ) ;
if ( Memory = = nullptr )
{
continue ;
}
if ( Memory - > GetOuter ( ) = = GetTransientPackage ( ) )
{
continue ;
}
2021-08-18 02:08:42 -04:00
// the UClass must be alive for the details view to access it
// this ensure can fail if VM memory is not updated immediately after compile
// because of deferred copy
2021-09-06 12:23:53 -04:00
if ( ! ensure ( IsValidChecked ( Memory - > GetClass ( ) ) ) )
2021-08-18 02:08:42 -04:00
{
continue ;
}
2021-08-05 19:30:58 -04:00
if ( Memory - > GetClass ( ) - > GetOuter ( ) = = GetTransientPackage ( ) )
{
continue ;
}
if ( ! Memory - > IsValidIndex ( Operand - > GetRegisterIndex ( ) ) )
{
continue ;
}
Property = Memory - > GetProperty ( Operand - > GetRegisterIndex ( ) ) ;
if ( Property = = nullptr )
{
continue ;
}
ExternalObjects . Add ( Memory ) ;
}
check ( ExternalObjects . Num ( ) > 0 ) ;
check ( Property ) ;
IDetailPropertyRow * PropertyRow = DebugCategory . AddExternalObjectProperty ( ExternalObjects , Property - > GetFName ( ) , EPropertyLocation : : Default , FAddPropertyParams ( ) . ForceShowProperty ( ) ) ;
if ( PropertyRow )
{
PropertyRow - > DisplayName ( FText : : FromString ( FString : : Printf ( TEXT ( " %s%s " ) , * Pin - > GetName ( ) , * NameSuffix ) ) ) ;
PropertyRow - > IsEnabled ( false ) ;
SuffixIndex + + ;
bAddedProperty = true ;
NameSuffix = FString : : Printf ( TEXT ( " _%d " ) , SuffixIndex ) ;
}
2021-08-05 11:08:05 -04:00
KnownOperands . Add ( * Operand ) ;
}
}
if ( ! bAddedProperty )
{
2021-11-11 11:47:13 -05:00
TSharedPtr < IPropertyHandle > PinHandle = DetailLayout . GetProperty ( Pin - > GetFName ( ) ) ;
2021-08-05 11:08:05 -04:00
if ( PinHandle . IsValid ( ) )
{
2021-08-05 19:30:58 -04:00
DebugCategory . AddProperty ( PinHandle )
2021-08-05 11:08:05 -04:00
. DisplayName ( FText : : FromName ( Pin - > GetDisplayName ( ) ) )
. IsEnabled ( false ) ;
}
}
}
}
# endif
2020-12-14 08:58:12 -04:00
# undef LOCTEXT_NAMESPACE