UENUM with BitFlags and UseEnumValuesAsMaskValuesInEditor = "true" doesn't set the EEnumFlags::Flags UEnum flag

To Whom It May Concern,

I discovered this by unintentionally reproducing [Content removed]

This affects an extraordinary number of UENUMs in the engine that specify both of these, but not Flags.

What is the expected usage? I’m having trouble finding good documentation anywhere for UENUM(Flags). I’ve been looking at https://dev.epicgames.com/documentation/unreal\-engine/unreal\-engine\-uproperties?application\_version\=5\.7 and https://unreal-garden.com/docs/uenum-umeta/. Is this equivalent to UENUM(meta=(BitFlags, UseEnumValuesAsMaskValuesInEditor = “true”))? Is the former not recommended usage?

I encountered this when I was trying to emit a json struct that contained enums with UENUM(meta=(BitFlags, UseEnumValuesAsMaskValuesInEditor = “true”)) and if the value didn’t match an existing one, I was getting the <enum name>_MAX value. I then altered JsonObjectConverter.cpp locally to GetValueOrBitfieldAsAuthoredNameString and it’s counterpart GetValueOrBitfieldFromString instead of GetAuthoredNameStringByValue and GetValueByName, respectively, but I was still getting the undesired output (using .

It wasn’t until I changed it to UENUM(Flags), along with my changes, that I got the desired output.

The questions that come to mind are:

* Can the enum export and import for JsonObjectConverter.cpp be changed to support bitfields?

* Could the meta with Bitflags and UseEnumValuesAsMaskValuesInEditor = true apply EEnumFlags::Flags?

* Could there be more documentation for the Flags property for UENUM?

It would be good to know if UENUM(Flags) is sufficient and instead of doing (as an example):

UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = “Tracking Settings”, meta=(Bitmask, BitmaskEnum = “EMovementTrackingFlags”))

uint8 movementTrackingFlags;

We could just use:

UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = “Tracking Settings”)

EMovementTrackingFlags movementTrackingFlags;

Thank you,

Brent

[Attachment Removed]

Steps to Reproduce
The example from https://dev.epicgames.com/documentation/unreal\-engine/unreal\-engine\-uproperties?application\_version\=5\.7 would reproduce this issue:

	UENUM(Meta = (Bitflags, UseEnumValuesAsMaskValuesInEditor = "true"))
	enum class EColorBits
	{
		ECB_Red = 0x01,
		ECB_Green = 0x02,
		ECB_Blue = 0x04
	};
	ENUM_CLASS_FLAGS(EColorBits);
  
  	USTRUCT()
    	struct FExportExample 
  	{
  		GENERATED_BODY()
  
  	  	UPROPERTY(EditAnywhere, Meta = (Bitmask, BitmaskEnum = "EColorBits"))
  		int32 ColorFlags;
  	};

  
  	FExportExample Example;
  	Example.ColorFlags = EColorBits::ECB_Green | EColorBits::ECB_Blue;

  	FString Result;
  	FJsonObjectConverter::UStructToJsonObjectString(*this, Result,
  		0 /* CheckFlags*/,
  		0 /* SkipFlags */,
  		1 /* Indent */
  		);

Emits EColorBits_MAX.

[Attachment Removed]

Hi Brent,

Apologies for the late response.

Essentially - the ‘Flags’ specifier is a native UHT specifier that was introduced on the engine side more recently, while the “Bitflags” et. al. metadata was our existing editing solution that was put in place originally to virtualize editing/visualization of enum-typed values as a bitmask in the editor while the engine still stored/serialized it as a numeric value for the runtime side.

As you’ve discovered, the editor side is not currently aware of the UHT specifier unfortunately, and there is a (backlogged) task for the work that would be needed to eventually deprecate the meta flags in favor of the more “native” UHT specifier solution. I do not have any good ETA on that for you.

As a workaround, for now, depending on which type of functionality you need, you may need to use one or both variations. I believe it’s ok to use both, albeit a bit confusing to see in the reflection markup admittedly. There are a few cases in the public engine code I believe; for example:

UENUM(Flags, meta=(Bitflags, UseEnumValuesAsMaskValuesInEditor = "true"))
enum class EMovieSceneServerClientMask : uint8
{
	None           = 0 UMETA(Hidden),
	Server         = 1 << 0,
	Client         = 1 << 1,
 
	All            = Server | Client UMETA(Hidden)
};
ENUM_CLASS_FLAGS(EMovieSceneServerClientMask)

Hope this helps! -phil.

[Attachment Removed]

I’ve been digging into this further to characterize the scenarios.

  • UEnum(Flags):
    • Has the UENumFlags::Flags
    • GetValueOrBitfieldAsAuthoredNameString & GetValueOrBitfieldFromString work correctly.
    • A property with this type declaration directly doesn’t allow setting multiple flags at once in the editor, however, if the property has a default value setting multiple flags, then it will show up in the editor correctly.
    • An int property with this specified as the BitmaskEnum behaves unexpectedly. A value of 6 is treated as a value of 3 (as if each bit was one off), and is serialized in json as a number.
  • UENUM(meta=(BitFlags)) behaves as described in https://dev.epicgames.com/documentation/unreal\-engine/unreal\-engine\-uproperties?application\_version\=5\.7
  • UENUM(meta=(BitFlags, UseEnumValuesAsMaskValuesInEditor = “true”))
    • Does not have UENumFlags::Flags set
    • GetValueOrBitfieldAsAuthoredNameString & GetValueOrBitfieldFromString emits an empty string or <enum name>_max (haven’t figured out the cases that trigger which one).
    • A property with this type declaration directly doesn’t allow setting multiple flags at once in the editor. If the property has a default value setting multiple flags, then it will show up in the editor with (INVALID).
    • An int property with this specified as the BitmaskEnum behaves as described in the docs. It is serialized in json as a number.
      [Attachment Removed]