finalise interface & documentation

Signed-off-by: Folling <mail@folling.io>
This commit is contained in:
folling 2023-11-06 13:14:39 +01:00 committed by Folling
parent c5157bd849
commit 52580a4382
Signed by: folling
SSH key fingerprint: SHA256:S9qEx5WCFFLK49tE/LKnKuJYM5sw+++Dn6qJbbyxnCY
56 changed files with 2074 additions and 780 deletions

View file

@ -1,23 +1,210 @@
#pragma once
/// \file blueprint.h
/// \author Folling <mail@folling.io>
/// \author Folling <folling@ikarus.world>
#include <ikarus/id.h>
#include <ikarus/macros.h>
#include <ikarus/stdtypes.h>
/// \defgroup blueprints Blueprints
/// \brief Blueprints are templates for entities.
/// @{
IKARUS_BEGIN_HEADER
/// \brief A blueprint object.
/// \details A blueprint is a collection of properties which can be linked to entities.
/// Each entity the blueprint is linked to will have values for the blueprints properties.
struct IkarusBlueprint {
/// \private \brief The id of the blueprint.
IkarusId id;
};
/// Each entity the blueprint is linked to will have values for the blueprints properties.q
struct IkarusBlueprint;
/// \brief Creates a blueprint.
/// \param project The project the blueprint is part of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param parent The parent folder of the blueprint.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param position The position of the blueprint in the parent folder. \see #FolderPosition
/// \pre \li Must be within bounds for the parent folder.
/// \param name The name of the blueprint.
/// \pre \li Must not be null.
/// \pre \li Must not be empty.
/// \return The created blueprint or null if an error occurs.
/// \remark Must be freed using #ikarus_free.
IKA_API IkarusBlueprint * ikarus_blueprint_create(
struct IkarusProject * project, struct IkarusBlueprintFolder * parent, size_t position, char const * name
);
/// \brief Creates a blueprint from an entity.
/// \details The created blueprint will have the same properties as the entity.
/// \param entity The entity to create the blueprint from.
/// \pre \li Must not be null.
/// \param link_entity If true, the entity will be linked to the blueprint. If not they will remain separate.
/// \param parent The parent folder of the blueprint.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param position The position of the blueprint in the parent folder. \see #FolderPosition
/// \pre \li Must be within bounds for the parent folder.
/// \param name The name of the blueprint. Must not be empty.
/// \pre \li Must not be null.
/// \pre \li Must not be empty.
/// \return The created blueprint or null if an error occurs.
/// \remark Must be freed using #ikarus_free.
IKA_API IkarusBlueprint * ikarus_blueprint_create_from_entity(
struct IkarusEntity * entity, bool link_entity, struct IkarusBlueprintFolder * parent, size_t position, char const * name
);
/// \brief Copies a blueprint.
/// \details Creates a deep copy of the blueprint including all of its properties.
/// \param blueprint The blueprint to copy.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param parent The parent folder of the blueprint.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param position The position of the blueprint in the parent folder. \see #FolderPosition
/// \pre \li Must be within bounds for the parent folder.
/// \param name The name of the blueprint.
/// \pre \li Must not be null.
/// \pre \li Must not be empty.
/// \return The created blueprint or null if an error occurs.
/// \remark Linked entities won't be copied.
/// \remark Must be freed using #ikarus_free.
IKA_API IkarusBlueprint * ikarus_blueprint_copy(
IkarusBlueprint const * blueprint, struct IkarusBlueprintFolder * parent, size_t position, char const * name
);
/// \brief Deletes a blueprint.
/// \param blueprint The blueprint to delete.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \remark The blueprint must not be accessed after deletion.
IKA_API void ikarus_blueprint_delete(IkarusBlueprint * blueprint);
/// \brief Gets the project of a blueprint.
/// \param blueprint The blueprint to get the project of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The project of the blueprint or null if an error occurs.
IKA_API struct IkarusProject * ikarus_blueprint_get_project(IkarusBlueprint const * blueprint);
/// \brief Gets the parent folder of a blueprint.
/// \param blueprint The blueprint to get the parent folder of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The parent folder of the blueprint or null if an error occurs.
IKA_API struct IkarusBlueprintFolder * ikarus_blueprint_get_parent(IkarusBlueprint const * blueprint);
/// \brief Gets the position of a blueprint within its parent folder.
/// \param blueprint The blueprint to get the position of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The position of the blueprint or undefined if an error occurs.
IKA_API size_t ikarus_blueprint_get_position(IkarusBlueprint const * blueprint);
/// \brief Gets the name of a blueprint.
/// \param blueprint The blueprint to get the name of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The name of the blueprint or null if an error occurs.
/// \remark The returned pointer is valid until the blueprint is freed but may be invalidated by other operations.
IKA_API char const * ikarus_blueprint_get_name(IkarusBlueprint const * blueprint);
/// \brief Gets the property root folder of a blueprint.
/// \param blueprint The blueprint to get the root folder of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The root folder of all properties of the blueprint or null if an error occurs.
/// \remark Must be freed using #ikarus_free.
IKA_API struct IkarusPropertyFolder * ikarus_blueprint_get_property_root_folder(IkarusBlueprint const * blueprint);
/// \brief Gets the number of properties of a blueprint.
/// \param blueprint The blueprint to get the number of properties of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The number of properties or undefined if an error occurs.
IKA_API size_t ikarus_blueprint_get_property_count(IkarusBlueprint const * blueprint);
/// \brief Gets the properties of a blueprint.
/// \param blueprint The blueprint to get the properties of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param properties_out The buffer to write the properties to.
/// \pre \li Must not be null.
/// \param properties_out_size The size of the buffer.
IKA_API void ikarus_blueprint_get_properties(
IkarusBlueprint const * blueprint, struct IkarusProperty ** properties_out, size_t properties_out_size
);
/// \brief Gets the number of entities linked to a blueprint.
/// \param blueprint The blueprint to get the number of linked entities of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The number of linked entities or undefined if an error occurs.
IKA_API size_t ikarus_blueprint_get_linked_entity_count(IkarusBlueprint const * blueprint);
/// \brief Gets the entities linked to a blueprint.
/// \param blueprint The blueprint to get the linked entities of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param entities_out The buffer to write the entities to.
/// \pre \li Must not be null.
/// \param entities_out_size The size of the buffer.
IKA_API void ikarus_blueprint_get_linked_entities(
IkarusBlueprint const * blueprint, struct IkarusEntity ** entities_out, size_t entities_out_size
);
/// \brief Sets the parent folder of a blueprint.
/// \param blueprint The blueprint to set the parent folder of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param new_parent The new parent folder of the blueprint.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param new_position The new position of the blueprint in the parent folder. \see #FolderPosition
/// \pre \li Must be within bounds for the parent folder.
/// \remark This adjusts the positions of old and new siblings.
IKA_API void ikarus_blueprint_set_parent(
IkarusBlueprint * blueprint, struct IkarusBlueprintFolder * new_parent, size_t new_position
);
/// \brief Sets the position of a blueprint within its parent folder.
/// \param blueprint The blueprint to set the position of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param new_position The new position of the blueprint. \see #FolderPosition
/// \pre \li Must be within bounds for the parent folder.
/// \remark This adjusts the positions of siblings.
IKA_API void ikarus_blueprint_set_position(IkarusBlueprint * blueprint, size_t new_position);
/// \brief Sets the name of a blueprint.
/// \param blueprint The blueprint to set the name of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param new_name The new name of the blueprint.
/// \pre \li Must not be null.
/// \pre \li Must not be empty.
IKA_API void ikarus_blueprint_set_name(IkarusBlueprint * blueprint, char const * new_name);
/// \brief Converts a blueprint to an object.
/// \param blueprint The blueprint to convert.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The constructed object, representing the blueprint.
/// \remark Must be freed using #ikarus_free.
IKA_API struct IkarusObject * ikarus_blueprint_to_object(IkarusBlueprint const * blueprint);
/// \brief Compares two blueprints.
/// \param left The left blueprint to compare.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param right The right blueprint to compare.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return True if the two blueprints are equal, false otherwise.
/// \remark This neither performs a pointer comparison nor a deep comparison. When we say "equal" we mean that the two
/// blueprints reference the same blueprint in the same project.
IKA_API bool ikarus_blueprint_is_equal(IkarusBlueprint const * left, IkarusBlueprint const * right);
IKARUS_END_HEADER

