diff --git a/legacy/ephysics/src/lib/EPhysics.h b/legacy/ephysics/src/lib/EPhysics.h index 6ce042c6fb..6ac6477e2f 100644 --- a/legacy/ephysics/src/lib/EPhysics.h +++ b/legacy/ephysics/src/lib/EPhysics.h @@ -21,6 +21,7 @@ * @li @ref EPhysics_Body * @li @ref EPhysics_Camera * @li @ref EPhysics_Constraint + * @li @ref EPhysics_Shape * * Please see the @ref authors page for contact details. */ @@ -119,6 +120,166 @@ EAPI int ephysics_shutdown(void); * @} */ +/** + * @defgroup EPhysics_Shape EPhysics Shape + * @ingroup EPhysics + * + * @{ + * + * Shapes are used to create bodies with shapes that differ from primitive + * ones, like box and circle. + * + * A shape consists in a group of points, the vertices of the body to be + * created later with @ref ephysics_body_shape_add(). + * + * A new shape is created with @ref ephysics_shape_new() and points are + * set with @ref ephysics_shape_point_add(). A shape can be used to + * create many bodies. When done, it's required to delete the shape + * with @ref ephysics_shape_del(). + * + * A shape can be load from a file describing it with + * @ref ephysics_shape_load(), and can be saved to a file with + * @ref ephysics_shape_save(). With that shapes can be done or visualized + * on design applications. + * + * @note Using primitive shapes has better perfomance than generic shapes. + * @note For now, only convex shapes are supported. + * + */ + +/** + * @typedef EPhysics_Shape + * + * Shape handle, represents a shape to be used to create a body. + * + * Created with @ref ephysics_shape_new() and deleted with + * @ref ephysics_shape_del(). + * + * @ingroup EPhysics_Shape + */ +typedef struct _EPhysics_Shape EPhysics_Shape; + +/** + * @brief + * Create a new shape. + * + * The returned shape initially doesn't has points set, so it's required + * to set vertices with @ref ephysics_shape_point_add(). + * + * After the shape is completelly defined, all the points were added, + * it's possible to create one or more bodies with + * @ref ephysics_body_shape_add(). + * + * @return The created shape or @c NULL on error. + * + * @see ephysics_shape_del(). + * @see ephysics_shape_load(). + * + * @ingroup EPhysics_Shape + */ +EAPI EPhysics_Shape *ephysics_shape_new(void); + +/** + * @brief + * Delete a shape. + * + * After a shape is used to create the wanted bodies, it's required + * to delete it. It won't be deleted automatically by ephysics + * at any point, even on shutdown. The creator is responsible to + * free it after usage is concluded. + * + * @param shape The shape to be deleted. + * + * @see ephysics_shape_new(). + * + * @ingroup EPhysics_Shape + */ +EAPI void ephysics_shape_del(EPhysics_Shape *shape); + +/** + * @brief + * Add a new point to the shape. + * + * Any point can be added to a shape, but only vertices matter. + * A vertex is a special kind of point that describes a corner of + * geometric shapes. The final shape will be constructed in such a way + * it will have all the added points and will be convex. + * + * The order of points doesn't matter. + * + * For example, to create a pentagon: + * + * @code + * EPhysics_Shape *shape = ephysics_shape_new(); + * + * ephysics_shape_point_add(shape, 0/70., 24/66.); + * ephysics_shape_point_add(shape, 35/70., 0/66.); + * ephysics_shape_point_add(shape, 70/70., 24/66.); + * ephysics_shape_point_add(shape, 56/70., 66/66.); + * ephysics_shape_point_add(shape, 14/70., 66/66.); + * + * ephysics_body_shape_add(world, shape); + * + * ephysics_shape_del(shape); + * @endcode + * + * @param shape The shape to be modified. + * @param x Point position at x axis. Should be a value between 0 and 1. + * @param y Point position at y axis. Should be a value between 0 and 1. + * @return @c EINA_TRUE on success or EINA_FALSE on error. + * + * @see ephysics_shape_new(). + * + * @ingroup EPhysics_Shape + */ +EAPI Eina_Bool ephysics_shape_point_add(EPhysics_Shape *shape, double x, double y); + +/** + * @brief + * Load the shape from a file. + * + * Useful to edit shapes on design tools and load it from an exported file. + * + * Also it helps to avoid lots of @ref ephysics_shape_point_add() in + * the code, and keep a better separation between code logic and + * design stuff. + * + * @param filename The path to the file describing the shape. + * @return The loaded shape or @c NULL on error. + * + * @note Not implemented yet. + * + * @see ephysics_shape_new() for more details. + * @see ephysics_shape_save(). + * + * @ingroup EPhysics_Shape + */ +EAPI EPhysics_Shape *ephysics_shape_load(const char *filename); + +/** + * @brief + * Save the shape to a file. + * + * It can be useful to visualize it on design tools. + * + * @param shape The shape to be saved. + * @param filename The path to save the shape. + * @return @c EINA_TRUE on success or EINA_FALSE on error. + * + * @note Not implemented yet. + * + * @see ephysics_shape_new(). + * @see ephysics_shape_load(). + * + * @ingroup EPhysics_Shape + */ +EAPI Eina_Bool ephysics_shape_save(const EPhysics_Shape *shape, const char *filename); + +/** + * @} + */ + + /** * @typedef EPhysics_Body * diff --git a/legacy/ephysics/src/lib/Makefile.am b/legacy/ephysics/src/lib/Makefile.am index 89cf011f6c..8e02c2ce6c 100644 --- a/legacy/ephysics/src/lib/Makefile.am +++ b/legacy/ephysics/src/lib/Makefile.am @@ -18,6 +18,7 @@ base_sources = \ ephysics_camera.cpp \ ephysics_constraints.cpp \ ephysics_main.cpp \ + ephysics_shape.cpp \ ephysics_world.cpp libephysics_la_SOURCES = $(base_sources) diff --git a/legacy/ephysics/src/lib/ephysics_private.h b/legacy/ephysics/src/lib/ephysics_private.h index fcc4b73b8b..88353ff82f 100644 --- a/legacy/ephysics/src/lib/ephysics_private.h +++ b/legacy/ephysics/src/lib/ephysics_private.h @@ -44,6 +44,8 @@ extern "C" { #define RAD_TO_DEG 57.29582 /* 2 * pi radians == 360 degree */ +typedef struct _EPhysics_Point EPhysics_Point; + typedef enum _EPhysics_World_Boundary { EPHYSICS_WORLD_BOUNDARY_TOP, @@ -53,6 +55,12 @@ typedef enum _EPhysics_World_Boundary EPHYSICS_WORLD_BOUNDARY_LAST } EPhysics_World_Boundary; +struct _EPhysics_Point { + EINA_INLIST; + double x; + double y; +}; + struct _EPhysics_Body { EINA_INLIST; btCollisionShape *collision_shape; @@ -95,6 +103,8 @@ void ephysics_camera_del(EPhysics_Camera *camera); void ephysics_camera_moved_set(EPhysics_Camera *camera, Eina_Bool moved); Eina_Bool ephysics_camera_moved_get(const EPhysics_Camera *camera); +const Eina_Inlist *ephysics_shape_points_get(const EPhysics_Shape *shape); + #ifdef __cplusplus } #endif diff --git a/legacy/ephysics/src/lib/ephysics_shape.cpp b/legacy/ephysics/src/lib/ephysics_shape.cpp new file mode 100644 index 0000000000..7970b09e63 --- /dev/null +++ b/legacy/ephysics/src/lib/ephysics_shape.cpp @@ -0,0 +1,123 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "ephysics_private.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct _EPhysics_Shape { + Eina_Inlist *points; +}; + +static EPhysics_Point * +_ephysics_shape_point_new(void) +{ + EPhysics_Point *point; + + point = (EPhysics_Point *)calloc(1, sizeof(EPhysics_Point)); + if (!point) + { + ERR("Failed to allocate point."); + return NULL; + } + + return point; +} + +const Eina_Inlist * +ephysics_shape_points_get(const EPhysics_Shape *shape) +{ + return shape->points; +} + +EAPI EPhysics_Shape * +ephysics_shape_new(void) +{ + EPhysics_Shape *shape; + + shape = (EPhysics_Shape *)calloc(1, sizeof(EPhysics_Shape)); + if (!shape) + { + ERR("Failed to allocate shape."); + return NULL; + } + + return shape; +} + +EAPI void +ephysics_shape_del(EPhysics_Shape *shape) +{ + EPhysics_Point *point; + + if (!shape) + { + ERR("Can't delete shape, it's null."); + return; + } + + while (shape->points) + { + point = EINA_INLIST_CONTAINER_GET(shape->points, EPhysics_Point); + shape->points = eina_inlist_remove(shape->points, shape->points); + free(point); + } + + free(shape); +} + +EAPI Eina_Bool +ephysics_shape_point_add(EPhysics_Shape *shape, double x, double y) +{ + EPhysics_Point *point; + + if (!shape) + { + ERR("Can't add point to shape, it's null."); + return EINA_FALSE;; + } + + if ((x < 0) || (x > 1) || (y < 0) || (y > 1)) + { + ERR("Points should be between 0 and 1."); + return EINA_FALSE; + } + + point = _ephysics_shape_point_new(); + if (!point) + return EINA_FALSE;; + + point->x = x; + point->y = y; + + shape->points = eina_inlist_append(shape->points, EINA_INLIST_GET(point)); + + return EINA_TRUE; +} + +/* TODO: load points from file */ +EAPI EPhysics_Shape * +ephysics_shape_load(const char *filename) +{ + EPhysics_Shape *shape; + + shape = ephysics_shape_new(); + if (!shape) + return NULL; + + return shape; +} + +/* TODO: save points to file */ +EAPI Eina_Bool +ephysics_shape_save(const EPhysics_Shape *shape, const char *filename) +{ + return EINA_TRUE; +} + +#ifdef __cplusplus +} +#endif