Added spine example

This commit is contained in:
WEREMSOFT 2020-01-09 22:23:30 +01:00
parent e0d4cc3143
commit df3ed39a25
83 changed files with 15884 additions and 1 deletions

4
.gitignore vendored
View File

@ -138,3 +138,7 @@ GPATH
GRTAGS
GTAGS
.vs
# Ignore intelliJ project files
.idea
cmake-build-debug

View File

@ -2,7 +2,7 @@
project(examples)
# Get the sources together
set(example_dirs audio core models others shaders shapes text textures)
set(example_dirs audio core models others others/spine shaders shapes text textures)
set(CMAKE_REQUIRED_DEFINITIONS -D_POSIX_C_SOURCE=199309L)
include(CheckSymbolExists)
check_symbol_exists(CLOCK_MONOTONIC time.h HAVE_CLOCK_MONOTONIC)

View File

@ -0,0 +1,588 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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/dll.h>
#include <spine/Event.h>
#include <spine/Attachment.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct spTimeline spTimeline;
struct spSkeleton;
typedef struct spAnimation {
const char* const name;
float duration;
int timelinesCount;
spTimeline** timelines;
#ifdef __cplusplus
spAnimation() :
name(0),
duration(0),
timelinesCount(0),
timelines(0) {
}
#endif
} spAnimation;
typedef enum {
SP_MIX_BLEND_SETUP,
SP_MIX_BLEND_FIRST,
SP_MIX_BLEND_REPLACE,
SP_MIX_BLEND_ADD
} spMixBlend;
typedef enum {
SP_MIX_DIRECTION_IN,
SP_MIX_DIRECTION_OUT
} spMixDirection;
SP_API spAnimation* spAnimation_create (const char* name, int timelinesCount);
SP_API void spAnimation_dispose (spAnimation* self);
/** Poses the skeleton at the specified time for this animation.
* @param lastTime The last time the animation was applied.
* @param events Any triggered events are added. May be null.*/
SP_API void spAnimation_apply (const spAnimation* self, struct spSkeleton* skeleton, float lastTime, float time, int loop,
spEvent** events, int* eventsCount, float alpha, spMixBlend blend, spMixDirection direction);
#ifdef SPINE_SHORT_NAMES
typedef spAnimation Animation;
#define Animation_create(...) spAnimation_create(__VA_ARGS__)
#define Animation_dispose(...) spAnimation_dispose(__VA_ARGS__)
#define Animation_apply(...) spAnimation_apply(__VA_ARGS__)
#endif
/**/
typedef enum {
SP_TIMELINE_ROTATE,
SP_TIMELINE_TRANSLATE,
SP_TIMELINE_SCALE,
SP_TIMELINE_SHEAR,
SP_TIMELINE_ATTACHMENT,
SP_TIMELINE_COLOR,
SP_TIMELINE_DEFORM,
SP_TIMELINE_EVENT,
SP_TIMELINE_DRAWORDER,
SP_TIMELINE_IKCONSTRAINT,
SP_TIMELINE_TRANSFORMCONSTRAINT,
SP_TIMELINE_PATHCONSTRAINTPOSITION,
SP_TIMELINE_PATHCONSTRAINTSPACING,
SP_TIMELINE_PATHCONSTRAINTMIX,
SP_TIMELINE_TWOCOLOR
} spTimelineType;
struct spTimeline {
const spTimelineType type;
const void* const vtable;
#ifdef __cplusplus
spTimeline() :
type(SP_TIMELINE_SCALE),
vtable(0) {
}
#endif
};
SP_API void spTimeline_dispose (spTimeline* self);
SP_API void spTimeline_apply (const spTimeline* self, struct spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents,
int* eventsCount, float alpha, spMixBlend blend, spMixDirection direction);
SP_API int spTimeline_getPropertyId (const spTimeline* self);
#ifdef SPINE_SHORT_NAMES
typedef spTimeline Timeline;
#define TIMELINE_SCALE SP_TIMELINE_SCALE
#define TIMELINE_ROTATE SP_TIMELINE_ROTATE
#define TIMELINE_TRANSLATE SP_TIMELINE_TRANSLATE
#define TIMELINE_COLOR SP_TIMELINE_COLOR
#define TIMELINE_ATTACHMENT SP_TIMELINE_ATTACHMENT
#define TIMELINE_EVENT SP_TIMELINE_EVENT
#define TIMELINE_DRAWORDER SP_TIMELINE_DRAWORDER
#define Timeline_dispose(...) spTimeline_dispose(__VA_ARGS__)
#define Timeline_apply(...) spTimeline_apply(__VA_ARGS__)
#endif
/**/
typedef struct spCurveTimeline {
spTimeline super;
float* curves; /* type, x, y, ... */
#ifdef __cplusplus
spCurveTimeline() :
super(),
curves(0) {
}
#endif
} spCurveTimeline;
SP_API void spCurveTimeline_setLinear (spCurveTimeline* self, int frameIndex);
SP_API void spCurveTimeline_setStepped (spCurveTimeline* self, int frameIndex);
/* Sets the control handle positions for an interpolation bezier curve used to transition from this keyframe to the next.
* cx1 and cx2 are from 0 to 1, representing the percent of time between the two keyframes. cy1 and cy2 are the percent of
* the difference between the keyframe's values. */
SP_API void spCurveTimeline_setCurve (spCurveTimeline* self, int frameIndex, float cx1, float cy1, float cx2, float cy2);
SP_API float spCurveTimeline_getCurvePercent (const spCurveTimeline* self, int frameIndex, float percent);
#ifdef SPINE_SHORT_NAMES
typedef spCurveTimeline CurveTimeline;
#define CurveTimeline_setLinear(...) spCurveTimeline_setLinear(__VA_ARGS__)
#define CurveTimeline_setStepped(...) spCurveTimeline_setStepped(__VA_ARGS__)
#define CurveTimeline_setCurve(...) spCurveTimeline_setCurve(__VA_ARGS__)
#define CurveTimeline_getCurvePercent(...) spCurveTimeline_getCurvePercent(__VA_ARGS__)
#endif
/**/
typedef struct spBaseTimeline {
spCurveTimeline super;
int const framesCount;
float* const frames; /* time, angle, ... for rotate. time, x, y, ... for translate and scale. */
int boneIndex;
#ifdef __cplusplus
spBaseTimeline() :
super(),
framesCount(0),
frames(0),
boneIndex(0) {
}
#endif
} spBaseTimeline;
/**/
static const int ROTATE_PREV_TIME = -2, ROTATE_PREV_ROTATION = -1;
static const int ROTATE_ROTATION = 1;
static const int ROTATE_ENTRIES = 2;
typedef struct spBaseTimeline spRotateTimeline;
SP_API spRotateTimeline* spRotateTimeline_create (int framesCount);
SP_API void spRotateTimeline_setFrame (spRotateTimeline* self, int frameIndex, float time, float angle);
#ifdef SPINE_SHORT_NAMES
typedef spRotateTimeline RotateTimeline;
#define RotateTimeline_create(...) spRotateTimeline_create(__VA_ARGS__)
#define RotateTimeline_setFrame(...) spRotateTimeline_setFrame(__VA_ARGS__)
#endif
/**/
static const int TRANSLATE_ENTRIES = 3;
typedef struct spBaseTimeline spTranslateTimeline;
SP_API spTranslateTimeline* spTranslateTimeline_create (int framesCount);
SP_API void spTranslateTimeline_setFrame (spTranslateTimeline* self, int frameIndex, float time, float x, float y);
#ifdef SPINE_SHORT_NAMES
typedef spTranslateTimeline TranslateTimeline;
#define TranslateTimeline_create(...) spTranslateTimeline_create(__VA_ARGS__)
#define TranslateTimeline_setFrame(...) spTranslateTimeline_setFrame(__VA_ARGS__)
#endif
/**/
typedef struct spBaseTimeline spScaleTimeline;
SP_API spScaleTimeline* spScaleTimeline_create (int framesCount);
SP_API void spScaleTimeline_setFrame (spScaleTimeline* self, int frameIndex, float time, float x, float y);
#ifdef SPINE_SHORT_NAMES
typedef spScaleTimeline ScaleTimeline;
#define ScaleTimeline_create(...) spScaleTimeline_create(__VA_ARGS__)
#define ScaleTimeline_setFrame(...) spScaleTimeline_setFrame(__VA_ARGS__)
#endif
/**/
typedef struct spBaseTimeline spShearTimeline;
SP_API spShearTimeline* spShearTimeline_create (int framesCount);
SP_API void spShearTimeline_setFrame (spShearTimeline* self, int frameIndex, float time, float x, float y);
#ifdef SPINE_SHORT_NAMES
typedef spShearTimeline ShearTimeline;
#define ShearTimeline_create(...) spShearTimeline_create(__VA_ARGS__)
#define ShearTimeline_setFrame(...) spShearTimeline_setFrame(__VA_ARGS__)
#endif
/**/
static const int COLOR_ENTRIES = 5;
typedef struct spColorTimeline {
spCurveTimeline super;
int const framesCount;
float* const frames; /* time, r, g, b, a, ... */
int slotIndex;
#ifdef __cplusplus
spColorTimeline() :
super(),
framesCount(0),
frames(0),
slotIndex(0) {
}
#endif
} spColorTimeline;
SP_API spColorTimeline* spColorTimeline_create (int framesCount);
SP_API void spColorTimeline_setFrame (spColorTimeline* self, int frameIndex, float time, float r, float g, float b, float a);
#ifdef SPINE_SHORT_NAMES
typedef spColorTimeline ColorTimeline;
#define ColorTimeline_create(...) spColorTimeline_create(__VA_ARGS__)
#define ColorTimeline_setFrame(...) spColorTimeline_setFrame(__VA_ARGS__)
#endif
/**/
static const int TWOCOLOR_ENTRIES = 8;
typedef struct spTwoColorTimeline {
spCurveTimeline super;
int const framesCount;
float* const frames; /* time, r, g, b, a, ... */
int slotIndex;
#ifdef __cplusplus
spTwoColorTimeline() :
super(),
framesCount(0),
frames(0),
slotIndex(0) {
}
#endif
} spTwoColorTimeline;
SP_API spTwoColorTimeline* spTwoColorTimeline_create (int framesCount);
SP_API void spTwoColorTimeline_setFrame (spTwoColorTimeline* self, int frameIndex, float time, float r, float g, float b, float a, float r2, float g2, float b2);
#ifdef SPINE_SHORT_NAMES
typedef spTwoColorTimeline TwoColorTimeline;
#define TwoColorTimeline_create(...) spTwoColorTimeline_create(__VA_ARGS__)
#define TwoColorTimeline_setFrame(...) spTwoColorTimeline_setFrame(__VA_ARGS__)
#endif
/**/
typedef struct spAttachmentTimeline {
spTimeline super;
int const framesCount;
float* const frames; /* time, ... */
int slotIndex;
const char** const attachmentNames;
#ifdef __cplusplus
spAttachmentTimeline() :
super(),
framesCount(0),
frames(0),
slotIndex(0),
attachmentNames(0) {
}
#endif
} spAttachmentTimeline;
SP_API spAttachmentTimeline* spAttachmentTimeline_create (int framesCount);
/* @param attachmentName May be 0. */
SP_API void spAttachmentTimeline_setFrame (spAttachmentTimeline* self, int frameIndex, float time, const char* attachmentName);
#ifdef SPINE_SHORT_NAMES
typedef spAttachmentTimeline AttachmentTimeline;
#define AttachmentTimeline_create(...) spAttachmentTimeline_create(__VA_ARGS__)
#define AttachmentTimeline_setFrame(...) spAttachmentTimeline_setFrame(__VA_ARGS__)
#endif
/**/
typedef struct spEventTimeline {
spTimeline super;
int const framesCount;
float* const frames; /* time, ... */
spEvent** const events;
#ifdef __cplusplus
spEventTimeline() :
super(),
framesCount(0),
frames(0),
events(0) {
}
#endif
} spEventTimeline;
SP_API spEventTimeline* spEventTimeline_create (int framesCount);
SP_API void spEventTimeline_setFrame (spEventTimeline* self, int frameIndex, spEvent* event);
#ifdef SPINE_SHORT_NAMES
typedef spEventTimeline EventTimeline;
#define EventTimeline_create(...) spEventTimeline_create(__VA_ARGS__)
#define EventTimeline_setFrame(...) spEventTimeline_setFrame(__VA_ARGS__)
#endif
/**/
typedef struct spDrawOrderTimeline {
spTimeline super;
int const framesCount;
float* const frames; /* time, ... */
const int** const drawOrders;
int const slotsCount;
#ifdef __cplusplus
spDrawOrderTimeline() :
super(),
framesCount(0),
frames(0),
drawOrders(0),
slotsCount(0) {
}
#endif
} spDrawOrderTimeline;
SP_API spDrawOrderTimeline* spDrawOrderTimeline_create (int framesCount, int slotsCount);
SP_API void spDrawOrderTimeline_setFrame (spDrawOrderTimeline* self, int frameIndex, float time, const int* drawOrder);
#ifdef SPINE_SHORT_NAMES
typedef spDrawOrderTimeline DrawOrderTimeline;
#define DrawOrderTimeline_create(...) spDrawOrderTimeline_create(__VA_ARGS__)
#define DrawOrderTimeline_setFrame(...) spDrawOrderTimeline_setFrame(__VA_ARGS__)
#endif
/**/
typedef struct spDeformTimeline {
spCurveTimeline super;
int const framesCount;
float* const frames; /* time, ... */
int const frameVerticesCount;
const float** const frameVertices;
int slotIndex;
spAttachment* attachment;
#ifdef __cplusplus
spDeformTimeline() :
super(),
framesCount(0),
frames(0),
frameVerticesCount(0),
frameVertices(0),
slotIndex(0) {
}
#endif
} spDeformTimeline;
SP_API spDeformTimeline* spDeformTimeline_create (int framesCount, int frameVerticesCount);
SP_API void spDeformTimeline_setFrame (spDeformTimeline* self, int frameIndex, float time, float* vertices);
#ifdef SPINE_SHORT_NAMES
typedef spDeformTimeline DeformTimeline;
#define DeformTimeline_create(...) spDeformTimeline_create(__VA_ARGS__)
#define DeformTimeline_setFrame(...) spDeformTimeline_setFrame(__VA_ARGS__)
#endif
/**/
static const int IKCONSTRAINT_ENTRIES = 6;
typedef struct spIkConstraintTimeline {
spCurveTimeline super;
int const framesCount;
float* const frames; /* time, mix, bendDirection, ... */
int ikConstraintIndex;
#ifdef __cplusplus
spIkConstraintTimeline() :
super(),
framesCount(0),
frames(0),
ikConstraintIndex(0) {
}
#endif
} spIkConstraintTimeline;
SP_API spIkConstraintTimeline* spIkConstraintTimeline_create (int framesCount);
SP_API void spIkConstraintTimeline_setFrame (spIkConstraintTimeline* self, int frameIndex, float time, float mix, float softness, int bendDirection, int /*boolean*/ compress, int /**boolean**/ stretch);
#ifdef SPINE_SHORT_NAMES
typedef spIkConstraintTimeline IkConstraintTimeline;
#define IkConstraintTimeline_create(...) spIkConstraintTimeline_create(__VA_ARGS__)
#define IkConstraintTimeline_setFrame(...) spIkConstraintTimeline_setFrame(__VA_ARGS__)
#endif
/**/
static const int TRANSFORMCONSTRAINT_ENTRIES = 5;
typedef struct spTransformConstraintTimeline {
spCurveTimeline super;
int const framesCount;
float* const frames; /* time, rotate mix, translate mix, scale mix, shear mix, ... */
int transformConstraintIndex;
#ifdef __cplusplus
spTransformConstraintTimeline() :
super(),
framesCount(0),
frames(0),
transformConstraintIndex(0) {
}
#endif
} spTransformConstraintTimeline;
SP_API spTransformConstraintTimeline* spTransformConstraintTimeline_create (int framesCount);
SP_API void spTransformConstraintTimeline_setFrame (spTransformConstraintTimeline* self, int frameIndex, float time, float rotateMix, float translateMix, float scaleMix, float shearMix);
#ifdef SPINE_SHORT_NAMES
typedef spTransformConstraintTimeline TransformConstraintTimeline;
#define TransformConstraintTimeline_create(...) spTransformConstraintTimeline_create(__VA_ARGS__)
#define TransformConstraintTimeline_setFrame(...) spTransformConstraintTimeline_setFrame(__VA_ARGS__)
#endif
/**/
static const int PATHCONSTRAINTPOSITION_ENTRIES = 2;
typedef struct spPathConstraintPositionTimeline {
spCurveTimeline super;
int const framesCount;
float* const frames; /* time, rotate mix, translate mix, scale mix, shear mix, ... */
int pathConstraintIndex;
#ifdef __cplusplus
spPathConstraintPositionTimeline() :
super(),
framesCount(0),
frames(0),
pathConstraintIndex(0) {
}
#endif
} spPathConstraintPositionTimeline;
SP_API spPathConstraintPositionTimeline* spPathConstraintPositionTimeline_create (int framesCount);
SP_API void spPathConstraintPositionTimeline_setFrame (spPathConstraintPositionTimeline* self, int frameIndex, float time, float value);
#ifdef SPINE_SHORT_NAMES
typedef spPathConstraintPositionTimeline PathConstraintPositionTimeline;
#define PathConstraintPositionTimeline_create(...) spPathConstraintPositionTimeline_create(__VA_ARGS__)
#define PathConstraintPositionTimeline_setFrame(...) spPathConstraintPositionTimeline_setFrame(__VA_ARGS__)
#endif
/**/
static const int PATHCONSTRAINTSPACING_ENTRIES = 2;
typedef struct spPathConstraintSpacingTimeline {
spCurveTimeline super;
int const framesCount;
float* const frames; /* time, rotate mix, translate mix, scale mix, shear mix, ... */
int pathConstraintIndex;
#ifdef __cplusplus
spPathConstraintSpacingTimeline() :
super(),
framesCount(0),
frames(0),
pathConstraintIndex(0) {
}
#endif
} spPathConstraintSpacingTimeline;
SP_API spPathConstraintSpacingTimeline* spPathConstraintSpacingTimeline_create (int framesCount);
SP_API void spPathConstraintSpacingTimeline_setFrame (spPathConstraintSpacingTimeline* self, int frameIndex, float time, float value);
#ifdef SPINE_SHORT_NAMES
typedef spPathConstraintSpacingTimeline PathConstraintSpacingTimeline;
#define PathConstraintSpacingTimeline_create(...) spPathConstraintSpacingTimeline_create(__VA_ARGS__)
#define PathConstraintSpacingTimeline_setFrame(...) spPathConstraintSpacingTimeline_setFrame(__VA_ARGS__)
#endif
/**/
static const int PATHCONSTRAINTMIX_ENTRIES = 3;
typedef struct spPathConstraintMixTimeline {
spCurveTimeline super;
int const framesCount;
float* const frames; /* time, rotate mix, translate mix, scale mix, shear mix, ... */
int pathConstraintIndex;
#ifdef __cplusplus
spPathConstraintMixTimeline() :
super(),
framesCount(0),
frames(0),
pathConstraintIndex(0) {
}
#endif
} spPathConstraintMixTimeline;
SP_API spPathConstraintMixTimeline* spPathConstraintMixTimeline_create (int framesCount);
SP_API void spPathConstraintMixTimeline_setFrame (spPathConstraintMixTimeline* self, int frameIndex, float time, float rotateMix, float translateMix);
#ifdef SPINE_SHORT_NAMES
typedef spPathConstraintMixTimeline PathConstraintMixTimeline;
#define PathConstraintMixTimeline_create(...) spPathConstraintMixTimeline_create(__VA_ARGS__)
#define PathConstraintMixTimeline_setFrame(...) spPathConstraintMixTimeline_setFrame(__VA_ARGS__)
#endif
/**/
#ifdef __cplusplus
}
#endif
#endif /* SPINE_ANIMATION_H_ */

View File

@ -0,0 +1,189 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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/dll.h>
#include <spine/Animation.h>
#include <spine/AnimationStateData.h>
#include <spine/Event.h>
#include <spine/Array.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
SP_ANIMATION_START, SP_ANIMATION_INTERRUPT, SP_ANIMATION_END, SP_ANIMATION_COMPLETE, SP_ANIMATION_DISPOSE, SP_ANIMATION_EVENT
} spEventType;
typedef struct spAnimationState spAnimationState;
typedef struct spTrackEntry spTrackEntry;
typedef void (*spAnimationStateListener) (spAnimationState* state, spEventType type, spTrackEntry* entry, spEvent* event);
_SP_ARRAY_DECLARE_TYPE(spTrackEntryArray, spTrackEntry*)
struct spTrackEntry {
spAnimation* animation;
spTrackEntry* next;
spTrackEntry* mixingFrom;
spTrackEntry* mixingTo;
spAnimationStateListener listener;
int trackIndex;
int /*boolean*/ loop;
int /*boolean*/ holdPrevious;
float eventThreshold, attachmentThreshold, drawOrderThreshold;
float animationStart, animationEnd, animationLast, nextAnimationLast;
float delay, trackTime, trackLast, nextTrackLast, trackEnd, timeScale;
float alpha, mixTime, mixDuration, interruptAlpha, totalAlpha;
spMixBlend mixBlend;
spIntArray* timelineMode;
spTrackEntryArray* timelineHoldMix;
float* timelinesRotation;
int timelinesRotationCount;
void* rendererObject;
void* userData;
#ifdef __cplusplus
spTrackEntry() :
animation(0),
next(0), mixingFrom(0), mixingTo(0),
listener(0),
trackIndex(0),
loop(0),
holdPrevious(0),
eventThreshold(0), attachmentThreshold(0), drawOrderThreshold(0),
animationStart(0), animationEnd(0), animationLast(0), nextAnimationLast(0),
delay(0), trackTime(0), trackLast(0), nextTrackLast(0), trackEnd(0), timeScale(0),
alpha(0), mixTime(0), mixDuration(0), interruptAlpha(0), totalAlpha(0),
mixBlend(SP_MIX_BLEND_REPLACE),
timelineMode(0),
timelineHoldMix(0),
timelinesRotation(0),
timelinesRotationCount(0),
rendererObject(0), userData(0) {
}
#endif
};
struct spAnimationState {
spAnimationStateData* const data;
int tracksCount;
spTrackEntry** tracks;
spAnimationStateListener listener;
float timeScale;
void* rendererObject;
void* userData;
#ifdef __cplusplus
spAnimationState() :
data(0),
tracksCount(0),
tracks(0),
listener(0),
timeScale(0),
rendererObject(0),
userData(0) {
}
#endif
};
/* @param data May be 0 for no mixing. */
SP_API spAnimationState* spAnimationState_create (spAnimationStateData* data);
SP_API void spAnimationState_dispose (spAnimationState* self);
SP_API void spAnimationState_update (spAnimationState* self, float delta);
SP_API int /**bool**/ spAnimationState_apply (spAnimationState* self, struct spSkeleton* skeleton);
SP_API void spAnimationState_clearTracks (spAnimationState* self);
SP_API void spAnimationState_clearTrack (spAnimationState* self, int trackIndex);
/** Set the current animation. Any queued animations are cleared. */
SP_API spTrackEntry* spAnimationState_setAnimationByName (spAnimationState* self, int trackIndex, const char* animationName,
int/*bool*/loop);
SP_API spTrackEntry* spAnimationState_setAnimation (spAnimationState* self, int trackIndex, spAnimation* animation, int/*bool*/loop);
/** Adds an animation to be played delay seconds after the current or last queued animation, taking into account any mix
* duration. */
SP_API spTrackEntry* spAnimationState_addAnimationByName (spAnimationState* self, int trackIndex, const char* animationName,
int/*bool*/loop, float delay);
SP_API spTrackEntry* spAnimationState_addAnimation (spAnimationState* self, int trackIndex, spAnimation* animation, int/*bool*/loop,
float delay);
SP_API spTrackEntry* spAnimationState_setEmptyAnimation(spAnimationState* self, int trackIndex, float mixDuration);
SP_API spTrackEntry* spAnimationState_addEmptyAnimation(spAnimationState* self, int trackIndex, float mixDuration, float delay);
SP_API void spAnimationState_setEmptyAnimations(spAnimationState* self, float mixDuration);
SP_API spTrackEntry* spAnimationState_getCurrent (spAnimationState* self, int trackIndex);
SP_API void spAnimationState_clearListenerNotifications(spAnimationState* self);
SP_API float spTrackEntry_getAnimationTime (spTrackEntry* entry);
/** Use this to dispose static memory before your app exits to appease your memory leak detector*/
SP_API void spAnimationState_disposeStatics ();
#ifdef SPINE_SHORT_NAMES
typedef spEventType EventType;
#define ANIMATION_START SP_ANIMATION_START
#define ANIMATION_INTERRUPT SP_ANIMATION_INTERRUPT
#define ANIMATION_END SP_ANIMATION_END
#define ANIMATION_COMPLETE SP_ANIMATION_COMPLETE
#define ANIMATION_DISPOSE SP_ANIMATION_DISPOSE
#define ANIMATION_EVENT SP_ANIMATION_EVENT
typedef spAnimationStateListener AnimationStateListener;
typedef spTrackEntry TrackEntry;
typedef spAnimationState AnimationState;
#define AnimationState_create(...) spAnimationState_create(__VA_ARGS__)
#define AnimationState_dispose(...) spAnimationState_dispose(__VA_ARGS__)
#define AnimationState_update(...) spAnimationState_update(__VA_ARGS__)
#define AnimationState_apply(...) spAnimationState_apply(__VA_ARGS__)
#define AnimationState_clearTracks(...) spAnimationState_clearTracks(__VA_ARGS__)
#define AnimationState_clearTrack(...) spAnimationState_clearTrack(__VA_ARGS__)
#define AnimationState_setAnimationByName(...) spAnimationState_setAnimationByName(__VA_ARGS__)
#define AnimationState_setAnimation(...) spAnimationState_setAnimation(__VA_ARGS__)
#define AnimationState_addAnimationByName(...) spAnimationState_addAnimationByName(__VA_ARGS__)
#define AnimationState_addAnimation(...) spAnimationState_addAnimation(__VA_ARGS__)
#define AnimationState_setEmptyAnimation(...) spAnimationState_setEmptyAnimation(__VA_ARGS__)
#define AnimationState_addEmptyAnimation(...) spAnimationState_addEmptyAnimation(__VA_ARGS__)
#define AnimationState_setEmptyAnimations(...) spAnimationState_setEmptyAnimations(__VA_ARGS__)
#define AnimationState_getCurrent(...) spAnimationState_getCurrent(__VA_ARGS__)
#define AnimationState_clearListenerNotifications(...) spAnimationState_clearListenerNotifications(__VA_ARGS__)
#endif
#ifdef __cplusplus
}
#endif
#endif /* SPINE_ANIMATIONSTATE_H_ */

View File

@ -0,0 +1,76 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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/dll.h>
#include <spine/Animation.h>
#include <spine/SkeletonData.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct spAnimationStateData {
spSkeletonData* const skeletonData;
float defaultMix;
const void* const entries;
#ifdef __cplusplus
spAnimationStateData() :
skeletonData(0),
defaultMix(0),
entries(0) {
}
#endif
} spAnimationStateData;
SP_API spAnimationStateData* spAnimationStateData_create (spSkeletonData* skeletonData);
SP_API void spAnimationStateData_dispose (spAnimationStateData* self);
SP_API void spAnimationStateData_setMixByName (spAnimationStateData* self, const char* fromName, const char* toName, float duration);
SP_API void spAnimationStateData_setMix (spAnimationStateData* self, spAnimation* from, spAnimation* to, float duration);
/* Returns 0 if there is no mixing between the animations. */
SP_API float spAnimationStateData_getMix (spAnimationStateData* self, spAnimation* from, spAnimation* to);
#ifdef SPINE_SHORT_NAMES
typedef spAnimationStateData AnimationStateData;
#define AnimationStateData_create(...) spAnimationStateData_create(__VA_ARGS__)
#define AnimationStateData_dispose(...) spAnimationStateData_dispose(__VA_ARGS__)
#define AnimationStateData_setMixByName(...) spAnimationStateData_setMixByName(__VA_ARGS__)
#define AnimationStateData_setMix(...) spAnimationStateData_setMix(__VA_ARGS__)
#define AnimationStateData_getMix(...) spAnimationStateData_getMix(__VA_ARGS__)
#endif
#ifdef __cplusplus
}
#endif
#endif /* SPINE_ANIMATIONSTATEDATA_H_ */

View File

@ -0,0 +1,132 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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/dll.h>
#ifdef __cplusplus
extern "C" {
#endif
#define _SP_ARRAY_DECLARE_TYPE(name, itemType) \
typedef struct name { int size; int capacity; itemType* items; } name; \
SP_API name* name##_create(int initialCapacity); \
SP_API void name##_dispose(name* self); \
SP_API void name##_clear(name* self); \
SP_API name* name##_setSize(name* self, int newSize); \
SP_API void name##_ensureCapacity(name* self, int newCapacity); \
SP_API void name##_add(name* self, itemType value); \
SP_API void name##_addAll(name* self, name* other); \
SP_API void name##_addAllValues(name* self, itemType* values, int offset, int count); \
SP_API void name##_removeAt(name* self, int index); \
SP_API int name##_contains(name* self, itemType value); \
SP_API itemType name##_pop(name* self); \
SP_API itemType name##_peek(name* self);
#define _SP_ARRAY_IMPLEMENT_TYPE(name, itemType) \
name* name##_create(int initialCapacity) { \
name* array = CALLOC(name, 1); \
array->size = 0; \
array->capacity = initialCapacity; \
array->items = CALLOC(itemType, initialCapacity); \
return array; \
} \
void name##_dispose(name* self) { \
FREE(self->items); \
FREE(self); \
} \
void name##_clear(name* self) { \
self->size = 0; \
} \
name* name##_setSize(name* self, int newSize) { \
self->size = newSize; \
if (self->capacity < newSize) { \
self->capacity = MAX(8, (int)(self->size * 1.75f)); \
self->items = REALLOC(self->items, itemType, self->capacity); \
} \
return self; \
} \
void name##_ensureCapacity(name* self, int newCapacity) { \
if (self->capacity >= newCapacity) return; \
self->capacity = newCapacity; \
self->items = REALLOC(self->items, itemType, self->capacity); \
} \
void name##_add(name* self, itemType value) { \
if (self->size == self->capacity) { \
self->capacity = MAX(8, (int)(self->size * 1.75f)); \
self->items = REALLOC(self->items, itemType, self->capacity); \
} \
self->items[self->size++] = value; \
} \
void name##_addAll(name* self, name* other) { \
int i = 0; \
for (; i < other->size; i++) { \
name##_add(self, other->items[i]); \
} \
} \
void name##_addAllValues(name* self, itemType* values, int offset, int count) { \
int i = offset, n = offset + count; \
for (; i < n; i++) { \
name##_add(self, values[i]); \
} \
} \
void name##_removeAt(name* self, int index) { \
self->size--; \
memmove(self->items + index, self->items + index + 1, sizeof(itemType) * (self->size - index)); \
} \
int name##_contains(name* self, itemType value) { \
itemType* items = self->items; \
int i, n; \
for (i = 0, n = self->size; i < n; i++) { \
if (items[i] == value) return -1; \
} \
return 0; \
} \
itemType name##_pop(name* self) { \
itemType item = self->items[--self->size]; \
return item; \
} \
itemType name##_peek(name* self) { \
return self->items[self->size - 1]; \
}
_SP_ARRAY_DECLARE_TYPE(spFloatArray, float)
_SP_ARRAY_DECLARE_TYPE(spIntArray, int)
_SP_ARRAY_DECLARE_TYPE(spShortArray, short)
_SP_ARRAY_DECLARE_TYPE(spUnsignedShortArray, unsigned short)
_SP_ARRAY_DECLARE_TYPE(spArrayFloatArray, spFloatArray*)
_SP_ARRAY_DECLARE_TYPE(spArrayShortArray, spShortArray*)
#ifdef __cplusplus
}
#endif
#endif /* SPINE_ARRAY_H */

View File

@ -0,0 +1,174 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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/dll.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct spAtlas spAtlas;
typedef enum {
SP_ATLAS_UNKNOWN_FORMAT,
SP_ATLAS_ALPHA,
SP_ATLAS_INTENSITY,
SP_ATLAS_LUMINANCE_ALPHA,
SP_ATLAS_RGB565,
SP_ATLAS_RGBA4444,
SP_ATLAS_RGB888,
SP_ATLAS_RGBA8888
} spAtlasFormat;
typedef enum {
SP_ATLAS_UNKNOWN_FILTER,
SP_ATLAS_NEAREST,
SP_ATLAS_LINEAR,
SP_ATLAS_MIPMAP,
SP_ATLAS_MIPMAP_NEAREST_NEAREST,
SP_ATLAS_MIPMAP_LINEAR_NEAREST,
SP_ATLAS_MIPMAP_NEAREST_LINEAR,
SP_ATLAS_MIPMAP_LINEAR_LINEAR
} spAtlasFilter;
typedef enum {
SP_ATLAS_MIRROREDREPEAT,
SP_ATLAS_CLAMPTOEDGE,
SP_ATLAS_REPEAT
} spAtlasWrap;
typedef struct spAtlasPage spAtlasPage;
struct spAtlasPage {
const spAtlas* atlas;
const char* name;
spAtlasFormat format;
spAtlasFilter minFilter, magFilter;
spAtlasWrap uWrap, vWrap;
void* rendererObject;
int width, height;
spAtlasPage* next;
};
SP_API spAtlasPage* spAtlasPage_create (spAtlas* atlas, const char* name);
SP_API void spAtlasPage_dispose (spAtlasPage* self);
#ifdef SPINE_SHORT_NAMES
typedef spAtlasFormat AtlasFormat;
#define ATLAS_UNKNOWN_FORMAT SP_ATLAS_UNKNOWN_FORMAT
#define ATLAS_ALPHA SP_ATLAS_ALPHA
#define ATLAS_INTENSITY SP_ATLAS_INTENSITY
#define ATLAS_LUMINANCE_ALPHA SP_ATLAS_LUMINANCE_ALPHA
#define ATLAS_RGB565 SP_ATLAS_RGB565
#define ATLAS_RGBA4444 SP_ATLAS_RGBA4444
#define ATLAS_RGB888 SP_ATLAS_RGB888
#define ATLAS_RGBA8888 SP_ATLAS_RGBA8888
typedef spAtlasFilter AtlasFilter;
#define ATLAS_UNKNOWN_FILTER SP_ATLAS_UNKNOWN_FILTER
#define ATLAS_NEAREST SP_ATLAS_NEAREST
#define ATLAS_LINEAR SP_ATLAS_LINEAR
#define ATLAS_MIPMAP SP_ATLAS_MIPMAP
#define ATLAS_MIPMAP_NEAREST_NEAREST SP_ATLAS_MIPMAP_NEAREST_NEAREST
#define ATLAS_MIPMAP_LINEAR_NEAREST SP_ATLAS_MIPMAP_LINEAR_NEAREST
#define ATLAS_MIPMAP_NEAREST_LINEAR SP_ATLAS_MIPMAP_NEAREST_LINEAR
#define ATLAS_MIPMAP_LINEAR_LINEAR SP_ATLAS_MIPMAP_LINEAR_LINEAR
typedef spAtlasWrap AtlasWrap;
#define ATLAS_MIRROREDREPEAT SP_ATLAS_MIRROREDREPEAT
#define ATLAS_CLAMPTOEDGE SP_ATLAS_CLAMPTOEDGE
#define ATLAS_REPEAT SP_ATLAS_REPEAT
typedef spAtlasPage AtlasPage;
#define AtlasPage_create(...) spAtlasPage_create(__VA_ARGS__)
#define AtlasPage_dispose(...) spAtlasPage_dispose(__VA_ARGS__)
#endif
/**/
typedef struct spAtlasRegion spAtlasRegion;
struct spAtlasRegion {
const char* name;
int x, y, width, height;
float u, v, u2, v2;
int offsetX, offsetY;
int originalWidth, originalHeight;
int index;
int/*bool*/rotate;
int degrees;
int/*bool*/flip;
int* splits;
int* pads;
spAtlasPage* page;
spAtlasRegion* next;
};
SP_API spAtlasRegion* spAtlasRegion_create ();
SP_API void spAtlasRegion_dispose (spAtlasRegion* self);
#ifdef SPINE_SHORT_NAMES
typedef spAtlasRegion AtlasRegion;
#define AtlasRegion_create(...) spAtlasRegion_create(__VA_ARGS__)
#define AtlasRegion_dispose(...) spAtlasRegion_dispose(__VA_ARGS__)
#endif
/**/
struct spAtlas {
spAtlasPage* pages;
spAtlasRegion* regions;
void* rendererObject;
};
/* Image files referenced in the atlas file will be prefixed with dir. */
SP_API spAtlas* spAtlas_create (const char* data, int length, const char* dir, void* rendererObject);
/* Image files referenced in the atlas file will be prefixed with the directory containing the atlas file. */
SP_API spAtlas* spAtlas_createFromFile (const char* path, void* rendererObject);
SP_API void spAtlas_dispose (spAtlas* atlas);
/* Returns 0 if the region was not found. */
SP_API spAtlasRegion* spAtlas_findRegion (const spAtlas* self, const char* name);
#ifdef SPINE_SHORT_NAMES
typedef spAtlas Atlas;
#define Atlas_create(...) spAtlas_create(__VA_ARGS__)
#define Atlas_createFromFile(...) spAtlas_createFromFile(__VA_ARGS__)
#define Atlas_dispose(...) spAtlas_dispose(__VA_ARGS__)
#define Atlas_findRegion(...) spAtlas_findRegion(__VA_ARGS__)
#endif
#ifdef __cplusplus
}
#endif
#endif /* SPINE_ATLAS_H_ */

View File

@ -0,0 +1,57 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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/dll.h>
#include <spine/AttachmentLoader.h>
#include <spine/Atlas.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct spAtlasAttachmentLoader {
spAttachmentLoader super;
spAtlas* atlas;
} spAtlasAttachmentLoader;
SP_API spAtlasAttachmentLoader* spAtlasAttachmentLoader_create (spAtlas* atlas);
#ifdef SPINE_SHORT_NAMES
typedef spAtlasAttachmentLoader AtlasAttachmentLoader;
#define AtlasAttachmentLoader_create(...) spAtlasAttachmentLoader_create(__VA_ARGS__)
#endif
#ifdef __cplusplus
}
#endif
#endif /* SPINE_ATLASATTACHMENTLOADER_H_ */

View File

@ -0,0 +1,86 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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/dll.h>
#ifdef __cplusplus
extern "C" {
#endif
struct spAttachmentLoader;
typedef enum {
SP_ATTACHMENT_REGION,
SP_ATTACHMENT_BOUNDING_BOX,
SP_ATTACHMENT_MESH,
SP_ATTACHMENT_LINKED_MESH,
SP_ATTACHMENT_PATH,
SP_ATTACHMENT_POINT,
SP_ATTACHMENT_CLIPPING
} spAttachmentType;
typedef struct spAttachment {
const char* const name;
const spAttachmentType type;
const void* const vtable;
int refCount;
struct spAttachmentLoader* attachmentLoader;
#ifdef __cplusplus
spAttachment() :
name(0),
type(SP_ATTACHMENT_REGION),
vtable(0),
refCount(0) {
}
#endif
} spAttachment;
void spAttachment_dispose (spAttachment* self);
spAttachment* spAttachment_copy (spAttachment* self);
#ifdef SPINE_SHORT_NAMES
typedef spAttachmentType AttachmentType;
#define ATTACHMENT_REGION SP_ATTACHMENT_REGION
#define ATTACHMENT_BOUNDING_BOX SP_ATTACHMENT_BOUNDING_BOX
#define ATTACHMENT_MESH SP_ATTACHMENT_MESH
#define ATTACHMENT_LINKED_MESH SP_ATTACHMENT_LINKED_MESH
typedef spAttachment Attachment;
#define Attachment_dispose(...) spAttachment_dispose(__VA_ARGS__)
#endif
#ifdef __cplusplus
}
#endif
#endif /* SPINE_ATTACHMENT_H_ */

View File

@ -0,0 +1,78 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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/dll.h>
#include <spine/Attachment.h>
#include <spine/Skin.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct spAttachmentLoader {
const char* error1;
const char* error2;
const void* const vtable;
#ifdef __cplusplus
spAttachmentLoader () :
error1(0),
error2(0),
vtable(0) {
}
#endif
} spAttachmentLoader;
SP_API void spAttachmentLoader_dispose (spAttachmentLoader* self);
/* Called to create each attachment. Returns 0 to not load an attachment. If 0 is returned and _spAttachmentLoader_setError was
* called, an error occurred. */
SP_API spAttachment* spAttachmentLoader_createAttachment (spAttachmentLoader* self, spSkin* skin, spAttachmentType type, const char* name,
const char* path);
/* Called after the attachment has been fully configured. */
SP_API void spAttachmentLoader_configureAttachment (spAttachmentLoader* self, spAttachment* attachment);
/* Called just before the attachment is disposed. This can release allocations made in spAttachmentLoader_configureAttachment. */
SP_API void spAttachmentLoader_disposeAttachment (spAttachmentLoader* self, spAttachment* attachment);
#ifdef SPINE_SHORT_NAMES
typedef spAttachmentLoader AttachmentLoader;
#define AttachmentLoader_dispose(...) spAttachmentLoader_dispose(__VA_ARGS__)
#define AttachmentLoader_createAttachment(...) spAttachmentLoader_createAttachment(__VA_ARGS__)
#define AttachmentLoader_configureAttachment(...) spAttachmentLoader_configureAttachment(__VA_ARGS__)
#define AttachmentLoader_disposeAttachment(...) spAttachmentLoader_disposeAttachment(__VA_ARGS__)
#endif
#ifdef __cplusplus
}
#endif
#endif /* SPINE_ATTACHMENTLOADER_H_ */

View File

@ -0,0 +1,127 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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/dll.h>
#include <spine/BoneData.h>
#ifdef __cplusplus
extern "C" {
#endif
struct spSkeleton;
typedef struct spBone spBone;
struct spBone {
spBoneData* const data;
struct spSkeleton* const skeleton;
spBone* const parent;
int childrenCount;
spBone** const children;
float x, y, rotation, scaleX, scaleY, shearX, shearY;
float ax, ay, arotation, ascaleX, ascaleY, ashearX, ashearY;
int /*bool*/ appliedValid;
float const a, b, worldX;
float const c, d, worldY;
int/*bool*/ sorted;
int/*bool*/ active;
#ifdef __cplusplus
spBone() :
data(0),
skeleton(0),
parent(0),
childrenCount(0), children(0),
x(0), y(0), rotation(0), scaleX(0), scaleY(0),
ax(0), ay(0), arotation(0), ascaleX(0), ascaleY(0), ashearX(0), ashearY(0),
appliedValid(0),
a(0), b(0), worldX(0),
c(0), d(0), worldY(0),
sorted(0), active(0) {
}
#endif
};
SP_API void spBone_setYDown (int/*bool*/yDown);
SP_API int/*bool*/spBone_isYDown ();
/* @param parent May be 0. */
SP_API spBone* spBone_create (spBoneData* data, struct spSkeleton* skeleton, spBone* parent);
SP_API void spBone_dispose (spBone* self);
SP_API void spBone_setToSetupPose (spBone* self);
SP_API void spBone_updateWorldTransform (spBone* self);
SP_API void spBone_updateWorldTransformWith (spBone* self, float x, float y, float rotation, float scaleX, float scaleY, float shearX, float shearY);
SP_API float spBone_getWorldRotationX (spBone* self);
SP_API float spBone_getWorldRotationY (spBone* self);
SP_API float spBone_getWorldScaleX (spBone* self);
SP_API float spBone_getWorldScaleY (spBone* self);
SP_API void spBone_updateAppliedTransform (spBone* self);
SP_API void spBone_worldToLocal (spBone* self, float worldX, float worldY, float* localX, float* localY);
SP_API void spBone_localToWorld (spBone* self, float localX, float localY, float* worldX, float* worldY);
SP_API float spBone_worldToLocalRotation (spBone* self, float worldRotation);
SP_API float spBone_localToWorldRotation (spBone* self, float localRotation);
SP_API void spBone_rotateWorld (spBone* self, float degrees);
#ifdef SPINE_SHORT_NAMES
typedef spBone Bone;
#define Bone_setYDown(...) spBone_setYDown(__VA_ARGS__)
#define Bone_isYDown() spBone_isYDown()
#define Bone_create(...) spBone_create(__VA_ARGS__)
#define Bone_dispose(...) spBone_dispose(__VA_ARGS__)
#define Bone_setToSetupPose(...) spBone_setToSetupPose(__VA_ARGS__)
#define Bone_updateWorldTransform(...) spBone_updateWorldTransform(__VA_ARGS__)
#define Bone_updateWorldTransformWith(...) spBone_updateWorldTransformWith(__VA_ARGS__)
#define Bone_getWorldRotationX(...) spBone_getWorldRotationX(__VA_ARGS__)
#define Bone_getWorldRotationY(...) spBone_getWorldRotationY(__VA_ARGS__)
#define Bone_getWorldScaleX(...) spBone_getWorldScaleX(__VA_ARGS__)
#define Bone_getWorldScaleY(...) spBone_getWorldScaleY(__VA_ARGS__)
#define Bone_updateAppliedTransform(...) spBone_updateAppliedTransform(__VA_ARGS__)
#define Bone_worldToLocal(...) spBone_worldToLocal(__VA_ARGS__)
#define Bone_localToWorld(...) spBone_localToWorld(__VA_ARGS__)
#define Bone_worldToLocalRotation(...) spBone_worldToLocalRotation(__VA_ARGS__)
#define Bone_localToWorldRotation(...) spBone_localToWorldRotation(__VA_ARGS__)
#define Bone_rotateWorld(...) spBone_rotateWorld(__VA_ARGS__)
#endif
#ifdef __cplusplus
}
#endif
#endif /* SPINE_BONE_H_ */

View File

@ -0,0 +1,86 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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/dll.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
SP_TRANSFORMMODE_NORMAL,
SP_TRANSFORMMODE_ONLYTRANSLATION,
SP_TRANSFORMMODE_NOROTATIONORREFLECTION,
SP_TRANSFORMMODE_NOSCALE,
SP_TRANSFORMMODE_NOSCALEORREFLECTION
} spTransformMode;
typedef struct spBoneData spBoneData;
struct spBoneData {
const int index;
const char* const name;
spBoneData* const parent;
float length;
float x, y, rotation, scaleX, scaleY, shearX, shearY;
spTransformMode transformMode;
int/*bool*/ skinRequired;
#ifdef __cplusplus
spBoneData() :
index(0),
name(0),
parent(0),
length(0),
x(0), y(0),
rotation(0),
scaleX(0), scaleY(0),
shearX(0), shearY(0),
transformMode(SP_TRANSFORMMODE_NORMAL),
skinRequired(0) {
}
#endif
};
SP_API spBoneData* spBoneData_create (int index, const char* name, spBoneData* parent);
SP_API void spBoneData_dispose (spBoneData* self);
#ifdef SPINE_SHORT_NAMES
typedef spBoneData BoneData;
#define BoneData_create(...) spBoneData_create(__VA_ARGS__)
#define BoneData_dispose(...) spBoneData_dispose(__VA_ARGS__)
#endif
#ifdef __cplusplus
}
#endif
#endif /* SPINE_BONEDATA_H_ */

View File

@ -0,0 +1,58 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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/dll.h>
#include <spine/Attachment.h>
#include <spine/VertexAttachment.h>
#include <spine/Atlas.h>
#include <spine/Slot.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct spBoundingBoxAttachment {
spVertexAttachment super;
} spBoundingBoxAttachment;
SP_API spBoundingBoxAttachment* spBoundingBoxAttachment_create (const char* name);
#ifdef SPINE_SHORT_NAMES
typedef spBoundingBoxAttachment BoundingBoxAttachment;
#define BoundingBoxAttachment_create(...) spBoundingBoxAttachment_create(__VA_ARGS__)
#endif
#ifdef __cplusplus
}
#endif
#endif /* SPINE_BOUNDINGBOXATTACHMENT_H_ */

View File

@ -0,0 +1,60 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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/dll.h>
#include <spine/Attachment.h>
#include <spine/VertexAttachment.h>
#include <spine/Atlas.h>
#include <spine/Slot.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct spClippingAttachment {
spVertexAttachment super;
spSlotData* endSlot;
} spClippingAttachment;
SP_API void _spClippingAttachment_dispose(spAttachment* self);
SP_API spClippingAttachment* spClippingAttachment_create (const char* name);
#ifdef SPINE_SHORT_NAMES
typedef spClippingAttachment ClippingAttachment;
#define ClippingAttachment_create(...) spClippingAttachment_create(__VA_ARGS__)
#endif
#ifdef __cplusplus
}
#endif
#endif /* SPINE_CLIPPINGATTACHMENT_H_ */

View File

@ -0,0 +1,77 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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/dll.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct spColor {
float r, g, b, a;
#ifdef __cplusplus
spColor() :
r(0), g(0), b(0), a(0) {
}
bool operator==(const spColor& rhs) {
return r == rhs.r && g == rhs.g && b == rhs.b && a == rhs.a;
}
#endif
} spColor;
/* @param attachmentName May be 0 for no setup pose attachment. */
SP_API spColor* spColor_create();
SP_API void spColor_dispose(spColor* self);
SP_API void spColor_setFromFloats(spColor* color, float r, float g, float b, float a);
SP_API void spColor_setFromColor(spColor* color, spColor* otherColor);
SP_API void spColor_addFloats(spColor* color, float r, float g, float b, float a);
SP_API void spColor_addColor(spColor* color, spColor* otherColor);
SP_API void spColor_clamp(spColor* color);
#ifdef SPINE_SHORT_NAMES
typedef spColor color;
#define Color_create() spColor_create()
#define Color_dispose(...) spColor_dispose(__VA_ARGS__)
#define Color_setFromFloats(...) spColor_setFromFloats(__VA_ARGS__)
#define Color_setFromColor(...) spColor_setFromColor(__VA_ARGS__)
#define Color_addColor(...) spColor_addColor(__VA_ARGS__)
#define Color_addFloats(...) spColor_addFloats(__VA_ARGS__)
#define Color_clamp(...) spColor_clamp(__VA_ARGS__)
#endif
#ifdef __cplusplus
}
#endif
#endif /* SPINE_COLOR_H_ */

View File

@ -0,0 +1,75 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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/dll.h>
#include <spine/EventData.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct spEvent {
spEventData* const data;
float const time;
int intValue;
float floatValue;
const char* stringValue;
float volume;
float balance;
#ifdef __cplusplus
spEvent() :
data(0),
time(0),
intValue(0),
floatValue(0),
stringValue(0),
volume(0),
balance(0) {
}
#endif
} spEvent;
SP_API spEvent* spEvent_create (float time, spEventData* data);
SP_API void spEvent_dispose (spEvent* self);
#ifdef SPINE_SHORT_NAMES
typedef spEvent Event;
#define Event_create(...) spEvent_create(__VA_ARGS__)
#define Event_dispose(...) spEvent_dispose(__VA_ARGS__)
#endif
#ifdef __cplusplus
}
#endif
#endif /* SPINE_EVENT_H_ */

View File

@ -0,0 +1,74 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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/dll.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct spEventData {
const char* const name;
int intValue;
float floatValue;
const char* stringValue;
const char* audioPath;
float volume;
float balance;
#ifdef __cplusplus
spEventData() :
name(0),
intValue(0),
floatValue(0),
stringValue(0),
audioPath(0),
volume(0),
balance(0) {
}
#endif
} spEventData;
SP_API spEventData* spEventData_create (const char* name);
SP_API void spEventData_dispose (spEventData* self);
#ifdef SPINE_SHORT_NAMES
typedef spEventData EventData;
#define EventData_create(...) spEventData_create(__VA_ARGS__)
#define EventData_dispose(...) spEventData_dispose(__VA_ARGS__)
#endif
#ifdef __cplusplus
}
#endif
#endif /* SPINE_EVENTDATA_H_ */

View File

@ -0,0 +1,94 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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/dll.h>
#include <spine/IkConstraintData.h>
#include <spine/Bone.h>
#ifdef __cplusplus
extern "C" {
#endif
struct spSkeleton;
typedef struct spIkConstraint {
spIkConstraintData* const data;
int bonesCount;
spBone** bones;
spBone* target;
int bendDirection;
int /*boolean*/ compress;
int /*boolean*/ stretch;
float mix;
float softness;
int /*boolean*/ active;
#ifdef __cplusplus
spIkConstraint() :
data(0),
bonesCount(0),
bones(0),
target(0),
bendDirection(0),
stretch(0),
mix(0),
softness(0),
active(0) {
}
#endif
} spIkConstraint;
SP_API spIkConstraint* spIkConstraint_create (spIkConstraintData* data, const struct spSkeleton* skeleton);
SP_API void spIkConstraint_dispose (spIkConstraint* self);
SP_API void spIkConstraint_apply (spIkConstraint* self);
SP_API void spIkConstraint_apply1 (spBone* bone, float targetX, float targetY, int /*boolean*/ compress, int /*boolean*/ stretch, int /*boolean*/ uniform, float alpha);
SP_API void spIkConstraint_apply2 (spBone* parent, spBone* child, float targetX, float targetY, int bendDirection, int /*boolean*/ stretch, float softness, float alpha);
#ifdef SPINE_SHORT_NAMES
typedef spIkConstraint IkConstraint;
#define IkConstraint_create(...) spIkConstraint_create(__VA_ARGS__)
#define IkConstraint_dispose(...) spIkConstraint_dispose(__VA_ARGS__)
#define IkConstraint_apply(...) spIkConstraint_apply(__VA_ARGS__)
#define IkConstraint_apply1(...) spIkConstraint_apply1(__VA_ARGS__)
#define IkConstraint_apply2(...) spIkConstraint_apply2(__VA_ARGS__)
#endif
#ifdef __cplusplus
}
#endif
#endif /* SPINE_IKCONSTRAINT_H_ */

View File

@ -0,0 +1,86 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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/dll.h>
#include <spine/BoneData.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct spIkConstraintData {
const char* const name;
int order;
int /*boolean*/ skinRequired;
int bonesCount;
spBoneData** bones;
spBoneData* target;
int bendDirection;
int /*boolean*/ compress;
int /*boolean*/ stretch;
int /*boolean*/ uniform;
float mix;
float softness;
#ifdef __cplusplus
spIkConstraintData() :
name(0),
order(0),
skinRequired(0),
bonesCount(0),
bones(0),
target(0),
bendDirection(0),
compress(0),
stretch(0),
uniform(0),
mix(0),
softness(0) {
}
#endif
} spIkConstraintData;
SP_API spIkConstraintData* spIkConstraintData_create (const char* name);
SP_API void spIkConstraintData_dispose (spIkConstraintData* self);
#ifdef SPINE_SHORT_NAMES
typedef spIkConstraintData IkConstraintData;
#define IkConstraintData_create(...) spIkConstraintData_create(__VA_ARGS__)
#define IkConstraintData_dispose(...) spIkConstraintData_dispose(__VA_ARGS__)
#endif
#ifdef __cplusplus
}
#endif
#endif /* SPINE_IKCONSTRAINTDATA_H_ */

View File

@ -0,0 +1,91 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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/dll.h>
#include <spine/Attachment.h>
#include <spine/VertexAttachment.h>
#include <spine/Atlas.h>
#include <spine/Slot.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct spMeshAttachment spMeshAttachment;
struct spMeshAttachment {
spVertexAttachment super;
void* rendererObject;
int regionOffsetX, regionOffsetY; /* Pixels stripped from the bottom left, unrotated. */
int regionWidth, regionHeight; /* Unrotated, stripped pixel size. */
int regionOriginalWidth, regionOriginalHeight; /* Unrotated, unstripped pixel size. */
float regionU, regionV, regionU2, regionV2;
int/*bool*/regionRotate;
int regionDegrees;
const char* path;
float* regionUVs;
float* uvs;
int trianglesCount;
unsigned short* triangles;
spColor color;
int hullLength;
spMeshAttachment* const parentMesh;
/* Nonessential. */
int edgesCount;
int* edges;
float width, height;
};
SP_API spMeshAttachment* spMeshAttachment_create (const char* name);
SP_API void spMeshAttachment_updateUVs (spMeshAttachment* self);
SP_API void spMeshAttachment_setParentMesh (spMeshAttachment* self, spMeshAttachment* parentMesh);
SP_API spMeshAttachment* spMeshAttachment_newLinkedMesh (spMeshAttachment* self);
#ifdef SPINE_SHORT_NAMES
typedef spMeshAttachment MeshAttachment;
#define MeshAttachment_create(...) spMeshAttachment_create(__VA_ARGS__)
#define MeshAttachment_updateUVs(...) spMeshAttachment_updateUVs(__VA_ARGS__)
#define MeshAttachment_setParentMesh(...) spMeshAttachment_setParentMesh(__VA_ARGS__)
#endif
#ifdef __cplusplus
}
#endif
#endif /* SPINE_MESHATTACHMENT_H_ */

View File

@ -0,0 +1,62 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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/dll.h>
#include <spine/Attachment.h>
#include <spine/VertexAttachment.h>
#include <spine/Atlas.h>
#include <spine/Slot.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct spPathAttachment {
spVertexAttachment super;
int lengthsLength;
float* lengths;
int/*bool*/ closed, constantSpeed;
} spPathAttachment;
SP_API spPathAttachment* spPathAttachment_create (const char* name);
#ifdef SPINE_SHORT_NAMES
typedef spPathAttachment PathAttachment;
#define PathAttachment_create(...) spPathAttachment_create(__VA_ARGS__)
#define PathAttachment_computeWorldVertices(...) spPathAttachment_computeWorldVertices(__VA_ARGS__)
#endif
#ifdef __cplusplus
}
#endif
#endif /* SPINE_PATHATTACHMENT_H_ */

View File

@ -0,0 +1,115 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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/dll.h>
#include <spine/PathConstraintData.h>
#include <spine/Bone.h>
#include <spine/Slot.h>
#include "PathAttachment.h"
#ifdef __cplusplus
extern "C" {
#endif
struct spSkeleton;
typedef struct spPathConstraint {
spPathConstraintData* const data;
int bonesCount;
spBone** const bones;
spSlot* target;
float position, spacing, rotateMix, translateMix;
int spacesCount;
float* spaces;
int positionsCount;
float* positions;
int worldCount;
float* world;
int curvesCount;
float* curves;
int lengthsCount;
float* lengths;
float segments[10];
int /*boolean*/ active;
#ifdef __cplusplus
spPathConstraint() :
data(0),
bonesCount(0),
bones(0),
target(0),
position(0),
spacing(0),
rotateMix(0),
translateMix(0),
spacesCount(0),
spaces(0),
positionsCount(0),
positions(0),
worldCount(0),
world(0),
curvesCount(0),
curves(0),
lengthsCount(0),
lengths(0),
active(0) {
}
#endif
} spPathConstraint;
#define SP_PATHCONSTRAINT_
SP_API spPathConstraint* spPathConstraint_create (spPathConstraintData* data, const struct spSkeleton* skeleton);
SP_API void spPathConstraint_dispose (spPathConstraint* self);
SP_API void spPathConstraint_apply (spPathConstraint* self);
SP_API float* spPathConstraint_computeWorldPositions(spPathConstraint* self, spPathAttachment* path, int spacesCount, int/*bool*/ tangents, int/*bool*/percentPosition, int/**/percentSpacing);
#ifdef SPINE_SHORT_NAMES
typedef spPathConstraint PathConstraint;
#define PathConstraint_create(...) spPathConstraint_create(__VA_ARGS__)
#define PathConstraint_dispose(...) spPathConstraint_dispose(__VA_ARGS__)
#define PathConstraint_apply(...) spPathConstraint_apply(__VA_ARGS__)
#endif
#ifdef __cplusplus
}
#endif
#endif /* SPINE_PATHCONSTRAINT_H_ */

View File

@ -0,0 +1,99 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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/dll.h>
#include <spine/BoneData.h>
#include <spine/SlotData.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
SP_POSITION_MODE_FIXED, SP_POSITION_MODE_PERCENT
} spPositionMode;
typedef enum {
SP_SPACING_MODE_LENGTH, SP_SPACING_MODE_FIXED, SP_SPACING_MODE_PERCENT
} spSpacingMode;
typedef enum {
SP_ROTATE_MODE_TANGENT, SP_ROTATE_MODE_CHAIN, SP_ROTATE_MODE_CHAIN_SCALE
} spRotateMode;
typedef struct spPathConstraintData {
const char* const name;
int order;
int/*bool*/ skinRequired;
int bonesCount;
spBoneData** const bones;
spSlotData* target;
spPositionMode positionMode;
spSpacingMode spacingMode;
spRotateMode rotateMode;
float offsetRotation;
float position, spacing, rotateMix, translateMix;
#ifdef __cplusplus
spPathConstraintData() :
name(0),
order(0),
skinRequired(0),
bonesCount(0),
bones(0),
target(0),
positionMode(SP_POSITION_MODE_FIXED),
spacingMode(SP_SPACING_MODE_LENGTH),
rotateMode(SP_ROTATE_MODE_TANGENT),
offsetRotation(0),
position(0),
spacing(0),
rotateMix(0),
translateMix(0) {
}
#endif
} spPathConstraintData;
SP_API spPathConstraintData* spPathConstraintData_create (const char* name);
SP_API void spPathConstraintData_dispose (spPathConstraintData* self);
#ifdef SPINE_SHORT_NAMES
typedef spPathConstraintData PathConstraintData;
#define PathConstraintData_create(...) spPathConstraintData_create(__VA_ARGS__)
#define PathConstraintData_dispose(...) spPathConstraintData_dispose(__VA_ARGS__)
#endif
#ifdef __cplusplus
}
#endif
#endif /* SPINE_PATHCONSTRAINTDATA_H_ */

View File

@ -0,0 +1,64 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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/dll.h>
#include <spine/Attachment.h>
#include <spine/VertexAttachment.h>
#include <spine/Atlas.h>
#include <spine/Slot.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct spPointAttachment {
spAttachment super;
float x, y, rotation;
spColor color;
} spPointAttachment;
SP_API spPointAttachment* spPointAttachment_create (const char* name);
SP_API void spPointAttachment_computeWorldPosition (spPointAttachment* self, spBone* bone, float* x, float* y);
SP_API float spPointAttachment_computeWorldRotation (spPointAttachment* self, spBone* bone);
#ifdef SPINE_SHORT_NAMES
typedef spPointAttachment PointAttachment;
#define PointAttachment_create(...) spPointAttachment_create(__VA_ARGS__)
#define PointAttachment_computeWorldPosition(...) spPointAttachment_computeWorldPosition(__VA_ARGS__)
#define PointAttachment_computeWorldRotation(...) spPointAttachment_computeWorldRotation(__VA_ARGS__)
#endif
#ifdef __cplusplus
}
#endif
#endif /* SPINE_POINTATTACHMENT_H_ */

View File

@ -0,0 +1,74 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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/dll.h>
#include <spine/Attachment.h>
#include <spine/Atlas.h>
#include <spine/Slot.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct spRegionAttachment {
spAttachment super;
const char* path;
float x, y, scaleX, scaleY, rotation, width, height;
spColor color;
void* rendererObject;
int regionOffsetX, regionOffsetY; /* Pixels stripped from the bottom left, unrotated. */
int regionWidth, regionHeight; /* Unrotated, stripped pixel size. */
int regionOriginalWidth, regionOriginalHeight; /* Unrotated, unstripped pixel size. */
float offset[8];
float uvs[8];
} spRegionAttachment;
SP_API spRegionAttachment* spRegionAttachment_create (const char* name);
SP_API void spRegionAttachment_setUVs (spRegionAttachment* self, float u, float v, float u2, float v2, int/*bool*/rotate);
SP_API void spRegionAttachment_updateOffset (spRegionAttachment* self);
SP_API void spRegionAttachment_computeWorldVertices (spRegionAttachment* self, spBone* bone, float* vertices, int offset, int stride);
#ifdef SPINE_SHORT_NAMES
typedef spRegionAttachment RegionAttachment;
#define RegionAttachment_create(...) spRegionAttachment_create(__VA_ARGS__)
#define RegionAttachment_setUVs(...) spRegionAttachment_setUVs(__VA_ARGS__)
#define RegionAttachment_updateOffset(...) spRegionAttachment_updateOffset(__VA_ARGS__)
#define RegionAttachment_computeWorldVertices(...) spRegionAttachment_computeWorldVertices(__VA_ARGS__)
#endif
#ifdef __cplusplus
}
#endif
#endif /* SPINE_REGIONATTACHMENT_H_ */

View File

@ -0,0 +1,173 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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/dll.h>
#include <spine/SkeletonData.h>
#include <spine/Slot.h>
#include <spine/Skin.h>
#include <spine/IkConstraint.h>
#include <spine/TransformConstraint.h>
#include <spine/PathConstraint.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct spSkeleton {
spSkeletonData* const data;
int bonesCount;
spBone** bones;
spBone* const root;
int slotsCount;
spSlot** slots;
spSlot** drawOrder;
int ikConstraintsCount;
spIkConstraint** ikConstraints;
int transformConstraintsCount;
spTransformConstraint** transformConstraints;
int pathConstraintsCount;
spPathConstraint** pathConstraints;
spSkin* const skin;
spColor color;
float time;
float scaleX, scaleY;
float x, y;
#ifdef __cplusplus
spSkeleton() :
data(0),
bonesCount(0),
bones(0),
root(0),
slotsCount(0),
slots(0),
drawOrder(0),
ikConstraintsCount(0),
ikConstraints(0),
transformConstraintsCount(0),
transformConstraints(0),
skin(0),
color(),
time(0),
scaleX(1),
scaleY(1),
x(0), y(0) {
}
#endif
} spSkeleton;
SP_API spSkeleton* spSkeleton_create (spSkeletonData* data);
SP_API void spSkeleton_dispose (spSkeleton* self);
/* Caches information about bones and constraints. Must be called if bones or constraints, or weighted path attachments
* are added or removed. */
SP_API void spSkeleton_updateCache (spSkeleton* self);
SP_API void spSkeleton_updateWorldTransform (const spSkeleton* self);
/* Sets the bones, constraints, and slots to their setup pose values. */
SP_API void spSkeleton_setToSetupPose (const spSkeleton* self);
/* Sets the bones and constraints to their setup pose values. */
SP_API void spSkeleton_setBonesToSetupPose (const spSkeleton* self);
SP_API void spSkeleton_setSlotsToSetupPose (const spSkeleton* self);
/* Returns 0 if the bone was not found. */
SP_API spBone* spSkeleton_findBone (const spSkeleton* self, const char* boneName);
/* Returns -1 if the bone was not found. */
SP_API int spSkeleton_findBoneIndex (const spSkeleton* self, const char* boneName);
/* Returns 0 if the slot was not found. */
SP_API spSlot* spSkeleton_findSlot (const spSkeleton* self, const char* slotName);
/* Returns -1 if the slot was not found. */
SP_API int spSkeleton_findSlotIndex (const spSkeleton* self, const char* slotName);
/* Sets the skin used to look up attachments before looking in the SkeletonData defaultSkin. 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 mode
* attachment is attached from the new skin.
* @param skin May be 0.*/
SP_API void spSkeleton_setSkin (spSkeleton* self, spSkin* skin);
/* Returns 0 if the skin was not found. See spSkeleton_setSkin.
* @param skinName May be 0. */
SP_API int spSkeleton_setSkinByName (spSkeleton* self, const char* skinName);
/* Returns 0 if the slot or attachment was not found. */
SP_API spAttachment* spSkeleton_getAttachmentForSlotName (const spSkeleton* self, const char* slotName, const char* attachmentName);
/* Returns 0 if the slot or attachment was not found. */
SP_API spAttachment* spSkeleton_getAttachmentForSlotIndex (const spSkeleton* self, int slotIndex, const char* attachmentName);
/* Returns 0 if the slot or attachment was not found.
* @param attachmentName May be 0. */
SP_API int spSkeleton_setAttachment (spSkeleton* self, const char* slotName, const char* attachmentName);
/* Returns 0 if the IK constraint was not found. */
SP_API spIkConstraint* spSkeleton_findIkConstraint (const spSkeleton* self, const char* constraintName);
/* Returns 0 if the transform constraint was not found. */
SP_API spTransformConstraint* spSkeleton_findTransformConstraint (const spSkeleton* self, const char* constraintName);
/* Returns 0 if the path constraint was not found. */
SP_API spPathConstraint* spSkeleton_findPathConstraint (const spSkeleton* self, const char* constraintName);
SP_API void spSkeleton_update (spSkeleton* self, float deltaTime);
#ifdef SPINE_SHORT_NAMES
typedef spSkeleton Skeleton;
#define Skeleton_create(...) spSkeleton_create(__VA_ARGS__)
#define Skeleton_dispose(...) spSkeleton_dispose(__VA_ARGS__)
#define Skeleton_updateWorldTransform(...) spSkeleton_updateWorldTransform(__VA_ARGS__)
#define Skeleton_setToSetupPose(...) spSkeleton_setToSetupPose(__VA_ARGS__)
#define Skeleton_setBonesToSetupPose(...) spSkeleton_setBonesToSetupPose(__VA_ARGS__)
#define Skeleton_setSlotsToSetupPose(...) spSkeleton_setSlotsToSetupPose(__VA_ARGS__)
#define Skeleton_findBone(...) spSkeleton_findBone(__VA_ARGS__)
#define Skeleton_findBoneIndex(...) spSkeleton_findBoneIndex(__VA_ARGS__)
#define Skeleton_findSlot(...) spSkeleton_findSlot(__VA_ARGS__)
#define Skeleton_findSlotIndex(...) spSkeleton_findSlotIndex(__VA_ARGS__)
#define Skeleton_setSkin(...) spSkeleton_setSkin(__VA_ARGS__)
#define Skeleton_setSkinByName(...) spSkeleton_setSkinByName(__VA_ARGS__)
#define Skeleton_getAttachmentForSlotName(...) spSkeleton_getAttachmentForSlotName(__VA_ARGS__)
#define Skeleton_getAttachmentForSlotIndex(...) spSkeleton_getAttachmentForSlotIndex(__VA_ARGS__)
#define Skeleton_setAttachment(...) spSkeleton_setAttachment(__VA_ARGS__)
#define Skeleton_update(...) spSkeleton_update(__VA_ARGS__)
#endif
#ifdef __cplusplus
}
#endif
#endif /* SPINE_SKELETON_H_*/

View File

@ -0,0 +1,71 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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/dll.h>
#include <spine/Attachment.h>
#include <spine/AttachmentLoader.h>
#include <spine/SkeletonData.h>
#include <spine/Atlas.h>
#ifdef __cplusplus
extern "C" {
#endif
struct spAtlasAttachmentLoader;
typedef struct spSkeletonBinary {
float scale;
spAttachmentLoader* attachmentLoader;
const char* const error;
} spSkeletonBinary;
SP_API spSkeletonBinary* spSkeletonBinary_createWithLoader (spAttachmentLoader* attachmentLoader);
SP_API spSkeletonBinary* spSkeletonBinary_create (spAtlas* atlas);
SP_API void spSkeletonBinary_dispose (spSkeletonBinary* self);
SP_API spSkeletonData* spSkeletonBinary_readSkeletonData (spSkeletonBinary* self, const unsigned char* binary, const int length);
SP_API spSkeletonData* spSkeletonBinary_readSkeletonDataFile (spSkeletonBinary* self, const char* path);
#ifdef SPINE_SHORT_NAMES
typedef spSkeletonBinary SkeletonBinary;
#define SkeletonBinary_createWithLoader(...) spSkeletonBinary_createWithLoader(__VA_ARGS__)
#define SkeletonBinary_create(...) spSkeletonBinary_create(__VA_ARGS__)
#define SkeletonBinary_dispose(...) spSkeletonBinary_dispose(__VA_ARGS__)
#define SkeletonBinary_readSkeletonData(...) spSkeletonBinary_readSkeletonData(__VA_ARGS__)
#define SkeletonBinary_readSkeletonDataFile(...) spSkeletonBinary_readSkeletonDataFile(__VA_ARGS__)
#endif
#ifdef __cplusplus
}
#endif
#endif /* SPINE_SKELETONBINARY_H_ */

View File

@ -0,0 +1,112 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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/dll.h>
#include <spine/BoundingBoxAttachment.h>
#include <spine/Skeleton.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct spPolygon {
float* const vertices;
int count;
int capacity;
} spPolygon;
SP_API spPolygon* spPolygon_create (int capacity);
SP_API void spPolygon_dispose (spPolygon* self);
SP_API int/*bool*/spPolygon_containsPoint (spPolygon* polygon, float x, float y);
SP_API int/*bool*/spPolygon_intersectsSegment (spPolygon* polygon, float x1, float y1, float x2, float y2);
#ifdef SPINE_SHORT_NAMES
typedef spPolygon Polygon;
#define Polygon_create(...) spPolygon_create(__VA_ARGS__)
#define Polygon_dispose(...) spPolygon_dispose(__VA_ARGS__)
#define Polygon_containsPoint(...) spPolygon_containsPoint(__VA_ARGS__)
#define Polygon_intersectsSegment(...) spPolygon_intersectsSegment(__VA_ARGS__)
#endif
/**/
typedef struct spSkeletonBounds {
int count;
spBoundingBoxAttachment** boundingBoxes;
spPolygon** polygons;
float minX, minY, maxX, maxY;
} spSkeletonBounds;
SP_API spSkeletonBounds* spSkeletonBounds_create ();
SP_API void spSkeletonBounds_dispose (spSkeletonBounds* self);
SP_API void spSkeletonBounds_update (spSkeletonBounds* self, spSkeleton* skeleton, int/*bool*/updateAabb);
/** Returns true if the axis aligned bounding box contains the point. */
SP_API int/*bool*/spSkeletonBounds_aabbContainsPoint (spSkeletonBounds* self, float x, float y);
/** Returns true if the axis aligned bounding box intersects the line segment. */
SP_API int/*bool*/spSkeletonBounds_aabbIntersectsSegment (spSkeletonBounds* self, 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. */
SP_API int/*bool*/spSkeletonBounds_aabbIntersectsSkeleton (spSkeletonBounds* self, spSkeletonBounds* bounds);
/** 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 spSkeletonBounds_aabbContainsPoint returns true. */
SP_API spBoundingBoxAttachment* spSkeletonBounds_containsPoint (spSkeletonBounds* self, float x, float y);
/** Returns the first bounding box attachment that contains the line segment, or null. When doing many checks, it is usually
* more efficient to only call this method if spSkeletonBounds_aabbIntersectsSegment returns true. */
SP_API spBoundingBoxAttachment* spSkeletonBounds_intersectsSegment (spSkeletonBounds* self, float x1, float y1, float x2, float y2);
/** Returns the polygon for the specified bounding box, or null. */
SP_API spPolygon* spSkeletonBounds_getPolygon (spSkeletonBounds* self, spBoundingBoxAttachment* boundingBox);
#ifdef SPINE_SHORT_NAMES
typedef spSkeletonBounds SkeletonBounds;
#define SkeletonBounds_create(...) spSkeletonBounds_create(__VA_ARGS__)
#define SkeletonBounds_dispose(...) spSkeletonBounds_dispose(__VA_ARGS__)
#define SkeletonBounds_update(...) spSkeletonBounds_update(__VA_ARGS__)
#define SkeletonBounds_aabbContainsPoint(...) spSkeletonBounds_aabbContainsPoint(__VA_ARGS__)
#define SkeletonBounds_aabbIntersectsSegment(...) spSkeletonBounds_aabbIntersectsSegment(__VA_ARGS__)
#define SkeletonBounds_aabbIntersectsSkeleton(...) spSkeletonBounds_aabbIntersectsSkeleton(__VA_ARGS__)
#define SkeletonBounds_containsPoint(...) spSkeletonBounds_containsPoint(__VA_ARGS__)
#define SkeletonBounds_intersectsSegment(...) spSkeletonBounds_intersectsSegment(__VA_ARGS__)
#define SkeletonBounds_getPolygon(...) spSkeletonBounds_getPolygon(__VA_ARGS__)
#endif
#ifdef __cplusplus
}
#endif
#endif /* SPINE_SKELETONBOUNDS_H_ */

View File

