diff --git a/dev/test/premake5.lua b/dev/test/premake5.lua index c0d716bb..163155dc 100644 --- a/dev/test/premake5.lua +++ b/dev/test/premake5.lua @@ -84,8 +84,10 @@ buildoptions {"-Wall", "-fno-exceptions", "-fno-rtti"} includedirs {"./include", "../../include"} -files {"../../src/**.cpp", -- the Rive runtime source -"../../test/**.cpp" -- the tests +files { + "../../src/**.cpp", -- the Rive runtime source + "../../test/**.cpp", -- the tests + "../../include/capi/**.cpp", } defines {"TESTING", "ENABLE_QUERY_FLAT_VERTICES"} @@ -97,4 +99,4 @@ symbols "On" filter "system:windows" architecture "x64" defines {"_USE_MATH_DEFINES"} - buildoptions {WINDOWS_CLANG_CL_SUPPRESSED_WARNINGS} \ No newline at end of file + buildoptions {WINDOWS_CLANG_CL_SUPPRESSED_WARNINGS} diff --git a/include/capi/rive_api.cpp b/include/capi/rive_api.cpp new file mode 100644 index 00000000..a3fd406d --- /dev/null +++ b/include/capi/rive_api.cpp @@ -0,0 +1,113 @@ +#include "capi/rive_api.h" + +#include "rive/file.hpp" +#include "rive/artboard.hpp" +#include "rive/span.hpp" +#include "rive/scene.hpp" +#include "rive/animation/linear_animation_instance.hpp" +#include "rive/animation/state_machine_instance.hpp" +#include "rive/math/aabb.hpp" + +static inline rive_file_t* toC(rive::File* file) { return (rive_file_t*)file; } +static inline rive_artboard_t* toC(rive::ArtboardInstance* abi) { return (rive_artboard_t*)abi; } +static inline rive_scene_t* toC(rive::Scene* scene) { return (rive_scene_t*)scene; } +static inline rive_animation_t* toC(rive::LinearAnimationInstance* anim) { + return (rive_animation_t*)anim; +} +static inline rive_statemachine_t* toC(rive::StateMachineInstance* smi) { + return (rive_statemachine_t*)smi; +} + +static inline rive::Factory* toRive(rive_factory_t* factory) { return (rive::Factory*)factory; } +static inline rive::Renderer* toRive(rive_renderer_t* renderer) { return (rive::Renderer*)renderer; } + +static inline rive::File* toRive(rive_file_t* file) { return (rive::File*)file; } +static inline rive::ArtboardInstance* toRive(rive_artboard_t* abi) { return (rive::ArtboardInstance*)abi; } +static inline rive::Scene* toRive(rive_scene_t* scene) { return (rive::Scene*)scene; } + +#if 0 +static inline rive_factory_t* toC(rive::Factory* factory) { return (rive_factory_t*)factory; } +static inline rive_renderer_t* toC(rive::Renderer* renderer) { return (rive_renderer_t*)renderer; } +static inline rive::LinearAnimationInstance* toRive(rive_animation_t* anim) { + return (rive::LinearAnimationInstance*)anim; +} +static inline rive::StateMachineInstance* toRive(rive_statemachine_t* smi) { + return (rive::StateMachineInstance*)smi; +} +#endif + +////////////////////////////////////// + +void rive_file_delete(rive_file_t* file) { delete toRive(file); } +void rive_artboard_delete(rive_artboard_t* abi) { delete toRive(abi); } +void rive_scene_delete(rive_scene_t* scene) { delete toRive(scene); } + +rive_file_t* rive_file_import(rive_span_t cspan, rive_factory_t* factory) { + rive::Span span((const uint8_t*)cspan.buffer, cspan.size); + return toC(rive::File::import(span, toRive(factory)).release()); +} + +int32_t rive_file_artboard_count(rive_file_t* file) { + return toRive(file)->artboardCount(); +} + +rive_artboard_t* rive_file_artboard_default(rive_file_t* file) { + return toC(toRive(file)->artboardDefault().release()); +} + +rive_artboard_t* rive_file_artboard_at(rive_file_t* file, int32_t index) { + return toC(toRive(file)->artboardAt(index).release()); +} + +rive_artboard_t* rive_file_artboard_named(rive_file_t* file, const char name[]) { + return toC(toRive(file)->artboardNamed(name).release()); +} + +/////////////////////////// + +int32_t rive_artboard_animation_count(rive_artboard_t* abi) { + return toRive(abi)->animationCount(); +} + +rive_animation_t* rive_artboard_animation_at(rive_artboard_t* abi, int32_t index) { + return toC(toRive(abi)->animationAt(index).release()); +} + +rive_animation_t* rive_artboard_animation_named(rive_artboard_t* abi, const char name[]) { + return toC(toRive(abi)->animationNamed(name).release()); +} + +int32_t rive_artboard_statemachine_count(rive_artboard_t* abi) { + return toRive(abi)->stateMachineCount(); +} + +rive_statemachine_t* rive_artboard_statemachine_at(rive_artboard_t* abi, int32_t index) { + return toC(toRive(abi)->stateMachineAt(index).release()); +} + +rive_statemachine_t* rive_artboard_statemachine_named(rive_artboard_t* abi, const char name[]) { + return toC(toRive(abi)->stateMachineNamed(name).release()); +} + +rive_statemachine_t* rive_artboard_statemachine_default(rive_artboard_t* abi) { + return toC(toRive(abi)->defaultStateMachine().release()); +} + +rive_scene_t* rive_artboard_scene_default(rive_artboard_t* abi) { + return toC(toRive(abi)->defaultScene().release()); +} + +//////////////////////////////// + +rive_aabb_t rive_scene_bounds(rive_scene_t* scene) { + auto aabb = toRive(scene)->bounds(); + return {aabb.left(), aabb.top(), aabb.right(), aabb.bottom()}; +} + +void rive_scene_draw(rive_scene_t* scene, rive_renderer_t* renderer) { + toRive(scene)->draw(toRive(renderer)); +} + +bool rive_scene_advance(rive_scene_t* scene, float seconds) { + return toRive(scene)->advanceAndApply(seconds); +} diff --git a/include/capi/rive_api.h b/include/capi/rive_api.h new file mode 100644 index 00000000..afb8697c --- /dev/null +++ b/include/capi/rive_api.h @@ -0,0 +1,36 @@ +#ifndef _RIVE_FILE_H_ +#define _RIVE_FILE_H_ + +#include "capi/rive_types.h" + +RIVE_C_PLUS_PLUS_BEGIN_GUARD + +rive_file_t* rive_file_import(rive_span_t, rive_factory_t*); + +int32_t rive_file_artboard_count(rive_file_t*); +rive_artboard_t* rive_file_artboard_default(rive_file_t*); +rive_artboard_t* rive_file_artboard_at(rive_file_t*, int32_t index); +rive_artboard_t* rive_file_artboard_named(rive_file_t*, const char name[]); + +rive_statemachine_t* rive_artboard_statemachine_default(rive_artboard_t*); +rive_scene_t* rive_artboard_scene_default(rive_artboard_t*); + +int32_t rive_artboard_animation_count(rive_artboard_t*); +rive_animation_t* rive_artboard_animation_at(rive_artboard_t*, int32_t index); +rive_animation_t* rive_artboard_animation_named(rive_artboard_t*, const char name[]); + +int32_t rive_artboard_count_statemachines(rive_artboard_t*); +rive_statemachine_t* rive_artboard_statemachine_at(rive_artboard_t*, int32_t index); +rive_statemachine_t* rive_artboard_statemachine_named(rive_artboard_t*, const char name[]); + +rive_aabb_t rive_scene_bounds(rive_scene_t*); +void rive_scene_draw(rive_scene_t*, rive_renderer_t*); +bool rive_scene_advance(rive_scene_t*, float seconds); + +void rive_file_delete(rive_file_t*); +void rive_artboard_delete(rive_artboard_t*); +void rive_scene_delete(rive_scene_t*); + +RIVE_C_PLUS_PLUS_END_GUARD + +#endif diff --git a/include/capi/rive_types.h b/include/capi/rive_types.h new file mode 100644 index 00000000..89f6d329 --- /dev/null +++ b/include/capi/rive_types.h @@ -0,0 +1,48 @@ +#ifndef _RIVE_TYPES_H_ +#define _RIVE_TYPES_H_ + +#include +#include + +#ifdef __cplusplus + #define RIVE_C_PLUS_PLUS_BEGIN_GUARD extern "C" { + #define RIVE_C_PLUS_PLUS_END_GUARD } +#else + #include + #define RIVE_C_PLUS_PLUS_BEGIN_GUARD + #define RIVE_C_PLUS_PLUS_END_GUARD +#endif + +RIVE_C_PLUS_PLUS_BEGIN_GUARD + +typedef uint32_t rive_colorint_t; + +typedef struct { + float x, y; +} rive_vec2d_t; + +typedef struct { + float left, top, right, bottom; +} rive_aabb_t; + +typedef struct { + float mat[6]; +} rive_mat2d_t; + +typedef struct { + void* buffer; + size_t size; +} rive_span_t; + +typedef struct rive_file_t rive_file_t; +typedef struct rive_artboard_t rive_artboard_t; +typedef struct rive_scene_t rive_scene_t; +typedef struct rive_animation_t rive_animation_t; +typedef struct rive_statemachine_t rive_statemachine_t; + +typedef struct rive_factory_t rive_factory_t; +typedef struct rive_renderer_t rive_renderer_t; + +RIVE_C_PLUS_PLUS_END_GUARD + +#endif diff --git a/test/capi_test.cpp b/test/capi_test.cpp new file mode 100644 index 00000000..a7c5a4c5 --- /dev/null +++ b/test/capi_test.cpp @@ -0,0 +1,30 @@ +#include "capi/rive_api.h" + +#include "no_op_factory.hpp" +#include +#include + +static rive::NoOpFactory gNoOpFactory; + +static rive_file_t* loadfile(const char path[]) { + FILE* fp = fopen(path, "rb"); + REQUIRE(fp != nullptr); + + fseek(fp, 0, SEEK_END); + const size_t length = ftell(fp); + fseek(fp, 0, SEEK_SET); + std::vector bytes(length); + REQUIRE(fread(bytes.data(), 1, length, fp) == length); + fclose(fp); + + rive_span_t span = {bytes.data(), length}; + return rive_file_import(span, (rive_factory_t*)&gNoOpFactory); +} + +TEST_CASE("capi", "[file]") { + auto file = loadfile("../../test/assets/two_artboards.riv"); + + REQUIRE(rive_file_artboard_count(file) == 2); + + rive_file_delete(file); +}