//////////////////////////////////////////////////////////////////////////
// FStructureEditorUtils
UUserDefinedStruct* FStructureEditorUtils::CreateUserDefinedStruct(UObject* InParent, FName Name, EObjectFlags Flags)
{
    UUserDefinedStruct* Struct = NULL;

    if (UserDefinedStructEnabled())
    {
        Struct = NewObject<UUserDefinedStruct>(InParent, Name, Flags);
        check(Struct);
        Struct->EditorData = NewObject<UUserDefinedStructEditorData>(Struct, NAME_None, RF_Transactional);
        check(Struct->EditorData);

        Struct->Guid = FGuid::NewGuid();
        Struct->SetMetaData(TEXT("BlueprintType"), TEXT("true"));
        Struct->Bind();
        Struct->StaticLink(true);
        Struct->Status = UDSS_Error;

        {
            const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>();
            AddVariable(Struct, FEdGraphPinType(K2Schema->PC_Boolean, FString(), NULL, false, false));
        }
    }

    return Struct;
}
bool UCreatureAnimGraphSchema::TryCreateConnection(UEdGraphPin* A, UEdGraphPin* B) const
{
	if (A==B)
	{
		return false;
	}
	else
	{
		UCreatureAnimTransitionNode* TransitionNode = NewObject<UCreatureAnimTransitionNode>(A->GetOwningNode()->GetGraph());
		TransitionNode->NodePosX = (A->GetOwningNode()->NodePosX+ B->GetOwningNode()->NodePosX) / 2;
		TransitionNode->NodePosY = (A->GetOwningNode()->NodePosY+ B->GetOwningNode()->NodePosY) / 2;
		if (UCreatureStateMachineGraph* Graph = Cast<UCreatureStateMachineGraph>(TransitionNode->GetGraph()))
		{
			if (TransitionNode->CompiledTransition != nullptr)
			{
				TransitionNode->CompiledTransition = NewObject<UCreatureAnimTransition>(Graph->GetOuter());
				TransitionNode->CompiledTransition->AnimStateMachine = Graph->ParentStateMachine;
			}
		}
		A->MakeLinkTo(TransitionNode->CreatePin(EEdGraphPinDirection::EGPD_Input, A->PinType, FString("In")));
		TransitionNode->CreatePin(EEdGraphPinDirection::EGPD_Output, FEdGraphPinType(), FString("Out"))->MakeLinkTo(B);
		A->GetOwningNode()->GetGraph()->AddNode(TransitionNode);
		TransitionNode->TransitionTargetNode = Cast<UCreatureAnimStateNode>(B->GetOwningNode());
	}
	
	return true;
}
void UK2Node_ConvertAsset::RefreshPinTypes()
{
	const UEdGraphSchema_K2* K2Schema = CastChecked<UEdGraphSchema_K2>(GetSchema());
	auto InutPin = FindPin(UK2Node_ConvertAssetImpl::InputPinName);
	auto OutputPin = FindPin(UK2Node_ConvertAssetImpl::OutputPinName);
	ensure(InutPin && OutputPin);
	if (InutPin && OutputPin)
	{
		const bool bIsConnected = InutPin->LinkedTo.Num() > 0;
		UClass* TargetType = bIsConnected ? GetTargetClass() : nullptr;
		const bool bIsAssetClass = bIsConnected ? IsAssetClassType() : false;

		const FString InputCategory = bIsConnected
			? (bIsAssetClass ? K2Schema->PC_AssetClass : K2Schema->PC_Asset)
			: K2Schema->PC_Wildcard;
		InutPin->PinType = FEdGraphPinType(InputCategory, FString(), TargetType, false, false);

		const FString OutputCategory = bIsConnected
			? (bIsAssetClass ? K2Schema->PC_Class : K2Schema->PC_Object)
			: K2Schema->PC_Wildcard;
		OutputPin->PinType = FEdGraphPinType(OutputCategory, FString(), TargetType, false, false);

		PinTypeChanged(InutPin);
		PinTypeChanged(OutputPin);

		if (OutputPin->LinkedTo.Num())
		{
			UClass const* CallingContext = NULL;
			if (UBlueprint const* Blueprint = GetBlueprint())
			{
				CallingContext = Blueprint->GeneratedClass;
				if (CallingContext == NULL)
				{
					CallingContext = Blueprint->ParentClass;
				}
			}

			for (auto TargetPin : OutputPin->LinkedTo)
			{
				if (TargetPin && !K2Schema->ArePinsCompatible(OutputPin, TargetPin, CallingContext))
				{
					OutputPin->BreakLinkTo(TargetPin);
				}
			}
		}
	}
}
FEdGraphPinType UK2Node_CommutativeAssociativeBinaryOperator::GetType() const
{
	for (int32 PinIt = 0; PinIt < Pins.Num(); PinIt++)
	{
		if (Pins[PinIt] != FindSelfPin())
		{
			return Pins[PinIt]->PinType;
		}
	}
	return FEdGraphPinType();
}
UEdGraphNode* FEdGraphSchemaAction_NewCreatureStateNode::PerformAction(class UEdGraph* ParentGraph, UEdGraphPin* FromPin, const FVector2D Location, bool bSelectNewNode /*= true*/)
{
	UCreatureAnimStateNode* NewStateNode = NewObject<UCreatureAnimStateNode>(ParentGraph);
	NewStateNode->NodePosX = Location.X;
	NewStateNode->NodePosY = Location.Y;
	NewStateNode->InputPins.Add(NewStateNode->CreatePin(EEdGraphPinDirection::EGPD_Input, FEdGraphPinType(), TEXT("Input")));
	NewStateNode->InputPins.Add(NewStateNode->CreatePin(EEdGraphPinDirection::EGPD_Output, FEdGraphPinType(), TEXT("Output")));
	if (UCreatureStateMachineGraph* Graph=Cast<UCreatureStateMachineGraph>(NewStateNode->GetGraph()))
	{
		if (NewStateNode->CompiledState==nullptr)
		{
			NewStateNode->CompiledState = NewObject<UCreatureAnimState>(ParentGraph->GetOuter());
			NewStateNode->CompiledState->AnimStateMachine = Graph->ParentStateMachine;
		}	
	}
	ParentGraph->AddNode(NewStateNode, true, false);

	return NewStateNode;
}
FEdGraphPinType FStructVariableDescription::ToPinType() const
{
	return FEdGraphPinType(Category, SubCategory, SubCategoryObject.Get(), bIsArray, false);
}
UEdGraphNode* FEdGraphSchemaAction_NewCreatureAnimationEndTransition::PerformAction(class UEdGraph* ParentGraph, UEdGraphPin* FromPin, const FVector2D Location, bool bSelectNewNode /*= true*/)
{
	UCreatureAnimTransitionNode* NewAnimationEndTransitionNode = NewObject<UCreatureAnimTransitionNode>(ParentGraph);
	NewAnimationEndTransitionNode->NodePosX		= Location.X;
	NewAnimationEndTransitionNode->NodePosY		= Location.Y;
	NewAnimationEndTransitionNode->InputPin		= NewAnimationEndTransitionNode->CreatePin(EEdGraphPinDirection::EGPD_Input, FEdGraphPinType(), TEXT("Input"));
	NewAnimationEndTransitionNode->OutputPin	= NewAnimationEndTransitionNode->CreatePin(EEdGraphPinDirection::EGPD_Output, FEdGraphPinType(), TEXT("Output"));
	NewAnimationEndTransitionNode->TransitionCondition = FString(TEXT("AnimationEnd"));
	NewAnimationEndTransitionNode->TransitionFlag = true;
	ParentGraph->AddNode(NewAnimationEndTransitionNode, true, false);

	return NewAnimationEndTransitionNode;
}
void UK2Node_TemporaryVariable::GetMenuActions(FBlueprintActionDatabaseRegistrar& ActionRegistrar) const
{
	// actions get registered under specific object-keys; the idea is that 
	// actions might have to be updated (or deleted) if their object-key is  
	// mutated (or removed)... here we use the node's class (so if the node 
	// type disappears, then the action should go with it)
	UClass* ActionKey = GetClass();
	// to keep from needlessly instantiating a UBlueprintNodeSpawner, first   
	// check to make sure that the registrar is looking for actions of this type
	// (could be regenerating actions for a specific asset, and therefore the 
	// registrar would only accept actions corresponding to that asset)
	if (!ActionRegistrar.IsOpenForRegistration(ActionKey))
	{
		return;
	}

	auto MakeTempVarNodeSpawner = [](FEdGraphPinType const& VarType, bool bVarIsPersistent)
	{
		UBlueprintNodeSpawner* NodeSpawner = UBlueprintNodeSpawner::Create(UK2Node_TemporaryVariable::StaticClass());
		check(NodeSpawner != nullptr);

		auto PostSpawnLambda = [](UEdGraphNode* NewNode, bool bIsTemplateNode, FEdGraphPinType InVarType, bool bInIsPersistent)
		{
			UK2Node_TemporaryVariable* TempVarNode = CastChecked<UK2Node_TemporaryVariable>(NewNode);
			TempVarNode->VariableType  = InVarType;
			TempVarNode->bIsPersistent = bInIsPersistent;
		};

		NodeSpawner->CustomizeNodeDelegate = UBlueprintNodeSpawner::FCustomizeNodeDelegate::CreateStatic(PostSpawnLambda, VarType, bVarIsPersistent);
		return NodeSpawner;
	};

	UEdGraphSchema_K2 const* K2Schema = GetDefault<UEdGraphSchema_K2>();

	ActionRegistrar.AddBlueprintAction(ActionKey, MakeTempVarNodeSpawner(FEdGraphPinType(K2Schema->PC_Int, TEXT(""), nullptr, /*bIsArray =*/false, /*bIsReference =*/false), /*bIsPersistent =*/false));
	ActionRegistrar.AddBlueprintAction(ActionKey, MakeTempVarNodeSpawner(FEdGraphPinType(K2Schema->PC_Int, TEXT(""), nullptr, /*bIsArray =*/ true, /*bIsReference =*/false), /*bIsPersistent =*/false));
	ActionRegistrar.AddBlueprintAction(ActionKey, MakeTempVarNodeSpawner(FEdGraphPinType(K2Schema->PC_Float, TEXT(""), nullptr, /*bIsArray =*/false, /*bIsReference =*/false), /*bIsPersistent =*/false));
	ActionRegistrar.AddBlueprintAction(ActionKey, MakeTempVarNodeSpawner(FEdGraphPinType(K2Schema->PC_Float, TEXT(""), nullptr, /*bIsArray =*/ true, /*bIsReference =*/false), /*bIsPersistent =*/false));
	ActionRegistrar.AddBlueprintAction(ActionKey, MakeTempVarNodeSpawner(FEdGraphPinType(K2Schema->PC_Boolean, TEXT(""), nullptr, /*bIsArray =*/false, /*bIsReference =*/false), /*bIsPersistent =*/false));
	ActionRegistrar.AddBlueprintAction(ActionKey, MakeTempVarNodeSpawner(FEdGraphPinType(K2Schema->PC_Boolean, TEXT(""), nullptr, /*bIsArray =*/ true, /*bIsReference =*/false), /*bIsPersistent =*/false));
	ActionRegistrar.AddBlueprintAction(ActionKey, MakeTempVarNodeSpawner(FEdGraphPinType(K2Schema->PC_String, TEXT(""), nullptr, /*bIsArray =*/false, /*bIsReference =*/false), /*bIsPersistent =*/false));
	ActionRegistrar.AddBlueprintAction(ActionKey, MakeTempVarNodeSpawner(FEdGraphPinType(K2Schema->PC_String, TEXT(""), nullptr, /*bIsArray =*/ true, /*bIsReference =*/false), /*bIsPersistent =*/false));
	ActionRegistrar.AddBlueprintAction(ActionKey, MakeTempVarNodeSpawner(FEdGraphPinType(K2Schema->PC_Text, TEXT(""), nullptr, /*bIsArray =*/false, /*bIsReference =*/false), /*bIsPersistent =*/false));
	ActionRegistrar.AddBlueprintAction(ActionKey, MakeTempVarNodeSpawner(FEdGraphPinType(K2Schema->PC_Text, TEXT(""), nullptr, /*bIsArray =*/ true, /*bIsReference =*/false), /*bIsPersistent =*/false));
	
	ActionRegistrar.AddBlueprintAction(ActionKey, MakeTempVarNodeSpawner(FEdGraphPinType(K2Schema->PC_Wildcard, TEXT(""), nullptr, /*bIsArray =*/false, /*bIsReference =*/false), /*bIsPersistent =*/false));
	ActionRegistrar.AddBlueprintAction(ActionKey, MakeTempVarNodeSpawner(FEdGraphPinType(K2Schema->PC_Wildcard, TEXT(""), nullptr, /*bIsArray =*/ true, /*bIsReference =*/false), /*bIsPersistent =*/false));

	UScriptStruct* VectorStruct  = TBaseStructure<FVector>::Get();
	ActionRegistrar.AddBlueprintAction(ActionKey, MakeTempVarNodeSpawner(FEdGraphPinType(K2Schema->PC_Struct, TEXT("Vector"), VectorStruct, /*bIsArray =*/false, /*bIsReference =*/false), /*bIsPersistent =*/false));
	ActionRegistrar.AddBlueprintAction(ActionKey, MakeTempVarNodeSpawner(FEdGraphPinType(K2Schema->PC_Struct, TEXT("Vector"), VectorStruct, /*bIsArray =*/ true, /*bIsReference =*/false), /*bIsPersistent =*/false));
	
	UScriptStruct* RotatorStruct = TBaseStructure<FRotator>::Get();
	ActionRegistrar.AddBlueprintAction(ActionKey, MakeTempVarNodeSpawner(FEdGraphPinType(K2Schema->PC_Struct, TEXT("Rotator"), RotatorStruct, /*bIsArray =*/false, /*bIsReference =*/false), /*bIsPersistent =*/false));
	ActionRegistrar.AddBlueprintAction(ActionKey, MakeTempVarNodeSpawner(FEdGraphPinType(K2Schema->PC_Struct, TEXT("Rotator"), RotatorStruct, /*bIsArray =*/ true, /*bIsReference =*/false), /*bIsPersistent =*/false));
	
	UScriptStruct* TransformStruct = TBaseStructure<FTransform>::Get();
	ActionRegistrar.AddBlueprintAction(ActionKey, MakeTempVarNodeSpawner(FEdGraphPinType(K2Schema->PC_Struct, TEXT("Transform"), TransformStruct, /*bIsArray =*/false, /*bIsReference =*/false), /*bIsPersistent =*/false));
	ActionRegistrar.AddBlueprintAction(ActionKey, MakeTempVarNodeSpawner(FEdGraphPinType(K2Schema->PC_Struct, TEXT("Transform"), TransformStruct, /*bIsArray =*/ true, /*bIsReference =*/false), /*bIsPersistent =*/false));

	UScriptStruct* BlendSampleStruct = FindObjectChecked<UScriptStruct>(ANY_PACKAGE, TEXT("BlendSampleData"));
	ActionRegistrar.AddBlueprintAction(ActionKey, MakeTempVarNodeSpawner(FEdGraphPinType(K2Schema->PC_Struct, TEXT("BlendSampleData"), BlendSampleStruct, /*bIsArray =*/false, /*bIsReference =*/false), /*bIsPersistent =*/false));
	ActionRegistrar.AddBlueprintAction(ActionKey, MakeTempVarNodeSpawner(FEdGraphPinType(K2Schema->PC_Struct, TEXT("BlendSampleData"), BlendSampleStruct, /*bIsArray =*/ true, /*bIsReference =*/false), /*bIsPersistent =*/false));

	// add persistent bool and int types (for macro graphs)
	ActionRegistrar.AddBlueprintAction(ActionKey, MakeTempVarNodeSpawner(FEdGraphPinType(K2Schema->PC_Int, TEXT(""), nullptr, /*bIsArray =*/false, /*bIsReference =*/false), /*bIsPersistent =*/true));
	ActionRegistrar.AddBlueprintAction(ActionKey, MakeTempVarNodeSpawner(FEdGraphPinType(K2Schema->PC_Boolean, TEXT(""), nullptr, /*bIsArray =*/false, /*bIsReference =*/false), /*bIsPersistent =*/true));
}