CustomProperties
CustomProperties
#Overview
name: CustomProperties
The value of this variable can be defined or overridden in .ini config files. 1
.ini config file referencing this setting variable.
It is referenced in 20
C++ source files.
#Summary
#Usage in the C++ source code
The purpose of CustomProperties is to handle custom property data in various Unreal Engine 5 subsystems and plugins. It is used for different purposes across multiple modules, including:
-
Rider Source Code Access: It is used to parse custom properties from a JSON file for the Rider IDE integration.
-
PCG (Procedural Content Generation): It is used in the PCG plugin to manage dynamic input pins for PCG settings.
-
Editor: It is used in the UnrealEd module for custom property color handling and importing custom properties for objects.
-
Core UObject: It is used in the serialization process for declaring custom versions.
-
Iris Networking: It is used in the Iris networking system for handling custom replication fragments.
-
MovieScene: It is used extensively in the MovieScene module for managing custom property accessors and values in the entity system.
The value of this variable is typically set through configuration files, JSON parsing, or programmatically during runtime, depending on the specific use case.
CustomProperties often interacts with other variables and systems specific to its context. For example, in the PCG system, it interacts with dynamic input pins, while in the MovieScene system, it interacts with property accessors and entity allocations.
Developers must be aware that CustomProperties is used differently across various subsystems, and its implementation may vary. It’s crucial to understand the specific context and requirements of the subsystem you’re working with when using CustomProperties.
Best practices when using CustomProperties include:
- Ensure proper initialization and cleanup of custom properties.
- Validate custom properties before using them, especially when importing from external sources.
- Follow the specific guidelines and patterns established for each subsystem that uses CustomProperties.
- When extending systems that use CustomProperties, maintain consistency with the existing implementation to avoid conflicts.
- Document any custom property usage thoroughly to help other developers understand their purpose and behavior.
#Setting Variables
#References In INI files
Location: <Workspace>/Engine/Config/BaseEditorSettings.ini:48, section: [/Script/UnrealEd.PropertyColorSettings]
- INI Section:
/Script/UnrealEd.PropertyColorSettings
- Raw value:
(Name="AffectsNavmesh",Text="Affects NavMesh",PropertyChain="RootComponent.bCanEverAffectNavigation",PropertyValue="True",PropertyColor=(R=0,G=0,B=255))
- Is Array:
True
#References in C++ code
#Callsites
This variable is referenced in the following C++ source code:
#Loc: <Workspace>/Engine/Plugins/Developer/RiderSourceCodeAccess/Source/RiderSourceCodeAccess/Private/RiderPathLocator/Common/RiderPathLocator.cpp:140
Scope (from outer to inner):
file
function void FRiderPathLocator::ParseProductInfoJson
Source code excerpt:
}
const TArray< TSharedPtr<FJsonValue> >* CustomProperties;
if(!JsonObject->TryGetArrayField(TEXT("customProperties"), CustomProperties)) return;
for (const TSharedPtr<FJsonValue>& CustomProperty : *CustomProperties)
{
const TSharedPtr<FJsonObject> Item = CustomProperty->AsObject();
if(!Item.IsValid()) continue;
FString SupportUprojectStateKey;
const bool bIsValidKey = Item->TryGetStringField(TEXT("key"), SupportUprojectStateKey);
#Loc: <Workspace>/Engine/Plugins/PCG/Source/PCG/Private/PCGSettingsWithDynamicInputs.cpp:59
Scope (from outer to inner):
file
function void UPCGSettingsWithDynamicInputs::AddDynamicInputPin
Source code excerpt:
void UPCGSettingsWithDynamicInputs::AddDynamicInputPin(FPCGPinProperties&& CustomProperties)
{
if (CustomPropertiesAreValid(CustomProperties))
{
DynamicInputPinProperties.Emplace(std::forward<FPCGPinProperties>(CustomProperties));
OnSettingsChangedDelegate.Broadcast(this, EPCGChangeType::Node | EPCGChangeType::Settings);
}
}
#endif // WITH_EDITOR
TArray<FPCGPinProperties> UPCGSettingsWithDynamicInputs::StaticInputPinProperties() const
#Loc: <Workspace>/Engine/Plugins/PCG/Source/PCG/Public/PCGSettingsWithDynamicInputs.h:19
Scope (from outer to inner):
file
class class UPCGSettingsWithDynamicInputs: public UPCGSettings
function virtual bool CustomPropertiesAreValid
Source code excerpt:
#if WITH_EDITOR
/** Validate custom pin properties */
virtual bool CustomPropertiesAreValid(const FPCGPinProperties& CustomProperties) { return true; }
/** User driven event to add a dynamic source pin */
virtual void OnUserAddDynamicInputPin();
/** Overridden logic to add a default source pin */
virtual void AddDefaultDynamicInputPin() PURE_VIRTUAL(PCGDynamicSettings::AddDefaultSourcePin, );
/** Check if the pin to remove is dynamic */
#Loc: <Workspace>/Engine/Plugins/PCG/Source/PCG/Public/PCGSettingsWithDynamicInputs.h:39
Scope (from outer to inner):
file
class class UPCGSettingsWithDynamicInputs: public UPCGSettings
Source code excerpt:
#if WITH_EDITOR
/** Add a new dynamic source pin with the specified properties */
void AddDynamicInputPin(FPCGPinProperties&& CustomProperties);
#endif // WITH_EDITOR
/** The input pin properties that are statically defined by the client class */
virtual TArray<FPCGPinProperties> StaticInputPinProperties() const;
/** Dynamic pin properties that the user can add or remove from */
#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/EditorEngine.cpp:528
Scope (from outer to inner):
file
function UEditorEngine::UEditorEngine
Source code excerpt:
});
for (const FPropertyColorCustomProperty& PropertyColorCustomProperty : GetDefault<UPropertyColorSettings>()->CustomProperties)
{
FActorPrimitiveColorHandler::Get().RegisterPrimitiveColorHandler(PropertyColorCustomProperty.Name,
FInternationalization::ForUseOnlyByLocMacroAndGraphNodeTextLiterals_CreateText(*PropertyColorCustomProperty.Text, TEXT("PropertyColor"), *PropertyColorCustomProperty.Name.ToString()),
[this, PropertyColorCustomProperty](const UPrimitiveComponent* InPrimitiveComponent)
{
if (AActor* Actor = InPrimitiveComponent->GetOwner())
#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/EditorObject.cpp:689
Scope (from outer to inner):
file
function static const TCHAR* ImportProperties
Source code excerpt:
}
}
else if( FParse::Command(&Str,TEXT("CustomProperties")))
{
check(SubobjectOuter);
SubobjectOuter->ImportCustomProperties(Str, Warn);
}
else if (IsEndOfProperties(Str, Depth))
#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/EditorObject.cpp:1430
Scope (from outer to inner):
file
namespace EditorUtilities
function static const TCHAR* ImportPropertiesStep
Source code excerpt:
}
}
else if( FParse::Command(&Str,TEXT("CustomProperties")))
{
check(SubobjectOuter);
SubobjectOuter->ImportCustomProperties(Str, Warn);
}
else if (IsEndOfProperties(Str, Depth))
#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/PropertyColorSettings.h:44
Scope (from outer to inner):
file
class class UPropertyColorSettings : public UObject
Source code excerpt:
UPROPERTY(Config)
TArray<FPropertyColorCustomProperty> CustomProperties;
};
#Loc: <Workspace>/Engine/Source/Runtime/CoreUObject/Private/UObject/Obj.cpp:1770
Scope (from outer to inner):
file
function void UObject::DeclareCustomVersions
Source code excerpt:
if (ScriptStruct)
{
// Construct an instance and collect CustomProperties from it via Serialize
int32 Size = ScriptStruct->GetPropertiesSize();
int32 Alignment = ScriptStruct->GetMinAlignment();
AllocationBuffer.SetNumUninitialized(Align(Size, Alignment) + Alignment);
uint8* StructBytes = Align(AllocationBuffer.GetData(), Alignment);
ScriptStruct->InitializeStruct(StructBytes);
ScriptStruct->SerializeItem(Ar, StructBytes, nullptr);
#Loc: <Workspace>/Engine/Source/Runtime/Experimental/Iris/Core/Private/Iris/ReplicationState/ReplicationStateDescriptorBuilder.cpp:2628
Scope (from outer to inner):
file
namespace UE::Net
function SIZE_T FReplicationStateDescriptorBuilder::CreateDescriptorsForClass
Source code excerpt:
// We add separate descriptors properties with custom replication fragments
TArray<FPropertyReplicationStateDescriptorBuilder::FMemberProperty, TInlineAllocator<8>> CustomProperties;
FPropertyReplicationStateDescriptorBuilder::FIsSupportedPropertyParams IsSupportedPropertyParams;
IsSupportedPropertyParams.LifeTimeProperties = &LifeTimeProperties;
IsSupportedPropertyParams.InObjectClass = InObjectClass;
IsSupportedPropertyParams.bAllowFastArrayWithExtraReplicatedProperties = Parameters.AllowFastArrayWithExtraReplicatedProperties;
#Loc: <Workspace>/Engine/Source/Runtime/Experimental/Iris/Core/Private/Iris/ReplicationState/ReplicationStateDescriptorBuilder.cpp:2666
Scope (from outer to inner):
file
namespace UE::Net
function SIZE_T FReplicationStateDescriptorBuilder::CreateDescriptorsForClass
Source code excerpt:
{
// We build separate descriptors for all properties with CustomReplicationFragments
CustomProperties.Add(MemberProperty);
continue;
}
else if (EnumHasAnyFlags(MemberProperty.Traits, EMemberPropertyTraits::IsFastArray))
{
// FastArrayProperties should use a custom replication fragment
UE_LOG(LogIris, Error, TEXT("FReplicationStateDescriptorBuilder::CreateDescriptorsForClass FFastArray property %s not registered and won't be replicated."), *Property->GetFullName());
#Loc: <Workspace>/Engine/Source/Runtime/Experimental/Iris/Core/Private/Iris/ReplicationState/ReplicationStateDescriptorBuilder.cpp:2792
Scope (from outer to inner):
file
namespace UE::Net
function SIZE_T FReplicationStateDescriptorBuilder::CreateDescriptorsForClass
Source code excerpt:
// If we have properties with a CreateAndRegisterReplicationFragmentFunction, we build separate descriptors for them
// We may have to re-order custom properties if there are more than one.
if (CustomProperties.Num() > 1)
{
InitCVarReplicateCustomDeltaPropertiesInRepIndexOrder();
// If CVarReplicateCustomDeltaPropertiesInRepIndexOrder is false then we use the GetLifetimeReplicatedPropsOrder instead, which is the RepLayout legacy behavior.
if (CVarReplicateCustomDeltaPropertiesInRepIndexOrder != nullptr && !CVarReplicateCustomDeltaPropertiesInRepIndexOrder->GetBool())
{
TArray<FPropertyReplicationStateDescriptorBuilder::FMemberProperty, TInlineAllocator<8>> NewCustomProperties;
NewCustomProperties.Reserve(CustomProperties.Num());
for (const FLifetimeProperty& LifetimeProperty : LifeTimePropertiesOriginalOrder)
{
if (const FPropertyReplicationStateDescriptorBuilder::FMemberProperty* MemberProperty = CustomProperties.FindByPredicate([RepIndex = LifetimeProperty.RepIndex](const FPropertyReplicationStateDescriptorBuilder::FMemberProperty& MemberProperty) { return RepIndex == MemberProperty.Property->RepIndex; }))
{
NewCustomProperties.Add(*MemberProperty);
}
}
CustomProperties = NewCustomProperties;
}
}
for (uint32 CustomPropertyIt = 0, CustomArrayPropertyEndIt = CustomProperties.Num(); CustomPropertyIt != CustomArrayPropertyEndIt; ++CustomPropertyIt)
{
const FPropertyReplicationStateDescriptorBuilder::FMemberProperty& MemberProperty = CustomProperties[CustomPropertyIt];
// Verify some assumptions, for now we do not support putting properties with custom replication fragments in multiple states
check(!EnumHasAllFlags(MemberProperty.Traits, EMemberPropertyTraits::InitOnly | EMemberPropertyTraits::HasLifetimeConditionals));
FPropertyReplicationStateDescriptorBuilder Builder;
FPropertyReplicationStateDescriptorBuilder::FBuildParameters BuildParameters = {};
#Loc: <Workspace>/Engine/Source/Runtime/MovieScene/Public/EntitySystem/MovieScenePartialProperties.h:55
Scope (from outer to inner):
file
namespace UE
namespace MovieScene
function explicit TSetPartialPropertyValuesImpl
Source code excerpt:
explicit TSetPartialPropertyValuesImpl(ICustomPropertyRegistration* InCustomProperties, TArrayView<const FPropertyCompositeDefinition> InCompositeDefinitions)
: CustomProperties(InCustomProperties)
, CompositeDefinitions(InCompositeDefinitions)
{
if (CustomProperties)
{
CustomAccessors = CustomProperties->GetAccessors();
}
}
void ForEachAllocation(const FEntityAllocation* Allocation, TRead<UObject*> BoundObjectComponents, FThreeWayAccessor PropertyBindingComponents, TRead<MetaDataTypes>... InMetaData, TReadOptional<CompositeTypes>... InCompositeComponents) const;
void ForEachAllocation(const FEntityAllocation* Allocation, TRead<UObject*> BoundObjectComponents, FTwoWayAccessor PropertyBindingComponents, TRead<MetaDataTypes>... InMetaData, TReadOptional<CompositeTypes>... InCompositeComponents) const;
#Loc: <Workspace>/Engine/Source/Runtime/MovieScene/Public/EntitySystem/MovieScenePartialProperties.h:77
Scope (from outer to inner):
file
namespace UE
namespace MovieScene
Source code excerpt:
private:
ICustomPropertyRegistration* CustomProperties;
FCustomAccessorView CustomAccessors;
TArrayView<const FPropertyCompositeDefinition> CompositeDefinitions;
};
template<typename PropertyTraits, typename ...CompositeTypes>
using TSetPartialPropertyValues = TSetPartialPropertyValuesImpl<PropertyTraits, typename PropertyTraits::MetaDataType, TMakeIntegerSequence<int, sizeof...(CompositeTypes)>, CompositeTypes...>;
#Loc: <Workspace>/Engine/Source/Runtime/MovieScene/Public/EntitySystem/MovieScenePropertySystemTypes.h:324
Scope (from outer to inner):
file
namespace UE
namespace MovieScene
function explicit TSetPropertyValuesImpl
Source code excerpt:
explicit TSetPropertyValuesImpl(ICustomPropertyRegistration* InCustomProperties)
: CustomProperties(InCustomProperties)
{
if (CustomProperties)
{
CustomAccessors = CustomProperties->GetAccessors();
}
}
/**
* Task callback that applies a value to an object property via a custom native setter function
* Must be invoked with a task builder with the specified parameters:
#Loc: <Workspace>/Engine/Source/Runtime/MovieScene/Public/EntitySystem/MovieScenePropertySystemTypes.h:401
Scope (from outer to inner):
file
namespace UE
namespace MovieScene
Source code excerpt:
private:
ICustomPropertyRegistration* CustomProperties;
FCustomAccessorView CustomAccessors;
};
/**
* Stateless entity task that will apply values to properties. Three types of property are supported: Custom native accessor functions, fast pointer offset, or FTrackInstancePropertyBindings
#Loc: <Workspace>/Engine/Source/Runtime/MovieScene/Public/EntitySystem/MovieScenePropertySystemTypes.h:456
Scope (from outer to inner):
file
namespace UE
namespace MovieScene
function explicit TGetPropertyValuesImpl
Source code excerpt:
explicit TGetPropertyValuesImpl(ICustomPropertyRegistration* InCustomProperties)
: CustomProperties(InCustomProperties)
{
if (CustomProperties)
{
CustomAccessors = CustomProperties->GetAccessors();
}
}
/**
* Task callback that retrieves the object's current value via a custom native setter function, and writes it to the specified output variable
* Must be invoked with a task builder with the specified parameters:
#Loc: <Workspace>/Engine/Source/Runtime/MovieScene/Public/EntitySystem/MovieScenePropertySystemTypes.h:537
Scope (from outer to inner):
file
namespace UE
namespace MovieScene
Source code excerpt:
private:
ICustomPropertyRegistration* CustomProperties;
FCustomAccessorView CustomAccessors;
};
template<typename PropertyTraits>
struct TGetPropertyValues : TGetPropertyValuesImpl<PropertyTraits, typename PropertyTraits::MetaDataType>
#Loc: <Workspace>/Engine/Source/Runtime/MovieScene/Public/EntitySystem/MovieScenePropertySystemTypes.h:591
Scope (from outer to inner):
file
namespace UE
namespace MovieScene
function explicit TSetCompositePropertyValuesImpl
Source code excerpt:
explicit TSetCompositePropertyValuesImpl(ICustomPropertyRegistration* InCustomProperties)
: CustomProperties(InCustomProperties)
{
if (CustomProperties)
{
CustomAccessors = CustomProperties->GetAccessors();
}
}
/**
* Task callback that applies a value to an object property via a custom native setter function
* Must be invoked with a task builder with the specified parameters:
#Loc: <Workspace>/Engine/Source/Runtime/MovieScene/Public/EntitySystem/MovieScenePropertySystemTypes.h:680
Scope (from outer to inner):
file
namespace UE
namespace MovieScene
Source code excerpt:
private:
ICustomPropertyRegistration* CustomProperties;
FCustomAccessorView CustomAccessors;
};
template<typename PropertyTraits, typename ...CompositeTypes>
using TSetCompositePropertyValues = TSetCompositePropertyValuesImpl<PropertyTraits, typename PropertyTraits::MetaDataType, CompositeTypes...>;