This is a quickstart guide for making new types of MetaSound Nodes through C++ code.
https://dev.epicgames.com/community/learning/tutorials/ry7p/unreal-engine-creating-metasound-nodes-in-c-quickstart
I just get the error:
Cannot open include file: ‘MetasoundExecutableOperator.h’: No such file or directory
Found this template on the Facebook audio group, maybe it helps paint the full picture:
You probably need to add the relevant Metasound module to your project’s .build.cs
file. Something like:
PrivateDependencyModuleNames.AddRange(new string[]
{
"MetasoundEngine",
"MetasoundFrontend"
});
@lantz.anna Any possibility of updating this tutorial for Unreal 5.1? I’m walking through it block-by-block and the very first block fails to work as expected because some of the types have been moved into the Metasound::
namespace.
There may be more incompatibilities… I’ve not gone through the full tutorial yet…
Hi I cant seem to create a new meta sound node to work
im in 5.3.1 and i keep having troubles with namespaces
Creating library C:\Users\tgall\Documents\Unreal Projects\AudioMixPlug\Plugins\MyCustomMetaSoundPlugin\Binaries\Win64\UnrealEditor-MyCustomMetaSoundPlugin.patch_14.lib and object C:\Users\tgall\Documents\Unreal Projects\AudioMixPlug\Plugins\MyCustomMetaSoundPlugin\Binaries\Win64\UnrealEditor-MyCustomMetaSoundPlugin.patch_14.exp
Module.MyCustomMetaSoundPlugin.cpp.obj : error LNK2001: unresolved external symbol “class FName const Metasound::StandardNodes::Namespace” (?Namespace@StandardNodes@Metasound@@3VFName@@B)
Module.MyCustomMetaSoundPlugin.cpp.obj : error LNK2001: unresolved external symbol “class FName const Metasound::StandardNodes::AudioVariant” (?AudioVariant@StandardNodes@Metasound@@3VFName@@B)
C:\Users\tgall\Documents\Unreal Projects\AudioMixPlug\Plugins\MyCustomMetaSoundPlugin\Binaries\Win64\UnrealEditor-MyCustomMetaSoundPlugin.patch_14.exe : fatal error LNK1120: 2 unresolved
Everythgin seems to compile until I use the line METASOUND_REGISTER_NODE(FTutorialNode);
my build.cs file contains
PublicDependencyModuleNames.AddRange(
new string[]
{
"Core",
"MetasoundFrontend",
"MetasoundGraphCore",
// ... add other public dependencies that you statically link with here ...
}
);
PrivateDependencyModuleNames.AddRange(
new string[]
{
"CoreUObject",
"Engine",
"Slate",
"SlateCore",
"MetasoundEngine",
"MetasoundEditor",
"MetasoundFrontend",
"MetasoundGraphCore",
"AudioMixer",
"SignalProcessing",
// ... add private dependencies that you statically link with here ...
}
My Plugin file to hold the meta sounds
{
“FileVersion”: 3,
“Version”: 1,
“VersionName”: “1.0”,
“FriendlyName”: “MyCustomMetaSoundPlugin”,
“Description”: “”,
“Category”: “Other”,
“CreatedBy”: “”,
“CreatedByURL”: “”,
“DocsURL”: “”,
“MarketplaceURL”: “”,
“SupportURL”: “”,
“CanContainContent”: true,
“IsBetaVersion”: false,
“IsExperimentalVersion”: false,
“Installed”: false,
“Modules”: [
{
“Name”: “MyCustomMetaSoundPlugin”,
“Type”: “Runtime”,
“LoadingPhase”: “Default”
}
],
"Plugins": [
{
"Name": "Metasound",
"Enabled": true
}
]
}
cant seem to get my head around this atall…
am i missing somehting extremly obvious
my cpp
include “MetasoundExecutableOperator.h” // TExecutableOperator class
include “MetasoundPrimitives.h” // ReadRef and WriteRef descriptions for bool, int32, float, and string
include “MetasoundNodeRegistrationMacro.h” // METASOUND_LOCTEXT and METASOUND_REGISTER_NODE macros
include “MetasoundStandardNodesNames.h” // StandardNodes namespace
include “MetasoundFacade.h” // FNodeFacade class, eliminates the need for a fair amount of boilerplate code
include “MetasoundParamHelper.h” // METASOUND_PARAM and METASOUND_GET_PARAM family of macros
// Required for ensuring the node is supported by all languages in engine. Must be unique per MetaSound.
#define LOCTEXT_NAMESPACE “MetasoundStandardNodes_MetaSoundTutorialNode”
namespace Metasound
{
// Vertex Names - define your node’s inputs and outputs here
namespace TutorialNodeNames
{
METASOUND_PARAM(InputAValue, “A”, “Input value A.”);
METASOUND_PARAM(InputBValue, “B”, “Input value B.”);
METASOUND_PARAM(OutputValue, "Sum of A and B", "The sum of A and B.");
}
// Operator Class - defines the way your node is described, created and executed
class FTutorialOperator : public TExecutableOperator<FTutorialOperator>
{
public:
// Constructor
FTutorialOperator(
const FFloatReadRef& InAValue,
const FFloatReadRef& InBValue)
: InputA(InAValue)
, InputB(InBValue)
, TutorialNodeOutput(FFloatWriteRef::CreateNew(*InputA + *InputB))
{
}
// Helper function for constructing vertex interface
static const FVertexInterface& DeclareVertexInterface()
{
using namespace TutorialNodeNames;
static const FVertexInterface Interface(
FInputVertexInterface(
TInputDataVertexModel<float>(METASOUND_GET_PARAM_NAME_AND_METADATA(InputAValue)),
TInputDataVertexModel<float>(METASOUND_GET_PARAM_NAME_AND_METADATA(InputBValue))
),
FOutputVertexInterface(
TOutputDataVertexModel<float>(METASOUND_GET_PARAM_NAME_AND_METADATA(OutputValue))
)
);
return Interface;
}
// Retrieves necessary metadata about your node
static const FNodeClassMetadata& GetNodeInfo()
{
auto CreateNodeClassMetadata = []() -> FNodeClassMetadata
{
FVertexInterface NodeInterface = DeclareVertexInterface();
FNodeClassMetadata Metadata
{
FNodeClassName { StandardNodes::Namespace, "Tutorial Node", StandardNodes::AudioVariant },
1, // Major Version
0, // Minor Version
METASOUND_LOCTEXT("TutorialNodeDisplayName", "Tutorial Node"),
METASOUND_LOCTEXT("TutorialNodeDesc", "A simple node to demonstrate how to create new MetaSound nodes in C++. Adds two floats together"),
PluginAuthor,
PluginNodeMissingPrompt,
NodeInterface,
{ }, // Category Hierarchy
{ }, // Keywords for searching
FNodeDisplayStyle{}
};
return Metadata;
};
static const FNodeClassMetadata Metadata = CreateNodeClassMetadata();
return Metadata;
}
// Allows MetaSound graph to interact with your node's inputs
virtual FDataReferenceCollection GetInputs() const override
{
using namespace TutorialNodeNames;
FDataReferenceCollection InputDataReferences;
InputDataReferences.AddDataReadReference(METASOUND_GET_PARAM_NAME(InputAValue), InputA);
InputDataReferences.AddDataReadReference(METASOUND_GET_PARAM_NAME(InputBValue), InputB);
return InputDataReferences;
}
// Allows MetaSound graph to interact with your node's outputs
virtual FDataReferenceCollection GetOutputs() const override
{
using namespace TutorialNodeNames;
FDataReferenceCollection OutputDataReferences;
OutputDataReferences.AddDataReadReference(METASOUND_GET_PARAM_NAME(OutputValue), TutorialNodeOutput);
return OutputDataReferences;
}
// Used to instantiate a new runtime instance of your node
static TUniquePtr<IOperator> CreateOperator(const FCreateOperatorParams& InParams, FBuildErrorArray& OutErrors)
{
using namespace TutorialNodeNames;
const Metasound::FDataReferenceCollection& InputCollection = InParams.InputDataReferences;
const Metasound::FInputVertexInterface& InputInterface = DeclareVertexInterface().GetInputInterface();
TDataReadReference<float> InputA = InputCollection.GetDataReadReferenceOrConstructWithVertexDefault<float>(InputInterface, METASOUND_GET_PARAM_NAME(InputAValue), InParams.OperatorSettings);
TDataReadReference<float> InputB = InputCollection.GetDataReadReferenceOrConstructWithVertexDefault<float>(InputInterface, METASOUND_GET_PARAM_NAME(InputBValue), InParams.OperatorSettings);
return MakeUnique<FTutorialOperator>(InputA, InputB);
}
// Primary node functionality
void Execute()
{
*TutorialNodeOutput = *InputA + *InputB;
}
private:
// Inputs
FFloatReadRef InputA;
FFloatReadRef InputB;
// Outputs
FFloatWriteRef TutorialNodeOutput;
};
// Node Class - Inheriting from FNodeFacade is recommended for nodes that have a static FVertexInterface
class FTutorialNode : public FNodeFacade
{
public:
FTutorialNode(const FNodeInitData& InitData)
: FNodeFacade(InitData.InstanceName, InitData.InstanceID, TFacadeOperatorClass<FTutorialOperator>())
{
}
};
// Register node
METASOUND_REGISTER_NODE(FTutorialNode);
}
#undef LOCTEXT_NAMESPACE
Ive also been through Aarons tutorial for the pitch shifter , Same Issues…
Hi my friend , I want create my custom node and use custom data type instead float , but this type can`t reflect correspond widget . Should I make-up anywhere?
Curve is my variable of custom type like WaveTableBank.
Hi, I am a game developer. Now I also want to create custom meta sound nodes to get curves, can you refer to how your code is composed? Thx!
Hi, if I follow the Building Off Of Existing Templates code as you wrote at the end and then put in the custom plugin, how should I activate it? I currently created a plugin and then put Building Off Of Existing Templates code into it, but it doesn’t take effect in the engine…