View file

@ -1,10 +1,9 @@
#pragma once
#include <ikarus/id.h>
#include <ikarus/macros.h>
/// \file entity.h
/// \author Folling <mail@folling.io>
/// \author Folling <folling@ikarus.world>
/// \defgroup entities Entities
/// \brief Entities are the core building blocks of Ikarus.
@ -17,7 +16,7 @@ IKARUS_BEGIN_HEADER
///
/// Properties can be associated with Entities in two ways:
/// - Directly: The property is linked to the entity.
/// - Indirectly: The property is linked to a blueprint of the entity.
/// - Indirectly: The property is linked to a blueprint the entity is linked to.
///
/// For each property an entity is linked to, it has a value. These values depend on the property's type.
/// For more information on the types see the property documentation.
@ -31,10 +30,223 @@ IKARUS_BEGIN_HEADER
/// \remark Values are guaranteed to be in valid format for a given type
/// but not guaranteed to be valid under the settings of the property.
/// This is because changing the settings can invalidate existing values without resetting them.
struct IkarusEntity {
/// \private \brief The ID of the entity.
IkarusId id;
};
struct IkarusEntity;
/// \brief Creates an entity.
/// \param project The project the entity is part of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param parent The parent folder of the entity.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param position The position of the entity in the parent folder. \see #FolderPosition
/// \pre \li Must be within bounds for the parent folder.
/// \param name The name of the entity.
/// \pre \li Must not be null.
/// \pre \li Must not be empty.
/// \param blueprints Blueprints to link the entity to (0..n). Null is treated as an empty array.
/// \param blueprints_count The number of blueprints.
/// \return The created entity or null if an error occurs.
/// \remark Must be freed using #ikarus_free.
IKA_API IkarusEntity * ikarus_entity_create(
struct IkarusProject * project,
struct IkarusEntityFolder * parent,
size_t position,
char const * name,
struct IkarusBlueprint ** blueprints,
size_t blueprints_count
);
/// \brief Copies an entity.
/// \details Creates a deep copy of the entity including all of its properties & associated values.
/// \param entity The entity to copy.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param parent The parent folder of the entity.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param position The position of the entity in the parent folder. \see #FolderPosition
/// \pre \li Must be within bounds for the parent folder.
/// \param name The name of the entity.
/// \pre \li Must not be null.
/// \pre \li Must not be empty.
/// \return The created entity or null if an error occurs.
/// \remark Must be freed using #ikarus_free.
IKA_API IkarusEntity * ikarus_entity_copy(
struct IkarusEntity * entity, struct IkarusEntityFolder * parent, size_t position, char const * name
);
/// \brief Deletes an entity.
/// \param entity The entity to delete.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \remark The entity must not be accessed after deletion.
IKA_API void ikarus_entity_delete(IkarusEntity * entity);
IKA_API bool ikarus_entity_is_linked_to_blueprint(IkarusEntity const * entity, struct IkarusBlueprint const * blueprint);
/// \brief Checks if an entity has a specific property.
/// \param entity The entity to check.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param property The property to check.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return True if the entity has the property, false otherwise.
IKA_API bool ikarus_entity_has_property(IkarusEntity const * entity, struct IkarusProperty const * property);
/// \brief Links an entity to a blueprint.
/// \param entity The entity to link.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param blueprint The blueprint to link the entity to.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \remark No-op if the entity is already linked to the blueprint.
IKA_API void ikarus_entity_link_to_blueprint(IkarusEntity * entity, struct IkarusBlueprint * blueprint);
/// \brief Unlinks an entity from a blueprint. All values of the properties of the blueprint the entity is linked with will be
/// deleted.
/// \param entity The entity to unlink.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param blueprint The blueprint to unlink the entity from.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \remark No-op if the entity is not linked to the blueprint.
IKA_API void ikarus_entity_unlink_from_blueprint(IkarusEntity * entity, struct IkarusBlueprint * blueprint);
/// \brief Gets the project of an entity.
/// \param entity The entity to get the project of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The project of the entity or null if an error occurs.
IKA_API struct IkarusProject * ikarus_entity_get_project(IkarusEntity const * entity);
/// \brief Gets the parent folder of an entity.
/// \param entity The entity to get the parent folder of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The parent folder of the entity or null if an error occurs.
IKA_API struct IkarusEntityFolder * ikarus_entity_get_parent(IkarusEntity const * entity);
/// \brief Gets the position of an entity within its parent folder.
/// \param entity The entity to get the position of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The position of the entity or undefined if an error occurs.
IKA_API size_t ikarus_entity_get_position(IkarusEntity const * entity);
/// \brief Gets the name of an entity.
/// \param entity The entity to get the name of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The name of the entity or null if an error occurs.
/// \remark The returned pointer is valid until the entity is freed but may be invalidated by other operations.
IKA_API char const * ikarus_entity_get_name(IkarusEntity const * entity);
/// \brief Gets the property root folder of an entity.
/// \param entity The entity to get the root folder of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The root folder of all properties of the entity or null if an error occurs.
/// \remark Must be freed using #ikarus_free.
IKA_API struct IkarusPropertyFolder * ikarus_entity_get_property_root_folder(IkarusEntity const * entity);
/// \brief Gets the number of properties of an entity.
/// \param entity The entity to get the number of properties of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The number of properties or undefined if an error occurs.
IKA_API size_t ikarus_entity_get_property_count(IkarusEntity const * entity);
/// \brief Gets the properties of an entity.
/// \param entity The entity to get the properties of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param properties_out The buffer to write the properties to.
/// \pre \li Must not be null.
/// \param properties_out_size The size of the buffer.
IKA_API void ikarus_entity_get_properties(
IkarusEntity const * entity, struct IkarusProperty ** properties_out, size_t properties_out_size
);
/// \brief Gets the value of a property of an entity.
/// \details If the entity has never set the value of the property, the default value is returned (which may be indeterminate).
/// \param entity The entity to get the value of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param property The property to get the value of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The value of the property or null if the entity does not have the property or an error occurs.
/// \remark Must be freed using #ikarus_free.
IKA_API struct IkarusEntityValue * get_value(IkarusEntity const * entity, struct IkarusProperty const * property);
/// \brief Sets the parent folder of an entity.
/// \param entity The entity to set the parent folder of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param new_parent The new parent folder of the entity.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param new_position The new position of the entity in the parent folder. \see #FolderPosition
/// \pre \li Must be within bounds for the parent folder.
/// \remark This adjusts the positions of old and new siblings.
IKA_API void ikarus_entity_set_parent(IkarusEntity * entity, struct IkarusEntityFolder * new_parent, size_t new_position);
/// \brief Sets the position of an entity within its parent folder.
/// \param entity The entity to set the position of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param new_position The new position of the entity. \see #FolderPosition
/// \pre \li Must be within bounds for the parent folder.
/// \remark This adjusts the positions of siblings.
IKA_API void ikarus_entity_set_position(IkarusEntity * entity, size_t new_position);
/// \brief Sets the name of an entity.
/// \param entity The entity to set the name of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param new_name The new name of the entity.
/// \pre \li Must not be null.
/// \pre \li Must not be empty.
IKA_API void ikarus_entity_set_name(IkarusEntity * entity, char const * new_name);
/// \brief Sets the value of a property of an entity.
/// \param entity The entity to set the value of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param property The property to set the value of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param value The new value of the property.
/// \pre \li Must not be null.
/// \pre \li Must be of the same type as the property.
/// \param validate_settings If set, this function fails not only if the type of the value is invalid, but also if it's not
/// valid under the properties settings. \see property.h
/// \remark If the entity does not have the property, this function fails.
IKA_API void ikarus_entity_set_value(
IkarusEntity * entity, struct IkarusProperty const * property, struct IkarusValue * value, bool validate_settings
);
/// \brief Converts an entity to an object.
/// \param entity The entity to convert.
/// \return The constructed object, representing the entity.
/// \remark Must be freed using #ikarus_free.
IKA_API struct IkarusObject * ikarus_entity_to_object(IkarusEntity const * entity);
/// \brief Compares two entities.
/// \param left The left entity to compare.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param right The right entity to compare.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return True if the two entities are equal, false otherwise.
/// \remark This neither performs a pointer comparison nor a deep comparison. When we say "equal" we mean that the two
/// entities reference the same entity in the same project.
IKA_API bool ikarus_entity_is_equal(IkarusEntity const * left, IkarusEntity const * right);
IKARUS_END_HEADER

