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
.
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 !