diff --git a/README.md b/README.md index 111aa6e..5700f46 100644 --- a/README.md +++ b/README.md @@ -1 +1,47 @@ -# SDL Framework \ No newline at end of file +# SDL Framework + +A small wrapper around SDL2 that makes development of non-demanding small projects easier. + +## Installation + +Add this project as a git submodule and include it in your CMake project. Alternatively you can clone the repository, build the binaries and use them like any other library. + +## Usage + +This library provides a window interface, that could be used directly, however it is better to derive from it and overload some (or all) of the callback functions. + +```cpp +class MyWindow : public sf::IWindow +{ +public: + MyWindow() { /* Constructor Stuff */ } + +private: + virtual bool OnCreate() { return true; } + virtual void OnClose() { } + virtual bool OnEvent(const SDL_Event& event) { return true;} + virtual bool OnUpdate(double frametime) { return true; } + virtual void OnRender(SDL_Renderer* renderer) { } +}; +``` + +Then simple instantiate your new window and call `IWindow::Launch(threaded)` on it. `threaded` controls wether the message loop of your window will be executed in the main thread, or in a worker thread to allow for multiple parallel windows. + +### What do the callbacks do? +The callbacks in `sf::IWindow` can be overridden and are called at certain points in the windows lifecycle: + +* `bool IWindow::OnCreate()` is called immediately after the SDL_Window and SDL_Renderer are created, and before the message loop starts. If this callback returns `false`, the message loop will not start and the windows life cycle ends here +* `void IWindow::OnClose()` is called immediately after exiting the message loop, and before any objects are destroyed +* `bool OnEvent(const SDL_Event& event)` gets called for each event that is polled from the message queue. If it returns `false`, then `sd::IWindow` will not process that same event again. (e.g. you can block `sf::IWindow` from closing on an `SDL_QUIT` event. +* `bool OnUpdate(double frametime)` gets called every frame right before the rendering step. It provides the callback with the current frametime. Returnung `false` will quit the message loop. +* `void OnRender(SDL_Renderer* renderer)` gets called every frame right after the update step. There is no need to call `SDL_RenderPresent` as the message loop does that. The message loop does not clear the screen however. + +### What are screens? +If your program will always have the same content, then this isn't of interest to you. +However if you plan on having different menus, different types of screens etc, then you might wanna read this. +A screen is basically a window without a message loop. It has (almost) the same callbacks as an `sf::IWindow`, +the only difference being `IScreen::OnFocus()` and `IScreen::OnDefocus()` which are called when a screen is switched to, or switched from. +A window holds a pointer to an `sf::IScreen`. If that pointer is `nullptr`, the above callbacks will be called. If it isn't `nullptr` then the callbacks from the `sf::IScreen` will be called instead. +You can switch screens via a the `IWindow::SwitchScreen()` function. + +To use a screen, you simple derive from `sf::IScreen` and implement the callbacks. `IScreen::OnFocus()` receives the calling `sf::IWindow` as a parameter. \ No newline at end of file diff --git a/src/example/main.cpp b/src/example/main.cpp index 256923d..6ee9bbb 100644 --- a/src/example/main.cpp +++ b/src/example/main.cpp @@ -63,7 +63,7 @@ private: } }; - +#undef main int main(int argc, char* argv[]) { diff --git a/src/sdlf/Screen.hpp b/src/sdlf/Screen.hpp index b901a1f..171d2d4 100644 --- a/src/sdlf/Screen.hpp +++ b/src/sdlf/Screen.hpp @@ -1,21 +1,20 @@ #pragma once -#include "SDL.h" +#include "util/Callback.hpp" namespace sf { - class IScreen + class IScreen : public ICallback { public: - virtual void OnFocus() {} // Called when the screen is being switched to - virtual void OnDefocus() {} // Called when the screen is being switched from - virtual bool OnUpdate(double frametime) { return true; } // Called every frame - virtual void OnEvent(const SDL_Event& event) {} // Called after an event occurs - virtual void OnRender(SDL_Renderer* renderer) {} // Called for rendering + virtual void OnFocus(IWindow* parent) { } + virtual void OnDefocus() { } + virtual bool OnUpdate(double frametime) override { return true; } + virtual bool OnEvent(const SDL_Event& event) override { return true; } + virtual void OnRender(SDL_Renderer* renderer) override {} protected: IScreen() = default; - private: }; } \ No newline at end of file diff --git a/src/sdlf/Window.cpp b/src/sdlf/Window.cpp index b38607a..95388f2 100644 --- a/src/sdlf/Window.cpp +++ b/src/sdlf/Window.cpp @@ -87,7 +87,7 @@ namespace sf m_oUpdateFunction = std::bind(&IScreen::OnUpdate, m_pCurrentScreen, std::placeholders::_1); m_oRenderFunction = std::bind(&IScreen::OnRender, m_pCurrentScreen, std::placeholders::_1); - m_pCurrentScreen->OnFocus(); + m_pCurrentScreen->OnFocus(this); } else { @@ -120,11 +120,13 @@ namespace sf { while (SDL_PollEvent(&m_oEvent)) { - m_oEventFunction(m_oEvent); - - if (m_oEvent.type == SDL_QUIT) + if (m_oEventFunction(m_oEvent)) { - m_atomWindowOpen = false; + + if (m_oEvent.type == SDL_QUIT) + { + m_atomWindowOpen = false; + } } } diff --git a/src/sdlf/Window.hpp b/src/sdlf/Window.hpp index e56abbd..fdc2e64 100644 --- a/src/sdlf/Window.hpp +++ b/src/sdlf/Window.hpp @@ -5,8 +5,8 @@ #include #include -#include "SDL.h" #include "util/Vector2.hpp" +#include "util/Callback.hpp" #include "Screen.hpp" #define SDLF_REQUIRED_SUBSYSTEMS SDL_INIT_VIDEO @@ -15,7 +15,7 @@ namespace sf { typedef std::function EventCallback; - class IWindow + class IWindow : public ICallback { public: void Create(Vector2u size, Vector2i position, std::string title, Uint32 flags = SDL_WINDOW_RESIZABLE); @@ -34,9 +34,9 @@ namespace sf virtual bool OnCreate() { return true; } virtual void OnClose() { } - virtual void OnEvent(const SDL_Event& event) { } - virtual bool OnUpdate(double frametime) { return true; } - virtual void OnRender(SDL_Renderer* renderer) { } + virtual bool OnEvent(const SDL_Event& event) override { return true; } + virtual bool OnUpdate(double frametime) override { return true; } + virtual void OnRender(SDL_Renderer* renderer) override { } protected: SDL_Window* m_pWindow; @@ -58,7 +58,7 @@ namespace sf std::thread m_oMsgLoopThread; std::atomic_bool m_atomWindowOpen; - std::function m_oEventFunction; + std::function m_oEventFunction; std::function m_oUpdateFunction; std::function m_oRenderFunction; }; diff --git a/src/sdlf/util/Callback.hpp b/src/sdlf/util/Callback.hpp new file mode 100644 index 0000000..54d0907 --- /dev/null +++ b/src/sdlf/util/Callback.hpp @@ -0,0 +1,19 @@ +#pragma once + +namespace sf +{ + #include + + class ICallback + { + protected: + virtual bool OnEvent(const SDL_Event& event) = 0; + virtual bool OnUpdate(double frametime) = 0; + virtual void OnRender(SDL_Renderer* renderer) = 0; + + protected: + ICallback() = default; + ICallback(const ICallback& other) = delete; + ICallback& operator=(const ICallback& other) = delete; + }; +} \ No newline at end of file