CelticCraft/Plugins/VoxelFree/Source/VoxelGraphEditor/Private/VoxelGraphEditor.cpp

237 lines
No EOL
6.4 KiB
C++

// Copyright 2020 Phyronnaz
#include "VoxelGraphEditor.h"
#include "VoxelEdGraph.h"
#include "VoxelNode.h"
#include "VoxelGraphSchema.h"
#include "VoxelGraphGenerator.h"
#include "IVoxelGraphEditorToolkit.h"
#include "VoxelGraphEditorUtilities.h"
#include "VoxelGraphNodes/VoxelGraphNode_Root.h"
#include "VoxelGraphNodes/VoxelGraphNode.h"
#include "VoxelGraphNodes/VoxelGraphNode_Knot.h"
#include "Kismet2/BlueprintEditorUtils.h"
inline TArray<FVoxelPin> CreateVoxelPinsFromGraphPin(UEdGraphPin& Pin)
{
TArray<FVoxelPin> Result;
if (Pin.SubPins.Num() == 0)
{
Result.Add(FVoxelPin(Pin.PinId, Pin.DefaultValue, FVoxelPinCategory::FromString(Pin.PinType.PinCategory)));
}
else
{
TArray<FString> SubDefaultValues;
Pin.DefaultValue.ParseIntoArray(SubDefaultValues, TEXT(","));
for (int32 Index = 0; Index < Pin.SubPins.Num(); Index++)
{
auto& SubPin = *Pin.SubPins[Index];
Result.Add(FVoxelPin(
SubPin.PinId,
SubDefaultValues.IsValidIndex(Index) ? SubDefaultValues[Index] : "",
FVoxelPinCategory::FromString(SubPin.PinType.PinCategory)));
}
}
const auto CheckOtherPin = [&](UEdGraphPin& OtherPin)
{
auto* const OtherNode = Cast<UVoxelGraphNode>(OtherPin.GetOwningNode());
if (!OtherNode)
{
return;
}
if (Pin.SubPins.Num() > 0)
{
if (!ensure(Pin.SubPins.Num() == OtherPin.SubPins.Num()))
{
return;
}
for (int32 Index = 0; Index < Pin.SubPins.Num(); Index++)
{
Result[Index].OtherNodes.Add(OtherNode->VoxelNode);
Result[Index].OtherPinIds.Add(OtherPin.SubPins[Index]->PinId);
}
}
else
{
Result[0].OtherNodes.Add(OtherNode->VoxelNode);
Result[0].OtherPinIds.Add(OtherPin.PinId);
}
};
if (Pin.LinkedTo.Num() > 0)
{
for (UEdGraphPin* OtherPin : Pin.LinkedTo)
{
auto Knot = Cast<UVoxelGraphNode_Knot>(OtherPin->GetOwningNode());
if (Knot)
{
const auto NewOtherPins = Pin.Direction == EGPD_Input ? Knot->GetAllInputPins() : Knot->GetAllOutputPins();
for (auto& NewOtherPin : NewOtherPins)
{
CheckOtherPin(*NewOtherPin);
}
}
else
{
CheckOtherPin(*OtherPin);
}
}
}
return Result;
}
UEdGraph* FVoxelGraphEditor::CreateNewVoxelGraph(UVoxelGraphGenerator* InGenerator)
{
return CastChecked<UVoxelEdGraph>(FBlueprintEditorUtils::CreateNewGraph(InGenerator, NAME_None, UVoxelEdGraph::StaticClass(), UVoxelGraphSchema::StaticClass()));
}
void FVoxelGraphEditor::CreateVoxelGraphNode(UEdGraph* VoxelGraph, UVoxelNode* InVoxelNode, bool bSelectNewNode)
{
FGraphNodeCreator<UVoxelGraphNode> NodeCreator(*VoxelGraph);
UVoxelGraphNode* GraphNode = NodeCreator.CreateUserInvokedNode(bSelectNewNode);
InVoxelNode->GraphNode = GraphNode;
GraphNode->SetVoxelNode(InVoxelNode);
NodeCreator.Finalize();
}
void FVoxelGraphEditor::CompileVoxelNodesFromGraphNodes(UVoxelGraphGenerator* Generator)
{
Generator->Modify();
{
Generator->FirstNode = nullptr;
Generator->AllNodes.Empty();
TArray<UVoxelNode*> AllNodes;
for (auto& Node : Generator->VoxelGraph->Nodes)
{
UVoxelGraphNode* GraphNode = Cast<UVoxelGraphNode>(Node);
if (GraphNode && GraphNode->VoxelNode)
{
UVoxelNode* VoxelNode = GraphNode->VoxelNode;
check(VoxelNode);
check(!AllNodes.Contains(VoxelNode));
AllNodes.Add(VoxelNode);
TArray<FVoxelPin> InputPins;
for (auto& InputPin : GraphNode->GetInputPins())
{
if (!InputPin->bHidden)
{
InputPins.Append(CreateVoxelPinsFromGraphPin(*InputPin));
}
}
TArray<FVoxelPin> OutputPins;
for (auto& OutputPin : GraphNode->GetOutputPins())
{
if (!OutputPin->bHidden)
{
OutputPins.Append(CreateVoxelPinsFromGraphPin(*OutputPin));
}
}
VoxelNode->SetFlags(RF_Transactional);
VoxelNode->Modify();
VoxelNode->InputPins = InputPins;
VoxelNode->OutputPins = OutputPins;
VoxelNode->PostEditChange();
}
else
{
UVoxelGraphNode_Root* GraphNodeRoot = Cast<UVoxelGraphNode_Root>(Node);
if (GraphNodeRoot)
{
const TArray<UEdGraphPin*> OutputPins = GraphNodeRoot->GetOutputPins();
check(OutputPins.Num() == 1);
check(OutputPins[0]->LinkedTo.Num() <= 1);
if (OutputPins[0]->LinkedTo.Num() == 1)
{
UEdGraphPin* OtherPin = OutputPins[0]->LinkedTo[0];
auto Knot = Cast<UVoxelGraphNode_Knot>(OtherPin->GetOwningNode());
if (Knot)
{
auto NewOtherPins = Knot->GetAllOutputPins();
if (NewOtherPins.Num() > 0)
{
check(NewOtherPins.Num() == 1);
auto NewOtherPin = NewOtherPins[0];
Generator->FirstNode = CastChecked<UVoxelGraphNode>(NewOtherPin->GetOwningNode())->VoxelNode;
Generator->FirstNodePinId = NewOtherPin->PinId;
}
}
else
{
Generator->FirstNode = CastChecked<UVoxelGraphNode>(OtherPin->GetOwningNode())->VoxelNode;
Generator->FirstNodePinId = OtherPin->PinId;
}
}
}
}
}
AllNodes.Remove(nullptr);
Generator->AllNodes = AllNodes;
}
Generator->PostEditChange();
UpdatePreview(Generator, EVoxelGraphPreviewFlags::UpdateTextures);
}
void FVoxelGraphEditor::UpdatePreview(UVoxelGraphGenerator* Generator, EVoxelGraphPreviewFlags Flags)
{
if (auto Editor = FVoxelGraphEditorUtilities::GetIVoxelEditorForGraph(Generator->VoxelGraph))
{
Editor->TriggerUpdatePreview(Flags);
}
}
void FVoxelGraphEditor::SelectNodesAndZoomToFit(UEdGraph* Graph, const TArray<UEdGraphNode*>& Nodes)
{
if (auto Editor = FVoxelGraphEditorUtilities::GetIVoxelEditorForGraph(Graph))
{
Editor->SelectNodesAndZoomToFit(Nodes);
}
}
void FVoxelGraphEditor::RefreshNodesMessages(UEdGraph* Graph)
{
if (auto Editor = FVoxelGraphEditorUtilities::GetIVoxelEditorForGraph(Graph))
{
Editor->RefreshNodesMessages();
}
}
void FVoxelGraphEditor::DebugNodes(UEdGraph* DebugGraph, const TSet<FVoxelCompilationNode*>& Nodes)
{
if (auto Editor = FVoxelGraphEditorUtilities::GetIVoxelEditorForGraph(DebugGraph))
{
Editor->DebugNodes(Nodes);
}
}
void FVoxelGraphEditor::AddMessages(const UVoxelGraphGenerator* Generator, const TArray<FVoxelGraphMessage>& Messages)
{
if (auto Editor = FVoxelGraphEditorUtilities::GetIVoxelEditorForGraph(Generator->VoxelGraph))
{
Editor->AddMessages(Messages);
}
}
void FVoxelGraphEditor::ClearMessages(const UVoxelGraphGenerator* Generator, bool bClearAll, EVoxelGraphNodeMessageType MessagesToClear)
{
if (auto Editor = FVoxelGraphEditorUtilities::GetIVoxelEditorForGraph(Generator->VoxelGraph))
{
Editor->ClearMessages(bClearAll, MessagesToClear);
}
}