参考链接
参考链接
参考链接
.h
#pragma region 泛型蓝图函数
/// <summary>
/// 字符串转泛型
/// </summary>
UFUNCTION(
BlueprintPure,
CustomThunk,
meta = (CompactNodeTitle = "->", CustomStructureParam = "Value"),
Category = "Vince|Variadic")
static void FstringToGeneric(const FString stringInfo, int32& Value);
DECLARE_FUNCTION(execFstringToGeneric)
{
//读取叫做DataInfo的Fstring。虚拟机要添加对应类。
P_GET_STRUCT_REF(FString, stringInfo);
//告诉虚拟机我们需要读取第一个函数的参数。NULL = 不需要它来分配内存
Stack.StepCompiledIn<FProperty>(NULL);
//指向真实的内存地址
void* SrcPropertyAddr = Stack.MostRecentPropertyAddress;
//这个值怎么被赋值和导出
FProperty* SrcProperty = CastFieldChecked<FProperty>(Stack.MostRecentProperty);
P_FINISH;
P_NATIVE_BEGIN;
SrcProperty->ImportText_Direct(*stringInfo, SrcPropertyAddr, 0, 0);
P_NATIVE_END;
}
/// <summary>
/// 泛型类获取数据
/// </summary>
UFUNCTION(BlueprintPure,
CustomThunk,
meta = (CoCompactNodeTitle = "Variadic", CustomStructureParam = "Target,Item", BlueprintThreadSafe), Category = "Vince|Variadic")
static void ThunkGetData(const int32& Target, int32& Item);
DECLARE_FUNCTION(execThunkGetData)
{
Stack.MostRecentProperty = nullptr;
Stack.StepCompiledIn<FArrayProperty>(NULL);
void* TargetAddr = Stack.MostRecentPropertyAddress;
FProperty* TargetProperty = CastField<FProperty>(Stack.MostRecentProperty);
if (!TargetProperty)
{
Stack.bArrayContextFailed = true;
return;
}
const FProperty* InnerProp = TargetProperty;
const int32 PropertySize = InnerProp->ElementSize * InnerProp->ArrayDim;
void* StorageSpace = FMemory_Alloca(PropertySize);
InnerProp->InitializeValue(StorageSpace);
Stack.MostRecentPropertyAddress = nullptr;
Stack.MostRecentPropertyContainer = nullptr;
Stack.StepCompiledIn<FProperty>(StorageSpace);
const FFieldClass* InnerPropClass = InnerProp->GetClass();
const FFieldClass* MostRecentPropClass = Stack.MostRecentProperty->GetClass();
void* ItemPtr;
// If the destination and the inner type are identical in size and their field classes derive from one another, then permit the writing out of the array element to the destination memory
if (Stack.MostRecentPropertyAddress != NULL && (PropertySize == Stack.MostRecentProperty->ElementSize * Stack.MostRecentProperty->ArrayDim) &&
(MostRecentPropClass->IsChildOf(InnerPropClass) || InnerPropClass->IsChildOf(MostRecentPropClass)))
{
ItemPtr = Stack.MostRecentPropertyAddress;
}
else
{
ItemPtr = StorageSpace;
}
P_FINISH;
P_NATIVE_BEGIN;
Generic_Get(TargetAddr, TargetProperty, ItemPtr);
P_NATIVE_END;
InnerProp->DestroyValue(StorageSpace);
}
static void Generic_Get(void* TargetArray, const FProperty* Prop, void* Item);
.cpp
void UVariadicBlueprintFunctionLibrary::Generic_Get(void* TargetArray, const FProperty* Prop, void* Item)
{
if (TargetArray)
{
Prop->CopyCompleteValueFromScriptVM(Item, TargetArray);
}
}
///Set通配符
///声明泛型Set参数时, SetParam说明符列表的泛型参数之间用”|”分隔符进行关联
///
/// 获取泛型Set Variable
/// Stack.MostRecentProperty = nullptr;
/// Stack.StepCompiledIn<USetProperty>(NULL);
/// void* SetAddr = Stack.MostRecentPropertyAddress;
/// USetProperty* SetProperty = Cast<USetProperty>(Stack.MostRecentProperty);
///
///TMap
///
/// 获取泛型Map Variable
/// Stack.MostRecentProperty = nullptr;
/// Stack.StepCompiledIn<UMapProperty>(NULL);
/// void* SrcMapAddr = Stack.MostRecentPropertyAddress;
/// UMapProperty* SrcMapProperty = Cast<UMapProperty>(Stack.MostRecentProperty);
///
///数组
//常用const TArray& ArrayName表示一个输入类型的泛型Array参数,TArray& ArrayName表示一个输出
类型的泛型Array参数。
// ArrayParm说明符标识多个泛型参数变量时,变量之间需以英文逗号”,”分隔,不得包含其他字符。
// ArrayTypeDependentParams说明符标识的多个泛型Array参数的类型相互依赖,在蓝图图表中被调用时
只有确定其中之一,余下泛型Array参数随之变化
///
/// 获取泛型Array Variable:
/// Stack.StepCompiledIn<UArrayProperty>(NULL);
/// void* SrcArrayAddr = Stack.MostRecentPropertyAddress;
/// UArrayProperty* SrcArrayProperty = Cast<UArrayProperty>(Stack.MostRecentProperty);
///
/// *** 泛型 https://blog.csdn.net/weixin_56946623/article/details/123982505 ***
///
/// (1) DECLARE_FUNCTION(execFunctionName) {},FucntionName为函数声明时的函数名称。在花括号{}内部包含的代码:
/// P_FINISH宏之前为获取函数参数的代码块、P_NATIVE_BEGIN和P_NATIVE_END宏包裹着真正执行该函数功能的被调用函数,若是泛型蓝图节点,
/// 此处调用该函数的泛型版本(泛型函数)。若函数无返回值,可以直接调用泛型函数;若存在返回值,则应当在"="左侧定义适当的返回值类型。
/// 如果函数具有返回值的话,用这个 *(Type*)RESULT_PARAM ,引擎版本5.0
///
/// DECLARE_FUNCTION(execFunctionName)
//{
// Get Parameters
// P_FINISH;
// P_NATIVE_BEGIN;
// *(FString*)Result = Generic_FunctionName(); // Call generic function
// P_NATIVE_END;
// }
///
/// (2) 当在Thunk函数体中获取多个参数时,获取的先后次序应与函数声明时变量在参数列表中出现的次序保持一致,否则在函数被调用时将引发程序崩溃。
///
/// (3) 在Thunk函数体中,泛型蓝图函数的参数列表中确定类型的参数(如bool / uint8 / int32 / float / FName / FString等)和泛型参数(wilcard SingleVariable / TArray / TMap / TSet)获取方式不同
///
/// (4) 4.25之后UProperty改成了FProperty
///P_FINISH代表参数获取完成,因此前方为获取参数,P_NATIVE_BEGIN为激活函数开始,P_NATIVE_BEGIN为激活函数结束。
/// 要自定义一个泛型函数,需要UFUNCTION添加CustomThunk,并声明泛型变量,DECLARE_FUNCTION中获取对应泛型数据,并调用自身真正的函数
///
/// 获取泛型参数需要同时获取该变量地址void*和变量属性UProperty*/ UArrayProperty* / UMapProperty* / USetProperty*
///
/// 获取泛型Single Variable
/// Stack.StepCompiledIn<UStructProperty>(NULL);
/// void* SrcPropertyAddr = Stack.MostRecentPropertyAddress;
/// UProperty* SrcProperty = Cast<UProperty>(Stack.MostRecentProperty);
///
///