diff options
| author | WBoerenkamps <wrj.boerenkamps@student.avans.nl> | 2024-11-27 14:25:32 +0100 | 
|---|---|---|
| committer | WBoerenkamps <wrj.boerenkamps@student.avans.nl> | 2024-11-27 14:25:32 +0100 | 
| commit | 7070f22d86057eafca3b82321d4146958c14a33e (patch) | |
| tree | 9355ce7728a5ab9a9dbf964461b854591e7018d9 /src | |
| parent | ad4de3ee60f699595bfd1950f88e5417fa29a0d5 (diff) | |
pr feedback
Diffstat (limited to 'src')
| -rw-r--r-- | src/crepe/api/Button.cpp | 7 | ||||
| -rw-r--r-- | src/crepe/api/Button.h | 52 | ||||
| -rw-r--r-- | src/crepe/api/Event.h | 7 | ||||
| -rw-r--r-- | src/crepe/api/UiObject.cpp | 2 | ||||
| -rw-r--r-- | src/crepe/api/UiObject.h | 2 | ||||
| -rw-r--r-- | src/crepe/facade/SDLContext.h | 14 | ||||
| -rw-r--r-- | src/crepe/system/InputSystem.cpp | 46 | ||||
| -rw-r--r-- | src/crepe/system/InputSystem.h | 7 | ||||
| -rw-r--r-- | src/test/inputTest.cpp | 45 | 
9 files changed, 109 insertions, 73 deletions
| diff --git a/src/crepe/api/Button.cpp b/src/crepe/api/Button.cpp index 547c0fc..077a5e7 100644 --- a/src/crepe/api/Button.cpp +++ b/src/crepe/api/Button.cpp @@ -1,5 +1,8 @@  #include "Button.h" -using namespace crepe; +namespace crepe { -Button::Button(game_object_id_t id) : UiObject(id) {} +Button::Button(game_object_id_t id, int width, int height, bool is_toggle, std::function<void()> on_click) +    : UiObject(id, width, height), is_toggle(is_toggle), is_pressed(false), hover(false), on_click(on_click) {} + +} // namespace crepe diff --git a/src/crepe/api/Button.h b/src/crepe/api/Button.h index 0056238..df6f1e0 100644 --- a/src/crepe/api/Button.h +++ b/src/crepe/api/Button.h @@ -1,7 +1,6 @@  #pragma once  #include <functional> -  #include "UiObject.h"  namespace crepe { @@ -9,34 +8,59 @@ 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 Button : public UiObject {  public:  	/** -     * \brief Constructs a Button with the specified game object ID. +     * \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. +     * \param is_toggle Optional flag to indicate if the button is a toggle button. Defaults to false. +     * \param on_click callback function that will be invoked when the button is clicked.       */ -	Button(game_object_id_t id); - -	//! Indicates if the button is interactable (can be clicked). -	bool interactable = true; +	Button(game_object_id_t id, int width, int height, bool is_toggle = false, std::function<void()> on_click = nullptr); -	//! Indicates if the button is a toggle button (can be pressed and released). -	bool is_toggle = false; +	/** +     * \brief Indicates if the button is a toggle button (can be pressed and released). +     *  +     * A toggle button allows for a pressed/released state, whereas a regular button +     * typically only has an on-click state. +     */ +	bool is_toggle; -	//! Indicates whether the button is currently pressed. -	bool is_pressed = false; +	/** +     * \brief Indicates whether the button is currently pressed. +     *  +     * This state is true when the button is actively pressed and false otherwise. +     */ +	bool is_pressed; -	//! Indicates whether the mouse is currently hovering over the button. -	bool hover = false; +	/** +     * \brief Indicates whether the mouse is currently hovering over the button. +     *  +     * This is set to true when the mouse is over the button and false otherwise. +     */ +	bool hover; -	//! The callback function to be executed when the button is clicked. +	/** +     * \brief The callback function to be executed when the button is clicked. +     *  +     * This function is invoked whenever the button is clicked. It can be set to any +     * function that matches the signature `void()`. Defaults to nullptr. +     */  	std::function<void()> on_click;  public:  	/**       * \brief Retrieves the maximum number of instances allowed for this button type. -     * \return Always returns 1, as only a single instance is allowed. +     *  +     * \return Always returns 1, as only a single instance of this type is allowed.       */  	virtual int get_instances_max() const override { return 1; }  }; diff --git a/src/crepe/api/Event.h b/src/crepe/api/Event.h index b13abc1..a7d5511 100644 --- a/src/crepe/api/Event.h +++ b/src/crepe/api/Event.h @@ -88,10 +88,12 @@ public:  	//! Y-coordinate of the mouse position at the time of the event.  	int mouse_y = 0; +  	// Relative movement in x -	int rel_x; +	int rel_x = 0; +  	// Relative movement in y -	int rel_y; +	int rel_y = 0;  };  /** @@ -104,6 +106,7 @@ public:  	//! Y-coordinate of the mouse position at the time of the event.  	int scroll_y = 0; +  	//! scroll direction (-1 = down, 1 = up)  	int direction = 0;  }; diff --git a/src/crepe/api/UiObject.cpp b/src/crepe/api/UiObject.cpp index 1c11fc3..987fc06 100644 --- a/src/crepe/api/UiObject.cpp +++ b/src/crepe/api/UiObject.cpp @@ -2,4 +2,4 @@  using namespace crepe; -UiObject::UiObject(game_object_id_t id) : Component(id){}; +UiObject::UiObject(game_object_id_t id,int width,int height) : Component(id),width(width),height(height){}; diff --git a/src/crepe/api/UiObject.h b/src/crepe/api/UiObject.h index 7bd1c2e..6b0323e 100644 --- a/src/crepe/api/UiObject.h +++ b/src/crepe/api/UiObject.h @@ -14,7 +14,7 @@ public:       * \brief Constructs a UiObject with the specified game object ID.       * \param id The unique ID of the game object associated with this UI object.       */ -	UiObject(game_object_id_t id); +	UiObject(game_object_id_t id,int width,int height);  	//! The width of the UI object.  	int width = 0; diff --git a/src/crepe/facade/SDLContext.h b/src/crepe/facade/SDLContext.h index 3e0b073..9f18728 100644 --- a/src/crepe/facade/SDLContext.h +++ b/src/crepe/facade/SDLContext.h @@ -11,20 +11,16 @@  #include <string>  #include <utility> -#include "../api/Event.h" -#include "../api/KeyCodes.h" -#include "../api/Sprite.h" -#include "../api/Transform.h" -#include "../api/Vector2.h" +#include "api/Event.h" +#include "api/KeyCodes.h" +#include "api/Sprite.h" +#include "api/Transform.h"  #include "api/Camera.h"  #include "types.h"  namespace crepe { -// TODO: SDL_Keycode is defined in a header not distributed with crepe, which means this -// typedef is unusable when crepe is packaged. Wouter will fix this later. -//typedef SDL_Keycode CREPE_KEYCODES;  class LoopManager;  class InputSystem;  /** @@ -93,7 +89,7 @@ private:  	 * @param sdlKey The SDL key code to convert.  	 * @return The corresponding `Keycode` value.  	 */ -	Keycode sdl_to_keycode(SDL_Keycode sdlKey); +	Keycode sdl_to_keycode(SDL_Keycode sdl_key);  	/**  	 * @brief Converts an SDL mouse button code to the custom MouseButton type. diff --git a/src/crepe/system/InputSystem.cpp b/src/crepe/system/InputSystem.cpp index 9690fec..590be8d 100644 --- a/src/crepe/system/InputSystem.cpp +++ b/src/crepe/system/InputSystem.cpp @@ -1,8 +1,8 @@ -#include "../api/Button.h" -#include "../api/EventManager.h" +#include "api/Button.h" +#include "api/EventManager.h"  #include "ComponentManager.h" -#include "system/InputSystem.h" +#include "InputSystem.h"  using namespace crepe; @@ -36,17 +36,15 @@ void InputSystem::update() {  				break;  			}  			case SDLContext::EventType::MOUSEUP: { -				MouseReleaseEvent mouse_release_event = MouseReleaseEvent{ +				event_mgr.queue_event<MouseReleaseEvent>(MouseReleaseEvent{  					.mouse_x = event.mouse_position.first,  					.mouse_y = event.mouse_position.second,  					.button = event.mouse_button, -				}; -				event_mgr.queue_event<MouseReleaseEvent>(mouse_release_event); +				}); -				// Calculate deltas for click detection  				int delta_x = event.mouse_position.first - last_mouse_down_position.first;  				int delta_y = event.mouse_position.second - last_mouse_down_position.second; - +		  				if (last_mouse_button == event.mouse_button  					&& std::abs(delta_x) <= click_tolerance  					&& std::abs(delta_y) <= click_tolerance) { @@ -96,10 +94,10 @@ void InputSystem::handle_move(const SDLContext::EventData & event_data) {  		= mgr.get_components_by_type<Transform>();  	for (Button & button : buttons) { -		Transform * transform = find_transform_for_button(button, transforms); +		OptionalRef<Transform> transform = find_transform_for_button(button, transforms);  		if (!transform) continue; -		if (button.interactable && is_mouse_inside_button(event_data, button, *transform)) { +		if (button.active && is_mouse_inside_button(event_data, button, transform)) {  			button.hover = true;  		} else {  			button.hover = false; @@ -111,29 +109,31 @@ void InputSystem::handle_click(const SDLContext::EventData & event_data) {  	ComponentManager & mgr = this->component_manager;  	std::vector<std::reference_wrapper<Button>> buttons = mgr.get_components_by_type<Button>(); -	std::vector<std::reference_wrapper<Transform>> transforms -		= mgr.get_components_by_type<Transform>(); +	std::vector<std::reference_wrapper<Transform>> transforms = mgr.get_components_by_type<Transform>();  	for (Button & button : buttons) { -		Transform * transform = find_transform_for_button(button, transforms); -		if (!transform) continue; +		OptionalRef<Transform> transform_ref = find_transform_for_button(button, transforms); -		if (button.interactable && is_mouse_inside_button(event_data, button, *transform)) { +		if (button.active && is_mouse_inside_button(event_data, button, transform_ref)) {  			handle_button_press(button);  		}  	}  } -Transform * InputSystem::find_transform_for_button( -	Button & button, std::vector<std::reference_wrapper<Transform>> & transforms) { -	for (Transform & transform : transforms) { -		if (button.game_object_id == transform.game_object_id) { -			return &transform; -		} -	} -	return nullptr; + +OptionalRef<Transform> InputSystem::find_transform_for_button( +    Button & button, std::vector<std::reference_wrapper<Transform>> & transforms) { +     +    for (auto& transform : transforms) { +        if (button.game_object_id == transform.get().game_object_id) { +            return OptionalRef<Transform>(transform); +        } +    } + +    return OptionalRef<Transform>();  } +  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 diff --git a/src/crepe/system/InputSystem.h b/src/crepe/system/InputSystem.h index cd7ca77..8b47e49 100644 --- a/src/crepe/system/InputSystem.h +++ b/src/crepe/system/InputSystem.h @@ -1,11 +1,14 @@  #pragma once +#include "facade/SDLContext.h" +#include "util/OptionalRef.h" +  #include "System.h" -#include "../facade/SDLContext.h"  namespace crepe {  class Button; +  class Transform;  /**   * \class InputSystem @@ -57,7 +60,7 @@ private:       * \param transforms A list of transforms to search through.       * \return A pointer to the transform of the button, or nullptr if not found.       */ -	Transform * +	OptionalRef<Transform>  	find_transform_for_button(Button & button,  							  std::vector<std::reference_wrapper<Transform>> & transforms); diff --git a/src/test/inputTest.cpp b/src/test/inputTest.cpp index 3a9d341..0e3e097 100644 --- a/src/test/inputTest.cpp +++ b/src/test/inputTest.cpp @@ -20,12 +20,14 @@ using namespace crepe;  class InputTest : public ::testing::Test {  public:  	ComponentManager mgr{}; -	InputSystem input_system{mgr}; +	InputSystem input_system{mgr};  // Initializes the InputSystem with the ComponentManager -	EventManager & event_manager = EventManager::get_instance(); +	EventManager& event_manager = EventManager::get_instance();  protected: -	void SetUp() override { event_manager.clear(); } +	void SetUp() override {  +		event_manager.clear();  +	}  	void simulate_mouse_click(int mouse_x, int mouse_y, Uint8 mouse_button) {  		SDL_Event event; @@ -37,6 +39,8 @@ protected:  		event.button.y = mouse_y;  		event.button.button = mouse_button;  		SDL_PushEvent(&event); + +		// Simulate Mouse Button Up event  		SDL_zero(event);  		event.type = SDL_MOUSEBUTTONUP;  		event.button.x = mouse_x; @@ -48,7 +52,7 @@ protected:  TEST_F(InputTest, MouseDown) {  	bool mouse_triggered = false; -	EventHandler<MousePressEvent> on_mouse_down = [&](const MousePressEvent & event) { +	EventHandler<MousePressEvent> on_mouse_down = [&](const MousePressEvent& event) {  		mouse_triggered = true;  		EXPECT_EQ(event.mouse_x, 10);  		EXPECT_EQ(event.mouse_y, 10); @@ -64,6 +68,7 @@ TEST_F(InputTest, MouseDown) {  	event.button.y = 10;  	event.button.button = SDL_BUTTON_LEFT;  	SDL_PushEvent(&event); +  	input_system.update();  	event_manager.dispatch_events();  	EXPECT_TRUE(mouse_triggered); @@ -71,8 +76,7 @@ TEST_F(InputTest, MouseDown) {  TEST_F(InputTest, MouseUp) {  	bool function_triggered = false; -	EventHandler<MouseReleaseEvent> on_mouse_release = [&](const MouseReleaseEvent & e) { -		// Handle the mouse click event here +	EventHandler<MouseReleaseEvent> on_mouse_release = [&](const MouseReleaseEvent& e) {  		function_triggered = true;  		EXPECT_EQ(e.mouse_x, 10);  		EXPECT_EQ(e.mouse_y, 10); @@ -88,6 +92,7 @@ TEST_F(InputTest, MouseUp) {  	event.button.y = 10;  	event.button.button = SDL_BUTTON_LEFT;  	SDL_PushEvent(&event); +  	input_system.update();  	event_manager.dispatch_events();  	EXPECT_TRUE(function_triggered); @@ -95,8 +100,7 @@ TEST_F(InputTest, MouseUp) {  TEST_F(InputTest, MouseMove) {  	bool function_triggered = false; -	EventHandler<MouseMoveEvent> on_mouse_move = [&](const MouseMoveEvent & e) { -		// Handle the mouse click event here +	EventHandler<MouseMoveEvent> on_mouse_move = [&](const MouseMoveEvent& e) {  		function_triggered = true;  		EXPECT_EQ(e.mouse_x, 10);  		EXPECT_EQ(e.mouse_y, 10); @@ -114,6 +118,7 @@ TEST_F(InputTest, MouseMove) {  	event.motion.xrel = 10;  	event.motion.yrel = 10;  	SDL_PushEvent(&event); +  	input_system.update();  	event_manager.dispatch_events();  	EXPECT_TRUE(function_triggered); @@ -123,7 +128,7 @@ TEST_F(InputTest, KeyDown) {  	bool function_triggered = false;  	// Define event handler for KeyPressEvent -	EventHandler<KeyPressEvent> on_key_press = [&](const KeyPressEvent & event) { +	EventHandler<KeyPressEvent> on_key_press = [&](const KeyPressEvent& event) {  		function_triggered = true;  		EXPECT_EQ(event.key, Keycode::B); // Validate the key is 'B'  		EXPECT_EQ(event.repeat, true); // Validate repeat flag @@ -148,7 +153,7 @@ TEST_F(InputTest, KeyDown) {  TEST_F(InputTest, KeyUp) {  	bool function_triggered = false; -	EventHandler<KeyReleaseEvent> on_key_release = [&](const KeyReleaseEvent & event) { +	EventHandler<KeyReleaseEvent> on_key_release = [&](const KeyReleaseEvent& event) {  		function_triggered = true;  		EXPECT_EQ(event.key, Keycode::B);  		return false; @@ -160,6 +165,7 @@ TEST_F(InputTest, KeyUp) {  	event.type = SDL_KEYUP;  	event.key.keysym.scancode = SDL_SCANCODE_B;  	SDL_PushEvent(&event); +  	input_system.update();  	event_manager.dispatch_events();  	EXPECT_TRUE(function_triggered); @@ -167,7 +173,7 @@ TEST_F(InputTest, KeyUp) {  TEST_F(InputTest, MouseClick) {  	bool on_click_triggered = false; -	EventHandler<MouseClickEvent> on_mouse_click = [&](const MouseClickEvent & event) { +	EventHandler<MouseClickEvent> on_mouse_click = [&](const MouseClickEvent& event) {  		on_click_triggered = true;  		EXPECT_EQ(event.button, MouseButton::LEFT_MOUSE);  		EXPECT_EQ(event.mouse_x, 10); @@ -184,13 +190,11 @@ TEST_F(InputTest, MouseClick) {  TEST_F(InputTest, testButtonClick) {  	GameObject obj = mgr.new_object("body", "person", vec2{0, 0}, 0, 1); -	auto & button = obj.add_component<Button>(); +	 +	auto& button = obj.add_component<Button>(100,100);  	bool button_clicked = false;  	bool hover = false;  	button.active = true; -	button.interactable = true; -	button.width = 100; -	button.height = 100;  	std::function<void()> on_click = [&]() { button_clicked = true; };  	button.on_click = on_click;  	button.is_pressed = false; @@ -199,6 +203,7 @@ TEST_F(InputTest, testButtonClick) {  	input_system.update();  	event_manager.dispatch_events();  	EXPECT_FALSE(button_clicked); +  	this->simulate_mouse_click(10, 10, SDL_BUTTON_LEFT);  	input_system.update();  	event_manager.dispatch_events(); @@ -207,15 +212,15 @@ TEST_F(InputTest, testButtonClick) {  TEST_F(InputTest, testButtonHover) {  	GameObject obj = mgr.new_object("body", "person", vec2{0, 0}, 0, 1); -	auto & button = obj.add_component<Button>(); +	auto& button = obj.add_component<Button>(100,100);  	bool button_clicked = false;  	button.active = true; -	button.interactable = true;  	button.width = 100;  	button.height = 100;  	button.is_pressed = false;  	button.is_toggle = false; -	//mouse not on button + +	// Mouse not on button  	SDL_Event event;  	SDL_zero(event);  	event.type = SDL_MOUSEMOTION; @@ -228,7 +233,8 @@ TEST_F(InputTest, testButtonHover) {  	input_system.update();  	event_manager.dispatch_events();  	EXPECT_FALSE(button.hover); -	//mouse on button + +	// Mouse on button  	SDL_Event hover_event;  	SDL_zero(hover_event);  	hover_event.type = SDL_MOUSEMOTION; @@ -237,6 +243,7 @@ TEST_F(InputTest, testButtonHover) {  	hover_event.motion.xrel = 10;  	hover_event.motion.yrel = 10;  	SDL_PushEvent(&hover_event); +  	input_system.update();  	event_manager.dispatch_events();  	EXPECT_TRUE(button.hover); |