View file

@ -1,16 +1,9 @@
#pragma once
/// \file object.h
/// \author Folling <mail@folling.io>
/// \author Folling <folling@ikarus.world>
#include <ikarus/folders/blueprint_folder.h>
#include <ikarus/folders/entity_folder.h>
#include <ikarus/folders/property_folder.h>
#include <ikarus/macros.h>
#include <ikarus/objects/blueprint.h>
#include <ikarus/objects/entity.h>
#include <ikarus/objects/object_type.h>
#include <ikarus/objects/property.h>
/// \defgroup object Objects
/// \brief Objects are a compound type of all types of objects in the database.
@ -25,96 +18,26 @@
IKARUS_BEGIN_HEADER
struct IkarusFolder;
/// \private \brief The data of an object.
union IkarusObjectData {
/// \private \brief The blueprint data of the object.
IkarusBlueprint blueprint;
/// \private \brief The property data of the object.
IkarusProperty property;
/// \private \brief The entity data of the object.
IkarusEntity entity;
/// \private \brief The blueprint folder data of the object.
IkarusBlueprintFolder blueprint_folder;
/// \private \brief The property folder data of the object.
IkarusPropertyFolder property_folder;
/// \private \brief The entity folder data of the object.
IkarusEntityFolder entity_folder;
};
/// \brief A generic object. Wraps all types of objects, including folders.
struct IkarusObject {
/// \private \brief The type of the object.
IkarusObjectType type;
/// \private \brief The data of the object.
IkarusObjectData data;
};
/// \brief Constructs an object from a blueprint.
/// \param blueprint The blueprint to construct the object from.
/// \return The constructed object, representing the blueprint.
IKA_API IkarusObject ikarus_object_from_blueprint(IkarusBlueprint blueprint);
/// \brief Constructs an object from a property.
/// \param property The property to construct the object from.
/// \return The constructed object, representing the property.
IKA_API IkarusObject ikarus_object_from_property(IkarusProperty property);
/// \brief Constructs an object from an entity.
/// \param entity The entity to construct the object from.
/// \return The constructed object, representing the entity.
IKA_API IkarusObject ikarus_object_from_entity(IkarusEntity entity);
/// \brief Constructs an object from a blueprint folder.
/// \param blueprint The folder to construct the object from.
/// \return The constructed object, representing the folder.
IKA_API IkarusObject ikarus_object_from_blueprint_folder(IkarusBlueprintFolder folder);
/// \brief Constructs an object from a property folder.
/// \param property The folder to construct the object from.
/// \return The constructed object, representing the folder.
IKA_API IkarusObject ikarus_object_from_property_folder(IkarusPropertyFolder folder);
/// \brief Constructs an object from a entity folder.
/// \param entity The folder to construct the object from.
/// \return The constructed object, representing the folder.
IKA_API IkarusObject ikarus_object_from_entity_folder(IkarusEntityFolder folder);
/// \brief Constructs an object from a folder.
/// \param folder The folder to construct the object from.
/// \return The constructed object, representing the folder.
IKA_API IkarusObject ikarus_object_from_folder(IkarusFolder folder);
/// \brief Compares two objects for equality.
/// \details Since ids store the type of the object, this boils down to a simple comparison of the ids.
/// \param left The left side of the comparison.
/// \param right The right side of the comparison.
/// \return Whether the objects are equal.
IKA_API bool ikarus_object_is_equal(IkarusObject left, IkarusObject right);
/// \brief Fetches the type of an object.
/// \param object The object to fetch the type of.
/// \return The type of the object.
IKA_API IkarusObjectType ikarus_object_get_type(IkarusObject object);
struct IkarusObject;
/// \brief Visits an object. Calling the appropriate function for the object's type.
/// \param object The object to visit.
/// \param blueprint The function to call if the object is a blueprint.
/// \param property The function to call if the object is a property.
/// \param entity The function to call if the object is an entity.
/// \param blueprint_folder The function to call if the object is a blueprint folder.
/// \param property_folder The function to call if the object is a property folder.
/// \param entity_folder The function to call if the object is an entity folder.
/// \param data The data to pass to the functions.
/// \param blueprint_visitor The function to call if the object is a blueprint. Skipped if null.
/// \param property_visitor The function to call if the object is a property. Skipped if null.
/// \param entity_visitor The function to call if the object is an entity. Skipped if null.
/// \param blueprint_folder_visitor The function to call if the object is a blueprint folder. Skipped if null.
/// \param property_folder_visitor The function to call if the object is a property folder. Skipped if null.
/// \param entity_folder_visitor The function to call if the object is an entity folder. Skipped if null.
/// \param data The data passed to the visitor functions.
IKA_API void ikarus_object_visit(
IkarusObject object,
void (*visit_blueprint)(IkarusBlueprint, void *),
void (*visit_property)(IkarusProperty, void *),
void (*visit_entity)(IkarusEntity, void *),
void (*visit_blueprint_folder)(IkarusBlueprintFolder, void *),
void (*visit_property_folder)(IkarusPropertyFolder, void *),
void (*visit_entity_folder)(IkarusEntityFolder, void *),
IkarusObject * object,
void (*blueprint_visitor)(struct IkarusBlueprint *, void *),
void (*property_visitor)(struct IkarusProperty *, void *),
void (*entity_visitor)(struct IkarusEntity *, void *),
void (*blueprint_folder_visitor)(struct IkarusBlueprintFolder *, void *),
void (*property_folder_visitor)(struct IkarusPropertyFolder *, void *),
void (*entity_folder_visitor)(struct IkarusEntityFolder *, void *),
void * data
);

View file

@ -1,38 +1,36 @@
#pragma once
/// \file object_type.h
/// \author Folling <folling@ikarus.world>
#include <ikarus/macros.h>
/// \addtogroup objects Objects
/// @{
IKARUS_BEGIN_HEADER
// IMPLEMENTATION_DETAIL_OBJECT_TYPES
/// \file object.h
/// \author Folling <mail@folling.io>
#include <ikarus/folders/folder_type.h>
#include <ikarus/macros.h>
/// \addtogroup object Objects
/// @{
/// \brief The type of an object.
/// \remark Folders have the 4th bit set.
/// \remark The folder types are identical to their counterparts in #IkarusFolderType.
enum IkarusObjectType {
/// \brief Not an object or no object.
IkarusObjectType_None = 0,
/// \brief An IkarusBlueprint.
IkarusObjectType_Blueprint = 1,
IkarusObjectType_Blueprint = 0b00000001,
/// \brief An IkarusProperty.
IkarusObjectType_Property = 2,
IkarusObjectType_Property = 0b00000010,
/// \brief An IkarusEntity.
IkarusObjectType_Entity = 3,
IkarusObjectType_Entity = 0b00000011,
/// \brief An IkarusBlueprintFolder
IkarusObjectType_BlueprintFolder = IkarusFolderType_BlueprintFolder,
IkarusObjectType_BlueprintFolder = 0b01000001,
/// \brief An IkarusPropertyFolder
IkarusObjectType_PropertyFolder = IkarusFolderType_PropertyFolder,
IkarusObjectType_PropertyFolder = 0b01000010,
/// \brief An IkarusEntityFolder
IkarusObjectType_EntityFolder = IkarusFolderType_EntityFolder,
IkarusObjectType_EntityFolder = 0b01000011,
};
/// \brief Constructs an IkarusObjectType from an IkarusFolderType.
/// \param type The IkarusFolderType of which to construct the IkarusObjectType from.
/// \return The constructed IkarusObjectType, representing the folder type.
IKA_API IkarusObjectType ikarus_object_type_from_folder_type(IkarusFolderType type);
IKARUS_END_HEADER
/// @}

