Skip to content

Instantly share code, notes, and snippets.

@DoubleDeez
Created September 27, 2022 20:01
Show Gist options
  • Save DoubleDeez/cc0ed2dfe67f5fb971908053acbc9596 to your computer and use it in GitHub Desktop.
Save DoubleDeez/cc0ed2dfe67f5fb971908053acbc9596 to your computer and use it in GitHub Desktop.
Example FieldNotify Classes
#include "ExampleFieldNotifyObject.h"
void UExampleFieldNotifyObject::SetMyValue(int32 InValue)
{
if (MyValue != InValue)
{
MyValue = InValue;
// FFieldNotificationClassDescriptor::MyValue is auto-generated by UHT
BroadcastFieldValueChanged(FFieldNotificationClassDescriptor::MyValue);
}
}
#pragma once
#include "CoreMinimal.h"
#include "FieldNotifyObjectBase.h"
#include "FieldNotification/FieldNotificationDeclaration.h"
#include "ExampleFieldNotifyObject.generated.h"
UCLASS()
class GYGAX_API UExampleFieldNotifyObject : public UFieldNotifyObjectBase
{
GENERATED_BODY()
public:
void SetMyValue(int32 InValue);
protected:
// All that's needed to use Field Notification now is the `FieldNotify` specifier
UPROPERTY(BlueprintReadOnly, Transient, FieldNotify)
int32 MyValue = 0;
};
#include "FieldNotifyObjectBase.h"
FDelegateHandle UFieldNotifyObjectBase::AddFieldValueChangedDelegate(UE::FieldNotification::FFieldId InFieldId, FFieldValueChangedDelegate InNewDelegate)
{
FDelegateHandle Result;
if (InFieldId.IsValid())
{
Result = FieldNotifyDelegates.Add(this, InFieldId, MoveTemp(InNewDelegate));
if (Result.IsValid())
{
EnabledFieldNotifications.PadToNum(InFieldId.GetIndex() + 1, false);
EnabledFieldNotifications[InFieldId.GetIndex()] = true;
}
}
return Result;
}
bool UFieldNotifyObjectBase::RemoveFieldValueChangedDelegate(UE::FieldNotification::FFieldId InFieldId, FDelegateHandle InHandle)
{
bool bResult = false;
if (InFieldId.IsValid() && InHandle.IsValid() && EnabledFieldNotifications.IsValidIndex(InFieldId.GetIndex()) && EnabledFieldNotifications[InFieldId.GetIndex()])
{
const UE::FieldNotification::FFieldMulticastDelegate::FRemoveFromResult RemoveResult = FieldNotifyDelegates.RemoveFrom(this, InFieldId, InHandle);
bResult = RemoveResult.bRemoved;
EnabledFieldNotifications[InFieldId.GetIndex()] = RemoveResult.bHasOtherBoundDelegates;
}
return bResult;
}
int32 UFieldNotifyObjectBase::RemoveAllFieldValueChangedDelegates(const void* InUserObject)
{
int32 bResult = 0;
if (InUserObject)
{
const UE::FieldNotification::FFieldMulticastDelegate::FRemoveAllResult RemoveResult = FieldNotifyDelegates.RemoveAll(this, InUserObject);
bResult = RemoveResult.RemoveCount;
EnabledFieldNotifications = RemoveResult.HasFields;
}
return bResult;
}
int32 UFieldNotifyObjectBase::RemoveAllFieldValueChangedDelegates(UE::FieldNotification::FFieldId InFieldId, const void* InUserObject)
{
int32 bResult = 0;
if (InUserObject)
{
const UE::FieldNotification::FFieldMulticastDelegate::FRemoveAllResult RemoveResult = FieldNotifyDelegates.RemoveAll(this, InFieldId, InUserObject);
bResult = RemoveResult.RemoveCount;
EnabledFieldNotifications = RemoveResult.HasFields;
}
return bResult;
}
const UE::FieldNotification::IClassDescriptor& UFieldNotifyObjectBase::GetFieldNotificationDescriptor() const
{
static FFieldNotificationClassDescriptor Local;
return Local;
}
void UFieldNotifyObjectBase::BroadcastFieldValueChanged(UE::FieldNotification::FFieldId InFieldId)
{
if (InFieldId.IsValid() && EnabledFieldNotifications.IsValidIndex(InFieldId.GetIndex()) && EnabledFieldNotifications[InFieldId.GetIndex()])
{
FieldNotifyDelegates.Broadcast(this, InFieldId);
}
}
#pragma once
#include "CoreMinimal.h"
#include "FieldNotification/FieldMulticastDelegate.h"
#include "FieldNotification/IFieldValueChanged.h"
#include "UObject/Object.h"
#include "FieldNotifyObjectBase.generated.h"
UCLASS()
class MYGAME_API UFieldNotifyObjectBase : public UObject, public INotifyFieldValueChanged
{
GENERATED_BODY()
public:
struct MYGAME_API FFieldNotificationClassDescriptor : public ::UE::FieldNotification::IClassDescriptor
{
// OPTIONAL - Only necessary if you need to inject additional fields, for example UMVVMViewModelBase will add blueprint field notify properties
// virtual void ForEachField(const UClass* Class, TFunctionRef<bool(UE::FieldNotification::FFieldId FielId)> Callback) const override;
};
virtual FDelegateHandle AddFieldValueChangedDelegate(UE::FieldNotification::FFieldId InFieldId, FFieldValueChangedDelegate InNewDelegate) override;
virtual bool RemoveFieldValueChangedDelegate(UE::FieldNotification::FFieldId InFieldId, FDelegateHandle InHandle) override;
virtual int32 RemoveAllFieldValueChangedDelegates(const void* InUserObject) override;
virtual int32 RemoveAllFieldValueChangedDelegates(UE::FieldNotification::FFieldId InFieldId, const void* InUserObject) override;
virtual const UE::FieldNotification::IClassDescriptor& GetFieldNotificationDescriptor() const override;
protected:
void BroadcastFieldValueChanged(UE::FieldNotification::FFieldId InFieldId);
private:
UE::FieldNotification::FFieldMulticastDelegate FieldNotifyDelegates;
TBitArray<> EnabledFieldNotifications;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment