From 1795b83c408288d9bd08f8252a843330c1ff3150 Mon Sep 17 00:00:00 2001 From: Flavien Chenu Date: Tue, 2 Apr 2024 22:14:01 +0200 Subject: [PATCH 01/12] feat(graphics:sdl2): copy SFML implementation for SDL2 adapting --- graphics/sdl2/CMakeLists.txt | 25 +++ graphics/sdl2/export.cpp | 26 +++ graphics/sdl2/src/GraphicsProvider.cpp | 51 +++++ graphics/sdl2/src/GraphicsProvider.hpp | 68 ++++++ graphics/sdl2/src/font/Font.cpp | 26 +++ graphics/sdl2/src/font/Font.hpp | 32 +++ graphics/sdl2/src/sound/Sound.cpp | 63 ++++++ graphics/sdl2/src/sound/Sound.hpp | 34 +++ graphics/sdl2/src/texture/Texture.cpp | 25 +++ graphics/sdl2/src/texture/Texture.hpp | 31 +++ graphics/sdl2/src/window/EventsHandler.cpp | 227 +++++++++++++++++++++ graphics/sdl2/src/window/EventsHandler.hpp | 137 +++++++++++++ graphics/sdl2/src/window/Renderer.cpp | 135 ++++++++++++ graphics/sdl2/src/window/Renderer.hpp | 112 ++++++++++ graphics/sdl2/src/window/Window.cpp | 171 ++++++++++++++++ graphics/sdl2/src/window/Window.hpp | 171 ++++++++++++++++ 16 files changed, 1334 insertions(+) create mode 100644 graphics/sdl2/CMakeLists.txt create mode 100644 graphics/sdl2/export.cpp create mode 100644 graphics/sdl2/src/GraphicsProvider.cpp create mode 100644 graphics/sdl2/src/GraphicsProvider.hpp create mode 100644 graphics/sdl2/src/font/Font.cpp create mode 100644 graphics/sdl2/src/font/Font.hpp create mode 100644 graphics/sdl2/src/sound/Sound.cpp create mode 100644 graphics/sdl2/src/sound/Sound.hpp create mode 100644 graphics/sdl2/src/texture/Texture.cpp create mode 100644 graphics/sdl2/src/texture/Texture.hpp create mode 100644 graphics/sdl2/src/window/EventsHandler.cpp create mode 100644 graphics/sdl2/src/window/EventsHandler.hpp create mode 100644 graphics/sdl2/src/window/Renderer.cpp create mode 100644 graphics/sdl2/src/window/Renderer.hpp create mode 100644 graphics/sdl2/src/window/Window.cpp create mode 100644 graphics/sdl2/src/window/Window.hpp diff --git a/graphics/sdl2/CMakeLists.txt b/graphics/sdl2/CMakeLists.txt new file mode 100644 index 0000000..2575c2e --- /dev/null +++ b/graphics/sdl2/CMakeLists.txt @@ -0,0 +1,25 @@ +project(sdl2) +add_library(sdl2 SHARED + export.cpp + src/GraphicsProvider.cpp + src/GraphicsProvider.hpp + src/window/Window.cpp + src/window/Window.hpp + src/window/EventsHandler.cpp + src/window/EventsHandler.hpp + src/sound/Sound.cpp + src/sound/Sound.hpp + src/texture/Texture.cpp + src/texture/Texture.hpp + src/font/Font.cpp + src/font/Font.hpp + src/window/Renderer.cpp + src/window/Renderer.hpp +) +add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/../common PRIVATE) + +target_include_directories(sdl2 PUBLIC ${CMAKE_CURRENT_LIST_DIR}/src) +target_include_directories(sdl2 PUBLIC ${CMAKE_CURRENT_LIST_DIR}/../..) +target_include_directories(sdl2 PUBLIC ${CMAKE_CURRENT_LIST_DIR}/..) + +target_link_libraries(sdl2 sfml-graphics sfml-window sfml-system sfml-audio) diff --git a/graphics/sdl2/export.cpp b/graphics/sdl2/export.cpp new file mode 100644 index 0000000..911cebc --- /dev/null +++ b/graphics/sdl2/export.cpp @@ -0,0 +1,26 @@ +/* +** EPITECH PROJECT, 2024 +** arcade-shared +** File description: +** export +*/ + +#include "shared/games/IGameProvider.hpp" +#include "shared/types/Libraries.hpp" +#include "src/GraphicsProvider.hpp" + +using namespace arcade::graphics; +using namespace shared::graphics; +using namespace shared::types; + +extern "C" { + LibraryType SHARED_LIBRARY_TYPE_GETTER_NAME(void) + { + return LibraryType::GRAPHIC; + } + + IGraphicsProvider *SHARED_GRAPHICS_PROVIDER_GETTER_NAME(void) + { + return new sdl2::GraphicsProvider(); + } +} diff --git a/graphics/sdl2/src/GraphicsProvider.cpp b/graphics/sdl2/src/GraphicsProvider.cpp new file mode 100644 index 0000000..5524070 --- /dev/null +++ b/graphics/sdl2/src/GraphicsProvider.cpp @@ -0,0 +1,51 @@ +/* +** EPITECH PROJECT, 2024 +** GraphicsProvider.cpp +** File description: +** GraphicsProvider class +*/ + +#include +#include "GraphicsProvider.hpp" +#include "utils/compiler.hpp" +#include "window/Window.hpp" +#include "font/Font.hpp" +#include "sound/Sound.hpp" +#include "texture/Texture.hpp" + +using namespace arcade::graphics::sdl2; + +const GraphicsManifest GraphicsProvider::_manifest = { + .name = "sdl2", + .description = "SDL2 Library", + .version = "1.0", + .authors = { + { + .name = "Flavien Chenu", + .email = "flavien.chenu@epitech.eu", + .website = "https://github.com/flavien-chenu" + } + } +}; + +GraphicsProvider::GraphicsProvider() = default; + +const shared::graphics::GraphicsManifest &GraphicsProvider::getManifest() const noexcept { + return GraphicsProvider::_manifest; +} + +std::unique_ptr GraphicsProvider::createWindow(const IWindow::WindowInitProps &props) { + return std::make_unique(props); +} + +std::shared_ptr GraphicsProvider::createSound(const std::string &path) { + return std::make_shared(path); +} + +std::shared_ptrGraphicsProvider::createTexture(const std::string &bin, unused const std::string &ascii) { + return std::make_shared(bin); +} + +std::shared_ptr GraphicsProvider::createFont(const std::string &path) { + return std::make_shared(path); +} diff --git a/graphics/sdl2/src/GraphicsProvider.hpp b/graphics/sdl2/src/GraphicsProvider.hpp new file mode 100644 index 0000000..abefc2e --- /dev/null +++ b/graphics/sdl2/src/GraphicsProvider.hpp @@ -0,0 +1,68 @@ +/* +** EPITECH PROJECT, 2024 +** GraphicsProvider.hpp +** File description: +** GraphicsProvider class +*/ + +#pragma once + +#include "shared/graphics/ITexture.hpp" +#include "shared/graphics/IGraphicsProvider.hpp" + +namespace arcade::graphics::sdl2 +{ + using namespace shared::graphics; + + class GraphicsProvider; +} + +class arcade::graphics::sdl2::GraphicsProvider : public IGraphicsProvider +{ +public: + GraphicsProvider(); + ~GraphicsProvider() override = default; + + /** + * @brief Get the manifest of the graphics library + * + * @return Manifest of the graphics library + */ + const GraphicsManifest &getManifest() const noexcept override; + + /** + * @brief Create a renderer object + * + * @param windowProps Properties to use to init the window + * @return Created renderer object + */ + std::unique_ptr createWindow(const IWindow::WindowInitProps &windowProps) override; + + /** + * @brief Create a sound object + * + * @param path Path of the sound file + * @return Created sound object + */ + std::shared_ptr createSound(const std::string &path) override; + + /** + * @brief Create a texture object + * + * @param bin Path of the binary texture file + * @param ascii Path of the ascii texture file + * @return Created texture object + */ + std::shared_ptr createTexture(const std::string &bin, const std::string &ascii) override; + + /** + * @brief Create a font object + * + * @param path Path of the font file + * @return Created font object + */ + std::shared_ptr createFont(const std::string &path) override; + +protected: + static const GraphicsManifest _manifest; +}; diff --git a/graphics/sdl2/src/font/Font.cpp b/graphics/sdl2/src/font/Font.cpp new file mode 100644 index 0000000..8c7a0bb --- /dev/null +++ b/graphics/sdl2/src/font/Font.cpp @@ -0,0 +1,26 @@ +/* +** EPITECH PROJECT, 2024 +** arcade +** File description: +** Font.cpp +*/ + +#include "Font.hpp" +#include "common/exceptions/FontException.hpp" + +using namespace arcade::graphics::sdl2::font; +using namespace arcade::graphics::common::exceptions; + +Font::Font(const std::string &path) +{ + if (!_font.loadFromFile(path)) + throw FontException( + "Failed to load font at: " + path, + "Font constructor in SDL2 library" + ); +} + +sf::Font &Font::getInnerFont() +{ + return _font; +} diff --git a/graphics/sdl2/src/font/Font.hpp b/graphics/sdl2/src/font/Font.hpp new file mode 100644 index 0000000..052b414 --- /dev/null +++ b/graphics/sdl2/src/font/Font.hpp @@ -0,0 +1,32 @@ +/* +** EPITECH PROJECT, 2024 +** arcade +** File description: +** Font.hpp +*/ + +#pragma once + +#include +#include +#include "shared/graphics/IFont.hpp" +#include "utils/compiler.hpp" + +namespace arcade::graphics::sdl2::font { + class Font; +} + +class arcade::graphics::sdl2::font::Font : public shared::graphics::IFont { +public: + explicit Font(const std::string &path); + ~Font() override = default; + + /** + * @brief Get the inner SDL2 font + * @return Reference to the inner SDL2 font + */ + sf::Font &getInnerFont(); + +private: + sf::Font _font; +}; diff --git a/graphics/sdl2/src/sound/Sound.cpp b/graphics/sdl2/src/sound/Sound.cpp new file mode 100644 index 0000000..b75a486 --- /dev/null +++ b/graphics/sdl2/src/sound/Sound.cpp @@ -0,0 +1,63 @@ +/* +** EPITECH PROJECT, 2024 +** arcade +** File description: +** Sound.cpp +*/ + +#include "Sound.hpp" +#include "common/exceptions/SoundException.hpp" + +using namespace arcade::graphics::sdl2::sound; +using namespace arcade::graphics::common::exceptions; + +Sound::Sound(const std::string &path, SoundState state) { + if(!_buffer.loadFromFile(path)) { + throw SoundException( + "Failed to load sound at: " + path, + "Sound constructor in SDL2 library" + ); + } + _sound.setBuffer(_buffer); + _sound.stop(); +} + +Sound::SoundVolume Sound::getVolume() const { + return static_cast(_sound.getVolume()); +} + +void Sound::setVolume(SoundVolume volume) { + _sound.setVolume(volume); +} + +void Sound::setState(SoundState state) { + switch (state) { + case PLAY: + return _sound.play(); + case PAUSE: + return _sound.pause(); + case STOP: + return _sound.stop(); + } +} + +Sound::SoundState Sound::getState() const { + auto state = _sound.getStatus(); + + switch (state) { + case sf::Sound::Playing: + return PLAY; + case sf::Sound::Paused: + return PAUSE; + default: + return STOP; + } +} + +void Sound::setLoopState(bool loop) { + _sound.setLoop(loop); +} + +bool Sound::getLoopState() const { + return _sound.getLoop(); +} diff --git a/graphics/sdl2/src/sound/Sound.hpp b/graphics/sdl2/src/sound/Sound.hpp new file mode 100644 index 0000000..bf83f77 --- /dev/null +++ b/graphics/sdl2/src/sound/Sound.hpp @@ -0,0 +1,34 @@ +/* +** EPITECH PROJECT, 2024 +** arcade +** File description: +** Sound.hpp +*/ + +#pragma once + +#include +#include + +#include "shared/graphics/ISound.hpp" + +namespace arcade::graphics::sdl2::sound { + class Sound; +} + +class arcade::graphics::sdl2::sound::Sound : public shared::graphics::ISound { +public: + explicit Sound(const std::string &path, SoundState state = STOP); + ~Sound() override = default; + + SoundVolume getVolume() const override; + SoundState getState() const override; + void setVolume(SoundVolume volume) override; + void setState(SoundState state) override; + void setLoopState(bool loop) override; + bool getLoopState() const override; + +private: + sf::SoundBuffer _buffer; + sf::Sound _sound; +}; diff --git a/graphics/sdl2/src/texture/Texture.cpp b/graphics/sdl2/src/texture/Texture.cpp new file mode 100644 index 0000000..9353532 --- /dev/null +++ b/graphics/sdl2/src/texture/Texture.cpp @@ -0,0 +1,25 @@ +/* +** EPITECH PROJECT, 2024 +** arcade +** File description: +** Texture.cpp +*/ + +#include "Texture.hpp" +#include "common/exceptions/TextureException.hpp" + +using namespace arcade::graphics::sdl2::texture; +using namespace arcade::graphics::common::exceptions; + +Texture::Texture(const std::string &path) { + if (!_texture.loadFromFile(path)) + throw TextureException( + "Failed to load texture at: " + path, + "Texture constructor in SDL2 library" + ); +} + +sf::Texture &Texture::getInnerTexture() +{ + return _texture; +} diff --git a/graphics/sdl2/src/texture/Texture.hpp b/graphics/sdl2/src/texture/Texture.hpp new file mode 100644 index 0000000..9283bd7 --- /dev/null +++ b/graphics/sdl2/src/texture/Texture.hpp @@ -0,0 +1,31 @@ +/* +** EPITECH PROJECT, 2024 +** arcade +** File description: +** Texture.hpp +*/ + +#pragma once + +#include +#include +#include "shared/graphics/ITexture.hpp" + +namespace arcade::graphics::sdl2::texture { + class Texture; +} + +class arcade::graphics::sdl2::texture::Texture: public shared::graphics::ITexture { +public: + explicit Texture(const std::string &path); + ~Texture() override = default; + + /** + * @brief Get the inner SDL2 texture + * @return Reference to the inner SDL2 texture + */ + sf::Texture &getInnerTexture(); + +private: + sf::Texture _texture; +}; diff --git a/graphics/sdl2/src/window/EventsHandler.cpp b/graphics/sdl2/src/window/EventsHandler.cpp new file mode 100644 index 0000000..eb8c9e1 --- /dev/null +++ b/graphics/sdl2/src/window/EventsHandler.cpp @@ -0,0 +1,227 @@ +/* +** EPITECH PROJECT, 2024 +** arcade +** File description: +** EventHandler.cpp +*/ + +#include + +#include "Window.hpp" +#include "EventsHandler.hpp" +#include "utils/compiler.hpp" + +using namespace arcade::graphics::sdl2::window; + +EventsHandler::EventHandler EventsHandler::_getHandler(sf::Event::EventType type) { + static std::map handlers = { + {sf::Event::KeyPressed, _handleKeyPressEvent}, + {sf::Event::KeyReleased, _handleKeyReleaseEvent}, + {sf::Event::MouseButtonPressed, _handleMouseButtonPressEvent}, + {sf::Event::MouseButtonReleased, _handleMouseBtnReleaseEvent}, + {sf::Event::MouseMoved, _handleMouseMoveEvent}, + {sf::Event::Closed, _handleWindowCloseEvent}, + {sf::Event::Resized, _handleWindowResizeEvent} + }; + auto handler = handlers.find(type); + + return handler != handlers.end() ? handler->second : nullptr; +} + +EventsHandler::EventsHandler(Window &window): _window(window) {} + +std::vector EventsHandler::handleEvents() { + std::vector events; + sf::Event SFMLEvent{}; + + while (_window.getInnerWindow().pollEvent(SFMLEvent)) { + auto handler = _getHandler(SFMLEvent.type); + auto event = handler ? handler(SFMLEvent, _window) : nullptr; + + if (event) + events.push_back(event); + } + return events; +} + +bool EventsHandler::_handleControlKey( + sf::Event::KeyEvent event, + IKeyEvent::KeyCode &code +) { + switch (event.code) { + case sf::Keyboard::LControl: + case sf::Keyboard::RControl: + case sf::Keyboard::LShift: + case sf::Keyboard::RShift: + case sf::Keyboard::LAlt: + case sf::Keyboard::RAlt: + return true; + + default: + return false; + } +} + +bool EventsHandler::_handleArrowKey( + sf::Event::KeyEvent event, + IKeyEvent::KeyCode &code +) { + switch (event.code) { + case sf::Keyboard::Left: + code.arrow = IKeyEvent::ArrowCode::LEFT; + return true; + case sf::Keyboard::Right: + code.arrow = IKeyEvent::ArrowCode::RIGHT; + return true; + case sf::Keyboard::Up: + code.arrow = IKeyEvent::ArrowCode::UP; + return true; + case sf::Keyboard::Down: + code.arrow = IKeyEvent::ArrowCode::DOWN; + return true; + default: + return false; + } +} + +bool EventsHandler::_handleFunctionKey( + sf::Event::KeyEvent event, + IKeyEvent::KeyCode &code +) +{ + if (event.code >= sf::Keyboard::F1 && event.code <= sf::Keyboard::F12) { + code.func = event.code - sf::Keyboard::F1 + 1; + return true; + } else { + return false; + } +} + +bool EventsHandler::_handleCharKey( + sf::Event::KeyEvent event, + IKeyEvent::KeyCode &code +) { + static const std::map specials = { + {sf::Keyboard::Space, ' '}, + {sf::Keyboard::LBracket, '['}, + {sf::Keyboard::RBracket, ']'}, + {sf::Keyboard::Semicolon, ';'}, + {sf::Keyboard::Comma, ','}, + {sf::Keyboard::Period, '.'}, + {sf::Keyboard::Quote, '\''}, + {sf::Keyboard::Slash, '/'}, + {sf::Keyboard::Backslash, '\\'}, + {sf::Keyboard::Tilde, '~'}, + {sf::Keyboard::Equal, '='}, + {sf::Keyboard::Hyphen, '-'}, + {sf::Keyboard::Enter, '\n'}, + {sf::Keyboard::Backspace, '\b'}, + {sf::Keyboard::Tab, '\t'}, + {sf::Keyboard::Escape, 0x1B}, + {sf::Keyboard::Add, '+'}, + {sf::Keyboard::Subtract, '-'}, + {sf::Keyboard::Multiply, '*'}, + {sf::Keyboard::Divide, '/'} + }; + + if (event.code >= sf::Keyboard::A && event.code <= sf::Keyboard::Z) { + code.character = static_cast(event.code - sf::Keyboard::A + 'a'); + } else if (event.code >= sf::Keyboard::Num0 && event.code <= sf::Keyboard::Num9) { + code.character = static_cast(event.code - sf::Keyboard::Num0 + '0'); + } else if (event.code >= sf::Keyboard::Numpad0 && event.code <= sf::Keyboard::Numpad9) { + code.character = static_cast(event.code - sf::Keyboard::Numpad0 + '0'); + } else { + auto special = specials.find(event.code); + + if (special != specials.end()) { + code.character = special->second; + } else { + return false; + } + } + return true; +} + +EventPtr EventsHandler::_handleKeyPressEvent(sf::Event &event, unused Window &window) { + IKeyEvent::KeyType type = IKeyEvent::KeyType::UNKNOWN; + IKeyEvent::KeyCode code; + + if (_handleControlKey(event.key, code)) + type = IKeyEvent::KeyType::CONTROL; + else if (_handleArrowKey(event.key, code)) + type = IKeyEvent::KeyType::ARROW; + else if (_handleFunctionKey(event.key, code)) + type = IKeyEvent::KeyType::FUNC; + else if (_handleCharKey(event.key, code)) + type = IKeyEvent::KeyType::CHAR; + return std::make_shared(type, code); +} + +EventPtr EventsHandler::_handleKeyReleaseEvent( + sf::Event &event, + unused Window &window +) { + IKeyEvent::KeyType type = IKeyEvent::KeyType::UNKNOWN; + IKeyEvent::KeyCode code; + + if (_handleControlKey(event.key, code)) + type = IKeyEvent::KeyType::CONTROL; + else if (_handleArrowKey(event.key, code)) + type = IKeyEvent::KeyType::ARROW; + else if (_handleFunctionKey(event.key, code)) + type = IKeyEvent::KeyType::FUNC; + else if (_handleCharKey(event.key, code)) + type = IKeyEvent::KeyType::CHAR; + return std::make_shared(type, code); +} + +EventPtr EventsHandler::_handleWindowCloseEvent( + unused sf::Event &event, + unused Window &window +) { + return std::make_shared(); +} + +EventPtr EventsHandler::_handleWindowResizeEvent( + unused sf::Event &event, + Window &window +) { + return std::make_shared(); +} + +EventPtr EventsHandler::_handleMouseMoveEvent( + sf::Event &event, + Window &window +) { + return std::make_shared( + window.pixelsToTiles(Vector2i(event.mouseMove.x, event.mouseMove.y)) + ); +} + +EventPtr EventsHandler::_handleMouseButtonPressEvent( + sf::Event &event, + Window &window +) { + Vector2i pos = window.pixelsToTiles(Vector2i(event.mouseButton.x, event.mouseButton.y)); + + if (event.mouseButton.button == sf::Mouse::Button::Left) + return std::make_shared(pos, IMouseButtonEvent::MouseButton::LEFT); + else if (event.mouseButton.button == sf::Mouse::Button::Right) + return std::make_shared(pos, IMouseButtonEvent::MouseButton::RIGHT); + else + return nullptr; +} + +EventPtr EventsHandler::_handleMouseBtnReleaseEvent( + sf::Event &event, + unused Window &window +) { + Vector2i pos = window.pixelsToTiles(Vector2i(event.mouseButton.x, event.mouseButton.y)); + + if (event.mouseButton.button == sf::Mouse::Button::Left) + return std::make_shared(pos, IMouseButtonEvent::MouseButton::LEFT); + else if (event.mouseButton.button == sf::Mouse::Button::Right) + return std::make_shared(pos, IMouseButtonEvent::MouseButton::RIGHT); + else + return nullptr; +} diff --git a/graphics/sdl2/src/window/EventsHandler.hpp b/graphics/sdl2/src/window/EventsHandler.hpp new file mode 100644 index 0000000..e7714d2 --- /dev/null +++ b/graphics/sdl2/src/window/EventsHandler.hpp @@ -0,0 +1,137 @@ +/* +** EPITECH PROJECT, 2024 +** arcade +** File description: +** EventHandler.hpp +*/ + +#pragma once + +#include +#include + +#include "common/events/window/window.hpp" +#include "common/events/mouse/mouse.hpp" +#include "common/events/key/key.hpp" + +namespace arcade::graphics::sdl2::window { + class EventsHandler; + class Window; +} + +class arcade::graphics::sdl2::window::EventsHandler { +public: + explicit EventsHandler(Window &window); + ~EventsHandler() = default; + + typedef EventPtr (*EventHandler)(sf::Event &event, Window &window); + + /** + * @brief Handle events from SDL2 + * @param window Window object + * @return Vector of events + */ + std::vector handleEvents(); + +private: + + static EventHandler _getHandler(sf::Event::EventType type); + + /** + * @brief Handle control key event if it's a control key + * @param event Event from SDL2 + * @param code Code of the key to set + * @return Status of handling + */ + static bool _handleControlKey(sf::Event::KeyEvent event, IKeyEvent::KeyCode &code); + + /** + * @brief Handle control key event if it's an arrow key + * @param event Event from SDL2 + * @param code Code of the key to set + * @return Status of handling + */ + static bool _handleArrowKey(sf::Event::KeyEvent event, IKeyEvent::KeyCode &code); + + /** + * @brief Handle control key event if it's a function key + * @param event Event from SDL2 + * @param code Code of the key to set + * @return Status of handling + */ + static bool _handleFunctionKey(sf::Event::KeyEvent event, IKeyEvent::KeyCode &code); + + /** + * @brief Handle control key event if it's a char key + * @param event Event from SDL2 + * @param code Code of the key to set + * @return Status of handling + */ + static bool _handleCharKey(sf::Event::KeyEvent event, IKeyEvent::KeyCode &code); + + /** + * @brief Handle key press event + * @param event Event from SDL2 + * @param window Window object + * @return Pointer to created event or null if not handled + */ + static EventPtr _handleKeyPressEvent(sf::Event &event, Window &window); + + /** + * @brief Handle key release event + * @param event Event from SDL2 + * @param window Window object + * @return Pointer to created event or null if not handled + */ + static EventPtr _handleKeyReleaseEvent(sf::Event &event, Window &window); + + /** + * @brief Handle mouse button press event + * @param event Event from SDL2 + * @param window Window object + * @return Pointer to created event or null if not handled + */ + static EventPtr _handleMouseButtonPressEvent(sf::Event &event, Window &window); + + /** + * @brief Handle mouse button release event + * @param event Event from SDL2 + * @param window Window object + * @return Pointer to created event or null if not handled + */ + static EventPtr _handleMouseBtnReleaseEvent(sf::Event &event, Window &window); + + /** + * @brief Handle mouse move event + * @param event Event from SDL2 + * @param window Window object + * @return Pointer to created event or null if not handled + */ + static EventPtr _handleMouseMoveEvent(sf::Event &event, Window &window); + + /** + * @brief Handle window close event + * @param event Event from SDL2 + * @param window Window object + * @return Pointer to created event or null if not handled + */ + static EventPtr _handleWindowCloseEvent(sf::Event &event, Window &window); + + /** + * @brief Handle window resize event + * @param event Event from SDL2 + * @param window Window object + * @return Pointer to created event or null if not handled + */ + static EventPtr _handleWindowResizeEvent(sf::Event &event, Window &window); + + /** + * @brief Resolve position of the event to convert it in tiles unit + * @param position Position to resolve + * @param window Window object of which relate the position + * @return Resolved position + */ + static Vector2i _resolvePosition(Vector2i position, Window &window); + + window::Window &_window; +}; diff --git a/graphics/sdl2/src/window/Renderer.cpp b/graphics/sdl2/src/window/Renderer.cpp new file mode 100644 index 0000000..48b53e7 --- /dev/null +++ b/graphics/sdl2/src/window/Renderer.cpp @@ -0,0 +1,135 @@ +/* +** EPITECH PROJECT, 2024 +** arcade +** File description: +** Renderer.cpp +*/ + +#include "Window.hpp" +#include "Renderer.hpp" +#include "font/Font.hpp" +#include "texture/Texture.hpp" +#include "common/exceptions/WindowException.hpp" + +using namespace arcade::graphics::sdl2::window; +using namespace arcade::graphics::common::exceptions; + +Renderer::Renderer(Window &window) : _window(window), _layer(_window.getInnerWindow()) { + _text.setFont(sf::Font()); + _sprite.setTexture(sf::Texture()); +} + +void Renderer::render(const shared::graphics::TextProps &props) { + auto font = _castOrThrow(props.font); + auto entityPosition = _entityPixelsPosition(props.position); + auto entitySize = _window.tilesToPixels(props.size); + + _reset(_text); + _text.setFont(font->getInnerFont()); + _text.setString(props.content); + _text.setCharacterSize(props.fontSize); + _text.setFillColor(sf::Color( + props.color.r, + props.color.g, + props.color.b, + props.color.a) + ); + _text.setPosition(entityPosition.x, entityPosition.y); + _textAlign(props.align, entitySize); + _textVerticalAlign(props.verticalAlign, entitySize); + _textAdjustPosition(); + _layer.draw(_text); +} + +void +Renderer::_textVerticalAlign(const shared::graphics::TextVerticalAlign &align, const shared::types::Vector2i &entitySize +) { + auto bounds = _text.getGlobalBounds(); + auto position = _text.getPosition(); + + if (align == shared::graphics::MIDDLE) { + position.y += (static_cast(entitySize.y) - bounds.height) / 2; + } else if (align == shared::graphics::BOTTOM) { + position.y += static_cast(entitySize.y) - bounds.height; + } + _text.setPosition(position); +} + +void Renderer::_textAlign(const shared::graphics::TextAlign &align, const shared::types::Vector2i &entitySize) { + auto bounds = _text.getGlobalBounds(); + auto position = _text.getPosition(); + + if (align == shared::graphics::CENTER) { + position.x += (static_cast(entitySize.x) - bounds.width) / 2; + } else if (align == shared::graphics::RIGHT) { + position.x += static_cast(entitySize.x) - bounds.width; + } + _text.setPosition(position); +} + +void Renderer::_textAdjustPosition() { + auto actual = _text.getPosition(); + sf::FloatRect bounds; + + _text.setPosition(0, 0); + bounds = _text.getGlobalBounds(); + _text.setPosition(actual.x - bounds.left, actual.y - bounds.top); +} + +void Renderer::render(const shared::graphics::TextureProps &props) { + auto texture = _castOrThrow(props.texture); + auto entityPosition = _entityPixelsPosition(props.position); + + _reset(_sprite); + _sprite.setTexture(texture->getInnerTexture()); + _sprite.setPosition(entityPosition.x, entityPosition.y); + _setTextureRectAndScale(props); + _layer.draw(_sprite); +} + +void Renderer::_setTextureRectAndScale(const shared::graphics::TextureProps &props) { + auto size = _window.tilesToPixels(props.size); + float width = static_cast(props.size.x) * props.binTileSize.x; + float height = static_cast(props.size.y) * props.binTileSize.y; + float left = static_cast(props.origin.x) * props.binTileSize.x; + float top = static_cast(props.origin.y) * props.binTileSize.y; + sf::IntRect rectangle = { + static_cast(left), + static_cast(top), + static_cast(width), + static_cast(height) + }; + + _sprite.setTextureRect(rectangle); + _sprite.setScale( + static_cast(size.x) / width, + static_cast(size.y) / height + ); +} + +void Renderer::_reset(sf::Text &text) { + text.setString(""); + text.setCharacterSize(0); + text.setFillColor(sf::Color::White); + text.setStyle(sf::Text::Regular); + text.setPosition(0, 0); + text.setScale(1, 1); + text.setOrigin(0, 0); +} + +void Renderer::_reset(sf::Sprite &sprite) { + sprite.setTextureRect(sf::IntRect(0, 0, 0, 0)); + sprite.setColor(sf::Color::White); + sprite.setScale(1, 1); + sprite.setPosition(0, 0); + sprite.setOrigin(0, 0); +} + +Vector2f Renderer::_entityPixelsPosition(const Vector2i &position) { + auto pixels = _window.tilesToPixels(position); + + return { + static_cast(pixels.x), + static_cast(pixels.y) + }; +} diff --git a/graphics/sdl2/src/window/Renderer.hpp b/graphics/sdl2/src/window/Renderer.hpp new file mode 100644 index 0000000..a95fbad --- /dev/null +++ b/graphics/sdl2/src/window/Renderer.hpp @@ -0,0 +1,112 @@ +/* +** EPITECH PROJECT, 2024 +** arcade +** File description: +** Renderer.hpp +*/ + +#pragma once + +#include +#include "shared/graphics/ITexture.hpp" +#include "shared/graphics/types/TextureProps.hpp" +#include "shared/graphics/types/TextProps.hpp" +#include "common/exceptions/WindowException.hpp" + +namespace arcade::graphics::sdl2::window { + class Renderer; + + class Window; +} + +class arcade::graphics::sdl2::window::Renderer { +public: + explicit Renderer(Window &window); + + ~Renderer() = default; + + /** + * @brief Render a texture on the window + * @param props Texture properties + */ + void render(const shared::graphics::TextureProps &props); + + /** + * @brief Render a text on the window + * @param props Text properties + */ + void render(const shared::graphics::TextProps &props); + +private: + Window &_window; + sf::RenderWindow &_layer; + sf::Text _text; + sf::Sprite _sprite; + + /** + * @brief Reset the text properties + * @param text Text to reset + */ + static void _reset(sf::Text &text); + + /** + * @brief Reset the sprite properties + * @param sprite Sprite to reset + */ + static void _reset(sf::Sprite &sprite); + + /** + * @brief Convert a tile position to pixel position + * @param position Tile position + * @return Pixel position + */ + Vector2f _entityPixelsPosition(const Vector2i &position); + + /** + * @brief Align vertically the text + * @param align Text alignment + * @param entityPos Entity position + * @param entitySize Entity size + */ + void _textVerticalAlign( + const shared::graphics::TextVerticalAlign &align, + const shared::types::Vector2i &entitySize + ); + + /** + * @brief Align the text + * @param align Text alignment + * @param entitySize Entity size + */ + void _textAlign(const shared::graphics::TextAlign &align, const shared::types::Vector2i &entitySize); + + /** + * @brief Adjust the text position + */ + void _textAdjustPosition(); + + /** + * @brief Set texture rect depending on the texture properties + * @param props Texture properties + */ + void _setTextureRectAndScale(const shared::graphics::TextureProps &props); + + /** + * @brief Cast a shared pointer from a type to another + * @tparam From Type from which to cast + * @tparam To Type to which cast + * @param from Value to cast + * @return Casted value + */ + template + static std::shared_ptr _castOrThrow(std::shared_ptr from) { + std::shared_ptr to = std::dynamic_pointer_cast(from); + if (!to) { + throw common::exceptions::WindowException( + "Failed to cast shared pointer of:" + std::string(typeid(from).name()) + " to " + typeid(to).name(), + "SDL2 Library Renderer::_castOrThrow" + ); + } + return to; + }; +}; diff --git a/graphics/sdl2/src/window/Window.cpp b/graphics/sdl2/src/window/Window.cpp new file mode 100644 index 0000000..11bece3 --- /dev/null +++ b/graphics/sdl2/src/window/Window.cpp @@ -0,0 +1,171 @@ +/* +** EPITECH PROJECT, 2024 +** Window.cpp +** File description: +** Window class +*/ + +#include "Window.hpp" +#include "EventsHandler.hpp" +#include "common/events/mouse/mouse.hpp" +#include "common/exceptions/WindowException.hpp" + +using namespace arcade::graphics::sdl2::window; +using namespace arcade::graphics::common::exceptions; + +const Vector2u Window::tileSize = { 12, 12 }; + +Window::Window(const IWindow::WindowInitProps &props): + _size(props.size), + _renderer(*this), + _eventsHandler(*this) +{ + auto size = _getPixelSizeFromTiles(props.size); + + _mode = props.mode; + _fps = props.fps; + _window.create( + sf::VideoMode(size.x, size.y), + props.title + ); + Window::setIcon(props.icon); +} + +Window::~Window() +{ + _window.close(); +} + +sf::RenderWindow &Window::getInnerWindow() noexcept { + return _window; +} + +void Window::setTitle(const std::string &title) { + _window.setTitle(title); +} + +void Window::setSize(shared::types::Vector2u size) { + auto real = _getPixelSizeFromTiles(size); + + _size = size; + _window.setSize(sf::Vector2u(real.x, real.y)); +} + +shared::types::Vector2u Window::getSize() const { + return _size; +} + +void Window::setFramerateLimit(unsigned int fps) { + _window.setFramerateLimit(fps); + _fps = fps; +} + +unsigned int Window::getFramerateLimit() const { + return _fps; +} + +void Window::setMode(IWindow::WindowMode mode) { + auto size = _window.getSize(); + + this->_mode = mode; + if (mode == FULLSCREEN) { + _window.create( + sf::VideoMode(size.x, size.y), + this->_title, + sf::Style::Fullscreen + ); + } else { + _window.create( + sf::VideoMode(size.x, size.y), + this->_title, + sf::Style::Default + ); + } +} + +Window::WindowMode Window::getMode() const { + return _mode; +} + +bool Window::isOpen() const { + return _window.isOpen(); +} + +void Window::setIcon(const std::string &path) { + if (path.empty()) + return; + if (!_icon.loadFromFile(path)) { + throw WindowException( + "Failed to load icon at: " + path, + "Window.setIcon in SDL2 library" + ); + } + _window.setIcon( + _icon.getSize().x, + _icon.getSize().y, + _icon.getPixelsPtr() + ); +} + +void Window::render(const shared::graphics::TextureProps &props) { + _renderer.render(props); +} + +void Window::render(const shared::graphics::TextProps &props) { + _renderer.render(props); +} + +void Window::clear() { + _window.clear(); +} + +void Window::display() { + _window.display(); +} + +void Window::close() { + _window.close(); +} + +std::vector Window::getEvents() { + return _eventsHandler.handleEvents(); +} + +Vector2u Window::_getPixelSizeFromTiles(const Vector2u &size) { + auto mode = sf::VideoMode::getDesktopMode(); + Vector2u real(mode.width, mode.height); + + if (size.x * static_cast(tileSize.x) < mode.width) + real.x = size.x * static_cast(tileSize.x); + if (size.y * static_cast(tileSize.y) < mode.height) + real.y = size.y * static_cast(tileSize.y); + return real; +} + +Vector2i Window::pixelsToTiles(const shared::types::Vector2i &position) const { + auto realSize = _window.getSize(); + + return { + static_cast(position.x * _size.x / realSize.x), + static_cast(position.y * _size.y / realSize.y) + }; +} + +Vector2i Window::tilesToPixels(const Vector2i &position) const { + auto realSize = _window.getSize(); + + return { + static_cast(position.x * realSize.x / _size.x), + static_cast(position.y * realSize.y / _size.y) + }; +} + +Vector2i Window::tilesToPixels(const Vector2u &position) const { + auto realSize = _window.getSize(); + + return { + static_cast(position.x * realSize.x / _size.x), + static_cast(position.y * realSize.y / _size.y) + }; +} + diff --git a/graphics/sdl2/src/window/Window.hpp b/graphics/sdl2/src/window/Window.hpp new file mode 100644 index 0000000..754f0e8 --- /dev/null +++ b/graphics/sdl2/src/window/Window.hpp @@ -0,0 +1,171 @@ +/* +** EPITECH PROJECT, 2024 +** Window.hpp +** File description: +** Window class +*/ + +#pragma once + +#include +#include "Renderer.hpp" +#include "shared/graphics/IWindow.hpp" +#include "EventsHandler.hpp" + +namespace arcade::graphics::sdl2::window { + class Window; +} + +class arcade::graphics::sdl2::window::Window: public shared::graphics::IWindow { +public: + explicit Window(const WindowInitProps &props); + ~Window() override; + + /** + * @brief Set the title of current window + * + * @param title Title of the window + */ + void setTitle(const std::string &title) override; + + /** + * @brief Set the size of the window + * + * @param size Size of the window + */ + void setSize(Vector2u size) override; + + /** + * @brief Get the size of the window + * + * @return Size of the window + */ + Vector2u getSize() const override; + + /** + * @brief Set the framerate Limit of the window + * + * @param fps Frame per seconds + */ + void setFramerateLimit(unsigned int fps) override; + + /** + * @brief Get the framerate Limit of the window + * + * @return Frame per seconds + */ + unsigned int getFramerateLimit() const override; + + /** + * @brief Set the mode of the window + * + * @param mode Mode to apply to the window + */ + void setMode(IWindow::WindowMode mode) override; + + /** + * @brief Get the mode of the window + * + * @return Mode of the window + */ + WindowMode getMode() const override; + + /** + * @brief Set the icon of the window + * + * @param icon Icon to use + */ + void setIcon(const std::string &icon) override; + + /** + * @brief Render the text with given properties + * + * @param props Properties of the entity to render + */ + void render(const shared::graphics::TextProps &props) override; + + /** + * @brief Render the entity with given properties + * + * @param props Properties of the entity to render + */ + void render(const shared::graphics::TextureProps &props) override; + + /** + * @brief Clear the content of the window + * + */ + void clear() override; + + /** + * @brief Display the content of the window + * + */ + void display() override; + + /** + * @brief Close the window + * + */ + void close() override; + + /** + * @brief Check if the window is open + * + * @return Open status of the window + */ + bool isOpen() const override; + + /** + * @brief Get the events object + * + * @return Last events occurred + * @warning Call successively this method will result in losing events + * @note Call `A` return `eventsA` containing 2 events, + * but make another call `B` (directly after call `A`) `eventsB` + * will result to an empty vector + */ + std::vector getEvents() override; + + /** + * @brief Get the window object + * @return Window object + */ + sf::RenderWindow &getInnerWindow() noexcept; + + /** + * @brief Convert a position in pixels to a position in tiles + * @return Converted position + */ + Vector2i pixelsToTiles(const Vector2i &position) const; + + /** + * @brief Convert a position in tiles to a position in pixels + * @return Converted position + */ + Vector2i tilesToPixels(const Vector2i &position) const; + + /** + * @brief Convert a position in tiles to a position in pixels + * @return Converted position + */ + Vector2i tilesToPixels(const Vector2u &position) const; + + /** + * @brief Get the size of a tile + * @return Size of a tile + */ + static const Vector2u tileSize; + +private: + static Vector2u _getPixelSizeFromTiles(const Vector2u &size); + + EventsHandler _eventsHandler; + Renderer _renderer; + sf::RenderWindow _window; + std::string _title; + unsigned int _fps; + WindowMode _mode; + sf::Image _icon; + Vector2u _size; +}; From bc24d4d308cd7d1421cb2a207214a9c90007a193 Mon Sep 17 00:00:00 2001 From: Flavien Chenu Date: Fri, 5 Apr 2024 00:28:32 +0200 Subject: [PATCH 02/12] feat(graphics:sdl): add SDL wrapper and some graphics provider objects --- graphics/CMakeLists.txt | 1 + graphics/sdl2/CMakeLists.txt | 15 ++- graphics/sdl2/sdl/CMakeLists.txt | 21 ++++ graphics/sdl2/sdl/exception/Exception.cpp | 20 +++ graphics/sdl2/sdl/exception/Exception.hpp | 29 +++++ graphics/sdl2/sdl/initializer/Initializer.cpp | 57 +++++++++ graphics/sdl2/sdl/initializer/Initializer.hpp | 59 +++++++++ graphics/sdl2/sdl/renderer/Renderer.cpp | 70 +++++++++++ graphics/sdl2/sdl/renderer/Renderer.hpp | 73 +++++++++++ graphics/sdl2/sdl/surface/Surface.cpp | 64 ++++++++++ graphics/sdl2/sdl/surface/Surface.hpp | 56 +++++++++ graphics/sdl2/sdl/text/Font.cpp | 65 ++++++++++ graphics/sdl2/sdl/text/Font.hpp | 64 ++++++++++ graphics/sdl2/sdl/text/Text.cpp | 101 +++++++++++++++ graphics/sdl2/sdl/text/Text.hpp | 117 ++++++++++++++++++ graphics/sdl2/sdl/texture/Texture.cpp | 51 ++++++++ graphics/sdl2/sdl/texture/Texture.hpp | 63 ++++++++++ graphics/sdl2/sdl/types/Color.hpp | 42 +++++++ graphics/sdl2/sdl/types/Rect.hpp | 77 ++++++++++++ graphics/sdl2/sdl/window/Window.cpp | 83 +++++++++++++ graphics/sdl2/sdl/window/Window.hpp | 98 +++++++++++++++ graphics/sdl2/src/GraphicsProvider.cpp | 7 +- graphics/sdl2/src/GraphicsProvider.hpp | 1 + graphics/sdl2/src/font/Font.cpp | 7 +- graphics/sdl2/src/font/Font.hpp | 6 +- graphics/sdl2/src/texture/Texture.cpp | 10 +- graphics/sdl2/src/texture/Texture.hpp | 9 +- graphics/sdl2/src/types/renderer.hpp | 18 +++ graphics/sdl2/src/types/surface.hpp | 18 +++ graphics/sdl2/src/types/window.hpp | 18 +++ graphics/sdl2/src/window/EventsHandler.cpp | 4 +- graphics/sdl2/src/window/Renderer.cpp | 73 +++++------ graphics/sdl2/src/window/Renderer.hpp | 23 ++-- graphics/sdl2/src/window/Window.cpp | 92 +++++++------- graphics/sdl2/src/window/Window.hpp | 21 +++- graphics/sfml/CMakeLists.txt | 6 +- 36 files changed, 1419 insertions(+), 120 deletions(-) create mode 100644 graphics/sdl2/sdl/CMakeLists.txt create mode 100644 graphics/sdl2/sdl/exception/Exception.cpp create mode 100644 graphics/sdl2/sdl/exception/Exception.hpp create mode 100644 graphics/sdl2/sdl/initializer/Initializer.cpp create mode 100644 graphics/sdl2/sdl/initializer/Initializer.hpp create mode 100644 graphics/sdl2/sdl/renderer/Renderer.cpp create mode 100644 graphics/sdl2/sdl/renderer/Renderer.hpp create mode 100644 graphics/sdl2/sdl/surface/Surface.cpp create mode 100644 graphics/sdl2/sdl/surface/Surface.hpp create mode 100644 graphics/sdl2/sdl/text/Font.cpp create mode 100644 graphics/sdl2/sdl/text/Font.hpp create mode 100644 graphics/sdl2/sdl/text/Text.cpp create mode 100644 graphics/sdl2/sdl/text/Text.hpp create mode 100644 graphics/sdl2/sdl/texture/Texture.cpp create mode 100644 graphics/sdl2/sdl/texture/Texture.hpp create mode 100644 graphics/sdl2/sdl/types/Color.hpp create mode 100644 graphics/sdl2/sdl/types/Rect.hpp create mode 100644 graphics/sdl2/sdl/window/Window.cpp create mode 100644 graphics/sdl2/sdl/window/Window.hpp create mode 100644 graphics/sdl2/src/types/renderer.hpp create mode 100644 graphics/sdl2/src/types/surface.hpp create mode 100644 graphics/sdl2/src/types/window.hpp diff --git a/graphics/CMakeLists.txt b/graphics/CMakeLists.txt index 2715642..194a091 100644 --- a/graphics/CMakeLists.txt +++ b/graphics/CMakeLists.txt @@ -1,2 +1,3 @@ #add_subdirectory(ncurses) add_subdirectory(sfml) +add_subdirectory(sdl2) diff --git a/graphics/sdl2/CMakeLists.txt b/graphics/sdl2/CMakeLists.txt index 2575c2e..d4a4d88 100644 --- a/graphics/sdl2/CMakeLists.txt +++ b/graphics/sdl2/CMakeLists.txt @@ -15,11 +15,18 @@ add_library(sdl2 SHARED src/font/Font.hpp src/window/Renderer.cpp src/window/Renderer.hpp + src/types/window.hpp + src/types/surface.hpp + src/types/renderer.hpp ) add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/../common PRIVATE) +add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/sdl) -target_include_directories(sdl2 PUBLIC ${CMAKE_CURRENT_LIST_DIR}/src) -target_include_directories(sdl2 PUBLIC ${CMAKE_CURRENT_LIST_DIR}/../..) -target_include_directories(sdl2 PUBLIC ${CMAKE_CURRENT_LIST_DIR}/..) +target_include_directories(sdl2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src) +target_include_directories(sdl2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/../..) +target_include_directories(sdl2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}/..) +target_include_directories(sdl2 PRIVATE ${CMAKE_CURRENT_LIST_DIR}) -target_link_libraries(sdl2 sfml-graphics sfml-window sfml-system sfml-audio) +target_link_libraries(sdl2 + SDL2 SDL2_image SDL2_ttf +) diff --git a/graphics/sdl2/sdl/CMakeLists.txt b/graphics/sdl2/sdl/CMakeLists.txt new file mode 100644 index 0000000..a7d55ab --- /dev/null +++ b/graphics/sdl2/sdl/CMakeLists.txt @@ -0,0 +1,21 @@ +target_sources(${PROJECT_NAME} PUBLIC + window/Window.cpp + window/Window.hpp + exception/Exception.cpp + exception/Exception.hpp + renderer/Renderer.cpp + renderer/Renderer.hpp + surface/Surface.cpp + surface/Surface.hpp + types/Color.hpp + types/Rect.hpp + text/Font.cpp + text/Font.hpp + text/Text.cpp + text/Text.hpp + texture/Texture.cpp + texture/Texture.hpp + initializer/Initializer.cpp + initializer/Initializer.hpp +) + diff --git a/graphics/sdl2/sdl/exception/Exception.cpp b/graphics/sdl2/sdl/exception/Exception.cpp new file mode 100644 index 0000000..fd8f967 --- /dev/null +++ b/graphics/sdl2/sdl/exception/Exception.cpp @@ -0,0 +1,20 @@ +/* +** EPITECH PROJECT, 2024 +** arcade +** File description: +** Exception.cpp +*/ + +#include "Exception.hpp" + +#include + +using namespace sdl; + +SDLException::SDLException(std::string message) : _message(std::move(message)) { +} + + +const char *SDLException::what() const noexcept { + return _message.c_str(); +} diff --git a/graphics/sdl2/sdl/exception/Exception.hpp b/graphics/sdl2/sdl/exception/Exception.hpp new file mode 100644 index 0000000..e5770de --- /dev/null +++ b/graphics/sdl2/sdl/exception/Exception.hpp @@ -0,0 +1,29 @@ +/* +** EPITECH PROJECT, 2024 +** arcade +** File description: +** Exception.hpp +*/ + +#pragma once +#include +#include + +namespace sdl { + class SDLException; +} + +class sdl::SDLException: public std::exception { +public: + explicit SDLException(std::string message); + ~SDLException() override = default; + + /** + * @brief Get the exception message + * @return Message of the exception + */ + const char *what() const noexcept override; + +private: + const std::string _message; +}; diff --git a/graphics/sdl2/sdl/initializer/Initializer.cpp b/graphics/sdl2/sdl/initializer/Initializer.cpp new file mode 100644 index 0000000..92375d4 --- /dev/null +++ b/graphics/sdl2/sdl/initializer/Initializer.cpp @@ -0,0 +1,57 @@ +/* +** EPITECH PROJECT, 2024 +** arcade +** File description: +** Initializer.cpp +*/ + +#include "Initializer.hpp" + +#include +#include +#include +#include "sdl/exception/Exception.hpp" + +using namespace sdl; + +void Initializer::init() { + _initSDL(); + _initIMG(); + _initTTF(); +} + +void Initializer::quit() { + _quitTTF(); + _quitIMG(); + _quitSDL(); +} + +void Initializer::_initSDL() { + if (SDL_Init(SDL_INIT_VIDEO) != 0) + throw SDLException("Failed to initialize SDL2"); +} + +void Initializer::_quitSDL() { + if (SDL_WasInit(SDL_INIT_EVERYTHING)) + SDL_Quit(); +} + +void Initializer::_initIMG() { + auto flags = IMG_INIT_PNG | IMG_INIT_JPG | IMG_INIT_TIF | IMG_INIT_WEBP; + if ((IMG_Init(flags) & flags) != flags) + throw SDLException("Failed to initialize SDL2_image"); +} + +void Initializer::_quitIMG() { + IMG_Quit(); +} + +void Initializer::_initTTF() { + if (TTF_Init() != 0) + throw SDLException("Failed to initialize SDL2_ttf"); +} + +void Initializer::_quitTTF() { + if (TTF_WasInit()) + TTF_Quit(); +} diff --git a/graphics/sdl2/sdl/initializer/Initializer.hpp b/graphics/sdl2/sdl/initializer/Initializer.hpp new file mode 100644 index 0000000..fa7521a --- /dev/null +++ b/graphics/sdl2/sdl/initializer/Initializer.hpp @@ -0,0 +1,59 @@ +/* +** EPITECH PROJECT, 2024 +** arcade +** File description: +** Initializer.hpp +*/ + +#pragma once + +namespace sdl { + class Initializer; +} + +class sdl::Initializer { +public: + Initializer() = delete; + ~Initializer() = delete; + + /** + * @brief Initialize all SDL2 modules + */ + static void init(); + + /** + * @brief Quit all SDL2 modules + */ + static void quit(); + +private: + /** + * @brief Initialize SDL2 module + */ + static void _initSDL(); + + /** + * @brief Quit SDL2 module + */ + static void _quitSDL(); + + /** + * @brief Initialize SDL2_image module + */ + static void _initIMG(); + + /** + * @brief Quit SDL2_image module + */ + static void _quitIMG(); + + /** + * @brief Initialize SDL2_ttf module + */ + static void _initTTF(); + + /** + * @brief Quit SDL2_ttf module + */ + static void _quitTTF(); +}; diff --git a/graphics/sdl2/sdl/renderer/Renderer.cpp b/graphics/sdl2/sdl/renderer/Renderer.cpp new file mode 100644 index 0000000..2accf4d --- /dev/null +++ b/graphics/sdl2/sdl/renderer/Renderer.cpp @@ -0,0 +1,70 @@ +/* +** EPITECH PROJECT, 2024 +** arcade +** File description: +** Renderer.cpp +*/ + +#include "Renderer.hpp" +#include "sdl/text/Text.hpp" +#include "sdl/types/Color.hpp" +#include "sdl/window/Window.hpp" +#include "sdl/texture/Texture.hpp" +#include "sdl/exception/Exception.hpp" + +using namespace sdl; + +Renderer::Renderer(const Window &window) : _window(window) { + _renderer = nullptr; +} + +SDL_Renderer *Renderer::operator()() const { + return _renderer; +} + +Renderer &Renderer::create() { + _renderer = SDL_CreateRenderer(_window(), -1, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED); + if (!_renderer) + throw SDLException("Failed to create renderer"); + return *this; +} + +void Renderer::drawColor(Color color) { + if (SDL_SetRenderDrawColor(_safeRenderer(), color.r, color.g, color.b, color.a) < 0) + throw SDLException("Failed to set draw color"); +} + +void Renderer::clear() { + if (SDL_RenderClear(_safeRenderer()) < 0) + throw SDLException("Failed to clear renderer"); +} + +void Renderer::present() { + SDL_RenderPresent(_safeRenderer()); +} + +Renderer::~Renderer() { + if (_renderer) + SDL_DestroyRenderer(_renderer); +} + +SDL_Renderer *Renderer::_safeRenderer() { + if (!_renderer) + throw SDLException("Renderer is not created"); + return _renderer; +} + +void Renderer::copy(Texture &texture, std::unique_ptr srcRect, std::unique_ptr destRect) { + SDL_Rect src = srcRect ? Rect::toSDLRect(*srcRect) : SDL_Rect{0, 0, 0, 0}; + SDL_FRect dest = destRect ? FRect::toSDLRect(*destRect) : SDL_FRect{0, 0, 0, 0}; + + auto copy = SDL_RenderCopyF( + _safeRenderer(), + texture(), + srcRect ? &src : nullptr, + destRect ? &dest : nullptr + ); + + if (copy < 0) + throw SDLException("Failed to copy texture"); +} diff --git a/graphics/sdl2/sdl/renderer/Renderer.hpp b/graphics/sdl2/sdl/renderer/Renderer.hpp new file mode 100644 index 0000000..eb8240e --- /dev/null +++ b/graphics/sdl2/sdl/renderer/Renderer.hpp @@ -0,0 +1,73 @@ +/* +** EPITECH PROJECT, 2024 +** arcade +** File description: +** Renderer.hpp +*/ + +#pragma once + +#include +#include +#include "sdl/types/Color.hpp" +#include "sdl/types/Rect.hpp" +#include "sdl/text/Text.hpp" + +namespace sdl { + class Renderer; + class Window; + class Texture; +} + +class sdl::Renderer { +public: + explicit Renderer(const Window &window); + ~Renderer(); + + /** + * @brief Create a renderer for current window + * @param window Window + * @return Renderer + */ + Renderer& create(); + + /** + * @brief Get the renderer + * @return SDL_Renderer + */ + SDL_Renderer *operator()() const; + + /** + * @brief Draw a color on the screen + * @param color Color to draw + */ + void drawColor(Color color); + + /** + * @brief Copy a texture to the screen + * @param texture Texture to copy + * @param srcRect Source rectangle + * @param destRect Source rectangle + */ + void copy(Texture &texture, std::unique_ptr srcRect, std::unique_ptr destRect); + + /** + * @brief Clear the screen + */ + void clear(); + + /** + * @brief Present the screen + */ + void present(); + +private: + /** + * @brief Get the renderer safely or throw an exception if it's null + * @return Get the renderer + */ + SDL_Renderer *_safeRenderer(); + + SDL_Renderer *_renderer; + const Window &_window; +}; diff --git a/graphics/sdl2/sdl/surface/Surface.cpp b/graphics/sdl2/sdl/surface/Surface.cpp new file mode 100644 index 0000000..1e1f1f8 --- /dev/null +++ b/graphics/sdl2/sdl/surface/Surface.cpp @@ -0,0 +1,64 @@ +/* +** EPITECH PROJECT, 2024 +** arcade +** File description: +** Image.cpp +*/ + +#include "Surface.hpp" +#include "sdl/exception/Exception.hpp" +#include "sdl/texture/Texture.hpp" +#include "sdl/renderer/Renderer.hpp" + +using namespace sdl; + +Surface::Surface() { + _surface = nullptr; +} + +Surface::Surface(SDL_Surface *surface) { + _surface = surface; +} + +Surface::Surface(const std::string &path): _surface(nullptr) { + if (!load(path)) + throw SDLException("Failed to load image at: " + path); +} + +bool Surface::load(const std::string &path) { + if (_surface) + SDL_FreeSurface(_surface); + _surface = IMG_Load(path.c_str()); + return _surface != nullptr; +} + +Surface::Surface(const Surface &other) { + if (!other._surface) { + _surface = nullptr; + return; + } + _surface = SDL_DuplicateSurface(other._surface); + if (!_surface) + throw SDLException("Failed to duplicate SDL surface"); +} + +Surface::~Surface() { + if (_surface) + SDL_FreeSurface(_surface); +} + +Vector2i Surface::getSize() const { + return {_surface->w, _surface->h }; +} + +SDL_Surface *Surface::operator()() const { + return _surface; +} + +Texture Surface::toTexture(Renderer &renderer) const { + auto raw = SDL_CreateTextureFromSurface(renderer(), _surface); + + if (!raw) + throw SDLException("Failed to create texture from surface"); + return Texture(raw); +} diff --git a/graphics/sdl2/sdl/surface/Surface.hpp b/graphics/sdl2/sdl/surface/Surface.hpp new file mode 100644 index 0000000..151ceea --- /dev/null +++ b/graphics/sdl2/sdl/surface/Surface.hpp @@ -0,0 +1,56 @@ +/* +** EPITECH PROJECT, 2024 +** arcade +** File description: +** Image.hpp +*/ + +#pragma once + +#include +#include +#include "shared/types/Vector.hpp" + +namespace sdl { + using namespace shared::types; + class Surface; + class Renderer; + class Texture; +} + +class sdl::Surface { +public: + Surface(); + Surface(const Surface &other); + explicit Surface(SDL_Surface *surface); + explicit Surface(const std::string &path); + ~Surface(); + + /** + * @brief Load an image from a file + * @param path Path to the image file + * @return Loading success status + */ + bool load(const std::string &path); + /** + * @brief Get the inner SDL surface + * @return SDL surface pointer + */ + SDL_Surface *operator()() const; + + /** + * @brief Get the size of the surface + * @return Size of the surface + */ + Vector2i getSize() const; + + /** + * @brief Convert the surface to a texture + * @param renderer Renderer to create the texture + * @return Created texture + */ + Texture toTexture(Renderer &renderer) const; + +private: + SDL_Surface *_surface; +}; diff --git a/graphics/sdl2/sdl/text/Font.cpp b/graphics/sdl2/sdl/text/Font.cpp new file mode 100644 index 0000000..651680f --- /dev/null +++ b/graphics/sdl2/sdl/text/Font.cpp @@ -0,0 +1,65 @@ +/* +** EPITECH PROJECT, 2024 +** arcade +** File description: +** Font.cpp +*/ + +#include +#include "Font.hpp" +#include "sdl/exception/Exception.hpp" + +using namespace sdl; + +Font::Font() { + _font = nullptr; +} + +Font::Font(const std::string &path, int ptSize): Font() { + if (!load(path, ptSize)) + throw SDLException("Failed to load font"); +} + +bool Font::load(const std::string &path, int ptSize) { + static bool init = false; + if (!init) { + if (TTF_Init() == -1) + throw SDLException("Failed to init TTF"); + init = true; + } + if (_font) + TTF_CloseFont(_font); + _font = TTF_OpenFont(path.c_str(), ptSize); + return _font != nullptr; +} + +Font::~Font() { + if (_font) + TTF_CloseFont(_font); +} + +TTF_Font *Font::_safeFont() const { + if (!_font) + throw SDLException("Font is not loaded"); + return _font; +} + +TTF_Font *Font::operator()() const { + return _font; +} + +void Font::setSize(unsigned int ptSize) { + if (TTF_SetFontSize(_safeFont(), static_cast(ptSize)) == -1) + throw SDLException("Failed to set font size"); +} + +Surface Font::renderText(const std::string &text, unsigned int fontSize, Color color) { + SDL_Surface *surface; + + this->setSize(fontSize); + surface = TTF_RenderText_Blended(_safeFont(), text.c_str(), color()); + + if (!surface) + throw SDLException("Failed to render text"); + return Surface(surface); +} diff --git a/graphics/sdl2/sdl/text/Font.hpp b/graphics/sdl2/sdl/text/Font.hpp new file mode 100644 index 0000000..fdf605b --- /dev/null +++ b/graphics/sdl2/sdl/text/Font.hpp @@ -0,0 +1,64 @@ +/* +** EPITECH PROJECT, 2024 +** arcade +** File description: +** Font.hpp +*/ + +#pragma once + +#include +#include +#include +#include "sdl/surface/Surface.hpp" +#include "sdl/types/Color.hpp" + +namespace sdl { + class Font; + typedef std::shared_ptr SharedFont; +} + +class sdl::Font { +public: + Font(); + explicit Font(const std::string &path, int ptSize = 12); + ~Font(); + + /** + * @brief Load a font from a file + * @param path Path to the font file + * @param ptSize Font size + * @return True if the font was loaded successfully + * @throw False if the font could not be loaded + */ + bool load(const std::string &path, int ptSize = 12); + + /** + * @brief Get inner SDL font pointer + * @return SDL Font pointer + */ + TTF_Font *operator()() const; + + /** + * @brief Set the size of the font + * @param ptSize Font size + */ + void setSize(unsigned int ptSize); + + /** + * @brief Create a surface from a string + * @param text Text to render + * @param color Color of the text + * @return Created surface + */ + Surface renderText(const std::string &text, unsigned int fontSize, Color color = ColorWhite); + +private: + TTF_Font *_font; + + /** + * @brief Get the font pointer if is not null or throw an exception + * @return SDL font pointer + */ + TTF_Font *_safeFont() const; +}; diff --git a/graphics/sdl2/sdl/text/Text.cpp b/graphics/sdl2/sdl/text/Text.cpp new file mode 100644 index 0000000..981780f --- /dev/null +++ b/graphics/sdl2/sdl/text/Text.cpp @@ -0,0 +1,101 @@ +/* +** EPITECH PROJECT, 2024 +** arcade +** File description: +** Text.cpp +*/ + +#include +#include "Text.hpp" +#include "sdl/renderer/Renderer.hpp" +#include "sdl/exception/Exception.hpp" + +using namespace sdl; + +Text::Text(): _font(nullptr), _position({0, 0}), _color(ColorWhite), _fontSize(12), _rendered(false) +{ +} + +Text::Text(const std::string &content): Text() +{ + _content = content; +} + +void Text::setFont(SharedFont font) +{ + _font = std::move(font); + _rendered = false; +} + +SharedFont Text::getFont() const +{ + return _font; +} + +void Text::setFontSize(unsigned int size) +{ + if (_fontSize != size) + _rendered = false; + _fontSize = size; +} + +unsigned int Text::getFontSize() const +{ + return _fontSize; +} + +void Text::setPosition(const shared::types::Vector2f &position) { + _position = position; +} + +const shared::types::Vector2f &Text::getPosition() const { + return _position; +} + +void Text::setContent(const std::string &content) { + if (_content != content) + _rendered = false; + _content = content; +} + +const std::string &Text::getContent() const { + return _content; +} + +const Color &Text::getColor() const { + return _color; +} + +void Text::setColor(const Color &color) { + if (_color != color) + _rendered = false; + _color = color; +} + +void Text::render(Renderer &renderer) { + if (!_font) + throw SDLException("Unable to render text of which font is not set"); + auto surface = _font->renderText( + _content, + _fontSize, + _color + ); + _texture = surface.toTexture(renderer); + _rendered = true; +} + +Texture &Text::toTexture(Renderer &renderer) { + render(renderer); + return _texture; +} + +FRect Text::getGlobalBounds() const { + if (!_rendered) + throw SDLException("Unable to get global bounds of text that is not rendered"); + return { + _position.x, + _position.y, + static_cast(_texture.getSize().x), + static_cast(_texture.getSize().y) + }; +} diff --git a/graphics/sdl2/sdl/text/Text.hpp b/graphics/sdl2/sdl/text/Text.hpp new file mode 100644 index 0000000..8632109 --- /dev/null +++ b/graphics/sdl2/sdl/text/Text.hpp @@ -0,0 +1,117 @@ +/* +** EPITECH PROJECT, 2024 +** arcade +** File description: +** Text.hpp +*/ + +#pragma once + +#include "Font.hpp" +#include +#include "sdl/surface/Surface.hpp" +#include "shared/types/Vector.hpp" +#include "sdl/types/Color.hpp" +#include "sdl/texture/Texture.hpp" +#include "sdl/types/Rect.hpp" + +namespace sdl { + class Text; + class Renderer; +} + +class sdl::Text { +public: + Text(); + + explicit Text(const std::string &content); + + ~Text() = default; + + /** + * @brief Get font of the text + * @return Font of the text + */ + SharedFont getFont() const; + + /** + * @brief Set font of the text + * @param font Font to set + */ + void setFont(SharedFont font); + + /** + * @brief Set content of the text + * @param content Content to set + */ + void setContent(const std::string &content); + + /** + * @brief Get content of the text + * @return Current text content + */ + const std::string &getContent() const; + + /** + * @brief Set position of the text + * @param position Position to set + */ + void setPosition(const shared::types::Vector2f &position); + + /** + * @brief Get position of the text + * @return Current text position + */ + const shared::types::Vector2f &getPosition() const; + + /** + * @brief Set the color of the font + * @param color Color + */ + void setColor(const Color &color); + + /** + * @brief Get the color of the font + * @return Color + */ + const Color &getColor() const; + + /** + * @brief Set the size of the font + * @param size Font size + */ + void setFontSize(unsigned int size); + + /** + * @brief Get the size of the font + * @return Font size + */ + unsigned int getFontSize() const; + + /** + * @brief Render the text + * @param renderer Renderer to use + */ + void render(Renderer &renderer); + + /** + * @brief Get the texture of the text + * @return Texture of the text + */ + Texture &toTexture(Renderer &renderer); + + /** + * @brief Get the texture of the text + * @return Texture of the text + */ + FRect getGlobalBounds() const; + +private: + SharedFont _font; + unsigned int _fontSize; + std::string _content; + shared::types::Vector2f _position; + Color _color; + Texture _texture; + bool _rendered; +}; diff --git a/graphics/sdl2/sdl/texture/Texture.cpp b/graphics/sdl2/sdl/texture/Texture.cpp new file mode 100644 index 0000000..fbebd5d --- /dev/null +++ b/graphics/sdl2/sdl/texture/Texture.cpp @@ -0,0 +1,51 @@ +/* +** EPITECH PROJECT, 2024 +** arcade +** File description: +** Texture.cpp +*/ + +#include +#include "Texture.hpp" +#include "sdl/renderer/Renderer.hpp" +#include "sdl/exception/Exception.hpp" + +using namespace sdl; + +Texture::Texture() { + _texture = nullptr; +} + +Texture::Texture(SDL_Texture *texture) { + _texture = texture; +} + +Texture::Texture(Renderer &renderer, Surface &surface) { + _texture = SDL_CreateTextureFromSurface(renderer(), surface()); + if (!_texture) + throw SDLException("Failed to create texture from surface"); +} + +Texture::~Texture() { + if (_texture) + SDL_DestroyTexture(_texture); +} + +SDL_Texture *Texture::operator()() const { + return _texture; +} + +Texture &Texture::operator=(Texture &&texture) noexcept { + if (_texture) + SDL_DestroyTexture(_texture); + _texture = texture._texture; + texture._texture = nullptr; + return *this; +} + +Vector2i Texture::getSize() const { + Vector2i size(0, 0); + + SDL_QueryTexture(_texture, nullptr, nullptr, &size.x, &size.y); + return size; +} diff --git a/graphics/sdl2/sdl/texture/Texture.hpp b/graphics/sdl2/sdl/texture/Texture.hpp new file mode 100644 index 0000000..a3756a8 --- /dev/null +++ b/graphics/sdl2/sdl/texture/Texture.hpp @@ -0,0 +1,63 @@ +/* +** EPITECH PROJECT, 2024 +** arcade +** File description: +** Texture.hpp +*/ + +#pragma once + +#include +#include "sdl/surface/Surface.hpp" + +namespace sdl { + class Texture; + class Renderer; +} + +class sdl::Texture { +public: + Texture(); + ~Texture(); + + /** + * @brief Construct a new Texture object from an existing SDL2 texture + * @param texture SDL2 texture + */ + explicit Texture(SDL_Texture *texture); + + /** + * @brief Construct a new Texture object from another texture + * @param texture Texture to copy + */ + Texture &operator=(Texture &&texture) noexcept; + + /** + * @brief Construct a new Texture object from a surface + * @param renderer Renderer to create the texture + * @param surface Surface to create the texture + */ + explicit Texture(Renderer &renderer, Surface &surface); + + /** + * @brief Get the inner SDL2 texture + * @return Reference to the inner SDL2 texture + */ + SDL_Texture *operator()() const; + + /** + * @brief Move the texture to another texture + * @param texture Texture to move to + * @return Current texture + */ + void reset(Texture &texture); + + /** + * @brief Get the size of the texture + * @return Texture size + */ + Vector2i getSize() const; + +private: + SDL_Texture *_texture; +}; diff --git a/graphics/sdl2/sdl/types/Color.hpp b/graphics/sdl2/sdl/types/Color.hpp new file mode 100644 index 0000000..b7efd7c --- /dev/null +++ b/graphics/sdl2/sdl/types/Color.hpp @@ -0,0 +1,42 @@ +/* +** EPITECH PROJECT, 2024 +** arcade +** File description: +** Color.hpp +*/ + +#pragma once + +namespace sdl { + typedef struct Color { + Color(unsigned char r, unsigned char g, unsigned char b, unsigned char a = 255) + : r(r), g(g), b(b), a(a) {} + + unsigned char r; + unsigned char g; + unsigned char b; + unsigned char a; + + SDL_Color operator()() { + return SDL_Color{r, g, b, a}; + } + + bool operator==(const Color &color) const { + return r == color.r && g == color.g && b == color.b && a == color.a; + } + + bool operator!=(const Color &color) const { + return !(*this == color); + } + } Color; + + const Color ColorBlack = Color(0, 0, 0); + const Color ColorWhite = Color(255, 255, 255); + const Color ColorRed = Color(255, 0, 0); + const Color ColorGreen = Color(0, 255, 0); + const Color ColorBlue = Color(0, 0, 255); + const Color ColorYellow = Color(255, 255, 0); + const Color ColorMagenta = Color(255, 0, 255); + const Color ColorCyan = Color(0, 255, 255); + const Color ColorTransparent = Color(0, 0, 0, 0); +} diff --git a/graphics/sdl2/sdl/types/Rect.hpp b/graphics/sdl2/sdl/types/Rect.hpp new file mode 100644 index 0000000..5f75cf6 --- /dev/null +++ b/graphics/sdl2/sdl/types/Rect.hpp @@ -0,0 +1,77 @@ +/* +** EPITECH PROJECT, 2024 +** arcade +** File description: +** Rect.hpp +*/ + +#pragma once + +#include + +namespace sdl { + typedef struct Rect { + Rect(int x, int y, int w, int h) : x(x), y(y), w(w), h(h) {} + + /** + * @brief X position of the rectangle + */ + int x; + + /** + * @brief Y position of the rectangle + */ + int y; + + /** + * @brief Width of the rectangle + */ + int w; + + /** + * @brief Height of the rectangle + */ + int h; + + /** + * @brief Convert a Rect to SDL_Rect + * @param rect The Rect to convert + * @return The converted SDL_Rect + */ + static SDL_Rect toSDLRect(Rect &rect) { + return { rect.x, rect.y, rect.w, rect.h }; + } + } Rect; + typedef struct FRect { + FRect(float x, float y, float w, float h) : x(x), y(y), w(w), h(h) {} + + /** + * @brief X position of the rectangle + */ + float x; + + /** + * @brief Y position of the rectangle + */ + float y; + + /** + * @brief Width of the rectangle + */ + float w; + + /** + * @brief Height of the rectangle + */ + float h; + + /** + * @brief Convert a Rect to SDL_Rect + * @param rect The Rect to convert + * @return The converted SDL_Rect + */ + static SDL_FRect toSDLRect(FRect &rect) { + return { rect.x, rect.y, rect.w, rect.h }; + } + } FRect; +} diff --git a/graphics/sdl2/sdl/window/Window.cpp b/graphics/sdl2/sdl/window/Window.cpp new file mode 100644 index 0000000..31bde60 --- /dev/null +++ b/graphics/sdl2/sdl/window/Window.cpp @@ -0,0 +1,83 @@ +/* +** EPITECH PROJECT, 2024 +** arcade +** File description: +** Window.cpp +*/ + +#include +#include "Window.hpp" +#include "sdl/exception/Exception.hpp" + +using namespace sdl; + +Window::Window(): _renderer(*this) { + _window = nullptr; +} + +Window &Window::create( + const std::string &title, + const Vector2i &position, + const Vector2i &size, + Uint32 flags +) { + _window = SDL_CreateWindow( + title.c_str(), + position.x, + position.y, + size.x, + size.y, + flags + ); + if (!_window) + throw SDLException("Failed to create window"); + _renderer.create(); + return *this; +} + +SDL_Window *Window::operator()() const { + return _window; +} + +Window::~Window() { + if (_window) + SDL_DestroyWindow(_window); +} + +SDL_Window *Window::_safeWindow() const { + if (!_window) + throw SDLException("Window is not created"); + return _window; +} + +void Window::setTitle(const std::string &title) { + SDL_SetWindowTitle(_safeWindow(), title.c_str()); +} + +void Window::setSize(Vector2i size) { + SDL_SetWindowSize(_safeWindow(), size.x, size.y); +} + +Vector2i Window::getSize() const { + Vector2i size(0, 0); + + SDL_GetWindowSize(_safeWindow(), &size.x, &size.y); + return size; +} + +void Window::setFullscreen(Uint32 flags) { + SDL_SetWindowFullscreen(_safeWindow(), flags); +} + +Uint32 Window::getFlags() const { + return SDL_GetWindowFlags(_safeWindow()); +} + +void Window::setIcon(const std::string &path) { + _icon.load(path); + SDL_SetWindowIcon(_safeWindow(), _icon()); +} + +Renderer &Window::getRenderer() { + return _renderer; +} diff --git a/graphics/sdl2/sdl/window/Window.hpp b/graphics/sdl2/sdl/window/Window.hpp new file mode 100644 index 0000000..5512359 --- /dev/null +++ b/graphics/sdl2/sdl/window/Window.hpp @@ -0,0 +1,98 @@ +/* +** EPITECH PROJECT, 2024 +** arcade +** File description: +** Window.hpp +*/ + +#pragma once + +#include +#include +#include "shared/types/Vector.hpp" +#include "sdl/renderer/Renderer.hpp" +#include "sdl/surface/Surface.hpp" + +namespace sdl { + using namespace shared::types; + + class Window; +} + +class sdl::Window { +public: + Window(); + ~Window(); + + /** + * @brief Create a window + * @param title Title of the window + * @param position Position of the window + * @param size Size of the window + */ + Window &create( + const std::string &title, + const Vector2i &position, + const Vector2i &size, + Uint32 flags = SDL_WINDOW_SHOWN + ); + + /** + * @brief Get the window + * @return SDL_Window + */ + SDL_Window *operator()() const; + + /** + * @brief Set the title of the window + * @param title Title + */ + void setTitle(const std::string &title); + + /** + * @brief Set the size of the window + * @param size Size + */ + void setSize(Vector2i size); + + /** + * @brief Get the size of the window + * @return Size + */ + Vector2i getSize() const; + + /** + * @brief Set the fullscreen mode + * @param fullscreen Fullscreen + */ + void setFullscreen(Uint32 flags); + + /** + * @brief Get the flags of the window + * @return Flags + */ + Uint32 getFlags() const; + + /** + * @brief Get the renderer + * @return Renderer + */ + Renderer &getRenderer(); + + /** + * @brief Set the icon of the window + * @param path Path of icon to set + */ + void setIcon(const std::string &path); + +private: + /** + * @brief Get the window safely and throw an exception if it's not created + * @return Window pointer + */ + SDL_Window *_safeWindow() const; + + SDL_Window *_window; + Surface _icon; + Renderer _renderer; +}; diff --git a/graphics/sdl2/src/GraphicsProvider.cpp b/graphics/sdl2/src/GraphicsProvider.cpp index 5524070..c460f9c 100644 --- a/graphics/sdl2/src/GraphicsProvider.cpp +++ b/graphics/sdl2/src/GraphicsProvider.cpp @@ -7,7 +7,6 @@ #include #include "GraphicsProvider.hpp" -#include "utils/compiler.hpp" #include "window/Window.hpp" #include "font/Font.hpp" #include "sound/Sound.hpp" @@ -28,7 +27,9 @@ const GraphicsManifest GraphicsProvider::_manifest = { } }; -GraphicsProvider::GraphicsProvider() = default; +GraphicsProvider::GraphicsProvider() { + sdl::Initializer::init(); +} const shared::graphics::GraphicsManifest &GraphicsProvider::getManifest() const noexcept { return GraphicsProvider::_manifest; @@ -42,7 +43,7 @@ std::shared_ptr GraphicsProvider::createSound(const std::string &path) { return std::make_shared(path); } -std::shared_ptrGraphicsProvider::createTexture(const std::string &bin, unused const std::string &ascii) { +std::shared_ptrGraphicsProvider::createTexture(const std::string &bin, const std::string &ascii) { return std::make_shared(bin); } diff --git a/graphics/sdl2/src/GraphicsProvider.hpp b/graphics/sdl2/src/GraphicsProvider.hpp index abefc2e..a21ec81 100644 --- a/graphics/sdl2/src/GraphicsProvider.hpp +++ b/graphics/sdl2/src/GraphicsProvider.hpp @@ -9,6 +9,7 @@ #include "shared/graphics/ITexture.hpp" #include "shared/graphics/IGraphicsProvider.hpp" +#include "sdl/initializer/Initializer.hpp" namespace arcade::graphics::sdl2 { diff --git a/graphics/sdl2/src/font/Font.cpp b/graphics/sdl2/src/font/Font.cpp index 8c7a0bb..0e6f485 100644 --- a/graphics/sdl2/src/font/Font.cpp +++ b/graphics/sdl2/src/font/Font.cpp @@ -13,14 +13,17 @@ using namespace arcade::graphics::common::exceptions; Font::Font(const std::string &path) { - if (!_font.loadFromFile(path)) + try { + _font = std::make_shared(path); + } catch (const std::exception &e) { throw FontException( "Failed to load font at: " + path, "Font constructor in SDL2 library" ); + } } -sf::Font &Font::getInnerFont() +sdl::SharedFont Font::getInnerFont() { return _font; } diff --git a/graphics/sdl2/src/font/Font.hpp b/graphics/sdl2/src/font/Font.hpp index 052b414..d367007 100644 --- a/graphics/sdl2/src/font/Font.hpp +++ b/graphics/sdl2/src/font/Font.hpp @@ -8,7 +8,7 @@ #pragma once #include -#include +#include "sdl/text/Font.hpp" #include "shared/graphics/IFont.hpp" #include "utils/compiler.hpp" @@ -25,8 +25,8 @@ class arcade::graphics::sdl2::font::Font : public shared::graphics::IFont { * @brief Get the inner SDL2 font * @return Reference to the inner SDL2 font */ - sf::Font &getInnerFont(); + sdl::SharedFont getInnerFont(); private: - sf::Font _font; + sdl::SharedFont _font; }; diff --git a/graphics/sdl2/src/texture/Texture.cpp b/graphics/sdl2/src/texture/Texture.cpp index 9353532..9337b0b 100644 --- a/graphics/sdl2/src/texture/Texture.cpp +++ b/graphics/sdl2/src/texture/Texture.cpp @@ -12,14 +12,14 @@ using namespace arcade::graphics::sdl2::texture; using namespace arcade::graphics::common::exceptions; Texture::Texture(const std::string &path) { - if (!_texture.loadFromFile(path)) + if (!_surface.load(path)) { throw TextureException( - "Failed to load texture at: " + path, + "Failed to load texture from file: " + path, "Texture constructor in SDL2 library" ); + } } -sf::Texture &Texture::getInnerTexture() -{ - return _texture; +sdl::Surface &Texture::getInnerSurface() { + return _surface; } diff --git a/graphics/sdl2/src/texture/Texture.hpp b/graphics/sdl2/src/texture/Texture.hpp index 9283bd7..2999072 100644 --- a/graphics/sdl2/src/texture/Texture.hpp +++ b/graphics/sdl2/src/texture/Texture.hpp @@ -10,6 +10,7 @@ #include #include #include "shared/graphics/ITexture.hpp" +#include "sdl/texture/Texture.hpp" namespace arcade::graphics::sdl2::texture { class Texture; @@ -21,11 +22,11 @@ class arcade::graphics::sdl2::texture::Texture: public shared::graphics::ITextur ~Texture() override = default; /** - * @brief Get the inner SDL2 texture - * @return Reference to the inner SDL2 texture + * @brief Get the inner SDL2 surface + * @return Reference to the inner SDL2 surface */ - sf::Texture &getInnerTexture(); + sdl::Surface &getInnerSurface(); private: - sf::Texture _texture; + sdl::Surface _surface; }; diff --git a/graphics/sdl2/src/types/renderer.hpp b/graphics/sdl2/src/types/renderer.hpp new file mode 100644 index 0000000..868c11b --- /dev/null +++ b/graphics/sdl2/src/types/renderer.hpp @@ -0,0 +1,18 @@ +/* +** EPITECH PROJECT, 2024 +** arcade +** File description: +** renderer.hpp +*/ + +#pragma once + +#include +#include + +#define SDL_DESTROY_RENDERER &SDL_DestroyRenderer + +namespace arcade::graphics::sdl2::types { + typedef decltype(SDL_DESTROY_RENDERER) SDLDestroyRenderer; + typedef std::unique_ptr SDLRenderer; +} \ No newline at end of file diff --git a/graphics/sdl2/src/types/surface.hpp b/graphics/sdl2/src/types/surface.hpp new file mode 100644 index 0000000..3b24459 --- /dev/null +++ b/graphics/sdl2/src/types/surface.hpp @@ -0,0 +1,18 @@ +/* +** EPITECH PROJECT, 2024 +** arcade +** File description: +** surface.hpp +*/ + +#pragma once + +#include +#include + +#define SDL_DESTROY_SURFACE &SDL_FreeSurface + +namespace arcade::graphics::sdl2::types { + typedef decltype(SDL_DESTROY_SURFACE) SDLDestroySurface; + typedef std::unique_ptr SDLSurface; +} diff --git a/graphics/sdl2/src/types/window.hpp b/graphics/sdl2/src/types/window.hpp new file mode 100644 index 0000000..45dc5e6 --- /dev/null +++ b/graphics/sdl2/src/types/window.hpp @@ -0,0 +1,18 @@ +/* +** EPITECH PROJECT, 2024 +** arcade +** File description: +** window.hpp +*/ + +#pragma once + +#include +#include + +#define SDL_DESTROY_WINDOW &SDL_DestroyWindow + +namespace arcade::graphics::sdl2::types { + typedef decltype(SDL_DESTROY_WINDOW) SDLDestroyWindow; + typedef std::unique_ptr SDLWindow; +} diff --git a/graphics/sdl2/src/window/EventsHandler.cpp b/graphics/sdl2/src/window/EventsHandler.cpp index eb8c9e1..e379eb5 100644 --- a/graphics/sdl2/src/window/EventsHandler.cpp +++ b/graphics/sdl2/src/window/EventsHandler.cpp @@ -32,7 +32,7 @@ EventsHandler::EventsHandler(Window &window): _window(window) {} std::vector EventsHandler::handleEvents() { std::vector events; - sf::Event SFMLEvent{}; + /* sf::Event SFMLEvent{}; while (_window.getInnerWindow().pollEvent(SFMLEvent)) { auto handler = _getHandler(SFMLEvent.type); @@ -40,7 +40,7 @@ std::vector EventsHandler::handleEvents() { if (event) events.push_back(event); - } + }*/ return events; } diff --git a/graphics/sdl2/src/window/Renderer.cpp b/graphics/sdl2/src/window/Renderer.cpp index 48b53e7..053c842 100644 --- a/graphics/sdl2/src/window/Renderer.cpp +++ b/graphics/sdl2/src/window/Renderer.cpp @@ -5,40 +5,43 @@ ** Renderer.cpp */ +#include #include "Window.hpp" #include "Renderer.hpp" #include "font/Font.hpp" #include "texture/Texture.hpp" -#include "common/exceptions/WindowException.hpp" -using namespace arcade::graphics::sdl2::window; +using namespace arcade::graphics::sdl2::window;; using namespace arcade::graphics::common::exceptions; -Renderer::Renderer(Window &window) : _window(window), _layer(_window.getInnerWindow()) { - _text.setFont(sf::Font()); - _sprite.setTexture(sf::Texture()); -} +Renderer::Renderer(Window &window) : _window(window), _renderer(window.getInnerWindow().getRenderer()) {} void Renderer::render(const shared::graphics::TextProps &props) { auto font = _castOrThrow(props.font); auto entityPosition = _entityPixelsPosition(props.position); auto entitySize = _window.tilesToPixels(props.size); + sdl::Texture texture; _reset(_text); _text.setFont(font->getInnerFont()); - _text.setString(props.content); - _text.setCharacterSize(props.fontSize); - _text.setFillColor(sf::Color( + _text.setContent(props.content); + _text.setFontSize(props.fontSize); + _text.setColor({ props.color.r, props.color.g, props.color.b, - props.color.a) - ); - _text.setPosition(entityPosition.x, entityPosition.y); + props.color.a + }); + _text.setPosition(entityPosition); + _text.render(_renderer); _textAlign(props.align, entitySize); _textVerticalAlign(props.verticalAlign, entitySize); _textAdjustPosition(); - _layer.draw(_text); + _renderer.copy( + _text.toTexture(_renderer), + nullptr, + std::make_unique(_text.getGlobalBounds()) + ); } void @@ -48,9 +51,9 @@ Renderer::_textVerticalAlign(const shared::graphics::TextVerticalAlign &align, c auto position = _text.getPosition(); if (align == shared::graphics::MIDDLE) { - position.y += (static_cast(entitySize.y) - bounds.height) / 2; + position.y += (static_cast(entitySize.y) - bounds.h) / 2; } else if (align == shared::graphics::BOTTOM) { - position.y += static_cast(entitySize.y) - bounds.height; + position.y += static_cast(entitySize.y) - bounds.h; } _text.setPosition(position); } @@ -60,23 +63,22 @@ void Renderer::_textAlign(const shared::graphics::TextAlign &align, const shared auto position = _text.getPosition(); if (align == shared::graphics::CENTER) { - position.x += (static_cast(entitySize.x) - bounds.width) / 2; + position.x += (static_cast(entitySize.x) - bounds.w) / 2; } else if (align == shared::graphics::RIGHT) { - position.x += static_cast(entitySize.x) - bounds.width; + position.x += static_cast(entitySize.x) - bounds.w; } _text.setPosition(position); } void Renderer::_textAdjustPosition() { - auto actual = _text.getPosition(); +/* auto actual = _text.getPosition(); sf::FloatRect bounds; - _text.setPosition(0, 0); - bounds = _text.getGlobalBounds(); - _text.setPosition(actual.x - bounds.left, actual.y - bounds.top); + _text.setPosition({0, 0}); + _text.setPosition(actual.x - bounds.left, actual.y - bounds.top);*/ } -void Renderer::render(const shared::graphics::TextureProps &props) { +/*void Renderer::render(const shared::graphics::TextureProps &props) { auto texture = _castOrThrow(props.texture); auto entityPosition = _entityPixelsPosition(props.position); @@ -84,9 +86,9 @@ void Renderer::render(const shared::graphics::TextureProps &props) { _sprite.setTexture(texture->getInnerTexture()); _sprite.setPosition(entityPosition.x, entityPosition.y); _setTextureRectAndScale(props); - _layer.draw(_sprite); -} - + //_layer.draw(_sprite); +}*/ +/* void Renderer::_setTextureRectAndScale(const shared::graphics::TextureProps &props) { auto size = _window.tilesToPixels(props.size); float width = static_cast(props.size.x) * props.binTileSize.x; @@ -105,17 +107,16 @@ void Renderer::_setTextureRectAndScale(const shared::graphics::TextureProps &pro static_cast(size.x) / width, static_cast(size.y) / height ); +}*/ + +void Renderer::_reset(sdl::Text &text) { + text.setContent(""); + text.setFont(nullptr); + text.setPosition({0, 0}); + text.setColor(sdl::ColorWhite); + text.setFontSize(12); } - -void Renderer::_reset(sf::Text &text) { - text.setString(""); - text.setCharacterSize(0); - text.setFillColor(sf::Color::White); - text.setStyle(sf::Text::Regular); - text.setPosition(0, 0); - text.setScale(1, 1); - text.setOrigin(0, 0); -} +/* void Renderer::_reset(sf::Sprite &sprite) { sprite.setTextureRect(sf::IntRect(0, 0, 0, 0)); @@ -124,6 +125,7 @@ void Renderer::_reset(sf::Sprite &sprite) { sprite.setPosition(0, 0); sprite.setOrigin(0, 0); } +*/ Vector2f Renderer::_entityPixelsPosition(const Vector2i &position) { auto pixels = _window.tilesToPixels(position); @@ -133,3 +135,4 @@ Vector2f Renderer::_entityPixelsPosition(const Vector2i &position) { static_cast(pixels.y) }; } + diff --git a/graphics/sdl2/src/window/Renderer.hpp b/graphics/sdl2/src/window/Renderer.hpp index a95fbad..0ce1803 100644 --- a/graphics/sdl2/src/window/Renderer.hpp +++ b/graphics/sdl2/src/window/Renderer.hpp @@ -7,15 +7,19 @@ #pragma once -#include #include "shared/graphics/ITexture.hpp" #include "shared/graphics/types/TextureProps.hpp" #include "shared/graphics/types/TextProps.hpp" #include "common/exceptions/WindowException.hpp" +#include "types/renderer.hpp" +#include "sdl/text/Text.hpp" + + namespace arcade::graphics::sdl2::window { - class Renderer; + using namespace arcade::graphics::sdl2::types; + class Renderer; class Window; } @@ -39,21 +43,22 @@ class arcade::graphics::sdl2::window::Renderer { private: Window &_window; - sf::RenderWindow &_layer; - sf::Text _text; - sf::Sprite _sprite; + sdl::Renderer &_renderer; + sdl::Text _text; +/* sf::Sprite _sprite;*/ + /** * @brief Reset the text properties * @param text Text to reset */ - static void _reset(sf::Text &text); + static void _reset(sdl::Text &text); - /** + /* *//** * @brief Reset the sprite properties * @param sprite Sprite to reset - */ - static void _reset(sf::Sprite &sprite); + *//* + static void _reset(sf::Sprite &sprite);*/ /** * @brief Convert a tile position to pixel position diff --git a/graphics/sdl2/src/window/Window.cpp b/graphics/sdl2/src/window/Window.cpp index 11bece3..2b56c2e 100644 --- a/graphics/sdl2/src/window/Window.cpp +++ b/graphics/sdl2/src/window/Window.cpp @@ -5,8 +5,10 @@ ** Window class */ +#include #include "Window.hpp" #include "EventsHandler.hpp" +#include "graphics/sdl2/sdl/exception/Exception.hpp" #include "common/events/mouse/mouse.hpp" #include "common/exceptions/WindowException.hpp" @@ -18,25 +20,18 @@ const Vector2u Window::tileSize = { 12, 12 }; Window::Window(const IWindow::WindowInitProps &props): _size(props.size), _renderer(*this), - _eventsHandler(*this) + _eventsHandler(*this), + _isOpen(true) { - auto size = _getPixelSizeFromTiles(props.size); - _mode = props.mode; _fps = props.fps; - _window.create( - sf::VideoMode(size.x, size.y), - props.title - ); + _initInnerWindow(props); Window::setIcon(props.icon); } -Window::~Window() -{ - _window.close(); -} +Window::~Window() = default; -sf::RenderWindow &Window::getInnerWindow() noexcept { +sdl::Window &Window::getInnerWindow() noexcept { return _window; } @@ -48,7 +43,10 @@ void Window::setSize(shared::types::Vector2u size) { auto real = _getPixelSizeFromTiles(size); _size = size; - _window.setSize(sf::Vector2u(real.x, real.y)); + _window.setSize({ + static_cast(real.x), + static_cast(real.y) + }); } shared::types::Vector2u Window::getSize() const { @@ -56,7 +54,6 @@ shared::types::Vector2u Window::getSize() const { } void Window::setFramerateLimit(unsigned int fps) { - _window.setFramerateLimit(fps); _fps = fps; } @@ -65,21 +62,13 @@ unsigned int Window::getFramerateLimit() const { } void Window::setMode(IWindow::WindowMode mode) { - auto size = _window.getSize(); + auto isFullscreen = _window.getFlags() & SDL_WINDOW_FULLSCREEN; this->_mode = mode; - if (mode == FULLSCREEN) { - _window.create( - sf::VideoMode(size.x, size.y), - this->_title, - sf::Style::Fullscreen - ); + if (mode == FULLSCREEN && !isFullscreen) { + _window.setFullscreen(SDL_WINDOW_FULLSCREEN); } else { - _window.create( - sf::VideoMode(size.x, size.y), - this->_title, - sf::Style::Default - ); + _window.setFullscreen(0); } } @@ -88,27 +77,24 @@ Window::WindowMode Window::getMode() const { } bool Window::isOpen() const { - return _window.isOpen(); + return _isOpen; } void Window::setIcon(const std::string &path) { if (path.empty()) return; - if (!_icon.loadFromFile(path)) { + try { + _window.setIcon(path); + } catch (const sdl::SDLException &e) { throw WindowException( - "Failed to load icon at: " + path, - "Window.setIcon in SDL2 library" + "Failed to set icon", + "setIcon in SDL2 library" ); } - _window.setIcon( - _icon.getSize().x, - _icon.getSize().y, - _icon.getPixelsPtr() - ); } void Window::render(const shared::graphics::TextureProps &props) { - _renderer.render(props); + //_renderer.render(props); } void Window::render(const shared::graphics::TextProps &props) { @@ -116,28 +102,47 @@ void Window::render(const shared::graphics::TextProps &props) { } void Window::clear() { - _window.clear(); + _window.getRenderer().drawColor(sdl::ColorBlack); + _window.getRenderer().clear(); } void Window::display() { - _window.display(); + _window.getRenderer().present(); } void Window::close() { - _window.close(); + _isOpen = false; } std::vector Window::getEvents() { return _eventsHandler.handleEvents(); } +void Window::_initInnerWindow(const shared::graphics::IWindow::WindowInitProps &props) { + auto size = _getPixelSizeFromTiles(props.size); + + try { + _window.create( + props.title, + { SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED }, + { static_cast(size.x), static_cast(size.y) }, + 0 + ); + } catch (const sdl::SDLException &e) { + throw WindowException( + "Failed to create window", + "Window constructor in SDL2 library" + ); + } +} + Vector2u Window::_getPixelSizeFromTiles(const Vector2u &size) { - auto mode = sf::VideoMode::getDesktopMode(); - Vector2u real(mode.width, mode.height); + //auto mode = sf::VideoMode::getDesktopMode(); + Vector2u real(1920, 1080); - if (size.x * static_cast(tileSize.x) < mode.width) + if (size.x * static_cast(tileSize.x) < 1920) real.x = size.x * static_cast(tileSize.x); - if (size.y * static_cast(tileSize.y) < mode.height) + if (size.y * static_cast(tileSize.y) < 1080) real.y = size.y * static_cast(tileSize.y); return real; } @@ -168,4 +173,3 @@ Vector2i Window::tilesToPixels(const Vector2u &position) const { static_cast(position.y * realSize.y / _size.y) }; } - diff --git a/graphics/sdl2/src/window/Window.hpp b/graphics/sdl2/src/window/Window.hpp index 754f0e8..7e2209c 100644 --- a/graphics/sdl2/src/window/Window.hpp +++ b/graphics/sdl2/src/window/Window.hpp @@ -7,12 +7,16 @@ #pragma once -#include +#include +#include #include "Renderer.hpp" -#include "shared/graphics/IWindow.hpp" #include "EventsHandler.hpp" +#include "shared/graphics/IWindow.hpp" +#include "graphics/sdl2/sdl/window/Window.hpp" namespace arcade::graphics::sdl2::window { + using namespace arcade::graphics::sdl2::types; + class Window; } @@ -131,7 +135,7 @@ class arcade::graphics::sdl2::window::Window: public shared::graphics::IWindow { * @brief Get the window object * @return Window object */ - sf::RenderWindow &getInnerWindow() noexcept; + sdl::Window &getInnerWindow() noexcept; /** * @brief Convert a position in pixels to a position in tiles @@ -160,12 +164,17 @@ class arcade::graphics::sdl2::window::Window: public shared::graphics::IWindow { private: static Vector2u _getPixelSizeFromTiles(const Vector2u &size); + /** + * @brief Initialize the inner window + * @param props Properties of the window + */ + void _initInnerWindow(const WindowInitProps &props); + EventsHandler _eventsHandler; Renderer _renderer; - sf::RenderWindow _window; - std::string _title; + sdl::Window _window; unsigned int _fps; WindowMode _mode; - sf::Image _icon; Vector2u _size; + bool _isOpen; }; diff --git a/graphics/sfml/CMakeLists.txt b/graphics/sfml/CMakeLists.txt index 9a4ffd1..6bc0fcd 100644 --- a/graphics/sfml/CMakeLists.txt +++ b/graphics/sfml/CMakeLists.txt @@ -18,8 +18,8 @@ add_library(sfml SHARED ) add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/../common PRIVATE) -target_include_directories(sfml PUBLIC ${CMAKE_CURRENT_LIST_DIR}/src) -target_include_directories(sfml PUBLIC ${CMAKE_CURRENT_LIST_DIR}/../..) -target_include_directories(sfml PUBLIC ${CMAKE_CURRENT_LIST_DIR}/..) +target_include_directories(sfml PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src) +target_include_directories(sfml PRIVATE ${CMAKE_CURRENT_LIST_DIR}/../..) +target_include_directories(sfml PRIVATE ${CMAKE_CURRENT_LIST_DIR}/..) target_link_libraries(sfml sfml-graphics sfml-window sfml-system sfml-audio) From 0339a1a4054a6b2e978daca1204b93cb22967432 Mon Sep 17 00:00:00 2001 From: Flavien Chenu Date: Sun, 7 Apr 2024 02:57:20 +0200 Subject: [PATCH 03/12] feat(graphics:sdl): add texture rendering --- graphics/sdl2/sdl/CMakeLists.txt | 2 + graphics/sdl2/sdl/renderer/Renderer.cpp | 26 ++++++++-- graphics/sdl2/sdl/renderer/Renderer.hpp | 24 +++++++-- graphics/sdl2/sdl/sprite/Sprite.cpp | 55 ++++++++++++++++++++ graphics/sdl2/sdl/sprite/Sprite.hpp | 69 +++++++++++++++++++++++++ graphics/sdl2/sdl/surface/Surface.cpp | 1 + graphics/sdl2/sdl/texture/Texture.cpp | 1 - graphics/sdl2/sdl/texture/Texture.hpp | 7 --- graphics/sdl2/sdl/types/Rect.hpp | 4 +- graphics/sdl2/src/texture/Texture.cpp | 14 +++-- graphics/sdl2/src/texture/Texture.hpp | 16 ++++-- graphics/sdl2/src/window/Renderer.cpp | 61 ++++++++-------------- graphics/sdl2/src/window/Renderer.hpp | 18 +++---- graphics/sdl2/src/window/Window.cpp | 3 +- 14 files changed, 221 insertions(+), 80 deletions(-) create mode 100644 graphics/sdl2/sdl/sprite/Sprite.cpp create mode 100644 graphics/sdl2/sdl/sprite/Sprite.hpp diff --git a/graphics/sdl2/sdl/CMakeLists.txt b/graphics/sdl2/sdl/CMakeLists.txt index a7d55ab..67e6d06 100644 --- a/graphics/sdl2/sdl/CMakeLists.txt +++ b/graphics/sdl2/sdl/CMakeLists.txt @@ -15,6 +15,8 @@ target_sources(${PROJECT_NAME} PUBLIC text/Text.hpp texture/Texture.cpp texture/Texture.hpp + sprite/Sprite.cpp + sprite/Sprite.hpp initializer/Initializer.cpp initializer/Initializer.hpp ) diff --git a/graphics/sdl2/sdl/renderer/Renderer.cpp b/graphics/sdl2/sdl/renderer/Renderer.cpp index 2accf4d..fbeda8d 100644 --- a/graphics/sdl2/sdl/renderer/Renderer.cpp +++ b/graphics/sdl2/sdl/renderer/Renderer.cpp @@ -11,6 +11,7 @@ #include "sdl/window/Window.hpp" #include "sdl/texture/Texture.hpp" #include "sdl/exception/Exception.hpp" +#include "sdl/sprite/Sprite.hpp" using namespace sdl; @@ -54,15 +55,30 @@ SDL_Renderer *Renderer::_safeRenderer() { return _renderer; } -void Renderer::copy(Texture &texture, std::unique_ptr srcRect, std::unique_ptr destRect) { - SDL_Rect src = srcRect ? Rect::toSDLRect(*srcRect) : SDL_Rect{0, 0, 0, 0}; - SDL_FRect dest = destRect ? FRect::toSDLRect(*destRect) : SDL_FRect{0, 0, 0, 0}; +void Renderer::copy(Text &text) { + SDL_FRect dest = FRect::toSDLRect(text.getGlobalBounds()); + _copy( + text.toTexture(*this), + nullptr, + &dest + ); +} + +void Renderer::copy(const Sprite &sprite, const Texture &texture) { + SDL_Rect src = Rect::toSDLRect(sprite.getTextureRect()); + SDL_FRect dest = FRect::toSDLRect(sprite.getGlobalBounds()); + + _copy(texture, &src, &dest); +} + +void Renderer::_copy(const Texture &texture, SDL_Rect *srcRect, SDL_FRect *destRect) +{ auto copy = SDL_RenderCopyF( _safeRenderer(), texture(), - srcRect ? &src : nullptr, - destRect ? &dest : nullptr + srcRect, + destRect ); if (copy < 0) diff --git a/graphics/sdl2/sdl/renderer/Renderer.hpp b/graphics/sdl2/sdl/renderer/Renderer.hpp index eb8240e..5c92104 100644 --- a/graphics/sdl2/sdl/renderer/Renderer.hpp +++ b/graphics/sdl2/sdl/renderer/Renderer.hpp @@ -12,6 +12,7 @@ #include "sdl/types/Color.hpp" #include "sdl/types/Rect.hpp" #include "sdl/text/Text.hpp" +#include "sdl/sprite/Sprite.hpp" namespace sdl { class Renderer; @@ -44,12 +45,17 @@ class sdl::Renderer { void drawColor(Color color); /** - * @brief Copy a texture to the screen - * @param texture Texture to copy - * @param srcRect Source rectangle - * @param destRect Source rectangle + * @brief Copy a text to the screen + * @param text Text to copy + */ + void copy(Text &text); + + /** + * @brief Copy a sprite to the screen + * @param sprite Sprite to copy + * @param texture Texture to use for the sprite */ - void copy(Texture &texture, std::unique_ptr srcRect, std::unique_ptr destRect); + void copy(const Sprite &sprite, const Texture &texture); /** * @brief Clear the screen @@ -68,6 +74,14 @@ class sdl::Renderer { */ SDL_Renderer *_safeRenderer(); + /** + * @brief Copy a texture to the screen + * @param texture Texture to copy + * @param srcRect Rect to copy from the texture + * @param destRect Rect to copy to the screen + */ + void _copy(const Texture &texture, SDL_Rect *srcRect, SDL_FRect *destRect); + SDL_Renderer *_renderer; const Window &_window; }; diff --git a/graphics/sdl2/sdl/sprite/Sprite.cpp b/graphics/sdl2/sdl/sprite/Sprite.cpp new file mode 100644 index 0000000..b0b494c --- /dev/null +++ b/graphics/sdl2/sdl/sprite/Sprite.cpp @@ -0,0 +1,55 @@ +/* +** EPITECH PROJECT, 2024 +** arcade +** File description: +** Sprite.cpp +*/ + +#include "Sprite.hpp" + +using namespace sdl; + +Sprite::Sprite(): _position(0, 0), _textureRect(0, 0, 0, 0), _scale(1, 1){ +} + +Sprite::~Sprite() = default; + +void Sprite::setPosition(const Vector2f &position) +{ + _position = position; +} + +const Vector2f &Sprite::getPosition() const +{ + return _position; +} + +void Sprite::setTextureRect(const Rect &textureRect) +{ + _textureRect = textureRect; +} + +const Rect &Sprite::getTextureRect() const +{ + return _textureRect; +} + +const Vector2f &Sprite::getScale() const +{ + return _scale; +} + +void Sprite::setScale(const Vector2f &scale) +{ + _scale = scale; +} + +FRect Sprite::getGlobalBounds() const +{ + return { + _position.x, + _position.y, + static_cast(_textureRect.w) * _scale.x, + static_cast(_textureRect.h) * _scale.y + }; +} diff --git a/graphics/sdl2/sdl/sprite/Sprite.hpp b/graphics/sdl2/sdl/sprite/Sprite.hpp new file mode 100644 index 0000000..cfd7656 --- /dev/null +++ b/graphics/sdl2/sdl/sprite/Sprite.hpp @@ -0,0 +1,69 @@ +/* +** EPITECH PROJECT, 2024 +** arcade +** File description: +** Sprite.hpp +*/ + +#pragma once + +#include "sdl/texture/Texture.hpp" +#include "sdl/types/Rect.hpp" + +namespace sdl { + class Sprite; + class Texture; +} + +class sdl::Sprite { +public: + Sprite(); + ~Sprite(); + + /** + * @brief Set the position of the sprite + * @param position Position to set + */ + void setPosition(const Vector2f &position); + + /** + * @brief Get the position of the sprite + * @return Position of the sprite + */ + const Vector2f &getPosition() const; + + /** + * @brief Set the texture rect of the sprite + * @param textureRect Texture rect to set + */ + void setTextureRect(const Rect &textureRect); + + /** + * @brief Get the texture rect of the sprite + * @return Texture rect of the sprite + */ + const Rect &getTextureRect() const; + + /** + * @brief Get the scale of the sprite + * @return Scale of the sprite + */ + const Vector2f &getScale() const; + + /** + * @brief Set the scale of the sprite + * @param scale Scale to set + */ + void setScale(const Vector2f &scale); + + /** + * @brief Get the global bounds of the sprite + * @return Sprite global bounds + */ + FRect getGlobalBounds() const; + +private: + Vector2f _position; + Rect _textureRect; + Vector2f _scale; +}; diff --git a/graphics/sdl2/sdl/surface/Surface.cpp b/graphics/sdl2/sdl/surface/Surface.cpp index 1e1f1f8..d54cc0e 100644 --- a/graphics/sdl2/sdl/surface/Surface.cpp +++ b/graphics/sdl2/sdl/surface/Surface.cpp @@ -60,5 +60,6 @@ Texture Surface::toTexture(Renderer &renderer) const { if (!raw) throw SDLException("Failed to create texture from surface"); + SDL_SetTextureScaleMode(raw, SDL_ScaleMode::SDL_ScaleModeLinear); return Texture(raw); } diff --git a/graphics/sdl2/sdl/texture/Texture.cpp b/graphics/sdl2/sdl/texture/Texture.cpp index fbebd5d..972253e 100644 --- a/graphics/sdl2/sdl/texture/Texture.cpp +++ b/graphics/sdl2/sdl/texture/Texture.cpp @@ -5,7 +5,6 @@ ** Texture.cpp */ -#include #include "Texture.hpp" #include "sdl/renderer/Renderer.hpp" #include "sdl/exception/Exception.hpp" diff --git a/graphics/sdl2/sdl/texture/Texture.hpp b/graphics/sdl2/sdl/texture/Texture.hpp index a3756a8..f2d46ba 100644 --- a/graphics/sdl2/sdl/texture/Texture.hpp +++ b/graphics/sdl2/sdl/texture/Texture.hpp @@ -45,13 +45,6 @@ class sdl::Texture { */ SDL_Texture *operator()() const; - /** - * @brief Move the texture to another texture - * @param texture Texture to move to - * @return Current texture - */ - void reset(Texture &texture); - /** * @brief Get the size of the texture * @return Texture size diff --git a/graphics/sdl2/sdl/types/Rect.hpp b/graphics/sdl2/sdl/types/Rect.hpp index 5f75cf6..de4c259 100644 --- a/graphics/sdl2/sdl/types/Rect.hpp +++ b/graphics/sdl2/sdl/types/Rect.hpp @@ -38,7 +38,7 @@ namespace sdl { * @param rect The Rect to convert * @return The converted SDL_Rect */ - static SDL_Rect toSDLRect(Rect &rect) { + static SDL_Rect toSDLRect(const Rect &rect) { return { rect.x, rect.y, rect.w, rect.h }; } } Rect; @@ -70,7 +70,7 @@ namespace sdl { * @param rect The Rect to convert * @return The converted SDL_Rect */ - static SDL_FRect toSDLRect(FRect &rect) { + static SDL_FRect toSDLRect(const FRect &rect) { return { rect.x, rect.y, rect.w, rect.h }; } } FRect; diff --git a/graphics/sdl2/src/texture/Texture.cpp b/graphics/sdl2/src/texture/Texture.cpp index 9337b0b..23f348b 100644 --- a/graphics/sdl2/src/texture/Texture.cpp +++ b/graphics/sdl2/src/texture/Texture.cpp @@ -11,7 +11,7 @@ using namespace arcade::graphics::sdl2::texture; using namespace arcade::graphics::common::exceptions; -Texture::Texture(const std::string &path) { +Texture::Texture(const std::string &path): _textured(false) { if (!_surface.load(path)) { throw TextureException( "Failed to load texture from file: " + path, @@ -20,6 +20,14 @@ Texture::Texture(const std::string &path) { } } -sdl::Surface &Texture::getInnerSurface() { - return _surface; +const sdl::Texture &Texture::getInnerTexture(sdl::Renderer &renderer) { + if (!_textured) { + _texture = _surface.toTexture(renderer); + _textured = true; + } + return _texture; +} + +shared::types::Vector2i Texture::getSize() const { + return _surface.getSize(); } diff --git a/graphics/sdl2/src/texture/Texture.hpp b/graphics/sdl2/src/texture/Texture.hpp index 2999072..612612c 100644 --- a/graphics/sdl2/src/texture/Texture.hpp +++ b/graphics/sdl2/src/texture/Texture.hpp @@ -8,7 +8,6 @@ #pragma once #include -#include #include "shared/graphics/ITexture.hpp" #include "sdl/texture/Texture.hpp" @@ -22,11 +21,20 @@ class arcade::graphics::sdl2::texture::Texture: public shared::graphics::ITextur ~Texture() override = default; /** - * @brief Get the inner SDL2 surface - * @return Reference to the inner SDL2 surface + * @brief Get the inner SDL2 texture + * @param renderer Renderer to create the texture + * @return Rendered texture */ - sdl::Surface &getInnerSurface(); + const sdl::Texture &getInnerTexture(sdl::Renderer &renderer); + + /** + * @brief Get the size of the texture + * @return Texture size + */ + shared::types::Vector2i getSize() const; private: sdl::Surface _surface; + sdl::Texture _texture; + bool _textured; }; diff --git a/graphics/sdl2/src/window/Renderer.cpp b/graphics/sdl2/src/window/Renderer.cpp index 053c842..d1159d5 100644 --- a/graphics/sdl2/src/window/Renderer.cpp +++ b/graphics/sdl2/src/window/Renderer.cpp @@ -5,7 +5,6 @@ ** Renderer.cpp */ -#include #include "Window.hpp" #include "Renderer.hpp" #include "font/Font.hpp" @@ -36,17 +35,12 @@ void Renderer::render(const shared::graphics::TextProps &props) { _text.render(_renderer); _textAlign(props.align, entitySize); _textVerticalAlign(props.verticalAlign, entitySize); - _textAdjustPosition(); - _renderer.copy( - _text.toTexture(_renderer), - nullptr, - std::make_unique(_text.getGlobalBounds()) - ); + _renderer.copy(_text); } -void -Renderer::_textVerticalAlign(const shared::graphics::TextVerticalAlign &align, const shared::types::Vector2i &entitySize -) { +void Renderer::_textVerticalAlign(const shared::graphics::TextVerticalAlign &align, + const shared::types::Vector2i &entitySize) +{ auto bounds = _text.getGlobalBounds(); auto position = _text.getPosition(); @@ -70,32 +64,23 @@ void Renderer::_textAlign(const shared::graphics::TextAlign &align, const shared _text.setPosition(position); } -void Renderer::_textAdjustPosition() { -/* auto actual = _text.getPosition(); - sf::FloatRect bounds; - - _text.setPosition({0, 0}); - _text.setPosition(actual.x - bounds.left, actual.y - bounds.top);*/ -} - -/*void Renderer::render(const shared::graphics::TextureProps &props) { +void Renderer::render(const shared::graphics::TextureProps &props) { auto texture = _castOrThrow(props.texture); auto entityPosition = _entityPixelsPosition(props.position); _reset(_sprite); - _sprite.setTexture(texture->getInnerTexture()); - _sprite.setPosition(entityPosition.x, entityPosition.y); - _setTextureRectAndScale(props); - //_layer.draw(_sprite); -}*/ -/* -void Renderer::_setTextureRectAndScale(const shared::graphics::TextureProps &props) { + _setTextureRect(props); + _sprite.setPosition(entityPosition); + _renderer.copy(_sprite, texture->getInnerTexture(_renderer)); +} + +void Renderer::_setTextureRect(const shared::graphics::TextureProps &props) { auto size = _window.tilesToPixels(props.size); float width = static_cast(props.size.x) * props.binTileSize.x; float height = static_cast(props.size.y) * props.binTileSize.y; float left = static_cast(props.origin.x) * props.binTileSize.x; float top = static_cast(props.origin.y) * props.binTileSize.y; - sf::IntRect rectangle = { + sdl::Rect rectangle = { static_cast(left), static_cast(top), static_cast(width), @@ -103,11 +88,11 @@ void Renderer::_setTextureRectAndScale(const shared::graphics::TextureProps &pro }; _sprite.setTextureRect(rectangle); - _sprite.setScale( - static_cast(size.x) / width, - static_cast(size.y) / height - ); -}*/ + _sprite.setScale({ + static_cast(size.x) / width, + static_cast(size.y) / height + }); +} void Renderer::_reset(sdl::Text &text) { text.setContent(""); @@ -116,16 +101,12 @@ void Renderer::_reset(sdl::Text &text) { text.setColor(sdl::ColorWhite); text.setFontSize(12); } -/* -void Renderer::_reset(sf::Sprite &sprite) { - sprite.setTextureRect(sf::IntRect(0, 0, 0, 0)); - sprite.setColor(sf::Color::White); - sprite.setScale(1, 1); - sprite.setPosition(0, 0); - sprite.setOrigin(0, 0); +void Renderer::_reset(sdl::Sprite &sprite) { + sprite.setTextureRect(sdl::Rect(0, 0, 0, 0)); + sprite.setScale({1, 1}); + sprite.setPosition({0, 0}); } -*/ Vector2f Renderer::_entityPixelsPosition(const Vector2i &position) { auto pixels = _window.tilesToPixels(position); diff --git a/graphics/sdl2/src/window/Renderer.hpp b/graphics/sdl2/src/window/Renderer.hpp index 0ce1803..68ee8be 100644 --- a/graphics/sdl2/src/window/Renderer.hpp +++ b/graphics/sdl2/src/window/Renderer.hpp @@ -13,8 +13,7 @@ #include "common/exceptions/WindowException.hpp" #include "types/renderer.hpp" #include "sdl/text/Text.hpp" - - +#include "sdl/sprite/Sprite.hpp" namespace arcade::graphics::sdl2::window { using namespace arcade::graphics::sdl2::types; @@ -45,7 +44,7 @@ class arcade::graphics::sdl2::window::Renderer { Window &_window; sdl::Renderer &_renderer; sdl::Text _text; -/* sf::Sprite _sprite;*/ + sdl::Sprite _sprite; /** @@ -54,11 +53,11 @@ class arcade::graphics::sdl2::window::Renderer { */ static void _reset(sdl::Text &text); - /* *//** + /** * @brief Reset the sprite properties * @param sprite Sprite to reset - *//* - static void _reset(sf::Sprite &sprite);*/ + */ + static void _reset(sdl::Sprite &sprite); /** * @brief Convert a tile position to pixel position @@ -85,16 +84,11 @@ class arcade::graphics::sdl2::window::Renderer { */ void _textAlign(const shared::graphics::TextAlign &align, const shared::types::Vector2i &entitySize); - /** - * @brief Adjust the text position - */ - void _textAdjustPosition(); - /** * @brief Set texture rect depending on the texture properties * @param props Texture properties */ - void _setTextureRectAndScale(const shared::graphics::TextureProps &props); + void _setTextureRect(const shared::graphics::TextureProps &props); /** * @brief Cast a shared pointer from a type to another diff --git a/graphics/sdl2/src/window/Window.cpp b/graphics/sdl2/src/window/Window.cpp index 2b56c2e..c7f41f8 100644 --- a/graphics/sdl2/src/window/Window.cpp +++ b/graphics/sdl2/src/window/Window.cpp @@ -94,7 +94,7 @@ void Window::setIcon(const std::string &path) { } void Window::render(const shared::graphics::TextureProps &props) { - //_renderer.render(props); + _renderer.render(props); } void Window::render(const shared::graphics::TextProps &props) { @@ -108,6 +108,7 @@ void Window::clear() { void Window::display() { _window.getRenderer().present(); + SDL_Delay(1000); } void Window::close() { From d87a965dd0daa0e976df93dbd3961be2e2b31287 Mon Sep 17 00:00:00 2001 From: Flavien Chenu Date: Sun, 7 Apr 2024 04:17:48 +0200 Subject: [PATCH 04/12] feat(graphics:sdl): add framerate limit handling --- graphics/sdl2/sdl/renderer/Renderer.cpp | 11 ++++++++++- graphics/sdl2/sdl/renderer/Renderer.hpp | 15 ++++++++++++++- graphics/sdl2/src/window/Window.cpp | 3 +-- 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/graphics/sdl2/sdl/renderer/Renderer.cpp b/graphics/sdl2/sdl/renderer/Renderer.cpp index fbeda8d..f91a6a6 100644 --- a/graphics/sdl2/sdl/renderer/Renderer.cpp +++ b/graphics/sdl2/sdl/renderer/Renderer.cpp @@ -15,7 +15,7 @@ using namespace sdl; -Renderer::Renderer(const Window &window) : _window(window) { +Renderer::Renderer(const Window &window, unsigned int fps) : _window(window), _fps(fps) { _renderer = nullptr; } @@ -42,6 +42,7 @@ void Renderer::clear() { void Renderer::present() { SDL_RenderPresent(_safeRenderer()); + SDL_Delay(1000 / _fps); } Renderer::~Renderer() { @@ -84,3 +85,11 @@ void Renderer::_copy(const Texture &texture, SDL_Rect *srcRect, SDL_FRect *destR if (copy < 0) throw SDLException("Failed to copy texture"); } + +void Renderer::setFramerateLimit(unsigned int fps) { + _fps = fps; +} + +unsigned int Renderer::getFramerateLimit() const { + return _fps; +} diff --git a/graphics/sdl2/sdl/renderer/Renderer.hpp b/graphics/sdl2/sdl/renderer/Renderer.hpp index 5c92104..95376bc 100644 --- a/graphics/sdl2/sdl/renderer/Renderer.hpp +++ b/graphics/sdl2/sdl/renderer/Renderer.hpp @@ -22,7 +22,7 @@ namespace sdl { class sdl::Renderer { public: - explicit Renderer(const Window &window); + explicit Renderer(const Window &window, unsigned int fps = 60); ~Renderer(); /** @@ -67,6 +67,18 @@ class sdl::Renderer { */ void present(); + /** + * @brief Set the framerate Limit of the window + * @param fps Framerate limit + */ + void setFramerateLimit(unsigned int fps); + + /** + * @brief Get the framerate Limit of the window + * @return Framerate limit + */ + unsigned int getFramerateLimit() const; + private: /** * @brief Get the renderer safely or throw an exception if it's null @@ -83,5 +95,6 @@ class sdl::Renderer { void _copy(const Texture &texture, SDL_Rect *srcRect, SDL_FRect *destRect); SDL_Renderer *_renderer; + unsigned int _fps; const Window &_window; }; diff --git a/graphics/sdl2/src/window/Window.cpp b/graphics/sdl2/src/window/Window.cpp index c7f41f8..7287c2a 100644 --- a/graphics/sdl2/src/window/Window.cpp +++ b/graphics/sdl2/src/window/Window.cpp @@ -5,7 +5,6 @@ ** Window class */ -#include #include "Window.hpp" #include "EventsHandler.hpp" #include "graphics/sdl2/sdl/exception/Exception.hpp" @@ -55,6 +54,7 @@ shared::types::Vector2u Window::getSize() const { void Window::setFramerateLimit(unsigned int fps) { _fps = fps; + _window.getRenderer().setFramerateLimit(_fps); } unsigned int Window::getFramerateLimit() const { @@ -108,7 +108,6 @@ void Window::clear() { void Window::display() { _window.getRenderer().present(); - SDL_Delay(1000); } void Window::close() { From 59b155ea3f5a4bc1a95a1839e28ec81e85f15999 Mon Sep 17 00:00:00 2001 From: Flavien Chenu Date: Sun, 7 Apr 2024 04:18:36 +0200 Subject: [PATCH 05/12] feat(graphics:sdl): add events handling --- graphics/sdl2/sdl/CMakeLists.txt | 1 + graphics/sdl2/sdl/types/Event.hpp | 20 +++ graphics/sdl2/sdl/window/Window.cpp | 5 +- graphics/sdl2/sdl/window/Window.hpp | 8 + graphics/sdl2/src/window/EventsHandler.cpp | 161 +++++++++++---------- graphics/sdl2/src/window/EventsHandler.hpp | 28 ++-- 6 files changed, 131 insertions(+), 92 deletions(-) create mode 100644 graphics/sdl2/sdl/types/Event.hpp diff --git a/graphics/sdl2/sdl/CMakeLists.txt b/graphics/sdl2/sdl/CMakeLists.txt index 67e6d06..2e74222 100644 --- a/graphics/sdl2/sdl/CMakeLists.txt +++ b/graphics/sdl2/sdl/CMakeLists.txt @@ -17,6 +17,7 @@ target_sources(${PROJECT_NAME} PUBLIC texture/Texture.hpp sprite/Sprite.cpp sprite/Sprite.hpp + types/Event.hpp initializer/Initializer.cpp initializer/Initializer.hpp ) diff --git a/graphics/sdl2/sdl/types/Event.hpp b/graphics/sdl2/sdl/types/Event.hpp new file mode 100644 index 0000000..05953b2 --- /dev/null +++ b/graphics/sdl2/sdl/types/Event.hpp @@ -0,0 +1,20 @@ +/* +** EPITECH PROJECT, 2024 +** arcade +** File description: +** events.hpp +*/ + +#pragma once + +#include + +namespace sdl { + typedef SDL_Event Event; + typedef SDL_EventType EventType; + typedef SDL_KeyboardEvent KeyboardEvent; + typedef SDL_MouseButtonEvent MouseButtonEvent; + typedef SDL_MouseMotionEvent MouseMotionEvent; + typedef SDL_QuitEvent QuitEvent; + typedef SDL_Keycode Keycode; +} diff --git a/graphics/sdl2/sdl/window/Window.cpp b/graphics/sdl2/sdl/window/Window.cpp index 31bde60..6e47a4c 100644 --- a/graphics/sdl2/sdl/window/Window.cpp +++ b/graphics/sdl2/sdl/window/Window.cpp @@ -5,7 +5,6 @@ ** Window.cpp */ -#include #include "Window.hpp" #include "sdl/exception/Exception.hpp" @@ -81,3 +80,7 @@ void Window::setIcon(const std::string &path) { Renderer &Window::getRenderer() { return _renderer; } + +bool Window::pollEvent(Event &event) { + return SDL_PollEvent(&event); +} diff --git a/graphics/sdl2/sdl/window/Window.hpp b/graphics/sdl2/sdl/window/Window.hpp index 5512359..7baf7df 100644 --- a/graphics/sdl2/sdl/window/Window.hpp +++ b/graphics/sdl2/sdl/window/Window.hpp @@ -12,6 +12,7 @@ #include "shared/types/Vector.hpp" #include "sdl/renderer/Renderer.hpp" #include "sdl/surface/Surface.hpp" +#include "sdl/types/Event.hpp" namespace sdl { using namespace shared::types; @@ -85,6 +86,13 @@ class sdl::Window { */ void setIcon(const std::string &path); + /** + * @brief Poll an event + * @param event Event to fill + * @return Event status + */ + static bool pollEvent(Event &event); + private: /** * @brief Get the window safely and throw an exception if it's not created diff --git a/graphics/sdl2/src/window/EventsHandler.cpp b/graphics/sdl2/src/window/EventsHandler.cpp index e379eb5..03f40cb 100644 --- a/graphics/sdl2/src/window/EventsHandler.cpp +++ b/graphics/sdl2/src/window/EventsHandler.cpp @@ -6,22 +6,22 @@ */ #include - +#include #include "Window.hpp" #include "EventsHandler.hpp" #include "utils/compiler.hpp" using namespace arcade::graphics::sdl2::window; -EventsHandler::EventHandler EventsHandler::_getHandler(sf::Event::EventType type) { - static std::map handlers = { - {sf::Event::KeyPressed, _handleKeyPressEvent}, - {sf::Event::KeyReleased, _handleKeyReleaseEvent}, - {sf::Event::MouseButtonPressed, _handleMouseButtonPressEvent}, - {sf::Event::MouseButtonReleased, _handleMouseBtnReleaseEvent}, - {sf::Event::MouseMoved, _handleMouseMoveEvent}, - {sf::Event::Closed, _handleWindowCloseEvent}, - {sf::Event::Resized, _handleWindowResizeEvent} +EventsHandler::EventHandler EventsHandler::_getHandler(sdl::EventType type) { + static std::map handlers = { + {SDL_KEYDOWN, _handleKeyPressEvent}, + {SDL_KEYUP, _handleKeyReleaseEvent}, + {SDL_MOUSEBUTTONDOWN, _handleMouseButtonPressEvent}, + {SDL_MOUSEBUTTONUP, _handleMouseBtnReleaseEvent}, + {SDL_MOUSEMOTION, _handleMouseMoveEvent}, + {SDL_QUIT, _handleWindowCloseEvent}, + {SDL_WINDOWEVENT, _handleWindowResizeEvent} }; auto handler = handlers.find(type); @@ -32,29 +32,36 @@ EventsHandler::EventsHandler(Window &window): _window(window) {} std::vector EventsHandler::handleEvents() { std::vector events; - /* sf::Event SFMLEvent{}; + sdl::Event originalEvent{}; - while (_window.getInnerWindow().pollEvent(SFMLEvent)) { - auto handler = _getHandler(SFMLEvent.type); - auto event = handler ? handler(SFMLEvent, _window) : nullptr; + while (sdl::Window::pollEvent(originalEvent)) { + auto handler = _getHandler(static_cast(originalEvent.type)); + auto event = handler ? handler(originalEvent, _window) : nullptr; if (event) events.push_back(event); - }*/ + } return events; } bool EventsHandler::_handleControlKey( - sf::Event::KeyEvent event, + sdl::KeyboardEvent &event, IKeyEvent::KeyCode &code ) { - switch (event.code) { - case sf::Keyboard::LControl: - case sf::Keyboard::RControl: - case sf::Keyboard::LShift: - case sf::Keyboard::RShift: - case sf::Keyboard::LAlt: - case sf::Keyboard::RAlt: + switch (event.keysym.sym) { + case SDLK_LCTRL: + case SDLK_RCTRL: + code.control = IKeyEvent::ControlCode::CTRL; + return true; + + case SDLK_LSHIFT: + case SDLK_RSHIFT: + code.control = IKeyEvent::ControlCode::SHIFT; + return true; + + case SDLK_LALT: + case SDLK_RALT: + code.control = IKeyEvent::ControlCode::ALT; return true; default: @@ -63,20 +70,20 @@ bool EventsHandler::_handleControlKey( } bool EventsHandler::_handleArrowKey( - sf::Event::KeyEvent event, + sdl::KeyboardEvent &event, IKeyEvent::KeyCode &code ) { - switch (event.code) { - case sf::Keyboard::Left: + switch (event.keysym.sym) { + case SDLK_LEFT: code.arrow = IKeyEvent::ArrowCode::LEFT; return true; - case sf::Keyboard::Right: + case SDLK_RIGHT: code.arrow = IKeyEvent::ArrowCode::RIGHT; return true; - case sf::Keyboard::Up: + case SDLK_UP: code.arrow = IKeyEvent::ArrowCode::UP; return true; - case sf::Keyboard::Down: + case SDLK_DOWN: code.arrow = IKeyEvent::ArrowCode::DOWN; return true; default: @@ -85,12 +92,12 @@ bool EventsHandler::_handleArrowKey( } bool EventsHandler::_handleFunctionKey( - sf::Event::KeyEvent event, + sdl::KeyboardEvent &event, IKeyEvent::KeyCode &code ) { - if (event.code >= sf::Keyboard::F1 && event.code <= sf::Keyboard::F12) { - code.func = event.code - sf::Keyboard::F1 + 1; + if (event.keysym.sym >= SDLK_F1 && event.keysym.sym <= SDLK_F12) { + code.func = static_cast(event.keysym.sym - SDLK_F1 + 1); return true; } else { return false; @@ -98,40 +105,37 @@ bool EventsHandler::_handleFunctionKey( } bool EventsHandler::_handleCharKey( - sf::Event::KeyEvent event, + sdl::KeyboardEvent &event, IKeyEvent::KeyCode &code ) { - static const std::map specials = { - {sf::Keyboard::Space, ' '}, - {sf::Keyboard::LBracket, '['}, - {sf::Keyboard::RBracket, ']'}, - {sf::Keyboard::Semicolon, ';'}, - {sf::Keyboard::Comma, ','}, - {sf::Keyboard::Period, '.'}, - {sf::Keyboard::Quote, '\''}, - {sf::Keyboard::Slash, '/'}, - {sf::Keyboard::Backslash, '\\'}, - {sf::Keyboard::Tilde, '~'}, - {sf::Keyboard::Equal, '='}, - {sf::Keyboard::Hyphen, '-'}, - {sf::Keyboard::Enter, '\n'}, - {sf::Keyboard::Backspace, '\b'}, - {sf::Keyboard::Tab, '\t'}, - {sf::Keyboard::Escape, 0x1B}, - {sf::Keyboard::Add, '+'}, - {sf::Keyboard::Subtract, '-'}, - {sf::Keyboard::Multiply, '*'}, - {sf::Keyboard::Divide, '/'} + static const std::map specials = { + {SDLK_SPACE, ' '}, + {SDLK_LEFTBRACKET, '['}, + {SDLK_RIGHTBRACKET, ']'}, + {SDLK_SEMICOLON, ';'}, + {SDLK_COMMA, ','}, + {SDLK_PERIOD, '.'}, + {SDLK_QUOTE, '\''}, + {SDLK_SLASH, '/'}, + {SDLK_BACKSLASH, '\\'}, + {SDLK_EQUALS, '='}, + {SDLK_RETURN, '\n'}, + {SDLK_BACKSPACE, '\b'}, + {SDLK_TAB, '\t'}, + {SDLK_ESCAPE, 0x1B}, + {SDLK_PLUS, '+'}, + {SDLK_MINUS, '-'}, + {SDLK_ASTERISK, '*'}, + {SDLK_SLASH, '/'} }; + auto sym = event.keysym.sym; - if (event.code >= sf::Keyboard::A && event.code <= sf::Keyboard::Z) { - code.character = static_cast(event.code - sf::Keyboard::A + 'a'); - } else if (event.code >= sf::Keyboard::Num0 && event.code <= sf::Keyboard::Num9) { - code.character = static_cast(event.code - sf::Keyboard::Num0 + '0'); - } else if (event.code >= sf::Keyboard::Numpad0 && event.code <= sf::Keyboard::Numpad9) { - code.character = static_cast(event.code - sf::Keyboard::Numpad0 + '0'); + if (sym >= SDLK_a && sym <= SDLK_z) { + code.character = static_cast(sym - SDLK_a + 'a'); + } else if (sym >= SDLK_0 && sym <= SDLK_9) { + code.character = static_cast(sym - SDLK_0 + '0'); } else { - auto special = specials.find(event.code); + auto special = specials.find(sym); if (special != specials.end()) { code.character = special->second; @@ -142,7 +146,7 @@ bool EventsHandler::_handleCharKey( return true; } -EventPtr EventsHandler::_handleKeyPressEvent(sf::Event &event, unused Window &window) { +EventPtr EventsHandler::_handleKeyPressEvent(sdl::Event &event, unused Window &window) { IKeyEvent::KeyType type = IKeyEvent::KeyType::UNKNOWN; IKeyEvent::KeyCode code; @@ -158,7 +162,7 @@ EventPtr EventsHandler::_handleKeyPressEvent(sf::Event &event, unused Window &wi } EventPtr EventsHandler::_handleKeyReleaseEvent( - sf::Event &event, + sdl::Event &event, unused Window &window ) { IKeyEvent::KeyType type = IKeyEvent::KeyType::UNKNOWN; @@ -176,51 +180,54 @@ EventPtr EventsHandler::_handleKeyReleaseEvent( } EventPtr EventsHandler::_handleWindowCloseEvent( - unused sf::Event &event, + unused sdl::Event &event, unused Window &window ) { return std::make_shared(); } EventPtr EventsHandler::_handleWindowResizeEvent( - unused sf::Event &event, - Window &window + sdl::Event &event, + unused Window &window ) { - return std::make_shared(); + if (event.window.event == SDL_WINDOWEVENT_RESIZED) + return std::make_shared(); + return nullptr; } EventPtr EventsHandler::_handleMouseMoveEvent( - sf::Event &event, + sdl::Event &event, Window &window ) { return std::make_shared( - window.pixelsToTiles(Vector2i(event.mouseMove.x, event.mouseMove.y)) + window.pixelsToTiles(Vector2i(event.motion.x, event.motion.y)) ); } EventPtr EventsHandler::_handleMouseButtonPressEvent( - sf::Event &event, + sdl::Event &event, Window &window ) { - Vector2i pos = window.pixelsToTiles(Vector2i(event.mouseButton.x, event.mouseButton.y)); + Vector2i pos = window.pixelsToTiles(Vector2i(event.button.x, event.button.y)); - if (event.mouseButton.button == sf::Mouse::Button::Left) + if (event.button.button == SDL_BUTTON_LEFT) return std::make_shared(pos, IMouseButtonEvent::MouseButton::LEFT); - else if (event.mouseButton.button == sf::Mouse::Button::Right) + else if (event.button.button == SDL_BUTTON_RIGHT) return std::make_shared(pos, IMouseButtonEvent::MouseButton::RIGHT); else return nullptr; } + EventPtr EventsHandler::_handleMouseBtnReleaseEvent( - sf::Event &event, + sdl::Event &event, unused Window &window ) { - Vector2i pos = window.pixelsToTiles(Vector2i(event.mouseButton.x, event.mouseButton.y)); + Vector2i pos = window.pixelsToTiles(Vector2i(event.button.x, event.button.y)); - if (event.mouseButton.button == sf::Mouse::Button::Left) + if (event.button.button == SDL_BUTTON_LEFT) return std::make_shared(pos, IMouseButtonEvent::MouseButton::LEFT); - else if (event.mouseButton.button == sf::Mouse::Button::Right) + else if (event.button.button == SDL_BUTTON_RIGHT) return std::make_shared(pos, IMouseButtonEvent::MouseButton::RIGHT); else return nullptr; diff --git a/graphics/sdl2/src/window/EventsHandler.hpp b/graphics/sdl2/src/window/EventsHandler.hpp index e7714d2..68c51ea 100644 --- a/graphics/sdl2/src/window/EventsHandler.hpp +++ b/graphics/sdl2/src/window/EventsHandler.hpp @@ -8,8 +8,8 @@ #pragma once #include -#include +#include "sdl/window/Window.hpp" #include "common/events/window/window.hpp" #include "common/events/mouse/mouse.hpp" #include "common/events/key/key.hpp" @@ -24,7 +24,7 @@ class arcade::graphics::sdl2::window::EventsHandler { explicit EventsHandler(Window &window); ~EventsHandler() = default; - typedef EventPtr (*EventHandler)(sf::Event &event, Window &window); + typedef EventPtr (*EventHandler)(sdl::Event &event, Window &window); /** * @brief Handle events from SDL2 @@ -35,7 +35,7 @@ class arcade::graphics::sdl2::window::EventsHandler { private: - static EventHandler _getHandler(sf::Event::EventType type); + static EventHandler _getHandler(sdl::EventType type); /** * @brief Handle control key event if it's a control key @@ -43,7 +43,7 @@ class arcade::graphics::sdl2::window::EventsHandler { * @param code Code of the key to set * @return Status of handling */ - static bool _handleControlKey(sf::Event::KeyEvent event, IKeyEvent::KeyCode &code); + static bool _handleControlKey(sdl::KeyboardEvent &event, IKeyEvent::KeyCode &code); /** * @brief Handle control key event if it's an arrow key @@ -51,7 +51,7 @@ class arcade::graphics::sdl2::window::EventsHandler { * @param code Code of the key to set * @return Status of handling */ - static bool _handleArrowKey(sf::Event::KeyEvent event, IKeyEvent::KeyCode &code); + static bool _handleArrowKey(sdl::KeyboardEvent &event, IKeyEvent::KeyCode &code); /** * @brief Handle control key event if it's a function key @@ -59,7 +59,7 @@ class arcade::graphics::sdl2::window::EventsHandler { * @param code Code of the key to set * @return Status of handling */ - static bool _handleFunctionKey(sf::Event::KeyEvent event, IKeyEvent::KeyCode &code); + static bool _handleFunctionKey(sdl::KeyboardEvent &event, IKeyEvent::KeyCode &code); /** * @brief Handle control key event if it's a char key @@ -67,7 +67,7 @@ class arcade::graphics::sdl2::window::EventsHandler { * @param code Code of the key to set * @return Status of handling */ - static bool _handleCharKey(sf::Event::KeyEvent event, IKeyEvent::KeyCode &code); + static bool _handleCharKey(sdl::KeyboardEvent &event, IKeyEvent::KeyCode &code); /** * @brief Handle key press event @@ -75,7 +75,7 @@ class arcade::graphics::sdl2::window::EventsHandler { * @param window Window object * @return Pointer to created event or null if not handled */ - static EventPtr _handleKeyPressEvent(sf::Event &event, Window &window); + static EventPtr _handleKeyPressEvent(sdl::Event &event, Window &window); /** * @brief Handle key release event @@ -83,7 +83,7 @@ class arcade::graphics::sdl2::window::EventsHandler { * @param window Window object * @return Pointer to created event or null if not handled */ - static EventPtr _handleKeyReleaseEvent(sf::Event &event, Window &window); + static EventPtr _handleKeyReleaseEvent(sdl::Event &event, Window &window); /** * @brief Handle mouse button press event @@ -91,7 +91,7 @@ class arcade::graphics::sdl2::window::EventsHandler { * @param window Window object * @return Pointer to created event or null if not handled */ - static EventPtr _handleMouseButtonPressEvent(sf::Event &event, Window &window); + static EventPtr _handleMouseButtonPressEvent(sdl::Event &event, Window &window); /** * @brief Handle mouse button release event @@ -99,7 +99,7 @@ class arcade::graphics::sdl2::window::EventsHandler { * @param window Window object * @return Pointer to created event or null if not handled */ - static EventPtr _handleMouseBtnReleaseEvent(sf::Event &event, Window &window); + static EventPtr _handleMouseBtnReleaseEvent(sdl::Event &event, Window &window); /** * @brief Handle mouse move event @@ -107,7 +107,7 @@ class arcade::graphics::sdl2::window::EventsHandler { * @param window Window object * @return Pointer to created event or null if not handled */ - static EventPtr _handleMouseMoveEvent(sf::Event &event, Window &window); + static EventPtr _handleMouseMoveEvent(sdl::Event &event, Window &window); /** * @brief Handle window close event @@ -115,7 +115,7 @@ class arcade::graphics::sdl2::window::EventsHandler { * @param window Window object * @return Pointer to created event or null if not handled */ - static EventPtr _handleWindowCloseEvent(sf::Event &event, Window &window); + static EventPtr _handleWindowCloseEvent(sdl::Event &event, Window &window); /** * @brief Handle window resize event @@ -123,7 +123,7 @@ class arcade::graphics::sdl2::window::EventsHandler { * @param window Window object * @return Pointer to created event or null if not handled */ - static EventPtr _handleWindowResizeEvent(sf::Event &event, Window &window); + static EventPtr _handleWindowResizeEvent(sdl::Event &event, Window &window); /** * @brief Resolve position of the event to convert it in tiles unit From 1b37aa07dc74d20de079bd8fbb45a064518dae30 Mon Sep 17 00:00:00 2001 From: Flavien Chenu Date: Sun, 7 Apr 2024 04:20:21 +0200 Subject: [PATCH 06/12] fix(graphics:sfml): bad control events handling --- graphics/sfml/src/window/EventsHandler.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/graphics/sfml/src/window/EventsHandler.cpp b/graphics/sfml/src/window/EventsHandler.cpp index 877a4d8..0de2fe8 100644 --- a/graphics/sfml/src/window/EventsHandler.cpp +++ b/graphics/sfml/src/window/EventsHandler.cpp @@ -51,10 +51,17 @@ bool EventsHandler::_handleControlKey( switch (event.code) { case sf::Keyboard::LControl: case sf::Keyboard::RControl: + code.control = IKeyEvent::ControlCode::CTRL; + return true; + case sf::Keyboard::LShift: case sf::Keyboard::RShift: + code.control = IKeyEvent::ControlCode::SHIFT; + return true; + case sf::Keyboard::LAlt: case sf::Keyboard::RAlt: + code.control = IKeyEvent::ControlCode::ALT; return true; default: From c31e66c9263f4be513d1bd3f6eb90da63f023b54 Mon Sep 17 00:00:00 2001 From: Flavien Chenu Date: Sun, 7 Apr 2024 11:12:12 +0200 Subject: [PATCH 07/12] refactor(core): passing some methods parameters to references instead of copies --- core/src/Core.cpp | 50 +++++++++------------- core/src/Core.hpp | 24 ++++------- graphics/sdl2/src/sound/Sound.cpp | 22 +++++----- graphics/sdl2/src/sound/Sound.hpp | 4 +- graphics/sdl2/src/window/EventsHandler.cpp | 4 +- graphics/sdl2/src/window/Renderer.cpp | 2 +- graphics/sdl2/src/window/Renderer.hpp | 2 +- graphics/sdl2/src/window/Window.cpp | 16 +++---- graphics/sdl2/src/window/Window.hpp | 4 +- 9 files changed, 58 insertions(+), 70 deletions(-) diff --git a/core/src/Core.cpp b/core/src/Core.cpp index c12b444..5965ae2 100644 --- a/core/src/Core.cpp +++ b/core/src/Core.cpp @@ -8,7 +8,6 @@ #include #include -#include #include "Core.hpp" #include "shared/games/components/IComponent.hpp" @@ -25,7 +24,7 @@ Core::Core(GameProviders &gameProviders, GraphicsProviders &graphicsProviders, c } } -Core::~Core() {} +Core::~Core() = default; std::shared_ptr Core::_getGameProvider(const unsigned char &index) { @@ -112,7 +111,7 @@ void Core::_initWindow() this->_sceneStage = PLAY; } -std::shared_ptr Core::_getTexture(std::string bin, std::string ascii) +std::shared_ptr Core::_getTexture(const std::string& bin, const std::string& ascii) { for (auto &failedTexture : this->_failedTextures) { if (failedTexture == bin + ascii) @@ -123,7 +122,7 @@ std::shared_ptr Core::_getTexture(std::string bin, std::string ascii) return this->_textures[bin + ascii]; } -std::shared_ptr Core::_getFont(std::string path) +std::shared_ptr Core::_getFont(const std::string& path) { for (auto &failedTexture : this->_failedTextures) { if (failedTexture == path) @@ -134,7 +133,7 @@ std::shared_ptr Core::_getFont(std::string path) return this->_fonts[path]; } -Core::SoundProps Core::_getSound(std::string path) +Core::SoundProps Core::_getSound(const std::string& path) { if (this->_sounds.find(path) == this->_sounds.end()) { SoundProps soundProps { @@ -148,7 +147,7 @@ Core::SoundProps Core::_getSound(std::string path) return this->_sounds[path]; } -void Core::_loadFailed(std::shared_ptr texture) +void Core::_loadFailed(const std::shared_ptr& texture) { if (!texture) return; @@ -156,7 +155,7 @@ void Core::_loadFailed(std::shared_ptr texture) this->_failedTextures.push_back(textureProps.sources.bin + textureProps.sources.ascii); } -void Core::_loadFailed(std::shared_ptr text) +void Core::_loadFailed(const std::shared_ptr& text) { if (!text) return; @@ -164,7 +163,7 @@ void Core::_loadFailed(std::shared_ptr text) this->_failedTextures.push_back(textProps.font.path); } -TextureProps Core::_getTextureEntity(std::shared_ptr texture) +TextureProps Core::_getTextureEntity(const std::shared_ptr& texture) { auto textureProps = texture->getTextureProps(); TextureProps entityTextureProps { @@ -178,7 +177,7 @@ TextureProps Core::_getTextureEntity(std::shared_ptr text) +TextProps Core::_getTextEntity(const std::shared_ptr& text) { auto textProps = text->getTextProps(); TextProps entityTextProps { @@ -293,7 +292,7 @@ components::IKeyboardComponent::KeyData Core::_convertKeyPressData(events::IKeyE return keyCodeData; } -void Core::_preventWindowEvents(std::vector events) +void Core::_preventWindowEvents(const std::vector& events) { for (auto &event : events) { auto type = event->getType(); @@ -356,7 +355,7 @@ void Core::_handleKeyPress(std::shared_ptr &keyEvent, std::sh { auto keyCode = keyEvent->getKeyCode(); auto keyType = keyEvent->getKeyType(); - auto keyCodeData = this->_convertKeyPressData(keyType, keyCode); + auto keyCodeData = Core::_convertKeyPressData(keyType, keyCode); this->_handleFunctionKeys(keyEvent); keyboard->onKeyPress(this->_game, keyCodeData); @@ -366,32 +365,30 @@ void Core::_handleKeyRelease(std::shared_ptr &keyEvent, std:: { auto keyCode = keyEvent->getKeyCode(); auto keyType = keyEvent->getKeyType(); - auto keyCodeData = this->_convertKeyPressData(keyType, keyCode); + auto keyCodeData = Core::_convertKeyPressData(keyType, keyCode); keyboard->onKeyRelease(this->_game, keyCodeData); } void Core::_handleMouseButtonPress(std::shared_ptr &event, std::shared_ptr &component) { - auto button = event->getButton(); auto mousePosition = event->getPosition(); auto entityPosition = component->getPosition(); auto entitySize = component->getSize(); - if (mousePosition.x >= entityPosition.x && mousePosition.x <= entityPosition.x + entitySize.x && - mousePosition.y >= entityPosition.y && mousePosition.y <= entityPosition.y + entitySize.y) + if (mousePosition.x >= entityPosition.x && mousePosition.x <= entityPosition.x + static_cast(entitySize.x) && + mousePosition.y >= entityPosition.y && mousePosition.y <= entityPosition.y + static_cast(entitySize.y)) component->onMousePress(this->_game); } void Core::_handleMouseButtonRelease(std::shared_ptr &event, std::shared_ptr &component) { - auto button = event->getButton(); auto mousePosition = event->getPosition(); auto entityPosition = component->getPosition(); auto entitySize = component->getSize(); - if (mousePosition.x >= entityPosition.x && mousePosition.x <= entityPosition.x + entitySize.x && - mousePosition.y >= entityPosition.y && mousePosition.y <= entityPosition.y + entitySize.y) + if (mousePosition.x >= entityPosition.x && mousePosition.x <= entityPosition.x + static_cast(entitySize.x) && + mousePosition.y >= entityPosition.y && mousePosition.y <= entityPosition.y + static_cast(entitySize.y)) component->onMouseRelease(this->_game); } @@ -401,8 +398,8 @@ void Core::_handleMouseMove(std::shared_ptr &event, std::sh auto entityPosition = component->getPosition(); auto entitySize = component->getSize(); - if (mousePosition.x >= entityPosition.x && mousePosition.x <= entityPosition.x + entitySize.x && - mousePosition.y >= entityPosition.y && mousePosition.y <= entityPosition.y + entitySize.y) + if (mousePosition.x >= entityPosition.x && mousePosition.x <= entityPosition.x + static_cast(entitySize.x) && + mousePosition.y >= entityPosition.y && mousePosition.y <= entityPosition.y + static_cast(entitySize.y)) component->onMouseHover(this->_game); } @@ -424,11 +421,6 @@ void Core::_handleWindowClose() } } -void Core::_handleWindowResize() -{ - std::cout << "Window resized" << std::endl; -} - void Core::_handleKeyboardEvents(std::vector &events, std::shared_ptr &component) { for (auto &event : events) { @@ -470,10 +462,10 @@ void Core::_handleCollisions(std::shared_ptr & auto targetPosition = target->getPosition(); auto targetSize = target->getSize(); - if (componentPosition.x < targetPosition.x + targetSize.x && - componentPosition.x + componentSize.x > targetPosition.x && - componentPosition.y < targetPosition.y + targetSize.y && - componentPosition.y + componentSize.y > targetPosition.y) + if (componentPosition.x < targetPosition.x + static_cast(targetSize.x) && + componentPosition.x + static_cast(componentSize.x) > targetPosition.x && + componentPosition.y < targetPosition.y + static_cast(targetSize.y) && + componentPosition.y + static_cast(componentSize.y) > targetPosition.y) component->onCollide(this->_game, target); } diff --git a/core/src/Core.hpp b/core/src/Core.hpp index 315907b..f05b370 100644 --- a/core/src/Core.hpp +++ b/core/src/Core.hpp @@ -87,14 +87,14 @@ class Core { * * @param texture The texture component */ - void _loadFailed(std::shared_ptr texture); + void _loadFailed(const std::shared_ptr& texture); /** * @brief Load the failed text * * @param text The text component */ - void _loadFailed(std::shared_ptr text); + void _loadFailed(const std::shared_ptr& text); /** * @brief Get a texture @@ -103,7 +103,7 @@ class Core { * @param ascii Path to the ascii file * @return The correct texture */ - std::shared_ptr _getTexture(std::string bin, std::string ascii); + std::shared_ptr _getTexture(const std::string& bin, const std::string& ascii); /** * @brief Get a font @@ -111,7 +111,7 @@ class Core { * @param path Path to the font file * @return The correct font */ - std::shared_ptr _getFont(std::string path); + std::shared_ptr _getFont(const std::string& path); /** * @brief Get a sound @@ -119,7 +119,7 @@ class Core { * @param path Path to the sound file * @return The correct sound */ - SoundProps _getSound(std::string path); + SoundProps _getSound(const std::string& path); /** * @brief Get the texture entity @@ -127,7 +127,7 @@ class Core { * @param texture The texture component * @return The texture entity */ - TextureProps _getTextureEntity(std::shared_ptr texture); + TextureProps _getTextureEntity(const std::shared_ptr& texture); /** * @brief Get the text entity @@ -135,7 +135,7 @@ class Core { * @param text The text component * @return The text entity */ - TextProps _getTextEntity(std::shared_ptr text); + TextProps _getTextEntity(const std::shared_ptr& text); /** * @brief Render the props @@ -259,18 +259,12 @@ class Core { */ void _stopAllGraphicsSounds(); - /** - * @brief Handle the window resize event - * - */ - void _handleWindowResize(); - /** * @brief Prevent the window from closing * * @param events The events */ - void _preventWindowEvents(std::vector events); + void _preventWindowEvents(const std::vector& events); /** * @brief Handle the key press event @@ -314,7 +308,7 @@ class Core { * @param code The code of the key * @return The converted key press data */ - components::IKeyboardComponent::KeyData _convertKeyPressData(events::IKeyEvent::KeyType type, events::IKeyEvent::KeyCode code); + static components::IKeyboardComponent::KeyData _convertKeyPressData(events::IKeyEvent::KeyType type, events::IKeyEvent::KeyCode code); /** * @brief Handle the mouse button press event diff --git a/graphics/sdl2/src/sound/Sound.cpp b/graphics/sdl2/src/sound/Sound.cpp index b75a486..b7f663a 100644 --- a/graphics/sdl2/src/sound/Sound.cpp +++ b/graphics/sdl2/src/sound/Sound.cpp @@ -12,37 +12,37 @@ using namespace arcade::graphics::sdl2::sound; using namespace arcade::graphics::common::exceptions; Sound::Sound(const std::string &path, SoundState state) { - if(!_buffer.loadFromFile(path)) { + /*if(!_buffer.loadFromFile(path)) { throw SoundException( "Failed to load sound at: " + path, "Sound constructor in SDL2 library" ); } _sound.setBuffer(_buffer); - _sound.stop(); + _sound.stop();*/ } Sound::SoundVolume Sound::getVolume() const { - return static_cast(_sound.getVolume()); + return 45; } void Sound::setVolume(SoundVolume volume) { - _sound.setVolume(volume); + } void Sound::setState(SoundState state) { - switch (state) { +/* switch (state) { case PLAY: return _sound.play(); case PAUSE: return _sound.pause(); case STOP: return _sound.stop(); - } + }*/ } Sound::SoundState Sound::getState() const { - auto state = _sound.getStatus(); + /*auto state = _sound.getStatus(); switch (state) { case sf::Sound::Playing: @@ -51,13 +51,15 @@ Sound::SoundState Sound::getState() const { return PAUSE; default: return STOP; - } + }*/ + return PLAY; } void Sound::setLoopState(bool loop) { - _sound.setLoop(loop); + //_sound.setLoop(loop); } bool Sound::getLoopState() const { - return _sound.getLoop(); + //return _sound.getLoop(); + return true; } diff --git a/graphics/sdl2/src/sound/Sound.hpp b/graphics/sdl2/src/sound/Sound.hpp index bf83f77..c2f20b6 100644 --- a/graphics/sdl2/src/sound/Sound.hpp +++ b/graphics/sdl2/src/sound/Sound.hpp @@ -29,6 +29,6 @@ class arcade::graphics::sdl2::sound::Sound : public shared::graphics::ISound { bool getLoopState() const override; private: - sf::SoundBuffer _buffer; - sf::Sound _sound; +/* sf::SoundBuffer _buffer; + sf::Sound _sound;*/ }; diff --git a/graphics/sdl2/src/window/EventsHandler.cpp b/graphics/sdl2/src/window/EventsHandler.cpp index 03f40cb..0554187 100644 --- a/graphics/sdl2/src/window/EventsHandler.cpp +++ b/graphics/sdl2/src/window/EventsHandler.cpp @@ -208,7 +208,7 @@ EventPtr EventsHandler::_handleMouseButtonPressEvent( sdl::Event &event, Window &window ) { - Vector2i pos = window.pixelsToTiles(Vector2i(event.button.x, event.button.y)); + Vector2f pos = window.pixelsToTiles(Vector2i(event.button.x, event.button.y)); if (event.button.button == SDL_BUTTON_LEFT) return std::make_shared(pos, IMouseButtonEvent::MouseButton::LEFT); @@ -223,7 +223,7 @@ EventPtr EventsHandler::_handleMouseBtnReleaseEvent( sdl::Event &event, unused Window &window ) { - Vector2i pos = window.pixelsToTiles(Vector2i(event.button.x, event.button.y)); + Vector2f pos = window.pixelsToTiles(Vector2i(event.button.x, event.button.y)); if (event.button.button == SDL_BUTTON_LEFT) return std::make_shared(pos, IMouseButtonEvent::MouseButton::LEFT); diff --git a/graphics/sdl2/src/window/Renderer.cpp b/graphics/sdl2/src/window/Renderer.cpp index d1159d5..5e1db7f 100644 --- a/graphics/sdl2/src/window/Renderer.cpp +++ b/graphics/sdl2/src/window/Renderer.cpp @@ -108,7 +108,7 @@ void Renderer::_reset(sdl::Sprite &sprite) { sprite.setPosition({0, 0}); } -Vector2f Renderer::_entityPixelsPosition(const Vector2i &position) { +Vector2f Renderer::_entityPixelsPosition(const Vector2f &position) { auto pixels = _window.tilesToPixels(position); return { diff --git a/graphics/sdl2/src/window/Renderer.hpp b/graphics/sdl2/src/window/Renderer.hpp index 68ee8be..97843f1 100644 --- a/graphics/sdl2/src/window/Renderer.hpp +++ b/graphics/sdl2/src/window/Renderer.hpp @@ -64,7 +64,7 @@ class arcade::graphics::sdl2::window::Renderer { * @param position Tile position * @return Pixel position */ - Vector2f _entityPixelsPosition(const Vector2i &position); + Vector2f _entityPixelsPosition(const Vector2f &position); /** * @brief Align vertically the text diff --git a/graphics/sdl2/src/window/Window.cpp b/graphics/sdl2/src/window/Window.cpp index 7287c2a..5512cbc 100644 --- a/graphics/sdl2/src/window/Window.cpp +++ b/graphics/sdl2/src/window/Window.cpp @@ -14,7 +14,7 @@ using namespace arcade::graphics::sdl2::window; using namespace arcade::graphics::common::exceptions; -const Vector2u Window::tileSize = { 12, 12 }; +const Vector2u Window::tileSize = { 35, 35 }; Window::Window(const IWindow::WindowInitProps &props): _size(props.size), @@ -126,7 +126,7 @@ void Window::_initInnerWindow(const shared::graphics::IWindow::WindowInitProps & props.title, { SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED }, { static_cast(size.x), static_cast(size.y) }, - 0 + SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE ); } catch (const sdl::SDLException &e) { throw WindowException( @@ -147,21 +147,21 @@ Vector2u Window::_getPixelSizeFromTiles(const Vector2u &size) { return real; } -Vector2i Window::pixelsToTiles(const shared::types::Vector2i &position) const { +Vector2f Window::pixelsToTiles(const shared::types::Vector2i &position) const { auto realSize = _window.getSize(); return { - static_cast(position.x * _size.x / realSize.x), - static_cast(position.y * _size.y / realSize.y) + static_cast(position.x) * static_cast(_size.x) / static_cast(realSize.x), + static_cast(position.y) * static_cast(_size.y) / static_cast(realSize.y) }; } -Vector2i Window::tilesToPixels(const Vector2i &position) const { +Vector2i Window::tilesToPixels(const Vector2f &position) const { auto realSize = _window.getSize(); return { - static_cast(position.x * realSize.x / _size.x), - static_cast(position.y * realSize.y / _size.y) + static_cast(position.x) * realSize.x / static_cast(_size.x), + static_cast(position.y) * realSize.y / static_cast(_size.y) }; } diff --git a/graphics/sdl2/src/window/Window.hpp b/graphics/sdl2/src/window/Window.hpp index 7e2209c..7b73a25 100644 --- a/graphics/sdl2/src/window/Window.hpp +++ b/graphics/sdl2/src/window/Window.hpp @@ -141,13 +141,13 @@ class arcade::graphics::sdl2::window::Window: public shared::graphics::IWindow { * @brief Convert a position in pixels to a position in tiles * @return Converted position */ - Vector2i pixelsToTiles(const Vector2i &position) const; + Vector2f pixelsToTiles(const Vector2i &position) const; /** * @brief Convert a position in tiles to a position in pixels * @return Converted position */ - Vector2i tilesToPixels(const Vector2i &position) const; + Vector2i tilesToPixels(const Vector2f &position) const; /** * @brief Convert a position in tiles to a position in pixels From 1aa07d529512dfb48abd75fdd9cad84c586fc0cf Mon Sep 17 00:00:00 2001 From: Flavien Chenu Date: Sun, 7 Apr 2024 14:55:50 +0200 Subject: [PATCH 08/12] refactor: improve menu performances and fix window switching --- core/src/Core.cpp | 8 +- core/src/Core.hpp | 8 +- core/src/menu/Menu.cpp | 147 ++++++++++++----------- core/src/menu/Menu.hpp | 30 ++--- core/src/menu/entity/text/Text.cpp | 8 +- core/src/menu/entity/text/Text.hpp | 2 +- core/src/menu/entity/texture/Texture.cpp | 8 +- core/src/menu/entity/texture/Texture.hpp | 2 +- graphics/sdl2/sdl/renderer/Renderer.cpp | 6 +- graphics/sdl2/sdl/window/Window.cpp | 8 ++ graphics/sdl2/sdl/window/Window.hpp | 6 + graphics/sdl2/src/window/Renderer.cpp | 1 + graphics/sdl2/src/window/Window.cpp | 2 + graphics/sfml/src/window/Renderer.cpp | 1 + graphics/sfml/src/window/Window.cpp | 1 + 15 files changed, 140 insertions(+), 98 deletions(-) diff --git a/core/src/Core.cpp b/core/src/Core.cpp index 5965ae2..9c497c3 100644 --- a/core/src/Core.cpp +++ b/core/src/Core.cpp @@ -108,6 +108,7 @@ void Core::_initWindow() std::cerr << "No graphic provider selected, using default provider" << std::endl; } this->_window = this->_graphicsProvider->createWindow(windowInitProps); + this->_textures.clear(); this->_sceneStage = PLAY; } @@ -581,13 +582,16 @@ void Core::run() } if (this->_sceneStage == NEWGAME) this->_initGame(); - if (this->_sceneStage == RESUME) + if (this->_sceneStage == RESUME) { this->_initWindow(); + } if (this->_sceneStage == PLAY) { this->_game->compute(deltaTime); this->_gameEntities = this->_game->getEntities(); this->_handleEvents(); - this->_renderEntities(); + if (this->_window->isOpen()) { + this->_renderEntities(); + } } } } diff --git a/core/src/Core.hpp b/core/src/Core.hpp index f05b370..9917a8c 100644 --- a/core/src/Core.hpp +++ b/core/src/Core.hpp @@ -45,7 +45,7 @@ class Core { } SoundProps; std::shared_ptr _game; - std::shared_ptr _window; + std::unique_ptr _window; std::shared_ptr _gameProvider; std::shared_ptr _graphicsProvider; std::map> _fonts; @@ -96,6 +96,12 @@ class Core { */ void _loadFailed(const std::shared_ptr& text); + /** + * @brief Free current resources + * + */ + void _freeResources(); + /** * @brief Get a texture * diff --git a/core/src/menu/Menu.cpp b/core/src/menu/Menu.cpp index 3bc9252..229cbf3 100644 --- a/core/src/menu/Menu.cpp +++ b/core/src/menu/Menu.cpp @@ -10,9 +10,14 @@ #include #include "Menu.hpp" -Menu::Menu(GameProviders &gameProviders, GraphicsProviders &graphicsProviders, - std::shared_ptr &gameProvider, std::shared_ptr &graphicsProvider, arcade::core::SceneStage &sceneStage) : - _gameProviders(gameProviders), _graphicsProviders(graphicsProviders), +Menu::Menu( + GameProviders &gameProviders, + GraphicsProviders &graphicsProviders, + std::shared_ptr &gameProvider, + std::shared_ptr &graphicsProvider, + arcade::core::SceneStage &sceneStage +) : + _gameProviders(gameProviders), _graphicsProviders(graphicsProviders), _window(nullptr), _gameProvider(gameProvider), _graphicsProvider(graphicsProvider), _sceneStage(sceneStage) { this->_score.player = ""; @@ -64,17 +69,17 @@ std::string Menu::_truncString(const std::string &str, int size) return newString; } -void Menu::_initHiddenAuthors(const GameManifest &gameManifest, std::shared_ptr checkBox, std::shared_ptr font) +void Menu::_initHiddenAuthors(const GameManifest &gameManifest, const std::shared_ptr& checkBox, std::shared_ptr font) { auto authorNames = std::make_shared(font, 35, "Authors:", TextAlign::LEFT, TextVerticalAlign::MIDDLE, Color{255, 255, 255, 255}, Vector2u{8, 1}, Vector2f{26, 8}); this->_hiddenAuthors[checkBox].push_back(authorNames); auto authors = gameManifest.authors; float index = 10.0; - for (auto author : authors) { - auto authorNameText = std::make_shared(font, 30, this->_truncString(author.name, 22) , TextAlign::LEFT, TextVerticalAlign::MIDDLE, Color{255, 255, 255, 255}, Vector2u{22, 1}, Vector2f{27, index}); - auto authorMailText = std::make_shared(font, 30, this->_truncString(author.email, 22), TextAlign::LEFT, TextVerticalAlign::MIDDLE, Color{255, 255, 255, 255}, Vector2u{22, 1}, Vector2f{27, index + 1}); - auto authorSiteText = std::make_shared(font, 30, this->_truncString(author.website, 22), TextAlign::LEFT, TextVerticalAlign::MIDDLE, Color{255, 255, 255, 255}, Vector2u{22, 1}, Vector2f{27, index + 2}); + for (const auto& author : authors) { + auto authorNameText = std::make_shared(font, 30, Menu::_truncString(author.name, 22) , TextAlign::LEFT, TextVerticalAlign::MIDDLE, Color{255, 255, 255, 255}, Vector2u{22, 1}, Vector2f{27, index}); + auto authorMailText = std::make_shared(font, 30, Menu::_truncString(author.email, 22), TextAlign::LEFT, TextVerticalAlign::MIDDLE, Color{255, 255, 255, 255}, Vector2u{22, 1}, Vector2f{27, index + 1}); + auto authorSiteText = std::make_shared(font, 30, Menu::_truncString(author.website, 22), TextAlign::LEFT, TextVerticalAlign::MIDDLE, Color{255, 255, 255, 255}, Vector2u{22, 1}, Vector2f{27, index + 2}); this->_hiddenAuthors[checkBox].push_back(authorNameText); this->_hiddenAuthors[checkBox].push_back(authorMailText); this->_hiddenAuthors[checkBox].push_back(authorSiteText); @@ -82,18 +87,18 @@ void Menu::_initHiddenAuthors(const GameManifest &gameManifest, std::shared_ptr< } } -void Menu::_initHiddenScoreHeader(const GameManifest &gameManifest, std::shared_ptr checkBox, std::shared_ptr font) +void Menu::_initHiddenScoreHeader(const GameManifest &gameManifest, const std::shared_ptr& checkBox, const std::shared_ptr& font) { - auto truncatName = this->_truncString(gameManifest.name, 23); - auto nameText = std::make_shared(font, 35, truncatName, TextAlign::CENTER, TextVerticalAlign::MIDDLE, Color{255, 255, 255, 255}, Vector2u{23, 1}, Vector2f{25, 8}); + auto truncatedName = Menu::_truncString(gameManifest.name, 23); + auto nameText = std::make_shared(font, 35, truncatedName, TextAlign::CENTER, TextVerticalAlign::MIDDLE, Color{255, 255, 255, 255}, Vector2u{23, 1}, Vector2f{25, 8}); this->_hiddenTexts[checkBox].push_back(nameText); - auto truncatDesc = this->_truncString(gameManifest.description, 23); - auto descriptionText = std::make_shared(font, 30, truncatDesc, TextAlign::CENTER, TextVerticalAlign::MIDDLE, Color{255, 255, 255, 255}, Vector2u{23, 1}, Vector2f{25, 10}); + auto truncatedDesc = Menu::_truncString(gameManifest.description, 23); + auto descriptionText = std::make_shared(font, 30, truncatedDesc, TextAlign::CENTER, TextVerticalAlign::MIDDLE, Color{255, 255, 255, 255}, Vector2u{23, 1}, Vector2f{25, 10}); this->_hiddenTexts[checkBox].push_back(descriptionText); } -void Menu::_initHiddenScoreBoard(const GameManifest &gameManifest, std::shared_ptr checkBox, std::shared_ptr font) +void Menu::_initHiddenScoreBoard(const GameManifest &gameManifest, const std::shared_ptr& checkBox, const std::shared_ptr& font) { auto scoreHI = std::make_shared(font, 30, "HI-SCORE", TextAlign::LEFT, TextVerticalAlign::MIDDLE, Color{255, 255, 255, 255}, Vector2u{8, 1}, Vector2f{26, 12}); this->_hiddenTexts[checkBox].push_back(scoreHI); @@ -117,12 +122,12 @@ void Menu::_initHiddenScoreBoard(const GameManifest &gameManifest, std::shared_p if (count > 7) break; auto playerName = scoreElem.player.empty() ? "Guest" : scoreElem.player; - auto truncatPlayer = this->_truncString(playerName, 17); - auto playerText = std::make_shared(font, 25, truncatPlayer, TextAlign::LEFT, TextVerticalAlign::MIDDLE, Color{255, 255, 255, 255}, Vector2u{17, 1}, Vector2f{26, index}); - auto scoreString = std::to_string(scoreElem.score).substr(0, 5); + auto truncatedPlayer = Menu::_truncString(playerName, 17); + auto playerText = std::make_shared(font, 25, truncatedPlayer, TextAlign::LEFT, TextVerticalAlign::MIDDLE, Color{255, 255, 255, 255}, Vector2u{17, 1}, Vector2f{26, index}); + scoreString = std::to_string(scoreElem.score).substr(0, 5); while (scoreString.length() < 5) scoreString = "0" + scoreString; - auto scoreText = std::make_shared(font, 25, scoreString, TextAlign::RIGHT, TextVerticalAlign::MIDDLE, Color{255, 255, 255, 255}, Vector2u{5, 1}, Vector2f{43, index}); + scoreText = std::make_shared(font, 25, scoreString, TextAlign::RIGHT, TextVerticalAlign::MIDDLE, Color{255, 255, 255, 255}, Vector2u{5, 1}, Vector2f{43, index}); this->_hiddenTexts[checkBox].push_back(playerText); this->_hiddenTexts[checkBox].push_back(scoreText); index += 1; @@ -131,7 +136,7 @@ void Menu::_initHiddenScoreBoard(const GameManifest &gameManifest, std::shared_p } } -void Menu::_initHiddenScore(const GameManifest &gameManifest, std::shared_ptr checkBox, std::shared_ptr font) +void Menu::_initHiddenScore(const GameManifest &gameManifest, const std::shared_ptr& checkBox, const std::shared_ptr& font) { this->_initHiddenScoreHeader(gameManifest, checkBox, font); this->_initHiddenScoreBoard(gameManifest, checkBox, font); @@ -159,7 +164,7 @@ void Menu::_initCheckBoxesGames() } catch (const std::exception &e) { std::cerr << e.what() << std::endl; } - for (auto gameProvider : this->_gameProviders) { + for (const auto& gameProvider : this->_gameProviders) { if (count > 5) break; std::string truncatedName = gameProvider.second->getManifest().name.substr(0, 20); @@ -178,25 +183,25 @@ void Menu::_initCheckBoxesGames() this->_initNoGameFound(); } -void Menu::_initHiddenGraphicsHeader(const GraphicsManifest &graphicsManifest, std::shared_ptr checkBox, std::shared_ptr font) +void Menu::_initHiddenGraphicsHeader(const GraphicsManifest &graphicsManifest, const std::shared_ptr& checkBox, const std::shared_ptr& font) { - auto truncatName = this->_truncString(graphicsManifest.name, 23); - auto nameText = std::make_shared(font, 35, truncatName, TextAlign::CENTER, TextVerticalAlign::MIDDLE, Color{255, 255, 255, 255}, Vector2u{23, 1}, Vector2f{25, 8}); + auto truncatedName = Menu::_truncString(graphicsManifest.name, 23); + auto nameText = std::make_shared(font, 35, truncatedName, TextAlign::CENTER, TextVerticalAlign::MIDDLE, Color{255, 255, 255, 255}, Vector2u{23, 1}, Vector2f{25, 8}); this->_hiddenTexts[checkBox].push_back(nameText); - auto truncatDesc = this->_truncString(graphicsManifest.description, 23); - auto descriptionText = std::make_shared(font, 30, truncatDesc, TextAlign::CENTER, TextVerticalAlign::MIDDLE, Color{255, 255, 255, 255}, Vector2u{23, 1}, Vector2f{25, 10}); + auto truncatedDesc = Menu::_truncString(graphicsManifest.description, 23); + auto descriptionText = std::make_shared(font, 30, truncatedDesc, TextAlign::CENTER, TextVerticalAlign::MIDDLE, Color{255, 255, 255, 255}, Vector2u{23, 1}, Vector2f{25, 10}); this->_hiddenTexts[checkBox].push_back(descriptionText); } -void Menu::_initHiddenGraphicsBoard(const GraphicsManifest &graphicsManifest, std::shared_ptr checkBox, std::shared_ptr font) +void Menu::_initHiddenGraphicsBoard(const GraphicsManifest &graphicsManifest, const std::shared_ptr& checkBox, const std::shared_ptr& font) { auto authors = graphicsManifest.authors; float index = 12.0; - for (auto author : authors) { - auto authorNameText = std::make_shared(font, 25, this->_truncString(author.name, 23), TextAlign::CENTER, TextVerticalAlign::MIDDLE, Color{255, 255, 255, 255}, Vector2u{23, 1}, Vector2f{25, index}); - auto authorMailText = std::make_shared(font, 25, this->_truncString(author.email, 23), TextAlign::CENTER, TextVerticalAlign::MIDDLE, Color{255, 255, 255, 255}, Vector2u{23, 1}, Vector2f{25, index + 1}); - auto authorSiteText = std::make_shared(font, 25, this->_truncString(author.website, 23), TextAlign::CENTER, TextVerticalAlign::MIDDLE, Color{255, 255, 255, 255}, Vector2u{23, 1}, Vector2f{25, index + 2}); + for (const auto& author : authors) { + auto authorNameText = std::make_shared(font, 25, Menu::_truncString(author.name, 23), TextAlign::CENTER, TextVerticalAlign::MIDDLE, Color{255, 255, 255, 255}, Vector2u{23, 1}, Vector2f{25, index}); + auto authorMailText = std::make_shared(font, 25, Menu::_truncString(author.email, 23), TextAlign::CENTER, TextVerticalAlign::MIDDLE, Color{255, 255, 255, 255}, Vector2u{23, 1}, Vector2f{25, index + 1}); + auto authorSiteText = std::make_shared(font, 25, Menu::_truncString(author.website, 23), TextAlign::CENTER, TextVerticalAlign::MIDDLE, Color{255, 255, 255, 255}, Vector2u{23, 1}, Vector2f{25, index + 2}); this->_hiddenTexts[checkBox].push_back(authorNameText); this->_hiddenTexts[checkBox].push_back(authorMailText); this->_hiddenTexts[checkBox].push_back(authorSiteText); @@ -204,7 +209,7 @@ void Menu::_initHiddenGraphicsBoard(const GraphicsManifest &graphicsManifest, st } } -void Menu::_initHiddenGraphics(const GraphicsManifest &graphicsManifest, std::shared_ptr checkBox, std::shared_ptr font) +void Menu::_initHiddenGraphics(const GraphicsManifest &graphicsManifest, const std::shared_ptr& checkBox, const std::shared_ptr& font) { this->_initHiddenGraphicsHeader(graphicsManifest, checkBox, font); this->_initHiddenGraphicsBoard(graphicsManifest, checkBox, font); @@ -222,7 +227,7 @@ void Menu::_initCheckBoxesGraphics() } catch (const std::exception &e) { std::cerr << e.what() << std::endl; } - for (auto graphicsProvider : this->_graphicsProviders) { + for (const auto& graphicsProvider : this->_graphicsProviders) { if (count > 5) break; std::string truncatedName = graphicsProvider.second->getManifest().name.substr(0, 20); @@ -255,12 +260,11 @@ void Menu::_initTextures() void Menu::_initTexts() { - auto font = this->_graphicsProvider->createFont("assets/menu/fonts/arcade.ttf"); + this->_font = this->_graphicsProvider->createFont("assets/menu/fonts/arcade.ttf"); - this->_font = font; - auto games = std::make_shared(font, 40, "Games", TextAlign::CENTER, TextVerticalAlign::MIDDLE, Color{255, 255, 255, 255}, Vector2u{24, 1}, Vector2f{1, 7}); + auto games = std::make_shared(this->_font, 40, "Games", TextAlign::CENTER, TextVerticalAlign::MIDDLE, Color{255, 255, 255, 255}, Vector2u{24, 1}, Vector2f{1, 7}); this->_texts.push_back(games); - auto graphics = std::make_shared(font, 40, "Graphics", TextAlign::CENTER, TextVerticalAlign::MIDDLE, Color{255, 255, 255, 255}, Vector2u{24, 1}, Vector2f{1, 15}); + auto graphics = std::make_shared(this->_font, 40, "Graphics", TextAlign::CENTER, TextVerticalAlign::MIDDLE, Color{255, 255, 255, 255}, Vector2u{24, 1}, Vector2f{1, 15}); this->_texts.push_back(graphics); } @@ -297,8 +301,8 @@ void Menu::_initWindow() IWindow::WindowInitProps windowInitProps { .size = {50, 25}, .mode = IWindow::WindowMode::WINDOWED, - .fps = 60, - .title = "Menu", + .fps = 1, + .title = "Arcade - Menu", .icon = "assets/menu/img/icon.png" }; @@ -318,7 +322,7 @@ void Menu::_initWindow() void Menu::_handleSelectUpperCheckBox() { - for (auto checkBox : this->_gamesCheckBoxes) { + for (auto &checkBox : this->_gamesCheckBoxes) { if (checkBox->isHovered()) { checkBox->unhover(); auto index = std::distance(this->_gamesCheckBoxes.begin(), std::find(this->_gamesCheckBoxes.begin(), this->_gamesCheckBoxes.end(), checkBox)); @@ -329,7 +333,7 @@ void Menu::_handleSelectUpperCheckBox() break; } } - for (auto checkBox : this->_graphicsCheckBoxes) { + for (const auto& checkBox : this->_graphicsCheckBoxes) { if (checkBox->isHovered()) { checkBox->unhover(); auto index = std::distance(this->_graphicsCheckBoxes.begin(), std::find(this->_graphicsCheckBoxes.begin(), this->_graphicsCheckBoxes.end(), checkBox)); @@ -350,7 +354,7 @@ void Menu::_handleSelectUpperCheckBox() void Menu::_handleSelectLowerCheckBox() { - for (auto checkBox : this->_graphicsCheckBoxes) { + for (const auto& checkBox : this->_graphicsCheckBoxes) { if (checkBox->isHovered()) { checkBox->unhover(); auto index = std::distance(this->_graphicsCheckBoxes.begin(), std::find(this->_graphicsCheckBoxes.begin(), this->_graphicsCheckBoxes.end(), checkBox)); @@ -361,7 +365,7 @@ void Menu::_handleSelectLowerCheckBox() break; } } - for (auto checkBox : this->_gamesCheckBoxes) { + for (const auto& checkBox : this->_gamesCheckBoxes) { if (checkBox->isHovered()) { checkBox->unhover(); auto index = std::distance(this->_gamesCheckBoxes.begin(), std::find(this->_gamesCheckBoxes.begin(), this->_gamesCheckBoxes.end(), checkBox)); @@ -376,7 +380,7 @@ void Menu::_handleSelectLowerCheckBox() } } -void Menu::_handleKeyboardEvents(std::shared_ptr key) +void Menu::_handleKeyboardEvents(const std::shared_ptr& key) { if (!key) return; @@ -408,7 +412,7 @@ void Menu::_handleKeyboardEvents(std::shared_ptr key) void Menu::_selectGame() { if (this->_checkBoxType == GAME_CHECKBOX) { - for (auto checkBox : this->_gamesCheckBoxes) { + for (const auto& checkBox : this->_gamesCheckBoxes) { if (checkBox->isHovered() && checkBox->isChecked()) this->_exitWithNewGame(); if (checkBox->isHovered()) @@ -417,7 +421,7 @@ void Menu::_selectGame() checkBox->uncheck(); } } else { - for (auto checkBox : this->_graphicsCheckBoxes) { + for (const auto& checkBox : this->_graphicsCheckBoxes) { if (checkBox->isHovered() && checkBox->isChecked()) this->_changeGraphics(checkBox); if (checkBox->isHovered()) @@ -428,13 +432,14 @@ void Menu::_selectGame() } } -void Menu::_changeGraphics(std::shared_ptr checkBox) +void Menu::_changeGraphics(const std::shared_ptr& checkBox) { auto index = std::distance(this->_graphicsCheckBoxes.begin(), std::find(this->_graphicsCheckBoxes.begin(), this->_graphicsCheckBoxes.end(), checkBox)); auto graphicsProvider = this->_getGraphicsProvider(index); if (graphicsProvider != this->_graphicsProvider) { this->_graphicsProvider = graphicsProvider; this->_window->close(); + this->_window.reset(); this->_initWindow(); } } @@ -447,7 +452,7 @@ void Menu::_exitAndPlayOldGame() void Menu::_exitWithNewGame() { - for (auto checkBox : this->_gamesCheckBoxes) { + for (const auto& checkBox : this->_gamesCheckBoxes) { if (checkBox->isChecked()) { this->_gameProvider = this->_getGameProvider(std::distance(this->_gamesCheckBoxes.begin(), std::find(this->_gamesCheckBoxes.begin(), this->_gamesCheckBoxes.end(), checkBox))); break; @@ -457,7 +462,7 @@ void Menu::_exitWithNewGame() this->_window->close(); } -void Menu::_handleMouseMouveEvents(std::shared_ptr mouse) +void Menu::_handleMouseMoveEvents(const std::shared_ptr& mouse) { if (!mouse) return; @@ -465,15 +470,15 @@ void Menu::_handleMouseMouveEvents(std::shared_ptr mouse) std::shared_ptr lastHoveredCheckBox = nullptr; bool hoveredAtLeastOne = false; - for (auto checkBox : this->_gamesCheckBoxes) { + for (const auto& checkBox : this->_gamesCheckBoxes) { if (checkBox->isHovered()) lastHoveredCheckBox = checkBox; } - for (auto checkBox : this->_graphicsCheckBoxes) { + for (const auto& checkBox : this->_graphicsCheckBoxes) { if (checkBox->isHovered()) lastHoveredCheckBox = checkBox; } - for (auto checkBox : this->_gamesCheckBoxes) { + for (const auto& checkBox : this->_gamesCheckBoxes) { if (checkBox->isHovered()) checkBox->unhover(); if (checkBox->isHovered(position)) { @@ -482,7 +487,7 @@ void Menu::_handleMouseMouveEvents(std::shared_ptr mouse) hoveredAtLeastOne = true; } } - for (auto checkBox : this->_graphicsCheckBoxes) { + for (const auto& checkBox : this->_graphicsCheckBoxes) { if (checkBox->isHovered()) checkBox->unhover(); if (checkBox->isHovered(position)) { @@ -495,7 +500,7 @@ void Menu::_handleMouseMouveEvents(std::shared_ptr mouse) lastHoveredCheckBox->hover(); } -void Menu::_handleMouseButtonEvents(std::shared_ptr mouse) +void Menu::_handleMouseButtonEvents(const std::shared_ptr& mouse) { if (!mouse) return; @@ -505,8 +510,8 @@ void Menu::_handleMouseButtonEvents(std::shared_ptr m if (button != events::IMouseButtonEvent::MouseButton::LEFT) return; - this->_handleMouseMouveEvents(move); - for (auto checkBox : this->_gamesCheckBoxes) { + this->_handleMouseMoveEvents(move); + for (const auto& checkBox : this->_gamesCheckBoxes) { if (checkBox->isHovered(position)) { this->_selectGame(); } @@ -517,7 +522,7 @@ void Menu::_handleEvents() { auto events = this->_window->getEvents(); - for (auto event : events) { + for (const auto& event : events) { auto type = event->getType(); if (type == events::WINDOW_CLOSE) { this->_window->close(); @@ -529,7 +534,7 @@ void Menu::_handleEvents() } if (type == events::MOUSE_MOVE) { auto mouse = std::dynamic_pointer_cast(event); - this->_handleMouseMouveEvents(mouse); + this->_handleMouseMoveEvents(mouse); } if (type == events::MOUSE_BTN_PRESS) { auto mouse = std::dynamic_pointer_cast(event); @@ -546,8 +551,8 @@ void Menu::_renderField() auto placeholder = std::make_shared(this->_font, 30, "Guest", TextAlign::CENTER, TextVerticalAlign::MIDDLE, Color{255, 255, 255, 255}, Vector2u{16, 1}, Vector2f{17, 23}); this->_nameField = placeholder; } else { - auto truncatName = this->_truncString(this->_score.player, 17); - auto name = std::make_shared(this->_font, 35, truncatName, TextAlign::CENTER, TextVerticalAlign::MIDDLE, Color{255, 255, 255, 255}, Vector2u{16, 1}, Vector2f{17, 23}); + auto truncatedName = Menu::_truncString(this->_score.player, 17); + auto name = std::make_shared(this->_font, 35, truncatedName, TextAlign::CENTER, TextVerticalAlign::MIDDLE, Color{255, 255, 255, 255}, Vector2u{16, 1}, Vector2f{17, 23}); this->_nameField = name; } if (this->_nameField) @@ -557,28 +562,28 @@ void Menu::_renderField() void Menu::_render() { this->_window->clear(); - for (auto texture : this->_textures) { + for (auto &texture : this->_textures) { texture->draw(this->_window); } - for (auto text : this->_texts) { + for (auto &text : this->_texts) { text->draw(this->_window); } - for (auto checkBox : this->_gamesCheckBoxes) { + for (auto &checkBox : this->_gamesCheckBoxes) { if (checkBox->isHovered()) { if (this->_textType == GAME) { - for (auto text : this->_hiddenTexts[checkBox]) { + for (auto &text : this->_hiddenTexts[checkBox]) { text->draw(this->_window); } } else { - for (auto text : this->_hiddenAuthors[checkBox]) { + for (auto &text : this->_hiddenAuthors[checkBox]) { text->draw(this->_window); } } } } - for (auto checkBox : this->_graphicsCheckBoxes) { + for (auto &checkBox : this->_graphicsCheckBoxes) { if (checkBox->isHovered()) { - for (auto text : this->_hiddenTexts[checkBox]) { + for (auto &text : this->_hiddenTexts[checkBox]) { text->draw(this->_window); } } @@ -592,7 +597,7 @@ void Menu::_previousSelectedGame() this->_checkBoxType = GAME_CHECKBOX; if (this->_gamesCheckBoxes.empty()) return; - for (auto gameProvider : this->_gameProviders) { + for (const auto& gameProvider : this->_gameProviders) { if (this->_gameProvider == gameProvider.second) { auto index = std::distance(this->_gameProviders.begin(), std::find(this->_gameProviders.begin(), this->_gameProviders.end(), gameProvider)); auto checkBox = this->_gamesCheckBoxes.at(index); @@ -613,7 +618,7 @@ void Menu::_previousSelectedGraphics() { if (this->_graphicsCheckBoxes.empty()) return; - for (auto graphicsProvider : this->_graphicsProviders) { + for (const auto& graphicsProvider : this->_graphicsProviders) { if (this->_graphicsProvider == graphicsProvider.second) { auto index = std::distance(this->_graphicsProviders.begin(), std::find(this->_graphicsProviders.begin(), this->_graphicsProviders.end(), graphicsProvider)); auto checkBox = this->_graphicsCheckBoxes.at(index); @@ -646,10 +651,12 @@ void Menu::run() throw ArcadeError("Can't create window"); while (this->_window->isOpen()) { this->_handleEvents(); - this->_render(); + if (this->_window->isOpen()) + this->_render(); } if (this->_music) this->_music->setState(ISound::SoundState::STOP); + this->_window.reset(); } void Menu::_readScores() @@ -690,7 +697,7 @@ void Menu::_writeScore() scoreFile.close(); } -void Menu::updateScore(std::shared_ptr game) +void Menu::updateScore(const std::shared_ptr& game) { if (!game) return; diff --git a/core/src/menu/Menu.hpp b/core/src/menu/Menu.hpp index 8b77dbb..cceae02 100644 --- a/core/src/menu/Menu.hpp +++ b/core/src/menu/Menu.hpp @@ -43,7 +43,7 @@ class Menu { * * @param game Game */ - void updateScore(std::shared_ptr game); + void updateScore(const std::shared_ptr& game); private: @@ -68,7 +68,7 @@ class Menu { Score _score; std::vector _scores; SceneStage &_sceneStage; - std::shared_ptr _window; + std::unique_ptr _window; GameProviders &_gameProviders; GraphicsProviders &_graphicsProviders; std::shared_ptr &_gameProvider; @@ -120,25 +120,25 @@ class Menu { void _handleEvents(); /** - * @brief Handle mouse mouve events + * @brief Handle mouse move events * * @param mouse Mouse event */ - void _handleMouseMouveEvents(std::shared_ptr mouse); + void _handleMouseMoveEvents(const std::shared_ptr& mouse); /** * @brief Handle mouse button events * * @param mouse Mouse event */ - void _handleMouseButtonEvents(std::shared_ptr mouse); + void _handleMouseButtonEvents(const std::shared_ptr& mouse); /** * @brief Handle checkbox events * * @param key Key event */ - void _handleKeyboardEvents(std::shared_ptr key); + void _handleKeyboardEvents(const std::shared_ptr& key); /** * @brief Handle select upper checkbox @@ -174,7 +174,7 @@ class Menu { * @brief Change the text type * */ - void _changeGraphics(std::shared_ptr checkBox); + void _changeGraphics(const std::shared_ptr& checkBox); /** * @brief Initialize checkboxes for games @@ -206,7 +206,7 @@ class Menu { * @param gameManifest GameManifest * @param checkBox CheckBox */ - void _initHiddenAuthors(const GameManifest &gameManifest, std::shared_ptr checkBox, std::shared_ptr font); + void _initHiddenAuthors(const GameManifest &gameManifest, const std::shared_ptr& checkBox, std::shared_ptr font); /** * @brief Initialize hidden texts @@ -215,7 +215,7 @@ class Menu { * @param checkBox CheckBox * @param font IFont */ - void _initHiddenScore(const GameManifest &gameManifest, std::shared_ptr checkBox, std::shared_ptr font); + void _initHiddenScore(const GameManifest &gameManifest, const std::shared_ptr& checkBox, const std::shared_ptr& font); /** * @brief Initialize hidden score header @@ -224,7 +224,7 @@ class Menu { * @param checkBox CheckBox * @param font IFont */ - void _initHiddenScoreHeader(const GameManifest &gameManifest, std::shared_ptr checkBox, std::shared_ptr font); + void _initHiddenScoreHeader(const GameManifest &gameManifest, const std::shared_ptr& checkBox, const std::shared_ptr& font); /** * @brief Initialize hidden score board @@ -233,7 +233,7 @@ class Menu { * @param checkBox CheckBox * @param font IFont */ - void _initHiddenScoreBoard(const GameManifest &gameManifest, std::shared_ptr checkBox, std::shared_ptr font); + void _initHiddenScoreBoard(const GameManifest &gameManifest, const std::shared_ptr& checkBox, const std::shared_ptr& font); /** * @brief Initialize When No game found @@ -247,7 +247,7 @@ class Menu { * @param graphicsManifest GraphicsManifest * @param checkBox CheckBox */ - void _initHiddenGraphics(const GraphicsManifest &graphicsManifest, std::shared_ptr checkBox, std::shared_ptr font); + void _initHiddenGraphics(const GraphicsManifest &graphicsManifest, const std::shared_ptr& checkBox, const std::shared_ptr& font); /** * @brief Initialize hidden graphics header @@ -255,7 +255,7 @@ class Menu { * @param graphicsManifest GraphicsManifest * @param checkBox CheckBox */ - void _initHiddenGraphicsHeader(const GraphicsManifest &graphicsManifest, std::shared_ptr checkBox, std::shared_ptr font); + void _initHiddenGraphicsHeader(const GraphicsManifest &graphicsManifest, const std::shared_ptr& checkBox, const std::shared_ptr& font); /** * @brief Initialize hidden graphics board @@ -263,7 +263,7 @@ class Menu { * @param graphicsManifest GraphicsManifest * @param checkBox CheckBox */ - void _initHiddenGraphicsBoard(const GraphicsManifest &graphicsManifest, std::shared_ptr checkBox, std::shared_ptr font); + void _initHiddenGraphicsBoard(const GraphicsManifest &graphicsManifest, const std::shared_ptr& checkBox, const std::shared_ptr& font); /** * @brief Initialize texts @@ -290,7 +290,7 @@ class Menu { * @param size * @return std::string */ - std::string _truncString(const std::string &str, int size); + static std::string _truncString(const std::string &str, int size); /** * @brief Sort the scores diff --git a/core/src/menu/entity/text/Text.cpp b/core/src/menu/entity/text/Text.cpp index ded76d3..ff62a44 100644 --- a/core/src/menu/entity/text/Text.cpp +++ b/core/src/menu/entity/text/Text.cpp @@ -7,15 +7,17 @@ #include "Text.hpp" +#include + Text::Text(std::shared_ptr font, unsigned int fontSize, std::string content, TextAlign align, TextVerticalAlign verticalAlign, Color color, Vector2u size, Vector2f position) : - _font(font), _fontSize(fontSize), _content(content), _align(align), _verticalAlign(verticalAlign), + _font(std::move(font)), _fontSize(fontSize), _content(std::move(content)), _align(align), _verticalAlign(verticalAlign), _color(color), _size(size), _position(position) {} -Text::~Text() {} +Text::~Text() = default; -void Text::draw(std::shared_ptr window) +void Text::draw(std::unique_ptr &window) { TextProps textProps = { .font = this->_font, diff --git a/core/src/menu/entity/text/Text.hpp b/core/src/menu/entity/text/Text.hpp index fa59e3a..d3ee9a7 100644 --- a/core/src/menu/entity/text/Text.hpp +++ b/core/src/menu/entity/text/Text.hpp @@ -35,7 +35,7 @@ class Text { * * @param window Window to draw on */ - void draw(std::shared_ptr window); + void draw(std::unique_ptr &window); /** * @brief Set the Color object diff --git a/core/src/menu/entity/texture/Texture.cpp b/core/src/menu/entity/texture/Texture.cpp index 64d088e..b8fd371 100644 --- a/core/src/menu/entity/texture/Texture.cpp +++ b/core/src/menu/entity/texture/Texture.cpp @@ -7,13 +7,15 @@ #include "Texture.hpp" +#include + Texture::Texture(std::shared_ptr texture, Vector2f binTileSize, Vector2u origin, - Vector2u size, Vector2f position) : _texture(texture), _binTileSize(binTileSize), _origin(origin), + Vector2u size, Vector2f position) : _texture(std::move(texture)), _binTileSize(binTileSize), _origin(origin), _size(size), _position(position) {} -Texture::~Texture() {} +Texture::~Texture() = default; -void Texture::draw(std::shared_ptr window) +void Texture::draw(std::unique_ptr &window) { TextureProps textureProps = { .texture = this->_texture, diff --git a/core/src/menu/entity/texture/Texture.hpp b/core/src/menu/entity/texture/Texture.hpp index 41a03ad..e2885d3 100644 --- a/core/src/menu/entity/texture/Texture.hpp +++ b/core/src/menu/entity/texture/Texture.hpp @@ -39,7 +39,7 @@ class Texture { * * @param window Window to draw on */ - void draw(std::shared_ptr window); + void draw(std::unique_ptr &window); /** * @brief Set the Position object diff --git a/graphics/sdl2/sdl/renderer/Renderer.cpp b/graphics/sdl2/sdl/renderer/Renderer.cpp index f91a6a6..ddb6eff 100644 --- a/graphics/sdl2/sdl/renderer/Renderer.cpp +++ b/graphics/sdl2/sdl/renderer/Renderer.cpp @@ -5,6 +5,7 @@ ** Renderer.cpp */ +#include #include "Renderer.hpp" #include "sdl/text/Text.hpp" #include "sdl/types/Color.hpp" @@ -82,8 +83,9 @@ void Renderer::_copy(const Texture &texture, SDL_Rect *srcRect, SDL_FRect *destR destRect ); - if (copy < 0) - throw SDLException("Failed to copy texture"); + if (copy < 0) { + throw SDLException("Failed to copy texture: " + std::string(SDL_GetError())); + } } void Renderer::setFramerateLimit(unsigned int fps) { diff --git a/graphics/sdl2/sdl/window/Window.cpp b/graphics/sdl2/sdl/window/Window.cpp index 6e47a4c..b8414ba 100644 --- a/graphics/sdl2/sdl/window/Window.cpp +++ b/graphics/sdl2/sdl/window/Window.cpp @@ -5,6 +5,7 @@ ** Window.cpp */ +#include #include "Window.hpp" #include "sdl/exception/Exception.hpp" @@ -81,6 +82,13 @@ Renderer &Window::getRenderer() { return _renderer; } +void Window::close() +{ + if (_window) + SDL_DestroyWindow(_window); + _window = nullptr; +} + bool Window::pollEvent(Event &event) { return SDL_PollEvent(&event); } diff --git a/graphics/sdl2/sdl/window/Window.hpp b/graphics/sdl2/sdl/window/Window.hpp index 7baf7df..e230b31 100644 --- a/graphics/sdl2/sdl/window/Window.hpp +++ b/graphics/sdl2/sdl/window/Window.hpp @@ -38,6 +38,12 @@ class sdl::Window { Uint32 flags = SDL_WINDOW_SHOWN ); + /** + * @brief Close the window + * + */ + void close(); + /** * @brief Get the window * @return SDL_Window diff --git a/graphics/sdl2/src/window/Renderer.cpp b/graphics/sdl2/src/window/Renderer.cpp index 5e1db7f..9e8c238 100644 --- a/graphics/sdl2/src/window/Renderer.cpp +++ b/graphics/sdl2/src/window/Renderer.cpp @@ -5,6 +5,7 @@ ** Renderer.cpp */ +#include #include "Window.hpp" #include "Renderer.hpp" #include "font/Font.hpp" diff --git a/graphics/sdl2/src/window/Window.cpp b/graphics/sdl2/src/window/Window.cpp index 5512cbc..c3089be 100644 --- a/graphics/sdl2/src/window/Window.cpp +++ b/graphics/sdl2/src/window/Window.cpp @@ -5,6 +5,7 @@ ** Window class */ +#include #include "Window.hpp" #include "EventsHandler.hpp" #include "graphics/sdl2/sdl/exception/Exception.hpp" @@ -112,6 +113,7 @@ void Window::display() { void Window::close() { _isOpen = false; + _window.close(); } std::vector Window::getEvents() { diff --git a/graphics/sfml/src/window/Renderer.cpp b/graphics/sfml/src/window/Renderer.cpp index c2b78d1..91434a8 100644 --- a/graphics/sfml/src/window/Renderer.cpp +++ b/graphics/sfml/src/window/Renderer.cpp @@ -5,6 +5,7 @@ ** Renderer.cpp */ +#include #include "Window.hpp" #include "Renderer.hpp" #include "font/Font.hpp" diff --git a/graphics/sfml/src/window/Window.cpp b/graphics/sfml/src/window/Window.cpp index 3122d32..dbf9424 100644 --- a/graphics/sfml/src/window/Window.cpp +++ b/graphics/sfml/src/window/Window.cpp @@ -5,6 +5,7 @@ ** Window class */ +#include #include "Window.hpp" #include "EventsHandler.hpp" #include "common/events/mouse/mouse.hpp" From c27f4719051dda80d73f44515acbf241d6f68367 Mon Sep 17 00:00:00 2001 From: Flavien Chenu Date: Sun, 7 Apr 2024 15:25:15 +0200 Subject: [PATCH 09/12] fix(graphics:sdl): illogical bug --- CMakeLists.txt | 2 +- core/src/menu/Menu.cpp | 5 +++-- graphics/sdl2/src/window/EventsHandler.cpp | 15 +++++---------- graphics/sdl2/src/window/EventsHandler.hpp | 18 +----------------- 4 files changed, 10 insertions(+), 30 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b23028f..9c06d1c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ set(ARCADE_BIN_DIR ${CMAKE_CURRENT_LIST_DIR}) set(ARCADE_LIB_DIR ${CMAKE_CURRENT_LIST_DIR}/lib) set(CMAKE_CXX_STANDARD 20) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++20") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++20 -g") set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${ARCADE_BIN_DIR}) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${ARCADE_LIB_DIR}) diff --git a/core/src/menu/Menu.cpp b/core/src/menu/Menu.cpp index 229cbf3..e390c6a 100644 --- a/core/src/menu/Menu.cpp +++ b/core/src/menu/Menu.cpp @@ -307,6 +307,7 @@ void Menu::_initWindow() }; try { + this->_window.reset(); this->_window = this->_graphicsProvider->createWindow(windowInitProps); this->_clearLists(); this->_preventGraphicsProvider(); @@ -459,7 +460,8 @@ void Menu::_exitWithNewGame() } } this->_sceneStage = NEWGAME; - this->_window->close(); + if (this->_window) + this->_window->close(); } void Menu::_handleMouseMoveEvents(const std::shared_ptr& mouse) @@ -656,7 +658,6 @@ void Menu::run() } if (this->_music) this->_music->setState(ISound::SoundState::STOP); - this->_window.reset(); } void Menu::_readScores() diff --git a/graphics/sdl2/src/window/EventsHandler.cpp b/graphics/sdl2/src/window/EventsHandler.cpp index 0554187..ae31923 100644 --- a/graphics/sdl2/src/window/EventsHandler.cpp +++ b/graphics/sdl2/src/window/EventsHandler.cpp @@ -20,8 +20,7 @@ EventsHandler::EventHandler EventsHandler::_getHandler(sdl::EventType type) { {SDL_MOUSEBUTTONDOWN, _handleMouseButtonPressEvent}, {SDL_MOUSEBUTTONUP, _handleMouseBtnReleaseEvent}, {SDL_MOUSEMOTION, _handleMouseMoveEvent}, - {SDL_QUIT, _handleWindowCloseEvent}, - {SDL_WINDOWEVENT, _handleWindowResizeEvent} + {SDL_WINDOWEVENT, _handleWindowEvents} }; auto handler = handlers.find(type); @@ -179,20 +178,16 @@ EventPtr EventsHandler::_handleKeyReleaseEvent( return std::make_shared(type, code); } -EventPtr EventsHandler::_handleWindowCloseEvent( - unused sdl::Event &event, - unused Window &window -) { - return std::make_shared(); -} - -EventPtr EventsHandler::_handleWindowResizeEvent( +EventPtr EventsHandler::_handleWindowEvents( sdl::Event &event, unused Window &window ) { + if (event.window.event == SDL_WINDOWEVENT_CLOSE) + return std::make_shared(); if (event.window.event == SDL_WINDOWEVENT_RESIZED) return std::make_shared(); return nullptr; + } EventPtr EventsHandler::_handleMouseMoveEvent( diff --git a/graphics/sdl2/src/window/EventsHandler.hpp b/graphics/sdl2/src/window/EventsHandler.hpp index 68c51ea..1f5d06c 100644 --- a/graphics/sdl2/src/window/EventsHandler.hpp +++ b/graphics/sdl2/src/window/EventsHandler.hpp @@ -115,23 +115,7 @@ class arcade::graphics::sdl2::window::EventsHandler { * @param window Window object * @return Pointer to created event or null if not handled */ - static EventPtr _handleWindowCloseEvent(sdl::Event &event, Window &window); - - /** - * @brief Handle window resize event - * @param event Event from SDL2 - * @param window Window object - * @return Pointer to created event or null if not handled - */ - static EventPtr _handleWindowResizeEvent(sdl::Event &event, Window &window); - - /** - * @brief Resolve position of the event to convert it in tiles unit - * @param position Position to resolve - * @param window Window object of which relate the position - * @return Resolved position - */ - static Vector2i _resolvePosition(Vector2i position, Window &window); + static EventPtr _handleWindowEvents(sdl::Event &event, Window &window); window::Window &_window; }; From ab936e04787e8f896ade16c80feab4511e741b5b Mon Sep 17 00:00:00 2001 From: Flavien Chenu Date: Sun, 7 Apr 2024 15:48:41 +0200 Subject: [PATCH 10/12] fix(graphics:sdl): white window when pausing --- core/src/menu/Menu.cpp | 1 - graphics/sdl2/sdl/renderer/Renderer.cpp | 8 ++++++++ graphics/sdl2/sdl/renderer/Renderer.hpp | 6 ++++++ graphics/sdl2/sdl/window/Window.cpp | 5 ++++- 4 files changed, 18 insertions(+), 2 deletions(-) diff --git a/core/src/menu/Menu.cpp b/core/src/menu/Menu.cpp index e390c6a..70a7ff4 100644 --- a/core/src/menu/Menu.cpp +++ b/core/src/menu/Menu.cpp @@ -307,7 +307,6 @@ void Menu::_initWindow() }; try { - this->_window.reset(); this->_window = this->_graphicsProvider->createWindow(windowInitProps); this->_clearLists(); this->_preventGraphicsProvider(); diff --git a/graphics/sdl2/sdl/renderer/Renderer.cpp b/graphics/sdl2/sdl/renderer/Renderer.cpp index ddb6eff..f91a110 100644 --- a/graphics/sdl2/sdl/renderer/Renderer.cpp +++ b/graphics/sdl2/sdl/renderer/Renderer.cpp @@ -25,12 +25,20 @@ SDL_Renderer *Renderer::operator()() const { } Renderer &Renderer::create() { + reset(); _renderer = SDL_CreateRenderer(_window(), -1, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED); if (!_renderer) throw SDLException("Failed to create renderer"); return *this; } +void Renderer::reset() { + if (_renderer) { + SDL_DestroyRenderer(_renderer); + _renderer = nullptr; + } +} + void Renderer::drawColor(Color color) { if (SDL_SetRenderDrawColor(_safeRenderer(), color.r, color.g, color.b, color.a) < 0) throw SDLException("Failed to set draw color"); diff --git a/graphics/sdl2/sdl/renderer/Renderer.hpp b/graphics/sdl2/sdl/renderer/Renderer.hpp index 95376bc..24e2054 100644 --- a/graphics/sdl2/sdl/renderer/Renderer.hpp +++ b/graphics/sdl2/sdl/renderer/Renderer.hpp @@ -32,6 +32,12 @@ class sdl::Renderer { */ Renderer& create(); + /** + * @brief Reset the internal renderer + * + */ + void reset(); + /** * @brief Get the renderer * @return SDL_Renderer diff --git a/graphics/sdl2/sdl/window/Window.cpp b/graphics/sdl2/sdl/window/Window.cpp index b8414ba..cca6fd4 100644 --- a/graphics/sdl2/sdl/window/Window.cpp +++ b/graphics/sdl2/sdl/window/Window.cpp @@ -40,8 +40,10 @@ SDL_Window *Window::operator()() const { } Window::~Window() { - if (_window) + if (_window) { SDL_DestroyWindow(_window); + _renderer.reset(); + } } SDL_Window *Window::_safeWindow() const { @@ -86,6 +88,7 @@ void Window::close() { if (_window) SDL_DestroyWindow(_window); + _renderer.reset(); _window = nullptr; } From 0b9a082b08a9763f1595b56825c20069f3ed2e47 Mon Sep 17 00:00:00 2001 From: Flavien Chenu Date: Sun, 7 Apr 2024 15:55:17 +0200 Subject: [PATCH 11/12] fix(graphics:sdl): white window when pausing --- graphics/sdl2/sdl/window/Window.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/graphics/sdl2/sdl/window/Window.cpp b/graphics/sdl2/sdl/window/Window.cpp index cca6fd4..18baa29 100644 --- a/graphics/sdl2/sdl/window/Window.cpp +++ b/graphics/sdl2/sdl/window/Window.cpp @@ -40,10 +40,7 @@ SDL_Window *Window::operator()() const { } Window::~Window() { - if (_window) { - SDL_DestroyWindow(_window); - _renderer.reset(); - } + close(); } SDL_Window *Window::_safeWindow() const { @@ -86,9 +83,10 @@ Renderer &Window::getRenderer() { void Window::close() { - if (_window) + if (_window) { + _renderer.reset(); SDL_DestroyWindow(_window); - _renderer.reset(); + } _window = nullptr; } From 574f4b199bb5fbbf052dba13a9ce1f1ae177fd62 Mon Sep 17 00:00:00 2001 From: Flavien Chenu Date: Sun, 7 Apr 2024 23:03:15 +0200 Subject: [PATCH 12/12] fix(graphics:sdl): sdl library switching --- CMakeLists.txt | 2 +- core/src/Core.cpp | 6 +++++- core/src/menu/Menu.cpp | 19 +++++++++++++------ graphics/ncurses/src/window/Window.cpp | 6 +++--- graphics/sdl2/sdl/text/Font.cpp | 1 + graphics/sdl2/sdl/window/Window.cpp | 4 ++-- graphics/sdl2/src/GraphicsProvider.cpp | 6 ++++-- graphics/sdl2/src/GraphicsProvider.hpp | 2 +- 8 files changed, 30 insertions(+), 16 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9c06d1c..ca4aca6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ set(ARCADE_BIN_DIR ${CMAKE_CURRENT_LIST_DIR}) set(ARCADE_LIB_DIR ${CMAKE_CURRENT_LIST_DIR}/lib) set(CMAKE_CXX_STANDARD 20) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++20 -g") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++20 -fno-gnu-unique") set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${ARCADE_BIN_DIR}) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${ARCADE_LIB_DIR}) diff --git a/core/src/Core.cpp b/core/src/Core.cpp index d1076b4..7a9e2b0 100644 --- a/core/src/Core.cpp +++ b/core/src/Core.cpp @@ -419,9 +419,13 @@ void Core::_handleWindowClose() { if (this->_window && this->_window->isOpen()) { this->_stopAllGraphicsSounds(); + this->_textures.clear(); + this->_fonts.clear(); this->_window->close(); + this->_sounds.clear(); this->_menu.updateScore(this->_game); this->_sceneStage = MENU; + this->_window.reset(); } } @@ -592,7 +596,7 @@ void Core::run() this->_game->compute(deltaTime); this->_gameEntities = this->_game->getEntities(); this->_handleEvents(); - if (this->_window->isOpen()) { + if (this->_window && this->_window->isOpen()) { this->_renderEntities(); } } diff --git a/core/src/menu/Menu.cpp b/core/src/menu/Menu.cpp index b5dbfaa..8ba2a46 100644 --- a/core/src/menu/Menu.cpp +++ b/core/src/menu/Menu.cpp @@ -452,7 +452,10 @@ void Menu::_changeGraphics(const std::shared_ptr& checkBox) void Menu::_exitAndPlayOldGame() { this->_sceneStage = RESUME; - this->_window->close(); + if (this->_window) { + this->_clearLists(); + this->_window.reset(); + } } void Menu::_exitWithNewGame() @@ -464,8 +467,11 @@ void Menu::_exitWithNewGame() } } this->_sceneStage = NEWGAME; - if (this->_window) + if (this->_window) { this->_window->close(); + this->_clearLists(); + this->_window.reset(); + } } void Menu::_handleMouseMoveEvents(const std::shared_ptr& mouse) @@ -522,7 +528,7 @@ void Menu::_handleMouseButtonEvents(const std::shared_ptr_selectGame(); } } - for (auto checkBox : this->_graphicsCheckBoxes) { + for (auto &checkBox : this->_graphicsCheckBoxes) { if (checkBox->isHovered(position)) { this->_selectGame(); } @@ -660,13 +666,14 @@ void Menu::run() this->_previousSelectedGraphics(); if (!this->_window) throw ArcadeError("Can't create window"); - while (this->_window->isOpen()) { + while (this->_window && this->_window->isOpen()) { + this->_render(); this->_handleEvents(); - if (this->_window->isOpen()) - this->_render(); } if (this->_music) this->_music->setState(ISound::SoundState::STOP); + this->_clearLists(); + this->_window.reset(); } void Menu::_readScores() diff --git a/graphics/ncurses/src/window/Window.cpp b/graphics/ncurses/src/window/Window.cpp index 2126418..4a03260 100644 --- a/graphics/ncurses/src/window/Window.cpp +++ b/graphics/ncurses/src/window/Window.cpp @@ -31,7 +31,7 @@ Window::Window(const IWindow::WindowInitProps &props): noecho(); keypad(stdscr, TRUE); nodelay(stdscr, TRUE); - mousemask(ALL_MOUSE_EVENTS, NULL); + mousemask(ALL_MOUSE_EVENTS, nullptr); curs_set(0); _window = std::unique_ptr(newwin(_size.y, _size.x, 0, 0), &delwin); } @@ -39,7 +39,7 @@ Window::Window(const IWindow::WindowInitProps &props): Window::~Window() { wclear(stdscr); - close(); + Window::close(); endwin(); } @@ -89,7 +89,7 @@ void Window::render(const shared::graphics::TextProps &props) { } void Window::clear() { - wclear(_window.get()); + werase(_window.get()); } void Window::display() { diff --git a/graphics/sdl2/sdl/text/Font.cpp b/graphics/sdl2/sdl/text/Font.cpp index 651680f..fd81df7 100644 --- a/graphics/sdl2/sdl/text/Font.cpp +++ b/graphics/sdl2/sdl/text/Font.cpp @@ -36,6 +36,7 @@ bool Font::load(const std::string &path, int ptSize) { Font::~Font() { if (_font) TTF_CloseFont(_font); + _font = nullptr; } TTF_Font *Font::_safeFont() const { diff --git a/graphics/sdl2/sdl/window/Window.cpp b/graphics/sdl2/sdl/window/Window.cpp index 18baa29..e2c3509 100644 --- a/graphics/sdl2/sdl/window/Window.cpp +++ b/graphics/sdl2/sdl/window/Window.cpp @@ -5,9 +5,9 @@ ** Window.cpp */ -#include #include "Window.hpp" #include "sdl/exception/Exception.hpp" +#include "sdl/initializer/Initializer.hpp" using namespace sdl; @@ -21,6 +21,7 @@ Window &Window::create( const Vector2i &size, Uint32 flags ) { + Initializer::init(); _window = SDL_CreateWindow( title.c_str(), position.x, @@ -84,7 +85,6 @@ Renderer &Window::getRenderer() { void Window::close() { if (_window) { - _renderer.reset(); SDL_DestroyWindow(_window); } _window = nullptr; diff --git a/graphics/sdl2/src/GraphicsProvider.cpp b/graphics/sdl2/src/GraphicsProvider.cpp index c460f9c..a53cd41 100644 --- a/graphics/sdl2/src/GraphicsProvider.cpp +++ b/graphics/sdl2/src/GraphicsProvider.cpp @@ -27,8 +27,10 @@ const GraphicsManifest GraphicsProvider::_manifest = { } }; -GraphicsProvider::GraphicsProvider() { - sdl::Initializer::init(); +GraphicsProvider::GraphicsProvider() = default; + +GraphicsProvider::~GraphicsProvider() { + sdl::Initializer::quit(); } const shared::graphics::GraphicsManifest &GraphicsProvider::getManifest() const noexcept { diff --git a/graphics/sdl2/src/GraphicsProvider.hpp b/graphics/sdl2/src/GraphicsProvider.hpp index a21ec81..2bd3eb9 100644 --- a/graphics/sdl2/src/GraphicsProvider.hpp +++ b/graphics/sdl2/src/GraphicsProvider.hpp @@ -22,7 +22,7 @@ class arcade::graphics::sdl2::GraphicsProvider : public IGraphicsProvider { public: GraphicsProvider(); - ~GraphicsProvider() override = default; + ~GraphicsProvider() override; /** * @brief Get the manifest of the graphics library