#include #define GLFW_INCLUDE_NONE #include extern "C" { #include #include } #include #include #ifdef _WIN32 #define WINDOWS_LEAN_AND_MEAN #include #define CHANGE_WORKING_DIRECTORY(path) !(SetCurrentDirectory(path)) #else #include #define CHANGE_WORKING_DIRECTORY(path) chdir(path) #endif namespace { int lglerminal_quit(lua_State* L) { glerminal_quit(); return 0; } int lglerminal_flush(lua_State* L) { glerminal_flush(); return 0; } int lglerminal_set(lua_State* L) { const int x = luaL_checkinteger(L, 1); const int y = luaL_checkinteger(L, 2); const int layer = luaL_checkinteger(L, 3) - 1; const unsigned short sprite = luaL_checkinteger(L, 4) - 1; glerminal_set(x, y, layer, sprite); return 0; } int lglerminal_get(lua_State* L) { const int x = luaL_checkinteger(L, 1); const int y = luaL_checkinteger(L, 2); const int layer = luaL_checkinteger(L, 3) - 1; lua_pushnumber(L, glerminal_get(x, y, layer) + 1); return 1; } int lglerminal_offset(lua_State* L) { const int x = luaL_checkinteger(L, 1); const int y = luaL_checkinteger(L, 2); const int layer = luaL_checkinteger(L, 3) - 1; const float ox = luaL_checknumber(L, 4); const float oy = luaL_checknumber(L, 5); glerminal_offset(x, y, layer, ox, oy); return 0; } int lglerminal_layer_color(lua_State* L) { const int x = luaL_checkinteger(L, 1); const int y = luaL_checkinteger(L, 2); const int layer = luaL_checkinteger(L, 3) - 1; const float r = luaL_checknumber(L, 4); const float g = luaL_checknumber(L, 5); const float b = luaL_checknumber(L, 6); const float a = luaL_optnumber(L, 7, 1.0f); int ri = 255 * r; int gi = 255 * g; int bi = 255 * b; int ai = 255 * a; if (ri > 255) { ri = 255; } if (ri < 0) { ri = 0; } if (gi > 255) { gi = 255; } if (gi < 0) { gi = 0; } if (bi > 255) { bi = 255; } if (bi < 0) { bi = 0; } if (ai > 255) { ai = 255; } if (ai < 0) { ai = 0; } const unsigned int color = ri | (gi << 8) | (bi << 16) | (ai << 24); glerminal_color(x, y, layer, color); return 0; } int lglerminal_layer_scale(lua_State* L) { const int x = luaL_checkinteger(L, 1); const int y = luaL_checkinteger(L, 2); const int layer = luaL_checkinteger(L, 3) - 1; const float scale = luaL_checknumber(L, 4); glerminal_scale(x, y, layer, scale); return 0; } int lglerminal_load_sprites_file(lua_State* L) { const char* path = luaL_checkstring(L, 1); lua_pushboolean(L, glerminal_load_sprites_file(path)); return 1; } int lglerminal_play_sound(lua_State* L) { const char* name = luaL_checkstring(L, 1); glerminal_sound(name); return 0; } const luaL_Reg lglerminal_methods[] = { { "quit", lglerminal_quit }, { "flush", lglerminal_flush }, { "set", lglerminal_set }, { "get", lglerminal_get }, { "offset", lglerminal_offset }, { "tint", lglerminal_layer_color }, { "scale", lglerminal_layer_scale }, { "sprites", lglerminal_load_sprites_file }, { "sound", lglerminal_play_sound }, { nullptr, nullptr } }; int message_handler(lua_State* L) { luaL_traceback(L, L, lua_tostring(L, -1), 1); lua_remove(L, -2); glerminal_quit(); return true; } lua_State* L; void init() { lua_pushcfunction(L, message_handler); const int handler = lua_gettop(L); lua_getglobal(L, "glerminal"); lua_getfield(L, -1, "init"); lua_remove(L, -2); if (lua_pcall(L, 0, 0, handler) != LUA_OK) { std::cout << lua_tostring(L, -1) << std::endl; lua_pop(L, 1); } lua_remove(L, handler); } void mainloop(double dt) { lua_pushcfunction(L, message_handler); const int handler = lua_gettop(L); lua_getglobal(L, "glerminal"); lua_getfield(L, -1, "main"); lua_remove(L, -2); lua_pushnumber(L, dt); if (lua_pcall(L, 1, 0, handler) != LUA_OK) { std::cout << lua_tostring(L, -1) << std::endl; lua_pop(L, 1); } lua_remove(L, handler); } void keypressed(int key) { const char* const name = glfwGetKeyName(key, 0); if (name) { lua_pushcfunction(L, message_handler); const int handler = lua_gettop(L); lua_getglobal(L, "glerminal"); lua_getfield(L, -1, "keypress"); lua_remove(L, -2); lua_pushstring(L, name); if (lua_pcall(L, 1, 0, handler) != LUA_OK) { std::cout << lua_tostring(L, -1) << std::endl; lua_pop(L, 1); } lua_remove(L, handler); } } void keyrelease(int key) { const char* const name = glfwGetKeyName(key, 0); if (name) { lua_pushcfunction(L, message_handler); const int handler = lua_gettop(L); lua_getglobal(L, "glerminal"); lua_getfield(L, -1, "keyrelease"); lua_remove(L, -2); lua_pushstring(L, name); if (lua_pcall(L, 1, 0, handler) != LUA_OK) { std::cout << lua_tostring(L, -1) << std::endl; lua_pop(L, 1); } lua_remove(L, handler); } } void mousemove(double x, double y) { lua_pushcfunction(L, message_handler); const int handler = lua_gettop(L); lua_getglobal(L, "glerminal"); lua_getfield(L, -1, "mousemove"); lua_remove(L, -2); lua_pushnumber(L, x); lua_pushnumber(L, y); if (lua_pcall(L, 2, 0, handler) != LUA_OK) { std::cout << lua_tostring(L, -1) << std::endl; lua_pop(L, 1); } lua_remove(L, handler); } void mousepress(int button, double x, double y) { const char* button_name = nullptr; switch (button) { case GLFW_MOUSE_BUTTON_LEFT: button_name = "left"; break; case GLFW_MOUSE_BUTTON_RIGHT: button_name = "right"; break; case GLFW_MOUSE_BUTTON_MIDDLE: button_name = "middle"; break; } if (button_name) { lua_pushcfunction(L, message_handler); const int handler = lua_gettop(L); lua_getglobal(L, "glerminal"); lua_getfield(L, -1, "mousepress"); lua_remove(L, -2); lua_pushstring(L, button_name); lua_pushnumber(L, x); lua_pushnumber(L, y); if (lua_pcall(L, 3, 0, handler) != LUA_OK) { std::cout << lua_tostring(L, -1) << std::endl; lua_pop(L, 1); } lua_remove(L, handler); } } void mouserelease(int button, double x, double y) { const char* button_name = nullptr; switch (button) { case GLFW_MOUSE_BUTTON_LEFT: button_name = "left"; break; case GLFW_MOUSE_BUTTON_RIGHT: button_name = "right"; break; case GLFW_MOUSE_BUTTON_MIDDLE: button_name = "middle"; break; } if (button_name) { lua_pushcfunction(L, message_handler); const int handler = lua_gettop(L); lua_getglobal(L, "glerminal"); lua_getfield(L, -1, "mouserelease"); lua_remove(L, -2); lua_pushstring(L, button_name); lua_pushnumber(L, x); lua_pushnumber(L, y); if (lua_pcall(L, 3, 0, handler) != LUA_OK) { std::cout << lua_tostring(L, -1) << std::endl; lua_pop(L, 1); } lua_remove(L, handler); } } } int main(int argc, char** argv) { if (argc == 1) { std::cout << "Usage: " << argv[0] << " " << std::endl; return 0; } if (CHANGE_WORKING_DIRECTORY(argv[1])) { std::cout << "Failed to find project directory" << std::endl; return 1; } L = luaL_newstate(); luaL_openlibs(L); luaL_newlib(L, lglerminal_methods); lua_setglobal(L, "glerminal"); lua_pushcfunction(L, message_handler); const int handler = lua_gettop(L); if (luaL_loadfile(L, "main.lua") != LUA_OK) { const char* str = lua_tostring(L, -1); std::cout << str << std::endl; lua_pop(L, 1); } else if (lua_pcall(L, 0, LUA_MULTRET, handler) != LUA_OK) { const char* str = lua_tostring(L, -1); std::cout << str << std::endl; lua_pop(L, 1); } else { glerminal_init_params params; params.init = init; params.main = mainloop; params.keypress = keypressed; params.keyrelease = keyrelease; params.moved = mousemove; params.mousepress = mousepress; params.mouserelease = mouserelease; glerminal_run(params); } lua_close(L); return 0; }