#jira UEAU-524

Implement UMetasoundSource, Archetype registry, and implement Archetype support in the metasound editor.
#rb rob.gay, phil.popp
#fyi rob.gay, phil.popp

[CL 13940440 by Ethan Geller in ue5-main branch]
This commit is contained in:
Ethan Geller
2020-07-23 20:32:26 -04:00
parent 6b4a1390f6
commit 529318d783
44 changed files with 1862 additions and 201 deletions

View File

@@ -3,6 +3,7 @@
#include "MetasoundAssetTypeActions.h"
#include "Metasound.h"
#include "MetasoundSource.h"
#include "MetasoundEditor.h"
@@ -40,6 +41,32 @@ namespace Metasound
}
}
}
UClass* FAssetTypeActions_MetasoundSource::GetSupportedClass() const
{
return UMetasoundSource::StaticClass();
}
void FAssetTypeActions_MetasoundSource::OpenAssetEditor(const TArray<UObject*>& InObjects, TSharedPtr<IToolkitHost> ToolkitHost)
{
const EToolkitMode::Type Mode = ToolkitHost.IsValid() ? EToolkitMode::WorldCentric : EToolkitMode::Standalone;
for (UObject* Object : InObjects)
{
if (UMetasoundSource* Metasound = Cast<UMetasoundSource>(Object))
{
TSharedRef<FEditor> NewEditor = MakeShared<FEditor>();
NewEditor->InitMetasoundEditor(Mode, ToolkitHost, Metasound);
}
}
}
const TArray<FText>& FAssetTypeActions_MetasoundSource::GetSubMenus() const
{
return AssetTypeActionSubMenu;
}
} // namespace Editor
} // namespace Metasound
#undef LOCTEXT_NAMESPACE

View File

@@ -24,5 +24,18 @@ namespace Metasound
virtual const TArray<FText>& GetSubMenus() const override;
};
class FAssetTypeActions_MetasoundSource : public FAssetTypeActions_Base
{
public:
// IAssetTypeActions Implementation
virtual FText GetName() const override { return NSLOCTEXT("AssetTypeActions", "AssetTypeActions_MetasoundSource", "MetasoundSource"); }
virtual FColor GetTypeColor() const override { return FColor(220, 160, 0); }
virtual UClass* GetSupportedClass() const override;
virtual uint32 GetCategories() override { return EAssetTypeCategories::Sounds; }
virtual void OpenAssetEditor(const TArray<UObject*>& InObjects, TSharedPtr<IToolkitHost> ToolkitHost) override;
virtual const TArray<FText>& GetSubMenus() const override;
};
} // namespace Editor
} // namespace Metasound

View File