View file

@ -1,17 +1,16 @@
#pragma once
// IMPLEMENTATION_DETAIL_LAZY_VALUE_CREATION, IMPLEMENTATION_DETAIL_PROPERTY_TYPES
// IMPLEMENTATION_DETAIL_LAZY_VALUE_CREATION
/// \file property.h
/// \author Folling <mail@folling.io>
/// \author Folling <folling@ikarus.world>
#include <ikarus/id.h>
#include <ikarus/macros.h>
#include <ikarus/objects/blueprint.h>
#include <ikarus/objects/entity.h>
#include <ikarus/objects/property_type.h>
/// \defgroup properties Properties
/// \brief Properties define the structure and types of data.
/// @{
IKARUS_BEGIN_HEADER
@ -50,23 +49,181 @@ IKARUS_BEGIN_HEADER
/// Fetching the value for some property of some entity will return the property's default value if none is specified.
/// This default value is specified when the property is created and can be updated later.
/// \remark Properties' tree structures are scoped to the entity or blueprint they are associated with.
struct IkarusProperty {
/// \private \brief The id of the property.
IkarusId id;
};
struct IkarusProperty;
/// \brief The type of a property.
/// \details Designates the type of data stored by the property as well as which settings are
/// available.
/// \see IkarusPropertySettings
enum IkarusPropertyType {
/// \brief A true/false boolean-like value.
IkarusPropertyType_Toggle,
/// \brief An arbitrary numeric value.
IkarusPropertyType_Number,
/// \brief An arbitrary textual value.
IkarusPropertyType_Text,
};
/// \brief Creates a property
/// \param project The project the property is part of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param property_source The property source the property is part of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param parent_folder The parent folder of the property.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param position The position of the property in the parent folder. \see #FolderPosition
/// \pre \li Must be within bounds for the parent folder.
/// \param name The name of the property.
/// \pre \li Must not be null.
/// \pre \li Must not be empty.
/// \param property_info The info of the property.
/// \pre \li Must not be null.
/// \return The created property or null if an error occurs.
/// \remark Must be freed using #ikarus_free.
IKA_API struct IkarusProperty * ikarus_property_create(
struct IkarusProject * project,
struct IkarusPropertySource * property_source,
struct IkarusPropertyFolder * parent_folder,
size_t position,
char const * name,
struct IkarusPropertyTypeInfo * property_info
);
/// \brief Copies a property.
/// \details Creates a deep copy of the property including all of its settings and associated values.
/// \param property The property to copy.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param source The source to copy the property to.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param parent_folder The parent folder of the property.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param position The position of the property in the parent folder. \see #FolderPosition
/// \pre \li Must be within bounds for the parent folder.
/// \param name The name of the property.
/// \pre \li Must not be null.
/// \pre \li Must not be empty.
/// \return The created property or null if an error occurs.
/// \remark Must be freed using #ikarus_free.
IKA_API struct IkarusProperty * ikarus_property_copy(
struct IkarusProperty * property,
struct IkarusPropertySource * source,
struct IkarusPropertyFolder * parent_folder,
size_t position,
char const * name
);
/// \brief Deletes a property.
/// \param property The property to delete.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \remark The property must not be accessed after deletion.
IKA_API void ikarus_property_delete(struct IkarusProperty * property);
/// \brief Gets the project of a property.
/// \param property The property to get the project of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The project of the property or null if an error occurs.
IKA_API struct IkarusProject * ikarus_property_get_project(IkarusProperty const * property);
/// \brief Gets the parent folder of a property.
/// \param property The property to get the parent folder of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The parent folder of the property or null if an error occurs.
IKA_API struct IkarusPropertyFolder * ikarus_property_get_parent(IkarusProperty const * property);
/// \brief Gets the position of a property within its parent folder.
/// \param property The property to get the position of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The position of the property or undefined if an error occurs.
IKA_API size_t ikarus_property_get_position(IkarusProperty const * property);
/// \brief Gets the name of a property.
/// \param property The property to get the name of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The name of the property or null if an error occurs.
/// \remark The returned pointer is valid until the property is freed but may be invalidated by other operations.
IKA_API char const * ikarus_property_get_name(IkarusProperty const * property);
/// \brief Gets the type info of a property.
/// \param property The property to get the type info of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The type info of the property or null if an error occurs.
/// \remark Must be freed using #ikarus_free.
IKA_API struct IkarusPropertyTypeInfo * ikarus_property_get_type_info(IkarusProperty const * property);
/// \brief Gets the source of a property.
/// \param property The property to get the source of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The source of the property or null if an error occurs.
/// \remark Must be freed using #ikarus_free.
IKA_API struct IkarusPropertySource * ikarus_property_get_source(IkarusProperty const * property);
/// \brief Gets the default value of a property.
/// \param property The property to get the default value of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The default value of the property or null if an error occurs.
/// \remark Must be freed using #ikarus_free.
IKA_API struct IkarusValue * ikarus_property_get_default_value(IkarusProperty const * property);
/// \brief Sets the parent folder of a property.
/// \param property The property to set the parent folder of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param new_parent The new parent folder of the property.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param new_position The new position of the property in the parent folder. \see #FolderPosition
/// \pre \li Must be within bounds for the parent folder.
/// \remark This adjusts the positions of old and new siblings.
IKA_API void ikarus_property_set_parent(
IkarusProperty * property, struct IkarusPropertyFolder * new_parent, size_t new_position
);
/// \brief Sets the position of a property within its parent folder.
/// \param property The property to set the position of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param new_position The new position of the property. \see #FolderPosition
/// \pre \li Must be within bounds for the parent folder.
/// \remark This adjusts the positions of siblings.
IKA_API void ikarus_property_set_position(IkarusProperty * property, size_t new_position);
/// \brief Sets the name of a property.
/// \param property The property to set the name of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param new_name The new name of the property.
/// \pre \li Must not be null.
/// \pre \li Must not be empty.
IKA_API void ikarus_property_set_name(IkarusProperty * property, char const * new_name);
/// \brief Sets the type info of a property and resets all values to the new default value.
/// \param property The property to set the type info of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param new_type The new type info of the property.
/// \param attempt_conversion Whether to attempt to convert the property's values to the new type info. Conversion rules are
/// unspecified for now, but follow common sense.
IKA_API void ikarus_property_set_type_info(
IkarusProperty * property, struct IkarusPropertyTypeInfo new_type_info, bool attempt_conversion
);
/// \brief Converts a property to an object.
/// \param property The property to convert.
/// \return The constructed object, representing the property.
IKA_API struct IkarusObject * ikarus_property_to_object(IkarusProperty const * property);
/// \brief Compares two properties.
/// \param left The left property to compare.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param right The right property to compare.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return True if the two properties are equal, false otherwise.
/// \remark This neither performs a pointer comparison nor a deep comparison. When we say "equal" we mean that the two
/// properties reference the same property in the same project.
IKA_API bool ikarus_property_is_equal(IkarusProperty const * left, IkarusProperty const * right);
IKARUS_END_HEADER

