diff --git a/core/Input.cpp b/core/Input.cpp index 0f2b368..780bf2f 100644 --- a/core/Input.cpp +++ b/core/Input.cpp @@ -20,29 +20,17 @@ void Input::Use(Window *window){ } void Input::HandleKeys(Window *window, int keys, int code, int action, int mods) { -#ifdef LUA_SCRIPTING - lua_State *L = (lua_State*) glfwGetWindowUserPointer(window); - lua_getglobal(L, "onkey"); - lua_pushinteger(L, keys); - lua_pushinteger(L, code); - lua_pushinteger(L, action); - lua_pushinteger(L, mods); - lua_call(L, 4, 0); -#endif // LUA_SCRIPTING + for (KeyHandler keyHandler : instance->keyHandlers) { + keyHandler(window, keys, code, action, mods); + } } void Input::HandleMousePosition(Window *window, double xpos, double ypos) { double relx = xpos - instance->lastx; double rely = ypos - instance->lasty; -#ifdef LUA_SCRIPTING - lua_State *L = (lua_State*) glfwGetWindowUserPointer(window); - lua_getglobal(L, "onmousemotion"); - lua_pushnumber(L, xpos); - lua_pushnumber(L, ypos); - lua_pushnumber(L, relx); - lua_pushnumber(L, rely); - lua_call(L, 4, 0); -#endif // LUA_SCRIPTING + for (MousePositionHandler mousePositionHandler : instance->mousePositionHandlers) { + mousePositionHandler(window, xpos, ypos, relx, rely); + } instance->lastx = xpos; instance->lasty = ypos; } diff --git a/core/Input.h b/core/Input.h index 987890c..96696d5 100644 --- a/core/Input.h +++ b/core/Input.h @@ -1,20 +1,21 @@ +#ifndef COUCH_H +#define COUCH_H #include #include -#ifdef LUA_SCRIPTING -extern "C" { -#include -#include -#include -} -#endif // LUA_SCRIPTING +#include #include "types.h" +typedef void (*KeyHandler)(Window *window, int key, int code, int action, int mods); +typedef void (*MousePositionHandler)(Window *window, double xpos, double ypos, double xrel, double yrel); + class Input { public: static Input *GetInstance(); void Use(Window *window); + std::vector keyHandlers; + std::vector mousePositionHandlers; private: double lastx, lasty; Input(); @@ -22,3 +23,5 @@ private: static void HandleMousePosition(Window *window, double xpos, double ypos); static Input *instance; }; + +#endif // COUCH_H diff --git a/core/Lua.cpp b/core/Lua.cpp new file mode 100644 index 0000000..42fb161 --- /dev/null +++ b/core/Lua.cpp @@ -0,0 +1,90 @@ +#include "Lua.h" + +#ifdef LUA_SCRIPTING + +lua_State *Lua::L { luaL_newstate() }; + +#endif // LUA_SCRIPTING + +void Lua::Initialize() { +#ifdef LUA_SCRIPTING + language = this; + int err; + // Initialize Lua + luaopen_base(L); + luaopen_couch(L); + err = luaL_loadfile(L, "main.lua"); + if (err == LUA_OK) { + err = lua_pcall(L, 0, 0, 0); + if (err != LUA_OK) { + Error(); + } + lua_getglobal(L, "init"); + err = lua_pcall(L, 0, 0, 0); + if (err != LUA_OK) { + Error(); + } + } else if (err == LUA_ERRFILE) { + std::cerr << "Could not find main.lua." << std::endl; + exit(1); + } else { + // Syntax error + Error(); + } + + // Bind input functions + //glfwSetWindowUserPointer(window, (void*) L); + Input *input = Input::GetInstance(); + input->keyHandlers.push_back(LuaKeyHandler); + input->mousePositionHandlers.push_back(LuaMousePositionHandler); +#else // LUA_SCRIPTING + std::cerr << "Lua is selected as scripting language, but this binary was built without Lua support." << std::endl; + exit(1); +#endif // LUA_SCRIPTING +} + +void Lua::Update(double delta) { +#ifdef LUA_SCRIPTING + lua_getglobal(L, "update"); + lua_pushnumber(L, delta); + lua_call(L, 1, 0); +#endif // LUA_SCRIPTING +} + +void Lua::Close() { +#ifdef LUA_SCRIPTING + lua_close(L); +#endif // LUA_SCRIPTING +} + +void Lua::Error() { +#ifdef LUA_SCRIPTING + const char *error = lua_tolstring(L, -1, 0); + std::cerr << error << std::endl; +#endif // LUA_SCRIPTING + exit(1); +} + +void Lua::LuaKeyHandler(Window *window, int key, int code, int action, int mods) { +#ifdef LUA_SCRIPTING + // lua_State *L = (lua_State*) glfwGetWindowUserPointer(window); + lua_getglobal(L, "onkey"); + lua_pushinteger(L, key); + lua_pushinteger(L, code); + lua_pushinteger(L, action); + lua_pushinteger(L, mods); + lua_call(L, 4, 0); +#endif // LUA_SCRIPTING +} + +void Lua::LuaMousePositionHandler(Window *window, double xpos, double ypos, double relx, double rely) { +#ifdef LUA_SCRIPTING + // lua_State *L = (lua_State*) glfwGetWindowUserPointer(window); + lua_getglobal(L, "onmousemotion"); + lua_pushnumber(L, xpos); + lua_pushnumber(L, ypos); + lua_pushnumber(L, relx); + lua_pushnumber(L, rely); + lua_call(L, 4, 0); +#endif // LUA_SCRIPTING +} diff --git a/core/Lua.h b/core/Lua.h new file mode 100644 index 0000000..de75192 --- /dev/null +++ b/core/Lua.h @@ -0,0 +1,35 @@ +#ifndef LUA_H +#define LUA_H + +#include +#include + +#include "Input.h" + +#ifdef LUA_SCRIPTING +// Lua includes +extern "C" { +#include "lua.h" +#include "lualib.h" +#include "lauxlib.h" +} +extern "C" int luaopen_couch(lua_State* L); +#endif // LUA_SCRIPTING + +#include "ScriptingLanguage.h" + +class Lua : public ScriptingLanguage { +public: + void Initialize(); + void Update(double delta); + void Close(); + void Error(); +private: +#ifdef LUA_SCRIPTING + static lua_State *L; + static void LuaKeyHandler(Window *window, int key, int code, int action, int mods); + static void LuaMousePositionHandler(Window *window, double xpos, double ypos, double xrel, double yrel); +#endif // LUA_SCRIPTING +}; + +#endif /* LUA_H */ diff --git a/core/ScriptingLanguage.cpp b/core/ScriptingLanguage.cpp new file mode 100644 index 0000000..0f1f6e3 --- /dev/null +++ b/core/ScriptingLanguage.cpp @@ -0,0 +1,8 @@ +#include "ScriptingLanguage.h" + +ScriptingLanguage *ScriptingLanguage::language { nullptr }; + +ScriptingLanguage *ScriptingLanguage::GetCurrentLanguage() { + return language; +} + diff --git a/core/ScriptingLanguage.h b/core/ScriptingLanguage.h index bd492ea..995da64 100644 --- a/core/ScriptingLanguage.h +++ b/core/ScriptingLanguage.h @@ -1,10 +1,15 @@ #ifndef SCRIPTINGLANGUAGE_H #define SCRIPTINGLANGUAGE_H -class ScriptingLangauge { - void Initialize(); - void Update(); - void Close(); -} +class ScriptingLanguage { +public: + virtual void Initialize() = 0; + virtual void Update(double delta) = 0; + virtual void Close() = 0; + virtual void Error() = 0; + static ScriptingLanguage *GetCurrentLanguage(); +protected: + static ScriptingLanguage *language; +}; #endif /* SCRIPTINGLANGUAGE_H */ diff --git a/core/couch.cpp b/core/couch.cpp index cd085bf..3e6a803 100644 --- a/core/couch.cpp +++ b/core/couch.cpp @@ -1,15 +1,6 @@ // C++ includes #include -#ifdef LUA_SCRIPTING -// Lua includes -extern "C" { -#include -#include -#include -} -#endif // LUA_SCRIPTING - // OpenGL Includes #include #include @@ -22,6 +13,7 @@ extern "C" { #include "Camera.h" #include "Input.h" #include "Node.h" +#include "Lua.h" Window *window; @@ -30,12 +22,6 @@ const int height = 600; Node *root; -#ifdef LUA_SCRIPTING - -extern "C" int luaopen_couch(lua_State* L); - -#endif // LUA_SCRIPTING - void render(Node *curr, Shader shader, Matrix model) { if (curr->IsDrawable()) { if (curr->IsTransformable()) { @@ -81,22 +67,6 @@ int main() { root = Node::GetRoot(); -#ifdef LUA_SCRIPTING - lua_State *L; - L = luaL_newstate(); - luaopen_base(L); - luaopen_couch(L); - if (luaL_loadfile(L, "main.lua") == 0){ - lua_call(L, 0, 0); - lua_getglobal(L, "init"); - lua_call(L, 0, 0); - } else { - std::cerr << "Could not find main.lua" << std::endl; - return 1; - } - glfwSetWindowUserPointer(window, (void*) L); -#endif // LUA_SCRIPTING - Input *input = Input::GetInstance(); input->Use(window); @@ -108,6 +78,10 @@ int main() { Matrix projection = glm::perspective(glm::radians(45.0f), 800.0f/600.0f, 0.1f, 100.0f); shader.UpdateProjection(projection); + // TODO Allow multiple scripting languages + Lua *lua = new Lua(); + lua->Initialize(); + double lastTime = glfwGetTime(); double delta = 0.0; @@ -115,6 +89,7 @@ int main() { glClearColor(0.5f, 0.5f, 0.5f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); + lua->Update(delta); Matrix view(1.0f); Camera *camera = Camera::GetCurrentCamera(); @@ -124,16 +99,8 @@ int main() { view = glm::translate(view, -camera->transform.position); shader.UpdateView(view); - -#ifdef LUA_SCRIPTING - lua_getglobal(L, "update"); - lua_pushnumber(L, delta); - lua_call(L, 1, 0); -#endif // LUA_SCRIPTING - // Render the scene tree render(root, shader, Matrix(1.0f)); - glfwSwapBuffers(window); glfwPollEvents(); @@ -143,12 +110,7 @@ int main() { lastTime = curTime; } -#ifdef LUA_SCRIPTING - - lua_close(L); - -#endif // LUA_SCRIPTING - + lua->Close(); glfwDestroyWindow(window); glfwTerminate(); return 0; diff --git a/roadmap.md b/roadmap.md index fa45367..0262779 100644 --- a/roadmap.md +++ b/roadmap.md @@ -27,3 +27,12 @@ I want to be able to build this for Windows - I have no clue what that entails - CMake? - How to run SWIG on windows? + +### Windows Compatible Postmortem +Pretty brittle as a result of needing to download Windows binaries, but it works +Eventually, we might need to include the source files as submodules, and build them all with CMake +For now, what we've got is good + +### Better error messages +Okay, now I want a message other than "main.lua not found!" if the lua file fucks up. +Also, I want Lua errors to kill the program with an error message and a stack trace.