88#include " BlueprintNodeSpawner.h"
99#include " EdGraphSchema_K2.h"
1010#include " K2Node_CallFunction.h"
11- #include " K2Node_Variable.h"
12- #include " K2Node_VariableGet.h"
13- #include " K2Node_MakeFunctionHandler.h"
1411#include " KismetCompiler.h"
15- #include " Kismet2/BlueprintEditorUtils.h"
1612
1713#include " UObject/UnrealType.h"
1814
1915#define LOCTEXT_NAMESPACE " K2Node_ExecuteFunctionHandler"
2016
2117const FName UK2Node_ExecuteFunctionHandler::PN_Target (TEXT(" Target" ));
22- const FName UK2Node_ExecuteFunctionHandler::PN_Handler (TEXT(" Handler" ));
2318const FName UK2Node_ExecuteFunctionHandler::PN_Success (TEXT(" Success" ));
2419
25- #pragma region UK2Node
26-
2720void UK2Node_ExecuteFunctionHandler::AllocateDefaultPins ()
2821{
2922 CreatePin (EGPD_Input, UEdGraphSchema_K2::PC_Exec, UEdGraphSchema_K2::PN_Execute);
@@ -119,7 +112,6 @@ void UK2Node_ExecuteFunctionHandler::ExpandNode(
119112 GetterNode->SetFromFunction (GetResultFunc);
120113 GetterNode->AllocateDefaultPins ();
121114
122- // Chain exec: previous → GetterNode → next.
123115 LastExecOut->MakeLinkTo (GetterNode->FindPinChecked (UEdGraphSchema_K2::PN_Execute));
124116 LastExecOut = GetterNode->FindPinChecked (UEdGraphSchema_K2::PN_Then);
125117
@@ -138,7 +130,6 @@ void UK2Node_ExecuteFunctionHandler::ExpandNode(
138130 }
139131 }
140132
141- // Wire final exec out to our Then pin.
142133 CompilerContext.MovePinLinksToIntermediate (
143134 *FindPinChecked (UEdGraphSchema_K2::PN_Then),
144135 *LastExecOut);
@@ -152,7 +143,6 @@ FText UK2Node_ExecuteFunctionHandler::GetNodeTitle(ENodeTitleType::Type TitleTyp
152143 {
153144 return LOCTEXT (" NodeTitle" , " Execute Function Handler" );
154145 }
155-
156146 return FText::Format (
157147 LOCTEXT (" NodeTitleWithFunc" , " Execute Handler: {0}" ),
158148 FText::FromName (CachedFunctionName));
@@ -163,11 +153,6 @@ FText UK2Node_ExecuteFunctionHandler::GetTooltipText() const
163153 return LOCTEXT (" Tooltip" , " Execute a function on the target using stored parameters from the handler, with typed result outputs." );
164154}
165155
166- FText UK2Node_ExecuteFunctionHandler::GetMenuCategory () const
167- {
168- return LOCTEXT (" MenuCategory" , " FunctionHandler" );
169- }
170-
171156void UK2Node_ExecuteFunctionHandler::GetMenuActions (
172157 FBlueprintActionDatabaseRegistrar& ActionRegistrar) const
173158{
@@ -186,55 +171,12 @@ void UK2Node_ExecuteFunctionHandler::ReallocatePinsDuringReconstruction(
186171 RestoreSplitPins (OldPins);
187172}
188173
189- void UK2Node_ExecuteFunctionHandler::PinConnectionListChanged (UEdGraphPin* Pin)
190- {
191- Super::PinConnectionListChanged (Pin);
192-
193- if (Pin && Pin->PinName == PN_Handler)
194- {
195- RefreshFromHandler ();
196- }
197- }
198-
199174void UK2Node_ExecuteFunctionHandler::PinDefaultValueChanged (UEdGraphPin* Pin)
200175{
201176 Super::PinDefaultValueChanged (Pin);
202177 RefreshFromHandler ();
203178}
204179
205- void UK2Node_ExecuteFunctionHandler::PostReconstructNode ()
206- {
207- Super::PostReconstructNode ();
208- BindBlueprintCompileDelegate ();
209- }
210-
211- void UK2Node_ExecuteFunctionHandler::PostPasteNode ()
212- {
213- Super::PostPasteNode ();
214- RefreshFromHandler ();
215- }
216-
217- void UK2Node_ExecuteFunctionHandler::DestroyNode ()
218- {
219- UnbindBlueprintCompileDelegate ();
220- Super::DestroyNode ();
221- }
222-
223- FSlateIcon UK2Node_ExecuteFunctionHandler::GetIconAndTint (FLinearColor& OutColor) const
224- {
225- OutColor = FLinearColor (0 .8f , 0 .3f , 0 .05f );
226- return FSlateIcon (FAppStyle::GetAppStyleSetName (), " Kismet.AllClasses.FunctionIcon" );
227- }
228-
229- FLinearColor UK2Node_ExecuteFunctionHandler::GetNodeTitleColor () const
230- {
231- return FLinearColor (0 .8f , 0 .3f , 0 .05f );
232- }
233-
234- #pragma endregion UK2Node
235-
236- #pragma region Helpers
237-
238180void UK2Node_ExecuteFunctionHandler::CreateOutputPinsForFunction (UFunction* Function)
239181{
240182 const UEdGraphSchema_K2* Schema = GetDefault<UEdGraphSchema_K2>();
@@ -266,144 +208,4 @@ void UK2Node_ExecuteFunctionHandler::CreateOutputPinsForFunction(UFunction* Func
266208 }
267209}
268210
269- UFunction* UK2Node_ExecuteFunctionHandler::TryResolveHandlerFunction ()
270- {
271- // Try to read from linked Handler variable.
272- const UEdGraphPin* HandlerPin = FindPin (PN_Handler);
273- if (HandlerPin && HandlerPin->LinkedTo .Num () == 1 )
274- {
275- const UEdGraphPin* SourcePin = HandlerPin->LinkedTo [0 ];
276- if (SourcePin)
277- {
278- // Resolve from MakeFunctionHandler node.
279- const UK2Node_MakeFunctionHandler* MakeNode = Cast<UK2Node_MakeFunctionHandler>(SourcePin->GetOwningNode ());
280- if (MakeNode)
281- {
282- if (UFunction* Func = MakeNode->GetTargetFunction ())
283- {
284- CachedTargetClass = MakeNode->TargetClass ;
285- CachedFunctionName = Func->GetFName ();
286- }
287- }
288-
289- // Resolve from variable getter via CDO.
290- const UK2Node_VariableGet* VarGetNode = Cast<UK2Node_VariableGet>(SourcePin->GetOwningNode ());
291- if (VarGetNode)
292- {
293- const UBlueprint* BP = FBlueprintEditorUtils::FindBlueprintForNode (this );
294- UClass* GenClass = BP ? (BP->GeneratedClass ? BP->GeneratedClass : BP->SkeletonGeneratedClass ) : nullptr ;
295- if (GenClass)
296- {
297- const FStructProperty* StructProp = CastField<FStructProperty>(
298- GenClass->FindPropertyByName (VarGetNode->GetVarName ()));
299-
300- if (StructProp && StructProp->Struct == FFunctionHandler::StaticStruct ())
301- {
302- const UObject* CDO = GenClass->GetDefaultObject (false );
303- if (CDO)
304- {
305- const FFunctionHandler* Handler = StructProp->ContainerPtrToValuePtr <FFunctionHandler>(CDO);
306- if (Handler && Handler->IsValid () && Handler->TargetClass )
307- {
308- CachedTargetClass = Handler->TargetClass ;
309- CachedFunctionName = Handler->FunctionName ;
310- }
311- }
312- }
313- }
314- }
315-
316- // Fallback: resolve from intermediate CallFunction node wrapping InternalMakeFunctionHandler.
317- // This handles the case where MakeFunctionHandler was already expanded before us.
318- if (CachedFunctionName.IsNone ())
319- {
320- const UK2Node_CallFunction* CallNode = Cast<UK2Node_CallFunction>(SourcePin->GetOwningNode ());
321- if (CallNode)
322- {
323- static const FName InternalMakeName = GET_FUNCTION_NAME_CHECKED (UFunctionHandlerLibrary, InternalMakeFunctionHandler);
324- if (CallNode->GetFunctionName () == InternalMakeName)
325- {
326- const UEdGraphPin* ClassPin = CallNode->FindPin (TEXT (" TargetClass" ));
327- const UEdGraphPin* FuncNamePin = CallNode->FindPin (TEXT (" FunctionName" ));
328- if (ClassPin && FuncNamePin)
329- {
330- UClass* ResolvedClass = Cast<UClass>(ClassPin->DefaultObject );
331- FName ResolvedFuncName = FName (*FuncNamePin->DefaultValue );
332- if (ResolvedClass && !ResolvedFuncName.IsNone ())
333- {
334- CachedTargetClass = ResolvedClass;
335- CachedFunctionName = ResolvedFuncName;
336- }
337- }
338- }
339- }
340- }
341- }
342- }
343-
344- // Fallback to cached values (during reconstruction when pins aren't linked yet).
345- if (CachedTargetClass && !CachedFunctionName.IsNone ())
346- {
347- return CachedTargetClass->FindFunctionByName (CachedFunctionName);
348- }
349-
350- return nullptr ;
351- }
352-
353- void UK2Node_ExecuteFunctionHandler::RefreshFromHandler ()
354- {
355- if (bIsRefreshing)
356- {
357- return ;
358- }
359-
360- bIsRefreshing = true ;
361-
362- const FName OldFunctionName = CachedFunctionName;
363- const TSubclassOf<UObject> OldTargetClass = CachedTargetClass;
364-
365- // Clear cache to force a fresh read.
366- CachedTargetClass = nullptr ;
367- CachedFunctionName = NAME_None;
368-
369- TryResolveHandlerFunction ();
370-
371- if (CachedFunctionName != OldFunctionName || CachedTargetClass != OldTargetClass)
372- {
373- ReconstructNode ();
374- }
375-
376- bIsRefreshing = false ;
377- }
378-
379- void UK2Node_ExecuteFunctionHandler::BindBlueprintCompileDelegate ()
380- {
381- UBlueprint* BP = FBlueprintEditorUtils::FindBlueprintForNode (this );
382- if (!BP || BoundBlueprint == BP)
383- {
384- return ;
385- }
386-
387- UnbindBlueprintCompileDelegate ();
388-
389- BP->OnCompiled ().AddUObject (this , &UK2Node_ExecuteFunctionHandler::OnBlueprintCompiled);
390- BoundBlueprint = BP;
391- }
392-
393- void UK2Node_ExecuteFunctionHandler::UnbindBlueprintCompileDelegate ()
394- {
395- if (UBlueprint* BP = BoundBlueprint.Get ())
396- {
397- BP->OnCompiled ().RemoveAll (this );
398- BoundBlueprint = nullptr ;
399- }
400- }
401-
402- void UK2Node_ExecuteFunctionHandler::OnBlueprintCompiled (UBlueprint* Blueprint)
403- {
404- RefreshFromHandler ();
405- }
406-
407- #pragma endregion Helpers
408-
409- #undef LOCTEXT_NAMESPACE
211+ #undef LOCTEXT_NAMESPACE
0 commit comments