From 3a23e41255af0de3c5c7f5d9df981c8b205e291f Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Fri, 13 Dec 2024 17:42:34 +0100 Subject: add timer functionality to script --- src/crepe/api/Script.cpp | 2 ++ src/crepe/api/Script.h | 12 ++++++++++++ src/crepe/system/ScriptSystem.cpp | 5 ++++- 3 files changed, 18 insertions(+), 1 deletion(-) (limited to 'src/crepe') diff --git a/src/crepe/api/Script.cpp b/src/crepe/api/Script.cpp index 753a9e3..50edea0 100644 --- a/src/crepe/api/Script.cpp +++ b/src/crepe/api/Script.cpp @@ -25,3 +25,5 @@ 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; } diff --git a/src/crepe/api/Script.h b/src/crepe/api/Script.h index 668e5d1..3569b4a 100644 --- a/src/crepe/api/Script.h +++ b/src/crepe/api/Script.h @@ -2,6 +2,7 @@ #include +#include "../manager/LoopTimerManager.h" #include "../manager/EventManager.h" #include "../manager/Mediator.h" #include "../system/CollisionSystem.h" @@ -46,9 +47,17 @@ 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(duration_t delta_time) { return this->update(); } + /** + * \brief Fallback script update function (empty by default) + * + * Allows the game programmer to ignore parameters passed to \c update() + */ virtual void update() {} //! \} @@ -135,6 +144,9 @@ protected: //! Retrieve SaveManager reference SaveManager & get_save_manager() const; + //! Retrieve LoopTimerManager reference + LoopTimerManager & get_loop_timer() const; + //! \} private: diff --git a/src/crepe/system/ScriptSystem.cpp b/src/crepe/system/ScriptSystem.cpp index d6b2ca1..4afd2ba 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 behavior_scripts = mgr.get_components_by_type(); 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_delta_time(); + script->update(delta_time); } } -- cgit v1.2.3 From ae80ecde90ea6ab3305deed899bbec1560b93a6f Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Fri, 13 Dec 2024 18:05:56 +0100 Subject: `make format` --- src/crepe/api/Script.h | 2 +- src/test/ScriptTest.cpp | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'src/crepe') diff --git a/src/crepe/api/Script.h b/src/crepe/api/Script.h index 3569b4a..1429108 100644 --- a/src/crepe/api/Script.h +++ b/src/crepe/api/Script.h @@ -2,8 +2,8 @@ #include -#include "../manager/LoopTimerManager.h" #include "../manager/EventManager.h" +#include "../manager/LoopTimerManager.h" #include "../manager/Mediator.h" #include "../system/CollisionSystem.h" #include "../types.h" diff --git a/src/test/ScriptTest.cpp b/src/test/ScriptTest.cpp index 2aee0fd..499be5a 100644 --- a/src/test/ScriptTest.cpp +++ b/src/test/ScriptTest.cpp @@ -85,4 +85,3 @@ TEST_F(ScriptTest, LoopTimerManager) { EXPECT_EQ(&script.get_loop_timer(), &this->loop_timer); } - -- cgit v1.2.3 From fa0d298afafdc81d00164765903161205cf09a7e Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Sat, 14 Dec 2024 16:24:08 +0100 Subject: move DB fix from `loek/doxygen` to `loek/savemgr` --- src/crepe/facade/DB.cpp | 13 ++----- src/crepe/facade/DB.h | 2 - src/crepe/manager/SaveManager.cpp | 49 ++++++++++++------------ src/crepe/manager/SaveManager.h | 6 +-- src/doc/feature/proxy.dox | 43 +++++++++++++++++++++ src/doc/feature/savemgr.dox | 80 +++++++++++++++++++++++++++++++++++++++ src/test/DBTest.cpp | 9 +++++ src/test/SaveManagerTest.cpp | 17 +++++++-- src/test/main.cpp | 3 +- 9 files changed, 179 insertions(+), 43 deletions(-) create mode 100644 src/doc/feature/proxy.dox create mode 100644 src/doc/feature/savemgr.dox (limited to 'src/crepe') diff --git a/src/crepe/facade/DB.cpp b/src/crepe/facade/DB.cpp index 95cf606..2232a21 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(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) { @@ -65,3 +59,4 @@ bool DB::has(const std::string & key) { } return true; } + 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> db; - //! RAII wrapper around \c DBC struct - std::unique_ptr> 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 @@ -128,10 +128,33 @@ template void SaveManager::set(const string &, const int64_t &); template void SaveManager::set(const string &, const float &); template void SaveManager::set(const string &, const double &); +template +T SaveManager::get(const string & key) { + return this->deserialize(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 ValueBroker SaveManager::get(const string & key, const T & default_value) { if (!this->has(key)) this->set(key, default_value); - return this->get(key); + T value; + return { + [this, key](const T & target) { this->set(key, target); }, + [this, key, value]() mutable -> const T & { + value = this->get(key); + return value; + }, + }; } template ValueBroker SaveManager::get(const string &, const uint8_t &); template ValueBroker SaveManager::get(const string &, const int8_t &); @@ -144,27 +167,3 @@ template ValueBroker SaveManager::get(const string &, const int64_t &); template ValueBroker SaveManager::get(const string &, const float &); template ValueBroker SaveManager::get(const string &, const double &); template ValueBroker SaveManager::get(const string &, const string &); - -template -ValueBroker SaveManager::get(const string & key) { - T value; - return { - [this, key](const T & target) { this->set(key, target); }, - [this, key, value]() mutable -> const T & { - DB & db = this->get_db(); - value = this->deserialize(db.get(key)); - return value; - }, - }; -} -template ValueBroker SaveManager::get(const string &); -template ValueBroker SaveManager::get(const string &); -template ValueBroker SaveManager::get(const string &); -template ValueBroker SaveManager::get(const string &); -template ValueBroker SaveManager::get(const string &); -template ValueBroker SaveManager::get(const string &); -template ValueBroker SaveManager::get(const string &); -template ValueBroker SaveManager::get(const string &); -template ValueBroker SaveManager::get(const string &); -template ValueBroker SaveManager::get(const string &); -template ValueBroker 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 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 - ValueBroker get(const std::string & key); + T get(const std::string & key); /** * \brief Set a value directly 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 +#include + +int calculation(int value) { + return 3 * value; +} + +void anywhere() { + crepe::ValueBroker 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("foo", 3); +// Get value of key "foo" +int foo = save_manager.get("foo"); + +// ~~~ arbitrary game code ~~~ +foo += 10; +// ~~~ arbitrary game code ~~~ + +// Save "foo" back to database +save_manager.set("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("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/test/DBTest.cpp b/src/test/DBTest.cpp index 99dedff..0c98e10 100644 --- a/src/test/DBTest.cpp +++ b/src/test/DBTest.cpp @@ -27,3 +27,12 @@ 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/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("foo", "bar"); ASSERT_TRUE(mgr.has("foo")); - ValueBroker value = mgr.get("foo"); - EXPECT_EQ(value.get(), "bar"); + string value = mgr.get("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("foo", 1); + ValueBroker bar = mgr.get("bar", 2); + + EXPECT_EQ(foo.get(), 1); + EXPECT_EQ(bar.get(), 2); + + EXPECT_EQ(mgr.get("foo"), 1); + EXPECT_EQ(mgr.get("bar"), 2); } 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 #include +#include + using namespace crepe; using namespace testing; -- cgit v1.2.3 From 154ed5353ef18eb46cc31744e8bf1bc54afd5acc Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Sat, 14 Dec 2024 16:24:25 +0100 Subject: `make format` --- src/crepe/facade/DB.cpp | 1 - src/test/DBTest.cpp | 1 - 2 files changed, 2 deletions(-) (limited to 'src/crepe') diff --git a/src/crepe/facade/DB.cpp b/src/crepe/facade/DB.cpp index 2232a21..ae2d4bc 100644 --- a/src/crepe/facade/DB.cpp +++ b/src/crepe/facade/DB.cpp @@ -59,4 +59,3 @@ bool DB::has(const std::string & key) { } return true; } - diff --git a/src/test/DBTest.cpp b/src/test/DBTest.cpp index 0c98e10..7f2c339 100644 --- a/src/test/DBTest.cpp +++ b/src/test/DBTest.cpp @@ -35,4 +35,3 @@ TEST_F(DBTest, MultipleKeys) { EXPECT_EQ(db.get("foo"), "foo"); EXPECT_EQ(db.get("bar"), "bar"); } - -- cgit v1.2.3 From c4c896c2995f2b74fca322736aa944b28b14a1f6 Mon Sep 17 00:00:00 2001 From: WBoerenkamps Date: Tue, 17 Dec 2024 09:29:47 +0100 Subject: start --- src/crepe/api/Button.h | 12 +++++++++++- src/crepe/api/Event.h | 9 --------- 2 files changed, 11 insertions(+), 10 deletions(-) (limited to 'src/crepe') diff --git a/src/crepe/api/Button.h b/src/crepe/api/Button.h index 08f5dec..e97f884 100644 --- a/src/crepe/api/Button.h +++ b/src/crepe/api/Button.h @@ -3,9 +3,19 @@ #include #include "UIObject.h" - +#include "Event.h" +#include "Metadata.h" namespace crepe { +/** + * \brief Event triggered when a button is pressed + * + */ +class ButtonPressEvent : public Event{ + public: + + +} //! Represents a clickable UI button, derived from the UiObject class. class Button : public UIObject { public: diff --git a/src/crepe/api/Event.h b/src/crepe/api/Event.h index 73bf461..b0dd931 100644 --- a/src/crepe/api/Event.h +++ b/src/crepe/api/Event.h @@ -94,15 +94,6 @@ public: float scroll_delta = 0; }; -/** - * \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. */ -- cgit v1.2.3 From eb9c76082d7d0ee0c3e55cb8eadfa5f8978bd8f2 Mon Sep 17 00:00:00 2001 From: WBoerenkamps Date: Tue, 17 Dec 2024 20:12:30 +0100 Subject: button improvements --- src/crepe/api/Button.cpp | 6 ++-- src/crepe/api/Button.h | 50 ++++++++-------------------------- src/crepe/api/Event.h | 3 +- src/crepe/system/InputSystem.cpp | 26 +++++++++--------- src/crepe/system/InputSystem.h | 22 +++++++++++++++ src/test/InputTest.cpp | 59 ++++++++++++++++++++++++++-------------- 6 files changed, 89 insertions(+), 77 deletions(-) (limited to 'src/crepe') 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 & 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 e97f884..5d4156b 100644 --- a/src/crepe/api/Button.h +++ b/src/crepe/api/Button.h @@ -5,18 +5,21 @@ #include "UIObject.h" #include "Event.h" #include "Metadata.h" + namespace crepe { /** - * \brief Event triggered when a button is pressed + * \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**: Triggered when the surface is clicked with the mouse. Contains GameObject metadata. + * - **MouseEnterEvent**: Triggered when the mouse enters the button area. Contains GameObject metadata. + * - **MouseExitEvent**: Triggered when the mouse leaves the button area. Contains GameObject metadata. + * \see EventManager * */ -class ButtonPressEvent : public Event{ - public: - - -} -//! Represents a clickable UI button, derived from the UiObject class. class Button : public UIObject { public: /** @@ -25,43 +28,14 @@ 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 & 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 on_click = nullptr; - - /** - * \brief Callback function to be executed when the mouse enters the button's boundaries. - * - * This function is triggered when the mouse cursor moves over the button, allowing - * custom actions like visual effects, highlighting, or sound effects. - */ - std::function 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 on_mouse_exit = nullptr; + Button(game_object_id_t id, const vec2 & dimensions, const vec2 & offset); 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 b0dd931..a03bb54 100644 --- a/src/crepe/api/Event.h +++ b/src/crepe/api/Event.h @@ -3,9 +3,10 @@ #include -#include "api/KeyCodes.h" #include "types.h" +#include "api/KeyCodes.h" + namespace crepe { /** diff --git a/src/crepe/system/InputSystem.cpp b/src/crepe/system/InputSystem.cpp index fca540f..5d1537d 100644 --- a/src/crepe/system/InputSystem.cpp +++ b/src/crepe/system/InputSystem.cpp @@ -155,28 +155,27 @@ 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