// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "CoreMinimal.h" #include // NOTE: Metasound Enum types are defined outside of Engine so can't use the UENUM type reflection here. // Basic reflection is provides using template specialization and Macros defined below. // Example usage: // // 1. Declare an Enum class. // enum class EMyOtherTestEnum : int32 // { // Alpha = 500, // Beta = -666, // Gamma = 333 // }; // 2. Declare its wrapper types using the DECLARE_METASOUND_ENUM macro. // DECLARE_METASOUND_ENUM(EMyOtherTestEnum, EMyOtherTestEnum::Gamma, METASOUNDSTANDARDNODES_API, FMyOtherTestEnumTypeInfo, FMyOtherTestEnumReadRef, FMyOtherTestEnumWriteRef) // 3. Define it using the BEGIN/ENTRY/END macros // DEFINE_METASOUND_ENUM_BEGIN(EMyOtherTestEnum) // DEFINE_METASOUND_ENUM_ENTRY(EMyOtherTestEnum::Alpha, LOCTEXT("AlphaDescription", "Alpha"), LOCTEXT("AlphaDescriptionTT", "Alpha tooltip")), // DEFINE_METASOUND_ENUM_ENTRY(EMyOtherTestEnum::Beta, LOCTEXT("BetaDescription", "Beta"), LOCTEXT("BetaDescriptioTT", "Beta tooltip")), // DEFINE_METASOUND_ENUM_ENTRY(EMyOtherTestEnum::Gamma, LOCTEXT("GammaDescription", "Gamma", LOCTEXT("GammaDescriptionTT", "Gamma tooltip")) // DEFINE_METASOUND_ENUM_END() namespace Metasound { // Struct to hold each of the entries of the Enum. template struct TEnumEntry { T Value; FName Name; FText DisplayName; // TODO: Remove this from runtime. FText Tooltip; // TODO: Remove this from runtime. // Allow implicit conversion to int32 entry operator TEnumEntry() const { return TEnumEntry{ static_cast(Value), Name, DisplayName, Tooltip }; } }; /** CRTP base class for Enum String Helper type. * Provides common code for all specializations. */ template struct TEnumStringHelperBase { // Give a enum value e.g. 'EMyEnum::One', convert that to a Name (if its valid) static TOptional ToName(EnumType InValue) { for (const TEnumEntry& i : Derived::GetAllEntries()) { if (i.Value == InValue) { return i.Name; } } return {}; } // Give a Name "EMyEnum::One", convert that to a Enum Value static TOptional FromName(const FName InName) { for (const TEnumEntry& i : Derived::GetAllEntries()) { if (i.Name == InName) { return i.Value; } } return {}; } // Return all possible names. static TArray GetAllNames() { TArray Names; for (const TEnumEntry& i : Derived::GetAllEntries()) { Names.Emplace(i.Name); } return Names; } }; /** Metasound Enum String Helper */ template struct METASOUNDFRONTEND_API TEnumStringHelper : TEnumStringHelperBase, T> { static_assert(TIsEnum::Value, "Please define a specialization of this class. The DECLARE_METASOUND_ENUM macros will do this for you"); }; /** Metasound Enum Wrapper */ template class TEnum final { public: using InnerType = EnumType; static_assert(TIsEnum::Value, "Expecting an Enum type"); // Allow Non-enum class Enum or Enum class that's are derived from int32 static_assert(TIsSame::type, int32>::Value || !TIsEnumClass::Value, "We serialize to int32, so limit to that for now"); // Default. explicit TEnum(EnumType InValue = DefaultValue) { // Try and convert to validate this is a valid value. TOptional Converted = ToName(InValue); if (ensure(Converted)) { EnumValue = InValue; } } // From Int32 (this is the common path from a Literal). explicit TEnum(int32 InIntValue) : TEnum(static_cast(InIntValue)) { } // From Name explicit TEnum(FName InValueName) { // Try and convert from Name to Value and ensure that we succeed TOptional Converted = NameToEnum(InValueName); if (ensure(Converted)) { EnumValue = *Converted; } } // Slow, construct from FString to FName. explicit TEnum(const FString& InString) : TEnum(FName(*InString)) { } EnumType Get() const { return EnumValue; } int32 ToInt() const { return static_cast(EnumValue); } // Convert to its FName (if possible). TOptional ToName() const { return ToName(EnumValue); } // Conversion operator to automatically convert this to its underlying enum type. operator EnumType() const { return EnumValue; } // Convert from EnumValue to FName (if possible). static TOptional ToName(EnumType InValue) { return TEnumStringHelper::ToName(InValue); } // Convert from Name to EnumValue (if possible). static TOptional NameToEnum(FName InValue) { return TEnumStringHelper::FromName(InValue); } // Return all possible Names static TArray GetAllNames() { return TEnumStringHelper::GetAllNames(); } private: // Keep the type in its fully typed form for debugging. EnumType EnumValue = DefaultValue; }; template struct TEnumTraits { static constexpr bool bIsEnum = false; using InnerType = int32; static constexpr int32 DefaultValue = 0; }; template struct TEnumTraits> { static constexpr bool bIsEnum = true; using InnerType = T; static constexpr T DefaultValue = D; }; }