More abstraction for scripting languages

This commit is contained in:
Dane Johnson 2021-01-15 15:43:32 -06:00
parent db160c2de4
commit e99b623fec
8 changed files with 175 additions and 75 deletions

View File

@ -20,29 +20,17 @@ void Input::Use(Window *window){
} }
void Input::HandleKeys(Window *window, int keys, int code, int action, int mods) { void Input::HandleKeys(Window *window, int keys, int code, int action, int mods) {
#ifdef LUA_SCRIPTING for (KeyHandler keyHandler : instance->keyHandlers) {
lua_State *L = (lua_State*) glfwGetWindowUserPointer(window); keyHandler(window, keys, code, action, mods);
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
} }
void Input::HandleMousePosition(Window *window, double xpos, double ypos) { void Input::HandleMousePosition(Window *window, double xpos, double ypos) {
double relx = xpos - instance->lastx; double relx = xpos - instance->lastx;
double rely = ypos - instance->lasty; double rely = ypos - instance->lasty;
#ifdef LUA_SCRIPTING for (MousePositionHandler mousePositionHandler : instance->mousePositionHandlers) {
lua_State *L = (lua_State*) glfwGetWindowUserPointer(window); mousePositionHandler(window, xpos, ypos, relx, rely);
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
instance->lastx = xpos; instance->lastx = xpos;
instance->lasty = ypos; instance->lasty = ypos;
} }

View File

@ -1,20 +1,21 @@
#ifndef COUCH_H
#define COUCH_H
#include <GL/glew.h> #include <GL/glew.h>
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
#ifdef LUA_SCRIPTING #include <vector>
extern "C" {
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
}
#endif // LUA_SCRIPTING
#include "types.h" #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 { class Input {
public: public:
static Input *GetInstance(); static Input *GetInstance();
void Use(Window *window); void Use(Window *window);
std::vector<KeyHandler> keyHandlers;
std::vector<MousePositionHandler> mousePositionHandlers;
private: private:
double lastx, lasty; double lastx, lasty;
Input(); Input();
@ -22,3 +23,5 @@ private:
static void HandleMousePosition(Window *window, double xpos, double ypos); static void HandleMousePosition(Window *window, double xpos, double ypos);
static Input *instance; static Input *instance;
}; };
#endif // COUCH_H

90
core/Lua.cpp Normal file
View File

@ -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
}

35
core/Lua.h Normal file
View File

@ -0,0 +1,35 @@
#ifndef LUA_H
#define LUA_H
#include <iostream>
#include <stdlib.h>
#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 */

View File

@ -0,0 +1,8 @@
#include "ScriptingLanguage.h"
ScriptingLanguage *ScriptingLanguage::language { nullptr };
ScriptingLanguage *ScriptingLanguage::GetCurrentLanguage() {
return language;
}

View File

@ -1,10 +1,15 @@
#ifndef SCRIPTINGLANGUAGE_H #ifndef SCRIPTINGLANGUAGE_H
#define SCRIPTINGLANGUAGE_H #define SCRIPTINGLANGUAGE_H
class ScriptingLangauge { class ScriptingLanguage {
void Initialize(); public:
void Update(); virtual void Initialize() = 0;
void Close(); virtual void Update(double delta) = 0;
} virtual void Close() = 0;
virtual void Error() = 0;
static ScriptingLanguage *GetCurrentLanguage();
protected:
static ScriptingLanguage *language;
};
#endif /* SCRIPTINGLANGUAGE_H */ #endif /* SCRIPTINGLANGUAGE_H */

View File

@ -1,15 +1,6 @@
// C++ includes // C++ includes
#include <iostream> #include <iostream>
#ifdef LUA_SCRIPTING
// Lua includes
extern "C" {
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
}
#endif // LUA_SCRIPTING
// OpenGL Includes // OpenGL Includes
#include <GL/glew.h> #include <GL/glew.h>
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
@ -22,6 +13,7 @@ extern "C" {
#include "Camera.h" #include "Camera.h"
#include "Input.h" #include "Input.h"
#include "Node.h" #include "Node.h"
#include "Lua.h"
Window *window; Window *window;
@ -30,12 +22,6 @@ const int height = 600;
Node *root; Node *root;
#ifdef LUA_SCRIPTING
extern "C" int luaopen_couch(lua_State* L);
#endif // LUA_SCRIPTING
void render(Node *curr, Shader shader, Matrix model) { void render(Node *curr, Shader shader, Matrix model) {
if (curr->IsDrawable()) { if (curr->IsDrawable()) {
if (curr->IsTransformable()) { if (curr->IsTransformable()) {
@ -81,22 +67,6 @@ int main() {
root = Node::GetRoot(); 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 *input = Input::GetInstance();
input->Use(window); 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); Matrix projection = glm::perspective(glm::radians(45.0f), 800.0f/600.0f, 0.1f, 100.0f);
shader.UpdateProjection(projection); shader.UpdateProjection(projection);
// TODO Allow multiple scripting languages
Lua *lua = new Lua();
lua->Initialize();
double lastTime = glfwGetTime(); double lastTime = glfwGetTime();
double delta = 0.0; double delta = 0.0;
@ -115,6 +89,7 @@ int main() {
glClearColor(0.5f, 0.5f, 0.5f, 1.0f); glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
lua->Update(delta);
Matrix view(1.0f); Matrix view(1.0f);
Camera *camera = Camera::GetCurrentCamera(); Camera *camera = Camera::GetCurrentCamera();
@ -124,17 +99,9 @@ int main() {
view = glm::translate(view, -camera->transform.position); view = glm::translate(view, -camera->transform.position);
shader.UpdateView(view); 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 the scene tree
render(root, shader, Matrix(1.0f)); render(root, shader, Matrix(1.0f));
glfwSwapBuffers(window); glfwSwapBuffers(window);
glfwPollEvents(); glfwPollEvents();
@ -143,12 +110,7 @@ int main() {
lastTime = curTime; lastTime = curTime;
} }
#ifdef LUA_SCRIPTING lua->Close();
lua_close(L);
#endif // LUA_SCRIPTING
glfwDestroyWindow(window); glfwDestroyWindow(window);
glfwTerminate(); glfwTerminate();
return 0; return 0;

View File

@ -27,3 +27,12 @@ I want to be able to build this for Windows
- I have no clue what that entails - I have no clue what that entails
- CMake? - CMake?
- How to run SWIG on windows? - 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.