#include "dl_lua_register.h" #include "dl_io.h" #include "render/dl_graphics.h" #include "system/dl_system.h" #include "script/dl_lua.h" #include "ui/dl_ui_manager.h" #include "render/dl_image.h" #include "memory/dl_crypto.h" #include "memory/dl_memory.h" #include "tool/dl_tool_archiver.h" namespace luabridge { using namespace dl; // GC类 template struct ContainerTraits> { using Type = T; static GC construct(T* c) { return c; } static T* get(const GC& c) { return (T*)c.GetPointer(); } }; // 枚举类绑定 template <> struct Stack : luabridge::Enum { }; template <> struct Stack : luabridge::Enum { }; } // namespace luabridge // Buffer类转换 namespace luabridge { using namespace dl; template <> struct StackConversion { static constexpr bool enabled = true; }; template <> struct StackConverter { static BufferView convert(const Buffer& v) { return CreateBufferView(v); } }; template struct StackConverter> { static BufferView convert(const std::array& v) { return CreateBufferView(v); } }; } // namespace luabridge namespace dl { void lua_print(luabridge::LuaRef ref) { Output(fmt::format("[lua-print]: {}\n", ref.tostring())); } void lua_print_ex(luabridge::LuaRef ref) { Output(fmt::format("[lua-print]: {}\n", ref.tostring())); } void lua_delete(Image* img) { delete img; } std::string lua_to_string(const luabridge::LuaRef& ref) { if (ref.isBool()) return dl::to_string(ref.cast().valueOr(false)); if (ref.isLightUserdata()) return dl::to_string(ref.cast().valueOr(0)); if (ref.isNumber()) return dl::to_string(ref.cast().valueOr(0)); if (ref.isString()) return ref.cast ().valueOr(""); // if (ref.isTable()) { luabridge::Range range = luabridge::pairs(ref); std::string ret; for (auto iter : range) { if (iter.first.isNumber()) { size_t index = iter.first.cast().valueOr(-1); ret += std::to_string(index); ret += "->"; ret += lua_to_string(iter.second); ret += ", "; } else if (iter.first.isString()) { std::string key = iter.first.tostring(); ret += String::AddQuotes(key); ret += "->"; ret += lua_to_string(iter.second); ret += ", "; } } return ret; } if (ref.getClassName() == "Buffer") { auto result = ref.cast(); if (!result) { log_warn("类型转换失败:", result.message()); return "cast error"; } return dl::to_string_hex(result.value()); } log_warn("未处理lua类型:{}, {}", ref.type(), ref.tostring()); return {}; } template Array lua_Array_op_add(const Array& a, const Array& b) { return a + b; } template Array lua_Array_op_sub(const Array& a, const Array& b) { return a - b; } template Array lua_Array_op_nag(const Array& a) { return -a; } void lua_register_base(lua_State* L) { luabridge::getGlobalNamespace(L) .addFunction("print", lua_print) .addFunction("print_ex", lua_print_ex) .addFunction("delete", lua_delete) .addFunction("to_string", lua_to_string) .addFunction("to_string_hex", +[](BufferView buf) { return to_string_hex(buf); }, +[](BufferView buf, bool upper) { return to_string_hex(buf, upper); }, +[](BufferView buf, bool upper, bool add_tag) { return to_string_hex(buf, upper, add_tag); } ); luabridge::getGlobalNamespace(L) .beginClass("Position") .addConstructor() .addPropertyReadWrite("x", &Position::x) .addPropertyReadWrite("y", &Position::y); luabridge::getGlobalNamespace(L) .beginClass("Position4") .addConstructor() .addPropertyReadWrite("x", &Position4::x) .addPropertyReadWrite("y", &Position4::y) .addPropertyReadWrite("z", &Position4::z) .addPropertyReadWrite("w", &Position4::w); luabridge::getGlobalNamespace(L) .beginClass("Point") .addConstructor() .addFunction("__add", lua_Array_op_add) .addFunction("__sub", lua_Array_op_sub) .addFunction("__unm", lua_Array_op_nag) .addPropertyReadWrite("x", &Point::x) .addPropertyReadWrite("y", &Point::y); luabridge::getGlobalNamespace(L) .beginClass("Size") .addConstructor() .addPropertyReadWrite("w", &Size::w) .addPropertyReadWrite("h", &Size::h); luabridge::getGlobalNamespace(L) .beginClass("PointU") .addConstructor() .addPropertyReadWrite("x", &PointU::x) .addPropertyReadWrite("y", &PointU::y); luabridge::getGlobalNamespace(L) .beginClass("RectU") .addConstructor() .addPropertyReadWrite("lt", &RectU::lt) .addPropertyReadWrite("rt", &RectU::rt) .addPropertyReadWrite("rb", &RectU::rb) .addPropertyReadWrite("lb", &RectU::lb); luabridge::getGlobalNamespace(L) .beginNamespace("Align") .addFunction("GetSize", Align::GetSize) .addFunction("GetLT", Align::GetLT) .endNamespace(); luabridge::getGlobalNamespace(L) .addFunction("toPoint", toPoint); luabridge::getGlobalNamespace(L) .beginNamespace("String") .addFunction("ErasePath", String::ErasePath) .addFunction("GetFileStem", String::GetFileStem) .addFunction("toPosition2", String::toPosition2) .addFunction("toPoint2", String::toPoint2) .addFunction("ReplaceExtension", luabridge::overload(String::ReplaceExtension)) .addFunction("EraseFilename", luabridge::overload(String::EraseFilename)) .endNamespace(); } void lua_register_system(lua_State* L) { #ifndef DL_DISABLE_RENDER luabridge::getGlobalNamespace(L) .beginClass("ParamWindow") .addConstructor() // 忽略这个构造会出错…… .addProperty("title", &ParamWindow::_strTitle, &ParamWindow::_strTitle) .endClass(); luabridge::getGlobalNamespace(L) .beginClass("System") .addFunction("SetFuncInit", &System::lua_SetFuncInit) .addFunction("SetFuncRun", &System::lua_SetFuncRun) .addFunction("Start", (void(System::*)(const ParamWindow&))&System::Start) .endClass(); auto result = luabridge::push(L, g_system); lua_setglobal(L, "g_system"); #endif } void lua_register_file(lua_State* L) { using namespace File::Lua; luabridge::getGlobalNamespace(L) .beginNamespace("File") .beginNamespace("CopyMode") .addVariable("NONE", File::CopyMode::NONE) .addVariable("OVERRIDE", File::CopyMode::OVERRIDE) .addVariable("SKIP",File::CopyMode::SKIP) .endNamespace() .endNamespace(); luabridge::getGlobalNamespace(L) .beginNamespace("File") .addFunction("GetPathFileAll", lua_GetPathFileAll_3, lua_GetPathFileAll_2, lua_GetPathFileAll_1) .addFunction("GetAbsolute", File::GetAbsolute) .addFunction("GetRelative", File::GetRelative) .addFunction("CreateFolder", File::CreateFolder) .addFunction("DeleteContent", File::DeleteContent) .addFunction("Rename", File::Rename) .addFunction("Copy", File::Copy) .addFunction("GetBuffer", luabridge::overload(File::GetBuffer), luabridge::overload(File::GetBuffer)) .addFunction("GetString", File::GetString) .addFunction("GetFilePath", File::GetFilePath) .addFunction("GetFileName", File::GetFileName) .addFunction("GetString", File::GetString) .addFunction("IsExist", File::IsExist) .addFunction("SaveBuffer", File::SaveBuffer) .addFunction("SaveString", luabridge::overload(File::SaveString)) .endNamespace(); } void lua_register_gfx(lua_State* L) { #ifndef DL_DISABLE_RENDER luabridge::getGlobalNamespace(L) .beginClass("Graphics") .addFunction("Rectangle2D", &Graphics::Rectangle2D) .endClass(); auto result = luabridge::push(L, g_gfx); lua_setglobal(L, "g_gfx"); #endif } void lua_register_ui(lua_State* L) { #ifndef DL_DISABLE_RENDER using namespace UI; luabridge::getGlobalNamespace(L) .beginClass("UIPanel") .addFunction("Add", (void(Panel::*)(UI::Text*))&Panel::Add) .endClass(); luabridge::getGlobalNamespace(L) .beginClass("UIText") .addFunction("SetString", &UI::Text::SetString) .addFunction("SetLang", &UI::Text::SetLang) .endClass(); luabridge::getGlobalNamespace(L) .beginClass("UIManager") .addFunction("CreatePanel", (Panel * (Manager::*)())&Manager::lua_CreatePanel) .addFunction("CreateText", &Manager::CreateText) .addFunction("CreateTextDefault", &Manager::CreateTextDefault) .endClass(); auto result = luabridge::push(L, g_ui); lua_setglobal(L, "g_ui"); #endif } void lua_register_factory(lua_State* L) { luabridge::getGlobalNamespace(L) .beginClass("Factory") .addFunction("CreateText", &Factory::CreateText) .addFunction("CreateTextDefault", &Factory::CreateTextDefault) .addFunction("CreateSprite", luabridge::overload(&Factory::CreateSprite), luabridge::overload(&Factory::CreateSprite)) .addFunction("SetPath", &Factory::SetPath) .addFunction("CompressMir2Res", &Factory::CompressMir2Res) .endClass(); auto result = luabridge::push(L, g_factory); lua_setglobal(L, "g_factory"); } void lua_register_sprite(lua_State* L) { luabridge::getGlobalNamespace(L) .beginClass("Sprite") .addFunction("Render", &Sprite::Render) .addFunction("SetColor", luabridge::overload(&Sprite::SetColor), luabridge::overload(&Sprite::SetColor)) .endClass(); } void lua_register_text(lua_State* L) { luabridge::getGlobalNamespace(L) .beginClass("Text") .addFunction("Render", &Text::Render) .addFunction("SetString", &Text::SetString) .endClass(); } void lua_register_memory(lua_State* L) { luabridge::getGlobalNamespace(L) .beginClass("Buffer") .addConverter() .endClass() .addFunction("CreateBufferHex", CreateBufferHex); luabridge::getGlobalNamespace(L) .beginClass("BufferView") .endClass(); luabridge::getGlobalNamespace(L) .beginNamespace("Memory") .beginNamespace("CompressMode") .addVariable("NONE", Memory::CompressMode::E_NONE) .addVariable("LZ4", Memory::CompressMode::E_LZ4) .addVariable("ZIP", Memory::CompressMode::E_ZIP) .endNamespace() .endNamespace(); using namespace dl::Crypto; luabridge::getGlobalNamespace(L) .beginNamespace("Crypto") .beginClass("Aes256Key") .addConstructor() .addProperty("_key", &Aes256Key::_key, &Aes256Key::_key) .addProperty("_iv", &Aes256Key::_iv, &Aes256Key::_iv) .addProperty("_tag", &Aes256Key::_tag, &Aes256Key::_tag) .endClass() .addFunction("GenerateKeyAes256", &GenerateKeyAes256) .addFunction("EncryptAes256", &EncryptAes256) .addFunction("DecryptAes256", &DecryptAes256) .addFunction("HashCrc32", &HashCrc32) .addFunction("HashMd5", &HashMd5) .addFunction("HashSha256", &HashSha256) .addFunction("HashSha512", &HashSha512) .endNamespace(); } luabridge::LuaRef lua_json_to_lua(lua_State* L, const json& j) { switch (j.type()) { case json::value_t::null: return luabridge::LuaRef(L, luabridge::LuaNil()); case json::value_t::object: { luabridge::LuaRef ret = luabridge::newTable(L); for (auto iter = j.begin(); iter != j.end(); ++iter) { std::string key = iter.key(); json value = iter.value(); //log_info("{}, {}", key, value.dump()); ret[key] = lua_json_to_lua(L, value); } return ret; } case json::value_t::array: { luabridge::LuaRef ret = luabridge::newTable(L); for (size_t i = 0; i < j.size(); ++i) { ret[i + 1] = lua_json_to_lua(L, j[i]); } return ret; } case json::value_t::string: return luabridge::LuaRef(L, j.get()); case json::value_t::number_integer: return luabridge::LuaRef(L, j.get()); case json::value_t::number_unsigned: return luabridge::LuaRef(L, j.get()); case json::value_t::number_float: return luabridge::LuaRef(L, j.get()); case json::value_t::binary: default: break; } log_warn("未处理json类型:{}, {}", j.type_name(), j.dump()); return luabridge::LuaRef(L, luabridge::LuaNil()); } json lua_lua_to_json(lua_State* L, const luabridge::LuaRef& ref) { if (ref.isBool()) return ref.cast().valueOr(false); if (ref.isLightUserdata()) return ref.cast().valueOr(0); if (ref.isNumber()) return ref.cast().valueOr(0); if (ref.isString()) return ref.cast ().valueOr(""); // if (ref.isTable()) { int type = 0; // 0.初始化 1.array 2.object -1.错误 luabridge::Range range = luabridge::pairs(ref); for (auto iter : range) { if (iter.first.isNumber()) { if (type == 0) type = 1; else if (type != 1) { type = -1; break; } } else if (iter.first.isString()) { if (type == 0) type = 2; else if (type != 2) { type = -1; break; } } } if (type == 0) return {}; else if (type == 1) { json j; for (auto iter : range) { size_t index = iter.first.cast().valueOr(-1); j[index - 1] = lua_lua_to_json(L, iter.second); } return j; } else if (type == 2) { json j; for (auto iter : range) { std::string key = iter.first.tostring(); j[key] = lua_lua_to_json(L, iter.second); } return j; } else return json(); } log_warn("未处理lua类型:{}, {}", ref.type(), ref.tostring()); return json(); } std::string lua_json_encode(luabridge::LuaRef ref, int indent) { json j = lua_lua_to_json(ref.state(), ref); return j.dump(indent); } luabridge::LuaRef lua_json_decode(std::string str) { json j = Json::ParseString(str); return lua_json_to_lua(g_lua->GetL(), j); } void lua_register_json(lua_State* L) { luabridge::getGlobalNamespace(L) .beginNamespace("json") .addFunction("encode", luabridge::bind_back(lua_json_encode, 4)) .addFunction("decode", lua_json_decode) .endNamespace(); } std::string_view lua_lang(std::string_view str) { return lang(str); } void lua_register_other(lua_State* L) { luabridge::getGlobalNamespace(L) .beginNamespace("ToolArchiver") .addFunction("Compress", &Tool::Archiver::Compress) .addFunction("Decompress", luabridge::overload(&Tool::Archiver::Decompress), luabridge::overload(&Tool::Archiver::Decompress)) .endNamespace(); luabridge::getGlobalNamespace(L) .beginClass("ToolArchiverParam") .addConstructor() .addProperty("_src", &Tool::Archiver::Param::_src, &Tool::Archiver::Param::_src) .addProperty("_out", &Tool::Archiver::Param::_out, &Tool::Archiver::Param::_out) .addProperty("_compressMode", &Tool::Archiver::Param::_compressMode, &Tool::Archiver::Param::_compressMode) .addProperty("_bCrc", &Tool::Archiver::Param::_bCrc, &Tool::Archiver::Param::_bCrc) .endClass(); luabridge::getGlobalNamespace(L) .beginClass("Language") .addFunction("GetTagVector", &Language::GetTagVector) .addFunction("GetTagMap", &Language::GetTagMap) .addFunction("GetTagNameVector", &Language::GetTagNameVector) .addFunction("GetTagNameMap", &Language::GetTagNameMap) .endClass(); luabridge::getGlobalNamespace(L) .addFunction("lang", lua_lang); auto result = luabridge::push(L, g_lang); lua_setglobal(L, "g_lang"); } void lua_register_image(lua_State* L) { luabridge::getGlobalNamespace(L) .beginNamespace("Img") .addVariable("REGEX_FORMAT", Img::REGEX_FORMAT) .addFunction("Create", luabridge::overload(&Img::Create), luabridge::overload(&Img::Create)) .addFunction("CreateSvg", &Img::CreateSvg) .addFunction("CreateWebp", luabridge::overload(&Img::CreateWebp), luabridge::overload(&Img::CreateWebp)) .addFunction("Save", &Img::Save) .addFunction("CalcLeastRect", &Img::CalcLeastRect) .addFunction("SetAlphaZero", luabridge::overload(&Img::SetAlphaZero), luabridge::overload(&Img::SetAlphaZero)) .addFunction("Resize", luabridge::overload(&Img::Resize), luabridge::overload(&Img::Resize)) .addFunction("AddRect", Img::AddRect) .addFunction("SetAlphaZero", luabridge::overload(Img::SetAlphaZero), luabridge::overload(Img::SetAlphaZero)) .addFunction("Save", Img::Save) .endNamespace(); luabridge::getGlobalNamespace(L) .beginClass("Image") .endClass(); luabridge::getGlobalNamespace(L) .beginNamespace("ColorDef") .addVariable("NONE", ColorDef::NONE) .addVariable("WHITE", ColorDef::WHITE) .addVariable("BLACK", ColorDef::BLACK) .addVariable("RED", ColorDef::RED) .addVariable("GREEN", ColorDef::GREEN) .addVariable("BLUE", ColorDef::BLUE) .addVariable("YELLOW", ColorDef::YELLOW) .addVariable("PURPLE", ColorDef::PURPLE) .addVariable("CYAN", ColorDef::CYAN) .addVariable("ORANGE", ColorDef::ORANGE) .addVariable("GREEN_DARK", ColorDef::GREEN_DARK) .addVariable("DISABLE", ColorDef::DISABLE) .addVariable("TEXT_BG", ColorDef::TEXT_BG) .addVariable("FACTOR_GRAY", ColorDef::FACTOR_GRAY) .addVariable("GRAY", ColorDef::GRAY) .addVariable("GRAY_LIGHT", ColorDef::GRAY_LIGHT) .addVariable("GRAY_DARK", ColorDef::GRAY_DARK) .addVariable("CLEAR_SCREEN", ColorDef::CLEAR_SCREEN) .addVariable("AXIS_X", ColorDef::AXIS_X) .addVariable("AXIS_Y", ColorDef::AXIS_Y) .addVariable("AXIS_Z", ColorDef::AXIS_Z) .endNamespace(); } #if DL_PLATFORM == DL_PLATFORM_WIN32 #define WIN32_LEAN_AND_MEAN #include #endif void lua_pause() { #if DL_PLATFORM == DL_PLATFORM_WIN32 system("pause"); #else printf("输入任意字符并按回车继续:"); char b; std::cin >> b; #endif } void lua_register_platform(lua_State* L) { luabridge::getGlobalNamespace(L) .addFunction("system", system); luabridge::getGlobalNamespace(L) .addFunction("pause", lua_pause); } void lua_register_all(lua_State* L) { lua_register_base(L); lua_register_system(L); lua_register_file(L); lua_register_gfx(L); lua_register_ui(L); lua_register_factory(L); lua_register_sprite(L); lua_register_text(L); lua_register_memory(L); lua_register_other(L); lua_register_json(L); lua_register_image(L); lua_register_platform(L); } }