Set/Get Editor Properties of various types using C++

Hello,
I have a list of property names (which are various property types) for an object. I am trying to get each editor property and modify the properties depending on their type. Here is some rough code showing what I am trying to do:

// obj = Object whose properties need to be modified
// propNames = TArray<FString> list of property names
for (FString propName : propNames)
{
	// Get editor property with same name
	const FName name = FName(*propName);
	int32 val;
	if (!UKismetSystemLibrary::GetEditorProperty(obj, name, val)) continue;;
	// Set property depending on property class type
	// if val is FLinearColor, then change it and pass to UKismetSystemLibrary::SetEditorProperty(obj, name, newVal);
	// Problem: Because val/newVal must be int32, cannot do non-int types
}

I have discovered UKismetSystemLibrary’s editor functions and have been trying to use them for this with no luck.
When trying to use UKismetSystemLibrary::GetEditorProperty() or UKismetSystemLibrary::SetEditorProperty() I run into the issue that these functions expect PropertyValue to be type int32, which prevents me from getting and setting non-numerical properties.

When trying to use the generics UKismetSystemLibrary::Generic_GetEditorProperty() or UKismetSystemLibrary::Generic_SetEditorProperty() I do not know what to set the const FProperty* ValueProp parameter to since I do not know the property type. Do I just set this to nullptr?

I found that UKismetSystemLibrary has a CustomThunk with the following but it uses the BP Stack to get the value property which afaik I do not have access to without being a BP function:

DEFINE_FUNCTION(UKismetSystemLibrary::execGetEditorProperty)
{
	P_GET_OBJECT(UObject, Object);
	P_GET_PROPERTY(FNameProperty, PropertyName);

	Stack.StepCompiledIn<FProperty>(nullptr);
	const FProperty* ValueProp = Stack.MostRecentProperty;
	void* ValuePtr = Stack.MostRecentPropertyAddress;

	P_FINISH;
	... // Eventually returns Generic_GetEditorProperty(Object, PropertyName, ValuePtr, ValueProp)
}

How do I set/get editor properties in C++ when the editor properties are effectively wildcard type? How do I check what type the property is upon getting it? Thank you!

If you’re interested in doing advanced stuff with reflection, take a look at how the UE5 python module deals with unknown property types.

I think the preferred method is to just try to cast the FProperty to each type-specific property, and then operate on it if the cast succeeds

void DoWork(UObject* yourObj, FName propName) {
	FProperty* prop = yourObj->GetClass()->FindPropertyByName(propName);
	if (FObjectPtrProperty* objPtrProp = Cast<FObjectPtrProperty>(prop)) {
		UObject* desiredValue = YourFunctionThatGetsSomeRandomUObj();
		objPtrProp->SetObjectPropertyValue_InContainer(yourObj, desiredValue);
	} else if (FBoolProperty* boolPtrProp = Cast<FBoolProperty>(prop)) {
		bool desiredValue = YourFunctionThatGetsSomeRandomBool();
		boolPtrProp ->SetPropertyValue(yourObj, desiredValue);
	}
	...
}

I have looked at the UE5 Python module and got dizzy with all the wrapping + reflection used to handle all the unknown types haha. Will keep trying to understand it though, it is fascinating.

I will try casting the FProperty and using SetPropertyValue(). Will SetPropertyValue() work for editor properties? I assume so since any property should be set by it. Thank you for your help!

I’m pretty new to it myself but I would operate on the assumption that the property system should work both for blueprint-defined properties (if that’s what you mean by editor properties) and native properties (c++ UCLASS() variables that are marked by UPROPERTY())

Editor properties are properties marked as editor-only (as in only in Editor should they be read/modified). SetPropertyValue() should still work since afaik editor-only properties are basically the same as normal properties just flagged to be editor-only.

I am on UE5.1.1 and I want to edit the UPROPERTY fields of an object via C++.

  auto* GridActorPlane = GetWorld()->SpawnActor<AGridPlane>(SpawnLocation);

  auto* Prop = GridActorPlane->GetClass()->FindPropertyByName("GridSize");
  FIntProperty* Prop_Field = CastField<FIntProperty>(Prop);
  Prop_Field->SetValue_InContainer(GridActorPlane, 4000);

The above code works as expected and the property is set to 4000. The problem is that PostEditChangeProperty doesn’t trigger.


To give more context:

I have a AGameConfigurations actor blueprint that I manually place in the world. This actor contains only UPROPERTY fields and I want to use it as a global manager to configure anything in the world.

Suppose I have the GridSize property in this actor as well and if I change it, I want this change to propagate to the GridSize from the AGridPlane actor.

The Grid plane with all its rows and columns is created in AGridPlane::OnConstruction . I have noticed that if I edit directly the GridSize UPROPERTY of this AGridPlane actor then the grid mesh properly updates again.

I want to be able to edit the AGridPlane using the GridSize from AGameConfigurations actor. This way I can centralize the configurations of all the actors settings that I use.

If somebody knows how to do this it will be greatly appreciated.

Hi there, I’m having the same issue as you seemed to be having. I was wondering if you found a solution to trigger PostEditChangeProperty?

Thanks

Unfortunately I didnt manage to find a solution and I went with a different implementation using subsystems.

No worries, thanks! :slight_smile: