运行时创建UField[贰]

上一回实现了运行时创建枚举,这次再试试结构体,虚幻中的反射结构体是UScriptStruct的实例.同样,蓝图新建的结构体是UUserDefinedStruct的实例.
结构体由多个字段构成,虚幻中称为属性,即FProperty,FProperty描述了一个变量在一段内存的位置和大小,结构体通过链表来保存各个字段.
要创建一个结构体,需要创建一个继承自UScriptStruct的类ULuaGeneratedStruct,然后根据所需要的字段及其类型创建FProperty,
这里并不需要手动去操作PropertyLink这个链表成员,只需要新建Fproperty,结束后调用StaticLink即可完成链表关联.
简要实现如下:

// Fill out your copyright notice in the Description page of Project Settings.


#include "LuaGeneratedStruct.h"


ULuaGeneratedStruct* ULuaGeneratedStruct::GenerateStruct(const FString& InStructName, const TMap<FString, int32>& InVariables)
{
	ULuaGeneratedStruct* NewStruct = FindObject<ULuaGeneratedStruct>(ANY_PACKAGE, *InStructName);
	if (!NewStruct)
	{
		NewStruct = NewObject<ULuaGeneratedStruct>(GetTransientPackage(), *InStructName, RF_Public | RF_Standalone | RF_Transient);
		NewStruct->SetMetaData(TEXT("BlueprintType"), TEXT("true"));
		NewStruct->Bind();
		NewStruct->StaticLink(true);
		NewStruct->AddToRoot();
	}
	else
	{
		return NewStruct;
	}

	int32 PropCount = 0;
	int32 PropOffset = 0;
	EObjectFlags ObjectFlags = EObjectFlags::RF_Standalone;
	EPropertyFlags PropertyFlags = EPropertyFlags::CPF_None;
	bool bIsPOD = true;
	for (const TPair<FString, int32>& It : InVariables)
	{
		FProperty* NewProp = nullptr;
		UE4CodeGen_Private::EPropertyGenFlags PropertyType = (UE4CodeGen_Private::EPropertyGenFlags)(It.Value);
		switch (PropertyType)
		{
		case UE4CodeGen_Private::EPropertyGenFlags::Int8:
			NewProp = new FInt8Property(NewStruct, FName(*It.Key), ObjectFlags, PropOffset, PropertyFlags);
			NewProp->SetPropertyFlags(EPropertyFlags::CPF_IsPlainOldData);
			break;

		case UE4CodeGen_Private::EPropertyGenFlags::Byte:
			NewProp = new FByteProperty(NewStruct, FName(*It.Key), ObjectFlags, PropOffset, PropertyFlags, nullptr);
			NewProp->SetPropertyFlags(EPropertyFlags::CPF_IsPlainOldData);
			break;

		case UE4CodeGen_Private::EPropertyGenFlags::Int16:
			NewProp = new FInt16Property(NewStruct, FName(*It.Key), ObjectFlags, PropOffset, PropertyFlags);
			NewProp->SetPropertyFlags(EPropertyFlags::CPF_IsPlainOldData);
			break;

		case UE4CodeGen_Private::EPropertyGenFlags::UInt16:
			NewProp = new FUInt16Property(NewStruct, FName(*It.Key), ObjectFlags, PropOffset, PropertyFlags);
			NewProp->SetPropertyFlags(EPropertyFlags::CPF_IsPlainOldData);
			break;

		case UE4CodeGen_Private::EPropertyGenFlags::Int:
			NewProp = new FIntProperty(NewStruct, FName(*It.Key), ObjectFlags, PropOffset, PropertyFlags);
			NewProp->SetPropertyFlags(EPropertyFlags::CPF_IsPlainOldData);
			break;

		case UE4CodeGen_Private::EPropertyGenFlags::UInt32:
			NewProp = new FUInt32Property(NewStruct, FName(*It.Key), ObjectFlags, PropOffset, PropertyFlags);
			NewProp->SetPropertyFlags(EPropertyFlags::CPF_IsPlainOldData);
			break;

		case UE4CodeGen_Private::EPropertyGenFlags::Int64:
			NewProp = new FInt64Property(NewStruct, FName(*It.Key), ObjectFlags, PropOffset, PropertyFlags);
			NewProp->SetPropertyFlags(EPropertyFlags::CPF_IsPlainOldData);
			break;

		case UE4CodeGen_Private::EPropertyGenFlags::UInt64:
			NewProp = new FUInt64Property(NewStruct, FName(*It.Key), ObjectFlags, PropOffset, PropertyFlags);
			NewProp->SetPropertyFlags(EPropertyFlags::CPF_IsPlainOldData);
			break;

		case UE4CodeGen_Private::EPropertyGenFlags::Float:
			NewProp = new FFloatProperty(NewStruct, FName(*It.Key), ObjectFlags, PropOffset, PropertyFlags);
			NewProp->SetPropertyFlags(EPropertyFlags::CPF_IsPlainOldData);
			break;

		case UE4CodeGen_Private::EPropertyGenFlags::Str:
			NewProp = new FStrProperty(NewStruct, FName(*It.Key), ObjectFlags, PropOffset, PropertyFlags);
			bIsPOD = false;
			break;

		case UE4CodeGen_Private::EPropertyGenFlags::Array:
			NewProp = new FArrayProperty(NewStruct, FName(*It.Key), ObjectFlags, PropOffset, PropertyFlags, EArrayPropertyFlags::None);
			bIsPOD = false;
			break;

		case UE4CodeGen_Private::EPropertyGenFlags::Map:
			NewProp = new FMapProperty(NewStruct, FName(*It.Key), ObjectFlags, PropOffset, PropertyFlags, EMapPropertyFlags::None);
			bIsPOD = false;
			break;
		}
		++PropCount;
		PropOffset += NewProp->GetSize();
	}

	if(bIsPOD)
	{
		NewStruct->StructFlags = (EStructFlags)(NewStruct->StructFlags | EStructFlags::STRUCT_IsPlainOldData);
	}
	NewStruct->Bind();
	NewStruct->StaticLink(true);
	return NewStruct;
}

