Adding a variable type - HiIAmMoot/RuntimeBPs GitHub Wiki
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.
- 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;
- 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)
};
- 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
- 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>();
- 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);
- 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)
}
- 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);
}
- 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 "";
}
Will be added soon.