View file

@ -0,0 +1,47 @@
#pragma once
/// \file property_source.h
/// \author Folling <folling@ikarus.world>
#include <ikarus/macros.h>
/// \addtogroup properties Properties
/// @{
IKARUS_BEGIN_HEADER
struct PropertySource;
/// \brief Creates an blueprint property source.
/// \param blueprint The blueprint to create the property source for.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The created property source or null if an error occurs.
/// \remark Must be freed using #ikarus_free.
IKA_API struct PropertySource * ikarus_property_source_create_blueprint(struct IkarusBlueprint * blueprint);
/// \brief Creates an entity property source.
/// \param entity The entity to create the property source for.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The created property source or null if an error occurs.
/// \remark Must be freed using #ikarus_free.
IKA_API struct PropertySource * ikarus_property_source_create_entity(struct IkarusEntity * entity);
/// \brief Visits a property source, calling the appropriate callback.
/// \param property_source The property source to visit.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param blueprint_visitor The callback to call if the source is a blueprint, skipped if null.
/// \param entity_visitor The callback to call if the source is an entity, skipped if null.
/// \param user_data User data to pass to the callbacks.
IKA_API void ikarus_property_source_visit(
struct PropertySource * property_source,
void (*blueprint_visitor)(struct IkarusBlueprint *, void *),
void (*entity_visitor)(struct IkarusEntity *, void *),
void * user_data
);
IKARUS_END_HEADER
/// @}