@ -0,0 +1,67 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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/dll.h>
#include <spine/Array.h>
#include <spine/ClippingAttachment.h>
#include <spine/Slot.h>
#include <spine/Triangulator.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct spSkeletonClipping {
spTriangulator* triangulator;
spFloatArray* clippingPolygon;
spFloatArray* clipOutput;
spFloatArray* clippedVertices;
spFloatArray* clippedUVs;
spUnsignedShortArray* clippedTriangles;
spFloatArray* scratch;
spClippingAttachment* clipAttachment;
spArrayFloatArray* clippingPolygons;
} spSkeletonClipping;
SP_API spSkeletonClipping* spSkeletonClipping_create();
SP_API int spSkeletonClipping_clipStart(spSkeletonClipping* self, spSlot* slot, spClippingAttachment* clip);
SP_API void spSkeletonClipping_clipEnd(spSkeletonClipping* self, spSlot* slot);
SP_API void spSkeletonClipping_clipEnd2(spSkeletonClipping* self);
SP_API int /*boolean*/ spSkeletonClipping_isClipping(spSkeletonClipping* self);
SP_API void spSkeletonClipping_clipTriangles(spSkeletonClipping* self, float* vertices, int verticesLength, unsigned short* triangles, int trianglesLength, float* uvs, int stride);
SP_API void spSkeletonClipping_dispose(spSkeletonClipping* self);
#ifdef __cplusplus
}
#endif
#endif /* SPINE_SKELETONCLIPPING_H */

View File

@ -0,0 +1,119 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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/dll.h>
#include <spine/BoneData.h>
#include <spine/SlotData.h>
#include <spine/Skin.h>
#include <spine/EventData.h>
#include <spine/Animation.h>
#include <spine/IkConstraintData.h>
#include <spine/TransformConstraintData.h>
#include <spine/PathConstraintData.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct spSkeletonData {
const char* version;
const char* hash;
float x, y, width, height;
int stringsCount;
char** strings;
int bonesCount;
spBoneData** bones;
int slotsCount;
spSlotData** slots;
int skinsCount;
spSkin** skins;
spSkin* defaultSkin;
int eventsCount;
spEventData** events;
int animationsCount;
spAnimation** animations;
int ikConstraintsCount;
spIkConstraintData** ikConstraints;
int transformConstraintsCount;
spTransformConstraintData** transformConstraints;
int pathConstraintsCount;
spPathConstraintData** pathConstraints;
} spSkeletonData;
SP_API spSkeletonData* spSkeletonData_create ();
SP_API void spSkeletonData_dispose (spSkeletonData* self);
SP_API spBoneData* spSkeletonData_findBone (const spSkeletonData* self, const char* boneName);
SP_API int spSkeletonData_findBoneIndex (const spSkeletonData* self, const char* boneName);
SP_API spSlotData* spSkeletonData_findSlot (const spSkeletonData* self, const char* slotName);
SP_API int spSkeletonData_findSlotIndex (const spSkeletonData* self, const char* slotName);
SP_API spSkin* spSkeletonData_findSkin (const spSkeletonData* self, const char* skinName);
SP_API spEventData* spSkeletonData_findEvent (const spSkeletonData* self, const char* eventName);
SP_API spAnimation* spSkeletonData_findAnimation (const spSkeletonData* self, const char* animationName);
SP_API spIkConstraintData* spSkeletonData_findIkConstraint (const spSkeletonData* self, const char* constraintName);
SP_API spTransformConstraintData* spSkeletonData_findTransformConstraint (const spSkeletonData* self, const char* constraintName);
SP_API spPathConstraintData* spSkeletonData_findPathConstraint (const spSkeletonData* self, const char* constraintName);
#ifdef SPINE_SHORT_NAMES
typedef spSkeletonData SkeletonData;
#define SkeletonData_create(...) spSkeletonData_create(__VA_ARGS__)
#define SkeletonData_dispose(...) spSkeletonData_dispose(__VA_ARGS__)
#define SkeletonData_findBone(...) spSkeletonData_findBone(__VA_ARGS__)
#define SkeletonData_findBoneIndex(...) spSkeletonData_findBoneIndex(__VA_ARGS__)
#define SkeletonData_findSlot(...) spSkeletonData_findSlot(__VA_ARGS__)
#define SkeletonData_findSlotIndex(...) spSkeletonData_findSlotIndex(__VA_ARGS__)
#define SkeletonData_findSkin(...) spSkeletonData_findSkin(__VA_ARGS__)
#define SkeletonData_findEvent(...) spSkeletonData_findEvent(__VA_ARGS__)
#define SkeletonData_findAnimation(...) spSkeletonData_findAnimation(__VA_ARGS__)
#endif
#ifdef __cplusplus
}
#endif
#endif /* SPINE_SKELETONDATA_H_ */

View File

@ -0,0 +1,72 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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/dll.h>
#include <spine/Attachment.h>
#include <spine/AttachmentLoader.h>
#include <spine/SkeletonData.h>
#include <spine/Atlas.h>
#include <spine/Animation.h>
#ifdef __cplusplus
extern "C" {
#endif
struct spAtlasAttachmentLoader;
typedef struct spSkeletonJson {
float scale;
spAttachmentLoader* attachmentLoader;
const char* const error;
} spSkeletonJson;
SP_API spSkeletonJson* spSkeletonJson_createWithLoader (spAttachmentLoader* attachmentLoader);
SP_API spSkeletonJson* spSkeletonJson_create (spAtlas* atlas);
SP_API void spSkeletonJson_dispose (spSkeletonJson* self);
SP_API spSkeletonData* spSkeletonJson_readSkeletonData (spSkeletonJson* self, const char* json);
SP_API spSkeletonData* spSkeletonJson_readSkeletonDataFile (spSkeletonJson* self, const char* path);
#ifdef SPINE_SHORT_NAMES
typedef spSkeletonJson SkeletonJson;
#define SkeletonJson_createWithLoader(...) spSkeletonJson_createWithLoader(__VA_ARGS__)
#define SkeletonJson_create(...) spSkeletonJson_create(__VA_ARGS__)
#define SkeletonJson_dispose(...) spSkeletonJson_dispose(__VA_ARGS__)
#define SkeletonJson_readSkeletonData(...) spSkeletonJson_readSkeletonData(__VA_ARGS__)
#define SkeletonJson_readSkeletonDataFile(...) spSkeletonJson_readSkeletonDataFile(__VA_ARGS__)
#endif
#ifdef __cplusplus
}
#endif
#endif /* SPINE_SKELETONJSON_H_ */

View File

@ -0,0 +1,135 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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/dll.h>
#include <spine/Attachment.h>
#include <spine/IkConstraintData.h>
#include <spine/TransformConstraintData.h>
#include <spine/PathConstraintData.h>
#include <spine/Array.h>
#ifdef __cplusplus
extern "C" {
#endif
/* Size of hashtable used in skin structure for fast attachment lookup. */
#define SKIN_ENTRIES_HASH_TABLE_SIZE 100
struct spSkeleton;
_SP_ARRAY_DECLARE_TYPE(spBoneDataArray, spBoneData*)
_SP_ARRAY_DECLARE_TYPE(spIkConstraintDataArray, spIkConstraintData*)
_SP_ARRAY_DECLARE_TYPE(spTransformConstraintDataArray, spTransformConstraintData*)
_SP_ARRAY_DECLARE_TYPE(spPathConstraintDataArray, spPathConstraintData*)
typedef struct spSkin {
const char* const name;
spBoneDataArray* bones;
spIkConstraintDataArray* ikConstraints;
spTransformConstraintDataArray* transformConstraints;
spPathConstraintDataArray* pathConstraints;
#ifdef __cplusplus
spSkin() :
name(0),
bones(0),
ikConstraints(0),
transformConstraints(0),
pathConstraints(0) {
}
#endif
} spSkin;
/* Private structs, needed by Skeleton */
typedef struct _Entry _Entry;
typedef struct _Entry spSkinEntry;
struct _Entry {
int slotIndex;
const char* name;
spAttachment* attachment;
_Entry* next;
};
typedef struct _SkinHashTableEntry _SkinHashTableEntry;
struct _SkinHashTableEntry {
_Entry* entry;
_SkinHashTableEntry* next;
};
typedef struct {
spSkin super;
_Entry* entries; /* entries list stored for getting attachment name by attachment index */
_SkinHashTableEntry* entriesHashTable[SKIN_ENTRIES_HASH_TABLE_SIZE]; /* hashtable for fast attachment lookup */
} _spSkin;
SP_API spSkin* spSkin_create (const char* name);
SP_API void spSkin_dispose (spSkin* self);
/* The Skin owns the attachment. */
SP_API void spSkin_setAttachment (spSkin* self, int slotIndex, const char* name, spAttachment* attachment);
/* Returns 0 if the attachment was not found. */
SP_API spAttachment* spSkin_getAttachment (const spSkin* self, int slotIndex, const char* name);
/* Returns 0 if the slot or attachment was not found. */
SP_API const char* spSkin_getAttachmentName (const spSkin* self, int slotIndex, int attachmentIndex);
/** Attach each attachment in this skin if the corresponding attachment in oldSkin is currently attached. */
SP_API void spSkin_attachAll (const spSkin* self, struct spSkeleton* skeleton, const spSkin* oldspSkin);
/** Adds all attachments, bones, and constraints from the specified skin to this skin. */
SP_API void spSkin_addSkin(spSkin* self, const spSkin* other);
/** Adds all attachments, bones, and constraints from the specified skin to this skin. Attachments are deep copied. */
SP_API void spSkin_copySkin(spSkin* self, const spSkin* other);
/** Returns all attachments in this skin. */
SP_API spSkinEntry* spSkin_getAttachments(const spSkin* self);
/** Clears all attachments, bones, and constraints. */
SP_API void spSkin_clear(spSkin* self);
#ifdef SPINE_SHORT_NAMES
typedef spSkin Skin;
#define Skin_create(...) spSkin_create(__VA_ARGS__)
#define Skin_dispose(...) spSkin_dispose(__VA_ARGS__)
#define Skin_setAttachment(...) spSkin_addAttachment(__VA_ARGS__)
#define Skin_getAttachment(...) spSkin_getAttachment(__VA_ARGS__)
#define Skin_getAttachmentName(...) spSkin_getAttachmentName(__VA_ARGS__)
#define Skin_attachAll(...) spSkin_attachAll(__VA_ARGS__)
#endif
#ifdef __cplusplus
}
#endif
#endif /* SPINE_SKIN_H_ */

View File

@ -0,0 +1,92 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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/dll.h>
#include <spine/Bone.h>
#include <spine/Attachment.h>
#include <spine/SlotData.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct spSlot {
spSlotData* const data;
spBone* const bone;
spColor color;
spColor* darkColor;
spAttachment* const attachment;
int deformCapacity;
int deformCount;
float* deform;
#ifdef __cplusplus
spSlot() :
data(0),
bone(0),
color(),
darkColor(0),
attachment(0),
deformCapacity(0),
deformCount(0),
deform(0) {
}
#endif
} spSlot;
SP_API spSlot* spSlot_create (spSlotData* data, spBone* bone);
SP_API void spSlot_dispose (spSlot* self);
/* @param attachment May be 0 to clear the attachment for the slot. */
SP_API void spSlot_setAttachment (spSlot* self, spAttachment* attachment);
SP_API void spSlot_setAttachmentTime (spSlot* self, float time);
SP_API float spSlot_getAttachmentTime (const spSlot* self);
SP_API void spSlot_setToSetupPose (spSlot* self);
#ifdef SPINE_SHORT_NAMES
typedef spSlot Slot;
#define Slot_create(...) spSlot_create(__VA_ARGS__)
#define Slot_dispose(...) spSlot_dispose(__VA_ARGS__)
#define Slot_setAttachment(...) spSlot_setAttachment(__VA_ARGS__)
#define Slot_setAttachmentTime(...) spSlot_setAttachmentTime(__VA_ARGS__)
#define Slot_getAttachmentTime(...) spSlot_getAttachmentTime(__VA_ARGS__)
#define Slot_setToSetupPose(...) spSlot_setToSetupPose(__VA_ARGS__)
#endif
#ifdef __cplusplus
}
#endif
#endif /* SPINE_SLOT_H_ */

View File

@ -0,0 +1,89 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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_SLOTDATA_H_
#define SPINE_SLOTDATA_H_
#include <spine/dll.h>
#include <spine/BoneData.h>
#include <spine/Color.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
SP_BLEND_MODE_NORMAL, SP_BLEND_MODE_ADDITIVE, SP_BLEND_MODE_MULTIPLY, SP_BLEND_MODE_SCREEN
} spBlendMode;
typedef struct spSlotData {
const int index;
const char* const name;
const spBoneData* const boneData;
const char* attachmentName;
spColor color;
spColor* darkColor;
spBlendMode blendMode;
#ifdef __cplusplus
spSlotData() :
index(0),
name(0),
boneData(0),
attachmentName(0),
color(),
darkColor(0),
blendMode(SP_BLEND_MODE_NORMAL) {
}
#endif
} spSlotData;
SP_API spSlotData* spSlotData_create (const int index, const char* name, spBoneData* boneData);
SP_API void spSlotData_dispose (spSlotData* self);
/* @param attachmentName May be 0 for no setup pose attachment. */
SP_API void spSlotData_setAttachmentName (spSlotData* self, const char* attachmentName);
#ifdef SPINE_SHORT_NAMES
typedef spBlendMode BlendMode;
#define BLEND_MODE_NORMAL SP_BLEND_MODE_NORMAL
#define BLEND_MODE_ADDITIVE SP_BLEND_MODE_ADDITIVE
#define BLEND_MODE_MULTIPLY SP_BLEND_MODE_MULTIPLY
#define BLEND_MODE_SCREEN SP_BLEND_MODE_SCREEN
typedef spSlotData SlotData;
#define SlotData_create(...) spSlotData_create(__VA_ARGS__)
#define SlotData_dispose(...) spSlotData_dispose(__VA_ARGS__)
#define SlotData_setAttachmentName(...) spSlotData_setAttachmentName(__VA_ARGS__)
#endif
#ifdef __cplusplus
}
#endif
#endif /* SPINE_SLOTDATA_H_ */

View File

@ -0,0 +1,82 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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_TRANSFORMCONSTRAINT_H_
#define SPINE_TRANSFORMCONSTRAINT_H_
#include <spine/dll.h>
#include <spine/TransformConstraintData.h>
#include <spine/Bone.h>
#ifdef __cplusplus
extern "C" {
#endif
struct spSkeleton;
typedef struct spTransformConstraint {
spTransformConstraintData* const data;
int bonesCount;
spBone** const bones;
spBone* target;
float rotateMix, translateMix, scaleMix, shearMix;
int /*boolean*/ active;
#ifdef __cplusplus
spTransformConstraint() :
data(0),
bonesCount(0),
bones(0),
target(0),
rotateMix(0),
translateMix(0),
scaleMix(0),
shearMix(0),
active(0) {
}
#endif
} spTransformConstraint;
SP_API spTransformConstraint* spTransformConstraint_create (spTransformConstraintData* data, const struct spSkeleton* skeleton);
SP_API void spTransformConstraint_dispose (spTransformConstraint* self);
SP_API void spTransformConstraint_apply (spTransformConstraint* self);
#ifdef SPINE_SHORT_NAMES
typedef spTransformConstraint TransformConstraint;
#define TransformConstraint_create(...) spTransformConstraint_create(__VA_ARGS__)
#define TransformConstraint_dispose(...) spTransformConstraint_dispose(__VA_ARGS__)
#define TransformConstraint_apply(...) spTransformConstraint_apply(__VA_ARGS__)
#endif
#ifdef __cplusplus
}
#endif
#endif /* SPINE_TRANSFORMCONSTRAINT_H_ */

View File

@ -0,0 +1,89 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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_TRANSFORMCONSTRAINTDATA_H_
#define SPINE_TRANSFORMCONSTRAINTDATA_H_
#include <spine/dll.h>
#include <spine/BoneData.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct spTransformConstraintData {
const char* const name;
int order;
int/*bool*/ skinRequired;
int bonesCount;
spBoneData** const bones;
spBoneData* target;
float rotateMix, translateMix, scaleMix, shearMix;
float offsetRotation, offsetX, offsetY, offsetScaleX, offsetScaleY, offsetShearY;
int /*boolean*/ relative;
int /*boolean*/ local;
#ifdef __cplusplus
spTransformConstraintData() :
name(0),
order(0),
skinRequired(0),
bonesCount(0),
bones(0),
target(0),
rotateMix(0),
translateMix(0),
scaleMix(0),
shearMix(0),
offsetRotation(0),
offsetX(0),
offsetY(0),
offsetScaleX(0),
offsetScaleY(0),
offsetShearY(0),
relative(0),
local(0) {
}
#endif
} spTransformConstraintData;
SP_API spTransformConstraintData* spTransformConstraintData_create (const char* name);
SP_API void spTransformConstraintData_dispose (spTransformConstraintData* self);
#ifdef SPINE_SHORT_NAMES
typedef spTransformConstraintData TransformConstraintData;
#define TransformConstraintData_create(...) spTransformConstraintData_create(__VA_ARGS__)
#define TransformConstraintData_dispose(...) spTransformConstraintData_dispose(__VA_ARGS__)
#endif
#ifdef __cplusplus
}
#endif
#endif /* SPINE_TRANSFORMCONSTRAINTDATA_H_ */

View File

@ -0,0 +1,62 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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_TRIANGULATOR_H
#define SPINE_TRIANGULATOR_H
#include <spine/dll.h>
#include <spine/Array.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct spTriangulator {
spArrayFloatArray* convexPolygons;
spArrayShortArray* convexPolygonsIndices;
spShortArray* indicesArray;
spIntArray* isConcaveArray;
spShortArray* triangles;
spArrayFloatArray* polygonPool;
spArrayShortArray* polygonIndicesPool;
} spTriangulator;
SP_API spTriangulator* spTriangulator_create();
SP_API spShortArray* spTriangulator_triangulate(spTriangulator* self, spFloatArray* verticesArray);
SP_API spArrayFloatArray* spTriangulator_decompose(spTriangulator* self, spFloatArray* verticesArray, spShortArray* triangles);
SP_API void spTriangulator_dispose(spTriangulator* self);
#ifdef __cplusplus
}
#endif
#endif /* SPINE_TRIANGULATOR_H_ */

View File

@ -0,0 +1,71 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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_VERTEXATTACHMENT_H_
#define SPINE_VERTEXATTACHMENT_H_
#include <spine/dll.h>
#include <spine/Attachment.h>
#include <spine/Slot.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct spVertexAttachment spVertexAttachment;
struct spVertexAttachment {
spAttachment super;
int bonesCount;
int* bones;
int verticesCount;
float* vertices;
int worldVerticesLength;
spVertexAttachment* deformAttachment;
int id;
};
SP_API void spVertexAttachment_computeWorldVertices (spVertexAttachment* self, spSlot* slot, int start, int count, float* worldVertices, int offset, int stride);
void spVertexAttachment_copyTo(spVertexAttachment* self, spVertexAttachment* other);
#ifdef SPINE_SHORT_NAMES
typedef spVertexAttachment VertexAttachment;
#define VertexAttachment_computeWorldVertices(...) spVertexAttachment_computeWorldVertices(__VA_ARGS__)
#endif
#ifdef __cplusplus
}
#endif
#endif /* SPINE_VERTEXATTACHMENT_H_ */

View File

@ -0,0 +1,84 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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_VERTEXEFFECT_H_
#define SPINE_VERTEXEFFECT_H_
#include <spine/dll.h>
#include <spine/Skeleton.h>
#include <spine/Color.h>
#ifdef __cplusplus
extern "C" {
#endif
struct spVertexEffect;
typedef void (*spVertexEffectBegin)(struct spVertexEffect *self, spSkeleton *skeleton);
typedef void (*spVertexEffectTransform)(struct spVertexEffect *self, float *x, float *y, float *u, float *v,
spColor *light, spColor *dark);
typedef void (*spVertexEffectEnd)(struct spVertexEffect *self);
typedef struct spVertexEffect {
spVertexEffectBegin begin;
spVertexEffectTransform transform;
spVertexEffectEnd end;
} spVertexEffect;
typedef struct spJitterVertexEffect {
spVertexEffect super;
float jitterX;
float jitterY;
} spJitterVertexEffect;
typedef struct spSwirlVertexEffect {
spVertexEffect super;
float centerX;
float centerY;
float radius;
float angle;
float worldX;
float worldY;
} spSwirlVertexEffect;
SP_API spJitterVertexEffect *spJitterVertexEffect_create(float jitterX, float jitterY);
SP_API void spJitterVertexEffect_dispose(spJitterVertexEffect *effect);
SP_API spSwirlVertexEffect *spSwirlVertexEffect_create(float radius);
SP_API void spSwirlVertexEffect_dispose(spSwirlVertexEffect *effect);
#ifdef __cplusplus
}
#endif
#endif /* SPINE_VERTEX_EFFECT_H_ */

View File

@ -0,0 +1,51 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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_SHAREDLIB_H
#define SPINE_SHAREDLIB_H
#ifdef _WIN32
#define DLLIMPORT __declspec(dllimport)
#define DLLEXPORT __declspec(dllexport)
#else
#ifndef DLLIMPORT
#define DLLIMPORT
#endif
#ifndef DLLEXPORT
#define DLLEXPORT
#endif
#endif
#ifdef SPINEPLUGIN_API
#define SP_API SPINEPLUGIN_API
#else
#define SP_API
#endif
#endif /* SPINE_SHAREDLIB_H */

View File

@ -0,0 +1,330 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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.
*****************************************************************************/
/*
Implementation notes:
- An OOP style is used where each "class" is made up of a struct and a number of functions prefixed with the struct name.
- struct fields that are const are readonly. Either they are set in a create function and can never be changed, or they can only
be changed by calling a function.
- Inheritance is done using a struct field named "super" as the first field, allowing the struct to be cast to its "super class".
This works because a pointer to a struct is guaranteed to be a pointer to the first struct field.
- Classes intended for inheritance provide init/deinit functions which subclasses must call in their create/dispose functions.
- Polymorphism is done by a base class providing function pointers in its init function. The public API delegates to these
function pointers.
- Subclasses do not provide a dispose function, instead the base class' dispose function should be used, which will delegate to
a dispose function pointer.
- Classes not designed for inheritance cannot be extended because they may use an internal subclass to hide private data and don't
expose function pointers.
- The public API hides implementation details, such as init/deinit functions. An internal API is exposed by extension.h to allow
classes to be extended. Internal functions begin with underscore (_).
- OOP in C tends to lose type safety. Macros for casting are provided in extension.h to give context for why a cast is being done.
- If SPINE_SHORT_NAMES is defined, the "sp" prefix for all class names is optional.
*/
#ifndef SPINE_EXTENSION_H_
#define SPINE_EXTENSION_H_
#include <spine/dll.h>
#include <raylib.h>
/* Required for sprintf and consorts on MSVC */
#ifdef _MSC_VER
#pragma warning(disable:4996)
#endif
/* All allocation uses these. */
#define MALLOC(TYPE,COUNT) ((TYPE*)_spMalloc(sizeof(TYPE) * (COUNT), __FILE__, __LINE__))
#define CALLOC(TYPE,COUNT) ((TYPE*)_spCalloc(COUNT, sizeof(TYPE), __FILE__, __LINE__))
#define REALLOC(PTR,TYPE,COUNT) ((TYPE*)_spRealloc(PTR, sizeof(TYPE) * (COUNT)))
#define NEW(TYPE) CALLOC(TYPE,1)
/* Gets the direct super class. Type safe. */
#define SUPER(VALUE) (&VALUE->super)
/* Cast to a super class. Not type safe, use with care. Prefer SUPER() where possible. */
#define SUPER_CAST(TYPE,VALUE) ((TYPE*)VALUE)
/* Cast to a sub class. Not type safe, use with care. */
#define SUB_CAST(TYPE,VALUE) ((TYPE*)VALUE)
/* Casts away const. Can be used as an lvalue. Not type safe, use with care. */
#define CONST_CAST(TYPE,VALUE) (*(TYPE*)&VALUE)
/* Gets the vtable for the specified type. Not type safe, use with care. */
#define VTABLE(TYPE,VALUE) ((_##TYPE##Vtable*)((TYPE*)VALUE)->vtable)
/* Frees memory. Can be used on const types. */
#define FREE(VALUE) _spFree((void*)VALUE)
/* Allocates a new char[], assigns it to TO, and copies FROM to it. Can be used on const types. */
#define MALLOC_STR(TO,FROM) strcpy(CONST_CAST(char*, TO) = (char*)MALLOC(char, strlen(FROM) + 1), FROM)
#define PI2 (PI * 2)
#define DEG_RAD (PI / 180)
#define RAD_DEG (180 / PI)
#define ABS(A) ((A) < 0? -(A): (A))
#define SIGNUM(A) ((A) < 0? -1.0f: (A) > 0 ? 1.0f : 0.0f)
#ifdef __STDC_VERSION__
#define FMOD(A,B) fmodf(A, B)
#define ATAN2(A,B) atan2f(A, B)
#define SIN(A) sinf(A)
#define COS(A) cosf(A)
#define SQRT(A) sqrtf(A)
#define ACOS(A) acosf(A)
#define POW(A,B) pow(A, B)
#else
#define FMOD(A,B) (float)fmod(A, B)
#define ATAN2(A,B) (float)atan2(A, B)
#define COS(A) (float)cos(A)
#define SIN(A) (float)sin(A)
#define SQRT(A) (float)sqrt(A)
#define ACOS(A) (float)acos(A)
#define POW(A,B) (float)pow(A, B)
#endif
#define SIN_DEG(A) SIN((A) * DEG_RAD)
#define COS_DEG(A) COS((A) * DEG_RAD)
#define CLAMP(x, min, max) ((x) < (min) ? (min) : ((x) > (max) ? (max) : (x)))
#ifndef MIN
#define MIN(x, y) ((x) < (y) ? (x) : (y))
#endif
#ifndef MAX
#define MAX(x, y) ((x) > (y) ? (x) : (y))
#endif
#define UNUSED(x) (void)(x)
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <spine/Skeleton.h>
#include <spine/Animation.h>
#include <spine/Atlas.h>
#include <spine/AttachmentLoader.h>
#include <spine/VertexAttachment.h>
#include <spine/RegionAttachment.h>
#include <spine/MeshAttachment.h>
#include <spine/BoundingBoxAttachment.h>
#include <spine/ClippingAttachment.h>
#include <spine/PathAttachment.h>
#include <spine/PointAttachment.h>
#include <spine/AnimationState.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* Functions that must be implemented:
*/
void _spAtlasPage_createTexture (spAtlasPage* self, const char* path);
void _spAtlasPage_disposeTexture (spAtlasPage* self);
char* _spUtil_readFile (const char* path, int* length);
#ifdef SPINE_SHORT_NAMES
#define _AtlasPage_createTexture(...) _spAtlasPage_createTexture(__VA_ARGS__)
#define _AtlasPage_disposeTexture(...) _spAtlasPage_disposeTexture(__VA_ARGS__)
#define _Util_readFile(...) _spUtil_readFile(__VA_ARGS__)
#endif
/*
* Internal API available for extension:
*/
void* _spMalloc (size_t size, const char* file, int line);
void* _spCalloc (size_t num, size_t size, const char* file, int line);
void* _spRealloc(void* ptr, size_t size);
void _spFree (void* ptr);
float _spRandom ();
SP_API void _spSetMalloc (void* (*_malloc) (size_t size));
SP_API void _spSetDebugMalloc (void* (*_malloc) (size_t size, const char* file, int line));
SP_API void _spSetRealloc(void* (*_realloc) (void* ptr, size_t size));
SP_API void _spSetFree (void (*_free) (void* ptr));
SP_API void _spSetRandom(float (*_random) ());
char* _spReadFile (const char* path, int* length);
/*
* Math utilities
*/
float _spMath_random(float min, float max);
float _spMath_randomTriangular(float min, float max);
float _spMath_randomTriangularWith(float min, float max, float mode);
float _spMath_interpolate(float (*apply) (float a), float start, float end, float a);
float _spMath_pow2_apply(float a);
float _spMath_pow2out_apply(float a);
/**/
typedef union _spEventQueueItem {
int type;
spTrackEntry* entry;
spEvent* event;
} _spEventQueueItem;
typedef struct _spAnimationState _spAnimationState;
typedef struct _spEventQueue {
_spAnimationState* state;
_spEventQueueItem* objects;
int objectsCount;
int objectsCapacity;
int /*boolean*/ drainDisabled;
#ifdef __cplusplus
_spEventQueue() :
state(0),
objects(0),
objectsCount(0),
objectsCapacity(0),
drainDisabled(0) {
}
#endif
} _spEventQueue;
struct _spAnimationState {
spAnimationState super;
int eventsCount;
spEvent** events;
_spEventQueue* queue;
int* propertyIDs;
int propertyIDsCount;
int propertyIDsCapacity;
int /*boolean*/ animationsChanged;
#ifdef __cplusplus
_spAnimationState() :
super(),
eventsCount(0),
events(0),
queue(0),
propertyIDs(0),
propertyIDsCount(0),
propertyIDsCapacity(0),
animationsChanged(0) {
}
#endif
};
/**/
/* configureAttachment and disposeAttachment may be 0. */
void _spAttachmentLoader_init (spAttachmentLoader* self,
void (*dispose) (spAttachmentLoader* self),
spAttachment* (*createAttachment) (spAttachmentLoader* self, spSkin* skin, spAttachmentType type, const char* name,
const char* path),
void (*configureAttachment) (spAttachmentLoader* self, spAttachment*),
void (*disposeAttachment) (spAttachmentLoader* self, spAttachment*)
);
void _spAttachmentLoader_deinit (spAttachmentLoader* self);
/* Can only be called from createAttachment. */
void _spAttachmentLoader_setError (spAttachmentLoader* self, const char* error1, const char* error2);
void _spAttachmentLoader_setUnknownTypeError (spAttachmentLoader* self, spAttachmentType type);
#ifdef SPINE_SHORT_NAMES
#define _AttachmentLoader_init(...) _spAttachmentLoader_init(__VA_ARGS__)
#define _AttachmentLoader_deinit(...) _spAttachmentLoader_deinit(__VA_ARGS__)
#define _AttachmentLoader_setError(...) _spAttachmentLoader_setError(__VA_ARGS__)
#define _AttachmentLoader_setUnknownTypeError(...) _spAttachmentLoader_setUnknownTypeError(__VA_ARGS__)
#endif
/**/
void _spAttachment_init (spAttachment* self, const char* name, spAttachmentType type,
void (*dispose) (spAttachment* self), spAttachment* (*copy) (spAttachment* self));
void _spAttachment_deinit (spAttachment* self);
void _spVertexAttachment_init (spVertexAttachment* self);
void _spVertexAttachment_deinit (spVertexAttachment* self);
#ifdef SPINE_SHORT_NAMES
#define _Attachment_init(...) _spAttachment_init(__VA_ARGS__)
#define _Attachment_deinit(...) _spAttachment_deinit(__VA_ARGS__)
#define _VertexAttachment_deinit(...) _spVertexAttachment_deinit(__VA_ARGS__)
#endif
/**/
void _spTimeline_init (spTimeline* self, spTimelineType type,
void (*dispose) (spTimeline* self),
void (*apply) (const spTimeline* self, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents,
int* eventsCount, float alpha, spMixBlend blend, spMixDirection direction),
int (*getPropertyId) (const spTimeline* self));
void _spTimeline_deinit (spTimeline* self);
#ifdef SPINE_SHORT_NAMES
#define _Timeline_init(...) _spTimeline_init(__VA_ARGS__)
#define _Timeline_deinit(...) _spTimeline_deinit(__VA_ARGS__)
#endif
/**/
void _spCurveTimeline_init (spCurveTimeline* self, spTimelineType type, int framesCount,
void (*dispose) (spTimeline* self),
void (*apply) (const spTimeline* self, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents, int* eventsCount, float alpha, spMixBlend blend, spMixDirection direction),
int (*getPropertyId) (const spTimeline* self));
void _spCurveTimeline_deinit (spCurveTimeline* self);
int _spCurveTimeline_binarySearch (float *values, int valuesLength, float target, int step);
#ifdef SPINE_SHORT_NAMES
#define _CurveTimeline_init(...) _spCurveTimeline_init(__VA_ARGS__)
#define _CurveTimeline_deinit(...) _spCurveTimeline_deinit(__VA_ARGS__)
#define _CurveTimeline_binarySearch(...) _spCurveTimeline_binarySearch(__VA_ARGS__)
#endif
#ifdef __cplusplus
}
#endif
// Extension functions needed to integrate raylib
void drawSkeleton(spSkeleton* skeleton, Vector3 position);
Texture2D* texture_2d_create(char *path);
void texture_2d_destroy();
#endif /* SPINE_EXTENSION_H_ */

View File

@ -0,0 +1,62 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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_SPINE_H_
#define SPINE_SPINE_H_
#include <spine/dll.h>
#include <spine/Animation.h>
#include <spine/AnimationState.h>
#include <spine/AnimationStateData.h>
#include <spine/Atlas.h>
#include <spine/AtlasAttachmentLoader.h>
#include <spine/Attachment.h>
#include <spine/AttachmentLoader.h>
#include <spine/Bone.h>
#include <spine/BoneData.h>
#include <spine/RegionAttachment.h>
#include <spine/VertexAttachment.h>
#include <spine/MeshAttachment.h>
#include <spine/BoundingBoxAttachment.h>
#include <spine/ClippingAttachment.h>
#include <spine/PointAttachment.h>
#include <spine/Skeleton.h>
#include <spine/SkeletonBounds.h>
#include <spine/SkeletonData.h>
#include <spine/SkeletonBinary.h>
#include <spine/SkeletonJson.h>
#include <spine/Skin.h>
#include <spine/Slot.h>
#include <spine/SlotData.h>
#include <spine/SkeletonClipping.h>
#include <spine/Event.h>
#include <spine/EventData.h>
#include <spine/VertexEffect.h>
#endif /* SPINE_SPINE_H_ */

View File

@ -0,0 +1,101 @@
/*******************************************************************************************
*
* raylib spine example - Loading and plating a spine animation
*
* This example has been created using raylib 2.5 (www.raylib.com) and Spine Runtime Libraries 3.8
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
* for details about spine, check esoteric software website http://esotericsoftware.com/
*
* Example contributed by WEREMSOFT (@werem) and reviewed by Ramon Santamaria (@raysan5)
*
* Copyright (c) 2020 WEREMSOFT (@werem) and Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "./spine/spine.h"
#include "./spine/extension.h"
#include <stdio.h>
#define SCREEN_WIDTH 800
#define SCREEN_HEIGHT 450
int main()
{
// Initialization
//--------------------------------------------------------------------------------------
InitWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "raylib spine example - basic window");
spAtlas* atlas = {0};
spSkeletonJson* json;
spSkeletonData* skeletonData;
spSkeleton* skeleton;
spAnimationStateData* animationStateData;
spAnimationState* animationState;
// Init spine
atlas = spAtlas_createFromFile("assets/dragon/NewDragon.atlas", 0);
json = spSkeletonJson_create(atlas);
skeletonData = spSkeletonJson_readSkeletonDataFile(json, "assets/dragon/NewDragon.json");
if (!skeletonData) {
printf("%s\n", json->error);
spSkeletonJson_dispose(json);
printf("ERROR!\n");
}
skeleton = spSkeleton_create(skeletonData);
skeleton->scaleX = 0.5;
skeleton->scaleY = 0.5;
// Create the spAnimationStateData
animationStateData = spAnimationStateData_create(skeletonData);
animationState = spAnimationState_create(animationStateData);
// Add the animation "walk" to track 0, without delay, and let it loop indefinitely
int track = 0;
int loop = 1;
float delay = 0;
spAnimationState_addAnimationByName(animationState, track, "flying", loop, delay);
spAnimationState_addAnimationByName(animationState, 0, "flying", 1, 0);
spAnimationState_update(animationState,.0f);
spAnimationState_apply(animationState, skeleton);
spSkeleton_updateWorldTransform(skeleton);
Vector3 skeletonPosition = { SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, 0};
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
spAnimationState_update(animationState, GetFrameTime());
spAnimationState_apply(animationState, skeleton);
spSkeleton_updateWorldTransform(skeleton);
drawSkeleton(skeleton, skeletonPosition);
DrawFPS(10, 10);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
spAtlas_dispose(atlas);
spSkeleton_dispose(skeleton);
texture_2d_destroy(); // Destroy textures loaded by spine
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,150 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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.
*****************************************************************************/
#include <spine/AnimationStateData.h>
#include <spine/extension.h>
typedef struct _ToEntry _ToEntry;
struct _ToEntry {
spAnimation* animation;
float duration;
_ToEntry* next;
};
_ToEntry* _ToEntry_create (spAnimation* to, float duration) {
_ToEntry* self = NEW(_ToEntry);
self->animation = to;
self->duration = duration;
return self;
}
void _ToEntry_dispose (_ToEntry* self) {
FREE(self);
}
/**/
typedef struct _FromEntry _FromEntry;
struct _FromEntry {
spAnimation* animation;
_ToEntry* toEntries;
_FromEntry* next;
};
_FromEntry* _FromEntry_create (spAnimation* from) {
_FromEntry* self = NEW(_FromEntry);
self->animation = from;
return self;
}
void _FromEntry_dispose (_FromEntry* self) {
FREE(self);
}
/**/
spAnimationStateData* spAnimationStateData_create (spSkeletonData* skeletonData) {
spAnimationStateData* self = NEW(spAnimationStateData);
CONST_CAST(spSkeletonData*, self->skeletonData) = skeletonData;
return self;
}
void spAnimationStateData_dispose (spAnimationStateData* self) {
_ToEntry* toEntry;
_ToEntry* nextToEntry;
_FromEntry* nextFromEntry;
_FromEntry* fromEntry = (_FromEntry*)self->entries;
while (fromEntry) {
toEntry = fromEntry->toEntries;
while (toEntry) {
nextToEntry = toEntry->next;
_ToEntry_dispose(toEntry);
toEntry = nextToEntry;
}
nextFromEntry = fromEntry->next;
_FromEntry_dispose(fromEntry);
fromEntry = nextFromEntry;
}
FREE(self);
}
void spAnimationStateData_setMixByName (spAnimationStateData* self, const char* fromName, const char* toName, float duration) {
spAnimation* to;
spAnimation* from = spSkeletonData_findAnimation(self->skeletonData, fromName);
if (!from) return;
to = spSkeletonData_findAnimation(self->skeletonData, toName);
if (!to) return;
spAnimationStateData_setMix(self, from, to, duration);
}
void spAnimationStateData_setMix (spAnimationStateData* self, spAnimation* from, spAnimation* to, float duration) {
/* Find existing FromEntry. */
_ToEntry* toEntry;
_FromEntry* fromEntry = (_FromEntry*)self->entries;
while (fromEntry) {
if (fromEntry->animation == from) {
/* Find existing ToEntry. */
toEntry = fromEntry->toEntries;
while (toEntry) {
if (toEntry->animation == to) {
toEntry->duration = duration;
return;
}
toEntry = toEntry->next;
}
break; /* Add new ToEntry to the existing FromEntry. */
}
fromEntry = fromEntry->next;
}
if (!fromEntry) {
fromEntry = _FromEntry_create(from);
fromEntry->next = (_FromEntry*)self->entries;
CONST_CAST(_FromEntry*, self->entries) = fromEntry;
}
toEntry = _ToEntry_create(to, duration);
toEntry->next = fromEntry->toEntries;
fromEntry->toEntries = toEntry;
}
float spAnimationStateData_getMix (spAnimationStateData* self, spAnimation* from, spAnimation* to) {
_FromEntry* fromEntry = (_FromEntry*)self->entries;
while (fromEntry) {
if (fromEntry->animation == from) {
_ToEntry* toEntry = fromEntry->toEntries;
while (toEntry) {
if (toEntry->animation == to) return toEntry->duration;
toEntry = toEntry->next;
}
}
fromEntry = fromEntry->next;
}
return self->defaultMix;
}

