diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/commands/move_cursor.cpp | 15 | ||||
-rw-r--r-- | src/commands/move_cursor.hpp | 3 | ||||
-rw-r--r-- | src/engine/graphics/scene.cpp | 5 | ||||
-rw-r--r-- | src/engine/user/cursor.cpp | 36 | ||||
-rw-r--r-- | src/engine/user/cursor.hpp | 9 | ||||
-rw-r--r-- | src/game/cursor_listener.cpp | 18 | ||||
-rw-r--r-- | src/game/cursor_listener.hpp | 19 | ||||
-rw-r--r-- | src/game/game.cpp | 15 | ||||
-rw-r--r-- | src/interfaces/command.hpp | 2 | ||||
-rw-r--r-- | src/interfaces/cursor.hpp | 25 | ||||
-rw-r--r-- | src/interfaces/subscriber.hpp | 2 |
12 files changed, 121 insertions, 29 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1a52ae8..c603b37 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -15,6 +15,7 @@ file(GLOB SOURCES argument_parser.cpp util/color.cpp game/game.cpp + game/cursor_listener.cpp engine/engine.cpp engine/data/vector2.cpp engine/data/bounds.cpp diff --git a/src/commands/move_cursor.cpp b/src/commands/move_cursor.cpp index 8dd7db7..1d2b4e8 100644 --- a/src/commands/move_cursor.cpp +++ b/src/commands/move_cursor.cpp @@ -1,16 +1,9 @@ #include "move_cursor.hpp" -#include "strings.hpp" - -#include <fmt/core.h> - MoveCursorCommand::MoveCursorCommand( const Vector2 &direction, const std::shared_ptr<ICursorController> &cursor_controller, - const std::shared_ptr<IScene> &scene, const std::shared_ptr<IWindow> &window) noexcept - : _direction(direction), - _cursor_controller(cursor_controller), - _scene(scene), - _window(window) + const std::shared_ptr<IWindow> &window) noexcept + : _direction(direction), _cursor_controller(cursor_controller), _window(window) { } @@ -30,8 +23,4 @@ void MoveCursorCommand::execute() noexcept } _cursor_controller->move_to(new_position); - - _scene->write_status(fmt::format(STATUS_BAR_COORDINATES, - fmt::arg("x", new_position.get_x()), - fmt::arg("y", new_position.get_y()))); } diff --git a/src/commands/move_cursor.hpp b/src/commands/move_cursor.hpp index 14a87e0..ff4723d 100644 --- a/src/commands/move_cursor.hpp +++ b/src/commands/move_cursor.hpp @@ -2,7 +2,6 @@ #include "interfaces/command.hpp" #include "interfaces/cursor.hpp" -#include "interfaces/scene.hpp" #include "interfaces/window.hpp" #include "engine/data/vector2.hpp" @@ -14,7 +13,6 @@ class MoveCursorCommand : public ICommand public: MoveCursorCommand(const Vector2 &direction, const std::shared_ptr<ICursorController> &cursor_controller, - const std::shared_ptr<IScene> &scene, const std::shared_ptr<IWindow> &window) noexcept; void execute() noexcept override; @@ -22,6 +20,5 @@ public: private: Vector2 _direction; const std::shared_ptr<ICursorController> &_cursor_controller; - const std::shared_ptr<IScene> &_scene; const std::shared_ptr<IWindow> &_window; }; diff --git a/src/engine/graphics/scene.cpp b/src/engine/graphics/scene.cpp index 476b966..4e382fe 100644 --- a/src/engine/graphics/scene.cpp +++ b/src/engine/graphics/scene.cpp @@ -52,7 +52,8 @@ void Scene::write_status(const std::string_view &str) noexcept const auto window_size = _window->size(); _cursor_controller->move_to( - Vector2({.x = 2, .y = static_cast<Vector2::Value>(window_size.get_height())})); + Vector2({.x = 2, .y = static_cast<Vector2::Value>(window_size.get_height())}), + true); auto background_color = get_background_esc_seq(STATUSBAR_COLOR); @@ -61,7 +62,7 @@ void Scene::write_status(const std::string_view &str) noexcept fmt::print(fmt::runtime(str.data())); fmt::print(RESET_ALL_MODES, fmt::arg("esc", ESC)); - _cursor_controller->move_to(previous_position); + _cursor_controller->move_to(previous_position, true); } const std::shared_ptr<IMatrix<std::string_view>> &Scene::get_matrix() const noexcept diff --git a/src/engine/user/cursor.cpp b/src/engine/user/cursor.cpp index b02a9bc..2a72663 100644 --- a/src/engine/user/cursor.cpp +++ b/src/engine/user/cursor.cpp @@ -16,15 +16,22 @@ void CursorController::move(const Vector2 &direction, const uint32_t &amount) no std::cout.flush(); _position = _position.to_direction(direction, static_cast<Vector2::Value>(amount)); + + notify_subscribers(CursorEvent::POSITION_CHANGE, _position); } -void CursorController::move_to(const Vector2 &position) noexcept +void CursorController::move_to(const Vector2 &position, bool silent) noexcept { fmt::print(MOVE_CURSOR_TO, fmt::arg("esc", ESC), fmt::arg("row", position.get_y()), fmt::arg("column", position.get_x())); std::cout.flush(); _position = position; + + if (!silent) + { + notify_subscribers(CursorEvent::POSITION_CHANGE, position); + } } Vector2 CursorController::where() const noexcept @@ -43,6 +50,8 @@ void CursorController::ensure_position() noexcept scanf("\033[%u;%uR", &vector2_options.y, &vector2_options.x); _position = Vector2(vector2_options); + + notify_subscribers(CursorEvent::POSITION_CHANGE, _position); } void CursorController::hide() noexcept @@ -56,3 +65,28 @@ void CursorController::show() noexcept fmt::print(CURSOR_VISIBLE, fmt::arg("esc", ESC)); std::cout.flush(); } + +void CursorController::subscribe(const Event &event, + const Subscriber &subscriber) noexcept +{ + if (_subscribers.count(event) == 0) + { + _subscribers.insert({event, std::vector<Subscriber>()}); + } + + _subscribers.at(event).push_back(subscriber); +} + +void CursorController::notify_subscribers(const Event &event, + const Context &context) const noexcept +{ + if (_subscribers.count(event) == 0) + { + return; + } + + for (const auto &subscriber : _subscribers.at(event)) + { + subscriber->update(context); + } +} diff --git a/src/engine/user/cursor.hpp b/src/engine/user/cursor.hpp index 713ee31..3ba8a40 100644 --- a/src/engine/user/cursor.hpp +++ b/src/engine/user/cursor.hpp @@ -37,7 +37,7 @@ public: void move(const Vector2 &direction, const uint32_t &amount) noexcept override; - void move_to(const Vector2 &position) noexcept override; + void move_to(const Vector2 &position, bool silent) noexcept override; [[nodiscard]] Vector2 where() const noexcept override; @@ -47,6 +47,13 @@ public: static void show() noexcept; + void subscribe(const Event &event, const Subscriber &subscriber) noexcept override; + + void notify_subscribers(const Event &event, + const Context &context) const noexcept override; + private: Vector2 _position; + + std::unordered_map<CursorEvent, std::vector<Subscriber>> _subscribers; }; diff --git a/src/game/cursor_listener.cpp b/src/game/cursor_listener.cpp new file mode 100644 index 0000000..c13ce44 --- /dev/null +++ b/src/game/cursor_listener.cpp @@ -0,0 +1,18 @@ +#include "cursor_listener.hpp" + +#include "strings.hpp" + +#include <fmt/core.h> +#include <utility> + +CursorListener::CursorListener(std::shared_ptr<IScene> scene) noexcept + : _scene(std::move(scene)) +{ +} + +void CursorListener::update(const Vector2 &context) noexcept +{ + _scene->write_status(fmt::format(STATUS_BAR_COORDINATES, + fmt::arg("x", context.get_x()), + fmt::arg("y", context.get_y()))); +} diff --git a/src/game/cursor_listener.hpp b/src/game/cursor_listener.hpp new file mode 100644 index 0000000..c74bb3d --- /dev/null +++ b/src/game/cursor_listener.hpp @@ -0,0 +1,19 @@ +#pragma once + +#include "interfaces/scene.hpp" +#include "interfaces/subscriber.hpp" + +#include "engine/data/vector2.hpp" + +#include <memory> + +class CursorListener : public ISubscriber<Vector2> +{ +public: + explicit CursorListener(std::shared_ptr<IScene> scene) noexcept; + + void update(const Vector2 &context) noexcept override; + +private: + std::shared_ptr<IScene> _scene; +}; diff --git a/src/game/game.cpp b/src/game/game.cpp index 5df3935..055e212 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -3,6 +3,7 @@ #include "commands/insert_cell.hpp" #include "commands/move_cursor.hpp" #include "commands/quit.hpp" +#include "game/cursor_listener.hpp" #include "strings.hpp" #include <fmt/core.h> @@ -16,6 +17,10 @@ Game::Game(const std::shared_ptr<IWindow> &window, const std::shared_ptr<IScene> void Game::on_start() noexcept { + auto cursor_listener = std::make_shared<CursorListener>(_scene); + + _cursor_controller->subscribe(CursorEvent::POSITION_CHANGE, cursor_listener); + const auto window_size = _window->size(); const auto center_position = @@ -50,11 +55,11 @@ Game::get_input_config() const noexcept return {{'q', std::make_shared<QuitCommand>()}, {'i', std::make_shared<InsertCellCommand>(_cursor_controller, _scene)}, {'k', std::make_shared<MoveCursorCommand>(Vector2::up(), _cursor_controller, - _scene, _window)}, + _window)}, {'j', std::make_shared<MoveCursorCommand>(Vector2::down(), _cursor_controller, - _scene, _window)}, + _window)}, {'h', std::make_shared<MoveCursorCommand>(Vector2::left(), _cursor_controller, - _scene, _window)}, - {'l', std::make_shared<MoveCursorCommand>( - Vector2::right(), _cursor_controller, _scene, _window)}}; + _window)}, + {'l', std::make_shared<MoveCursorCommand>(Vector2::right(), + _cursor_controller, _window)}}; } diff --git a/src/interfaces/command.hpp b/src/interfaces/command.hpp index 62d7a59..6220af1 100644 --- a/src/interfaces/command.hpp +++ b/src/interfaces/command.hpp @@ -7,7 +7,7 @@ class ICommand : public ISubscriber<std::nullptr_t> { public: - virtual ~ICommand() = default; + ~ICommand() override = default; virtual void execute() noexcept = 0; diff --git a/src/interfaces/cursor.hpp b/src/interfaces/cursor.hpp index 77c5096..ec2f60c 100644 --- a/src/interfaces/cursor.hpp +++ b/src/interfaces/cursor.hpp @@ -1,17 +1,30 @@ #pragma once +#include "interfaces/publisher.hpp" +#include "interfaces/subscriber.hpp" + #include "engine/data/vector2.hpp" #include <memory> -class ICursorController +enum CursorEvent +{ + POSITION_CHANGE +}; + +class ICursorController : public IPublisher<CursorEvent, Vector2> { public: - virtual ~ICursorController() noexcept = default; + using Event = CursorEvent; + using Context = Vector2; + using Subscriber = std::shared_ptr<ISubscriber<Context>>; + + ~ICursorController() noexcept override = default; virtual void move(const Vector2 &direction, const uint32_t &amount) noexcept = 0; - virtual void move_to(const Vector2 &position) noexcept = 0; + // NOLINTNEXTLINE(google-default-arguments) + virtual void move_to(const Vector2 &position, bool silent = false) noexcept = 0; [[nodiscard]] virtual Vector2 where() const noexcept = 0; @@ -20,4 +33,10 @@ public: static void hide() noexcept; static void show() noexcept; + + void subscribe(const Event &event, + const Subscriber &subscriber) noexcept override = 0; + + void notify_subscribers(const Event &event, + const Context &context) const noexcept override = 0; }; diff --git a/src/interfaces/subscriber.hpp b/src/interfaces/subscriber.hpp index 17d87ef..6641be7 100644 --- a/src/interfaces/subscriber.hpp +++ b/src/interfaces/subscriber.hpp @@ -4,5 +4,7 @@ template <typename Context> class ISubscriber { public: + virtual ~ISubscriber() = default; + virtual void update(const Context &context) noexcept = 0; }; |