New UHT specifiers: FieldNotify, Getter, Setter, etc.

So I’m working on some UI in UE5.2, and as usual when I’m not sure how best to go about something, I start thumbing through the engine source code for examples/ideas. In UMG’s UImage, I notice this:

UE_DEPRECATED(5.2, "Direct access to Brush is deprecated. Please use the getter or setter.")
/** Image to draw */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Getter, Setter, BlueprintSetter = "SetBrush", FieldNotify, Category=Appearance)
FSlateBrush Brush;

Huh. I don’t remember seeing FieldNotify, Getter or Setter anywhere before. Coupled with the 5.2 deprecation notice, I’m guessing these must be new. I check out the property specifiers documentation and… FML.

This page was written for a previous version of Unreal Engine and has not been updated for the current Unreal Engine 5.2 release.

So I check Image.cpp to see what GetBrush and SetBrush look like, and I see this in the SetBrush definition:

BroadcastFieldValueChanged(FFieldNotificationClassDescriptor::Brush);

Rider highlights “Brush” there as an undefined symbol, and when I jump to the declaration of FFieldNotificationClassDescriptor it takes me to this macro soup at the top of UWidget (UImage’s parent class):

UE_FIELD_NOTIFICATION_DECLARE_CLASS_DESCRIPTOR_BASE_BEGIN(UMG_API)
	UE_FIELD_NOTIFICATION_DECLARE_FIELD(ToolTipText)
	UE_FIELD_NOTIFICATION_DECLARE_FIELD(Visibility)
	UE_FIELD_NOTIFICATION_DECLARE_FIELD(bIsEnabled)
	UE_FIELD_NOTIFICATION_DECLARE_ENUM_FIELD_BEGIN(ToolTipText)
	UE_FIELD_NOTIFICATION_DECLARE_ENUM_FIELD(Visibility)
	UE_FIELD_NOTIFICATION_DECLARE_ENUM_FIELD(bIsEnabled)
	UE_FIELD_NOTIFICATION_DECLARE_ENUM_FIELD_END()
UE_FIELD_NOTIFICATION_DECLARE_CLASS_DESCRIPTOR_BASE_END();

Finally I dig up the Image.generated.h to try and figure out what UHT is spitting out for the specifiers:

#define FID_Engine_Source_Runtime_UMG_Public_Components_Image_h_32_FIELDNOTIFY \
	UE_FIELD_NOTIFICATION_DECLARE_CLASS_DESCRIPTOR_BEGIN(UMG_API ) \
	UE_FIELD_NOTIFICATION_DECLARE_FIELD(Brush) \
	UE_FIELD_NOTIFICATION_DECLARE_ENUM_FIELD_BEGIN(Brush) \
	UE_FIELD_NOTIFICATION_DECLARE_ENUM_FIELD_END() \
	UE_FIELD_NOTIFICATION_DECLARE_CLASS_DESCRIPTOR_END();

Clumsily inlining those macros by hand I manage to come up with:

struct UMG_API FFieldNotificationClassDescriptor : public Super::FFieldNotificationClassDescriptor
{
private:
	using SuperDescriptor = Super::FFieldNotificationClassDescriptor;
	static const ::UE::FieldNotification::FFieldId* AllFields[];
	friend ThisClass;
public:
	static const ::UE::FieldNotification::FFieldId Brush;
	enum EField {
		IndexOf_Brush = SuperDescriptor::Max_IndexOf_ + 0,
		Max_IndexOf_,
	};

	virtual void ForEachField(const UClass* Class, IFunctionRef<bool(::UE::FieldNotification::FFieldId FieldId)> Callback) const override
	{
		for (int32 Index = 0; Index < Max_IndexOf_-SuperDescriptor::Max_IndexOf_; ++Index)
		{
			if (!Callback(*AllFields[Index]))
			{
				return;
			}
		}
		SuperDescriptor::ForEachField(Class, Callback);
	}
};

virtual const ::UE::FieldNotification::IClassDescriptor& GetFieldNotificationDescriptor() const
{
	static FFieldNotificationClassDescriptor Instance;
	return Instance;
}

Which explains why Rider could find a definition for FFieldNotificationClassDescriptor but not FFieldNotificationClassDescriptor::Brush, but doesn’t really tell me much else.

Has this new FieldNotify system been talked about anywhere publicly that could possibly give me some insight into what its purpose is, what work it’s related to, or how/when/why I might want to use it?

Interesting, didn’t know about FieldNotify either. Seems to be used mostly with UMG together with the new ModelViewViewModel plugin. ForEachField seems to be called from UE::MVVM::Private::GetAvailableBindings in MVVMSubystem.cpp.

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.