diff options
| author | Loek Le Blansch <loek@pipeframe.xyz> | 2024-12-19 09:13:43 +0100 | 
|---|---|---|
| committer | Loek Le Blansch <loek@pipeframe.xyz> | 2024-12-19 09:13:43 +0100 | 
| commit | d8f1e161b0c98baa7dde287c484529a8b1291626 (patch) | |
| tree | 2f0eb1c7175375eac6efbf6d1e847d51bcd257cd | |
| parent | a6ba1eb5b6b6a1782182008e0044bf1ac04733dc (diff) | |
| parent | 7c76d1743d5b0c3cf6eb05076fae88e948f3e22f (diff) | |
Merge branch 'wouter/button-improvement' of github.com:lonkaars/crepe
| -rw-r--r-- | src/crepe/api/Button.cpp | 6 | ||||
| -rw-r--r-- | src/crepe/api/Button.h | 49 | ||||
| -rw-r--r-- | src/crepe/api/Event.h | 12 | ||||
| -rw-r--r-- | src/crepe/system/InputSystem.cpp | 32 | ||||
| -rw-r--r-- | src/crepe/system/InputSystem.h | 33 | ||||
| -rw-r--r-- | src/test/InputTest.cpp | 54 | 
6 files changed, 103 insertions, 83 deletions
diff --git a/src/crepe/api/Button.cpp b/src/crepe/api/Button.cpp index 305922c..40153c9 100644 --- a/src/crepe/api/Button.cpp +++ b/src/crepe/api/Button.cpp @@ -2,9 +2,7 @@  namespace crepe { -Button::Button(game_object_id_t id, const vec2 & dimensions, const vec2 & offset, -			   const std::function<void()> & on_click) -	: UIObject(id, dimensions, offset), -	  on_click(on_click) {} +Button::Button(game_object_id_t id, const vec2 & dimensions, const vec2 & offset) +	: UIObject(id, dimensions, offset) {}  } // namespace crepe diff --git a/src/crepe/api/Button.h b/src/crepe/api/Button.h index 08f5dec..d42527e 100644 --- a/src/crepe/api/Button.h +++ b/src/crepe/api/Button.h @@ -2,11 +2,23 @@  #include <functional> +#include "Event.h"  #include "UIObject.h"  namespace crepe { -//! Represents a clickable UI button, derived from the UiObject class. +/** + * \brief Button component. + *  + * This component creates a clickable surface at the transform location with the specified width and height. + *  + * The Button can be used in scripts by subscribing a EventHandler to the following events: + * - ButtonPressEvent + * - ButtonEnterEvent + * - ButtonExitEvent + * \see EventManager + *  + */  class Button : public UIObject {  public:  	/** @@ -15,43 +27,22 @@ public:  	 * \param id The unique ID of the game object associated with this button.  	 * \param dimensions The width and height of the UIObject  	 * \param offset The offset relative this GameObjects Transform -	 * \param on_click callback function that will be invoked when the button is clicked.  	 */ -	Button(game_object_id_t id, const vec2 & dimensions, const vec2 & offset, -		   const std::function<void()> & on_click); - -	// TODO: create separate toggle button class -	/** -	 * \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()`. -	 */ -	std::function<void()> on_click = nullptr; - +	Button(game_object_id_t id, const vec2 & dimensions, const vec2 & offset);  	/** -	 * \brief Callback function to be executed when the mouse enters the button's boundaries. +	 * \brief Get the maximum number of instances for this component  	 * -	 * This function is triggered when the mouse cursor moves over the button, allowing -	 * custom actions like visual effects, highlighting, or sound effects. +	 * Since the button Event transfers the GameObject Metadata it will be the same for each button so only one button is allowed per GameObject	 +	 *  +	 * \return 1  	 */ -	std::function<void()> on_mouse_enter = nullptr; - -	/** -	 * \brief Callback function to be executed when the mouse exits the button's boundaries. -	 * -	 * This function is triggered when the mouse cursor moves out of the button's area, -	 * allowing custom actions like resetting visual effects or playing exit-related effects. -	 */ -	std::function<void()> on_mouse_exit = nullptr; +	virtual int get_instances_max() const { return 1; }  private: -	//! friend relation for is_pressed and hover variables +	//! friend relation hover variable  	friend class InputSystem;  	//! Indicates whether the mouse is currently hovering over the button  	bool hover = false; - -public:  };  } // namespace crepe diff --git a/src/crepe/api/Event.h b/src/crepe/api/Event.h index 73bf461..8e38280 100644 --- a/src/crepe/api/Event.h +++ b/src/crepe/api/Event.h @@ -3,9 +3,10 @@  #include <string> -#include "api/KeyCodes.h"  #include "types.h" +#include "KeyCodes.h" +  namespace crepe {  /** @@ -95,15 +96,6 @@ public:  };  /** - * \brief Event triggered when text is submitted, e.g., from a text input. - */ -class TextSubmitEvent : public Event { -public: -	//! The submitted text. -	std::string text = ""; -}; - -/**   * \brief Event triggered to indicate the application is shutting down.   */  class ShutDownEvent : public Event {}; diff --git a/src/crepe/system/InputSystem.cpp b/src/crepe/system/InputSystem.cpp index fca540f..60daa55 100644 --- a/src/crepe/system/InputSystem.cpp +++ b/src/crepe/system/InputSystem.cpp @@ -10,10 +10,8 @@ using namespace crepe;  void InputSystem::update() {  	ComponentManager & mgr = this->mediator.component_manager; -  	SDLContext & context = this->mediator.sdl_context;  	std::vector<EventData> event_list = context.get_events(); -	RefVector<Button> buttons = mgr.get_components_by_type<Button>();  	RefVector<Camera> cameras = mgr.get_components_by_type<Camera>();  	OptionalRef<Camera> curr_cam_ref; @@ -155,28 +153,25 @@ void InputSystem::handle_non_mouse_event(const EventData & event) {  void InputSystem::handle_move(const EventData & event_data, const vec2 & mouse_pos) {  	ComponentManager & mgr = this->mediator.component_manager; - +	EventManager & event_mgr = this->mediator.event_manager;  	RefVector<Button> buttons = mgr.get_components_by_type<Button>();  	for (Button & button : buttons) {  		if (!button.active) continue; -		RefVector<Transform> transform_vec -			= mgr.get_components_by_id<Transform>(button.game_object_id); -		Transform & transform(transform_vec.front().get()); - +		Metadata & metadata +			= mgr.get_components_by_id<Metadata>(button.game_object_id).front(); +		Transform & transform +			= mgr.get_components_by_id<Transform>(button.game_object_id).front();  		bool was_hovering = button.hover;  		if (this->is_mouse_inside_button(mouse_pos, button, transform)) {  			button.hover = true; -			if (!button.on_mouse_enter) continue;  			if (!was_hovering) { -				button.on_mouse_enter(); +				event_mgr.trigger_event<ButtonEnterEvent>(metadata);  			}  		} else {  			button.hover = false; -			// Trigger the on_exit callback if the hover state just changed to false -			if (!button.on_mouse_exit) continue;  			if (was_hovering) { -				button.on_mouse_exit(); +				event_mgr.trigger_event<ButtonExitEvent>(metadata);  			}  		}  	} @@ -184,19 +179,18 @@ void InputSystem::handle_move(const EventData & event_data, const vec2 & mouse_p  void InputSystem::handle_click(const MouseButton & mouse_button, const vec2 & mouse_pos) {  	ComponentManager & mgr = this->mediator.component_manager; - +	EventManager & event_mgr = this->mediator.event_manager;  	RefVector<Button> buttons = mgr.get_components_by_type<Button>();  	for (Button & button : buttons) {  		if (!button.active) continue; -		if (!button.on_click) continue; -		RefVector<Transform> transform_vec -			= mgr.get_components_by_id<Transform>(button.game_object_id); -		Transform & transform = transform_vec.front().get(); +		Metadata & metadata +			= mgr.get_components_by_id<Metadata>(button.game_object_id).front(); +		Transform & transform +			= mgr.get_components_by_id<Transform>(button.game_object_id).front();  		if (this->is_mouse_inside_button(mouse_pos, button, transform)) { - -			button.on_click(); +			event_mgr.trigger_event<ButtonPressEvent>(metadata);  		}  	}  } diff --git a/src/crepe/system/InputSystem.h b/src/crepe/system/InputSystem.h index eefd9fe..e580d8e 100644 --- a/src/crepe/system/InputSystem.h +++ b/src/crepe/system/InputSystem.h @@ -3,6 +3,8 @@  #include "../api/Config.h"  #include "../facade/EventData.h" +#include "../api/Event.h" +#include "../api/Metadata.h"  #include "../types.h"  #include "../util/OptionalRef.h" @@ -13,6 +15,37 @@ namespace crepe {  class Camera;  class Button;  class Transform; +//! Event triggered when a button is clicked +class ButtonPressEvent : public Event { +public: +	//! Metadata of the button. +	const Metadata & metadata; +	/** +	 * \param metadata Metadata of the button pressed +	 */ +	ButtonPressEvent(const Metadata & metadata) : metadata(metadata){}; +}; +//! Event triggered when the mouse enters a button +class ButtonEnterEvent : public Event { +public: +	//! Metadata of the button. +	const Metadata & metadata; +	/** +	 * \param metadata Metadata of the button pressed +	 */ +	ButtonEnterEvent(const Metadata & metadata) : metadata(metadata){}; +}; +//! Event triggered when the mouse leaves a button +class ButtonExitEvent : public Event { +public: +	//! Metadata of the button. +	const Metadata & metadata; +	/** +	 * \param metadata Metadata of the button pressed +	 */ +	ButtonExitEvent(const Metadata & metadata) : metadata(metadata){}; +}; +  /**   * \brief Handles the processing of input events created by SDLContext   * diff --git a/src/test/InputTest.cpp b/src/test/InputTest.cpp index 2d844d4..ce8ea44 100644 --- a/src/test/InputTest.cpp +++ b/src/test/InputTest.cpp @@ -2,7 +2,6 @@  #include <crepe/manager/ResourceManager.h>  #include <crepe/system/RenderSystem.h> -  #define protected public  #define private public @@ -214,8 +213,12 @@ TEST_F(InputTest, MouseClick) {  TEST_F(InputTest, testButtonClick) {  	GameObject button_obj = mgr.new_object("body", "person", vec2{0, 0}, 0, 1);  	bool button_clicked = false; -	std::function<void()> on_click = [&]() { button_clicked = true; }; -	auto & button = button_obj.add_component<Button>(vec2{100, 100}, vec2{0, 0}, on_click); +	event_manager.subscribe<ButtonPressEvent>([&](const ButtonPressEvent & event) { +		button_clicked = true; +		EXPECT_EQ(event.metadata.game_object_id, button_obj.id); +		return false; +	}); +	auto & button = button_obj.add_component<Button>(vec2{100, 100}, vec2{0, 0});  	bool hover = false;  	button.active = true; @@ -232,25 +235,19 @@ TEST_F(InputTest, testButtonClick) {  TEST_F(InputTest, testButtonHover) {  	GameObject button_obj = mgr.new_object("body", "person", vec2{0, 0}, 0, 1); -	bool button_clicked = false; -	std::function<void()> on_click = [&]() { button_clicked = true; }; -	auto & button = button_obj.add_component<Button>(vec2{100, 100}, vec2{0, 0}, on_click); +	bool button_hover = false; +	event_manager.subscribe<ButtonEnterEvent>([&](const ButtonEnterEvent & event) { +		button_hover = true; +		EXPECT_EQ(event.metadata.game_object_id, button_obj.id); +		return false; +	}); +	event_manager.subscribe<ButtonExitEvent>([&](const ButtonExitEvent & event) { +		button_hover = false; +		EXPECT_EQ(event.metadata.game_object_id, button_obj.id); +		return false; +	}); +	auto & button = button_obj.add_component<Button>(vec2{100, 100}, vec2{0, 0});  	button.active = true; - -	// Mouse not on button -	SDL_Event event; -	SDL_zero(event); -	event.type = SDL_MOUSEMOTION; -	event.motion.x = 700; -	event.motion.y = 700; -	event.motion.xrel = 10; -	event.motion.yrel = 10; -	SDL_PushEvent(&event); - -	input_system.update(); -	event_manager.dispatch_events(); -	EXPECT_FALSE(button.hover); -  	// Mouse on button  	SDL_Event hover_event;  	SDL_zero(hover_event); @@ -264,4 +261,19 @@ TEST_F(InputTest, testButtonHover) {  	input_system.update();  	event_manager.dispatch_events();  	EXPECT_TRUE(button.hover); +	EXPECT_TRUE(button_hover); +	// Mouse not on button +	SDL_Event event; +	SDL_zero(event); +	event.type = SDL_MOUSEMOTION; +	event.motion.x = 500; +	event.motion.y = 500; +	event.motion.xrel = 10; +	event.motion.yrel = 10; +	SDL_PushEvent(&event); + +	input_system.update(); +	event_manager.dispatch_events(); +	EXPECT_FALSE(button.hover); +	EXPECT_FALSE(button_hover);  }  |