EM_Task/CoreUObject/Public/UObject/PropertyAccessUtil.h

295 lines
16 KiB
C
Raw Normal View History

2026-02-13 16:18:33 +08:00
// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "UObject/UnrealType.h"
#include "Templates/UniquePtr.h"
#include "Misc/EnumClassFlags.h"
class UObject;
class UStruct;
class FProperty;
/**
* Result flags from property access.
*/
enum class EPropertyAccessResultFlags : uint8
{
/** The property was accessed successfully */
Success = 0,
/** The property could not be accessed due to a permission error (the permission flags can give more detail of the error) */
PermissionDenied = 1 << 0,
/** The property could not be read or written due to a failure converting from the source or to the destination */
ConversionFailed = 1 << 1,
/** Permission flag added when the property cannot be accessed due to being protected (is not marked for editor or Blueprint access) */
AccessProtected = 1 << 4,
/** Permission flag added when attempting to edit a property on a template that cannot be edited on templates */
CannotEditTemplate = 1 << 5,
/** Permission flag added when attempting to edit a property on an instance that cannot be edited on instances */
CannotEditInstance = 1 << 6,
/** Permission flag added when attempting to edit a property that is read-only (based on the given read-only flags) */
ReadOnly = 1 << 7,
};
ENUM_CLASS_FLAGS(EPropertyAccessResultFlags);
/**
* Enum controlling when to emit property change notifications when setting a property value.
* @note Mirrored in NoExportTypes.h for UHT.
*/
enum class EPropertyAccessChangeNotifyMode : uint8
{
/** Notify only when a value change has actually occurred */
Default,
/** Never notify that a value change has occurred */
Never,
/** Always notify that a value change has occurred, even if the value is unchanged */
Always,
};
/**
* Information needed to emit property change notifications when setting a property value.
*/
struct FPropertyAccessChangeNotify
{
/** The kind of change that occurred */
EPropertyChangeType::Type ChangeType = EPropertyChangeType::Unspecified;
/** The object that is being changed */
UObject* ChangedObject = nullptr;
/** The chain of properties that are being changed */
FEditPropertyChain ChangedPropertyChain;
/** When to emit property change notifications */
EPropertyAccessChangeNotifyMode NotifyMode = EPropertyAccessChangeNotifyMode::Default;
};
/**
* Callback used to get the value of a property.
*/
using FPropertyAccessGetFunc = TFunctionRef<bool()>;
/**
* Callback used to set the value of a property.
*/
using FPropertyAccessSetFunc = TFunctionRef<bool(const FPropertyAccessChangeNotify*)>;
/**
* Callback used to build the information needed to emit property change notifications when setting a property value.
*/
using FPropertyAccessBuildChangeNotifyFunc = TFunctionRef<TUniquePtr<FPropertyAccessChangeNotify>()>;
namespace PropertyAccessUtil
{
/** Flags that make a property read-only when settings its value at runtime */
static const uint64 RuntimeReadOnlyFlags = CPF_EditConst | CPF_BlueprintReadOnly;
/** Flags that make a property read-only when settings its value in the editor */
static const uint64 EditorReadOnlyFlags = CPF_EditConst;
/**
* High-level function for getting the value of a property from an object.
* @note This function calls CanGetPropertyValue internally.
*
* @param InObjectProp Property to get the value of.
* @param InObject Object containing the property.
* @param InDestProp Property of the value to set (must be compatible with the source property).
* @param InDestValue Instance to fill with the property value (must be a valid and constructed block of memory that is compatible with the property).
* @param InArrayIndex For fixed-size array properties denotes which index of the array to get, or INDEX_NONE to get the entire property.
*
* @return Flags describing whether the get was successful.
*/
COREUOBJECT_API EPropertyAccessResultFlags GetPropertyValue_Object(const FProperty* InObjectProp, const UObject* InObject, const FProperty* InDestProp, void* InDestValue, const int32 InArrayIndex);
/**
* High-level function for getting the value of a property from a property container (object or struct).
* @note This function calls CanGetPropertyValue internally.
*
* @param InContainerProp Property to get the value of.
* @param InContainerData The instance data containing the property.
* @param InDestProp Property of the value to set (must be compatible with the source property).
* @param InDestValue Instance to fill with the property value (must be a valid and constructed block of memory that is compatible with the property).
* @param InArrayIndex For fixed-size array properties denotes which index of the array to get, or INDEX_NONE to get the entire property.
*
* @return Flags describing whether the get was successful.
*/
COREUOBJECT_API EPropertyAccessResultFlags GetPropertyValue_InContainer(const FProperty* InContainerProp, const void* InContainerData, const FProperty* InDestProp, void* InDestValue, const int32 InArrayIndex);
/**
* High-level function for getting the single-element value of a property from memory.
* @note This function calls CanGetPropertyValue internally.
*
* @param InSrcProp Property to get the value of.
* @param InSrcValue The property value to copy.
* @param InDestProp Property of the value to set (must be compatible with the source property).
* @param InDestValue Instance to fill with the property value (must be a valid and constructed block of memory that is compatible with the property).
*
* @return Flags describing whether the get was successful.
*/
COREUOBJECT_API EPropertyAccessResultFlags GetPropertyValue_DirectSingle(const FProperty* InSrcProp, const void* InSrcValue, const FProperty* InDestProp, void* InDestValue);
/**
* High-level function for getting the multi-element value of a property from memory.
* @note This function calls CanGetPropertyValue internally.
*
* @param InSrcProp Property to get the value of.
* @param InSrcValue The property value to copy.
* @param InDestProp Property of the value to set (must be compatible with the source property).
* @param InDestValue Instance to fill with the property value (must be a valid and constructed block of memory that is compatible with the property).
*
* @return Flags describing whether the get was successful.
*/
COREUOBJECT_API EPropertyAccessResultFlags GetPropertyValue_DirectComplete(const FProperty* InSrcProp, const void* InSrcValue, const FProperty* InDestProp, void* InDestValue);
/**
* Low-level function for getting the value of a property.
* @note This function does *not* CanGetPropertyValue internally, you must call it yourself to validate the get.
*
* @param InGetFunc Logic for getting the value of the property.
*
* @return Flags describing whether the get was successful.
*/
COREUOBJECT_API EPropertyAccessResultFlags GetPropertyValue(const FPropertyAccessGetFunc& InGetFunc);
/**
* Low-level function for checking whether it's valid to get the value of a property.
*
* @param InProp Property to query.
*
* @return Flags describing whether it's valid to get the value of the property.
*/
COREUOBJECT_API EPropertyAccessResultFlags CanGetPropertyValue(const FProperty* InProp);
/**
* High-level function for setting the value of a property on an object.
* @note This function calls CanSetPropertyValue internally, and will emit property change notifications for the object.
*
* @param InObjectProp Property to set the value of.
* @param InObject Object containing the property.
* @param InSrcProp Property of the value to set (must be compatible with the dest property).
* @param InSrcValue The value to set on the property.
* @param InArrayIndex For fixed-size array properties denotes which index of the array to set, or INDEX_NONE to set the entire property.
* @param InReadOnlyFlags Flags controlling which properties are considered read-only.
* @param InNotifyMode When to emit property change notifications.
*
* @return Flags describing whether the set was successful.
*/
COREUOBJECT_API EPropertyAccessResultFlags SetPropertyValue_Object(const FProperty* InObjectProp, UObject* InObject, const FProperty* InSrcProp, const void* InSrcValue, const int32 InArrayIndex, const uint64 InReadOnlyFlags, const EPropertyAccessChangeNotifyMode InNotifyMode);
/**
* High-level function for setting the value of a property on a property container (object or struct).
* @note This function calls CanSetPropertyValue internally.
*
* @param InContainerProp Property to set the value of.
* @param InContainerData The instance data containing the property.
* @param InSrcProp Property of the value to set (must be compatible with the dest property).
* @param InSrcValue The value to set on the property.
* @param InArrayIndex For fixed-size array properties denotes which index of the array to set, or INDEX_NONE to set the entire property.
* @param InReadOnlyFlags Flags controlling which properties are considered read-only.
* @param InOwnerIsTemplate True if the owner object is considered a template (see IsObjectTemplate).
* @param InBuildChangeNotifyFunc Logic for building the information needed to emit property change notifications when setting a property value (can return nullptr if no notifications are needed or possible).
*
* @return Flags describing whether the set was successful.
*/
COREUOBJECT_API EPropertyAccessResultFlags SetPropertyValue_InContainer(const FProperty* InContainerProp, void* InContainerData, const FProperty* InSrcProp, const void* InSrcValue, const int32 InArrayIndex, const uint64 InReadOnlyFlags, const bool InOwnerIsTemplate, const FPropertyAccessBuildChangeNotifyFunc& InBuildChangeNotifyFunc);
/**
* High-level function for setting the single-element value of a property in memory.
* @note This function calls CanSetPropertyValue internally.
*
* @param InSrcProp Property to set the value of.
* @param InSrcValue The value to set on the property.
* @param InDestProp Property to get the value from (must be compatible with the source property).
* @param InDestValue Instance to fill with the property value (must be a valid and constructed block of memory that is compatible with the property).
* @param InReadOnlyFlags Flags controlling which properties are considered read-only.
* @param InOwnerIsTemplate True if the owner object is considered a template (see IsObjectTemplate).
* @param InBuildChangeNotifyFunc Logic for building the information needed to emit property change notifications when setting a property value (can return nullptr if no notifications are needed or possible).
*
* @return Flags describing whether the set was successful.
*/
COREUOBJECT_API EPropertyAccessResultFlags SetPropertyValue_DirectSingle(const FProperty* InSrcProp, const void* InSrcValue, const FProperty* InDestProp, void* InDestValue, const uint64 InReadOnlyFlags, const bool InOwnerIsTemplate, const FPropertyAccessBuildChangeNotifyFunc& InBuildChangeNotifyFunc);
/**
* High-level function for setting the multi-element value of a property in memory.
* @note This function calls CanSetPropertyValue internally.
*
* @param InSrcProp Property to set the value of.
* @param InSrcValue The value to set on the property.
* @param InDestProp Property to get the value from (must be compatible with the source property).
* @param InDestValue Instance to fill with the property value (must be a valid and constructed block of memory that is compatible with the property).
* @param InReadOnlyFlags Flags controlling which properties are considered read-only.
* @param InOwnerIsTemplate True if the owner object is considered a template (see IsObjectTemplate).
* @param InBuildChangeNotifyFunc Logic for building the information needed to emit property change notifications when setting a property value (can return nullptr if no notifications are needed or possible).
*
* @return Flags describing whether the set was successful.
*/
COREUOBJECT_API EPropertyAccessResultFlags SetPropertyValue_DirectComplete(const FProperty* InSrcProp, const void* InSrcValue, const FProperty* InDestProp, void* InDestValue, const uint64 InReadOnlyFlags, const bool InOwnerIsTemplate, const FPropertyAccessBuildChangeNotifyFunc& InBuildChangeNotifyFunc);
/**
* Low-level function for setting the value of a property.
* @note This function does *not* CanSetPropertyValue internally, you must call it yourself to validate the set.
*
* @param InSetFunc Logic for setting the value of the property (should call EmitPreChangeNotify and EmitPostChangeNotify using the given FPropertyAccessChangeNotify instance).
* @param InBuildChangeNotifyFunc Logic for building the information needed to emit property change notifications when setting a property value (can return nullptr if no notifications are needed or possible).
*
* @return Flags describing whether the get was successful.
*/
COREUOBJECT_API EPropertyAccessResultFlags SetPropertyValue(const FPropertyAccessSetFunc& InSetFunc, const FPropertyAccessBuildChangeNotifyFunc& InBuildChangeNotifyFunc);
/**
* Low-level function for checking whether it's valid to set the value of a property.
*
* @param InProp Property to query.
*
* @return Flags describing whether it's valid to set the value of the property.
*/
COREUOBJECT_API EPropertyAccessResultFlags CanSetPropertyValue(const FProperty* InProp, const uint64 InReadOnlyFlags, const bool InOwnerIsTemplate);
/**
* Low-level function called before modifying an object to notify that its value is about to change.
*
* @param InChangeNotify Information needed to emit property change notifications, or nullptr if no notifications are needed or possible.
* @param InIdenticalValue True if the value being set was identical to the current value, false otherwise.
*/
COREUOBJECT_API void EmitPreChangeNotify(const FPropertyAccessChangeNotify* InChangeNotify, const bool InIdenticalValue);
/**
* Low-level function called after modifying an object to notify that its value has changed.
*
* @param InChangeNotify Information needed to emit property change notifications, or nullptr if no notifications are needed or possible.
* @param InIdenticalValue True if the value being set was identical to the current value, false otherwise.
*/
COREUOBJECT_API void EmitPostChangeNotify(const FPropertyAccessChangeNotify* InChangeNotify, const bool InIdenticalValue);
/**
* Low-level function to build the basic information needed to emit property change notifications.
* @note This function can only build the notification for a property directly on the object instance, as more complex cases require external management as the reflection data doesn't let you backtrack over different types.
*
* @param InProp Property being modified.
* @param InObject Object being modified.
* @param InNotifyMode When to emit property change notifications.
*
* @return The information needed to emit property change notifications.
*/
COREUOBJECT_API TUniquePtr<FPropertyAccessChangeNotify> BuildBasicChangeNotify(const FProperty* InProp, const UObject* InObject, const EPropertyAccessChangeNotifyMode InNotifyMode);
/**
* Low-level function for checking whether the given object instance is considered a template for property access.
*
* @param InObject Object to query.
*
* @return True if the object instance is considered a template.
*/
COREUOBJECT_API bool IsObjectTemplate(const UObject* InObject);
/**
* Low-level function to find a property by its name, following redirectors if it cannot be found.
*
* @param InPropName The name of the property to find.
* @param InStruct The struct that should contain the property.
*
* @return The found property, or null if the property cannot be found.
*/
COREUOBJECT_API FProperty* FindPropertyByName(const FName InPropName, const UStruct* InStruct);
} // namespace PropertyAccessUtil