// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. #include "EnvironmentQueryEditorPrivatePCH.h" #include "Editor/UnrealEd/Public/Kismet2/KismetDebugUtilities.h" #include "Editor/UnrealEd/Public/Kismet2/BlueprintEditorUtils.h" #include "KismetNodes/KismetNodeInfoContext.h" #include "EnvironmentQueryConnectionDrawingPolicy.h" FEnvironmentQueryConnectionDrawingPolicy::FEnvironmentQueryConnectionDrawingPolicy(int32 InBackLayerID, int32 InFrontLayerID, float ZoomFactor, const FSlateRect& InClippingRect, FSlateWindowElementList& InDrawElements, UEdGraph* InGraphObj) : FConnectionDrawingPolicy(InBackLayerID, InFrontLayerID, ZoomFactor, InClippingRect, InDrawElements) , GraphObj(InGraphObj) { } void FEnvironmentQueryConnectionDrawingPolicy::DetermineWiringStyle(UEdGraphPin* OutputPin, UEdGraphPin* InputPin, /*inout*/ float& Thickness, /*inout*/ FLinearColor& WireColor, /*inout*/ bool& bDrawBubbles, /*inout*/ bool& bBidirectional) { Thickness = 1.5f; WireColor = FLinearColor::White; bBidirectional = false; const bool bDeemphasizeUnhoveredPins = HoveredPins.Num() > 0; if (bDeemphasizeUnhoveredPins) { ApplyHoverDeemphasis(OutputPin, InputPin, /*inout*/ Thickness, /*inout*/ WireColor); } } void FEnvironmentQueryConnectionDrawingPolicy::Draw(TMap, 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 ChildNode = StaticCastSharedRef(CurWidget.Widget); NodeWidgetMap.Add(ChildNode->GetNodeObj(), NodeIndex); } // Now draw FConnectionDrawingPolicy::Draw(PinGeometries, ArrangedNodes); } void FEnvironmentQueryConnectionDrawingPolicy::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); if (Pin->Direction == EEdGraphPinDirection::EGPD_Output) { DrawSplineWithArrow(FGeometryHelper::FindClosestPointOnGeom(PinGeometry, EndPoint), EndPoint, WireColor, Thickness, bDrawBubbles, bBiDirectional); } else { DrawSplineWithArrow(FGeometryHelper::FindClosestPointOnGeom(PinGeometry, StartPoint), StartPoint, WireColor, Thickness, bDrawBubbles, bBiDirectional); } } void FEnvironmentQueryConnectionDrawingPolicy::DrawSplineWithArrow(const FVector2D& StartAnchorPoint, const FVector2D& EndAnchorPoint, const FLinearColor& WireColor, float WireThickness, bool bDrawBubbles, bool Bidirectional) { Internal_DrawLineWithArrow(StartAnchorPoint, EndAnchorPoint, WireColor, WireThickness, bDrawBubbles); } void FEnvironmentQueryConnectionDrawingPolicy::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.SafeNormal(); const FVector2D Normal = FVector2D(DeltaPos.Y, -DeltaPos.X).SafeNormal(); // 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(), FSlateDrawElement::RelativeToElement, WireColor ); } void FEnvironmentQueryConnectionDrawingPolicy::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 FEnvironmentQueryConnectionDrawingPolicy::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.SafeNormal(); 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 }