diff options
Diffstat (limited to 'src')
| -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/api/LoopManager.h | 19 | ||||
| -rw-r--r-- | src/crepe/api/Script.cpp | 3 | ||||
| -rw-r--r-- | src/crepe/api/Script.h | 10 | ||||
| -rw-r--r-- | src/crepe/facade/DB.cpp | 12 | ||||
| -rw-r--r-- | src/crepe/facade/DB.h | 2 | ||||
| -rw-r--r-- | src/crepe/manager/SaveManager.cpp | 49 | ||||
| -rw-r--r-- | src/crepe/manager/SaveManager.h | 6 | ||||
| -rw-r--r-- | src/crepe/system/InputSystem.cpp | 26 | ||||
| -rw-r--r-- | src/crepe/system/InputSystem.h | 33 | ||||
| -rw-r--r-- | src/crepe/system/ScriptSystem.cpp | 5 | ||||
| -rw-r--r-- | src/doc/feature/proxy.dox | 43 | ||||
| -rw-r--r-- | src/doc/feature/savemgr.dox | 80 | ||||
| -rw-r--r-- | src/example/game.cpp | 2 | ||||
| -rw-r--r-- | src/test/CollisionTest.cpp | 1 | ||||
| -rw-r--r-- | src/test/DBTest.cpp | 8 | ||||
| -rw-r--r-- | src/test/InputTest.cpp | 72 | ||||
| -rw-r--r-- | src/test/SaveManagerTest.cpp | 17 | ||||
| -rw-r--r-- | src/test/ScriptTest.cpp | 22 | ||||
| -rw-r--r-- | src/test/ScriptTest.h | 7 | ||||
| -rw-r--r-- | src/test/main.cpp | 3 | 
23 files changed, 342 insertions, 145 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/api/LoopManager.h b/src/crepe/api/LoopManager.h index 1d23cbf..124cd3a 100644 --- a/src/crepe/api/LoopManager.h +++ b/src/crepe/api/LoopManager.h @@ -71,9 +71,19 @@ private:  private:  	//! Global context  	Mediator mediator; +	/** +	 * \brief Collection of System instances +	 * +	 * This map holds System instances indexed by the system's class typeid. It is filled in the +	 * constructor of LoopManager using LoopManager::load_system. +	 */ +	std::unordered_map<std::type_index, std::unique_ptr<System>> systems;  	//! SDLContext instance  	SDLContext sdl_context{mediator}; +	//! Resource manager instance +	ResourceManager resource_manager{mediator}; +  	//! Component manager instance  	ComponentManager component_manager{mediator};  	//! Scene manager instance @@ -82,8 +92,6 @@ private:  	LoopTimerManager loop_timer{mediator};  	//! EventManager instance  	EventManager event_manager{mediator}; -	//! Resource manager instance -	ResourceManager resource_manager{mediator};  	//! Save manager instance  	SaveManager save_manager{mediator}; @@ -95,13 +103,6 @@ private:  	 */  	bool on_shutdown(const ShutDownEvent & e);  	/** -	 * \brief Collection of System instances -	 * -	 * This map holds System instances indexed by the system's class typeid. It is filled in the -	 * constructor of LoopManager using LoopManager::load_system. -	 */ -	std::unordered_map<std::type_index, std::unique_ptr<System>> systems; -	/**  	 * \brief Initialize a system  	 * \tparam T System type (must be derivative of \c System)  	 */ diff --git a/src/crepe/api/Script.cpp b/src/crepe/api/Script.cpp index 583c04f..85016f5 100644 --- a/src/crepe/api/Script.cpp +++ b/src/crepe/api/Script.cpp @@ -26,6 +26,8 @@ void Script::set_next_scene(const string & name) {  SaveManager & Script::get_save_manager() const { return this->mediator->save_manager; } +LoopTimerManager & Script::get_loop_timer() const { return this->mediator->loop_timer; } +  const keyboard_state_t & Script::get_keyboard_state() const {  	SDLContext & sdl_context = this->mediator->sdl_context;  	return sdl_context.get_keyboard_state(); @@ -38,3 +40,4 @@ bool Script::get_key_state(Keycode key) const noexcept {  		return false;  	}  } + diff --git a/src/crepe/api/Script.h b/src/crepe/api/Script.h index 65306cd..a87af4e 100644 --- a/src/crepe/api/Script.h +++ b/src/crepe/api/Script.h @@ -4,6 +4,7 @@  #include "../api/KeyCodes.h"  #include "../manager/EventManager.h" +#include "../manager/LoopTimerManager.h"  #include "../manager/Mediator.h"  #include "../system/CollisionSystem.h"  #include "../types.h" @@ -47,10 +48,12 @@ protected:  	/**  	 * \brief Script update function (empty by default)  	 * +	 * \param delta_time Time since last fixed update +	 *  	 * This function is called during the ScriptSystem::update() routine if the \c BehaviorScript  	 * component holding this script instance is active.  	 */ -	virtual void update() {} +	virtual void update(duration_t delta_time) {}  	//! \}  	//! ScriptSystem calls \c init() and \c update() @@ -135,6 +138,10 @@ protected:  	//! Retrieve SaveManager reference  	SaveManager & get_save_manager() const; + +	//! Retrieve LoopTimerManager reference +	LoopTimerManager & get_loop_timer() const; +  	/**  	 * \brief Utility function to retrieve the keyboard state  	 * \see SDLContext::get_keyboard_state @@ -151,7 +158,6 @@ protected:  	 *   	 */  	bool get_key_state(Keycode key) const noexcept; -	//! \}  private:  	/** diff --git a/src/crepe/facade/DB.cpp b/src/crepe/facade/DB.cpp index 95cf606..ae2d4bc 100644 --- a/src/crepe/facade/DB.cpp +++ b/src/crepe/facade/DB.cpp @@ -21,12 +21,6 @@ DB::DB(const string & path) {  	const char * file = path.empty() ? NULL : path.c_str();  	ret = this->db->open(this->db.get(), NULL, file, NULL, libdb::DB_BTREE, DB_CREATE, 0);  	if (ret != 0) throw runtime_error(format("db->open: {}", libdb::db_strerror(ret))); - -	// create cursor -	libdb::DBC * cursor; -	ret = this->db->cursor(this->db.get(), NULL, &cursor, 0); -	if (ret != 0) throw runtime_error(format("db->cursor: {}", libdb::db_strerror(ret))); -	this->cursor = {cursor, [](libdb::DBC * cursor) { cursor->close(cursor); }};  }  libdb::DBT DB::to_thing(const string & thing) const noexcept { @@ -42,10 +36,10 @@ string DB::get(const string & key) {  	libdb::DBT db_val;  	memset(&db_val, 0, sizeof(libdb::DBT)); -	int ret = this->cursor->get(this->cursor.get(), &db_key, &db_val, DB_FIRST); +	int ret = this->db->get(this->db.get(), NULL, &db_key, &db_val, 0);  	if (ret == 0) return {static_cast<char *>(db_val.data), db_val.size}; -	string err = format("cursor->get: {}", libdb::db_strerror(ret)); +	string err = format("db->get: {}", libdb::db_strerror(ret));  	if (ret == DB_NOTFOUND) throw out_of_range(err);  	else throw runtime_error(err);  } @@ -54,7 +48,7 @@ void DB::set(const string & key, const string & value) {  	libdb::DBT db_key = this->to_thing(key);  	libdb::DBT db_val = this->to_thing(value);  	int ret = this->db->put(this->db.get(), NULL, &db_key, &db_val, 0); -	if (ret != 0) throw runtime_error(format("cursor->get: {}", libdb::db_strerror(ret))); +	if (ret != 0) throw runtime_error(format("db->get: {}", libdb::db_strerror(ret)));  }  bool DB::has(const std::string & key) { diff --git a/src/crepe/facade/DB.h b/src/crepe/facade/DB.h index 115c0f1..84cdf19 100644 --- a/src/crepe/facade/DB.h +++ b/src/crepe/facade/DB.h @@ -61,8 +61,6 @@ public:  private:  	//! RAII wrapper around \c DB struct  	std::unique_ptr<libdb::DB, std::function<void(libdb::DB *)>> db; -	//! RAII wrapper around \c DBC struct -	std::unique_ptr<libdb::DBC, std::function<void(libdb::DBC *)>> cursor;  private:  	/** diff --git a/src/crepe/manager/SaveManager.cpp b/src/crepe/manager/SaveManager.cpp index 691ea2f..f313ed2 100644 --- a/src/crepe/manager/SaveManager.cpp +++ b/src/crepe/manager/SaveManager.cpp @@ -129,9 +129,32 @@ template void SaveManager::set(const string &, const float &);  template void SaveManager::set(const string &, const double &);  template <typename T> +T SaveManager::get(const string & key) { +	return this->deserialize<T>(this->get_db().get(key)); +} +template uint8_t SaveManager::get(const string &); +template int8_t SaveManager::get(const string &); +template uint16_t SaveManager::get(const string &); +template int16_t SaveManager::get(const string &); +template uint32_t SaveManager::get(const string &); +template int32_t SaveManager::get(const string &); +template uint64_t SaveManager::get(const string &); +template int64_t SaveManager::get(const string &); +template float SaveManager::get(const string &); +template double SaveManager::get(const string &); +template string SaveManager::get(const string &); + +template <typename T>  ValueBroker<T> SaveManager::get(const string & key, const T & default_value) {  	if (!this->has(key)) this->set<T>(key, default_value); -	return this->get<T>(key); +	T value; +	return { +		[this, key](const T & target) { this->set<T>(key, target); }, +		[this, key, value]() mutable -> const T & { +			value = this->get<T>(key); +			return value; +		}, +	};  }  template ValueBroker<uint8_t> SaveManager::get(const string &, const uint8_t &);  template ValueBroker<int8_t> SaveManager::get(const string &, const int8_t &); @@ -144,27 +167,3 @@ template ValueBroker<int64_t> SaveManager::get(const string &, const int64_t &);  template ValueBroker<float> SaveManager::get(const string &, const float &);  template ValueBroker<double> SaveManager::get(const string &, const double &);  template ValueBroker<string> SaveManager::get(const string &, const string &); - -template <typename T> -ValueBroker<T> SaveManager::get(const string & key) { -	T value; -	return { -		[this, key](const T & target) { this->set<T>(key, target); }, -		[this, key, value]() mutable -> const T & { -			DB & db = this->get_db(); -			value = this->deserialize<T>(db.get(key)); -			return value; -		}, -	}; -} -template ValueBroker<uint8_t> SaveManager::get(const string &); -template ValueBroker<int8_t> SaveManager::get(const string &); -template ValueBroker<uint16_t> SaveManager::get(const string &); -template ValueBroker<int16_t> SaveManager::get(const string &); -template ValueBroker<uint32_t> SaveManager::get(const string &); -template ValueBroker<int32_t> SaveManager::get(const string &); -template ValueBroker<uint64_t> SaveManager::get(const string &); -template ValueBroker<int64_t> SaveManager::get(const string &); -template ValueBroker<float> SaveManager::get(const string &); -template ValueBroker<double> SaveManager::get(const string &); -template ValueBroker<string> SaveManager::get(const string &); diff --git a/src/crepe/manager/SaveManager.h b/src/crepe/manager/SaveManager.h index 61a978d..1e34bc0 100644 --- a/src/crepe/manager/SaveManager.h +++ b/src/crepe/manager/SaveManager.h @@ -36,17 +36,17 @@ public:  	ValueBroker<T> get(const std::string & key, const T & default_value);  	/** -	 * \brief Get a read/write reference to a value +	 * \brief Get a value directly  	 *  	 * \param key  The value key  	 * -	 * \return Read/write reference to the value +	 * \return The value  	 *  	 * \note Attempting to read this value before it is initialized (i.e. set) will result in an  	 * exception  	 */  	template <typename T> -	ValueBroker<T> get(const std::string & key); +	T get(const std::string & key);  	/**  	 * \brief Set a value directly diff --git a/src/crepe/system/InputSystem.cpp b/src/crepe/system/InputSystem.cpp index fee664c..cd6091d 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; @@ -156,7 +154,7 @@ void InputSystem::handle_non_mouse_event(const EventData & event) {  void InputSystem::handle_move(const EventData & event_data, const vec2 & mouse_pos,  							  const Camera & current_cam) {  	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) { @@ -166,20 +164,19 @@ void InputSystem::handle_move(const EventData & event_data, const vec2 & mouse_p  			= mgr.get_components_by_id<Transform>(button.game_object_id).front();  		Transform & cam_transform  			= mgr.get_components_by_id<Transform>(current_cam.game_object_id).front(); +		Metadata & metadata +			= mgr.get_components_by_id<Metadata>(button.game_object_id).front();  		bool was_hovering = button.hover;  		if (this->is_mouse_inside_button(mouse_pos, button, transform, cam_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);  			}  		}  	} @@ -188,19 +185,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,  							   const Camera & current_cam) {  	ComponentManager & mgr = this->mediator.component_manager; - +	EventManager & event_mgr = this->mediator.event_manager;  	RefVector<Button> buttons = mgr.get_components_by_type<Button>();  	Transform & cam_transform  		= mgr.get_components_by_id<Transform>(current_cam.game_object_id).front();  	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, cam_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 9ab76f6..fbcf3f6 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/crepe/system/ScriptSystem.cpp b/src/crepe/system/ScriptSystem.cpp index d6b2ca1..0605c7a 100644 --- a/src/crepe/system/ScriptSystem.cpp +++ b/src/crepe/system/ScriptSystem.cpp @@ -11,6 +11,7 @@ void ScriptSystem::update() {  	dbg_trace();  	ComponentManager & mgr = this->mediator.component_manager; +	LoopTimerManager & timer = this->mediator.loop_timer;  	RefVector<BehaviorScript> behavior_scripts = mgr.get_components_by_type<BehaviorScript>();  	for (BehaviorScript & behavior_script : behavior_scripts) { @@ -23,6 +24,8 @@ void ScriptSystem::update() {  			script->init();  			script->initialized = true;  		} -		script->update(); + +		duration_t delta_time = timer.get_scaled_fixed_delta_time(); +		script->update(delta_time);  	}  } diff --git a/src/doc/feature/proxy.dox b/src/doc/feature/proxy.dox new file mode 100644 index 0000000..66bbd2f --- /dev/null +++ b/src/doc/feature/proxy.dox @@ -0,0 +1,43 @@ +// vim:ft=doxygen +namespace crepe { +/** + +\defgroup feature_proxy Proxy utility +\ingroup feature +\brief Use ValueBroker as if it were a regular variable + +Proxy provides operators that allow you to use a ValueBroker instance as if it +were a regular variable. Proxy implements a constructor that allows it to be +used as a substitute return type for any function that returns ValueBroker. + +\see ValueBroker +\see Proxy + +\par Example + +```cpp +#include <crepe/util/Proxy.h> +#include <crepe/ValueBroker.h> + +int calculation(int value) { +	return 3 * value; +} + +void anywhere() { +	crepe::ValueBroker<int> foo_handle; +	crepe::Proxy foo = foo_handle; + +	// implicitly calls .set() +	foo += 10; + +	// implicitly calls .get() +	int out = calculation(foo); + +	// explicitly cast (also calls .get()) +	int casted = int(foo); +} + +``` + +*/ +} diff --git a/src/doc/feature/savemgr.dox b/src/doc/feature/savemgr.dox new file mode 100644 index 0000000..6aeab03 --- /dev/null +++ b/src/doc/feature/savemgr.dox @@ -0,0 +1,80 @@ +// vim:ft=doxygen +namespace crepe { +/** + +\defgroup feature_savemgr Save data +\ingroup feature +\brief Functions to persistently store and retrieve arbitrary values + +The SaveManager may be used to persistently store game state such as player +progress, statistics, achievements, etc. It works like a key-value store, where +the key is a string and the value is an arbitrary type. + +SaveManager implements the following: + +- Storage and retrieval of primitive types and strings. +- Automatic initialization of the database using default values. +- The underlying database format is journaled, which reduces the likelihood of +	players losing save data when an unexpected crash occurs while the SaveManager +	is writing to disk. + +\see SaveManager + +\par Example + +The SaveManager instance reference may be retrieved by calling \c +get_save_manager(). This function is available--- + +- Within (derivatives of) Script + +- \todo Within (derivatives of) Scene + +- \todo As a public member function of LoopManager + +```cpp +// Retrieve save manager +crepe::SaveManager & save_manager = get_save_manager(); +``` + +SaveManager may be used *explicitly*, using the \ref SaveManager::set "set()", +\ref SaveManager::get "get()" and  \ref SaveManager::has "has()" methods: +```cpp +// Check if the key "foo" exists, and initialize it to 3 if it doesn't +if (!save_manager.has("foo")) +	save_manager.set<int>("foo", 3); +// Get value of key "foo" +int foo = save_manager.get<int>("foo"); + +// ~~~ arbitrary game code ~~~ +foo += 10; +// ~~~ arbitrary game code ~~~ + +// Save "foo" back to database +save_manager.set<int>("foo", foo); +``` + +Alternatively, SaveManager::get may be called with a default value as second +parameter. This changes its return type to ValueBroker, which acts as a +read/write handle to the specific key requested, and remembers the key and its +value type for you: +```cpp +// Get a read/write handle to the value stored in key "foo", and initialize it +// to 3 if it doesn't exist yet +ValueBroker foo_handle = save_manager.get<int>("foo", 3); +int foo = foo_handle.get(); + +// ~~~ arbitrary game code ~~~ +foo += 10; +// ~~~ arbitrary game code ~~~ + +// Save back to database +foo_handle.set(foo); +``` + +To further simplify game code, the return value of SaveManager::get may be +implicitly cast to Proxy instead of ValueBroker. This allows the database value +to be used as if it were a regular variable. This usage is detailed separately +in \"\ref feature_proxy\". + +*/ +} diff --git a/src/example/game.cpp b/src/example/game.cpp index 22effd2..3975650 100644 --- a/src/example/game.cpp +++ b/src/example/game.cpp @@ -86,7 +86,7 @@ class MyScript1 : public Script {  		subscribe<KeyPressEvent>(  			[this](const KeyPressEvent & ev) -> bool { return this->keypressed(ev); });  	} -	void update() { +	void update(duration_t) {  		Rigidbody & tf = this->get_component<Rigidbody>();  		Log::logf("linear_velocity.x {}", tf.data.linear_velocity.x);  		Log::logf("linear_velocity.y {}", tf.data.linear_velocity.y); diff --git a/src/test/CollisionTest.cpp b/src/test/CollisionTest.cpp index ff9e7cc..baa95c1 100644 --- a/src/test/CollisionTest.cpp +++ b/src/test/CollisionTest.cpp @@ -54,6 +54,7 @@ public:  	ComponentManager mgr{m};  	CollisionSystem collision_sys{m};  	ScriptSystem script_sys{m}; +	LoopTimerManager loop_timer{m};  	GameObject world = mgr.new_object("world", "", {50, 50});  	GameObject game_object1 = mgr.new_object("object1", "", {50, 50}); diff --git a/src/test/DBTest.cpp b/src/test/DBTest.cpp index 99dedff..7f2c339 100644 --- a/src/test/DBTest.cpp +++ b/src/test/DBTest.cpp @@ -27,3 +27,11 @@ TEST_F(DBTest, Has) {  	db.set("foo", "bar");  	EXPECT_EQ(db.has("foo"), true);  } + +TEST_F(DBTest, MultipleKeys) { +	db.set("foo", "foo"); +	db.set("bar", "bar"); + +	EXPECT_EQ(db.get("foo"), "foo"); +	EXPECT_EQ(db.get("bar"), "bar"); +} diff --git a/src/test/InputTest.cpp b/src/test/InputTest.cpp index 1d29cee..25a1eeb 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 @@ -215,8 +214,13 @@ 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{10, 10}, 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;  	this->simulate_mouse_click(999, 999, SDL_BUTTON_LEFT); @@ -232,8 +236,13 @@ TEST_F(InputTest, testButtonClick) {  TEST_F(InputTest, buttonPositionCamera) {  	GameObject button_obj = mgr.new_object("body", "person", vec2{50, 50}, 0, 1);  	bool button_clicked = false; -	std::function<void()> on_click = [&]() { button_clicked = true; }; -	auto & button = button_obj.add_component<Button>(vec2{10, 10}, 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{10, 10}, vec2{0, 0}); +  	button.world_space = false;  	bool hover = false;  	button.active = true; @@ -250,8 +259,12 @@ TEST_F(InputTest, buttonPositionCamera) {  TEST_F(InputTest, buttonPositionWorld) {  	GameObject button_obj = mgr.new_object("body", "person", vec2{50, 50}, 0, 1);  	bool button_clicked = false; -	std::function<void()> on_click = [&]() { button_clicked = true; }; -	auto & button = button_obj.add_component<Button>(vec2{10, 10}, 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{10, 10}, vec2{0, 0});  	button.world_space = true;  	bool hover = false;  	button.active = true; @@ -267,25 +280,19 @@ TEST_F(InputTest, buttonPositionWorld) {  }  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); @@ -299,4 +306,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);  } diff --git a/src/test/SaveManagerTest.cpp b/src/test/SaveManagerTest.cpp index e9b0c29..7609e69 100644 --- a/src/test/SaveManagerTest.cpp +++ b/src/test/SaveManagerTest.cpp @@ -27,8 +27,8 @@ TEST_F(SaveManagerTest, ReadWrite) {  	mgr.set<string>("foo", "bar");  	ASSERT_TRUE(mgr.has("foo")); -	ValueBroker value = mgr.get<string>("foo"); -	EXPECT_EQ(value.get(), "bar"); +	string value = mgr.get<string>("foo"); +	EXPECT_EQ(value, "bar");  }  TEST_F(SaveManagerTest, DefaultValue) { @@ -36,5 +36,16 @@ TEST_F(SaveManagerTest, DefaultValue) {  	ASSERT_EQ(value.get(), 3);  	value.set(5); -	ASSERT_EQ(value.get(), 5); +	EXPECT_EQ(value.get(), 5); +} + +TEST_F(SaveManagerTest, MultipleKeys) { +	ValueBroker foo = mgr.get<int>("foo", 1); +	ValueBroker bar = mgr.get<int>("bar", 2); + +	EXPECT_EQ(foo.get(), 1); +	EXPECT_EQ(bar.get(), 2); + +	EXPECT_EQ(mgr.get<int>("foo"), 1); +	EXPECT_EQ(mgr.get<int>("bar"), 2);  } diff --git a/src/test/ScriptTest.cpp b/src/test/ScriptTest.cpp index acdae70..846e398 100644 --- a/src/test/ScriptTest.cpp +++ b/src/test/ScriptTest.cpp @@ -28,7 +28,7 @@ void ScriptTest::SetUp() {  TEST_F(ScriptTest, Default) {  	MyScript & script = this->script;  	EXPECT_CALL(script, init()).Times(0); -	EXPECT_CALL(script, update()).Times(0); +	EXPECT_CALL(script, update(_)).Times(0);  }  TEST_F(ScriptTest, UpdateOnce) { @@ -38,7 +38,7 @@ TEST_F(ScriptTest, UpdateOnce) {  		InSequence seq;  		EXPECT_CALL(script, init()).Times(1); -		EXPECT_CALL(script, update()).Times(1); +		EXPECT_CALL(script, update(_)).Times(1);  		system.update();  	} @@ -46,7 +46,7 @@ TEST_F(ScriptTest, UpdateOnce) {  		InSequence seq;  		EXPECT_CALL(script, init()).Times(0); -		EXPECT_CALL(script, update()).Times(1); +		EXPECT_CALL(script, update(_)).Times(1);  		system.update();  	}  } @@ -59,7 +59,7 @@ TEST_F(ScriptTest, UpdateInactive) {  		InSequence seq;  		EXPECT_CALL(script, init()).Times(0); -		EXPECT_CALL(script, update()).Times(0); +		EXPECT_CALL(script, update(_)).Times(0);  		behaviorscript.active = false;  		system.update();  	} @@ -68,8 +68,20 @@ TEST_F(ScriptTest, UpdateInactive) {  		InSequence seq;  		EXPECT_CALL(script, init()).Times(1); -		EXPECT_CALL(script, update()).Times(1); +		EXPECT_CALL(script, update(_)).Times(1);  		behaviorscript.active = true;  		system.update();  	}  } + +TEST_F(ScriptTest, SaveManager) { +	MyScript & script = this->script; + +	EXPECT_EQ(&script.get_save_manager(), &this->save_manager); +} + +TEST_F(ScriptTest, LoopTimerManager) { +	MyScript & script = this->script; + +	EXPECT_EQ(&script.get_loop_timer(), &this->loop_timer); +} diff --git a/src/test/ScriptTest.h b/src/test/ScriptTest.h index 31fa7c9..f3dbda4 100644 --- a/src/test/ScriptTest.h +++ b/src/test/ScriptTest.h @@ -7,7 +7,10 @@  #include <crepe/api/Script.h>  #include <crepe/manager/ComponentManager.h>  #include <crepe/manager/EventManager.h> +#include <crepe/manager/LoopTimerManager.h> +#include <crepe/manager/SaveManager.h>  #include <crepe/system/ScriptSystem.h> +  class ScriptTest : public testing::Test {  protected:  	crepe::Mediator mediator; @@ -17,6 +20,8 @@ public:  	crepe::ComponentManager component_manager{mediator};  	crepe::ScriptSystem system{mediator};  	crepe::EventManager event_mgr{mediator}; +	crepe::LoopTimerManager loop_timer{mediator}; +	crepe::SaveManager save_manager{mediator};  	crepe::GameObject entity = component_manager.new_object(OBJ_NAME);  	class MyScript : public crepe::Script { @@ -24,7 +29,7 @@ public:  	public:  		MOCK_METHOD(void, init, (), (override)); -		MOCK_METHOD(void, update, (), (override)); +		MOCK_METHOD(void, update, (crepe::duration_t), (override));  	};  	crepe::OptionalRef<crepe::BehaviorScript> behaviorscript; diff --git a/src/test/main.cpp b/src/test/main.cpp index ed2aed5..0e1bc75 100644 --- a/src/test/main.cpp +++ b/src/test/main.cpp @@ -1,6 +1,7 @@ -#include <crepe/api/Config.h>  #include <gtest/gtest.h> +#include <crepe/api/Config.h> +  using namespace crepe;  using namespace testing;  |