You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
551 lines
20 KiB
551 lines
20 KiB
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
|
|
|
|
#pragma once
|
|
|
|
#ifndef NGA_WITH_ENGINE_CPP
|
|
|
|
#include "Version.h"
|
|
|
|
#if (ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION > 22) || ENGINE_MAJOR_VERSION > 4
|
|
// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "StateMachineConnectionDrawingPolicy.h"
|
|
#include "Rendering/DrawElements.h"
|
|
#include "AnimStateNodeBase.h"
|
|
#include "AnimStateTransitionNode.h"
|
|
#include "AnimationStateNodes/SGraphNodeAnimTransition.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*/ FConnectionParams& Params)
|
|
{
|
|
Params.AssociatedPin1 = OutputPin;
|
|
Params.AssociatedPin2 = InputPin;
|
|
Params.WireThickness = 1.5f;
|
|
|
|
if (InputPin)
|
|
{
|
|
if (UAnimStateTransitionNode* TransNode = Cast<UAnimStateTransitionNode>(InputPin->GetOwningNode()))
|
|
{
|
|
Params.WireColor = SGraphNodeAnimTransition::StaticGetTransitionColor(TransNode, HoveredPins.Contains(InputPin));
|
|
|
|
Params.bUserFlag1 = TransNode->Bidirectional;
|
|
}
|
|
}
|
|
|
|
const bool bDeemphasizeUnhoveredPins = HoveredPins.Num() > 0;
|
|
if (bDeemphasizeUnhoveredPins)
|
|
{
|
|
ApplyHoverDeemphasis(OutputPin, InputPin, /*inout*/ Params.WireThickness, /*inout*/ Params.WireColor);
|
|
}
|
|
}
|
|
|
|
void FStateMachineConnectionDrawingPolicy::DetermineLinkGeometry(
|
|
FArrangedChildren& ArrangedNodes,
|
|
TSharedRef<SWidget>& OutputPinWidget,
|
|
UEdGraphPin* OutputPin,
|
|
UEdGraphPin* InputPin,
|
|
/*out*/ FArrangedWidget*& StartWidgetGeometry,
|
|
/*out*/ FArrangedWidget*& EndWidgetGeometry
|
|
)
|
|
{
|
|
if (UAnimStateEntryNode* EntryNode = Cast<UAnimStateEntryNode>(OutputPin->GetOwningNode()))
|
|
{
|
|
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 (TSharedPtr<SGraphPin>* pTargetWidget = PinToPinWidgetMap.Find(InputPin))
|
|
{
|
|
TSharedRef<SGraphPin> InputWidget = (*pTargetWidget).ToSharedRef();
|
|
EndWidgetGeometry = PinGeometries->Find(InputWidget);
|
|
}
|
|
}
|
|
}
|
|
|
|
void FStateMachineConnectionDrawingPolicy::Draw(TMap<TSharedRef<SWidget>, FArrangedWidget>& InPinGeometries, 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(InPinGeometries, ArrangedNodes);
|
|
}
|
|
|
|
void FStateMachineConnectionDrawingPolicy::DrawPreviewConnector(const FGeometry& PinGeometry, const FVector2D& StartPoint, const FVector2D& EndPoint, UEdGraphPin* Pin)
|
|
{
|
|
FConnectionParams Params;
|
|
DetermineWiringStyle(Pin, nullptr, /*inout*/ Params);
|
|
|
|
const FVector2D SeedPoint = EndPoint;
|
|
const FVector2D AdjustedStartPoint = FGeometryHelper::FindClosestPointOnGeom(PinGeometry, SeedPoint);
|
|
|
|
DrawSplineWithArrow(AdjustedStartPoint, EndPoint, Params);
|
|
}
|
|
|
|
|
|
void FStateMachineConnectionDrawingPolicy::DrawSplineWithArrow(const FVector2D& StartAnchorPoint, const FVector2D& EndAnchorPoint, const FConnectionParams& Params)
|
|
{
|
|
Internal_DrawLineWithArrow(StartAnchorPoint, EndAnchorPoint, Params);
|
|
|
|
// Is the connection bidirectional?
|
|
if (Params.bUserFlag1)
|
|
{
|
|
Internal_DrawLineWithArrow(EndAnchorPoint, StartAnchorPoint, Params);
|
|
}
|
|
}
|
|
|
|
void FStateMachineConnectionDrawingPolicy::Internal_DrawLineWithArrow(const FVector2D& StartAnchorPoint, const FVector2D& EndAnchorPoint, const FConnectionParams& Params)
|
|
{
|
|
//@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, Params);
|
|
|
|
// 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,
|
|
ESlateDrawEffect::None,
|
|
AngleInRadians,
|
|
TOptional<FVector2D>(),
|
|
FSlateDrawElement::RelativeToElement,
|
|
Params.WireColor
|
|
);
|
|
}
|
|
|
|
void FStateMachineConnectionDrawingPolicy::DrawSplineWithArrow(const FGeometry& StartGeom, const FGeometry& EndGeom, const FConnectionParams& Params)
|
|
{
|
|
// 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, Params);
|
|
}
|
|
|
|
FVector2D FStateMachineConnectionDrawingPolicy::ComputeSplineTangent(const FVector2D& Start, const FVector2D& End) const
|
|
{
|
|
const FVector2D Delta = End - Start;
|
|
const FVector2D NormDelta = Delta.GetSafeNormal();
|
|
|
|
return NormDelta;
|
|
}
|
|
|
|
#elif (ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION > 17) || ENGINE_MAJOR_VERSION > 4
|
|
|
|
#include "StateMachineConnectionDrawingPolicy.h"
|
|
#include "Rendering/DrawElements.h"
|
|
#include "AnimStateNodeBase.h"
|
|
#include "AnimStateTransitionNode.h"
|
|
#include "AnimationStateNodes/SGraphNodeAnimTransition.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*/ FConnectionParams& Params)
|
|
{
|
|
Params.AssociatedPin1 = OutputPin;
|
|
Params.AssociatedPin2 = InputPin;
|
|
Params.WireThickness = 1.5f;
|
|
|
|
if (InputPin)
|
|
{
|
|
if (UAnimStateTransitionNode* TransNode = Cast<UAnimStateTransitionNode>(InputPin->GetOwningNode()))
|
|
{
|
|
Params.WireColor = SGraphNodeAnimTransition::StaticGetTransitionColor(TransNode, HoveredPins.Contains(InputPin));
|
|
|
|
Params.bUserFlag1 = TransNode->Bidirectional;
|
|
}
|
|
}
|
|
|
|
const bool bDeemphasizeUnhoveredPins = HoveredPins.Num() > 0;
|
|
if (bDeemphasizeUnhoveredPins)
|
|
{
|
|
ApplyHoverDeemphasis(OutputPin, InputPin, /*inout*/ Params.WireThickness, /*inout*/ Params.WireColor);
|
|
}
|
|
}
|
|
|
|
void FStateMachineConnectionDrawingPolicy::DetermineLinkGeometry(
|
|
FArrangedChildren& ArrangedNodes,
|
|
TSharedRef<SWidget>& OutputPinWidget,
|
|
UEdGraphPin* OutputPin,
|
|
UEdGraphPin* InputPin,
|
|
/*out*/ FArrangedWidget*& StartWidgetGeometry,
|
|
/*out*/ FArrangedWidget*& EndWidgetGeometry
|
|
)
|
|
{
|
|
if (UAnimStateEntryNode* EntryNode = Cast<UAnimStateEntryNode>(OutputPin->GetOwningNode()))
|
|
{
|
|
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>& InPinGeometries, 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(InPinGeometries, ArrangedNodes);
|
|
}
|
|
|
|
void FStateMachineConnectionDrawingPolicy::DrawPreviewConnector(const FGeometry& PinGeometry, const FVector2D& StartPoint, const FVector2D& EndPoint, UEdGraphPin* Pin)
|
|
{
|
|
FConnectionParams Params;
|
|
DetermineWiringStyle(Pin, nullptr, /*inout*/ Params);
|
|
|
|
const FVector2D SeedPoint = EndPoint;
|
|
const FVector2D AdjustedStartPoint = FGeometryHelper::FindClosestPointOnGeom(PinGeometry, SeedPoint);
|
|
|
|
DrawSplineWithArrow(AdjustedStartPoint, EndPoint, Params);
|
|
}
|
|
|
|
|
|
void FStateMachineConnectionDrawingPolicy::DrawSplineWithArrow(const FVector2D& StartAnchorPoint, const FVector2D& EndAnchorPoint, const FConnectionParams& Params)
|
|
{
|
|
Internal_DrawLineWithArrow(StartAnchorPoint, EndAnchorPoint, Params);
|
|
|
|
// Is the connection bidirectional?
|
|
if (Params.bUserFlag1)
|
|
{
|
|
Internal_DrawLineWithArrow(EndAnchorPoint, StartAnchorPoint, Params);
|
|
}
|
|
}
|
|
|
|
void FStateMachineConnectionDrawingPolicy::Internal_DrawLineWithArrow(const FVector2D& StartAnchorPoint, const FVector2D& EndAnchorPoint, const FConnectionParams& Params)
|
|
{
|
|
//@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, Params);
|
|
|
|
// 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,
|
|
Params.WireColor
|
|
);
|
|
}
|
|
|
|
void FStateMachineConnectionDrawingPolicy::DrawSplineWithArrow(const FGeometry& StartGeom, const FGeometry& EndGeom, const FConnectionParams& Params)
|
|
{
|
|
// 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, Params);
|
|
}
|
|
|
|
FVector2D FStateMachineConnectionDrawingPolicy::ComputeSplineTangent(const FVector2D& Start, const FVector2D& End) const
|
|
{
|
|
const FVector2D Delta = End - Start;
|
|
const FVector2D NormDelta = Delta.GetSafeNormal();
|
|
|
|
return NormDelta;
|
|
}
|
|
#else
|
|
|
|
#include "StateMachineConnectionDrawingPolicy.h"
|
|
#include "Rendering/DrawElements.h"
|
|
#include "AnimStateNodeBase.h"
|
|
#include "AnimStateTransitionNode.h"
|
|
#include "AnimationStateNodes/SGraphNodeAnimTransition.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*/ FConnectionParams& Params)
|
|
{
|
|
Params.AssociatedPin1 = OutputPin;
|
|
Params.AssociatedPin2 = InputPin;
|
|
Params.WireThickness = 1.5f;
|
|
|
|
if (InputPin)
|
|
{
|
|
if (UAnimStateTransitionNode* TransNode = Cast<UAnimStateTransitionNode>(InputPin->GetOwningNode()))
|
|
{
|
|
Params.WireColor = SGraphNodeAnimTransition::StaticGetTransitionColor(TransNode, HoveredPins.Contains(InputPin));
|
|
|
|
Params.bUserFlag1 = TransNode->Bidirectional;
|
|
}
|
|
}
|
|
|
|
const bool bDeemphasizeUnhoveredPins = HoveredPins.Num() > 0;
|
|
if (bDeemphasizeUnhoveredPins)
|
|
{
|
|
ApplyHoverDeemphasis(OutputPin, InputPin, /*inout*/ Params.WireThickness, /*inout*/ Params.WireColor);
|
|
}
|
|
}
|
|
|
|
void FStateMachineConnectionDrawingPolicy::DetermineLinkGeometry(
|
|
FArrangedChildren& ArrangedNodes,
|
|
TSharedRef<SWidget>& OutputPinWidget,
|
|
UEdGraphPin* OutputPin,
|
|
UEdGraphPin* InputPin,
|
|
/*out*/ FArrangedWidget*& StartWidgetGeometry,
|
|
/*out*/ FArrangedWidget*& EndWidgetGeometry
|
|
)
|
|
{
|
|
if (UAnimStateEntryNode* EntryNode = Cast<UAnimStateEntryNode>(OutputPin->GetOwningNode()))
|
|
{
|
|
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>& InPinGeometries, 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(InPinGeometries, ArrangedNodes);
|
|
}
|
|
|
|
void FStateMachineConnectionDrawingPolicy::DrawPreviewConnector(const FGeometry& PinGeometry, const FVector2D& StartPoint, const FVector2D& EndPoint, UEdGraphPin* Pin)
|
|
{
|
|
FConnectionParams Params;
|
|
DetermineWiringStyle(Pin, nullptr, /*inout*/ Params);
|
|
|
|
const FVector2D SeedPoint = EndPoint;
|
|
const FVector2D AdjustedStartPoint = FGeometryHelper::FindClosestPointOnGeom(PinGeometry, SeedPoint);
|
|
|
|
DrawSplineWithArrow(AdjustedStartPoint, EndPoint, Params);
|
|
}
|
|
|
|
|
|
void FStateMachineConnectionDrawingPolicy::DrawSplineWithArrow(const FVector2D& StartAnchorPoint, const FVector2D& EndAnchorPoint, const FConnectionParams& Params)
|
|
{
|
|
Internal_DrawLineWithArrow(StartAnchorPoint, EndAnchorPoint, Params);
|
|
|
|
// Is the connection bidirectional?
|
|
if (Params.bUserFlag1)
|
|
{
|
|
Internal_DrawLineWithArrow(EndAnchorPoint, StartAnchorPoint, Params);
|
|
}
|
|
}
|
|
|
|
void FStateMachineConnectionDrawingPolicy::Internal_DrawLineWithArrow(const FVector2D& StartAnchorPoint, const FVector2D& EndAnchorPoint, const FConnectionParams& Params)
|
|
{
|
|
//@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, Params);
|
|
|
|
// 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,
|
|
ESlateDrawEffect::None,
|
|
AngleInRadians,
|
|
TOptional<FVector2D>(),
|
|
FSlateDrawElement::RelativeToElement,
|
|
Params.WireColor
|
|
);
|
|
}
|
|
|
|
void FStateMachineConnectionDrawingPolicy::DrawSplineWithArrow(const FGeometry& StartGeom, const FGeometry& EndGeom, const FConnectionParams& Params)
|
|
{
|
|
// 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, Params);
|
|
}
|
|
|
|
FVector2D FStateMachineConnectionDrawingPolicy::ComputeSplineTangent(const FVector2D& Start, const FVector2D& End) const
|
|
{
|
|
const FVector2D Delta = End - Start;
|
|
const FVector2D NormDelta = Delta.GetSafeNormal();
|
|
|
|
return NormDelta;
|
|
}
|
|
#endif
|
|
|
|
#endif
|