diff --git a/include/fggl/app.hpp b/include/fggl/app.hpp index b07203a601e381c73cb2687cd0e2907dd6009189..0fffefb57abf3b9a6fb42e4f6f28744c59603040 100644 --- a/include/fggl/app.hpp +++ b/include/fggl/app.hpp @@ -44,6 +44,8 @@ namespace fggl { * A state is responsible for managing user interaction with the app. When created, the appstate * is passed a reference to the application that owns it. The lifetime of the state is bounded * by the lifetype of this object. + * + * Ie. the lifetime of reference to the App is at least that of the AppState. * * @param owner a non-owned reference to the owner of the state. */ @@ -72,8 +74,24 @@ namespace fggl { */ virtual void render(gfx::Graphics &paint) = 0; + /** + * Notify the State it has just been switched to. + * + * This state should perform any setup it requires (eg, registering callbacks, requesting + * resources, etc...). + * + * FIXME: This should probably be RAII + */ virtual void activate() {} + /** + * Notify the State it is about to be switched from. + * + * This state should perform any cleanup it requires (eg, unregistering callbacks, freeing + * resources, etc...). + * + * FIXME: This should probably be RAII + */ virtual void deactivate() {} [[nodiscard]] inline auto owner() const -> App& { @@ -84,9 +102,27 @@ namespace fggl { App &m_owner; }; + /*! \class App app.hpp fggl/app.hpp + * + * Main entrypoint to the game framework. + */ class App { public: + /** + * Create an instance of an application, with a set of modules and name. + * + * The name is used to derrive verious settings, such as the location of same games and user + * configuration and content. + */ explicit App(modules::Manager *manager, const Identifer &name); + + /** + * Create an instance of an application, with a set of modules and name. + * + * This version of the constructor allows explicitly setting the name used for user-data rather + * than derriving it from the application name. This is useful if you want to use a shortened + * version of your application name for configuration. + */ App(modules::Manager *manager, const Identifer &name, const Identifer &folderName); // class is non copy-able @@ -96,32 +132,65 @@ namespace fggl { auto operator=(const App &other) -> App & = delete; auto operator=(App &&other) -> App & = delete; + /** + * Set the currently active window. + * + * FIXME: this is a nasty hack to get round the setup order for windows, graphics APIs and + * screen refreshes. Should be fixed with observer pattern. + */ inline void setWindow(display::Window *window) { m_window = window; } /** * Perform main game loop functions. + * + * You should pass in argc and argv used to invoke main to this method. At the moment it does + * not use these, but in the future they will be used to provide game-agnostic options. */ auto run(int argc, const char **argv) -> int; + /** + * Register a new state with the application. + * + * States are intended to be a block of code which can be started, will execute a single frame + * of work, and can be invoked repeatedly. For example, a main menu, options menu, + * single-player game and multi-player game might be all be suitable to be states. When a state + * change is requested, the currently running state is stopped and garabage collected. + * + * This is similar to the concept of an 'activity' in Android. + */ template<typename T> auto addState(const Identifer &name) -> T * { static_assert(std::is_base_of<AppState, T>::value, "States must be AppStates"); return m_states.put<T>(name, *this); } + /** + * Request the game changes states. + * + * This will be executed at the next opporunity (most likley next iteration of the game loop). + * Identifer should be an identifier used when calling addState, and the state should previouslly + * been registered using addState. + */ inline void change_state(const Identifer &name) { m_expectedScene = name; - /*m_states.active().deactivate(); - m_states.change(name); - m_states.active().activate();*/ } + /** + * Return the currently active state (the state that is currently executing). + */ inline auto active_state() const -> AppState & { return m_states.active(); } + /** + * Get a pointer to a service. + * + * This is the primary way in which states can get access to resources they require. + * + * returns nullptr if the service does not exist, or cannot be provided. + */ template<typename T> inline auto service() -> T * { try { diff --git a/include/fggl/modules/manager.hpp b/include/fggl/modules/manager.hpp index 48acb0c2d8aa6aaa49d76cc3c8bfbdcf49b3cc4d..b29490ef55160ec5e164394744abaca3fef77045 100644 --- a/include/fggl/modules/manager.hpp +++ b/include/fggl/modules/manager.hpp @@ -23,6 +23,7 @@ #include "fggl/debug/logging.hpp" #include "fggl/ds/graph.hpp" +#include <cassert> #include <queue> #include <vector> #include <map> @@ -86,6 +87,7 @@ namespace fggl::modules { addVirtual(config); } + // FIXME this should be in cpp file bool buildGraph() { // resolve links between modules for (auto &moduleItr : m_modules) { @@ -124,6 +126,7 @@ namespace fggl::modules { return { this }; } + //FIXME this should be in cpp file! void resolve() { assert( !m_locked ); if (!buildGraph()) {