Download

Casting UBlueprint to actual Parent Class

Hi,

i just cant get any solution for the following issue:

I want a list of Blueprints to be assigned to a custom Blueprint through the editor and then worked with in code.
First i made a new Blueprint out of the HUD containing:



UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Indy)
TArray<UBlueprint*> Elements;


Then i made a new Class UTest : UObject with the Blueprintable directive, created a new Blueprint in the editor using UTest as parent class, and added that blueprint then into the Elements of the HUD.

So far so good.

Now, in the actual implementation i iterate over the TArray and want the actual BaseClass of the Blueprint:



	for (TArray<UBlueprint*>::TIterator eleIter(Elements); eleIter; ++eleIter) {
		UBlueprint* current = *eleIter;
		if (current) {
			UTest* currentElement = Cast<UTest>(current);
			currentElement->GetCustomStuff();


Now the cast does fail and currentElement is NULL.

The Question is: How can i cast the UBlueprint back to the actual Parent Object? Is there some special property i need to get?

Thanks!
Cheers,
Indy

If you go to Blueprint.h


/** Pointer to the parent class that the generated class should derive from */
	UPROPERTY(AssetRegistrySearchable)
	TSubclassOf<class UObject>  ParentClass;

You should be able to access the parent class directly :slight_smile:


current->ParentClass;

Let us all know if that works!

there’s also this, which I always thought was rather nifty:


/** 
	 * Gets an array of all blueprints used to generate this class and its parents.  0th elements is the BP used to generate InClass
	 *
	 * @param InClass				The class to get the blueprint lineage for
	 * @param OutBlueprintParents	Array with the blueprints used to generate this class and its parents.  0th = this, Nth = least derived BP-based parent
	 * @return						true if there were no status errors in any of the parent blueprints, otherwise false
	 */
	static bool GetBlueprintHierarchyFromClass(const UClass* InClass, TArray<UBlueprint*>& OutBlueprintParents);

_


PS: I know your question is about casting

I’m hoping you will magically figure this out with some kind of additional inspiration from my above info

Given that request, what Rama suggested is the right way to convert a blueprint into a class. However, you shouldn’t be using blueprint pointers or arrays of blueprint pointers in general. Instead, point to the base class itself. This means you can exchange native C++ and Blueprint generated classes without worrying about the underlying type.

For example, you might do:
TSubclassOf<AActor> ActorClass;

Where you can replace AActor with whatever class name you want, or if it can literally be anything, use UClass* instead.

Cheers,
Michael Noland

Hi Michael,

understood. Though, what would then be the correct way to achieve the following:

I have a Class UHudButton, which contains something like this:




UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = IndyHUD)
UTexture2D* ButtonUpTexture;

UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = IndyHUD)
UTexture2D* ButtonHoverTexture;

...


Now in the Editor i create a few Blueprint from that Class and assign each one the individual textures, i.e. for Start Game, for Quit, etc.

In my HUD Class (which i got blueprinted too) i then have want to have a list of UHudButton’s, each with it’s textures.

Of course i first tried with



TArray<UHudButton*> Elements;


though it’s still not supported to have a TArray with a BlueprintBaseClass (=UHudButton) and fill it from the Editor with the Blueprints that got this one as parent class.

I simply couldnt find a different way to not have all the textures for the buttons hardcoded, or have a hardcoded number of buttons, thus the TArray.

Any ideas?

Cheers,
Indy

TArray<UHudButton*> is an array of instances, not an array of classes.

TArray<TSubclassOf<UHudButton>> should allow you to pick subclasses of UHudButton in the details panel. If they’re just data assets, you can then use GetDefault to read the member variables:



for (TSubclassOf<UHudButton> ButtonClass : Elements)
{
	if (const UHudButton* DefaultInstance = ButtonClass->GetDefaultObject())
	{
		do something with DefaultInstance->ButtonHoverTexture, etc...
	}
}

Otherwise if those values are computed or change over time, you may need to instantiate the button class (NewObject<UHudButton>(Outer, Class)).

Cheers,
Michael Noland

Hi Michael,

in the meanwhile i already figured out how to use TSubclassOf in the array correctly; Finally i understood the concept completely :wink:

Thanks to you and Rama for the support!

Cheers,
Indy