K2Node_JsonLibraryToStruct.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. // Copyright 2022 Tracer Interactive, LLC. All Rights Reserved.
  2. #include "K2Node_JsonLibraryToStruct.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 "JsonLibraryObject.h"
  14. #include "JsonLibraryBlueprintHelpers.h"
  15. #define LOCTEXT_NAMESPACE "K2Node_JsonLibraryToStruct"
  16. struct UK2Node_JsonLibraryToStructHelper
  17. {
  18. static FName DataPinName;
  19. static FName FailedPinName;
  20. };
  21. FName UK2Node_JsonLibraryToStructHelper::FailedPinName( *LOCTEXT( "FailedPinName", "Failed" ).ToString() );
  22. FName UK2Node_JsonLibraryToStructHelper::DataPinName( *LOCTEXT( "DataPinName", "Object" ).ToString() );
  23. UK2Node_JsonLibraryToStruct::UK2Node_JsonLibraryToStruct( const FObjectInitializer& ObjectInitializer )
  24. : Super( ObjectInitializer )
  25. {
  26. NodeTooltip = LOCTEXT( "NodeTooltip", "Attempts to parse a JSON object into a structure." );
  27. }
  28. void UK2Node_JsonLibraryToStruct::AllocateDefaultPins()
  29. {
  30. const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>();
  31. CreatePin( EGPD_Input, UEdGraphSchema_K2::PC_Exec, UEdGraphSchema_K2::PN_Execute );
  32. UEdGraphPin* SuccessPin = CreatePin( EGPD_Output, UEdGraphSchema_K2::PC_Exec, UEdGraphSchema_K2::PN_Then );
  33. SuccessPin->PinFriendlyName = LOCTEXT( "JsonLibraryToStruct Success Exec pin", "Success" );
  34. UEdGraphPin* FailedPin = CreatePin( EGPD_Output, UEdGraphSchema_K2::PC_Exec, UK2Node_JsonLibraryToStructHelper::FailedPinName );
  35. FailedPin->PinFriendlyName = LOCTEXT( "JsonLibraryToStruct Failed Exec pin", "Failure" );
  36. UScriptStruct* JsonObjectStruct = TBaseStructure<FJsonLibraryObject>::Get();
  37. UEdGraphPin* DataPin = CreatePin( EGPD_Input, UEdGraphSchema_K2::PC_Struct, JsonObjectStruct, UK2Node_JsonLibraryToStructHelper::DataPinName );
  38. SetPinToolTip( *DataPin, LOCTEXT( "DataPinDescription", "The JSON object to convert." ) );
  39. UEdGraphPin* ResultPin = CreatePin( EGPD_Output, UEdGraphSchema_K2::PC_Wildcard, UEdGraphSchema_K2::PN_ReturnValue );
  40. //ResultPin->bDisplayAsMutableRef = true;
  41. ResultPin->PinFriendlyName = LOCTEXT( "JsonLibraryToStruct Out Struct", "Structure" );
  42. SetPinToolTip( *ResultPin, LOCTEXT( "ResultPinDescription", "The returned structure, if converted." ) );
  43. Super::AllocateDefaultPins();
  44. }
  45. void UK2Node_JsonLibraryToStruct::SetPinToolTip( UEdGraphPin& MutatablePin, const FText& PinDescription ) const
  46. {
  47. MutatablePin.PinToolTip = UEdGraphSchema_K2::TypeToText( MutatablePin.PinType ).ToString();
  48. UEdGraphSchema_K2 const* const K2Schema = Cast<const UEdGraphSchema_K2>( GetSchema() );
  49. if ( K2Schema )
  50. {
  51. MutatablePin.PinToolTip += TEXT( " " );
  52. MutatablePin.PinToolTip += K2Schema->GetPinDisplayName( &MutatablePin ).ToString();
  53. }
  54. MutatablePin.PinToolTip += FString( TEXT( "\n" ) ) + PinDescription.ToString();
  55. }
  56. void UK2Node_JsonLibraryToStruct::RefreshOutputPinType()
  57. {
  58. UEdGraphPin* ResultPin = GetResultPin();
  59. const bool bFillTypeFromConnected = ResultPin && ( ResultPin->PinType.PinCategory == UEdGraphSchema_K2::PC_Wildcard );
  60. UScriptStruct* OutputType = nullptr;
  61. if ( bFillTypeFromConnected )
  62. {
  63. FEdGraphPinType PinType = ResultPin->PinType;
  64. if ( ResultPin->LinkedTo.Num() > 0 )
  65. PinType = ResultPin->LinkedTo[ 0 ]->PinType;
  66. if ( PinType.PinCategory == UEdGraphSchema_K2::PC_Struct )
  67. OutputType = Cast<UScriptStruct>( PinType.PinSubCategoryObject.Get() );
  68. }
  69. SetReturnTypeForStruct( OutputType );
  70. }
  71. void UK2Node_JsonLibraryToStruct::SetReturnTypeForStruct( UScriptStruct* StructType )
  72. {
  73. if ( StructType == GetReturnTypeForStruct() )
  74. return;
  75. UEdGraphPin* ResultPin = GetResultPin();
  76. if ( ResultPin->SubPins.Num() > 0 )
  77. GetSchema()->RecombinePin( ResultPin );
  78. ResultPin->PinType.PinSubCategoryObject = StructType;
  79. ResultPin->PinType.PinCategory = StructType ?
  80. UEdGraphSchema_K2::PC_Struct :
  81. UEdGraphSchema_K2::PC_Wildcard;
  82. CachedNodeTitle.Clear();
  83. }
  84. UScriptStruct* UK2Node_JsonLibraryToStruct::GetReturnTypeForStruct() const
  85. {
  86. UScriptStruct* ReturnStructType = (UScriptStruct*)( GetResultPin()->PinType.PinSubCategoryObject.Get() );
  87. return ReturnStructType;
  88. }
  89. void UK2Node_JsonLibraryToStruct::GetMenuActions( FBlueprintActionDatabaseRegistrar& ActionRegistrar ) const
  90. {
  91. UClass* ActionKey = GetClass();
  92. if ( ActionRegistrar.IsOpenForRegistration( ActionKey ) )
  93. {
  94. UBlueprintNodeSpawner* NodeSpawner = UBlueprintNodeSpawner::Create( GetClass() );
  95. check( NodeSpawner != nullptr );
  96. ActionRegistrar.AddBlueprintAction( ActionKey, NodeSpawner );
  97. }
  98. }
  99. FText UK2Node_JsonLibraryToStruct::GetMenuCategory() const
  100. {
  101. return FText::FromString( TEXT( "JSON Library|Structure" ) );
  102. }
  103. bool UK2Node_JsonLibraryToStruct::IsConnectionDisallowed( const UEdGraphPin* MyPin, const UEdGraphPin* OtherPin, FString& OutReason ) const
  104. {
  105. if ( MyPin == GetResultPin() && MyPin->PinType.PinCategory == UEdGraphSchema_K2::PC_Wildcard )
  106. {
  107. bool bDisallowed = true;
  108. if ( OtherPin->PinType.PinCategory == UEdGraphSchema_K2::PC_Struct )
  109. {
  110. if ( UScriptStruct* ConnectionType = Cast<UScriptStruct>( OtherPin->PinType.PinSubCategoryObject.Get() ) )
  111. bDisallowed = false;
  112. }
  113. else if ( OtherPin->PinType.PinCategory == UEdGraphSchema_K2::PC_Wildcard )
  114. bDisallowed = false;
  115. if ( bDisallowed )
  116. OutReason = TEXT( "Must be a structure." );
  117. return bDisallowed;
  118. }
  119. return false;
  120. }
  121. FText UK2Node_JsonLibraryToStruct::GetTooltipText() const
  122. {
  123. return NodeTooltip;
  124. }
  125. UEdGraphPin* UK2Node_JsonLibraryToStruct::GetThenPin()const
  126. {
  127. const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>();
  128. UEdGraphPin* Pin = FindPinChecked( UEdGraphSchema_K2::PN_Then );
  129. check( Pin->Direction == EGPD_Output );
  130. return Pin;
  131. }
  132. UEdGraphPin* UK2Node_JsonLibraryToStruct::GetDataPin() const
  133. {
  134. UEdGraphPin* Pin = FindPinChecked( UK2Node_JsonLibraryToStructHelper::DataPinName );
  135. check( Pin->Direction == EGPD_Input );
  136. return Pin;
  137. }
  138. UEdGraphPin* UK2Node_JsonLibraryToStruct::GetFailedPin() const
  139. {
  140. UEdGraphPin* Pin = FindPinChecked( UK2Node_JsonLibraryToStructHelper::FailedPinName );
  141. check( Pin->Direction == EGPD_Output );
  142. return Pin;
  143. }
  144. UEdGraphPin* UK2Node_JsonLibraryToStruct::GetResultPin() const
  145. {
  146. const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>();
  147. UEdGraphPin* Pin = FindPinChecked( UEdGraphSchema_K2::PN_ReturnValue );
  148. check( Pin->Direction == EGPD_Output );
  149. return Pin;
  150. }
  151. FText UK2Node_JsonLibraryToStruct::GetNodeTitle( ENodeTitleType::Type TitleType ) const
  152. {
  153. if ( TitleType == ENodeTitleType::MenuTitle )
  154. return LOCTEXT( "ListViewTitle", "JSON to Structure" );
  155. if ( UEdGraphPin* ResultPin = GetResultPin() )
  156. {
  157. UScriptStruct* StructType = GetReturnTypeForStruct();
  158. if ( !StructType || ResultPin->LinkedTo.Num() == 0 )
  159. return NSLOCTEXT( "K2Node", "JsonToStruct_Title_None", "JSON to Structure" );
  160. if ( CachedNodeTitle.IsOutOfDate( this ) )
  161. {
  162. FFormatNamedArguments Args;
  163. Args.Add( TEXT( "StructName" ), FText::FromName( StructType->GetFName() ) );
  164. FText LocFormat = NSLOCTEXT( "K2Node", "JsonToStruct", "JSON to {StructName}" );
  165. CachedNodeTitle.SetCachedText( FText::Format( LocFormat, Args ), this );
  166. }
  167. }
  168. else
  169. return NSLOCTEXT( "K2Node", "JsonToStruct_Title_None", "JSON to Structure" );
  170. return CachedNodeTitle;
  171. }
  172. void UK2Node_JsonLibraryToStruct::ExpandNode( FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph )
  173. {
  174. Super::ExpandNode( CompilerContext, SourceGraph );
  175. const FName StructFromJsonFunctionName = GET_FUNCTION_NAME_CHECKED( UJsonLibraryBlueprintHelpers, StructFromJson );
  176. UK2Node_CallFunction* CallStructFromJsonFunction = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>( this, SourceGraph );
  177. CallStructFromJsonFunction->FunctionReference.SetExternalMember( StructFromJsonFunctionName, UJsonLibraryBlueprintHelpers::StaticClass() );
  178. CallStructFromJsonFunction->AllocateDefaultPins();
  179. CompilerContext.MovePinLinksToIntermediate( *GetExecPin(), *( CallStructFromJsonFunction->GetExecPin() ) );
  180. UScriptStruct* StructType = GetReturnTypeForStruct();
  181. UUserDefinedStruct* UserStructType = Cast<UUserDefinedStruct>( StructType );
  182. UEdGraphPin* StructTypePin = CallStructFromJsonFunction->FindPinChecked( TEXT( "StructType" ) );
  183. if ( UserStructType && UserStructType->PrimaryStruct.IsValid() )
  184. StructTypePin->DefaultObject = UserStructType->PrimaryStruct.Get();
  185. else
  186. StructTypePin->DefaultObject = StructType;
  187. UEdGraphPin* DataInPin = CallStructFromJsonFunction->FindPinChecked( TEXT( "Object" ) );
  188. CompilerContext.MovePinLinksToIntermediate( *GetDataPin(), *DataInPin );
  189. UEdGraphPin* OriginalReturnPin = FindPinChecked( UEdGraphSchema_K2::PN_ReturnValue );
  190. UEdGraphPin* FunctionOutStructPin = CallStructFromJsonFunction->FindPinChecked( TEXT( "OutStruct" ) );
  191. UEdGraphPin* FunctionReturnPin = CallStructFromJsonFunction->FindPinChecked( UEdGraphSchema_K2::PN_ReturnValue );
  192. UEdGraphPin* FunctionThenPin = CallStructFromJsonFunction->GetThenPin();
  193. FunctionOutStructPin->PinType = OriginalReturnPin->PinType;
  194. FunctionOutStructPin->PinType.PinSubCategoryObject = OriginalReturnPin->PinType.PinSubCategoryObject;
  195. UK2Node_IfThenElse* BranchNode = CompilerContext.SpawnIntermediateNode<UK2Node_IfThenElse>( this, SourceGraph );
  196. BranchNode->AllocateDefaultPins();
  197. FunctionThenPin->MakeLinkTo( BranchNode->GetExecPin() );
  198. FunctionReturnPin->MakeLinkTo( BranchNode->GetConditionPin() );
  199. CompilerContext.MovePinLinksToIntermediate( *GetThenPin(), *( BranchNode->GetThenPin() ) );
  200. CompilerContext.MovePinLinksToIntermediate( *GetFailedPin(), *( BranchNode->GetElsePin() ) );
  201. CompilerContext.MovePinLinksToIntermediate( *OriginalReturnPin, *FunctionOutStructPin );
  202. BreakAllNodeLinks();
  203. }
  204. FSlateIcon UK2Node_JsonLibraryToStruct::GetIconAndTint( FLinearColor& OutColor ) const
  205. {
  206. OutColor = GetNodeTitleColor();
  207. static FSlateIcon Icon( "EditorStyle", "Kismet.AllClasses.FunctionIcon" );
  208. return Icon;
  209. }
  210. void UK2Node_JsonLibraryToStruct::PostReconstructNode()
  211. {
  212. Super::PostReconstructNode();
  213. RefreshOutputPinType();
  214. }
  215. void UK2Node_JsonLibraryToStruct::EarlyValidation( FCompilerResultsLog& MessageLog ) const
  216. {
  217. Super::EarlyValidation( MessageLog );
  218. if ( UEdGraphPin* ResultPin = GetResultPin() )
  219. {
  220. if ( ResultPin->LinkedTo.Num() == 0 )
  221. {
  222. MessageLog.Error( *LOCTEXT( "MissingPins", "Missing pins in @@" ).ToString(), this );
  223. return;
  224. }
  225. }
  226. }
  227. void UK2Node_JsonLibraryToStruct::NotifyPinConnectionListChanged( UEdGraphPin* Pin )
  228. {
  229. Super::NotifyPinConnectionListChanged( Pin );
  230. if ( Pin == GetResultPin() )
  231. RefreshOutputPinType();
  232. }
  233. #undef LOCTEXT_NAMESPACE