@@ -93,18 +93,22 @@ namespace Metasound
void FEditor::InitMetasoundEditor(const EToolkitMode::Type Mode, const TSharedPtr<IToolkitHost>& InitToolkitHost, UObject* ObjectToEdit)
{
Metasound = CastChecked<UMetasound>(ObjectToEdit);
checkf(Frontend::IsObjectAMetasoundArchetype(ObjectToEdit), TEXT("Object passed in was not registered as a valid metasound archetype!"));
Metasound = ObjectToEdit;
FMetasoundAssetBase* MetasoundAsset = Frontend::GetObjectAsAssetBase(ObjectToEdit);
check(MetasoundAsset);
// Support undo/redo
Metasound->SetFlags(RF_Transactional);
ObjectToEdit->SetFlags(RF_Transactional);
if (!Metasound->GetGraph())
if (!MetasoundAsset->GetGraph())
{
UMetasoundEditorGraph* Graph = NewObject<UMetasoundEditorGraph>(Metasound);
Graph->ParentMetasound = Metasound;
Graph->Schema = UMetasoundEditorGraphSchema::StaticClass();
Metasound->SetGraph(Graph);
MetasoundAsset->SetGraph(Graph);
FGraphBuilder::RebuildGraph(*Metasound);
}
GEditor->RegisterForUndo(this);
@@ -163,7 +167,7 @@ namespace Metasound
RegenerateMenusAndToolbars();
}
UMetasound* FEditor::GetMetasound() const
UObject* FEditor::GetMetasoundObject() const
{
return Metasound;
}
@@ -338,44 +342,70 @@ namespace Metasound
void FEditor::Import()
{
if (Metasound)
FMetasoundAssetBase* MetasoundAsset = Frontend::GetObjectAsAssetBase(Metasound);
if (MetasoundAsset)
{
// TODO: Prompt OFD and provide path from user
const FString Path = FPaths::ProjectIntermediateDir() / TEXT("Metasounds") + FPaths::ChangeExtension(Metasound->GetPathName(), FMetasoundAssetBase::FileExtension);
Metasound->ImportFromJSON(Path);
const FString InputPath = FPaths::ProjectIntermediateDir() / TEXT("Metasounds") + FPaths::ChangeExtension(Metasound->GetPathName(), FMetasoundAssetBase::FileExtension);
// TODO: use the same directory as the currently open metasound
const FString OutputPath = FString("/Game/ImportedMetasound/GeneratedMetasound");
FMetasoundDocument MetasoundDoc;
if (Frontend::ImportJSONToMetasound(InputPath, MetasoundDoc))
{
Frontend::GetObjectForDocument(MetasoundDoc, OutputPath);
}
else
{
UE_LOG(LogTemp, Warning, TEXT("Couldn't import Metasound at path: %s"), *InputPath);
}
}
}
void FEditor::Export()
{
if (Metasound)
FMetasoundAssetBase* InMetasoundAsset = Frontend::GetObjectAsAssetBase(Metasound);
check(InMetasoundAsset);
if (!InMetasoundAsset)
{
// TODO: Prompt OFD and provide path from user
const FString Path = FPaths::ProjectIntermediateDir() / TEXT("Metasounds") + FPaths::ChangeExtension(Metasound->GetPathName(), FMetasoundAssetBase::FileExtension);
Metasound->ExportToJSON(Path);
return;
}
static const FString MetasoundExtension(TEXT(".metasound"));
// TODO: We could just make this an object.
const FString Path = FPaths::ProjectSavedDir() / TEXT("Metasounds") + FPaths::ChangeExtension(Metasound->GetPathName(), MetasoundExtension);
InMetasoundAsset->ExportToJSON(Path);
}
void FEditor::Play()
{
// TODO: Implement play
// check(GEditor);
// GEditor->PlayPreviewSound(Metasound);
//
// MetasoundGraphEditor->RegisterActiveTimer(0.0f,
// FWidgetActiveTimerDelegate::CreateLambda([](double InCurrentTime, float InDeltaTime)
// {
// UAudioComponent* PreviewComp = GEditor->GetPreviewAudioComponent();
// if (PreviewComp && PreviewComp->IsPlaying())
// {
// return EActiveTimerReturnType::Continue;
// }
// else
// {
// return EActiveTimerReturnType::Stop;
// }
// })
// );
check(GEditor);
// TODO: toggle the Play button if Metasound is a USoundBase
if (USoundBase* MetasoundToPlay = Cast<USoundBase>(Metasound))
{
GEditor->PlayPreviewSound(MetasoundToPlay);
MetasoundGraphEditor->RegisterActiveTimer(0.0f,
FWidgetActiveTimerDelegate::CreateLambda([](double InCurrentTime, float InDeltaTime)
{
UAudioComponent* PreviewComp = GEditor->GetPreviewAudioComponent();
if (PreviewComp && PreviewComp->IsPlaying())
{
return EActiveTimerReturnType::Continue;
}
else
{
return EActiveTimerReturnType::Stop;
}
})
);
}
}
void FEditor::PlayNode()
@@ -543,11 +573,14 @@ namespace Metasound
InEvents.OnTextCommitted = FOnNodeTextCommitted::CreateSP(this, &FEditor::OnNodeTitleCommitted);
InEvents.OnNodeDoubleClicked = FSingleNodeEvent::CreateSP(this, &FEditor::PlaySingleNode);
FMetasoundAssetBase* MetasoundAsset = Frontend::GetObjectAsAssetBase(Metasound);
check(MetasoundAsset);
return SNew(SGraphEditor)
.AdditionalCommands(GraphEditorCommands)
.IsEditable(true)
.Appearance(AppearanceInfo)
.GraphToEdit(Metasound->GetGraph())
.GraphToEdit(MetasoundAsset->GetGraph())
.GraphEvents(InEvents)
.AutoExpandActionMenu(true)
.ShowGraphStateOverlay(false);
@@ -563,7 +596,7 @@ namespace Metasound
{
if (Cast<UMetasoundEditorGraphNode>(*SetIt))
{
Selection.Add(GetMetasound());
Selection.Add(GetMetasoundObject());
}
else
{
@@ -573,7 +606,7 @@ namespace Metasound
}
else
{
Selection.Add(GetMetasound());
Selection.Add(GetMetasoundObject());
}
SetSelection(Selection);
@@ -601,11 +634,16 @@ namespace Metasound
const FGraphPanelSelectionSet SelectedNodes = MetasoundGraphEditor->GetSelectedNodes();
MetasoundGraphEditor->ClearSelectionSet();
FGraphHandle GraphHandle = Graph->ParentMetasound->GetRootGraphHandle();
for (FGraphPanelSelectionSet::TConstIterator NodeIt(SelectedNodes); NodeIt; ++NodeIt)
UObject* ParentMetasoundObject = Graph->ParentMetasound;
if (FMetasoundAssetBase* MetasoundAsset = GetObjectAsAssetBase(ParentMetasoundObject))
{
UMetasoundEditorGraphNode* Node = CastChecked<UMetasoundEditorGraphNode>(*NodeIt);
FGraphBuilder::DeleteNode(*Node, false /* bInRecordTransaction */);
FGraphHandle GraphHandle = MetasoundAsset->GetRootGraphHandle();
for (FGraphPanelSelectionSet::TConstIterator NodeIt(SelectedNodes); NodeIt; ++NodeIt)
{
UMetasoundEditorGraphNode* Node = CastChecked<UMetasoundEditorGraphNode>(*NodeIt);
FGraphBuilder::DeleteNode(*Node, false /* bInRecordTransaction */);
}
}
}
@@ -708,7 +746,14 @@ namespace Metasound
void FEditor::PasteNodesAtLocation(const FVector2D& Location)
{
UEdGraph* Graph = Metasound->GetGraph();
FMetasoundAssetBase* MetasoundAsset = Frontend::GetObjectAsAssetBase(Metasound);
if (!ensureAlways(MetasoundAsset))
{
return;
}
UEdGraph* Graph = MetasoundAsset->GetGraph();
if (!Graph)
{
return;

View File

@@ -43,7 +43,7 @@ namespace Metasound
void InitMetasoundEditor(const EToolkitMode::Type Mode, const TSharedPtr<IToolkitHost>& InitToolkitHost, UObject* ObjectToEdit);
/** IMetasoundEditor interface */
virtual UMetasound* GetMetasound() const override;
virtual UObject* GetMetasoundObject() const override;
virtual void SetSelection(const TArray<UObject*>& SelectedObjects) override;
virtual bool GetBoundsForSelectedNodes(FSlateRect& Rect, float Padding) override;
@@ -194,7 +194,7 @@ namespace Metasound
TSharedPtr<FUICommandList> GraphEditorCommands;
/** The Metasound asset being edited */
UMetasound* Metasound = nullptr;
UObject* Metasound = nullptr;
/** Whether or not metasound being edited is valid */
bool bPassedValidation = true;

View File

@@ -4,12 +4,12 @@
#include "EdGraph/EdGraphNode.h"
UMetasound* UMetasoundEditorGraph::GetMetasound() const
UObject* UMetasoundEditorGraph::GetMetasound() const
{
return ParentMetasound;
}
UMetasound& UMetasoundEditorGraph::GetMetasoundChecked() const
UObject& UMetasoundEditorGraph::GetMetasoundChecked() const
{
check(ParentMetasound);
return *ParentMetasound;

View File

@@ -26,13 +26,16 @@ namespace Metasound
const FName FGraphBuilder::PinPrimitiveInteger = "Int";
const FName FGraphBuilder::PinPrimitiveString = "String";
UEdGraphNode* FGraphBuilder::AddNode(UMetasound& InMetasound, const FVector2D& Location, Frontend::FNodeHandle& InNodeHandle, bool bInSelectNewNode)
UEdGraphNode* FGraphBuilder::AddNode(UObject& InMetasound, const FVector2D& Location, Frontend::FNodeHandle& InNodeHandle, bool bInSelectNewNode)
{
const FScopedTransaction Transaction(LOCTEXT("AddMetasoundGraphNode", "Add Metasound Node"));
const FString EdNodeName = InNodeHandle.GetNodeClassName() + TEXT("_") + FString::FromInt(InNodeHandle.GetNodeID());
UEdGraph& Graph = InMetasound.GetGraphChecked();
FMetasoundAssetBase* MetasoundAsset = Frontend::GetObjectAsAssetBase(&InMetasound);
check(MetasoundAsset);
UEdGraph& Graph = MetasoundAsset->GetGraphChecked();
FGraphNodeCreator<UMetasoundEditorGraphNode> NodeCreator(Graph);
UMetasoundEditorGraphNode* NewGraphNode = NodeCreator.CreateNode(bInSelectNewNode);
NodeCreator.Finalize();
@@ -50,31 +53,40 @@ namespace Metasound
return NewGraphNode;
}
UEdGraphNode* FGraphBuilder::AddNode(UMetasound& InMetasound, const FVector2D& Location, const Frontend::FNodeClassInfo& InClassInfo, bool bInSelectNewNode)
UEdGraphNode* FGraphBuilder::AddNode(UObject& InMetasound, const FVector2D& Location, const Frontend::FNodeClassInfo& InClassInfo, bool bInSelectNewNode)
{
Frontend::FNodeHandle NodeHandle = InMetasound.GetRootGraphHandle().AddNewNode(InClassInfo);
FMetasoundAssetBase* MetasoundAsset = Frontend::GetObjectAsAssetBase(&InMetasound);
check(MetasoundAsset);
Frontend::FNodeHandle NodeHandle = MetasoundAsset->GetRootGraphHandle().AddNewNode(InClassInfo);
return AddNode(InMetasound, Location, NodeHandle, bInSelectNewNode);
}
UEdGraphNode* FGraphBuilder::AddInput(UMetasound& InMetasound, const FVector2D& Location, const FString& InName, const FName InTypeName, const FText& InToolTip, bool bInSelectNewNode)
UEdGraphNode* FGraphBuilder::AddInput(UObject& InMetasound, const FVector2D& Location, const FString& InName, const FName InTypeName, const FText& InToolTip, bool bInSelectNewNode)
{
FMetasoundInputDescription Description;
Description.Name = InName;
Description.TypeName = InTypeName;
Description.ToolTip = InToolTip;
Frontend::FNodeHandle NodeHandle = InMetasound.GetRootGraphHandle().AddNewInput(Description);
FMetasoundAssetBase* MetasoundAsset = Frontend::GetObjectAsAssetBase(&InMetasound);
check(MetasoundAsset);
Frontend::FNodeHandle NodeHandle = MetasoundAsset->GetRootGraphHandle().AddNewInput(Description);
return AddNode(InMetasound, Location, NodeHandle, bInSelectNewNode);
}
UEdGraphNode* FGraphBuilder::AddOutput(UMetasound& InMetasound, const FVector2D& Location, const FString& InName, const FName InTypeName, const FText& InToolTip, bool bInSelectNewNode)
UEdGraphNode* FGraphBuilder::AddOutput(UObject& InMetasound, const FVector2D& Location, const FString& InName, const FName InTypeName, const FText& InToolTip, bool bInSelectNewNode)
{
FMetasoundOutputDescription Description;
Description.Name = InName;
Description.TypeName = InTypeName;
Description.ToolTip = InToolTip;
Frontend::FNodeHandle NodeHandle = InMetasound.GetRootGraphHandle().AddNewOutput(Description);
FMetasoundAssetBase* MetasoundAsset = Frontend::GetObjectAsAssetBase(&InMetasound);
check(MetasoundAsset);
Frontend::FNodeHandle NodeHandle = MetasoundAsset->GetRootGraphHandle().AddNewOutput(Description);
return AddNode(InMetasound, Location, NodeHandle, bInSelectNewNode);
}
@@ -90,7 +102,11 @@ namespace Metasound
}
const Frontend::FNodeHandle& NodeHandle = InNode.GetNodeHandle();
Frontend::FGraphHandle GraphHandle = Graph->GetMetasoundChecked().GetRootGraphHandle();
FMetasoundAssetBase* MetasoundAsset = Frontend::GetObjectAsAssetBase(Graph->GetMetasound());
check(MetasoundAsset);
Frontend::FGraphHandle GraphHandle = MetasoundAsset->GetRootGraphHandle();
if (GraphHandle.IsValid() && NodeHandle.IsValid())
{
switch (NodeHandle.GetNodeType())
@@ -119,12 +135,15 @@ namespace Metasound
InNode.MarkPackageDirty();
}
void FGraphBuilder::RebuildGraph(UMetasound& InMetasound)
void FGraphBuilder::RebuildGraph(UObject& InMetasound)
{
using namespace Frontend;
FGraphHandle GraphHandle = InMetasound.GetRootGraphHandle();
UMetasoundEditorGraph* Graph = CastChecked<UMetasoundEditorGraph>(InMetasound.GetGraph());
FMetasoundAssetBase* MetasoundAsset = GetObjectAsAssetBase(&InMetasound);
check(MetasoundAsset);
FGraphHandle GraphHandle = MetasoundAsset->GetRootGraphHandle();
UMetasoundEditorGraph* Graph = CastChecked<UMetasoundEditorGraph>(MetasoundAsset->GetGraph());
Graph->Nodes.Reset();

View File

@@ -28,18 +28,18 @@ namespace Metasound
static const FName PinPrimitiveString;
// Adds a node to the editor graph that corresponds to the provided node handle.
static UEdGraphNode* AddNode(UMetasound& InMetasound, const FVector2D& Location, Frontend::FNodeHandle& InNodeHandle, bool bInSelectNewNode = true);
static UEdGraphNode* AddNode(UObject& InMetasound, const FVector2D& Location, Frontend::FNodeHandle& InNodeHandle, bool bInSelectNewNode = true);
// Adds a node with the given class info to both the editor and document graphs
static UEdGraphNode* AddNode(UMetasound& InMetasound, const FVector2D& Location, const Frontend::FNodeClassInfo& InClassInfo, bool bInSelectNewNode = true);
static UEdGraphNode* AddNode(UObject& InMetasound, const FVector2D& Location, const Frontend::FNodeClassInfo& InClassInfo, bool bInSelectNewNode = true);
static UEdGraphNode* AddInput(UMetasound& InMetasound, const FVector2D& Location, const FString& InName, const FName InTypeName, const FText& InToolTip, bool bInSelectNewNode = true);
static UEdGraphNode* AddInput(UObject& InMetasound, const FVector2D& Location, const FString& InName, const FName InTypeName, const FText& InToolTip, bool bInSelectNewNode = true);
static UEdGraphNode* AddOutput(UMetasound& InMetasound, const FVector2D& Location, const FString& InName, const FName InTypeName, const FText& InToolTip, bool bInSelectNewNode = true);
static UEdGraphNode* AddOutput(UObject& InMetasound, const FVector2D& Location, const FString& InName, const FName InTypeName, const FText& InToolTip, bool bInSelectNewNode = true);
static void DeleteNode(UMetasoundEditorGraphNode& InNode, bool bInRecordTransaction = true);
static void RebuildGraph(UMetasound& InMetasound);
static void RebuildGraph(UObject& InMetasound);
static void RebuildNodePins(UMetasoundEditorGraphNode& InGraphNode, Frontend::FNodeHandle& InNodeHandle, bool bInRecordTransaction = true);
};

View File

@@ -8,6 +8,7 @@
#include "Framework/Commands/GenericCommands.h"
#include "GraphEditorActions.h"
#include "Metasound.h"
#include "MetasoundFrontend.h"
#include "MetasoundEditorGraph.h"
#include "MetasoundEditorGraphBuilder.h"
#include "MetasoundEditorGraphSchema.h"
@@ -72,13 +73,13 @@ int32 UMetasoundEditorGraphNode::EstimateNodeWidth() const
}
}
UMetasound& UMetasoundEditorGraphNode::GetMetasoundChecked()
UObject& UMetasoundEditorGraphNode::GetMetasoundChecked()
{
UMetasoundEditorGraph* EdGraph = CastChecked<UMetasoundEditorGraph>(GetGraph());
return EdGraph->GetMetasoundChecked();
}
const UMetasound& UMetasoundEditorGraphNode::GetMetasoundChecked() const
const UObject& UMetasoundEditorGraphNode::GetMetasoundChecked() const
{
UMetasoundEditorGraph* EdGraph = CastChecked<UMetasoundEditorGraph>(GetGraph());
return EdGraph->GetMetasoundChecked();
@@ -86,7 +87,10 @@ const UMetasound& UMetasoundEditorGraphNode::GetMetasoundChecked() const
Metasound::Frontend::FGraphHandle UMetasoundEditorGraphNode::GetRootGraphHandle() const
{
return GetMetasoundChecked().GetRootGraphHandle();
const FMetasoundAssetBase* MetasoundAsset = Metasound::Frontend::GetObjectAsAssetBase(&GetMetasoundChecked());
check(MetasoundAsset);
return MetasoundAsset->GetRootGraphHandle();
}
Metasound::Frontend::FNodeHandle UMetasoundEditorGraphNode::GetNodeHandle() const
@@ -282,17 +286,21 @@ FText UMetasoundEditorGraphNode::GetTooltipText() const
// TODO: Add author to ToolTip
FNodeHandle NodeHandle = GetNodeHandle();
const FMetasoundAssetBase* MetasoundAsset = GetObjectAsAssetBase(&GetMetasoundChecked());
check(MetasoundAsset);
switch (NodeHandle.GetNodeType())
{
case EMetasoundClassType::Input:
{
return GetMetasoundChecked().GetInputToolTip(NodeHandle.GetNodeName());
return MetasoundAsset->GetInputToolTip(NodeHandle.GetNodeName());
}
break;
case EMetasoundClassType::Output:
{
return GetMetasoundChecked().GetOutputToolTip(NodeHandle.GetNodeName());
return MetasoundAsset->GetOutputToolTip(NodeHandle.GetNodeName());
}
break;

View File

@@ -57,7 +57,7 @@ namespace Metasound
return Categories;
}
TSharedPtr<FEditor> GetEditorForGraph(const UMetasound& Metasound)
TSharedPtr<FEditor> GetEditorForGraph(const UObject& Metasound)
{
TSharedPtr<IToolkit> FoundAssetEditor = FToolkitManager::Get().FindEditorForAsset(CastChecked<const UObject>(&Metasound));
return StaticCastSharedPtr<FEditor, IToolkit>(FoundAssetEditor);
@@ -170,7 +170,7 @@ UEdGraphNode* FMetasoundGraphSchemaAction_NewNode::PerformAction(UEdGraph* Paren
ParentGraph->Modify();
UMetasound& ParentMetasound = CastChecked<UMetasoundEditorGraph>(ParentGraph)->GetMetasoundChecked();
UObject& ParentMetasound = CastChecked<UMetasoundEditorGraph>(ParentGraph)->GetMetasoundChecked();
ParentMetasound.Modify();
UEdGraphNode* NewGraphNode = FGraphBuilder::AddNode(ParentMetasound, Location, NodeClassInfo);
@@ -193,12 +193,15 @@ UEdGraphNode* FMetasoundGraphSchemaAction_NewInput::PerformAction(UEdGraph* Pare
ParentGraph->Modify();
UMetasound& ParentMetasound = CastChecked<UMetasoundEditorGraph>(ParentGraph)->GetMetasoundChecked();
UObject& ParentMetasound = CastChecked<UMetasoundEditorGraph>(ParentGraph)->GetMetasoundChecked();
ParentMetasound.Modify();
FString NameBase = GetDataTypeDisplayName(NodeTypeName);
FGraphHandle GraphHandle = ParentMetasound.GetRootGraphHandle();
FMetasoundAssetBase* MetasoundAsset = GetObjectAsAssetBase(&ParentMetasound);
check(MetasoundAsset);
FGraphHandle GraphHandle = MetasoundAsset->GetRootGraphHandle();
int32 i = 1;
FString NewNodeName = NameBase + FString::Printf(TEXT("_%02d"), i);
@@ -226,12 +229,15 @@ UEdGraphNode* FMetasoundGraphSchemaAction_NewOutput::PerformAction(UEdGraph* Par
ParentGraph->Modify();
UMetasound& ParentMetasound = CastChecked<UMetasoundEditorGraph>(ParentGraph)->GetMetasoundChecked();
UObject& ParentMetasound = CastChecked<UMetasoundEditorGraph>(ParentGraph)->GetMetasoundChecked();
ParentMetasound.Modify();
FString NameBase = GetDataTypeDisplayName(NodeTypeName);
FGraphHandle GraphHandle = ParentMetasound.GetRootGraphHandle();
FMetasoundAssetBase* MetasoundAsset = GetObjectAsAssetBase(&ParentMetasound);
check(MetasoundAsset);
FGraphHandle GraphHandle = MetasoundAsset->GetRootGraphHandle();
int32 i = 1;
FString NewNodeName = NameBase + FString::Printf(TEXT("_%02d"), i);

View File

@@ -11,6 +11,7 @@
#include "EditorStyleSet.h"
#include "IDetailCustomization.h"
#include "Metasound.h"
#include "MetasoundSource.h"
#include "MetasoundAssetTypeActions.h"
#include "MetasoundDetailCustomization.h"
#include "MetasoundEditorGraphBuilder.h"
@@ -150,19 +151,24 @@ namespace Metasound
// Register Metasound asset type actions
IAssetTools& AssetTools = FModuleManager::LoadModuleChecked<FAssetToolsModule>(AssetToolName).Get();
AddAssetAction<FAssetTypeActions_Metasound>(AssetTools, AssetActions);
AddAssetAction<FAssetTypeActions_MetasoundSource>(AssetTools, AssetActions);
FPropertyEditorModule& PropertyModule = FModuleManager::LoadModuleChecked<FPropertyEditorModule>("PropertyEditor");
PropertyModule.RegisterCustomClassLayout(
UMetasound::StaticClass()->GetFName(),
FOnGetDetailCustomizationInstance::CreateLambda([]() { return MakeShared<FMetasoundDetailCustomization>(); }));
PropertyModule.RegisterCustomClassLayout(
UMetasoundSource::StaticClass()->GetFName(),
FOnGetDetailCustomizationInstance::CreateLambda([]() { return MakeShared<FMetasoundDetailCustomization>(); }));
StyleSet = MakeShared<FSlateStyle>();
RegisterCoreDataTypes();
GraphConnectionFactory = MakeShared<FGraphConnectionDrawingPolicyFactory>();
FEdGraphUtilities::RegisterVisualPinConnectionFactory(GraphConnectionFactory);
}
virtual void ShutdownModule() override

View File

@@ -3,8 +3,9 @@
#include "Kismet/KismetSystemLibrary.h"
#include "Metasound.h"
#include "MetasoundSource.h"
#include "MetasoundEditorGraphNode.h"
#include "MetasoundEditorGraphBuilder.h"
UMetasoundFactory::UMetasoundFactory(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
@@ -18,13 +19,37 @@ UMetasoundFactory::UMetasoundFactory(const FObjectInitializer& ObjectInitializer
UObject* UMetasoundFactory::FactoryCreateNew(UClass* InClass, UObject* InParent, FName Name, EObjectFlags Flags, UObject* InContext, FFeedbackContext* InFeedbackContext)
{
UMetasound* Metasound = NewObject<UMetasound>(InParent, Name, Flags);
UMetasound* NewMetasound = NewObject<UMetasound>(InParent, Name, Flags);
FMetasoundClassMetadata Metadata;
Metadata.NodeName = Metasound->GetName();
Metadata.NodeName = NewMetasound->GetName();
Metadata.NodeType = EMetasoundClassType::MetasoundGraph;
Metadata.AuthorName = FText::FromString(UKismetSystemLibrary::GetPlatformUserName());
Metasound->SetMetadata(Metadata);
NewMetasound->SetMetadata(Metadata);
return Metasound;
NewMetasound->ConformDocumentToArchetype();
return NewMetasound;
}
UMetasoundSourceFactory::UMetasoundSourceFactory(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
SupportedClass = UMetasoundSource::StaticClass();
bCreateNew = true;
bEditorImport = false;
bEditAfterNew = true;
}
UObject* UMetasoundSourceFactory::FactoryCreateNew(UClass* InClass, UObject* InParent, FName Name, EObjectFlags Flags, UObject* InContext, FFeedbackContext* InFeedbackContext)
{
UMetasoundSource* MetasoundSource = NewObject<UMetasoundSource>(InParent, Name, Flags);
FMetasoundClassMetadata Metadata;
Metadata.NodeName = MetasoundSource->GetName();
Metadata.NodeType = EMetasoundClassType::MetasoundGraph;
Metadata.AuthorName = FText::FromString(UKismetSystemLibrary::GetPlatformUserName());
MetasoundSource->SetMetadata(Metadata);
MetasoundSource->ConformDocumentToArchetype();
return MetasoundSource;
}

View File

@@ -12,7 +12,7 @@
class IMetasoundEditor : public FAssetEditorToolkit
{
virtual UMetasound* GetMetasound() const = 0;
virtual UObject* GetMetasoundObject() const = 0;
virtual void SetSelection(const TArray<UObject*>& SelectedObjects) = 0;
virtual bool GetBoundsForSelectedNodes(FSlateRect& Rect, float Padding) = 0;
};

View File

@@ -19,12 +19,12 @@ class UMetasoundEditorGraph : public UEdGraph
GENERATED_BODY()
public:
UMetasound* GetMetasound() const;
UMetasound& GetMetasoundChecked() const;
UObject* GetMetasound() const;
UObject& GetMetasoundChecked() const;
private:
UPROPERTY()
UMetasound* ParentMetasound;
UObject* ParentMetasound;
friend class Metasound::Editor::FEditor;
};

View File

@@ -54,8 +54,8 @@ public:
virtual void PostDuplicate(bool bDuplicateForPIE) override;
// End of UObject interface
UMetasound& GetMetasoundChecked();
const UMetasound& GetMetasoundChecked() const;
UObject& GetMetasoundChecked();
const UObject& GetMetasoundChecked() const;
Metasound::Frontend::FGraphHandle GetRootGraphHandle() const;
Metasound::Frontend::FNodeHandle GetNodeHandle() const;

View File

@@ -17,3 +17,13 @@ class UMetasoundFactory : public UFactory
virtual UObject* FactoryCreateNew(UClass* InClass, UObject* InParent, FName Name, EObjectFlags Flags, UObject* InContext, FFeedbackContext* InFeedbackContext) override;
//~ Begin UFactory Interface
};
UCLASS(hidecategories = Object, MinimalAPI)
class UMetasoundSourceFactory : public UFactory
{
GENERATED_UCLASS_BODY()
//~ Begin UFactory Interface
virtual UObject* FactoryCreateNew(UClass* InClass, UObject* InParent, FName Name, EObjectFlags Flags, UObject* InContext, FFeedbackContext* InFeedbackContext) override;
//~ Begin UFactory Interface
};

View File

@@ -14,7 +14,8 @@ namespace UnrealBuildTool.Rules
new string[]
{
"Core",
"MetasoundGraphCore"
"MetasoundGraphCore",
"MetasoundGenerator"
}
);

View File

@@ -6,6 +6,7 @@
#include "StructSerializer.h"
#include "UObject/UnrealType.h"
#include "MetasoundArchetypeRegistration.h"
UMetasound::UMetasound(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
@@ -36,32 +37,6 @@ const UEdGraph& UMetasound::GetGraphChecked() const
return *Graph;
}
const FText& UMetasound::GetInputToolTip(FString InputName) const
{
for (const FMetasoundInputDescription& Desc : RootMetasoundDocument.RootClass.Inputs)
{
if (Desc.Name == InputName)
{
return Desc.ToolTip;
}
}
return FText::GetEmpty();
}
const FText& UMetasound::GetOutputToolTip(FString OutputName) const
{
for (const FMetasoundOutputDescription& Desc : RootMetasoundDocument.RootClass.Outputs)
{
if (Desc.Name == OutputName)
{
return Desc.ToolTip;
}
}
return FText::GetEmpty();
}
void UMetasound::SetGraph(UEdGraph* InGraph)
{
Graph = InGraph;
@@ -76,9 +51,17 @@ void UMetasound::SetMetadata(FMetasoundClassMetadata& InMetadata)
MarkPackageDirty();
}
// delete this asset's current metasound document,
// and replace it with InClassDescription.
void UMetasound::SetMetasoundDocument(const FMetasoundDocument& InDocument)
void UMetasound::PostLoad()
{
RootMetasoundDocument = InDocument;
ConformDocumentToArchetype();
}
FMetasoundArchetype UMetasound::GetArchetype() const
{
FMetasoundArchetype Archetype;
static FName MetasoundArchetypeName = TEXT("Generic Metasound");
Archetype.ArchetypeName = MetasoundArchetypeName;
return Archetype;
}

View File

@@ -2,6 +2,7 @@
#include "MetasoundEngineModule.h"
#include "Metasound.h"
#include "MetasoundSource.h"
#include "Modules/ModuleManager.h"
@@ -11,6 +12,9 @@ class FMetasoundEngineModule : public IMetasoundEngineModule
{
virtual void StartupModule() override
{
Metasound::Frontend::RegisterArchetype<UMetasoundSource>();
Metasound::Frontend::RegisterArchetype<UMetasound>();
UE_LOG(LogMetasoundEngine, Log, TEXT("Metasound Engine Initialized"));
}
};

View File

@@ -0,0 +1,147 @@
// Copyright Epic Games, Inc. All Rights Reserved.
#include "MetasoundSource.h"
#include "CoreMinimal.h"
#include "Internationalization/Text.h"
#include "AssetRegistryModule.h"
#include "MetasoundAssetBase.h"
#include "MetasoundGenerator.h"
#include "MetasoundAudioFormats.h"
#include "MetasoundPrimitives.h"
#include "MetasoundDataReferenceTypes.h"
#include "MetasoundArchetypeRegistration.h"
#if WITH_EDITORONLY_DATA
#include "EdGraph/EdGraph.h"
#endif // WITH_EDITORONLY_DATA
#define LOCTEXT_NAMESPACE "MetasoundSource"
static FName MetasoundSourceArchetypeName = FName(TEXT("Metasound Source"));
UMetasoundSource::UMetasoundSource(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
, FMetasoundAssetBase(RootMetasoundDocument)
{
// TODO:
NumChannels = 1;
Duration = INDEFINITELY_LOOPING_DURATION;
bLooping = true;
// todo: ensure that we have a method so that the audio engine can be authoritative over the sample rate the UMetasoundSource runs at.
SampleRate = 48000.0f;
}
void UMetasoundSource::SetMetadata(FMetasoundClassMetadata& InMetadata)
{
RootMetasoundDocument.RootClass.Metadata = InMetadata;
}
bool UMetasoundSource::IsPlayable() const
{
// todo: cache off whether this metasound is buildable to an operator.
return true;
}
bool UMetasoundSource::SupportsSubtitles() const
{
return Super::SupportsSubtitles();
}
float UMetasoundSource::GetDuration()
{
// eh? this is kind of a weird field anyways.
return Super::GetDuration();
}
ISoundGeneratorPtr UMetasoundSource::CreateSoundGenerator(const FSoundGeneratorInitParams& InParams)
{
NumChannels = 1;
Duration = INDEFINITELY_LOOPING_DURATION;
bLooping = true;
SampleRate = InParams.SampleRate;
Metasound::FOperatorSettings InSettings(InParams.SampleRate, InParams.NumFramesPerCallback);
TArray<Metasound::IOperatorBuilder::FBuildErrorPtr> BuildErrors;
Metasound::Frontend::FGraphHandle RootGraph = GetRootGraphHandle();
ensureAlways(RootGraph.IsValid());
TUniquePtr<Metasound::IOperator> Operator = RootGraph.BuildOperator(InSettings, BuildErrors);
if (ensureAlways(Operator.IsValid()))
{
Metasound::FDataReferenceCollection Outputs = Operator->GetOutputs();
Metasound::FMetasoundGeneratorInitParams InitParams =
{
MoveTemp(Operator),
Outputs.GetDataReadReferenceOrConstruct<Metasound::FAudioBuffer>(GetAudioOutputName(), InParams.NumFramesPerCallback),
Outputs.GetDataReadReferenceOrConstruct<Metasound::FBop>(GetIsFinishedOutputName(), false)
};
return ISoundGeneratorPtr(new Metasound::FMetasoundGenerator(MoveTemp(InitParams)));
}
else
{
return ISoundGeneratorPtr(nullptr);
}
}
void UMetasoundSource::PostLoad()
{
Super::PostLoad();
ConformDocumentToArchetype();
}
const FString& UMetasoundSource::GetOnPlayInputName()
{
static FString BopInputName = FString(TEXT("On Play"));
return BopInputName;
}
const FString& UMetasoundSource::GetAudioOutputName()
{
static FString AudioOutputName = FString(TEXT("Generated Audio"));
return AudioOutputName;
}
const FString& UMetasoundSource::GetIsFinishedOutputName()
{
static FString OnFinishedOutputName = FString(TEXT("On Finished"));
return OnFinishedOutputName;
}
FMetasoundArchetype UMetasoundSource::GetArchetype() const
{
FMetasoundArchetype Archetype;
Archetype.ArchetypeName = MetasoundSourceArchetypeName;
FMetasoundInputDescription OnPlayBop;
OnPlayBop.Name = GetOnPlayInputName();
OnPlayBop.TypeName = Metasound::Frontend::GetDataTypeName<Metasound::FBop>();
OnPlayBop.ToolTip = LOCTEXT("OnPlayBopToolTip", "This input is bopped when this source is first played.");
Archetype.RequiredInputs.Add(OnPlayBop);
FMetasoundOutputDescription GeneratedAudio;
GeneratedAudio.Name = GetAudioOutputName();
GeneratedAudio.TypeName = Metasound::Frontend::GetDataTypeName<Metasound::FAudioBuffer>();
GeneratedAudio.ToolTip = LOCTEXT("GeneratedAudioToolTip", "This should be the resulting output audio from this source.");
Archetype.RequiredOutputs.Add(GeneratedAudio);
FMetasoundOutputDescription OnFinished;
OnFinished.Name = GetIsFinishedOutputName();
OnFinished.TypeName = Metasound::Frontend::GetDataTypeName<Metasound::FBop>();
OnFinished.ToolTip = LOCTEXT("OnFinishedToolTip", "This output can be bopped to stop the sound.");
Archetype.RequiredOutputs.Add(OnFinished);
return Archetype;
}
#undef LOCTEXT_NAMESPACE

View File

@@ -44,18 +44,15 @@ public:
// Returns the graph associated with this Metasound. Graph is required to be referenced on
// Metasound UObject for editor serialization purposes.
// @return Editor graph associated with UMetasound.
UEdGraph* GetGraph();
const UEdGraph* GetGraph() const;
UEdGraph& GetGraphChecked();
const UEdGraph& GetGraphChecked() const;
virtual UEdGraph* GetGraph() override;
virtual const UEdGraph* GetGraph() const override;
virtual UEdGraph& GetGraphChecked() override;
virtual const UEdGraph& GetGraphChecked() const override;
// Sets the graph associated with this Metasound. Graph is required to be referenced on
// Metasound UObject for editor serialization purposes.
// @param Editor graph associated with UMetasound.
void SetGraph(UEdGraph* InGraph);
const FText& GetInputToolTip(FString InputName) const;
const FText& GetOutputToolTip(FString OutputName) const;
virtual void SetGraph(UEdGraph* InGraph) override;
#endif // WITH_EDITORONLY_DATA
@@ -80,6 +77,9 @@ public:
// @param InMetadata Metadata containing corrections to the class metadata.
void SetMetadata(FMetasoundClassMetadata& InMetadata) override;
// Deletes Metasound's current metasound document, and replaces it with InClassDescription.
void SetMetasoundDocument(const FMetasoundDocument& InDocument);
// Get the most up to date archetype for metasound.
virtual FMetasoundArchetype GetArchetype() const override;
void PostLoad() override;
};

Some files were not shown because too many files have changed in this diff Show More