View File

@ -0,0 +1,38 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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.
*****************************************************************************/
#include <spine/Array.h>
#include <spine/extension.h>
_SP_ARRAY_IMPLEMENT_TYPE(spFloatArray, float)
_SP_ARRAY_IMPLEMENT_TYPE(spIntArray, int)
_SP_ARRAY_IMPLEMENT_TYPE(spShortArray, short)
_SP_ARRAY_IMPLEMENT_TYPE(spUnsignedShortArray, unsigned short)
_SP_ARRAY_IMPLEMENT_TYPE(spArrayFloatArray, spFloatArray*)
_SP_ARRAY_IMPLEMENT_TYPE(spArrayShortArray, spShortArray*)

View File

@ -0,0 +1,361 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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.
*****************************************************************************/
#include <spine/Atlas.h>
#include <ctype.h>
#include <spine/extension.h>
spAtlasPage* spAtlasPage_create(spAtlas* atlas, const char* name) {
spAtlasPage* self = NEW(spAtlasPage);
CONST_CAST(spAtlas*, self->atlas) = atlas;
MALLOC_STR(self->name, name);
return self;
}
void spAtlasPage_dispose(spAtlasPage* self) {
_spAtlasPage_disposeTexture(self);
FREE(self->name);
FREE(self);
}
/**/
spAtlasRegion* spAtlasRegion_create() {
return NEW(spAtlasRegion);
}
void spAtlasRegion_dispose(spAtlasRegion* self) {
FREE(self->name);
FREE(self->splits);
FREE(self->pads);
FREE(self);
}
/**/
typedef struct {
const char* begin;
const char* end;
} Str;
static void trim(Str* str) {
while (isspace((unsigned char)*str->begin) && str->begin < str->end)
(str->begin)++;
if (str->begin == str->end) return;
str->end--;
while (((unsigned char)*str->end == '\r') && str->end >= str->begin)
str->end--;
str->end++;
}
/* Tokenize string without modification. Returns 0 on failure. */
static int readLine(const char** begin, const char* end, Str* str) {
if (*begin == end) return 0;
str->begin = *begin;
/* Find next delimiter. */
while (*begin != end && **begin != '\n')
(*begin)++;
str->end = *begin;
trim(str);
if (*begin != end) (*begin)++;
return 1;
}
/* Moves str->begin past the first occurence of c. Returns 0 on failure. */
static int beginPast(Str* str, char c) {
const char* begin = str->begin;
while (1) {
char lastSkippedChar = *begin;
if (begin == str->end) return 0;
begin++;
if (lastSkippedChar == c) break;
}
str->begin = begin;
return 1;
}
/* Returns 0 on failure. */
static int readValue(const char** begin, const char* end, Str* str) {
readLine(begin, end, str);
if (!beginPast(str, ':')) return 0;
trim(str);
return 1;
}
/* Returns the number of tuple values read (1, 2, 4, or 0 for failure). */
static int readTuple(const char** begin, const char* end, Str tuple[]) {
int i;
Str str = { NULL, NULL };
readLine(begin, end, &str);
if (!beginPast(&str, ':')) return 0;
for (i = 0; i < 3; ++i) {
tuple[i].begin = str.begin;
if (!beginPast(&str, ',')) break;
tuple[i].end = str.begin - 2;
trim(&tuple[i]);
}
tuple[i].begin = str.begin;
tuple[i].end = str.end;
trim(&tuple[i]);
return i + 1;
}
static char* mallocString(Str* str) {
int length = (int)(str->end - str->begin);
char* string = MALLOC(char, length + 1);
memcpy(string, str->begin, length);
string[length] = '\0';
return string;
}
static int indexOf(const char** array, int count, Str* str) {
int length = (int)(str->end - str->begin);
int i;
for (i = count - 1; i >= 0; i--)
if (strncmp(array[i], str->begin, length) == 0) return i;
return 0;
}
static int equals(Str* str, const char* other) {
return strncmp(other, str->begin, str->end - str->begin) == 0;
}
static int toInt(Str* str) {
return (int)strtol(str->begin, (char**)&str->end, 10);
}
static spAtlas* abortAtlas(spAtlas* self) {
spAtlas_dispose(self);
return 0;
}
static const char* formatNames[] = { "", "Alpha", "Intensity", "LuminanceAlpha", "RGB565", "RGBA4444", "RGB888", "RGBA8888" };
static const char* textureFilterNames[] = { "", "Nearest", "Linear", "MipMap", "MipMapNearestNearest", "MipMapLinearNearest",
"MipMapNearestLinear", "MipMapLinearLinear" };
spAtlas* spAtlas_create(const char* begin, int length, const char* dir, void* rendererObject) {
spAtlas* self;
int count;
const char* end = begin + length;
int dirLength = (int)strlen(dir);
int needsSlash = dirLength > 0 && dir[dirLength - 1] != '/' && dir[dirLength - 1] != '\\';
spAtlasPage *page = 0;
spAtlasPage *lastPage = 0;
spAtlasRegion *lastRegion = 0;
Str str;
Str tuple[4];
self = NEW(spAtlas);
self->rendererObject = rendererObject;
while (readLine(&begin, end, &str)) {
if (str.end - str.begin == 0)
page = 0;
else if (!page) {
char* name = mallocString(&str);
char* path = MALLOC(char, dirLength + needsSlash + strlen(name) + 1);
memcpy(path, dir, dirLength);
if (needsSlash) path[dirLength] = '/';
strcpy(path + dirLength + needsSlash, name);
page = spAtlasPage_create(self, name);
FREE(name);
if (lastPage)
lastPage->next = page;
else
self->pages = page;
lastPage = page;
switch (readTuple(&begin, end, tuple)) {
case 0:
return abortAtlas(self);
case 2: /* size is only optional for an atlas packed with an old TexturePacker. */
page->width = toInt(tuple);
page->height = toInt(tuple + 1);
if (!readTuple(&begin, end, tuple)) return abortAtlas(self);
}
page->format = (spAtlasFormat)indexOf(formatNames, 8, tuple);
if (!readTuple(&begin, end, tuple)) return abortAtlas(self);
page->minFilter = (spAtlasFilter)indexOf(textureFilterNames, 8, tuple);
page->magFilter = (spAtlasFilter)indexOf(textureFilterNames, 8, tuple + 1);
if (!readValue(&begin, end, &str)) return abortAtlas(self);
page->uWrap = SP_ATLAS_CLAMPTOEDGE;
page->vWrap = SP_ATLAS_CLAMPTOEDGE;
if (!equals(&str, "none")) {
if (str.end - str.begin == 1) {
if (*str.begin == 'x')
page->uWrap = SP_ATLAS_REPEAT;
else if (*str.begin == 'y')
page->vWrap = SP_ATLAS_REPEAT;
}
else if (equals(&str, "xy")) {
page->uWrap = SP_ATLAS_REPEAT;
page->vWrap = SP_ATLAS_REPEAT;
}
}
_spAtlasPage_createTexture(page, path);
FREE(path);
} else {
spAtlasRegion *region = spAtlasRegion_create();
if (lastRegion)
lastRegion->next = region;
else
self->regions = region;
lastRegion = region;
region->page = page;
region->name = mallocString(&str);
if (!readValue(&begin, end, &str)) return abortAtlas(self);
if (equals(&str, "true"))
region->degrees = 90;
else if (equals(&str, "false"))
region->degrees = 0;
else
region->degrees = toInt(&str);
region->rotate = region->degrees == 90;
if (readTuple(&begin, end, tuple) != 2) return abortAtlas(self);
region->x = toInt(tuple);
region->y = toInt(tuple + 1);
if (readTuple(&begin, end, tuple) != 2) return abortAtlas(self);
region->width = toInt(tuple);
region->height = toInt(tuple + 1);
region->u = region->x / (float)page->width;
region->v = region->y / (float)page->height;
if (region->rotate) {
region->u2 = (region->x + region->height) / (float)page->width;
region->v2 = (region->y + region->width) / (float)page->height;
} else {
region->u2 = (region->x + region->width) / (float)page->width;
region->v2 = (region->y + region->height) / (float)page->height;
}
count = readTuple(&begin, end, tuple);
if (!count) return abortAtlas(self);
if (count == 4) { /* split is optional */
region->splits = MALLOC(int, 4);
region->splits[0] = toInt(tuple);
region->splits[1] = toInt(tuple + 1);
region->splits[2] = toInt(tuple + 2);
region->splits[3] = toInt(tuple + 3);
count = readTuple(&begin, end, tuple);
if (!count) return abortAtlas(self);
if (count == 4) { /* pad is optional, but only present with splits */
region->pads = MALLOC(int, 4);
region->pads[0] = toInt(tuple);
region->pads[1] = toInt(tuple + 1);
region->pads[2] = toInt(tuple + 2);
region->pads[3] = toInt(tuple + 3);
if (!readTuple(&begin, end, tuple)) return abortAtlas(self);
}
}
region->originalWidth = toInt(tuple);
region->originalHeight = toInt(tuple + 1);
readTuple(&begin, end, tuple);
region->offsetX = toInt(tuple);
region->offsetY = toInt(tuple + 1);
if (!readValue(&begin, end, &str)) return abortAtlas(self);
region->index = toInt(&str);
}
}
return self;
}
spAtlas* spAtlas_createFromFile(const char* path, void* rendererObject) {
int dirLength;
char *dir;
int length;
const char* data;
spAtlas* atlas = 0;
/* Get directory from atlas path. */
const char* lastForwardSlash = strrchr(path, '/');
const char* lastBackwardSlash = strrchr(path, '\\');
const char* lastSlash = lastForwardSlash > lastBackwardSlash ? lastForwardSlash : lastBackwardSlash;
if (lastSlash == path) lastSlash++; /* Never drop starting slash. */
dirLength = (int)(lastSlash ? lastSlash - path : 0);
dir = MALLOC(char, dirLength + 1);
memcpy(dir, path, dirLength);
dir[dirLength] = '\0';
data = _spUtil_readFile(path, &length);
if (data) atlas = spAtlas_create(data, length, dir, rendererObject);
FREE(data);
FREE(dir);
return atlas;
}
void spAtlas_dispose(spAtlas* self) {
spAtlasRegion* region, *nextRegion;
spAtlasPage* page = self->pages;
while (page) {
spAtlasPage* nextPage = page->next;
spAtlasPage_dispose(page);
page = nextPage;
}
region = self->regions;
while (region) {
nextRegion = region->next;
spAtlasRegion_dispose(region);
region = nextRegion;
}
FREE(self);
}
spAtlasRegion* spAtlas_findRegion(const spAtlas* self, const char* name) {
spAtlasRegion* region = self->regions;
while (region) {
if (strcmp(region->name, name) == 0) return region;
region = region->next;
}
return 0;
}

View File

@ -0,0 +1,100 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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.
*****************************************************************************/
#include <spine/AtlasAttachmentLoader.h>
#include <spine/extension.h>
spAttachment* _spAtlasAttachmentLoader_createAttachment (spAttachmentLoader* loader, spSkin* skin, spAttachmentType type,
const char* name, const char* path) {
spAtlasAttachmentLoader* self = SUB_CAST(spAtlasAttachmentLoader, loader);
switch (type) {
case SP_ATTACHMENT_REGION: {
spRegionAttachment* attachment;
spAtlasRegion* region = spAtlas_findRegion(self->atlas, path);
if (!region) {
_spAttachmentLoader_setError(loader, "Region not found: ", path);
return 0;
}
attachment = spRegionAttachment_create(name);
attachment->rendererObject = region;
spRegionAttachment_setUVs(attachment, region->u, region->v, region->u2, region->v2, region->rotate);
attachment->regionOffsetX = region->offsetX;
attachment->regionOffsetY = region->offsetY;
attachment->regionWidth = region->width;
attachment->regionHeight = region->height;
attachment->regionOriginalWidth = region->originalWidth;
attachment->regionOriginalHeight = region->originalHeight;
return SUPER(attachment);
}
case SP_ATTACHMENT_MESH:
case SP_ATTACHMENT_LINKED_MESH: {
spMeshAttachment* attachment;
spAtlasRegion* region = spAtlas_findRegion(self->atlas, path);
if (!region) {
_spAttachmentLoader_setError(loader, "Region not found: ", path);
return 0;
}
attachment = spMeshAttachment_create(name);
attachment->rendererObject = region;
attachment->regionU = region->u;
attachment->regionV = region->v;
attachment->regionU2 = region->u2;
attachment->regionV2 = region->v2;
attachment->regionRotate = region->rotate;
attachment->regionDegrees = region->degrees;
attachment->regionOffsetX = region->offsetX;
attachment->regionOffsetY = region->offsetY;
attachment->regionWidth = region->width;
attachment->regionHeight = region->height;
attachment->regionOriginalWidth = region->originalWidth;
attachment->regionOriginalHeight = region->originalHeight;
return SUPER(SUPER(attachment));
}
case SP_ATTACHMENT_BOUNDING_BOX:
return SUPER(SUPER(spBoundingBoxAttachment_create(name)));
case SP_ATTACHMENT_PATH:
return SUPER(SUPER(spPathAttachment_create(name)));
case SP_ATTACHMENT_POINT:
return SUPER(spPointAttachment_create(name));
case SP_ATTACHMENT_CLIPPING:
return SUPER(SUPER(spClippingAttachment_create(name)));
default:
_spAttachmentLoader_setUnknownTypeError(loader, type);
return 0;
}
UNUSED(skin);
}
spAtlasAttachmentLoader* spAtlasAttachmentLoader_create (spAtlas* atlas) {
spAtlasAttachmentLoader* self = NEW(spAtlasAttachmentLoader);
_spAttachmentLoader_init(SUPER(self), _spAttachmentLoader_deinit, _spAtlasAttachmentLoader_createAttachment, 0, 0);
self->atlas = atlas;
return self;
}

View File

@ -0,0 +1,64 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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.
*****************************************************************************/
#include <spine/Attachment.h>
#include <spine/extension.h>
#include <spine/Slot.h>
typedef struct _spAttachmentVtable {
void (*dispose) (spAttachment* self);
spAttachment* (*copy) (spAttachment* self);
} _spAttachmentVtable;
void _spAttachment_init (spAttachment* self, const char* name, spAttachmentType type, /**/
void (*dispose) (spAttachment* self), spAttachment* (*copy) (spAttachment* self)) {
CONST_CAST(_spAttachmentVtable*, self->vtable) = NEW(_spAttachmentVtable);
VTABLE(spAttachment, self)->dispose = dispose;
VTABLE(spAttachment, self)->copy = copy;
MALLOC_STR(self->name, name);
CONST_CAST(spAttachmentType, self->type) = type;
}
void _spAttachment_deinit (spAttachment* self) {
if (self->attachmentLoader) spAttachmentLoader_disposeAttachment(self->attachmentLoader, self);
FREE(self->vtable);
FREE(self->name);
}
spAttachment* spAttachment_copy (spAttachment* self) {
return VTABLE(spAttachment, self) ->copy(self);
}
void spAttachment_dispose (spAttachment* self) {
self->refCount--;
if (self->refCount <= 0)
VTABLE(spAttachment, self) ->dispose(self);
}

View File

@ -0,0 +1,96 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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.
*****************************************************************************/
#include <spine/AttachmentLoader.h>
#include <stdio.h>
#include <spine/extension.h>
typedef struct _spAttachmentLoaderVtable {
spAttachment* (*createAttachment) (spAttachmentLoader* self, spSkin* skin, spAttachmentType type, const char* name, const char* path);
void (*configureAttachment) (spAttachmentLoader* self, spAttachment*);
void (*disposeAttachment) (spAttachmentLoader* self, spAttachment*);
void (*dispose) (spAttachmentLoader* self);
} _spAttachmentLoaderVtable;
void _spAttachmentLoader_init (spAttachmentLoader* self,
void (*dispose) (spAttachmentLoader* self),
spAttachment* (*createAttachment) (spAttachmentLoader* self, spSkin* skin, spAttachmentType type, const char* name,
const char* path),
void (*configureAttachment) (spAttachmentLoader* self, spAttachment*),
void (*disposeAttachment) (spAttachmentLoader* self, spAttachment*)
) {
CONST_CAST(_spAttachmentLoaderVtable*, self->vtable) = NEW(_spAttachmentLoaderVtable);
VTABLE(spAttachmentLoader, self)->dispose = dispose;
VTABLE(spAttachmentLoader, self)->createAttachment = createAttachment;
VTABLE(spAttachmentLoader, self)->configureAttachment = configureAttachment;
VTABLE(spAttachmentLoader, self)->disposeAttachment = disposeAttachment;
}
void _spAttachmentLoader_deinit (spAttachmentLoader* self) {
FREE(self->vtable);
FREE(self->error1);
FREE(self->error2);
}
void spAttachmentLoader_dispose (spAttachmentLoader* self) {
VTABLE(spAttachmentLoader, self)->dispose(self);
FREE(self);
}
spAttachment* spAttachmentLoader_createAttachment (spAttachmentLoader* self, spSkin* skin, spAttachmentType type, const char* name,
const char* path) {
FREE(self->error1);
FREE(self->error2);
self->error1 = 0;
self->error2 = 0;
return VTABLE(spAttachmentLoader, self)->createAttachment(self, skin, type, name, path);
}
void spAttachmentLoader_configureAttachment (spAttachmentLoader* self, spAttachment* attachment) {
if (!VTABLE(spAttachmentLoader, self)->configureAttachment) return;
VTABLE(spAttachmentLoader, self)->configureAttachment(self, attachment);
}
void spAttachmentLoader_disposeAttachment (spAttachmentLoader* self, spAttachment* attachment) {
if (!VTABLE(spAttachmentLoader, self)->disposeAttachment) return;
VTABLE(spAttachmentLoader, self)->disposeAttachment(self, attachment);
}
void _spAttachmentLoader_setError (spAttachmentLoader* self, const char* error1, const char* error2) {
FREE(self->error1);
FREE(self->error2);
MALLOC_STR(self->error1, error1);
MALLOC_STR(self->error2, error2);
}
void _spAttachmentLoader_setUnknownTypeError (spAttachmentLoader* self, spAttachmentType type) {
char buffer[16];
sprintf(buffer, "%d", type);
_spAttachmentLoader_setError(self, "Unknown attachment type: ", buffer);
}

View File

@ -0,0 +1,287 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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.
*****************************************************************************/
#include <spine/Bone.h>
#include <spine/extension.h>
#include <stdio.h>
static int yDown;
void spBone_setYDown (int value) {
yDown = value;
}
int spBone_isYDown () {
return yDown;
}
spBone* spBone_create (spBoneData* data, spSkeleton* skeleton, spBone* parent) {
spBone* self = NEW(spBone);
CONST_CAST(spBoneData*, self->data) = data;
CONST_CAST(spSkeleton*, self->skeleton) = skeleton;
CONST_CAST(spBone*, self->parent) = parent;
CONST_CAST(float, self->a) = 1.0f;
CONST_CAST(float, self->d) = 1.0f;
spBone_setToSetupPose(self);
return self;
}
void spBone_dispose (spBone* self) {
FREE(self->children);
FREE(self);
}
void spBone_updateWorldTransform (spBone* self) {
spBone_updateWorldTransformWith(self, self->x, self->y, self->rotation, self->scaleX, self->scaleY, self->shearX, self->shearY);
}
void spBone_updateWorldTransformWith (spBone* self, float x, float y, float rotation, float scaleX, float scaleY, float shearX, float shearY) {
float cosine, sine;
float pa, pb, pc, pd;
spBone* parent = self->parent;
float sx = self->skeleton->scaleX;
float sy = self->skeleton->scaleY * (spBone_isYDown() ? -1 : 1);
self->ax = x;
self->ay = y;
self->arotation = rotation;
self->ascaleX = scaleX;
self->ascaleY = scaleY;
self->ashearX = shearX;
self->ashearY = shearY;
self->appliedValid = 1;
if (!parent) { /* Root bone. */
float rotationY = rotation + 90 + shearY;
CONST_CAST(float, self->a) = COS_DEG(rotation + shearX) * scaleX * sx;
CONST_CAST(float, self->b) = COS_DEG(rotationY) * scaleY * sx;
CONST_CAST(float, self->c) = SIN_DEG(rotation + shearX) * scaleX * sy;
CONST_CAST(float, self->d) = SIN_DEG(rotationY) * scaleY * sy;
CONST_CAST(float, self->worldX) = x * sx + self->skeleton->x;
CONST_CAST(float, self->worldY) = y * sy + self->skeleton->y;
return;
}
pa = parent->a;
pb = parent->b;
pc = parent->c;
pd = parent->d;
CONST_CAST(float, self->worldX) = pa * x + pb * y + parent->worldX;
CONST_CAST(float, self->worldY) = pc * x + pd * y + parent->worldY;
switch (self->data->transformMode) {
case SP_TRANSFORMMODE_NORMAL: {
float rotationY = rotation + 90 + shearY;
float la = COS_DEG(rotation + shearX) * scaleX;
float lb = COS_DEG(rotationY) * scaleY;
float lc = SIN_DEG(rotation + shearX) * scaleX;
float ld = SIN_DEG(rotationY) * scaleY;
CONST_CAST(float, self->a) = pa * la + pb * lc;
CONST_CAST(float, self->b) = pa * lb + pb * ld;
CONST_CAST(float, self->c) = pc * la + pd * lc;
CONST_CAST(float, self->d) = pc * lb + pd * ld;
return;
}
case SP_TRANSFORMMODE_ONLYTRANSLATION: {
float rotationY = rotation + 90 + shearY;
CONST_CAST(float, self->a) = COS_DEG(rotation + shearX) * scaleX;
CONST_CAST(float, self->b) = COS_DEG(rotationY) * scaleY;
CONST_CAST(float, self->c) = SIN_DEG(rotation + shearX) * scaleX;
CONST_CAST(float, self->d) = SIN_DEG(rotationY) * scaleY;
break;
}
case SP_TRANSFORMMODE_NOROTATIONORREFLECTION: {
float s = pa * pa + pc * pc;
float prx, rx, ry, la, lb, lc, ld;
if (s > 0.0001f) {
s = ABS(pa * pd - pb * pc) / s;
pb = pc * s;
pd = pa * s;
prx = ATAN2(pc, pa) * RAD_DEG;
} else {
pa = 0;
pc = 0;
prx = 90 - ATAN2(pd, pb) * RAD_DEG;
}
rx = rotation + shearX - prx;
ry = rotation + shearY - prx + 90;
la = COS_DEG(rx) * scaleX;
lb = COS_DEG(ry) * scaleY;
lc = SIN_DEG(rx) * scaleX;
ld = SIN_DEG(ry) * scaleY;
CONST_CAST(float, self->a) = pa * la - pb * lc;
CONST_CAST(float, self->b) = pa * lb - pb * ld;
CONST_CAST(float, self->c) = pc * la + pd * lc;
CONST_CAST(float, self->d) = pc * lb + pd * ld;
break;
}
case SP_TRANSFORMMODE_NOSCALE:
case SP_TRANSFORMMODE_NOSCALEORREFLECTION: {
float za, zc, s;
float r, zb, zd, la, lb, lc, ld;
cosine = COS_DEG(rotation); sine = SIN_DEG(rotation);
za = (pa * cosine + pb * sine) / sx;
zc = (pc * cosine + pd * sine) / sy;
s = SQRT(za * za + zc * zc);
if (s > 0.00001f) s = 1 / s;
za *= s;
zc *= s;
s = SQRT(za * za + zc * zc);
if (self->data->transformMode == SP_TRANSFORMMODE_NOSCALE && (pa * pd - pb * pc < 0) != (sx < 0 != sy < 0))
s = -s;
r = PI / 2 + ATAN2(zc, za);
zb = COS(r) * s;
zd = SIN(r) * s;
la = COS_DEG(shearX) * scaleX;
lb = COS_DEG(90 + shearY) * scaleY;
lc = SIN_DEG(shearX) * scaleX;
ld = SIN_DEG(90 + shearY) * scaleY;
CONST_CAST(float, self->a) = za * la + zb * lc;
CONST_CAST(float, self->b) = za * lb + zb * ld;
CONST_CAST(float, self->c) = zc * la + zd * lc;
CONST_CAST(float, self->d) = zc * lb + zd * ld;
break;
}
}
CONST_CAST(float, self->a) *= sx;
CONST_CAST(float, self->b) *= sx;
CONST_CAST(float, self->c) *= sy;
CONST_CAST(float, self->d) *= sy;
}
void spBone_setToSetupPose (spBone* self) {
self->x = self->data->x;
self->y = self->data->y;
self->rotation = self->data->rotation;
self->scaleX = self->data->scaleX;
self->scaleY = self->data->scaleY;
self->shearX = self->data->shearX;
self->shearY = self->data->shearY;
}
float spBone_getWorldRotationX (spBone* self) {
return ATAN2(self->c, self->a) * RAD_DEG;
}
float spBone_getWorldRotationY (spBone* self) {
return ATAN2(self->d, self->b) * RAD_DEG;
}
float spBone_getWorldScaleX (spBone* self) {
return SQRT(self->a * self->a + self->c * self->c);
}
float spBone_getWorldScaleY (spBone* self) {
return SQRT(self->b * self->b + self->d * self->d);
}
/** Computes the individual applied transform values from the world transform. This can be useful to perform processing using
* the applied transform after the world transform has been modified directly (eg, by a constraint).
* <p>
* Some information is ambiguous in the world transform, such as -1,-1 scale versus 180 rotation. */
void spBone_updateAppliedTransform (spBone* self) {
spBone* parent = self->parent;
self->appliedValid = 1;
if (!parent) {
self->ax = self->worldX;
self->ay = self->worldY;
self->arotation = ATAN2(self->c, self->a) * RAD_DEG;
self->ascaleX = SQRT(self->a * self->a + self->c * self->c);
self->ascaleY = SQRT(self->b * self->b + self->d * self->d);
self->ashearX = 0;
self->ashearY = ATAN2(self->a * self->b + self->c * self->d, self->a * self->d - self->b * self->c) * RAD_DEG;
} else {
float pa = parent->a, pb = parent->b, pc = parent->c, pd = parent->d;
float pid = 1 / (pa * pd - pb * pc);
float dx = self->worldX - parent->worldX, dy = self->worldY - parent->worldY;
float ia = pid * pd;
float id = pid * pa;
float ib = pid * pb;
float ic = pid * pc;
float ra = ia * self->a - ib * self->c;
float rb = ia * self->b - ib * self->d;
float rc = id * self->c - ic * self->a;
float rd = id * self->d - ic * self->b;
self->ax = (dx * pd * pid - dy * pb * pid);
self->ay = (dy * pa * pid - dx * pc * pid);
self->ashearX = 0;
self->ascaleX = SQRT(ra * ra + rc * rc);
if (self->ascaleX > 0.0001f) {
float det = ra * rd - rb * rc;
self->ascaleY = det / self->ascaleX;
self->ashearY = ATAN2(ra * rb + rc * rd, det) * RAD_DEG;
self->arotation = ATAN2(rc, ra) * RAD_DEG;
} else {
self->ascaleX = 0;
self->ascaleY = SQRT(rb * rb + rd * rd);
self->ashearY = 0;
self->arotation = 90 - ATAN2(rd, rb) * RAD_DEG;
}
}
}
void spBone_worldToLocal (spBone* self, float worldX, float worldY, float* localX, float* localY) {
float a = self->a, b = self->b, c = self->c, d = self->d;
float invDet = 1 / (a * d - b * c);
float x = worldX - self->worldX, y = worldY - self->worldY;
*localX = (x * d * invDet - y * b * invDet);
*localY = (y * a * invDet - x * c * invDet);
}
void spBone_localToWorld (spBone* self, float localX, float localY, float* worldX, float* worldY) {
float x = localX, y = localY;
*worldX = x * self->a + y * self->b + self->worldX;
*worldY = x * self->c + y * self->d + self->worldY;
}
float spBone_worldToLocalRotation (spBone* self, float worldRotation) {
float sine, cosine;
sine = SIN_DEG(worldRotation);
cosine = COS_DEG(worldRotation);
return ATAN2(self->a * sine - self->c * cosine, self->d * cosine - self->b * sine) * RAD_DEG + self->rotation - self->shearX;
}
float spBone_localToWorldRotation (spBone* self, float localRotation) {
float sine, cosine;
localRotation -= self->rotation - self->shearX;
sine = SIN_DEG(localRotation);
cosine = COS_DEG(localRotation);
return ATAN2(cosine * self->c + sine * self->d, cosine * self->a + sine * self->b) * RAD_DEG;
}
void spBone_rotateWorld (spBone* self, float degrees) {
float a = self->a, b = self->b, c = self->c, d = self->d;
float cosine = COS_DEG(degrees), sine = SIN_DEG(degrees);
CONST_CAST(float, self->a) = cosine * a - sine * c;
CONST_CAST(float, self->b) = cosine * b - sine * d;
CONST_CAST(float, self->c) = sine * a + cosine * c;
CONST_CAST(float, self->d) = sine * b + cosine * d;
CONST_CAST(int, self->appliedValid) = 0;
}

View File

@ -0,0 +1,47 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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.
*****************************************************************************/
#include <spine/BoneData.h>
#include <spine/extension.h>
spBoneData* spBoneData_create (int index, const char* name, spBoneData* parent) {
spBoneData* self = NEW(spBoneData);
CONST_CAST(int, self->index) = index;
MALLOC_STR(self->name, name);
CONST_CAST(spBoneData*, self->parent) = parent;
self->scaleX = 1;
self->scaleY = 1;
self->transformMode = SP_TRANSFORMMODE_NORMAL;
return self;
}
void spBoneData_dispose (spBoneData* self) {
FREE(self->name);
FREE(self);
}

View File

@ -0,0 +1,53 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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.
*****************************************************************************/
#include <spine/BoundingBoxAttachment.h>
#include <spine/extension.h>
void _spBoundingBoxAttachment_dispose (spAttachment* attachment) {
spBoundingBoxAttachment* self = SUB_CAST(spBoundingBoxAttachment, attachment);
_spVertexAttachment_deinit(SUPER(self));
FREE(self);
}
spAttachment* _spBoundingBoxAttachment_copy (spAttachment* attachment) {
spBoundingBoxAttachment* copy = spBoundingBoxAttachment_create(attachment->name);
spBoundingBoxAttachment* self = SUB_CAST(spBoundingBoxAttachment, attachment);
spVertexAttachment_copyTo(SUPER(self), SUPER(copy));
return SUPER(SUPER(copy));
}
spBoundingBoxAttachment* spBoundingBoxAttachment_create (const char* name) {
spBoundingBoxAttachment* self = NEW(spBoundingBoxAttachment);
_spVertexAttachment_init(SUPER(self));
_spAttachment_init(SUPER(SUPER(self)), name, SP_ATTACHMENT_BOUNDING_BOX, _spBoundingBoxAttachment_dispose, _spBoundingBoxAttachment_copy);
return self;
}

View File

@ -0,0 +1,55 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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.
*****************************************************************************/
#include <spine/ClippingAttachment.h>
#include <spine/extension.h>
void _spClippingAttachment_dispose (spAttachment* attachment) {
spClippingAttachment* self = SUB_CAST(spClippingAttachment, attachment);
_spVertexAttachment_deinit(SUPER(self));
FREE(self);
}
spAttachment* _spClippingAttachment_copy (spAttachment* attachment) {
spClippingAttachment* copy = spClippingAttachment_create(attachment->name);
spClippingAttachment* self = SUB_CAST(spClippingAttachment, attachment);
spVertexAttachment_copyTo(SUPER(self), SUPER(copy));
copy->endSlot = self->endSlot;
return SUPER(SUPER(copy));
}
spClippingAttachment* spClippingAttachment_create (const char* name) {
spClippingAttachment* self = NEW(spClippingAttachment);
_spVertexAttachment_init(SUPER(self));
_spAttachment_init(SUPER(SUPER(self)), name, SP_ATTACHMENT_CLIPPING, _spClippingAttachment_dispose, _spClippingAttachment_copy);
self->endSlot = 0;
return self;
}

View File

@ -0,0 +1,84 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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.
*****************************************************************************/
#include <spine/Color.h>
#include <spine/extension.h>
spColor* spColor_create() {
return MALLOC(spColor, 1);
}
void spColor_dispose(spColor* self) {
if (self) FREE(self);
}
void spColor_setFromFloats(spColor* self, float r, float g, float b, float a) {
self->r = r;
self->g = g;
self->b = b;
self->a = a;
spColor_clamp(self);
}
void spColor_setFromColor(spColor* self, spColor* otherColor) {
self->r = otherColor->r;
self->g = otherColor->g;
self->b = otherColor->b;
self->a = otherColor->a;
}
void spColor_addColor(spColor* self, spColor* otherColor) {
self->r += otherColor->r;
self->g += otherColor->g;
self->b += otherColor->b;
self->a += otherColor->a;
spColor_clamp(self);
}
void spColor_addFloats(spColor* self, float r, float g, float b, float a) {
self->r += r;
self->g += g;
self->b += b;
self->a += a;
spColor_clamp(self);
}
void spColor_clamp(spColor* self) {
if (self->r < 0) self->r = 0;
else if (self->r > 1) self->r = 1;
if (self->g < 0) self->g = 0;
else if (self->g > 1) self->g = 1;
if (self->b < 0) self->b = 0;
else if (self->b > 1) self->b = 1;
if (self->a < 0) self->a = 0;
else if (self->a > 1) self->a = 1;
}

View File

@ -0,0 +1,43 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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.
*****************************************************************************/
#include <spine/Event.h>
#include <spine/extension.h>
spEvent* spEvent_create (float time, spEventData* data) {
spEvent* self = NEW(spEvent);
CONST_CAST(spEventData*, self->data) = data;
CONST_CAST(float, self->time) = time;
return self;
}
void spEvent_dispose (spEvent* self) {
FREE(self->stringValue);
FREE(self);
}

View File

@ -0,0 +1,44 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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.
*****************************************************************************/
#include <spine/EventData.h>
#include <spine/extension.h>
spEventData* spEventData_create (const char* name) {
spEventData* self = NEW(spEventData);
MALLOC_STR(self->name, name);
return self;
}
void spEventData_dispose (spEventData* self) {
FREE(self->audioPath);
FREE(self->stringValue);
FREE(self->name);
FREE(self);
}

View File

