// Fill out your copyright notice in the Description page of Project Settings.
#include "SMyGraphPin.h"
#include "TestGraphAndBlueprintStyle.h"
#include "SGraphPin.h"
#include "SGraphPanel.h"
#include "EdGraph/EdGraphNode.h"
#include "EdGraph/EdGraphPin.h"
/**
* @Function OwnerNodePtr.Pin() 当前指针还在有效时分享当前指针
*/
//我们将逻辑上的Pin(UEdGraphPin)简称为GraphPin,用来显示的Pin(SGraphPin)称为SlatePin.Node同理
void SMyGraphPin::Construct(const FArguments& InArgs, UEdGraphPin* InPin)
{
//1、初始化设置以及获取其对应的GraphPin、Shema
//设置鼠标悬停时的鼠标样式
this->SetCursor(EMouseCursor::Hand);
//可编辑
IsEditable = true;
//获取到自己对应的GraphPin并检查
GraphPinObj = InPin;
check(GraphPinObj);
//获取到所属的Shema并检查
const UEdGraphSchema* OwnerSchema = GraphPinObj->GetSchema();
check(OwnerSchema);
//2、创建用于显示的SlatePin
SBorder::Construct(SBorder::FArguments()
//背景颜色
.BorderBackgroundColor_Lambda([&]() {
return FSlateColor(FLinearColor(0.f, 1.f, 1.f, 0.5f)); })
//鼠标按下事件 Geometry:几何信息 PointerEvent:按键信息
.OnMouseButtonDown_Lambda([&](const FGeometry& Geometry, const FPointerEvent& PointerEvent)
{
//?干啥的
bIsMovingLinks = false;
//判断是否是鼠标左键&&该节点是可编辑的
if (PointerEvent.GetEffectingButton() == EKeys::LeftMouseButton&& IsEditingEnabled())
{
//该GraphPin可连接
if (!GraphPinObj->bNotConnectable)
{
/**
* OwnerNodePtr.Pin():
* Converts this weak pointer to a shared pointer that you can use to access the object (if it
* hasn't expired yet.) Remember, if there are no more shared references to the object, the
* returned shared pointer will not be valid. You should always check to make sure the returned
* pointer is valid before trying to dereference the shared pointer!
*
* @return Shared pointer for this object (will only be valid if still referenced!)
*/
//获取到当前Pin所属的SlateNode?: Node为什么不能放在Lambda外面被赋值,会引发断点
TSharedPtr<SGraphNode> OwnerSlateNode = OwnerNodePtr.Pin();
//同时按了Alt时,断开连接的所有引脚
if (PointerEvent.IsAltDown())
{
//?: 同理,为什么使用同样代码的OwnerSchema调用时会引发断点,而这里获取的不会
const UEdGraphSchema* Schema = GraphPinObj->GetSchema();
/**BreakPinLinks()
* Breaks all links from/to a single pin
*
* @param TargetPin The pin to break links on
* @param bSendsNodeNotifcation whether to send a notification to the node post pin connection change
*/
//断掉该GraphPin的所有连接
Schema->BreakPinLinks(*GraphPinObj, true);
return FReply::Handled();
}
//同时按了Ctrl/Cmd时,可将连接线拖动至别的引脚(是否按下Controller&&该引脚连接数目>0)
if (PointerEvent.IsControlDown() && (GraphPinObj->LinkedTo.Num() > 0))
{
//一、挑选出Panel中所有被线连接的Pin塞进AllPinsMap<FGraphPinHandle,SGraphPin>
//获取当前面板中到所有的SlatePin
TSet<TSharedRef<SWidget>> AllSlatePins;
OwnerSlateNode->GetOwnerPanel()->GetAllPins(AllSlatePins);
//有连线的Pin的Map<GraphPin,SlatePin>
TMap<FGraphPinHandle, TSharedRef<SGraphPin>> AllPinsMap;
//将所有Pin中有至少一个连接的塞进AllPinsMap
for (const TSharedRef<SWidget>& SlatePinRef : AllSlatePins)
{
UEdGraphPin* GraphPinPtr = static_cast<const SGraphPin&>(SlatePinRef.Get()).GetPinObj();
if (GraphPinPtr->LinkedTo.Num() > 0)
{
AllPinsMap.Add(FGraphPinHandle(GraphPinPtr), StaticCastSharedRef<SGraphPin>(SlatePinRef));
}
}
//二、获取到与当前Pin直接相连的Pin信息,存入LinkedPinInfoArray中
//存储Pin信息的struct(名字、所处GraphNode)
struct FLinkedPinInfo {
FString PinName;
TWeakObjectPtr<UEdGraphNode> OwnerGraphNode;
};
//通过在AllPinsMap中使用名字配对的方式找到哪些是直接连接在当前Pin上的Pin,并将其塞进LinkedPinInfoArray中
TArray<FLinkedPinInfo> LinkedPinInfoArray;
for (UEdGraphPin* Pin : GetPinObj()->LinkedTo)
{
if (auto PinWidget = AllPinsMap.Find(Pin))
{
FLinkedPinInfo PinInfo;
//PinInfo.PinName = (*PinWidget)->GetPinObj()->PinName.ToString();
PinInfo.PinName = Pin->GetName();
// UE_LOG(LogTemp, Warning, TEXT("PinWidget name: %s"), *(*PinWidget)->GetPinObj()->PinName.ToString());
// UE_LOG(LogTemp, Warning, TEXT("Pin name: %s"), *(Pin->GetName()));
if (StaticCastSharedRef<SMyGraphPin>(*PinWidget)->GetGraphNode())
{
//PinInfo.OwnerGraphNode = StaticCastSharedRef<SMyGraphPin>(*PinWidget)->GetGraphNode()->GetNodeObj();
PinInfo.OwnerGraphNode = Pin->GetOwningNode();
if (PinInfo.OwnerGraphNode.IsValid())
{
LinkedPinInfoArray.Add(MoveTemp(PinInfo));
}
}
}
}
//三、
TArray<TSharedRef<SGraphPin>> PinArray;
for (FLinkedPinInfo PinInfo : LinkedPinInfoArray)
{
//遍历Pin所属Node的所有GraphPin
for (UEdGraphPin* Pin : PinInfo.OwnerGraphNode.Get()->Pins)
{
//判断两者名字是否相同
if (Pin->PinName.ToString() == PinInfo.PinName)
{
//将对应名字的SlatePin塞入PinArray中
if (TSharedRef<SGraphPin>* pWidget = AllPinsMap.Find(FGraphPinHandle(Pin)))
{
PinArray.Add(*pWidget);
}
}
}
}
//生成所有连线的拖拽
TSharedPtr<FDragDropOperation> DragEvent;
if (PinArray.Num() > 0)
{
DragEvent = SpawnPinDragEvent(OwnerSlateNode->GetOwnerPanel().ToSharedRef(), PinArray);
}
//?: 为什么又要GetShema一次
const UEdGraphSchema* Schema = GraphPinObj->GetSchema();
//断开原有Pin
Schema->BreakPinLinks(*GraphPinObj, true);
//进行新的PinDrag
if (DragEvent.IsValid())
{
bIsMovingLinks = true;
return FReply::Handled().BeginDragDrop(DragEvent.ToSharedRef());
}
else {
return FReply::Handled();
}
}
//如果是正常的鼠标拖拽
if (!ensure(OwnerSlateNode.IsValid()))
{
return FReply::Unhandled();
}
else
{
TArray<TSharedRef<SGraphPin>> PinArray;
PinArray.Add(SharedThis(this));
TSharedPtr<FDragDropOperation> DragEvent = SpawnPinDragEvent(OwnerSlateNode->GetOwnerPanel().ToSharedRef(), PinArray);
return FReply::Handled().BeginDragDrop(DragEvent.ToSharedRef());
}
}
}
return FReply::Handled();
}));
#if 0
//背景图片
.BorderImage_Lambda([&]() {
const FVector2D ICOSize(64.f, 64.f);
return FTestGraphAndBlueprintStyle::GetImageBrush(TEXT("ButtonIcon_40x"), ICOSize); })
#endif
}