From fc883e0b0449509ba2e1c5d14d187feee098ab34 Mon Sep 17 00:00:00 2001 From: 3gg <3gg@shellblade.net> Date: Thu, 18 Jan 2024 19:33:18 -0800 Subject: Simplify game callbacks. --- gfx-app/include/gfx/gfx_app.h | 39 +++++++++++++++++++++---- gltfview/CMakeLists.txt | 3 +- gltfview/src/game.c | 52 ++++++++++++++++++++++++--------- gltfview/src/game.h | 34 ++++++---------------- gltfview/src/main.c | 67 ------------------------------------------- 5 files changed, 82 insertions(+), 113 deletions(-) delete mode 100644 gltfview/src/main.c diff --git a/gfx-app/include/gfx/gfx_app.h b/gfx-app/include/gfx/gfx_app.h index 0033bde..3c544fa 100644 --- a/gfx-app/include/gfx/gfx_app.h +++ b/gfx-app/include/gfx/gfx_app.h @@ -2,6 +2,7 @@ #include +/// Application settings. typedef struct GfxAppDesc { int argc; // Number of application arguments. const char** argv; // Application arguments. @@ -12,12 +13,19 @@ typedef struct GfxAppDesc { const char* title; // Window title. } GfxAppDesc; +typedef bool (*GfxAppInit)(const GfxAppDesc*, void** app_state); +typedef void (*GfxAppUpdate)(void* app_state, double t, double dt); +typedef void (*GfxAppRender)(void* app_state); +typedef void (*GfxAppResize)(void* app_state, int width, int height); +typedef void (*GfxAppShutdown)(void* app_state); + +/// Application callback functions. typedef struct GfxAppCallbacks { - bool (*init)(const GfxAppDesc*, void** app_state); - void (*update)(void* app_state, double t, double dt); - void (*render)(void* app_state); - void (*resize)(void* app_state, int width, int height); - void (*shutdown)(void* app_state); + GfxAppInit init; + GfxAppUpdate update; + GfxAppRender render; + GfxAppResize resize; + GfxAppShutdown shutdown; } GfxAppCallbacks; /// Create a window with an OpenGL context and run the main loop. @@ -25,3 +33,24 @@ bool gfx_app_run(const GfxAppDesc*, const GfxAppCallbacks*); /// Get the mouse coordinates relative to the app's window. void gfx_app_get_mouse_position(double* x, double* y); + +/// Define a main function that initializes and puts the application in a loop. +/// See also: gfx_app_run(). +#define GFX_APP_MAIN(WIDTH, HEIGHT, MAX_FPS) \ + int main(int argc, const char** argv) { \ + gfx_app_run( \ + &(GfxAppDesc){ \ + .argc = argc, \ + .argv = argv, \ + .width = WIDTH, \ + .height = HEIGHT, \ + .max_fps = MAX_FPS, \ + .update_delta_time = MAX_FPS > 0 ? 1.0 / (double)MAX_FPS : 0.0}, \ + &(GfxAppCallbacks){ \ + .init = (GfxAppInit)app_init, \ + .update = (GfxAppUpdate)app_update, \ + .render = (GfxAppRender)app_render, \ + .resize = (GfxAppResize)app_resize, \ + .shutdown = (GfxAppShutdown)app_end}); \ + return 0; \ + } diff --git a/gltfview/CMakeLists.txt b/gltfview/CMakeLists.txt index de745ce..98c3b47 100644 --- a/gltfview/CMakeLists.txt +++ b/gltfview/CMakeLists.txt @@ -5,8 +5,7 @@ add_subdirectory(src/plugins) project(gltfview) add_executable(gltfview - src/game.c - src/main.c) + src/game.c) target_include_directories(gltfview PRIVATE src/) diff --git a/gltfview/src/game.c b/gltfview/src/game.c index 5ca9ad4..c331190 100644 --- a/gltfview/src/game.c +++ b/gltfview/src/game.c @@ -7,11 +7,17 @@ #define _GNU_SOURCE 200112L // For readlink() #include "game.h" + #include "plugins/plugin.h" +#include +#include #include +#include #include +#include #include +#include #include #include @@ -21,6 +27,7 @@ #include #include #include +#include #include @@ -28,18 +35,32 @@ #undef _GNU_SOURCE -// Plugin to load if no plugin is provided. -static const char* DEFAULT_PLUGIN = "texture_view"; +static const int WIDTH = 1350; +static const int HEIGHT = 900; +static const int MAX_FPS = 60; -bool game_new(Game* game, int argc, const char** argv) { - assert(game); +void app_end(Game* game); + +bool app_init(const GfxAppDesc* desc, void** app_state) { + assert(desc); + + if (desc->argc <= 1) { + LOGE("Usage: %s [plugin args]", desc->argv[0]); + return false; + } + + Game* game = calloc(1, sizeof(Game)); + if (!game) { + LOGE("Failed to allocate game state"); + return false; + } - // Syntax: game [plugin] + // Syntax: game [plugin args] // - // Here we consume the [plugin] arg so that plugins receive the remainder + // Here we consume the arg so that plugins receive the remainder // args starting from 0. - game->argc = argc - 1; - game->argv = argv + 1; + game->argc = desc->argc - 1; + game->argv = desc->argv + 1; char exe_path_buf[NAME_MAX] = {0}; if (readlink("/proc/self/exe", exe_path_buf, sizeof(exe_path_buf)) == -1) { @@ -59,7 +80,7 @@ bool game_new(Game* game, int argc, const char** argv) { goto cleanup; } - const char* plugin = argc > 1 ? argv[1] : DEFAULT_PLUGIN; + const char* plugin = desc->argv[1]; if (!(game->plugin = load_plugin(game->plugin_engine, plugin))) { goto cleanup; } @@ -91,15 +112,16 @@ bool game_new(Game* game, int argc, const char** argv) { } } + *app_state = game; return true; cleanup: LOGE("Gfx error: %s", get_error()); - game_end(game); + app_end(game); return false; } -void game_end(Game* game) { +void app_end(Game* game) { assert(game); if (game->gfx) { gfx_destroy(&game->gfx); @@ -112,7 +134,7 @@ void game_end(Game* game) { } } -void game_update(Game* game, double t, double dt) { +void app_update(Game* game, double t, double dt) { plugin_engine_update(game->plugin_engine); if (plugin_reloaded(game->plugin) && plugin_resolve(game->plugin, plugin_init, "init")) { @@ -129,7 +151,7 @@ void game_update(Game* game, double t, double dt) { } } -void game_render(const Game* game) { +void app_render(const Game* game) { RenderBackend* render_backend = gfx_get_render_backend(game->gfx); Renderer* renderer = gfx_get_renderer(game->gfx); @@ -149,7 +171,7 @@ void game_render(const Game* game) { gfx_end_frame(render_backend); } -void game_set_viewport(Game* game, int width, int height) { +void app_resize(Game* game, int width, int height) { RenderBackend* render_backend = gfx_get_render_backend(game->gfx); gfx_set_viewport(render_backend, width, height); @@ -162,3 +184,5 @@ void game_set_viewport(Game* game, int width, int height) { Camera* camera = gfx_get_camera_camera(game->camera); camera->projection = projection; } + +GFX_APP_MAIN(WIDTH, HEIGHT, MAX_FPS); diff --git a/gltfview/src/game.h b/gltfview/src/game.h index 2a7b7ef..53725c7 100644 --- a/gltfview/src/game.h +++ b/gltfview/src/game.h @@ -1,19 +1,13 @@ +/* + * Header file defining the game state, included by plugins. + */ #pragma once -#include -#include -#include -#include -#include -#include - -#include - -typedef struct Plugin Plugin; typedef struct PluginEngine PluginEngine; - -/// The delta time the game should be updated with. -static const double game_dt = 1.0 / 60.0; +typedef struct Plugin Plugin; +typedef struct Gfx Gfx; +typedef struct Scene Scene; +typedef struct SceneCamera SceneCamera; /// Game state. typedef struct { @@ -22,16 +16,6 @@ typedef struct { PluginEngine* plugin_engine; Plugin* plugin; Gfx* gfx; - Scene* scene; - SceneCamera* camera; + Scene* scene; // TODO: Move scene graph to plugin? + SceneCamera* camera; // TODO: Move too. } Game; - -bool game_new(Game*, int argc, const char** argv); - -void game_end(Game*); - -void game_update(Game*, double t, double dt); - -void game_render(const Game*); - -void game_set_viewport(Game*, int width, int height); diff --git a/gltfview/src/main.c b/gltfview/src/main.c deleted file mode 100644 index f4863b4..0000000 --- a/gltfview/src/main.c +++ /dev/null @@ -1,67 +0,0 @@ -#include "game.h" - -#include -#include - -#include - -static bool init(const GfxAppDesc* desc, void** app_state) { - Game* game = calloc(1, sizeof(Game)); - if (!game) { - LOGE("Failed to allocate game state"); - return false; - } - if (!game_new(game, desc->argc, desc->argv)) { - LOGE("Failed to initialize game"); - return false; - } - *app_state = game; - return true; -} - -static void shutdown(void* app_state) { - assert(app_state); - Game* game = (Game*)(app_state); - game_end(game); -} - -static void update(void* app_state, double t, double dt) { - assert(app_state); - Game* game = (Game*)(app_state); - game_update(game, t, dt); -} - -static void render(void* app_state) { - assert(app_state); - Game* game = (Game*)(app_state); - game_render(game); -} - -static void resize(void* app_state, int width, int height) { - assert(app_state); - Game* game = (Game*)(app_state); - game_set_viewport(game, width, height); -} - -int main(int argc, const char** argv) { - const int initial_width = 1350; - const int initial_height = 900; - const int max_fps = 60; - - gfx_app_run( - &(GfxAppDesc){ - .argc = argc, - .argv = argv, - .width = initial_width, - .height = initial_height, - .max_fps = max_fps, - .update_delta_time = max_fps > 0 ? 1.0 / (double)max_fps : 0.0}, - &(GfxAppCallbacks){ - .init = init, - .update = update, - .render = render, - .resize = resize, - .shutdown = shutdown}); - - return 0; -} -- cgit v1.2.3