@ -0,0 +1,275 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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.
*****************************************************************************/
#include <spine/IkConstraint.h>
#include <spine/Skeleton.h>
#include <spine/extension.h>
#include <float.h>
spIkConstraint *spIkConstraint_create(spIkConstraintData *data, const spSkeleton *skeleton) {
int i;
spIkConstraint *self = NEW(spIkConstraint);
CONST_CAST(spIkConstraintData*, self->data) = data;
self->bendDirection = data->bendDirection;
self->compress = data->compress;
self->stretch = data->stretch;
self->mix = data->mix;
self->softness = data->softness;
self->bonesCount = self->data->bonesCount;
self->bones = MALLOC(spBone*, self->bonesCount);
for (i = 0; i < self->bonesCount; ++i)
self->bones[i] = spSkeleton_findBone(skeleton, self->data->bones[i]->name);
self->target = spSkeleton_findBone(skeleton, self->data->target->name);
return self;
}
void spIkConstraint_dispose(spIkConstraint *self) {
FREE(self->bones);
FREE(self);
}
void spIkConstraint_apply(spIkConstraint *self) {
switch (self->bonesCount) {
case 1:
spIkConstraint_apply1(self->bones[0], self->target->worldX, self->target->worldY, self->compress, self->stretch, self->data->uniform, self->mix);
break;
case 2:
spIkConstraint_apply2(self->bones[0], self->bones[1], self->target->worldX, self->target->worldY, self->bendDirection, self->stretch, self->softness, self->mix);
break;
}
}
void spIkConstraint_apply1 (spBone* bone, float targetX, float targetY, int /*boolean*/ compress, int /*boolean*/ stretch, int /*boolean*/ uniform, float alpha) {
spBone* p = bone->parent;
float pa = p->a, pb = p->b, pc = p->c, pd = p->d;
float rotationIK = -bone->ashearX - bone->arotation;
float tx = 0, ty = 0, sx = 0, sy = 0, s = 0;
if (!bone->appliedValid) spBone_updateAppliedTransform(bone);
switch(bone->data->transformMode) {
case SP_TRANSFORMMODE_ONLYTRANSLATION:
tx = targetX - bone->worldX;
ty = targetY - bone->worldY;
break;
case SP_TRANSFORMMODE_NOROTATIONORREFLECTION: {
float ps;
rotationIK += ATAN2(pc, pa) * RAD_DEG;
ps = ABS(pa * pd - pb * pc) / (pa * pa + pc * pc);
pb = -pc * ps;
pd = pa * ps;
}
default: {
float x = targetX - p->worldX, y = targetY - p->worldY;
float d = pa * pd - pb * pc;
tx = (x * pd - y * pb) / d - bone->ax;
ty = (y * pa - x * pc) / d - bone->ay;
}
}
rotationIK += ATAN2(ty, tx) * RAD_DEG;
if (bone->ascaleX < 0) rotationIK += 180;
if (rotationIK > 180) rotationIK -= 360;
else if (rotationIK < -180) rotationIK += 360;
sx = bone->ascaleX;
sy = bone->ascaleY;
if (compress || stretch) {
float b, dd;
switch(bone->data->transformMode) {
case SP_TRANSFORMMODE_NOSCALE:
case SP_TRANSFORMMODE_NOSCALEORREFLECTION:
tx = targetX - bone->worldX;
ty = targetY - bone->worldY;
default: ;
}
b = bone->data->length * sx, dd = SQRT(tx * tx + ty * ty);
if ((compress && dd < b) || ((stretch && dd > b) && (b > 0.0001f))) {
s = (dd / b - 1) * alpha + 1;
sx *= s;
if (uniform) sy *= s;
}
}
spBone_updateWorldTransformWith(bone, bone->ax, bone->ay, bone->arotation + rotationIK * alpha, sx,
sy, bone->ashearX, bone->ashearY);
}
void spIkConstraint_apply2 (spBone* parent, spBone* child, float targetX, float targetY, int bendDir, int /*boolean*/ stretch, float softness, float alpha) {
float a, b, c, d;
float px, py, psx, sx, psy;
float cx, cy, csx, cwx, cwy;
int o1, o2, s2, u;
spBone* pp = parent->parent;
float tx, ty, dd, dx, dy, l1, l2, a1, a2, r, td, sd, p;
float id, x, y;
float aa, bb, ll, ta, c0, c1, c2;
if (alpha == 0) {
spBone_updateWorldTransform(child);
return;
}
if (!parent->appliedValid) spBone_updateAppliedTransform(parent);
if (!child->appliedValid) spBone_updateAppliedTransform(child);
px = parent->ax; py = parent->ay; psx = parent->ascaleX; sx = psx; psy = parent->ascaleY; csx = child->ascaleX;
if (psx < 0) {
psx = -psx;
o1 = 180;
s2 = -1;
} else {
o1 = 0;
s2 = 1;
}
if (psy < 0) {
psy = -psy;
s2 = -s2;
}
if (csx < 0) {
csx = -csx;
o2 = 180;
} else
o2 = 0;
r = psx - psy;
cx = child->ax;
u = (r < 0 ? -r : r) <= 0.0001f;
if (!u) {
cy = 0;
cwx = parent->a * cx + parent->worldX;
cwy = parent->c * cx + parent->worldY;
} else {
cy = child->ay;
cwx = parent->a * cx + parent->b * cy + parent->worldX;
cwy = parent->c * cx + parent->d * cy + parent->worldY;
}
a = pp->a;
b = pp->b;
c = pp->c;
d = pp->d;
id = 1 / (a * d - b * c);
x = cwx - pp->worldX;
y = cwy - pp->worldY;
dx = (x * d - y * b) * id - px;
dy = (y * a - x * c) * id - py;
l1 = SQRT(dx * dx + dy * dy);
l2 = child->data->length * csx;
if (l1 < 0.0001) {
spIkConstraint_apply1(parent, targetX, targetY, 0, stretch, 0, alpha);
spBone_updateWorldTransformWith(child, cx, cy, 0, child->ascaleX, child->ascaleY, child->ashearX, child->ashearY);
return;
}
x = targetX - pp->worldX;
y = targetY - pp->worldY;
tx = (x * d - y * b) * id - px;
ty = (y * a - x * c) * id - py;
dd = tx * tx + ty * ty;
if (softness != 0) {
softness *= psx * (csx + 1) / 2;
td = SQRT(dd);
sd = td - l1 - l2 * psx + softness;
if (sd > 0) {
p = MIN(1, sd / (softness * 2)) - 1;
p = (sd - softness * (1 - p * p)) / td;
tx -= p * tx;
ty -= p * ty;
dd = tx * tx + ty * ty;
}
}
if (u) {
float cosine;
l2 *= psx;
cosine = (dd - l1 * l1 - l2 * l2) / (2 * l1 * l2);
if (cosine < -1) cosine = -1;
else if (cosine > 1) {
cosine = 1;
if (stretch) sx *= (SQRT(dd) / (l1 + l2) - 1) * alpha + 1;
}
a2 = ACOS(cosine) * bendDir;
a = l1 + l2 * cosine;
b = l2 * SIN(a2);
a1 = ATAN2(ty * a - tx * b, tx * a + ty * b);
} else {
a = psx * l2; b = psy * l2;
aa = a * a, bb = b * b, ll = l1 * l1, ta = ATAN2(ty, tx);
c0 = bb * ll + aa * dd - aa * bb, c1 = -2 * bb * l1, c2 = bb - aa;
d = c1 * c1 - 4 * c2 * c0;
if (d >= 0) {
float q = SQRT(d), r0, r1;
if (c1 < 0) q = -q;
q = -(c1 + q) / 2;
r0 = q / c2; r1 = c0 / q;
r = ABS(r0) < ABS(r1) ? r0 : r1;
if (r * r <= dd) {
y = SQRT(dd - r * r) * bendDir;
a1 = ta - ATAN2(y, r);
a2 = ATAN2(y / psy, (r - l1) / psx);
goto break_outer;
}
}
{
float minAngle = PI, minX = l1 - a, minDist = minX * minX, minY = 0;
float maxAngle = 0, maxX = l1 + a, maxDist = maxX * maxX, maxY = 0;
c0 = -a * l1 / (aa - bb);
if (c0 >= -1 && c0 <= 1) {
c0 = ACOS(c0);
x = a * COS(c0) + l1;
y = b * SIN(c0);
d = x * x + y * y;
if (d < minDist) {
minAngle = c0;
minDist = d;
minX = x;
minY = y;
}
if (d > maxDist) {
maxAngle = c0;
maxDist = d;
maxX = x;
maxY = y;
}
}
if (dd <= (minDist + maxDist) / 2) {
a1 = ta - ATAN2(minY * bendDir, minX);
a2 = minAngle * bendDir;
} else {
a1 = ta - ATAN2(maxY * bendDir, maxX);
a2 = maxAngle * bendDir;
}
}
}
break_outer: {
float os = ATAN2(cy, cx) * s2;
a1 = (a1 - os) * RAD_DEG + o1 - parent->arotation;
if (a1 > 180) a1 -= 360;
else if (a1 < -180) a1 += 360;
spBone_updateWorldTransformWith(parent, px, py, parent->rotation + a1 * alpha, sx, parent->ascaleY, 0, 0);
a2 = ((a2 + os) * RAD_DEG - child->ashearX) * s2 + o2 - child->arotation;
if (a2 > 180) a2 -= 360;
else if (a2 < -180) a2 += 360;
spBone_updateWorldTransformWith(child, cx, cy, child->arotation + a2 * alpha, child->ascaleX, child->ascaleY, child->ashearX, child->ashearY);
}
}

View File

@ -0,0 +1,48 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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.
*****************************************************************************/
#include <spine/IkConstraintData.h>
#include <spine/extension.h>
spIkConstraintData* spIkConstraintData_create (const char* name) {
spIkConstraintData* self = NEW(spIkConstraintData);
MALLOC_STR(self->name, name);
self->bendDirection = 1;
self->compress = 0;
self->stretch = 0;
self->uniform = 0;
self->mix = 1;
return self;
}
void spIkConstraintData_dispose (spIkConstraintData* self) {
FREE(self->name);
FREE(self->bones);
FREE(self);
}

View File

@ -0,0 +1,461 @@
/*
Copyright (c) 2009, Dave Gamble
Copyright (c) 2013, Esoteric Software
Permission is hereby granted, dispose of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
/* Json */
/* JSON parser in C. */
#ifndef _DEFAULT_SOURCE
/* Bring strings.h definitions into string.h, where appropriate */
#define _DEFAULT_SOURCE
#endif
#ifndef _BSD_SOURCE
/* Bring strings.h definitions into string.h, where appropriate */
#define _BSD_SOURCE
#endif
#include "Json.h"
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h> /* strtod (C89), strtof (C99) */
#include <string.h> /* strcasecmp (4.4BSD - compatibility), _stricmp (_WIN32) */
#include <spine/extension.h>
#ifndef SPINE_JSON_DEBUG
/* Define this to do extra NULL and expected-character checking */
#define SPINE_JSON_DEBUG 0
#endif
static const char* ep;
const char* Json_getError (void) {
return ep;
}
static int Json_strcasecmp (const char* s1, const char* s2) {
/* TODO we may be able to elide these NULL checks if we can prove
the graph and input (only callsite is Json_getItem) should not have NULLs */
if (s1 && s2) {
#if defined(_WIN32)
return _stricmp(s1, s2);
#else
return strcasecmp( s1, s2 );
#endif
} else {
if (s1 < s2)
return -1; /* s1 is null, s2 is not */
else if (s1 == s2)
return 0; /* both are null */
else
return 1; /* s2 is nul s1 is not */
}
}
/* Internal constructor. */
static Json *Json_new (void) {
return (Json*)CALLOC(Json, 1);
}
/* Delete a Json structure. */
void Json_dispose (Json *c) {
Json *next;
while (c) {
next = c->next;
if (c->child) Json_dispose(c->child);
if (c->valueString) FREE(c->valueString);
if (c->name) FREE(c->name);
FREE(c);
c = next;
}
}
/* Parse the input text to generate a number, and populate the result into item. */
static const char* parse_number (Json *item, const char* num) {
double result = 0.0;
int negative = 0;
char* ptr = (char*)num;
if (*ptr == '-') {
negative = -1;
++ptr;
}
while (*ptr >= '0' && *ptr <= '9') {
result = result * 10.0 + (*ptr - '0');
++ptr;
}
if (*ptr == '.') {
double fraction = 0.0;
int n = 0;
++ptr;
while (*ptr >= '0' && *ptr <= '9') {
fraction = (fraction * 10.0) + (*ptr - '0');
++ptr;
++n;
}
result += fraction / POW(10.0, n);
}
if (negative) result = -result;
if (*ptr == 'e' || *ptr == 'E') {
double exponent = 0;
int expNegative = 0;
int n = 0;
++ptr;
if (*ptr == '-') {
expNegative = -1;
++ptr;
} else if (*ptr == '+') {
++ptr;
}
while (*ptr >= '0' && *ptr <= '9') {
exponent = (exponent * 10.0) + (*ptr - '0');
++ptr;
++n;
}
if (expNegative)
result = result / POW(10, exponent);
else
result = result * POW(10, exponent);
}
if (ptr != num) {
/* Parse success, number found. */
item->valueFloat = (float)result;
item->valueInt = (int)result;
item->type = Json_Number;
return ptr;
} else {
/* Parse failure, ep is set. */
ep = num;
return 0;
}
}
/* Parse the input text into an unescaped cstring, and populate item. */
static const unsigned char firstByteMark[7] = {0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC};
static const char* parse_string (Json *item, const char* str) {
const char* ptr = str + 1;
char* ptr2;
char* out;
int len = 0;
unsigned uc, uc2;
if (*str != '\"') { /* TODO: don't need this check when called from parse_value, but do need from parse_object */
ep = str;
return 0;
} /* not a string! */
while (*ptr != '\"' && *ptr && ++len)
if (*ptr++ == '\\') ptr++; /* Skip escaped quotes. */
out = MALLOC(char, len + 1); /* The length needed for the string, roughly. */
if (!out) return 0;
ptr = str + 1;
ptr2 = out;
while (*ptr != '\"' && *ptr) {
if (*ptr != '\\')
*ptr2++ = *ptr++;
else {
ptr++;
switch (*ptr) {
case 'b':
*ptr2++ = '\b';
break;
case 'f':
*ptr2++ = '\f';
break;
case 'n':
*ptr2++ = '\n';
break;
case 'r':
*ptr2++ = '\r';
break;
case 't':
*ptr2++ = '\t';
break;
case 'u': /* transcode utf16 to utf8. */
sscanf(ptr + 1, "%4x", &uc);
ptr += 4; /* get the unicode char. */
if ((uc >= 0xDC00 && uc <= 0xDFFF) || uc == 0) break; /* check for invalid. */
/* TODO provide an option to ignore surrogates, use unicode replacement character? */
if (uc >= 0xD800 && uc <= 0xDBFF) /* UTF16 surrogate pairs. */
{
if (ptr[1] != '\\' || ptr[2] != 'u') break; /* missing second-half of surrogate. */
sscanf(ptr + 3, "%4x", &uc2);
ptr += 6;
if (uc2 < 0xDC00 || uc2 > 0xDFFF) break; /* invalid second-half of surrogate. */
uc = 0x10000 + (((uc & 0x3FF) << 10) | (uc2 & 0x3FF));
}
len = 4;
if (uc < 0x80)
len = 1;
else if (uc < 0x800)
len = 2;
else if (uc < 0x10000) len = 3;
ptr2 += len;
switch (len) {
case 4:
*--ptr2 = ((uc | 0x80) & 0xBF);
uc >>= 6;
/* fallthrough */
case 3:
*--ptr2 = ((uc | 0x80) & 0xBF);
uc >>= 6;
/* fallthrough */
case 2:
*--ptr2 = ((uc | 0x80) & 0xBF);
uc >>= 6;
/* fallthrough */
case 1:
*--ptr2 = (uc | firstByteMark[len]);
}
ptr2 += len;
break;
default:
*ptr2++ = *ptr;
break;
}
ptr++;
}
}
*ptr2 = 0;
if (*ptr == '\"') ptr++; /* TODO error handling if not \" or \0 ? */
item->valueString = out;
item->type = Json_String;
return ptr;
}
/* Predeclare these prototypes. */
static const char* parse_value (Json *item, const char* value);
static const char* parse_array (Json *item, const char* value);
static const char* parse_object (Json *item, const char* value);
/* Utility to jump whitespace and cr/lf */
static const char* skip (const char* in) {
if (!in) return 0; /* must propagate NULL since it's often called in skip(f(...)) form */
while (*in && (unsigned char)*in <= 32)
in++;
return in;
}
/* Parse an object - create a new root, and populate. */
Json *Json_create (const char* value) {
Json *c;
ep = 0;
if (!value) return 0; /* only place we check for NULL other than skip() */
c = Json_new();
if (!c) return 0; /* memory fail */
value = parse_value(c, skip(value));
if (!value) {
Json_dispose(c);
return 0;
} /* parse failure. ep is set. */
return c;
}
/* Parser core - when encountering text, process appropriately. */
static const char* parse_value (Json *item, const char* value) {
/* Referenced by Json_create(), parse_array(), and parse_object(). */
/* Always called with the result of skip(). */
#if SPINE_JSON_DEBUG /* Checked at entry to graph, Json_create, and after every parse_ call. */
if (!value) return 0; /* Fail on null. */
#endif
switch (*value) {
case 'n': {
if (!strncmp(value + 1, "ull", 3)) {
item->type = Json_NULL;
return value + 4;
}
break;
}
case 'f': {
if (!strncmp(value + 1, "alse", 4)) {
item->type = Json_False;
/* calloc prevents us needing item->type = Json_False or valueInt = 0 here */
return value + 5;
}
break;
}
case 't': {
if (!strncmp(value + 1, "rue", 3)) {
item->type = Json_True;
item->valueInt = 1;
return value + 4;
}
break;
}
case '\"':
return parse_string(item, value);
case '[':
return parse_array(item, value);
case '{':
return parse_object(item, value);
case '-': /* fallthrough */
case '0': /* fallthrough */
case '1': /* fallthrough */
case '2': /* fallthrough */
case '3': /* fallthrough */
case '4': /* fallthrough */
case '5': /* fallthrough */
case '6': /* fallthrough */
case '7': /* fallthrough */
case '8': /* fallthrough */
case '9':
return parse_number(item, value);
default:
break;
}
ep = value;
return 0; /* failure. */
}
/* Build an array from input text. */
static const char* parse_array (Json *item, const char* value) {
Json *child;
#if SPINE_JSON_DEBUG /* unnecessary, only callsite (parse_value) verifies this */
if (*value != '[') {
ep = value;
return 0;
} /* not an array! */
#endif
item->type = Json_Array;
value = skip(value + 1);
if (*value == ']') return value + 1; /* empty array. */
item->child = child = Json_new();
if (!item->child) return 0; /* memory fail */
value = skip(parse_value(child, skip(value))); /* skip any spacing, get the value. */
if (!value) return 0;
item->size = 1;
while (*value == ',') {
Json *new_item = Json_new();
if (!new_item) return 0; /* memory fail */
child->next = new_item;
#if SPINE_JSON_HAVE_PREV
new_item->prev = child;
#endif
child = new_item;
value = skip(parse_value(child, skip(value + 1)));
if (!value) return 0; /* parse fail */
item->size++;
}
if (*value == ']') return value + 1; /* end of array */
ep = value;
return 0; /* malformed. */
}
/* Build an object from the text. */
static const char* parse_object (Json *item, const char* value) {
Json *child;
#if SPINE_JSON_DEBUG /* unnecessary, only callsite (parse_value) verifies this */
if (*value != '{') {
ep = value;
return 0;
} /* not an object! */
#endif
item->type = Json_Object;
value = skip(value + 1);
if (*value == '}') return value + 1; /* empty array. */
item->child = child = Json_new();
if (!item->child) return 0;
value = skip(parse_string(child, skip(value)));
if (!value) return 0;
child->name = child->valueString;
child->valueString = 0;
if (*value != ':') {
ep = value;
return 0;
} /* fail! */
value = skip(parse_value(child, skip(value + 1))); /* skip any spacing, get the value. */
if (!value) return 0;
item->size = 1;
while (*value == ',') {
Json *new_item = Json_new();
if (!new_item) return 0; /* memory fail */
child->next = new_item;
#if SPINE_JSON_HAVE_PREV
new_item->prev = child;
#endif
child = new_item;
value = skip(parse_string(child, skip(value + 1)));
if (!value) return 0;
child->name = child->valueString;
child->valueString = 0;
if (*value != ':') {
ep = value;
return 0;
} /* fail! */
value = skip(parse_value(child, skip(value + 1))); /* skip any spacing, get the value. */
if (!value) return 0;
item->size++;
}
if (*value == '}') return value + 1; /* end of array */
ep = value;
return 0; /* malformed. */
}
Json *Json_getItem (Json *object, const char* string) {
Json *c = object->child;
while (c && Json_strcasecmp(c->name, string))
c = c->next;
return c;
}
const char* Json_getString (Json* object, const char* name, const char* defaultValue) {
object = Json_getItem(object, name);
if (object) return object->valueString;
return defaultValue;
}
float Json_getFloat (Json* value, const char* name, float defaultValue) {
value = Json_getItem(value, name);
return value ? value->valueFloat : defaultValue;
}
int Json_getInt (Json* value, const char* name, int defaultValue) {
value = Json_getItem(value, name);
return value ? value->valueInt : defaultValue;
}

View File

