View difference between Paste ID: h4dmuHYf and qkWhr31q
SHOW: | | - or go back to the newest paste.
1
#include "SagaEditor.h"
2
#include "UObject/UnrealType.h"
3
#include "EdGraph/EdGraphPin.h"
4
#include "Kismet/KismetSystemLibrary.h"
5
#include "EdGraphSchema_K2.h"
6
#include "K2Node_CallFunction.h"
7
#include "K2Node_AssignmentStatement.h"
8
#include "K2Node_CustomEvent.h"
9
#include "K2Node_TemporaryVariable.h"
10
#include "KismetCompiler.h"
11
#include "BlueprintNodeSpawner.h"
12
#include "BlueprintActionDatabaseRegistrar.h"
13
#include "K2Node_Await.h"
14
#include "Network/WarholdNetworkClasses.h"
15
#include "K2Node_GetDataTableRow.h"
16
#include "Network/UE4App.h"
17
#include "BlueprintEditorUtils.h"
18
#include "SGraphNode.h"
19
#include "ContentBrowserModule.h"
20
#include "Private/SAssetDialog.h"
21
#include "GraphEditorSettings.h"
22
23
#define LOCTEXT_NAMESPACE "K2Node_WN"
24
25
void UK2Node_WN_Await::AllocateDefaultPins()
26
{
27
	const UEdGraphSchema_K2* K2Schema = Cast<UEdGraphSchema_K2>(GetSchema());
28
29
	CachedFunctionName = TEXT("...");
30
31
	if (K2Schema)
32
	{
33
		CreatePin(EGPD_Input, K2Schema->PC_Exec, TEXT(""), nullptr, false, false, K2Schema->PN_Execute);
34
		UEdGraphPin* OutputExecPin = CreatePin(EGPD_Output, K2Schema->PC_Exec, TEXT(""), nullptr, false, false, K2Schema->PN_Then);
35
		if (OutputExecPin)
36
		{
37
			OutputExecPin->PinFriendlyName = FText::FromString(K2Schema->PN_Completed);
38
		}
39
40
		CreatePin(EGPD_Input, K2Schema->PC_Object, TEXT(""), UMailbox::StaticClass(), false, false, TEXT("Target"), false, INDEX_NONE, false, false);
41
	}
42
}
43
44
void UK2Node_WN_Await::ReallocatePinsDuringReconstruction(TArray<UEdGraphPin*>& OldPins)
45
{
46
	AllocateDefaultPins();
47
48
	ConstructMethodPinByMailbox(&OldPins);
49
	MailboxPinChanged(&OldPins);
50
51
	RestoreSplitPins(OldPins);
52
}
53
54
void UK2Node_WN_Await::PinConnectionListChanged(UEdGraphPin* Pin)
55
{
56
	Super::PinConnectionListChanged(Pin);
57
58
	if (Pin->PinName == TEXT("Target"))
59
	{
60
		MailboxPinChanged();
61
62
		// Refresh the UI for the graph so the pin changes show up
63
		GetGraph()->NotifyGraphChanged();
64
		
65
		// Mark dirty
66
		FBlueprintEditorUtils::MarkBlueprintAsModified(GetBlueprint());
67
	}
68
}
69
70
71
UEdGraphPin* UK2Node_WN_Await::GetPinSpecified(FString PinName, TArray<UEdGraphPin*>* OldPins)
72
{
73
	if (OldPins != nullptr)
74
		for (auto& pin : *OldPins)
75
			if (pin->PinName == PinName)
76
				return pin;
77
	return FindPin(PinName);
78
}
79
80
UClass* UK2Node_WN_Await::GetMailboxClass(TArray<UEdGraphPin*>* OldPins)
81
{
82
	UEdGraphPin* target_pin = GetPinSpecified("Target", OldPins);
83
84
	UClass* MailboxClass = nullptr;
85
86
	if (target_pin && target_pin->DefaultObject && target_pin->LinkedTo.Num() == 0)
87
	{
88
		MailboxClass = Cast<UClass>(target_pin->DefaultObject);
89
	}
90
	else if (target_pin && target_pin->LinkedTo.Num())
91
	{
92
		UEdGraphPin* ClassSource = target_pin->LinkedTo[0];
93
		MailboxClass = ClassSource ? Cast<UClass>(ClassSource->PinType.PinSubCategoryObject.Get()) : nullptr;
94
	}
95
96
	return MailboxClass;
97
}
98
99
UEdGraphPin* UK2Node_WN_Await::ConstructMethodPinByMailbox(TArray<UEdGraphPin*>* OldPins, bool bRemovePrevious)
100
{
101
	CachedMailboxName = TEXT("");
102
103
	const UEdGraphSchema_K2* K2Schema = Cast<UEdGraphSchema_K2>(GetSchema());
104
105
	UEdGraphPin* method_pin = nullptr;
106
107
	if (K2Schema)
108
	{
109
		UClass* MailboxClass = GetMailboxClass(OldPins);
110
		
111
		if (!MailboxClass)
112
			CachedFunctionName = TEXT("...");
113
114
		MailboxFunctionNames.Empty();
115
		if (MailboxClass)
116
		{
117
118
			CachedMailboxName = MailboxClass->GetName();
119
			for (auto func : TFieldRange<UFunction>(MailboxClass))
120
			{
121
				if (func->FunctionFlags & FUNC_BlueprintCallable)
122
					if (auto ret_property = Cast<UObjectPropertyBase>(func->GetReturnProperty()))
123
					{
124
						if (ret_property->PropertyClass && ret_property->PropertyClass->IsChildOf<UFuture>())
125
						{
126
							MailboxFunctionNames.Add(*func->GetName());
127
						}
128
					}
129
			}
130
		}
131
132
		method_pin = GetPinSpecified(TEXT("Method"), OldPins);
133
134
		if (bRemovePrevious && method_pin && OldPins == nullptr)
135
			RemovePin(method_pin);
136
137
		if (MailboxClass && MailboxClass != UMailbox::StaticClass() && method_pin == nullptr)
138
			method_pin = CreatePin(EGPD_Input, K2Schema->PC_Name, TEXT(""), nullptr, false, false, TEXT("Method"), false, INDEX_NONE, false, false);
139
140
		if (method_pin)
141
			method_pin->bHidden = false;
142
	}
143
144
	return method_pin;
145
}
146
147
void UK2Node_WN_Await::MailboxPinChanged(TArray<UEdGraphPin*>* OldPins)
148
{
149
150
	const UEdGraphSchema_K2* K2Schema = Cast<UEdGraphSchema_K2>(GetSchema());
151
152
	if (K2Schema)
153
	{
154
		UClass* MailboxClass = GetMailboxClass(OldPins);
155
156
		UFunction* func = nullptr;
157
158
		UEdGraphPin* method_pin = ConstructMethodPinByMailbox(OldPins, MailboxClass != CurrentMailboxClass || MailboxClass == nullptr);
159
160
		if (MailboxClass)
161
			func = GetMailboxFunction(MailboxClass, *method_pin->DefaultValue);
162
163
164
		if (func != CurrentFunction || MailboxClass != CurrentMailboxClass || func == nullptr || MailboxClass == nullptr)
165
		{
166
			// Clears all previous pins
167
			for (auto pin : CachedPins)
168
				RemovePin(pin);
169
			CachedPins.Empty();
170
171
			CurrentFunction = func;
172
			CurrentMailboxClass = MailboxClass;
173
		} else
174
		{
175
			return;
176
		}
177
178
		CachedMailboxName = TEXT("");
179
180
		if (MailboxClass)
181
		{
182
			CachedMailboxName = MailboxClass->GetName();
183
184
			method_pin->bHidden = false;
185
186
			if (func)
187
			{
188
				CachedFunctionName = method_pin->DefaultValue;
189
				const UObject* const ClassDefaultObject = MailboxClass->GetDefaultObject(false);
190
191
				UObjectPropertyBase* ReturnProperty = Cast<UObjectPropertyBase>(func->GetReturnProperty());
192
193
				const TArray<UEdGraphPin*> in_pins = GeneratePinsForAsyncFunction(func, EGPD_Input);
194
				CachedPins.Append(in_pins);
195
196
				if (ReturnProperty)
197
				{
198
					UFunction* exec_func_return = ReturnProperty->PropertyClass->FindFunctionByName(TEXT("Execute"));
199
					const TArray<UEdGraphPin*> out_pins = GeneratePinsForAsyncFunction(exec_func_return, EGPD_Output);
200
					CachedPins.Append(out_pins);
201
				}
202
203
			}
204
			else
205
			{
206
207
				CachedFunctionName = TEXT("...");
208
			}
209
		}
210
	}
211
}
212
213
UFunction* UK2Node_WN_Await::GetMailboxFunction(UClass* MailboxClass, FName FunctionName)
214
{
215
	if (MailboxClass)
216
		for (auto func : TFieldRange<UFunction>(MailboxClass))
217
			if (func->FunctionFlags & FUNC_BlueprintCallable)
218
				if (auto ret_property = Cast<UObjectPropertyBase>(func->GetReturnProperty()))
219
					if (ret_property->PropertyClass && ret_property->PropertyClass->IsChildOf<UFuture>())
220
						if (func->GetName() == FunctionName.ToString())
221
							return func;
222
	return nullptr;
223
}
224
225
TArray<UEdGraphPin*> UK2Node_WN_Await::GeneratePinsForAsyncFunction(UFunction* func, EEdGraphPinDirection direction)
226
{
227
	TArray<UEdGraphPin*> OutPins;
228
	const UEdGraphSchema_K2* K2Schema = Cast<UEdGraphSchema_K2>(GetSchema());
229
	if (K2Schema && func)
230
	{
231
		UProperty* ReturnProperty = func->GetReturnProperty();
232
		for (TFieldIterator<UProperty> PropertyIt(func, EFieldIteratorFlags::IncludeSuper); PropertyIt; ++PropertyIt)
233
		{
234
			UProperty* Property = *PropertyIt;
235
			if (*PropertyIt != ReturnProperty)
236
				if (FBlueprintEditorUtils::PropertyStillExists(Property))
237
					if (UEdGraphPin* Pin = CreatePin(direction, FString(), FString(), nullptr, Property->GetName()))
238
					{
239
						K2Schema->ConvertPropertyToPinType(Property, /*out*/ Pin->PinType);
240
						OutPins.Add(Pin);
241
					}
242
		}
243
	}
244
	return OutPins;
245
}
246
247
void UK2Node_WN_Await::ExpandNode(class FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph)
248
{
249
	Super::ExpandNode(CompilerContext, SourceGraph);
250
251
	// TODO: Currently turned off due to reorganization of node from generated to customizable!
252
253
	//const UEdGraphSchema_K2* Schema = CompilerContext.GetSchema();
254
	//check(Schema);
255
	//bool bIsErrorFree = true;
256
	//const UEdGraphSchema_K2* K2Schema = Cast<UEdGraphSchema_K2>(GetSchema());
257
	//// Create intermediate function call
258
	//auto CallIntermediateFunctionNode = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this, SourceGraph);
259
	//CallIntermediateFunctionNode->FunctionReference.SetExternalMember(NativeFunctionName(), GetTargetClass());
260
	//CallIntermediateFunctionNode->AllocateDefaultPins();
261
	//
262
	//TArray<FString> retvals;
263
    //TMap<FString, UObject*> retclasses;
264
	//TMap<FString, bool> ret_bisarrays;
265
	//
266
    //
267
	//retvals.Add(TEXT("RetVal1"));
268
	//retclasses.Add(TEXT("RetVal1"), USessionBaseMailbox::StaticClass());
269
	//ret_bisarrays.Add(TEXT("RetVal1"), false);
270
	//
271
	//retvals.Add(TEXT("RetVal2"));
272
	//retclasses.Add(TEXT("RetVal2"), FindObject<UEnum>(ANY_PACKAGE, TEXT("ELoginResult"), true));
273
	//ret_bisarrays.Add(TEXT("RetVal2"), false);
274
	//
275
	//retvals.Add(TEXT("RetVal3"));
276
	//retclasses.Add(TEXT("RetVal3"), nullptr);
277
	//ret_bisarrays.Add(TEXT("RetVal3"), false);
278
	//
279
	//
280
	//
281
	//TArray<FString> connectors;
282
	//
283
	//connectors.Add(TEXT("username"));
284
	//connectors.Add(TEXT("password"));
285
	//
286
	//
287
	//
288
	//// connect to input exe
289
	//{
290
	//	auto InputExePin = GetExecPin();
291
	//	auto CallFunctionInputExePin = CallIntermediateFunctionNode->GetExecPin();
292
	//	bIsErrorFree &= InputExePin && CallFunctionInputExePin && CompilerContext.MovePinLinksToIntermediate(*InputExePin, *CallFunctionInputExePin).CanSafeConnect();
293
	//}
294
	//
295
	//TMap<FString, UK2Node_AssignmentStatement*> assignment_nodes_by_name;
296
	//TArray<UK2Node_AssignmentStatement*>  assignment_nodes;
297
	///// RetVals assignment section
298
	//
299
	//for (auto& retval_name : retvals)
300
	//{
301
	//	// Create Local Variable (for RetVal1)
302
	//	auto PinCategory = FindPin(retval_name)->PinType.PinCategory;
303
	//	// TODO: Old: // UK2Node_TemporaryVariable* TempVarOutput = CompilerContext.SpawnInternalVariable(this, PinCategory, FString(""), retclasses[retval_name], ret_bisarrays[retval_name]);
304
    //    UK2Node_TemporaryVariable* TempVarOutput = CompilerContext.SpawnInternalVariable(this, PinCategory, FString(""), retclasses[retval_name], FEdGraphPinType::ToPinContainerType(ret_bisarrays[retval_name], false, false));
305
	//
306
	//	// Create assign node (for RetVal1)
307
	//	UK2Node_AssignmentStatement* AssignNode = CompilerContext.SpawnIntermediateNode<UK2Node_AssignmentStatement>(this, SourceGraph);
308
	//	assignment_nodes_by_name.Add(retval_name, AssignNode);
309
	//	assignment_nodes.Add(AssignNode);
310
	//
311
	//	AssignNode->AllocateDefaultPins();
312
	//
313
	//
314
	//	auto RetVal_VariablePin = TempVarOutput->GetVariablePin();
315
	//
316
	//	// connect local variable (for RetVal1) to assign node
317
	//	auto AssignLHSPPin = AssignNode->GetVariablePin();
318
	//	bIsErrorFree &= AssignLHSPPin && RetVal_VariablePin && Schema->TryCreateConnection(AssignLHSPPin, RetVal_VariablePin);
319
	//
320
	//	// connect local variable (for RetVal1) to output
321
	//	auto OutputObjectPinPin = FindPin(retval_name);
322
	//	bIsErrorFree &= RetVal_VariablePin && OutputObjectPinPin && CompilerContext.MovePinLinksToIntermediate(*OutputObjectPinPin, *RetVal_VariablePin).CanSafeConnect();
323
	//}
324
	//
325
	//auto SchemaThen = FindPin(Schema->PN_Then);
326
	//auto FirstPin = CallIntermediateFunctionNode->FindPin(Schema->PN_Then);
327
	//auto LastPin = SchemaThen;
328
	//
329
	//for (int32 i = 0; i < assignment_nodes.Num(); i++)
330
	//{
331
	//	auto AssignNode = assignment_nodes[i];
332
	//
333
	//	UEdGraphPin* PrevPin = (i == 0)								? FirstPin : assignment_nodes[i - 1]->GetThenPin();
334
	//	UEdGraphPin* NextPin = (i == assignment_nodes.Num() - 1)	? LastPin  : assignment_nodes[i + 1]->GetThenPin();
335
	//
336
	//	// connect assign (for RetVal1) exec input to function output
337
	//	auto AssignInputExePin = AssignNode->GetExecPin();
338
	//	bIsErrorFree &= AssignInputExePin && PrevPin && Schema->TryCreateConnection(AssignInputExePin, PrevPin);
339
	//
340
	//	// auto AssignOutputExePin = AssignNode->GetThenPin();
341
	//	// bIsErrorFree &= NextPin && AssignOutputExePin && Schema->TryCreateConnection(NextPin, AssignOutputExePin);
342
	//	if (i == assignment_nodes.Num() - 1)
343
	//	{
344
	//		auto AssignInputThenPin = AssignNode->GetThenPin();
345
	//		bIsErrorFree &= AssignInputThenPin && LastPin && CompilerContext.MovePinLinksToIntermediate(*LastPin, *AssignInputThenPin).CanSafeConnect();
346
	//	}
347
	//
348
	//}
349
	//
350
	//
351
	//
352
	//
353
	///// END OF assignment sections
354
	//
355
	//
356
	//// connect to Target
357
	//auto CallIntermediateFunctionNodePin = CallIntermediateFunctionNode->FindPin(TEXT("Target"));
358
	//{
359
	//	auto TargetPin = FindPin(TEXT("Target"));
360
	//	ensure(CallIntermediateFunctionNodePin);
361
	//	bIsErrorFree &= TargetPin && CallIntermediateFunctionNodePin && CompilerContext.MovePinLinksToIntermediate(*TargetPin, *CallIntermediateFunctionNodePin).CanSafeConnect();
362
	//}
363
	//
364
	//// Iterate over all named parameters
365
	//for (auto& connector : connectors)
366
	//{
367
	//	auto IntermediatePin = CallIntermediateFunctionNode->FindPin(connector);
368
	//	auto Pin = FindPin(connector);
369
	//	ensure(IntermediatePin);
370
	//	bIsErrorFree &= Pin && IntermediatePin && CompilerContext.MovePinLinksToIntermediate(*Pin, *IntermediatePin).CanSafeConnect();
371
	//}
372
	//
373
	//// Create OnLoadEvent
374
	//const FString DelegateOnLoadedParamName(TEXT("OnDone"));
375
	//auto OnDoneEventNode = CompilerContext.SpawnIntermediateEventNode<UK2Node_CustomEvent>(this, CallIntermediateFunctionNodePin, SourceGraph);
376
	//OnDoneEventNode->CustomFunctionName = *FString::Printf(TEXT("OnDone_%s"), *CompilerContext.GetGuid(this));
377
	//OnDoneEventNode->AllocateDefaultPins();
378
	//{
379
	//	UFunction* LoadAssetFunction = CallIntermediateFunctionNode->GetTargetFunction();
380
	//	UDelegateProperty* OnLoadDelegateProperty = LoadAssetFunction ? FindField<UDelegateProperty>(LoadAssetFunction, *DelegateOnLoadedParamName) : nullptr;
381
	//	UFunction* OnLoadedSignature = OnLoadDelegateProperty ? OnLoadDelegateProperty->SignatureFunction : nullptr;
382
	//	ensure(OnLoadedSignature);
383
	//	for (TFieldIterator<UProperty> PropIt(OnLoadedSignature); PropIt && (PropIt->PropertyFlags & CPF_Parm); ++PropIt)
384
	//	{
385
	//		const UProperty* Param = *PropIt;
386
	//		if (!Param->HasAnyPropertyFlags(CPF_OutParm) || Param->HasAnyPropertyFlags(CPF_ReferenceParm))
387
	//		{
388
	//			FEdGraphPinType PinType;
389
	//			bIsErrorFree &= Schema->ConvertPropertyToPinType(Param, /*out*/ PinType);
390
	//			bIsErrorFree &= (NULL != OnDoneEventNode->CreateUserDefinedPin(Param->GetName(), PinType, EGPD_Output));
391
	//		}
392
	//	}
393
	//}
394
	//
395
	//// connect delegate
396
	//{
397
	//	auto CallFunctionDelegatePin = CallIntermediateFunctionNode->FindPin(DelegateOnLoadedParamName);
398
	//	ensure(CallFunctionDelegatePin);
399
	//	auto EventDelegatePin = OnDoneEventNode->FindPin(UK2Node_CustomEvent::DelegateOutputName);
400
	//	bIsErrorFree &= CallFunctionDelegatePin && EventDelegatePin && Schema->TryCreateConnection(CallFunctionDelegatePin, EventDelegatePin);
401
	//}
402
	//
403
	//// connect loaded object from event to assign
404
	//for (auto& pair : assignment_nodes_by_name)
405
	//{
406
	//	auto RetValEventPin = OnDoneEventNode->FindPin(pair.Key);
407
	//	ensure(RetValEventPin);
408
	//	auto AssignRHSPPin = pair.Value->GetValuePin();
409
	//	bIsErrorFree &= AssignRHSPPin && RetValEventPin && Schema->TryCreateConnection(RetValEventPin, AssignRHSPPin);
410
	//}
411
	//
412
	//if (!bIsErrorFree)
413
	//{
414
	//	CompilerContext.MessageLog.Error(*LOCTEXT("InternalConnectionError", "K2Node_WN_K2Node_BaseApp_login_LatentFunction: Internal connection error. @@").ToString(), this);
415
	//}
416
	//
417
	BreakAllNodeLinks();
418
}
419
420
FText UK2Node_WN_Await::GetTooltipText() const
421
{
422
	return FText::Format(LOCTEXT("Await::GetTooltipText", "await {0}:{1}"), FText::FromString(CachedMailboxName), FText::FromString(CachedFunctionName));
423
}
424
425
void UK2Node_WN_Await::PinDefaultValueChanged(UEdGraphPin* Pin)
426
{
427
	if (Pin->PinName == TEXT("Method"))
428
	{
429
		MailboxPinChanged();
430
431
		// Refresh the UI for the graph so the pin changes show up
432
		GetGraph()->NotifyGraphChanged();
433
434
		// Mark dirty
435
		FBlueprintEditorUtils::MarkBlueprintAsModified(GetBlueprint());
436
	}
437
}
438
439
FText UK2Node_WN_Await::GetNodeTitle(ENodeTitleType::Type TitleType) const
440
{
441
	return FText::Format(LOCTEXT("Await::GetNodeTitle", "await {0}"), FText::FromString(CachedFunctionName));
442
}
443
444
bool UK2Node_WN_Await::IsCompatibleWithGraph(const UEdGraph* TargetGraph) const
445
{
446
	bool bIsCompatible = false;
447
	// Can only place events in ubergraphs and macros (other code will help prevent macros with latents from ending up in functions), and basicasync task creates an event node:
448
	EGraphType GraphType = TargetGraph->GetSchema()->GetGraphType(TargetGraph);
449
	if (GraphType == EGraphType::GT_Ubergraph || GraphType == EGraphType::GT_Macro)
450
	{
451
		bIsCompatible = true;
452
	}
453
	return bIsCompatible && Super::IsCompatibleWithGraph(TargetGraph);
454
}
455
456
FLinearColor UK2Node_WN_Await::GetNodeTitleColor() const
457
{
458
	return FLinearColor(1.f, 0.3, 0.3, 1.f);
459
}
460
461
FName UK2Node_WN_Await::GetCornerIcon() const
462
{
463
	return TEXT("Graph.Latent.LatentIcon");
464
}
465
466
void UK2Node_WN_Await::GetMenuActions(FBlueprintActionDatabaseRegistrar& ActionRegistrar) const
467
{
468
	// actions get registered under specific object-keys; the idea is that
469
	// actions might have to be updated (or deleted) if their object-key is
470
	// mutated (or removed)... here we use the node's class (so if the node
471
	// type disappears, then the action should go with it)
472
	UClass* ActionKey = GetClass();
473
	// to keep from needlessly instantiating a UBlueprintNodeSpawner, first
474
	// check to make sure that the registrar is looking for actions of this type
475
	// (could be regenerating actions for a specific asset, and therefore the
476
	// registrar would only accept actions corresponding to that asset)
477
	if (ActionRegistrar.IsOpenForRegistration(ActionKey))
478
	{
479
		UBlueprintNodeSpawner* NodeSpawner = UBlueprintNodeSpawner::Create(GetClass());
480
		check(NodeSpawner != nullptr);
481
482
		ActionRegistrar.AddBlueprintAction(ActionKey, NodeSpawner);
483
	}
484
}
485
486
FText UK2Node_WN_Await::GetMenuCategory() const
487
{
488
	return FText(LOCTEXT("Await", "Utilities"));
489
}
490
491
TSharedPtr<SGraphNode> UK2Node_WN_Await::CreateVisualWidget()
492
{
493
494
	return SNew(SK2Node_MethodsDropdown, this);
495
}
496
497
498
499
500
const UEdGraphSchema_K2* UK2Node_WN_Await::GetK2Schema()
501
{
502
	return CastChecked<UEdGraphSchema_K2>(GetSchema());
503
}
504
505
/// SK2Node_MethodsDropdown
506
507
SK2Node_MethodsDropdown::FArguments::FArguments()
508
{
509
	
510
}
511
512
513
void SK2Node_MethodsDropdown::Construct(const FArguments& InArgs, UK2Node_WN_Await* InNode)
514
{
515
	GraphNode = InNode;
516
	Names = InNode->MailboxFunctionNames;
517
	CurrentIcon = FSlateIcon();
518
	UpdateGraphNode();
519
}
520
521
void SK2Node_MethodsDropdown::CreateStandardPinWidget(UEdGraphPin* Pin)
522
{
523
	if (Pin->PinName == "Method")
524
	{
525
		CreateDetailsPickers();
526
	}
527
	else
528
	{
529
		SGraphNode::CreateStandardPinWidget(Pin);
530
	}
531
}
532
533
TSharedRef<SWidget> SK2Node_MethodsDropdown::GetPickerMenu()
534
{
535
	// Close self only to enable use inside context menus
536
	FMenuBuilder MenuBuilder(true, nullptr, nullptr, true);
537
538
539
	FSlateIcon Icon;
540
541
	for (auto name : Names)
542
	{
543
		MenuBuilder.AddMenuEntry(
544
			FText::FromName(name),
545
			FText(),
546
			Icon,
547
			FUIAction(
548
				FExecuteAction::CreateRaw(this, &SK2Node_MethodsDropdown::SetMethodName, name)
549
			)
550
		);
551
	}
552
553
554
	return MenuBuilder.MakeWidget();
555
}
556
557
void SK2Node_MethodsDropdown::OnAssetSelectedFromPicker(const FAssetData& AssetData)
558
{
559
	UpdateGraphNode();
560
}
561
562
FText SK2Node_MethodsDropdown::GetAssetName() const
563
{
564
	return FText(); 
565
}
566
567
void SK2Node_MethodsDropdown::CreateDetailsPickers()
568
{
569
	LeftNodeBox->AddSlot()
570
	           .AutoHeight()
571
	           .HAlign(HAlign_Left)
572
	           .VAlign(VAlign_Center)
573
	           .Padding(Settings->GetInputPinPadding())
574
	[
575
		SNew(SBox)
576
		.MaxDesiredWidth(200.0f)
577
		.Padding(FMargin(2, 0))
578
		[
579
			SNew(SComboButton)
580
			.ButtonStyle(FEditorStyle::Get(), "PropertyEditor.AssetComboStyle")
581
			// .ToolTipText(this, &SGraphNodeGetSequenceBinding::GetToolTipText)
582
			.ForegroundColor(this, &SK2Node_MethodsDropdown::OnGetComboForeground)
583
			.ButtonColorAndOpacity(this, &SK2Node_MethodsDropdown::OnGetWidgetBackground)
584
			.ContentPadding(FMargin(2, 2, 2, 1))
585
			.MenuPlacement(MenuPlacement_BelowAnchor)
586
			.ButtonContent()
587
			[
588
				/// 
589
				GetCurrentItemWidget(
590
					SNew(STextBlock)
591
					.TextStyle(FEditorStyle::Get(), "PropertyEditor.AssetClass")
592
					.Font(FEditorStyle::GetFontStyle("PropertyWindow.NormalFont"))
593
				)
594
				///
595
			]
596
			.OnGetMenuContent(this, &SK2Node_MethodsDropdown::GetPickerMenu)
597
		]
598
	];
599
}
600
601
TSharedRef<SWidget> SK2Node_MethodsDropdown::GetCurrentItemWidget(TSharedRef<STextBlock> TextContent)
602
{
603
	TextContent->SetText(TAttribute<FText>::Create(TAttribute<FText>::FGetter::CreateRaw(this, &SK2Node_MethodsDropdown::GetCurrentText)));
604
605
	return SNew(SHorizontalBox)
606
		+ SHorizontalBox::Slot()
607
		.AutoWidth()
608
		[
609
			SNew(SOverlay)
610
			+ SOverlay::Slot()
611
		[
612
			SNew(SImage)
613
			.Image_Raw(this, &SK2Node_MethodsDropdown::GetCurrentIconBrush)
614
		]
615
616
	+ SOverlay::Slot()
617
		.VAlign(VAlign_Top)
618
		.HAlign(HAlign_Right)
619
		[
620
			SNew(SImage)
621
			// .Visibility_Raw(this, &::GetSpawnableIconOverlayVisibility)
622
		.Image(FEditorStyle::GetBrush("Sequencer.SpawnableIconOverlay"))
623
		]
624
		]
625
626
	+ SHorizontalBox::Slot()
627
		.Padding(4.f, 0, 0, 0)
628
		.VAlign(VAlign_Center)
629
		[
630
			TextContent
631
		];
632
}
633
634
FText SK2Node_MethodsDropdown::GetCurrentText()
635
{
636
	if (auto node = Cast<UK2Node_WN_Await>(GraphNode))
637
		if (node->CurrentFunction)
638
			return node->CurrentFunction->GetDisplayNameText();
639
	
640
	return LOCTEXT("SelectMethod", "Select method");
641
}
642
643
const FSlateBrush* SK2Node_MethodsDropdown::GetCurrentIconBrush() const
644
{
645
	return CurrentIcon.GetOptionalIcon();
646
}
647
648
void SK2Node_MethodsDropdown::SetMethodName(FName InName)
649
{
650
	if (UEdGraphPin* method_pin = GraphNode->FindPin("Method"))
651
	{
652
		const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>();
653
654
		K2Schema->TrySetDefaultValue(*method_pin, InName.ToString());
655
	}
656
657
}
658
659
FSlateColor SK2Node_MethodsDropdown::OnGetComboForeground() const
660
{
661
	return FSlateColor(FLinearColor(1.f, 1.f, 1.f, IsHovered() ? 1.f : 0.6f));
662
}
663
664
FSlateColor SK2Node_MethodsDropdown::OnGetWidgetForeground() const
665
{
666
	return FSlateColor(FLinearColor(1.f, 1.f, 1.f, IsHovered() ? 1.f : 0.15f));
667
}
668
669
FSlateColor SK2Node_MethodsDropdown::OnGetWidgetBackground() const
670
{
671
{
672
	return FSlateColor(FLinearColor(1.f, 1.f, 1.f, IsHovered() ? 0.8f : 0.4f));
673
}
674
675
676
677
678
679
#undef LOCTEXT_NAMESPACE