From 4c0d14609c2c3a3e33d1f6c807dc7651ba5e0016 Mon Sep 17 00:00:00 2001 From: raylanhong Date: Wed, 26 Aug 2020 10:10:45 +0800 Subject: [PATCH] Support use lua table for Incoming ustruct/array/map type parameter. --- .../Source/slua_unreal/Private/LuaObject.cpp | 95 +++++++++++++++++++ 1 file changed, 95 insertions(+) diff --git a/Plugins/slua_unreal/Source/slua_unreal/Private/LuaObject.cpp b/Plugins/slua_unreal/Source/slua_unreal/Private/LuaObject.cpp index 02c8a426..af201259 100644 --- a/Plugins/slua_unreal/Source/slua_unreal/Private/LuaObject.cpp +++ b/Plugins/slua_unreal/Source/slua_unreal/Private/LuaObject.cpp @@ -993,6 +993,30 @@ namespace NS_SLUA { int checkUArrayProperty(lua_State* L,UProperty* prop,uint8* parms,int i) { auto p = Cast(prop); ensure(p); + if (lua_istable(L, i)) { + int arraySize = lua_rawlen(L, i); + if (arraySize <= 0) + return 0; + int tableIndex = i; + if (i < 0 && i > LUA_REGISTRYINDEX) { + tableIndex = i - 1; + } + + FScriptArrayHelper arrayHelper(p, parms); + arrayHelper.AddValues(arraySize); + + auto checker = LuaObject::getChecker(p->Inner); + + int index = 0; + + lua_pushnil(L); + while (index < arraySize && lua_next(L, tableIndex) != 0) { + checker(L, p->Inner, arrayHelper.GetRawPtr(index++), -1); + lua_pop(L, 1); + } + return 0; + } + CheckUD(LuaArray,L,i); LuaArray::clone((FScriptArray*)parms,p->Inner,UD->get()); return 0; @@ -1001,6 +1025,31 @@ namespace NS_SLUA { int checkUMapProperty(lua_State* L, UProperty* prop, uint8* parms, int i) { auto p = Cast(prop); ensure(p); + + if (lua_istable(L, i)) { + int tableIndex = i; + if (i < 0 && i > LUA_REGISTRYINDEX) { + tableIndex = i - 1; + } + + FScriptMapHelper mapHelper(p, parms); + + lua_pushnil(L); + while (lua_next(L, tableIndex) != 0) { + FDefaultConstructedPropertyElement tempKey(p->KeyProp); + FDefaultConstructedPropertyElement tempValue(p->ValueProp); + auto keyPtr = tempKey.GetObjAddress(); + auto valuePtr = tempValue.GetObjAddress(); + auto keyChecker = LuaObject::getChecker(p->KeyProp); + auto valueChecker = LuaObject::getChecker(p->ValueProp); + keyChecker(L, p->KeyProp, (uint8*)keyPtr, -2); + valueChecker(L, p->ValueProp, (uint8*)valuePtr, -1); + mapHelper.AddPair(keyPtr, valuePtr); + lua_pop(L, 1); + } + return 0; + } + CheckUD(LuaMap, L, i); LuaMap::clone((FScriptMap*)parms,p->KeyProp,p->ValueProp,UD->get()); return 0; @@ -1122,9 +1171,55 @@ namespace NS_SLUA { return 0; } + FString getPropertyFriendlyName(UProperty* prop, bool isNative) { + if (isNative) { + return prop->GetName(); + } + + FString fieldName = prop->GetName(); + + int index = fieldName.Len(); + for (int i = 0; i < 2; ++i) { + int findIndex = fieldName.Find(TEXT("_"), ESearchCase::CaseSensitive, ESearchDir::FromEnd, index); + if (findIndex != INDEX_NONE) { + index = findIndex; + } + } + + return fieldName.Left(index); + } + + bool fillUStructWithTable(lua_State* L, UStructProperty* prop, uint8* params, int i) { + check(lua_istable(L, i)); + + auto* uss = prop->Struct; + bool isNative = uss->IsNative(); + + for (TFieldIterator it(uss); it; ++it) { + AutoStack as(L); + FString fieldName = getPropertyFriendlyName(*it, isNative); + if (lua_getfield(L, i, TCHAR_TO_UTF8(*fieldName)) == LUA_TNIL) { + continue; + } + + auto checker = LuaObject::getChecker(*it); + if (checker) { + checker(L, *it, it->ContainerPtrToValuePtr(params), -1); + } + } + + return true; + } + int checkUStructProperty(lua_State* L,UProperty* prop,uint8* parms,int i) { auto p = Cast(prop); ensure(p); + + if (lua_istable(L, i)) { + fillUStructWithTable(L, p, parms, i); + return 0; + } + auto uss = p->Struct; // if it's LuaBPVar