139 lines
5.5 KiB
C++
139 lines
5.5 KiB
C++
#include "property.hpp"
|
|
|
|
#include <cppbase/logger.hpp>
|
|
|
|
#include <ikarus/errors.hpp>
|
|
#include <ikarus/objects/properties/property.h>
|
|
#include <ikarus/objects/properties/property_scope.hpp>
|
|
#include <ikarus/objects/properties/property_type.h>
|
|
#include <ikarus/objects/util.hpp>
|
|
#include <ikarus/persistence/project.hpp>
|
|
#include <ikarus/values/value.hpp>
|
|
|
|
IkarusProperty::IkarusProperty(IkarusProject * project, IkarusId id, Data data):
|
|
IkarusObject{project, id},
|
|
data{data} {}
|
|
|
|
IKA_API void ikarus_property_delete(IkarusProperty * property, IkarusErrorData * error_out) {
|
|
IKARUS_FAIL_IF_NULL(property, );
|
|
IKARUS_FAIL_IF_OBJECT_MISSING(property, );
|
|
|
|
IKARUS_TRYRV_OR_FAIL(
|
|
,
|
|
"unable to delete property: {}",
|
|
IkarusErrorInfo_Database_QueryFailed,
|
|
property->project->db->execute("DELETE FROM `objects` WHERE `id` = ?", property->id)
|
|
);
|
|
|
|
property->project->uncache(property);
|
|
}
|
|
|
|
IkarusProject * ikarus_property_get_project(IkarusProperty const * property, IkarusErrorData * error_out) {
|
|
return ikarus::util::object_get_project(property, error_out);
|
|
}
|
|
|
|
char const * ikarus_property_get_name(IkarusProperty const * property, IkarusErrorData * error_out) {
|
|
return ikarus::util::object_get_name(property, error_out);
|
|
}
|
|
|
|
void ikarus_property_set_name(IkarusProperty * property, char const * name, IkarusErrorData * error_out) {
|
|
ikarus::util::object_set_name(property, name, error_out);
|
|
}
|
|
|
|
IkarusPropertyType ikarus_property_get_type(IkarusProperty const * property, IkarusErrorData * error_out) {
|
|
IKARUS_FAIL_IF_NULL(property, IkarusPropertyType_Toggle);
|
|
IKARUS_FAIL_IF_OBJECT_MISSING(property, IkarusPropertyType_Toggle);
|
|
|
|
IKARUS_VTRYRV_OR_FAIL(
|
|
auto const ret,
|
|
IkarusPropertyType_Toggle,
|
|
"unable to fetch property type from database: {}",
|
|
IkarusErrorInfo_Database_QueryFailed,
|
|
property->project->db->query_one<int>("SELECT `type` FROM `properties` WHERE `id` = ?", property->id)
|
|
);
|
|
|
|
return static_cast<IkarusPropertyType>(ret);
|
|
}
|
|
|
|
IkarusPropertyScope const * ikarus_property_get_scope(IkarusProperty const * property, IkarusErrorData * error_out) {
|
|
IKARUS_FAIL_IF_NULL(property, nullptr);
|
|
IKARUS_FAIL_IF_OBJECT_MISSING(property, nullptr);
|
|
|
|
IKARUS_VTRYRV_OR_FAIL(
|
|
auto const source,
|
|
nullptr,
|
|
"unable to fetch property source from database: {}",
|
|
IkarusErrorInfo_Database_QueryFailed,
|
|
property->project->db->query_one<IkarusId>("SELECT `source` FROM `properties` WHERE `id` = ?", property->id)
|
|
);
|
|
|
|
switch (ikarus_id_get_object_type(source)) {
|
|
case IkarusObjectType_Blueprint: return new IkarusPropertyScope{property->project->get_blueprint(source)};
|
|
case IkarusObjectType_Entity: return new IkarusPropertyScope{property->project->get_entity(source)};
|
|
default:
|
|
IKARUS_FAIL(
|
|
nullptr,
|
|
fmt::format("invalid property source type: {}", ikarus_object_type_to_string(ikarus_id_get_object_type(source))),
|
|
IkarusErrorInfo_LibIkarus_InvalidState
|
|
);
|
|
}
|
|
}
|
|
|
|
IkarusValue * ikarus_property_get_default_value(IkarusProperty const * property, IkarusErrorData * error_out) {
|
|
IKARUS_FAIL_IF_NULL(property, nullptr);
|
|
IKARUS_FAIL_IF_OBJECT_MISSING(property, nullptr);
|
|
|
|
return fetch_value_from_db(property->project, error_out, "SELECT `default_value` FROM `properties` WHERE `id` = ?", property->id);
|
|
}
|
|
|
|
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,
|
|
IkarusErrorData * error_out
|
|
) {
|
|
IKARUS_FAIL_IF_NULL(property, );
|
|
IKARUS_FAIL_IF_OBJECT_MISSING(property, );
|
|
|
|
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->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,
|
|
IkarusErrorData * error_out
|
|
) {
|
|
IKARUS_FAIL_IF_NULL(property, );
|
|
IKARUS_FAIL_IF_OBJECT_MISSING(property, );
|
|
|
|
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->data
|
|
);
|
|
}
|
|
|
|
// No existence checks here for performance reasons. All methods on IkarusObject perform this check anyway.
|
|
|
|
IkarusObject * ikarus_property_to_object(IkarusProperty * property) {
|
|
return static_cast<IkarusObject *>(property);
|
|
}
|
|
|
|
IkarusObject const * ikarus_property_to_object_const(IkarusProperty const * property) {
|
|
return static_cast<IkarusObject const *>(property);
|
|
}
|