Adding a variable type - HiIAmMoot/RuntimeBPs GitHub Wiki

Adding a variable type

This is currently a mess, but here's the order of things: First you determine wether your variable will be saveable. If it's an object spawned at runtime, then it is not saveable. This doesn't necessarily mean all pointers however. Because there are asset classes that can be saved in the form of filepaths.

For saveable variables, we use FIntPoint as an example. For non-saveable ones, we use ARuntimeBpGrenade*, a custom made class as an example.

Actions for both saveable and not-saveable

RuntimeBlueprintsEditor.Target.cs
  • Expand the variable count by editing the TypeInfo int
	Type = TargetType.Editor;

        // For some reason, the LongUnion update does not happen after the first build since the change. You will have to cancel and build again to have the TypeAmount value updated.
        // This seems to be a bug with UHT, although unsure.
        int TypeAmount = 28;
RuntimeBpData.h
  • Add IntPoint to the EVariableTypes enum
// The kind of variables a pin can be
UENUM(BlueprintType)
enum class EVariableTypes : uint8
{
	// Variables
	Bool 		UMETA(DisplayName = "Bool"),
	Byte 		UMETA(DisplayName = "Byte"),
	Int		UMETA(DisplayName = "Integer"),
  	...
	IntPoint	UMETA(DisplayName = "IntPoint"),
	Grenade		UMETA(DisplayName = "Grenade"),
	// Misc
	Exec 		UMETA(DisplayName = "Exec"),
	WildCard 	UMETA(DisplayName = "WildCard")
};
  • Add the FIntPoint type to the TLongUnion in the NODE_VAR_ARG_UNION macro
#define NODE_VAR_ARG_UNION \
TLongUnion< bool, /* 0 */ \
	uint8, /* 1 */ \
	int,  /* 2 */ \
	...
	FIntPoint, /* 26 */ \
	ARuntimeBpGrenade* > /* 27 */ \
  • Add an entry to the switch in the constructor with EVariableTypes as input
// Constructor with a variable type as input
	FNodeVarArgs(EVariableTypes VariableType)
	{
		switch (VariableType)
		{
		case EVariableTypes::Bool: SetBoolArg(); break;
		case EVariableTypes::Byte: SetByteArg(); break;
		case EVariableTypes::Int: SetIntArg(); break;
		...
		case EVariableTypes::IntPoint: SetIntPointArg(); break;
		case EVariableTypes::IntPoint: SetGrenadeArg(); break;
		default: break;
		}
	}
  • Add a struct deriving from FSaveableProperty for your variable type, if your variable is saveable.
//Saveable formats of each variable type
USTRUCT(BlueprintType)
struct FSaveableBoolArray : public FSaveableProperty 
{ 
	GENERATED_BODY() 
	
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	TArray<bool> Array; 
	SAVEABLE_PROPERTY_ARRAY(bool, Bool, FSaveableBoolArray) 
};

...

USTRUCT(BlueprintType)
struct FSaveableIntPointArray : public FSaveableProperty 
{ 
	GENERATED_BODY() 
	
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	TArray<FIntPoint> Array; 
	SAVEABLE_PROPERTY_ARRAY(FIntPoint, IntPoint, FSaveableIntPointArray) 
};
Additional steps for UE4 object types
  • In case of an UObject hierarchy, add a return to each parent Getter (which are part of the list of variable types) of the new variable type. For example: If you add ACharacter, you need to add this to AActor, APawn and UObject
RuntimeBpJsonLibrary.cpp
  • Add an entry to the switch in the ScriptValueToJsonValue function, if your variable is saveable.
	switch (VariableType)
	{
		case EVariableTypes::Bool: SCRIPT_TO_JSON_CASE(FSaveableBoolArray)
		...
		case EVariableTypes::IntPoint: SCRIPT_TO_JSON_CASE(FSaveableIntPointArray)
		default: break;
	}
	return TArray<TSharedPtr<FJsonValue>>();
  • Add an entry to the switch in the JsonValueToScriptValue function, if your variable is saveable.
	switch (VariableType)
	{
		case EVariableTypes::Bool: JSON_TO_SCRIPT_CASE(FSaveableBoolArray)
		...
		case EVariableTypes::IntPoint: JSON_TO_SCRIPT_CASE(FSaveableIntPointArray)
		default: break;
	}
	return TArray<FNodeVarArgs>();
RuntimeBpLibrary.h
  • Add a BP exposed, safe Getter function
	// Gets the variable in the form of an IntPoint
	UFUNCTION(BlueprintPure, meta = (Category = "Runtime Values|Get", Keywords = "Get Node Var Args Int Point"))
	static TArray<FIntPoint> GetIntPointArg(UPARAM(ref) TArray<FNodeVarArgs>& Values, bool Array = false);
  • Add a BP exposed, safe Setter function
	// Sets the variable in the form of an IntPoint
	UFUNCTION(BlueprintCallable, meta = (Category = "Runtime Values|Set", Keywords = "Set Node Var Args Int Point"))
	static void SetIntPointArg(UPARAM(ref) TArray<FNodeVarArgs>& Values, TArray<FIntPoint> Value);
RuntimeBpLibrary.cpp
  • Add a BP exposed, safe Getter function
TArray<FIntPoint> URuntimeBpLibrary::GetIntPointArg(UPARAM(ref) TArray<FNodeVarArgs>& Values, bool Array)
{
	NODE_VAR_ARG_GETTER_SAFE(FIntPoint, IntPoint)
}
  • Add a BP exposed, safe Setter function
void URuntimeBpLibrary::SetIntPointArg(UPARAM(ref) TArray<FNodeVarArgs>& Values, TArray<FIntPoint> Value)
{
	NODE_VAR_ARG_SETTER_SAFE(FIntPoint, IntPoint)
}
Additional steps for UE4 object types
  • Add an entry to the exclusion switch in the SaveableValueToJson function
	// We make sure that live object references are excluded
	switch (VariableType)
	{
		case EVariableTypes::Object: return FString();
		...
		case EVariableTypes::ParticleSystemComponent: return FString();
		default: return SaveableValue.ToJson(Indent, PrettyPrint);
	}
EditorGraph.cpp
  • Add a case to the switch in the ValueToString function, only for saveable variables.
	switch (VariableType)
	{
		case EVariableTypes::Bool: return URuntimeBpLibrary::GetBoolArg(Values)[0] ? TEXT("true") : TEXT("false");
		case EVariableTypes::Byte: return FString::FromInt(URuntimeBpLibrary::GetByteArg(Values)[0]);
		...
		case EVariableTypes::IntPoint: return URuntimeBpLibrary::GetIntPointArg(Values)[0].ToString();
		default: return "";
	}
  • Add a case to the switch in the PinValueToJson function, only for saveable variables.
	switch (NodePin.VariableType)
	{
		case EVariableTypes::Bool: PINVALUE_TO_JSON_CASE(FSaveableBoolArray)
		...
		case EVariableTypes::MaterialInterface: PINVALUE_TO_JSON_CASE(FSaveableIntPointArray)
		default: return "";
	}
Blueprints

Will be added soon.

⚠️ **GitHub.com Fallback** ⚠️