diff options
-rw-r--r-- | src/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/crepe/api/CMakeLists.txt | 3 | ||||
-rw-r--r-- | src/crepe/api/Font.cpp | 45 | ||||
-rw-r--r-- | src/crepe/api/Font.h | 60 | ||||
-rw-r--r-- | src/crepe/api/Text.h | 42 | ||||
-rw-r--r-- | src/crepe/facade/SDLContext.cpp | 70 | ||||
-rw-r--r-- | src/crepe/system/InputSystem.cpp | 79 | ||||
-rw-r--r-- | src/crepe/system/InputSystem.h | 84 | ||||
-rw-r--r-- | src/test/InputTest.cpp | 7 |
9 files changed, 167 insertions, 225 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b0b034f..c3f29da 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -9,7 +9,6 @@ project(crepe C CXX) find_package(SDL2 REQUIRED) find_package(SDL2_image REQUIRED) -find_package(SDL2_ttf REQUIRED) find_package(SoLoud REQUIRED) find_package(GTest REQUIRED) find_package(whereami REQUIRED) @@ -25,7 +24,6 @@ target_include_directories(crepe target_link_libraries(crepe PRIVATE soloud PUBLIC SDL2 - PUBLIC SDL_ttf PUBLIC SDL2_image PUBLIC ${BERKELEY_DB} PUBLIC whereami diff --git a/src/crepe/api/CMakeLists.txt b/src/crepe/api/CMakeLists.txt index 2d86968..aeb451d 100644 --- a/src/crepe/api/CMakeLists.txt +++ b/src/crepe/api/CMakeLists.txt @@ -25,7 +25,6 @@ target_sources(crepe PUBLIC Script.cpp Button.cpp UiObject.cpp - Font.cpp ) target_sources(crepe PUBLIC FILE_SET HEADERS FILES @@ -63,6 +62,4 @@ target_sources(crepe PUBLIC FILE_SET HEADERS FILES Asset.h Button.h UiObject.h - Font.h - Text.h ) diff --git a/src/crepe/api/Font.cpp b/src/crepe/api/Font.cpp deleted file mode 100644 index 8db4b23..0000000 --- a/src/crepe/api/Font.cpp +++ /dev/null @@ -1,45 +0,0 @@ -#include <SDL2/SDL_ttf.h> - -#include "facade/SDLContext.h" -#include "util/Log.h" - -#include "Asset.h" -#include "Font.h" - -using namespace crepe; -using namespace std; - -Font::Font(const Asset &src, int size) : font_size(size) { - dbg_trace(); - this->load(src, size); -} - -Font::~Font() { - dbg_trace(); - this->font.reset(); -} - -void Font::load(const Asset &res, int size) { - SDLContext &ctx = SDLContext::get_instance(); - // Open the font using SDL's TTF_OpenFontRW, which supports loading from memory - SDL_RWops *rw_ops = SDL_RWFromFile(res.get_path().c_str(), "rb"); - if (!rw_ops) { - // dbg_log("Failed to create RWops for font: %s", SDL_GetError()); - return; - } - - TTF_Font *loaded_font = TTF_OpenFontRW(rw_ops, 1, size); // 1 indicates SDL should free the RWops - if (!loaded_font) { - // dbg_log("Failed to load font from asset: %s", TTF_GetError()); - return; - } - - // Wrap the TTF_Font with a unique_ptr for automatic cleanup - this->font = unique_ptr<TTF_Font, function<void(TTF_Font *)>>(loaded_font, [](TTF_Font *f) { - if (f) TTF_CloseFont(f); - }); -} - -int Font::get_size() const { - return this->font_size; -} diff --git a/src/crepe/api/Font.h b/src/crepe/api/Font.h deleted file mode 100644 index 012c271..0000000 --- a/src/crepe/api/Font.h +++ /dev/null @@ -1,60 +0,0 @@ -#pragma once - -#include <SDL2/SDL_ttf.h> -#include <functional> -#include <memory> - -#include "Asset.h" - -namespace crepe { - -class SDLContext; - -/** - * \class Font - * \brief Manages font loading and text rendering properties. - * - * The Font class is responsible for loading font resources and providing a way to render text - * with different styles and sizes. It can be used for text rendering in the game engine. - */ -class Font { - -public: - /** - * \brief Constructs a Font from an Asset resource. - * \param src Asset with font data to load. - * \param size The point size to render the font at. - */ - Font(const Asset &src, int size); - - /** - * \brief Destroys the Font instance, freeing associated resources. - */ - ~Font(); - - /** - * \brief Gets the size of the font. - * \return The point size of the font. - */ - int get_size() const; - -private: - /** - * \brief Loads the font from an Asset resource. - * \param res The Asset resource containing the font data. - * \param size The point size to render the font at. - */ - void load(const Asset &res, int size); - -private: - //! The font resource from the SDL_ttf library. - std::unique_ptr<TTF_Font, std::function<void(TTF_Font *)>> font; - - //! The size of the font in points. - int font_size; - - //! Grants SDLContext access to private members. - friend class SDLContext; -}; - -} // namespace crepe diff --git a/src/crepe/api/Text.h b/src/crepe/api/Text.h deleted file mode 100644 index 6bb011c..0000000 --- a/src/crepe/api/Text.h +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once - -#include <string> - -#include "Color.h" -#include "UiObject.h" -#include "" -namespace crepe { - -/** - * \class Button - * \brief Represents a clickable UI button, derived from the UiObject class. - * - * This class provides functionality for a button in the UI, including toggle state, - * click handling, and mouse hover detection. A callback function can be provided to - * handle button clicks. - */ -class Text : public UiObject { -public: - /** - * \brief Constructs a Button with the specified game object ID and dimensions. - * - * \param id The unique ID of the game object associated with this button. - * \param width The width of the button. - * \param height The height of the button. - */ - Text(game_object_id_t id, int width, int height); - - Color color = Color{0,0,0,0}; - std::string text = ""; - int size = 0; - const std::shared_ptr<Font> sprite_image; -public: - /** - * \brief Retrieves the maximum number of instances allowed for this button type. - * - * \return Always returns 1, as only a single instance of this type is allowed. - */ - virtual int get_instances_max() const override { return 10; } -}; - -} // namespace crepe diff --git a/src/crepe/facade/SDLContext.cpp b/src/crepe/facade/SDLContext.cpp index 9b4595e..03b0cdc 100644 --- a/src/crepe/facade/SDLContext.cpp +++ b/src/crepe/facade/SDLContext.cpp @@ -16,6 +16,8 @@ #include <stdexcept> #include "../api/Camera.h" +#include "../api/EventManager.h" +#include "../api/Config.h" #include "../api/Sprite.h" #include "../api/Texture.h" #include "../util/Log.h" @@ -213,7 +215,10 @@ MouseButton SDLContext::sdl_to_mousebutton(Uint8 sdl_button) { return MOUSE_BUTTON_LOOKUP_TABLE[sdl_button]; } -void SDLContext::clear_screen() { SDL_RenderClear(this->game_renderer.get()); } +void SDLContext::clear_screen() { + SDL_SetRenderDrawColor(this->game_renderer.get(), 0, 0, 0, 255); + SDL_RenderClear(this->game_renderer.get()); +} void SDLContext::present_screen() { SDL_RenderPresent(this->game_renderer.get()); } SDL_Rect SDLContext::get_src_rect(const Sprite & sprite) const { @@ -336,3 +341,66 @@ ivec2 SDLContext::get_size(const Texture & ctx) { } void SDLContext::delay(int ms) const { SDL_Delay(ms); } + +std::vector<SDLContext::EventData> SDLContext::get_events() { + std::vector<SDLContext::EventData> event_list; + SDL_Event event; + while (SDL_PollEvent(&event)) { + switch (event.type) { + case SDL_QUIT: + event_list.push_back(EventData{ + .event_type = SDLContext::EventType::SHUTDOWN, + }); + break; + case SDL_KEYDOWN: + event_list.push_back(EventData{ + .event_type = SDLContext::EventType::KEYDOWN, + .key = sdl_to_keycode(event.key.keysym.scancode), + .key_repeat = (event.key.repeat != 0), + }); + break; + case SDL_KEYUP: + event_list.push_back(EventData{ + .event_type = SDLContext::EventType::KEYUP, + .key = sdl_to_keycode(event.key.keysym.scancode), + }); + break; + case SDL_MOUSEBUTTONDOWN: + event_list.push_back(EventData{ + .event_type = SDLContext::EventType::MOUSEDOWN, + .mouse_button = sdl_to_mousebutton(event.button.button), + .mouse_position = {event.button.x, event.button.y}, + }); + break; + case SDL_MOUSEBUTTONUP: { + int x, y; + SDL_GetMouseState(&x, &y); + event_list.push_back(EventData{ + .event_type = SDLContext::EventType::MOUSEUP, + .mouse_button = sdl_to_mousebutton(event.button.button), + .mouse_position = {event.button.x, event.button.y}, + }); + } break; + + case SDL_MOUSEMOTION: { + event_list.push_back( + EventData{.event_type = SDLContext::EventType::MOUSEMOVE, + .mouse_position = {event.motion.x, event.motion.y}, + .rel_mouse_move = {event.motion.xrel, event.motion.yrel}}); + } break; + + case SDL_MOUSEWHEEL: { + event_list.push_back(EventData{ + .event_type = SDLContext::EventType::MOUSEWHEEL, + .mouse_position = {event.motion.x, event.motion.y}, + .wheel_delta = event.wheel.y, + }); + } break; + } + } + return event_list; +} +void SDLContext::set_color_texture(const Texture & texture, const Color & color) { + SDL_SetTextureColorMod(texture.texture.get(), color.r, color.g, color.b); + SDL_SetTextureAlphaMod(texture.texture.get(), color.a); +} diff --git a/src/crepe/system/InputSystem.cpp b/src/crepe/system/InputSystem.cpp index beeef87..5b220eb 100644 --- a/src/crepe/system/InputSystem.cpp +++ b/src/crepe/system/InputSystem.cpp @@ -1,16 +1,35 @@ -#include "ComponentManager.h" -#include "api/Button.h" -#include "api/EventManager.h" +#include "../ComponentManager.h" +#include "../api/Button.h" +#include "../api/EventManager.h" #include "InputSystem.h" using namespace crepe; + void InputSystem::update() { + ComponentManager & mgr = this->component_manager; EventManager & event_mgr = EventManager::get_instance(); std::vector<SDLContext::EventData> event_list = SDLContext::get_instance().get_events(); + RefVector<Button> buttons = mgr.get_components_by_type<Button>(); + RefVector<Camera> cameras = mgr.get_components_by_type<Camera>(); + // Find the active camera + for (Camera & cam : cameras) { + if (!cam.active) continue; + this->curr_cam_ref = cam; + break; + } + if (!curr_cam_ref) return; + Camera& current_cam = curr_cam_ref; + RefVector<Transform> transform_vec = mgr.get_components_by_id<Transform>(current_cam.game_object_id); + Transform& cam_transform = transform_vec.front().get(); + int camera_origin_x = cam_transform.position.x + current_cam.offset.x - (current_cam.viewport_size.x / 2); + int camera_origin_y = cam_transform.position.y + current_cam.offset.y - (current_cam.viewport_size.y / 2); for (const SDLContext::EventData & event : event_list) { + int world_mouse_x = event.mouse_position.first + camera_origin_x; + int world_mouse_y = event.mouse_position.second + camera_origin_y; + switch (event.event_type) { case SDLContext::EventType::KEYDOWN: event_mgr.queue_event<KeyPressEvent>(KeyPressEvent{ @@ -25,43 +44,43 @@ void InputSystem::update() { break; case SDLContext::EventType::MOUSEDOWN: event_mgr.queue_event<MousePressEvent>(MousePressEvent{ - .mouse_x = event.mouse_position.first, - .mouse_y = event.mouse_position.second, + .mouse_x = world_mouse_x, + .mouse_y = world_mouse_y, .button = event.mouse_button, }); - last_mouse_down_position = event.mouse_position; + last_mouse_down_position = {world_mouse_x, world_mouse_y}; last_mouse_button = event.mouse_button; break; case SDLContext::EventType::MOUSEUP: { event_mgr.queue_event<MouseReleaseEvent>(MouseReleaseEvent{ - .mouse_x = event.mouse_position.first, - .mouse_y = event.mouse_position.second, + .mouse_x = world_mouse_x, + .mouse_y = world_mouse_y, .button = event.mouse_button, }); - - int delta_x = event.mouse_position.first - last_mouse_down_position.first; - int delta_y = event.mouse_position.second - last_mouse_down_position.second; + //check if its a click by checking the last button down + int delta_x = world_mouse_x - last_mouse_down_position.first; + int delta_y = world_mouse_y - last_mouse_down_position.second; if (last_mouse_button == event.mouse_button && std::abs(delta_x) <= click_tolerance && std::abs(delta_y) <= click_tolerance) { event_mgr.queue_event<MouseClickEvent>(MouseClickEvent{ - .mouse_x = event.mouse_position.first, - .mouse_y = event.mouse_position.second, + .mouse_x = world_mouse_x, + .mouse_y = world_mouse_y, .button = event.mouse_button, }); - handle_click(event); + handle_click(event.mouse_button, world_mouse_x, world_mouse_y); } } break; case SDLContext::EventType::MOUSEMOVE: event_mgr.queue_event<MouseMoveEvent>(MouseMoveEvent{ - .mouse_x = event.mouse_position.first, - .mouse_y = event.mouse_position.second, + .mouse_x = world_mouse_x, + .mouse_y = world_mouse_y, .rel_x = event.rel_mouse_move.first, .rel_y = event.rel_mouse_move.second, }); - handle_move(event); + handle_move(event, world_mouse_x, world_mouse_y); break; case SDLContext::EventType::MOUSEWHEEL: event_mgr.queue_event<MouseScrollEvent>(MouseScrollEvent{ @@ -79,7 +98,7 @@ void InputSystem::update() { } } -void InputSystem::handle_move(const SDLContext::EventData & event_data) { +void InputSystem::handle_move(const SDLContext::EventData & event_data, const int& world_mouse_x, const int& world_mouse_y) { ComponentManager & mgr = this->component_manager; RefVector<Button> buttons = mgr.get_components_by_type<Button>(); @@ -90,19 +109,14 @@ void InputSystem::handle_move(const SDLContext::EventData & event_data) { OptionalRef<Transform> transform(transform_vec.front().get()); if (!transform) continue; - bool was_hovering = button.hover; // Store previous hover state - - // Check if the mouse is inside the button - if (button.active && is_mouse_inside_button(event_data, button, transform)) { + bool was_hovering = button.hover; + if (button.active && is_mouse_inside_button(world_mouse_x, world_mouse_y, button, transform)) { button.hover = true; - - // Trigger the on_enter callback if the hover state just changed to true if (!was_hovering && button.on_enter) { button.on_enter(); } } else { button.hover = false; - // Trigger the on_exit callback if the hover state just changed to false if (was_hovering && button.on_exit) { button.on_exit(); @@ -111,7 +125,7 @@ void InputSystem::handle_move(const SDLContext::EventData & event_data) { } } -void InputSystem::handle_click(const SDLContext::EventData & event_data) { +void InputSystem::handle_click(const MouseButton& mouse_button, const int& world_mouse_x, const int& world_mouse_y) { ComponentManager & mgr = this->component_manager; RefVector<Button> buttons = mgr.get_components_by_type<Button>(); @@ -121,18 +135,17 @@ void InputSystem::handle_click(const SDLContext::EventData & event_data) { = mgr.get_components_by_id<Transform>(button.game_object_id); OptionalRef<Transform> transform(transform_vec.front().get()); - if (button.active && is_mouse_inside_button(event_data, button, transform)) { + if (button.active && is_mouse_inside_button(world_mouse_x, world_mouse_y, button, transform)) { handle_button_press(button); } } } -bool InputSystem::is_mouse_inside_button(const SDLContext::EventData & event_data, - const Button & button, const Transform & transform) { - return event_data.mouse_position.first >= transform.position.x - && event_data.mouse_position.first <= transform.position.x + button.width - && event_data.mouse_position.second >= transform.position.y - && event_data.mouse_position.second <= transform.position.y + button.height; +bool InputSystem::is_mouse_inside_button(const int& mouse_x, const int& mouse_y, const Button & button, const Transform & transform) { + return mouse_x >= transform.position.x + && mouse_x <= transform.position.x + button.width + && mouse_y >= transform.position.y + && mouse_y <= transform.position.y + button.height; } void InputSystem::handle_button_press(Button & button) { diff --git a/src/crepe/system/InputSystem.h b/src/crepe/system/InputSystem.h index c6ca114..e937d01 100644 --- a/src/crepe/system/InputSystem.h +++ b/src/crepe/system/InputSystem.h @@ -8,69 +8,77 @@ namespace crepe { +class Camera; class Button; - class Transform; + /** - * \class InputSystem * \brief Handles the processing of input events like mouse and keyboard interactions. - * + * * This system processes events such as mouse clicks, mouse movement, and keyboard * actions. It is responsible for detecting interactions with UI buttons and * passing the corresponding events to the registered listeners. */ class InputSystem : public System { public: - using System::System; + using System::System; - /** + /** * \brief Updates the system, processing all input events. * This method processes all events and triggers corresponding actions. */ - void update() override; + void update() override; private: - //! Stores the last position of the mouse when the button was pressed. - std::pair<int, int> last_mouse_down_position{-1, -1}; + //! Reference to the currently active camera. + OptionalRef<Camera> curr_cam_ref; - //! Stores the last mouse button pressed. - MouseButton last_mouse_button = MouseButton::NONE; + //! Stores the last position of the mouse when the button was pressed. + std::pair<int, int> last_mouse_down_position{INFINITY, INFINITY}; - //! The tolerance in game units for detecting a mouse click. - const int click_tolerance = 5; + //! Stores the last mouse button pressed. + MouseButton last_mouse_button = MouseButton::NONE; + // + //! The tolerance in game units for detecting a mouse click. + const int click_tolerance = 5; /** - * \brief Handles the click event. - * \param eventData The event data containing information about the mouse click. - * - * This method processes the mouse click event and triggers the corresponding button action. - */ - void handle_click(const SDLContext::EventData & eventData); + * \brief Handles the mouse click event. + * \param mouse_button The mouse button involved in the click. + * \param world_mouse_x The X coordinate of the mouse in world space. + * \param world_mouse_y The Y coordinate of the mouse in world space. + * + * This method processes the mouse click event and triggers the corresponding button action. + */ + void handle_click(const MouseButton& mouse_button, const int& world_mouse_x, const int& world_mouse_y); /** - * \brief Handles the mouse movement event. - * \param eventData The event data containing information about the mouse movement. - * - * This method processes the mouse movement event and updates the button hover state. - */ - void handle_move(const SDLContext::EventData & eventData); + * \brief Handles the mouse movement event. + * \param event_data The event data containing information about the mouse movement. + * \param world_mouse_x The X coordinate of the mouse in world space. + * \param world_mouse_y The Y coordinate of the mouse in world space. + * + * This method processes the mouse movement event and updates the button hover state. + */ + void handle_move(const SDLContext::EventData& event_data, const int& world_mouse_x, const int& world_mouse_y); + /** - * \brief Checks if the mouse position is inside the bounds of the button. - * \param eventData The event data containing the mouse position. - * \param button The button to check. - * \param transform The transform component of the button. - * \return True if the mouse is inside the button, false otherwise. - */ - bool is_mouse_inside_button(const SDLContext::EventData & eventData, const Button & button, - const Transform & transform); + * \brief Checks if the mouse position is inside the bounds of the button. + * \param mouse_x The X coordinate of the mouse. + * \param mouse_y The Y coordinate of the mouse. + * \param button The button to check. + * \param transform The transform component of the button. + * \return True if the mouse is inside the button, false otherwise. + */ + bool is_mouse_inside_button(const int& mouse_x, const int& mouse_y, const Button& button, const Transform& transform); /** - * \brief Handles the button press event, calling the on_click callback if necessary. - * \param button The button being pressed. - * - * This method triggers the on_click action for the button when it is pressed. - */ - void handle_button_press(Button & button); + * \brief Handles the button press event, calling the on_click callback if necessary. + * \param button The button being pressed. + * + * This method triggers the on_click action for the button when it is pressed. + */ + void handle_button_press(Button& button); }; } // namespace crepe diff --git a/src/test/InputTest.cpp b/src/test/InputTest.cpp index 4f6077b..9725836 100644 --- a/src/test/InputTest.cpp +++ b/src/test/InputTest.cpp @@ -12,6 +12,7 @@ #include <crepe/api/Metadata.h> #include <crepe/api/Transform.h> #include <crepe/api/Vector2.h> +#include <crepe/api/Camera.h> #include <gmock/gmock.h> using namespace std; @@ -26,7 +27,10 @@ public: EventManager & event_manager = EventManager::get_instance(); protected: - void SetUp() override { event_manager.clear(); } + void SetUp() override { + event_manager.clear(); + // GameObject camera = mgr.new_object<Camera>(Color{0,0,0,0},ivec2{0,0},vec2{500,500},0,vec2{0,0}); + } void simulate_mouse_click(int mouse_x, int mouse_y, Uint8 mouse_button) { SDL_Event event; @@ -47,6 +51,7 @@ protected: event.button.button = mouse_button; SDL_PushEvent(&event); } + GameObject camera; }; TEST_F(InputTest, MouseDown) { |