加入5套spine官方运行时

This commit is contained in:
tianmo
2026-09-07 21:40:29 +08:00
parent 98e51a259e
commit 6837ecada9
935 changed files with 204665 additions and 8 deletions
@@ -0,0 +1,22 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "headless test (cpp)",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build/headless-test",
"args": [
"${workspaceFolder}/../examples/spineboy/export/spineboy-pro.json",
"${workspaceFolder}/../examples/spineboy/export/spineboy-pma.atlas",
"run"
],
"stopAtEntry": false,
"cwd": "${workspaceFolder}/build",
"environment": [],
"externalConsole": false,
"MIMode": "lldb",
"preLaunchTask": "CMake: build"
}
]
}
@@ -0,0 +1,54 @@
cmake_minimum_required(VERSION 3.10)
project(spine-cpp)
include(${CMAKE_CURRENT_LIST_DIR}/../flags.cmake)
option(SPINE_NO_FILE_IO "Disable file I/O operations" OFF)
include_directories(include)
file(GLOB INCLUDES "include/**/*.h")
file(GLOB SOURCES "src/**/*.cpp")
add_library(spine-cpp STATIC ${SOURCES} ${INCLUDES})
target_include_directories(spine-cpp PUBLIC include)
if(SPINE_NO_FILE_IO)
target_compile_definitions(spine-cpp PRIVATE SPINE_NO_FILE_IO)
endif()
# Install target
install(TARGETS spine-cpp EXPORT spine-cpp_TARGETS DESTINATION dist/lib)
install(FILES ${INCLUDES} DESTINATION dist/include)
# Export target
export(
EXPORT spine-cpp_TARGETS
FILE ${CMAKE_CURRENT_BINARY_DIR}/spine-cppTargets.cmake
NAMESPACE "Spine::")
# Optional tests
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
add_executable(headless-test ${CMAKE_CURRENT_SOURCE_DIR}/tests/HeadlessTest.cpp)
target_link_libraries(headless-test spine-cpp)
add_executable(map-test ${CMAKE_CURRENT_SOURCE_DIR}/tests/MapTest.cpp)
target_link_libraries(map-test spine-cpp)
enable_testing()
add_test(NAME map-test COMMAND map-test)
if(SPINE_NO_FILE_IO)
target_compile_definitions(headless-test PRIVATE SPINE_NO_FILE_IO)
endif()
# Static variants (Linux only, but not with sanitizers)
if(UNIX AND NOT APPLE AND NOT SPINE_SANITIZE)
add_executable(headless-test-static ${CMAKE_CURRENT_SOURCE_DIR}/tests/HeadlessTest.cpp)
target_link_libraries(headless-test-static spine-cpp)
target_link_options(headless-test-static PRIVATE -static)
if(SPINE_NO_FILE_IO)
target_compile_definitions(headless-test-static PRIVATE SPINE_NO_FILE_IO)
endif()
endif()
endif()
@@ -0,0 +1,35 @@
{
"version": 3,
"configurePresets": [
{
"name": "debug",
"displayName": "Debug Config",
"description": "Debug build using Ninja generator",
"generator": "Ninja",
"binaryDir": "${sourceDir}/build",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON"
}
},
{
"name": "release",
"inherits": "debug",
"displayName": "Release Config",
"description": "Release build using Ninja generator",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release"
}
}
],
"buildPresets": [
{
"name": "debug",
"configurePreset": "debug"
},
{
"name": "release",
"configurePreset": "release"
}
]
}
@@ -0,0 +1,26 @@
Spine Runtimes License Agreement
Last updated April 5, 2025. Replaces all prior versions.
Copyright (c) 2013-2025, Esoteric Software LLC
Integration of the Spine Runtimes into software or otherwise creating
derivative works of the Spine Runtimes is permitted under the terms and
conditions of Section 2 of the Spine Editor License Agreement:
https://esotericsoftware.com/spine-editor-license
Otherwise, it is permitted to integrate the Spine Runtimes into software
or otherwise create derivative works of the Spine Runtimes (collectively,
"Products"), provided that each user of the Products must obtain their own
Spine Editor license and redistribution of the Products in any form must
include this license and copyright notice.
THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,56 @@
# spine-cpp
The spine-cpp runtime provides basic functionality to load and manipulate [spine](http://esotericsoftware.com) skeletal animation data using C++. It does not perform rendering but can be extended to enable spine animations for other projects that utilize C++.
## Licensing
You are welcome to evaluate the Spine Runtimes and the examples we provide in this repository free of charge.
You can integrate the Spine Runtimes into your software free of charge, but users of your software must have their own [Spine license](https://esotericsoftware.com/spine-purchase). Please make your users aware of this requirement! This option is often chosen by those making development tools, such as an SDK, game toolkit, or software library.
In order to distribute your software containing the Spine Runtimes to others that don't have a Spine license, you need a [Spine license](https://esotericsoftware.com/spine-purchase) at the time of integration. Then you can distribute your software containing the Spine Runtimes however you like, provided others don't modify it or use it to create new software. If others want to do that, they'll need their own Spine license.
For the official legal terms governing the Spine Runtimes, please read the [Spine Runtimes License Agreement](http://esotericsoftware.com/spine-runtimes-license) and Section 2 of the [Spine Editor License Agreement](http://esotericsoftware.com/spine-editor-license#s2).
## Spine version
spine-cpp works with data exported from spine 4.3.xx.
spine-cpp supports all spine features.
## Usage
### [Please see the spine-cpp guide for full documentation](http://esotericsoftware.com/spine-cpp)
## Setup
### Manual Copy
1. Download the spine Runtimes source using [git](https://help.github.com/articles/set-up-git) or by downloading it as a zip via the download button above.
2. Copy the contents of the `spine-cpp/spine-cpp/src` and `spine-cpp/spine-cpp/include` directories into your project. Be sure your header search is configured to find the contents of the `spine-cpp/spine-cpp/include` directory. Note that the includes use `spine/Xxx.h`, so the `spine` directory cannot be omitted when copying the files.
### CMake
You can use CMake's FetchContent to include spine-cpp in your project:
```cmake
include(FetchContent)
FetchContent_Declare(
spine-runtimes
GIT_REPOSITORY https://github.com/EsotericSoftware/spine-runtimes.git
GIT_TAG 4.3
)
FetchContent_MakeAvailable(spine-runtimes)
add_subdirectory(${spine-runtimes_SOURCE_DIR}/spine-cpp ${spine-runtimes_BINARY_DIR}/spine-cpp)
target_link_libraries(your_target PRIVATE spine-cpp)
```
## Runtimes extending spine-cpp
- [spine-glfw](../spine-glfw)
- [spine-sdl](../spine-sdl)
- [spine-sfml](../spine-sfml/cpp)
- [spine-godot](../spine-godot)
- [spine-ue](../spine-ue)
- [spine-flutter (via spine-c & FFI)](../spine-flutter)
- [spine-ios (via spine-c & FFI)](../spine-ios)
+68
View File
@@ -0,0 +1,68 @@
#!/bin/bash
set -e
cd "$(dirname "$0")"
# Source logging utilities
source ../formatters/logging/logging.sh
# Parse arguments
BUILD_TYPE="debug"
NOFILEIO=""
SANITIZE=""
CLEAN=""
for arg in "$@"; do
case $arg in
clean)
CLEAN="true"
;;
release)
BUILD_TYPE="release"
;;
debug)
BUILD_TYPE="debug"
;;
nofileio)
NOFILEIO="-DSPINE_NO_FILE_IO=ON"
;;
sanitize)
SANITIZE="-DSPINE_SANITIZE=ON"
;;
*)
log_fail "Unknown argument: $arg"
log_detail "Usage: $0 [clean] [release|debug] [nofileio] [sanitize]"
exit 1
;;
esac
done
log_title "spine-cpp build"
# Clean if requested
if [ "$CLEAN" = "true" ]; then
log_action "Cleaning build directory"
rm -rf build
log_ok
fi
# Configure and build
log_action "Configuring $BUILD_TYPE build"
if CMAKE_OUTPUT=$(cmake --preset=$BUILD_TYPE $NOFILEIO $SANITIZE . 2>&1); then
log_ok
else
log_fail
log_error_output "$CMAKE_OUTPUT"
exit 1
fi
log_action "Building"
if BUILD_OUTPUT=$(cmake --build --preset=$BUILD_TYPE 2>&1); then
log_ok
else
log_fail
log_error_output "$BUILD_OUTPUT"
exit 1
fi
log_summary "✓ Build successful"
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,184 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_Animation_h
#define Spine_Animation_h
#include <spine/Array.h>
#include <spine/Color.h>
#include <spine/Map.h>
#include <spine/SpineObject.h>
#include <spine/SpineString.h>
#include <spine/Property.h>
#include <spine/Timeline.h>
namespace spine {
class Timeline;
class BoneTimeline;
class Skeleton;
class Event;
class AnimationState;
/// Stores a list of timelines to animate a skeleton's pose over time.
///
/// See <a href='https://esotericsoftware.com/spine-applying-animations#Timeline-API'>Applying Animations</a> in the Spine
/// Runtimes Guide.
class SP_API Animation : public SpineObject {
friend class AnimationState;
friend class TrackEntry;
friend class AnimationStateData;
friend class AttachmentTimeline;
friend class RGBATimeline;
friend class RGBTimeline;
friend class AlphaTimeline;
friend class RGBA2Timeline;
friend class RGB2Timeline;
friend class DeformTimeline;
friend class DrawOrderTimeline;
friend class EventTimeline;
friend class IkConstraintTimeline;
friend class PathConstraintMixTimeline;
friend class PathConstraintPositionTimeline;
friend class PathConstraintSpacingTimeline;
friend class RotateTimeline;
friend class ScaleTimeline;
friend class ShearTimeline;
friend class TransformConstraintTimeline;
friend class TranslateTimeline;
friend class TranslateXTimeline;
friend class TranslateYTimeline;
friend class TwoColorTimeline;
friend class Slider;
public:
/// Creates a new animation. The timelines must be set before use.
Animation(const String &name);
~Animation();
/// If this list or the timelines it contains are modified, the timelines and bones must be set again to recompute the
/// animation's bone indices and timeline property IDs.
///
/// See setTimelines().
Array<Timeline *> &getTimelines();
/// Sets the timelines and bone indices.
void setTimelines(Array<Timeline *> &timelines, Array<int> &bones);
/// Returns true if this animation contains a timeline with any of the specified property IDs.
bool hasTimeline(Array<PropertyId> &ids);
/// The duration of the animation in seconds, which is usually the highest time of all frames in the timeline. The duration is
/// used to know when it has completed and when it should loop back to the start.
float getDuration();
void setDuration(float inValue);
/// Applies the animation's timelines to the specified skeleton.
///
/// See Timeline::apply() and
/// <a href='https://esotericsoftware.com/spine-applying-animations#Timeline-API'>Applying Animations</a> in the Spine
/// Runtimes Guide.
/// @param skeleton The skeleton the animation is applied to. This provides access to the bones, slots, and other skeleton
/// components the timelines may change.
/// @param lastTime The last time in seconds this animation was applied. Some timelines trigger only at discrete times, in
/// which case all keys are triggered between lastTime (exclusive) and time (inclusive). Pass -1 the first time an
/// animation is applied to ensure frame 0 is triggered.
/// @param time The time in seconds the skeleton is being posed for. Timelines find the frame before and after this time and
/// interpolate between the frame values.
/// @param loop True if time beyond the animation duration repeats the animation, else the last frame is used.
/// @param events If any events are fired, they are added to this list. Can be NULL to ignore fired events or if no timelines
/// fire events.
/// @param alpha 0 applies setup or current values (depending on from), 1 uses timeline values, and intermediate values
/// interpolate between them. Adjusting alpha over time can mix an animation in or out.
/// @param from If true, alpha transitions between setup and timeline values, setup values are used before the first
/// frame (current values are not used). If false, alpha transitions between current and timeline values, no change
/// is made before the first frame.
/// @param add If true, for timelines that support it, their values are added to the setup or current values (depending on
/// from).
/// @param out True when the animation is mixing out, else it is mixing in. Used by timelines that perform instant
/// transitions.
/// @param appliedPose True to modify getAppliedPose(), else the unconstrained pose is modified.
void apply(Skeleton &skeleton, float lastTime, float time, bool loop, Array<Event *> *events, float alpha, MixFrom from, bool add, bool out,
bool appliedPose);
/// The animation's name, which is unique across all animations in the skeleton.
const String &getName();
/// The Skeleton::getBones() indices affected by this animation.
///
/// See setTimelines() and BoneTimeline::getBoneIndex().
const Array<int> &getBones();
/// The color of the animation as it was in Spine, or a default color if nonessential data was not exported.
Color &getColor();
/// @param target After the first and before the last entry.
static int search(Array<float> &values, float target);
static int search(Array<float> &values, float target, int step);
protected:
Array<Timeline *> _timelines;
Map<PropertyId, bool> _timelineIds;
Array<int> _bones;
float _duration;
String _name;
Color _color;
};
}
#endif /* Spine_Animation_h */
@@ -0,0 +1,619 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_AnimationState_h
#define Spine_AnimationState_h
#include <spine/Array.h>
#include <spine/Map.h>
#include <spine/Pool.h>
#include <spine/Property.h>
#include <spine/SpineObject.h>
#include <spine/SpineString.h>
#include <spine/Timeline.h>
#include <spine/HasRendererObject.h>
#include <spine/Interpolation.h>
#include "Slot.h"
#ifdef SPINE_USE_STD_FUNCTION
#include <functional>
#endif
namespace spine {
enum EventType {
EventType_Start = 0,
EventType_Interrupt,
EventType_End,
EventType_Dispose,
EventType_Complete,
EventType_Event
};
class AnimationState;
class TrackEntry;
class Animation;
class Event;
class AnimationStateData;
class Skeleton;
class RotateTimeline;
class AttachmentTimeline;
#ifdef SPINE_USE_STD_FUNCTION
typedef std::function<void(AnimationState *state, EventType type, TrackEntry *entry, Event *event)> AnimationStateListener;
#else
typedef void (*AnimationStateListener)(AnimationState *state, EventType type, TrackEntry *entry, Event *event, void *userData);
#endif
/// Abstract class to inherit from to create a callback object
class SP_API AnimationStateListenerObject {
public:
AnimationStateListenerObject() {};
virtual ~AnimationStateListenerObject() {};
public:
/// The callback function to be called
virtual void callback(AnimationState *state, EventType type, TrackEntry *entry, Event *event) = 0;
};
/// State for the playback of an animation
class SP_API TrackEntry : public SpineObject, public HasRendererObject {
friend class EventQueue;
friend class AnimationState;
public:
TrackEntry();
virtual ~TrackEntry();
/// The index of the track where this entry is either current or queued.
int getTrackIndex();
/// The animation to apply for this track entry.
Animation &getAnimation();
/// Sets the animation for this track entry.
void setAnimation(Animation &animation);
TrackEntry *getPrevious();
/// If true, the animation will repeat. If false, it will not, instead its last frame is applied if played beyond its duration.
bool getLoop();
void setLoop(bool inValue);
/// When true, timelines in this animation that support additive have their values added to the setup or current pose values
/// instead of replacing them. Additive can be set for a new track entry only before AnimationState::apply() is next called.
bool getAdditive();
void setAdditive(bool inValue);
bool getReverse();
void setReverse(bool inValue);
bool getShortestRotation();
void setShortestRotation(bool inValue);
/// Seconds to postpone playing the animation. Must be >= 0. When this track entry is the current track entry,
/// delay postpones incrementing the track time. When this track entry is queued, delay is the time from the start of the
/// previous animation to when this track entry will become the current track entry (ie when the previous track entry's track
/// time >= this track entry's delay).
///
/// Time scale affects the delay.
///
/// When passing delay <= 0 to AnimationState::addAnimation(int, Animation, bool, float), this delay is set using a mix
/// duration from AnimationStateData. To change the mix duration afterward, use setMixDuration(float, float) so this delay is
/// adjusted.
float getDelay();
void setDelay(float inValue);
/// The time in seconds this track entry has been the current track entry, starting at 0 and increasing forever.
/// Compare to getAnimationTime(), which is always between animationStart and animationEnd.
///
/// The track time can be set to start the animation at a time other than 0, without affecting looping. When doing so,
/// animationLast can be set to the same value to avoid firing events from the start of the animation.
float getTrackTime();
void setTrackTime(float inValue);
/// The track time in seconds when this animation will be removed from the track. Defaults to the highest possible float
/// value, meaning the animation will be applied until a new animation is set or the track is cleared. If the track end time
/// is reached, no other animations are queued for playback, and mixing from any previous animations is complete, then the
/// properties keyed by the animation are set to the setup pose and the track is cleared.
///
/// It may be desired to use AnimationState::addEmptyAnimation(int, float, float) rather than have the animation
/// abruptly cease being applied, leaving the current pose.
float getTrackEnd();
void setTrackEnd(float inValue);
/// The time in seconds for the first frame of this animation, both initially and after looping. Defaults to 0.
///
/// When setting the animation start time, animationLast can be set to the same value to avoid firing events from the
/// start of the animation.
float getAnimationStart();
void setAnimationStart(float inValue);
/// The time in seconds for the last frame of this animation. Past this time, non-looping animations hold the pose at this
/// time while looping animations will loop back to animationStart. Defaults to the animation duration.
float getAnimationEnd();
void setAnimationEnd(float inValue);
/// The time in seconds this animation was last applied. Some timelines use this for one-time triggers. Eg, when this
/// animation is applied, event timelines will fire all events between the animation last time (exclusive) and animation time
/// (inclusive). Defaults to -1 to ensure triggers on frame 0 happen the first time this animation is applied.
float getAnimationLast();
void setAnimationLast(float inValue);
/// Uses the track time to compute animationTime, which is always between animationStart and animationEnd. When trackTime is
/// 0, animationTime is equal to animationStart.
float getAnimationTime();
/// Multiplier for the delta time when this track entry is updated, causing time for this animation to pass slower or
/// faster. Defaults to 1.
///
/// Values < 0 are not supported. To play an animation in reverse, use reverse.
///
/// mixTime is not affected by track entry time scale, so mixDuration may need to be adjusted to match the animation speed.
///
/// When using AnimationState::addAnimation(int, Animation, bool, float) with a delay <= 0, delay is set using the mix
/// duration from AnimationStateData, assuming time scale to be 1. If the time scale is not 1, the delay may need to be
/// adjusted.
///
/// See AnimationState::getTimeScale() for affecting all animations.
float getTimeScale();
void setTimeScale(float inValue);
/// Values less than 1 mix this animation with the last skeleton pose. Defaults to 1, which overwrites the last skeleton pose with
/// this animation.
///
/// Typically track 0 is used to completely pose the skeleton, then alpha can be used on higher tracks. It doesn't make sense
/// to use alpha on track 0 if the skeleton pose is from the last frame render.
float getAlpha();
void setAlpha(float inValue);
///
/// When the interpolated mix percentage is less than the event threshold, event timelines for the animation being mixed out
/// will be applied. Defaults to 0, so event timelines are not applied for an animation being mixed out.
float getEventThreshold();
void setEventThreshold(float inValue);
/// When the interpolated mix percentage is less than the attachment threshold, attachment timelines for the animation being
/// mixed out will be applied. Defaults to 0, so attachment timelines are not applied for an animation being mixed out.
float getMixAttachmentThreshold();
void setMixAttachmentThreshold(float inValue);
/// When the computed alpha is greater than alphaAttachmentThreshold, attachment timelines are applied. The computed alpha
/// includes alpha and the interpolated mix percentage. Defaults to 0, so attachment timelines are always applied.
float getAlphaAttachmentThreshold();
void setAlphaAttachmentThreshold(float inValue);
/// When the interpolated mix percentage is less than the draw order threshold, draw order timelines for the animation being
/// mixed out will be applied. Defaults to 0, so draw order timelines are not applied for an animation being mixed out.
float getMixDrawOrderThreshold();
void setMixDrawOrderThreshold(float inValue);
/// The animation queued to start after this animation, or NULL.
TrackEntry *getNext();
/// Returns true if at least one loop has been completed.
bool isComplete();
/// Seconds from 0 to the mix duration when mixing from the previous animation to this animation. May be slightly more than
/// mixDuration when the mix is complete.
float getMixTime();
void setMixTime(float inValue);
/// Seconds for mixing from the previous animation to this animation. Defaults to the value provided by
/// AnimationStateData based on the animation before this animation (if any).
///
/// The mix duration can be set manually rather than use the value from AnimationStateData.GetMix.
/// In that case, the mixDuration must be set before AnimationState.update(float) is next called.
///
/// When using AnimationState::addAnimation(int, Animation, bool, float) with a delay
/// less than or equal to 0, note the Delay is set using the mix duration from the AnimationStateData
float getMixDuration();
void setMixDuration(float inValue);
/// Sets both mixDuration and delay.
/// @param delay If > 0, sets delay. If <= 0, the delay set is the duration of the previous track
/// entry minus the specified mix duration plus the specified delay (ie the mix ends at
/// (delay = 0) or before (delay < 0) the previous track entry duration). If the previous
/// entry is looping, its next loop completion is used instead of its duration.
void setMixDuration(float mixDuration, float delay);
/// The interpolation to apply to the mix percentage (mix time / mix duration) when mixing from the previous animation to
/// this animation. Defaults to linear.
Interpolation &getMixInterpolation();
void setMixInterpolation(Interpolation &mixInterpolation);
/// The track entry for the previous animation when mixing to this animation, or NULL if no mixing is currently occurring.
/// When mixing from multiple animations, MixingFrom makes up a doubly linked list with MixingTo.
TrackEntry *getMixingFrom();
/// The track entry for the next animation when mixing from this animation, or NULL if no mixing is currently occurring.
/// When mixing to multiple animations, MixingTo makes up a doubly linked list with MixingFrom.
TrackEntry *getMixingTo();
/// Resets the rotation directions for mixing this entry's rotate timelines. This can be useful to avoid bones rotating the
/// long way around when using alpha and starting animations on other tracks.
///
/// Mixing involves finding a rotation between two others, which has two possible solutions: the short way or the long way around.
/// The two rotations likely change over time, so which direction is the short or long way also changes.
/// If the short way was always chosen, bones would flip to the other side when that direction became the long way.
/// TrackEntry chooses the short way the first time it is applied and remembers that direction.
void resetRotationDirections();
float getTrackComplete();
#ifdef SPINE_USE_STD_FUNCTION
void setListener(AnimationStateListener listener);
#else
void setListener(AnimationStateListener listener, void *userData = NULL);
#endif
void setListener(AnimationStateListenerObject *listener);
/// Returns true if this entry is for the empty animation.
bool isEmptyAnimation();
/// Returns true if this track entry has been applied at least once.
///
/// See AnimationState::apply(Skeleton).
bool wasApplied();
/// Returns true if there is a next track entry that is ready to become the current track entry during the
/// next AnimationState::update(float)}
bool isNextReady() {
return _next != NULL && _nextTrackLast - _next->_delay >= 0;
}
// The AnimationState this track entry belongs to. May be NULL if TrackEntry is directly instantiated.
AnimationState *getAnimationState() {
return _state;
}
void setAnimationState(AnimationState *state) {
_state = state;
}
private:
Animation *_animation;
TrackEntry *_previous;
TrackEntry *_next;
TrackEntry *_mixingFrom;
TrackEntry *_mixingTo;
int _trackIndex;
bool _loop, _additive, _reverse, _shortestRotation, _keepHold;
float _eventThreshold, _mixAttachmentThreshold, _alphaAttachmentThreshold, _mixDrawOrderThreshold;
float _animationStart, _animationEnd, _animationLast, _nextAnimationLast;
float _delay, _trackTime, _trackLast, _nextTrackLast, _trackEnd, _timeScale;
float _alpha, _mixTime, _mixDuration, _totalAlpha;
Interpolation *_mixInterpolation;
Array<int> _timelineMode;
Array<TrackEntry *> _timelineHoldMix;
Array<float> _timelinesRotation;
AnimationStateListener _listener;
#ifndef SPINE_USE_STD_FUNCTION
void *_listenerUserData;
#endif
AnimationStateListenerObject *_listenerObject;
AnimationState *_state;
float mix();
void reset();
};
class SP_API EventQueueEntry : public SpineObject {
friend class EventQueue;
public:
EventType _type;
TrackEntry *_entry;
Event *_event;
EventQueueEntry(EventType eventType, TrackEntry *trackEntry, Event *event = NULL);
};
class SP_API EventQueue : public SpineObject {
friend class AnimationState;
private:
Array<EventQueueEntry> _eventQueueEntries;
AnimationState &_state;
bool _drainDisabled;
static EventQueue *newEventQueue(AnimationState &state);
static EventQueueEntry newEventQueueEntry(EventType eventType, TrackEntry *entry, Event *event = NULL);
EventQueue(AnimationState &state);
~EventQueue();
void start(TrackEntry *entry);
void interrupt(TrackEntry *entry);
void end(TrackEntry *entry);
void dispose(TrackEntry *entry);
void complete(TrackEntry *entry);
void event(TrackEntry *entry, Event *event);
/// Raises all events in the queue and drains the queue.
void drain();
};
/// Applies animations over time, queues animations for later playback, mixes (crossfading) between animations, and applies
/// multiple animations on top of each other (layering).
///
/// See <a href='https://esotericsoftware.com/spine-applying-animations#AnimationState-API'>Applying Animations</a> in the
/// Spine Runtimes Guide.
class SP_API AnimationState : public SpineObject, public HasRendererObject {
friend class TrackEntry;
friend class EventQueue;
public:
explicit AnimationState(AnimationStateData &data);
~AnimationState();
/// Increments each track entry's track time, setting queued animations as current if needed.
void update(float delta);
/// Poses the skeleton using the track entry animations. The animation state is not changed, so can be applied to multiple
/// skeletons to pose them identically.
/// @return True if any animations were applied.
bool apply(Skeleton &skeleton);
/// Removes all animations from all tracks, leaving skeletons in their current pose.
///
/// It may be desired to use AnimationState::setEmptyAnimations(float) to mix the skeletons back to the setup pose,
/// rather than leaving them in their current pose.
void clearTracks();
/// Removes all animations from the track, leaving skeletons in their current pose.
///
/// It may be desired to use AnimationState::setEmptyAnimation(int, float) to mix the skeletons back to the setup pose,
/// rather than leaving them in their current pose.
void clearTrack(size_t trackIndex);
/// Sets an animation by name.
///
/// See setAnimation(int, Animation, bool).
TrackEntry &setAnimation(size_t trackIndex, const String &animationName, bool loop);
/// Sets the current animation for a track, discarding any queued animations.
///
/// If the formerly current track entry is for the same animation and was never applied to a skeleton, it is replaced (not mixed
/// from).
/// @param loop If true, the animation will repeat.
/// If false, it will not, instead its last frame is applied if played beyond its duration.
/// In either case TrackEntry.TrackEnd determines when the track is cleared.
/// @return
/// A track entry to allow further customization of animation playback. References to the track entry must not be kept
/// after AnimationState.Dispose.
TrackEntry &setAnimation(size_t trackIndex, Animation &animation, bool loop);
/// Queues an animation by name.
///
/// See addAnimation(int, Animation, bool, float).
TrackEntry &addAnimation(size_t trackIndex, const String &animationName, bool loop, float delay);
/// Adds an animation to be played delay seconds after the current or last queued animation
/// for a track. If the track has no entries, this is equivalent to calling setAnimation.
/// @param delay
/// Seconds to begin this animation after the start of the previous animation. May be &lt;= 0 to use the animation
/// duration of the previous track minus any mix duration plus the negative delay.
///
/// @return A track entry to allow further customization of animation playback. References to the track entry must not be kept
/// after AnimationState.Dispose
TrackEntry &addAnimation(size_t trackIndex, Animation &animation, bool loop, float delay);
/// Sets an empty animation for a track, discarding any queued animations, and sets the track entry's
/// TrackEntry::getMixDuration(). An empty animation has no timelines and serves as a placeholder for mixing in or out.
///
/// Mixing out is done by setting an empty animation with a mix duration using either setEmptyAnimation(int, float),
/// setEmptyAnimations(float), or addEmptyAnimation(int, float, float). Mixing to an empty animation causes
/// the previous animation to be applied less and less over the mix duration. Properties keyed in the previous animation
/// transition to the value from lower tracks or to the setup pose value if no lower tracks key the property. A mix duration of
/// 0 still mixes out over one frame.
///
/// Mixing in is done by first setting an empty animation, then adding an animation using
/// addAnimation(int, Animation, bool, float) with the desired delay (an empty animation has a duration of 0) and on
/// the returned track entry set TrackEntry::setMixDuration(float). Mixing from an empty animation causes the new
/// animation to be applied more and more over the mix duration. Properties keyed in the new animation transition from the value
/// from lower tracks or from the setup pose value if no lower tracks key the property to the value keyed in the new animation.
///
/// See <a href='https://esotericsoftware.com/spine-applying-animations#Empty-animations'>Empty animations</a> in the Spine
/// Runtimes Guide.
TrackEntry &setEmptyAnimation(size_t trackIndex, float mixDuration);
/// Adds an empty animation to be played after the current or last queued animation for a track, and sets the track entry's
/// TrackEntry::getMixDuration(). If the track has no entries, it is equivalent to calling
/// setEmptyAnimation(int, float).
///
/// See setEmptyAnimation(int, float) and
/// <a href='https://esotericsoftware.com/spine-applying-animations#Empty-animations'>Empty animations</a> in the Spine
/// Runtimes Guide.
/// @param delay If > 0, sets TrackEntry::getDelay(). If <= 0, the delay set is the duration of the previous track entry
/// minus any mix duration plus the specified <code>delay</code> (ie the mix ends at (<code>delay</code> = 0) or before
/// (<code>delay</code> < 0) the previous track entry duration). If the previous entry is looping, its next loop completion
/// is used instead of its duration.
/// @return A track entry to allow further customization of animation playback. References to the track entry must not be kept
/// after the AnimationStateListener::dispose(TrackEntry) event occurs.
TrackEntry &addEmptyAnimation(size_t trackIndex, float mixDuration, float delay);
/// Sets an empty animation for every track, discarding any queued animations, and mixes to it over the specified mix duration.
///
/// See <a href='https://esotericsoftware.com/spine-applying-animations#Empty-animations'>Empty animations</a> in the Spine
/// Runtimes Guide.
void setEmptyAnimations(float mixDuration);
/// @return The track entry for the animation currently playing on the track, or NULL if no animation is currently playing.
TrackEntry *getTrack(size_t trackIndex);
/// The AnimationStateData to look up mix durations.
AnimationStateData &getData();
/// The list of tracks that have had animations, which may contain null entries for tracks that currently have no animation.
Array<TrackEntry *> &getTracks();
/// Multiplier for the delta time when the animation state is updated, causing time for all animations and mixes to play slower
/// or faster. Defaults to 1.
///
/// See TrackEntry::getTimeScale() for affecting a single animation.
float getTimeScale();
void setTimeScale(float inValue);
/// Adds a listener to receive events for all track entries.
#ifdef SPINE_USE_STD_FUNCTION
void setListener(AnimationStateListener listener);
#else
void setListener(AnimationStateListener listener, void *userData = NULL);
#endif
/// Adds a listener to receive events for all track entries.
void setListener(AnimationStateListenerObject *listener);
void disableQueue();
void enableQueue();
void setManualTrackEntryDisposal(bool inValue);
bool getManualTrackEntryDisposal();
void disposeTrackEntry(TrackEntry *entry);
private:
static const int Current = 0;
static const int Setup = 1;
static const int First = 2;
static const int Mode = 3;
static const int Hold = 4;
static const int AttachSetup = 1;
static const int AttachRetain = 2;
AnimationStateData *_data;
Pool<TrackEntry> _trackEntryPool;
Array<TrackEntry *> _tracks;
Array<Event *> _events;
EventQueue *_queue;
Map<PropertyId, TrackEntry *> _propertyIDs;
bool _animationsChanged;
AnimationStateListener _listener;
#ifndef SPINE_USE_STD_FUNCTION
void *_listenerUserData;
#endif
AnimationStateListenerObject *_listenerObject;
int _unkeyedState;
float _timeScale;
bool _manualTrackEntryDisposal;
static Animation *getEmptyAnimation();
/// Applies the rotate timeline, mixing with the current pose while keeping the same rotation direction chosen as the shortest
/// the first time the mixing was applied.
static void applyRotateTimeline(RotateTimeline *rotateTimeline, Skeleton &skeleton, float time, float alpha, MixFrom from,
Array<float> &timelinesRotation, size_t i, bool firstFrame);
/// Applies the attachment timeline and sets Slot::attachmentState.
/// @param retain True if the attachment remains after apply, false if temporary for deform timelines.
void applyAttachmentTimeline(AttachmentTimeline *attachmentTimeline, Skeleton &skeleton, float animationTime, MixFrom from, bool retain);
/// Returns true when all mixing from entries are complete.
bool updateMixingFrom(TrackEntry *to, float delta);
float applyMixingFrom(TrackEntry *to, Skeleton &skeleton);
void queueEvents(TrackEntry *entry, float animationTime);
void eventsReverse(TrackEntry *entry, float animationLast, float animationTime);
/// Sets the active TrackEntry for a given track number.
void setTrack(size_t index, TrackEntry *current, bool interrupt);
/// Removes the specified entry's next track entry and all entries after it.
void clearNext(TrackEntry *entry);
TrackEntry *expandToIndex(size_t index);
/// Object-pooling version of new TrackEntry. Obtain an unused TrackEntry from the pool and clear/initialize its values.
/// @param last May be NULL.
TrackEntry *newTrackEntry(size_t trackIndex, Animation *animation, bool loop, TrackEntry *last);
void animationsChanged();
void computeHold(TrackEntry *entry, TrackEntry *track);
int from(TrackEntry *track, Timeline *timeline, Array<PropertyId> &ids);
};
}
#endif /* Spine_AnimationState_h */
@@ -0,0 +1,95 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_AnimationStateData_h
#define Spine_AnimationStateData_h
#include <spine/Map.h>
#include <spine/SpineObject.h>
#include <spine/SpineString.h>
#include <assert.h>
namespace spine {
class SkeletonData;
class Animation;
/// Stores mix (crossfade) durations to be applied when AnimationState animations are changed on the same track.
class SP_API AnimationStateData : public SpineObject {
friend class AnimationState;
public:
explicit AnimationStateData(SkeletonData &skeletonData);
/// The SkeletonData to look up animations when they are specified by name.
SkeletonData &getSkeletonData();
/// The mix duration to use when no mix duration has been specifically defined between two animations.
float getDefaultMix();
void setDefaultMix(float inValue);
/// Sets a mix duration by animation names.
void setMix(const String &fromName, const String &toName, float duration);
/// Sets a mix duration when changing from the specified animation to the other.
/// See TrackEntry.MixDuration.
void setMix(Animation &from, Animation &to, float duration);
/// Returns the mix duration to use when changing from the specified animation to the other on the same track,
/// or the default mix if no mix duration has been set.
float getMix(Animation &from, Animation &to);
/// Removes all mixes and sets the default mix to 0.
void clear();
private:
class AnimationPair : public SpineObject {
public:
Animation *_a1;
Animation *_a2;
explicit AnimationPair(Animation *a1 = NULL, Animation *a2 = NULL);
bool operator==(const AnimationPair &other) const;
};
class AnimationPairHash {
public:
size_t operator()(const AnimationPair &pair) const;
};
SkeletonData *_skeletonData;
float _defaultMix;
Map<AnimationPair, float, AnimationPairHash> _animationToMixTime;
};
}
#endif /* Spine_AnimationStateData_h */
@@ -0,0 +1,249 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_Array_h
#define Spine_Array_h
#include <spine/Extension.h>
#include <spine/SpineObject.h>
#include <spine/SpineString.h>
#include <assert.h>
namespace spine {
template<typename T>
class SP_API Array : public SpineObject {
public:
using size_type = size_t;
using value_type = T;
Array() : _size(0), _capacity(0), _buffer(NULL) {
}
Array(size_t capacity) : _size(0), _capacity(0), _buffer(NULL) {
ensureCapacity(capacity);
}
Array(const Array &inArray) : _size(inArray._size), _capacity(inArray._capacity), _buffer(NULL) {
if (_capacity > 0) {
_buffer = allocate(_capacity);
for (size_t i = 0; i < _size; ++i) {
construct(_buffer + i, inArray._buffer[i]);
}
}
}
~Array() {
clear();
deallocate(_buffer);
}
inline void clear() {
for (size_t i = 0; i < _size; ++i) {
destroy(_buffer + (_size - 1 - i));
}
_size = 0;
}
inline size_t getCapacity() const {
return _capacity;
}
inline size_t size() const {
return _size;
}
inline Array<T> &setSize(size_t newSize, const T &defaultValue) {
size_t oldSize = _size;
_size = newSize;
if (_capacity < newSize) {
if (_capacity == 0) {
_capacity = _size;
} else {
_capacity = (int) (_size * 1.75f);
}
if (_capacity < 8) _capacity = 8;
_buffer = SpineExtension::realloc<T>(_buffer, _capacity, __FILE__, __LINE__);
}
if (oldSize < _size) {
for (size_t i = oldSize; i < _size; i++) {
construct(_buffer + i, defaultValue);
}
} else {
for (size_t i = _size; i < oldSize; i++) {
destroy(_buffer + i);
}
}
return *this;
}
inline void ensureCapacity(size_t newCapacity = 0) {
if (_capacity >= newCapacity) return;
_capacity = newCapacity;
_buffer = SpineExtension::realloc<T>(_buffer, newCapacity, __FILE__, __LINE__);
}
inline void add(const T &inValue) {
if (_size == _capacity) {
// inValue might reference an element in this buffer
// When we reallocate, the reference becomes invalid.
// We thus need to create a defensive copy before
// reallocating.
T valueCopy = inValue;
_capacity = (int) (_size * 1.75f);
if (_capacity < 8) _capacity = 8;
_buffer = SpineExtension::realloc<T>(_buffer, _capacity, __FILE__, __LINE__);
construct(_buffer + _size++, valueCopy);
} else {
construct(_buffer + _size++, inValue);
}
}
inline void addAll(const Array<T> &inValue) {
ensureCapacity(this->size() + inValue.size());
for (size_t i = 0; i < inValue.size(); i++) {
add(inValue[i]);
}
}
inline void clearAndAddAll(const Array<T> &inValue) {
ensureCapacity(inValue.size());
for (size_t i = 0; i < inValue.size(); i++) _buffer[i] = inValue[i];
_size = inValue.size();
}
inline void removeAt(size_t inIndex) {
assert(inIndex < _size);
--_size;
if (inIndex != _size) {
for (size_t i = inIndex; i < _size; ++i) {
T tmp(_buffer[i]);
_buffer[i] = _buffer[i + 1];
_buffer[i + 1] = tmp;
}
}
destroy(_buffer + _size);
}
inline bool contains(const T &inValue) {
for (size_t i = 0; i < _size; ++i) {
if (_buffer[i] == inValue) {
return true;
}
}
return false;
}
inline int indexOf(const T &inValue) {
for (size_t i = 0; i < _size; ++i) {
if (_buffer[i] == inValue) {
return (int) i;
}
}
return -1;
}
inline T &operator[](size_t inIndex) {
assert(inIndex < _size);
return _buffer[inIndex];
}
inline const T &operator[](size_t inIndex) const {
assert(inIndex < _size);
return _buffer[inIndex];
}
inline friend bool operator==(Array<T> &lhs, Array<T> &rhs) {
if (lhs.size() != rhs.size()) {
return false;
}
for (size_t i = 0, n = lhs.size(); i < n; ++i) {
if (lhs[i] != rhs[i]) {
return false;
}
}
return true;
}
inline friend bool operator!=(Array<T> &lhs, Array<T> &rhs) {
return !(lhs == rhs);
}
Array &operator=(const Array &inArray) {
if (this != &inArray) {
clearAndAddAll(inArray);
}
return *this;
}
inline T *buffer() {
return _buffer;
}
private:
size_t _size;
size_t _capacity;
T *_buffer;
inline T *allocate(size_t n) {
assert(n > 0);
T *ptr = SpineExtension::calloc<T>(n, __FILE__, __LINE__);
assert(ptr);
return ptr;
}
inline void deallocate(T *buffer) {
if (_buffer) {
SpineExtension::free(buffer, __FILE__, __LINE__);
}
}
inline void construct(T *buffer, const T &val) {
new (buffer) T(val);
}
inline void destroy(T *buffer) {
buffer->~T();
}
};
}
#endif /* Spine_Array_h */
@@ -0,0 +1,128 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_ContainerUtil_h
#define Spine_ContainerUtil_h
#include <spine/Extension.h>
#include <spine/Array.h>
#include <spine/SpineObject.h>
#include <spine/SpineString.h>
#include <assert.h>
namespace spine {
class SP_API ArrayUtils : public SpineObject {
public:
/// Finds an item by comparing each item's name.
/// It is more efficient to cache the results of this method than to call it multiple times.
/// @return May be NULL.
template<typename T>
static T *findWithName(Array<T *> &items, const String &name) {
assert(name.length() > 0);
for (size_t i = 0; i < items.size(); ++i) {
T *item = items[i];
if (item->getName() == name) {
return item;
}
}
return NULL;
}
/// @return -1 if the item was not found.
template<typename T>
static int findIndexWithName(Array<T *> &items, const String &name) {
assert(name.length() > 0);
for (size_t i = 0, len = items.size(); i < len; ++i) {
T *item = items[i];
if (item->getName() == name) {
return static_cast<int>(i);
}
}
return -1;
}
/// Finds an item by comparing each item's name.
/// It is more efficient to cache the results of this method than to call it multiple times.
/// @return May be NULL.
template<typename T>
static T *findWithDataName(Array<T *> &items, const String &name) {
assert(name.length() > 0);
for (size_t i = 0; i < items.size(); ++i) {
T *item = items[i];
if (item->getData().getName() == name) {
return item;
}
}
return NULL;
}
/// @return -1 if the item was not found.
template<typename T>
static int findIndexWithDataName(Array<T *> &items, const String &name) {
assert(name.length() > 0);
for (size_t i = 0, len = items.size(); i < len; ++i) {
T *item = items[i];
if (item->getData().getName() == name) {
return static_cast<int>(i);
}
}
return -1;
}
template<typename T>
static void deleteElements(Array<T *> &items) {
for (int i = (int) items.size() - 1; i >= 0; i--) {
T *item = items[i];
delete item;
items.removeAt(i);
}
}
private:
// ctor, copy ctor, and assignment should be private in a Singleton
ArrayUtils();
ArrayUtils(const ArrayUtils &);
ArrayUtils &operator=(const ArrayUtils &);
};
}
#endif /* Spine_ContainerUtil_h */
@@ -0,0 +1,273 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_Atlas_h
#define Spine_Atlas_h
#include <spine/Array.h>
#include <spine/Extension.h>
#include <spine/SpineObject.h>
#include <spine/SpineString.h>
#include <spine/HasRendererObject.h>
#include "TextureRegion.h"
#include "spine/MeshAttachment.h"
#include "spine/RegionAttachment.h"
namespace spine {
enum Format {
Format_Alpha,
Format_Intensity,
Format_LuminanceAlpha,
Format_RGB565,
Format_RGBA4444,
Format_RGB888,
Format_RGBA8888
};
// Our TextureFilter collides with UE4's TextureFilter in unity builds. We rename
// TextureFilter to SpineTextureFilter in UE4.
#ifdef SPINE_UE4
enum SpineTextureFilter {
TextureFilter_Unknown,
TextureFilter_Nearest,
TextureFilter_Linear,
TextureFilter_MipMap,
TextureFilter_MipMapNearestNearest,
TextureFilter_MipMapLinearNearest,
TextureFilter_MipMapNearestLinear,
TextureFilter_MipMapLinearLinear
};
#else
enum TextureFilter {
TextureFilter_Unknown,
TextureFilter_Nearest,
TextureFilter_Linear,
TextureFilter_MipMap,
TextureFilter_MipMapNearestNearest,
TextureFilter_MipMapLinearNearest,
TextureFilter_MipMapNearestLinear,
TextureFilter_MipMapLinearLinear
};
#endif
enum TextureWrap {
TextureWrap_MirroredRepeat,
TextureWrap_ClampToEdge,
TextureWrap_Repeat
};
class SP_API AtlasPage : public SpineObject {
public:
String name;
String texturePath;
Format format;
#ifdef SPINE_UE4
SpineTextureFilter minFilter;
SpineTextureFilter magFilter;
#else
TextureFilter minFilter;
TextureFilter magFilter;
#endif
TextureWrap uWrap;
TextureWrap vWrap;
int width, height;
bool pma;
int index;
void *texture;
explicit AtlasPage(const String &inName)
: name(inName), format(Format_RGBA8888), minFilter(TextureFilter_Nearest), magFilter(TextureFilter_Nearest),
uWrap(TextureWrap_ClampToEdge), vWrap(TextureWrap_ClampToEdge), width(0), height(0), pma(false), index(0), texture(nullptr) {
}
};
class SP_API AtlasRegion : public TextureRegion {
friend class Atlas;
friend class RegionAttachment;
friend class MeshAttachment;
RTTI_DECL
public:
AtlasRegion()
: TextureRegion(), _page(nullptr), _name(""), _index(0), _x(0), _y(0), _offsetX(0), _offsetY(0), _packedWidth(0), _packedHeight(0),
_originalWidth(0), _originalHeight(0), _rotate(false), _degrees(0) {
}
~AtlasRegion() {
}
AtlasPage *getPage() const {
return _page;
}
const String &getName() const {
return _name;
}
int getIndex() const {
return _index;
}
int getX() const {
return _x;
}
int getY() const {
return _y;
}
float getOffsetX() const {
return _offsetX;
}
float getOffsetY() const {
return _offsetY;
}
int getPackedWidth() const {
return _packedWidth;
}
int getPackedHeight() const {
return _packedHeight;
}
int getOriginalWidth() const {
return _originalWidth;
}
int getOriginalHeight() const {
return _originalHeight;
}
bool getRotate() const {
return _rotate;
}
int getDegrees() const {
return _degrees;
}
Array<int> &getSplits() {
return _splits;
}
Array<int> &getPads() {
return _pads;
}
Array<String> &getNames() {
return _names;
}
Array<float> &getValues() {
return _values;
}
void setPage(AtlasPage *value) {
_page = value;
}
void setName(const String &value) {
_name = value;
}
void setIndex(int value) {
_index = value;
}
void setX(int value) {
_x = value;
}
void setY(int value) {
_y = value;
}
void setOffsetX(float value) {
_offsetX = value;
}
void setOffsetY(float value) {
_offsetY = value;
}
void setPackedWidth(int value) {
_packedWidth = value;
}
void setPackedHeight(int value) {
_packedHeight = value;
}
void setOriginalWidth(int value) {
_originalWidth = value;
}
void setOriginalHeight(int value) {
_originalHeight = value;
}
void setRotate(bool value) {
_rotate = value;
}
void setDegrees(int value) {
_degrees = value;
}
void setSplits(const Array<int> &value) {
_splits = value;
}
void setPads(const Array<int> &value) {
_pads = value;
}
void setNames(const Array<String> &value) {
_names = value;
}
void setValues(const Array<float> &value) {
_values = value;
}
private:
AtlasPage *_page;
String _name;
int _index;
int _x, _y;
float _offsetX, _offsetY;
int _packedWidth, _packedHeight;
int _originalWidth, _originalHeight;
bool _rotate;
int _degrees;
Array<int> _splits;
Array<int> _pads;
Array<String> _names;
Array<float> _values;
};
class TextureLoader;
class SP_API Atlas : public SpineObject {
public:
Atlas(const String &path, TextureLoader *textureLoader, bool createTexture = true);
Atlas(const char *data, int length, const char *dir, TextureLoader *textureLoader, bool createTexture = true);
~Atlas();
void flipV();
/// Returns the first region found with the specified name. This method uses String comparison to find the region, so the result
/// should be cached rather than calling this method multiple times.
/// @return The region, or nullptr.
AtlasRegion *findRegion(const String &name);
Array<AtlasPage *> &getPages();
Array<AtlasRegion *> &getRegions();
private:
Array<AtlasPage *> _pages;
Array<AtlasRegion *> _regions;
TextureLoader *_textureLoader;
void load(const char *begin, int length, const char *dir, bool createTexture);
};
}// namespace spine
#endif /* Spine_Atlas_h */
@@ -0,0 +1,71 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_AtlasAttachmentLoader_h
#define Spine_AtlasAttachmentLoader_h
#include <spine/AttachmentLoader.h>
#include <spine/Array.h>
#include <spine/SpineString.h>
namespace spine {
class Atlas;
class AtlasRegion;
/// An AttachmentLoader that configures attachments using texture regions from an Atlas.
///
/// See https://esotericsoftware.com/spine-loading-skeleton-data#JSON-and-binary-data Loading skeleton data in the
/// Spine Runtimes Guide.
class SP_API AtlasAttachmentLoader : public AttachmentLoader {
public:
explicit AtlasAttachmentLoader(Atlas &atlas);
virtual RegionAttachment *newRegionAttachment(Skin &skin, const String &placeholder, const String &name, const String &path,
Sequence *sequence);
virtual MeshAttachment *newMeshAttachment(Skin &skin, const String &placeholder, const String &name, const String &path, Sequence *sequence);
virtual BoundingBoxAttachment *newBoundingBoxAttachment(Skin &skin, const String &placeholder, const String &name);
virtual PathAttachment *newPathAttachment(Skin &skin, const String &placeholder, const String &name);
virtual PointAttachment *newPointAttachment(Skin &skin, const String &placeholder, const String &name);
virtual ClippingAttachment *newClippingAttachment(Skin &skin, const String &placeholder, const String &name);
AtlasRegion *findRegion(const String &name);
private:
Atlas *_atlas;
};
}
#endif /* Spine_AtlasAttachmentLoader_h */
@@ -0,0 +1,81 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_Attachment_h
#define Spine_Attachment_h
#include <spine/Array.h>
#include <spine/RTTI.h>
#include <spine/SpineObject.h>
#include <spine/SpineString.h>
namespace spine {
class Slot;
/// The base class for all attachments. Multiple Skeleton instances, slots, or skins can use the same attachments.
class SP_API Attachment : public SpineObject {
RTTI_DECL_NOPARENT
public:
explicit Attachment(const String &name);
virtual ~Attachment();
const String &getName() const;
virtual Attachment &copy() = 0;
Attachment *getTimelineAttachment();
void setTimelineAttachment(Attachment *attachment);
Array<int> &getTimelineSlots();
void setTimelineSlots(Array<int> &timelineSlots);
/// Returns true if the slotIndex or any getTimelineSlots() have an attachment whose getTimelineAttachment() is this attachment.
/// @param slots The Skeleton::getSlots().
/// @param slotIndex The timeline's primary slot index.
bool isTimelineActive(Array<Slot *> &slots, int slotIndex, bool appliedPose);
int getRefCount();
void reference();
void dereference();
private:
const String _name;
Attachment *_timelineAttachment;
Array<int> _timelineSlots;
int _refCount;
};
}
#endif /* Spine_Attachment_h */
@@ -0,0 +1,82 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_AttachmentLoader_h
#define Spine_AttachmentLoader_h
#include <spine/RTTI.h>
#include <spine/SpineObject.h>
#include <spine/SpineString.h>
namespace spine {
class Skin;
class Attachment;
class RegionAttachment;
class MeshAttachment;
class BoundingBoxAttachment;
class PathAttachment;
class PointAttachment;
class ClippingAttachment;
class Sequence;
class SP_API AttachmentLoader : public SpineObject {
public:
AttachmentLoader();
virtual ~AttachmentLoader();
/// @return May be NULL to not load any attachment.
virtual RegionAttachment *newRegionAttachment(Skin &skin, const String &placeholder, const String &name, const String &path,
Sequence *sequence) = 0;
/// @return May be NULL to not load any attachment.
virtual MeshAttachment *newMeshAttachment(Skin &skin, const String &placeholder, const String &name, const String &path,
Sequence *sequence) = 0;
/// @return May be NULL to not load any attachment.
virtual BoundingBoxAttachment *newBoundingBoxAttachment(Skin &skin, const String &placeholder, const String &name) = 0;
/// @return May be NULL to not load any attachment
virtual PathAttachment *newPathAttachment(Skin &skin, const String &placeholder, const String &name) = 0;
virtual PointAttachment *newPointAttachment(Skin &skin, const String &placeholder, const String &name) = 0;
virtual ClippingAttachment *newClippingAttachment(Skin &skin, const String &placeholder, const String &name) = 0;
};
}
#endif /* Spine_AttachmentLoader_h */
@@ -0,0 +1,88 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_AttachmentTimeline_h
#define Spine_AttachmentTimeline_h
#include <spine/Timeline.h>
#include <spine/SpineObject.h>
#include <spine/Array.h>
#include <spine/SpineString.h>
#include <spine/SlotTimeline.h>
namespace spine {
class Skeleton;
class Slot;
class SlotPose;
class Event;
class SP_API AttachmentTimeline : public Timeline, public SlotTimeline {
friend class SkeletonBinary;
friend class SkeletonJson;
RTTI_DECL
public:
explicit AttachmentTimeline(size_t frameCount, int slotIndex);
virtual ~AttachmentTimeline();
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixFrom from, bool add, bool out,
bool appliedPose) override;
/// Sets the time and attachment name for the specified frame.
/// @param frame Between 0 and frameCount, inclusive.
/// @param time The frame time in seconds.
void setFrame(int frame, float time, const String &attachmentName);
/// The attachment name for each frame. May contain null values to clear the attachment.
Array<String> &getAttachmentNames();
virtual int getSlotIndex() override {
return _slotIndex;
}
virtual void setSlotIndex(int inValue) override {
_slotIndex = inValue;
}
protected:
int _slotIndex;
Array<String> _attachmentNames;
void setAttachment(Skeleton &skeleton, SlotPose &pose, String *attachmentName);
};
}
#endif /* Spine_AttachmentTimeline_h */
@@ -0,0 +1,66 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_AttachmentType_h
#define Spine_AttachmentType_h
#include <string.h>
namespace spine {
enum AttachmentType {
AttachmentType_Region,
AttachmentType_Boundingbox,
AttachmentType_Mesh,
AttachmentType_Linkedmesh,
AttachmentType_Path,
AttachmentType_Point,
AttachmentType_Clipping
};
inline AttachmentType AttachmentType_valueOf(const char *value) {
if (strcmp(value, "region") == 0)
return AttachmentType_Region;
else if (strcmp(value, "mesh") == 0)
return AttachmentType_Mesh;
else if (strcmp(value, "linkedmesh") == 0)
return AttachmentType_Linkedmesh;
else if (strcmp(value, "boundingbox") == 0)
return AttachmentType_Boundingbox;
else if (strcmp(value, "path") == 0)
return AttachmentType_Path;
else if (strcmp(value, "clipping") == 0)
return AttachmentType_Clipping;
else if (strcmp(value, "point") == 0)
return AttachmentType_Point;
else
return AttachmentType_Region;// default
}
}
#endif /* Spine_AttachmentType_h */
@@ -0,0 +1,57 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_BlendMode_h
#define Spine_BlendMode_h
#include <string.h>
namespace spine {
enum BlendMode {
BlendMode_Normal = 0,
BlendMode_Additive,
BlendMode_Multiply,
BlendMode_Screen
};
inline BlendMode BlendMode_valueOf(const char *value) {
if (strcmp(value, "normal") == 0)
return BlendMode_Normal;
else if (strcmp(value, "additive") == 0)
return BlendMode_Additive;
else if (strcmp(value, "multiply") == 0)
return BlendMode_Multiply;
else if (strcmp(value, "screen") == 0)
return BlendMode_Screen;
else
return BlendMode_Normal;// default
}
}
#endif /* Spine_BlendMode_h */
@@ -0,0 +1,114 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_BlockAllocator_h
#define Spine_BlockAllocator_h
#include <cstdint>
#include <spine/SpineObject.h>
#include <spine/Extension.h>
#include <spine/MathUtil.h>
#include <spine/Array.h>
namespace spine {
struct Block {
int size;
int allocated;
uint8_t *memory;
int free() {
return size - allocated;
}
bool canFit(int numBytes) {
return free() >= numBytes;
}
uint8_t *allocate(int numBytes) {
uint8_t *ptr = memory + allocated;
allocated += numBytes;
return ptr;
}
};
class BlockAllocator : public SpineObject {
int initialBlockSize;
Array<Block> blocks;
public:
BlockAllocator(int initialBlockSize) : initialBlockSize(initialBlockSize) {
blocks.add(newBlock(initialBlockSize));
}
~BlockAllocator() {
for (int i = 0, n = (int) blocks.size(); i < n; i++) {
SpineExtension::free(blocks[i].memory, __FILE__, __LINE__);
}
}
template<typename T>
T *allocate(size_t num) {
return (T *) _allocate((int) (sizeof(T) * num));
}
void compress() {
if (blocks.size() == 1) {
blocks[0].allocated = 0;
return;
}
int totalSize = 0;
for (int i = 0, n = (int) blocks.size(); i < n; i++) {
totalSize += blocks[i].size;
SpineExtension::free(blocks[i].memory, __FILE__, __LINE__);
}
blocks.clear();
blocks.add(newBlock(totalSize));
}
private:
void *_allocate(int numBytes) {
// 16-byte align allocations
int alignedNumBytes = numBytes + (numBytes % 16 != 0 ? 16 - (numBytes % 16) : 0);
Block *block = &blocks[blocks.size() - 1];
if (!block->canFit(alignedNumBytes)) {
blocks.add(newBlock(MathUtil::max(initialBlockSize, alignedNumBytes)));
block = &blocks[blocks.size() - 1];
}
return block->allocate(alignedNumBytes);
}
Block newBlock(int numBytes) {
Block block = {MathUtil::max(initialBlockSize, numBytes), 0, nullptr};
block.memory = SpineExtension::alloc<uint8_t>(block.size, __FILE__, __LINE__);
return block;
}
};
}
#endif
@@ -0,0 +1,111 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_Bone_h
#define Spine_Bone_h
#include <spine/Posed.h>
#include <spine/PosedActive.h>
#include <spine/BoneData.h>
#include <spine/BonePose.h>
#include <spine/Array.h>
namespace spine {
/// A node in a skeleton's hierarchy with a transform that affects its children and their attachments. A bone has a number of
/// poses:
/// - getData(): The setup pose data.
/// - getPose(): The unconstrained local pose. Set by animations and application code.
/// - getAppliedPose(): The local pose to use for rendering. Possibly modified by constraints.
/// - World transform: the local pose combined with the parent world transform. Computed on a pose by
/// BonePose::updateWorldTransform(Skeleton) and Skeleton::updateWorldTransform(Physics).
class SP_API Bone : public PosedGeneric<BoneData, BonePose, BonePose>, public PosedActive, public Update {
friend class AnimationState;
friend class RotateTimeline;
friend class IkConstraint;
friend class TransformConstraint;
friend class VertexAttachment;
friend class PathConstraint;
friend class PhysicsConstraint;
friend class Skeleton;
friend class Slider;
friend class RegionAttachment;
friend class PointAttachment;
friend class AttachmentTimeline;
friend class RGBATimeline;
friend class RGBTimeline;
friend class AlphaTimeline;
friend class RGBA2Timeline;
friend class RGB2Timeline;
friend class ScaleTimeline;
friend class ScaleXTimeline;
friend class ScaleYTimeline;
friend class ShearTimeline;
friend class ShearXTimeline;
friend class ShearYTimeline;
friend class TranslateTimeline;
friend class TranslateXTimeline;
friend class TranslateYTimeline;
friend class InheritTimeline;
RTTI_DECL
public:
/// @param parent May be NULL.
Bone(BoneData &data, Bone *parent);
/// Copy constructor. Does not copy the child bones.
Bone(Bone &bone, Bone *parent);
/// The parent bone, or null if this is the root bone.
Bone *getParent();
/// The immediate children of this bone.
Array<Bone *> &getChildren();
static bool isYDown() {
return yDown;
}
static void setYDown(bool value) {
yDown = value;
}
virtual void update(Skeleton &skeleton, Physics physics) override {
// No-op, need to extend Update so we can stuff Bone into Skeleton.updateCache temporarily.
// See Skeleton::updateCache().
}
private:
static bool yDown;
Bone *const _parent;
Array<Bone *> _children;
bool _sorted;
};
}
#endif /* Spine_Bone_h */
@@ -0,0 +1,115 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_BoneData_h
#define Spine_BoneData_h
#include <spine/PosedData.h>
#include <spine/BonePose.h>
#include <spine/SpineString.h>
#include <spine/Color.h>
#include <spine/RTTI.h>
namespace spine {
class SP_API BoneData : public PosedDataGeneric<BonePose> {
friend class SkeletonBinary;
friend class SkeletonJson;
friend class AnimationState;
friend class RotateTimeline;
friend class ScaleTimeline;
friend class ScaleXTimeline;
friend class ScaleYTimeline;
friend class ShearTimeline;
friend class ShearXTimeline;
friend class ShearYTimeline;
friend class TranslateTimeline;
friend class TranslateXTimeline;
friend class TranslateYTimeline;
friend class Slot;
public:
BoneData(int index, const String &name, BoneData *parent = NULL);
/// The Skeleton::getBones() index for this bone.
int getIndex();
/// The parent bone, or NULL if this bone is the root.
BoneData *getParent();
float getLength();
void setLength(float inValue);
Color &getColor();
/// The bone icon name as it was in Spine, or empty if nonessential data was not exported.
const String &getIcon();
void setIcon(const String &icon);
/// The bone icon's display size scale, or 1 if nonessential data was not exported.
float getIconSize();
void setIconSize(float iconSize);
/// The bone icon's display rotation in degrees, or 0 if nonessential data was not exported.
float getIconRotation();
void setIconRotation(float iconRotation);
bool getVisible();
void setVisible(bool inValue);
private:
const int _index;
BoneData *_parent;
float _length;
Color _color;
String _icon;
float _iconSize;
float _iconRotation;
bool _visible;
};
}
#endif /* Spine_BoneData_h */
@@ -0,0 +1,127 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef SPINE_BONELOCAL_H_
#define SPINE_BONELOCAL_H_
#include <spine/SpineObject.h>
#include <spine/RTTI.h>
#include <spine/Pose.h>
#include <spine/Inherit.h>
namespace spine {
/// Stores a bone's local pose.
class SP_API BoneLocal : public Pose<BoneLocal> {
friend class IkConstraint;
friend class BoneTimeline1;
friend class BoneTimeline2;
friend class RotateTimeline;
friend class InheritTimeline;
friend class ScaleTimeline;
friend class ScaleXTimeline;
friend class ScaleYTimeline;
friend class ShearTimeline;
friend class ShearXTimeline;
friend class ShearYTimeline;
friend class TranslateTimeline;
friend class TranslateXTimeline;
friend class TranslateYTimeline;
friend class SkeletonJson;
friend class SkeletonBinary;
friend class Skeleton;
friend class FromProperty;
friend class ToProperty;
friend class FromRotate;
friend class ToRotate;
friend class FromX;
friend class ToX;
friend class FromY;
friend class ToY;
friend class FromScaleX;
friend class ToScaleX;
friend class FromScaleY;
friend class ToScaleY;
friend class FromShearY;
friend class ToShearY;
friend class AnimationState;
protected:
float _x, _y, _rotation, _scaleX, _scaleY, _shearX, _shearY;
Inherit _inherit;
public:
BoneLocal();
virtual ~BoneLocal();
virtual void set(BoneLocal &pose) override;
/// The local x translation.
float getX();
void setX(float x);
/// The local y translation.
float getY();
void setY(float y);
/// Sets local x and y translation.
void setPosition(float x, float y);
/// The local rotation in degrees, counter clockwise.
float getRotation();
void setRotation(float rotation);
/// The local scaleX.
float getScaleX();
void setScaleX(float scaleX);
/// The local scaleY.
float getScaleY();
void setScaleY(float scaleY);
/// Sets local scaleX and scaleY.
void setScale(float scaleX, float scaleY);
/// Sets local scaleX and scaleY to the same value.
void setScale(float scale);
/// The local shearX.
float getShearX();
void setShearX(float shearX);
/// The local shearY.
float getShearY();
void setShearY(float shearY);
/// Determines how parent world transforms affect this bone.
Inherit getInherit();
void setInherit(Inherit inherit);
};
}
#endif /* SPINE_BONELOCAL_H_ */
@@ -0,0 +1,173 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef SPINE_BONEPOSE_H_
#define SPINE_BONEPOSE_H_
#include <spine/BoneLocal.h>
#include <spine/Update.h>
#include <spine/RTTI.h>
namespace spine {
class Bone;
class Skeleton;
/// The applied local pose and world transform for a bone. This is the bone's unconstrained pose with constraints applied and
/// the world transform computed by Skeleton::updateWorldTransform(Physics) and updateWorldTransform(Skeleton).
///
/// If the world transform is changed, call updateLocalTransform(Skeleton) before using the local transform. The local
/// transform may be needed by other code (eg to apply another constraint).
///
/// After changing the world transform, call updateWorldTransform(Skeleton) on every descendant bone. It may be more
/// convenient to modify the local transform instead, then call Skeleton::updateWorldTransform(Physics) to update the world
/// transforms for all bones and apply constraints.
class SP_API BonePose : public BoneLocal, public Update {
friend class IkConstraint;
friend class PathConstraint;
friend class PhysicsConstraint;
friend class TransformConstraint;
friend class TransformConstraintData;
friend class FromRotate;
friend class ToRotate;
friend class FromX;
friend class ToX;
friend class FromY;
friend class ToY;
friend class FromScaleX;
friend class ToScaleX;
friend class FromScaleY;
friend class ToScaleY;
friend class FromShearX;
friend class ToShearX;
friend class FromShearY;
friend class ToShearY;
friend class Skeleton;
friend class Bone;
RTTI_DECL
public:
BonePose();
virtual ~BonePose();
/// Called by Skeleton::updateCache() to compute the world transform, if needed.
virtual void update(Skeleton &skeleton, Physics physics) override;
/// Computes the world transform using the parent bone's world transform and this applied local pose. Child bones are not
/// updated.
///
/// See <a href="https://esotericsoftware.com/spine-runtime-skeletons#World-transforms">World transforms</a> in the Spine
/// Runtimes Guide.
void updateWorldTransform(Skeleton &skeleton);
/// Computes the local transform values from the world transform.
///
/// Some information is ambiguous in the world transform, such as -1,-1 scale versus 180 rotation. The local transform after
/// calling this method is equivalent to the local transform used to compute the world transform, but may not be identical.
void updateLocalTransform(Skeleton &skeleton);
/// If the world transform has been modified by constraints and the local transform no longer matches,
/// updateLocalTransform() is called. Call this after Skeleton::updateWorldTransform(Physics) before using the applied
/// local transform.
void validateLocalTransform(Skeleton &skeleton);
void modifyLocal(Skeleton &skeleton);
void modifyWorld(Skeleton &skeleton);
/// The world transform <code>[a b][c d]</code> x-axis x component.
float getA();
void setA(float a);
/// The world transform <code>[a b][c d]</code> y-axis x component.
float getB();
void setB(float b);
/// The world transform <code>[a b][c d]</code> x-axis y component.
float getC();
void setC(float c);
/// The world transform <code>[a b][c d]</code> y-axis y component.
float getD();
void setD(float d);
/// The world X position.
float getWorldX();
void setWorldX(float worldX);
/// The world Y position.
float getWorldY();
void setWorldY(float worldY);
/// The world rotation for the X axis, calculated using a and c. This is the direction the bone is pointing.
float getWorldRotationX();
/// The world rotation for the Y axis, calculated using b and d.
float getWorldRotationY();
/// The magnitude (always positive) of the world scale X, calculated using a and c.
float getWorldScaleX();
/// The magnitude (always positive) of the world scale Y, calculated using b and d.
float getWorldScaleY();
/// Transforms a point from world coordinates to the bone's local coordinates.
void worldToLocal(float worldX, float worldY, float &outLocalX, float &outLocalY);
/// Transforms a point from the bone's local coordinates to world coordinates.
void localToWorld(float localX, float localY, float &outWorldX, float &outWorldY);
/// Transforms a point from world coordinates to the parent bone's local coordinates.
void worldToParent(float worldX, float worldY, float &outParentX, float &outParentY);
/// Transforms a point from the parent bone's coordinates to world coordinates.
void parentToWorld(float parentX, float parentY, float &outWorldX, float &outWorldY);
/// Transforms a world rotation to a local rotation.
float worldToLocalRotation(float worldRotation);
/// Transforms a local rotation to a world rotation.
float localToWorldRotation(float localRotation);
/// Rotates the world transform the specified amount.
void rotateWorld(float degrees);
private:
void setLocal(float ra, float rb, float rc, float rd);
void setLocal(float ra, float rb, float rc, float rd, float ro);
void resetWorld(Skeleton &skeleton, int update);
protected:
Bone *_bone;
float _a, _b, _worldX;
float _c, _d, _worldY;
int _world, _local;
};
}// namespace spine
#endif /* SPINE_BONEPOSE_H_ */
@@ -0,0 +1,123 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_BoneTimeline_h
#define Spine_BoneTimeline_h
#include <cstddef>
#include <spine/dll.h>
#include <spine/CurveTimeline.h>
namespace spine {
class Skeleton;
class Event;
class BonePose;
/// An interface for timelines which change the property of a bone.
class SP_API BoneTimeline {
RTTI_DECL_NOPARENT
public:
BoneTimeline(int boneIndex) {
}
virtual ~BoneTimeline() {
}
/// The Skeleton::getBones() index of the bone that will be changed when this timeline is applied.
virtual int getBoneIndex() const = 0;
virtual void setBoneIndex(int inValue) = 0;
};
/// Base class for timelines that animate a single bone property.
class SP_API BoneTimeline1 : public CurveTimeline1, public BoneTimeline {
friend class SkeletonBinary;
friend class SkeletonJson;
friend class AnimationState;
RTTI_DECL
public:
BoneTimeline1(size_t frameCount, size_t bezierCount, int boneIndex, Property property);
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixFrom from, bool add, bool out,
bool appliedPose) override;
virtual int getBoneIndex() const override {
return _boneIndex;
}
virtual void setBoneIndex(int inValue) override {
_boneIndex = inValue;
}
protected:
/// Applies changes to the pose based on the timeline values.
virtual void _apply(BonePose &pose, BonePose &setup, float time, float alpha, MixFrom from, bool add, bool out) = 0;
int _boneIndex;
};
/// Base class for timelines that animate two bone properties.
class SP_API BoneTimeline2 : public CurveTimeline, public BoneTimeline {
friend class SkeletonBinary;
friend class SkeletonJson;
friend class AnimationState;
RTTI_DECL
public:
BoneTimeline2(size_t frameCount, size_t bezierCount, int boneIndex, Property property1, Property property2);
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixFrom from, bool add, bool out,
bool appliedPose) override;
virtual int getBoneIndex() const override {
return _boneIndex;
}
virtual void setBoneIndex(int inValue) override {
_boneIndex = inValue;
}
virtual void setFrame(size_t frame, float time, float value1, float value2);
protected:
/// Applies changes to the pose based on the timeline values.
virtual void _apply(BonePose &pose, BonePose &setup, float time, float alpha, MixFrom from, bool add, bool out) = 0;
int _boneIndex;
static const int ENTRIES;
static const int VALUE1;
static const int VALUE2;
};
}
#endif
@@ -0,0 +1,54 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_BoundingBoxAttachment_h
#define Spine_BoundingBoxAttachment_h
#include <spine/VertexAttachment.h>
#include <spine/Color.h>
#include <spine/SpineObject.h>
namespace spine {
/// Attachment that has a polygon for bounds checking.
class SP_API BoundingBoxAttachment : public VertexAttachment {
RTTI_DECL
public:
explicit BoundingBoxAttachment(const String &name);
Color &getColor();
virtual Attachment &copy() override;
private:
Color _color;
};
}
#endif /* Spine_BoundingBoxAttachment_h */
@@ -0,0 +1,82 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_ClippingAttachment_h
#define Spine_ClippingAttachment_h
#include <spine/VertexAttachment.h>
#include <spine/Color.h>
namespace spine {
class SlotData;
class SP_API ClippingAttachment : public VertexAttachment {
friend class SkeletonBinary;
friend class SkeletonJson;
friend class SkeletonClipping;
RTTI_DECL
public:
explicit ClippingAttachment(const String &name);
/// Clipping is performed between the clipping attachment's slot and the end slot. If NULL, clipping is done until
/// the end of the skeleton's rendering.
SlotData *getEndSlot();
void setEndSlot(SlotData *inValue);
/// When true the clipping polygon is treated as convex for more efficient clipping. If the polygon deforms to concave then the
/// convex hull is used. When false the clipping polygon can be concave and if so has an additional CPU cost. Inverse clipping
/// always uses convex.
bool getConvex();
void setConvex(bool convex);
/// When false, everything inside the clipping polygon is visible. When true, everything outside the clipping polygon is
/// visible and clipping is convex.
bool getInverse();
void setInverse(bool inverse);
Color &getColor();
virtual Attachment &copy() override;
private:
SlotData *_endSlot;
bool _convex;
bool _inverse;
Color _color;
};
}
#endif /* Spine_ClippingAttachment_h */
@@ -0,0 +1,156 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef SPINE_COLOR_H
#define SPINE_COLOR_H
#include <spine/MathUtil.h>
#include <string.h>
#include <stdlib.h>
namespace spine {
class SP_API Color : public SpineObject {
public:
Color() : r(0), g(0), b(0), a(0) {
}
Color(float r, float g, float b, float a) : r(r), g(g), b(b), a(a) {
clamp();
}
inline Color &set(float _r, float _g, float _b, float _a) {
this->r = _r;
this->g = _g;
this->b = _b;
this->a = _a;
clamp();
return *this;
}
inline Color &set(float _r, float _g, float _b) {
this->r = _r;
this->g = _g;
this->b = _b;
clamp();
return *this;
}
inline Color &set(const Color &other) {
r = other.r;
g = other.g;
b = other.b;
a = other.a;
clamp();
return *this;
}
inline Color &add(float _r, float _g, float _b, float _a) {
this->r += _r;
this->g += _g;
this->b += _b;
this->a += _a;
clamp();
return *this;
}
inline Color &add(float _r, float _g, float _b) {
this->r += _r;
this->g += _g;
this->b += _b;
clamp();
return *this;
}
inline Color &add(const Color &other) {
r += other.r;
g += other.g;
b += other.b;
a += other.a;
clamp();
return *this;
}
inline Color &clamp() {
r = MathUtil::clamp(this->r, 0, 1);
g = MathUtil::clamp(this->g, 0, 1);
b = MathUtil::clamp(this->b, 0, 1);
a = MathUtil::clamp(this->a, 0, 1);
return *this;
}
// Parse hex color string like "ff0000ff" (RRGGBBAA) or "ff0000" (RRGGBB)
static Color valueOf(const char *hexString) {
Color color;
valueOf(hexString, color);
return color;
}
// Parse hex color string into existing Color object
static void valueOf(const char *hexString, Color &color) {
size_t len = strlen(hexString);
if (len >= 6) {
color.r = parseHex(hexString, 0);
color.g = parseHex(hexString, 1);
color.b = parseHex(hexString, 2);
color.a = len >= 8 ? parseHex(hexString, 3) : 1.0f;
}
}
static float parseHex(const char *value, size_t index) {
char digits[3];
digits[0] = value[index * 2];
digits[1] = value[index * 2 + 1];
digits[2] = '\0';
return strtoul(digits, NULL, 16) / 255.0f;
}
// Convert packed RGBA8888 integer to Color
static void rgba8888ToColor(Color &color, int value) {
unsigned int rgba = (unsigned int) value;
color.r = ((rgba & 0xff000000) >> 24) / 255.0f;
color.g = ((rgba & 0x00ff0000) >> 16) / 255.0f;
color.b = ((rgba & 0x0000ff00) >> 8) / 255.0f;
color.a = (rgba & 0x000000ff) / 255.0f;
}
// Convert packed RGB888 integer to Color (no alpha)
static void rgb888ToColor(Color &color, int value) {
unsigned int rgb = (unsigned int) value;
color.r = ((rgb & 0xff0000) >> 16) / 255.0f;
color.g = ((rgb & 0x00ff00) >> 8) / 255.0f;
color.b = (rgb & 0x0000ff) / 255.0f;
color.a = 1.0f;
}
float r, g, b, a;
};
}
#endif//SPINE_COLOR_H
@@ -0,0 +1,177 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_ColorTimeline_h
#define Spine_ColorTimeline_h
#include <spine/SlotCurveTimeline.h>
#include <spine/SlotTimeline.h>
namespace spine {
/// Changes a slot's color.
class SP_API RGBATimeline : public SlotCurveTimeline {
friend class SkeletonBinary;
friend class SkeletonJson;
RTTI_DECL
public:
explicit RGBATimeline(size_t frameCount, size_t bezierCount, int slotIndex);
virtual ~RGBATimeline();
/// Sets the time and color for the specified frame.
/// @param frame Between 0 and frameCount, inclusive.
/// @param time The frame time in seconds.
void setFrame(int frame, float time, float r, float g, float b, float a);
protected:
virtual void _apply(Slot &slot, SlotPose &pose, float time, float alpha, MixFrom from, bool add) override;
static const int ENTRIES = 5;
static const int R = 1;
static const int G = 2;
static const int B = 3;
static const int A = 4;
};
/// Changes RGB for a slot's color.
class SP_API RGBTimeline : public SlotCurveTimeline {
friend class SkeletonBinary;
friend class SkeletonJson;
RTTI_DECL
public:
explicit RGBTimeline(size_t frameCount, size_t bezierCount, int slotIndex);
virtual ~RGBTimeline();
/// Sets the time and color for the specified frame.
/// @param frame Between 0 and frameCount, inclusive.
/// @param time The frame time in seconds.
void setFrame(int frame, float time, float r, float g, float b);
protected:
virtual void _apply(Slot &slot, SlotPose &pose, float time, float alpha, MixFrom from, bool add) override;
static const int ENTRIES = 4;
static const int R = 1;
static const int G = 2;
static const int B = 3;
};
class SP_API AlphaTimeline : public CurveTimeline1, public SlotTimeline {
friend class SkeletonBinary;
friend class SkeletonJson;
RTTI_DECL
public:
explicit AlphaTimeline(size_t frameCount, size_t bezierCount, int slotIndex);
virtual ~AlphaTimeline();
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixFrom from, bool add, bool out,
bool appliedPose) override;
virtual int getSlotIndex() override;
virtual void setSlotIndex(int inValue) override;
protected:
int _slotIndex;
};
/// Changes a slot's light and dark colors for two color tinting.
class SP_API RGBA2Timeline : public SlotCurveTimeline {
friend class SkeletonBinary;
friend class SkeletonJson;
RTTI_DECL
public:
explicit RGBA2Timeline(size_t frameCount, size_t bezierCount, int slotIndex);
virtual ~RGBA2Timeline();
/// Sets the time, light color, and dark color for the specified frame.
/// @param frame Between 0 and frameCount, inclusive.
/// @param time The frame time in seconds.
void setFrame(int frame, float time, float r, float g, float b, float a, float r2, float g2, float b2);
protected:
virtual void _apply(Slot &slot, SlotPose &pose, float time, float alpha, MixFrom from, bool add) override;
static const int ENTRIES = 8;
static const int R = 1;
static const int G = 2;
static const int B = 3;
static const int A = 4;
static const int R2 = 5;
static const int G2 = 6;
static const int B2 = 7;
};
/// Changes RGB for a slot's light and dark colors for two color tinting.
class SP_API RGB2Timeline : public SlotCurveTimeline {
friend class SkeletonBinary;
friend class SkeletonJson;
RTTI_DECL
public:
explicit RGB2Timeline(size_t frameCount, size_t bezierCount, int slotIndex);
virtual ~RGB2Timeline();
/// Sets the time, light color, and dark color for the specified frame.
/// @param frame Between 0 and frameCount, inclusive.
/// @param time The frame time in seconds.
void setFrame(int frame, float time, float r, float g, float b, float r2, float g2, float b2);
protected:
virtual void _apply(Slot &slot, SlotPose &pose, float time, float alpha, MixFrom from, bool add) override;
static const int ENTRIES = 7;
static const int R = 1;
static const int G = 2;
static const int B = 3;
static const int R2 = 4;
static const int G2 = 5;
static const int B2 = 6;
};
}
#endif /* Spine_ColorTimeline_h */
@@ -0,0 +1,92 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_Constraint_h
#define Spine_Constraint_h
#include <spine/Posed.h>
#include <spine/PosedActive.h>
#include <spine/Update.h>
#include <spine/RTTI.h>
#include <spine/ConstraintData.h>
namespace spine {
class Skeleton;
class SP_API Constraint : public Update {
friend class Skeleton;
public:
RTTI_DECL
Constraint();
virtual ~Constraint();
virtual ConstraintData &getData() = 0;
virtual void sort(Skeleton &skeleton) = 0;
virtual bool isSourceActive() = 0;
// Inherited from Update
virtual void update(Skeleton &skeleton, Physics physics) override = 0;
protected:
virtual void unconstrained() = 0;
virtual void setupPose() = 0;
bool _active;
};
template<class T, class D, class P>
class ConstraintGeneric : public PosedGeneric<D, P, P>, public PosedActive, public Constraint {
public:
ConstraintGeneric(D &data) : PosedGeneric<D, P, P>(data), PosedActive(), Constraint() {
}
virtual ~ConstraintGeneric() {
}
virtual D &getData() override {
return PosedGeneric<D, P, P>::getData();
}
protected:
virtual void unconstrained() override {
PosedGeneric<D, P, P>::unconstrained();
}
virtual void setupPose() override {
PosedGeneric<D, P, P>::setupPose();
}
};
}// namespace spine
#endif /* Spine_Constraint_h */
@@ -0,0 +1,108 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_ConstraintData_h
#define Spine_ConstraintData_h
#include <spine/SpineString.h>
#include <spine/SpineObject.h>
#include <spine/PosedData.h>
#include <spine/RTTI.h>
#include <string.h>
namespace spine {
class Skeleton;
class Constraint;
enum ScaleYMode {
ScaleYMode_None = 0,
ScaleYMode_Uniform,
ScaleYMode_Volume
};
inline ScaleYMode ScaleYMode_valueOf(const char *value) {
if (strcmp(value, "uniform") == 0)
return ScaleYMode_Uniform;
else if (strcmp(value, "volume") == 0)
return ScaleYMode_Volume;
else
return ScaleYMode_None;
}
inline const char *ScaleYMode_toString(ScaleYMode scaleYMode) {
switch (scaleYMode) {
case ScaleYMode_Uniform:
return "uniform";
case ScaleYMode_Volume:
return "volume";
default:
return "none";
}
}
class SP_API ConstraintData : public SpineObject {
RTTI_DECL_NOPARENT
friend class Skeleton;
friend class Constraint;
public:
ConstraintData(const String &name) : SpineObject(name) {
}
virtual ~ConstraintData() {
}
virtual Constraint &create(Skeleton &skeleton) = 0;
virtual const String &getName() const = 0;
virtual bool getSkinRequired() const = 0;
};
/// Base class for all constraint data types.
template<class T, class P>
class ConstraintDataGeneric : public PosedDataGeneric<P>, public ConstraintData {
public:
ConstraintDataGeneric(const String &name) : PosedDataGeneric<P>(name), ConstraintData(name) {
}
virtual ~ConstraintDataGeneric() {
}
virtual Constraint &create(Skeleton &skeleton) override = 0;
// Resolve ambiguity by forwarding to PosedData's implementation
virtual const String &getName() const override {
return PosedDataGeneric<P>::getName();
}
virtual bool getSkinRequired() const override {
return PosedDataGeneric<P>::getSkinRequired();
}
};
}
#endif /* Spine_ConstraintData_h */
@@ -0,0 +1,52 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_ConstraintTimeline_h
#define Spine_ConstraintTimeline_h
#include <spine/dll.h>
#include <spine/RTTI.h>
namespace spine {
/// An interface for timelines which change the property of a constraint.
class SP_API ConstraintTimeline {
RTTI_DECL_NOPARENT
public:
ConstraintTimeline();
virtual ~ConstraintTimeline();
/// The Skeleton::getConstraints() index of the constraint that will be changed when this timeline is applied.
virtual int getConstraintIndex() const = 0;
virtual void setConstraintIndex(int inValue) = 0;
};
}
#endif
@@ -0,0 +1,59 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated July 28, 2023. Replaces all prior versions.
*
* Copyright (c) 2013-2023, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software or
* otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
* SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_ConstraintTimeline1_h
#define Spine_ConstraintTimeline1_h
#include <spine/ConstraintTimeline.h>
#include <spine/CurveTimeline.h>
#include <spine/Property.h>
namespace spine {
/// The base class for timelines that change 1 constraint property with a curve.
class SP_API ConstraintTimeline1 : public CurveTimeline1, public ConstraintTimeline {
RTTI_DECL
public:
ConstraintTimeline1(size_t frameCount, size_t bezierCount, int constraintIndex, Property property);
virtual ~ConstraintTimeline1();
virtual int getConstraintIndex() const override {
return _constraintIndex;
}
virtual void setConstraintIndex(int inValue) override {
_constraintIndex = inValue;
}
protected:
int _constraintIndex;
};
}// namespace spine
#endif /* Spine_ConstraintTimeline1_h */
@@ -0,0 +1,101 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_CurveTimeline_h
#define Spine_CurveTimeline_h
#include <spine/Timeline.h>
#include <spine/Array.h>
namespace spine {
/// Base class for frames that use an interpolation bezier curve.
class SP_API CurveTimeline : public Timeline {
RTTI_DECL
public:
explicit CurveTimeline(size_t frameCount, size_t frameEntries, size_t bezierCount);
virtual ~CurveTimeline();
void setLinear(size_t frame);
void setStepped(size_t frame);
virtual void setBezier(size_t bezier, size_t frame, float value, float time1, float value1, float cx1, float cy1, float cx2, float cy2,
float time2, float value2);
float getBezierValue(float time, size_t frame, size_t valueOffset, size_t i);
Array<float> &getCurves();
protected:
static const int LINEAR = 0;
static const int STEPPED = 1;
static const int BEZIER = 2;
static const int BEZIER_SIZE = 18;
Array<float> _curves;// type, x, y, ...
};
/// The base class for a CurveTimeline that sets one property.
class SP_API CurveTimeline1 : public CurveTimeline {
RTTI_DECL
public:
/// @param frameCount The number of frames for this timeline.
/// @param bezierCount The maximum number of Bezier curves.
explicit CurveTimeline1(size_t frameCount, size_t bezierCount);
virtual ~CurveTimeline1();
/// Sets the time and value for the specified frame.
/// @param frame Between 0 and frameCount, inclusive.
/// @param time The frame time in seconds.
void setFrame(size_t frame, float time, float value);
/// Returns the interpolated value for the specified time.
float getCurveValue(float time);
float getRelativeValue(float time, float alpha, MixFrom from, bool add, float current, float setup);
float getAbsoluteValue(float time, float alpha, MixFrom from, bool add, float current, float setup);
float getAbsoluteValue(float time, float alpha, MixFrom from, bool add, float current, float setup, float value);
float getScaleValue(float time, float alpha, MixFrom from, bool add, bool out, float current, float setup);
static float beforeFirstKey(MixFrom from, float alpha, float current, float setup);
protected:
static const int ENTRIES = 2;
static const int VALUE = 1;
};
}
#endif /* Spine_CurveTimeline_h */
@@ -0,0 +1,368 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef SPINE_LOG_H
#define SPINE_LOG_H
#include <spine/Extension.h>
#include <spine/Array.h>
#ifndef SPINE_NO_CPP_RT
#include <unordered_map>
#endif
namespace spine {
#ifdef SPINE_NO_CPP_RT
// Need a copy as HashMap extends SpineObject, which would trigger
// infinite recursion when used in DebugExtension
template<typename K, typename V>
class DebugHashMap {
private:
class DebugEntry;
public:
class SP_API DebugPair {
public:
explicit DebugPair(K &k, V &v) : key(k), value(v) {
}
K &key;
V &value;
};
class SP_API DebugEntries {
public:
friend class DebugHashMap;
explicit DebugEntries(DebugEntry *entry) : _hasChecked(false) {
_start.next = entry;
_entry = &_start;
}
DebugPair next() {
assert(_entry);
assert(_hasChecked);
_entry = _entry->next;
DebugPair pair(_entry->_key, _entry->_value);
_hasChecked = false;
return pair;
}
bool hasNext() {
_hasChecked = true;
return _entry->next;
}
private:
bool _hasChecked;
DebugEntry _start;
DebugEntry *_entry;
};
DebugHashMap() : _head(NULL), _size(0) {
}
~DebugHashMap() {
clear();
}
void clear() {
for (DebugEntry *entry = _head; entry != NULL;) {
DebugEntry *next = entry->next;
delete entry;
entry = next;
}
_head = NULL;
_size = 0;
}
size_t size() {
return _size;
}
void put(const K &key, const V &value) {
DebugEntry *entry = find(key);
if (entry) {
entry->_key = key;
entry->_value = value;
} else {
entry = new DebugEntry();
entry->_key = key;
entry->_value = value;
DebugEntry *oldHead = _head;
if (oldHead) {
_head = entry;
oldHead->prev = entry;
entry->next = oldHead;
} else {
_head = entry;
}
_size++;
}
}
bool addAll(Array<K> &keys, const V &value) {
size_t oldSize = _size;
for (size_t i = 0; i < keys.size(); i++) {
put(keys[i], value);
}
return _size != oldSize;
}
bool containsKey(const K &key) {
return find(key) != NULL;
}
bool remove(const K &key) {
DebugEntry *entry = find(key);
if (!entry) return false;
DebugEntry *prev = entry->prev;
DebugEntry *next = entry->next;
if (prev)
prev->next = next;
else
_head = next;
if (next) next->prev = entry->prev;
delete entry;
_size--;
return true;
}
V operator[](const K &key) {
DebugEntry *entry = find(key);
if (entry)
return entry->_value;
else {
assert(false);
return 0;
}
}
DebugEntries getEntries() const {
return DebugEntries(_head);
}
private:
DebugEntry *find(const K &key) {
for (DebugEntry *entry = _head; entry != NULL; entry = entry->next) {
if (entry->_key == key) return entry;
}
return NULL;
}
class SP_API DebugEntry {
public:
K _key;
V _value;
DebugEntry *next;
DebugEntry *prev;
DebugEntry() : next(NULL), prev(NULL) {
}
};
DebugEntry *_head;
size_t _size;
};
#endif// SPINE_NO_CPP_RT
class SP_API DebugExtension : public SpineExtension {
struct Allocation {
void *address;
size_t size;
const char *fileName;
int line;
Allocation() : address(NULL), size(0), fileName(NULL), line(0) {
}
Allocation(void *a, size_t s, const char *f, int l) : address(a), size(s), fileName(f), line(l) {
}
};
public:
DebugExtension(SpineExtension *extension) : _extension(extension), _allocations(0), _reallocations(0), _frees(0) {
}
void reportLeaks() {
#ifdef SPINE_NO_CPP_RT
DebugHashMap<void *, Allocation>::DebugEntries entries = _allocated.getEntries();
while (entries.hasNext()) {
DebugHashMap<void *, Allocation>::DebugPair pair = entries.next();
printf("\"%s:%i (%zu bytes at %p)\n", pair.value.fileName, pair.value.line, pair.value.size, pair.value.address);
}
#else
for (const auto &pair : _allocated) {
printf("\"%s:%i (%zu bytes at %p)\n", pair.second.fileName, pair.second.line, pair.second.size, pair.second.address);
}
#endif
printf("allocations: %zu, reallocations: %zu, frees: %zu\n", _allocations, _reallocations, _frees);
if (_allocated.size() == 0) printf("No leaks detected\n");
}
void clearAllocations() {
_allocated.clear();
_usedMemory = 0;
}
virtual void *_alloc(size_t size, const char *file, int line) {
void *result = _extension->_alloc(size, file, line);
#ifdef SPINE_NO_CPP_RT
_allocated.put(result, Allocation(result, size, file, line));
#else
_allocated[result] = Allocation(result, size, file, line);
#endif
_allocations++;
_usedMemory += size;
return result;
}
virtual void *_calloc(size_t size, const char *file, int line) {
void *result = _extension->_calloc(size, file, line);
#ifdef SPINE_NO_CPP_RT
_allocated.put(result, Allocation(result, size, file, line));
#else
_allocated[result] = Allocation(result, size, file, line);
#endif
_allocations++;
_usedMemory += size;
return result;
}
virtual void *_realloc(void *ptr, size_t size, const char *file, int line) {
#ifdef SPINE_NO_CPP_RT
if (_allocated.containsKey(ptr)) {
// Find and store the size before removing
DebugHashMap<void *, Allocation>::DebugEntries entries = _allocated.getEntries();
while (entries.hasNext()) {
DebugHashMap<void *, Allocation>::DebugPair pair = entries.next();
if (pair.key == ptr) {
_usedMemory -= pair.value.size;
break;
}
}
_allocated.remove(ptr);
}
#else
auto it = _allocated.find(ptr);
if (it != _allocated.end()) {
_usedMemory -= it->second.size;
_allocated.erase(it);
}
#endif
void *result = _extension->_realloc(ptr, size, file, line);
_reallocations++;
#ifdef SPINE_NO_CPP_RT
_allocated.put(result, Allocation(result, size, file, line));
#else
_allocated[result] = Allocation(result, size, file, line);
#endif
_usedMemory += size;
return result;
}
virtual void _free(void *mem, const char *file, int line) {
#ifdef SPINE_NO_CPP_RT
if (_allocated.containsKey(mem)) {
_extension->_free(mem, file, line);
_frees++;
// Find and store the size before removing
DebugHashMap<void *, Allocation>::DebugEntries entries = _allocated.getEntries();
while (entries.hasNext()) {
DebugHashMap<void *, Allocation>::DebugPair pair = entries.next();
if (pair.key == mem) {
_usedMemory -= pair.value.size;
break;
}
}
_allocated.remove(mem);
return;
}
#else
auto it = _allocated.find(mem);
if (it != _allocated.end()) {
_extension->_free(mem, file, line);
_frees++;
_usedMemory -= it->second.size;
_allocated.erase(it);
return;
}
#endif
printf("%s:%i (address %p): Double free or not allocated through SpineExtension\n", file, line, mem);
_extension->_free(mem, file, line);
}
virtual char *_readFile(const String &path, int *length) {
auto data = _extension->_readFile(path, length);
#ifdef SPINE_NO_CPP_RT
if (!_allocated.containsKey(data)) {
_allocated.put(data, Allocation(data, sizeof(char) * (*length), nullptr, 0));
_allocations++;
_usedMemory += sizeof(char) * (*length);
}
#else
if (_allocated.find(data) == _allocated.end()) {
_allocated[data] = Allocation(data, sizeof(char) * (*length), nullptr, 0);
_allocations++;
_usedMemory += sizeof(char) * (*length);
}
#endif
return data;
}
size_t getUsedMemory() {
return _usedMemory;
}
private:
SpineExtension *_extension;
#ifdef SPINE_NO_CPP_RT
DebugHashMap<void *, Allocation> _allocated;
#else
std::unordered_map<void *, Allocation> _allocated;
#endif
size_t _allocations;
size_t _reallocations;
size_t _frees;
size_t _usedMemory;
};
}
#endif//SPINE_LOG_H
@@ -0,0 +1,87 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_DeformTimeline_h
#define Spine_DeformTimeline_h
#include <spine/SlotCurveTimeline.h>
namespace spine {
class VertexAttachment;
/// Changes a slot's deform to deform a VertexAttachment.
class SP_API DeformTimeline : public SlotCurveTimeline {
friend class SkeletonBinary;
friend class SkeletonJson;
RTTI_DECL
public:
explicit DeformTimeline(size_t frameCount, size_t bezierCount, int slotIndex, VertexAttachment &attachment);
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixFrom from, bool add, bool out,
bool appliedPose) override;
/// Sets the time and vertices for the specified frame.
void setFrame(int frameIndex, float time, Array<float> &vertices);
/// The vertices for each frame.
Array<Array<float>> &getVertices();
/// The attachment whose vertices will be deformed.
VertexAttachment &getAttachment();
void setAttachment(VertexAttachment &inValue);
virtual void setBezier(size_t bezier, size_t frame, float value, float time1, float value1, float cx1, float cy1, float cx2, float cy2,
float time2, float value2) override;
float getCurvePercent(float time, int frame);
size_t getFrameCount() {
return _frames.size();
}
protected:
void _apply(Slot &slot, SlotPose &pose, float time, float alpha, MixFrom from, bool add) override;
private:
void applyBeforeFirst(Slot &slot, bool appliedPose, float alpha, MixFrom from);
void applyToPose(SlotPose &pose, Array<float> &v1, Array<float> *v2, float percent, size_t vertexCount, float alpha, MixFrom from, bool add);
void applyToSlot(Slot &slot, bool appliedPose, Array<float> &v1, Array<float> *v2, float percent, size_t vertexCount, float alpha,
MixFrom from, bool add);
Array<Array<float>> _vertices;
VertexAttachment *_attachment;
};
}
#endif /* Spine_DeformTimeline_h */
@@ -0,0 +1,79 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_DrawOrder_h
#define Spine_DrawOrder_h
#include <spine/Array.h>
#include <spine/SpineObject.h>
namespace spine {
class Slot;
/// Stores the skeleton's draw order, which is the order that each slot's attachment is rendered.
class SP_API DrawOrder : public SpineObject {
friend class Skeleton;
friend class DrawOrderTimeline;
friend class DrawOrderFolderTimeline;
friend class Slider;
public:
explicit DrawOrder(Array<Slot *> &setupPose);
/// Sets the unconstrained draw order to the setup pose order.
void setupPose();
/// The unconstrained draw order, set by animations and application code.
Array<Slot *> &getPose();
/// The constrained draw order for rendering. If no constraints modify the draw order, this is the same as getPose().
/// Otherwise it is a copy of getPose() modified by constraints.
Array<Slot *> &getAppliedPose();
private:
/// Sets the applied pose to the unconstrained pose, for when no constraints will modify the draw order.
void unconstrained();
/// Sets the applied pose to the constrained pose, in anticipation of the applied pose being modified by constraints.
void constrained();
/// Copies the unconstrained pose to the constrained pose, as a starting point for constraints to be applied.
void reset();
Array<Slot *> &_setupPose;
Array<Slot *> _pose;
Array<Slot *> _constrainedPose;
Array<Slot *> *_appliedPose;
};
}
#endif /* Spine_DrawOrder_h */
@@ -0,0 +1,76 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_DrawOrderFolderTimeline_h
#define Spine_DrawOrderFolderTimeline_h
#include <spine/Timeline.h>
namespace spine {
class Slot;
/// Changes a subset of the Skeleton::getDrawOrder() draw order.
class SP_API DrawOrderFolderTimeline : public Timeline {
friend class SkeletonBinary;
friend class SkeletonJson;
RTTI_DECL
public:
DrawOrderFolderTimeline(size_t frameCount, Array<int> &slots, size_t slotCount);
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixFrom from, bool add, bool out,
bool appliedPose) override;
size_t getFrameCount();
/// The Skeleton::getSlots() indices that this timeline affects, in setup order.
Array<int> &getSlots();
/// The draw order for each frame. See setFrame().
Array<Array<int>> &getDrawOrders();
/// Sets the time and draw order for the specified frame.
/// @param frame Between 0 and frameCount, inclusive.
/// @param time The frame time in seconds.
/// @param drawOrder Ordered getSlots() indices, or null to use setup pose order.
void setFrame(size_t frame, float time, Array<int> *drawOrder);
private:
Array<int> _slots;
Array<bool> _inFolder;
Array<Array<int>> _drawOrders;
void setup(Array<Slot *> &pose, Array<Slot *> &setupPose);
void apply(Array<Slot *> &pose, Array<Slot *> &setupPose, Array<int> &drawOrder);
};
}
#endif /* Spine_DrawOrderFolderTimeline_h */
@@ -0,0 +1,69 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_DrawOrderTimeline_h
#define Spine_DrawOrderTimeline_h
#include <spine/Timeline.h>
namespace spine {
/// Changes the Skeleton::getDrawOrder().
class SP_API DrawOrderTimeline : public Timeline {
friend class SkeletonBinary;
friend class SkeletonJson;
RTTI_DECL
public:
static PropertyId getPropertyId();
explicit DrawOrderTimeline(size_t frameCount);
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixFrom from, bool add, bool out,
bool appliedPose) override;
size_t getFrameCount();
/// The draw order for each frame. See setFrame().
Array<Array<int>> &getDrawOrders();
/// Sets the time and draw order for the specified frame.
/// @param frame Between 0 and frameCount, inclusive.
/// @param time The frame time in seconds.
/// @param drawOrder For each slot in Skeleton::getSlots(), the index of the slot in the new draw order. May be null to use
/// setup pose draw order.
void setFrame(size_t frame, float time, Array<int> *drawOrder);
private:
Array<Array<int>> _drawOrders;
};
}
#endif /* Spine_DrawOrderTimeline_h */
@@ -0,0 +1,95 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_Event_h
#define Spine_Event_h
#include <spine/SpineObject.h>
#include <spine/SpineString.h>
namespace spine {
class EventData;
/// Fired by EventTimeline when specific animation times are reached.
///
/// See Timeline::apply(), AnimationStateListener::event(), and
/// https://esotericsoftware.com/spine-events Events in the Spine User Guide.
class SP_API Event : public SpineObject {
friend class SkeletonBinary;
friend class SkeletonJson;
friend class AnimationState;
public:
Event(float time, const EventData &data);
/// The event's setup pose data.
const EventData &getData();
/// The animation time this event was keyed, or -1 for the setup pose.
float getTime();
/// The integer payload for this event.
int getInt();
void setInt(int inValue);
/// The float payload for this event.
float getFloat();
void setFloat(float inValue);
/// The string payload for this event.
const String &getString();
void setString(const String &inValue);
/// If an audio path is set, the volume for the audio.
float getVolume();
void setVolume(float inValue);
/// If an audio path is set, the left/right balance for the audio.
float getBalance();
void setBalance(float inValue);
private:
const EventData &_data;
const float _time;
int _intValue;
float _floatValue;
String _stringValue;
float _volume;
float _balance;
};
}
#endif /* Spine_Event_h */
@@ -0,0 +1,68 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_EventData_h
#define Spine_EventData_h
#include <spine/SpineObject.h>
#include <spine/SpineString.h>
#include <spine/Event.h>
namespace spine {
/// Stores the setup pose values for an Event.
class SP_API EventData : public SpineObject {
friend class SkeletonBinary;
friend class SkeletonJson;
friend class Event;
public:
explicit EventData(const String &name);
/// The name of the event, unique across all events in the skeleton.
const String &getName() const;
/// The setup values that are shared by all events with this data.
Event &getSetupPose();
const Event &getSetupPose() const;
/// Path to an audio file relative to the audio folder as defined in Spine.
const String &getAudioPath() const;
void setAudioPath(const String &inValue);
private:
const String _name;
String _audioPath;
Event _setupPose;
};
}
#endif /* Spine_EventData_h */
@@ -0,0 +1,67 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_EventTimeline_h
#define Spine_EventTimeline_h
#include <spine/Timeline.h>
namespace spine {
/// Fires an Event when specific animation times are reached.
class SP_API EventTimeline : public Timeline {
friend class SkeletonBinary;
friend class SkeletonJson;
RTTI_DECL
public:
explicit EventTimeline(size_t frameCount);
~EventTimeline();
/// Fires events for frames > lastTime and <= time.
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixFrom from, bool add, bool out,
bool appliedPose) override;
size_t getFrameCount();
/// The event for each frame.
Array<Event *> &getEvents();
/// Sets the time and event for the specified frame.
/// @param frame Between 0 and frameCount, inclusive.
void setFrame(size_t frame, Event &event);
private:
Array<Event *> _events;
};
}
#endif /* Spine_EventTimeline_h */
@@ -0,0 +1,136 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_Extension_h
#define Spine_Extension_h
#include <stdlib.h>
#include <string.h>
#include <spine/dll.h>
#define SP_UNUSED(x) (void) (x)
namespace spine {
class String;
class SP_API SpineExtension {
public:
template<typename T>
static T *alloc(size_t num, const char *file, int line) {
return (T *) getInstance()->_alloc(sizeof(T) * num, file, line);
}
template<typename T>
static T *calloc(size_t num, const char *file, int line) {
return (T *) getInstance()->_calloc(sizeof(T) * num, file, line);
}
template<typename T>
static T *realloc(T *ptr, size_t num, const char *file, int line) {
return (T *) getInstance()->_realloc(ptr, sizeof(T) * num, file, line);
}
template<typename T>
static void free(T *ptr, const char *file, int line) {
getInstance()->_free((void *) ptr, file, line);
}
template<typename T>
static void beforeFree(T *ptr) {
getInstance()->_beforeFree((void *) ptr);
}
static char *readFile(const String &path, int *length) {
return getInstance()->_readFile(path, length);
}
static char *strdup(const char *str, const char *file, int line) {
if (!str) return nullptr;
size_t len = strlen(str) + 1;
char *copy = (char *) getInstance()->_alloc(len, file, line);
memcpy(copy, str, len);
return copy;
}
static void setInstance(SpineExtension *inSpineExtension);
static SpineExtension *getInstance();
virtual ~SpineExtension();
/// Implement this function to use your own memory allocator
virtual void *_alloc(size_t size, const char *file, int line) = 0;
virtual void *_calloc(size_t size, const char *file, int line) = 0;
virtual void *_realloc(void *ptr, size_t size, const char *file, int line) = 0;
/// If you provide a spineAllocFunc, you should also provide a spineFreeFunc
virtual void _free(void *mem, const char *file, int line) = 0;
virtual char *_readFile(const String &path, int *length) = 0;
virtual void _beforeFree(void *ptr) {
SP_UNUSED(ptr);
}
protected:
SpineExtension();
private:
static SpineExtension *_instance;
};
class SP_API DefaultSpineExtension : public SpineExtension {
public:
DefaultSpineExtension();
virtual ~DefaultSpineExtension();
protected:
virtual void *_alloc(size_t size, const char *file, int line) override;
virtual void *_calloc(size_t size, const char *file, int line) override;
virtual void *_realloc(void *ptr, size_t size, const char *file, int line) override;
virtual void _free(void *mem, const char *file, int line) override;
virtual char *_readFile(const String &path, int *length) override;
};
// This function is to be implemented by engine specific runtimes to provide
// the default extension for that engine. It is called the first time
// SpineExtension::getInstance() is called, when no instance has been set
// yet.
extern SpineExtension *getDefaultExtension();
}
#endif /* Spine_Extension_h */
@@ -0,0 +1,65 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_HasRendererObject_h
#define Spine_HasRendererObject_h
#include <spine/dll.h>
namespace spine {
typedef void (*DisposeRendererObject)(void *rendererObject);
class SP_API HasRendererObject {
public:
explicit HasRendererObject() : _rendererObject(0), _dispose(0) {};
virtual ~HasRendererObject() {
if (_dispose && _rendererObject) _dispose(_rendererObject);
}
void *getRendererObject() {
return _rendererObject;
}
void setRendererObject(void *rendererObject, DisposeRendererObject dispose = 0) {
if (_dispose && _rendererObject && _rendererObject != rendererObject) _dispose(_rendererObject);
_rendererObject = rendererObject;
_dispose = dispose;
}
private:
void *_rendererObject;
DisposeRendererObject _dispose;
};
}
#endif
@@ -0,0 +1,202 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_HashMap_h
#define Spine_HashMap_h
#include <spine/Array.h>
#include <spine/SpineObject.h>
// Required for new with line number and file name in MSVC
#ifdef _MSC_VER
#pragma warning(disable : 4291)
#pragma warning(disable : 4251)
#endif
namespace spine {
template<typename K, typename V>
class HashMap : public SpineObject {
private:
class Entry;
public:
class Pair {
public:
explicit Pair(K &k, V &v) : key(k), value(v) {
}
K &key;
V &value;
};
class Entries {
public:
friend class HashMap;
explicit Entries(Entry *entry) : _hasChecked(false) {
_start.next = entry;
_entry = &_start;
}
Pair next() {
assert(_entry);
assert(_hasChecked);
_entry = _entry->next;
Pair pair(_entry->_key, _entry->_value);
_hasChecked = false;
return pair;
}
bool hasNext() {
_hasChecked = true;
return _entry->next;
}
private:
bool _hasChecked;
Entry _start;
Entry *_entry;
};
HashMap() : _head(NULL), _size(0) {
}
~HashMap() {
clear();
}
void clear() {
for (Entry *entry = _head; entry != NULL;) {
Entry *next = entry->next;
delete entry;
entry = next;
}
_head = NULL;
_size = 0;
}
size_t size() {
return _size;
}
void put(const K &key, const V &value) {
Entry *entry = find(key);
if (entry) {
entry->_key = key;
entry->_value = value;
} else {
entry = new (__FILE__, __LINE__) Entry();
entry->_key = key;
entry->_value = value;
Entry *oldHead = _head;
if (oldHead) {
_head = entry;
oldHead->prev = entry;
entry->next = oldHead;
} else {
_head = entry;
}
_size++;
}
}
bool addAll(Array<K> &keys, const V &value) {
size_t oldSize = _size;
for (size_t i = 0; i < keys.size(); i++) {
put(keys[i], value);
}
return _size != oldSize;
}
bool containsKey(const K &key) {
return find(key) != NULL;
}
bool remove(const K &key) {
Entry *entry = find(key);
if (!entry) return false;
Entry *prev = entry->prev;
Entry *next = entry->next;
if (prev)
prev->next = next;
else
_head = next;
if (next) next->prev = entry->prev;
delete entry;
_size--;
return true;
}
V operator[](const K &key) {
Entry *entry = find(key);
if (entry)
return entry->_value;
else {
assert(false);
return 0;
}
}
Entries getEntries() const {
return Entries(_head);
}
private:
Entry *find(const K &key) {
for (Entry *entry = _head; entry != NULL; entry = entry->next) {
if (entry->_key == key) return entry;
}
return NULL;
}
class SP_API Entry : public SpineObject {
public:
K _key;
V _value;
Entry *next;
Entry *prev;
Entry() : next(NULL), prev(NULL) {
}
};
Entry *_head;
size_t _size;
};
}
#endif /* Spine_HashMap_h */
@@ -0,0 +1,92 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_IkConstraint_h
#define Spine_IkConstraint_h
#include <spine/Constraint.h>
#include <spine/ConstraintData.h>
#include <spine/IkConstraintData.h>
#include <spine/IkConstraintPose.h>
#include <spine/Array.h>
namespace spine {
class Skeleton;
class Bone;
class BonePose;
// Non-exported base class that inherits from the template
class IkConstraintBase : public ConstraintGeneric<IkConstraint, IkConstraintData, IkConstraintPose> {
public:
IkConstraintBase(IkConstraintData &data) : ConstraintGeneric<IkConstraint, IkConstraintData, IkConstraintPose>(data) {
}
};
class SP_API IkConstraint : public IkConstraintBase {
friend class Skeleton;
friend class IkConstraintTimeline;
RTTI_DECL
public:
IkConstraint(IkConstraintData &data, Skeleton &skeleton);
virtual IkConstraint &copy(Skeleton &skeleton);
virtual void update(Skeleton &skeleton, Physics physics) override;
virtual void sort(Skeleton &skeleton) override;
virtual bool isSourceActive() override;
Array<BonePose *> &getBones();
Bone &getTarget();
void setTarget(Bone &inValue);
/// Adjusts the local rotation of the bone so the world position of the tip is as close to the target position as
/// possible. The target is specified in the world coordinate system.
static void apply(Skeleton &skeleton, BonePose &bone, float targetX, float targetY, bool compress, bool stretch, ScaleYMode scaleYMode,
float mix);
/// Adjusts the parent and child bone rotations so the tip of the child is as close to the target position as
/// possible. The target is specified in the world coordinate system.
/// @param child A direct descendant of the parent bone.
static void apply(Skeleton &skeleton, BonePose &parent, BonePose &child, float targetX, float targetY, int bendDirection, bool stretch,
ScaleYMode scaleYMode, float softness, float mix);
private:
Array<BonePose *> _bones;
Bone *_target;
};
}
#endif /* Spine_IkConstraint_h */
@@ -0,0 +1,83 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_IkConstraintData_h
#define Spine_IkConstraintData_h
#include <spine/Array.h>
#include <spine/SpineObject.h>
#include <spine/SpineString.h>
#include <spine/ConstraintData.h>
#include <spine/PosedData.h>
#include <spine/IkConstraintPose.h>
namespace spine {
class BoneData;
class IkConstraint;
class SP_API IkConstraintData : public ConstraintDataGeneric<IkConstraint, IkConstraintPose> {
friend class SkeletonBinary;
friend class SkeletonJson;
friend class IkConstraint;
friend class Skeleton;
friend class IkConstraintTimeline;
RTTI_DECL
public:
explicit IkConstraintData(const String &name);
virtual Constraint &create(Skeleton &skeleton) override;
/// The bones that are constrained by this IK Constraint.
Array<BoneData *> &getBones();
/// The bone that is the IK target.
BoneData &getTarget();
void setTarget(BoneData &inValue);
/// Determines how BonePose::getScaleY() changes when IkConstraintPose::getCompress() or IkConstraintPose::getStretch()
/// sets BonePose::getScaleX().
ScaleYMode getScaleYMode();
void setScaleYMode(ScaleYMode scaleYMode);
private:
Array<BoneData *> _bones;
BoneData *_target;
ScaleYMode _scaleYMode;
};
}
#endif /* Spine_IkConstraintData_h */
@@ -0,0 +1,84 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_IkConstraintPose_h
#define Spine_IkConstraintPose_h
#include <spine/Pose.h>
#include <spine/RTTI.h>
namespace spine {
/// Stores a pose for an IK constraint.
class SP_API IkConstraintPose : public Pose<IkConstraintPose> {
friend class IkConstraint;
friend class IkConstraintTimeline;
friend class SkeletonJson;
friend class SkeletonBinary;
public:
IkConstraintPose();
virtual ~IkConstraintPose();
virtual void set(IkConstraintPose &pose) override;
/// A percentage (0-1) that controls the mix between the constrained and unconstrained rotation.
///
/// For two bone IK: if the parent bone has local nonuniform scale, the child bone's local Y translation is set to 0.
float getMix();
void setMix(float mix);
/// For two bone IK, the target bone's distance from the maximum reach of the bones where rotation begins to slow. The bones
/// will not straighten completely until the target is this far out of range.
float getSoftness();
void setSoftness(float softness);
/// For two bone IK, controls the bend direction of the IK bones, either 1 or -1.
int getBendDirection();
void setBendDirection(int bendDirection);
/// For one bone IK, when true and the target is too close, the bone is scaled to reach it.
bool getCompress();
void setCompress(bool compress);
/// When true and the target is out of range, the parent bone is scaled to reach it.
///
/// For two bone IK: 1) the child bone's local Y translation is set to 0, 2) stretch is not applied if softness is
/// > 0, and 3) if the parent bone has local nonuniform scale, stretch is not applied.
bool getStretch();
void setStretch(bool stretch);
private:
int _bendDirection;
bool _compress, _stretch;
float _mix, _softness;
};
}
#endif /* Spine_IkConstraintPose_h */
@@ -0,0 +1,80 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_IkConstraintTimeline_h
#define Spine_IkConstraintTimeline_h
#include <spine/CurveTimeline.h>
#include <spine/ConstraintTimeline.h>
namespace spine {
/// Changes an IK constraint's mix, softness, bend direction, stretch, and compress values.
class SP_API IkConstraintTimeline : public CurveTimeline, public ConstraintTimeline {
friend class SkeletonBinary;
friend class SkeletonJson;
RTTI_DECL
public:
explicit IkConstraintTimeline(size_t frameCount, size_t bezierCount, int constraintIndex);
virtual ~IkConstraintTimeline();
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixFrom from, bool add, bool out,
bool appliedPose) override;
/// Sets the time, mix, softness, bend direction, compress, and stretch for the specified frame.
/// @param frame Between 0 and frameCount, inclusive.
/// @param time The frame time in seconds.
/// @param bendDirection 1 or -1.
void setFrame(int frame, float time, float mix, float softness, int bendDirection, bool compress, bool stretch);
virtual int getConstraintIndex() const override {
return _constraintIndex;
}
virtual void setConstraintIndex(int inValue) override {
_constraintIndex = inValue;
}
private:
int _constraintIndex;
static const int ENTRIES = 6;
static const int MIX = 1;
static const int SOFTNESS = 2;
static const int BEND_DIRECTION = 3;
static const int COMPRESS = 4;
static const int STRETCH = 5;
};
}
#endif /* Spine_IkConstraintTimeline_h */
@@ -0,0 +1,61 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_TransformMode_h
#define Spine_TransformMode_h
#include <string.h>
namespace spine {
/// Determines how a bone inherits world transforms from parent bones.
enum Inherit {
Inherit_Normal = 0,
Inherit_OnlyTranslation,
Inherit_NoRotationOrReflection,
Inherit_NoScale,
Inherit_NoScaleOrReflection
};
inline Inherit Inherit_valueOf(const char *value) {
if (strcmp(value, "normal") == 0)
return Inherit_Normal;
else if (strcmp(value, "onlyTranslation") == 0)
return Inherit_OnlyTranslation;
else if (strcmp(value, "noRotationOrReflection") == 0)
return Inherit_NoRotationOrReflection;
else if (strcmp(value, "noScale") == 0)
return Inherit_NoScale;
else if (strcmp(value, "noScaleOrReflection") == 0)
return Inherit_NoScaleOrReflection;
else
return Inherit_Normal;// default
}
}
#endif /* Spine_TransformMode_h */
@@ -0,0 +1,79 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_InheritTimeline_h
#define Spine_InheritTimeline_h
#include <spine/Timeline.h>
#include <spine/BoneTimeline.h>
#include <spine/Animation.h>
#include <spine/Property.h>
#include <spine/Inherit.h>
namespace spine {
/// Changes a bone's inherit mode.
class SP_API InheritTimeline : public Timeline, public BoneTimeline {
friend class SkeletonBinary;
friend class SkeletonJson;
RTTI_DECL
public:
explicit InheritTimeline(size_t frameCount, int boneIndex);
virtual ~InheritTimeline();
/// Sets the inherit transform mode for the specified frame.
/// @param frame Between 0 and frameCount, inclusive.
/// @param time The frame time in seconds.
void setFrame(int frame, float time, Inherit inherit);
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixFrom from, bool add, bool out,
bool appliedPose) override;
virtual int getBoneIndex() const override {
return _boneIndex;
}
void setBoneIndex(int inValue) override {
_boneIndex = inValue;
}
private:
int _boneIndex;
static const int ENTRIES = 2;
static const int INHERIT = 1;
};
}
#endif /* Spine_InheritTimeline_h */
@@ -0,0 +1,61 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_Interpolation_h
#define Spine_Interpolation_h
#include <spine/SpineObject.h>
namespace spine {
/// Takes a linear value in the range 0-1 and outputs a usually non-linear, interpolated value.
class SP_API Interpolation : public SpineObject {
public:
virtual ~Interpolation();
/// @param a Alpha value between 0 and 1.
virtual float apply(float a);
float apply(float start, float end, float a);
static Interpolation &linear();
/// Aka "smoothstep".
static Interpolation &smooth();
/// Slow, then fast.
static Interpolation &slowFast();
/// Fast, then slow.
static Interpolation &fastSlow();
static Interpolation &circle();
};
}
#endif /* Spine_Interpolation_h */
@@ -0,0 +1,141 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_Json_h
#define Spine_Json_h
#include <spine/SpineObject.h>
#include <spine/Array.h>
#ifndef SPINE_JSON_HAVE_PREV
/* spine doesn't use the "prev" link in the Json sibling lists. */
#define SPINE_JSON_HAVE_PREV 0
#endif
namespace spine {
class SP_API Json : public SpineObject {
friend class SkeletonJson;
public:
/* Json Types: */
static const int JSON_FALSE;
static const int JSON_TRUE;
static const int JSON_NULL;
static const int JSON_NUMBER;
static const int JSON_STRING;
static const int JSON_ARRAY;
static const int JSON_OBJECT;
static bool asFloatArray(Json *value, Array<float> &array) {
if (value == NULL) return false;
array.setSize(value->_size, 0);
Json *vertex = value->_child;
for (int i = 0; vertex; vertex = vertex->_next, i++) array[i] = vertex->_valueFloat;
return true;
}
static bool asIntArray(Json *value, Array<int> &array) {
if (value == NULL) return false;
array.setSize(value->_size, 0);
Json *vertex = value->_child;
for (int i = 0; vertex; vertex = vertex->_next, i++) array[i] = vertex->_valueInt;
return true;
}
static bool asUnsignedShortArray(Json *value, Array<unsigned short> &array) {
if (value == NULL) return false;
array.setSize(value->_size, 0);
Json *vertex = value->_child;
for (int i = 0; vertex; vertex = vertex->_next, i++) array[i] = (unsigned short) vertex->_valueInt;
return true;
}
/* Get item "string" from object. Case insensitive. */
static Json *getItem(Json *object, const char *string);
static Json *getItem(Json *object, int childIndex);
static const char *getString(Json *object, const char *name, const char *defaultValue);
static float getFloat(Json *object, const char *name, float defaultValue);
static int getInt(Json *object, const char *name, int defaultValue);
static bool getBoolean(Json *object, const char *name, bool defaultValue);
/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when Json_create() returns 0. 0 when Json_create() succeeds. */
static const char *getError();
/* Supply a block of JSON, and this returns a Json object you can interrogate. Call Json_dispose when finished. */
explicit Json(const char *value);
~Json();
private:
static const char *_error;
Json *_next;
#if SPINE_JSON_HAVE_PREV
Json *_prev; /* next/prev allow you to walk array/object chains. Alternatively, use getSize/getItem */
#endif
Json *_child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
int _type; /* The type of the item, as above. */
int _size; /* The number of children. */
const char *_valueString; /* The item's string, if type==JSON_STRING */
int _valueInt; /* The item's number, if type==JSON_NUMBER */
float _valueFloat; /* The item's number, if type==JSON_NUMBER */
const char *_name; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
/* Utility to jump whitespace and cr/lf */
static const char *skip(const char *inValue);
/* Parser core - when encountering text, process appropriately. */
static const char *parseValue(Json *item, const char *value);
/* Parse the input text into an unescaped cstring, and populate item. */
static const char *parseString(Json *item, const char *str);
/* Parse the input text to generate a number, and populate the result into item. */
static const char *parseNumber(Json *item, const char *num);
/* Build an array from input text. */
static const char *parseArray(Json *item, const char *value);
/* Build an object from the text. */
static const char *parseObject(Json *item, const char *value);
static int json_strcasecmp(const char *s1, const char *s2);
};
}
#endif /* Spine_Json_h */
@@ -0,0 +1,60 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_LinkedMesh_h
#define Spine_LinkedMesh_h
#include <spine/SpineObject.h>
#include <spine/SpineString.h>
namespace spine {
class MeshAttachment;
class SP_API LinkedMesh : public SpineObject {
friend class SkeletonBinary;
friend class SkeletonJson;
public:
LinkedMesh(MeshAttachment &mesh, const int skinIndex, size_t slotIndex, size_t sourceIndex, const String &source, bool inheritTimelines);
LinkedMesh(MeshAttachment &mesh, const String &skin, size_t slotIndex, size_t sourceIndex, const String &source, bool inheritTimelines);
private:
MeshAttachment *_mesh;
int _skinIndex;
String _skin;
size_t _slotIndex;
size_t _sourceIndex;
String _source;
bool _inheritTimelines;
};
}
#endif /* Spine_LinkedMesh_h */
@@ -0,0 +1,400 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_Map_h
#define Spine_Map_h
#include <spine/Array.h>
#include <spine/Extension.h>
#include <spine/SpineObject.h>
#include <spine/SpineString.h>
#include <assert.h>
#include <stdint.h>
#include <string.h>
namespace spine {
template<typename K>
class MapHash {
public:
size_t operator()(const K &key) const {
return (size_t) key;
}
};
template<typename T>
class MapHash<T *> {
public:
size_t operator()(T *const &key) const {
uintptr_t value = (uintptr_t) key;
return (size_t) (value >> 4);
}
};
template<>
class MapHash<long long> {
public:
size_t operator()(const long long &key) const {
unsigned long long value = (unsigned long long) key;
return (size_t) (value ^ (value >> 32));
}
};
template<>
class MapHash<unsigned long long> {
public:
size_t operator()(const unsigned long long &key) const {
return (size_t) (key ^ (key >> 32));
}
};
template<>
class MapHash<String> {
public:
size_t operator()(const String &key) const {
const unsigned char *buffer = (const unsigned char *) key.buffer();
size_t length = key.length();
uint64_t hash = 14695981039346656037ULL;
for (size_t i = 0; i < length; i++) {
hash ^= buffer[i];
hash *= 1099511628211ULL;
}
return (size_t) (hash ^ (hash >> 32));
}
};
template<typename K>
class MapEquals {
public:
bool operator()(const K &a, const K &b) const {
return a == b;
}
};
/// A compact open-addressed hash map. Unlike HashMap, this implementation does not allocate per entry.
/// Iteration order is unspecified and may change when the map grows or entries are removed.
template<typename K, typename V, typename Hash = MapHash<K>, typename Equals = MapEquals<K>>
class Map : public SpineObject {
private:
enum State {
Empty = 0,
Occupied = 1,
Deleted = 2
};
struct Entry {
K key;
V value;
};
public:
class Pair {
public:
explicit Pair(K &k, V &v) : key(k), value(v) {
}
K &key;
V &value;
};
class Entries {
public:
friend class Map;
bool hasNext() {
while (_index < _map->_capacity) {
if (_map->_states[_index] == Occupied) return true;
_index++;
}
return false;
}
Pair next() {
assert(_index < _map->_capacity);
assert(_map->_states[_index] == Occupied);
Entry &entry = _map->_entries[_index++];
return Pair(entry.key, entry.value);
}
private:
explicit Entries(Map &map) : _map(&map), _index(0) {
}
Map *_map;
size_t _index;
};
Map() : _entries(NULL), _states(NULL), _capacity(0), _size(0), _deleted(0), _hash(), _equals() {
}
explicit Map(size_t capacity) : _entries(NULL), _states(NULL), _capacity(0), _size(0), _deleted(0), _hash(), _equals() {
ensureCapacity(capacity);
}
Map(const Map &other) : _entries(NULL), _states(NULL), _capacity(0), _size(0), _deleted(0), _hash(other._hash), _equals(other._equals) {
ensureCapacity(other._size);
for (size_t i = 0; i < other._capacity; i++) {
if (other._states[i] == Occupied) put(other._entries[i].key, other._entries[i].value);
}
}
Map &operator=(const Map &other) {
if (this == &other) return *this;
clear();
_hash = other._hash;
_equals = other._equals;
ensureCapacity(other._size);
for (size_t i = 0; i < other._capacity; i++) {
if (other._states[i] == Occupied) put(other._entries[i].key, other._entries[i].value);
}
return *this;
}
~Map() {
release();
}
size_t size() const {
return _size;
}
size_t getCapacity() const {
return _capacity;
}
bool isEmpty() const {
return _size == 0;
}
void ensureCapacity(size_t expectedSize) {
size_t needed = capacityFor(expectedSize);
if (_capacity < needed) rehash(needed);
}
void clear() {
for (size_t i = 0; i < _capacity; i++) {
if (_states[i] == Occupied) resetEntry(i);
_states[i] = Empty;
}
_size = 0;
_deleted = 0;
}
void release() {
if (!_entries) return;
clear();
for (size_t i = 0; i < _capacity; i++) _entries[i].~Entry();
SpineExtension::free(_entries, __FILE__, __LINE__);
SpineExtension::free(_states, __FILE__, __LINE__);
_entries = NULL;
_states = NULL;
_capacity = 0;
}
bool containsKey(const K &key) const {
return findIndex(key) >= 0;
}
V *get(const K &key) {
int index = findIndex(key);
return index >= 0 ? &_entries[index].value : NULL;
}
const V *get(const K &key) const {
int index = findIndex(key);
return index >= 0 ? &_entries[index].value : NULL;
}
V operator[](const K &key) const {
const V *value = get(key);
assert(value);
return *value;
}
void put(const K &key, const V &value) {
ensureLoadForOneMore();
bool found = false;
size_t index = findSlot(key, found);
if (found) {
_entries[index].value = value;
return;
}
if (_states[index] == Deleted) _deleted--;
_states[index] = Occupied;
_entries[index].key = key;
_entries[index].value = value;
_size++;
}
/// Adds the key and value only if the key is not already present.
/// @return The existing value, or V() if the key was not present and the new value was added.
V putMissing(const K &key, const V &value) {
ensureLoadForOneMore();
bool found = false;
size_t index = findSlot(key, found);
if (found) return _entries[index].value;
if (_states[index] == Deleted) _deleted--;
_states[index] = Occupied;
_entries[index].key = key;
_entries[index].value = value;
_size++;
return V();
}
bool addAll(Array<K> &keys, const V &value) {
size_t oldSize = _size;
ensureCapacity(_size + keys.size());
for (size_t i = 0; i < keys.size(); i++) put(keys[i], value);
return _size != oldSize;
}
bool remove(const K &key) {
int index = findIndex(key);
if (index < 0) return false;
resetEntry((size_t) index);
_states[index] = Deleted;
_size--;
_deleted++;
if (_size == 0) {
memset(_states, Empty, _capacity);
_deleted = 0;
}
return true;
}
Entries getEntries() {
return Entries(*this);
}
private:
Entry *_entries;
unsigned char *_states;
size_t _capacity;
size_t _size;
size_t _deleted;
Hash _hash;
Equals _equals;
static size_t mix(size_t h) {
h ^= h >> 16;
h *= (size_t) 0x7feb352d;
h ^= h >> 15;
h *= (size_t) 0x846ca68b;
h ^= h >> 16;
return h;
}
static size_t nextPowerOfTwo(size_t value) {
size_t result = 8;
while (result < value) result <<= 1;
return result;
}
static size_t capacityFor(size_t expectedSize) {
if (expectedSize < 6) return 8;
return nextPowerOfTwo((expectedSize * 4 + 2) / 3);
}
void ensureLoadForOneMore() {
if (_capacity == 0) {
rehash(8);
return;
}
if ((_size + _deleted + 1) * 4 > _capacity * 3) {
size_t newCapacity = _deleted > _size ? _capacity : _capacity << 1;
rehash(newCapacity);
}
}
int findIndex(const K &key) const {
if (_capacity == 0) return -1;
size_t mask = _capacity - 1;
size_t index = mix(_hash(key)) & mask;
while (true) {
unsigned char state = _states[index];
if (state == Empty) return -1;
if (state == Occupied && _equals(_entries[index].key, key)) return (int) index;
index = (index + 1) & mask;
}
}
/// Returns an index containing key, an empty slot, or the first deleted slot encountered.
size_t findSlot(const K &key, bool &found) const {
size_t mask = _capacity - 1;
size_t index = mix(_hash(key)) & mask;
size_t firstDeleted = (size_t) -1;
while (true) {
unsigned char state = _states[index];
if (state == Empty) {
found = false;
return firstDeleted != (size_t) -1 ? firstDeleted : index;
}
if (state == Deleted) {
if (firstDeleted == (size_t) -1) firstDeleted = index;
} else if (_equals(_entries[index].key, key)) {
found = true;
return index;
}
index = (index + 1) & mask;
}
}
void rehash(size_t newCapacity) {
newCapacity = nextPowerOfTwo(newCapacity);
Entry *oldEntries = _entries;
unsigned char *oldStates = _states;
size_t oldCapacity = _capacity;
_entries = SpineExtension::alloc<Entry>(newCapacity, __FILE__, __LINE__);
_states = SpineExtension::calloc<unsigned char>(newCapacity, __FILE__, __LINE__);
assert(_entries);
assert(_states);
_capacity = newCapacity;
_size = 0;
_deleted = 0;
for (size_t i = 0; i < _capacity; i++) new (_entries + i) Entry();
if (oldEntries) {
for (size_t i = 0; i < oldCapacity; i++) {
if (oldStates[i] == Occupied) put(oldEntries[i].key, oldEntries[i].value);
oldEntries[i].~Entry();
}
SpineExtension::free(oldEntries, __FILE__, __LINE__);
SpineExtension::free(oldStates, __FILE__, __LINE__);
}
}
void resetEntry(size_t index) {
_entries[index].key = K();
_entries[index].value = V();
}
};
}
#endif /* Spine_Map_h */
@@ -0,0 +1,111 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_MathUtil_h
#define Spine_MathUtil_h
#include <spine/SpineObject.h>
#include <string.h>
// Needed for older MSVC versions
#undef min
#undef max
namespace spine {
class SP_API MathUtil : public SpineObject {
private:
MathUtil();
public:
static const float Epsilon;
static const float EpsilonSq;
static const float Pi;
static const float Pi_2;
static const float InvPi_2;
static const float Deg_Rad;
static const float Rad_Deg;
template<typename T>
static inline T min(T a, T b) {
return a < b ? a : b;
}
template<typename T>
static inline T max(T a, T b) {
return a > b ? a : b;
}
static float sign(float val);
static float clamp(float x, float lower, float upper);
static float abs(float v);
/// Returns the sine in radians from a lookup table.
static float sin(float radians);
/// Returns the cosine in radians from a lookup table.
static float cos(float radians);
/// Returns the sine in radians from a lookup table.
static float sinDeg(float degrees);
/// Returns the cosine in radians from a lookup table.
static float cosDeg(float degrees);
/// Returns atan2 in radians, faster but less accurate than Math.Atan2. Average error of 0.00231 radians (0.1323
/// degrees), largest error of 0.00488 radians (0.2796 degrees).
static float atan2(float y, float x);
static float atan2Deg(float x, float y);
static float acos(float v);
static float sqrt(float v);
static float fmod(float a, float b);
static bool isNan(float v);
static float quietNan();
static float random();
static float randomTriangular(float min, float max);
static float randomTriangular(float min, float max, float mode);
static float pow(float a, float b);
static float ceil(float v);
};
}
#endif /* Spine_MathUtil_h */
@@ -0,0 +1,116 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_MeshAttachment_h
#define Spine_MeshAttachment_h
#include <spine/Array.h>
#include <spine/Color.h>
#include <spine/HasRendererObject.h>
#include <spine/Sequence.h>
#include <spine/TextureRegion.h>
#include <spine/VertexAttachment.h>
namespace spine {
/// Attachment that displays a texture region using a mesh.
class SP_API MeshAttachment : public VertexAttachment {
friend class SkeletonBinary;
friend class SkeletonJson;
friend class AtlasAttachmentLoader;
RTTI_DECL
public:
explicit MeshAttachment(const String &name, Sequence *sequence);
virtual ~MeshAttachment();
using VertexAttachment::computeWorldVertices;
virtual void computeWorldVertices(Skeleton &skeleton, Slot &slot, size_t start, size_t count, float *worldVertices, size_t offset,
size_t stride = 2) override;
Array<float> &getRegionUVs();
void setRegionUVs(Array<float> &inValue);
Array<unsigned short> &getTriangles();
void setTriangles(Array<unsigned short> &inValue);
int getHullLength();
void setHullLength(int inValue);
Sequence &getSequence();
void updateSequence();
const String &getPath();
void setPath(const String &inValue);
Color &getColor();
/// The source mesh if this is a linked mesh, else NULL. A linked mesh shares the bones, vertices, regionUVs,
/// triangles, hullLength, edges, width, and height with the source mesh, but may have a different name or path,
/// and therefore a different texture region.
MeshAttachment *getSourceMesh();
void setSourceMesh(MeshAttachment *inValue);
/// Vertex index pairs describing edges for controlling triangulation, or empty if nonessential data was not
/// exported. Mesh triangles do not cross edges. Triangulation is not performed at runtime.
Array<unsigned short> &getEdges();
void setEdges(Array<unsigned short> &inValue);
float getWidth();
void setWidth(float inValue);
float getHeight();
void setHeight(float inValue);
virtual Attachment &copy() override;
MeshAttachment &newLinkedMesh();
/// Computes UVs for a mesh attachment.
/// @param uvs Output array for the computed UVs, same length as regionUVs.
static void computeUVs(TextureRegion *region, Array<float> &regionUVs, Array<float> &uvs);
private:
Sequence *_sequence;
Array<float> _regionUVs;
Array<unsigned short> _triangles;
int _hullLength;
String _path;
Color _color;
MeshAttachment *_sourceMesh;
Array<unsigned short> _edges;
float _width, _height;
};
}
#endif /* Spine_MeshAttachment_h */
@@ -0,0 +1,74 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_PathAttachment_h
#define Spine_PathAttachment_h
#include <spine/VertexAttachment.h>
#include <spine/Color.h>
namespace spine {
class SP_API PathAttachment : public VertexAttachment {
friend class SkeletonBinary;
friend class SkeletonJson;
RTTI_DECL
public:
explicit PathAttachment(const String &name);
/// The length in the setup pose from the start of the path to the end of each curve.
Array<float> &getLengths();
void setLengths(Array<float> &inValue);
bool getClosed();
void setClosed(bool inValue);
/// If true, additional calculations are performed to make computing positions along the path more accurate so
/// movement along the path has a constant speed.
bool getConstantSpeed();
void setConstantSpeed(bool inValue);
Color &getColor();
virtual Attachment &copy() override;
private:
Array<float> _lengths;
bool _closed;
bool _constantSpeed;
Color _color;
};
}
#endif /* Spine_PathAttachment_h */
@@ -0,0 +1,118 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_PathConstraint_h
#define Spine_PathConstraint_h
#include <spine/Constraint.h>
#include <spine/ConstraintData.h>
#include <spine/PathConstraintData.h>
#include <spine/PathConstraintPose.h>
#include <spine/Array.h>
namespace spine {
class Skeleton;
class PathAttachment;
class BonePose;
class Slot;
class Bone;
class Skin;
class Attachment;
/// Adjusts the rotation, translation, and scale of the constrained bones so they follow a PathAttachment.
///
/// See https://esotericsoftware.com/spine-path-constraints Path constraints in the Spine User Guide.
// Non-exported base class that inherits from the template
class PathConstraintBase : public ConstraintGeneric<PathConstraint, PathConstraintData, PathConstraintPose> {
public:
PathConstraintBase(PathConstraintData &data) : ConstraintGeneric<PathConstraint, PathConstraintData, PathConstraintPose>(data) {
}
};
class SP_API PathConstraint : public PathConstraintBase {
friend class Skeleton;
friend class PathConstraintMixTimeline;
friend class PathConstraintPositionTimeline;
friend class PathConstraintPositionTimeline;
friend class PathConstraintSpacingTimeline;
RTTI_DECL
public:
static const float epsilon;
static const int NONE;
static const int BEFORE;
static const int AFTER;
PathConstraint(PathConstraintData &data, Skeleton &skeleton);
PathConstraint &copy(Skeleton &skeleton);
/// Applies the constraint to the constrained bones.
virtual void update(Skeleton &skeleton, Physics physics) override;
virtual void sort(Skeleton &skeleton) override;
virtual bool isSourceActive() override;
/// The bones that will be modified by this path constraint.
Array<BonePose *> &getBones();
/// The slot whose path attachment will be used to constrained the bones.
Slot &getSlot();
void setSlot(Slot &slot);
private:
Array<BonePose *> _bones;
Slot *_slot;
Array<float> _spaces;
Array<float> _positions;
Array<float> _world;
Array<float> _curves;
Array<float> _lengths;
Array<float> _segments;
Array<float> &computeWorldPositions(Skeleton &skeleton, PathAttachment &path, int spacesCount, bool tangents);
void addBeforePosition(float p, Array<float> &temp, int i, Array<float> &output, int o);
void addAfterPosition(float p, Array<float> &temp, int i, Array<float> &output, int o);
void addCurvePosition(float p, float x1, float y1, float cx1, float cy1, float cx2, float cy2, float x2, float y2, Array<float> &output,
int o, bool tangents);
void sortPathSlot(Skeleton &skeleton, Skin &skin, int slotIndex, Bone &slotBone);
void sortPath(Skeleton &skeleton, Attachment *attachment, Bone &slotBone);
};
}
#endif /* Spine_PathConstraint_h */
@@ -0,0 +1,111 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_PathConstraintData_h
#define Spine_PathConstraintData_h
#include <spine/ConstraintData.h>
#include <spine/PosedData.h>
#include <spine/Array.h>
#include <spine/PathConstraintPose.h>
#include <spine/dll.h>
#include <spine/PositionMode.h>
#include <spine/SpacingMode.h>
#include <spine/RotateMode.h>
namespace spine {
class BoneData;
class SlotData;
class PathConstraint;
class Skeleton;
/// Stores the setup pose for a PathConstraint.
///
/// See https://esotericsoftware.com/spine-path-constraints Path constraints in the Spine User Guide.
class SP_API PathConstraintData : public ConstraintDataGeneric<PathConstraint, PathConstraintPose> {
friend class SkeletonBinary;
friend class SkeletonJson;
friend class PathConstraint;
friend class Skeleton;
friend class PathConstraintMixTimeline;
friend class PathConstraintPositionTimeline;
friend class PathConstraintSpacingTimeline;
RTTI_DECL
public:
explicit PathConstraintData(const String &name);
virtual Constraint &create(Skeleton &skeleton) override;
/// The bones that will be modified by this path constraint.
Array<BoneData *> &getBones();
/// The slot whose path attachment will be used to constrained the bones.
SlotData &getSlot();
void setSlot(SlotData &slot);
/// The mode for positioning the first bone on the path.
PositionMode getPositionMode();
void setPositionMode(PositionMode positionMode);
/// The mode for positioning the bones after the first bone on the path.
SpacingMode getSpacingMode();
void setSpacingMode(SpacingMode spacingMode);
/// The mode for adjusting the rotation of the bones.
RotateMode getRotateMode();
void setRotateMode(RotateMode rotateMode);
/// An offset added to the constrained bone rotation.
float getOffsetRotation();
void setOffsetRotation(float offsetRotation);
private:
Array<BoneData *> _bones;
SlotData *_slot;
PositionMode _positionMode;
SpacingMode _spacingMode;
RotateMode _rotateMode;
float _offsetRotation;
};
}
#endif /* Spine_PathConstraintData_h */
@@ -0,0 +1,77 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_PathConstraintMixTimeline_h
#define Spine_PathConstraintMixTimeline_h
#include <spine/CurveTimeline.h>
#include <spine/ConstraintTimeline.h>
namespace spine {
/// Changes a path constraint's rotate, x, and y mix values.
class SP_API PathConstraintMixTimeline : public CurveTimeline, public ConstraintTimeline {
friend class SkeletonBinary;
friend class SkeletonJson;
RTTI_DECL
public:
explicit PathConstraintMixTimeline(size_t frameCount, size_t bezierCount, int constraintIndex);
virtual ~PathConstraintMixTimeline();
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixFrom from, bool add, bool out,
bool appliedPose) override;
/// Sets the time and color for the specified frame.
/// @param frame Between 0 and frameCount, inclusive.
/// @param time The frame time in seconds.
void setFrame(int frame, float time, float mixRotate, float mixX, float mixY);
virtual int getConstraintIndex() const override {
return _constraintIndex;
}
virtual void setConstraintIndex(int inValue) override {
_constraintIndex = inValue;
}
private:
int _constraintIndex;
static const int ENTRIES = 4;
static const int ROTATE = 1;
static const int X = 2;
static const int Y = 3;
};
}
#endif /* Spine_PathConstraintMixTimeline_h */
@@ -0,0 +1,81 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_PathConstraintPose_h
#define Spine_PathConstraintPose_h
#include <spine/Pose.h>
#include <spine/RTTI.h>
namespace spine {
/// Stores a pose for a path constraint.
class SP_API PathConstraintPose : public Pose<PathConstraintPose> {
friend class PathConstraint;
friend class PathConstraintPositionTimeline;
friend class PathConstraintSpacingTimeline;
friend class PathConstraintMixTimeline;
friend class SkeletonJson;
friend class SkeletonBinary;
private:
float _position;
float _spacing;
float _mixRotate;
float _mixX;
float _mixY;
public:
PathConstraintPose();
virtual ~PathConstraintPose();
virtual void set(PathConstraintPose &pose) override;
/// The position along the path.
float getPosition();
void setPosition(float position);
/// The spacing between bones.
float getSpacing();
void setSpacing(float spacing);
/// A percentage (0-1) that controls the mix between the constrained and unconstrained rotation.
float getMixRotate();
void setMixRotate(float mixRotate);
/// A percentage (0-1) that controls the mix between the constrained and unconstrained translation X.
float getMixX();
void setMixX(float mixX);
/// A percentage (0-1) that controls the mix between the constrained and unconstrained translation Y.
float getMixY();
void setMixY(float mixY);
};
}
#endif
@@ -0,0 +1,57 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_PathConstraintPositionTimeline_h
#define Spine_PathConstraintPositionTimeline_h
#include <spine/ConstraintTimeline1.h>
namespace spine {
/// Changes a path constraint's position.
class SP_API PathConstraintPositionTimeline : public ConstraintTimeline1 {
friend class SkeletonBinary;
friend class SkeletonJson;
RTTI_DECL
public:
static const int ENTRIES;
explicit PathConstraintPositionTimeline(size_t frameCount, size_t bezierCount, int constraintIndex);
virtual ~PathConstraintPositionTimeline();
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixFrom from, bool add, bool out,
bool appliedPose) override;
};
}// namespace spine
#endif /* Spine_PathConstraintPositionTimeline_h */
@@ -0,0 +1,54 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_PathConstraintSpacingTimeline_h
#define Spine_PathConstraintSpacingTimeline_h
#include <spine/ConstraintTimeline1.h>
namespace spine {
/// Changes a path constraint's spacing.
class SP_API PathConstraintSpacingTimeline : public ConstraintTimeline1 {
friend class SkeletonBinary;
friend class SkeletonJson;
RTTI_DECL
public:
explicit PathConstraintSpacingTimeline(size_t frameCount, size_t bezierCount, int constraintIndex);
virtual ~PathConstraintSpacingTimeline();
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixFrom from, bool add, bool out,
bool appliedPose) override;
};
}
#endif /* Spine_PathConstraintSpacingTimeline_h */
@@ -0,0 +1,50 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_Physics_h
#define Spine_Physics_h
namespace spine {
/// Determines how physics and other non-deterministic updates are applied.
enum Physics {
/// Physics are not updated or applied.
Physics_None,
/// Physics are reset via PhysicsConstraint::reset().
Physics_Reset,
/// Physics are updated and the pose from physics is applied.
Physics_Update,
/// Physics are not updated but the pose from physics is applied.
Physics_Pose
};
}
#endif
@@ -0,0 +1,104 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_PhysicsConstraint_h
#define Spine_PhysicsConstraint_h
#include <spine/Constraint.h>
#include <spine/PhysicsConstraintData.h>
#include <spine/PhysicsConstraintPose.h>
#include <spine/BonePose.h>
#include <spine/Array.h>
namespace spine {
class Skeleton;
class BonePose;
class PhysicsConstraintPose;
/// Applies physics to a bone.
///
/// See https://esotericsoftware.com/spine-physics-constraints Physics constraints in the Spine User Guide.
// Non-exported base class that inherits from the template
class PhysicsConstraintBase : public ConstraintGeneric<PhysicsConstraint, PhysicsConstraintData, PhysicsConstraintPose> {
public:
PhysicsConstraintBase(PhysicsConstraintData &data)
: ConstraintGeneric<PhysicsConstraint, PhysicsConstraintData, PhysicsConstraintPose>(data) {
}
};
class SP_API PhysicsConstraint : public PhysicsConstraintBase {
friend class Skeleton;
friend class PhysicsConstraintTimeline;
friend class PhysicsConstraintInertiaTimeline;
friend class PhysicsConstraintStrengthTimeline;
friend class PhysicsConstraintDampingTimeline;
friend class PhysicsConstraintMassTimeline;
friend class PhysicsConstraintWindTimeline;
friend class PhysicsConstraintGravityTimeline;
friend class PhysicsConstraintMixTimeline;
friend class PhysicsConstraintResetTimeline;
public:
RTTI_DECL
PhysicsConstraint(PhysicsConstraintData &data, Skeleton &skeleton);
void update(Skeleton &skeleton, Physics physics) override;
void sort(Skeleton &skeleton) override;
bool isSourceActive() override;
PhysicsConstraint &copy(Skeleton &skeleton);
/// Resets all physics state that was the result of previous movement. Use this after moving a bone to prevent physics
/// from reacting to the movement.
void reset(Skeleton &skeleton);
/// Translates the physics constraint so the next update() forces are applied as if the bone moved an additional amount in world space.
void translate(float x, float y);
/// Rotates the physics constraint so the next update() forces are applied as if the bone rotated around the specified point in world space.
void rotate(float x, float y, float degrees);
/// The bone constrained by this physics constraint.
BonePose &getBone();
void setBone(BonePose &bone);
private:
BonePose *_bone;
bool _reset;
float _ux, _uy, _cx, _cy, _tx, _ty;
float _xOffset, _xLag, _xVelocity;
float _yOffset, _yLag, _yVelocity;
float _rotateOffset, _rotateLag, _rotateVelocity;
float _scaleOffset, _scaleLag, _scaleVelocity;
float _remaining, _lastTime;
};
}
#endif /* Spine_PhysicsConstraint_h */
@@ -0,0 +1,128 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_PhysicsConstraintData_h
#define Spine_PhysicsConstraintData_h
#include <spine/ConstraintData.h>
#include <spine/PosedData.h>
#include <spine/PhysicsConstraintPose.h>
namespace spine {
class BoneData;
class PhysicsConstraint;
/// Stores the setup pose for a PhysicsConstraint.
///
/// See https://esotericsoftware.com/spine-physics-constraints Physics constraints in the Spine User Guide.
class SP_API PhysicsConstraintData : public ConstraintDataGeneric<PhysicsConstraint, PhysicsConstraintPose> {
friend class SkeletonBinary;
friend class SkeletonJson;
friend class PhysicsConstraint;
friend class Skeleton;
RTTI_DECL
public:
explicit PhysicsConstraintData(const String &name);
virtual Constraint &create(Skeleton &skeleton) override;
/// The bone constrained by this physics constraint.
BoneData &getBone();
void setBone(BoneData &bone);
/// The time in milliseconds required to advanced the physics simulation one step.
float getStep();
void setStep(float step);
/// Physics influence on x translation, 0-1.
float getX();
void setX(float x);
/// Physics influence on y translation, 0-1.
float getY();
void setY(float y);
/// Physics influence on rotation, 0-1.
float getRotate();
void setRotate(float rotate);
/// Physics influence on scaleX, 0-1.
float getScaleX();
void setScaleX(float scaleX);
/// Physics influence on shearX, 0-1.
float getShearX();
void setShearX(float shearX);
/// Movement greater than the limit will not have a greater affect on physics.
float getLimit();
void setLimit(float limit);
/// Determines how BonePose::getScaleY() changes when getScaleX() sets BonePose::getScaleX().
ScaleYMode getScaleYMode();
void setScaleYMode(ScaleYMode scaleYMode);
/// True when this constraint's inertia is controlled by global slider timelines.
bool getInertiaGlobal();
void setInertiaGlobal(bool inertiaGlobal);
/// True when this constraint's strength is controlled by global slider timelines.
bool getStrengthGlobal();
void setStrengthGlobal(bool strengthGlobal);
/// True when this constraint's damping is controlled by global slider timelines.
bool getDampingGlobal();
void setDampingGlobal(bool dampingGlobal);
/// True when this constraint's mass is controlled by global slider timelines.
bool getMassGlobal();
void setMassGlobal(bool massGlobal);
/// True when this constraint's wind is controlled by global slider timelines.
bool getWindGlobal();
void setWindGlobal(bool windGlobal);
/// True when this constraint's gravity is controlled by global slider timelines.
bool getGravityGlobal();
void setGravityGlobal(bool gravityGlobal);
/// True when this constraint's mix is controlled by global slider timelines.
bool getMixGlobal();
void setMixGlobal(bool mixGlobal);
private:
BoneData *_bone;
float _x, _y, _rotate, _scaleX, _shearX, _limit, _step;
ScaleYMode _scaleYMode;
bool _inertiaGlobal, _strengthGlobal, _dampingGlobal, _massGlobal, _windGlobal, _gravityGlobal, _mixGlobal;
};
}
#endif /* Spine_PhysicsConstraintData_h */
@@ -0,0 +1,89 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_PhysicsConstraintPose_h
#define Spine_PhysicsConstraintPose_h
#include <spine/Pose.h>
#include <spine/RTTI.h>
namespace spine {
/// Stores a pose for a physics constraint.
class SP_API PhysicsConstraintPose : public Pose<PhysicsConstraintPose> {
friend class PhysicsConstraint;
friend class PhysicsConstraintTimeline;
friend class SkeletonJson;
friend class SkeletonBinary;
private:
float _inertia;
float _strength;
float _damping;
float _massInverse;
float _wind;
float _gravity;
float _mix;
public:
PhysicsConstraintPose();
virtual ~PhysicsConstraintPose();
virtual void set(PhysicsConstraintPose &pose) override;
/// Controls how much bone movement is converted into physics movement.
float getInertia();
void setInertia(float inertia);
/// The amount of force used to return properties to the unconstrained value.
float getStrength();
void setStrength(float strength);
/// Reduces the speed of physics movements, with more of a reduction at higher speeds.
float getDamping();
void setDamping(float damping);
/// Determines susceptibility to acceleration.
float getMassInverse();
void setMassInverse(float massInverse);
/// Applies a constant force along the Skeleton::getWindX(), Skeleton::getWindY() vector.
float getWind();
void setWind(float wind);
/// Applies a constant force along the Skeleton::getGravityX(), Skeleton::getGravityY() vector.
float getGravity();
void setGravity(float gravity);
/// A percentage (0+) that controls the mix between the constrained and unconstrained poses.
float getMix();
void setMix(float mix);
};
}
#endif
@@ -0,0 +1,300 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_PhysicsConstraintTimeline_h
#define Spine_PhysicsConstraintTimeline_h
#include <spine/ConstraintTimeline.h>
#include <spine/CurveTimeline.h>
#include <spine/PhysicsConstraint.h>
#include <spine/PhysicsConstraintData.h>
#include <spine/PhysicsConstraintPose.h>
namespace spine {
/// The base class for most PhysicsConstraint timelines.
class SP_API PhysicsConstraintTimeline : public CurveTimeline1, public ConstraintTimeline {
friend class SkeletonBinary;
friend class SkeletonJson;
RTTI_DECL
public:
/// @param constraintIndex -1 for all physics constraints in the skeleton.
explicit PhysicsConstraintTimeline(size_t frameCount, size_t bezierCount, int constraintIndex, Property property);
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixFrom from, bool add, bool out,
bool appliedPose) override;
virtual int getConstraintIndex() const override {
return _constraintIndex;
}
virtual void setConstraintIndex(int inValue) override {
_constraintIndex = inValue;
}
protected:
virtual float get(PhysicsConstraintPose &pose) = 0;
virtual void set(PhysicsConstraintPose &pose, float value) = 0;
virtual bool global(PhysicsConstraintData &constraintData) = 0;
int _constraintIndex;
};
/// Changes a physics constraint's inertia.
class SP_API PhysicsConstraintInertiaTimeline : public PhysicsConstraintTimeline {
friend class SkeletonBinary;
friend class SkeletonJson;
RTTI_DECL
public:
explicit PhysicsConstraintInertiaTimeline(size_t frameCount, size_t bezierCount, int physicsConstraintIndex)
: PhysicsConstraintTimeline(frameCount, bezierCount, physicsConstraintIndex, Property_PhysicsConstraintInertia) {};
protected:
float get(PhysicsConstraintPose &pose) override {
return pose.getInertia();
}
void set(PhysicsConstraintPose &pose, float value) override {
pose.setInertia(value);
}
bool global(PhysicsConstraintData &constraintData) override {
return constraintData.getInertiaGlobal();
}
};
/// Changes a physics constraint's strength.
class SP_API PhysicsConstraintStrengthTimeline : public PhysicsConstraintTimeline {
friend class SkeletonBinary;
friend class SkeletonJson;
RTTI_DECL
public:
explicit PhysicsConstraintStrengthTimeline(size_t frameCount, size_t bezierCount, int physicsConstraintIndex)
: PhysicsConstraintTimeline(frameCount, bezierCount, physicsConstraintIndex, Property_PhysicsConstraintStrength) {};
protected:
float get(PhysicsConstraintPose &pose) override {
return pose.getStrength();
}
void set(PhysicsConstraintPose &pose, float value) override {
pose.setStrength(value);
}
bool global(PhysicsConstraintData &constraintData) override {
return constraintData.getStrengthGlobal();
}
};
/// Changes a physics constraint's damping.
class SP_API PhysicsConstraintDampingTimeline : public PhysicsConstraintTimeline {
friend class SkeletonBinary;
friend class SkeletonJson;
RTTI_DECL
public:
explicit PhysicsConstraintDampingTimeline(size_t frameCount, size_t bezierCount, int physicsConstraintIndex)
: PhysicsConstraintTimeline(frameCount, bezierCount, physicsConstraintIndex, Property_PhysicsConstraintDamping) {};
protected:
float get(PhysicsConstraintPose &pose) override {
return pose.getDamping();
}
void set(PhysicsConstraintPose &pose, float value) override {
pose.setDamping(value);
}
bool global(PhysicsConstraintData &constraintData) override {
return constraintData.getDampingGlobal();
}
};
/// Changes a physics constraint's mass inverse. The timeline values are not inverted.
class SP_API PhysicsConstraintMassTimeline : public PhysicsConstraintTimeline {
friend class SkeletonBinary;
friend class SkeletonJson;
RTTI_DECL
public:
explicit PhysicsConstraintMassTimeline(size_t frameCount, size_t bezierCount, int physicsConstraintIndex)
: PhysicsConstraintTimeline(frameCount, bezierCount, physicsConstraintIndex, Property_PhysicsConstraintMass) {};
protected:
float get(PhysicsConstraintPose &pose) override {
return 1 / pose.getMassInverse();
}
void set(PhysicsConstraintPose &pose, float value) override {
pose.setMassInverse(1 / value);
}
bool global(PhysicsConstraintData &constraintData) override {
return constraintData.getMassGlobal();
}
};
/// Changes a physics constraint's wind.
class SP_API PhysicsConstraintWindTimeline : public PhysicsConstraintTimeline {
friend class SkeletonBinary;
friend class SkeletonJson;
RTTI_DECL
public:
explicit PhysicsConstraintWindTimeline(size_t frameCount, size_t bezierCount, int physicsConstraintIndex)
: PhysicsConstraintTimeline(frameCount, bezierCount, physicsConstraintIndex, Property_PhysicsConstraintWind) {
_additive = true;
};
protected:
float get(PhysicsConstraintPose &pose) override {
return pose.getWind();
}
void set(PhysicsConstraintPose &pose, float value) override {
pose.setWind(value);
}
bool global(PhysicsConstraintData &constraintData) override {
return constraintData.getWindGlobal();
}
};
/// Changes a physics constraint's gravity.
class SP_API PhysicsConstraintGravityTimeline : public PhysicsConstraintTimeline {
friend class SkeletonBinary;
friend class SkeletonJson;
RTTI_DECL
public:
explicit PhysicsConstraintGravityTimeline(size_t frameCount, size_t bezierCount, int physicsConstraintIndex)
: PhysicsConstraintTimeline(frameCount, bezierCount, physicsConstraintIndex, Property_PhysicsConstraintGravity) {
_additive = true;
};
protected:
float get(PhysicsConstraintPose &pose) override {
return pose.getGravity();
}
void set(PhysicsConstraintPose &pose, float value) override {
pose.setGravity(value);
}
bool global(PhysicsConstraintData &constraintData) override {
return constraintData.getGravityGlobal();
}
};
/// Changes a physics constraint's mix.
class SP_API PhysicsConstraintMixTimeline : public PhysicsConstraintTimeline {
friend class SkeletonBinary;
friend class SkeletonJson;
RTTI_DECL
public:
explicit PhysicsConstraintMixTimeline(size_t frameCount, size_t bezierCount, int physicsConstraintIndex)
: PhysicsConstraintTimeline(frameCount, bezierCount, physicsConstraintIndex, Property_PhysicsConstraintMix) {};
protected:
float get(PhysicsConstraintPose &pose) override {
return pose.getMix();
}
void set(PhysicsConstraintPose &pose, float value) override {
pose.setMix(value);
}
bool global(PhysicsConstraintData &constraintData) override {
return constraintData.getMixGlobal();
}
};
/// Resets a physics constraint when specific animation times are reached.
class SP_API PhysicsConstraintResetTimeline : public Timeline, public ConstraintTimeline {
friend class SkeletonBinary;
friend class SkeletonJson;
RTTI_DECL
public:
/// @param constraintIndex -1 for all physics constraints in the skeleton.
explicit PhysicsConstraintResetTimeline(size_t frameCount, int constraintIndex)
: Timeline(frameCount, 1), ConstraintTimeline(), _constraintIndex(constraintIndex) {
PropertyId ids[] = {((PropertyId) Property_PhysicsConstraintReset) << 32};
setPropertyIds(ids, 1);
_instant = true;
}
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixFrom from, bool add, bool out,
bool appliedPose) override;
int getFrameCount() {
return (int) _frames.size();
}
virtual int getConstraintIndex() const override {
return _constraintIndex;
}
virtual void setConstraintIndex(int inValue) override {
_constraintIndex = inValue;
}
/// Sets the time for the specified frame.
void setFrame(int frame, float time) {
_frames[frame] = time;
}
private:
int _constraintIndex;
};
}// namespace spine
#endif /* Spine_PhysicsConstraintTimeline_h */
@@ -0,0 +1,87 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_PointAttachment_h
#define Spine_PointAttachment_h
#include <spine/Attachment.h>
#include <spine/Color.h>
namespace spine {
class Bone;
class BonePose;
/// An attachment which is a single point and a rotation. This can be used to spawn projectiles, particles, etc. A bone can be
/// used in similar ways, but a PointAttachment is slightly less expensive to compute and can be hidden, shown, and placed in a
/// skin.
///
/// See https://esotericsoftware.com/spine-points for Point Attachments in the Spine User Guide.
///
class SP_API PointAttachment : public Attachment {
friend class SkeletonBinary;
friend class SkeletonJson;
RTTI_DECL
public:
explicit PointAttachment(const String &name);
/// The local x position.
float getX();
void setX(float inValue);
/// The local y position.
float getY();
void setY(float inValue);
/// The local rotation in degrees, counter clockwise.
float getRotation();
void setRotation(float inValue);
Color &getColor();
/// Computes the world position from the local position.
void computeWorldPosition(BonePose &bone, float &ox, float &oy);
/// Computes the world rotation from the local rotation.
float computeWorldRotation(BonePose &bone);
virtual Attachment &copy() override;
private:
float _x, _y, _rotation;
Color _color;
};
}
#endif /* Spine_PointAttachment_h */
@@ -0,0 +1,74 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_Pool_h
#define Spine_Pool_h
#include <spine/Extension.h>
#include <spine/Array.h>
#include <spine/ArrayUtils.h>
#include <spine/SpineObject.h>
namespace spine {
template<typename T>
class SP_API Pool : public SpineObject {
public:
Pool() {
}
~Pool() {
ArrayUtils::deleteElements(_objects);
}
T *obtain() {
if (_objects.size() > 0) {
T **object = &_objects[_objects.size() - 1];
T *ret = *object;
_objects.removeAt(_objects.size() - 1);
return ret;
} else {
T *ret = new (__FILE__, __LINE__) T();
return ret;
}
}
void free(T *object) {
if (!_objects.contains(object)) {
_objects.add(object);
}
}
private:
Array<T *> _objects;
};
}
#endif /* Spine_Pool_h */
@@ -0,0 +1,48 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_Pose_h
#define Spine_Pose_h
#include <spine/SpineObject.h>
namespace spine {
/// An interface for an object representing a pose.
template<class P>
class SP_API Pose : public SpineObject {
public:
Pose() {};
virtual ~Pose() {};
/// Sets this pose to the specified pose.
virtual void set(P &pose) = 0;
};
}
#endif
@@ -0,0 +1,148 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_Posed_h
#define Spine_Posed_h
#include <spine/SpineObject.h>
namespace spine {
/// Base interface for posed objects.
class SP_API Posed {
public:
Posed() {
}
virtual ~Posed() {
}
virtual void constrained() = 0;
virtual void resetConstrained() = 0;
virtual bool isPoseEqualToApplied() = 0;
protected:
virtual void setupPose() = 0;
virtual void unconstrained() = 0;
};
/// The base class for an object with a number of poses:
/// - getData(): The setup pose data.
/// - getPose(): The unconstrained pose. Set by animations and application code.
/// - getAppliedPose(): The pose to use for rendering. Possibly modified by constraints.
template<class D, class P, class A>
class PosedGeneric : public Posed, public SpineObject {
friend class AnimationState;
friend class BoneTimeline1;
friend class BoneTimeline2;
friend class RotateTimeline;
friend class IkConstraint;
friend class TransformConstraint;
friend class VertexAttachment;
friend class PathConstraint;
friend class PhysicsConstraint;
friend class Skeleton;
friend class RegionAttachment;
friend class PointAttachment;
friend class AttachmentTimeline;
friend class RGBATimeline;
friend class RGBTimeline;
friend class AlphaTimeline;
friend class RGBA2Timeline;
friend class RGB2Timeline;
friend class ScaleTimeline;
friend class ScaleXTimeline;
friend class ScaleYTimeline;
friend class ShearTimeline;
friend class ShearXTimeline;
friend class ShearYTimeline;
friend class TranslateTimeline;
friend class TranslateXTimeline;
friend class TranslateYTimeline;
friend class InheritTimeline;
friend class Skeleton;
public:
PosedGeneric(D &data) : _data(data), _pose(), _constrainedPose(), _appliedPose(&_pose) {
setupPose();
}
virtual ~PosedGeneric() {
}
/// The setup pose data. May be shared with multiple instances.
D &getData() {
return _data;
}
/// The unconstrained pose for this object, set by animations and application code.
P &getPose() {
return _pose;
}
/// The pose to use for rendering. If no constraints modify this pose, this is the same as getPose(). Otherwise it is a
/// copy of getPose() modified by constraints.
A &getAppliedPose() {
return *_appliedPose;
}
/// Sets the constrained pose to the unconstrained pose, as a starting point for constraints to be applied.
virtual void resetConstrained() override {
_constrainedPose.set(_pose);
}
/// Sets the applied pose to the constrained pose, in anticipation of the applied pose being modified by constraints.
virtual void constrained() override {
_appliedPose = &_constrainedPose;
}
virtual bool isPoseEqualToApplied() override {
return _appliedPose == &_pose;
}
protected:
/// Sets the applied pose to the unconstrained pose, for when no constraints will modify the pose.
virtual void unconstrained() override {
_appliedPose = &_pose;
}
/// Sets the unconstrained pose to the setup pose.
virtual void setupPose() override {
_pose.set(_data.getSetupPose());
}
protected:
D &_data;
A _pose; ///< Stored as A type (concrete pose type) to match Java behavior
A _constrainedPose;///< Stored as A type (concrete pose type) to match Java behavior
A *_appliedPose; ///< Points to either _pose or _constrainedPose, reassignable like Java
};
}// namespace spine
#endif /* Spine_Posed_h */
@@ -0,0 +1,59 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_PosedActive_h
#define Spine_PosedActive_h
#include <spine/dll.h>
namespace spine {
/// A posed object that may be active or inactive.
class SP_API PosedActive {
protected:
bool _active;
public:
PosedActive() : _active(true) {
}
virtual ~PosedActive() {
}
/// Returns false when this won't be updated by Skeleton::updateWorldTransform(Physics) because a skin is
/// required and the active skin does not contain this item. See Skin::getBones(), Skin::getConstraints(),
/// PosedData::getSkinRequired(), and Skeleton::updateCache().
bool isActive() const {
return _active;
}
void setActive(bool active) {
_active = active;
}
};
}
#endif /* Spine_PosedActive_h */
@@ -0,0 +1,146 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_PosedData_h
#define Spine_PosedData_h
#include <spine/SpineObject.h>
#include <spine/SpineString.h>
namespace spine {
template<class P>
class Pose;
class SP_API PosedData : public SpineObject {
friend class SkeletonBinary;
friend class SkeletonJson;
friend class BoneTimeline1;
friend class BoneTimeline2;
friend class RotateTimeline;
friend class AttachmentTimeline;
friend class RGBATimeline;
friend class RGBTimeline;
friend class AlphaTimeline;
friend class RGBA2Timeline;
friend class RGB2Timeline;
friend class ScaleTimeline;
friend class ScaleXTimeline;
friend class ScaleYTimeline;
friend class ShearTimeline;
friend class ShearXTimeline;
friend class ShearYTimeline;
friend class TranslateTimeline;
friend class TranslateXTimeline;
friend class TranslateYTimeline;
friend class InheritTimeline;
friend class Skeleton;
friend class Slot;
public:
PosedData(const String &name);
virtual ~PosedData();
const String &getName() const {
return _name;
};
/// When true, Skeleton::updateWorldTransform(Physics) only updates this constraint if the Skeleton::getSkin()
/// contains this constraint.
///
/// See Skin::getConstraints().
bool getSkinRequired() const {
return _skinRequired;
};
void setSkinRequired(bool skinRequired) {
_skinRequired = skinRequired;
};
protected:
String _name;
bool _skinRequired;
};
inline PosedData::PosedData(const String &name) : _name(name), _skinRequired(false) {
}
inline PosedData::~PosedData() {
}
/// The base class for storing setup data for a posed object. May be shared with multiple instances.
template<class P>
class PosedDataGeneric : public PosedData {
friend class SkeletonBinary;
friend class SkeletonJson;
friend class BoneTimeline1;
friend class BoneTimeline2;
friend class RotateTimeline;
friend class AttachmentTimeline;
friend class RGBATimeline;
friend class RGBTimeline;
friend class AlphaTimeline;
friend class RGBA2Timeline;
friend class RGB2Timeline;
friend class ScaleTimeline;
friend class ScaleXTimeline;
friend class ScaleYTimeline;
friend class ShearTimeline;
friend class ShearXTimeline;
friend class ShearYTimeline;
friend class TranslateTimeline;
friend class TranslateXTimeline;
friend class TranslateYTimeline;
friend class InheritTimeline;
friend class PhysicsConstraintTimeline;
friend class PhysicsConstraintInertiaTimeline;
friend class PhysicsConstraintStrengthTimeline;
friend class PhysicsConstraintDampingTimeline;
friend class PhysicsConstraintMassTimeline;
friend class PhysicsConstraintWindTimeline;
friend class PhysicsConstraintGravityTimeline;
friend class Slot;
protected:
P _setupPose;
public:
PosedDataGeneric(const String &name) : PosedData(name), _setupPose() {
}
virtual ~PosedDataGeneric() {};
/// The setup pose that most animations are relative to.
P &getSetupPose() {
return _setupPose;
};
const P &getSetupPose() const {
return _setupPose;
};
};
}
#endif
@@ -0,0 +1,54 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_PositionMode_h
#define Spine_PositionMode_h
#include <string.h>
namespace spine {
/// Controls how the first bone is positioned along the path.
///
/// @see https://esotericsoftware.com/spine-path-constraints#Position-mode Position mode in the Spine User Guide.
enum PositionMode {
PositionMode_Fixed = 0,
PositionMode_Percent
};
inline PositionMode PositionMode_valueOf(const char *value) {
if (strcmp(value, "fixed") == 0)
return PositionMode_Fixed;
else if (strcmp(value, "percent") == 0)
return PositionMode_Percent;
else
return PositionMode_Percent;// default
}
}
#endif /* Spine_PositionMode_h */
@@ -0,0 +1,71 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_Property_h
#define Spine_Property_h
namespace spine {
typedef long long PropertyId;
enum Property {
Property_Rotate = 0,
Property_X,
Property_Y,
Property_ScaleX,
Property_ScaleY,
Property_ShearX,
Property_ShearY,
Property_Inherit,
Property_Rgb,
Property_Alpha,
Property_Rgb2,
Property_Attachment,
Property_Deform,
Property_Event,
Property_DrawOrder,
Property_IkConstraint,
Property_TransformConstraint,
Property_PathConstraintPosition,
Property_PathConstraintSpacing,
Property_PathConstraintMix,
Property_PhysicsConstraintInertia,
Property_PhysicsConstraintStrength,
Property_PhysicsConstraintDamping,
Property_PhysicsConstraintMass,
Property_PhysicsConstraintWind,
Property_PhysicsConstraintGravity,
Property_PhysicsConstraintMix,
Property_PhysicsConstraintReset,
Property_Sequence,
Property_SliderTime,
Property_SliderMix,
Property_DrawOrderFolder
};
}
#endif /* Spine_Property_h */
@@ -0,0 +1,92 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_RTTI_h
#define Spine_RTTI_h
#include <spine/dll.h>
namespace spine {
class SP_API RTTI {
public:
explicit RTTI(const char *className);
RTTI(const char *className, const RTTI &baseRTTI);
// New constructor for multiple interfaces (up to 3)
RTTI(const char *className, const RTTI &baseRTTI, const RTTI *interface1, const RTTI *interface2 = 0, const RTTI *interface3 = 0);
const char *getClassName() const;
bool isExactly(const RTTI &rtti) const;
bool instanceOf(const RTTI &rtti) const;
private:
// Prevent copying
RTTI(const RTTI &obj);
RTTI &operator=(const RTTI &obj);
const char *_className;
const RTTI *_pBaseRTTI;
const RTTI *_interfaces[3];// Support up to 3 interfaces
int _interfaceCount;
};
}
#define RTTI_DECL_NOPARENT \
public: \
static const RTTI rtti; \
virtual const RTTI &getRTTI() const;
#define RTTI_DECL \
public: \
static const RTTI rtti; \
virtual const RTTI &getRTTI() const override;
#define RTTI_IMPL_NOPARENT(name) \
const RTTI name::rtti(#name); \
const RTTI &name::getRTTI() const { \
return rtti; \
}
#define RTTI_IMPL(name, parent) \
const RTTI name::rtti(#name, parent::rtti); \
const RTTI &name::getRTTI() const { \
return rtti; \
}
#define RTTI_IMPL_MULTI(name, parent, ...) \
const RTTI name::rtti(#name, parent::rtti, &__VA_ARGS__::rtti); \
const RTTI &name::getRTTI() const { \
return rtti; \
}
#endif /* Spine_RTTI_h */
@@ -0,0 +1,126 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_RegionAttachment_h
#define Spine_RegionAttachment_h
#include <spine/Attachment.h>
#include <spine/Array.h>
#include <spine/Color.h>
#include <spine/HasRendererObject.h>
#include <spine/Sequence.h>
#include <spine/TextureRegion.h>
namespace spine {
class Slot;
class SlotPose;
/// Attachment that displays a texture region.
class SP_API RegionAttachment : public Attachment {
friend class SkeletonBinary;
friend class SkeletonJson;
friend class AtlasAttachmentLoader;
RTTI_DECL
public:
explicit RegionAttachment(const String &name, Sequence *sequence);
virtual ~RegionAttachment();
/// Transforms the attachment's four vertices to world coordinates.
/// @param slot The parent slot.
/// @param vertexOffsets The vertex offsets.
/// @param worldVertices The output world vertices. Must have a length greater than or equal to offset + 8.
/// @param offset The worldVertices index to begin writing values.
/// @param stride The number of worldVertices entries between the value pairs written.
void computeWorldVertices(Slot &slot, float *vertexOffsets, float *worldVertices, size_t offset, size_t stride = 2);
void computeWorldVertices(Slot &slot, Array<float> &vertexOffsets, Array<float> &worldVertices, size_t offset, size_t stride = 2);
/// Returns the vertex offsets for the specified slot pose.
Array<float> &getOffsets(SlotPose &pose);
float getX();
void setX(float inValue);
float getY();
void setY(float inValue);
float getScaleX();
void setScaleX(float inValue);
float getScaleY();
void setScaleY(float inValue);
/// The local rotation in degrees, counter clockwise.
float getRotation();
void setRotation(float inValue);
float getWidth();
void setWidth(float inValue);
float getHeight();
void setHeight(float inValue);
Sequence &getSequence();
void updateSequence();
const String &getPath();
void setPath(const String &inValue);
Color &getColor();
virtual Attachment &copy() override;
/// Computes UVs and offsets for a region attachment.
/// @param uvs Output array for the computed UVs, length of 8.
/// @param offset Output array for the computed vertex offsets, length of 8.
static void computeUVs(TextureRegion *region, float x, float y, float scaleX, float scaleY, float rotation, float width, float height,
Array<float> &offset, Array<float> &uvs);
private:
static const int BLX;
static const int BLY;
static const int ULX;
static const int ULY;
static const int URX;
static const int URY;
static const int BRX;
static const int BRY;
Sequence *_sequence;
float _x, _y, _scaleX, _scaleY, _rotation, _width, _height;
String _path;
Color _color;
};
}
#endif /* Spine_RegionAttachment_h */
@@ -0,0 +1,59 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_RotateMode_h
#define Spine_RotateMode_h
#include <string.h>
namespace spine {
/// Controls how bones are rotated, translated, and scaled to match the path.
///
/// @see https://esotericsoftware.com/spine-path-constraints#Rotate-Mix Rotate mode in the Spine User Guide.
enum RotateMode {
RotateMode_Tangent = 0,
RotateMode_Chain,
/// When chain scale, constrained bones should all have the same parent. That way when the path constraint scales a bone, it
/// doesn't affect other constrained bones.
RotateMode_ChainScale
};
inline RotateMode RotateMode_valueOf(const char *value) {
if (strcmp(value, "tangent") == 0)
return RotateMode_Tangent;
else if (strcmp(value, "chain") == 0)
return RotateMode_Chain;
else if (strcmp(value, "chainScale") == 0)
return RotateMode_ChainScale;
else
return RotateMode_Tangent;// default
}
}
#endif /* Spine_RotateMode_h */
@@ -0,0 +1,54 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_RotateTimeline_h
#define Spine_RotateTimeline_h
#include <spine/BoneTimeline.h>
namespace spine {
/// Changes a bone's local rotation.
class SP_API RotateTimeline : public BoneTimeline1 {
friend class SkeletonBinary;
friend class SkeletonJson;
friend class AnimationState;
RTTI_DECL
public:
explicit RotateTimeline(size_t frameCount, size_t bezierCount, int boneIndex);
protected:
virtual void _apply(BonePose &pose, BonePose &setup, float time, float alpha, MixFrom from, bool add, bool out) override;
};
}
#endif /* Spine_RotateTimeline_h */
@@ -0,0 +1,82 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_ScaleTimeline_h
#define Spine_ScaleTimeline_h
#include <spine/BoneTimeline.h>
namespace spine {
/// Changes a bone's local scaleX and scaleY.
class SP_API ScaleTimeline : public BoneTimeline2 {
friend class SkeletonBinary;
friend class SkeletonJson;
RTTI_DECL
public:
explicit ScaleTimeline(size_t frameCount, size_t bezierCount, int boneIndex);
protected:
virtual void _apply(BonePose &pose, BonePose &setup, float time, float alpha, MixFrom from, bool add, bool out) override;
};
/// Changes a bone's local scaleX.
class SP_API ScaleXTimeline : public BoneTimeline1 {
friend class SkeletonBinary;
friend class SkeletonJson;
RTTI_DECL
public:
explicit ScaleXTimeline(size_t frameCount, size_t bezierCount, int boneIndex);
protected:
virtual void _apply(BonePose &pose, BonePose &setup, float time, float alpha, MixFrom from, bool add, bool out) override;
};
/// Changes a bone's local scaleY.
class SP_API ScaleYTimeline : public BoneTimeline1 {
friend class SkeletonBinary;
friend class SkeletonJson;
RTTI_DECL
public:
explicit ScaleYTimeline(size_t frameCount, size_t bezierCount, int boneIndex);
protected:
virtual void _apply(BonePose &pose, BonePose &setup, float time, float alpha, MixFrom from, bool add, bool out) override;
};
}
#endif /* Spine_ScaleTimeline_h */
@@ -0,0 +1,163 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_Sequence_h
#define Spine_Sequence_h
#include <spine/Array.h>
#include <spine/RTTI.h>
#include <spine/SpineString.h>
#include <spine/TextureRegion.h>
namespace spine {
class SlotPose;
class RegionAttachment;
class MeshAttachment;
class SkeletonBinary;
class SkeletonJson;
/// Holds texture regions, UVs, and vertex offsets for rendering a region or mesh attachment.
/// Regions must be populated and update() called before use.
class SP_API Sequence : public SpineObject {
friend class SkeletonBinary;
friend class SkeletonJson;
public:
/// @param count The number of texture regions this sequence will display.
/// @param pathSuffix If true, getPath(String, int) has a numeric suffix. If false, all regions will use the same path,
/// so count should be 1.
Sequence(int count, bool pathSuffix);
/// Copy constructor.
Sequence(const Sequence &other);
~Sequence();
/// Computes UVs and offsets for the specified attachment. Must be called if the regions
/// or attachment properties are changed.
void update(RegionAttachment &attachment);
void update(MeshAttachment &attachment);
/// The list of texture regions this sequence will display.
Array<TextureRegion *> &getRegions() {
return _regions;
}
/// Returns the getRegions() index for SlotPose::getSequenceIndex().
int resolveIndex(SlotPose &pose);
/// Returns the texture region from getRegions() for the specified index.
TextureRegion *getRegion(int index);
/// Returns the UVs for the specified index. getRegions() must be populated and update() called before calling this method.
Array<float> &getUVs(int index);
/// Returns vertex offsets from the center of a RegionAttachment. Invalid to call for a MeshAttachment.
Array<float> &getOffsets(int index);
/// The starting number for the numeric getPath(String, int) suffix.
int getStart() {
return _start;
}
void setStart(int start) {
_start = start;
}
/// The minimum number of digits in the numeric getPath(String, int) suffix, for zero padding. 0 for no zero padding.
int getDigits() {
return _digits;
}
void setDigits(int digits) {
_digits = digits;
}
/// The index of the region to show for the setup pose.
int getSetupIndex() {
return _setupIndex;
}
void setSetupIndex(int setupIndex) {
_setupIndex = setupIndex;
}
/// Returns true if getPath(String, int) has a numeric suffix.
bool hasPathSuffix() {
return _pathSuffix;
}
/// Returns the specified base path with an optional numeric suffix for the specified index.
String &getPath(const String &basePath, int index);
/// Returns a unique ID for this sequence.
int getId() {
return _id;
}
private:
static int _nextID;
int _id;
Array<TextureRegion *> _regions;
bool _pathSuffix;
Array<Array<float>> _uvs;
Array<Array<float>> _offsets;
int _start;
int _digits;
int _setupIndex;
String _tmpPath;
static int nextID();
};
/// Controls how getRegions() are displayed over time.
enum SequenceMode {
SequenceMode_hold = 0,
SequenceMode_once = 1,
SequenceMode_loop = 2,
SequenceMode_pingpong = 3,
SequenceMode_onceReverse = 4,
SequenceMode_loopReverse = 5,
SequenceMode_pingpongReverse = 6
};
inline SequenceMode SequenceMode_valueOf(const String &value) {
if (value == "hold") return SequenceMode_hold;
if (value == "once") return SequenceMode_once;
if (value == "loop") return SequenceMode_loop;
if (value == "pingpong") return SequenceMode_pingpong;
if (value == "onceReverse") return SequenceMode_onceReverse;
if (value == "loopReverse") return SequenceMode_loopReverse;
if (value == "pingpongReverse") return SequenceMode_pingpongReverse;
return SequenceMode_hold;
}
}
#endif
@@ -0,0 +1,87 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_SequenceTimeline_h
#define Spine_SequenceTimeline_h
#include <spine/Timeline.h>
#include <spine/SlotTimeline.h>
#include <spine/Sequence.h>
namespace spine {
class Attachment;
class HasTextureRegion;
class Slot;
/// Changes the sequence index for an attachment's Sequence.
class SP_API SequenceTimeline : public Timeline, public SlotTimeline {
friend class SkeletonBinary;
friend class SkeletonJson;
RTTI_DECL
public:
explicit SequenceTimeline(size_t frameCount, int slotIndex, Attachment &attachment);
virtual ~SequenceTimeline();
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixFrom from, bool add, bool out,
bool appliedPose) override;
/// Sets the time, mode, index, and frame time for the specified frame.
/// @param frame Between 0 and frameCount, inclusive.
/// @param delay Seconds between frames.
void setFrame(int frame, float time, SequenceMode mode, int index, float delay);
/// The attachment for which the sequence index will be set.
///
/// See Attachment::getTimelineAttachment().
Attachment &getAttachment() {
return *(Attachment *) _attachment;
}
virtual int getSlotIndex() override;
virtual void setSlotIndex(int inValue) override;
protected:
int _slotIndex;
Attachment *_attachment;
void setupPose(Slot &slot, bool appliedPose);
void applyToSlot(Slot &slot, bool appliedPose, Sequence &sequence, float time, float before, int modeAndIndex, float delay);
static const int ENTRIES = 3;
static const int MODE = 1;
static const int DELAY = 2;
};
}
#endif /* Spine_SequenceTimeline_h */
@@ -0,0 +1,82 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_ShearTimeline_h
#define Spine_ShearTimeline_h
#include <spine/BoneTimeline.h>
namespace spine {
/// Changes a bone's local shearX and shearY.
class SP_API ShearTimeline : public BoneTimeline2 {
friend class SkeletonBinary;
friend class SkeletonJson;
RTTI_DECL
public:
explicit ShearTimeline(size_t frameCount, size_t bezierCount, int boneIndex);
protected:
virtual void _apply(BonePose &pose, BonePose &setup, float time, float alpha, MixFrom from, bool add, bool out) override;
};
/// Changes a bone's local shearX.
class SP_API ShearXTimeline : public BoneTimeline1 {
friend class SkeletonBinary;
friend class SkeletonJson;
RTTI_DECL
public:
explicit ShearXTimeline(size_t frameCount, size_t bezierCount, int boneIndex);
protected:
virtual void _apply(BonePose &pose, BonePose &setup, float time, float alpha, MixFrom from, bool add, bool out) override;
};
/// Changes a bone's local shearY.
class SP_API ShearYTimeline : public BoneTimeline1 {
friend class SkeletonBinary;
friend class SkeletonJson;
RTTI_DECL
public:
explicit ShearYTimeline(size_t frameCount, size_t bezierCount, int boneIndex);
protected:
virtual void _apply(BonePose &pose, BonePose &setup, float time, float alpha, MixFrom from, bool add, bool out) override;
};
}
#endif /* Spine_ShearTimeline_h */
@@ -0,0 +1,368 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_Skeleton_h
#define Spine_Skeleton_h
#include <spine/Array.h>
#include <spine/MathUtil.h>
#include <spine/SpineObject.h>
#include <spine/SpineString.h>
#include <spine/Color.h>
#include <spine/Physics.h>
#include <spine/Update.h>
#include <spine/Posed.h>
#include <spine/Constraint.h>
#include <spine/DrawOrder.h>
namespace spine {
class SkeletonData;
class Bone;
class BonePose;
class Updatable;
class Slot;
class DrawOrder;
class IkConstraint;
class PathConstraint;
class PhysicsConstraint;
class TransformConstraint;
class Skin;
class Attachment;
class SkeletonClipping;
/// Stores bones and slots to be posed by animations and application code. Multiple skeleton instances can share the same
/// SkeletonData, including animations, attachments, and skins.
///
/// After posing, call updateWorldTransform(Physics) to apply constraints and compute world transforms for rendering.
class SP_API Skeleton : public SpineObject {
friend class AnimationState;
friend class SkeletonBounds;
friend class SkeletonClipping;
friend class SlotCurveTimeline;
friend class AttachmentTimeline;
friend class RGBATimeline;
friend class RGBTimeline;
friend class AlphaTimeline;
friend class RGBA2Timeline;
friend class RGB2Timeline;
friend class DeformTimeline;
friend class DrawOrderFolderTimeline;
friend class DrawOrderTimeline;
friend class EventTimeline;
friend class IkConstraintTimeline;
friend class InheritTimeline;
friend class PathConstraint;
friend class PathConstraintMixTimeline;
friend class PathConstraintPositionTimeline;
friend class PathConstraintSpacingTimeline;
friend class SliderTimeline;
friend class SliderMixTimeline;
friend class ScaleTimeline;
friend class ScaleXTimeline;
friend class ScaleYTimeline;
friend class ShearTimeline;
friend class ShearXTimeline;
friend class ShearYTimeline;
friend class TransformConstraintTimeline;
friend class BoneTimeline1;
friend class BoneTimeline2;
friend class RotateTimeline;
friend class TranslateTimeline;
friend class TranslateXTimeline;
friend class TranslateYTimeline;
friend class TwoColorTimeline;
friend class PhysicsConstraint;
friend class BonePose;
friend class IkConstraint;
friend class PathConstraint;
friend class PhysicsConstraint;
friend class TransformConstraint;
friend class Slider;
public:
explicit Skeleton(SkeletonData &skeletonData);
~Skeleton();
/// Caches information about bones and constraints. Must be called if the active skin is modified or if bones, constraints, or
/// weighted path attachments are added or removed.
void updateCache();
void printUpdateCache();
void constrained(Posed &object);
void sortBone(Bone *bone);
static void sortReset(Array<Bone *> &bones);
/// Updates the world transform for each bone and applies all constraints.
///
/// See [World transforms](http://esotericsoftware.com/spine-runtime-skeletons#World-transforms) in the Spine
/// Runtimes Guide.
void updateWorldTransform(Physics physics);
/// Sets the bones, constraints, and slots to their setup pose values.
void setupPose();
/// Sets the bones and constraints to their setup pose values.
void setupPoseBones();
void setupPoseSlots();
SkeletonData &getData();
Array<Bone *> &getBones();
Array<Update *> &getUpdateCache();
Bone *getRootBone();
/// @return May be NULL.
Bone *findBone(const String &boneName);
/// The skeleton's slots in setup pose order. To change the order use DrawOrder::getPose(). For rendering use
/// DrawOrder::getAppliedPose().
Array<Slot *> &getSlots();
/// @return May be NULL.
Slot *findSlot(const String &slotName);
/// The skeleton's draw order. Use DrawOrder::getAppliedPose() for rendering and DrawOrder::getPose() for changing the
/// draw order.
DrawOrder &getDrawOrder();
Skin *getSkin();
/// Sets a skin by name (see setSkin).
void setSkin(const String &skinName);
/// Sets the skin used to look up attachments before looking in SkeletonData::getDefaultSkin(). If the skin is changed,
/// updateCache() is called.
///
/// Attachments from the new skin are attached if the corresponding attachment from the old skin was attached. If there was
/// no old skin, each slot's setup pose placeholder attachment is attached from the new skin.
///
/// After changing the skin, the visible attachments can be reset to those attached in the setup pose by calling
/// setupPoseSlots(). Also, AnimationState::apply(Skeleton&) is often called before the next time the skeleton is rendered
/// so attachment keys in the current animation(s) can hide or show attachments from the new skin.
/// @param newSkin May be NULL.
void setSkin(Skin *newSkin);
/// Finds an attachment by looking in getSkin() and SkeletonData::getDefaultSkin() using the slot name and skin
/// placeholder name. First the skin is checked and if the attachment was not found, the default skin is checked.
/// @return May be NULL.
Attachment *getAttachment(const String &slotName, const String &placeholder);
/// Finds an attachment by looking in getSkin() and SkeletonData::getDefaultSkin() using the slot index and skin
/// placeholder name. First the skin is checked and if the attachment was not found, the default skin is checked.
/// @return May be NULL.
Attachment *getAttachment(int slotIndex, const String &placeholder);
/// A convenience method to set an attachment by finding the slot with findSlot(String), finding the attachment with
/// getAttachment(int, String), then setting the slot's SlotPose::getAttachment().
/// @param placeholder May be empty.
void setAttachment(const String &slotName, const String &placeholder);
Array<Constraint *> &getConstraints();
/// The skeleton's physics constraints.
Array<PhysicsConstraint *> &getPhysicsConstraints();
/// Finds a constraint of the specified type by comparing each constraint's name. It is more efficient to cache the results of
/// this method than to call it multiple times.
template<class T>
T *findConstraint(const String &constraintName) {
if (constraintName.isEmpty()) return NULL;
for (size_t i = 0; i < _constraints.size(); i++) {
Constraint *constraint = _constraints[i];
if (constraint->getRTTI().isExactly(T::rtti)) {
if (constraint->getData().getName() == constraintName) {
return (T *) constraint;
}
}
}
return NULL;
}
/// Returns the axis aligned bounding box (AABB) of the region and mesh attachments for the applied pose.
/// @param outX The horizontal distance between the skeleton origin and the left side of the AABB.
/// @param outY The vertical distance between the skeleton origin and the bottom side of the AABB.
/// @param outWidth The width of the AABB
/// @param outHeight The height of the AABB.
void getBounds(float &outX, float &outY, float &outWidth, float &outHeight);
/// Returns the axis aligned bounding box (AABB) of the region and mesh attachments for the applied pose.
/// @param outX The horizontal distance between the skeleton origin and the left side of the AABB.
/// @param outY The vertical distance between the skeleton origin and the bottom side of the AABB.
/// @param outWidth The width of the AABB
/// @param outHeight The height of the AABB.
/// @param outVertexBuffer Reference to hold an array of floats. This method will assign it with new floats as needed.
/// @param clipping Pointer to a SkeletonClipping instance or NULL. If a clipper is given, clipping attachments will be taken into account.
void getBounds(float &outX, float &outY, float &outWidth, float &outHeight, Array<float> &outVertexBuffer, SkeletonClipping *clipping);
Color &getColor();
void setColor(Color &color);
void setColor(float r, float g, float b, float a);
float getScaleX();
void setScaleX(float inValue);
float getScaleY();
void setScaleY(float inValue);
void setScale(float scaleX, float scaleY);
float getX();
void setX(float inValue);
float getY();
void setY(float inValue);
void setPosition(float x, float y);
void getPosition(float &x, float &y);
/// The x component of a vector that defines the direction PhysicsConstraintPose::getWind() is applied.
float getWindX();
void setWindX(float windX);
/// The y component of a vector that defines the direction PhysicsConstraintPose::getWind() is applied.
float getWindY();
void setWindY(float windY);
/// The x component of a vector that defines the direction PhysicsConstraintPose::getGravity() is applied.
float getGravityX();
void setGravityX(float gravityX);
/// The y component of a vector that defines the direction PhysicsConstraintPose::getGravity() is applied.
float getGravityY();
void setGravityY(float gravityY);
/// Rotates the physics constraint so next {@link #update(Physics)} forces are applied as if the bone rotated around the
/// specified point in world space.
void physicsTranslate(float x, float y);
/// Calls {@link PhysicsConstraint#rotate(float, float, float)} for each physics constraint. */
void physicsRotate(float x, float y, float degrees);
/// Returns the skeleton's time, used for time-based manipulations, such as PhysicsConstraint.
///
/// See update().
float getTime();
void setTime(float time);
void update(float delta);
protected:
SkeletonData &_data;
Array<Bone *> _bones;
Array<Slot *> _slots;
DrawOrder _drawOrder;
Array<Constraint *> _constraints;
Array<PhysicsConstraint *> _physics;
Array<Update *> _updateCache;
Array<Posed *> _resetCache;
Skin *_skin;
Color _color;
float _x, _y;
float _scaleX, _scaleY;
float _windX, _windY, _gravityX, _gravityY;
float _time;
int _update;
};
}// namespace spine
#endif /* Spine_Skeleton_h */
@@ -0,0 +1,267 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_SkeletonBinary_h
#define Spine_SkeletonBinary_h
#include <spine/Inherit.h>
#include <spine/Array.h>
#include <spine/SpineObject.h>
#include <spine/SpineString.h>
#include <spine/Color.h>
#include <spine/BoneTimeline.h>
#include <spine/SkeletonData.h>
namespace spine {
class SkeletonData;
class Atlas;
class AttachmentLoader;
class LinkedMesh;
class Skin;
class Attachment;
class VertexAttachment;
class Animation;
class Timeline;
class CurveTimeline;
class CurveTimeline1;
class BoneTimeline2;
class Sequence;
class SP_API SkeletonBinary : public SpineObject {
public:
static const int BONE_ROTATE = 0;
static const int BONE_TRANSLATE = 1;
static const int BONE_TRANSLATEX = 2;
static const int BONE_TRANSLATEY = 3;
static const int BONE_SCALE = 4;
static const int BONE_SCALEX = 5;
static const int BONE_SCALEY = 6;
static const int BONE_SHEAR = 7;
static const int BONE_SHEARX = 8;
static const int BONE_SHEARY = 9;
static const int BONE_INHERIT = 10;
static const int SLOT_ATTACHMENT = 0;
static const int SLOT_RGBA = 1;
static const int SLOT_RGB = 2;
static const int SLOT_RGBA2 = 3;
static const int SLOT_RGB2 = 4;
static const int SLOT_ALPHA = 5;
static const int CONSTRAINT_IK = 0;
static const int CONSTRAINT_PATH = 1;
static const int CONSTRAINT_TRANSFORM = 2;
static const int CONSTRAINT_PHYSICS = 3;
static const int CONSTRAINT_SLIDER = 4;
static const int ATTACHMENT_DEFORM = 0;
static const int ATTACHMENT_SEQUENCE = 1;
static const int PATH_POSITION = 0;
static const int PATH_SPACING = 1;
static const int PATH_MIX = 2;
static const int PHYSICS_INERTIA = 0;
static const int PHYSICS_STRENGTH = 1;
static const int PHYSICS_DAMPING = 2;
static const int PHYSICS_MASS = 4;
static const int PHYSICS_WIND = 5;
static const int PHYSICS_GRAVITY = 6;
static const int PHYSICS_MIX = 7;
static const int PHYSICS_RESET = 8;
static const int SLIDER_TIME = 0;
static const int SLIDER_MIX = 1;
static const int CURVE_LINEAR = 0;
static const int CURVE_STEPPED = 1;
static const int CURVE_BEZIER = 2;
explicit SkeletonBinary(Atlas &atlas);
explicit SkeletonBinary(AttachmentLoader &attachmentLoader, bool ownsLoader = false);
~SkeletonBinary();
SkeletonData *readSkeletonData(const unsigned char *binary, int length);
SkeletonData *readSkeletonDataFile(const String &path);
void setScale(float scale) {
_scale = scale;
}
const String &getError() const {
return _error;
}
private:
struct DataInput : public SpineObject {
const unsigned char *cursor;
const unsigned char *end;
SkeletonData *skeletonData;
DataInput(SkeletonData *skeletonData, const unsigned char *data, size_t length)
: cursor(data), end(data + length), skeletonData(skeletonData) {
}
inline int read() {
return readUnsignedByte();
}
inline signed char readByte() {
return (signed char) *cursor++;
}
inline unsigned char readUnsignedByte() {
return (unsigned char) *cursor++;
}
inline bool readBoolean() {
return readByte() != 0;
}
inline int readInt() {
int result = readUnsignedByte();
result <<= 8;
result |= readUnsignedByte();
result <<= 8;
result |= readUnsignedByte();
result <<= 8;
result |= readUnsignedByte();
return result;
}
inline long long readLong() {
unsigned long long result = (unsigned int) readInt();
result <<= 32;
result |= (unsigned int) readInt();
return (long long) result;
}
inline float readFloat() {
union {
int intValue;
float floatValue;
} intToFloat;
intToFloat.intValue = readInt();
return intToFloat.floatValue;
}
inline void readColor(Color &color) {
color.r = readUnsignedByte() / 255.0f;
color.g = readUnsignedByte() / 255.0f;
color.b = readUnsignedByte() / 255.0f;
color.a = readUnsignedByte() / 255.0f;
}
inline int readInt(bool optimizePositive) {
unsigned char b = readUnsignedByte();
int value = b & 0x7F;
if (b & 0x80) {
b = readUnsignedByte();
value |= (b & 0x7F) << 7;
if (b & 0x80) {
b = readUnsignedByte();
value |= (b & 0x7F) << 14;
if (b & 0x80) {
b = readUnsignedByte();
value |= (b & 0x7F) << 21;
if (b & 0x80) value |= (readUnsignedByte() & 0x7F) << 28;
}
}
}
if (!optimizePositive) value = (((unsigned int) value >> 1) ^ -(value & 1));
return value;
}
char *readString() {
int length = readInt(true);
char *string;
if (length == 0) return NULL;
string = SpineExtension::alloc<char>(length, __FILE__, __LINE__);
memcpy(string, cursor, length - 1);
cursor += length - 1;
string[length - 1] = '\0';
return string;
}
char *readStringRef() {
int index = readInt(true);
return index == 0 ? NULL : skeletonData->_strings[index - 1];
}
};
AttachmentLoader *_attachmentLoader;
Array<LinkedMesh *> _linkedMeshes;
String _error;
float _scale;
const bool _ownsLoader;
void setError(const char *value1, const char *value2);
Skin *readSkin(DataInput &input, SkeletonData &skeletonData, bool defaultSkin, bool nonessential);
Attachment *readAttachment(DataInput &input, Skin &skin, int slotIndex, const String &placeholder, SkeletonData &skeletonData,
bool nonessential);
Sequence *readSequence(DataInput &input, bool hasPathSuffix);
int readVertices(DataInput &input, Array<float> &vertices, Array<int> &bones, bool weighted);
void readFloatArray(DataInput &input, int n, float scale, Array<float> &array);
void readUnsignedShortArray(DataInput &input, Array<unsigned short> &array, int n);
Animation *readAnimation(DataInput &input, const String &name, SkeletonData &skeletonData, bool nonessential);
void readTimeline(DataInput &input, Array<Timeline *> &timelines, CurveTimeline1 &timeline, float scale);
void readTimeline(DataInput &input, Array<Timeline *> &timelines, BoneTimeline2 &timeline, float scale);
void readDrawOrder(DataInput &input, size_t slotCount, Array<int> &drawOrder);
void setBezier(DataInput &input, CurveTimeline &timeline, int bezier, int frame, int value, float time1, float time2, float value1,
float value2, float scale);
};
}// namespace spine
#endif /* Spine_SkeletonBinary_h */
@@ -0,0 +1,135 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_SkeletonBounds_h
#define Spine_SkeletonBounds_h
#include <spine/Array.h>
#include <spine/Pool.h>
#include <spine/SpineObject.h>
namespace spine {
class Skeleton;
class BoundingBoxAttachment;
class Polygon;
/// Collects each BoundingBoxAttachment that is visible and computes the world vertices for its polygon.
/// The polygon vertices are provided along with convenience methods for doing hit detection.
class SP_API SkeletonBounds : public SpineObject {
public:
SkeletonBounds();
~SkeletonBounds();
/// Clears any previous polygons, finds all visible bounding box attachments,
/// and computes the world vertices for each bounding box's polygon.
/// @param skeleton The skeleton.
/// @param updateAabb
/// If true, the axis aligned bounding box containing all the polygons is computed.
/// If false, the SkeletonBounds AABB methods will always return true.
///
void update(Skeleton &skeleton, bool updateAabb);
/// Returns true if the axis aligned bounding box contains the point.
bool aabbContainsPoint(float x, float y);
/// Returns true if the axis aligned bounding box intersects the line segment.
bool aabbIntersectsSegment(float x1, float y1, float x2, float y2);
/// Returns true if the axis aligned bounding box intersects the axis aligned bounding box of the specified bounds.
bool aabbIntersectsSkeleton(SkeletonBounds &bounds);
/// Returns true if the polygon contains the point.
bool containsPoint(Polygon &polygon, float x, float y);
/// Returns the first bounding box attachment that contains the point, or null. When doing many checks, it is usually more
/// efficient to only call this method if aabbContainsPoint(float, float) returns true.
BoundingBoxAttachment *containsPoint(float x, float y);
/// Returns the first bounding box attachment that contains any part of the line segment, or null. When doing many checks, it
/// is usually more efficient to only call this method if aabbIntersectsSegment(float, float, float, float) returns true.
BoundingBoxAttachment *intersectsSegment(float x1, float y1, float x2, float y2);
/// Returns true if the polygon contains any part of the line segment.
bool intersectsSegment(Polygon &polygon, float x1, float y1, float x2, float y2);
/// Returns the polygon for the given bounding box attachment or null if no
/// polygon can be found for the attachment. Requires a call to update() first.
Polygon *getPolygon(BoundingBoxAttachment *attachment);
/// Returns the bounding box for the given polygon or null. Requires a call to update() first.
BoundingBoxAttachment *getBoundingBox(Polygon *polygon);
/// Returns all polygons or an empty array. Requires a call to update() first.
Array<Polygon *> &getPolygons();
/// Returns all bounding boxes. Requires a call to update() first.
Array<BoundingBoxAttachment *> &getBoundingBoxes();
/// The left edge of the axis aligned bounding box.
float getMinX();
/// The bottom edge of the axis aligned bounding box.
float getMinY();
/// The right edge of the axis aligned bounding box.
float getMaxX();
/// The top edge of the axis aligned bounding box.
float getMaxY();
/// The width of the axis aligned bounding box.
float getWidth();
/// The height of the axis aligned bounding box.
float getHeight();
private:
Pool<Polygon> _polygonPool;
Array<BoundingBoxAttachment *> _boundingBoxes;
Array<Polygon *> _polygons;
float _minX, _minY, _maxX, _maxY;
void aabbCompute();
};
class Polygon : public SpineObject {
public:
Array<float> _vertices;
int _count;
Polygon() : _count(0) {
_vertices.ensureCapacity(16);
}
};
}
#endif /* Spine_SkeletonBounds_h */
@@ -0,0 +1,90 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_SkeletonClipping_h
#define Spine_SkeletonClipping_h
#include <spine/Array.h>
#include <spine/Triangulator.h>
namespace spine {
class Slot;
class Skeleton;
class ClippingAttachment;
class SP_API SkeletonClipping : public SpineObject {
public:
SkeletonClipping();
size_t clipStart(Skeleton &skeleton, Slot &slot, ClippingAttachment *clip);
void clipEnd(Slot &slot);
void clipEnd();
bool clipTriangles(float *vertices, unsigned short *triangles, size_t trianglesLength);
bool clipTriangles(float *vertices, unsigned short *triangles, size_t trianglesLength, float *uvs, size_t stride);
bool clipTriangles(Array<float> &vertices, Array<unsigned short> &triangles, Array<float> &uvs, size_t stride);
bool isClipping();
Array<float> &getClippedVertices();
Array<unsigned short> &getClippedTriangles();
Array<float> &getClippedUVs();
private:
Triangulator _triangulator;
Array<float> _clippingPolygon;
Array<Array<float> *> _clippingPolygons;
Array<float> _clipOutput;
Array<float> _clippedVertices;
Array<unsigned short> _clippedTriangles;
Array<float> _clippedUVs;
Array<float> _inverseVertices;
Array<float> _scratch;
ClippingAttachment *_clipAttachment;
bool _inverse;
/** Clips the input triangle against the convex, clockwise clipping area. If the triangle lies entirely within the clipping
* area, false is returned. The clipping area must duplicate the first vertex at the end of the vertices list. */
bool clip(float x1, float y1, float x2, float y2, float x3, float y3, Array<float> *polygon);
void clipInverse(float x1, float y1, float x2, float y2, float x3, float y3, Array<float> *polygon);
static bool makeClockwise(Array<float> &polygon);
void makeConvex(Array<float> &polygon);
};
}
#endif /* Spine_SkeletonClipping_h */
@@ -0,0 +1,213 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_SkeletonData_h
#define Spine_SkeletonData_h
#include <spine/Array.h>
#include <spine/SpineString.h>
#include <spine/ConstraintData.h>
namespace spine {
class BoneData;
class SlotData;
class Skin;
class EventData;
class Animation;
class IkConstraintData;
class TransformConstraintData;
class PathConstraintData;
class PhysicsConstraintData;
class ConstraintData;
/// Stores the setup pose and all of the stateless data for a skeleton.
///
/// See <a href="https://esotericsoftware.com/spine-runtime-architecture#Data-objects">Data objects</a> in the Spine Runtimes
/// Guide.
class SP_API SkeletonData : public SpineObject {
friend class SkeletonBinary;
friend class SkeletonJson;
friend class Skeleton;
public:
SkeletonData();
~SkeletonData();
/// Finds a bone by comparing each bone's name.
/// It is more efficient to cache the results of this method than to call it multiple times.
/// @return May be NULL.
BoneData *findBone(const String &boneName);
/// @return May be NULL.
SlotData *findSlot(const String &slotName);
/// @return May be NULL.
Skin *findSkin(const String &skinName);
/// @return May be NULL.
EventData *findEvent(const String &eventDataName);
/// @return May be NULL.
Animation *findAnimation(const String &animationName);
/// Collects animations used by slider constraints.
Array<Animation *> &findSliderAnimations(Array<Animation *> &animations);
/// The skeleton's name, which by default is the name of the skeleton data file when possible, or null when a name hasn't been
/// set.
const String &getName();
void setName(const String &inValue);
/// The skeleton's bones, sorted parent first. The root bone is always the first bone.
Array<BoneData *> &getBones();
/// The skeleton's slots in the setup pose draw order.
Array<SlotData *> &getSlots();
/// All skins, including the default skin.
Array<Skin *> &getSkins();
/// The skeleton's default skin.
/// By default this skin contains all attachments that were not in a skin in Spine.
/// @return May be NULL.
Skin *getDefaultSkin();
void setDefaultSkin(Skin *inValue);
/// The skeleton's events.
Array<EventData *> &getEvents();
/// The skeleton's animations.
Array<Animation *> &getAnimations();
/// The skeleton's constraints.
Array<ConstraintData *> &getConstraints();
/// Finds a constraint of the specified type by comparing each constraint's name. It is more efficient to cache the results of
/// this method than to call it multiple times.
/// @return May be NULL.
template<class T>
T *findConstraint(const String &constraintName) {
getConstraints();// Ensure constraints array is populated
for (size_t i = 0, n = _constraints.size(); i < n; i++) {
ConstraintData *constraint = _constraints[i];
if (constraint->getName() == constraintName && constraint->getRTTI().instanceOf(T::rtti)) {
return static_cast<T *>(constraint);
}
}
return NULL;
}
/// The X coordinate of the skeleton's axis aligned bounding box in the setup pose.
float getX();
void setX(float inValue);
/// The Y coordinate of the skeleton's axis aligned bounding box in the setup pose.
float getY();
void setY(float inValue);
/// The width of the skeleton's axis aligned bounding box in the setup pose.
float getWidth();
void setWidth(float inValue);
/// The height of the skeleton's axis aligned bounding box in the setup pose.
float getHeight();
void setHeight(float inValue);
/// Baseline scale factor for applying physics and other effects based on distance to non-scalable properties, such as angle or
/// scale. Default is 100.
float getReferenceScale();
void setReferenceScale(float inValue);
/// The Spine version used to export this data, or NULL.
const String &getVersion();
void setVersion(const String &inValue);
/// The skeleton data hash. This value will change if any of the skeleton data has changed.
const String &getHash();
void setHash(const String &inValue);
/// The path to the images folder as defined in Spine, or null if nonessential data was not exported.
const String &getImagesPath();
void setImagesPath(const String &inValue);
/// The path to the audio folder as defined in Spine, or null if nonessential data was not exported.
const String &getAudioPath();
void setAudioPath(const String &inValue);
/// The dopesheet FPS in Spine. Available only when nonessential data was exported.
float getFps();
void setFps(float inValue);
private:
String _name;
Array<BoneData *> _bones;// Ordered parents first
Array<SlotData *> _slots;// Setup pose draw order.
Array<Skin *> _skins;
Skin *_defaultSkin;
Array<EventData *> _events;
Array<Animation *> _animations;
Array<ConstraintData *> _constraints;
float _x, _y, _width, _height;
float _referenceScale;
String _version;
String _hash;
Array<char *> _strings;
// Nonessential.
float _fps;
String _imagesPath;
String _audioPath;
};
}
#endif /* Spine_SkeletonData_h */
@@ -0,0 +1,122 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_SkeletonJson_h
#define Spine_SkeletonJson_h
#include <spine/Array.h>
#include <spine/SpineObject.h>
#include <spine/SpineString.h>
namespace spine {
class Timeline;
class CurveTimeline;
class CurveTimeline1;
class BoneTimeline2;
class VertexAttachment;
class Animation;
class Json;
class SkeletonData;
class Atlas;
class AttachmentLoader;
class LinkedMesh;
class String;
class Sequence;
class Skin;
class Attachment;
class SP_API SkeletonJson : public SpineObject {
public:
explicit SkeletonJson(Atlas &atlas);
explicit SkeletonJson(AttachmentLoader &attachmentLoader, bool ownsLoader = false);
~SkeletonJson();
SkeletonData *readSkeletonDataFile(const String &path);
SkeletonData *readSkeletonData(const char *json);
void setScale(float scale) {
_scale = scale;
}
const String &getError() const {
return _error;
}
private:
AttachmentLoader *_attachmentLoader;
Array<LinkedMesh *> _linkedMeshes;
float _scale;
const bool _ownsLoader;
String _error;
static Sequence *readSequence(Json *sequence);
static void setBezier(CurveTimeline *timeline, int frame, int value, int bezier, float time1, float value1, float cx1, float cy1, float cx2,
float cy2, float time2, float value2);
static int readCurve(Json *curve, CurveTimeline *timeline, int bezier, int frame, int value, float time1, float time2, float value1,
float value2, float scale);
static void readTimeline(Array<Timeline *> &timelines, Json *keyMap, CurveTimeline1 *timeline, float defaultValue, float scale);
static void readTimeline(Array<Timeline *> &timelines, Json *keyMap, BoneTimeline2 *timeline, const char *name1, const char *name2,
float defaultValue, float scale);
Animation *readAnimation(Json *root, SkeletonData *skeletonData);
Attachment *readAttachment(Json *map, Skin *skin, int slotIndex, const char *placeholder, SkeletonData *skeletonData);
void readVertices(Json *attachmentMap, VertexAttachment *attachment, size_t verticesLength);
bool readDrawOrder(SkeletonData *skeletonData, Json *keyMap, int slotCount, const Array<int> *folderSlots, Array<int> &drawOrder);
void setError(Json *root, const String &value1, const String &value2);
int findSlotIndex(SkeletonData *skeletonData, const String &slotName, Array<Timeline *> timelines);
};
}
#endif /* Spine_SkeletonJson_h */
@@ -0,0 +1,70 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_SkeletonRenderer_h
#define Spine_SkeletonRenderer_h
#include <spine/BlockAllocator.h>
#include <spine/BlendMode.h>
#include <spine/SkeletonClipping.h>
namespace spine {
class Skeleton;
struct SP_API RenderCommand {
float *positions;
float *uvs;
uint32_t *colors;
uint32_t *darkColors;
int32_t numVertices;
uint16_t *indices;
int32_t numIndices;
BlendMode blendMode;
void *texture;
RenderCommand *next;
};
class SP_API SkeletonRenderer : public SpineObject {
public:
explicit SkeletonRenderer();
~SkeletonRenderer();
RenderCommand *render(Skeleton &skeleton);
private:
BlockAllocator _allocator;
Array<float> _worldVertices;
Array<unsigned short> _quadIndices;
SkeletonClipping _clipping;
Array<RenderCommand *> _renderCommands;
};
}
#endif
@@ -0,0 +1,170 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_Skin_h
#define Spine_Skin_h
#include <spine/Array.h>
#include <spine/SpineString.h>
#include <spine/Color.h>
namespace spine {
class Attachment;
class Skeleton;
class BoneData;
class ConstraintData;
/// Stores attachments by slot index and placeholder name. Multiple Skeleton instances can use the same skins.
/// See SkeletonData::getDefaultSkin, Skeleton::getSkin, and
/// http://esotericsoftware.com/spine-runtime-skins in the Spine Runtimes Guide.
class SP_API Skin : public SpineObject {
friend class Skeleton;
public:
class SP_API AttachmentMap : public SpineObject {
friend class Skin;
public:
struct SP_API Entry {
size_t _slotIndex;
String _placeholder;
Attachment *_attachment;
Entry(size_t slotIndex, const String &placeholder, Attachment *attachment)
: _slotIndex(slotIndex), _placeholder(placeholder), _attachment(attachment) {
}
};
class SP_API Entries {
friend class AttachmentMap;
public:
bool hasNext() {
while (true) {
if (_slotIndex >= _buckets.size()) return false;
if (_bucketIndex >= _buckets[_slotIndex].size()) {
_bucketIndex = 0;
++_slotIndex;
continue;
};
return true;
}
}
Entry &next() {
Entry &result = _buckets[_slotIndex][_bucketIndex];
++_bucketIndex;
return result;
}
protected:
Entries(Array<Array<Entry>> &buckets) : _buckets(buckets), _slotIndex(0), _bucketIndex(0) {
}
private:
Array<Array<Entry>> &_buckets;
size_t _slotIndex;
size_t _bucketIndex;
};
void put(size_t slotIndex, const String &placeholder, Attachment *attachment);
Attachment *get(size_t slotIndex, const String &placeholder);
void remove(size_t slotIndex, const String &placeholder);
Entries getEntries();
protected:
AttachmentMap();
private:
int findInBucket(Array<Entry> &, const String &placeholder);
Array<Array<Entry>> _buckets;
};
explicit Skin(const String &name);
~Skin();
/// Adds an attachment to the skin for the specified slot index and placeholder name.
/// If the placeholder name already exists for the slot, the previous value is replaced.
void setAttachment(size_t slotIndex, const String &placeholder, Attachment *attachment);
/// Returns the attachment for the specified slot index and placeholder name, or NULL.
Attachment *getAttachment(size_t slotIndex, const String &placeholder);
// Removes the attachment from the skin.
void removeAttachment(size_t slotIndex, const String &placeholder);
/// Finds the placeholder names for a given slot. The results are added to the passed array.
/// @param slotIndex The target slotIndex. To find the slot index, use SkeletonData::findSlot and SlotData::getIndex.
/// @param names Found placeholder names will be added to this array.
void findNamesForSlot(size_t slotIndex, Array<String> &names);
/// Finds the attachments for a given slot. The results are added to the passed array of Attachments.
/// @param slotIndex The target slotIndex. To find the slot index, use SkeletonData::findSlot and SlotData::getIndex.
/// @param attachments Found Attachments will be added to this array.
void findAttachmentsForSlot(size_t slotIndex, Array<Attachment *> &attachments);
const String &getName();
/// Adds all attachments, bones, and constraints from the specified skin to this skin.
void addSkin(Skin &other);
/// Adds all attachments, bones, and constraints from the specified skin to this skin. Attachments are deep copied.
void copySkin(Skin &other);
AttachmentMap::Entries getAttachments();
Array<BoneData *> &getBones();
Array<ConstraintData *> &getConstraints();
Color &getColor() {
return _color;
}
private:
const String _name;
AttachmentMap _attachments;
Array<BoneData *> _bones;
Array<ConstraintData *> _constraints;
Color _color;
/// Attach all attachments from this skin if the corresponding attachment from the old skin is currently attached.
void attachAll(Skeleton &skeleton, Skin &oldSkin);
};
}
#endif /* Spine_Skin_h */
@@ -0,0 +1,81 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_Slider_h
#define Spine_Slider_h
#include <spine/Constraint.h>
#include <spine/SliderData.h>
#include <spine/SliderPose.h>
namespace spine {
class Skeleton;
class Bone;
class Animation;
/// Applies an animation based on either the slider's SliderPose::getTime() or a bone's transform property.
///
/// See https://esotericsoftware.com/spine-sliders Sliders in the Spine User Guide.
// Non-exported base class that inherits from the template
class SliderBase : public ConstraintGeneric<Slider, SliderData, SliderPose> {
public:
SliderBase(SliderData &data) : ConstraintGeneric<Slider, SliderData, SliderPose>(data) {
}
};
class SP_API Slider : public SliderBase {
friend class Skeleton;
friend class SliderTimeline;
friend class SliderMixTimeline;
RTTI_DECL
public:
Slider(SliderData &data, Skeleton &skeleton);
Slider &copy(Skeleton &skeleton);
virtual void update(Skeleton &skeleton, Physics physics) override;
virtual void sort(Skeleton &skeleton) override;
virtual bool isSourceActive() override;
/// When set, the bone's transform property is used to set the slider's SliderPose::getTime().
Bone &getBone();
void setBone(Bone &bone);
private:
Bone *_bone;
static float _offsets[6];
};
}
#endif /* Spine_Slider_h */
@@ -0,0 +1,112 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_SliderData_h
#define Spine_SliderData_h
#include <spine/ConstraintData.h>
#include <spine/PosedData.h>
#include <spine/SliderPose.h>
#include <spine/SpineString.h>
namespace spine {
class Animation;
class BoneData;
class FromProperty;
class Slider;
class Skeleton;
/// Stores the setup pose for a Slider
class SP_API SliderData : public ConstraintDataGeneric<Slider, SliderPose> {
friend class SkeletonBinary;
friend class SkeletonData;
friend class SkeletonJson;
friend class Slider;
friend class SliderMixTimeline;
friend class SliderTimeline;
RTTI_DECL
public:
explicit SliderData(const String &name);
~SliderData();
/// Creates a slider instance.
virtual Constraint &create(Skeleton &skeleton) override;
/// The animation the slider will apply.
Animation &getAnimation();
void setAnimation(Animation &animation);
/// When true, the animation is applied by adding it to the current pose rather than overwriting it.
bool getAdditive();
void setAdditive(bool additive);
/// When true, the animation repeats after its duration, otherwise the last frame is used.
bool getLoop();
void setLoop(bool loop);
/// When set, the bone's transform property is used to set the slider's SliderPose::getTime().
BoneData *getBone();
void setBone(BoneData *bone);
/// When a bone is set, the specified transform property is used to set the slider's SliderPose::getTime().
FromProperty *getProperty();
void setProperty(FromProperty *property);
/// When a bone is set, this is the scale of the property value in relation to the slider time.
float getScale();
void setScale(float scale);
/// When a bone is set, the offset is added to the property.
float getOffset();
void setOffset(float offset);
/// When a bone is set, the maximum slider time for the bone property range, or 0 if nonessential data was not exported.
float getMax();
void setMax(float max);
/// When true and a bone is set, the bone's local transform property is read instead of its world transform.
bool getLocal();
void setLocal(bool local);
private:
Animation *_animation;
bool _additive;
bool _loop;
BoneData *_bone;
FromProperty *_property;
float _offset;
float _scale;
float _max;
bool _local;
};
}
#endif /* Spine_SliderData_h */
@@ -0,0 +1,53 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_SliderMixTimeline_h
#define Spine_SliderMixTimeline_h
#include <spine/ConstraintTimeline1.h>
namespace spine {
/// Changes a slider's mix.
class SP_API SliderMixTimeline : public ConstraintTimeline1 {
friend class SkeletonBinary;
friend class SkeletonJson;
RTTI_DECL
public:
explicit SliderMixTimeline(size_t frameCount, size_t bezierCount, int sliderIndex);
virtual ~SliderMixTimeline();
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixFrom from, bool add, bool out,
bool appliedPose) override;
};
}
#endif /* Spine_SliderMixTimeline_h */
@@ -0,0 +1,66 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_SliderPose_h
#define Spine_SliderPose_h
#include <spine/Pose.h>
#include <spine/RTTI.h>
namespace spine {
class Slider;
/// Stores a pose for a slider.
class SP_API SliderPose : public Pose<SliderPose> {
friend class Slider;
friend class SliderMixTimeline;
friend class SliderTimeline;
friend class SkeletonJson;
friend class SkeletonBinary;
private:
float _time, _mix;
public:
SliderPose();
virtual ~SliderPose();
virtual void set(SliderPose &pose) override;
/// The time in SliderData::getAnimation() to apply the animation.
float getTime();
void setTime(float time);
/// A percentage (unbounded) that controls the mix between the constrained and unconstrained poses.
float getMix();
void setMix(float mix);
};
}
#endif
@@ -0,0 +1,53 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_SliderTimeline_h
#define Spine_SliderTimeline_h
#include <spine/ConstraintTimeline1.h>
namespace spine {
/// Changes a slider's time.
class SP_API SliderTimeline : public ConstraintTimeline1 {
friend class SkeletonBinary;
friend class SkeletonJson;
RTTI_DECL
public:
explicit SliderTimeline(size_t frameCount, size_t bezierCount, int sliderIndex);
virtual ~SliderTimeline();
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixFrom from, bool add, bool out,
bool appliedPose) override;
};
}
#endif /* Spine_SliderTimeline_h */
@@ -0,0 +1,113 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_Slot_h
#define Spine_Slot_h
#include <spine/Posed.h>
#include <spine/SlotData.h>
#include <spine/SlotPose.h>
#include <spine/Array.h>
#include <spine/Color.h>
#include <spine/Update.h>
namespace spine {
class Bone;
class Skeleton;
class Attachment;
/// Organizes attachments for Skeleton drawOrder purposes and provide a place to store state for an attachment.
///
/// State cannot be stored in an attachment itself because attachments are stateless and may be shared across multiple
/// skeletons.
class SP_API Slot : public PosedGeneric<SlotData, SlotPose, SlotPose> {
friend class VertexAttachment;
friend class Skeleton;
friend class SkeletonBounds;
friend class SkeletonClipping;
friend class SlotCurveTimeline;
friend class AttachmentTimeline;
friend class RGBATimeline;
friend class RGBTimeline;
friend class AlphaTimeline;
friend class RGBA2Timeline;
friend class RGB2Timeline;
friend class DeformTimeline;
friend class DrawOrderTimeline;
friend class EventTimeline;
friend class IkConstraintTimeline;
friend class PathConstraintMixTimeline;
friend class PathConstraintPositionTimeline;
friend class PathConstraintSpacingTimeline;
friend class ScaleTimeline;
friend class ShearTimeline;
friend class TransformConstraintTimeline;
friend class TranslateTimeline;
friend class TwoColorTimeline;
friend class AnimationState;
public:
Slot(SlotData &data, Skeleton &skeleton);
/// The bone this slot belongs to.
Bone &getBone();
void setupPose() override;
private:
Skeleton &_skeleton;
Bone &_bone;
int _attachmentState;
};
}
#endif /* Spine_Slot_h */
@@ -0,0 +1,67 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef Spine_SlotCurveTimeline_h
#define Spine_SlotCurveTimeline_h
#include <spine/CurveTimeline.h>
#include <spine/SlotTimeline.h>
namespace spine {
class Slot;
class SlotPose;
/// Base class for slot timelines that use curves.
class SP_API SlotCurveTimeline : public CurveTimeline, public SlotTimeline {
friend class SkeletonBinary;
friend class SkeletonJson;
RTTI_DECL
public:
SlotCurveTimeline(size_t frameCount, size_t frameEntries, size_t bezierCount, int slotIndex);
virtual ~SlotCurveTimeline();
virtual void apply(Skeleton &skeleton, float lastTime, float time, Array<Event *> *events, float alpha, MixFrom from, bool add, bool out,
bool appliedPose) override;
virtual int getSlotIndex() override;
virtual void setSlotIndex(int inValue) override;
protected:
/// Applies the timeline to the slot pose.
virtual void _apply(Slot &slot, SlotPose &pose, float time, float alpha, MixFrom from, bool add) = 0;
int _slotIndex;
};
}
#endif /* Spine_SlotCurveTimeline_h */

Some files were not shown because too many files have changed in this diff Show More