View file

@ -3,29 +3,33 @@
// IMPLEMENTATION_DETAIL_PROPERTY_TYPES
/// \file property_type.h
/// \author Folling <mail@folling.io>
/// \author Folling <folling@ikarus.world>
#include <ikarus/macros.h>
IKARUS_BEGIN_HEADER
/// \defgroup property_types Property Types
/// \brief Property Types delineate the type of data stored by a property.
/// \addtogroup properties Properties
/// @{
IKARUS_BEGIN_HEADER
/// \brief The type of a property.
/// \details Designates the type of data stored by the property as well as which settings are
/// available.
/// \see IkarusPropertySettings
enum IkarusPropertyType {
/// \brief A true/false boolean-like value.
/// \brief A true/false boolean-esque value.
IkarusPropertyType_Toggle,
/// \brief An arbitrary numeric value.
/// \brief A numeric value, limited to IEEE 80 bit floating point numbers.
IkarusPropertyType_Number,
/// \brief An arbitrary textual value.
/// \brief An arbitrary UTF-8 textual value.
IkarusPropertyType_Text,
};
/// @}
/// \brief Fetches the default value for a property type.
/// \remark Not to be confused with the default value of a property. See ikarus_property_get_default_value
/// \param type The property type.
/// \return The default value for the property type or null if an error occurs.
IKA_API struct IkarusValue * ikarus_property_type_get_default_default_value(IkarusPropertyType type);
IKARUS_END_HEADER
/// @}

