Download

[Plugin] Is there any way to access and *set* blueprint data from C++ in my plugin?

One of the planned features in my plugin is to have the ability to spawn blueprints with varied functionality into the user’s scene.
However, I’ve been looking for a way to adjust their data and have been drawing a blank so far.
There’s samples out there for reading data from a blueprint, but nothing for actually changing anything on it as far as I can see without deriving from a user class.
(And definitely not for let’s say adding to an array of a UserDefinedStruct)

Is there any way to do this without having to have users put random bits of my C++ code for base classes and structs in their possibly Blueprint only projects?

You mean changing blueprint-defined properties? Yes, it’s entirely possible. You can iterate through all of an class properties (UProperty) using the TFieldIterator and then use UProperty’s ContainerPtrToValuePtr() function to grab the pointer to where the actual value is stored for a specific object.

Take a look at the FJsonObjectConverter source code to get an idea how it works.

I’m… still quite stumped as to how to pull it all together, to be quite honest.
I have an idea of how it’s supposed to work now, yes, but this code makes my brain hurt.
Hell, my gut tells me I’m not even iterating the actual spawned version.
I might be wrong, but that’s what my gut tells me…



                        UBlueprint* BPtoUse = NULL;
			BPtoUse = HammUErSettings::FindInBPDatabase("logic_auto"); // the BP we want to modify
			UUserDefinedStruct* UDStoUse = NULL;
			UDStoUse = HammUErSettings::FindInUDSDatabase("hammeroutput"); // the definition of the struct we'll need to fill
			if (BPtoUse && UDStoUse)
			{
				TSubclassOf<AActor> BPClass = (UClass*)BPtoUse->GeneratedClass;
				AActor* LogicAutoActor = editorWorld->SpawnActor<AActor>(BPClass, FAS);
				for (TFieldIterator<UProperty> PropIt(LogicAutoActor->GetClass()); PropIt; ++PropIt)
				{
					UProperty* Property = *PropIt;
					FString PropertyName = Property->GetName();
					if (PropertyName == "HammerOutputs")
					{
                                                      // now what? Am I even touching the actual LogicAutoActor? how the hell do I declare an array of UDStoUse and fill it, then assign it?
					}
				}


For context, Logic_Auto is a blueprint with a HammerOutputs array of HammerOutput structs (defined in-editor as a UserDefinedStruct consisting of FStrings, a float and a bool) that I want to declare and fill in code.

I think what you need to do is cast your Property to [FONT=Courier New]UArrayProperty and create a [FONT=Courier New]FScriptArrayHelper so that dealing with the array via properties becomes a bit easier. You can then use the helper’s [FONT=Courier New]AddValue method to add uninitialized values to the array, and the [FONT=Courier New]Inner property of the [FONT=Courier New]UArrayProperty to determine how to create the values. This is rather tedious, but it seems to work.

I’ve put a small project demonstrating all this at https://gitlab.com/mhoelzl/PropertyTest. (Not a plugin, the code just lives in the game mode.)

Thanks, that did it.
You’re a prince.