@ -0,0 +1,83 @@
/*
Copyright (c) 2009 Dave Gamble
Permission is hereby granted, dispose of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
/* Esoteric Software: Removed everything except parsing, shorter method names, more get methods, double to float, formatted. */
#ifndef SPINE_JSON_H_
#define SPINE_JSON_H_
#ifdef __cplusplus
extern "C" {
#endif
/* Json Types: */
#define Json_False 0
#define Json_True 1
#define Json_NULL 2
#define Json_Number 3
#define Json_String 4
#define Json_Array 5
#define Json_Object 6
#ifndef SPINE_JSON_HAVE_PREV
/* Spine doesn't use the "prev" link in the Json sibling lists. */
#define SPINE_JSON_HAVE_PREV 0
#endif
/* The Json structure: */
typedef struct Json {
struct Json* next;
#if SPINE_JSON_HAVE_PREV
struct Json* prev; /* next/prev allow you to walk array/object chains. Alternatively, use getSize/getItem */
#endif
struct 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. */
} Json;
/* Supply a block of JSON, and this returns a Json object you can interrogate. Call Json_dispose when finished. */
Json* Json_create (const char* value);
/* Delete a Json entity and all subentities. */
void Json_dispose (Json* json);
/* Get item "string" from object. Case insensitive. */
Json* Json_getItem (Json* json, const char* string);
const char* Json_getString (Json* json, const char* name, const char* defaultValue);
float Json_getFloat (Json* json, const char* name, float defaultValue);
int Json_getInt (Json* json, const char* name, int 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. */
const char* Json_getError (void);
#ifdef __cplusplus
}
#endif
#endif /* SPINE_JSON_H_ */

View File

@ -0,0 +1,211 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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.
*****************************************************************************/
#include <spine/MeshAttachment.h>
#include <spine/extension.h>
#include <stdio.h>
void _spMeshAttachment_dispose (spAttachment* attachment) {
spMeshAttachment* self = SUB_CAST(spMeshAttachment, attachment);
FREE(self->path);
FREE(self->uvs);
if (!self->parentMesh) {
_spVertexAttachment_deinit(SUPER(self));
FREE(self->regionUVs);
FREE(self->triangles);
FREE(self->edges);
} else
_spAttachment_deinit(attachment);
FREE(self);
}
spAttachment* _spMeshAttachment_copy (spAttachment* attachment) {
spMeshAttachment* copy;
spMeshAttachment* self = SUB_CAST(spMeshAttachment, attachment);
if (self->parentMesh)
return SUPER(SUPER(spMeshAttachment_newLinkedMesh(self)));
copy = spMeshAttachment_create(attachment->name);
copy->rendererObject = self->rendererObject;
copy->regionU = self->regionU;
copy->regionV = self->regionV;
copy->regionU2 = self->regionU2;
copy->regionV2 = self->regionV2;
copy->regionRotate = self->regionRotate;
copy->regionDegrees = self->regionDegrees;
copy->regionOffsetX = self->regionOffsetX;
copy->regionOffsetY = self->regionOffsetY;
copy->regionWidth = self->regionWidth;
copy->regionHeight = self->regionHeight;
copy->regionOriginalWidth = self->regionOriginalWidth;
copy->regionOriginalHeight = self->regionOriginalHeight;
MALLOC_STR(copy->path, self->path);
spColor_setFromColor(&copy->color, &self->color);
spVertexAttachment_copyTo(SUPER(self), SUPER(copy));
copy->regionUVs = MALLOC(float, SUPER(self)->worldVerticesLength);
memcpy(copy->regionUVs, self->regionUVs, SUPER(self)->worldVerticesLength * sizeof(float));
copy->uvs = MALLOC(float, SUPER(self)->worldVerticesLength);
memcpy(copy->uvs, self->uvs, SUPER(self)->worldVerticesLength * sizeof(float));
copy->trianglesCount = self->trianglesCount;
copy->triangles = MALLOC(unsigned short, self->trianglesCount);
memcpy(copy->triangles, self->triangles, self->trianglesCount * sizeof(short));
copy->hullLength = self->hullLength;
if (self->edgesCount > 0) {
copy->edgesCount = self->edgesCount;
copy->edges = MALLOC(int, self->edgesCount);
memcpy(copy->edges, self->edges, self->edgesCount * sizeof(int));
}
copy->width = self->width;
copy->height = self->height;
return SUPER(SUPER(copy));
}
spMeshAttachment* spMeshAttachment_newLinkedMesh (spMeshAttachment* self) {
spMeshAttachment* copy = spMeshAttachment_create(self->super.super.name);
copy->rendererObject = self->rendererObject;
copy->regionU = self->regionU;
copy->regionV = self->regionV;
copy->regionU2 = self->regionU2;
copy->regionV2 = self->regionV2;
copy->regionRotate = self->regionRotate;
copy->regionDegrees = self->regionDegrees;
copy->regionOffsetX = self->regionOffsetX;
copy->regionOffsetY = self->regionOffsetY;
copy->regionWidth = self->regionWidth;
copy->regionHeight = self->regionHeight;
copy->regionOriginalWidth = self->regionOriginalWidth;
copy->regionOriginalHeight = self->regionOriginalHeight;
MALLOC_STR(copy->path, self->path);
spColor_setFromColor(&copy->color, &self->color);
copy->super.deformAttachment = self->super.deformAttachment;
spMeshAttachment_setParentMesh(copy, self->parentMesh ? self->parentMesh : self);
spMeshAttachment_updateUVs(copy);
return copy;
}
spMeshAttachment* spMeshAttachment_create (const char* name) {
spMeshAttachment* self = NEW(spMeshAttachment);
_spVertexAttachment_init(SUPER(self));
spColor_setFromFloats(&self->color, 1, 1, 1, 1);
_spAttachment_init(SUPER(SUPER(self)), name, SP_ATTACHMENT_MESH, _spMeshAttachment_dispose, _spMeshAttachment_copy);
return self;
}
void spMeshAttachment_updateUVs (spMeshAttachment* self) {
int i, n;
float* uvs;
float u, v, width, height;
int verticesLength = SUPER(self)->worldVerticesLength;
FREE(self->uvs);
uvs = self->uvs = MALLOC(float, verticesLength);
n = verticesLength;
u = self->regionU; v = self->regionV;
switch (self->regionDegrees) {
case 90: {
float textureWidth = self->regionHeight / (self->regionU2 - self->regionU);
float textureHeight = self->regionWidth / (self->regionV2 - self->regionV);
u -= (self->regionOriginalHeight - self->regionOffsetY - self->regionHeight) / textureWidth;
v -= (self->regionOriginalWidth - self->regionOffsetX - self->regionWidth) / textureHeight;
width = self->regionOriginalHeight / textureWidth;
height = self->regionOriginalWidth / textureHeight;
for (i = 0; i < n; i += 2) {
uvs[i] = u + self->regionUVs[i + 1] * width;
uvs[i + 1] = v + (1 - self->regionUVs[i]) * height;
}
return;
}
case 180: {
float textureWidth = self->regionWidth / (self->regionU2 - self->regionU);
float textureHeight = self->regionHeight / (self->regionV2 - self->regionV);
u -= (self->regionOriginalWidth - self->regionOffsetX - self->regionWidth) / textureWidth;
v -= self->regionOffsetY / textureHeight;
width = self->regionOriginalWidth / textureWidth;
height = self->regionOriginalHeight / textureHeight;
for (i = 0; i < n; i += 2) {
uvs[i] = u + (1 - self->regionUVs[i]) * width;
uvs[i + 1] = v + (1 - self->regionUVs[i + 1]) * height;
}
return;
}
case 270: {
float textureHeight = self->regionHeight / (self->regionV2 - self->regionV);
float textureWidth = self->regionWidth / (self->regionU2 - self->regionU);
u -= self->regionOffsetY / textureWidth;
v -= self->regionOffsetX / textureHeight;
width = self->regionOriginalHeight / textureWidth;
height = self->regionOriginalWidth / textureHeight;
for (i = 0; i < n; i += 2) {
uvs[i] = u + (1 - self->regionUVs[i + 1]) * width;
uvs[i + 1] = v + self->regionUVs[i] * height;
}
return;
}
default: {
float textureWidth = self->regionWidth / (self->regionU2 - self->regionU);
float textureHeight = self->regionHeight / (self->regionV2 - self->regionV);
u -= self->regionOffsetX / textureWidth;
v -= (self->regionOriginalHeight - self->regionOffsetY - self->regionHeight) / textureHeight;
width = self->regionOriginalWidth / textureWidth;
height = self->regionOriginalHeight / textureHeight;
for (i = 0; i < n; i += 2) {
uvs[i] = u + self->regionUVs[i] * width;
uvs[i + 1] = v + self->regionUVs[i + 1] * height;
}
}
}
}
void spMeshAttachment_setParentMesh (spMeshAttachment* self, spMeshAttachment* parentMesh) {
CONST_CAST(spMeshAttachment*, self->parentMesh) = parentMesh;
if (parentMesh) {
self->super.bones = parentMesh->super.bones;
self->super.bonesCount = parentMesh->super.bonesCount;
self->super.vertices = parentMesh->super.vertices;
self->super.verticesCount = parentMesh->super.verticesCount;
self->regionUVs = parentMesh->regionUVs;
self->triangles = parentMesh->triangles;
self->trianglesCount = parentMesh->trianglesCount;
self->hullLength = parentMesh->hullLength;
self->super.worldVerticesLength = parentMesh->super.worldVerticesLength;
self->edges = parentMesh->edges;
self->edgesCount = parentMesh->edgesCount;
self->width = parentMesh->width;
self->height = parentMesh->height;
}
}

View File

@ -0,0 +1,59 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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.
*****************************************************************************/
#include <spine/PathAttachment.h>
#include <spine/extension.h>
void _spPathAttachment_dispose (spAttachment* attachment) {
spPathAttachment* self = SUB_CAST(spPathAttachment, attachment);
_spVertexAttachment_deinit(SUPER(self));
FREE(self->lengths);
FREE(self);
}
spAttachment* _spPathAttachment_copy (spAttachment* attachment) {
spPathAttachment* copy = spPathAttachment_create(attachment->name);
spPathAttachment* self = SUB_CAST(spPathAttachment, attachment);
spVertexAttachment_copyTo(SUPER(self), SUPER(copy));
copy->lengthsLength = self->lengthsLength;
copy->lengths = MALLOC(float, self->lengthsLength);
memcpy(copy->lengths, self->lengths, self->lengthsLength * sizeof(float));
copy->closed = self->closed;
copy->constantSpeed = self->constantSpeed;
return SUPER(SUPER(copy));
}
spPathAttachment* spPathAttachment_create (const char* name) {
spPathAttachment* self = NEW(spPathAttachment);
_spVertexAttachment_init(SUPER(self));
_spAttachment_init(SUPER(SUPER(self)), name, SP_ATTACHMENT_PATH, _spPathAttachment_dispose, _spPathAttachment_copy);
return self;
}

View File

@ -0,0 +1,492 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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.
*****************************************************************************/
#include <spine/PathConstraint.h>
#include <spine/Skeleton.h>
#include <spine/extension.h>
#define PATHCONSTRAINT_NONE -1
#define PATHCONSTRAINT_BEFORE -2
#define PATHCONSTRAINT_AFTER -3
#define EPSILON 0.00001f
spPathConstraint* spPathConstraint_create (spPathConstraintData* data, const spSkeleton* skeleton) {
int i;
spPathConstraint *self = NEW(spPathConstraint);
CONST_CAST(spPathConstraintData*, self->data) = data;
self->bonesCount = data->bonesCount;
CONST_CAST(spBone**, self->bones) = MALLOC(spBone*, self->bonesCount);
for (i = 0; i < self->bonesCount; ++i)
self->bones[i] = spSkeleton_findBone(skeleton, self->data->bones[i]->name);
self->target = spSkeleton_findSlot(skeleton, self->data->target->name);
self->position = data->position;
self->spacing = data->spacing;
self->rotateMix = data->rotateMix;
self->translateMix = data->translateMix;
self->spacesCount = 0;
self->spaces = 0;
self->positionsCount = 0;
self->positions = 0;
self->worldCount = 0;
self->world = 0;
self->curvesCount = 0;
self->curves = 0;
self->lengthsCount = 0;
self->lengths = 0;
return self;
}
void spPathConstraint_dispose (spPathConstraint* self) {
FREE(self->bones);
FREE(self->spaces);
if (self->positions) FREE(self->positions);
if (self->world) FREE(self->world);
if (self->curves) FREE(self->curves);
if (self->lengths) FREE(self->lengths);
FREE(self);
}
void spPathConstraint_apply (spPathConstraint* self) {
int i, p, n;
float length, setupLength, x, y, dx, dy, s;
float* spaces, *lengths, *positions;
float spacing;
float boneX, boneY, offsetRotation;
int/*bool*/tip;
float rotateMix = self->rotateMix, translateMix = self->translateMix;
int/*bool*/ translate = translateMix > 0, rotate = rotateMix > 0;
int lengthSpacing;
spPathAttachment* attachment = (spPathAttachment*)self->target->attachment;
spPathConstraintData* data = self->data;
int percentSpacing = data->spacingMode == SP_SPACING_MODE_PERCENT;
spRotateMode rotateMode = data->rotateMode;
int tangents = rotateMode == SP_ROTATE_MODE_TANGENT, scale = rotateMode == SP_ROTATE_MODE_CHAIN_SCALE;
int boneCount = self->bonesCount, spacesCount = tangents ? boneCount : boneCount + 1;
spBone** bones = self->bones;
spBone* pa;
if (!translate && !rotate) return;
if ((attachment == 0) || (attachment->super.super.type != SP_ATTACHMENT_PATH)) return;
if (self->spacesCount != spacesCount) {
if (self->spaces) FREE(self->spaces);
self->spaces = MALLOC(float, spacesCount);
self->spacesCount = spacesCount;
}
spaces = self->spaces;
spaces[0] = 0;
lengths = 0;
spacing = self->spacing;
if (scale || !percentSpacing) {
if (scale) {
if (self->lengthsCount != boneCount) {
if (self->lengths) FREE(self->lengths);
self->lengths = MALLOC(float, boneCount);
self->lengthsCount = boneCount;
}
lengths = self->lengths;
}
lengthSpacing = data->spacingMode == SP_SPACING_MODE_LENGTH;
for (i = 0, n = spacesCount - 1; i < n;) {
spBone *bone = bones[i];
setupLength = bone->data->length;
if (setupLength < EPSILON) {
if (scale) lengths[i] = 0;
spaces[++i] = 0;
} else if (percentSpacing) {
if (scale) {
x = setupLength * bone->a, y = setupLength * bone->c;
length = SQRT(x * x + y * y);
lengths[i] = length;
}
spaces[++i] = spacing;
} else {
x = setupLength * bone->a, y = setupLength * bone->c;
length = SQRT(x * x + y * y);
if (scale) lengths[i] = length;
spaces[++i] = (lengthSpacing ? setupLength + spacing : spacing) * length / setupLength;
}
}
} else {
for (i = 1; i < spacesCount; i++) {
spaces[i] = spacing;
}
}
positions = spPathConstraint_computeWorldPositions(self, attachment, spacesCount, tangents,
data->positionMode == SP_POSITION_MODE_PERCENT, percentSpacing);
boneX = positions[0], boneY = positions[1], offsetRotation = self->data->offsetRotation;
tip = 0;
if (offsetRotation == 0)
tip = rotateMode == SP_ROTATE_MODE_CHAIN;
else {
tip = 0;
pa = self->target->bone;
offsetRotation *= pa->a * pa->d - pa->b * pa->c > 0 ? DEG_RAD : -DEG_RAD;
}
for (i = 0, p = 3; i < boneCount; i++, p += 3) {
spBone* bone = bones[i];
CONST_CAST(float, bone->worldX) += (boneX - bone->worldX) * translateMix;
CONST_CAST(float, bone->worldY) += (boneY - bone->worldY) * translateMix;
x = positions[p], y = positions[p + 1], dx = x - boneX, dy = y - boneY;
if (scale) {
length = lengths[i];
if (length != 0) {
s = (SQRT(dx * dx + dy * dy) / length - 1) * rotateMix + 1;
CONST_CAST(float, bone->a) *= s;
CONST_CAST(float, bone->c) *= s;
}
}
boneX = x;
boneY = y;
if (rotate) {
float a = bone->a, b = bone->b, c = bone->c, d = bone->d, r, cosine, sine;
if (tangents)
r = positions[p - 1];
else if (spaces[i + 1] == 0)
r = positions[p + 2];
else
r = ATAN2(dy, dx);
r -= ATAN2(c, a) - offsetRotation * DEG_RAD;
if (tip) {
cosine = COS(r);
sine = SIN(r);
length = bone->data->length;
boneX += (length * (cosine * a - sine * c) - dx) * rotateMix;
boneY += (length * (sine * a + cosine * c) - dy) * rotateMix;
} else
r += offsetRotation;
if (r > PI)
r -= PI2;
else if (r < -PI)
r += PI2;
r *= rotateMix;
cosine = COS(r);
sine = SIN(r);
CONST_CAST(float, bone->a) = cosine * a - sine * c;
CONST_CAST(float, bone->b) = cosine * b - sine * d;
CONST_CAST(float, bone->c) = sine * a + cosine * c;
CONST_CAST(float, bone->d) = sine * b + cosine * d;
}
CONST_CAST(int, bone->appliedValid) = -1;
}
}
static void _addBeforePosition(float p, float* temp, int i, float* out, int o) {
float x1 = temp[i], y1 = temp[i + 1], dx = temp[i + 2] - x1, dy = temp[i + 3] - y1, r = ATAN2(dy, dx);
out[o] = x1 + p * COS(r);
out[o + 1] = y1 + p * SIN(r);
out[o + 2] = r;
}
static void _addAfterPosition (float p, float* temp, int i, float* out, int o) {
float x1 = temp[i + 2], y1 = temp[i + 3], dx = x1 - temp[i], dy = y1 - temp[i + 1], r = ATAN2(dy, dx);
out[o] = x1 + p * COS(r);
out[o + 1] = y1 + p * SIN(r);
out[o + 2] = r;
}
/* Need to pass 0 as an argument, so VC++ doesn't error with C2124 */
static int _isNan(float value, float zero) {
float _nan = (float)0.0 / zero;
return 0 == memcmp((void*)&value, (void*)&_nan, sizeof(value));
}
static void _addCurvePosition (float p, float x1, float y1, float cx1, float cy1, float cx2, float cy2, float x2, float y2,
float* out, int o, int/*bool*/tangents) {
float tt, ttt, u, uu, uuu;
float ut, ut3, uut3, utt3;
float x, y;
if (p == 0 || _isNan(p, 0)) {
out[o] = x1;
out[o + 1] = y1;
out[o + 2] = ATAN2(cy1 - y1, cx1 - x1);
return;
}
tt = p * p, ttt = tt * p, u = 1 - p, uu = u * u, uuu = uu * u;
ut = u * p, ut3 = ut * 3, uut3 = u * ut3, utt3 = ut3 * p;
x = x1 * uuu + cx1 * uut3 + cx2 * utt3 + x2 * ttt, y = y1 * uuu + cy1 * uut3 + cy2 * utt3 + y2 * ttt;
out[o] = x;
out[o + 1] = y;
if (tangents) {
if (p < 0.001)
out[o + 2] = ATAN2(cy1 - y1, cx1 - x1);
else
out[o + 2] = ATAN2(y - (y1 * uu + cy1 * ut * 2 + cy2 * tt), x - (x1 * uu + cx1 * ut * 2 + cx2 * tt));
}
}
float* spPathConstraint_computeWorldPositions(spPathConstraint* self, spPathAttachment* path, int spacesCount, int/*bool*/ tangents, int/*bool*/percentPosition, int/**/percentSpacing) {
int i, o, w, curve, segment, /*bool*/closed, verticesLength, curveCount, prevCurve;
float* out, *curves, *segments;
float tmpx, tmpy, dddfx, dddfy, ddfx, ddfy, dfx, dfy, pathLength, curveLength, p;
float x1, y1, cx1, cy1, cx2, cy2, x2, y2;
spSlot* target = self->target;
float position = self->position;
float* spaces = self->spaces, *world = 0;
if (self->positionsCount != spacesCount * 3 + 2) {
if (self->positions) FREE(self->positions);
self->positions = MALLOC(float, spacesCount * 3 + 2);
self->positionsCount = spacesCount * 3 + 2;
}
out = self->positions;
closed = path->closed;
verticesLength = path->super.worldVerticesLength, curveCount = verticesLength / 6, prevCurve = PATHCONSTRAINT_NONE;
if (!path->constantSpeed) {
float* lengths = path->lengths;
curveCount -= closed ? 1 : 2;
pathLength = lengths[curveCount];
if (percentPosition) position *= pathLength;
if (percentSpacing) {
for (i = 1; i < spacesCount; i++)
spaces[i] *= pathLength;
}
if (self->worldCount != 8) {
if (self->world) FREE(self->world);
self->world = MALLOC(float, 8);
self->worldCount = 8;
}
world = self->world;
for (i = 0, o = 0, curve = 0; i < spacesCount; i++, o += 3) {
float space = spaces[i];
position += space;
p = position;
if (closed) {
p = FMOD(p, pathLength);
if (p < 0) p += pathLength;
curve = 0;
} else if (p < 0) {
if (prevCurve != PATHCONSTRAINT_BEFORE) {
prevCurve = PATHCONSTRAINT_BEFORE;
spVertexAttachment_computeWorldVertices(SUPER(path), target, 2, 4, world, 0, 2);
}
_addBeforePosition(p, world, 0, out, o);
continue;
} else if (p > pathLength) {
if (prevCurve != PATHCONSTRAINT_AFTER) {
prevCurve = PATHCONSTRAINT_AFTER;
spVertexAttachment_computeWorldVertices(SUPER(path), target, verticesLength - 6, 4, world, 0, 2);
}
_addAfterPosition(p - pathLength, world, 0, out, o);
continue;
}
/* Determine curve containing position. */
for (;; curve++) {
float length = lengths[curve];
if (p > length) continue;
if (curve == 0)
p /= length;
else {
float prev = lengths[curve - 1];
p = (p - prev) / (length - prev);
}
break;
}
if (curve != prevCurve) {
prevCurve = curve;
if (closed && curve == curveCount) {
spVertexAttachment_computeWorldVertices(SUPER(path), target, verticesLength - 4, 4, world, 0, 2);
spVertexAttachment_computeWorldVertices(SUPER(path), target, 0, 4, world, 4, 2);
} else
spVertexAttachment_computeWorldVertices(SUPER(path), target, curve * 6 + 2, 8, world, 0, 2);
}
_addCurvePosition(p, world[0], world[1], world[2], world[3], world[4], world[5], world[6], world[7], out, o,
tangents || (i > 0 && space == 0));
}
return out;
}
/* World vertices. */
if (closed) {
verticesLength += 2;
if (self->worldCount != verticesLength) {
if (self->world) FREE(self->world);
self->world = MALLOC(float, verticesLength);
self->worldCount = verticesLength;
}
world = self->world;
spVertexAttachment_computeWorldVertices(SUPER(path), target, 2, verticesLength - 4, world, 0, 2);
spVertexAttachment_computeWorldVertices(SUPER(path), target, 0, 2, world, verticesLength - 4, 2);
world[verticesLength - 2] = world[0];
world[verticesLength - 1] = world[1];
} else {
curveCount--;
verticesLength -= 4;
if (self->worldCount != verticesLength) {
if (self->world) FREE(self->world);
self->world = MALLOC(float, verticesLength);
self->worldCount = verticesLength;
}
world = self->world;
spVertexAttachment_computeWorldVertices(SUPER(path), target, 2, verticesLength, world, 0, 2);
}
/* Curve lengths. */
if (self->curvesCount != curveCount) {
if (self->curves) FREE(self->curves);
self->curves = MALLOC(float, curveCount);
self->curvesCount = curveCount;
}
curves = self->curves;
pathLength = 0;
x1 = world[0], y1 = world[1], cx1 = 0, cy1 = 0, cx2 = 0, cy2 = 0, x2 = 0, y2 = 0;
for (i = 0, w = 2; i < curveCount; i++, w += 6) {
cx1 = world[w];
cy1 = world[w + 1];
cx2 = world[w + 2];
cy2 = world[w + 3];
x2 = world[w + 4];
y2 = world[w + 5];
tmpx = (x1 - cx1 * 2 + cx2) * 0.1875f;
tmpy = (y1 - cy1 * 2 + cy2) * 0.1875f;
dddfx = ((cx1 - cx2) * 3 - x1 + x2) * 0.09375f;
dddfy = ((cy1 - cy2) * 3 - y1 + y2) * 0.09375f;
ddfx = tmpx * 2 + dddfx;
ddfy = tmpy * 2 + dddfy;
dfx = (cx1 - x1) * 0.75f + tmpx + dddfx * 0.16666667f;
dfy = (cy1 - y1) * 0.75f + tmpy + dddfy * 0.16666667f;
pathLength += SQRT(dfx * dfx + dfy * dfy);
dfx += ddfx;
dfy += ddfy;
ddfx += dddfx;
ddfy += dddfy;
pathLength += SQRT(dfx * dfx + dfy * dfy);
dfx += ddfx;
dfy += ddfy;
pathLength += SQRT(dfx * dfx + dfy * dfy);
dfx += ddfx + dddfx;
dfy += ddfy + dddfy;
pathLength += SQRT(dfx * dfx + dfy * dfy);
curves[i] = pathLength;
x1 = x2;
y1 = y2;
}
if (percentPosition)
position *= pathLength;
else
position *= pathLength / path->lengths[curveCount - 1];
if (percentSpacing) {
for (i = 1; i < spacesCount; i++)
spaces[i] *= pathLength;
}
segments = self->segments;
curveLength = 0;
for (i = 0, o = 0, curve = 0, segment = 0; i < spacesCount; i++, o += 3) {
float space = spaces[i];
position += space;
p = position;
if (closed) {
p = FMOD(p, pathLength);
if (p < 0) p += pathLength;
curve = 0;
} else if (p < 0) {
_addBeforePosition(p, world, 0, out, o);
continue;
} else if (p > pathLength) {
_addAfterPosition(p - pathLength, world, verticesLength - 4, out, o);
continue;
}
/* Determine curve containing position. */
for (;; curve++) {
float length = curves[curve];
if (p > length) continue;
if (curve == 0)
p /= length;
else {
float prev = curves[curve - 1];
p = (p - prev) / (length - prev);
}
break;
}
/* Curve segment lengths. */
if (curve != prevCurve) {
int ii;
prevCurve = curve;
ii = curve * 6;
x1 = world[ii];
y1 = world[ii + 1];
cx1 = world[ii + 2];
cy1 = world[ii + 3];
cx2 = world[ii + 4];
cy2 = world[ii + 5];
x2 = world[ii + 6];
y2 = world[ii + 7];
tmpx = (x1 - cx1 * 2 + cx2) * 0.03f;
tmpy = (y1 - cy1 * 2 + cy2) * 0.03f;
dddfx = ((cx1 - cx2) * 3 - x1 + x2) * 0.006f;
dddfy = ((cy1 - cy2) * 3 - y1 + y2) * 0.006f;
ddfx = tmpx * 2 + dddfx;
ddfy = tmpy * 2 + dddfy;
dfx = (cx1 - x1) * 0.3f + tmpx + dddfx * 0.16666667f;
dfy = (cy1 - y1) * 0.3f + tmpy + dddfy * 0.16666667f;
curveLength = SQRT(dfx * dfx + dfy * dfy);
segments[0] = curveLength;
for (ii = 1; ii < 8; ii++) {
dfx += ddfx;
dfy += ddfy;
ddfx += dddfx;
ddfy += dddfy;
curveLength += SQRT(dfx * dfx + dfy * dfy);
segments[ii] = curveLength;
}
dfx += ddfx;
dfy += ddfy;
curveLength += SQRT(dfx * dfx + dfy * dfy);
segments[8] = curveLength;
dfx += ddfx + dddfx;
dfy += ddfy + dddfy;
curveLength += SQRT(dfx * dfx + dfy * dfy);
segments[9] = curveLength;
segment = 0;
}
/* Weight by segment length. */
p *= curveLength;
for (;; segment++) {
float length = segments[segment];
if (p > length) continue;
if (segment == 0)
p /= length;
else {
float prev = segments[segment - 1];
p = segment + (p - prev) / (length - prev);
}
break;
}
_addCurvePosition(p * 0.1f, x1, y1, cx1, cy1, cx2, cy2, x2, y2, out, o, tangents || (i > 0 && space == 0));
}
return out;
}

View File

@ -0,0 +1,43 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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.
*****************************************************************************/
#include <spine/PathConstraintData.h>
#include <spine/extension.h>
spPathConstraintData* spPathConstraintData_create (const char* name) {
spPathConstraintData* self = NEW(spPathConstraintData);
MALLOC_STR(self->name, name);
return self;
}
void spPathConstraintData_dispose (spPathConstraintData* self) {
FREE(self->name);
FREE(self->bones);
FREE(self);
}

View File

@ -0,0 +1,67 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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.
*****************************************************************************/
#include <spine/PointAttachment.h>
#include <spine/extension.h>
void _spPointAttachment_dispose (spAttachment* attachment) {
spPointAttachment* self = SUB_CAST(spPointAttachment, attachment);
_spAttachment_deinit(attachment);
FREE(self);
}
spAttachment* _spPointAttachment_copy (spAttachment* attachment) {
spPointAttachment* self = SUB_CAST(spPointAttachment, attachment);
spPointAttachment* copy = spPointAttachment_create(attachment->name);
copy->x = self->x;
copy->y = self->y;
copy->rotation = self->rotation;
spColor_setFromColor(&copy->color, &self->color);
return SUPER(copy);
}
spPointAttachment* spPointAttachment_create (const char* name) {
spPointAttachment* self = NEW(spPointAttachment);
_spAttachment_init(SUPER(self), name, SP_ATTACHMENT_POINT, _spPointAttachment_dispose, _spPointAttachment_copy);
return self;
}
void spPointAttachment_computeWorldPosition (spPointAttachment* self, spBone* bone, float* x, float* y) {
*x = self->x * bone->a + self->y * bone->b + bone->worldX;
*y = self->x * bone->c + self->y * bone->d + bone->worldY;
}
float spPointAttachment_computeWorldRotation (spPointAttachment* self, spBone* bone) {
float cosine, sine, x, y;
cosine = COS_DEG(self->rotation);
sine = SIN_DEG(self->rotation);
x = cosine * bone->a + sine * bone->b;
y = cosine * bone->c + sine * bone->d;
return ATAN2(y, x) * RAD_DEG;
}

View File

@ -0,0 +1,153 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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.
*****************************************************************************/
#include <spine/RegionAttachment.h>
#include <spine/extension.h>
typedef enum {
BLX = 0, BLY, ULX, ULY, URX, URY, BRX, BRY
} spVertexIndex;
void _spRegionAttachment_dispose (spAttachment* attachment) {
spRegionAttachment* self = SUB_CAST(spRegionAttachment, attachment);
_spAttachment_deinit(attachment);
FREE(self->path);
FREE(self);
}
spAttachment* _spRegionAttachment_copy (spAttachment* attachment) {
spRegionAttachment* self = SUB_CAST(spRegionAttachment, attachment);
spRegionAttachment* copy = spRegionAttachment_create(attachment->name);
copy->regionWidth = self->regionWidth;
copy->regionHeight = self->regionHeight;
copy->regionOffsetX = self->regionOffsetX;
copy->regionOffsetY = self->regionOffsetY;
copy->regionOriginalWidth = self->regionOriginalWidth;
copy->regionOriginalHeight = self->regionOriginalHeight;
copy->rendererObject = self->rendererObject;
MALLOC_STR(copy->path, self->path);
copy->x = self->x;
copy->y = self->y;
copy->scaleX = self->scaleX;
copy->scaleY = self->scaleY;
copy->rotation = self->rotation;
copy->width = self->width;
copy->height = self->height;
memcpy(copy->uvs, self->uvs, sizeof(float) * 8);
memcpy(copy->offset, self->offset, sizeof(float) * 8);
spColor_setFromColor(&copy->color, &self->color);
return SUPER(copy);
}
spRegionAttachment* spRegionAttachment_create (const char* name) {
spRegionAttachment* self = NEW(spRegionAttachment);
self->scaleX = 1;
self->scaleY = 1;
spColor_setFromFloats(&self->color, 1, 1, 1, 1);
_spAttachment_init(SUPER(self), name, SP_ATTACHMENT_REGION, _spRegionAttachment_dispose, _spRegionAttachment_copy);
return self;
}
void spRegionAttachment_setUVs (spRegionAttachment* self, float u, float v, float u2, float v2, int/*bool*/rotate) {
if (rotate) {
self->uvs[URX] = u;
self->uvs[URY] = v2;
self->uvs[BRX] = u;
self->uvs[BRY] = v;
self->uvs[BLX] = u2;
self->uvs[BLY] = v;
self->uvs[ULX] = u2;
self->uvs[ULY] = v2;
} else {
self->uvs[ULX] = u;
self->uvs[ULY] = v2;
self->uvs[URX] = u;
self->uvs[URY] = v;
self->uvs[BRX] = u2;
self->uvs[BRY] = v;
self->uvs[BLX] = u2;
self->uvs[BLY] = v2;
}
}
void spRegionAttachment_updateOffset (spRegionAttachment* self) {
float regionScaleX = self->width / self->regionOriginalWidth * self->scaleX;
float regionScaleY = self->height / self->regionOriginalHeight * self->scaleY;
float localX = -self->width / 2 * self->scaleX + self->regionOffsetX * regionScaleX;
float localY = -self->height / 2 * self->scaleY + self->regionOffsetY * regionScaleY;
float localX2 = localX + self->regionWidth * regionScaleX;
float localY2 = localY + self->regionHeight * regionScaleY;
float radians = self->rotation * DEG_RAD;
float cosine = COS(radians), sine = SIN(radians);
float localXCos = localX * cosine + self->x;
float localXSin = localX * sine;
float localYCos = localY * cosine + self->y;
float localYSin = localY * sine;
float localX2Cos = localX2 * cosine + self->x;
float localX2Sin = localX2 * sine;
float localY2Cos = localY2 * cosine + self->y;
float localY2Sin = localY2 * sine;
self->offset[BLX] = localXCos - localYSin;
self->offset[BLY] = localYCos + localXSin;
self->offset[ULX] = localXCos - localY2Sin;
self->offset[ULY] = localY2Cos + localXSin;
self->offset[URX] = localX2Cos - localY2Sin;
self->offset[URY] = localY2Cos + localX2Sin;
self->offset[BRX] = localX2Cos - localYSin;
self->offset[BRY] = localYCos + localX2Sin;
}
void spRegionAttachment_computeWorldVertices (spRegionAttachment* self, spBone* bone, float* vertices, int offset, int stride) {
const float* offsets = self->offset;
float x = bone->worldX, y = bone->worldY;
float offsetX, offsetY;
offsetX = offsets[BRX];
offsetY = offsets[BRY];
vertices[offset] = offsetX * bone->a + offsetY * bone->b + x; /* br */
vertices[offset + 1] = offsetX * bone->c + offsetY * bone->d + y;
offset += stride;
offsetX = offsets[BLX];
offsetY = offsets[BLY];
vertices[offset] = offsetX * bone->a + offsetY * bone->b + x; /* bl */
vertices[offset + 1] = offsetX * bone->c + offsetY * bone->d + y;
offset += stride;
offsetX = offsets[ULX];
offsetY = offsets[ULY];
vertices[offset] = offsetX * bone->a + offsetY * bone->b + x; /* ul */
vertices[offset + 1] = offsetX * bone->c + offsetY * bone->d + y;
offset += stride;
offsetX = offsets[URX];
offsetY = offsets[URY];
vertices[offset] = offsetX * bone->a + offsetY * bone->b + x; /* ur */
vertices[offset + 1] = offsetX * bone->c + offsetY * bone->d + y;
}

View File

@ -0,0 +1,617 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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.
*****************************************************************************/
#include <spine/Skeleton.h>
#include <stdlib.h>
#include <string.h>
#include <spine/extension.h>
typedef enum {
SP_UPDATE_BONE, SP_UPDATE_IK_CONSTRAINT, SP_UPDATE_PATH_CONSTRAINT, SP_UPDATE_TRANSFORM_CONSTRAINT
} _spUpdateType;
typedef struct {
_spUpdateType type;
void* object;
} _spUpdate;
typedef struct {
spSkeleton super;
int updateCacheCount;
int updateCacheCapacity;
_spUpdate* updateCache;
int updateCacheResetCount;
int updateCacheResetCapacity;
spBone** updateCacheReset;
} _spSkeleton;
spSkeleton* spSkeleton_create (spSkeletonData* data) {
int i;
int* childrenCounts;
_spSkeleton* internal = NEW(_spSkeleton);
spSkeleton* self = SUPER(internal);
CONST_CAST(spSkeletonData*, self->data) = data;
self->bonesCount = self->data->bonesCount;
self->bones = MALLOC(spBone*, self->bonesCount);
childrenCounts = CALLOC(int, self->bonesCount);
for (i = 0; i < self->bonesCount; ++i) {
spBoneData* boneData = self->data->bones[i];
spBone* newBone;
if (!boneData->parent)
newBone = spBone_create(boneData, self, 0);
else {
spBone* parent = self->bones[boneData->parent->index];
newBone = spBone_create(boneData, self, parent);
++childrenCounts[boneData->parent->index];
}
self->bones[i] = newBone;
}
for (i = 0; i < self->bonesCount; ++i) {
spBoneData* boneData = self->data->bones[i];
spBone* bone = self->bones[i];
CONST_CAST(spBone**, bone->children) = MALLOC(spBone*, childrenCounts[boneData->index]);
}
for (i = 0; i < self->bonesCount; ++i) {
spBone* bone = self->bones[i];
spBone* parent = bone->parent;
if (parent)
parent->children[parent->childrenCount++] = bone;
}
CONST_CAST(spBone*, self->root) = (self->bonesCount > 0 ? self->bones[0] : NULL);
self->slotsCount = data->slotsCount;
self->slots = MALLOC(spSlot*, self->slotsCount);
for (i = 0; i < self->slotsCount; ++i) {
spSlotData *slotData = data->slots[i];
spBone* bone = self->bones[slotData->boneData->index];
self->slots[i] = spSlot_create(slotData, bone);
}
self->drawOrder = MALLOC(spSlot*, self->slotsCount);
memcpy(self->drawOrder, self->slots, sizeof(spSlot*) * self->slotsCount);
self->ikConstraintsCount = data->ikConstraintsCount;
self->ikConstraints = MALLOC(spIkConstraint*, self->ikConstraintsCount);
for (i = 0; i < self->data->ikConstraintsCount; ++i)
self->ikConstraints[i] = spIkConstraint_create(self->data->ikConstraints[i], self);
self->transformConstraintsCount = data->transformConstraintsCount;
self->transformConstraints = MALLOC(spTransformConstraint*, self->transformConstraintsCount);
for (i = 0; i < self->data->transformConstraintsCount; ++i)
self->transformConstraints[i] = spTransformConstraint_create(self->data->transformConstraints[i], self);
self->pathConstraintsCount = data->pathConstraintsCount;
self->pathConstraints = MALLOC(spPathConstraint*, self->pathConstraintsCount);
for (i = 0; i < self->data->pathConstraintsCount; i++)
self->pathConstraints[i] = spPathConstraint_create(self->data->pathConstraints[i], self);
spColor_setFromFloats(&self->color, 1, 1, 1, 1);
self->scaleX = 1;
self->scaleY = 1;
spSkeleton_updateCache(self);
FREE(childrenCounts);
return self;
}
void spSkeleton_dispose (spSkeleton* self) {
int i;
_spSkeleton* internal = SUB_CAST(_spSkeleton, self);
FREE(internal->updateCache);
FREE(internal->updateCacheReset);
for (i = 0; i < self->bonesCount; ++i)
spBone_dispose(self->bones[i]);
FREE(self->bones);
for (i = 0; i < self->slotsCount; ++i)
spSlot_dispose(self->slots[i]);
FREE(self->slots);
for (i = 0; i < self->ikConstraintsCount; ++i)
spIkConstraint_dispose(self->ikConstraints[i]);
FREE(self->ikConstraints);
for (i = 0; i < self->transformConstraintsCount; ++i)
spTransformConstraint_dispose(self->transformConstraints[i]);
FREE(self->transformConstraints);
for (i = 0; i < self->pathConstraintsCount; i++)
spPathConstraint_dispose(self->pathConstraints[i]);
FREE(self->pathConstraints);
FREE(self->drawOrder);
FREE(self);
}
static void _addToUpdateCache(_spSkeleton* const internal, _spUpdateType type, void *object) {
_spUpdate* update;
if (internal->updateCacheCount == internal->updateCacheCapacity) {
internal->updateCacheCapacity *= 2;
internal->updateCache = (_spUpdate*)realloc(internal->updateCache, sizeof(_spUpdate) * internal->updateCacheCapacity);
}
update = internal->updateCache + internal->updateCacheCount;
update->type = type;
update->object = object;
++internal->updateCacheCount;
}
static void _addToUpdateCacheReset(_spSkeleton* const internal, spBone* bone) {
if (internal->updateCacheResetCount == internal->updateCacheResetCapacity) {
internal->updateCacheResetCapacity *= 2;
internal->updateCacheReset = (spBone**)realloc(internal->updateCacheReset, sizeof(spBone*) * internal->updateCacheResetCapacity);
}
internal->updateCacheReset[internal->updateCacheResetCount] = bone;
++internal->updateCacheResetCount;
}
static void _sortBone(_spSkeleton* const internal, spBone* bone) {
if (bone->sorted) return;
if (bone->parent) _sortBone(internal, bone->parent);
bone->sorted = 1;
_addToUpdateCache(internal, SP_UPDATE_BONE, bone);
}
static void _sortPathConstraintAttachmentBones(_spSkeleton* const internal, spAttachment* attachment, spBone* slotBone) {
spPathAttachment* pathAttachment = (spPathAttachment*)attachment;
int* pathBones;
int pathBonesCount;
if (pathAttachment->super.super.type != SP_ATTACHMENT_PATH) return;
pathBones = pathAttachment->super.bones;
pathBonesCount = pathAttachment->super.bonesCount;
if (pathBones == 0)
_sortBone(internal, slotBone);
else {
spBone** bones = internal->super.bones;
int i = 0, n;
while (i < pathBonesCount) {
int boneCount = pathBones[i++];
for (n = i + boneCount; i < n; i++)
_sortBone(internal, bones[pathBones[i]]);
}
}
}
static void _sortPathConstraintAttachment(_spSkeleton* const internal, spSkin* skin, int slotIndex, spBone* slotBone) {
_Entry* entry = SUB_CAST(_spSkin, skin)->entries;
while (entry) {
if (entry->slotIndex == slotIndex) _sortPathConstraintAttachmentBones(internal, entry->attachment, slotBone);
entry = entry->next;
}
}
static void _sortReset(spBone** bones, int bonesCount) {
int i;
for (i = 0; i < bonesCount; ++i) {
spBone* bone = bones[i];
if (!bone->active) continue;
if (bone->sorted) _sortReset(bone->children, bone->childrenCount);
bone->sorted = 0;
}
}
static void _sortIkConstraint (_spSkeleton* const internal, spIkConstraint* constraint) {
int /*bool*/ contains = 0;
int i;
spBone* target = constraint->target;
spBone** constrained;
spBone* parent;
constraint->active = constraint->target->active && (!constraint->data->skinRequired || (internal->super.skin != 0 && spIkConstraintDataArray_contains(internal->super.skin->ikConstraints, constraint->data)));
if (!constraint->active) return;
_sortBone(internal, target);
constrained = constraint->bones;
parent = constrained[0];
_sortBone(internal, parent);
if (constraint->bonesCount > 1) {
spBone* child = constrained[constraint->bonesCount - 1];
contains = 0;
for (i = 0; i < internal->updateCacheCount; i++) {
_spUpdate update = internal->updateCache[i];
if (update.object == child) {
contains = -1;
break;
}
}
if (!contains) _addToUpdateCacheReset(internal, child);
}
_addToUpdateCache(internal, SP_UPDATE_IK_CONSTRAINT, constraint);
_sortReset(parent->children, parent->childrenCount);
constrained[constraint->bonesCount-1]->sorted = 1;
}
static void _sortPathConstraint(_spSkeleton* const internal, spPathConstraint* constraint) {
spSlot* slot = constraint->target;
int slotIndex = slot->data->index;
spBone* slotBone = slot->bone;
int i, n, boneCount;
spAttachment* attachment;
spBone** constrained;
spSkeleton* skeleton = SUPER_CAST(spSkeleton, internal);
constraint->active = constraint->target->bone->active && (!constraint->data->skinRequired || (internal->super.skin != 0 && spPathConstraintDataArray_contains(internal->super.skin->pathConstraints, constraint->data)));
if (!constraint->active) return;
if (skeleton->skin) _sortPathConstraintAttachment(internal, skeleton->skin, slotIndex, slotBone);
if (skeleton->data->defaultSkin && skeleton->data->defaultSkin != skeleton->skin)
_sortPathConstraintAttachment(internal, skeleton->data->defaultSkin, slotIndex, slotBone);
for (i = 0, n = skeleton->data->skinsCount; i < n; i++)
_sortPathConstraintAttachment(internal, skeleton->data->skins[i], slotIndex, slotBone);
attachment = slot->attachment;
if (attachment && attachment->type == SP_ATTACHMENT_PATH) _sortPathConstraintAttachmentBones(internal, attachment, slotBone);
constrained = constraint->bones;
boneCount = constraint->bonesCount;
for (i = 0; i < boneCount; i++)
_sortBone(internal, constrained[i]);
_addToUpdateCache(internal, SP_UPDATE_PATH_CONSTRAINT, constraint);
for (i = 0; i < boneCount; i++)
_sortReset(constrained[i]->children, constrained[i]->childrenCount);
for (i = 0; i < boneCount; i++)
constrained[i]->sorted = 1;
}
static void _sortTransformConstraint(_spSkeleton* const internal, spTransformConstraint* constraint) {
int i, boneCount;
spBone** constrained;
spBone* child;
int /*boolean*/ contains = 0;
constraint->active = constraint->target->active && (!constraint->data->skinRequired || (internal->super.skin != 0 && spTransformConstraintDataArray_contains(internal->super.skin->transformConstraints, constraint->data)));
if (!constraint->active) return;
_sortBone(internal, constraint->target);
constrained = constraint->bones;
boneCount = constraint->bonesCount;
if (constraint->data->local) {
for (i = 0; i < boneCount; i++) {
child = constrained[i];
_sortBone(internal, child);
contains = 0;
for (i = 0; i < internal->updateCacheCount; i++) {
_spUpdate update = internal->updateCache[i];
if (update.object == child) {
contains = -1;
break;
}
}
if (!contains) _addToUpdateCacheReset(internal, child);
}
} else {
for (i = 0; i < boneCount; i++)
_sortBone(internal, constrained[i]);
}
_addToUpdateCache(internal, SP_UPDATE_TRANSFORM_CONSTRAINT, constraint);
for (i = 0; i < boneCount; i++)
_sortReset(constrained[i]->children, constrained[i]->childrenCount);
for (i = 0; i < boneCount; i++)
constrained[i]->sorted = 1;
}
void spSkeleton_updateCache (spSkeleton* self) {
int i, ii;
spBone** bones;
spIkConstraint** ikConstraints;
spPathConstraint** pathConstraints;
spTransformConstraint** transformConstraints;
int ikCount, transformCount, pathCount, constraintCount;
_spSkeleton* internal = SUB_CAST(_spSkeleton, self);
internal->updateCacheCapacity = self->bonesCount + self->ikConstraintsCount + self->transformConstraintsCount + self->pathConstraintsCount;
FREE(internal->updateCache);
internal->updateCache = MALLOC(_spUpdate, internal->updateCacheCapacity);
internal->updateCacheCount = 0;
internal->updateCacheResetCapacity = self->bonesCount;
FREE(internal->updateCacheReset);
internal->updateCacheReset = MALLOC(spBone*, internal->updateCacheResetCapacity);
internal->updateCacheResetCount = 0;
bones = self->bones;
for (i = 0; i < self->bonesCount; ++i) {
spBone* bone = bones[i];
bone->sorted = bone->data->skinRequired;
bone->active = !bone->sorted;
}
if (self->skin) {
spBoneDataArray* skinBones = self->skin->bones;
for(i = 0; i < skinBones->size; i++) {
spBone* bone = self->bones[skinBones->items[i]->index];
do {
bone->sorted = 0;
bone->active = -1;
bone = bone->parent;
} while (bone != 0);
}
}
/* IK first, lowest hierarchy depth first. */
ikConstraints = self->ikConstraints;
transformConstraints = self->transformConstraints;
pathConstraints = self->pathConstraints;
ikCount = self->ikConstraintsCount; transformCount = self->transformConstraintsCount; pathCount = self->pathConstraintsCount;
constraintCount = ikCount + transformCount + pathCount;
i = 0;
continue_outer:
for (; i < constraintCount; i++) {
for (ii = 0; ii < ikCount; ii++) {
spIkConstraint* ikConstraint = ikConstraints[ii];
if (ikConstraint->data->order == i) {
_sortIkConstraint(internal, ikConstraint);
i++;
goto continue_outer;
}
}
for (ii = 0; ii < transformCount; ii++) {
spTransformConstraint* transformConstraint = transformConstraints[ii];
if (transformConstraint->data->order == i) {
_sortTransformConstraint(internal, transformConstraint);
i++;
goto continue_outer;
}
}
for (ii = 0; ii < pathCount; ii++) {
spPathConstraint* pathConstraint = pathConstraints[ii];
if (pathConstraint->data->order == i) {
_sortPathConstraint(internal, pathConstraint);
i++;
goto continue_outer;
}
}
}
for (i = 0; i < self->bonesCount; ++i)
_sortBone(internal, self->bones[i]);
}
void spSkeleton_updateWorldTransform (const spSkeleton* self) {
int i;
_spSkeleton* internal = SUB_CAST(_spSkeleton, self);
spBone** updateCacheReset = internal->updateCacheReset;
for (i = 0; i < internal->updateCacheResetCount; i++) {
spBone* bone = updateCacheReset[i];
CONST_CAST(float, bone->ax) = bone->x;
CONST_CAST(float, bone->ay) = bone->y;
CONST_CAST(float, bone->arotation) = bone->rotation;
CONST_CAST(float, bone->ascaleX) = bone->scaleX;
CONST_CAST(float, bone->ascaleY) = bone->scaleY;
CONST_CAST(float, bone->ashearX) = bone->shearX;
CONST_CAST(float, bone->ashearY) = bone->shearY;
CONST_CAST(int, bone->appliedValid) = 1;
}
for (i = 0; i < internal->updateCacheCount; ++i) {
_spUpdate* update = internal->updateCache + i;
switch (update->type) {
case SP_UPDATE_BONE:
spBone_updateWorldTransform((spBone*)update->object);
break;
case SP_UPDATE_IK_CONSTRAINT:
spIkConstraint_apply((spIkConstraint*)update->object);
break;
case SP_UPDATE_TRANSFORM_CONSTRAINT:
spTransformConstraint_apply((spTransformConstraint*)update->object);
break;
case SP_UPDATE_PATH_CONSTRAINT:
spPathConstraint_apply((spPathConstraint*)update->object);
break;
}
}
}
void spSkeleton_setToSetupPose (const spSkeleton* self) {
spSkeleton_setBonesToSetupPose(self);
spSkeleton_setSlotsToSetupPose(self);
}
void spSkeleton_setBonesToSetupPose (const spSkeleton* self) {
int i;
for (i = 0; i < self->bonesCount; ++i)
spBone_setToSetupPose(self->bones[i]);
for (i = 0; i < self->ikConstraintsCount; ++i) {
spIkConstraint* ikConstraint = self->ikConstraints[i];
ikConstraint->bendDirection = ikConstraint->data->bendDirection;
ikConstraint->compress = ikConstraint->data->compress;
ikConstraint->stretch = ikConstraint->data->stretch;
ikConstraint->softness = ikConstraint->data->softness;
ikConstraint->mix = ikConstraint->data->mix;
}
for (i = 0; i < self->transformConstraintsCount; ++i) {
spTransformConstraint* constraint = self->transformConstraints[i];
spTransformConstraintData* data = constraint->data;
constraint->rotateMix = data->rotateMix;
constraint->translateMix = data->translateMix;
constraint->scaleMix = data->scaleMix;
constraint->shearMix = data->shearMix;
}
for (i = 0; i < self->pathConstraintsCount; ++i) {
spPathConstraint* constraint = self->pathConstraints[i];
spPathConstraintData* data = constraint->data;
constraint->position = data->position;
constraint->spacing = data->spacing;
constraint->rotateMix = data->rotateMix;
constraint->translateMix = data->translateMix;
}
}
void spSkeleton_setSlotsToSetupPose (const spSkeleton* self) {
int i;
memcpy(self->drawOrder, self->slots, self->slotsCount * sizeof(spSlot*));
for (i = 0; i < self->slotsCount; ++i)
spSlot_setToSetupPose(self->slots[i]);
}
spBone* spSkeleton_findBone (const spSkeleton* self, const char* boneName) {
int i;
for (i = 0; i < self->bonesCount; ++i)
if (strcmp(self->data->bones[i]->name, boneName) == 0) return self->bones[i];
return 0;
}
int spSkeleton_findBoneIndex (const spSkeleton* self, const char* boneName) {
int i;
for (i = 0; i < self->bonesCount; ++i)
if (strcmp(self->data->bones[i]->name, boneName) == 0) return i;
return -1;
}
spSlot* spSkeleton_findSlot (const spSkeleton* self, const char* slotName) {
int i;
for (i = 0; i < self->slotsCount; ++i)
if (strcmp(self->data->slots[i]->name, slotName) == 0) return self->slots[i];
return 0;
}
int spSkeleton_findSlotIndex (const spSkeleton* self, const char* slotName) {
int i;
for (i = 0; i < self->slotsCount; ++i)
if (strcmp(self->data->slots[i]->name, slotName) == 0) return i;
return -1;
}
int spSkeleton_setSkinByName (spSkeleton* self, const char* skinName) {
spSkin *skin;
if (!skinName) {
spSkeleton_setSkin(self, 0);
return 1;
}
skin = spSkeletonData_findSkin(self->data, skinName);
if (!skin) return 0;
spSkeleton_setSkin(self, skin);
return 1;
}
void spSkeleton_setSkin (spSkeleton* self, spSkin* newSkin) {
if (self->skin == newSkin) return;
if (newSkin) {
if (self->skin)
spSkin_attachAll(newSkin, self, self->skin);
else {
/* No previous skin, attach setup pose attachments. */
int i;
for (i = 0; i < self->slotsCount; ++i) {
spSlot* slot = self->slots[i];
if (slot->data->attachmentName) {
spAttachment* attachment = spSkin_getAttachment(newSkin, i, slot->data->attachmentName);
if (attachment) spSlot_setAttachment(slot, attachment);
}
}
}
}
CONST_CAST(spSkin*, self->skin) = newSkin;
spSkeleton_updateCache(self);
}
spAttachment* spSkeleton_getAttachmentForSlotName (const spSkeleton* self, const char* slotName, const char* attachmentName) {
int slotIndex = spSkeletonData_findSlotIndex(self->data, slotName);
return spSkeleton_getAttachmentForSlotIndex(self, slotIndex, attachmentName);
}
spAttachment* spSkeleton_getAttachmentForSlotIndex (const spSkeleton* self, int slotIndex, const char* attachmentName) {
if (slotIndex == -1) return 0;
if (self->skin) {
spAttachment *attachment = spSkin_getAttachment(self->skin, slotIndex, attachmentName);
if (attachment) return attachment;
}
if (self->data->defaultSkin) {
spAttachment *attachment = spSkin_getAttachment(self->data->defaultSkin, slotIndex, attachmentName);
if (attachment) return attachment;
}
return 0;
}
int spSkeleton_setAttachment (spSkeleton* self, const char* slotName, const char* attachmentName) {
int i;
for (i = 0; i < self->slotsCount; ++i) {
spSlot *slot = self->slots[i];
if (strcmp(slot->data->name, slotName) == 0) {
if (!attachmentName)
spSlot_setAttachment(slot, 0);
else {
spAttachment* attachment = spSkeleton_getAttachmentForSlotIndex(self, i, attachmentName);
if (!attachment) return 0;
spSlot_setAttachment(slot, attachment);
}
return 1;
}
}
return 0;
}
spIkConstraint* spSkeleton_findIkConstraint (const spSkeleton* self, const char* constraintName) {
int i;
for (i = 0; i < self->ikConstraintsCount; ++i)
if (strcmp(self->ikConstraints[i]->data->name, constraintName) == 0) return self->ikConstraints[i];
return 0;
}
spTransformConstraint* spSkeleton_findTransformConstraint (const spSkeleton* self, const char* constraintName) {
int i;
for (i = 0; i < self->transformConstraintsCount; ++i)
if (strcmp(self->transformConstraints[i]->data->name, constraintName) == 0) return self->transformConstraints[i];
return 0;
}
spPathConstraint* spSkeleton_findPathConstraint (const spSkeleton* self, const char* constraintName) {
int i;
for (i = 0; i < self->pathConstraintsCount; ++i)
if (strcmp(self->pathConstraints[i]->data->name, constraintName) == 0) return self->pathConstraints[i];
return 0;
}
void spSkeleton_update (spSkeleton* self, float deltaTime) {
self->time += deltaTime;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,209 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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.
*****************************************************************************/
#include <spine/SkeletonBounds.h>
#include <limits.h>
#include <spine/extension.h>
spPolygon* spPolygon_create (int capacity) {
spPolygon* self = NEW(spPolygon);
self->capacity = capacity;
CONST_CAST(float*, self->vertices) = MALLOC(float, capacity);
return self;
}
void spPolygon_dispose (spPolygon* self) {
FREE(self->vertices);
FREE(self);
}
int/*bool*/spPolygon_containsPoint (spPolygon* self, float x, float y) {
int prevIndex = self->count - 2;
int inside = 0;
int i;
for (i = 0; i < self->count; i += 2) {
float vertexY = self->vertices[i + 1];
float prevY = self->vertices[prevIndex + 1];
if ((vertexY < y && prevY >= y) || (prevY < y && vertexY >= y)) {
float vertexX = self->vertices[i];
if (vertexX + (y - vertexY) / (prevY - vertexY) * (self->vertices[prevIndex] - vertexX) < x) inside = !inside;
}
prevIndex = i;
}
return inside;
}
int/*bool*/spPolygon_intersectsSegment (spPolygon* self, float x1, float y1, float x2, float y2) {
float width12 = x1 - x2, height12 = y1 - y2;
float det1 = x1 * y2 - y1 * x2;
float x3 = self->vertices[self->count - 2], y3 = self->vertices[self->count - 1];
int i;
for (i = 0; i < self->count; i += 2) {
float x4 = self->vertices[i], y4 = self->vertices[i + 1];
float det2 = x3 * y4 - y3 * x4;
float width34 = x3 - x4, height34 = y3 - y4;
float det3 = width12 * height34 - height12 * width34;
float x = (det1 * width34 - width12 * det2) / det3;
if (((x >= x3 && x <= x4) || (x >= x4 && x <= x3)) && ((x >= x1 && x <= x2) || (x >= x2 && x <= x1))) {
float y = (det1 * height34 - height12 * det2) / det3;
if (((y >= y3 && y <= y4) || (y >= y4 && y <= y3)) && ((y >= y1 && y <= y2) || (y >= y2 && y <= y1))) return 1;
}
x3 = x4;
y3 = y4;
}
return 0;
}
/**/
typedef struct {
spSkeletonBounds super;
int capacity;
} _spSkeletonBounds;
spSkeletonBounds* spSkeletonBounds_create () {
return SUPER(NEW(_spSkeletonBounds));
}
void spSkeletonBounds_dispose (spSkeletonBounds* self) {
int i;
for (i = 0; i < SUB_CAST(_spSkeletonBounds, self)->capacity; ++i)
if (self->polygons[i]) spPolygon_dispose(self->polygons[i]);
FREE(self->polygons);
FREE(self->boundingBoxes);
FREE(self);
}
void spSkeletonBounds_update (spSkeletonBounds* self, spSkeleton* skeleton, int/*bool*/updateAabb) {
int i;
_spSkeletonBounds* internal = SUB_CAST(_spSkeletonBounds, self);
if (internal->capacity < skeleton->slotsCount) {
spPolygon** newPolygons;
FREE(self->boundingBoxes);
self->boundingBoxes = MALLOC(spBoundingBoxAttachment*, skeleton->slotsCount);
newPolygons = CALLOC(spPolygon*, skeleton->slotsCount);
memcpy(newPolygons, self->polygons, sizeof(spPolygon*) * internal->capacity);
FREE(self->polygons);
self->polygons = newPolygons;
internal->capacity = skeleton->slotsCount;
}
self->minX = (float)INT_MAX;
self->minY = (float)INT_MAX;
self->maxX = (float)INT_MIN;
self->maxY = (float)INT_MIN;
self->count = 0;
for (i = 0; i < skeleton->slotsCount; ++i) {
spPolygon* polygon;
spBoundingBoxAttachment* boundingBox;
spAttachment* attachment;
spSlot* slot = skeleton->slots[i];
if (!slot->bone->active) continue;
attachment = slot->attachment;
if (!attachment || attachment->type != SP_ATTACHMENT_BOUNDING_BOX) continue;
boundingBox = (spBoundingBoxAttachment*)attachment;
self->boundingBoxes[self->count] = boundingBox;
polygon = self->polygons[self->count];
if (!polygon || polygon->capacity < boundingBox->super.worldVerticesLength) {
if (polygon) spPolygon_dispose(polygon);
self->polygons[self->count] = polygon = spPolygon_create(boundingBox->super.worldVerticesLength);
}
polygon->count = boundingBox->super.worldVerticesLength;
spVertexAttachment_computeWorldVertices(SUPER(boundingBox), slot, 0, polygon->count, polygon->vertices, 0, 2);
if (updateAabb) {
int ii = 0;
for (; ii < polygon->count; ii += 2) {
float x = polygon->vertices[ii];
float y = polygon->vertices[ii + 1];
if (x < self->minX) self->minX = x;
if (y < self->minY) self->minY = y;
if (x > self->maxX) self->maxX = x;
if (y > self->maxY) self->maxY = y;
}
}
self->count++;
}
}
int/*bool*/spSkeletonBounds_aabbContainsPoint (spSkeletonBounds* self, float x, float y) {
return x >= self->minX && x <= self->maxX && y >= self->minY && y <= self->maxY;
}
int/*bool*/spSkeletonBounds_aabbIntersectsSegment (spSkeletonBounds* self, float x1, float y1, float x2, float y2) {
float m, x, y;
if ((x1 <= self->minX && x2 <= self->minX)
|| (y1 <= self->minY && y2 <= self->minY)
|| (x1 >= self->maxX && x2 >= self->maxX)
|| (y1 >= self->maxY && y2 >= self->maxY)
) return 0;
m = (y2 - y1) / (x2 - x1);
y = m * (self->minX - x1) + y1;
if (y > self->minY && y < self->maxY) return 1;
y = m * (self->maxX - x1) + y1;
if (y > self->minY && y < self->maxY) return 1;
x = (self->minY - y1) / m + x1;
if (x > self->minX && x < self->maxX) return 1;
x = (self->maxY - y1) / m + x1;
if (x > self->minX && x < self->maxX) return 1;
return 0;
}
int/*bool*/spSkeletonBounds_aabbIntersectsSkeleton (spSkeletonBounds* self, spSkeletonBounds* bounds) {
return self->minX < bounds->maxX && self->maxX > bounds->minX && self->minY < bounds->maxY && self->maxY > bounds->minY;
}
spBoundingBoxAttachment* spSkeletonBounds_containsPoint (spSkeletonBounds* self, float x, float y) {
int i;
for (i = 0; i < self->count; ++i)
if (spPolygon_containsPoint(self->polygons[i], x, y)) return self->boundingBoxes[i];
return 0;
}
spBoundingBoxAttachment* spSkeletonBounds_intersectsSegment (spSkeletonBounds* self, float x1, float y1, float x2, float y2) {
int i;
for (i = 0; i < self->count; ++i)
if (spPolygon_intersectsSegment(self->polygons[i], x1, y1, x2, y2)) return self->boundingBoxes[i];
return 0;
}
spPolygon* spSkeletonBounds_getPolygon (spSkeletonBounds* self, spBoundingBoxAttachment* boundingBox) {
int i;
for (i = 0; i < self->count; ++i)
if (self->boundingBoxes[i] == boundingBox) return self->polygons[i];
return 0;
}

View File

@ -0,0 +1,325 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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.
*****************************************************************************/
#include <spine/SkeletonClipping.h>
#include <spine/extension.h>
spSkeletonClipping* spSkeletonClipping_create() {
spSkeletonClipping* clipping = CALLOC(spSkeletonClipping, 1);
clipping->triangulator = spTriangulator_create();
clipping->clippingPolygon = spFloatArray_create(128);
clipping->clipOutput = spFloatArray_create(128);
clipping->clippedVertices = spFloatArray_create(128);
clipping->clippedUVs = spFloatArray_create(128);
clipping->clippedTriangles = spUnsignedShortArray_create(128);
clipping->scratch = spFloatArray_create(128);
return clipping;
}
void spSkeletonClipping_dispose(spSkeletonClipping* self) {
spTriangulator_dispose(self->triangulator);
spFloatArray_dispose(self->clippingPolygon);
spFloatArray_dispose(self->clipOutput);
spFloatArray_dispose(self->clippedVertices);
spFloatArray_dispose(self->clippedUVs);
spUnsignedShortArray_dispose(self->clippedTriangles);
spFloatArray_dispose(self->scratch);
FREE(self);
}
static void _makeClockwise (spFloatArray* polygon) {
int i, n, lastX;
float* vertices = polygon->items;
int verticeslength = polygon->size;
float area = vertices[verticeslength - 2] * vertices[1] - vertices[0] * vertices[verticeslength - 1], p1x, p1y, p2x, p2y;
for (i = 0, n = verticeslength - 3; i < n; i += 2) {
p1x = vertices[i];
p1y = vertices[i + 1];
p2x = vertices[i + 2];
p2y = vertices[i + 3];
area += p1x * p2y - p2x * p1y;
}
if (area < 0) return;
for (i = 0, lastX = verticeslength - 2, n = verticeslength >> 1; i < n; i += 2) {
float x = vertices[i], y = vertices[i + 1];
int other = lastX - i;
vertices[i] = vertices[other];
vertices[i + 1] = vertices[other + 1];
vertices[other] = x;
vertices[other + 1] = y;
}
}
int spSkeletonClipping_clipStart(spSkeletonClipping* self, spSlot* slot, spClippingAttachment* clip) {
int i, n;
float* vertices;
if (self->clipAttachment) return 0;
self->clipAttachment = clip;
n = clip->super.worldVerticesLength;
vertices = spFloatArray_setSize(self->clippingPolygon, n)->items;
spVertexAttachment_computeWorldVertices(SUPER(clip), slot, 0, n, vertices, 0, 2);
_makeClockwise(self->clippingPolygon);
self->clippingPolygons = spTriangulator_decompose(self->triangulator, self->clippingPolygon, spTriangulator_triangulate(self->triangulator, self->clippingPolygon));
for (i = 0, n = self->clippingPolygons->size; i < n; i++) {
spFloatArray* polygon = self->clippingPolygons->items[i];
_makeClockwise(polygon);
spFloatArray_add(polygon, polygon->items[0]);
spFloatArray_add(polygon, polygon->items[1]);
}
return self->clippingPolygons->size;
}
void spSkeletonClipping_clipEnd(spSkeletonClipping* self, spSlot* slot) {
if (self->clipAttachment != 0 && self->clipAttachment->endSlot == slot->data) spSkeletonClipping_clipEnd2(self);
}
void spSkeletonClipping_clipEnd2(spSkeletonClipping* self) {
if (!self->clipAttachment) return;
self->clipAttachment = 0;
self->clippingPolygons = 0;
spFloatArray_clear(self->clippedVertices);
spFloatArray_clear(self->clippedUVs);
spUnsignedShortArray_clear(self->clippedTriangles);
spFloatArray_clear(self->clippingPolygon);
}
int /*boolean*/ spSkeletonClipping_isClipping(spSkeletonClipping* self) {
return self->clipAttachment != 0;
}
int /*boolean*/ _clip(spSkeletonClipping* self, float x1, float y1, float x2, float y2, float x3, float y3, spFloatArray* clippingArea, spFloatArray* output) {
int i;
spFloatArray* originalOutput = output;
int clipped = 0;
float* clippingVertices;
int clippingVerticesLast;
spFloatArray* input = 0;
if (clippingArea->size % 4 >= 2) {
input = output;
output = self->scratch;
} else
input = self->scratch;
spFloatArray_clear(input);
spFloatArray_add(input, x1);
spFloatArray_add(input, y1);
spFloatArray_add(input, x2);
spFloatArray_add(input, y2);
spFloatArray_add(input, x3);
spFloatArray_add(input, y3);
spFloatArray_add(input, x1);
spFloatArray_add(input, y1);
spFloatArray_clear(output);
clippingVertices = clippingArea->items;
clippingVerticesLast = clippingArea->size - 4;
for (i = 0;; i += 2) {
int ii;
spFloatArray* temp;
float edgeX = clippingVertices[i], edgeY = clippingVertices[i + 1];
float edgeX2 = clippingVertices[i + 2], edgeY2 = clippingVertices[i + 3];
float deltaX = edgeX - edgeX2, deltaY = edgeY - edgeY2;
float* inputVertices = input->items;
int inputVerticesLength = input->size - 2, outputStart = output->size;
for (ii = 0; ii < inputVerticesLength; ii += 2) {
float inputX = inputVertices[ii], inputY = inputVertices[ii + 1];
float inputX2 = inputVertices[ii + 2], inputY2 = inputVertices[ii + 3];
int side2 = deltaX * (inputY2 - edgeY2) - deltaY * (inputX2 - edgeX2) > 0;
if (deltaX * (inputY - edgeY2) - deltaY * (inputX - edgeX2) > 0) {
float c0, c2;
float s, ua;
if (side2) {
spFloatArray_add(output, inputX2);
spFloatArray_add(output, inputY2);
continue;
}
c0 = inputY2 - inputY, c2 = inputX2 - inputX;
s = c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY);
if (ABS(s) > 0.000001f) {
ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / s;
spFloatArray_add(output, edgeX + (edgeX2 - edgeX) * ua);
spFloatArray_add(output, edgeY + (edgeY2 - edgeY) * ua);
} else {
spFloatArray_add(output, edgeX);
spFloatArray_add(output, edgeY);
}
} else if (side2) {
float c0 = inputY2 - inputY, c2 = inputX2 - inputX;
float s = c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY);
if (ABS(s) > 0.000001f) {
float ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / s;
spFloatArray_add(output, edgeX + (edgeX2 - edgeX) * ua);
spFloatArray_add(output, edgeY + (edgeY2 - edgeY) * ua);
} else {
spFloatArray_add(output, edgeX);
spFloatArray_add(output, edgeY);
}
spFloatArray_add(output, inputX2);
spFloatArray_add(output, inputY2);
}
clipped = 1;
}
if (outputStart == output->size) {
spFloatArray_clear(originalOutput);
return 1;
}
spFloatArray_add(output, output->items[0]);
spFloatArray_add(output, output->items[1]);
if (i == clippingVerticesLast) break;
temp = output;
output = input;
spFloatArray_clear(output);
input = temp;
}
if (originalOutput != output) {
spFloatArray_clear(originalOutput);
spFloatArray_addAllValues(originalOutput, output->items, 0, output->size - 2);
} else
spFloatArray_setSize(originalOutput, originalOutput->size - 2);
return clipped;
}
void spSkeletonClipping_clipTriangles(spSkeletonClipping* self, float* vertices, int verticesLength, unsigned short* triangles, int trianglesLength, float* uvs, int stride) {
int i;
spFloatArray* clipOutput = self->clipOutput;
spFloatArray* clippedVertices = self->clippedVertices;
spFloatArray* clippedUVs = self->clippedUVs;
spUnsignedShortArray* clippedTriangles = self->clippedTriangles;
spFloatArray** polygons = self->clippingPolygons->items;
int polygonsCount = self->clippingPolygons->size;
short index = 0;
spFloatArray_clear(clippedVertices);
spFloatArray_clear(clippedUVs);
spUnsignedShortArray_clear(clippedTriangles);
i = 0;
continue_outer:
for (; i < trianglesLength; i += 3) {
int p;
int vertexOffset = triangles[i] * stride;
float x2, y2, u2, v2, x3, y3, u3, v3;
float x1 = vertices[vertexOffset], y1 = vertices[vertexOffset + 1];
float u1 = uvs[vertexOffset], v1 = uvs[vertexOffset + 1];
vertexOffset = triangles[i + 1] * stride;
x2 = vertices[vertexOffset]; y2 = vertices[vertexOffset + 1];
u2 = uvs[vertexOffset]; v2 = uvs[vertexOffset + 1];
vertexOffset = triangles[i + 2] * stride;
x3 = vertices[vertexOffset]; y3 = vertices[vertexOffset + 1];
u3 = uvs[vertexOffset]; v3 = uvs[vertexOffset + 1];
for (p = 0; p < polygonsCount; p++) {
int s = clippedVertices->size;
if (_clip(self, x1, y1, x2, y2, x3, y3, polygons[p], clipOutput)) {
int ii;
float d0, d1, d2, d4, d;
unsigned short* clippedTrianglesItems;
int clipOutputCount;
float* clipOutputItems;
float* clippedVerticesItems;
float* clippedUVsItems;
int clipOutputLength = clipOutput->size;
if (clipOutputLength == 0) continue;
d0 = y2 - y3; d1 = x3 - x2; d2 = x1 - x3; d4 = y3 - y1;
d = 1 / (d0 * d2 + d1 * (y1 - y3));
clipOutputCount = clipOutputLength >> 1;
clipOutputItems = clipOutput->items;
clippedVerticesItems = spFloatArray_setSize(clippedVertices, s + (clipOutputCount << 1))->items;
clippedUVsItems = spFloatArray_setSize(clippedUVs, s + (clipOutputCount << 1))->items;
for (ii = 0; ii < clipOutputLength; ii += 2) {
float c0, c1, a, b, c;
float x = clipOutputItems[ii], y = clipOutputItems[ii + 1];
clippedVerticesItems[s] = x;
clippedVerticesItems[s + 1] = y;
c0 = x - x3; c1 = y - y3;
a = (d0 * c0 + d1 * c1) * d;
b = (d4 * c0 + d2 * c1) * d;
c = 1 - a - b;
clippedUVsItems[s] = u1 * a + u2 * b + u3 * c;
clippedUVsItems[s + 1] = v1 * a + v2 * b + v3 * c;
s += 2;
}
s = clippedTriangles->size;
clippedTrianglesItems = spUnsignedShortArray_setSize(clippedTriangles, s + 3 * (clipOutputCount - 2))->items;
clipOutputCount--;
for (ii = 1; ii < clipOutputCount; ii++) {
clippedTrianglesItems[s] = index;
clippedTrianglesItems[s + 1] = (unsigned short)(index + ii);
clippedTrianglesItems[s + 2] = (unsigned short)(index + ii + 1);
s += 3;
}
index += clipOutputCount + 1;
} else {
unsigned short* clippedTrianglesItems;
float* clippedVerticesItems = spFloatArray_setSize(clippedVertices, s + (3 << 1))->items;
float* clippedUVsItems = spFloatArray_setSize(clippedUVs, s + (3 << 1))->items;
clippedVerticesItems[s] = x1;
clippedVerticesItems[s + 1] = y1;
clippedVerticesItems[s + 2] = x2;
clippedVerticesItems[s + 3] = y2;
clippedVerticesItems[s + 4] = x3;
clippedVerticesItems[s + 5] = y3;
clippedUVsItems[s] = u1;
clippedUVsItems[s + 1] = v1;
clippedUVsItems[s + 2] = u2;
clippedUVsItems[s + 3] = v2;
clippedUVsItems[s + 4] = u3;
clippedUVsItems[s + 5] = v3;
s = clippedTriangles->size;
clippedTrianglesItems = spUnsignedShortArray_setSize(clippedTriangles, s + 3)->items;
clippedTrianglesItems[s] = index;
clippedTrianglesItems[s + 1] = (unsigned short)(index + 1);
clippedTrianglesItems[s + 2] = (unsigned short)(index + 2);
index += 3;
i += 3;
goto continue_outer;
}
}
}
UNUSED(verticesLength);
}