View file

@ -0,0 +1,79 @@
#pragma once
/// \file property_info.h
/// \author Folling <folling@ikarus.world>
#include <ikarus/macros.h>
/// \addtogroup properties Properties
/// @{
IKARUS_BEGIN_HEADER
/// \brief Information about a property.
/// \details Property information includes their type and settings consolidated to ascertain type safety.
struct IkarusPropertyTypeInfo;
/// \brief Information about a toggle property.
struct IkarusTogglePropertyInfo;
/// \brief Information about a number property.
struct IkarusNumberPropertyInfo;
/// \brief Information about a text property.
struct IkarusTextPropertyInfo;
/// \brief Creates a new toggle property info.
/// \return The created toggle property info.
/// \remark Must be freed with #ikarus_free.
IKA_API IkarusTogglePropertyInfo * ikarus_toggle_property_info_create();
/// \brief Sets the default value of a toggle property info.
/// \param toggle_property_info The toggle property info to set the default value of.
/// \pre \li Must not be null.
/// \param default_value The default value to set.
/// \pre \li Must not be null.
IKA_API void ikarus_toggle_property_info_set_default_value(
IkarusTogglePropertyInfo * toggle_property_info, struct IkarusToggleValue * default_value
);
/// \brief Converts a toggle property info to a generic property info.
/// \param toggle_property_info The toggle property info to convert.
/// \return The converted property info.
IKA_API IkarusPropertyTypeInfo * ikarus_toggle_property_info_to_property_info(IkarusTogglePropertyInfo * toggle_property_info);
/// \brief Creates a new number property info.
/// \return The created number property info.
/// \remark Must be freed with #ikarus_free.
IKA_API IkarusNumberPropertyInfo * ikarus_number_property_info_create();
/// \brief Sets the default value of a number property info.
/// \param number_property_info The number property info to set the default value of.
/// \pre \li Must not be null.
/// \param default_value The default value to set.
/// \pre \li Must not be null.
IKA_API void ikarus_number_property_info_set_default_value(
IkarusNumberPropertyInfo * number_property_info, struct IkarusNumberValue * default_value
);
/// \brief Converts a number property info to a generic property info.
/// \param number_property_info The number property info to convert.
/// \return The converted property info.
IKA_API IkarusPropertyTypeInfo * ikarus_number_property_info_to_property_info(IkarusNumberPropertyInfo * number_property_info);
/// \brief Creates a new text property info.
/// \return The created text property info.
/// \remark Must be freed with #ikarus_free.
IKA_API IkarusTextPropertyInfo * ikarus_text_property_info_create();
/// \brief Sets the default value of a text property info.
/// \param text_property_info The text property info to set the default value of.
/// \pre \li Must not be null.
/// \param default_value The default value to set.
/// \pre \li Must not be null.
IKA_API void ikarus_text_property_info_set_default_value(
IkarusTextPropertyInfo * text_property_info, struct IkarusTextValue * default_value
);
/// \brief Converts a text property info to a generic property info.
/// \param text_property_info The text property info to convert.
/// \return The converted property info.
IKA_API IkarusPropertyTypeInfo * ikarus_text_property_info_to_property_info(IkarusTextPropertyInfo * text_property_info);
IKARUS_END_HEADER
/// @}