LUA中新建结构体如下:

--结构体名字,描述成员名字和类型
local TmpStructName = 'XQStruct'
	local TmpVatList =
	{
		['MyID'] = UnrealPropertyType.EPropertyGenFlags.Int,
		['MyName'] = UnrealPropertyType.EPropertyGenFlags.Str
	}

	local NewStruct = LuaGeneratedStruct:GenerateStruct(TmpStructName, TmpVatList)
        --用LUA表填充结构体实例
	local XQVal = 
	{
		['MyID'] = 111,
		['MyName'] = 'efrewfr34'
	}
	local MyT = Unreal.LuaNewStruct('XQStruct', XQVal)
	print(MyT.MyID, MyT.MyName)

--虚幻中属性类型对应的枚举值如下,取自UE4CodeGen_Private::EPropertyGenFlags
LuaGeneratedEnum = LuaGeneratedEnum or Unreal.LuaGetUnrealCDO('LuaGeneratedEnum')

LuaGeneratedStruct = LuaGeneratedStruct or Unreal.LuaGetUnrealCDO('LuaGeneratedStruct')

UnrealProperty = UnrealProperty or {}

UnrealProperty.EPropertyGenFlags =
{
	None              = 0x00,
	Byte              = 0x00,
	Int8              = 0x01,
	Int16             = 0x02,
	Int               = 0x03,
	Int64             = 0x04,
	UInt16            = 0x05,
	UInt32            = 0x06,
	UInt64            = 0x07,
	UnsizedInt        = 0x08,
	UnsizedUInt       = 0x09,
	Float             = 0x0A,
	Double            = 0x0B,
	Bool              = 0x0C,
	SoftClass         = 0x0D,
	WeakObject        = 0x0E,
	LazyObject        = 0x0F,
	SoftObject        = 0x10,
	Class             = 0x11,
	Object            = 0x12,
	Interface         = 0x13,
	Name              = 0x14,
	Str               = 0x15,
	Array             = 0x16,
	Map               = 0x17,
	Set               = 0x18,
	Struct            = 0x19,
	Delegate          = 0x1A,
	InlineMulticastDelegate = 0x1B,
	SparseMulticastDelegate = 0x1C,
	Text              = 0x1D,
	Enum              = 0x1E,
	FieldPath         = 0x1F,

	NativeBool        = 0x20
}


return UnrealProperty
原文地址:https://www.cnblogs.com/rpg3d/p/12601602.html