| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426 |
- // Copyright (c) 2008-2022 the Urho3D project
- // License: MIT
- #include "../Precompiled.h"
- #ifndef _WIN32
- #include "../GraphicsAPI/IndexBuffer.h"
- #include "../GraphicsAPI/VertexBuffer.h"
- #endif
- #include "../IO/VectorBuffer.h"
- #include <toluapp/tolua++.h>
- #include "../LuaScript/ToluaUtils.h"
- const char* tolua_tourho3dstring(lua_State* L, int narg, const char* str)
- {
- return tolua_tostring(L, narg, str);
- }
- const char* tolua_tourho3dstring(lua_State* L, int narg, const String& str)
- {
- return tolua_tourho3dstring(L, narg, str.CString());
- }
- void SetContext(lua_State* L, Context* context)
- {
- assert(L && context);
- tolua_pushusertype(L, static_cast<void*>(context), "Context");
- lua_setglobal(L, ".context"); // This property is internal, the exposed 'context' property is obtained via GetContext() call
- }
- Context* GetContext(lua_State* L)
- {
- lua_getglobal(L, ".context");
- if (lua_isnil(L, -1))
- {
- lua_State* L1 = lua_getmainthread(L);
- return (L == L1) ? nullptr : GetContext(L1);
- }
- tolua_Error error; // Ensure we are indeed getting a Context object before casting
- return tolua_isusertype(L, -1, "Context", 0, &error) ? static_cast<Context*>(tolua_tousertype(L, -1, nullptr)) : nullptr;
- }
- // Explicit template specialization for StringVector
- template <> int ToluaIsVector<String>(lua_State* L, int lo, const char* /*type*/, int def, tolua_Error* err)
- {
- return tolua_isstringarray(L, lo, -1, def, err);
- }
- template <> void* ToluaToVector<String>(lua_State* L, int narg, void* /*def*/)
- {
- if (!lua_istable(L, narg))
- return nullptr;
- static Vector<String> result;
- result.Clear();
- result.Resize((unsigned)lua_objlen(L, narg));
- for (unsigned i = 0; i < result.Size(); ++i)
- {
- lua_rawgeti(L, narg, i + 1);
- result[i] = tolua_tourho3dstring(L, -1, "");
- lua_pop(L, 1);
- }
- return &result;
- }
- template <> int ToluaPushVector<String>(lua_State* L, void* data, const char* /*type*/)
- {
- lua_newtable(L);
- const Vector<String>& vector = *static_cast<const Vector<String>*>(data);
- for (unsigned i = 0; i < vector.Size(); ++i)
- {
- tolua_pushurho3dstring(L, vector[i]);
- lua_rawseti(L, -2, i + 1);
- }
- return 1;
- }
- // Explicit template specialization for boolean
- template <> int ToluaIsPODVector<bool>(double /*overload*/, lua_State* L, int lo, const char* /*type*/, int def, tolua_Error* err)
- {
- return tolua_isbooleanarray(L, lo, -1, def, err);
- }
- template <> void* ToluaToPODVector<bool>(double /*overload*/, lua_State* L, int narg, void* /*def*/)
- {
- if (!lua_istable(L, narg))
- return nullptr;
- static PODVector<bool> result;
- result.Clear();
- result.Resize((unsigned)lua_objlen(L, narg));
- for (unsigned i = 0; i < result.Size(); ++i)
- {
- lua_rawgeti(L, narg, i + 1);
- result[i] = (bool)tolua_toboolean(L, -1, 0);
- lua_pop(L, 1);
- }
- return &result;
- }
- template <> int ToluaPushPODVector<bool>(double /*overload*/, lua_State* L, void* data, const char* /*type*/)
- {
- lua_newtable(L);
- const PODVector<bool>& vector = *static_cast<const PODVector<bool>*>(data);
- for (unsigned i = 0; i < vector.Size(); ++i)
- {
- lua_pushboolean(L, vector[i]);
- lua_rawseti(L, -2, i + 1);
- }
- return 1;
- }
- // Explicit template specialization for Vector<SharedPtr<IndexBuffer>> and Vector<SharedPtr<VertexBuffer>>
- template <> void* ToluaToVector<SharedPtr<IndexBuffer>>(lua_State* L, int narg, void* def)
- {
- if (!lua_istable(L, narg))
- return nullptr;
- static Vector<SharedPtr<IndexBuffer>> result;
- result.Clear();
- result.Resize((unsigned)lua_objlen(L, narg));
- for (unsigned i = 0; i < result.Size(); ++i)
- {
- lua_rawgeti(L, narg, i + 1); // Lua index starts from 1
- result[i] = SharedPtr<IndexBuffer>(static_cast<IndexBuffer*>(tolua_tousertype(L, -1, def)));
- lua_pop(L, 1);
- }
- return &result;
- }
- template <> void* ToluaToVector<SharedPtr<VertexBuffer>>(lua_State* L, int narg, void* def)
- {
- if (!lua_istable(L, narg))
- return nullptr;
- static Vector<SharedPtr<VertexBuffer>> result;
- result.Clear();
- result.Resize((unsigned)lua_objlen(L, narg));
- for (unsigned i = 0; i < result.Size(); ++i)
- {
- lua_rawgeti(L, narg, i + 1); // Lua index starts from 1
- result[i] = SharedPtr<VertexBuffer>(static_cast<VertexBuffer*>(tolua_tousertype(L, -1, def)));
- lua_pop(L, 1);
- }
- return &result;
- }
- namespace Urho3D
- {
- template <> const VariantValue* Variant::Get<const VariantValue*>() const
- {
- return &value_;
- }
- }
- void ToluaToVariant(lua_State* L, int narg, void* def, Variant& variant)
- {
- switch (lua_type(L, narg)) // Use the type of lua object to determine the final variant type
- {
- case LUA_TNIL:
- variant = Variant::EMPTY;
- break;
- case LUA_TBOOLEAN:
- variant = (bool)lua_toboolean(L, narg); // Still need to cast to bool as Lua/LuaJIT return it as int
- break;
- case LUA_TNUMBER:
- {
- // Use the original variant type to further determine the final variant type
- // CAVEAT: if lhs has integral data type and double is desired then lhs needs to be reset first before assigning
- double value = lua_tonumber(L, narg);
- switch (variant.GetType())
- {
- case VAR_INT:
- variant = (int)value;
- break;
- case VAR_INT64:
- variant = (long long)value;
- break;
- case VAR_BOOL:
- variant = value != 0.0f;
- break;
- case VAR_FLOAT:
- variant = (float)value;
- break;
- default:
- variant = value;
- }
- }
- break;
- case LUA_TSTRING:
- variant = lua_tostring(L, narg);
- break;
- case LUA_TUSERDATA:
- {
- if (lua_getmetatable(L, narg))
- {
- lua_rawget(L, LUA_REGISTRYINDEX); // registry[mt]
- const char* typeName = lua_tostring(L, -1);
- lua_pop(L, 1);
- void* value = tolua_tousertype(L, narg, def);
- switch (Variant::GetTypeFromName(typeName))
- {
- case VAR_NONE:
- // Handle special cases
- if (typeName)
- {
- tolua_Error error;
- if (strcmp(typeName, "Variant") == 0)
- variant = *static_cast<Variant*>(value);
- else if (strcmp(typeName, "VectorBuffer") == 0)
- variant = *static_cast<VectorBuffer*>(value);
- else if (tolua_isusertype(L, narg, "RefCounted", 0, &error))
- variant = static_cast<RefCounted*>(value);
- else
- variant = value; // void*
- }
- break;
- case VAR_VECTOR2:
- variant = *static_cast<Vector2*>(value);
- break;
- case VAR_VECTOR3:
- variant = *static_cast<Vector3*>(value);
- break;
- case VAR_VECTOR4:
- variant = *static_cast<Vector4*>(value);
- break;
- case VAR_QUATERNION:
- variant = *static_cast<Quaternion*>(value);
- break;
- case VAR_COLOR:
- variant = *static_cast<Color*>(value);
- break;
- case VAR_INTRECT:
- variant = *static_cast<IntRect*>(value);
- break;
- case VAR_INTVECTOR2:
- variant = *static_cast<IntVector2*>(value);
- break;
- case VAR_INTVECTOR3:
- variant = *static_cast<IntVector3*>(value);
- break;
- case VAR_MATRIX3:
- variant = *static_cast<Matrix3*>(value);
- break;
- case VAR_MATRIX3X4:
- variant = *static_cast<Matrix3x4*>(value);
- break;
- case VAR_MATRIX4:
- variant = *static_cast<Matrix4*>(value);
- break;
- case VAR_RESOURCEREF:
- variant = *static_cast<ResourceRef*>(value);
- break;
- case VAR_RESOURCEREFLIST:
- variant = *static_cast<ResourceRefList*>(value);
- break;
- case VAR_VARIANTMAP:
- variant = *static_cast<VariantMap*>(value);
- break;
- default: break;
- }
- };
- }
- break;
- case LUA_TTABLE:
- {
- tolua_Error error;
- if (ToluaIsPODVector<unsigned char>(0.f, L, narg, "unsigned char", 0, &error))
- variant = *static_cast<PODVector<unsigned char>*>(ToluaToPODVector<unsigned char>(0.f, L, narg, def));
- else if (ToluaIsVector<Variant>(L, narg, "Variant", 0, &error))
- variant = *static_cast<VariantVector*>(ToluaToVector<Variant>(L, narg, def));
- else if (ToluaIsVector<String>(L, narg, "String", 0, &error))
- variant = *static_cast<StringVector*>(ToluaToVector<String>(L, narg, def));
- }
- break;
- default: break;
- }
- }
- void ToluaPushVariant(lua_State* L, const Variant* variant, const char* type)
- {
- String typeName(type);
- switch (variant->GetType())
- {
- case VAR_INT:
- if (typeName == "unsigned" || typeName == "unsigned int" || typeName == "UInt" || typeName == "uint")
- tolua_pushnumber(L, (lua_Number)variant->GetUInt());
- else if (typeName == "StringHash")
- {
- // Make a new local copy
- tolua_pushusertype(L, Mtolua_new(StringHash(variant->GetStringHash())), "StringHash");
- tolua_register_gc(L, lua_gettop(L));
- }
- else
- tolua_pushnumber(L, (lua_Number)variant->GetInt());
- break;
- case VAR_INT64:
- if (typeName == "unsigned" || typeName == "unsigned int" || typeName == "UInt" || typeName == "uint")
- tolua_pushnumber(L, (lua_Number)variant->GetUInt64());
- else
- tolua_pushnumber(L, (lua_Number)variant->GetInt64());
- break;
- case VAR_BOOL:
- tolua_pushboolean(L, (int)variant->GetBool());
- break;
- case VAR_FLOAT:
- tolua_pushnumber(L, (lua_Number)variant->GetFloat());
- break;
- case VAR_DOUBLE:
- tolua_pushnumber(L, (lua_Number)variant->GetDouble());
- break;
- case VAR_VECTOR2:
- case VAR_VECTOR3:
- case VAR_VECTOR4:
- case VAR_QUATERNION:
- case VAR_COLOR:
- case VAR_RESOURCEREF:
- case VAR_RESOURCEREFLIST:
- case VAR_VARIANTMAP:
- case VAR_INTRECT:
- case VAR_INTVECTOR2:
- case VAR_INTVECTOR3:
- tolua_pushusertype(L, (void*)variant->Get<const VariantValue*>(), variant->GetTypeName().CString());
- break;
- case VAR_STRING:
- tolua_pushurho3dstring(L, variant->GetString());
- break;
- case VAR_BUFFER:
- if (typeName == "VectorBuffer")
- {
- tolua_pushusertype(L, Mtolua_new(VectorBuffer(variant->GetVectorBuffer())), "VectorBuffer");
- tolua_register_gc(L, lua_gettop(L));
- }
- else
- ToluaPushPODVector<unsigned char>(0.f, L, (void*)&variant->GetBuffer(), "unsigned char");
- break;
- case VAR_VOIDPTR:
- ToluaPushRegisteredUserType(L, static_cast<void*>(variant->GetVoidPtr()), type);
- break;
- case VAR_PTR:
- ToluaPushRegisteredUserType(L, static_cast<void*>(variant->GetPtr()), type);
- break;
- case VAR_VARIANTVECTOR:
- ToluaPushVector<Variant>(L, (void*)&variant->GetVariantVector(), "Variant");
- break;
- case VAR_STRINGVECTOR:
- ToluaPushVector<String>(L, (void*)&variant->GetStringVector(), "String");
- break;
- case VAR_MATRIX3:
- tolua_pushusertype(L, variant->Get<const VariantValue*>()->matrix3_, "Matrix3");
- break;
- case VAR_MATRIX3X4:
- tolua_pushusertype(L, variant->Get<const VariantValue*>()->matrix3x4_, "Matrix3x4");
- break;
- case VAR_MATRIX4:
- tolua_pushusertype(L, variant->Get<const VariantValue*>()->matrix4_, "Matrix4");
- break;
- default:
- lua_pushnil(L);
- break;
- }
- }
- void ToluaPushRegisteredUserType(lua_State* L, void* data, const char* type)
- {
- if (type)
- {
- luaL_getmetatable(L, type);
- if (!lua_isnil(L, -1))
- {
- lua_pop(L, 1);
- tolua_pushusertype(L, data, type);
- }
- }
- else
- lua_pushnil(L);
- }
- void ToluaPushObject(lua_State* L, void* data, const char* type)
- {
- tolua_pushusertype(L, data, data ? static_cast<Object*>(data)->GetTypeName().CString() : type);
- }
|