From 8d280e93e2526b504f20973e04b6c32b2af1995d Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Wed, 27 Aug 2025 13:42:59 +0200 Subject: [PATCH] [sdl][glfw] Old and new docs --- spine-glfw/docs-new.md | 368 +++++++++++++++++++++++++++++++++++++++++ spine-glfw/docs.md | 333 +++++++++++++++++++++++++++++++++++++ spine-sdl/docs-new.md | 291 ++++++++++++++++++++++++++++++++ spine-sdl/docs.md | 213 ++++++++++++++++++++++++ 4 files changed, 1205 insertions(+) create mode 100644 spine-glfw/docs-new.md create mode 100644 spine-glfw/docs.md create mode 100644 spine-sdl/docs-new.md create mode 100644 spine-sdl/docs.md diff --git a/spine-glfw/docs-new.md b/spine-glfw/docs-new.md new file mode 100644 index 000000000..e7d7ba05d --- /dev/null +++ b/spine-glfw/docs-new.md @@ -0,0 +1,368 @@ +# spine-glfw Runtime Documentation + +> **Licensing** +> +> Please see the [Spine Runtimes License](/spine-runtimes-license) before integrating the Spine Runtimes into your applications. + +# Getting Started +spine-glfw is a C++ based runtime to load, manipulate and render Spine skeletons with [GLFW](https://www.glfw.org/) and OpenGL. + +spine-glfw requires GLFW 3.0+ and OpenGL 3.3+ and supports all Spine features. + +## Installation + +The spine-glfw runtime is available as a C++ API based on the generic [spine-cpp](/spine-cpp) runtime and also supports [spine-c](/spine-c) API. Note that spine-c depends on spine-cpp. + +### Integration with CMake (Recommended) + +The easiest way to integrate spine-glfw into your project is via CMake FetchContent: + +```cmake +cmake_minimum_required(VERSION 3.16) +project(MySpineProject) + +include(FetchContent) +FetchContent_Declare( + spine-glfw + GIT_REPOSITORY https://github.com/esotericsoftware/spine-runtimes.git + GIT_TAG 4.3 + SOURCE_SUBDIR spine-glfw +) +FetchContent_MakeAvailable(spine-glfw) + +# Create your executable +add_executable(MyApp main.cpp) + +# Link against spine-glfw (includes spine-cpp, spine-c, GLFW, and glbinding) +target_link_libraries(MyApp spine-glfw) +``` + +This will automatically fetch and build spine-glfw along with all its dependencies (spine-c, spine-cpp, GLFW, and glbinding). + +### Manual Integration + +If you prefer manual integration: + +1. Download the Spine Runtimes source using git (`git clone https://github.com/esotericsoftware/spine-runtimes`) or download as a zip. +2. Add the required source files to your project: + - Add sources from `spine-cpp/src`, `spine-c/src`, and `spine-glfw/src/spine-glfw.cpp` +3. Add the include directories: `spine-cpp/include`, `spine-c/include`, and `spine-glfw/src` +4. Link against GLFW, OpenGL, and glbinding libraries + +In your C++ code, include the following header file to get access to the `spine-glfw` API: + +```cpp +#include +``` + +> *Note:* spine-glfw requires OpenGL 3.3 Core Profile or higher. The runtime uses modern OpenGL features including vertex array objects, vertex buffer objects, and GLSL shaders. + +## Samples +The spine-glfw example works on Windows, Linux and Mac OS X. For a [spine-cpp](/spine-cpp) based example, see [example/main.cpp](/git/spine-runtimes/tree/spine-glfw/example/main.cpp), for a spine-c example see [example/main-c.cpp](/git/spine-runtimes/tree/spine-glfw/example/main-c.cpp). + +### Windows + +1. Install [Visual Studio Community](https://visualstudio.microsoft.com/downloads/). Make sure you install support for C++ and CMake. +2. Download the Spine Runtimes repository using git (`git clone https://github.com/esotericsoftware/spine-runtimes`) or download it as a zip. +3. Open Visual Studio Community, then open `spine-glfw/` via the **Open a local folder** button in the Visual Studio Community launcher. +4. Wait for CMake to finish, then select either `spine-glfw-example.exe` or `spine-glfw-example-c.exe` as the start-up project and start debugging. + +### Linux + +1. Install dependencies: + ```bash + sudo apt-get install cmake ninja-build libgl1-mesa-dev libx11-dev libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev # Ubuntu/Debian + # or equivalent for your distribution + ``` +2. Clone the repository: `git clone https://github.com/esotericsoftware/spine-runtimes` +3. Build and run: + ```bash + cd spine-runtimes/spine-glfw + ./build.sh + ./build/debug/spine-glfw-example-c # Run C example + ./build/debug/spine-glfw-example # Run C++ example + ``` + +### macOS + +1. Install [Xcode](https://developer.apple.com/xcode/) +2. Install [Homebrew](http://brew.sh/) +3. Install dependencies: + ```bash + brew install cmake ninja + ``` +4. Clone the repository: `git clone https://github.com/esotericsoftware/spine-runtimes` +5. Build and run: + ```bash + cd spine-runtimes/spine-glfw + ./build.sh + ./build/debug/spine-glfw-example-c # Run C example + ./build/debug/spine-glfw-example # Run C++ example + ``` + +## Using spine-glfw +The spine-glfw runtime supports playback and manipulation of animations created with Spine using [GLFW](https://www.glfw.org/) and OpenGL. The spine-glfw runtime is implemented in C++ and is based on the generic [spine-cpp](/spine-cpp) runtime. It adds loading and rendering implementations based on OpenGL APIs. + +Please consult the [Spine Runtimes Guide](/spine-runtimes) for a detailed overview of the Spine Runtime architecture, and the [spine-cpp](/spine-cpp) documentation for information on the core APIs used to playback and manipulate animations created with Spine with C++. + +### Exporting for GLFW +![](/img/spine-runtimes-guide/spine-ue4/export.png) +Please follow the instructions in the Spine User Guide on how to + +1. [Export skeleton & animation data](/spine-export) +2. [Export texture atlases containing the images of your skeleton](/spine-texture-packer) + +An export of the skeleton data and texture atlas of your skeleton will yield the following files: + +![](/img/spine-runtimes-guide/spine-ue4/exported-files.png) + +1. `skeleton-name.json` or `skeleton-name.skel`, containing your skeleton and animation data. +2. `skeleton-name.atlas`, containing information about the texture atlas. +3. One or more `.png` files, each representing on page of your texture atlas containing the packed images your skeleton uses. + +### Loading Spine skeletons +The spine-glfw runtime uses OpenGL for rendering skeletons. Before a skeleton can be loaded from exported files, a GLFW window and OpenGL context must be created: + +```cpp +// Initialize GLFW +if (!glfwInit()) { + // Handle error + return -1; +} + +// Set OpenGL version to 3.3 Core Profile +glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); +glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); +glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); + +// Create window +GLFWwindow* window = glfwCreateWindow(800, 600, "Spine GLFW", NULL, NULL); +glfwMakeContextCurrent(window); + +// Initialize OpenGL function loading (e.g., with glbinding) +glbinding::initialize(glfwGetProcAddress); +``` + +Next, the texture atlas can be loaded using the `GlTextureLoader`: + +```cpp +// C++ API +spine::GlTextureLoader textureLoader; +spine::Atlas *atlas = new spine::Atlas("data/spineboy-pma.atlas", &textureLoader); +``` + +With the atlas loaded, the `.json` or `.skel` file can be loaded: + +```cpp +// C++ API +spine::SkeletonBinary binary(*atlas); +spine::SkeletonData *skeletonData = binary.readSkeletonDataFile("data/spineboy-pro.skel"); +``` + +For JSON format: + +```cpp +// C++ API +spine::SkeletonJson json(*atlas); +spine::SkeletonData *skeletonData = json.readSkeletonDataFile("data/spineboy-pro.json"); +``` + +The `spine::Atlas` and `spine::SkeletonData` instances can then be used to create `spine::Skeleton` instances for rendering. + +> *Note:* the loaded skeleton data and atlas can and should be shared across `spine::Skeleton` instances to reduce memory consumption and enable batched rendering of skeletons that share the same atlas data. + +### Renderer +The main addition of spine-glfw on top of [spine-cpp](/spine-cpp) is the renderer system. The renderer handles the OpenGL rendering pipeline including shaders, meshes, and textures. Unlike other runtimes that provide a drawable class, spine-glfw uses a more modular approach with separate renderer and mesh components. + +You can create a renderer like this: + +```cpp +// Create the renderer and set viewport size +renderer_t *renderer = renderer_create(); +renderer_set_viewport_size(renderer, windowWidth, windowHeight); +``` + +The renderer automatically creates and manages OpenGL shaders optimized for Spine skeleton rendering. + +### Creating and animating skeletons +With the skeleton data loaded, you can create a skeleton instance: + +```cpp +// Set coordinate system (spine-glfw uses y-down by default) +spine::Bone::setYDown(true); + +// Create a skeleton from the data +spine::Skeleton skeleton(*skeletonData); +skeleton.setPosition(400, 500); +skeleton.setScaleX(0.5f); +skeleton.setScaleY(0.5f); +``` + +For animation, create an animation state: + +```cpp +// Create animation state +spine::AnimationStateData animationStateData(*skeletonData); +animationStateData.setDefaultMix(0.2f); +spine::AnimationState animationState(animationStateData); + +// Set animations +animationState.setAnimation(0, "portal", true); +animationState.addAnimation(0, "run", true, 0); +``` + +Please refer to the [spine-cpp](/spine-cpp) documentation for more information on the APIs to manipulate skeletons and animation states. + +### Updating and rendering +In your main loop, update the animation state and skeleton, then render: + +```cpp +double lastTime = glfwGetTime(); +while (!glfwWindowShouldClose(window)) { + double currTime = glfwGetTime(); + float delta = currTime - lastTime; + lastTime = currTime; + + // Update animation state + animationState.update(delta); + animationState.apply(skeleton); + + // Update skeleton + skeleton.update(delta); + skeleton.updateWorldTransform(spine::Physics_Update); + + // Clear screen + gl::glClear(gl::GL_COLOR_BUFFER_BIT); + + // Render skeleton + renderer_draw(renderer, &skeleton, true); // true for premultiplied alpha + + // Present + glfwSwapBuffers(window); + glfwPollEvents(); +} +``` + +### Using spine-c +spine-glfw also supports the [spine-c](/spine-c) API for applications that need a C interface or are written in programming languages that cannot interface with C++ code directly. The key differences when using spine-c with spine-glfw are: + +#### Key Differences from spine-cpp: + +1. **C API instead of C++**: All functions use C-style naming (e.g., `spine_skeleton_set_position` vs `skeleton.setPosition`) +2. **Manual file loading**: You must manually load atlas and skeleton files into memory +3. **Callback-based texture loading**: Textures are loaded via user-provided callback functions +4. **Skeleton drawable wrapper**: Uses `spine_skeleton_drawable` which wraps skeleton and animation state +5. **Different renderer function**: Uses `renderer_draw_c()` instead of `renderer_draw()` + +#### Texture Loading with Callbacks +First, you need to provide texture loading callbacks that bridge spine-c to spine-glfw's texture system: + +```cpp +// Callback function to load textures +void *load_texture(const char *path) { + return (void *)(uintptr_t)texture_load(path); +} + +// Callback function to unload textures +void unload_texture(void *texture) { + texture_dispose((texture_t)(uintptr_t)texture); +} +``` + +#### Loading Atlas and Skeleton Data +Unlike spine-cpp which can load files directly, spine-c requires manual file reading: + +```cpp +// Read atlas file into memory +int atlas_length = 0; +uint8_t *atlas_bytes = read_file("data/spineboy-pma.atlas", &atlas_length); +spine_atlas_result result = spine_atlas_load_callback( + (const char*)atlas_bytes, "data/", load_texture, unload_texture); +spine_atlas atlas = spine_atlas_result_get_atlas(result); + +// Read skeleton file into memory +int skeleton_length = 0; +uint8_t *skeleton_bytes = read_file("data/spineboy-pro.skel", &skeleton_length); +spine_skeleton_data_result result2 = spine_skeleton_data_load_binary( + atlas, skeleton_bytes, skeleton_length, "data/"); +spine_skeleton_data skeleton_data = spine_skeleton_data_result_get_data(result2); +``` + +#### Creating and Manipulating Skeletons +spine-c uses a drawable wrapper and C-style function calls: + +```cpp +// Create skeleton drawable (combines skeleton + animation state) +spine_skeleton_drawable drawable = spine_skeleton_drawable_create(skeleton_data); +spine_skeleton skeleton = spine_skeleton_drawable_get_skeleton(drawable); + +// Set skeleton properties using C functions +spine_skeleton_set_position(skeleton, width / 2, height - 100); +spine_skeleton_set_scale(skeleton, 0.3f, 0.3f); + +// Get animation state from drawable +spine_animation_state animation_state = spine_skeleton_drawable_get_animation_state(drawable); +spine_animation_state_data animation_state_data = spine_animation_state_get_data(animation_state); +spine_animation_state_data_set_default_mix(animation_state_data, 0.2f); + +// Set animations using C functions +spine_animation_state_set_animation_1(animation_state, 0, "portal", true); +spine_animation_state_add_animation_1(animation_state, 0, "run", true, 0); +``` + +#### Updating and Rendering +The update loop uses C-style function calls and a different renderer function: + +```cpp +// Update animation state and skeleton (full sequence required) +spine_animation_state_update(animation_state, delta); +spine_animation_state_apply(animation_state, skeleton); +spine_skeleton_update(skeleton, delta); +spine_skeleton_update_world_transform(skeleton, SPINE_PHYSICS_UPDATE); + +// Render using the C-specific function +renderer_draw_c(renderer, skeleton, true); +``` + +The `renderer_draw_c()` function is specifically designed to work with spine-c's `spine_skeleton` opaque type, while `renderer_draw()` works with spine-cpp's `spine::Skeleton` class. + +### Cleanup + +#### Cleanup for spine-cpp +When using the spine-cpp API, use C++ delete operators: + +```cpp +// Dispose renderer +renderer_dispose(renderer); + +// Dispose skeleton data and atlas (C++ API) +delete skeletonData; +delete atlas; + +// Cleanup GLFW +glfwTerminate(); +``` + +#### Cleanup for spine-c +When using the spine-c API, use the C-style dispose functions: + +```cpp +// Dispose renderer +renderer_dispose(renderer); + +// Dispose skeleton drawable and data (C API) +spine_skeleton_drawable_dispose(drawable); +spine_skeleton_data_dispose(skeleton_data); +spine_atlas_dispose(atlas); +spine_skeleton_data_result_dispose(result2); +spine_atlas_result_dispose(result); + +// Free manually allocated file data +free(atlas_bytes); +free(skeleton_bytes); + +// Cleanup GLFW +glfwTerminate(); +``` + +> *Note:* freeing skeleton data and atlas instances will automatically dispose of any associated OpenGL textures through the texture loader. With spine-c, you must also free any memory you allocated for file data using `malloc()`/`read_file()`. \ No newline at end of file diff --git a/spine-glfw/docs.md b/spine-glfw/docs.md new file mode 100644 index 000000000..fbb836966 --- /dev/null +++ b/spine-glfw/docs.md @@ -0,0 +1,333 @@ +# spine-glfw Runtime Documentation + +> **Licensing** +> +> Please see the [Spine Runtimes License](/spine-runtimes-license) before integrating the Spine Runtimes into your applications. + +# Getting Started +spine-glfw is a C++ based runtime to load, manipulate and render Spine skeletons with [GLFW](https://www.glfw.org/) and OpenGL. + +spine-glfw requires GLFW 3.0+ and OpenGL 3.3+ and supports all Spine features including [two-color tinting](https://en.esotericsoftware.com/spine-slots#Tint-black). + +## Installation + +The spine-glfw runtime is available as a C++ API based on the generic [spine-cpp](/spine-cpp) runtime and also supports [spine-c](/spine-c) API. To integrate spine-glfw into your project: + +1. Create a new GLFW project. See the [GLFW documentation](https://www.glfw.org/docs/latest/) or have a look at the example in [spine-runtimes repository](/git/spine-runtimes/tree/spine-glfw), which uses [CMake](https://cmake.org) as the build system. +2. Download the Spine Runtimes source using git (`git clone https://github.com/esotericsoftware/spine-runtimes`). +3. Add the sources from `spine-cpp/spine-cpp/src/spine` and the files `spine-glfw/src/spine-glfw.cpp` and `spine-glfw/src/spine-glfw.h` to your project. +4. Add the folders `spine-cpp/spine-cpp/include` and `spine-glfw/src` to your header search path. +5. Link against GLFW, OpenGL, and optionally glbinding for modern OpenGL function loading. + +In your C++ code, include the following header file to get access to the `spine-glfw` API: + +```cpp +#include +``` + +> *Note:* spine-glfw requires OpenGL 3.3 Core Profile or higher. The runtime uses modern OpenGL features including vertex array objects, vertex buffer objects, and GLSL shaders. + +## Samples +The spine-glfw example works on Windows, Linux and Mac OS X. For a [spine-cpp](/spine-cpp) based example, see [example/main.cpp](/git/spine-runtimes/tree/spine-glfw/example/main.cpp), for a spine-c example see [example/main-c.cpp](/git/spine-runtimes/tree/spine-glfw/example/main-c.cpp). + +### Windows + +1. Install [Visual Studio Community](https://visualstudio.microsoft.com/downloads/). Make sure you install support for C++ and CMake. +2. Download the Spine Runtimes repository using git (`git clone https://github.com/esotericsoftware/spine-runtimes`) or download it as a zip. +3. Open Visual Studio Community, then open `spine-glfw/` via the **Open a local folder** button in the Visual Studio Community launcher. +4. Wait for CMake to finish, then select either `spine-glfw-example.exe` or `spine-glfw-example-c.exe` as the start-up project and start debugging. + +### Linux + +1. Install dependencies: + ```bash + sudo apt-get install cmake ninja-build libgl1-mesa-dev libx11-dev libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev # Ubuntu/Debian + # or equivalent for your distribution + ``` +2. Clone the repository: `git clone https://github.com/esotericsoftware/spine-runtimes` +3. Build and run: + ```bash + cd spine-runtimes/spine-glfw + ./build.sh + ./build/debug/spine-glfw-example-c # Run C example + ./build/debug/spine-glfw-example # Run C++ example + ``` + +### macOS + +1. Install [Xcode](https://developer.apple.com/xcode/) +2. Install [Homebrew](http://brew.sh/) +3. Install dependencies: + ```bash + brew install cmake ninja + ``` +4. Clone the repository: `git clone https://github.com/esotericsoftware/spine-runtimes` +5. Build and run: + ```bash + cd spine-runtimes/spine-glfw + ./build.sh + ./build/debug/spine-glfw-example-c # Run C example + ./build/debug/spine-glfw-example # Run C++ example + ``` + +## Using spine-glfw +The spine-glfw runtime supports playback and manipulation of animations created with Spine using [GLFW](https://www.glfw.org/) and OpenGL. The spine-glfw runtime is implemented in C++ and is based on the generic [spine-cpp](/spine-cpp) runtime. It adds loading and rendering implementations based on OpenGL APIs. + +Please consult the [Spine Runtimes Guide](/spine-runtimes) for a detailed overview of the Spine Runtime architecture, and the [spine-cpp](/spine-cpp) documentation for information on the core APIs used to playback and manipulate animations created with Spine with C++. + +### Exporting for GLFW +![](/img/spine-runtimes-guide/spine-ue4/export.png) +Please follow the instructions in the Spine User Guide on how to + +1. [Export skeleton & animation data](/spine-export) +2. [Export texture atlases containing the images of your skeleton](/spine-texture-packer) + +An export of the skeleton data and texture atlas of your skeleton will yield the following files: + +![](/img/spine-runtimes-guide/spine-ue4/exported-files.png) + +1. `skeleton-name.json` or `skeleton-name.skel`, containing your skeleton and animation data. +2. `skeleton-name.atlas`, containing information about the texture atlas. +3. One or more `.png` files, each representing on page of your texture atlas containing the packed images your skeleton uses. + +> **Note:** The spine-glfw runtime does not support the screen blend mode available in the Spine editor. + +### Loading Spine skeletons +The spine-glfw runtime uses OpenGL for rendering skeletons. Before a skeleton can be loaded from exported files, a GLFW window and OpenGL context must be created: + +```cpp +// Initialize GLFW +if (!glfwInit()) { + // Handle error + return -1; +} + +// Set OpenGL version to 3.3 Core Profile +glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); +glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); +glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); + +// Create window +GLFWwindow* window = glfwCreateWindow(800, 600, "Spine GLFW", NULL, NULL); +glfwMakeContextCurrent(window); + +// Initialize OpenGL function loading (e.g., with glbinding) +glbinding::initialize(glfwGetProcAddress); +``` + +Next, the texture atlas can be loaded using the `GlTextureLoader`: + +```cpp +// C++ API +spine::GlTextureLoader textureLoader; +spine::Atlas *atlas = new spine::Atlas("data/spineboy-pma.atlas", &textureLoader); +``` + +With the atlas loaded, the `.json` or `.skel` file can be loaded: + +```cpp +// C++ API +spine::SkeletonBinary binary(atlas); +spine::SkeletonData *skeletonData = binary.readSkeletonDataFile("data/spineboy-pro.skel"); +``` + +For JSON format: + +```cpp +// C++ API +spine::SkeletonJson json(atlas); +spine::SkeletonData *skeletonData = json.readSkeletonDataFile("data/spineboy-pro.json"); +``` + +The `spine::Atlas` and `spine::SkeletonData` instances can then be used to create `spine::Skeleton` instances for rendering. + +> *Note:* the loaded skeleton data and atlas can and should be shared across `spine::Skeleton` instances to reduce memory consumption and enable batched rendering of skeletons that share the same atlas data. + +### Renderer +The main addition of spine-glfw on top of [spine-cpp](/spine-cpp) is the renderer system. The renderer handles the OpenGL rendering pipeline including shaders, meshes, and textures. Unlike other runtimes that provide a drawable class, spine-glfw uses a more modular approach with separate renderer and mesh components. + +You can create a renderer like this: + +```cpp +// Create the renderer and set viewport size +renderer_t *renderer = renderer_create(); +renderer_set_viewport_size(renderer, windowWidth, windowHeight); +``` + +The renderer automatically creates and manages OpenGL shaders optimized for Spine skeleton rendering. + +### Creating and animating skeletons +With the skeleton data loaded, you can create a skeleton instance: + +```cpp +// Set coordinate system (spine-glfw uses y-down by default) +spine::Bone::setYDown(true); + +// Create a skeleton from the data +spine::Skeleton skeleton(skeletonData); +skeleton.setPosition(400, 500); +skeleton.setScaleX(0.5f); +skeleton.setScaleY(0.5f); +``` + +For animation, create an animation state: + +```cpp +// Create animation state +spine::AnimationStateData animationStateData(skeletonData); +animationStateData.setDefaultMix(0.2f); +spine::AnimationState animationState(&animationStateData); + +// Set animations +animationState.setAnimation(0, "portal", true); +animationState.addAnimation(0, "run", true, 0); +``` + +Please refer to the [spine-cpp](/spine-cpp) documentation for more information on the APIs to manipulate skeletons and animation states. + +### Updating and rendering +In your main loop, update the animation state and skeleton, then render: + +```cpp +double lastTime = glfwGetTime(); +while (!glfwWindowShouldClose(window)) { + double currTime = glfwGetTime(); + float delta = currTime - lastTime; + lastTime = currTime; + + // Update animation state + animationState.update(delta); + animationState.apply(skeleton); + + // Update skeleton + skeleton.update(delta); + skeleton.updateWorldTransform(spine::Physics_Update); + + // Clear screen + gl::glClear(gl::GL_COLOR_BUFFER_BIT); + + // Render skeleton + renderer_draw(renderer, &skeleton, true); // true for premultiplied alpha + + // Present + glfwSwapBuffers(window); + glfwPollEvents(); +} +``` + +### Using spine-c +spine-glfw also supports the [spine-c](/spine-cpp-lite) API for applications that need a C interface or are written in programming languages that cannot interface with C++ code directly. The key differences when using spine-c with spine-glfw are: + +#### Key Differences from spine-cpp: + +1. **C API instead of C++**: All functions use C-style naming (e.g., `spine_skeleton_set_position` vs `skeleton.setPosition`) +2. **Manual file loading**: You must manually load atlas and skeleton files into memory +3. **Callback-based texture loading**: Textures are loaded via user-provided callback functions +4. **Skeleton drawable wrapper**: Uses `spine_skeleton_drawable` which wraps skeleton and animation state +5. **Different renderer function**: Uses `renderer_draw_c()` instead of `renderer_draw()` + +#### Texture Loading with Callbacks +First, you need to provide texture loading callbacks that bridge spine-cpp-lite to spine-glfw's texture system: + +```cpp +// Callback function to load textures +void *load_texture(const char *path) { + return (void *)(uintptr_t)texture_load(path); +} + +// Callback function to unload textures +void unload_texture(void *texture) { + texture_dispose((texture_t)(uintptr_t)texture); +} +``` + +#### Loading Atlas and Skeleton Data +Unlike spine-cpp which can load files directly, spine-c requires manual file reading: + +```cpp +// Read atlas file into memory +int atlas_length = 0; +uint8_t *atlas_bytes = read_file("data/spineboy-pma.atlas", &atlas_length); +spine_atlas atlas = spine_atlas_load_callback( + (utf8*)atlas_bytes, "data/", load_texture, unload_texture); + +// Read skeleton file into memory +int skeleton_length = 0; +uint8_t *skeleton_bytes = read_file("data/spineboy-pro.skel", &skeleton_length); +spine_skeleton_data_result result = spine_skeleton_data_load_binary(atlas, skeleton_bytes, skeleton_length); +spine_skeleton_data skeleton_data = spine_skeleton_data_result_get_data(result); +``` + +#### Creating and Manipulating Skeletons +spine-c uses a drawable wrapper and C-style function calls: + +```cpp +// Create skeleton drawable (combines skeleton + animation state) +spine_skeleton_drawable drawable = spine_skeleton_drawable_create(skeleton_data); +spine_skeleton skeleton = spine_skeleton_drawable_get_skeleton(drawable); + +// Set skeleton properties using C functions +spine_skeleton_set_position(skeleton, width / 2, height - 100); +spine_skeleton_set_scale(skeleton, 0.3f, 0.3f); + +// Get animation state from drawable +spine_animation_state animation_state = spine_skeleton_drawable_get_animation_state(drawable); +spine_animation_state_data animation_state_data = spine_animation_state_get_data(animation_state); +spine_animation_state_data_set_default_mix(animation_state_data, 0.2f); + +// Set animations using C functions +spine_animation_state_set_animation_1(animation_state, 0, "portal", true); +spine_animation_state_add_animation_1(animation_state, 0, "run", true, 0); +``` + +#### Updating and Rendering +The update loop uses C-style function calls and a different renderer function: + +```cpp +// Update animation state and skeleton +spine_skeleton_drawable_update(drawable, deltaTimeInSeconds) + +// Render using the C-specific function +renderer_draw_c(renderer, skeleton, true); +``` + +The `renderer_draw_c()` function is specifically designed to work with spine-c's `spine_skeleton` opaque type, while `renderer_draw()` works with spine-cpp's `spine::Skeleton` class. + +### Cleanup + +#### Cleanup for spine-cpp +When using the spine-cpp API, use C++ delete operators: + +```cpp +// Dispose renderer +renderer_dispose(renderer); + +// Dispose skeleton data and atlas (C++ API) +delete skeletonData; +delete atlas; + +// Cleanup GLFW +glfwTerminate(); +``` + +#### Cleanup for spine-c +When using the spine-c API, use the C-style dispose functions: + +```cpp +// Dispose renderer +renderer_dispose(renderer); + +// Dispose skeleton data and atlas (C API) +spine_skeleton_drawable_dispose(drawable); +spine_skeleton_data_dispose(skeleton_data); +spine_atlas_dispose(atlas); + +// Free manually allocated file data +free(atlas_bytes); +free(skeleton_bytes); + +// Cleanup GLFW +glfwTerminate(); +``` + +> *Note:* freeing skeleton data and atlas instances will automatically dispose of any associated OpenGL textures through the texture loader. With spine-c, you must also free any memory you allocated for file data using `malloc()`/`read_file()`. \ No newline at end of file diff --git a/spine-sdl/docs-new.md b/spine-sdl/docs-new.md new file mode 100644 index 000000000..1c646709c --- /dev/null +++ b/spine-sdl/docs-new.md @@ -0,0 +1,291 @@ +# spine-sdl Runtime Documentation + +> **Licensing** +> +> Please see the [Spine Runtimes License](/spine-runtimes-license) before integrating the Spine Runtimes into your applications. + +# Getting Started +spine-sdl is a C and C++ based runtime to load, manipulate and render Spine skeletons with [SDL](https://www.libsdl.org/). + +spine-sdl requires SDL 2.0.18+ and supports all Spine features except two-color tinting. + +## Installation + +The spine-sdl runtime is available as a C and C++ API. Both APIs are based on [spine-c](/spine-c) and [spine-cpp](/spine-cpp) runtimes. Note that spine-c depends on spine-cpp, so both are required regardless of which API you choose to use. + +### Integration with CMake (Recommended) + +The easiest way to integrate spine-sdl into your project is via CMake FetchContent: + +```cmake +cmake_minimum_required(VERSION 3.16) +project(MySpineProject) + +include(FetchContent) +FetchContent_Declare( + spine-sdl + GIT_REPOSITORY https://github.com/esotericsoftware/spine-runtimes.git + GIT_TAG 4.3 + SOURCE_SUBDIR spine-sdl +) +FetchContent_MakeAvailable(spine-sdl) + +# Create your executable +add_executable(MyApp main.cpp) + +# For C API +target_link_libraries(MyApp spine-sdl-c) + +# For C++ API +target_link_libraries(MyApp spine-sdl-cpp) +``` + +This will automatically fetch and build spine-sdl along with all its dependencies (spine-c, spine-cpp, and SDL). + +### Manual Integration + +If you prefer manual integration: + +1. Download the Spine Runtimes source using git (`git clone https://github.com/esotericsoftware/spine-runtimes`) or download as a zip. +2. Add the required source files to your project: + - For C API: Add sources from `spine-cpp/src`, `spine-c/src`, and `spine-sdl/src/spine-sdl-c.c` + - For C++ API: Add sources from `spine-cpp/src`, `spine-c/src`, and `spine-sdl/src/spine-sdl-cpp.cpp` +3. Add the include directories: `spine-cpp/include`, `spine-c/include`, and `spine-sdl/src` +4. Link against SDL2 + +In your C or C++ code, include either of the following header files to get access to the `spine-sdl` API: + +```cpp +// C API +#include + +// C++ API +#include +``` + +> *Note:* spine-sdl requires the [`SDL_RenderGeometry`](https://wiki.libsdl.org/SDL_RenderGeometry) API which is available since SDL 2.0.18. Earlier versions of SDL are not compatible with spine-sdl. + +## Samples +The spine-sdl example works on Windows, Linux and Mac OS X. For a [spine-c](/spine-c) based example, see [example/main.c](/git/spine-runtimes/tree/spine-sdl/example/main.c), for a spine-cpp example see [example/main.cpp](/git/spine-runtimes/tree/spine-sdl/example/main.cpp). + +### Windows + +1. Install [Visual Studio Community](https://visualstudio.microsoft.com/downloads/). Make sure you install support for C++ and CMake. +2. Download the Spine Runtimes repository using git (`git clone https://github.com/esotericsoftware/spine-runtimes`) or download it as a zip. +3. Open Visual Studio Community, then open `spine-sdl/` via the **Open a local folder** button in the Visual Studio Community launcher. +4. Wait for CMake to finish, then select either `spine-sdl-c-example.exe` or `spine-sdl-cpp-example.exe` as the start-up project and start debugging. + +### Linux + +1. Install dependencies: + ```bash + sudo apt-get install cmake ninja-build # Ubuntu/Debian + # or equivalent for your distribution + ``` +2. Clone the repository: `git clone https://github.com/esotericsoftware/spine-runtimes` +3. Build and run: + ```bash + cd spine-runtimes/spine-sdl + ./build.sh + ./build/debug/spine-sdl-c-example # Run C example + ./build/debug/spine-sdl-cpp-example # Run C++ example + ``` + +### macOS + +1. Install [Xcode](https://developer.apple.com/xcode/) +2. Install [Homebrew](http://brew.sh/) +3. Install dependencies: + ```bash + brew install cmake ninja + ``` +4. Clone the repository: `git clone https://github.com/esotericsoftware/spine-runtimes` +5. Build and run: + ```bash + cd spine-runtimes/spine-sdl + ./build.sh + ./build/debug/spine-sdl-c-example # Run C example + ./build/debug/spine-sdl-cpp-example # Run C++ example + ``` + +## Using spine-sdl +The spine-sdl runtime supports playback and manipulation of animations created with Spine with [SDL](https://www.libsdl.org). The spine-sdl runtime comes as both a C and C++ implementation, based on the generic [spine-c](/spine-c) and [spine-cpp](/spine-cpp) runtimes. It adds loading and rendering implementations based on the SDL APIs. + +Please consult the [Spine Runtimes Guide](/spine-runtimes) for a detailed overview of the Spine Runtime architecture, and the [spine-c](/spine-c) and [spine-cpp](/spine-cpp) documentation for information on the core APIs used to playback and manipulate animations created with Spine with C and C++. + +### Exporting for SDL +![](/img/spine-runtimes-guide/spine-ue4/export.png) +Please follow the instructions in the Spine User Guide on how to + +1. [Export skeleton & animation data](/spine-export) +2. [Export texture atlases containing the images of your skeleton](/spine-texture-packer) + +An export of the skeleton data and texture atlas of your skeleton will yield the following files: + +![](/img/spine-runtimes-guide/spine-ue4/exported-files.png) + +1. `skeleton-name.json` or `skeleton-name.skel`, containing your skeleton and animation data. +2. `skeleton-name.atlas`, containing information about the texture atlas. +3. One or more `.png` files, each representing on page of your texture atlas containing the packed images your skeleton uses. + +> **Note:** The spine-sdl runtime does not support two-color tinting. + +### Loading Spine skeletons +The spine-sdl runtime uses the [`SDL_Renderer`](https://wiki.libsdl.org/SDL_Renderer) API to display skeletons. Before a skeleton can be loaded from exported files, an `SDL_Renderer` must be created: + +```cpp +SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); +``` + +#### Loading with C API + +With the new spine-c API, loading requires texture loading callbacks and manual file reading: + +```cpp +// Global renderer for texture loading callbacks +static SDL_Renderer *g_renderer; + +// Texture loading callbacks +void *load_texture_callback(const char *path) { + extern void *load_texture(const char *path, SDL_Renderer *renderer); + return load_texture(path, g_renderer); +} + +void unload_texture_callback(void *texture) { + SDL_DestroyTexture((SDL_Texture*)texture); +} + +// Set the global renderer +g_renderer = renderer; + +// Read atlas file into memory +int atlas_length; +char *atlas_data = read_file("data/spineboy-pma.atlas", &atlas_length); + +// Load atlas with callbacks +spine_atlas_result atlas_result = spine_atlas_load_callback( + atlas_data, "data/", load_texture_callback, unload_texture_callback); +spine_atlas atlas = spine_atlas_result_get_atlas(atlas_result); + +// Read skeleton file into memory +int skeleton_length; +char *skeleton_data = read_file("data/spineboy-pro.json", &skeleton_length); + +// Load skeleton data +spine_skeleton_data_result skeleton_result = spine_skeleton_data_load_json( + atlas, skeleton_data, "data/"); +spine_skeleton_data skeleton_data_handle = spine_skeleton_data_result_get_data(skeleton_result); + +// Free file data +free(atlas_data); +free(skeleton_data); +``` + +#### Loading with C++ API + +For the C++ API, a `SDLTextureLoader` is needed: + +```cpp +// C++ API +spine::SDLTextureLoader textureLoader(renderer); +spine::Atlas atlas("data/spineboy-pma.atlas", &textureLoader); +spine::SkeletonJson json(atlas); +spine::SkeletonData *skeletonData = json.readSkeletonDataFile("data/spineboy-pro.json"); +``` + +The loaded skeleton data and atlas can and should be shared across skeleton instances to reduce memory consumption and enable batched rendering of skeletons that share the same atlas data. + +### Rendering Skeletons + +spine-sdl provides simple rendering functions that work directly with skeletons and skeleton drawables. + +#### C API + +```cpp +// Create skeleton drawable (combines skeleton + animation state) +spine_skeleton_drawable drawable = spine_skeleton_drawable_create(skeleton_data_handle); +spine_skeleton skeleton = spine_skeleton_drawable_get_skeleton(drawable); +spine_animation_state animation_state = spine_skeleton_drawable_get_animation_state(drawable); + +// Setup skeleton +spine_skeleton_set_position(skeleton, 400, 500); +spine_skeleton_set_scale(skeleton, 0.5f, 0.5f); +spine_skeleton_setup_pose(skeleton); + +// Setup animation +spine_animation_state_set_animation_1(animation_state, 0, "portal", false); +spine_animation_state_add_animation_1(animation_state, 0, "run", true, 0); + +// Update and render (in your main loop) +spine_skeleton_drawable_update(drawable, deltaTime); +spine_sdl_draw(drawable, renderer, true); // true for premultiplied alpha + +// Or draw skeleton directly without drawable +spine_sdl_draw_skeleton(skeleton, renderer, true); + +// Cleanup +spine_skeleton_drawable_dispose(drawable); +spine_skeleton_data_dispose(skeleton_data_handle); +spine_atlas_dispose(atlas); +spine_skeleton_data_result_dispose(skeleton_result); +spine_atlas_result_dispose(atlas_result); +``` + +#### C++ API + +```cpp +// Create skeleton and animation state +spine::Skeleton skeleton(*skeletonData); +spine::AnimationStateData animationStateData(*skeletonData); +spine::AnimationState animationState(animationStateData); + +// Setup skeleton +skeleton.setPosition(400, 500); +skeleton.setupPose(); + +// Setup animation +animationState.setAnimation(0, "portal", false); +animationState.addAnimation(0, "run", true, 0); + +// Update and render (in your main loop) +animationState.update(deltaTime); +animationState.apply(skeleton); +skeleton.update(deltaTime); +skeleton.updateWorldTransform(spine::Physics_Update); + +// Draw using the simple SDL_draw function +spine::SDL_draw(skeleton, renderer, true); // true for premultiplied alpha + +// Cleanup +delete skeletonData; +delete &atlas; +``` + +Please refer to the [spine-c](/spine-c) and [spine-cpp](/spine-cpp) documentation for more information on the APIs to manipulate skeletons and animation states. + +### Cleanup + +When you no longer need the skeleton and atlas data, free their memory: + +#### C API +```cpp +// Dispose skeleton drawable and data +spine_skeleton_drawable_dispose(drawable); +spine_skeleton_data_dispose(skeleton_data_handle); +spine_atlas_dispose(atlas); +spine_skeleton_data_result_dispose(skeleton_result); +spine_atlas_result_dispose(atlas_result); + +// Free manually allocated file data +free(atlas_data); +free(skeleton_data); +``` + +#### C++ API +```cpp +// C++ API cleanup +delete skeletonData; +delete &atlas; // If allocated with new +``` + +> *Note:* Freeing skeleton data and atlas instances will automatically dispose of any associated SDL textures through the texture loader. \ No newline at end of file diff --git a/spine-sdl/docs.md b/spine-sdl/docs.md new file mode 100644 index 000000000..a38f1a5c9 --- /dev/null +++ b/spine-sdl/docs.md @@ -0,0 +1,213 @@ +# spine-sdl Runtime Documentation + +> **Licensing** +> +> Please see the [Spine Runtimes License](/spine-runtimes-license) before integrating the Spine Runtimes into your applications. + +# Getting Started +spine-sdl is a C and C++ based runtime to load, manipulate and render Spine skeletons with [SDL](https://www.libsdl.org/). + +spine-sdl requires SDL +2.0 and supports all Spine features except [two-color tinting](https://en.esotericsoftware.com/spine-slots#Tint-black) + +## Installation + +The spine-sdl runtime is available as a C and C++ API. The C API is based on the generic [spine-c](/spine-c) runtime, the C++ API is based on generic [spine-cpp](/spine-cpp) runtime. To integrate spine-sdl into your project: + +1. Create a new SDL project. See the [SDL documentation](https://wiki.libsdl.org/FrontPage) or have a look at the example in [spine-runtimes repository](/git/spine-runtimes/tree/spine-sdl), which uses [CMake](https://cmake.org) as the build system. +2. Download the Spine Runtimes source using git (`git clone https://github.com/esotericsoftware/spine-runtimes`). +3. If you are using C: + * Add the sources from `spine-c/spine-c/src/spine` and the file `spine-sdl/src/spine-sdl-c.c` to your project. + * Add the folders `spine-c/spine-c/include` and `spine-sdl/src/` to your header search path. +3. If you are using C++: + * Add the sources from `spine-cpp/spine-cpp/src/spine` and the file `spine-sdl/src/spine-sdl-cpp.cpp` to your project. + * Add the folders `spine-cpp/spine-cpp/include` and `spine-sdl/src` to your header search path. + +In your C or C++ code, include either of the following header files to get access to the `spine-sdl` API: + +``` +// C API +#include + +// C++ API +#include +``` + +> *Note:* spine-sdl requires the [`SDL_RenderGeometry`](https://wiki.libsdl.org/SDL_RenderGeometry) API which is available since SDL 2.0.18. Earlier versions of SDL are not compatible with spine-sdl. + +## Samples +The spine-sdl example works on Windows, Linux and Mac OS X. For a [spine-c](/spine-c) based example, see [example/main.c](/git/spine-runtimes/tree/spine-sdl/example/main.c), for a spine-cpp example see [example/main.cpp](/git/spine-runtimes/tree/spine-sdl/example/main.cpp). + +### Windows +1. Install [Visual Studio Community](https://www.visualstudio.com/en-us/downloads/download-visual-studio-vs.aspx). Make sure you install support for C++ and CMake. +1. Download the Spine Runtimes repository using git (`git clone https://github.com/esotericsoftware/spine-runtimes`) or download it as a zip via the download button above. +1. Open Visual Studio Community, then open `spine-sdl/` via the `Open a local folder` button in the Visual Studio Community launcher +1. Wait for CMake to finish, then select either `spine-sdl-c-example.exe` or `spine-sdl-cpp-example.exe` as the start-up project and start debugging. + +The entire example code is contained in [main.cpp](/git/spine-runtimes/tree/spine-sdl/example/main.cpp#L61). + +### Linux +1. Install the [SDL build dependencies](https://github.com/libsdl-org/SDL/blob/main/docs/README-linux.md). +3. Download the Spine Runtimes repository using git (`git clone https://github.com/esotericsoftware/spine-runtimes`) or download it as a zip via the download button above. +4. Open a terminal, and `cd` into the `spine-runtimes/spine-sdl` folder. +5. Type `mkdir build && cd build && cmake ..` to generate Make files. +6. Type `make -j` to compile the example. +7. Run the example by `./spine-sdl-c-example` (C) or by `./spine-sdl-cpp-example` (C++). + +### Mac OS X +1. Install [Xcode](https://developer.apple.com/xcode/). +2. Install [Homebrew](http://brew.sh/). +3. Open a terminal and install CMake via `brew install cmake`. +3. Download the Spine Runtimes repository using git (`git clone https://github.com/esotericsoftware/spine-runtimes`) or download it as a zip via the download button above. +4. Open a terminal, and `cd` into the `spine-runtimes/spine-sdl` folder. +5. Type `mkdir build && cd build && cmake -G Xcode ..` to generate Make files. +6. Type `open spine-sdl.xcodeproj` to open the Xcode project. +7. Run the example `spine-sdl-c-example` (C) or spine-sdl-cpp-example` (C++). + +## Using spine-sdl +The spine-sdl runtime supports playback and manipulation of animations created with Spine with [SDL](https://www.libsdl.org). The spine-sdl runtime comes as both a C and C++ implementation, based on the generic [spine-c](/spine-c) and [spine-cpp](/spine-cpp) runtimes. It adds loading and rendering implementations based on the SDL APIs. + +Please consult the [Spine Runtimes Guide](/spine-runtimes) for a detailed overview of the Spine Runtime architecture, and the [spine-c](/spine-c) and [spine-cpp](/spine-cpp) documentation for information on the core APIs used to playback and manipulate animations created with Spine with C and C++. + +### Exporting for SDL +![](/img/spine-runtimes-guide/spine-ue4/export.png) +Please follow the instructions in the Spine User Guide on how to + +1. [Export skeleton & animation data](/spine-export) +2. [Export texture atlases containing the images of your skeleton](/spine-texture-packer) + +An export of the skeleton data and texture atlas of your skeleton will yield the following files: + +![](/img/spine-runtimes-guide/spine-ue4/exported-files.png) + +1. `skeleton-name.json` or `skeleton-name.skel`, containing your skeleton and animation data. +2. `skeleton-name.atlas`, containing information about the texture atlas. +3. One or more `.png` files, each representing on page of your texture atlas containing the packed images your skeleton uses. + +> **Note:** The spine-sdl runtime does also not support two color tinting and the screen blend mode available in the Spine editor. + +### Loading Spine skeletons +The spine-sdl runtime uses the [`SDL_Renderer`](https://wiki.libsdl.org/SDL_Renderer) API to display skeletons. Before a skeleton can be loaded from exported files, an `SDL_Renderer` must be created: + +``` +SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); +``` + +Next, the texture atlas can be loaded like this using the C API: + +``` +// C API +spAtlas *atlas = spAtlas_createFromFile("data/spineboy.atlas", renderer); + +``` + +For the C++ API, a `SDLTextureLoader` is needed: + +``` +// C++ API +spine::SDLTextureLoader textureLoader(renderer); +spine::Atlas atlas("data/spineboy.atlas", &textureLoader); + +``` + +With the atlas loaded, the `.json` or `.skel` file can be loaded using the C-API like this: + +``` +// C API +spSkeletonJson *json = spSkeletonJson_create(atlas); +spSkeletonData *skeletonData = spSkeletonJson_readSkeletonDataFile(json, "data/spineboy-pro.json"); +spSkeletonJson_dispose(json); +``` + +For the C++ API, loading of the skeleton file is achieved like this: + +``` +// C++ API +spine::AtlasAttachmentLoader attachmentLoader(&atlas); +spine::SkeletonJson json(&attachmentLoader); +spine::SkeletonData *skeletonData = json.readSkeletonDataFile("data/spineboy-pro.json"); +``` + +The `spAtlas`/`spine::Atlas` and `spSkeletonData`/`spine::SkeletonData` instances can then be used to create `spSkeletonDrawable`/`spine::SkeletonDrawable` instances to render the skeleton data. + +> *Note:* the loaded skeleton data and atlas can and should be shared across `spSkeletonDrawable`/`spine::SkeletonDrawable` instances to reduce memory consumption and enable batched rendering of skeletons that share the same atlas data. + +### Skeleton drawable +The main addition of spine-sdl on top of [spine-c](/spine-c) and [spine-cpp](/spine-cpp) is the skeleton drawable. It holds a `spSkeleton` (C API) or `spine::Skeleton` (C++ API), which stores the skeletons bones, slots, attachments, constraints and so on, and a `spAnimationState` (C API) or `spine::AnimationState`, which manages animating the skeleton. The skeleton drawable provides methods to update the animation state, apply it to the skeleton, update the skeleton and draw the skeleton using `SDL_Renderer`. + +You can creating a skeleton drawable using the C API like this: + +``` +// C API +spAnimationStateData *animationStateData = spAnimationStateData_create(skeletonData); +spSkeletonDrawable *drawable = spSkeletonDrawable_create(skeletonData, animationStateData); +``` + +The `spAnimationStateData` stores mix times between animations and is required to construct the internal `spAnimationState`. Please refer to the [spine-c](/spine-c) documentation for more information. + +For the C++ API, creating a skeleton drawable works like this: + +``` +// C++ API +spine::SkeletonDrawable drawable(skeletonData); +``` + +You can optionally pass a `spine::AnimationStateData` to the `spine::SkeletonDrawable` constructor if you want to share mix times between drawables. Please refer to the [spine-cpp](/spine-cpp) documentation for more information. + +With the skeleton drawable created, you can access the contained skeleton and animation state instances to manipulate them. + +``` +// C API +drawable->skeleton->x = 400; +drawable->skeleton->y = 500; +spSkeleton_setToSetupPose(drawable->skeleton); + +spAnimationState_setAnimationByName(drawable->animationState, 0, "portal", 0); +spAnimationState_addAnimationByName(drawable->animationState, 0, "run", -1, 0); +``` + +Or in C++: + +``` +// C++ API +drawable.skeleton->setPosition(400, 500); +drawable.skeleton->setToSetupPose(); + +drawable.animationState->setAnimation(0, "portal", true); +drawable.animationState->addAnimation(0, "run", true, 0); +``` + +Please refer to the [spine-c](/spine-c) and [spine-cpp](/spine-cpp) documentation for more information on the APIs to manipulate skeletons and animation states. + +The skeleton drawable also provides a method to conveniently update the skeleton and animation state it contains: + +``` +// C API +spSkeletonDrawable_update(drawable, deltaTimeInSeconds); + +// C++ API +drawable.update(deltaTimeInSeconds); +``` + +The update method takes the delta time between the last and current frame in seconds and then updates the animation state, applies the animation state to the skeleton, and finally udpates the world transforms of the skeleton. + +After the animation state and skeleton have been updated, it can be drawn: + +``` +// C API +spSkeletonDrawable_draw(drawable, renderer); + +// C++ API +drawable.draw(renderer); +``` + +Once you no longer need the skeleton drawable, you can free its memory via: + +``` +// C API +spSkeletonDrawable_dipose(drawable); + +// C++ API, if the drawable was allocated on the heap via new +delete drawable; +``` + +> *Note:* freeing a skeleton drawable does not free the skeleton data and atlas it was created from. The skeleton data and atlas need to be freed separately through the respective API (`spSkeletonData_dipose(skeletonData)`/`spAtlas_dispose(atlas)` in C, or `delete` in C++). \ No newline at end of file