diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/common.h | 1 | ||||
-rw-r--r-- | src/honey.c | 173 | ||||
-rw-r--r-- | src/honey.h | 50 | ||||
-rw-r--r-- | src/input/input.c | 3 | ||||
-rw-r--r-- | src/main.c | 186 |
5 files changed, 195 insertions, 218 deletions
diff --git a/src/common.h b/src/common.h index 66500eb..47b7ee4 100644 --- a/src/common.h +++ b/src/common.h @@ -152,4 +152,5 @@ void honey_lua_push_element(lua_State* L, void honey_lua_create_table(lua_State* L, honey_lua_element* elements, unsigned int n_elements); + #endif diff --git a/src/honey.c b/src/honey.c index 79ff970..0bd5b25 100644 --- a/src/honey.c +++ b/src/honey.c @@ -1,71 +1,138 @@ #include "honey.h" -static void default_honey_update_callback(float dt) {} -static void default_honey_draw_callback() {} - -honey_window honey_setup(int screen_width, int screen_height, char* window_title) { - honey_update_callback = &default_honey_update_callback; - honey_draw_callback = &default_honey_draw_callback; - - glfwInit(); - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); - glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); - - honey_window window = glfwCreateWindow(screen_width, screen_height, window_title, NULL, NULL); - if (window == NULL) { - fprintf(stderr, "ERROR: failed to create window!\n"); - glfwTerminate(); - return NULL; - } - - glfwMakeContextCurrent(window); - glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); - - if (!gladLoadGLLoader((GLADloadproc) glfwGetProcAddress)) { - fprintf(stderr, "ERROR: failed to initialize GLAD!\n"); - glfwTerminate(); - return NULL; - } - - honey_setup_keyboard(); - glfwSetKeyCallback(window, default_honey_keyboard_callback); - - // Enable blending - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - return window; +void honey_print_help() +{ + printf("usage: honey [OPTIONS] SCRIPT_DIR\n" + " -v Enable verbose logging\n" + " -h Show this help message and exit\n" + " -l LOG Log to LOG instead of stdout\n"); } /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -void honey_set_update_callback(void (*update_callback)(float)) { - honey_update_callback = update_callback; +bool honey_parse_options(honey_options* options, int argc, char** argv) +{ + honey_options opts; + opts.verbose = false; + opts.script_directory = NULL; + opts.logfile = NULL; + + opterr = 0; + int c; + + while ((c = getopt(argc, argv, "vhl:")) != -1) { + switch (c) { + case 'v': + opts.verbose = true; + break; + + case 'h': + honey_print_help(); + return false; + + case 'l': + opts.logfile = optarg; + break; + + case '?': + fprintf(stderr, "unknown option: '%c'\n", optopt); + honey_print_help(); + return false; + + default: + return false; + } + } + + if (optind < argc) { + opts.script_directory = argv[optind]; + } + + *options = opts; + + return true; } -void honey_set_draw_callback(void (*draw_callback)()) { - honey_draw_callback = draw_callback; +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +bool honey_setup(lua_State** L, honey_window* window) +{ + /* set up glfw */ + glfwInit(); + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); + + *window = glfwCreateWindow(640, 480, "honey", NULL, NULL); + if (*window == NULL) { + fprintf(stderr, "[honey] ERROR: failed to create window!\n"); + glfwTerminate(); + return false; + } + + glfwMakeContextCurrent(*window); + + if (!gladLoadGLLoader((GLADloadproc) glfwGetProcAddress)) { + fprintf(stderr, "[honey] ERROR: failed to initialize GLAD!\n"); + glfwTerminate(); + return false; + } + + honey_setup_keyboard(); + glfwSetKeyCallback(*window, default_honey_keyboard_callback); + + // Enable blending + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + + /* set up lua and honey lua bindings */ + *L = luaL_newstate(); + luaL_openlibs(*L); + glfwSetWindowUserPointer(*window, *L); + + lua_createtable(*L, 0, 1); + + honey_setup_input(*L); + lua_setfield(*L, -2, "input"); + + lua_setglobal(*L, "honey"); + + return true; } /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ void honey_run(honey_window window) { - float prevTime = 0; - float currentTime = 0; - float dt; - float draw_dt = 0; - - while(!glfwWindowShouldClose(window)) { - currentTime = (float) glfwGetTime(); - dt = currentTime - prevTime; - prevTime = currentTime; - - honey_update_callback(dt); - honey_draw_callback(); - } + /*float prevTime = 0; + float currentTime = 0; + float dt; + float draw_dt = 0; + + while(!glfwWindowShouldClose(window)) { + currentTime = (float) glfwGetTime(); + dt = currentTime - prevTime; + prevTime = currentTime; + + honey_update_callback(dt); + honey_draw_callback(); + }*/ } /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ +int honey_get_callback(lua_State* L, char* callback) +{ + lua_getglobal(L, "honey"); + lua_getfield(L, -1, callback); + int ref = LUA_NOREF; + + if (lua_isfunction(L, -1)) + ref = luaL_ref(L, LUA_REGISTRYINDEX); + else + lua_pop(L, 1); + lua_pop(L, 1); + + return ref; +} diff --git a/src/honey.h b/src/honey.h index c134894..b349475 100644 --- a/src/honey.h +++ b/src/honey.h @@ -17,28 +17,38 @@ #include "shader/shader.h" #include "texture/texture.h" -/** @brief Initialize Honey. - * - * @param[in] screen_width The desired width of the screen in pixels - * @param[in] screen_height The desired height of the screen in pixels - * @param[in] window_title Title to use for the window. - */ -honey_window honey_setup(int screen_width, int screen_height, char* window_title); +/** @struct Helper struct to wrap command-line options. */ +typedef struct { + bool verbose; + char* script_directory; + char* logfile; +} honey_options; -static void (*honey_update_callback)(float dt); -static void (*honey_draw_callback)(); +/** @brief Print usage help for honey. */ +void honey_print_help(); -/** @brief Set the main update function. +/** @brief Parse command-line options for honey. + * + * This function returns false if the -h option was passed, for simplicity's sake. * - * @param[in] update_callback The function to call every loop + * @param[in] argc The number of arguments passed to honey. + * @param[in] argv Argument string array. + * @param[out] options Pointer to the honey_options struct to populate. + * + * @returns true if parsing was successful and execution should continue; + * false otherwise. */ -void honey_set_update_callback(void (*update_callback)(float)); +bool honey_parse_options(honey_options* options, int argc, char** argv); -/** @brief Set the main draw function +/** @brief Initialize Honey and set up lua bindings. + * + * @param[out] L The lua state with honey configured. + * @param[out] window The GLFW window configured by honey. + * Also accessible from lua as honey.window.glfw_window. * - * @param[in] draw_callback The function to call every draw cycle + * @returns true on a success; false otherwise. */ -void honey_set_draw_callback(void (*draw_callback)()); +bool honey_setup(lua_State** L, honey_window* window); /** @brief The main game loop. * @@ -46,6 +56,16 @@ void honey_set_draw_callback(void (*draw_callback)()); */ void honey_run(honey_window window); +/** @brief Get a registry reference to a given honey callback. + * + * @param[in] L The lua state to find the reference in. + * @param[in] callback Name of the callback to find. + * + * @returns Registry reference to the function if it exists; + * LUA_NOREF otherwise. + */ +int honey_get_callback(lua_State* L, char* callback); + #define honey_set_resize_callback glfwSetFramebufferSizeCallback #define honey_set_mouse_move_callback glfwSetCursorPosCallback diff --git a/src/input/input.c b/src/input/input.c index ec28695..c231157 100644 --- a/src/input/input.c +++ b/src/input/input.c @@ -182,7 +182,8 @@ int honey_key_bind(lua_State* L) } else { char* error_message; - honey_format_string(error_message, "expected 2 or 3 arguments; received %d instead", n_args); + honey_format_string(&error_message, "expected 2 or 3 arguments; received %d instead", n_args); + lua_pushstring(L, error_message); free(error_message); lua_error(L); } @@ -1,144 +1,42 @@ #include "honey.h" -struct options { - bool verbose; - bool run; - bool has_update; - bool has_draw; - char* scriptdir; -}; - -bool has_function(lua_State* L, char* field) -{ - lua_getglobal(L, "honey"); - lua_getfield(L, -1, field); - if (lua_isfunction(L, -1)) - return true; - return false; -} - -bool parse_options(struct options* opt, int argc, char** argv) -{ - opt->verbose = false; - opt->run = false; - - opterr = 0; - int c; - - while ((c = getopt(argc, argv, "vh")) != -1) { - switch (c) { - case 'v': - opt->verbose = true; - break; - - case 'h': - // print help - break; - - case '?': - if (isprint (optopt)) - fprintf (stderr, "Unknown option `-%c'.\n", optopt); - else - fprintf (stderr, - "Unknown option character `\\x%x'.\n", - optopt); - return false; - - default: - return false; - } - } - - if (optind < argc) { - opt->run = true; - opt->scriptdir = argv[optind]; - } - - return true; -} - -GLFWwindow* setup_window(int width, int height, char* title) -{ - glfwInit(); - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); - glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); - - GLFWwindow* window = glfwCreateWindow(width, height, title, NULL, NULL); - if (window == NULL) { - fprintf(stderr, "ERROR: failed to create window!\n"); - glfwTerminate(); - return NULL; - } - - glfwMakeContextCurrent(window); - glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); - - if (!gladLoadGLLoader((GLADloadproc) glfwGetProcAddress)) { - fprintf(stderr, "ERROR: failed to initialize GLAD!\n"); - glfwTerminate(); - return NULL; - } - - honey_setup_keyboard(); - glfwSetKeyCallback(window, default_honey_keyboard_callback); - - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - return window; -} - -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - int main(int argc, char** argv) { - struct options opt; - if (!parse_options(&opt, argc, argv)) { - fprintf(stderr, "ERROR: failed to parse command line options!\n"); - return 1; - } - - if (!opt.run) + honey_options opts; + if (!honey_parse_options(&opts, argc, argv)) { return 0; + } - printf("%d\n", LUA_NOREF); - - GLFWwindow* window = setup_window(480, 320, "honey-engine"); - - lua_State* L = luaL_newstate(); - glfwSetWindowUserPointer(window, L); - luaL_openlibs(L); + honey_window window; + lua_State* L; - lua_createtable(L, 0, 1); - - honey_setup_input(L); - lua_setfield(L, -2, "input"); + if (!honey_setup(&L, &window)) + return 1; - lua_setglobal(L, "honey"); - - size_t dirlen = strlen(opt.scriptdir) + 10; - char* scriptfile = malloc(sizeof(char) * dirlen); - if (scriptfile == NULL) { - fprintf(stderr, "ERROR: failed to allocate memory for script file string!\n"); + char* script; + honey_result res = honey_format_string(&script, + "%s/main.lua", + opts.script_directory); + if (res != HONEY_OK) { + fprintf(stderr, "[honey] FATAL: could not allocate space for script filename!"); return 1; } - - snprintf(scriptfile, dirlen, "%s/main.lua", opt.scriptdir); - if (luaL_loadfile(L, scriptfile) == 0) { - if (lua_pcall(L, 0, 1, 0) == 0) { - lua_pop(L, lua_gettop(L)); + if (luaL_loadfile(L, script) == 0) { + if (!lua_pcall(L, 0, 1, 0) == 0) { + const char* error = lua_tostring(L, -1); + fprintf(stderr, "[honey] ERROR: %s\n", error); + return 1; } } else { - fprintf(stderr, "ERROR: failed to open %s!\n", scriptfile); + fprintf(stderr, "ERROR: failed to open %s!\n", script); return 1; } - opt.has_update = has_function(L, "update"); - opt.has_draw = has_function(L, "draw"); - + int update_callback = honey_get_callback(L, "update"); + int draw_callback = honey_get_callback(L, "draw"); + float prevTime = 0; float currentTime = 0; float dt; @@ -149,36 +47,26 @@ int main(int argc, char** argv) prevTime = currentTime; glfwPollEvents(); - lua_getglobal(L, "honey"); - - if (opt.has_update) { - lua_getfield(L, -1, "update"); - if (lua_isfunction(L, -1)) { - lua_pushnumber(L, dt); - int result = lua_pcall(L, 1, 0, 0); - if (result != 0) { - glfwSetWindowShouldClose(window, true); - } - } - else { - lua_pop(L, 1); + if (update_callback != LUA_NOREF) { + lua_rawgeti(L, LUA_REGISTRYINDEX, update_callback); + lua_pushnumber(L, dt); + int result = lua_pcall(L, 1, 0, 0); + if (result != 0) { + const char* error = lua_tostring(L, -1); + fprintf(stderr, "[honey] ERROR: %s\n", error); + glfwSetWindowShouldClose(window, true); } } - if (opt.has_draw) { - lua_getfield(L, -1, "draw"); - if (lua_isfunction(L, -1)) { - int result = lua_pcall(L, 0, 0, 0); - if (result != 0) { - glfwSetWindowShouldClose(window, true); - } - } - else { - lua_pop(L, 1); + if (draw_callback != LUA_NOREF) { + lua_rawgeti(L, LUA_REGISTRYINDEX, draw_callback); + int result = lua_pcall(L, 0, 0, 0); + if (result != 0) { + const char* error = lua_tostring(L, -1); + fprintf(stderr, "[honey] ERROR: %s\n", error); + glfwSetWindowShouldClose(window, true); } } - - lua_pop(L, 1); } lua_close(L); |