void FMaterialGraphConnectionDrawingPolicy::DetermineWiringStyle(UEdGraphPin* OutputPin, UEdGraphPin* InputPin, /*inout*/ float& Thickness, /*inout*/ FLinearColor& WireColor, /*inout*/bool& bDrawBubbles, /*inout*/ bool& bBidirectional)
{
	WireColor = MaterialGraphSchema->ActivePinColor;

	// Have to consider both pins as the input will be an 'output' when previewing a connection
	if (OutputPin)
	{
		if (!MaterialGraph->IsInputActive(OutputPin))
		{
			WireColor = MaterialGraphSchema->InactivePinColor;
		}
	}
	if (InputPin)
	{
		if (!MaterialGraph->IsInputActive(InputPin))
		{
			WireColor = MaterialGraphSchema->InactivePinColor;
		}
	}

	const bool bDeemphasizeUnhoveredPins = HoveredPins.Num() > 0;
	if (bDeemphasizeUnhoveredPins)
	{
		ApplyHoverDeemphasis(OutputPin, InputPin, /*inout*/ Thickness, /*inout*/ WireColor);
	}
}
// Give specific editor modes a chance to highlight this connection or darken non-interesting connections
void FKismetConnectionDrawingPolicy::DetermineWiringStyle(UEdGraphPin* OutputPin, UEdGraphPin* InputPin, /*inout*/ float& Thickness, /*inout*/ FLinearColor& WireColor, /*inout*/bool& bDrawBubbles, /*inout*/bool& bBidirectional)
{
	// Get the schema and grab the default color from it
	check(OutputPin);
	check(GraphObj);
	const UEdGraphSchema* Schema = GraphObj->GetSchema();

	WireColor = Schema->GetPinTypeColor(OutputPin->PinType);

	const bool bDeemphasizeUnhoveredPins = HoveredPins.Num() > 0;

	// If this is a K2 graph, try to be a little more specific
	const UEdGraphSchema_K2* K2Schema = Cast<const UEdGraphSchema_K2>(Schema);
	if (K2Schema != NULL)
	{
		if (TreatWireAsExecutionPin(InputPin, OutputPin))
		{
			if (CanBuildRoadmap())
			{
				bool bExecuted = false;

				// Run thru the predecessors, and on
				if (FExecPairingMap* PredecessorMap = PredecessorNodes.Find(InputPin->GetOwningNode()))
				{
					if (FTimePair* Times = PredecessorMap->Find(OutputPin->GetOwningNode()))
					{
						bExecuted = true;

						DetermineStyleOfExecWire(/*inout*/ Thickness, /*inout*/ WireColor, /*inout*/ bDrawBubbles, *Times);
					}
				}

				if (!bExecuted)
				{
					// It's not followed, fade it and keep it thin
					WireColor = ReleaseColor;
					Thickness = ReleaseWireThickness;
				}
			}
			else
			{
				// Make exec wires slightly thicker even outside of debug
				Thickness = 3.0f;
			}
		}
		else
		{
			// Array types should draw thicker
			if( (InputPin && InputPin->PinType.bIsArray) || (OutputPin && OutputPin->PinType.bIsArray) )
			{
				Thickness = 3.0f;
			}
		}
	}

	if (bDeemphasizeUnhoveredPins)
	{
		ApplyHoverDeemphasis(OutputPin, InputPin, /*inout*/ Thickness, /*inout*/ WireColor);
	}
}
void FBehaviorTreeConnectionDrawingPolicy::DetermineWiringStyle(UEdGraphPin* OutputPin, UEdGraphPin* InputPin, /*inout*/ float& Thickness, /*inout*/ FLinearColor& WireColor, /*inout*/ bool& bDrawBubbles, /*inout*/ bool& bBidirectional)
{
	Thickness = 1.5f;

	WireColor = BehaviorTreeColors::Connection::Default;
	bBidirectional = false;

	const bool bDeemphasizeUnhoveredPins = HoveredPins.Num() > 0;
	if (bDeemphasizeUnhoveredPins)
	{
		ApplyHoverDeemphasis(OutputPin, InputPin, /*inout*/ Thickness, /*inout*/ WireColor);
	}

	UBehaviorTreeGraphNode* FromNode = OutputPin ? Cast<UBehaviorTreeGraphNode>(OutputPin->GetOwningNode()) : NULL;
	UBehaviorTreeGraphNode* ToNode = InputPin ? Cast<UBehaviorTreeGraphNode>(InputPin->GetOwningNode()) : NULL;
	if (ToNode && FromNode)
	{
		if ((ToNode->bDebuggerMarkCurrentlyActive && FromNode->bDebuggerMarkCurrentlyActive) ||
			(ToNode->bDebuggerMarkPreviouslyActive && FromNode->bDebuggerMarkPreviouslyActive))
		{
			Thickness = 10.0f;
			bDrawBubbles = true;
		}
		else if (FBehaviorTreeDebugger::IsPlaySessionPaused())
		{
			UBehaviorTreeGraphNode* FirstToNode = ToNode;
			int32 FirstPathIdx = ToNode->DebuggerSearchPathIndex;
			for (int32 i = 0; i < ToNode->Decorators.Num(); i++)
			{
				UBehaviorTreeGraphNode* TestNode = ToNode->Decorators[i];
				if (TestNode->DebuggerSearchPathIndex != INDEX_NONE &&
					(TestNode->bDebuggerMarkSearchSucceeded || TestNode->bDebuggerMarkSearchFailed))
				{
					if (TestNode->DebuggerSearchPathIndex < FirstPathIdx || FirstPathIdx == INDEX_NONE)
					{
						FirstPathIdx = TestNode->DebuggerSearchPathIndex;
						FirstToNode = TestNode;
					}
				}
			}

			if (FirstToNode->bDebuggerMarkSearchSucceeded || FirstToNode->bDebuggerMarkSearchFailed)
			{
				Thickness = 5.0f;
				WireColor = FirstToNode->bDebuggerMarkSearchSucceeded ? BehaviorTreeColors::Debugger::SearchSucceeded :
					BehaviorTreeColors::Debugger::SearchFailed;

				// hacky: use bBidirectional flag to reverse direction of connection (used by debugger)
				bBidirectional = true;
			}
		}
	}
}
void FStateMachineConnectionDrawingPolicy::DetermineWiringStyle(UEdGraphPin* OutputPin, UEdGraphPin* InputPin, /*inout*/ float& Thickness, /*inout*/ FLinearColor& WireColor, /*inout*/ bool& bDrawBubbles, /*inout*/ bool& bBidirectional)
{
	Thickness = 1.5f;

	if (InputPin)
	{
		if (UAnimStateTransitionNode* TransNode = Cast<UAnimStateTransitionNode>(InputPin->GetOwningNode()))
		{
			WireColor = SGraphNodeAnimTransition::StaticGetTransitionColor(TransNode, HoveredPins.Contains(InputPin));

			bBidirectional = TransNode->Bidirectional;
		}
	}

	const bool bDeemphasizeUnhoveredPins = HoveredPins.Num() > 0;
	if (bDeemphasizeUnhoveredPins)
	{
		ApplyHoverDeemphasis(OutputPin, InputPin, /*inout*/ Thickness, /*inout*/ WireColor);
	}
}
// Give specific editor modes a chance to highlight this connection or darken non-interesting connections
void FKismetConnectionDrawingPolicy::DetermineWiringStyle(UEdGraphPin* OutputPin, UEdGraphPin* InputPin, /*inout*/ FConnectionParams& Params)
{
	Params.AssociatedPin1 = OutputPin;
	Params.AssociatedPin2 = InputPin;

	// Get the schema and grab the default color from it
	check(OutputPin);
	check(GraphObj);
	const UEdGraphSchema* Schema = GraphObj->GetSchema();

	Params.WireColor = Schema->GetPinTypeColor(OutputPin->PinType);

	UEdGraphNode* OutputNode = OutputPin->GetOwningNode();
	UEdGraphNode* InputNode = (InputPin != nullptr) ? InputPin->GetOwningNode() : nullptr;

	const bool bDeemphasizeUnhoveredPins = HoveredPins.Num() > 0;

	// If this is a K2 graph, try to be a little more specific
	const UEdGraphSchema_K2* K2Schema = Cast<const UEdGraphSchema_K2>(Schema);
	if (K2Schema != NULL)
	{
		// If the output or input connect to a knot that is going backwards, we will flip the direction on values going into them
		{
			if (UK2Node_Knot* OutputKnotNode = Cast<UK2Node_Knot>(OutputNode))
			{
				if (ShouldChangeTangentForKnot(OutputKnotNode))
				{
					Params.StartDirection = EGPD_Input;
				}
			}

			if (UK2Node_Knot* InputKnotNode = Cast<UK2Node_Knot>(InputNode))
			{
				if (ShouldChangeTangentForKnot(InputKnotNode))
				{
					Params.EndDirection = EGPD_Output;
				}
			}
		}

		if (TreatWireAsExecutionPin(InputPin, OutputPin))
		{
			if (CanBuildRoadmap())
			{
				// knot nodes are removed from the graph at compile time, so we 
				// have to follow them until we find something that would have 
				// actually executed
				while (UK2Node_Knot* InputKnotNode = Cast<UK2Node_Knot>(InputNode))
				{
					InputNode = nullptr;

					UEdGraphPin* OutPin = InputKnotNode->GetOutputPin();
					if (OutPin->LinkedTo.Num() > 0)
					{
						check(OutPin->LinkedTo.Num() == 1);
						InputNode = OutPin->LinkedTo[0]->GetOwningNode();
					}	
				}

				// track if this node connection was ran or not
				bool bExecuted = false;

				// if the node belonging to InputPin was actually executed
				if (FExecPairingMap* ExecPaths = PredecessorPins.Find(InputNode))
				{
					// if the output pin is one of the pins that lead to InputNode being ran
					if (FTimePair const* ExecTiming = BackTraceExecPath(OutputPin, ExecPaths))
					{
						bExecuted = true;
						DetermineStyleOfExecWire(/*inout*/ Params.WireThickness, /*inout*/ Params.WireColor, /*inout*/ Params.bDrawBubbles, *ExecTiming);
					}
				}
				
				if (!bExecuted)
				{
					// It's not followed, fade it and keep it thin
					Params.WireColor = ReleaseColor;
					Params.WireThickness = ReleaseWireThickness;
				}
			}
			else
			{
				// Make exec wires slightly thicker even outside of debug
				Params.WireThickness = 3.0f;
			}
		}
		else
		{
			// Array types should draw thicker
			if ((InputPin && InputPin->PinType.bIsArray) || (OutputPin && OutputPin->PinType.bIsArray))
			{
				Params.WireThickness = 3.0f;
			}
		}
	}

	if (bDeemphasizeUnhoveredPins)
	{
		ApplyHoverDeemphasis(OutputPin, InputPin, /*inout*/ Params.WireThickness, /*inout*/ Params.WireColor);
	}
}