diff --git a/include/RenderWindow.hpp b/include/RenderWindow.hpp index d4b7823..9623052 100644 --- a/include/RenderWindow.hpp +++ b/include/RenderWindow.hpp @@ -17,66 +17,154 @@ namespace kn { -/// @brief The renderer context. -/// @warning This class must be a singleton. +/** + * @brief The renderer context. + * + * @warning This class must be a singleton. + */ class RenderWindow final { public: - /// @brief Create a window. - /// @param title The title of the window. - /// @param scale The scale of the window. - /// @param fullscreen Whether to make the window fullscreen. - RenderWindow(const std::string &title = "Kraken Window", int scale = 1, bool fullscreen = false); - ~RenderWindow(); - - /// @brief Clear the screen. - /// @param color The color to clear the screen. - void cls(SDL_Color color = { 0, 0, 0, 255 }); - - /// @brief Flip the render frame buffer. - void flip(); - - /// @brief Draw a texture using rects. - /// @param texture The texture to draw. - /// @param crop The rectangle to draw from. - /// @param rect The rectangle to draw to. - void blit(const std::shared_ptr& texture, Rect crop, Rect rect); - - /// @brief Draw a texture to a position. - /// @param texture The texture to draw. - /// @param position The position to draw at. - void blit(const std::shared_ptr& texture, const math::Vec2& position); - - /// @brief Draw a texture using rects. - /// @param texture The texture to draw. - /// @param crop The rectangle to draw from. - /// @param rect The rectangle to draw to. - /// @param angle The angle to draw the texture. - /// @param flipX Whether to flip the texture on the x-axis. - /// @param flipY Whether to flip the texture on the y-axis. - void blitEx(const std::shared_ptr& texture, Rect crop, Rect rect, double angle = 0.0, bool flipX = false, bool flipY = false); - - /// @brief Draw a texture to a position. - /// @param texture The texture to draw. - /// @param position The position to draw at. - /// @param angle The angle to draw the texture. - /// @param flipX Whether to flip the texture on the x-axis. - /// @param flipY Whether to flip the texture on the y-axis. - void blitEx(const std::shared_ptr& texture, const math::Vec2& position, double angle = 0.0, bool flipX = false, bool flipY = false); - - /// @brief Get the window renderer. - /// @return The window renderer. - SDL_Renderer* getRenderer() { return renderer; } - - /// @brief Get user events. - /// @return The user events. - const std::vector& getEvents(); - + /** + * @brief Get a reference to the instance of the singleton + * + * @return reference to the instance + */ + static RenderWindow& getInstance(); + + /** + * @brief Clear the screen. + * + * @param color The color to clear the screen. + */ + void cls(SDL_Color color = { 0, 0, 0, 255 }); + + /** + * @brief Flip the render frame buffer. + */ + void flip(); + + /** + * @brief Draw a texture using rects. + * + * @param texture The texture to draw. + * @param crop The rectangle to draw from. + * @param rect The rectangle to draw to. + */ + void blit(const std::shared_ptr& texture, Rect crop, Rect rect); + + /** + * @brief Draw a texture to a position. + * @param texture The texture to draw. + * @param position The position to draw at. + */ + void blit(const std::shared_ptr& texture, const math::Vec2& position); + + /** + * @brief Draw a texture using rects. + * @param texture The texture to draw. + * @param crop The rectangle to draw from. + * @param rect The rectangle to draw to. + * @param angle The angle to draw the texture. + * @param flipX Whether to flip the texture on the x-axis. + * @param flipY Whether to flip the texture on the y-axis. + */ + void blitEx(const std::shared_ptr& texture, Rect crop, Rect rect, double angle = 0.0, bool flipX = false, bool flipY = false); + + /** + * @brief Draw a texture to a position. + * @param texture The texture to draw. + * @param position The position to draw at. + * @param angle The angle to draw the texture. + * @param flipX Whether to flip the texture on the x-axis. + * @param flipY Whether to flip the texture on the y-axis. + */ + void blitEx(const std::shared_ptr& texture, const math::Vec2& position, double angle = 0.0, bool flipX = false, bool flipY = false); + + /** + * @brief Get the window renderer. + * @return The window renderer. + */ + SDL_Renderer* getRenderer() { return m_renderer; } + + /** + * @brief Get user events. + * @return The user events. + */ + const std::vector& getEvents(); + + /** + * @brief Get the title of the window + * + * @return the title + */ + const std::string getTitle() const; + + /** + * @brief Get whether the window is fullscreen or not + * + * @return true if fullscreen + * @return false otherwise + */ + bool getFullscreen() const; + + /** + * @brief Get the scale of the window + * + * @return the scale + */ + static int getScale(); + + /** + * @brief Set the title of the window + * + * @param newTitle the new title + */ + void setTitle(const std::string& newTitle); + + /** + * @brief Set whether the window is fullscreen or not + * + * @param fullscreen true if setting fullscreen, false otherwise + */ + void setFullscreen(bool fullscreen); + + /** + * @brief Set the scale of the window. Only valid before instantiating + * RenderWindow for the first time + * + * @param newScale the scale of the window + * + * @return true if successfully set scale + * @return false otherwise + */ + static bool setScale(int newScale); + private: - SDL_Renderer* renderer = nullptr; - SDL_Window* window = nullptr; + /** + * @brief Private constructor for singleton design pattern + */ + RenderWindow(); + + /** + * @brief Destructor + */ + ~RenderWindow(); + + /** + * @brief Deleted copy constructor to prevent copy + */ + RenderWindow(const RenderWindow& other) = delete; + + /** + * @brief Deleted assignment operator to prevent assignment + */ + RenderWindow& operator=(const RenderWindow& rhs) = delete; + + SDL_Renderer* m_renderer = nullptr; + SDL_Window* m_window = nullptr; - KN_Event event; - std::vector events; + KN_Event m_event; + std::vector m_events; }; } diff --git a/src/render_window.cpp b/src/render_window.cpp index de8a8c2..4dc85e4 100644 --- a/src/render_window.cpp +++ b/src/render_window.cpp @@ -1,145 +1,211 @@ #include +#include "SDL.h" + #include "../include/RenderWindow.hpp" namespace kn { -RenderWindow::RenderWindow(const std::string &title, int scale, bool fullscreen) { - if (SDL_Init(SDL_INIT_VIDEO)) { - std::cerr << "SDL_Init Error: " << SDL_GetError() << std::endl; - exit(3); - } - if (!IMG_Init(IMG_INIT_PNG)) { - std::cerr << "IMG_Init Error: " << IMG_GetError() << std::endl; - SDL_Quit(); - exit(3); - } - if (TTF_Init() < 0) { - std::cerr << "TTF_Init Error: " << TTF_GetError() << std::endl; - IMG_Quit(); - SDL_Quit(); - exit(3); - } - if (Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 2048) < 0) { - std::cerr << "Mix_OpenAudio Error: " << Mix_GetError() << std::endl; - TTF_Quit(); - IMG_Quit(); - SDL_Quit(); - } - - scale = std::min(std::max(scale, 1), 32); +static int scale = 1; +static bool instanceCreated = false; +static std::string title = "Kraken"; +static bool fullscreen = false; - this->window = SDL_CreateWindow( - title.c_str(), - SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, - (int)SCREEN_SIZE.x * scale, (int)SCREEN_SIZE.y * scale, - fullscreen ? SDL_WINDOW_FULLSCREEN : SDL_WINDOW_SHOWN - ); - if (!window) { - std::cerr << "SDL_CreateWindow Error: " << SDL_GetError() << std::endl; - SDL_Quit(); - exit(3); - } +RenderWindow& RenderWindow::getInstance() +{ + static RenderWindow __instance; + instanceCreated = true; - renderer = SDL_CreateRenderer( - window, -1, SDL_RENDERER_ACCELERATED - ); - - if (!renderer) { - std::cerr << "SDL_CreateRenderer Error: " << SDL_GetError() << std::endl; - SDL_DestroyWindow(window); - SDL_Quit(); - exit(3); - } + return __instance; +} - if (scale > 1) { - SDL_RenderSetLogicalSize(renderer, SCREEN_SIZE.x, SCREEN_SIZE.y); - SDL_RenderSetIntegerScale(renderer, SDL_TRUE); - } +RenderWindow::RenderWindow() +{ + if (SDL_Init(SDL_INIT_VIDEO)) { + std::cerr << "SDL_Init Error: " << SDL_GetError() << std::endl; + exit(3); + } + if (!IMG_Init(IMG_INIT_PNG)) { + std::cerr << "IMG_Init Error: " << IMG_GetError() << std::endl; + SDL_Quit(); + exit(3); + } + if (TTF_Init() < 0) { + std::cerr << "TTF_Init Error: " << TTF_GetError() << std::endl; + IMG_Quit(); + SDL_Quit(); + exit(3); + } + if (Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 2048) < 0) { + std::cerr << "Mix_OpenAudio Error: " << Mix_GetError() << std::endl; + TTF_Quit(); + IMG_Quit(); + SDL_Quit(); + } + + this->m_window = SDL_CreateWindow( + title.c_str(), + SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, + (int)SCREEN_SIZE.x * scale, (int)SCREEN_SIZE.y * scale, + fullscreen ? SDL_WINDOW_FULLSCREEN : SDL_WINDOW_SHOWN + ); + + if (!m_window) { + std::cerr << "SDL_CreateWindow Error: " << SDL_GetError() << std::endl; + SDL_Quit(); + exit(3); + } + + m_renderer = SDL_CreateRenderer( + m_window, -1, SDL_RENDERER_ACCELERATED + ); + + if (!m_renderer) { + std::cerr << "SDL_CreateRenderer Error: " << SDL_GetError() << std::endl; + SDL_DestroyWindow(m_window); + SDL_Quit(); + exit(3); + } + + if (scale > 1) { + SDL_RenderSetLogicalSize(m_renderer, SCREEN_SIZE.x, SCREEN_SIZE.y); + SDL_RenderSetIntegerScale(m_renderer, SDL_TRUE); + } } RenderWindow::~RenderWindow() { - SDL_DestroyRenderer(renderer); - SDL_DestroyWindow(window); - Mix_CloseAudio(); - IMG_Quit(); - TTF_Quit(); - SDL_Quit(); + SDL_DestroyRenderer(m_renderer); + SDL_DestroyWindow(m_window); + Mix_CloseAudio(); + IMG_Quit(); + TTF_Quit(); + SDL_Quit(); } const std::vector& RenderWindow::getEvents() { - events.clear(); - while (SDL_PollEvent(&event)) { - events.push_back(event); - } - return events; + m_events.clear(); + while (SDL_PollEvent(&m_event)) { + m_events.push_back(m_event); + } + return m_events; } void RenderWindow::cls(SDL_Color color) { - SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, color.a); - SDL_RenderClear(renderer); + SDL_SetRenderDrawColor(m_renderer, color.r, color.g, color.b, color.a); + SDL_RenderClear(m_renderer); } void RenderWindow::flip() { - SDL_RenderPresent(renderer); + SDL_RenderPresent(m_renderer); } void RenderWindow::blit(const std::shared_ptr& texture, Rect crop, Rect rect) { - if (crop.getSize() == math::Vec2::ZERO()) { - SDL_RenderCopyF(renderer, texture->getSDLTexture(), nullptr, &rect); - return; - } - SDL_Rect src; - src.x = crop.x; - src.y = crop.y; - src.w = crop.w; - src.h = crop.h; - SDL_RenderCopyF(renderer, texture->getSDLTexture(), &src, &rect); + if (crop.getSize() == math::Vec2::ZERO()) { + SDL_RenderCopyF(m_renderer, texture->getSDLTexture(), nullptr, &rect); + return; + } + SDL_Rect src; + src.x = crop.x; + src.y = crop.y; + src.w = crop.w; + src.h = crop.h; + SDL_RenderCopyF(m_renderer, texture->getSDLTexture(), &src, &rect); } void RenderWindow::blit(const std::shared_ptr& texture, const math::Vec2& position) { - SDL_FRect rect = { - position.x, position.y, - texture->getSize().x, texture->getSize().y - }; - SDL_RenderCopyF(renderer, texture->getSDLTexture(), nullptr, &rect); + SDL_FRect rect = { + position.x, position.y, + texture->getSize().x, texture->getSize().y + }; + SDL_RenderCopyF(m_renderer, texture->getSDLTexture(), nullptr, &rect); } void RenderWindow::blitEx(const std::shared_ptr& texture, Rect crop, Rect rect, double angle, bool flipX, bool flipY) { - SDL_RendererFlip flip = SDL_FLIP_NONE; - if (flipX) { - flip = (SDL_RendererFlip)(flip | SDL_FLIP_HORIZONTAL); - } - if (flipY) { - flip = (SDL_RendererFlip)(flip | SDL_FLIP_VERTICAL); - } - if (crop.getSize() == math::Vec2::ZERO()) { - SDL_RenderCopyExF(renderer, texture->getSDLTexture(), nullptr, &rect, angle, nullptr, flip); - return; - } - SDL_Rect src; - src.x = crop.x; - src.y = crop.y; - src.w = crop.w; - src.h = crop.h; - SDL_RenderCopyExF(renderer, texture->getSDLTexture(), &src, &rect, angle, nullptr, flip); + SDL_RendererFlip flip = SDL_FLIP_NONE; + if (flipX) { + flip = (SDL_RendererFlip)(flip | SDL_FLIP_HORIZONTAL); + } + if (flipY) { + flip = (SDL_RendererFlip)(flip | SDL_FLIP_VERTICAL); + } + if (crop.getSize() == math::Vec2::ZERO()) { + SDL_RenderCopyExF(m_renderer, texture->getSDLTexture(), nullptr, &rect, angle, nullptr, flip); + return; + } + SDL_Rect src; + src.x = crop.x; + src.y = crop.y; + src.w = crop.w; + src.h = crop.h; + SDL_RenderCopyExF(m_renderer, texture->getSDLTexture(), &src, &rect, angle, nullptr, flip); } void RenderWindow::blitEx(const std::shared_ptr& texture, const math::Vec2& position, double angle, bool flipX, bool flipY) { - SDL_RendererFlip flip = SDL_FLIP_NONE; - if (flipX) { - flip = (SDL_RendererFlip)(flip | SDL_FLIP_HORIZONTAL); + SDL_RendererFlip flip = SDL_FLIP_NONE; + if (flipX) { + flip = (SDL_RendererFlip)(flip | SDL_FLIP_HORIZONTAL); + } + if (flipY) { + flip = (SDL_RendererFlip)(flip | SDL_FLIP_VERTICAL); + } + SDL_FRect rect = { + position.x, position.y, + texture->getSize().x, texture->getSize().y + }; + SDL_RenderCopyExF(m_renderer, texture->getSDLTexture(), nullptr, &rect, angle, nullptr, flip); +} + +const std::string RenderWindow::getTitle() const +{ + if (m_window != nullptr) + { + return SDL_GetWindowTitle(m_window); } - if (flipY) { - flip = (SDL_RendererFlip)(flip | SDL_FLIP_VERTICAL); + return title; +} + +bool RenderWindow::getFullscreen() const +{ + return (SDL_GetWindowFlags(m_window) & SDL_WINDOW_FULLSCREEN) > 0; +} + +int RenderWindow::getScale() +{ + return scale; +} + +void RenderWindow::setTitle(const std::string& newTitle) +{ + title = newTitle; + + if (m_window != nullptr) + { + SDL_SetWindowTitle(m_window, newTitle.c_str()); } - SDL_FRect rect = { - position.x, position.y, - texture->getSize().x, texture->getSize().y - }; - SDL_RenderCopyExF(renderer, texture->getSDLTexture(), nullptr, &rect, angle, nullptr, flip); } +void RenderWindow::setFullscreen(bool fullscreenValue) +{ + fullscreen = fullscreenValue; + + if (m_window != nullptr) + { + SDL_SetWindowFullscreen(m_window, fullscreen); + } +} + +bool RenderWindow::setScale(int newScale) +{ + if (instanceCreated) + { + std::cout << "Cannot set scale after creating the window\n"; + return false; + } + + scale = std::min(std::max(newScale, 1), 32); + + return true; +} }