diff --git a/src/xrt/targets/gui/CMakeLists.txt b/src/xrt/targets/gui/CMakeLists.txt index 3077e6e8c..742e5c774 100644 --- a/src/xrt/targets/gui/CMakeLists.txt +++ b/src/xrt/targets/gui/CMakeLists.txt @@ -18,6 +18,7 @@ set(SOURCE_FILES gui_main.c gui_ogl.c gui_prober.c + gui_scene.cpp gui_sdl2.c ../../../external/glad/gl.h ../../../external/glad/gl.c diff --git a/src/xrt/targets/gui/gui_common.h b/src/xrt/targets/gui/gui_common.h index 9f20f6b6e..aa665913e 100644 --- a/src/xrt/targets/gui/gui_common.h +++ b/src/xrt/targets/gui/gui_common.h @@ -28,6 +28,7 @@ extern "C" { struct xrt_device; struct xrt_prober; struct time_state; +struct gui_scene_manager; /*! * Common struct holding state for the GUI interface. @@ -42,6 +43,8 @@ struct program bool stopped; bool initialized; + struct gui_scene_manager *gsm; + struct { SDL_Surface *sf; @@ -59,6 +62,15 @@ struct program struct gui_ogl_texture *texs[256]; }; +/*! + * A single currently running scene. + */ +struct gui_scene +{ + void (*render)(struct gui_scene *, struct program *); + void (*destroy)(struct gui_scene *); +}; + /*! * A OpenGL texture. * @@ -156,6 +168,46 @@ gui_ogl_sink_create(const char *name, void gui_ogl_sink_update(struct gui_ogl_texture *); +/*! + * Push the scene to the top of the lists. + * + * @ingroup gui + */ +void +gui_scene_push_front(struct program *p, struct gui_scene *me); + +/*! + * Put a scene on the delete list, also removes it from any other list. + * + * @ingroup gui + */ +void +gui_scene_delete_me(struct program *p, struct gui_scene *me); + +/*! + * Render the scenes. + * + * @ingroup gui + */ +void +gui_scene_manager_render(struct program *p); + +/*! + * Initialize the scene manager. + * + * @ingroup gui + */ +void +gui_scene_manager_init(struct program *p); + +/*! + * Destroy the scene manager. + * + * @ingroup gui + */ +void +gui_scene_manager_destroy(struct program *p); + #ifdef __cplusplus } diff --git a/src/xrt/targets/gui/gui_scene.cpp b/src/xrt/targets/gui/gui_scene.cpp new file mode 100644 index 000000000..b9603c40b --- /dev/null +++ b/src/xrt/targets/gui/gui_scene.cpp @@ -0,0 +1,96 @@ +// Copyright 2019, Collabora, Ltd. +// SPDX-License-Identifier: BSL-1.0 +/*! + * @file + * @brief SDL2 functions to drive the GUI. + * @author Jakob Bornecrantz + * @ingroup gui + */ + + +#include "gui_common.h" + +#include + + +struct gui_scene_manager +{ +public: + std::vector scenes = {}; + std::vector del = {}; +}; + +extern "C" void +gui_scene_push_front(struct program *p, struct gui_scene *me) +{ + auto &gsm = *p->gsm; + + // Need to remove the scene if it is already on the list. + auto index = gsm.scenes.begin(); + for (auto scene : gsm.scenes) { + if (scene != me) { + index++; + continue; + } + + gsm.scenes.erase(index); + break; + } + + // Now push it to the front. + gsm.scenes.push_back(me); +} + +extern "C" void +gui_scene_delete_me(struct program *p, struct gui_scene *me) +{ + auto &gsm = *p->gsm; + + auto index = gsm.scenes.begin(); + for (auto scene : gsm.scenes) { + if (scene != me) { + index++; + continue; + } + + gsm.scenes.erase(index); + break; + } + + gsm.del.push_back(me); +} + +extern "C" void +gui_scene_manager_render(struct program *p) +{ + auto &gsm = *p->gsm; + auto copy = gsm.scenes; + + for (auto scene : copy) { + scene->render(scene, p); + } + + copy = gsm.del; + gsm.del.clear(); + for (auto scene : copy) { + scene->destroy(scene); + } + + // If there are no scenes left stop the program. + if (gsm.scenes.size() == 0) { + p->stopped = true; + } +} + +extern "C" void +gui_scene_manager_init(struct program *p) +{ + p->gsm = new gui_scene_manager; +} + +extern "C" void +gui_scene_manager_destroy(struct program *p) +{ + delete p->gsm; + p->gsm = NULL; +}