BlueprintAutocast in C++ UBlueprintFunctionLibrary Subclass

Hello,

I am making a Plugin and realized that I could use some faster Blueprint prototyping for the end developer if I add auto conversions for various types in my system. After building the project however, the auto cast does not work. I followed the meta categories of the String library. Is this not supported outside of the core modules or am I doing something wrong?


	
UFUNCTION(BlueprintPure, meta = (DisplayName = "Value (MyObject)", CompactNodeTitle = "->", BlueprintAutocast), Category = "MyObject")
static FString Conv_MissionStringBindingValue(const class UMyObject* MyObjectPtr);


Thank you.

Looking at the engine source and trying to follow what happens with the BlueprintAutocast metadata this seems to be the flow:

All functions with the BlueprintAutocast metadata are added to the FAutocastFunctionMap singelton. This map is refreshed for example when you HotReload from the editor (FAutocastFunctionMap::OnProjectHotReload) or a module changes (FAutocastFunctionMap::OnModulesChanged). The FAutocastFunctionMap::InnerMap maps strings to TWeakObjectPtr<UFunction>. The string keys contain the type information of the first input pin and the return property.

So now we have this map available where is it actually used?
The AutocastFunctionMap is searched for an appropriate entry via FAutocastFunctionMap::Find using the input and return pin type information. The search is done in UEdGraphSchema_K2::SearchForAutocastFunction. It is used to determine whether a connection is possible (UEdGraphSchema_K2::CanCreateConnection) and in UEdGraphSchema_K2::CreateAutomaticConversionNodeAndConnections. This function is called when you try to connect a wire for example from a ā€˜floatā€™ type output pin to a ā€˜stringā€™ type input pin. Thanks to the BlueprintAutocast function/system, the function call to UKismetStringLibrary::Conv_FloatToString will be added automagically :slight_smile:

In your case this means when you drag a wire from a UMyObject* to a string input, your Conv_MissionStringBindingValue function should be automatically created for you.

Is this what you were expecting to happen with the BlueprintAutocast metadata or were you looking for something different?

Yes, I was expecting that. However, that was not the behaviour. Ill step through the code later to see if its not being imported properly to the autocrats registry.

Iā€™ve used it without problems. As far as I can see, your declaration is the same as mine, so Iā€™m not sure why itā€™s not working for you.

Actually looking at my code, for my versions taking UObject/UClass, the parameter is non-const. Seems unlikely that would be an issue, but something to try. The use of const in Blueprint-facing code is rather inconsistent in my experience.

Thanks. That wasnā€™t something I consideredā€¦ funny considering that the definition of Blueprint Pure implies the same contract as constā€¦

Seems that removing the constness of the parameter worked. However, now it is just passing in a nullptr despite the fact that in the BP Graph in debug, it has a valid referenceā€¦ another problem for another day. Thanks.

Another solution (for people with a similar problem): in my case it worked after setting the functions as public.
I forgot that because I was copying it from Epicā€™s code. Interestingly, theirs worked without being public.
And I found this on EdGraphSchema_K2.cpp:


static bool IsAutocastFunction(const UFunction* Function)
{
    const FName BlueprintAutocast(TEXT("BlueprintAutocast"));
    return Function
        && Function->HasMetaData(BlueprintAutocast)
        && Function->HasAllFunctionFlags(FUNC_Static | FUNC_Native | FUNC_Public | FUNC_BlueprintPure)
        && Function->GetReturnProperty()
        && GetFirstInputProperty(Function);
}

This means itā€™ll only consider a function as an auto-cast if all of these are true:

  • it has the meta BlueprintAutocast
  • itā€™s static
  • itā€™s native (C++, so itā€™s always true)
  • itā€™s public
  • itā€™s BlueprintPure.
  • it returns something
  • it has an input parameter

Thatā€™s how I solved my problem. Hope it helps someone.

Edit 2023/08/23: make it more detailed

4 Likes

Resurrecting an old thread here, but itā€™s the top result when trying to work out why BlueprintAutocast functions are not working.

I had an issue where I wanted to convert a custom type to/from a float, and while I could easily make the function work, it would never show up as an automatic cast/conversion when using drag-and-drop.

The problem was that if you are using Unreal Engine 5, all ā€œfloatā€ variables in Blueprint are actually doubles. So, you will need to use double instead of float in the code for any such autocast functions.

If you use float instead, the function will work as a normal function without issue, but it will never be selected for autocasting to/from a Blueprint float variable.

Example code for an autocast function to convert a custom struct to a Blueprint float:

	UFUNCTION(BlueprintPure, meta = (DisplayName="To Float (Time Value)", CompactNodeTitle = "->", Keywords = "cast convert", BlueprintAutocast), Category="Math|Conversions")
	static double Conv_CustomValueToFloat(FCustomValue InValue)
	{
		return InValue.Value;
	}
2 Likes
UCLASS() 
class UMyFunctionLib : public UBlueprintFunctionLibrary //Must be UBlueprintFunctionLibrary
{
	GENERATED_BODY()
public: //must be public
	
	UFUNCTION(BlueprintPure, meta = (DisplayName = "A To B",CompactNodeTitle = "->", BlueprintAutocast), Category = "MyUtils")
	static FStructB Conv_AToB(FStructA In)
	{
		return ....
	}
}