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) { |