I’m doing a custom struct property layout that would allow me to set a UObject property value through a custom widget interface. I usually do this by getting a property handle to the property I am editing, then setting or getting the value through the handle.** In this example, I am trying to modify a UCameraComponent property.**
Below is an example of how I retrieve the property handle. This step is fine.
void FCustomStructCustomization::CustomizeHeader(TSharedRef<class IPropertyHandle> StructPropertyHandle, FDetailWidgetRow& HeaderRow, IPropertyTypeCustomizationUtils& StructCustomizationUtils)
{
uint32 NumChildren;
StructPropertyHandle->GetNumChildren(NumChildren);
for(uint32 i = 0; i < NumChildren; i++)
{
TSharedPtr<IPropertyHandle> Prop = StructPropertyHandle->GetChildHandle(i);
if(Prop->GetProperty()->GetFName() == FName("MyPropertyName"))
{
// Store this property handle for later..
MyPropertyHandle= Prop;
}
}
The issue is, when the time comes for my UI to change the value of my property, my usual method no longer works. I set the value after an item from a ListView is selected.
if(SelectionInfo == ESelectInfo::OnNavigation)
{
return;
}
if(MyPropertyHandle.IsValid() && MyPropertyHandle->IsValidHandle())
{
UCameraComponent* component = // component pointer I acquired from the owning actor using GetComponents(TArray<UCameraComponent*>)
MyPropertyHandle->SetValue(component);
}
I expected that would cause the UProperty in my struct to now point to the CameraComponent I acquired from the actor. The above fails as detailed in the source code implementation:
FPropertyAccess::Result FPropertyHandleObject::SetValue( const UObject* const& NewValue, EPropertyValueSetFlags::Type Flags )
{
UProperty* Property = Implementation->GetPropertyNode()->GetProperty();
bool bResult = false;
// Instanced references can not be set this way (most likely editinlinenew )
if( !Property->HasAnyPropertyFlags(CPF_InstancedReference) )
{
FString ObjectPathName = NewValue ? NewValue->GetPathName() : TEXT("None");
bResult = Implementation->SendTextToObjectProperty( ObjectPathName, Flags );
}
return bResult ? FPropertyAccess::Success : FPropertyAccess::Fail;
}
So it appears that the UPROPERTY I am modifying is an InstancedReference. I am not sure of the implications but that is not surprising for an actor component. Is there a way to set the property nonetheless? Or is it impossible by design?