I’d like to set&get ustruct property value. What I have is
UProperty* Property - property that I want to get (float)
UObject* PropertyOwner - owner of this property (UStruct in this case)
For example: I’m trying to get FilmContrast value from FPostProcessSettings struct inside camera component.
So normally I would do something like this: *Property->ContainerPtrToValuePtr(PropertyOwner) to get this property value. But because PropertyOwner is a UStruct the line above crashes.
I’ve seen some examples in the source code that uses ContainerPtrToValuePtr method but I’m not sure if this is the right way to get into ustruct properties and how exactly can i do it.
I’m not sure of what you are trying to do, you want to get the value from a default property of a struct? Or just access the property value from an instance of a struct? Or something else?
Structs are a little different than UObjects, but you can get and set their members like so:
float GetSetVectorX(UObject * ObjectWithVector)
{
FName PropName = FName("MyVector");
FName VectorMemberName = FName("X");
float NewValue = 42.0;
// Get property representing struct
UProperty * Prop = ObjectWithVector->GetClass()->FindPropertyByName(PropName);
// Ensure ObjectWithVector actually has a myVector member
if (Prop)
{
// Get struct address
void * StructAddress = Prop->ContainerPtrToValuePtr<void>(ObjectWithVector);
// Ensure MyVector really is a vector
if (UStructProperty * StructProp = Cast<UStructProperty>(Prop))
{
// We'll get struct properties through a UScriptStruct, not a UObject
// ScriptStructs are just templates and don't hold any of your data
UScriptStruct * ScriptStruct = StructProp->Struct;
// Get the vector's "X" property
UProperty * ChildProp = ScriptStruct->FindPropertyByName(VectorMemberName);
// Cast to FloatProperty
if (UFloatProperty * ChildFloatProp = Cast<UFloatProperty>(ChildProp))
{
// Get
float OldValue = ChildFloatProp->GetFloatingPointPropertyValue(StructAddress);
// Set
ChildFloatProp->SetFloatingPointPropertyValue(StructAddress, NewValue);
return OldValue;
}
}
}
return 0;
}
I should note that (at least in my environment) Structs created in blueprints have invisible extensions added to their member names. So a member called “CrazyName” might look like this:
CrazyName_2_8879DD6E49624206B15E6DB35EFD0E09
It’s not exactly elegant, but I parse all the Struct’s members into a map beforehand:
UScriptStruct * ScriptStruct = StructProp->Struct;
// FriendlyNames => BlueprintNames
TMap<FString, FString> BlueprintNames;
// Is this Struct not made with Cpp?
if (!ScriptStruct->IsNative())
{
// Get Struct's first member
UField * Field = ScriptStruct->Children;
while (Field)
{
// Get Blueprint name
FString FieldName = Field->GetName();
// Chop off the second-to-last underscore (_)
int index = FieldName.Len();
for (int i = 0; i < 2; ++i)
{
index = FieldName.Find(FString("_"), ESearchCase::CaseSensitive, ESearchDir::FromEnd, index);
}
// Get the friendly name
FString MemberName = FieldName.Left(index);
// Add to map
BlueprintNames.Add(MemberName, FieldName);
// Go to next member
Field = Field->Next;
}
}
Then I get and set the Struct’s members as normal:
// Only difference:
FString LiteralName = FString("CrazyName");
FName MemberName = FName(*(ScriptStruct->IsNative() ? LiteralName : BlueprintNames[LiteralName]));
// Normal business
UProperty * Prop = ScriptStruct->FindPropertyByName(MemberName);
// ... Get / Set logic ...
I know this is an old question, but I arrived here while trying to do something similar, so I’ll add what worked for me. If the object in question has a UPROPERTY that is a struct, then you can just cast it to a UStructProperty and then ContainerPtrToValuePtr does what you need.
For example, for an object with an FVector property inside it:
If for some reason you need to be able to serialize and deserialize your UStructProperty, or any other type of property for that matter, regardless of what type it is, then you can use the following to get its value as a byte array.