How do I get a Metasound Enum to show up as a dropdown in my custom node?

Hi there,

I wrote a custom Metasound Node that includes a custom enum as a parameter. I used the TriggerComparison and other classes as a reference.

The node loads fine and works as it is supposed to, but the enum doesn’t show up as a dropdown, but just as a brown pin.

Here’s a screenshot showing the Trigger Compare node from the standard library, where the enum shows up as a dropdown, and my custom node, where it doesn’t.

image

The int32 to enum conversion value shows up fine, and if I promote the input to graph input, I can choose the different values from a dropdown just fine - it just doesn’t show up in this node. Any pointers on how I can get the node to display the dropdown are greatly appreciated.

I’ve attached a minimal reproducible example of the code I’m using for the custom enum here:

#pragma once

#include "CoreMinimal.h"
#include "MetasoundParamHelper.h"
#include "MetasoundEnumRegistrationMacro.h"


#define LOCTEXT_NAMESPACE "FEnumTestModule"

namespace Metasound
{
	enum class EMyEnum
	{
		SomeEntry = 0,
		AnotherEntry,
	};

	DECLARE_METASOUND_ENUM(EMyEnum, EMyEnum::SomeEntry, ENUMTEST_API, FEnumMyEnum, FEnumMyEnumInfo, FEnumMyEnumReadRef, FEnumMyEnumWriteRef);

	DEFINE_METASOUND_ENUM_BEGIN(EMyEnum, FEnumMyEnum, "MyEnum")
		DEFINE_METASOUND_ENUM_ENTRY(EMyEnum::SomeEntry, "SomeEntryDescription", "SomeEntry", "SomeEntryDescriptionTT", "Some Entry"),
		DEFINE_METASOUND_ENUM_ENTRY(EMyEnum::AnotherEntry, "AnotherEntryDescription", "AnotherEntry", "AnotherEntryDescriptionTT", "Another Entry"),
	DEFINE_METASOUND_ENUM_END()

	namespace EnumTestNode
	{
		METASOUND_PARAM(MyEnumPin, "Enum Value", "Set the enum value")
	}

	class FMyEnumTestOperator : public TExecutableOperator<FMyEnumTestOperator>
	{
	public:
		FMyEnumTestOperator(const FOperatorSettings& InSettings, FEnumMyEnumReadRef InMyEnum)
			: MyEnumValue(InMyEnum) {}

		static const FNodeClassMetadata& GetNodeInfo()
		{
			auto InitNodeInfo = []() -> FNodeClassMetadata
				{
					FNodeClassMetadata Info;

					Info.ClassName = { TEXT("UE"), TEXT("Enum Test"), TEXT("Audio") };
					Info.MajorVersion = 1;
					Info.MinorVersion = 0;
					Info.DisplayName = LOCTEXT("EnumTest_DisplayName", "Enum Test");
					Info.DefaultInterface = GetVertexInterface();

					return Info;
				};

			static const FNodeClassMetadata Info = InitNodeInfo();

			return Info;
		}

		virtual void BindInputs(FInputVertexInterfaceData& InOutVertexData) override
		{
			using namespace EnumTestNode;

			InOutVertexData.BindReadVertex(METASOUND_GET_PARAM_NAME(MyEnumPin), MyEnumValue);
		}


		static const FVertexInterface& GetVertexInterface()
		{
			using namespace EnumTestNode;

			static const FVertexInterface Interface(
				FInputVertexInterface(
					TInputDataVertex<FEnumMyEnum>(METASOUND_GET_PARAM_NAME_AND_METADATA(MyEnumPin), (int32)(EMyEnum::SomeEntry))
				),
				FOutputVertexInterface()
			);

			return Interface;
		}


		static TUniquePtr<IOperator> CreateOperator(const FCreateOperatorParams& InParams, FBuildErrorArray& OutErrors)
		{
			using namespace EnumTestNode;

			const FDataReferenceCollection& InputCollection = InParams.InputDataReferences;
			const FInputVertexInterface& InputInterface = GetVertexInterface().GetInputInterface();


			FEnumMyEnumReadRef MyEnumRef = InputCollection.GetDataReadReferenceOrConstructWithVertexDefault<FEnumMyEnum>(InputInterface, METASOUND_GET_PARAM_NAME(MyEnumPin), InParams.OperatorSettings);

			return MakeUnique<FMyEnumTestOperator>(InParams.OperatorSettings, MyEnumRef);
		}

		void Execute() {}

	private:
		FEnumMyEnumReadRef MyEnumValue;
	};


	class FMyEnumTestNode : public FNodeFacade
	{
	public:
		FMyEnumTestNode(const FNodeInitData& InitData)
			: FNodeFacade(InitData.InstanceName, InitData.InstanceID, TFacadeOperatorClass<FMyEnumTestOperator>())
		{

		}
	};

	METASOUND_REGISTER_NODE(FMyEnumTestNode);
}

#undef LOCTEXT_NAMESPACE

Hi Walgesang, did you ever work this out? Just hit the exact same problem

The answer is load you module from your uplugin config file as “LoadingPhase”: “EarliestPossible”