View File

@ -0,0 +1,151 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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.
*****************************************************************************/
#include <spine/SkeletonData.h>
#include <string.h>
#include <spine/extension.h>
spSkeletonData* spSkeletonData_create () {
return NEW(spSkeletonData);
}
void spSkeletonData_dispose (spSkeletonData* self) {
int i;
for (i = 0; i < self->stringsCount; ++i)
FREE(self->strings[i]);
FREE(self->strings);
for (i = 0; i < self->bonesCount; ++i)
spBoneData_dispose(self->bones[i]);
FREE(self->bones);
for (i = 0; i < self->slotsCount; ++i)
spSlotData_dispose(self->slots[i]);
FREE(self->slots);
for (i = 0; i < self->skinsCount; ++i)
spSkin_dispose(self->skins[i]);
FREE(self->skins);
for (i = 0; i < self->eventsCount; ++i)
spEventData_dispose(self->events[i]);
FREE(self->events);
for (i = 0; i < self->animationsCount; ++i)
spAnimation_dispose(self->animations[i]);
FREE(self->animations);
for (i = 0; i < self->ikConstraintsCount; ++i)
spIkConstraintData_dispose(self->ikConstraints[i]);
FREE(self->ikConstraints);
for (i = 0; i < self->transformConstraintsCount; ++i)
spTransformConstraintData_dispose(self->transformConstraints[i]);
FREE(self->transformConstraints);
for (i = 0; i < self->pathConstraintsCount; i++)
spPathConstraintData_dispose(self->pathConstraints[i]);
FREE(self->pathConstraints);
FREE(self->hash);
FREE(self->version);
FREE(self);
}
spBoneData* spSkeletonData_findBone (const spSkeletonData* self, const char* boneName) {
int i;
for (i = 0; i < self->bonesCount; ++i)
if (strcmp(self->bones[i]->name, boneName) == 0) return self->bones[i];
return 0;
}
int spSkeletonData_findBoneIndex (const spSkeletonData* self, const char* boneName) {
int i;
for (i = 0; i < self->bonesCount; ++i)
if (strcmp(self->bones[i]->name, boneName) == 0) return i;
return -1;
}
spSlotData* spSkeletonData_findSlot (const spSkeletonData* self, const char* slotName) {
int i;
for (i = 0; i < self->slotsCount; ++i)
if (strcmp(self->slots[i]->name, slotName) == 0) return self->slots[i];
return 0;
}
int spSkeletonData_findSlotIndex (const spSkeletonData* self, const char* slotName) {
int i;
for (i = 0; i < self->slotsCount; ++i)
if (strcmp(self->slots[i]->name, slotName) == 0) return i;
return -1;
}
spSkin* spSkeletonData_findSkin (const spSkeletonData* self, const char* skinName) {
int i;
for (i = 0; i < self->skinsCount; ++i)
if (strcmp(self->skins[i]->name, skinName) == 0) return self->skins[i];
return 0;
}
spEventData* spSkeletonData_findEvent (const spSkeletonData* self, const char* eventName) {
int i;
for (i = 0; i < self->eventsCount; ++i)
if (strcmp(self->events[i]->name, eventName) == 0) return self->events[i];
return 0;
}
spAnimation* spSkeletonData_findAnimation (const spSkeletonData* self, const char* animationName) {
int i;
for (i = 0; i < self->animationsCount; ++i)
if (strcmp(self->animations[i]->name, animationName) == 0) return self->animations[i];
return 0;
}
spIkConstraintData* spSkeletonData_findIkConstraint (const spSkeletonData* self, const char* constraintName) {
int i;
for (i = 0; i < self->ikConstraintsCount; ++i)
if (strcmp(self->ikConstraints[i]->name, constraintName) == 0) return self->ikConstraints[i];
return 0;
}
spTransformConstraintData* spSkeletonData_findTransformConstraint (const spSkeletonData* self, const char* constraintName) {
int i;
for (i = 0; i < self->transformConstraintsCount; ++i)
if (strcmp(self->transformConstraints[i]->name, constraintName) == 0) return self->transformConstraints[i];
return 0;
}
spPathConstraintData* spSkeletonData_findPathConstraint (const spSkeletonData* self, const char* constraintName) {
int i;
for (i = 0; i < self->pathConstraintsCount; ++i)
if (strcmp(self->pathConstraints[i]->name, constraintName) == 0) return self->pathConstraints[i];
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,276 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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.
*****************************************************************************/
#include <spine/Skin.h>
#include <spine/extension.h>
#include <stdio.h>
_SP_ARRAY_IMPLEMENT_TYPE(spBoneDataArray, spBoneData*)
_SP_ARRAY_IMPLEMENT_TYPE(spIkConstraintDataArray, spIkConstraintData*)
_SP_ARRAY_IMPLEMENT_TYPE(spTransformConstraintDataArray, spTransformConstraintData*)
_SP_ARRAY_IMPLEMENT_TYPE(spPathConstraintDataArray, spPathConstraintData*)
_Entry* _Entry_create (int slotIndex, const char* name, spAttachment* attachment) {
_Entry* self = NEW(_Entry);
self->slotIndex = slotIndex;
MALLOC_STR(self->name, name);
self->attachment = attachment;
return self;
}
void _Entry_dispose (_Entry* self) {
spAttachment_dispose(self->attachment);
FREE(self->name);
FREE(self);
}
static _SkinHashTableEntry* _SkinHashTableEntry_create (_Entry* entry) {
_SkinHashTableEntry* self = NEW(_SkinHashTableEntry);
self->entry = entry;
return self;
}
static void _SkinHashTableEntry_dispose (_SkinHashTableEntry* self) {
FREE(self);
}
/**/
spSkin* spSkin_create (const char* name) {
spSkin* self = SUPER(NEW(_spSkin));
MALLOC_STR(self->name, name);
self->bones = spBoneDataArray_create(4);
self->ikConstraints = spIkConstraintDataArray_create(4);
self->transformConstraints = spTransformConstraintDataArray_create(4);
self->pathConstraints = spPathConstraintDataArray_create(4);
return self;
}
void spSkin_dispose (spSkin* self) {
_Entry* entry = SUB_CAST(_spSkin, self)->entries;
while (entry) {
_Entry* nextEntry = entry->next;
_Entry_dispose(entry);
entry = nextEntry;
}
{
_SkinHashTableEntry** currentHashtableEntry = SUB_CAST(_spSkin, self)->entriesHashTable;
int i;
for (i = 0; i < SKIN_ENTRIES_HASH_TABLE_SIZE; ++i, ++currentHashtableEntry) {
_SkinHashTableEntry* hashtableEntry = *currentHashtableEntry;
while (hashtableEntry) {
_SkinHashTableEntry* nextEntry = hashtableEntry->next;
_SkinHashTableEntry_dispose(hashtableEntry);
hashtableEntry = nextEntry;
}
}
}
spBoneDataArray_dispose(self->bones);
spIkConstraintDataArray_dispose(self->ikConstraints);
spTransformConstraintDataArray_dispose(self->transformConstraints);
spPathConstraintDataArray_dispose(self->pathConstraints);
FREE(self->name);
FREE(self);
}
void spSkin_setAttachment (spSkin* self, int slotIndex, const char* name, spAttachment* attachment) {
_SkinHashTableEntry* existingEntry = 0;
_SkinHashTableEntry* hashEntry = SUB_CAST(_spSkin, self)->entriesHashTable[(unsigned int)slotIndex % SKIN_ENTRIES_HASH_TABLE_SIZE];
while (hashEntry) {
if (hashEntry->entry->slotIndex == slotIndex && strcmp(hashEntry->entry->name, name) == 0) {
existingEntry = hashEntry;
break;
}
hashEntry = hashEntry->next;
}
if (attachment) attachment->refCount++;
if (existingEntry) {
if (hashEntry->entry->attachment) spAttachment_dispose(hashEntry->entry->attachment);
hashEntry->entry->attachment = attachment;
} else {
_Entry* newEntry = _Entry_create(slotIndex, name, attachment);
newEntry->next = SUB_CAST(_spSkin, self)->entries;
SUB_CAST(_spSkin, self)->entries = newEntry;
{
unsigned int hashTableIndex = (unsigned int)slotIndex % SKIN_ENTRIES_HASH_TABLE_SIZE;
_SkinHashTableEntry** hashTable = SUB_CAST(_spSkin, self)->entriesHashTable;
_SkinHashTableEntry* newHashEntry = _SkinHashTableEntry_create(newEntry);
newHashEntry->next = hashTable[hashTableIndex];
SUB_CAST(_spSkin, self)->entriesHashTable[hashTableIndex] = newHashEntry;
}
}
}
spAttachment* spSkin_getAttachment (const spSkin* self, int slotIndex, const char* name) {
const _SkinHashTableEntry* hashEntry = SUB_CAST(_spSkin, self)->entriesHashTable[(unsigned int)slotIndex % SKIN_ENTRIES_HASH_TABLE_SIZE];
while (hashEntry) {
if (hashEntry->entry->slotIndex == slotIndex && strcmp(hashEntry->entry->name, name) == 0) return hashEntry->entry->attachment;
hashEntry = hashEntry->next;
}
return 0;
}
const char* spSkin_getAttachmentName (const spSkin* self, int slotIndex, int attachmentIndex) {
const _Entry* entry = SUB_CAST(_spSkin, self)->entries;
int i = 0;
while (entry) {
if (entry->slotIndex == slotIndex) {
if (i == attachmentIndex) return entry->name;
i++;
}
entry = entry->next;
}
return 0;
}
void spSkin_attachAll (const spSkin* self, spSkeleton* skeleton, const spSkin* oldSkin) {
const _Entry *entry = SUB_CAST(_spSkin, oldSkin)->entries;
while (entry) {
spSlot *slot = skeleton->slots[entry->slotIndex];
if (slot->attachment == entry->attachment) {
spAttachment *attachment = spSkin_getAttachment(self, entry->slotIndex, entry->name);
if (attachment) spSlot_setAttachment(slot, attachment);
}
entry = entry->next;
}
}
void spSkin_addSkin(spSkin* self, const spSkin* other) {
int i = 0;
spSkinEntry* entry;
for (i = 0; i < other->bones->size; i++) {
if (!spBoneDataArray_contains(self->bones, other->bones->items[i]))
spBoneDataArray_add(self->bones, other->bones->items[i]);
}
for (i = 0; i < other->ikConstraints->size; i++) {
if (!spIkConstraintDataArray_contains(self->ikConstraints, other->ikConstraints->items[i]))
spIkConstraintDataArray_add(self->ikConstraints, other->ikConstraints->items[i]);
}
for (i = 0; i < other->transformConstraints->size; i++) {
if (!spTransformConstraintDataArray_contains(self->transformConstraints, other->transformConstraints->items[i]))
spTransformConstraintDataArray_add(self->transformConstraints, other->transformConstraints->items[i]);
}
for (i = 0; i < other->pathConstraints->size; i++) {
if (!spPathConstraintDataArray_contains(self->pathConstraints, other->pathConstraints->items[i]))
spPathConstraintDataArray_add(self->pathConstraints, other->pathConstraints->items[i]);
}
entry = spSkin_getAttachments(other);
while (entry) {
spSkin_setAttachment(self, entry->slotIndex, entry->name, entry->attachment);
entry = entry->next;
}
}
void spSkin_copySkin(spSkin* self, const spSkin* other) {
int i = 0;
spSkinEntry* entry;
for (i = 0; i < other->bones->size; i++) {
if (!spBoneDataArray_contains(self->bones, other->bones->items[i]))
spBoneDataArray_add(self->bones, other->bones->items[i]);
}
for (i = 0; i < other->ikConstraints->size; i++) {
if (!spIkConstraintDataArray_contains(self->ikConstraints, other->ikConstraints->items[i]))
spIkConstraintDataArray_add(self->ikConstraints, other->ikConstraints->items[i]);
}
for (i = 0; i < other->transformConstraints->size; i++) {
if (!spTransformConstraintDataArray_contains(self->transformConstraints, other->transformConstraints->items[i]))
spTransformConstraintDataArray_add(self->transformConstraints, other->transformConstraints->items[i]);
}
for (i = 0; i < other->pathConstraints->size; i++) {
if (!spPathConstraintDataArray_contains(self->pathConstraints, other->pathConstraints->items[i]))
spPathConstraintDataArray_add(self->pathConstraints, other->pathConstraints->items[i]);
}
entry = spSkin_getAttachments(other);
while (entry) {
if (entry->attachment->type == SP_ATTACHMENT_MESH) {
spMeshAttachment* attachment = spMeshAttachment_newLinkedMesh(SUB_CAST(spMeshAttachment, entry->attachment));
spSkin_setAttachment(self, entry->slotIndex, entry->name, SUPER(SUPER(attachment)));
} else {
spAttachment* attachment = entry->attachment ? spAttachment_copy(entry->attachment) : 0;
spSkin_setAttachment(self, entry->slotIndex, entry->name, attachment);
}
entry = entry->next;
}
}
spSkinEntry* spSkin_getAttachments(const spSkin* self) {
return SUB_CAST(_spSkin, self)->entries;
}
void spSkin_clear(spSkin* self) {
_Entry* entry = SUB_CAST(_spSkin, self)->entries;
while (entry) {
_Entry* nextEntry = entry->next;
_Entry_dispose(entry);
entry = nextEntry;
}
SUB_CAST(_spSkin, self)->entries = 0;
{
_SkinHashTableEntry** currentHashtableEntry = SUB_CAST(_spSkin, self)->entriesHashTable;
int i;
for (i = 0; i < SKIN_ENTRIES_HASH_TABLE_SIZE; ++i, ++currentHashtableEntry) {
_SkinHashTableEntry* hashtableEntry = *currentHashtableEntry;
while (hashtableEntry) {
_SkinHashTableEntry* nextEntry = hashtableEntry->next;
_SkinHashTableEntry_dispose(hashtableEntry);
hashtableEntry = nextEntry;
}
SUB_CAST(_spSkin, self)->entriesHashTable[i] = 0;
}
}
spBoneDataArray_clear(self->bones);
spIkConstraintDataArray_clear(self->ikConstraints);
spTransformConstraintDataArray_clear(self->transformConstraints);
spPathConstraintDataArray_clear(self->pathConstraints);
}

View File

@ -0,0 +1,81 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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.
*****************************************************************************/
#include <spine/Slot.h>
#include <spine/extension.h>
typedef struct {
spSlot super;
float attachmentTime;
} _spSlot;
spSlot* spSlot_create (spSlotData* data, spBone* bone) {
spSlot* self = SUPER(NEW(_spSlot));
CONST_CAST(spSlotData*, self->data) = data;
CONST_CAST(spBone*, self->bone) = bone;
spColor_setFromFloats(&self->color, 1, 1, 1, 1);
self->darkColor = data->darkColor == 0 ? 0 : spColor_create();
spSlot_setToSetupPose(self);
return self;
}
void spSlot_dispose (spSlot* self) {
FREE(self->deform);
FREE(self->darkColor);
FREE(self);
}
void spSlot_setAttachment (spSlot* self, spAttachment* attachment) {
if (attachment == self->attachment) return;
CONST_CAST(spAttachment*, self->attachment) = attachment;
SUB_CAST(_spSlot, self)->attachmentTime = self->bone->skeleton->time;
self->deformCount = 0;
}
void spSlot_setAttachmentTime (spSlot* self, float time) {
SUB_CAST(_spSlot, self)->attachmentTime = self->bone->skeleton->time - time;
}
float spSlot_getAttachmentTime (const spSlot* self) {
return self->bone->skeleton->time - SUB_CAST(_spSlot, self) ->attachmentTime;
}
void spSlot_setToSetupPose (spSlot* self) {
spColor_setFromColor(&self->color, &self->data->color);
if (self->darkColor) spColor_setFromColor(self->darkColor, self->data->darkColor);
if (!self->data->attachmentName)
spSlot_setAttachment(self, 0);
else {
spAttachment* attachment = spSkeleton_getAttachmentForSlotIndex(
self->bone->skeleton, self->data->index, self->data->attachmentName);
CONST_CAST(spAttachment*, self->attachment) = 0;
spSlot_setAttachment(self, attachment);
}
}

View File

@ -0,0 +1,55 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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.
*****************************************************************************/
#include <spine/SlotData.h>
#include <spine/extension.h>
spSlotData* spSlotData_create (const int index, const char* name, spBoneData* boneData) {
spSlotData* self = NEW(spSlotData);
CONST_CAST(int, self->index) = index;
MALLOC_STR(self->name, name);
CONST_CAST(spBoneData*, self->boneData) = boneData;
spColor_setFromFloats(&self->color, 1, 1, 1, 1);
return self;
}
void spSlotData_dispose (spSlotData* self) {
FREE(self->name);
FREE(self->attachmentName);
FREE(self->darkColor);
FREE(self);
}
void spSlotData_setAttachmentName (spSlotData* self, const char* attachmentName) {
FREE(self->attachmentName);
if (attachmentName)
MALLOC_STR(self->attachmentName, attachmentName);
else
CONST_CAST(char*, self->attachmentName) = 0;
}

View File

@ -0,0 +1,272 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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.
*****************************************************************************/
#include <spine/TransformConstraint.h>
#include <spine/Skeleton.h>
#include <spine/extension.h>
spTransformConstraint* spTransformConstraint_create (spTransformConstraintData* data, const spSkeleton* skeleton) {
int i;
spTransformConstraint* self = NEW(spTransformConstraint);
CONST_CAST(spTransformConstraintData*, self->data) = data;
self->rotateMix = data->rotateMix;
self->translateMix = data->translateMix;
self->scaleMix = data->scaleMix;
self->shearMix = data->shearMix;
self->bonesCount = data->bonesCount;
CONST_CAST(spBone**, self->bones) = MALLOC(spBone*, self->bonesCount);
for (i = 0; i < self->bonesCount; ++i)
self->bones[i] = spSkeleton_findBone(skeleton, self->data->bones[i]->name);
self->target = spSkeleton_findBone(skeleton, self->data->target->name);
return self;
}
void spTransformConstraint_dispose (spTransformConstraint* self) {
FREE(self->bones);
FREE(self);
}
void _spTransformConstraint_applyAbsoluteWorld (spTransformConstraint* self) {
float rotateMix = self->rotateMix, translateMix = self->translateMix, scaleMix = self->scaleMix, shearMix = self->shearMix;
spBone* target = self->target;
float ta = target->a, tb = target->b, tc = target->c, td = target->d;
float degRadReflect = ta * td - tb * tc > 0 ? DEG_RAD : -DEG_RAD;
float offsetRotation = self->data->offsetRotation * degRadReflect, offsetShearY = self->data->offsetShearY * degRadReflect;
int /*bool*/ modified;
int i;
float a, b, c, d, r, cosine, sine, x, y, s, ts, by;
for (i = 0; i < self->bonesCount; ++i) {
spBone* bone = self->bones[i];
modified = 0;
if (rotateMix != 0) {
a = bone->a, b = bone->b, c = bone->c, d = bone->d;
r = ATAN2(tc, ta) - ATAN2(c, a) + offsetRotation;
if (r > PI) r -= PI2;
else if (r < -PI) r += PI2;
r *= rotateMix;
cosine = COS(r);
sine = SIN(r);
CONST_CAST(float, bone->a) = cosine * a - sine * c;
CONST_CAST(float, bone->b) = cosine * b - sine * d;
CONST_CAST(float, bone->c) = sine * a + cosine * c;
CONST_CAST(float, bone->d) = sine * b + cosine * d;
modified = 1;
}
if (translateMix != 0) {
spBone_localToWorld(target, self->data->offsetX, self->data->offsetY, &x, &y);
CONST_CAST(float, bone->worldX) += (x - bone->worldX) * translateMix;
CONST_CAST(float, bone->worldY) += (y - bone->worldY) * translateMix;
modified = 1;
}
if (scaleMix > 0) {
s = SQRT(bone->a * bone->a + bone->c * bone->c);
ts = SQRT(ta * ta + tc * tc);
if (s > 0.00001f) s = (s + (ts - s + self->data->offsetScaleX) * scaleMix) / s;
CONST_CAST(float, bone->a) *= s;
CONST_CAST(float, bone->c) *= s;
s = SQRT(bone->b * bone->b + bone->d * bone->d);
ts = SQRT(tb * tb + td * td);
if (s > 0.00001f) s = (s + (ts - s + self->data->offsetScaleY) * scaleMix) / s;
CONST_CAST(float, bone->b) *= s;
CONST_CAST(float, bone->d) *= s;
modified = 1;
}
if (shearMix > 0) {
b = bone->b, d = bone->d;
by = ATAN2(d, b);
r = ATAN2(td, tb) - ATAN2(tc, ta) - (by - ATAN2(bone->c, bone->a));
s = SQRT(b * b + d * d);
if (r > PI) r -= PI2;
else if (r < -PI) r += PI2;
r = by + (r + offsetShearY) * shearMix;
CONST_CAST(float, bone->b) = COS(r) * s;
CONST_CAST(float, bone->d) = SIN(r) * s;
modified = 1;
}
if (modified) CONST_CAST(int, bone->appliedValid) = 0;
}
}
void _spTransformConstraint_applyRelativeWorld (spTransformConstraint* self) {
float rotateMix = self->rotateMix, translateMix = self->translateMix, scaleMix = self->scaleMix, shearMix = self->shearMix;
spBone* target = self->target;
float ta = target->a, tb = target->b, tc = target->c, td = target->d;
float degRadReflect = ta * td - tb * tc > 0 ? DEG_RAD : -DEG_RAD;
float offsetRotation = self->data->offsetRotation * degRadReflect, offsetShearY = self->data->offsetShearY * degRadReflect;
int /*bool*/ modified;
int i;
float a, b, c, d, r, cosine, sine, x, y, s;
for (i = 0; i < self->bonesCount; ++i) {
spBone* bone = self->bones[i];
modified = 0;
if (rotateMix != 0) {
a = bone->a, b = bone->b, c = bone->c, d = bone->d;
r = ATAN2(tc, ta) + offsetRotation;
if (r > PI) r -= PI2;
else if (r < -PI) r += PI2;
r *= rotateMix;
cosine = COS(r);
sine = SIN(r);
CONST_CAST(float, bone->a) = cosine * a - sine * c;
CONST_CAST(float, bone->b) = cosine * b - sine * d;
CONST_CAST(float, bone->c) = sine * a + cosine * c;
CONST_CAST(float, bone->d) = sine * b + cosine * d;
modified = 1;
}
if (translateMix != 0) {
spBone_localToWorld(target, self->data->offsetX, self->data->offsetY, &x, &y);
CONST_CAST(float, bone->worldX) += (x * translateMix);
CONST_CAST(float, bone->worldY) += (y * translateMix);
modified = 1;
}
if (scaleMix > 0) {
s = (SQRT(ta * ta + tc * tc) - 1 + self->data->offsetScaleX) * scaleMix + 1;
CONST_CAST(float, bone->a) *= s;
CONST_CAST(float, bone->c) *= s;
s = (SQRT(tb * tb + td * td) - 1 + self->data->offsetScaleY) * scaleMix + 1;
CONST_CAST(float, bone->b) *= s;
CONST_CAST(float, bone->d) *= s;
modified = 1;
}
if (shearMix > 0) {
r = ATAN2(td, tb) - ATAN2(tc, ta);
if (r > PI) r -= PI2;
else if (r < -PI) r += PI2;
b = bone->b, d = bone->d;
r = ATAN2(d, b) + (r - PI / 2 + offsetShearY) * shearMix;
s = SQRT(b * b + d * d);
CONST_CAST(float, bone->b) = COS(r) * s;
CONST_CAST(float, bone->d) = SIN(r) * s;
modified = 1;
}
if (modified) CONST_CAST(int, bone->appliedValid) = 0;
}
}
void _spTransformConstraint_applyAbsoluteLocal (spTransformConstraint* self) {
float rotateMix = self->rotateMix, translateMix = self->translateMix, scaleMix = self->scaleMix, shearMix = self->shearMix;
spBone* target = self->target;
int i;
float rotation, r, x, y, scaleX, scaleY, shearY;
if (!target->appliedValid) spBone_updateAppliedTransform(target);
for (i = 0; i < self->bonesCount; ++i) {
spBone* bone = self->bones[i];
if (!bone->appliedValid) spBone_updateAppliedTransform(bone);
rotation = bone->arotation;
if (rotateMix != 0) {
r = target->arotation - rotation + self->data->offsetRotation;
r -= (16384 - (int)(16384.499999999996 - r / 360)) * 360;
rotation += r * rotateMix;
}
x = bone->ax, y = bone->ay;
if (translateMix != 0) {
x += (target->ax - x + self->data->offsetX) * translateMix;
y += (target->ay - y + self->data->offsetY) * translateMix;
}
scaleX = bone->ascaleX, scaleY = bone->ascaleY;
if (scaleMix != 0) {
if (scaleX > 0.00001) scaleX = (scaleX + (target->ascaleX - scaleX + self->data->offsetScaleX) * scaleMix) / scaleX;
if (scaleY > 0.00001) scaleY = (scaleY + (target->ascaleY - scaleY + self->data->offsetScaleY) * scaleMix) / scaleY;
}
shearY = bone->ashearY;
if (shearMix != 0) {
r = target->ashearY - shearY + self->data->offsetShearY;
r -= (16384 - (int)(16384.499999999996 - r / 360)) * 360;
bone->shearY += r * shearMix;
}
spBone_updateWorldTransformWith(bone, x, y, rotation, scaleX, scaleY, bone->ashearX, shearY);
}
}
void _spTransformConstraint_applyRelativeLocal (spTransformConstraint* self) {
float rotateMix = self->rotateMix, translateMix = self->translateMix, scaleMix = self->scaleMix, shearMix = self->shearMix;
spBone* target = self->target;
int i;
float rotation, x, y, scaleX, scaleY, shearY;
if (!target->appliedValid) spBone_updateAppliedTransform(target);
for (i = 0; i < self->bonesCount; ++i) {
spBone* bone = self->bones[i];
if (!bone->appliedValid) spBone_updateAppliedTransform(bone);
rotation = bone->arotation;
if (rotateMix != 0) rotation += (target->arotation + self->data->offsetRotation) * rotateMix;
x = bone->ax;
y = bone->ay;
if (translateMix != 0) {
x += (target->ax + self->data->offsetX) * translateMix;
y += (target->ay + self->data->offsetY) * translateMix;
}
scaleX = bone->ascaleX;
scaleY = bone->ascaleY;
if (scaleMix != 0) {
if (scaleX > 0.00001f) scaleX *= ((target->ascaleX - 1 + self->data->offsetScaleX) * scaleMix) + 1;
if (scaleY > 0.00001f) scaleY *= ((target->ascaleY - 1 + self->data->offsetScaleY) * scaleMix) + 1;
}
shearY = bone->ashearY;
if (shearMix != 0) shearY += (target->ashearY + self->data->offsetShearY) * shearMix;
spBone_updateWorldTransformWith(bone, x, y, rotation, scaleX, scaleY, bone->ashearX, shearY);
}
}
void spTransformConstraint_apply (spTransformConstraint* self) {
if (self->data->local) {
if (self->data->relative)
_spTransformConstraint_applyRelativeLocal(self);
else
_spTransformConstraint_applyAbsoluteLocal(self);
} else {
if (self->data->relative)
_spTransformConstraint_applyRelativeWorld(self);
else
_spTransformConstraint_applyAbsoluteWorld(self);
}
}

View File

@ -0,0 +1,43 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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.
*****************************************************************************/
#include <spine/TransformConstraintData.h>
#include <spine/extension.h>
spTransformConstraintData* spTransformConstraintData_create (const char* name) {
spTransformConstraintData* self = NEW(spTransformConstraintData);
MALLOC_STR(self->name, name);
return self;
}
void spTransformConstraintData_dispose (spTransformConstraintData* self) {
FREE(self->name);
FREE(self->bones);
FREE(self);
}

View File

@ -0,0 +1,361 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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.
*****************************************************************************/
#include <spine/Triangulator.h>
#include <spine/extension.h>
#include <stdio.h>
spTriangulator* spTriangulator_create() {
spTriangulator* triangulator = CALLOC(spTriangulator, 1);
triangulator->convexPolygons = spArrayFloatArray_create(16);
triangulator->convexPolygonsIndices = spArrayShortArray_create(16);
triangulator->indicesArray = spShortArray_create(128);
triangulator->isConcaveArray = spIntArray_create(128);
triangulator->triangles = spShortArray_create(128);
triangulator->polygonPool = spArrayFloatArray_create(16);
triangulator->polygonIndicesPool = spArrayShortArray_create(128);
return triangulator;
}
void spTriangulator_dispose(spTriangulator* self) {
int i;
for (i = 0; i < self->convexPolygons->size; i++) {
spFloatArray_dispose(self->convexPolygons->items[i]);
}
spArrayFloatArray_dispose(self->convexPolygons);
for (i = 0; i < self->convexPolygonsIndices->size; i++) {
spShortArray_dispose(self->convexPolygonsIndices->items[i]);
}
spArrayShortArray_dispose(self->convexPolygonsIndices);
spShortArray_dispose(self->indicesArray);
spIntArray_dispose(self->isConcaveArray);
spShortArray_dispose(self->triangles);
for (i = 0; i < self->polygonPool->size; i++) {
spFloatArray_dispose(self->polygonPool->items[i]);
}
spArrayFloatArray_dispose(self->polygonPool);
for (i = 0; i < self->polygonIndicesPool->size; i++) {
spShortArray_dispose(self->polygonIndicesPool->items[i]);
}
spArrayShortArray_dispose(self->polygonIndicesPool);
FREE(self);
}
static spFloatArray* _obtainPolygon(spTriangulator* self) {
if (self->polygonPool->size == 0) return spFloatArray_create(16);
else return spArrayFloatArray_pop(self->polygonPool);
}
static void _freePolygon(spTriangulator* self, spFloatArray* polygon) {
spArrayFloatArray_add(self->polygonPool, polygon);
}
static void _freeAllPolygons(spTriangulator* self, spArrayFloatArray* polygons) {
int i;
for (i = 0; i < polygons->size; i++) {
_freePolygon(self, polygons->items[i]);
}
}
static spShortArray* _obtainPolygonIndices(spTriangulator* self) {
if (self->polygonIndicesPool->size == 0) return spShortArray_create(16);
else return spArrayShortArray_pop(self->polygonIndicesPool);
}
static void _freePolygonIndices(spTriangulator* self, spShortArray* indices) {
spArrayShortArray_add(self->polygonIndicesPool, indices);
}
static void _freeAllPolygonIndices(spTriangulator* self, spArrayShortArray* polygonIndices) {
int i;
for (i = 0; i < polygonIndices->size; i++) {
_freePolygonIndices(self, polygonIndices->items[i]);
}
}
static int _positiveArea(float p1x, float p1y, float p2x, float p2y, float p3x, float p3y) {
return p1x * (p3y - p2y) + p2x * (p1y - p3y) + p3x * (p2y - p1y) >= 0;
}
static int _isConcave(int index, int vertexCount, float* vertices, short* indices) {
int previous = indices[(vertexCount + index - 1) % vertexCount] << 1;
int current = indices[index] << 1;
int next = indices[(index + 1) % vertexCount] << 1;
return !_positiveArea(vertices[previous], vertices[previous + 1],
vertices[current], vertices[current + 1],
vertices[next], vertices[next + 1]);
}
static int _winding (float p1x, float p1y, float p2x, float p2y, float p3x, float p3y) {
float px = p2x - p1x, py = p2y - p1y;
return p3x * py - p3y * px + px * p1y - p1x * py >= 0 ? 1 : -1;
}
spShortArray* spTriangulator_triangulate(spTriangulator* self, spFloatArray* verticesArray) {
float* vertices = verticesArray->items;
int vertexCount = verticesArray->size >> 1;
int i, n, ii;
spShortArray* indicesArray = self->indicesArray;
short* indices;
spIntArray* isConcaveArray;
int* isConcave;
spShortArray* triangles;
spShortArray_clear(indicesArray);
indices = spShortArray_setSize(indicesArray, vertexCount)->items;
for (i = 0; i < vertexCount; i++)
indices[i] = (short)i;
isConcaveArray = self->isConcaveArray;
isConcave = spIntArray_setSize(isConcaveArray, vertexCount)->items;
for (i = 0, n = vertexCount; i < n; ++i)
isConcave[i] = _isConcave(i, vertexCount, vertices, indices);
triangles = self->triangles;
spShortArray_clear(triangles);
spShortArray_ensureCapacity(triangles, MAX(0, vertexCount - 2) << 2);
while (vertexCount > 3) {
int previous = vertexCount - 1, next = 1;
int previousIndex, nextIndex;
i = 0;
while (1) {
if (!isConcave[i]) {
int p1 = indices[previous] << 1, p2 = indices[i] << 1, p3 = indices[next] << 1;
float p1x = vertices[p1], p1y = vertices[p1 + 1];
float p2x = vertices[p2], p2y = vertices[p2 + 1];
float p3x = vertices[p3], p3y = vertices[p3 + 1];
for (ii = (next + 1) % vertexCount; ii != previous; ii = (ii + 1) % vertexCount) {
int v;
float vx, vy;
if (!isConcave[ii]) continue;
v = indices[ii] << 1;
vx = vertices[v]; vy = vertices[v + 1];
if (_positiveArea(p3x, p3y, p1x, p1y, vx, vy)) {
if (_positiveArea(p1x, p1y, p2x, p2y, vx, vy)) {
if (_positiveArea(p2x, p2y, p3x, p3y, vx, vy)) goto break_outer;
}
}
}
break;
}
break_outer:
if (next == 0) {
do {
if (!isConcave[i]) break;
i--;
} while (i > 0);
break;
}
previous = i;
i = next;
next = (next + 1) % vertexCount;
}
spShortArray_add(triangles, indices[(vertexCount + i - 1) % vertexCount]);
spShortArray_add(triangles, indices[i]);
spShortArray_add(triangles, indices[(i + 1) % vertexCount]);
spShortArray_removeAt(indicesArray, i);
spIntArray_removeAt(isConcaveArray, i);
vertexCount--;
previousIndex = (vertexCount + i - 1) % vertexCount;
nextIndex = i == vertexCount ? 0 : i;
isConcave[previousIndex] = _isConcave(previousIndex, vertexCount, vertices, indices);
isConcave[nextIndex] = _isConcave(nextIndex, vertexCount, vertices, indices);
}
if (vertexCount == 3) {
spShortArray_add(triangles, indices[2]);
spShortArray_add(triangles, indices[0]);
spShortArray_add(triangles, indices[1]);
}
return triangles;
}
spArrayFloatArray* spTriangulator_decompose(spTriangulator* self, spFloatArray* verticesArray, spShortArray* triangles) {
float* vertices = verticesArray->items;
spArrayFloatArray* convexPolygons = self->convexPolygons;
spArrayShortArray* convexPolygonsIndices;
spShortArray* polygonIndices;
spFloatArray* polygon;
int fanBaseIndex, lastWinding;
short* trianglesItems;
int i, n;
_freeAllPolygons(self, convexPolygons);
spArrayFloatArray_clear(convexPolygons);
convexPolygonsIndices = self->convexPolygonsIndices;
_freeAllPolygonIndices(self, convexPolygonsIndices);
spArrayShortArray_clear(convexPolygonsIndices);
polygonIndices = _obtainPolygonIndices(self);
spShortArray_clear(polygonIndices);
polygon = _obtainPolygon(self);
spFloatArray_clear(polygon);
fanBaseIndex = -1; lastWinding = 0;
trianglesItems = triangles->items;
for (i = 0, n = triangles->size; i < n; i += 3) {
int t1 = trianglesItems[i] << 1, t2 = trianglesItems[i + 1] << 1, t3 = trianglesItems[i + 2] << 1;
float x1 = vertices[t1], y1 = vertices[t1 + 1];
float x2 = vertices[t2], y2 = vertices[t2 + 1];
float x3 = vertices[t3], y3 = vertices[t3 + 1];
int merged = 0;
if (fanBaseIndex == t1) {
int o = polygon->size - 4;
float* p = polygon->items;
int winding1 = _winding(p[o], p[o + 1], p[o + 2], p[o + 3], x3, y3);
int winding2 = _winding(x3, y3, p[0], p[1], p[2], p[3]);
if (winding1 == lastWinding && winding2 == lastWinding) {
spFloatArray_add(polygon, x3);
spFloatArray_add(polygon, y3);
spShortArray_add(polygonIndices, t3);
merged = 1;
}
}
if (!merged) {
if (polygon->size > 0) {
spArrayFloatArray_add(convexPolygons, polygon);
spArrayShortArray_add(convexPolygonsIndices, polygonIndices);
} else {
_freePolygon(self, polygon);
_freePolygonIndices(self, polygonIndices);
}
polygon = _obtainPolygon(self);
spFloatArray_clear(polygon);
spFloatArray_add(polygon, x1);
spFloatArray_add(polygon, y1);
spFloatArray_add(polygon, x2);
spFloatArray_add(polygon, y2);
spFloatArray_add(polygon, x3);
spFloatArray_add(polygon, y3);
polygonIndices = _obtainPolygonIndices(self);
spShortArray_clear(polygonIndices);
spShortArray_add(polygonIndices, t1);
spShortArray_add(polygonIndices, t2);
spShortArray_add(polygonIndices, t3);
lastWinding = _winding(x1, y1, x2, y2, x3, y3);
fanBaseIndex = t1;
}
}
if (polygon->size > 0) {
spArrayFloatArray_add(convexPolygons, polygon);
spArrayShortArray_add(convexPolygonsIndices, polygonIndices);
}
for (i = 0, n = convexPolygons->size; i < n; i++) {
int firstIndex, lastIndex;
int o;
float* p;
float prevPrevX, prevPrevY, prevX, prevY, firstX, firstY, secondX, secondY;
int winding;
int ii;
polygonIndices = convexPolygonsIndices->items[i];
if (polygonIndices->size == 0) continue;
firstIndex = polygonIndices->items[0];
lastIndex = polygonIndices->items[polygonIndices->size - 1];
polygon = convexPolygons->items[i];
o = polygon->size - 4;
p = polygon->items;
prevPrevX = p[o]; prevPrevY = p[o + 1];
prevX = p[o + 2]; prevY = p[o + 3];
firstX = p[0]; firstY = p[1];
secondX = p[2]; secondY = p[3];
winding = _winding(prevPrevX, prevPrevY, prevX, prevY, firstX, firstY);
for (ii = 0; ii < n; ii++) {
spShortArray* otherIndices;
int otherFirstIndex, otherSecondIndex, otherLastIndex;
spFloatArray* otherPoly;
float x3, y3;
int winding1, winding2;
if (ii == i) continue;
otherIndices = convexPolygonsIndices->items[ii];
if (otherIndices->size != 3) continue;
otherFirstIndex = otherIndices->items[0];
otherSecondIndex = otherIndices->items[1];
otherLastIndex = otherIndices->items[2];
otherPoly = convexPolygons->items[ii];
x3 = otherPoly->items[otherPoly->size - 2]; y3 = otherPoly->items[otherPoly->size - 1];
if (otherFirstIndex != firstIndex || otherSecondIndex != lastIndex) continue;
winding1 = _winding(prevPrevX, prevPrevY, prevX, prevY, x3, y3);
winding2 = _winding(x3, y3, firstX, firstY, secondX, secondY);
if (winding1 == winding && winding2 == winding) {
spFloatArray_clear(otherPoly);
spShortArray_clear(otherIndices);
spFloatArray_add(polygon, x3);
spFloatArray_add(polygon, y3);
spShortArray_add(polygonIndices, otherLastIndex);
prevPrevX = prevX;
prevPrevY = prevY;
prevX = x3;
prevY = y3;
ii = 0;
}
}
}
for (i = convexPolygons->size - 1; i >= 0; i--) {
polygon = convexPolygons->items[i];
if (polygon->size == 0) {
spArrayFloatArray_removeAt(convexPolygons, i);
_freePolygon(self, polygon);
polygonIndices = convexPolygonsIndices->items[i];
spArrayShortArray_removeAt(convexPolygonsIndices, i);
_freePolygonIndices(self, polygonIndices);
}
}
return convexPolygons;
}

View File

@ -0,0 +1,141 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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.
*****************************************************************************/
#include <spine/VertexAttachment.h>
#include <spine/extension.h>
/* FIXME this is not thread-safe */
static int nextID = 0;
void _spVertexAttachment_init (spVertexAttachment* attachment) {
attachment->id = (nextID++ & 65535) << 11;
attachment->deformAttachment = attachment;
}
void _spVertexAttachment_deinit (spVertexAttachment* attachment) {
_spAttachment_deinit(SUPER(attachment));
FREE(attachment->bones);
FREE(attachment->vertices);
}
void spVertexAttachment_computeWorldVertices (spVertexAttachment* self, spSlot* slot, int start, int count, float* worldVertices, int offset, int stride) {
spSkeleton* skeleton;
int deformLength;
float* deformArray;
float* vertices;
int* bones;
count = offset + (count >> 1) * stride;
skeleton = slot->bone->skeleton;
deformLength = slot->deformCount;
deformArray = slot->deform;
vertices = self->vertices;
bones = self->bones;
if (!bones) {
spBone* bone;
int v, w;
float x, y;
if (deformLength > 0) vertices = deformArray;
bone = slot->bone;
x = bone->worldX;
y = bone->worldY;
for (v = start, w = offset; w < count; v += 2, w += stride) {
float vx = vertices[v], vy = vertices[v + 1];
worldVertices[w] = vx * bone->a + vy * bone->b + x;
worldVertices[w + 1] = vx * bone->c + vy * bone->d + y;
}
} else {
int v = 0, skip = 0, i;
spBone** skeletonBones;
for (i = 0; i < start; i += 2) {
int n = bones[v];
v += n + 1;
skip += n;
}
skeletonBones = skeleton->bones;
if (deformLength == 0) {
int w, b;
for (w = offset, b = skip * 3; w < count; w += stride) {
float wx = 0, wy = 0;
int n = bones[v++];
n += v;
for (; v < n; v++, b += 3) {
spBone* bone = skeletonBones[bones[v]];
float vx = vertices[b], vy = vertices[b + 1], weight = vertices[b + 2];
wx += (vx * bone->a + vy * bone->b + bone->worldX) * weight;
wy += (vx * bone->c + vy * bone->d + bone->worldY) * weight;
}
worldVertices[w] = wx;
worldVertices[w + 1] = wy;
}
} else {
int w, b, f;
for (w = offset, b = skip * 3, f = skip << 1; w < count; w += stride) {
float wx = 0, wy = 0;
int n = bones[v++];
n += v;
for (; v < n; v++, b += 3, f += 2) {
spBone* bone = skeletonBones[bones[v]];
float vx = vertices[b] + deformArray[f], vy = vertices[b + 1] + deformArray[f + 1], weight = vertices[b + 2];
wx += (vx * bone->a + vy * bone->b + bone->worldX) * weight;
wy += (vx * bone->c + vy * bone->d + bone->worldY) * weight;
}
worldVertices[w] = wx;
worldVertices[w + 1] = wy;
}
}
}
}
void spVertexAttachment_copyTo(spVertexAttachment* from, spVertexAttachment* to) {
if (from->bonesCount) {
to->bonesCount = from->bonesCount;
to->bones = MALLOC(int, from->bonesCount);
memcpy(to->bones, from->bones, from->bonesCount * sizeof(int));
} else {
to->bonesCount = 0;
if (to->bones) {
FREE(to->bones);
to->bones = 0;
}
}
if (from->verticesCount) {
to->verticesCount = from->verticesCount;
to->vertices = MALLOC(float, from->verticesCount);
memcpy(to->vertices, from->vertices, from->verticesCount * sizeof(float));
} else {
to->verticesCount = 0;
if (to->vertices) {
FREE(to->vertices);
to->vertices = 0;
}
}
to->worldVerticesLength = from->worldVerticesLength;
}

View File

@ -0,0 +1,109 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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.
*****************************************************************************/
#include <spine/VertexEffect.h>
#include <spine/extension.h>
void _spJitterVertexEffect_begin(spVertexEffect* self, spSkeleton* skeleton) {
UNUSED(self);
UNUSED(skeleton);
}
void _spJitterVertexEffect_transform(spVertexEffect* self, float* x, float* y, float* u, float* v, spColor* light, spColor* dark) {
spJitterVertexEffect* internal = (spJitterVertexEffect*)self;
float jitterX = internal->jitterX;
float jitterY = internal->jitterY;
(*x) += _spMath_randomTriangular(-jitterX, jitterY);
(*y) += _spMath_randomTriangular(-jitterX, jitterY);
UNUSED(u);
UNUSED(v);
UNUSED(light);
UNUSED(dark);
}
void _spJitterVertexEffect_end(spVertexEffect* self) {
UNUSED(self);
}
spJitterVertexEffect* spJitterVertexEffect_create(float jitterX, float jitterY) {
spJitterVertexEffect* effect = CALLOC(spJitterVertexEffect, 1);
effect->super.begin = _spJitterVertexEffect_begin;
effect->super.transform = _spJitterVertexEffect_transform;
effect->super.end = _spJitterVertexEffect_end;
effect->jitterX = jitterX;
effect->jitterY = jitterY;
return effect;
}
void spJitterVertexEffect_dispose(spJitterVertexEffect* effect) {
FREE(effect);
}
void _spSwirlVertexEffect_begin(spVertexEffect* self, spSkeleton* skeleton) {
spSwirlVertexEffect* internal = (spSwirlVertexEffect*)self;
internal->worldX = skeleton->x + internal->centerX;
internal->worldY = skeleton->y + internal->centerY;
}
void _spSwirlVertexEffect_transform(spVertexEffect* self, float* positionX, float* positionY, float* u, float* v, spColor* light, spColor* dark) {
spSwirlVertexEffect* internal = (spSwirlVertexEffect*)self;
float radAngle = internal->angle * DEG_RAD;
float x = *positionX - internal->worldX;
float y = *positionY - internal->worldY;
float dist = SQRT(x * x + y * y);
if (dist < internal->radius) {
float theta = _spMath_interpolate(_spMath_pow2_apply, 0, radAngle, (internal->radius - dist) / internal->radius);
float cosine = COS(theta);
float sine = SIN(theta);
(*positionX) = cosine * x - sine * y + internal->worldX;
(*positionY) = sine * x + cosine * y + internal->worldY;
}
UNUSED(self);
UNUSED(u);
UNUSED(v);
UNUSED(light);
UNUSED(dark);
}
void _spSwirlVertexEffect_end(spVertexEffect* self) {
UNUSED(self);
}
spSwirlVertexEffect* spSwirlVertexEffect_create(float radius) {
spSwirlVertexEffect* effect = CALLOC(spSwirlVertexEffect, 1);
effect->super.begin = _spSwirlVertexEffect_begin;
effect->super.transform = _spSwirlVertexEffect_transform;
effect->super.end = _spSwirlVertexEffect_end;
effect->radius = radius;
return effect;
}
void spSwirlVertexEffect_dispose(spSwirlVertexEffect* effect) {
FREE(effect);
}

View File

@ -0,0 +1,325 @@
/******************************************************************************
* Spine Runtimes License Agreement
* Last updated January 1, 2020. Replaces all prior versions.
*
* Copyright (c) 2013-2020, 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.
*****************************************************************************/
#include <spine/extension.h>
#include <stdio.h>
#include <raylib.h>
#include <rlgl.h>
#define MAX_TEXTURES 10
static Texture2D tm_textures[MAX_TEXTURES] = {0};
static int texture_index = 0;
typedef struct Vertex {
// Position in x/y plane
float x, y;
// UV coordinates
float u, v;
// Color, each channel in the range from 0-1
// (Should really be a 32-bit RGBA packed color)
float r, g, b, a;
} Vertex;
#define MAX_VERTICES_PER_ATTACHMENT 2048
float worldVerticesPositions[MAX_VERTICES_PER_ATTACHMENT];
Vertex vertices[MAX_VERTICES_PER_ATTACHMENT];
void addVertex(float x, float y, float u, float v, float r, float g, float b, float a, int* index) {
Vertex* vertex = &vertices[*index];
vertex->x = x;
vertex->y = y;
vertex->u = u;
vertex->v = v;
vertex->r = r;
vertex->g = g;
vertex->b = b;
vertex->a = a;
*index += 1;
}
void draw_vertex(Vertex vertex, Vector3 position){
rlTexCoord2f(vertex.u, vertex.v);
rlColor4f(vertex.r, vertex.g, vertex.b, vertex.a);
rlVertex3f( position.x + vertex.x, position.y + vertex.y, position.z);
}
void engine_drawMesh(Vertex* vertices, int numVertices, Texture* texture, Vector3 position){
Vertex vertex;
rlEnableTexture(texture->id);
rlPushMatrix();
{
rlBegin(RL_QUADS);
{
rlNormal3f(0.0f, 0.0f, 1.0f);
for (int i = 0; i < numVertices; i++){
if(i < 3 || i == 4){
vertex = vertices[i];
draw_vertex(vertex, position);
}
}
}rlEnd();
}rlPopMatrix();
rlDisableTexture();
}
Texture2D* texture_2d_create(char *path) {
tm_textures[texture_index] = LoadTexture(path);
Texture2D *t = &tm_textures[texture_index];
texture_index++;
return t;
}
void texture_2d_destroy() {
while(texture_index--) UnloadTexture(tm_textures[texture_index]);
}
float _spInternalRandom () {
return rand() / (float)RAND_MAX;
}
static void* (*mallocFunc) (size_t size) = malloc;
static void* (*reallocFunc) (void* ptr, size_t size) = realloc;
static void* (*debugMallocFunc) (size_t size, const char* file, int line) = NULL;
static void (*freeFunc) (void* ptr) = free;
static float (*randomFunc) () = _spInternalRandom;
void* _spMalloc (size_t size, const char* file, int line) {
if(debugMallocFunc)
return debugMallocFunc(size, file, line);
return mallocFunc(size);
}
void* _spCalloc (size_t num, size_t size, const char* file, int line) {
void* ptr = _spMalloc(num * size, file, line);
if (ptr) memset(ptr, 0, num * size);
return ptr;
}
void* _spRealloc(void* ptr, size_t size) {
return reallocFunc(ptr, size);
}
void _spFree (void* ptr) {
freeFunc(ptr);
}
float _spRandom () {
return randomFunc();
}
void _spSetDebugMalloc(void* (*malloc) (size_t size, const char* file, int line)) {
debugMallocFunc = malloc;
}
void _spSetMalloc (void* (*malloc) (size_t size)) {
mallocFunc = malloc;
}
void _spSetRealloc (void* (*realloc) (void* ptr, size_t size)) {
reallocFunc = realloc;
}
void _spSetFree (void (*free) (void* ptr)) {
freeFunc = free;
}
void _spSetRandom (float (*random) ()) {
randomFunc = random;
}
char* _spReadFile (const char* path, int* length) {
char *data;
FILE *file = fopen(path, "rb");
if (!file) return 0;
fseek(file, 0, SEEK_END);
*length = (int)ftell(file);
fseek(file, 0, SEEK_SET);
data = MALLOC(char, *length);
fread(data, 1, *length, file);
fclose(file);
return data;
}
char* _spUtil_readFile(const char* path, int* length) {
return _spReadFile(path, length);
}
void _spAtlasPage_createTexture (spAtlasPage* self, const char* path) {
Texture2D* t = texture_2d_create((char *)path);
self->rendererObject = t;
self->width = t->width;
self->height = t->height;
}
#define MAX_VERTICES_PER_ATTACHMENT 2048
float worldVerticesPositions[MAX_VERTICES_PER_ATTACHMENT];
Vertex vertices[MAX_VERTICES_PER_ATTACHMENT];
void drawSkeleton(spSkeleton* skeleton, Vector3 position) {
// For each slot in the draw order array of the skeleton
for (int i = 0; i < skeleton->slotsCount; ++i) {
spSlot* slot = skeleton->drawOrder[i];
// Fetch the currently active attachment, continue
// with the next slot in the draw order if no
// attachment is active on the slot
spAttachment* attachment = slot->attachment;
if (!attachment) continue;
// Calculate the tinting color based on the skeleton's color
// and the slot's color. Each color channel is given in the
// range [0-1], you may have to multiply by 255 and cast to
// and int if your engine uses integer ranges for color channels.
float tintR = skeleton->color.r * slot->color.r;
float tintG = skeleton->color.g * slot->color.g;
float tintB = skeleton->color.b * slot->color.b;
float tintA = skeleton->color.a * slot->color.a;
// Fill the vertices array depending on the type of attachment
Texture* texture = 0;
int vertexIndex = 0;
if (attachment->type == SP_ATTACHMENT_REGION) {
// Cast to an spRegionAttachment so we can get the rendererObject
// and compute the world vertices
spRegionAttachment* regionAttachment = (spRegionAttachment*)attachment;
// Our engine specific Texture is stored in the spAtlasRegion which was
// assigned to the attachment on load. It represents the texture atlas
// page that contains the image the region attachment is mapped to
texture = (Texture*)((spAtlasRegion*)regionAttachment->rendererObject)->page->rendererObject;
// Computed the world vertices positions for the 4 vertices that make up
// the rectangular region attachment. This assumes the world transform of the
// bone to which the slot (and hence attachment) is attached has been calculated
// before rendering via spSkeleton_updateWorldTransform
spRegionAttachment_computeWorldVertices(regionAttachment, slot->bone, worldVerticesPositions, 0, 2);
// Create 2 triangles, with 3 vertices each from the region's
// world vertex positions and its UV coordinates (in the range [0-1]).
addVertex(worldVerticesPositions[0], worldVerticesPositions[1],
regionAttachment->uvs[0], regionAttachment->uvs[1],
tintR, tintG, tintB, tintA, &vertexIndex);
addVertex(worldVerticesPositions[2], worldVerticesPositions[3],
regionAttachment->uvs[2], regionAttachment->uvs[3],
tintR, tintG, tintB, tintA, &vertexIndex);
addVertex(worldVerticesPositions[4], worldVerticesPositions[5],
regionAttachment->uvs[4], regionAttachment->uvs[5],
tintR, tintG, tintB, tintA, &vertexIndex);
addVertex(worldVerticesPositions[4], worldVerticesPositions[5],
regionAttachment->uvs[4], regionAttachment->uvs[5],
tintR, tintG, tintB, tintA, &vertexIndex);
addVertex(worldVerticesPositions[6], worldVerticesPositions[7],
regionAttachment->uvs[6], regionAttachment->uvs[7],
tintR, tintG, tintB, tintA, &vertexIndex);
addVertex(worldVerticesPositions[0], worldVerticesPositions[1],
regionAttachment->uvs[0], regionAttachment->uvs[1],
tintR, tintG, tintB, tintA, &vertexIndex);
} else if (attachment->type == SP_ATTACHMENT_MESH) {
// Cast to an spMeshAttachment so we can get the rendererObject
// and compute the world vertices
spMeshAttachment* mesh = (spMeshAttachment*)attachment;
// Check the number of vertices in the mesh attachment. If it is bigger
// than our scratch buffer, we don't render the mesh. We do this here
// for simplicity, in production you want to reallocate the scratch buffer
// to fit the mesh.
if (mesh->super.worldVerticesLength > MAX_VERTICES_PER_ATTACHMENT) continue;
// Our engine specific Texture is stored in the spAtlasRegion which was
// assigned to the attachment on load. It represents the texture atlas
// page that contains the image the mesh attachment is mapped to
texture = (Texture*)((spAtlasRegion*)mesh->rendererObject)->page->rendererObject;
// Computed the world vertices positions for the vertices that make up
// the mesh attachment. This assumes the world transform of the
// bone to which the slot (and hence attachment) is attached has been calculated
// before rendering via spSkeleton_updateWorldTransform
spVertexAttachment_computeWorldVertices(SUPER(mesh), slot, 0, mesh->super.worldVerticesLength, worldVerticesPositions, 0, 2);
// Mesh attachments use an array of vertices, and an array of indices to define which
// 3 vertices make up each triangle. We loop through all triangle indices
// and simply emit a vertex for each triangle's vertex.
for (int i = 0; i < mesh->trianglesCount; ++i) {
int index = mesh->triangles[i] << 1;
addVertex(worldVerticesPositions[index], worldVerticesPositions[index + 1],
mesh->uvs[index], mesh->uvs[index + 1],
tintR, tintG, tintB, tintA, &vertexIndex);
}
}
// Draw the mesh we created for the attachment
engine_drawMesh(vertices, vertexIndex, texture, position);
}
}
void _spAtlasPage_disposeTexture (spAtlasPage* self) {
if (self->rendererObject == NULL) return;
Texture2D *t2d = self->rendererObject;
UnloadTexture(*t2d);
}
float _spMath_random(float min, float max) {
return min + (max - min) * _spRandom();
}
float _spMath_randomTriangular(float min, float max) {
return _spMath_randomTriangularWith(min, max, (min + max) * 0.5f);
}
float _spMath_randomTriangularWith(float min, float max, float mode) {
float u = _spRandom();
float d = max - min;
if (u <= (mode - min) / d) return min + SQRT(u * d * (mode - min));
return max - SQRT((1 - u) * d * (max - mode));
}
float _spMath_interpolate(float (*apply) (float a), float start, float end, float a) {
return start + (end - start) * apply(a);
}
float _spMath_pow2_apply(float a) {
if (a <= 0.5) return POW(a * 2, 2) / 2;
return POW((a - 1) * 2, 2) / -2 + 1;
}
float _spMath_pow2out_apply(float a) {
return POW(a - 1, 2) * -1 + 1;
}