2024-01-25 11:21:15 +08:00

173 lines
3.9 KiB
C++

// Fill out your copyright notice in the Description page of Project Settings.
#include "SChannelNode.h"
#include "MultiBoxBuilder.h"
#include "SButton.h"
#include "SChannelNodeButton.h"
#include "SlateApplication.h"
#include "SlateOptMacros.h"
#include "SMenuAnchor.h"
#include "SOverlay.h"
#include "SSplitter.h"
#include "STextBlock.h"
#include "Singleton/MixerList.h"
#include "Mixer/MixerTrack.h"
#include "Widgets/SBoxPanel.h"
BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
void SChannelNode::Construct(const FArguments& InArgs, FChannelNode* InChannelNode, FChannelInterface* InNodeOwner, int32 NodeNameIndex)
{
ChannelNode = InChannelNode;
ChannelNodeType = InArgs._ChannelNodeType;
NodeOwner = InNodeOwner;
NodeIndex = NodeNameIndex;
FText PortName = FText::FromString(GetNodeName(NodeNameIndex));
ChildSlot
[
SNew(SHorizontalBox)
+SHorizontalBox::Slot()
.FillWidth(1)
[
SAssignNew(PortTextBlock, STextBlock)
.Text(PortName)
]
+SHorizontalBox::Slot()
.AutoWidth()
[
SAssignNew(ChangeNodeButton, SButton)
.OnClicked_Lambda([this]()
{
ShowNodeSelectMenu();
return FReply::Handled();
})
[
SAssignNew(NodeNameTextBlock, STextBlock)
.Text(FText::FromString(ChannelNode->GetName()))
]
]
];
}
void SChannelNode::ShowNodeSelectMenu()
{
FMenuBuilder MenuBuilder(true, nullptr);
MenuBuilder.AddWidget(
CreateNodeSelectMenu(),
FText()
);
auto Pos = ChangeNodeButton->GetTickSpaceGeometry().GetAbsolutePosition();
Pos.Y += ChangeNodeButton->GetTickSpaceGeometry().GetAbsoluteSize().Y;
FSlateApplication::Get().PushMenu(SharedThis(this), FWidgetPath(), MenuBuilder.MakeWidget(), Pos, FPopupTransitionEffect::ComboButton);
}
TSharedRef<SWidget> SChannelNode::CreateNodeSelectMenu()
{
TSharedRef<SVerticalBox> MenuBox = SNew(SVerticalBox);
MenuBox->AddSlot()
.AutoHeight()
[
SNew(SChannelNodeButton, FNullChannelNode::Get())
.OnClickedDelegate(this, &SChannelNode::OnMenuNodeSelected)
];
FMixerList& MixerList = FMixerList::Get();
for (const FMixerTrack* Mixer : MixerList)
{
MenuBox->AddSlot()
.AutoHeight()
[
SNew(STextBlock)
.Text(FText::FromString(Mixer->GetName()))
];
const TArray<FChannelNode*>& MixerOutputNodes = Mixer->GetChannelInterface()->OutputChannelNodes;
for (FChannelNode* MixerChannelNode : MixerOutputNodes)
{
MenuBox->AddSlot()
.AutoHeight()
[
SNew(SChannelNodeButton, MixerChannelNode)
.OnClickedDelegate(this, &SChannelNode::OnMenuNodeSelected)
];
}
}
return MenuBox;
}
void SChannelNode::OnMenuNodeSelected(FChannelNode* Node)
{
check(NodeOwner);
switch (ChannelNodeType)
{
case EChannelNodeType::InputNode:
{
NodeIndex = NodeOwner->GetInputNodeIndex(ChannelNode);
NodeOwner->SetInputChannel(NodeIndex, Node);
break;
}
case EChannelNodeType::OutputNode:
{
NodeIndex = NodeOwner->GetOutputNodeIndex(ChannelNode);
NodeOwner->SetOutputChannel(NodeIndex, Node);
break;
}
default: ;
}
ChannelNode = Node;
NodeNameTextBlock->SetText(FText::FromString(Node->GetName()));
}
FString SChannelNode::GetNodeName(int32 NodeNameIndex)
{
FString PortName;
TMap<int32, FName> PortNames;
switch (ChannelNodeType)
{
case EChannelNodeType::InputNode:
PortNames = NodeOwner->GetInputChannelNodeName(ChannelNode);
break;
case EChannelNodeType::OutputNode:
PortNames = NodeOwner->GetOutputChannelNodeName(ChannelNode);
break;
default: ;
}
const FName* NameA = PortNames.Find(NodeNameIndex);
const FName* NameB = PortNames.Find(NodeNameIndex + 1);
if (NameA && NameB)
{
if (*NameA == *NameB)
PortName = NameA->ToString();
else
PortName = FString::Printf(TEXT("%s-%s"), *NameA->ToString(), *NameB->ToString());
}
else if (NameA)
{
PortName = NameA->ToString();
}
else if (NameB)
{
PortName = NameB->ToString();
}
else
{
PortName = TEXT("Null");
}
return PortName;
}
END_SLATE_FUNCTION_BUILD_OPTIMIZATION