Files
UnrealEngineUWP/Engine/Source/Editor/GraphEditor/Private/StateMachineConnectionDrawingPolicy.cpp
Ben Marsh 149375b14b Update copyright notices to 2015.
[CL 2379638 by Ben Marsh in Main branch]
2014-12-07 19:09:38 -05:00

201 lines
7.6 KiB
C++

// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
#include "GraphEditorCommon.h"
#include "StateMachineConnectionDrawingPolicy.h"
#include "AnimationStateNodes/SGraphNodeAnimTransition.h"
#include "AnimStateTransitionNode.h"
#include "AnimStateEntryNode.h"
/////////////////////////////////////////////////////
// FStateMachineConnectionDrawingPolicy
FStateMachineConnectionDrawingPolicy::FStateMachineConnectionDrawingPolicy(int32 InBackLayerID, int32 InFrontLayerID, float ZoomFactor, const FSlateRect& InClippingRect, FSlateWindowElementList& InDrawElements, UEdGraph* InGraphObj)
: FConnectionDrawingPolicy(InBackLayerID, InFrontLayerID, ZoomFactor, InClippingRect, InDrawElements)
, GraphObj(InGraphObj)
{
}
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);
}
}
void FStateMachineConnectionDrawingPolicy::DetermineLinkGeometry(
TMap<TSharedRef<SWidget>, FArrangedWidget>& PinGeometries,
FArrangedChildren& ArrangedNodes,
TSharedRef<SWidget>& OutputPinWidget,
UEdGraphPin* OutputPin,
UEdGraphPin* InputPin,
/*out*/ FArrangedWidget*& StartWidgetGeometry,
/*out*/ FArrangedWidget*& EndWidgetGeometry
)
{
if (UAnimStateEntryNode* EntryNode = Cast<UAnimStateEntryNode>(OutputPin->GetOwningNode()))
{
//FConnectionDrawingPolicy::DetermineLinkGeometry(PinGeometries, ArrangedNodes, OutputPinWidget, OutputPin, InputPin, StartWidgetGeometry, EndWidgetGeometry);
StartWidgetGeometry = PinGeometries.Find(OutputPinWidget);
UAnimStateNodeBase* State = CastChecked<UAnimStateNodeBase>(InputPin->GetOwningNode());
int32 StateIndex = NodeWidgetMap.FindChecked(State);
EndWidgetGeometry = &(ArrangedNodes[StateIndex]);
}
else if (UAnimStateTransitionNode* TransNode = Cast<UAnimStateTransitionNode>(InputPin->GetOwningNode()))
{
UAnimStateNodeBase* PrevState = TransNode->GetPreviousState();
UAnimStateNodeBase* NextState = TransNode->GetNextState();
if ((PrevState != NULL) && (NextState != NULL))
{
int32* PrevNodeIndex = NodeWidgetMap.Find(PrevState);
int32* NextNodeIndex = NodeWidgetMap.Find(NextState);
if ((PrevNodeIndex != NULL) && (NextNodeIndex != NULL))
{
StartWidgetGeometry = &(ArrangedNodes[*PrevNodeIndex]);
EndWidgetGeometry = &(ArrangedNodes[*NextNodeIndex]);
}
}
}
else
{
StartWidgetGeometry = PinGeometries.Find(OutputPinWidget);
if (TSharedRef<SGraphPin>* pTargetWidget = PinToPinWidgetMap.Find(InputPin))
{
TSharedRef<SGraphPin> InputWidget = *pTargetWidget;
EndWidgetGeometry = PinGeometries.Find(InputWidget);
}
}
}
void FStateMachineConnectionDrawingPolicy::Draw(TMap<TSharedRef<SWidget>, FArrangedWidget>& PinGeometries, FArrangedChildren& ArrangedNodes)
{
// Build an acceleration structure to quickly find geometry for the nodes
NodeWidgetMap.Empty();
for (int32 NodeIndex = 0; NodeIndex < ArrangedNodes.Num(); ++NodeIndex)
{
FArrangedWidget& CurWidget = ArrangedNodes[NodeIndex];
TSharedRef<SGraphNode> ChildNode = StaticCastSharedRef<SGraphNode>(CurWidget.Widget);
NodeWidgetMap.Add(ChildNode->GetNodeObj(), NodeIndex);
}
// Now draw
FConnectionDrawingPolicy::Draw(PinGeometries, ArrangedNodes);
}
void FStateMachineConnectionDrawingPolicy::DrawPreviewConnector(const FGeometry& PinGeometry, const FVector2D& StartPoint, const FVector2D& EndPoint, UEdGraphPin* Pin)
{
float Thickness = 1.0f;
FLinearColor WireColor = FLinearColor::White;
bool bDrawBubbles = false;
bool bBiDirectional = false;
DetermineWiringStyle(Pin, NULL, /*inout*/ Thickness, /*inout*/ WireColor, /*inout*/ bDrawBubbles, /*inout*/ bBiDirectional);
const FVector2D SeedPoint = EndPoint;
const FVector2D AdjustedStartPoint = FGeometryHelper::FindClosestPointOnGeom(PinGeometry, SeedPoint);
DrawSplineWithArrow(AdjustedStartPoint, EndPoint, WireColor, Thickness, bDrawBubbles, bBiDirectional);
}
void FStateMachineConnectionDrawingPolicy::DrawSplineWithArrow(const FVector2D& StartAnchorPoint, const FVector2D& EndAnchorPoint, const FLinearColor& WireColor, float WireThickness, bool bDrawBubbles, bool Bidirectional)
{
Internal_DrawLineWithArrow(StartAnchorPoint, EndAnchorPoint, WireColor, WireThickness, bDrawBubbles);
if (Bidirectional)
{
Internal_DrawLineWithArrow(EndAnchorPoint, StartAnchorPoint, WireColor, WireThickness, bDrawBubbles);
}
}
void FStateMachineConnectionDrawingPolicy::Internal_DrawLineWithArrow(const FVector2D& StartAnchorPoint, const FVector2D& EndAnchorPoint, const FLinearColor& WireColor, float WireThickness, bool bDrawBubbles)
{
//@TODO: Should this be scaled by zoom factor?
const float LineSeparationAmount = 4.5f;
const FVector2D DeltaPos = EndAnchorPoint - StartAnchorPoint;
const FVector2D UnitDelta = DeltaPos.GetSafeNormal();
const FVector2D Normal = FVector2D(DeltaPos.Y, -DeltaPos.X).GetSafeNormal();
// Come up with the final start/end points
const FVector2D DirectionBias = Normal * LineSeparationAmount;
const FVector2D LengthBias = ArrowRadius.X * UnitDelta;
const FVector2D StartPoint = StartAnchorPoint + DirectionBias + LengthBias;
const FVector2D EndPoint = EndAnchorPoint + DirectionBias - LengthBias;
// Draw a line/spline
DrawConnection(WireLayerID, StartPoint, EndPoint, WireColor, WireThickness, bDrawBubbles);
// Draw the arrow
const FVector2D ArrowDrawPos = EndPoint - ArrowRadius;
const float AngleInRadians = FMath::Atan2(DeltaPos.Y, DeltaPos.X);
FSlateDrawElement::MakeRotatedBox(
DrawElementsList,
ArrowLayerID,
FPaintGeometry(ArrowDrawPos, ArrowImage->ImageSize * ZoomFactor, ZoomFactor),
ArrowImage,
ClippingRect,
ESlateDrawEffect::None,
AngleInRadians,
TOptional<FVector2D>(),
FSlateDrawElement::RelativeToElement,
WireColor
);
}
void FStateMachineConnectionDrawingPolicy::DrawSplineWithArrow(FGeometry& StartGeom, FGeometry& EndGeom, const FLinearColor& WireColor, float WireThickness, bool bDrawBubbles, bool Bidirectional)
{
// Get a reasonable seed point (halfway between the boxes)
const FVector2D StartCenter = FGeometryHelper::CenterOf(StartGeom);
const FVector2D EndCenter = FGeometryHelper::CenterOf(EndGeom);
const FVector2D SeedPoint = (StartCenter + EndCenter) * 0.5f;
// Find the (approximate) closest points between the two boxes
const FVector2D StartAnchorPoint = FGeometryHelper::FindClosestPointOnGeom(StartGeom, SeedPoint);
const FVector2D EndAnchorPoint = FGeometryHelper::FindClosestPointOnGeom(EndGeom, SeedPoint);
DrawSplineWithArrow(StartAnchorPoint, EndAnchorPoint, WireColor, WireThickness, bDrawBubbles, Bidirectional);
}
void FStateMachineConnectionDrawingPolicy::DrawConnection(int32 LayerId, const FVector2D& Start, const FVector2D& End, const FLinearColor& InColor, float Thickness, bool bDrawBubbles)
{
const FVector2D& P0 = Start;
const FVector2D& P1 = End;
const FVector2D Delta = End-Start;
const FVector2D NormDelta = Delta.GetSafeNormal();
const FVector2D P0Tangent = NormDelta;
const FVector2D P1Tangent = NormDelta;
// Draw the spline itself
FSlateDrawElement::MakeDrawSpaceSpline(
DrawElementsList,
LayerId,
P0, P0Tangent,
P1, P1Tangent,
ClippingRect,
Thickness,
ESlateDrawEffect::None,
InColor
);
//@TODO: Handle bDrawBubbles
}