Creating and editing Blueprint from C++

Hello,
I am working on a plugin who import a file and create the corresponding actor completely setup and ready to use in UE.
The file is correctly readed but I am stuck on the creation of the Actor : I created a C++ class derivated from AActor. I can instantiate it from C++ but I am unable to save this instance as an Asset on the Content Browser. From the UI I can create a Blueprint derivated from this C++ class but I am unable to find how to do the same thing from code.

There is a way to save this ready to use instance on the Content Browser ?
Thanks in advance.

First create a package for your new asset (blueprint), then use FKismetEditorUtilities::CreateBlueprint to create a blueprint based on your parent class.

UPackage* Package = CreatePackage("/Game/Blueprints/BP_MyClass");

// Create and init a new Blueprint
UBlueprint* Blueprint = FKismetEditorUtilities::CreateBlueprint(ParentClass, Package, "BP_MyClass", BPTYPE_Normal, UBlueprint::StaticClass(), UBlueprintGeneratedClass::StaticClass());

if (Blueprint)
{
	// Notify the asset registry
	FAssetRegistryModule::AssetCreated(Blueprint);

	// Mark the package dirty...
	Package->MarkPackageDirty();
}

Hello,

I can create a blueprint derivated from my C++ class but I would like now to tune the properties values to make the BP ready to use for the user. I have this for now:

FName BluePrintName = FName(ObjectTools::SanitizeObjectName("A_MyBPActor");
FString AssetPath = InParent->GetName() + "/" + BluePrintName.ToString();
UPackage* BluePrintPackage = MyUtilsClass::PreparePackage(BluePrintName.ToString(), AssetPath);

// Create and init a new blank Blueprint
UBlueprint* Blueprint = FKismetEditorUtilities::CreateBlueprint(AMyActor::StaticClass(), BluePrintPackage, BluePrintName, BPTYPE_Normal, UBlueprint::StaticClass(), UBlueprintGeneratedClass::StaticClass());

if (Blueprint) {

	// HERE I WOULD LIKE TO EDIT ACTOR PROPERTIES

	// Save the Asset init
	FCompilerResultsLog LogResults; // We don't really care of the logs here.
	FKismetEditorUtilities::CompileBlueprint(Blueprint, EBlueprintCompileOptions::None, &LogResults);

	// Notify the asset registry
	FAssetRegistryModule::AssetCreated(Blueprint);

	// Mark the package dirty...
	BluePrintPackage->MarkPackageDirty();
}

I found this who seems to be interesting but it fails trying to get the value because it is a blueprint instance and not AMyActor instance : Edit Blueprint Variable in C++

Default values are stored in the Class Default Object (CDO).

After creating blueprint, you can get the UClass (which should be a BlueprintGeneratedClass if that matters) via Blueprint->GeneratedClass.

Then you can get the CDO via Class->GetDefaultObject().

So here is an example :

UClass* Class = Blueprint->GeneratedClass;
AMyActor* CDO = Class->GetDefaultObject<AMyActor>();

// For c++ properties you can edit them directly
CDO->SomeCppProperty = 42.f;

// If you are generating new BP properties, you'll have to modify them through reflection
UProperty* SomeBpProp = Class->FindPropertyByName("SomeBpProp");
*SomeBpProp->ContainerPtrToValuePtr<float>(CDO) = 42.f;

Whether you need to compile before accessing it, or after modifying it, I have no idea, you’ll have to figure it out through trial and error.

1 Like

I already tried to edit the CDO some days ago but my edits wasn’t restored after a reboot of Unreal. I finally found why: I forgotten to compile the blueprint after my edits :man_facepalming:.
Finally the complete working code is:

FName BluePrintName = FName(ObjectTools::SanitizeObjectName("A_MyBPActor");
FString AssetPath = InParent->GetName() + "/" + BluePrintName.ToString();
UPackage* BluePrintPackage = MyUtilsClass::PreparePackage(BluePrintName.ToString(), AssetPath);

// Create and init a new blank Blueprint
UBlueprint* Blueprint = FKismetEditorUtilities::CreateBlueprint(AMyActor::StaticClass(), BluePrintPackage, BluePrintName, BPTYPE_Normal, UBlueprint::StaticClass(), UBlueprintGeneratedClass::StaticClass());

if (Blueprint) {

	// Editing the BluePrint
	AMyActor* BlueprintValues = Blueprint->GeneratedClass.Get()->GetDefaultObject<AMyActor>();
	BlueprintValues->bSomeProperty = true;

	// Compile the changes
	FCompilerResultsLog LogResults; // We don't really care of the logs here.
	FKismetEditorUtilities::CompileBlueprint(Blueprint, EBlueprintCompileOptions::None, &LogResults);

	// Notify the asset registry
	FAssetRegistryModule::AssetCreated(Blueprint);

	// Mark the package dirty...
	BluePrintPackage->MarkPackageDirty();
}

Thanks a lot !