From 8b8e9c89782026ef5ed46ec9e5c1c73242de0a77 Mon Sep 17 00:00:00 2001 From: Yann Date: Sun, 7 Apr 2024 17:41:13 +0200 Subject: [PATCH 1/7] feat(ncurses): add base --- graphics/CMakeLists.txt | 2 +- graphics/ncurses/CMakeLists.txt | 21 ++ graphics/ncurses/export.cpp | 15 +- graphics/ncurses/src/GraphicsProvider.cpp | 52 ++++ graphics/ncurses/src/GraphicsProvider.hpp | 68 +++++ graphics/ncurses/src/font/Font.cpp | 13 + graphics/ncurses/src/font/Font.hpp | 22 ++ graphics/ncurses/src/sound/Sound.cpp | 32 +++ graphics/ncurses/src/sound/Sound.hpp | 31 +++ graphics/ncurses/src/texture/Texture.cpp | 45 ++++ graphics/ncurses/src/texture/Texture.hpp | 37 +++ graphics/ncurses/src/window/EventsHandler.cpp | 247 ++++++++++++++++++ graphics/ncurses/src/window/EventsHandler.hpp | 136 ++++++++++ graphics/ncurses/src/window/Renderer.cpp | 67 +++++ graphics/ncurses/src/window/Renderer.hpp | 89 +++++++ graphics/ncurses/src/window/Window.cpp | 107 ++++++++ graphics/ncurses/src/window/Window.hpp | 160 ++++++++++++ 17 files changed, 1138 insertions(+), 6 deletions(-) create mode 100644 graphics/ncurses/src/GraphicsProvider.cpp create mode 100644 graphics/ncurses/src/GraphicsProvider.hpp create mode 100644 graphics/ncurses/src/font/Font.cpp create mode 100644 graphics/ncurses/src/font/Font.hpp create mode 100644 graphics/ncurses/src/sound/Sound.cpp create mode 100644 graphics/ncurses/src/sound/Sound.hpp create mode 100644 graphics/ncurses/src/texture/Texture.cpp create mode 100644 graphics/ncurses/src/texture/Texture.hpp create mode 100644 graphics/ncurses/src/window/EventsHandler.cpp create mode 100644 graphics/ncurses/src/window/EventsHandler.hpp create mode 100644 graphics/ncurses/src/window/Renderer.cpp create mode 100644 graphics/ncurses/src/window/Renderer.hpp create mode 100644 graphics/ncurses/src/window/Window.cpp create mode 100644 graphics/ncurses/src/window/Window.hpp diff --git a/graphics/CMakeLists.txt b/graphics/CMakeLists.txt index 2715642..1d54559 100644 --- a/graphics/CMakeLists.txt +++ b/graphics/CMakeLists.txt @@ -1,2 +1,2 @@ -#add_subdirectory(ncurses) +add_subdirectory(ncurses) add_subdirectory(sfml) diff --git a/graphics/ncurses/CMakeLists.txt b/graphics/ncurses/CMakeLists.txt index 8abe0ed..4293bad 100644 --- a/graphics/ncurses/CMakeLists.txt +++ b/graphics/ncurses/CMakeLists.txt @@ -1,5 +1,26 @@ +project(ncurses) add_library(ncurses 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(ncurses PUBLIC ${CMAKE_CURRENT_LIST_DIR}/src) target_include_directories(ncurses PUBLIC ${CMAKE_CURRENT_LIST_DIR}/../..) +target_include_directories(ncurses PUBLIC ${CMAKE_CURRENT_LIST_DIR}/..) + +find_package(Curses REQUIRED) +target_link_libraries(ncurses ${CURSES_LIBRARIES}) diff --git a/graphics/ncurses/export.cpp b/graphics/ncurses/export.cpp index 8ba688b..e5f48bd 100644 --- a/graphics/ncurses/export.cpp +++ b/graphics/ncurses/export.cpp @@ -7,16 +7,21 @@ #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" { - shared::types::LibraryType SHARED_LIBRARY_TYPE_GETTER_NAME(void) + LibraryType SHARED_LIBRARY_TYPE_GETTER_NAME(void) { - return shared::types::LibraryType::GRAPHIC; + return LibraryType::GRAPHIC; } -/* std::shared_ptr SHARED_GRAPHICS_PROVIDER_LOADER_NAME(void) + IGraphicsProvider *SHARED_GRAPHICS_PROVIDER_GETTER_NAME(void) { - return std::make_shared(...); - }*/ + return new ncurses::GraphicsProvider(); + } } diff --git a/graphics/ncurses/src/GraphicsProvider.cpp b/graphics/ncurses/src/GraphicsProvider.cpp new file mode 100644 index 0000000..e154ef6 --- /dev/null +++ b/graphics/ncurses/src/GraphicsProvider.cpp @@ -0,0 +1,52 @@ +/* +** 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 shared::graphics; +using namespace arcade::graphics::ncurses; + +const shared::graphics::GraphicsManifest GraphicsProvider::_manifest = { + .name = "ncurses", + .description = "NCURSES Library", + .version = "1.0", + .authors = { + { + .name = "Yann Masson", + .email = "yann.masson@epitech.eu", + .website = "yannmasson.fr" + } + } +}; + +GraphicsProvider::GraphicsProvider() = default; + +const 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_ptr GraphicsProvider::createTexture(unused const std::string &bin, const std::string &ascii) { + return std::make_shared(ascii); +} + +std::shared_ptr GraphicsProvider::createFont(const std::string &path) { + return std::make_shared(path); +} diff --git a/graphics/ncurses/src/GraphicsProvider.hpp b/graphics/ncurses/src/GraphicsProvider.hpp new file mode 100644 index 0000000..b617564 --- /dev/null +++ b/graphics/ncurses/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" + +using namespace shared::graphics; + +namespace arcade::graphics::ncurses +{ + class GraphicsProvider; +} + +class arcade::graphics::ncurses::GraphicsProvider : public shared::graphics::IGraphicsProvider +{ +public: + GraphicsProvider(); + ~GraphicsProvider() override = default; + + /** + * @brief Get the manifest of the graphics library + * + * @return Manifest of the graphics library + */ + const shared::graphics::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 shared::graphics::GraphicsManifest _manifest; +}; diff --git a/graphics/ncurses/src/font/Font.cpp b/graphics/ncurses/src/font/Font.cpp new file mode 100644 index 0000000..50012e8 --- /dev/null +++ b/graphics/ncurses/src/font/Font.cpp @@ -0,0 +1,13 @@ +/* +** EPITECH PROJECT, 2024 +** arcade +** File description: +** Font.cpp +*/ + +#include "Font.hpp" +#include "common/exceptions/FontException.hpp" + +using namespace arcade::graphics::ncurses::font; + +Font::Font(const std::string &path) {} diff --git a/graphics/ncurses/src/font/Font.hpp b/graphics/ncurses/src/font/Font.hpp new file mode 100644 index 0000000..9ac74d6 --- /dev/null +++ b/graphics/ncurses/src/font/Font.hpp @@ -0,0 +1,22 @@ +/* +** EPITECH PROJECT, 2024 +** arcade +** File description: +** Font.hpp +*/ + +#pragma once + +#include +#include "shared/graphics/IFont.hpp" +#include "utils/compiler.hpp" + +namespace arcade::graphics::ncurses::font { + class Font; +} + +class arcade::graphics::ncurses::font::Font : public shared::graphics::IFont { +public: + explicit Font(const std::string &path); + ~Font() override = default; +}; diff --git a/graphics/ncurses/src/sound/Sound.cpp b/graphics/ncurses/src/sound/Sound.cpp new file mode 100644 index 0000000..7766418 --- /dev/null +++ b/graphics/ncurses/src/sound/Sound.cpp @@ -0,0 +1,32 @@ +/* +** EPITECH PROJECT, 2024 +** arcade +** File description: +** Sound.cpp +*/ + +#include "Sound.hpp" +#include "common/exceptions/SoundException.hpp" + +using namespace arcade::graphics::ncurses::sound; +using namespace arcade::graphics::common::exceptions; + +Sound::Sound(const std::string &path, SoundState state) {} + +Sound::SoundVolume Sound::getVolume() const { + return 100; +} + +void Sound::setVolume(SoundVolume volume) {} + +void Sound::setState(SoundState state) {} + +Sound::SoundState Sound::getState() const { + return SoundState::STOP; +} + +void Sound::setLoopState(bool loop) {} + +bool Sound::getLoopState() const { + return false; +} diff --git a/graphics/ncurses/src/sound/Sound.hpp b/graphics/ncurses/src/sound/Sound.hpp new file mode 100644 index 0000000..bd2228c --- /dev/null +++ b/graphics/ncurses/src/sound/Sound.hpp @@ -0,0 +1,31 @@ +/* +** EPITECH PROJECT, 2024 +** arcade +** File description: +** Sound.hpp +*/ + +#pragma once + +#include + +#include "shared/graphics/ISound.hpp" + +namespace arcade::graphics::ncurses::sound { + class Sound; +} + +class arcade::graphics::ncurses::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: +}; diff --git a/graphics/ncurses/src/texture/Texture.cpp b/graphics/ncurses/src/texture/Texture.cpp new file mode 100644 index 0000000..d291d6a --- /dev/null +++ b/graphics/ncurses/src/texture/Texture.cpp @@ -0,0 +1,45 @@ +/* +** EPITECH PROJECT, 2024 +** arcade +** File description: +** Texture.cpp +*/ + +#include +#include "Texture.hpp" +#include "common/exceptions/TextureException.hpp" + +using namespace arcade::graphics::ncurses::texture; +using namespace arcade::graphics::common::exceptions; + +Texture::Texture(const std::string &path) { + this->_loadFromFile(path); +} + +std::map> &Texture::getInnerTexture() +{ + return _texture; +} + +void Texture::_loadFromFile(const std::string &path) +{ + std::ifstream file(path); + std::string line; + int x = 0; + int y = 0; + + if (!file.is_open()) + throw TextureException( + "Failed to open file at: " + path, + "loadFromFile in NCURSES library" + ); + while (std::getline(file, line)) { + for (const auto &c : line) { + _texture[y][x] = c; + x++; + } + x = 0; + y++; + } + file.close(); +} diff --git a/graphics/ncurses/src/texture/Texture.hpp b/graphics/ncurses/src/texture/Texture.hpp new file mode 100644 index 0000000..78ea78c --- /dev/null +++ b/graphics/ncurses/src/texture/Texture.hpp @@ -0,0 +1,37 @@ +/* +** EPITECH PROJECT, 2024 +** arcade +** File description: +** Texture.hpp +*/ + +#pragma once + +#include +#include +#include "shared/graphics/ITexture.hpp" + +namespace arcade::graphics::ncurses::texture { + class Texture; +} + +class arcade::graphics::ncurses::texture::Texture: public shared::graphics::ITexture { +public: + explicit Texture(const std::string &path); + ~Texture() override = default; + + /** + * @brief Get the inner NCURSES texture + * @return Reference to the inner NCURSES texture + */ + std::map> &getInnerTexture(); + +private: + std::map> _texture; + + /** + * @brief Load a texture from a file + * @param path Path to the file + */ + void _loadFromFile(const std::string &path); +}; diff --git a/graphics/ncurses/src/window/EventsHandler.cpp b/graphics/ncurses/src/window/EventsHandler.cpp new file mode 100644 index 0000000..59db715 --- /dev/null +++ b/graphics/ncurses/src/window/EventsHandler.cpp @@ -0,0 +1,247 @@ +/* +** EPITECH PROJECT, 2024 +** arcade +** File description: +** EventHandler.cpp +*/ + +#include + +#include "Window.hpp" +#include "EventsHandler.hpp" +#include "utils/compiler.hpp" + +#include + +using namespace arcade::graphics::ncurses::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) {} + +#include +std::vector EventsHandler::handleEvents() { + int key = getch(); + + std::cout << key << std::endl; + return {}; + // std::vector events; + // sf::Event NCURSESEvent{}; + + // while (_window.getInnerWindow().pollEvent(NCURSESEvent)) { + // auto handler = _getHandler(NCURSESEvent.type); + // auto event = handler ? handler(NCURSESEvent, _window) : nullptr; + + // if (event) + // events.push_back(event); + // } + // return events; +} + +// bool EventsHandler::_handleControlKey( +// sf::Event::KeyEvent event, +// unused 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 +// ) { +// window.onResize(); +// return std::make_shared(); +// } + +// EventPtr EventsHandler::_handleMouseMoveEvent( +// sf::Event &event, +// Window &window +// ) { +// auto pos = window.mapPositionToTile({ +// event.mouseMove.x, +// event.mouseMove.y +// }); + +// return pos.x >= 0 && pos.y >= 0 +// ? std::make_shared(pos) +// : nullptr; +// } + +// EventPtr EventsHandler::_handleMouseButtonPressEvent( +// sf::Event &event, +// Window &window +// ) { +// auto pos = window.mapPositionToTile({ +// event.mouseButton.x, +// event.mouseButton.y +// }); + +// if (pos.x < 0 || pos.y < 0) +// return nullptr; +// 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); +// return nullptr; +// } + +// EventPtr EventsHandler::_handleMouseBtnReleaseEvent( +// sf::Event &event, +// unused Window &window +// ) { +// auto pos = window.mapPositionToTile({ +// event.mouseMove.x, +// event.mouseMove.y +// }); + +// if (pos.x < 0 || pos.y < 0) +// return nullptr; +// 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); +// return nullptr; +// } diff --git a/graphics/ncurses/src/window/EventsHandler.hpp b/graphics/ncurses/src/window/EventsHandler.hpp new file mode 100644 index 0000000..c3517e2 --- /dev/null +++ b/graphics/ncurses/src/window/EventsHandler.hpp @@ -0,0 +1,136 @@ +/* +** EPITECH PROJECT, 2024 +** arcade +** File description: +** EventHandler.hpp +*/ + +#pragma once + +#include + +#include "common/events/window/window.hpp" +#include "common/events/mouse/mouse.hpp" +#include "common/events/key/key.hpp" + +namespace arcade::graphics::ncurses::window { + class EventsHandler; + class Window; +} + +class arcade::graphics::ncurses::window::EventsHandler { +public: + explicit EventsHandler(Window &window); + ~EventsHandler() = default; + + // typedef EventPtr (*EventHandler)(sf::Event &event, Window &window); + + /** + * @brief Handle events from NCURSES + * @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 NCURSES + // * @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 NCURSES + // * @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 NCURSES + // * @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 NCURSES + // * @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 NCURSES + // * @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 NCURSES + // * @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 NCURSES + // * @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 NCURSES + // * @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 NCURSES + // * @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 NCURSES + // * @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 NCURSES + // * @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/ncurses/src/window/Renderer.cpp b/graphics/ncurses/src/window/Renderer.cpp new file mode 100644 index 0000000..fcd3d8c --- /dev/null +++ b/graphics/ncurses/src/window/Renderer.cpp @@ -0,0 +1,67 @@ +/* +** 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::ncurses::window; +using namespace arcade::graphics::common::exceptions; + +Renderer::Renderer(Window &window) : _window(window) +{ +} + +void Renderer::render(const shared::graphics::TextProps &props) +{ + int index = 0; + + for (const auto &letter : props.content) { + _window.map[props.position.y][props.position.x + index] = letter; + index += 1; + } +} + +void Renderer::_textVerticalAlign(const shared::graphics::TextVerticalAlign &align, const shared::types::Vector2u &entitySize) +{ +} + +void Renderer::_textAlign(const shared::graphics::TextAlign &align, const shared::types::Vector2i &entitySize) +{ +} + +#include +void Renderer::render(const shared::graphics::TextureProps &props) +{ + auto texture = _castOrThrow(props.texture); + auto map = texture->getInnerTexture(); + + int x = props.size.x; + int y = props.size.y; + + for (int j = 0; j < y ; j++) { + for (int i = 0; i < x; i++) { + auto securedChar = _getRightChar(props, Vector2i(i, j)); + _window.map[props.position.y + j][props.position.x + i] = securedChar; + } + } +} + +char Renderer::_getRightChar(const shared::graphics::TextureProps &props, const Vector2i &tilePosition) +{ + auto texture = _castOrThrow(props.texture); + auto map = texture->getInnerTexture(); + + auto newPos = Vector2i(props.origin.x + tilePosition.x, props.origin.y + tilePosition.y); + if (newPos.y < map.size() && newPos.x < map[newPos.y].size()) { + return map[newPos.y][newPos.x]; + } else { + return ' '; + } +} \ No newline at end of file diff --git a/graphics/ncurses/src/window/Renderer.hpp b/graphics/ncurses/src/window/Renderer.hpp new file mode 100644 index 0000000..d21575a --- /dev/null +++ b/graphics/ncurses/src/window/Renderer.hpp @@ -0,0 +1,89 @@ +/* +** 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" +#include "texture/Texture.hpp" + +namespace arcade::graphics::ncurses::window { + class Renderer; + + class Window; +} + +class arcade::graphics::ncurses::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; + + /** + * @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::Vector2u &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 Get the right character in the texture + * It manage origin of the texture, of course its size + * @param props Texture properties + * @param tilePosition Position of the tile + * @return Right character + */ + char _getRightChar(const shared::graphics::TextureProps &props, const Vector2i &tilePosition); + + /** + * @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(), + "NCURSES Library Renderer::_castOrThrow" + ); + } + return to; + }; +}; diff --git a/graphics/ncurses/src/window/Window.cpp b/graphics/ncurses/src/window/Window.cpp new file mode 100644 index 0000000..a3deaa4 --- /dev/null +++ b/graphics/ncurses/src/window/Window.cpp @@ -0,0 +1,107 @@ +/* +** 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::ncurses::window; +using namespace arcade::graphics::common::exceptions; + +const Vector2u Window::tileSize = { 35, 35 }; + +Window::Window(const IWindow::WindowInitProps &props): + _size(props.size), + _initialSize(0, 0), + _renderer(*this), + _eventsHandler(*this), + _window(nullptr, &delwin) +{ + _mode = props.mode; + _fps = props.fps; + _initialSize = _size; + _isOpen = true; + _window = std::unique_ptr(initscr(), &delwin); +} + +Window::~Window() +{ + if (_isOpen) + close(); +} + +std::unique_ptr &Window::getWindow() +{ + return _window; +} + +void Window::setTitle(const std::string &title) { + _title = title; +} + +void Window::setSize(shared::types::Vector2u size) { + _size = size; +} + +shared::types::Vector2u Window::getSize() const { + return _size; +} + +void Window::setFramerateLimit(unsigned int fps) { + _fps = fps; +} + +unsigned int Window::getFramerateLimit() const { + return _fps; +} + +void Window::setMode(IWindow::WindowMode mode) {} + +Window::WindowMode Window::getMode() const { + return _mode; +} + +bool Window::isOpen() const { + return _isOpen; +} + +void Window::setIcon(const std::string &path) {} + +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() { + wclear(stdscr); +} + +void Window::display() { + for (auto &line : map) { + for (auto &c : line.second) { + mvwprintw(stdscr, line.first, c.first, &c.second); + } + } + refresh(); +} + +void Window::close() { + if (_isOpen) { + _isOpen = false; + endwin(); + } +} + +std::vector Window::getEvents() { + return _eventsHandler.handleEvents(); +} + +void Window::onResize() {} diff --git a/graphics/ncurses/src/window/Window.hpp b/graphics/ncurses/src/window/Window.hpp new file mode 100644 index 0000000..f5b9635 --- /dev/null +++ b/graphics/ncurses/src/window/Window.hpp @@ -0,0 +1,160 @@ +/* +** EPITECH PROJECT, 2024 +** Window.hpp +** File description: +** Window class +*/ + +#pragma once + +#include +#include +#include "Renderer.hpp" +#include "shared/graphics/IWindow.hpp" +#include "EventsHandler.hpp" + +namespace arcade::graphics::ncurses::window { + class Window; +} + +class arcade::graphics::ncurses::window::Window: public shared::graphics::IWindow { +public: + explicit Window(const WindowInitProps &props); + ~Window() override; + + /** + * @brief Get window object + * + */ + std::unique_ptr &getWindow(); + + /** + * @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 size of a tile + * @return Size of a tile + */ + static const Vector2u tileSize; + + /** + * @brief Resize the view of the window + */ + void onResize(); + + std::map> map; + +private: + std::unique_ptr _window; + EventsHandler _eventsHandler; + Renderer _renderer; + std::string _title; + unsigned int _fps; + WindowMode _mode; + Vector2u _size; + Vector2u _initialSize; + bool _isOpen; +}; From c5f53afa521c10bb6a6a259c7024b0577ce4911d Mon Sep 17 00:00:00 2001 From: Yann Date: Sun, 7 Apr 2024 20:20:25 +0200 Subject: [PATCH 2/7] feat(ncurses): add events --- assets/nibbler/tail.ascii | 4 +- assets/snake/tail.ascii | 4 +- core/src/Core.cpp | 3 + core/src/menu/Menu.cpp | 11 +- graphics/ncurses/src/window/EventsHandler.cpp | 279 ++++-------------- graphics/ncurses/src/window/EventsHandler.hpp | 117 ++------ graphics/ncurses/src/window/Renderer.cpp | 2 +- graphics/ncurses/src/window/Window.cpp | 27 +- main.cpp | 44 +++ output | Bin 0 -> 17096 bytes test.txt | 30 ++ 11 files changed, 190 insertions(+), 331 deletions(-) create mode 100644 main.cpp create mode 100755 output create mode 100644 test.txt diff --git a/assets/nibbler/tail.ascii b/assets/nibbler/tail.ascii index 2afd973..301fb5f 100644 --- a/assets/nibbler/tail.ascii +++ b/assets/nibbler/tail.ascii @@ -1,3 +1,3 @@ -║═ +|- ~~~~ -╝╚╗╔ \ No newline at end of file +~~~~ \ No newline at end of file diff --git a/assets/snake/tail.ascii b/assets/snake/tail.ascii index 2afd973..301fb5f 100644 --- a/assets/snake/tail.ascii +++ b/assets/snake/tail.ascii @@ -1,3 +1,3 @@ -║═ +|- ~~~~ -╝╚╗╔ \ No newline at end of file +~~~~ \ No newline at end of file diff --git a/core/src/Core.cpp b/core/src/Core.cpp index c12b444..8cf6683 100644 --- a/core/src/Core.cpp +++ b/core/src/Core.cpp @@ -108,6 +108,9 @@ void Core::_initWindow() this->_graphicsProvider = this->_getGraphicsProvider(0); std::cerr << "No graphic provider selected, using default provider" << std::endl; } + this->_textures.clear(); + this->_fonts.clear(); + this->_sounds.clear(); this->_window = this->_graphicsProvider->createWindow(windowInitProps); this->_sceneStage = PLAY; } diff --git a/core/src/menu/Menu.cpp b/core/src/menu/Menu.cpp index 3bc9252..1ae3583 100644 --- a/core/src/menu/Menu.cpp +++ b/core/src/menu/Menu.cpp @@ -266,6 +266,9 @@ void Menu::_initTexts() void Menu::_clearLists() { + this->_nameField.reset(); + this->_font.reset(); + this->_music.reset(); this->_hiddenAuthors.clear(); this->_hiddenTexts.clear(); this->_texts.clear(); @@ -303,8 +306,8 @@ void Menu::_initWindow() }; try { - this->_window = this->_graphicsProvider->createWindow(windowInitProps); this->_clearLists(); + this->_window = this->_graphicsProvider->createWindow(windowInitProps); this->_preventGraphicsProvider(); this->_initTexts(); this->_initTextures(); @@ -410,7 +413,7 @@ void Menu::_selectGame() if (this->_checkBoxType == GAME_CHECKBOX) { for (auto checkBox : this->_gamesCheckBoxes) { if (checkBox->isHovered() && checkBox->isChecked()) - this->_exitWithNewGame(); + return this->_exitWithNewGame(); if (checkBox->isHovered()) checkBox->check(); else @@ -419,7 +422,7 @@ void Menu::_selectGame() } else { for (auto checkBox : this->_graphicsCheckBoxes) { if (checkBox->isHovered() && checkBox->isChecked()) - this->_changeGraphics(checkBox); + return this->_changeGraphics(checkBox); if (checkBox->isHovered()) checkBox->check(); else @@ -436,6 +439,8 @@ void Menu::_changeGraphics(std::shared_ptr checkBox) this->_graphicsProvider = graphicsProvider; this->_window->close(); this->_initWindow(); + this->_previousSelectedGame(); + this->_previousSelectedGraphics(); } } diff --git a/graphics/ncurses/src/window/EventsHandler.cpp b/graphics/ncurses/src/window/EventsHandler.cpp index 59db715..a5f95c2 100644 --- a/graphics/ncurses/src/window/EventsHandler.cpp +++ b/graphics/ncurses/src/window/EventsHandler.cpp @@ -15,233 +15,68 @@ using namespace arcade::graphics::ncurses::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) {} -#include -std::vector EventsHandler::handleEvents() { - int key = getch(); - - std::cout << key << std::endl; - return {}; - // std::vector events; - // sf::Event NCURSESEvent{}; - - // while (_window.getInnerWindow().pollEvent(NCURSESEvent)) { - // auto handler = _getHandler(NCURSESEvent.type); - // auto event = handler ? handler(NCURSESEvent, _window) : nullptr; - - // if (event) - // events.push_back(event); - // } - // return events; +std::vector EventsHandler::handleEvents() +{ + std::vector events; + + while (true) { + int event = getch(); + + if (event == ERR) { + break; + } else { + auto eventPtr = _handleKeyPressEvent(event); + if (eventPtr) + events.push_back(eventPtr); + } + } + return events; } -// bool EventsHandler::_handleControlKey( -// sf::Event::KeyEvent event, -// unused 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 -// ) { -// window.onResize(); -// return std::make_shared(); -// } - -// EventPtr EventsHandler::_handleMouseMoveEvent( -// sf::Event &event, -// Window &window -// ) { -// auto pos = window.mapPositionToTile({ -// event.mouseMove.x, -// event.mouseMove.y -// }); - -// return pos.x >= 0 && pos.y >= 0 -// ? std::make_shared(pos) -// : nullptr; -// } +EventPtr EventsHandler::_handleKeyPressEvent(int code) +{ + if (code >= 265 && code <= 276) + return _handleFunctionKey(code); + if (code >= 258 && code <= 261) + return _handleArrowKey(code); + if (code == 263) + return std::make_shared(IKeyEvent::KeyType::CHAR, IKeyEvent::KeyCode{.character = '\b'}); + return _handleCharKey(code); +} -// EventPtr EventsHandler::_handleMouseButtonPressEvent( -// sf::Event &event, -// Window &window -// ) { -// auto pos = window.mapPositionToTile({ -// event.mouseButton.x, -// event.mouseButton.y -// }); +EventPtr EventsHandler::_handleFunctionKey(int code) +{ + unsigned char funcCode = code - 265 + 1; -// if (pos.x < 0 || pos.y < 0) -// return nullptr; -// 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); -// return nullptr; -// } + return std::make_shared(IKeyEvent::KeyType::FUNC, IKeyEvent::KeyCode{.func = funcCode}); +} -// EventPtr EventsHandler::_handleMouseBtnReleaseEvent( -// sf::Event &event, -// unused Window &window -// ) { -// auto pos = window.mapPositionToTile({ -// event.mouseMove.x, -// event.mouseMove.y -// }); +EventPtr EventsHandler::_handleArrowKey(int code) +{ + IKeyEvent::ArrowCode arrowCode; + + switch (code) { + case 259: + arrowCode = IKeyEvent::ArrowCode::UP; + break; + case 258: + arrowCode = IKeyEvent::ArrowCode::DOWN; + break; + case 260: + arrowCode = IKeyEvent::ArrowCode::LEFT; + break; + case 261: + arrowCode = IKeyEvent::ArrowCode::RIGHT; + break; + default: + return nullptr; + } + return std::make_shared(IKeyEvent::KeyType::ARROW, IKeyEvent::KeyCode{.arrow = arrowCode}); +} -// if (pos.x < 0 || pos.y < 0) -// return nullptr; -// 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); -// return nullptr; -// } +EventPtr EventsHandler::_handleCharKey(int code) +{ + return std::make_shared(IKeyEvent::KeyType::CHAR, IKeyEvent::KeyCode{.character = static_cast(code)}); +} diff --git a/graphics/ncurses/src/window/EventsHandler.hpp b/graphics/ncurses/src/window/EventsHandler.hpp index c3517e2..1ab4970 100644 --- a/graphics/ncurses/src/window/EventsHandler.hpp +++ b/graphics/ncurses/src/window/EventsHandler.hpp @@ -23,7 +23,7 @@ class arcade::graphics::ncurses::window::EventsHandler { explicit EventsHandler(Window &window); ~EventsHandler() = default; - // typedef EventPtr (*EventHandler)(sf::Event &event, Window &window); + typedef EventPtr (*EventHandler)(int code, Window &window); /** * @brief Handle events from NCURSES @@ -36,101 +36,34 @@ class arcade::graphics::ncurses::window::EventsHandler { // static EventHandler _getHandler(sf::Event::EventType type); - // /** - // * @brief Handle control key event if it's a control key - // * @param event Event from NCURSES - // * @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 NCURSES - // * @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 NCURSES - // * @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 NCURSES - // * @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 NCURSES - // * @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 NCURSES - // * @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 NCURSES - // * @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 NCURSES - // * @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 NCURSES - // * @param window Window object - // * @return Pointer to created event or null if not handled - // */ - // static EventPtr _handleMouseMoveEvent(sf::Event &event, Window &window); + /** + * @brief Handle key press event + * @param code Code of the key + * @return EventPtr, depending on the key + */ + EventPtr _handleKeyPressEvent(int code); - // /** - // * @brief Handle window close event - // * @param event Event from NCURSES - // * @param window Window object - // * @return Pointer to created event or null if not handled - // */ - // static EventPtr _handleWindowCloseEvent(sf::Event &event, Window &window); + /** + * @brief Handle Function key event, F1 to F12 + * @param code Code of the key + * @return EventPtr, F1 to F12 + */ + EventPtr _handleFunctionKey(int code); - // /** - // * @brief Handle window resize event - // * @param event Event from NCURSES - // * @param window Window object - // * @return Pointer to created event or null if not handled - // */ - // static EventPtr _handleWindowResizeEvent(sf::Event &event, Window &window); + /** + * @brief Handle arrow key event, UP, DOWN, LEFT, RIGHT + * @param code Code of the key + * @return EventPtr, UP, DOWN, LEFT, RIGHT + */ + EventPtr _handleArrowKey(int code); - // /** - // * @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); + /** + * @brief Handle char key event + * @param code Code of the key + * @return EventPtr, depending on the key + */ + EventPtr _handleCharKey(int code); window::Window &_window; }; diff --git a/graphics/ncurses/src/window/Renderer.cpp b/graphics/ncurses/src/window/Renderer.cpp index fcd3d8c..b0eb6bb 100644 --- a/graphics/ncurses/src/window/Renderer.cpp +++ b/graphics/ncurses/src/window/Renderer.cpp @@ -48,7 +48,7 @@ void Renderer::render(const shared::graphics::TextureProps &props) for (int j = 0; j < y ; j++) { for (int i = 0; i < x; i++) { auto securedChar = _getRightChar(props, Vector2i(i, j)); - _window.map[props.position.y + j][props.position.x + i] = securedChar; + _window.map[props.position.y + j][props.position.x + i] = securedChar; } } } diff --git a/graphics/ncurses/src/window/Window.cpp b/graphics/ncurses/src/window/Window.cpp index a3deaa4..9a4bd02 100644 --- a/graphics/ncurses/src/window/Window.cpp +++ b/graphics/ncurses/src/window/Window.cpp @@ -26,13 +26,20 @@ Window::Window(const IWindow::WindowInitProps &props): _fps = props.fps; _initialSize = _size; _isOpen = true; - _window = std::unique_ptr(initscr(), &delwin); + initscr(); + cbreak(); + noecho(); + keypad(stdscr, TRUE); + nodelay(stdscr, TRUE); + _window = std::unique_ptr(newwin(_size.y, _size.x, 0, 0), &delwin); + box(_window.get(), 0, 0); } Window::~Window() { - if (_isOpen) - close(); + wclear(stdscr); + close(); + endwin(); } std::unique_ptr &Window::getWindow() @@ -81,23 +88,25 @@ void Window::render(const shared::graphics::TextProps &props) { } void Window::clear() { - wclear(stdscr); + wclear(_window.get()); } void Window::display() { for (auto &line : map) { for (auto &c : line.second) { - mvwprintw(stdscr, line.first, c.first, &c.second); + mvwprintw(_window.get(), line.first, c.first, &c.second); } } - refresh(); + wrefresh(_window.get()); } void Window::close() { - if (_isOpen) { - _isOpen = false; - endwin(); + if (_window) { + wclear(_window.get()); + wrefresh(_window.get()); } + _isOpen = false; + _window.reset(); } std::vector Window::getEvents() { diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..cf1d991 --- /dev/null +++ b/main.cpp @@ -0,0 +1,44 @@ +#include + +int main() { + // Initialisation de ncurses + initscr(); + cbreak(); + noecho(); + keypad(stdscr, TRUE); + + // Création d'une première fenêtre + WINDOW *win1 = newwin(10, 30, 5, 5); // Créer une fenêtre 10x30 à la position (5,5) + box(win1, 0, 0); // Dessiner une bordure autour de la fenêtre + mvwprintw(win1, 1, 1, "Fenetre 1"); // Afficher un message dans la fenêtre + wrefresh(win1); // Rafraîchir la fenêtre + getch(); // Attendre une touche + + // Libérer la première fenêtre + delwin(win1); + + // Création d'une deuxième fenêtre + WINDOW *win2 = newwin(5, 20, 8, 8); // Créer une fenêtre 5x20 à la position (8,8) + box(win2, 0, 0); + mvwprintw(win2, 1, 1, "Fenetre 2"); + wrefresh(win2); + getch(); + + // Libérer la deuxième fenêtre + delwin(win2); + + // Création d'une troisième fenêtre + WINDOW *win3 = newwin(15, 40, 3, 3); // Créer une fenêtre 15x40 à la position (3,3) + box(win3, 0, 0); + mvwprintw(win3, 1, 1, "Fenetre 3"); + wrefresh(win3); + getch(); + + // Libérer la troisième fenêtre + delwin(win3); + + // Libération de ncurses + endwin(); + + return 0; +} diff --git a/output b/output new file mode 100755 index 0000000000000000000000000000000000000000..0ac527c15dab7925186b2ae61bf1f87329c2df80 GIT binary patch literal 17096 zcmeHOeQX@X6`wof#FWGzgn%J@tXhYLg3o6=7}p_ij(zsIa=;`ZfJ(bQ->vOa&Ue?l zHMS`#X`!?R+6Mlh6j2pg6;P$NRzWBUYA~bEqmDed)=@>O zdPfJZ8d262w@>5@*F&V(mC7?freH+05c#&FDUog-eDhSZWAN1Wh>nPShW&D!rSPDF zcaV7pnJ3ay5s_Couo5Zd-9S9}<-ZNm&AYg~O8sy%`%@(P8=)ng8tK^Dl1?_KQ<=%> z=IPFk=8mnQLN?T<(^0Q5T^LjS*WIXs`_()!;RjS;l^$fBOmu+lIdsA8;Kw`nMfYy| zc_O7QY`AFccls}VVBJNqK|7EqY!G12Rn|J)D zljM0)ra3l|&6ou{p0`a?73^dokylA8J(bF+Ox8+_XVui0Whchf#BEc#d@5s4DJzpi z@>Jd$&0B?Wm9eIvr!pxU?2+uW+Gow=;z^Yl$y@P#R0@sH1eY=qCtK1piOGDyDqxUy zK(|ww(QHYhnj|j2yrfQ)Vq*!)2wE#h2?y^V9N5ugwuRcaqIoo$>5s;6nLpipjUSlE-=Ax;ru-5lr1itKQS5)yYSK&pp;G*ekSJ)5pm%kbKx-;ewGU#a^dS- zxF7XB;CsOLfbRj{1HK1*4}4e;{H^Zdf5z^5yC!yD^@$dxVqcxNgUheP?)pW|QJv-T zmA@o-dGoL7UUx}^V$jEtwz#lNVe^a7F%?^UMeB#52cgev{b$fI^;(?M`j4Pv3b^=~ z*1r!OQ?SJYT7LvOre2Htwf-Pb=oW-6eMuMJd=HT~QAl#6&c< z9d~=fL0G^=XFd;Ld13Ux(a{xS_~(eW|MELp%r3=Vc<0*K3n!~$fn%`~AJ`409M*CU zUOvj-zx_82Xz zLA)dAo!IP4#qSYz2(CVi+Yzkso`NBZGs3-o78c?Pbk5bYhblPFuj$q~cJnB#!1ZOt7M21VNOMcOz zFCDs|e8~@TI2&R>myhbPrJuFZ(?#|0gYN;~1HK1*5BMJN zJ>Yx5_kiyK-vhn}J|Yj`R~>igvoe;Qw~SULv9?mIoeTq;smMqX*U-Y4!4u}tl*t-mMO zvwlt0V*x6X06+L1@IByr!1sXf0pA0@2Ye6s9`HTjd*J`W1M~D_CBgxgSmGeeIHI%{ zZq}oJ+oM0>(dRt6{^5_X(q6Orh_;ZudFc&~e!fO&e>3k--o(1Bv@T$Mj?-lms-*w@ zgXJtt=BpywQr3Gz)s8NE?~0r*d*xo$)=J49xklDEvJ`=#9tTNBYz@Nw3q-Z7o3luHR7`noz#liWAh z6+TUJe|J}_8XD-@s&+@a!YZ|!ZmVjC{k^D)t_3T)NRI3LIlhWWyNm5qqB(D+vk9jy zVZ)2*Og*5^+=J;tJeX1#@A!WVUM&6HO@a1!Yw1kL8h!_rv)RaLBFot*9wX`zjpUNx#)*$;yMfE;2FezONh2R7hI;d-9Igj%vcoBShVQ~ytr z(l!v@5Uf`74mn#kL&p)4Krpl_CG$Hx=_Bi2|d zLtxU%Q>w4+* zi)qr=-;Bmg2aNUZQfBWh*LCk4=uu|>;PpGY2hHpI`gTY6n0vZ+3`U7zCF6EnnFH6; z;g)17V@?*Vq|zr`sDXv7IUdg>)0P~e;R7`*CuwwZs9ewSn275T8I-jrIR?i&6MAsoju$pK8QoLp^7>uaH!Uqq#X6(vpjs_$23O@1-9a| zJAAmub5KZy3NsUSe1xQ(cjUOl=!}q+[}x{PHeL%Do5XXWh~7c?@NqQh#bBtzXh z2AVNyLNFhX)0v`BawbDXIMU8LDYseqLMoeCrI?gP{)vOYv0U0#A^1jxY-^hC7&MfY z)twcx#(9{GCy6VX!*Irn!;m;-9G^%fsMIXwMYoVHz{!mKr9w1pCulUP5YO~<(+Njw zbW1~V+s>y(CT$w||BHb23q6XZU&9)!B05_+pDODY4bly^?(hjxux1D{*vWi3j~QWH z1itg`fOBkazMQ|5bD2$UV~WdnM&JPtU*->w@Pfs(vOXsh9lZVjD4}k?!QW+r`ST8~bY~bd zA03{gyPLnj`~^0+PaMPc!edqa*u$6kOL~K2A^(36dvE=pW`3y{BjT7Ej=+X$cM$&x z_8dh}f8on{V>lf0lF0UVG6+ z{)xDCF22my=b8zmAa;(nq6_{OC1C7G`7&RYbLa*;2IC(=c+!vW5r*~)U(S2J)&gr@ zOFB_~7rw}U5bEa3|80uQ&$+mW3QuH^$Zo#O2X78LL~nn=)*bMCAup*v_U|Ly%6w_3 z2I*!H!#T!N3>;Qn-;29 z3?229?+22(i`l{v!|jgjWC!9sig~j5UEbgLf0+2rVL11PuX5zOp7K2^&B@F2XFu)m Kw|NL2Rs9FcmZ*mS literal 0 HcmV?d00001 diff --git a/test.txt b/test.txt new file mode 100644 index 0000000..b15d26a --- /dev/null +++ b/test.txt @@ -0,0 +1,30 @@ +Creating Window +Deleting Window +Creating Window +Creating Window +Deleting Window +Creating Window +Deleting Window +Creating Window +Deleting Window +Deleting Window +Deleting Window +Deleting Window +Creating Window +Deleting Window +Creating Window +Deleting Window +Creating Window +Deleting Window +Deleting Window +Deleting Window +Deleting Window +Creating Window +Deleting Window +Creating Window +Deleting Window +Creating Window +Deleting Window +Deleting Window +Creating Window +Deleting Window From 5d9904296c160868e06171abef6133cea39002c4 Mon Sep 17 00:00:00 2001 From: Yann Date: Sun, 7 Apr 2024 20:24:11 +0200 Subject: [PATCH 3/7] feat(ncurses): add closing event --- graphics/ncurses/src/window/EventsHandler.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/graphics/ncurses/src/window/EventsHandler.cpp b/graphics/ncurses/src/window/EventsHandler.cpp index a5f95c2..f2e5d42 100644 --- a/graphics/ncurses/src/window/EventsHandler.cpp +++ b/graphics/ncurses/src/window/EventsHandler.cpp @@ -43,6 +43,8 @@ EventPtr EventsHandler::_handleKeyPressEvent(int code) return _handleArrowKey(code); if (code == 263) return std::make_shared(IKeyEvent::KeyType::CHAR, IKeyEvent::KeyCode{.character = '\b'}); + if (code & KEY_EXIT == code) + return std::make_shared(); return _handleCharKey(code); } From 073116ff23b819233c03d9ae1cba4b60b4de545c Mon Sep 17 00:00:00 2001 From: Yann Date: Sun, 7 Apr 2024 20:38:41 +0200 Subject: [PATCH 4/7] fix(ncurses): fix close window --- graphics/ncurses/src/window/EventsHandler.cpp | 2 +- main.cpp | 44 ------------------ output | Bin 17096 -> 0 bytes test.txt | 30 ------------ 4 files changed, 1 insertion(+), 75 deletions(-) delete mode 100644 main.cpp delete mode 100755 output delete mode 100644 test.txt diff --git a/graphics/ncurses/src/window/EventsHandler.cpp b/graphics/ncurses/src/window/EventsHandler.cpp index f2e5d42..0aa38ca 100644 --- a/graphics/ncurses/src/window/EventsHandler.cpp +++ b/graphics/ncurses/src/window/EventsHandler.cpp @@ -43,7 +43,7 @@ EventPtr EventsHandler::_handleKeyPressEvent(int code) return _handleArrowKey(code); if (code == 263) return std::make_shared(IKeyEvent::KeyType::CHAR, IKeyEvent::KeyCode{.character = '\b'}); - if (code & KEY_EXIT == code) + if (code == 330) return std::make_shared(); return _handleCharKey(code); } diff --git a/main.cpp b/main.cpp deleted file mode 100644 index cf1d991..0000000 --- a/main.cpp +++ /dev/null @@ -1,44 +0,0 @@ -#include - -int main() { - // Initialisation de ncurses - initscr(); - cbreak(); - noecho(); - keypad(stdscr, TRUE); - - // Création d'une première fenêtre - WINDOW *win1 = newwin(10, 30, 5, 5); // Créer une fenêtre 10x30 à la position (5,5) - box(win1, 0, 0); // Dessiner une bordure autour de la fenêtre - mvwprintw(win1, 1, 1, "Fenetre 1"); // Afficher un message dans la fenêtre - wrefresh(win1); // Rafraîchir la fenêtre - getch(); // Attendre une touche - - // Libérer la première fenêtre - delwin(win1); - - // Création d'une deuxième fenêtre - WINDOW *win2 = newwin(5, 20, 8, 8); // Créer une fenêtre 5x20 à la position (8,8) - box(win2, 0, 0); - mvwprintw(win2, 1, 1, "Fenetre 2"); - wrefresh(win2); - getch(); - - // Libérer la deuxième fenêtre - delwin(win2); - - // Création d'une troisième fenêtre - WINDOW *win3 = newwin(15, 40, 3, 3); // Créer une fenêtre 15x40 à la position (3,3) - box(win3, 0, 0); - mvwprintw(win3, 1, 1, "Fenetre 3"); - wrefresh(win3); - getch(); - - // Libérer la troisième fenêtre - delwin(win3); - - // Libération de ncurses - endwin(); - - return 0; -} diff --git a/output b/output deleted file mode 100755 index 0ac527c15dab7925186b2ae61bf1f87329c2df80..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17096 zcmeHOeQX@X6`wof#FWGzgn%J@tXhYLg3o6=7}p_ij(zsIa=;`ZfJ(bQ->vOa&Ue?l zHMS`#X`!?R+6Mlh6j2pg6;P$NRzWBUYA~bEqmDed)=@>O zdPfJZ8d262w@>5@*F&V(mC7?freH+05c#&FDUog-eDhSZWAN1Wh>nPShW&D!rSPDF zcaV7pnJ3ay5s_Couo5Zd-9S9}<-ZNm&AYg~O8sy%`%@(P8=)ng8tK^Dl1?_KQ<=%> z=IPFk=8mnQLN?T<(^0Q5T^LjS*WIXs`_()!;RjS;l^$fBOmu+lIdsA8;Kw`nMfYy| zc_O7QY`AFccls}VVBJNqK|7EqY!G12Rn|J)D zljM0)ra3l|&6ou{p0`a?73^dokylA8J(bF+Ox8+_XVui0Whchf#BEc#d@5s4DJzpi z@>Jd$&0B?Wm9eIvr!pxU?2+uW+Gow=;z^Yl$y@P#R0@sH1eY=qCtK1piOGDyDqxUy zK(|ww(QHYhnj|j2yrfQ)Vq*!)2wE#h2?y^V9N5ugwuRcaqIoo$>5s;6nLpipjUSlE-=Ax;ru-5lr1itKQS5)yYSK&pp;G*ekSJ)5pm%kbKx-;ewGU#a^dS- zxF7XB;CsOLfbRj{1HK1*4}4e;{H^Zdf5z^5yC!yD^@$dxVqcxNgUheP?)pW|QJv-T zmA@o-dGoL7UUx}^V$jEtwz#lNVe^a7F%?^UMeB#52cgev{b$fI^;(?M`j4Pv3b^=~ z*1r!OQ?SJYT7LvOre2Htwf-Pb=oW-6eMuMJd=HT~QAl#6&c< z9d~=fL0G^=XFd;Ld13Ux(a{xS_~(eW|MELp%r3=Vc<0*K3n!~$fn%`~AJ`409M*CU zUOvj-zx_82Xz zLA)dAo!IP4#qSYz2(CVi+Yzkso`NBZGs3-o78c?Pbk5bYhblPFuj$q~cJnB#!1ZOt7M21VNOMcOz zFCDs|e8~@TI2&R>myhbPrJuFZ(?#|0gYN;~1HK1*5BMJN zJ>Yx5_kiyK-vhn}J|Yj`R~>igvoe;Qw~SULv9?mIoeTq;smMqX*U-Y4!4u}tl*t-mMO zvwlt0V*x6X06+L1@IByr!1sXf0pA0@2Ye6s9`HTjd*J`W1M~D_CBgxgSmGeeIHI%{ zZq}oJ+oM0>(dRt6{^5_X(q6Orh_;ZudFc&~e!fO&e>3k--o(1Bv@T$Mj?-lms-*w@ zgXJtt=BpywQr3Gz)s8NE?~0r*d*xo$)=J49xklDEvJ`=#9tTNBYz@Nw3q-Z7o3luHR7`noz#liWAh z6+TUJe|J}_8XD-@s&+@a!YZ|!ZmVjC{k^D)t_3T)NRI3LIlhWWyNm5qqB(D+vk9jy zVZ)2*Og*5^+=J;tJeX1#@A!WVUM&6HO@a1!Yw1kL8h!_rv)RaLBFot*9wX`zjpUNx#)*$;yMfE;2FezONh2R7hI;d-9Igj%vcoBShVQ~ytr z(l!v@5Uf`74mn#kL&p)4Krpl_CG$Hx=_Bi2|d zLtxU%Q>w4+* zi)qr=-;Bmg2aNUZQfBWh*LCk4=uu|>;PpGY2hHpI`gTY6n0vZ+3`U7zCF6EnnFH6; z;g)17V@?*Vq|zr`sDXv7IUdg>)0P~e;R7`*CuwwZs9ewSn275T8I-jrIR?i&6MAsoju$pK8QoLp^7>uaH!Uqq#X6(vpjs_$23O@1-9a| zJAAmub5KZy3NsUSe1xQ(cjUOl=!}q+[}x{PHeL%Do5XXWh~7c?@NqQh#bBtzXh z2AVNyLNFhX)0v`BawbDXIMU8LDYseqLMoeCrI?gP{)vOYv0U0#A^1jxY-^hC7&MfY z)twcx#(9{GCy6VX!*Irn!;m;-9G^%fsMIXwMYoVHz{!mKr9w1pCulUP5YO~<(+Njw zbW1~V+s>y(CT$w||BHb23q6XZU&9)!B05_+pDODY4bly^?(hjxux1D{*vWi3j~QWH z1itg`fOBkazMQ|5bD2$UV~WdnM&JPtU*->w@Pfs(vOXsh9lZVjD4}k?!QW+r`ST8~bY~bd zA03{gyPLnj`~^0+PaMPc!edqa*u$6kOL~K2A^(36dvE=pW`3y{BjT7Ej=+X$cM$&x z_8dh}f8on{V>lf0lF0UVG6+ z{)xDCF22my=b8zmAa;(nq6_{OC1C7G`7&RYbLa*;2IC(=c+!vW5r*~)U(S2J)&gr@ zOFB_~7rw}U5bEa3|80uQ&$+mW3QuH^$Zo#O2X78LL~nn=)*bMCAup*v_U|Ly%6w_3 z2I*!H!#T!N3>;Qn-;29 z3?229?+22(i`l{v!|jgjWC!9sig~j5UEbgLf0+2rVL11PuX5zOp7K2^&B@F2XFu)m Kw|NL2Rs9FcmZ*mS diff --git a/test.txt b/test.txt deleted file mode 100644 index b15d26a..0000000 --- a/test.txt +++ /dev/null @@ -1,30 +0,0 @@ -Creating Window -Deleting Window -Creating Window -Creating Window -Deleting Window -Creating Window -Deleting Window -Creating Window -Deleting Window -Deleting Window -Deleting Window -Deleting Window -Creating Window -Deleting Window -Creating Window -Deleting Window -Creating Window -Deleting Window -Deleting Window -Deleting Window -Deleting Window -Creating Window -Deleting Window -Creating Window -Deleting Window -Creating Window -Deleting Window -Deleting Window -Creating Window -Deleting Window From c8f16cd74c6f88d1beef6646eb8e5e0e3c337469 Mon Sep 17 00:00:00 2001 From: Yann Date: Sun, 7 Apr 2024 21:34:12 +0200 Subject: [PATCH 5/7] feat(ncurses): add centered texts --- core/src/menu/Menu.cpp | 5 ++++ graphics/ncurses/src/window/Renderer.cpp | 30 ++++++++++++++++++++---- graphics/ncurses/src/window/Renderer.hpp | 14 ++++------- graphics/ncurses/src/window/Window.cpp | 1 + 4 files changed, 35 insertions(+), 15 deletions(-) diff --git a/core/src/menu/Menu.cpp b/core/src/menu/Menu.cpp index 1ae3583..d1f7f1e 100644 --- a/core/src/menu/Menu.cpp +++ b/core/src/menu/Menu.cpp @@ -516,6 +516,11 @@ void Menu::_handleMouseButtonEvents(std::shared_ptr m this->_selectGame(); } } + for (auto checkBox : this->_graphicsCheckBoxes) { + if (checkBox->isHovered(position)) { + this->_selectGame(); + } + } } void Menu::_handleEvents() diff --git a/graphics/ncurses/src/window/Renderer.cpp b/graphics/ncurses/src/window/Renderer.cpp index b0eb6bb..20e79a4 100644 --- a/graphics/ncurses/src/window/Renderer.cpp +++ b/graphics/ncurses/src/window/Renderer.cpp @@ -22,21 +22,41 @@ void Renderer::render(const shared::graphics::TextProps &props) { int index = 0; + int x = _textAlign(props); + int y = _textVerticalAlign(props); + Vector2i position = {x, y}; for (const auto &letter : props.content) { - _window.map[props.position.y][props.position.x + index] = letter; + _window.map[position.y][position.x + index] = letter; index += 1; } } -void Renderer::_textVerticalAlign(const shared::graphics::TextVerticalAlign &align, const shared::types::Vector2u &entitySize) +int Renderer::_textVerticalAlign(const shared::graphics::TextProps &props) { + switch (props.verticalAlign) { + case shared::graphics::TextVerticalAlign::TOP: + return props.position.y; + case shared::graphics::TextVerticalAlign::MIDDLE: + return props.position.y + (props.size.y / 2); + case shared::graphics::TextVerticalAlign::BOTTOM: + return props.position.y + props.size.y; + } + return props.position.y; } -void Renderer::_textAlign(const shared::graphics::TextAlign &align, const shared::types::Vector2i &entitySize) +int Renderer::_textAlign(const shared::graphics::TextProps &props) { + switch (props.align) { + case shared::graphics::TextAlign::LEFT: + return props.position.x; + case shared::graphics::TextAlign::CENTER: + return props.position.x + (props.size.x / 2) - (props.content.size() / 2); + case shared::graphics::TextAlign::RIGHT: + return props.position.x + props.size.x - props.content.size(); + } + return props.position.x; } -#include void Renderer::render(const shared::graphics::TextureProps &props) { auto texture = _castOrThrow(props.texture); @@ -64,4 +84,4 @@ char Renderer::_getRightChar(const shared::graphics::TextureProps &props, const } else { return ' '; } -} \ No newline at end of file +} diff --git a/graphics/ncurses/src/window/Renderer.hpp b/graphics/ncurses/src/window/Renderer.hpp index d21575a..6cee926 100644 --- a/graphics/ncurses/src/window/Renderer.hpp +++ b/graphics/ncurses/src/window/Renderer.hpp @@ -43,21 +43,15 @@ class arcade::graphics::ncurses::window::Renderer { /** * @brief Align vertically the text - * @param align Text alignment - * @param entityPos Entity position - * @param entitySize Entity size + * @param props Text properties */ - void _textVerticalAlign( - const shared::graphics::TextVerticalAlign &align, - const shared::types::Vector2u &entitySize - ); + int _textVerticalAlign(const shared::graphics::TextProps &props); /** * @brief Align the text - * @param align Text alignment - * @param entitySize Entity size + * @param props Text properties */ - void _textAlign(const shared::graphics::TextAlign &align, const shared::types::Vector2i &entitySize); + int _textAlign(const shared::graphics::TextProps &props); /** * @brief Get the right character in the texture diff --git a/graphics/ncurses/src/window/Window.cpp b/graphics/ncurses/src/window/Window.cpp index 9a4bd02..980459a 100644 --- a/graphics/ncurses/src/window/Window.cpp +++ b/graphics/ncurses/src/window/Window.cpp @@ -31,6 +31,7 @@ Window::Window(const IWindow::WindowInitProps &props): noecho(); keypad(stdscr, TRUE); nodelay(stdscr, TRUE); + curs_set(0); _window = std::unique_ptr(newwin(_size.y, _size.x, 0, 0), &delwin); box(_window.get(), 0, 0); } From 239264299b57fa7d10b544afc3f73694e3c948da Mon Sep 17 00:00:00 2001 From: Yann Date: Sun, 7 Apr 2024 21:59:46 +0200 Subject: [PATCH 6/7] feat(ncurses): add mouse events --- core/src/menu/Menu.cpp | 5 + graphics/ncurses/src/window/EventsHandler.cpp | 8 ++ graphics/ncurses/src/window/Window.cpp | 2 +- main.cpp | 49 ++++++++ output | Bin 0 -> 17064 bytes test.txt | 110 ++++++++++++++++++ 6 files changed, 173 insertions(+), 1 deletion(-) create mode 100644 main.cpp create mode 100755 output create mode 100644 test.txt diff --git a/core/src/menu/Menu.cpp b/core/src/menu/Menu.cpp index d1f7f1e..13ece97 100644 --- a/core/src/menu/Menu.cpp +++ b/core/src/menu/Menu.cpp @@ -521,6 +521,11 @@ void Menu::_handleMouseButtonEvents(std::shared_ptr m this->_selectGame(); } } + std::ofstream file("test.txt", std::ios::app); + if (file.is_open()) { + file << "Hello World!" << move->getPosition().x << move->getPosition().x << std::endl; + file.close(); + } } void Menu::_handleEvents() diff --git a/graphics/ncurses/src/window/EventsHandler.cpp b/graphics/ncurses/src/window/EventsHandler.cpp index 0aa38ca..7d31f05 100644 --- a/graphics/ncurses/src/window/EventsHandler.cpp +++ b/graphics/ncurses/src/window/EventsHandler.cpp @@ -31,6 +31,14 @@ std::vector EventsHandler::handleEvents() if (eventPtr) events.push_back(eventPtr); } + MEVENT mouseEvent; + if (getmouse(&mouseEvent) == OK) { + if (mouseEvent.bstate & BUTTON1_CLICKED) { + float delta = 0.1; + auto pos = Vector2f{delta + static_cast(mouseEvent.x), delta + static_cast(mouseEvent.y)}; + events.push_back(std::make_shared(pos, arcade::graphics::common::events::MouseButtonPressEvent::MouseButton::LEFT)); + } + } } return events; } diff --git a/graphics/ncurses/src/window/Window.cpp b/graphics/ncurses/src/window/Window.cpp index 980459a..2126418 100644 --- a/graphics/ncurses/src/window/Window.cpp +++ b/graphics/ncurses/src/window/Window.cpp @@ -31,9 +31,9 @@ Window::Window(const IWindow::WindowInitProps &props): noecho(); keypad(stdscr, TRUE); nodelay(stdscr, TRUE); + mousemask(ALL_MOUSE_EVENTS, NULL); curs_set(0); _window = std::unique_ptr(newwin(_size.y, _size.x, 0, 0), &delwin); - box(_window.get(), 0, 0); } Window::~Window() diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..a2748bd --- /dev/null +++ b/main.cpp @@ -0,0 +1,49 @@ +/* +** EPITECH PROJECT, 2024 +** arcade +** File description: +** main +*/ + +#include + +int main() { + // Initialisation de ncurses + initscr(); + cbreak(); + noecho(); + keypad(stdscr, TRUE); + + // Activer le support de la souris + mousemask(ALL_MOUSE_EVENTS, NULL); + + printw("Utilisez la souris pour cliquer :\n"); + printw("Appuyez sur 'q' pour quitter.\n"); + + // Boucle pour récupérer les événements de la souris + while (true) { + int ch = getch(); + + if (ch == 'q') { + break; + } + + // Vérifier s'il y a des événements de souris + MEVENT event; + if (getmouse(&event) == OK) { + // Vérifier si un clic de souris a eu lieu + if (event.bstate & BUTTON1_CLICKED) { + // Afficher les coordonnées du clic de souris + printw("Clic de souris à la position : %d, %d\n", event.x, event.y); + } + } + + // Rafraîchir l'écran + refresh(); + } + + // Fermeture de ncurses + endwin(); + + return 0; +} diff --git a/output b/output new file mode 100755 index 0000000000000000000000000000000000000000..4c7da4ebd58c7bf3e070b70f73151074b86c8b7e GIT binary patch literal 17064 zcmeHOYiu0V6~4R9!#rZI!^;pL(~=ZZ@c0#syFfFJV|(3(;3iH;rP9fGXKatMJG+^k zB{qE-!b2uON?Sx9$`4vv8dbElXoUi(#55(8LZ#5EQut93QIKqeJt;yda`7@pgaZ15EM-cmN!wwScZA%n*+_h`GK2#9?Qq6yx);z9;(PY zNW6o@W2ulmOZF%F1b9<&6_>oa|YyhdeN_#4<2!e$zAmm+}UQ zH>t>M#H6Ch2+QkySg_>sz5qP*%YPfVn>SH;)%sx@`IBXW3TVmM!<}nda%OYRcFN<; z<6WK2oom!mL2Z{7Sg%(2;h5^*xJ4u<#SCK1Pl&`kJxMy4$bhyN!Vle!{693gr!If# z_<;{G^ zgzeZK(p+oAwMt`Rhc!_&OpzUSEn^210fR70MdS@&g6?F?ZpkX)NbE%2vz?Jbpg}dV z*IpZ_`5-o$g^W;ZLsHhq`!@`%>(SfQjy2FW7_syRV|CsiHXM;>K=OU{t8YFG!!0SE z$3zIn)@oAX7^HD1_2VJ@e2MrM_9xyyIDUgbe#XZ*_6djD5RPM>Ln?&RBTObWhH$)( zI4B`pz7Hs&DTLE2M5eTc@SyJ@r7MJ=!v>Agulk>Nr)KJ1X_3QBR^iBlRax$En%ewA6o!I!?*v9+CPFQOBv++&-y)A9b8U z&P_`FTd3odY_2Hv2T;eU*xYuh-;Fv>!R7`*$M&@SePHU9FK4D+&+LBV`y4 zv@!bQS!sXQTT)D&%sltj+RStB*JKh$GOwKS8iE{_QVvl*mOpv(UvT+UzFdo0Z zp%q6KzXV9)_QPkChxR8PKtt#?W%k#nDwWyy@$x8KpcD53?^*1P%+w3BhX8vP+i(c- zte@3DJ(N;3A!{|;jcQk*w)+`;9x^~~52#bUAMXCzhdayX&)y4~WS!755B45MgXI9- zJ5&GA%sn&Ssy)3Yr)G8^Uxd!OWY3n_J-u&C9XYfu$o$X$hAJw+II;i5!`KEn=7Ld% zb&Nyof!G7F2VxJz9*8{XqCue6B)8af1KY|$+3nkmL z3yzXjR-4zs?_7~sQF9}H>&1TvJo0v>QUp185|*+cCqaG*Wam4T%6CCxz;C7)5_fJA ziSblo#raEX_rZD>ze~vvoxu4N8mwQMLaY^W!1!CwDolc36O=U#Qq-mT>KZ>+f8MUz zNwM~_8$aE#>XQg#UOD(Z3|zT{?ygJSm+V=#B>5DSh!$~(JrH{!_CV}`*aNW#Vh_X~ zh&>Q{AojpVB=3#8L!zhm%H0>yAByOYM)aRWbll^IA=s-&`=oh~p0`|+ z>6gkY>~E(1$ty_brO{=iPgA;Fn*qk@|2$PGpvg>)hQi;Q4YF&ohH9{faF)_}FWpg@ zDg^JLYb5<5k}P;H;4JMwOj5#0lDv-Oy?(f_6~n$Inv{%ZNauQIWU3In=a0*WPn)tm zO=J%rT&2$a1j|UN*HSuV^RWruKOQZxllr%hEX(ThngYacpN) zf$geMu2{DeTDJly$bX2q9d{{12A5LSrkPX*$ z#aZgib-jz~EGt#zg3p6R;+;w~8Ou&U%6@v@DP*u5V z1;)W@f`<7n4cjJ0E^`h(Wme+eTx({a7ZxZ_YFK+C3GGF+fcorU}fj6jLw5>A^-^k`eRztV+Q1j?G4ipb{_Rrx! z100i2`_OqFT^}x$C^jxxO6Z7@QNb+@etB{AAQAt3|g^v|Mi@ z1PzyMIEiMP1a+?)XvQIA8N&9hO^yuPyTw9n!!V1`;S%%y~k^ zt{19jjl&g345SrgPpQ@zjgc`ExUBgMf3Wxrjzh*q-p)d)1;`67sw}|I3>+m?7_)g8 zibAF7oNPMa*c#bV)$lym9xi(@?Eg;z*C%i*24A}xYc!cNpFidGi3H(-w&8FUD7Yp_ z64*t2K5wZJ&H~@(;m`?6m_JT@K6kk)Yz%RJpD;WS;qyFUKP_|=HY6G4-v;=5um<7! z&rta@#OLyt5IDW4*)}-aQ?x25~d&+c>V2bXO5r!kPzl8^qy6S zKg~pv1mg@xhM&MS%;)prN6Fwvm>3GoV+jAx5a#o|!=uR(|9^q)(O2Q{OHh!{{^xm@ zP<*RNUj$e79|O-oB+TdY#*>O~aUC0yjF$f*;9>r>qDjkXMGCRk7r`}J{+}QPW>4}S zKqLOY37<=j+Oy8`HQ>~T_&hJ4ZpPeBj~8D%tuy}wB;eSg+clUM^Eq>c9E;;01M|2a z-vtcY&wM`bd8`GkX+7vi<(2s?{{?86&-3qD;*W*67-b&IB#^^=p5G0&`ow5|p=~(S z0)TmO{kLnHOdcXWx05*vM@TNC^2t0%Wj^ehpBK1%mKQ?=%Z~EzCSWfcQZB5rTn!QK z8#F0y*Q8~tT?(WzcE6HsNz48315K# literal 0 HcmV?d00001 diff --git a/test.txt b/test.txt new file mode 100644 index 0000000..b9665a6 --- /dev/null +++ b/test.txt @@ -0,0 +1,110 @@ +Hello World! +Hello World! +Hello World! +Hello World!1010 +Hello World!11 +Hello World!00 +Hello World!1010 +Hello World!1818 +Hello World!1717 +Hello World!99 +Hello World!99 +Hello World!99 +Hello World!99 +Hello World!99 +Hello World!99 +Hello World!99 +Hello World!99 +Hello World!1010 +Hello World!1818 +Hello World!1919 +Hello World!1010 +Hello World!99 +Hello World!99 +Hello World!99 +Hello World!99 +Hello World!99 +Hello World!99 +Hello World!99 +Hello World!1111 +Hello World!1010 +Hello World!99 +Hello World!99 +Hello World!1010 +Hello World!1010 +Hello World!99 +Hello World!88 +Hello World!88 +Hello World!88 +Hello World!88 +Hello World!99 +Hello World!88 +Hello World!1010 +Hello World!1010 +Hello World!1010 +Hello World!1111 +Hello World!1111 +Hello World!1111 +Hello World!1212 +Hello World!2020 +Hello World!1919 +Hello World!1919 +Hello World!1919 +Hello World!1919 +Hello World!1919 +Hello World!1919 +Hello World!1919 +Hello World!1818 +Hello World!1818 +Hello World!1818 +Hello World!1919 +Hello World!1818 +Hello World!1818 +Hello World!1818 +Hello World!1818 +Hello World!1818 +Hello World!1919 +Hello World!2020 +Hello World!2121 +Hello World!1717 +Hello World!1616 +Hello World!1616 +Hello World!1616 +Hello World!1515 +Hello World!12.628612.6286 +Hello World!12.457112.4571 +Hello World!12.885712.8857 +Hello World!12.812.8 +Hello World!13.028613.0286 +Hello World!12.942912.9429 +Hello World!13.057113.0571 +Hello World!13.171413.1714 +Hello World!13.228613.2286 +Hello World!13.285713.2857 +Hello World!13.257113.2571 +Hello World!13.257113.2571 +Hello World!13.228613.2286 +Hello World!13.457113.4571 +Hello World!13.457113.4571 +Hello World!13.657113.6571 +Hello World!22.622.6 +Hello World!10.110.1 +Hello World!10.110.1 +Hello World!10.110.1 +Hello World!11.111.1 +Hello World!12.112.1 +Hello World!10.110.1 +Hello World!18.118.1 +Hello World!18.118.1 +Hello World!10.110.1 +Hello World!0.10.1 +Hello World!0.10.1 +Hello World!0.10.1 +Hello World!0.10.1 +Hello World!0.10.1 +Hello World!30.130.1 +Hello World!22.122.1 +Hello World!12.112.1 +Hello World!13.113.1 +Hello World!15.115.1 +Hello World!12.112.1 From b8ab83b40f1f73ddea78008705e935bc7ae1d217 Mon Sep 17 00:00:00 2001 From: Yann Date: Sun, 7 Apr 2024 22:09:09 +0200 Subject: [PATCH 7/7] fix(ncurses): remvoe useless debug --- .gitignore | 1 + core/src/menu/Menu.cpp | 5 -- main.cpp | 49 ------------------ test.txt | 110 ----------------------------------------- 4 files changed, 1 insertion(+), 164 deletions(-) delete mode 100644 main.cpp delete mode 100644 test.txt diff --git a/.gitignore b/.gitignore index 1571a4d..181f0ca 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,4 @@ lib *.gcda *.o scores.txt +*.zip diff --git a/core/src/menu/Menu.cpp b/core/src/menu/Menu.cpp index 13ece97..d1f7f1e 100644 --- a/core/src/menu/Menu.cpp +++ b/core/src/menu/Menu.cpp @@ -521,11 +521,6 @@ void Menu::_handleMouseButtonEvents(std::shared_ptr m this->_selectGame(); } } - std::ofstream file("test.txt", std::ios::app); - if (file.is_open()) { - file << "Hello World!" << move->getPosition().x << move->getPosition().x << std::endl; - file.close(); - } } void Menu::_handleEvents() diff --git a/main.cpp b/main.cpp deleted file mode 100644 index a2748bd..0000000 --- a/main.cpp +++ /dev/null @@ -1,49 +0,0 @@ -/* -** EPITECH PROJECT, 2024 -** arcade -** File description: -** main -*/ - -#include - -int main() { - // Initialisation de ncurses - initscr(); - cbreak(); - noecho(); - keypad(stdscr, TRUE); - - // Activer le support de la souris - mousemask(ALL_MOUSE_EVENTS, NULL); - - printw("Utilisez la souris pour cliquer :\n"); - printw("Appuyez sur 'q' pour quitter.\n"); - - // Boucle pour récupérer les événements de la souris - while (true) { - int ch = getch(); - - if (ch == 'q') { - break; - } - - // Vérifier s'il y a des événements de souris - MEVENT event; - if (getmouse(&event) == OK) { - // Vérifier si un clic de souris a eu lieu - if (event.bstate & BUTTON1_CLICKED) { - // Afficher les coordonnées du clic de souris - printw("Clic de souris à la position : %d, %d\n", event.x, event.y); - } - } - - // Rafraîchir l'écran - refresh(); - } - - // Fermeture de ncurses - endwin(); - - return 0; -} diff --git a/test.txt b/test.txt deleted file mode 100644 index b9665a6..0000000 --- a/test.txt +++ /dev/null @@ -1,110 +0,0 @@ -Hello World! -Hello World! -Hello World! -Hello World!1010 -Hello World!11 -Hello World!00 -Hello World!1010 -Hello World!1818 -Hello World!1717 -Hello World!99 -Hello World!99 -Hello World!99 -Hello World!99 -Hello World!99 -Hello World!99 -Hello World!99 -Hello World!99 -Hello World!1010 -Hello World!1818 -Hello World!1919 -Hello World!1010 -Hello World!99 -Hello World!99 -Hello World!99 -Hello World!99 -Hello World!99 -Hello World!99 -Hello World!99 -Hello World!1111 -Hello World!1010 -Hello World!99 -Hello World!99 -Hello World!1010 -Hello World!1010 -Hello World!99 -Hello World!88 -Hello World!88 -Hello World!88 -Hello World!88 -Hello World!99 -Hello World!88 -Hello World!1010 -Hello World!1010 -Hello World!1010 -Hello World!1111 -Hello World!1111 -Hello World!1111 -Hello World!1212 -Hello World!2020 -Hello World!1919 -Hello World!1919 -Hello World!1919 -Hello World!1919 -Hello World!1919 -Hello World!1919 -Hello World!1919 -Hello World!1818 -Hello World!1818 -Hello World!1818 -Hello World!1919 -Hello World!1818 -Hello World!1818 -Hello World!1818 -Hello World!1818 -Hello World!1818 -Hello World!1919 -Hello World!2020 -Hello World!2121 -Hello World!1717 -Hello World!1616 -Hello World!1616 -Hello World!1616 -Hello World!1515 -Hello World!12.628612.6286 -Hello World!12.457112.4571 -Hello World!12.885712.8857 -Hello World!12.812.8 -Hello World!13.028613.0286 -Hello World!12.942912.9429 -Hello World!13.057113.0571 -Hello World!13.171413.1714 -Hello World!13.228613.2286 -Hello World!13.285713.2857 -Hello World!13.257113.2571 -Hello World!13.257113.2571 -Hello World!13.228613.2286 -Hello World!13.457113.4571 -Hello World!13.457113.4571 -Hello World!13.657113.6571 -Hello World!22.622.6 -Hello World!10.110.1 -Hello World!10.110.1 -Hello World!10.110.1 -Hello World!11.111.1 -Hello World!12.112.1 -Hello World!10.110.1 -Hello World!18.118.1 -Hello World!18.118.1 -Hello World!10.110.1 -Hello World!0.10.1 -Hello World!0.10.1 -Hello World!0.10.1 -Hello World!0.10.1 -Hello World!0.10.1 -Hello World!30.130.1 -Hello World!22.122.1 -Hello World!12.112.1 -Hello World!13.113.1 -Hello World!15.115.1 -Hello World!12.112.1