K2Node_JsonSerialize.cpp 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. // Copyright 2021-2022, DearBing. All Rights Reserved.
  2. #include "K2Node_JsonSerialize.h"
  3. #include "Engine/UserDefinedStruct.h"
  4. #include "EdGraph/EdGraphPin.h"
  5. #include "EdGraphSchema_K2.h"
  6. #include "K2Node_CallFunction.h"
  7. #include "K2Node_IfThenElse.h"
  8. #include "Kismet2/BlueprintEditorUtils.h"
  9. #include "KismetCompiler.h"
  10. #include "BlueprintActionDatabaseRegistrar.h"
  11. #include "BlueprintNodeSpawner.h"
  12. #include "EditorCategoryUtils.h"
  13. #include "DBJsonBPLibrary.h"
  14. #include "Json.h"
  15. #define LOCTEXT_NAMESPACE "UK2Node_JsonSerialize"
  16. UK2Node_JsonSerialize::UK2Node_JsonSerialize( const FObjectInitializer& ObjectInitializer )
  17. : Super( ObjectInitializer )
  18. {
  19. NodeTooltip = LOCTEXT( "NodeTooltip", "Try to parse a structure a Json string." );
  20. }
  21. void UK2Node_JsonSerialize::AllocateDefaultPins()
  22. {
  23. const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>();
  24. CreatePin( EGPD_Input, UEdGraphSchema_K2::PC_Exec, UEdGraphSchema_K2::PN_Execute );
  25. UEdGraphPin* SuccessPin = CreatePin( EGPD_Output, UEdGraphSchema_K2::PC_Exec, UEdGraphSchema_K2::PN_Then );
  26. SuccessPin->PinFriendlyName = LOCTEXT( "Success Exec pin", "" );
  27. UEdGraphPin* DataPin = CreatePin( EGPD_Input, UEdGraphSchema_K2::PC_Wildcard, TEXT("Structure"));
  28. DataPin->bDisplayAsMutableRef = true;
  29. SetPinToolTip( *DataPin, LOCTEXT( "DataPinDescription", "The structure to convert." ) );
  30. UEdGraphPin* ResultPin = CreatePin( EGPD_Output, UEdGraphSchema_K2::PC_String, UEdGraphSchema_K2::PN_ReturnValue );
  31. ResultPin->PinFriendlyName = LOCTEXT( "Out JsonStr", "JsonStr" );
  32. SetPinToolTip( *ResultPin, LOCTEXT( "ResultPinDescription", "The returned JSON String" ) );
  33. Super::AllocateDefaultPins();
  34. }
  35. void UK2Node_JsonSerialize::SetPinToolTip( UEdGraphPin& MutatablePin, const FText& PinDescription ) const
  36. {
  37. MutatablePin.PinToolTip = UEdGraphSchema_K2::TypeToText( MutatablePin.PinType ).ToString();
  38. UEdGraphSchema_K2 const* const K2Schema = Cast<const UEdGraphSchema_K2>( GetSchema() );
  39. if ( K2Schema )
  40. {
  41. MutatablePin.PinToolTip += TEXT( " " );
  42. MutatablePin.PinToolTip += K2Schema->GetPinDisplayName( &MutatablePin ).ToString();
  43. }
  44. MutatablePin.PinToolTip += FString( TEXT( "\n" ) ) + PinDescription.ToString();
  45. }
  46. void UK2Node_JsonSerialize::RefreshInputPinType()
  47. {
  48. UEdGraphPin* DataPin = GetDataPin();
  49. const bool bFillTypeFromConnected = DataPin && ( DataPin->PinType.PinCategory == UEdGraphSchema_K2::PC_Wildcard );
  50. UScriptStruct* InputType = nullptr;
  51. if ( bFillTypeFromConnected )
  52. {
  53. FEdGraphPinType PinType = DataPin->PinType;
  54. if ( DataPin->LinkedTo.Num() > 0 )
  55. PinType = DataPin->LinkedTo[ 0 ]->PinType;
  56. if ( PinType.PinCategory == UEdGraphSchema_K2::PC_Struct )
  57. InputType = Cast<UScriptStruct>( PinType.PinSubCategoryObject.Get() );
  58. }
  59. SetPropertyTypeForStruct( InputType );
  60. }
  61. void UK2Node_JsonSerialize::SetPropertyTypeForStruct( UScriptStruct* StructType )
  62. {
  63. if ( StructType == GetPropertyTypeForStruct() )
  64. return;
  65. UEdGraphPin* DataPin = GetDataPin();
  66. if ( DataPin->SubPins.Num() > 0 )
  67. GetSchema()->RecombinePin( DataPin );
  68. DataPin->PinType.PinSubCategoryObject = StructType;
  69. DataPin->PinType.PinCategory = StructType ?
  70. UEdGraphSchema_K2::PC_Struct :
  71. UEdGraphSchema_K2::PC_Wildcard;
  72. CachedNodeTitle.Clear();
  73. }
  74. UScriptStruct* UK2Node_JsonSerialize::GetPropertyTypeForStruct() const
  75. {
  76. UScriptStruct* DataStructType = (UScriptStruct*)( GetDataPin()->PinType.PinSubCategoryObject.Get() );
  77. return DataStructType;
  78. }
  79. void UK2Node_JsonSerialize::GetMenuActions( FBlueprintActionDatabaseRegistrar& ActionRegistrar ) const
  80. {
  81. UClass* ActionKey = GetClass();
  82. if ( ActionRegistrar.IsOpenForRegistration( ActionKey ) )
  83. {
  84. UBlueprintNodeSpawner* NodeSpawner = UBlueprintNodeSpawner::Create( GetClass() );
  85. check( NodeSpawner != nullptr );
  86. ActionRegistrar.AddBlueprintAction( ActionKey, NodeSpawner );
  87. }
  88. }
  89. FText UK2Node_JsonSerialize::GetMenuCategory() const
  90. {
  91. return FText::FromString( TEXT( "DBJson " ) );
  92. }
  93. bool UK2Node_JsonSerialize::IsConnectionDisallowed( const UEdGraphPin* MyPin, const UEdGraphPin* OtherPin, FString& OutReason ) const
  94. {
  95. if ( MyPin == GetDataPin() && MyPin->PinType.PinCategory == UEdGraphSchema_K2::PC_Wildcard )
  96. {
  97. bool bDisallowed = true;
  98. if ( OtherPin->PinType.PinCategory == UEdGraphSchema_K2::PC_Struct )
  99. {
  100. if ( UScriptStruct* ConnectionType = Cast<UScriptStruct>( OtherPin->PinType.PinSubCategoryObject.Get() ) )
  101. bDisallowed = false;
  102. }
  103. else if ( OtherPin->PinType.PinCategory == UEdGraphSchema_K2::PC_Wildcard )
  104. bDisallowed = false;
  105. if ( bDisallowed )
  106. OutReason = TEXT( "Must be a structure." );
  107. return bDisallowed;
  108. }
  109. return false;
  110. }
  111. FText UK2Node_JsonSerialize::GetTooltipText() const
  112. {
  113. return NodeTooltip;
  114. }
  115. UEdGraphPin* UK2Node_JsonSerialize::GetThenPin()const
  116. {
  117. const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>();
  118. UEdGraphPin* Pin = FindPinChecked( UEdGraphSchema_K2::PN_Then );
  119. check( Pin->Direction == EGPD_Output );
  120. return Pin;
  121. }
  122. UEdGraphPin* UK2Node_JsonSerialize::GetDataPin() const
  123. {
  124. UEdGraphPin* Pin = FindPin(TEXT("Structure"));
  125. if (Pin == nullptr)
  126. {
  127. return nullptr;
  128. }
  129. check( Pin->Direction == EGPD_Input );
  130. return Pin;
  131. }
  132. FText UK2Node_JsonSerialize::GetNodeTitle( ENodeTitleType::Type TitleType ) const
  133. {
  134. if ( TitleType == ENodeTitleType::MenuTitle )
  135. return LOCTEXT( "ListViewTitle", "JsonSerialize" );
  136. if ( UEdGraphPin* DataPin = GetDataPin() )
  137. {
  138. UScriptStruct* StructType = GetPropertyTypeForStruct();
  139. if ( !StructType || DataPin->LinkedTo.Num() == 0 )
  140. return NSLOCTEXT( "K2Node", "JsonSerialize_Title_None", "JsonSerialize Structure" );
  141. if ( CachedNodeTitle.IsOutOfDate( this ) )
  142. {
  143. FFormatNamedArguments Args;
  144. Args.Add( TEXT( "StructName" ), FText::FromName( StructType->GetFName() ) );
  145. FText LocFormat = NSLOCTEXT( "K2Node", "JsonSerialize", "JsonSerialize {StructName}" );
  146. CachedNodeTitle.SetCachedText( FText::Format( LocFormat, Args ), this );
  147. }
  148. }
  149. else
  150. return NSLOCTEXT( "K2Node", "JsonSerialize_Title_None", "JsonSerialize Structure" );
  151. return CachedNodeTitle;
  152. }
  153. void UK2Node_JsonSerialize::ExpandNode( FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph )
  154. {
  155. Super::ExpandNode( CompilerContext, SourceGraph );
  156. const FName StructToJsonFunctionName = GET_FUNCTION_NAME_CHECKED( UDBJsonBPLibrary, JsonSerialize);
  157. UK2Node_CallFunction* CallStructToJsonFunction = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>( this, SourceGraph );
  158. CallStructToJsonFunction->FunctionReference.SetExternalMember( StructToJsonFunctionName, UDBJsonBPLibrary::StaticClass() );
  159. CallStructToJsonFunction->AllocateDefaultPins();
  160. CompilerContext.MovePinLinksToIntermediate( *GetExecPin(), *( CallStructToJsonFunction->GetExecPin() ) );
  161. UScriptStruct* StructType = GetPropertyTypeForStruct();
  162. UUserDefinedStruct* UserStructType = Cast<UUserDefinedStruct>( StructType );
  163. UEdGraphPin* StructTypePin = CallStructToJsonFunction->FindPinChecked( TEXT( "StructType" ) );
  164. if ( UserStructType && UserStructType->PrimaryStruct.IsValid() )
  165. StructTypePin->DefaultObject = UserStructType->PrimaryStruct.Get();
  166. else
  167. StructTypePin->DefaultObject = StructType;
  168. UEdGraphPin* OriginalDataPin = GetDataPin();
  169. UEdGraphPin* StructInPin = CallStructToJsonFunction->FindPinChecked( TEXT( "Struct" ) );
  170. StructInPin->PinType = OriginalDataPin->PinType;
  171. StructInPin->PinType.PinSubCategoryObject = OriginalDataPin->PinType.PinSubCategoryObject;
  172. CompilerContext.MovePinLinksToIntermediate( *OriginalDataPin, *StructInPin );
  173. UEdGraphPin* OriginalReturnPin = FindPinChecked( UEdGraphSchema_K2::PN_ReturnValue );
  174. UEdGraphPin* FunctionReturnPin = CallStructToJsonFunction->FindPinChecked( UEdGraphSchema_K2::PN_ReturnValue );
  175. UEdGraphPin* FunctionThenPin = CallStructToJsonFunction->GetThenPin();
  176. CompilerContext.MovePinLinksToIntermediate( *GetThenPin(), *FunctionThenPin);
  177. CompilerContext.MovePinLinksToIntermediate( *OriginalReturnPin, *FunctionReturnPin );
  178. BreakAllNodeLinks();
  179. }
  180. FSlateIcon UK2Node_JsonSerialize::GetIconAndTint( FLinearColor& OutColor ) const
  181. {
  182. OutColor = GetNodeTitleColor();
  183. static FSlateIcon Icon( "EditorStyle", "Kismet.AllClasses.FunctionIcon" );
  184. return Icon;
  185. }
  186. void UK2Node_JsonSerialize::PostReconstructNode()
  187. {
  188. Super::PostReconstructNode();
  189. RefreshInputPinType();
  190. }
  191. void UK2Node_JsonSerialize::EarlyValidation( FCompilerResultsLog& MessageLog ) const
  192. {
  193. Super::EarlyValidation( MessageLog );
  194. if ( UEdGraphPin* DataPin = GetDataPin() )
  195. {
  196. if ( DataPin->LinkedTo.Num() == 0 )
  197. {
  198. MessageLog.Error( *LOCTEXT( "MissingPins", "Missing pins in @@" ).ToString(), this );
  199. return;
  200. }
  201. }
  202. }
  203. void UK2Node_JsonSerialize::NotifyPinConnectionListChanged( UEdGraphPin* Pin )
  204. {
  205. Super::NotifyPinConnectionListChanged( Pin );
  206. if ( Pin == GetDataPin() )
  207. RefreshInputPinType();
  208. }
  209. #undef LOCTEXT_NAMESPACE