diff options
Diffstat (limited to 'src/window.c')
-rw-r--r-- | src/window.c | 268 |
1 files changed, 268 insertions, 0 deletions
diff --git a/src/window.c b/src/window.c new file mode 100644 index 0000000..6a1fe6f --- /dev/null +++ b/src/window.c @@ -0,0 +1,268 @@ +#include "window.h" + +int honey_window_info_ref = LUA_NOREF; +int honey_window_resize_callback_ref = LUA_NOREF; +int honey_window_resize_callback_data_ref = LUA_NOREF; +int honey_window_focus_callback_ref = LUA_NOREF; +int honey_window_focus_callback_data_ref = LUA_NOREF; + +static void honey_glfw_window_resize_callback(honey_window window, + int width, int height) +{ + lua_State* L = glfwGetWindowUserPointer(window); + + int callback = honey_window_resize_callback_ref; + int data = honey_window_resize_callback_data_ref; + + if (callback == LUA_NOREF) + return; + + lua_rawgeti(L, LUA_REGISTRYINDEX, callback); + + lua_pushinteger(L, width); + lua_pushinteger(L, height); + + if (data == LUA_NOREF || data == LUA_REFNIL) + lua_pushnil(L); + else + lua_rawgeti(L, LUA_REGISTRYINDEX, data); + + honey_lua_pcall(L, 3, 0); +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +static void honey_glfw_window_focus_callback(honey_window window, + int focused) +{ + lua_State* L = glfwGetWindowUserPointer(window); + + int callback = honey_window_focus_callback_ref; + int data = honey_window_focus_callback_data_ref; + + if (callback == LUA_NOREF) + return; + + lua_rawgeti(L, LUA_REGISTRYINDEX, callback); + + lua_pushboolean(L, focused); + + if (data == LUA_NOREF || data == LUA_REFNIL) + lua_pushnil(L); + else + lua_rawgeti(L, LUA_REGISTRYINDEX, data); + + honey_lua_pcall(L, 2, 0); +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +bool honey_setup_window(lua_State* L) +{ + honey_window_information* info = lua_newuserdata(L, sizeof(honey_window_information)); + honey_window_info_ref = luaL_ref(L, LUA_REGISTRYINDEX); + + glfwInit(); + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); + + info->window = glfwCreateWindow(HONEY_WINDOW_DEFAULT_WIDTH, + HONEY_WINDOW_DEFAULT_HEIGHT, + "honey", NULL, NULL); + + info->width = HONEY_WINDOW_DEFAULT_WIDTH; + info->height = HONEY_WINDOW_DEFAULT_WIDTH; + info->fullscreen = false; + + if (info->window == NULL) { + fprintf(stderr, "[honey] ERROR: failed to create window!\n"); + glfwTerminate(); + return false; + } + /* store lua state in window, so it's accessible from GLFW callbacks */ + glfwSetWindowUserPointer(info->window, L); + glfwMakeContextCurrent(info->window); + + if (!gladLoadGLLoader((GLADloadproc) glfwGetProcAddress)) { + fprintf(stderr, "[honey] ERROR: failed to initialize GLAD!\n"); + glfwTerminate(); + return false; + } + + // Enable blending + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + // Enable depth testing + glEnable(GL_DEPTH_TEST); + + // Enable face culling + glEnable(GL_CULL_FACE); + + glfwSetWindowSizeCallback(info->window, honey_glfw_window_resize_callback); + glfwSetWindowFocusCallback(info->window, honey_glfw_window_focus_callback); + + + honey_lua_element window_elements[] = { + { "set_fullscreen", HONEY_FUNCTION, { .function = honey_window_set_fullscreen } }, + { "set_title", HONEY_FUNCTION, { .function = honey_window_set_title } }, + { "get_size", HONEY_FUNCTION, { .function = honey_window_get_size } }, + { "set_size", HONEY_FUNCTION, { .function = honey_window_set_size } }, + { "resize_bind", HONEY_FUNCTION, { .function = honey_window_resize_bind } }, + { "resize_unbind", HONEY_FUNCTION, { .function = honey_window_resize_unbind } }, + { "focus_bind", HONEY_FUNCTION, { .function = honey_window_focus_bind } }, + { "focus_unbind", HONEY_FUNCTION, { .function = honey_window_focus_unbind } }, + }; + + honey_lua_create_table(L, window_elements, 8); + return true; +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +int honey_window_set_fullscreen(lua_State* L) +{ + if (!honey_lua_validate_types(L, 1, HONEY_BOOLEAN)) + lua_error(L); + + bool fullscreen = lua_toboolean(L, 1); + + lua_rawgeti(L, LUA_REGISTRYINDEX, honey_window_info_ref); + honey_window_information* info = lua_touserdata(L, -1); + + if (fullscreen) { + glfwGetWindowSize(info->window, &(info->width), &(info->height)); + + GLFWmonitor* monitor = glfwGetPrimaryMonitor(); + const GLFWvidmode* mode = glfwGetVideoMode(monitor); + glfwSetWindowMonitor(info->window, monitor, 0, 0, mode->width, mode->height, mode->refreshRate); + info->fullscreen = true; + } + else { + glfwSetWindowMonitor(info->window, NULL, 20, 20, info->width, info->height, 0); + info->fullscreen = false; + } + return 0; +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +int honey_window_set_title(lua_State* L) +{ + if (!honey_lua_validate_types(L, 1, HONEY_STRING)) + lua_error(L); + + const char* title = lua_tostring(L, 1); + + lua_rawgeti(L, LUA_REGISTRYINDEX, honey_window_info_ref); + honey_window_information* info = lua_touserdata(L, -1); + + glfwSetWindowTitle(info->window, title); + return 0; +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +int honey_window_get_size(lua_State* L) +{ + lua_rawgeti(L, LUA_REGISTRYINDEX, honey_window_info_ref); + honey_window_information* info = lua_touserdata(L, -1); + + int width, height; + glfwGetWindowSize(info->window, &width, &height); + lua_pushinteger(L, width); + lua_pushinteger(L, height); + return 2; +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +int honey_window_set_size(lua_State* L) +{ + if (!honey_lua_validate_types(L, 2, HONEY_INTEGER, HONEY_INTEGER)) + lua_error(L); + + int width = lua_tointeger(L, 1); + int height = lua_tointeger(L, 2); + + lua_rawgeti(L, LUA_REGISTRYINDEX, honey_window_info_ref); + honey_window_information* info = lua_touserdata(L, -1); + + glfwSetWindowSize(info->window, width, height); + return 0; +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +int honey_window_resize_bind(lua_State* L) +{ + if (!honey_lua_validate_types(L, 2, HONEY_FUNCTION, HONEY_ANY)) + lua_error(L); + + lua_pushvalue(L, 1); + honey_window_resize_callback_ref = luaL_ref(L, LUA_REGISTRYINDEX); + lua_pushvalue(L, 2); + honey_window_resize_callback_data_ref = luaL_ref(L, LUA_REGISTRYINDEX); + + return 0; +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +int honey_window_resize_unbind(lua_State* L) +{ + int callback = honey_window_resize_callback_ref; + int data = honey_window_resize_callback_data_ref; + + if (callback != LUA_NOREF) { + lua_pushnil(L); + lua_rawseti(L, LUA_REGISTRYINDEX, callback); + } + + if (data != LUA_NOREF && data != LUA_REFNIL) { + lua_pushnil(L); + lua_rawseti(L, LUA_REGISTRYINDEX, callback); + } + + honey_window_resize_callback_ref = LUA_NOREF; + honey_window_resize_callback_data_ref = LUA_NOREF; + return 0; +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +int honey_window_focus_bind(lua_State* L) +{ + if (!honey_lua_validate_types(L, 2, HONEY_FUNCTION, HONEY_ANY)) + lua_error(L); + + lua_pushvalue(L, 1); + honey_window_focus_callback_ref = luaL_ref(L, LUA_REGISTRYINDEX); + lua_pushvalue(L, 2); + honey_window_focus_callback_data_ref = luaL_ref(L, LUA_REGISTRYINDEX); + + return 0; +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +int honey_window_focus_unbind(lua_State* L) +{ + int callback = honey_window_focus_callback_ref; + int data = honey_window_focus_callback_data_ref; + + if (callback != LUA_NOREF) { + lua_pushnil(L); + lua_rawseti(L, LUA_REGISTRYINDEX, callback); + } + + if (data != LUA_NOREF && data != LUA_REFNIL) { + lua_pushnil(L); + lua_rawseti(L, LUA_REGISTRYINDEX, callback); + } + + honey_window_focus_callback_ref = LUA_NOREF; + honey_window_focus_callback_data_ref = LUA_NOREF; + return 0; +} |