diff --git a/include/ikarus/objects/properties/property.h b/include/ikarus/objects/properties/property.h index 1da35e6..a6ebad8 100644 --- a/include/ikarus/objects/properties/property.h +++ b/include/ikarus/objects/properties/property.h @@ -82,24 +82,24 @@ IKA_API struct IkarusPropertySource const * ikarus_property_get_source(IkarusPro /// \param property The property to visit. /// \pre \li Must not be null. /// \pre \li Must exist. -/// \param toggle_property The function to call if the property is a toggle property. Skipped if null. -/// \param number_property The function to call if the property is a number property. Skipped if null. -/// \param text_property The function to call if the property is a text property. Skipped if null. +/// \param toggle_property_visitor The function to call if the property is a toggle property. Skipped if null. +/// \param number_property_visitor The function to call if the property is a number property. Skipped if null. +/// \param text_property_visitor The function to call if the property is a text property. Skipped if null. /// \param data The data to pass to the functions. IKA_API void ikarus_property_visit( IkarusProperty * property, - void (*toggle_property)(struct IkarusToggleProperty *, void *), - void (*number_property)(struct IkarusNumberProperty *, void *), - void (*text_property)(struct IkarusTextProperty *, void *), + void (*toggle_property_visitor)(struct IkarusToggleProperty *, void *), + void (*number_property_visitor)(struct IkarusNumberProperty *, void *), + void (*text_property_visitor)(struct IkarusTextProperty *, void *), void * data ); /// \see ikarus_property_visit IKA_API void ikarus_property_visit_const( IkarusProperty const * property, - void (*toggle_property)(struct IkarusToggleProperty const *, void *), - void (*number_property)(struct IkarusNumberProperty const *, void *), - void (*text_property)(struct IkarusTextProperty const *, void *), + void (*toggle_property_visitor)(struct IkarusToggleProperty const *, void *), + void (*number_property_visitor)(struct IkarusNumberProperty const *, void *), + void (*text_property_visitor)(struct IkarusTextProperty const *, void *), void * data ); diff --git a/src/objects/properties/property.cpp b/src/objects/properties/property.cpp index 3afcf66..cda8434 100644 --- a/src/objects/properties/property.cpp +++ b/src/objects/properties/property.cpp @@ -4,13 +4,23 @@ #include +#include #include #include +#include IkarusProperty::IkarusProperty(IkarusProject * project, IkarusId id, Data data): IkarusObject{project, id}, _data{data} {} +IkarusProperty::Data& IkarusProperty::get_data() { + return _data; +} + +IkarusProperty::Data const& IkarusProperty::get_data() const { + return _data; +} + cppbase::Result IkarusProperty::get_property_type( IkarusProject * project, IkarusId id ) { @@ -18,7 +28,21 @@ cppbase::Result IkarusProperty: LOG_VERBOSE("project={};property={}", project->get_path().c_str(), id); - VTRY(auto const type, project->get_db()->query_one("SELECT `type` FROM `objects` WHERE `id` = ?", id)); + auto * ctx = project->get_function_context(); + + VTRY( + auto const type, + project->get_db() + ->query_one("SELECT `type` FROM `properties` WHERE `id` = ?", id) + .on_error([ctx](auto const& err) { + ctx->set_error( + fmt::format("failed to fetch unboxed property type: {}", err), + true, + IkarusErrorInfo_Source_SubSystem, + IkarusErrorInfo_Type_SubSystem_Database + ); + }) + ); return cppbase::ok(static_cast(type)); } @@ -53,5 +77,88 @@ IKA_API void ikarus_property_delete(IkarusProperty * property) { } IkarusPropertyType ikarus_property_get_type(IkarusProperty const * property) { - LOG_DEBUG("fetching property type"); + LOG_VERBOSE("fetching property type"); + + return IkarusProperty::get_property_type(property->get_project(), property->get_id()) + .unwrap_value_or(IkarusPropertyType_Toggle); +} + +IkarusPropertySource const * ikarus_property_get_source(IkarusProperty const * property) { + LOG_VERBOSE("fetching property source"); + + LOG_VERBOSE("project={};property={}", property->get_project()->get_path().c_str(), property->get_id()); + + auto * ctx = property->get_project()->get_function_context(); + + VTRY( + auto const source, + property->get_project() + ->get_db() + ->query_one("SELECT `source` FROM `properties` WHERE `id` = ?", property->get_id()) + .on_error([ctx](auto const& err) { + ctx->set_error( + fmt::format("failed to fetch property's source: {}", err), + true, + IkarusErrorInfo_Source_SubSystem, + IkarusErrorInfo_Type_SubSystem_Database + ); + }) + ); + + switch (ikarus_id_get_object_type(source)) { + case IkarusObjectType_Blueprint: return new IkarusPropertySource{property->get_project()->get_blueprint(source)}; + case IkarusObjectType_Entity: return new IkarusPropertySource{property->get_project()->get_entity(source)}; + default: { + ctx->set_error( + fmt::format("PropertySource is neither blueprint nor entity"), + true, + IkarusErrorInfo_Source_LibIkarus, + IkarusErrorInfo_Type_LibIkarus_InvalidState + ); + + return nullptr; + } + } +} + +void ikarus_property_visit( + IkarusProperty * property, + void (*toggle_property_visitor)(struct IkarusToggleProperty *, void *), + void (*number_property_visitor)(struct IkarusNumberProperty *, void *), + void (*text_property_visitor)(struct IkarusTextProperty *, void *), + void * data +) { + std::visit( + cppbase::overloaded{ + [toggle_property_visitor, data](IkarusToggleProperty * property) { toggle_property_visitor(property, data); }, + [number_property_visitor, data](IkarusNumberProperty * property) { number_property_visitor(property, data); }, + [text_property_visitor, data](IkarusTextProperty * property) { text_property_visitor(property, data); } + }, + property->get_data() + ); +} + +void ikarus_property_visit_const( + IkarusProperty const * property, + void (*toggle_property_visitor)(struct IkarusToggleProperty const *, void *), + void (*number_property_visitor)(struct IkarusNumberProperty const *, void *), + void (*text_property_visitor)(struct IkarusTextProperty const *, void *), + void * data +) { + std::visit( + cppbase::overloaded{ + [toggle_property_visitor, data](IkarusToggleProperty const * property) { toggle_property_visitor(property, data); }, + [number_property_visitor, data](IkarusNumberProperty const * property) { number_property_visitor(property, data); }, + [text_property_visitor, data](IkarusTextProperty const * property) { text_property_visitor(property, data); } + }, + property->get_data() + ); +} + +IkarusObject * ikarus_property_to_object(IkarusProperty * property) { + return static_cast(property); +} + +IkarusObject const * ikarus_property_to_object_const(IkarusProperty const * property) { + return static_cast(property); } diff --git a/src/objects/properties/property.hpp b/src/objects/properties/property.hpp index b11a8ff..6acd377 100644 --- a/src/objects/properties/property.hpp +++ b/src/objects/properties/property.hpp @@ -31,6 +31,10 @@ public: ~IkarusProperty() override = default; +public: + [[nodiscard]] Data& get_data(); + [[nodiscard]] Data const& get_data() const; + private: Data _data; };