From 4e542e2931c7524c7d4d2baa4a289a7df5e286b2 Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Wed, 27 Sep 2017 16:42:00 -0400 Subject: [PATCH 01/83] Initial Commit, nothing special going on here yet! --- spine-cpp/LICENSE | 27 + spine-cpp/README.md | 40 + spine-cpp/spine-cpp/include/spine/Animation.h | 588 +++++++ .../spine-cpp/include/spine/AnimationState.h | 185 ++ .../include/spine/AnimationStateData.h | 77 + spine-cpp/spine-cpp/include/spine/Array.h | 133 ++ spine-cpp/spine-cpp/include/spine/Atlas.h | 174 ++ .../include/spine/AtlasAttachmentLoader.h | 58 + .../spine-cpp/include/spine/Attachment.h | 83 + .../include/spine/AttachmentLoader.h | 79 + spine-cpp/spine-cpp/include/spine/Bone.h | 127 ++ spine-cpp/spine-cpp/include/spine/BoneData.h | 85 + .../include/spine/BoundingBoxAttachment.h | 59 + .../include/spine/ClippingAttachment.h | 61 + spine-cpp/spine-cpp/include/spine/Color.h | 78 + spine-cpp/spine-cpp/include/spine/Event.h | 72 + spine-cpp/spine-cpp/include/spine/EventData.h | 69 + .../spine-cpp/include/spine/IkConstraint.h | 87 + .../include/spine/IkConstraintData.h | 76 + .../spine-cpp/include/spine/MeshAttachment.h | 91 + .../spine-cpp/include/spine/PathAttachment.h | 63 + .../spine-cpp/include/spine/PathConstraint.h | 113 ++ .../include/spine/PathConstraintData.h | 97 ++ .../spine-cpp/include/spine/PointAttachment.h | 65 + .../include/spine/RegionAttachment.h | 75 + spine-cpp/spine-cpp/include/spine/Skeleton.h | 174 ++ .../spine-cpp/include/spine/SkeletonBinary.h | 72 + .../spine-cpp/include/spine/SkeletonBounds.h | 113 ++ .../include/spine/SkeletonClipping.h | 68 + .../spine-cpp/include/spine/SkeletonData.h | 117 ++ .../spine-cpp/include/spine/SkeletonJson.h | 73 + spine-cpp/spine-cpp/include/spine/Skin.h | 95 + spine-cpp/spine-cpp/include/spine/Slot.h | 93 + spine-cpp/spine-cpp/include/spine/SlotData.h | 90 + .../include/spine/TransformConstraint.h | 81 + .../include/spine/TransformConstraintData.h | 87 + .../spine-cpp/include/spine/Triangulator.h | 63 + .../include/spine/VertexAttachment.h | 68 + .../spine-cpp/include/spine/VertexEffect.h | 85 + spine-cpp/spine-cpp/include/spine/dll.h | 48 + spine-cpp/spine-cpp/include/spine/extension.h | 318 ++++ spine-cpp/spine-cpp/include/spine/spine.h | 63 + spine-cpp/spine-cpp/src/spine/Animation.c | 1529 +++++++++++++++++ .../spine-cpp/src/spine/AnimationState.c | 932 ++++++++++ .../spine-cpp/src/spine/AnimationStateData.c | 151 ++ spine-cpp/spine-cpp/src/spine/Array.c | 39 + spine-cpp/spine-cpp/src/spine/Atlas.c | 359 ++++ .../src/spine/AtlasAttachmentLoader.c | 100 ++ spine-cpp/spine-cpp/src/spine/Attachment.c | 57 + .../spine-cpp/src/spine/AttachmentLoader.c | 98 ++ spine-cpp/spine-cpp/src/spine/Bone.c | 304 ++++ spine-cpp/spine-cpp/src/spine/BoneData.c | 48 + .../src/spine/BoundingBoxAttachment.c | 47 + .../spine-cpp/src/spine/ClippingAttachment.c | 48 + spine-cpp/spine-cpp/src/spine/Color.c | 84 + spine-cpp/spine-cpp/src/spine/Event.c | 44 + spine-cpp/spine-cpp/src/spine/EventData.c | 44 + spine-cpp/spine-cpp/src/spine/IkConstraint.c | 208 +++ .../spine-cpp/src/spine/IkConstraintData.c | 46 + spine-cpp/spine-cpp/src/spine/Json.c | 426 +++++ spine-cpp/spine-cpp/src/spine/Json.h | 83 + .../spine-cpp/src/spine/MeshAttachment.c | 100 ++ .../spine-cpp/src/spine/PathAttachment.c | 48 + .../spine-cpp/src/spine/PathConstraint.c | 467 +++++ .../spine-cpp/src/spine/PathConstraintData.c | 44 + .../spine-cpp/src/spine/PointAttachment.c | 61 + .../spine-cpp/src/spine/RegionAttachment.c | 130 ++ spine-cpp/spine-cpp/src/spine/Skeleton.c | 583 +++++++ .../spine-cpp/src/spine/SkeletonBinary.c | 1095 ++++++++++++ .../spine-cpp/src/spine/SkeletonBounds.c | 205 +++ .../spine-cpp/src/spine/SkeletonClipping.c | 313 ++++ spine-cpp/spine-cpp/src/spine/SkeletonData.c | 147 ++ spine-cpp/spine-cpp/src/spine/SkeletonJson.c | 1119 ++++++++++++ spine-cpp/spine-cpp/src/spine/Skin.c | 106 ++ spine-cpp/spine-cpp/src/spine/Slot.c | 82 + spine-cpp/spine-cpp/src/spine/SlotData.c | 56 + .../spine-cpp/src/spine/TransformConstraint.c | 273 +++ .../src/spine/TransformConstraintData.c | 44 + spine-cpp/spine-cpp/src/spine/Triangulator.c | 361 ++++ .../spine-cpp/src/spine/VertexAttachment.c | 114 ++ spine-cpp/spine-cpp/src/spine/VertexEffect.c | 98 ++ spine-cpp/spine-cpp/src/spine/extension.c | 128 ++ spine-cpp/spine-cpp/src/spine/kvec.h | 105 ++ 83 files changed, 14696 insertions(+) create mode 100644 spine-cpp/LICENSE create mode 100644 spine-cpp/README.md create mode 100644 spine-cpp/spine-cpp/include/spine/Animation.h create mode 100644 spine-cpp/spine-cpp/include/spine/AnimationState.h create mode 100644 spine-cpp/spine-cpp/include/spine/AnimationStateData.h create mode 100644 spine-cpp/spine-cpp/include/spine/Array.h create mode 100644 spine-cpp/spine-cpp/include/spine/Atlas.h create mode 100644 spine-cpp/spine-cpp/include/spine/AtlasAttachmentLoader.h create mode 100644 spine-cpp/spine-cpp/include/spine/Attachment.h create mode 100644 spine-cpp/spine-cpp/include/spine/AttachmentLoader.h create mode 100644 spine-cpp/spine-cpp/include/spine/Bone.h create mode 100644 spine-cpp/spine-cpp/include/spine/BoneData.h create mode 100644 spine-cpp/spine-cpp/include/spine/BoundingBoxAttachment.h create mode 100644 spine-cpp/spine-cpp/include/spine/ClippingAttachment.h create mode 100644 spine-cpp/spine-cpp/include/spine/Color.h create mode 100644 spine-cpp/spine-cpp/include/spine/Event.h create mode 100644 spine-cpp/spine-cpp/include/spine/EventData.h create mode 100644 spine-cpp/spine-cpp/include/spine/IkConstraint.h create mode 100644 spine-cpp/spine-cpp/include/spine/IkConstraintData.h create mode 100644 spine-cpp/spine-cpp/include/spine/MeshAttachment.h create mode 100644 spine-cpp/spine-cpp/include/spine/PathAttachment.h create mode 100644 spine-cpp/spine-cpp/include/spine/PathConstraint.h create mode 100644 spine-cpp/spine-cpp/include/spine/PathConstraintData.h create mode 100644 spine-cpp/spine-cpp/include/spine/PointAttachment.h create mode 100644 spine-cpp/spine-cpp/include/spine/RegionAttachment.h create mode 100644 spine-cpp/spine-cpp/include/spine/Skeleton.h create mode 100644 spine-cpp/spine-cpp/include/spine/SkeletonBinary.h create mode 100644 spine-cpp/spine-cpp/include/spine/SkeletonBounds.h create mode 100644 spine-cpp/spine-cpp/include/spine/SkeletonClipping.h create mode 100644 spine-cpp/spine-cpp/include/spine/SkeletonData.h create mode 100644 spine-cpp/spine-cpp/include/spine/SkeletonJson.h create mode 100644 spine-cpp/spine-cpp/include/spine/Skin.h create mode 100644 spine-cpp/spine-cpp/include/spine/Slot.h create mode 100644 spine-cpp/spine-cpp/include/spine/SlotData.h create mode 100644 spine-cpp/spine-cpp/include/spine/TransformConstraint.h create mode 100644 spine-cpp/spine-cpp/include/spine/TransformConstraintData.h create mode 100644 spine-cpp/spine-cpp/include/spine/Triangulator.h create mode 100644 spine-cpp/spine-cpp/include/spine/VertexAttachment.h create mode 100644 spine-cpp/spine-cpp/include/spine/VertexEffect.h create mode 100644 spine-cpp/spine-cpp/include/spine/dll.h create mode 100644 spine-cpp/spine-cpp/include/spine/extension.h create mode 100644 spine-cpp/spine-cpp/include/spine/spine.h create mode 100644 spine-cpp/spine-cpp/src/spine/Animation.c create mode 100644 spine-cpp/spine-cpp/src/spine/AnimationState.c create mode 100644 spine-cpp/spine-cpp/src/spine/AnimationStateData.c create mode 100644 spine-cpp/spine-cpp/src/spine/Array.c create mode 100644 spine-cpp/spine-cpp/src/spine/Atlas.c create mode 100644 spine-cpp/spine-cpp/src/spine/AtlasAttachmentLoader.c create mode 100644 spine-cpp/spine-cpp/src/spine/Attachment.c create mode 100644 spine-cpp/spine-cpp/src/spine/AttachmentLoader.c create mode 100644 spine-cpp/spine-cpp/src/spine/Bone.c create mode 100644 spine-cpp/spine-cpp/src/spine/BoneData.c create mode 100644 spine-cpp/spine-cpp/src/spine/BoundingBoxAttachment.c create mode 100644 spine-cpp/spine-cpp/src/spine/ClippingAttachment.c create mode 100644 spine-cpp/spine-cpp/src/spine/Color.c create mode 100644 spine-cpp/spine-cpp/src/spine/Event.c create mode 100644 spine-cpp/spine-cpp/src/spine/EventData.c create mode 100644 spine-cpp/spine-cpp/src/spine/IkConstraint.c create mode 100644 spine-cpp/spine-cpp/src/spine/IkConstraintData.c create mode 100644 spine-cpp/spine-cpp/src/spine/Json.c create mode 100644 spine-cpp/spine-cpp/src/spine/Json.h create mode 100644 spine-cpp/spine-cpp/src/spine/MeshAttachment.c create mode 100644 spine-cpp/spine-cpp/src/spine/PathAttachment.c create mode 100644 spine-cpp/spine-cpp/src/spine/PathConstraint.c create mode 100644 spine-cpp/spine-cpp/src/spine/PathConstraintData.c create mode 100644 spine-cpp/spine-cpp/src/spine/PointAttachment.c create mode 100644 spine-cpp/spine-cpp/src/spine/RegionAttachment.c create mode 100644 spine-cpp/spine-cpp/src/spine/Skeleton.c create mode 100644 spine-cpp/spine-cpp/src/spine/SkeletonBinary.c create mode 100644 spine-cpp/spine-cpp/src/spine/SkeletonBounds.c create mode 100644 spine-cpp/spine-cpp/src/spine/SkeletonClipping.c create mode 100644 spine-cpp/spine-cpp/src/spine/SkeletonData.c create mode 100644 spine-cpp/spine-cpp/src/spine/SkeletonJson.c create mode 100644 spine-cpp/spine-cpp/src/spine/Skin.c create mode 100644 spine-cpp/spine-cpp/src/spine/Slot.c create mode 100644 spine-cpp/spine-cpp/src/spine/SlotData.c create mode 100644 spine-cpp/spine-cpp/src/spine/TransformConstraint.c create mode 100644 spine-cpp/spine-cpp/src/spine/TransformConstraintData.c create mode 100644 spine-cpp/spine-cpp/src/spine/Triangulator.c create mode 100644 spine-cpp/spine-cpp/src/spine/VertexAttachment.c create mode 100644 spine-cpp/spine-cpp/src/spine/VertexEffect.c create mode 100644 spine-cpp/spine-cpp/src/spine/extension.c create mode 100644 spine-cpp/spine-cpp/src/spine/kvec.h diff --git a/spine-cpp/LICENSE b/spine-cpp/LICENSE new file mode 100644 index 000000000..daceab94a --- /dev/null +++ b/spine-cpp/LICENSE @@ -0,0 +1,27 @@ +Spine Runtimes Software License v2.5 + +Copyright (c) 2013-2016, Esoteric Software +All rights reserved. + +You are granted a perpetual, non-exclusive, non-sublicensable, and +non-transferable license to use, install, execute, and perform the Spine +Runtimes software and derivative works solely for personal or internal +use. Without the written permission of Esoteric Software (see Section 2 of +the Spine Software License Agreement), you may not (a) modify, translate, +adapt, or develop new applications using the Spine Runtimes or otherwise +create derivative works or improvements of the Spine Runtimes or (b) remove, +delete, alter, or obscure any trademarks or any copyright, trademark, patent, +or other intellectual property or proprietary rights notices on or in the +Software, including any copy thereof. Redistributions in binary or source +form must include this license and terms. + +THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/spine-cpp/README.md b/spine-cpp/README.md new file mode 100644 index 000000000..03c7df908 --- /dev/null +++ b/spine-cpp/README.md @@ -0,0 +1,40 @@ +# spine-cpp + +The spine-cpp runtime provides basic functionality to load and manipulate [Spine](http://esotericsoftware.com) skeletal animation data using C++. It does not perform rendering but can be extended to enable Spine animations for other projects that utilize C++. Note, this library uses C++03 for maximum portability and therefore does not take advantage of any C++11 or newer features such as std::unique_ptr. + +## Licensing + +This Spine Runtime may only be used for personal or internal use, typically to evaluate Spine before purchasing. If you would like to incorporate a Spine Runtime into your applications, distribute software containing a Spine Runtime, or modify a Spine Runtime, then you will need a valid [Spine license](https://esotericsoftware.com/spine-purchase). Please see the [Spine Runtimes Software License](https://github.com/EsotericSoftware/spine-runtimes/blob/master/LICENSE) for detailed information. + +The Spine Runtimes are developed with the intent to be used with data exported from Spine. By purchasing Spine, `Section 2` of the [Spine Software License](https://esotericsoftware.com/files/license.txt) grants the right to create and distribute derivative works of the Spine Runtimes. + +## Spine version + +spine-cpp works with data exported from Spine 3.6.xx. + +spine-cpp supports all Spine features. + +## Setup + +1. Download the Spine Runtimes source using [git](https://help.github.com/articles/set-up-git) or by downloading it [as a zip](https://github.com/EsotericSoftware/spine-runtimes/archive/3.6.zip). +1. Open the `spine-c.sln` Visual C++ 2010 Express project file. For other IDEs, you will need to create a new project and import the source. + +Alternatively, the contents of the `spine-c/spine-c/src` and `spine-c/spine-c/include` directories can be copied into your project. Be sure your header search is configured to find the contents of the `spine-c/spine-c/include` directory. Note that the includes use `spine/Xxx.h`, so the `spine` directory cannot be omitted when copying the files. + +If `SPINE_SHORT_NAMES` is defined, the `sp` prefix for all structs and functions is optional. Only use this if the spine-c names won't cause a conflict. + +## Extension + +Extending spine-c requires implementing three methods: + +- `_spAtlasPage_createTexture` Loads a texture and stores it and its size in the `void* rendererObject`, `width` and `height` fields of an `spAtlasPage` struct. +- `_spAtlasPage_disposeTexture` Disposes of a texture loaded with `_spAtlasPage_createTexture`. +- `_spUtil_readFile` Reads a file. If this doesn't need to be customized, `_readFile` is provided which reads a file using `fopen`. + +With these implemented, the spine-c API can then be used to load Spine animation data. Rendering is done by enumerating the slots for a skeleton and rendering the attachment for each slot. Each attachment has a `rendererObject` field that is set when the attachment is loaded. + +For example, `AtlasAttachmentLoader` is typically used to load attachments when using a Spine texture atlas. When `AtlasAttachmentLoader` loads a `RegionAttachment`, the attachment's `void* rendererObject` is set to an `AtlasRegion`. Rendering code can then obtain the `AtlasRegion` from the attachment, get the `AtlasPage` it belongs to, and get the page's `void* rendererObject`. This is the renderer specific texture object set by `_spAtlasPage_createTexture`. Attachment loading can be [customized](http://esotericsoftware.com/spine-using-runtimes/#attachmentloader) if not using `AtlasAttachmentLoader` or to provider different renderer specific data. + +[spine-sfml](https://github.com/EsotericSoftware/spine-runtimes/blob/master/spine-sfml/src/spine/spine-sfml.cpp#L39) serves as a simple example of extending spine-c. + +spine-c uses an OOP style of programming where each "class" is made up of a struct and a number of functions prefixed with the struct name. More detals about how this works are available in [extension.h](https://github.com/EsotericSoftware/spine-runtimes/blob/master/spine-c/spine-c/include/spine/extension.h#L2). This mechanism allows you to provide your own implementations for `spAttachmentLoader`, `spAttachment` and `spTimeline`, if necessary. diff --git a/spine-cpp/spine-cpp/include/spine/Animation.h b/spine-cpp/spine-cpp/include/spine/Animation.h new file mode 100644 index 000000000..e47a835ce --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/Animation.h @@ -0,0 +1,588 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_ANIMATION_H_ +#define SPINE_ANIMATION_H_ + +#include +#include +#include + +#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_POSE_SETUP, + SP_MIX_POSE_CURRENT, + SP_MIX_POSE_CURRENT_LAYERED +} spMixPose; + +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, spMixPose pose, 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, spMixPose pose, 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 = 3; + +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, int bendDirection); + +#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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/AnimationState.h b/spine-cpp/spine-cpp/include/spine/AnimationState.h new file mode 100644 index 000000000..fe6ae515a --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/AnimationState.h @@ -0,0 +1,185 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_ANIMATIONSTATE_H_ +#define SPINE_ANIMATIONSTATE_H_ + +#include +#include +#include +#include +#include + +#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; + spAnimationStateListener listener; + int trackIndex; + int /*boolean*/ loop; + float eventThreshold, attachmentThreshold, drawOrderThreshold; + float animationStart, animationEnd, animationLast, nextAnimationLast; + float delay, trackTime, trackLast, nextTrackLast, trackEnd, timeScale; + float alpha, mixTime, mixDuration, interruptAlpha, totalAlpha; + spIntArray* timelineData; + spTrackEntryArray* timelineDipMix; + float* timelinesRotation; + int timelinesRotationCount; + void* rendererObject; + void* userData; + +#ifdef __cplusplus + spTrackEntry() : + animation(0), + next(0), mixingFrom(0), + listener(0), + trackIndex(0), + loop(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), + timelineData(0), + timelineDipMix(0), + timelinesRotation(0), + timelinesRotationCount(0) { + } +#endif +}; + +struct spAnimationState { + spAnimationStateData* const data; + + int tracksCount; + spTrackEntry** tracks; + + spAnimationStateListener listener; + + float timeScale; + + spTrackEntryArray* mixingTo; + + void* rendererObject; + +#ifdef __cplusplus + spAnimationState() : + data(0), + tracksCount(0), + tracks(0), + listener(0), + timeScale(0), + mixingTo(0), + rendererObject(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(...) spAnimatinState_setEmptyAnimation(__VA_ARGS__) +#define AnimationState_addEmptyAnimation(...) spAnimatinState_addEmptyAnimation(__VA_ARGS__) +#define AnimationState_setEmptyAnimations(...) spAnimatinState_setEmptyAnimations(__VA_ARGS__) +#define AnimationState_getCurrent(...) spAnimationState_getCurrent(__VA_ARGS__) +#define AnimationState_clearListenerNotifications(...) spAnimatinState_clearListenerNotifications(__VA_ARGS__) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* SPINE_ANIMATIONSTATE_H_ */ diff --git a/spine-cpp/spine-cpp/include/spine/AnimationStateData.h b/spine-cpp/spine-cpp/include/spine/AnimationStateData.h new file mode 100644 index 000000000..95f936e80 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/AnimationStateData.h @@ -0,0 +1,77 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_ANIMATIONSTATEDATA_H_ +#define SPINE_ANIMATIONSTATEDATA_H_ + +#include +#include +#include + +#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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/Array.h b/spine-cpp/spine-cpp/include/spine/Array.h new file mode 100644 index 000000000..3beb08325 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/Array.h @@ -0,0 +1,133 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_ARRAY_H +#define SPINE_ARRAY_H + +#include + +#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 */ diff --git a/spine-cpp/spine-cpp/include/spine/Atlas.h b/spine-cpp/spine-cpp/include/spine/Atlas.h new file mode 100644 index 000000000..7812e0440 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/Atlas.h @@ -0,0 +1,174 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_ATLAS_H_ +#define SPINE_ATLAS_H_ + +#include + +#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/*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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/AtlasAttachmentLoader.h b/spine-cpp/spine-cpp/include/spine/AtlasAttachmentLoader.h new file mode 100644 index 000000000..6b9ed688e --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/AtlasAttachmentLoader.h @@ -0,0 +1,58 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_ATLASATTACHMENTLOADER_H_ +#define SPINE_ATLASATTACHMENTLOADER_H_ + +#include +#include +#include + +#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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/Attachment.h b/spine-cpp/spine-cpp/include/spine/Attachment.h new file mode 100644 index 000000000..286a8bec4 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/Attachment.h @@ -0,0 +1,83 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_ATTACHMENT_H_ +#define SPINE_ATTACHMENT_H_ + +#include + +#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; + struct spAttachmentLoader* attachmentLoader; + +#ifdef __cplusplus + spAttachment() : + name(0), + type(SP_ATTACHMENT_REGION), + vtable(0) { + } +#endif +} spAttachment; + +void spAttachment_dispose (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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/AttachmentLoader.h b/spine-cpp/spine-cpp/include/spine/AttachmentLoader.h new file mode 100644 index 000000000..f0f556553 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/AttachmentLoader.h @@ -0,0 +1,79 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_ATTACHMENTLOADER_H_ +#define SPINE_ATTACHMENTLOADER_H_ + +#include +#include +#include + +#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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/Bone.h b/spine-cpp/spine-cpp/include/spine/Bone.h new file mode 100644 index 000000000..12b2af928 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/Bone.h @@ -0,0 +1,127 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_BONE_H_ +#define SPINE_BONE_H_ + +#include +#include + +#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; + +#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) { + } +#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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/BoneData.h b/spine-cpp/spine-cpp/include/spine/BoneData.h new file mode 100644 index 000000000..d73162b2b --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/BoneData.h @@ -0,0 +1,85 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_BONEDATA_H_ +#define SPINE_BONEDATA_H_ + +#include + +#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; + +#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) { + } +#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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/BoundingBoxAttachment.h b/spine-cpp/spine-cpp/include/spine/BoundingBoxAttachment.h new file mode 100644 index 000000000..2c9194b69 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/BoundingBoxAttachment.h @@ -0,0 +1,59 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_BOUNDINGBOXATTACHMENT_H_ +#define SPINE_BOUNDINGBOXATTACHMENT_H_ + +#include +#include +#include +#include +#include + +#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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/ClippingAttachment.h b/spine-cpp/spine-cpp/include/spine/ClippingAttachment.h new file mode 100644 index 000000000..8683437c7 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/ClippingAttachment.h @@ -0,0 +1,61 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_CLIPPINGATTACHMENT_H_ +#define SPINE_CLIPPINGATTACHMENT_H_ + +#include +#include +#include +#include +#include + +#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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/Color.h b/spine-cpp/spine-cpp/include/spine/Color.h new file mode 100644 index 000000000..272ba9552 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/Color.h @@ -0,0 +1,78 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_COLOR_H_ +#define SPINE_COLOR_H_ + +#include + +#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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/Event.h b/spine-cpp/spine-cpp/include/spine/Event.h new file mode 100644 index 000000000..c92b713de --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/Event.h @@ -0,0 +1,72 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_EVENT_H_ +#define SPINE_EVENT_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct spEvent { + spEventData* const data; + float const time; + int intValue; + float floatValue; + const char* stringValue; + +#ifdef __cplusplus + spEvent() : + data(0), + time(0), + intValue(0), + floatValue(0), + stringValue(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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/EventData.h b/spine-cpp/spine-cpp/include/spine/EventData.h new file mode 100644 index 000000000..70b955071 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/EventData.h @@ -0,0 +1,69 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_EVENTDATA_H_ +#define SPINE_EVENTDATA_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct spEventData { + const char* const name; + int intValue; + float floatValue; + const char* stringValue; + +#ifdef __cplusplus + spEventData() : + name(0), + intValue(0), + floatValue(0), + stringValue(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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/IkConstraint.h b/spine-cpp/spine-cpp/include/spine/IkConstraint.h new file mode 100644 index 000000000..e5b0f7b72 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/IkConstraint.h @@ -0,0 +1,87 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_IKCONSTRAINT_H_ +#define SPINE_IKCONSTRAINT_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct spSkeleton; + +typedef struct spIkConstraint { + spIkConstraintData* const data; + + int bonesCount; + spBone** bones; + + spBone* target; + int bendDirection; + float mix; + +#ifdef __cplusplus + spIkConstraint() : + data(0), + bonesCount(0), + bones(0), + target(0), + bendDirection(0), + mix(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, float alpha); +SP_API void spIkConstraint_apply2 (spBone* parent, spBone* child, float targetX, float targetY, int bendDirection, 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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/IkConstraintData.h b/spine-cpp/spine-cpp/include/spine/IkConstraintData.h new file mode 100644 index 000000000..fc3f3cc09 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/IkConstraintData.h @@ -0,0 +1,76 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_IKCONSTRAINTDATA_H_ +#define SPINE_IKCONSTRAINTDATA_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct spIkConstraintData { + const char* const name; + int order; + int bonesCount; + spBoneData** bones; + + spBoneData* target; + int bendDirection; + float mix; + +#ifdef __cplusplus + spIkConstraintData() : + name(0), + bonesCount(0), + bones(0), + target(0), + bendDirection(0), + mix(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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/MeshAttachment.h b/spine-cpp/spine-cpp/include/spine/MeshAttachment.h new file mode 100644 index 000000000..2876abfd5 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/MeshAttachment.h @@ -0,0 +1,91 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_MESHATTACHMENT_H_ +#define SPINE_MESHATTACHMENT_H_ + +#include +#include +#include +#include +#include + +#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; + + const char* path; + + float* regionUVs; + float* uvs; + + int trianglesCount; + unsigned short* triangles; + + spColor color; + + int hullLength; + + spMeshAttachment* const parentMesh; + int/*bool*/inheritDeform; + + /* 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); + +#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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/PathAttachment.h b/spine-cpp/spine-cpp/include/spine/PathAttachment.h new file mode 100644 index 000000000..a953924a1 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/PathAttachment.h @@ -0,0 +1,63 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_PATHATTACHMENT_H_ +#define SPINE_PATHATTACHMENT_H_ + +#include +#include +#include +#include +#include + +#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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraint.h b/spine-cpp/spine-cpp/include/spine/PathConstraint.h new file mode 100644 index 000000000..9d0ec10be --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/PathConstraint.h @@ -0,0 +1,113 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_PATHCONSTRAINT_H_ +#define SPINE_PATHCONSTRAINT_H_ + +#include +#include +#include +#include +#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]; + +#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) { + } +#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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraintData.h b/spine-cpp/spine-cpp/include/spine/PathConstraintData.h new file mode 100644 index 000000000..5a24cc37f --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/PathConstraintData.h @@ -0,0 +1,97 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_PATHCONSTRAINTDATA_H_ +#define SPINE_PATHCONSTRAINTDATA_H_ + +#include +#include +#include + +#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 bonesCount; + spBoneData** const bones; + spSlotData* target; + spPositionMode positionMode; + spSpacingMode spacingMode; + spRotateMode rotateMode; + float offsetRotation; + float position, spacing, rotateMix, translateMix; + +#ifdef __cplusplus + spPathConstraintData() : + name(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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/PointAttachment.h b/spine-cpp/spine-cpp/include/spine/PointAttachment.h new file mode 100644 index 000000000..da8df6cbb --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/PointAttachment.h @@ -0,0 +1,65 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_POINTATTACHMENT_H_ +#define SPINE_POINTATTACHMENT_H_ + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct spPointAttachment { + spVertexAttachment 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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/RegionAttachment.h b/spine-cpp/spine-cpp/include/spine/RegionAttachment.h new file mode 100644 index 000000000..9e23d5bdf --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/RegionAttachment.h @@ -0,0 +1,75 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_REGIONATTACHMENT_H_ +#define SPINE_REGIONATTACHMENT_H_ + +#include +#include +#include +#include + +#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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/Skeleton.h b/spine-cpp/spine-cpp/include/spine/Skeleton.h new file mode 100644 index 000000000..0df9fe076 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/Skeleton.h @@ -0,0 +1,174 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_SKELETON_H_ +#define SPINE_SKELETON_H_ + +#include +#include +#include +#include +#include +#include +#include + +#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; + int/*bool*/flipX, flipY; + 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), + flipX(0), + flipY(0), + 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_*/ diff --git a/spine-cpp/spine-cpp/include/spine/SkeletonBinary.h b/spine-cpp/spine-cpp/include/spine/SkeletonBinary.h new file mode 100644 index 000000000..3d96a1da9 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/SkeletonBinary.h @@ -0,0 +1,72 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_SKELETONBINARY_H_ +#define SPINE_SKELETONBINARY_H_ + +#include +#include +#include +#include +#include + +#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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/SkeletonBounds.h b/spine-cpp/spine-cpp/include/spine/SkeletonBounds.h new file mode 100644 index 000000000..da435c0a7 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/SkeletonBounds.h @@ -0,0 +1,113 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_SKELETONBOUNDS_H_ +#define SPINE_SKELETONBOUNDS_H_ + +#include +#include +#include + +#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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/SkeletonClipping.h b/spine-cpp/spine-cpp/include/spine/SkeletonClipping.h new file mode 100644 index 000000000..74f21fccb --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/SkeletonClipping.h @@ -0,0 +1,68 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_SKELETONCLIPPING_H +#define SPINE_SKELETONCLIPPING_H + +#include +#include +#include +#include +#include + +#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 */ diff --git a/spine-cpp/spine-cpp/include/spine/SkeletonData.h b/spine-cpp/spine-cpp/include/spine/SkeletonData.h new file mode 100644 index 000000000..5cbf3e1d4 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/SkeletonData.h @@ -0,0 +1,117 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_SKELETONDATA_H_ +#define SPINE_SKELETONDATA_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct spSkeletonData { + const char* version; + const char* hash; + float width, height; + + 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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/SkeletonJson.h b/spine-cpp/spine-cpp/include/spine/SkeletonJson.h new file mode 100644 index 000000000..96f1b86ec --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/SkeletonJson.h @@ -0,0 +1,73 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_SKELETONJSON_H_ +#define SPINE_SKELETONJSON_H_ + +#include +#include +#include +#include +#include +#include + +#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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/Skin.h b/spine-cpp/spine-cpp/include/spine/Skin.h new file mode 100644 index 000000000..806cde877 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/Skin.h @@ -0,0 +1,95 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_SKIN_H_ +#define SPINE_SKIN_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct spSkeleton; + +typedef struct spSkin { + const char* const name; + +#ifdef __cplusplus + spSkin() : + name(0) { + } +#endif +} spSkin; + +/* Private structs, needed by Skeleton */ +typedef struct _Entry _Entry; +struct _Entry { + int slotIndex; + const char* name; + spAttachment* attachment; + _Entry* next; +}; + +typedef struct { + spSkin super; + _Entry* entries; +} _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_addAttachment (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); + +#ifdef SPINE_SHORT_NAMES +typedef spSkin Skin; +#define Skin_create(...) spSkin_create(__VA_ARGS__) +#define Skin_dispose(...) spSkin_dispose(__VA_ARGS__) +#define Skin_addAttachment(...) 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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/Slot.h b/spine-cpp/spine-cpp/include/spine/Slot.h new file mode 100644 index 000000000..04647689a --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/Slot.h @@ -0,0 +1,93 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_SLOT_H_ +#define SPINE_SLOT_H_ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct spSlot { + spSlotData* const data; + spBone* const bone; + spColor color; + spColor* darkColor; + spAttachment* const attachment; + + int attachmentVerticesCapacity; + int attachmentVerticesCount; + float* attachmentVertices; + +#ifdef __cplusplus + spSlot() : + data(0), + bone(0), + color(), + darkColor(0), + attachment(0), + attachmentVerticesCapacity(0), + attachmentVerticesCount(0), + attachmentVertices(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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/SlotData.h b/spine-cpp/spine-cpp/include/spine/SlotData.h new file mode 100644 index 000000000..1e12da61a --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/SlotData.h @@ -0,0 +1,90 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_SLOTDATA_H_ +#define SPINE_SLOTDATA_H_ + +#include +#include +#include + +#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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/TransformConstraint.h b/spine-cpp/spine-cpp/include/spine/TransformConstraint.h new file mode 100644 index 000000000..07721cf14 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/TransformConstraint.h @@ -0,0 +1,81 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_TRANSFORMCONSTRAINT_H_ +#define SPINE_TRANSFORMCONSTRAINT_H_ + +#include +#include +#include + +#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; + +#ifdef __cplusplus + spTransformConstraint() : + data(0), + bonesCount(0), + bones(0), + target(0), + rotateMix(0), + translateMix(0), + scaleMix(0), + shearMix(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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h b/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h new file mode 100644 index 000000000..8e6c33ff7 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h @@ -0,0 +1,87 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_TRANSFORMCONSTRAINTDATA_H_ +#define SPINE_TRANSFORMCONSTRAINTDATA_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct spTransformConstraintData { + const char* const name; + int order; + 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), + 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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/Triangulator.h b/spine-cpp/spine-cpp/include/spine/Triangulator.h new file mode 100644 index 000000000..69863b2f7 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/Triangulator.h @@ -0,0 +1,63 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_TRIANGULATOR_H +#define SPINE_TRIANGULATOR_H + +#include +#include + +#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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/VertexAttachment.h b/spine-cpp/spine-cpp/include/spine/VertexAttachment.h new file mode 100644 index 000000000..7d232cc6e --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/VertexAttachment.h @@ -0,0 +1,68 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_VERTEXATTACHMENT_H_ +#define SPINE_VERTEXATTACHMENT_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct spVertexAttachment spVertexAttachment; +struct spVertexAttachment { + spAttachment super; + + int bonesCount; + int* bones; + + int verticesCount; + float* vertices; + + int worldVerticesLength; + + int id; +}; + +SP_API void spVertexAttachment_computeWorldVertices (spVertexAttachment* self, spSlot* slot, int start, int count, float* worldVertices, int offset, int stride); + +#ifdef SPINE_SHORT_NAMES +typedef spVertexAttachment VertexAttachment; +#define VertexAttachment_computeWorldVertices(...) spVertexAttachment_computeWorldVertices(__VA_ARGS__) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* SPINE_VERTEXATTACHMENT_H_ */ diff --git a/spine-cpp/spine-cpp/include/spine/VertexEffect.h b/spine-cpp/spine-cpp/include/spine/VertexEffect.h new file mode 100644 index 000000000..4f670119b --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/VertexEffect.h @@ -0,0 +1,85 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_VERTEXEFFECT_H_ +#define SPINE_VERTEXEFFECT_H_ + +#include +#include +#include + +#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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/dll.h b/spine-cpp/spine-cpp/include/spine/dll.h new file mode 100644 index 000000000..02714ca45 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/dll.h @@ -0,0 +1,48 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, 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 + #define DLLIMPORT + #define DLLEXPORT +#endif + +#ifdef SPINEPLUGIN_API + #define SP_API SPINEPLUGIN_API +#else + #define SP_API +#endif + +#endif /* SPINE_SHAREDLIB_H */ diff --git a/spine-cpp/spine-cpp/include/spine/extension.h b/spine-cpp/spine-cpp/include/spine/extension.h new file mode 100644 index 000000000..0823b5667 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/extension.h @@ -0,0 +1,318 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, 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_ + +/* 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 PI 3.1415926535897932385f +#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: (A) > 0 ? 1 : 0) + +#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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 (); + +void _spSetMalloc (void* (*_malloc) (size_t size)); +void _spSetDebugMalloc (void* (*_malloc) (size_t size, const char* file, int line)); +void _spSetRealloc(void* (*_realloc) (void* ptr, size_t size)); +void _spSetFree (void (*_free) (void* ptr)); +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)); +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, spMixPose pose, 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, spMixPose pose, 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 + +#endif /* SPINE_EXTENSION_H_ */ diff --git a/spine-cpp/spine-cpp/include/spine/spine.h b/spine-cpp/spine-cpp/include/spine/spine.h new file mode 100644 index 000000000..5085ed8e3 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/spine.h @@ -0,0 +1,63 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef SPINE_SPINE_H_ +#define SPINE_SPINE_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif /* SPINE_SPINE_H_ */ diff --git a/spine-cpp/spine-cpp/src/spine/Animation.c b/spine-cpp/spine-cpp/src/spine/Animation.c new file mode 100644 index 000000000..0c2c7194f --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/Animation.c @@ -0,0 +1,1529 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include +#include +#include + +spAnimation* spAnimation_create (const char* name, int timelinesCount) { + spAnimation* self = NEW(spAnimation); + MALLOC_STR(self->name, name); + self->timelinesCount = timelinesCount; + self->timelines = MALLOC(spTimeline*, timelinesCount); + return self; +} + +void spAnimation_dispose (spAnimation* self) { + int i; + for (i = 0; i < self->timelinesCount; ++i) + spTimeline_dispose(self->timelines[i]); + FREE(self->timelines); + FREE(self->name); + FREE(self); +} + +void spAnimation_apply (const spAnimation* self, spSkeleton* skeleton, float lastTime, float time, int loop, spEvent** events, + int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) { + int i, n = self->timelinesCount; + + if (loop && self->duration) { + time = FMOD(time, self->duration); + if (lastTime > 0) lastTime = FMOD(lastTime, self->duration); + } + + for (i = 0; i < n; ++i) + spTimeline_apply(self->timelines[i], skeleton, lastTime, time, events, eventsCount, alpha, pose, direction); +} + +/**/ + +typedef struct _spTimelineVtable { + void (*apply) (const spTimeline* self, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents, + int* eventsCount, float alpha, spMixPose pose, spMixDirection direction); + int (*getPropertyId) (const spTimeline* self); + void (*dispose) (spTimeline* self); +} _spTimelineVtable; + +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, spMixPose pose, spMixDirection direction), + int (*getPropertyId) (const spTimeline* self)) { + CONST_CAST(spTimelineType, self->type) = type; + CONST_CAST(_spTimelineVtable*, self->vtable) = NEW(_spTimelineVtable); + VTABLE(spTimeline, self)->dispose = dispose; + VTABLE(spTimeline, self)->apply = apply; + VTABLE(spTimeline, self)->getPropertyId = getPropertyId; +} + +void _spTimeline_deinit (spTimeline* self) { + FREE(self->vtable); +} + +void spTimeline_dispose (spTimeline* self) { + VTABLE(spTimeline, self)->dispose(self); +} + +void spTimeline_apply (const spTimeline* self, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents, + int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) { + VTABLE(spTimeline, self)->apply(self, skeleton, lastTime, time, firedEvents, eventsCount, alpha, pose, direction); +} + +int spTimeline_getPropertyId (const spTimeline* self) { + return VTABLE(spTimeline, self)->getPropertyId(self); +} + +/**/ + +static const float CURVE_LINEAR = 0, CURVE_STEPPED = 1, CURVE_BEZIER = 2; +static const int BEZIER_SIZE = 10 * 2 - 1; + +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, spMixPose pose, spMixDirection direction), + int (*getPropertyId)(const spTimeline* self)) { + _spTimeline_init(SUPER(self), type, dispose, apply, getPropertyId); + self->curves = CALLOC(float, (framesCount - 1) * BEZIER_SIZE); +} + +void _spCurveTimeline_deinit (spCurveTimeline* self) { + _spTimeline_deinit(SUPER(self)); + FREE(self->curves); +} + +void spCurveTimeline_setLinear (spCurveTimeline* self, int frameIndex) { + self->curves[frameIndex * BEZIER_SIZE] = CURVE_LINEAR; +} + +void spCurveTimeline_setStepped (spCurveTimeline* self, int frameIndex) { + self->curves[frameIndex * BEZIER_SIZE] = CURVE_STEPPED; +} + +void spCurveTimeline_setCurve (spCurveTimeline* self, int frameIndex, float cx1, float cy1, float cx2, float cy2) { + float tmpx = (-cx1 * 2 + cx2) * 0.03f, tmpy = (-cy1 * 2 + cy2) * 0.03f; + float dddfx = ((cx1 - cx2) * 3 + 1) * 0.006f, dddfy = ((cy1 - cy2) * 3 + 1) * 0.006f; + float ddfx = tmpx * 2 + dddfx, ddfy = tmpy * 2 + dddfy; + float dfx = cx1 * 0.3f + tmpx + dddfx * 0.16666667f, dfy = cy1 * 0.3f + tmpy + dddfy * 0.16666667f; + float x = dfx, y = dfy; + + int i = frameIndex * BEZIER_SIZE, n = i + BEZIER_SIZE - 1; + self->curves[i++] = CURVE_BEZIER; + + for (; i < n; i += 2) { + self->curves[i] = x; + self->curves[i + 1] = y; + dfx += ddfx; + dfy += ddfy; + ddfx += dddfx; + ddfy += dddfy; + x += dfx; + y += dfy; + } +} + +float spCurveTimeline_getCurvePercent (const spCurveTimeline* self, int frameIndex, float percent) { + float x, y; + int i = frameIndex * BEZIER_SIZE, start, n; + float type = self->curves[i]; + percent = CLAMP(percent, 0, 1); + if (type == CURVE_LINEAR) return percent; + if (type == CURVE_STEPPED) return 0; + i++; + x = 0; + for (start = i, n = i + BEZIER_SIZE - 1; i < n; i += 2) { + x = self->curves[i]; + if (x >= percent) { + float prevX, prevY; + if (i == start) { + prevX = 0; + prevY = 0; + } else { + prevX = self->curves[i - 2]; + prevY = self->curves[i - 1]; + } + return prevY + (self->curves[i + 1] - prevY) * (percent - prevX) / (x - prevX); + } + } + y = self->curves[i - 1]; + return y + (1 - y) * (percent - x) / (1 - x); /* Last point is 1,1. */ +} + +/* @param target After the first and before the last entry. */ +static int binarySearch (float *values, int valuesLength, float target, int step) { + int low = 0, current; + int high = valuesLength / step - 2; + if (high == 0) return step; + current = high >> 1; + while (1) { + if (values[(current + 1) * step] <= target) + low = current + 1; + else + high = current; + if (low == high) return (low + 1) * step; + current = (low + high) >> 1; + } + return 0; +} + +int _spCurveTimeline_binarySearch (float *values, int valuesLength, float target, int step) { + return binarySearch(values, valuesLength, target, step); +} + +/* @param target After the first and before the last entry. */ +static int binarySearch1 (float *values, int valuesLength, float target) { + int low = 0, current; + int high = valuesLength - 2; + if (high == 0) return 1; + current = high >> 1; + while (1) { + if (values[(current + 1)] <= target) + low = current + 1; + else + high = current; + if (low == high) return low + 1; + current = (low + high) >> 1; + } + return 0; +} + +/**/ + +void _spBaseTimeline_dispose (spTimeline* timeline) { + struct spBaseTimeline* self = SUB_CAST(struct spBaseTimeline, timeline); + _spCurveTimeline_deinit(SUPER(self)); + FREE(self->frames); + FREE(self); +} + +/* Many timelines have structure identical to struct spBaseTimeline and extend spCurveTimeline. **/ +struct spBaseTimeline* _spBaseTimeline_create (int framesCount, spTimelineType type, int frameSize, /**/ + void (*apply) (const spTimeline* self, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents, + int* eventsCount, float alpha, spMixPose pose, spMixDirection direction), + int (*getPropertyId) (const spTimeline* self)) { + struct spBaseTimeline* self = NEW(struct spBaseTimeline); + _spCurveTimeline_init(SUPER(self), type, framesCount, _spBaseTimeline_dispose, apply, getPropertyId); + + CONST_CAST(int, self->framesCount) = framesCount * frameSize; + CONST_CAST(float*, self->frames) = CALLOC(float, self->framesCount); + + return self; +} + +/**/ + +void _spRotateTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents, + int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) { + spBone *bone; + int frame; + float prevRotation, frameTime, percent, r; + + spRotateTimeline* self = SUB_CAST(spRotateTimeline, timeline); + + bone = skeleton->bones[self->boneIndex]; + if (time < self->frames[0]) { + switch (pose) { + case SP_MIX_POSE_SETUP: + bone->rotation = bone->data->rotation; + return; + case SP_MIX_POSE_CURRENT: + case SP_MIX_POSE_CURRENT_LAYERED: /* to appease compiler */ + r = bone->data->rotation - bone->rotation; + r -= (16384 - (int)(16384.499999999996 - r / 360)) * 360; + bone->rotation += r * alpha; + } + return; + } + + if (time >= self->frames[self->framesCount - ROTATE_ENTRIES]) { /* Time is after last frame. */ + if (pose == SP_MIX_POSE_SETUP) + bone->rotation = bone->data->rotation + self->frames[self->framesCount + ROTATE_PREV_ROTATION] * alpha; + else { + r = bone->data->rotation + self->frames[self->framesCount + ROTATE_PREV_ROTATION] - bone->rotation; + r -= (16384 - (int)(16384.499999999996 - r / 360)) * 360; /* Wrap within -180 and 180. */ + bone->rotation += r * alpha; + } + return; + } + + /* Interpolate between the previous frame and the current frame. */ + frame = binarySearch(self->frames, self->framesCount, time, ROTATE_ENTRIES); + prevRotation = self->frames[frame + ROTATE_PREV_ROTATION]; + frameTime = self->frames[frame]; + percent = spCurveTimeline_getCurvePercent(SUPER(self), (frame >> 1) - 1, 1 - (time - frameTime) / (self->frames[frame + ROTATE_PREV_TIME] - frameTime)); + + r = self->frames[frame + ROTATE_ROTATION] - prevRotation; + r -= (16384 - (int)(16384.499999999996 - r / 360)) * 360; + r = prevRotation + r * percent; + if (pose == SP_MIX_POSE_SETUP) { + r -= (16384 - (int)(16384.499999999996 - r / 360)) * 360; + bone->rotation = bone->data->rotation + r * alpha; + } else { + r = bone->data->rotation + r - bone->rotation; + r -= (16384 - (int)(16384.499999999996 - r / 360)) * 360; + bone->rotation += r * alpha; + } + + UNUSED(lastTime); + UNUSED(firedEvents); + UNUSED(eventsCount); +} + +int _spRotateTimeline_getPropertyId (const spTimeline* timeline) { + return (SP_TIMELINE_ROTATE << 25) + SUB_CAST(spRotateTimeline, timeline)->boneIndex; +} + +spRotateTimeline* spRotateTimeline_create (int framesCount) { + return _spBaseTimeline_create(framesCount, SP_TIMELINE_ROTATE, ROTATE_ENTRIES, _spRotateTimeline_apply, _spRotateTimeline_getPropertyId); +} + +void spRotateTimeline_setFrame (spRotateTimeline* self, int frameIndex, float time, float degrees) { + frameIndex <<= 1; + self->frames[frameIndex] = time; + self->frames[frameIndex + ROTATE_ROTATION] = degrees; +} + +/**/ + +static const int TRANSLATE_PREV_TIME = -3, TRANSLATE_PREV_X = -2, TRANSLATE_PREV_Y = -1; +static const int TRANSLATE_X = 1, TRANSLATE_Y = 2; + +void _spTranslateTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, + spEvent** firedEvents, int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) { + spBone *bone; + int frame; + float frameTime, percent; + float x, y; + float *frames; + int framesCount; + + spTranslateTimeline* self = SUB_CAST(spTranslateTimeline, timeline); + + bone = skeleton->bones[self->boneIndex]; + if (time < self->frames[0]) { + switch (pose) { + case SP_MIX_POSE_SETUP: + bone->x = bone->data->x; + bone->y = bone->data->y; + return; + case SP_MIX_POSE_CURRENT: + case SP_MIX_POSE_CURRENT_LAYERED: /* to appease compiler */ + bone->x += (bone->data->x - bone->x) * alpha; + bone->y += (bone->data->y - bone->y) * alpha; + } + return; + } + + frames = self->frames; + framesCount = self->framesCount; + if (time >= frames[framesCount - TRANSLATE_ENTRIES]) { /* Time is after last frame. */ + x = frames[framesCount + TRANSLATE_PREV_X]; + y = frames[framesCount + TRANSLATE_PREV_Y]; + } else { + /* Interpolate between the previous frame and the current frame. */ + frame = binarySearch(frames, framesCount, time, TRANSLATE_ENTRIES); + x = frames[frame + TRANSLATE_PREV_X]; + y = frames[frame + TRANSLATE_PREV_Y]; + frameTime = frames[frame]; + percent = spCurveTimeline_getCurvePercent(SUPER(self), frame / TRANSLATE_ENTRIES - 1, + 1 - (time - frameTime) / (frames[frame + TRANSLATE_PREV_TIME] - frameTime)); + + x += (frames[frame + TRANSLATE_X] - x) * percent; + y += (frames[frame + TRANSLATE_Y] - y) * percent; + } + if (pose == SP_MIX_POSE_SETUP) { + bone->x = bone->data->x + x * alpha; + bone->y = bone->data->y + y * alpha; + } else { + bone->x += (bone->data->x + x - bone->x) * alpha; + bone->y += (bone->data->y + y - bone->y) * alpha; + } + + UNUSED(lastTime); + UNUSED(firedEvents); + UNUSED(eventsCount); +} + +int _spTranslateTimeline_getPropertyId (const spTimeline* self) { + return (SP_TIMELINE_TRANSLATE << 24) + SUB_CAST(spTranslateTimeline, self)->boneIndex; +} + +spTranslateTimeline* spTranslateTimeline_create (int framesCount) { + return _spBaseTimeline_create(framesCount, SP_TIMELINE_TRANSLATE, TRANSLATE_ENTRIES, _spTranslateTimeline_apply, _spTranslateTimeline_getPropertyId); +} + +void spTranslateTimeline_setFrame (spTranslateTimeline* self, int frameIndex, float time, float x, float y) { + frameIndex *= TRANSLATE_ENTRIES; + self->frames[frameIndex] = time; + self->frames[frameIndex + TRANSLATE_X] = x; + self->frames[frameIndex + TRANSLATE_Y] = y; +} + +/**/ + +void _spScaleTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents, + int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) { + spBone *bone; + int frame; + float frameTime, percent, x, y; + float *frames; + int framesCount; + + spScaleTimeline* self = SUB_CAST(spScaleTimeline, timeline); + + bone = skeleton->bones[self->boneIndex]; + if (time < self->frames[0]) { + switch (pose) { + case SP_MIX_POSE_SETUP: + bone->scaleX = bone->data->scaleX; + bone->scaleY = bone->data->scaleY; + return; + case SP_MIX_POSE_CURRENT: + case SP_MIX_POSE_CURRENT_LAYERED: /* to appease compiler */ + bone->scaleX += (bone->data->scaleX - bone->scaleX) * alpha; + bone->scaleY += (bone->data->scaleY - bone->scaleY) * alpha; + } + return; + } + + frames = self->frames; + framesCount = self->framesCount; + if (time >= frames[framesCount - TRANSLATE_ENTRIES]) { /* Time is after last frame. */ + x = frames[framesCount + TRANSLATE_PREV_X] * bone->data->scaleX; + y = frames[framesCount + TRANSLATE_PREV_Y] * bone->data->scaleY; + } else { + /* Interpolate between the previous frame and the current frame. */ + frame = binarySearch(frames, framesCount, time, TRANSLATE_ENTRIES); + x = frames[frame + TRANSLATE_PREV_X]; + y = frames[frame + TRANSLATE_PREV_Y]; + frameTime = frames[frame]; + percent = spCurveTimeline_getCurvePercent(SUPER(self), frame / TRANSLATE_ENTRIES - 1, + 1 - (time - frameTime) / (frames[frame + TRANSLATE_PREV_TIME] - frameTime)); + + x = (x + (frames[frame + TRANSLATE_X] - x) * percent) * bone->data->scaleX; + y = (y + (frames[frame + TRANSLATE_Y] - y) * percent) * bone->data->scaleY; + } + if (alpha == 1) { + bone->scaleX = x; + bone->scaleY = y; + } else { + float bx, by; + if (pose == SP_MIX_POSE_SETUP) { + bx = bone->data->scaleX; + by = bone->data->scaleY; + } else { + bx = bone->scaleX; + by = bone->scaleY; + } + /* Mixing out uses sign of setup or current pose, else use sign of key. */ + if (direction == SP_MIX_DIRECTION_OUT) { + x = ABS(x) * SIGNUM(bx); + y = ABS(y) * SIGNUM(by); + } else { + bx = ABS(bx) * SIGNUM(x); + by = ABS(by) * SIGNUM(y); + } + bone->scaleX = bx + (x - bx) * alpha; + bone->scaleY = by + (y - by) * alpha; + } + + UNUSED(lastTime); + UNUSED(firedEvents); + UNUSED(eventsCount); +} + +int _spScaleTimeline_getPropertyId (const spTimeline* timeline) { + return (SP_TIMELINE_SCALE << 24) + SUB_CAST(spScaleTimeline, timeline)->boneIndex; +} + +spScaleTimeline* spScaleTimeline_create (int framesCount) { + return _spBaseTimeline_create(framesCount, SP_TIMELINE_SCALE, TRANSLATE_ENTRIES, _spScaleTimeline_apply, _spScaleTimeline_getPropertyId); +} + +void spScaleTimeline_setFrame (spScaleTimeline* self, int frameIndex, float time, float x, float y) { + spTranslateTimeline_setFrame(self, frameIndex, time, x, y); +} + +/**/ + +void _spShearTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents, + int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) { + spBone *bone; + int frame; + float frameTime, percent, x, y; + float *frames; + int framesCount; + + spShearTimeline* self = SUB_CAST(spShearTimeline, timeline); + + bone = skeleton->bones[self->boneIndex]; + frames = self->frames; + framesCount = self->framesCount; + if (time < self->frames[0]) { + switch (pose) { + case SP_MIX_POSE_SETUP: + bone->shearX = bone->data->shearX; + bone->shearY = bone->data->shearY; + return; + case SP_MIX_POSE_CURRENT: + case SP_MIX_POSE_CURRENT_LAYERED: /* to appease compiler */ + bone->shearX += (bone->data->shearX - bone->shearX) * alpha; + bone->shearY += (bone->data->shearY - bone->shearY) * alpha; + } + return; + } + + if (time >= frames[framesCount - TRANSLATE_ENTRIES]) { /* Time is after last frame. */ + x = frames[framesCount + TRANSLATE_PREV_X]; + y = frames[framesCount + TRANSLATE_PREV_Y]; + } else { + /* Interpolate between the previous frame and the current frame. */ + frame = binarySearch(frames, framesCount, time, TRANSLATE_ENTRIES); + x = frames[frame + TRANSLATE_PREV_X]; + y = frames[frame + TRANSLATE_PREV_Y]; + frameTime = frames[frame]; + percent = spCurveTimeline_getCurvePercent(SUPER(self), frame / TRANSLATE_ENTRIES - 1, + 1 - (time - frameTime) / (frames[frame + TRANSLATE_PREV_TIME] - frameTime)); + + x = x + (frames[frame + TRANSLATE_X] - x) * percent; + y = y + (frames[frame + TRANSLATE_Y] - y) * percent; + } + if (pose == SP_MIX_POSE_SETUP) { + bone->shearX = bone->data->shearX + x * alpha; + bone->shearY = bone->data->shearY + y * alpha; + } else { + bone->shearX += (bone->data->shearX + x - bone->shearX) * alpha; + bone->shearY += (bone->data->shearY + y - bone->shearY) * alpha; + } + + UNUSED(lastTime); + UNUSED(firedEvents); + UNUSED(eventsCount); +} + +int _spShearTimeline_getPropertyId (const spTimeline* timeline) { + return (SP_TIMELINE_SHEAR << 24) + SUB_CAST(spShearTimeline, timeline)->boneIndex; +} + +spShearTimeline* spShearTimeline_create (int framesCount) { + return (spShearTimeline*)_spBaseTimeline_create(framesCount, SP_TIMELINE_SHEAR, 3, _spShearTimeline_apply, _spShearTimeline_getPropertyId); +} + +void spShearTimeline_setFrame (spShearTimeline* self, int frameIndex, float time, float x, float y) { + spTranslateTimeline_setFrame(self, frameIndex, time, x, y); +} + +/**/ + +static const int COLOR_PREV_TIME = -5, COLOR_PREV_R = -4, COLOR_PREV_G = -3, COLOR_PREV_B = -2, COLOR_PREV_A = -1; +static const int COLOR_R = 1, COLOR_G = 2, COLOR_B = 3, COLOR_A = 4; + +void _spColorTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents, + int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) { + spSlot *slot; + int frame; + float percent, frameTime; + float r, g, b, a; + spColor* color; + spColor* setup; + spColorTimeline* self = (spColorTimeline*)timeline; + slot = skeleton->slots[self->slotIndex]; + + if (time < self->frames[0]) { + switch (pose) { + case SP_MIX_POSE_SETUP: + spColor_setFromColor(&slot->color, &slot->data->color); + return; + case SP_MIX_POSE_CURRENT: + case SP_MIX_POSE_CURRENT_LAYERED: /* to appease compiler */ + color = &slot->color; + setup = &slot->data->color; + spColor_addFloats(color, (setup->r - color->r) * alpha, (setup->g - color->g) * alpha, (setup->b - color->b) * alpha, + (setup->a - color->a) * alpha); + } + return; + } + + if (time >= self->frames[self->framesCount - 5]) { /* Time is after last frame */ + int i = self->framesCount; + r = self->frames[i + COLOR_PREV_R]; + g = self->frames[i + COLOR_PREV_G]; + b = self->frames[i + COLOR_PREV_B]; + a = self->frames[i + COLOR_PREV_A]; + } else { + /* Interpolate between the previous frame and the current frame. */ + frame = binarySearch(self->frames, self->framesCount, time, COLOR_ENTRIES); + + r = self->frames[frame + COLOR_PREV_R]; + g = self->frames[frame + COLOR_PREV_G]; + b = self->frames[frame + COLOR_PREV_B]; + a = self->frames[frame + COLOR_PREV_A]; + + frameTime = self->frames[frame]; + percent = spCurveTimeline_getCurvePercent(SUPER(self), frame / COLOR_ENTRIES - 1, + 1 - (time - frameTime) / (self->frames[frame + COLOR_PREV_TIME] - frameTime)); + + r += (self->frames[frame + COLOR_R] - r) * percent; + g += (self->frames[frame + COLOR_G] - g) * percent; + b += (self->frames[frame + COLOR_B] - b) * percent; + a += (self->frames[frame + COLOR_A] - a) * percent; + } + if (alpha == 1) { + spColor_setFromFloats(&slot->color, r, g, b, a); + } else { + if (pose == SP_MIX_POSE_SETUP) { + spColor_setFromColor(&slot->color, &slot->data->color); + } + spColor_addFloats(&slot->color, (r - slot->color.r) * alpha, (g - slot->color.g) * alpha, (b - slot->color.b) * alpha, (a - slot->color.a) * alpha); + } + + UNUSED(lastTime); + UNUSED(firedEvents); + UNUSED(eventsCount); +} + +int _spColorTimeline_getPropertyId (const spTimeline* timeline) { + return (SP_TIMELINE_COLOR << 24) + SUB_CAST(spColorTimeline, timeline)->slotIndex; +} + +spColorTimeline* spColorTimeline_create (int framesCount) { + return (spColorTimeline*)_spBaseTimeline_create(framesCount, SP_TIMELINE_COLOR, 5, _spColorTimeline_apply, _spColorTimeline_getPropertyId); +} + +void spColorTimeline_setFrame (spColorTimeline* self, int frameIndex, float time, float r, float g, float b, float a) { + frameIndex *= COLOR_ENTRIES; + self->frames[frameIndex] = time; + self->frames[frameIndex + COLOR_R] = r; + self->frames[frameIndex + COLOR_G] = g; + self->frames[frameIndex + COLOR_B] = b; + self->frames[frameIndex + COLOR_A] = a; +} + +/**/ + +static const int TWOCOLOR_PREV_TIME = -8, TWOCOLOR_PREV_R = -7, TWOCOLOR_PREV_G = -6, TWOCOLOR_PREV_B = -5, TWOCOLOR_PREV_A = -4; +static const int TWOCOLOR_PREV_R2 = -3, TWOCOLOR_PREV_G2 = -2, TWOCOLOR_PREV_B2 = -1; +static const int TWOCOLOR_R = 1, TWOCOLOR_G = 2, TWOCOLOR_B = 3, TWOCOLOR_A = 4, TWOCOLOR_R2 = 5, TWOCOLOR_G2 = 6, TWOCOLOR_B2 = 7; + +void _spTwoColorTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents, + int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) { + spSlot *slot; + int frame; + float percent, frameTime; + float r, g, b, a, r2, g2, b2; + spColor* light; + spColor* dark; + spColor* setupLight; + spColor* setupDark; + spColorTimeline* self = (spColorTimeline*)timeline; + slot = skeleton->slots[self->slotIndex]; + + if (time < self->frames[0]) { + switch (pose) { + case SP_MIX_POSE_SETUP: + spColor_setFromColor(&slot->color, &slot->data->color); + spColor_setFromColor(slot->darkColor, slot->data->darkColor); + return; + case SP_MIX_POSE_CURRENT: + case SP_MIX_POSE_CURRENT_LAYERED: /* to appease compiler */ + light = &slot->color; + dark = slot->darkColor; + setupLight = &slot->data->color; + setupDark = slot->data->darkColor; + spColor_addFloats(light, (setupLight->r - light->r) * alpha, (setupLight->g - light->g) * alpha, (setupLight->b - light->b) * alpha, + (setupLight->a - light->a) * alpha); + spColor_addFloats(dark, (setupDark->r - dark->r) * alpha, (setupDark->g - dark->g) * alpha, (setupDark->b - dark->b) * alpha, 0); + } + return; + } + + if (time >= self->frames[self->framesCount - TWOCOLOR_ENTRIES]) { /* Time is after last frame */ + int i = self->framesCount; + r = self->frames[i + TWOCOLOR_PREV_R]; + g = self->frames[i + TWOCOLOR_PREV_G]; + b = self->frames[i + TWOCOLOR_PREV_B]; + a = self->frames[i + TWOCOLOR_PREV_A]; + r2 = self->frames[i + TWOCOLOR_PREV_R2]; + g2 = self->frames[i + TWOCOLOR_PREV_G2]; + b2 = self->frames[i + TWOCOLOR_PREV_B2]; + } else { + /* Interpolate between the previous frame and the current frame. */ + frame = binarySearch(self->frames, self->framesCount, time, TWOCOLOR_ENTRIES); + + r = self->frames[frame + TWOCOLOR_PREV_R]; + g = self->frames[frame + TWOCOLOR_PREV_G]; + b = self->frames[frame + TWOCOLOR_PREV_B]; + a = self->frames[frame + TWOCOLOR_PREV_A]; + r2 = self->frames[frame + TWOCOLOR_PREV_R2]; + g2 = self->frames[frame + TWOCOLOR_PREV_G2]; + b2 = self->frames[frame + TWOCOLOR_PREV_B2]; + + frameTime = self->frames[frame]; + percent = spCurveTimeline_getCurvePercent(SUPER(self), frame / TWOCOLOR_ENTRIES - 1, + 1 - (time - frameTime) / (self->frames[frame + TWOCOLOR_PREV_TIME] - frameTime)); + + r += (self->frames[frame + TWOCOLOR_R] - r) * percent; + g += (self->frames[frame + TWOCOLOR_G] - g) * percent; + b += (self->frames[frame + TWOCOLOR_B] - b) * percent; + a += (self->frames[frame + TWOCOLOR_A] - a) * percent; + r2 += (self->frames[frame + TWOCOLOR_R2] - r2) * percent; + g2 += (self->frames[frame + TWOCOLOR_G2] - g2) * percent; + b2 += (self->frames[frame + TWOCOLOR_B2] - b2) * percent; + } + if (alpha == 1) { + spColor_setFromFloats(&slot->color, r, g, b, a); + spColor_setFromFloats(slot->darkColor, r2, g2, b2, 1); + } else { + light = &slot->color; + dark = slot->darkColor; + if (pose == SP_MIX_POSE_SETUP) { + spColor_setFromColor(light, &slot->data->color); + spColor_setFromColor(dark, slot->data->darkColor); + } + spColor_addFloats(light, (r - light->r) * alpha, (g - light->g) * alpha, (b - light->b) * alpha, (a - light->a) * alpha); + spColor_addFloats(dark, (r2 - dark->r) * alpha, (g2 - dark->g) * alpha, (b2 - dark->b) * alpha, 0); + } + + UNUSED(lastTime); + UNUSED(firedEvents); + UNUSED(eventsCount); +} + +int _spTwoColorTimeline_getPropertyId (const spTimeline* timeline) { + return (SP_TIMELINE_TWOCOLOR << 24) + SUB_CAST(spTwoColorTimeline, timeline)->slotIndex; +} + +spTwoColorTimeline* spTwoColorTimeline_create (int framesCount) { + return (spTwoColorTimeline*)_spBaseTimeline_create(framesCount, SP_TIMELINE_TWOCOLOR, TWOCOLOR_ENTRIES, _spTwoColorTimeline_apply, _spTwoColorTimeline_getPropertyId); +} + +void spTwoColorTimeline_setFrame (spTwoColorTimeline* self, int frameIndex, float time, float r, float g, float b, float a, float r2, float g2, float b2) { + frameIndex *= TWOCOLOR_ENTRIES; + self->frames[frameIndex] = time; + self->frames[frameIndex + TWOCOLOR_R] = r; + self->frames[frameIndex + TWOCOLOR_G] = g; + self->frames[frameIndex + TWOCOLOR_B] = b; + self->frames[frameIndex + TWOCOLOR_A] = a; + self->frames[frameIndex + TWOCOLOR_R2] = r2; + self->frames[frameIndex + TWOCOLOR_G2] = g2; + self->frames[frameIndex + TWOCOLOR_B2] = b2; +} + +/**/ + +void _spAttachmentTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, + spEvent** firedEvents, int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) { + const char* attachmentName; + spAttachmentTimeline* self = (spAttachmentTimeline*)timeline; + int frameIndex; + spSlot* slot = skeleton->slots[self->slotIndex]; + + if (direction == SP_MIX_DIRECTION_OUT && pose == SP_MIX_POSE_SETUP) { + const char* attachmentName = slot->data->attachmentName; + spSlot_setAttachment(slot, attachmentName ? spSkeleton_getAttachmentForSlotIndex(skeleton, self->slotIndex, attachmentName) : 0); + return; + } + + if (time < self->frames[0]) { + if (pose == SP_MIX_POSE_SETUP) { + attachmentName = slot->data->attachmentName; + spSlot_setAttachment(skeleton->slots[self->slotIndex], + attachmentName ? spSkeleton_getAttachmentForSlotIndex(skeleton, self->slotIndex, attachmentName) : 0); + } + return; + } + + if (time >= self->frames[self->framesCount - 1]) + frameIndex = self->framesCount - 1; + else + frameIndex = binarySearch1(self->frames, self->framesCount, time) - 1; + + attachmentName = self->attachmentNames[frameIndex]; + spSlot_setAttachment(skeleton->slots[self->slotIndex], + attachmentName ? spSkeleton_getAttachmentForSlotIndex(skeleton, self->slotIndex, attachmentName) : 0); + + UNUSED(lastTime); + UNUSED(firedEvents); + UNUSED(eventsCount); + UNUSED(alpha); +} + +int _spAttachmentTimeline_getPropertyId (const spTimeline* timeline) { + return (SP_TIMELINE_ATTACHMENT << 24) + SUB_CAST(spAttachmentTimeline, timeline)->slotIndex; +} + +void _spAttachmentTimeline_dispose (spTimeline* timeline) { + spAttachmentTimeline* self = SUB_CAST(spAttachmentTimeline, timeline); + int i; + + _spTimeline_deinit(timeline); + + for (i = 0; i < self->framesCount; ++i) + FREE(self->attachmentNames[i]); + FREE(self->attachmentNames); + FREE(self->frames); + FREE(self); +} + +spAttachmentTimeline* spAttachmentTimeline_create (int framesCount) { + spAttachmentTimeline* self = NEW(spAttachmentTimeline); + _spTimeline_init(SUPER(self), SP_TIMELINE_ATTACHMENT, _spAttachmentTimeline_dispose, _spAttachmentTimeline_apply, _spAttachmentTimeline_getPropertyId); + + CONST_CAST(int, self->framesCount) = framesCount; + CONST_CAST(float*, self->frames) = CALLOC(float, framesCount); + CONST_CAST(char**, self->attachmentNames) = CALLOC(char*, framesCount); + + return self; +} + +void spAttachmentTimeline_setFrame (spAttachmentTimeline* self, int frameIndex, float time, const char* attachmentName) { + self->frames[frameIndex] = time; + + FREE(self->attachmentNames[frameIndex]); + if (attachmentName) + MALLOC_STR(self->attachmentNames[frameIndex], attachmentName); + else + self->attachmentNames[frameIndex] = 0; +} + +/**/ + +void _spDeformTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents, + int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) { + int frame, i, vertexCount; + float percent, frameTime; + const float* prevVertices; + const float* nextVertices; + float* frames; + int framesCount; + const float** frameVertices; + float* vertices; + spDeformTimeline* self = (spDeformTimeline*)timeline; + + spSlot *slot = skeleton->slots[self->slotIndex]; + + if (slot->attachment != self->attachment) { + if (!slot->attachment) return; + switch (slot->attachment->type) { + case SP_ATTACHMENT_MESH: { + spMeshAttachment* mesh = SUB_CAST(spMeshAttachment, slot->attachment); + if (!mesh->inheritDeform || mesh->parentMesh != (void*)self->attachment) return; + break; + } + default: + return; + } + } + + frames = self->frames; + framesCount = self->framesCount; + vertexCount = self->frameVerticesCount; + if (slot->attachmentVerticesCount < vertexCount) { + if (slot->attachmentVerticesCapacity < vertexCount) { + FREE(slot->attachmentVertices); + slot->attachmentVertices = MALLOC(float, vertexCount); + slot->attachmentVerticesCapacity = vertexCount; + } + } + slot->attachmentVerticesCount = vertexCount; + + frameVertices = self->frameVertices; + vertices = slot->attachmentVertices; + + if (time < frames[0]) { /* Time is before first frame. */ + spVertexAttachment* vertexAttachment = SUB_CAST(spVertexAttachment, slot->attachment); + switch (pose) { + case SP_MIX_POSE_SETUP: + if (!vertexAttachment->bones) { + memcpy(vertices, vertexAttachment->vertices, vertexCount * sizeof(float)); + } else { + for (i = 0; i < vertexCount; i++) vertices[i] = 0; + } + return; + case SP_MIX_POSE_CURRENT: + case SP_MIX_POSE_CURRENT_LAYERED: /* to appease compiler */ + if (alpha == 1) break; + if (!vertexAttachment->bones) { + float* setupVertices = vertexAttachment->vertices; + for (i = 0; i < vertexCount; i++) { + vertices[i] += (setupVertices[i] - vertices[i]) * alpha; + } + } else { + alpha = 1 - alpha; + for (i = 0; i < vertexCount; i++) { + vertices[i] *= alpha; + } + } + } + return; + } + + if (time >= frames[framesCount - 1]) { /* Time is after last frame. */ + const float* lastVertices = self->frameVertices[framesCount - 1]; + if (alpha == 1) { + /* Vertex positions or deform offsets, no alpha. */ + memcpy(vertices, lastVertices, vertexCount * sizeof(float)); + } else if (pose == SP_MIX_POSE_SETUP) { + spVertexAttachment* vertexAttachment = SUB_CAST(spVertexAttachment, slot->attachment); + if (!vertexAttachment->bones) { + /* Unweighted vertex positions, with alpha. */ + float* setupVertices = vertexAttachment->vertices; + for (i = 0; i < vertexCount; i++) { + float setup = setupVertices[i]; + vertices[i] = setup + (lastVertices[i] - setup) * alpha; + } + } else { + /* Weighted deform offsets, with alpha. */ + for (i = 0; i < vertexCount; i++) + vertices[i] = lastVertices[i] * alpha; + } + } else { + /* Vertex positions or deform offsets, with alpha. */ + for (i = 0; i < vertexCount; i++) + vertices[i] += (lastVertices[i] - vertices[i]) * alpha; + } + return; + } + + /* Interpolate between the previous frame and the current frame. */ + frame = binarySearch(frames, framesCount, time, 1); + prevVertices = frameVertices[frame - 1]; + nextVertices = frameVertices[frame]; + frameTime = frames[frame]; + percent = spCurveTimeline_getCurvePercent(SUPER(self), frame - 1, 1 - (time - frameTime) / (frames[frame - 1] - frameTime)); + + if (alpha == 1) { + /* Vertex positions or deform offsets, no alpha. */ + for (i = 0; i < vertexCount; i++) { + float prev = prevVertices[i]; + vertices[i] = prev + (nextVertices[i] - prev) * percent; + } + } else if (pose == SP_MIX_POSE_SETUP) { + spVertexAttachment* vertexAttachment = SUB_CAST(spVertexAttachment, slot->attachment); + if (!vertexAttachment->bones) { + /* Unweighted vertex positions, with alpha. */ + float* setupVertices = vertexAttachment->vertices; + for (i = 0; i < vertexCount; i++) { + float prev = prevVertices[i], setup = setupVertices[i]; + vertices[i] = setup + (prev + (nextVertices[i] - prev) * percent - setup) * alpha; + } + } else { + /* Weighted deform offsets, with alpha. */ + for (i = 0; i < vertexCount; i++) { + float prev = prevVertices[i]; + vertices[i] = (prev + (nextVertices[i] - prev) * percent) * alpha; + } + } + } else { + /* Vertex positions or deform offsets, with alpha. */ + for (i = 0; i < vertexCount; i++) { + float prev = prevVertices[i]; + vertices[i] += (prev + (nextVertices[i] - prev) * percent - vertices[i]) * alpha; + } + } + + UNUSED(lastTime); + UNUSED(firedEvents); + UNUSED(eventsCount); +} + +int _spDeformTimeline_getPropertyId (const spTimeline* timeline) { + return (SP_TIMELINE_DEFORM << 27) + SUB_CAST(spVertexAttachment, SUB_CAST(spDeformTimeline, timeline)->attachment)->id + SUB_CAST(spDeformTimeline, timeline)->slotIndex; +} + +void _spDeformTimeline_dispose (spTimeline* timeline) { + spDeformTimeline* self = SUB_CAST(spDeformTimeline, timeline); + int i; + + _spCurveTimeline_deinit(SUPER(self)); + + for (i = 0; i < self->framesCount; ++i) + FREE(self->frameVertices[i]); + FREE(self->frameVertices); + FREE(self->frames); + FREE(self); +} + +spDeformTimeline* spDeformTimeline_create (int framesCount, int frameVerticesCount) { + spDeformTimeline* self = NEW(spDeformTimeline); + _spCurveTimeline_init(SUPER(self), SP_TIMELINE_DEFORM, framesCount, _spDeformTimeline_dispose, _spDeformTimeline_apply, _spDeformTimeline_getPropertyId); + CONST_CAST(int, self->framesCount) = framesCount; + CONST_CAST(float*, self->frames) = CALLOC(float, self->framesCount); + CONST_CAST(float**, self->frameVertices) = CALLOC(float*, framesCount); + CONST_CAST(int, self->frameVerticesCount) = frameVerticesCount; + return self; +} + +void spDeformTimeline_setFrame (spDeformTimeline* self, int frameIndex, float time, float* vertices) { + self->frames[frameIndex] = time; + + FREE(self->frameVertices[frameIndex]); + if (!vertices) + self->frameVertices[frameIndex] = 0; + else { + self->frameVertices[frameIndex] = MALLOC(float, self->frameVerticesCount); + memcpy(CONST_CAST(float*, self->frameVertices[frameIndex]), vertices, self->frameVerticesCount * sizeof(float)); + } +} + + +/**/ + +/** Fires events for frames > lastTime and <= time. */ +void _spEventTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents, + int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) { + spEventTimeline* self = (spEventTimeline*)timeline; + int frame; + if (!firedEvents) return; + + if (lastTime > time) { /* Fire events after last time for looped animations. */ + _spEventTimeline_apply(timeline, skeleton, lastTime, (float)INT_MAX, firedEvents, eventsCount, alpha, pose, direction); + lastTime = -1; + } else if (lastTime >= self->frames[self->framesCount - 1]) /* Last time is after last frame. */ + return; + if (time < self->frames[0]) return; /* Time is before first frame. */ + + if (lastTime < self->frames[0]) + frame = 0; + else { + float frameTime; + frame = binarySearch1(self->frames, self->framesCount, lastTime); + frameTime = self->frames[frame]; + while (frame > 0) { /* Fire multiple events with the same frame. */ + if (self->frames[frame - 1] != frameTime) break; + frame--; + } + } + for (; frame < self->framesCount && time >= self->frames[frame]; ++frame) { + firedEvents[*eventsCount] = self->events[frame]; + (*eventsCount)++; + } +} + +int _spEventTimeline_getPropertyId (const spTimeline* timeline) { + return SP_TIMELINE_EVENT << 24; +} + +void _spEventTimeline_dispose (spTimeline* timeline) { + spEventTimeline* self = SUB_CAST(spEventTimeline, timeline); + int i; + + _spTimeline_deinit(timeline); + + for (i = 0; i < self->framesCount; ++i) + spEvent_dispose(self->events[i]); + FREE(self->events); + FREE(self->frames); + FREE(self); +} + +spEventTimeline* spEventTimeline_create (int framesCount) { + spEventTimeline* self = NEW(spEventTimeline); + _spTimeline_init(SUPER(self), SP_TIMELINE_EVENT, _spEventTimeline_dispose, _spEventTimeline_apply, _spEventTimeline_getPropertyId); + + CONST_CAST(int, self->framesCount) = framesCount; + CONST_CAST(float*, self->frames) = CALLOC(float, framesCount); + CONST_CAST(spEvent**, self->events) = CALLOC(spEvent*, framesCount); + + return self; +} + +void spEventTimeline_setFrame (spEventTimeline* self, int frameIndex, spEvent* event) { + self->frames[frameIndex] = event->time; + + FREE(self->events[frameIndex]); + self->events[frameIndex] = event; +} + +/**/ + +void _spDrawOrderTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, + spEvent** firedEvents, int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) { + int i; + int frame; + const int* drawOrderToSetupIndex; + spDrawOrderTimeline* self = (spDrawOrderTimeline*)timeline; + + if (direction == SP_MIX_DIRECTION_OUT && pose == SP_MIX_POSE_SETUP) { + memcpy(skeleton->drawOrder, skeleton->slots, self->slotsCount * sizeof(spSlot*)); + return; + } + + if (time < self->frames[0]) { + if (pose == SP_MIX_POSE_SETUP) memcpy(skeleton->drawOrder, skeleton->slots, self->slotsCount * sizeof(spSlot*)); + return; + } + + if (time >= self->frames[self->framesCount - 1]) /* Time is after last frame. */ + frame = self->framesCount - 1; + else + frame = binarySearch1(self->frames, self->framesCount, time) - 1; + + drawOrderToSetupIndex = self->drawOrders[frame]; + if (!drawOrderToSetupIndex) + memcpy(skeleton->drawOrder, skeleton->slots, self->slotsCount * sizeof(spSlot*)); + else { + for (i = 0; i < self->slotsCount; ++i) + skeleton->drawOrder[i] = skeleton->slots[drawOrderToSetupIndex[i]]; + } + + UNUSED(lastTime); + UNUSED(firedEvents); + UNUSED(eventsCount); + UNUSED(alpha); +} + +int _spDrawOrderTimeline_getPropertyId (const spTimeline* timeline) { + return SP_TIMELINE_DRAWORDER << 24; +} + +void _spDrawOrderTimeline_dispose (spTimeline* timeline) { + spDrawOrderTimeline* self = SUB_CAST(spDrawOrderTimeline, timeline); + int i; + + _spTimeline_deinit(timeline); + + for (i = 0; i < self->framesCount; ++i) + FREE(self->drawOrders[i]); + FREE(self->drawOrders); + FREE(self->frames); + FREE(self); +} + +spDrawOrderTimeline* spDrawOrderTimeline_create (int framesCount, int slotsCount) { + spDrawOrderTimeline* self = NEW(spDrawOrderTimeline); + _spTimeline_init(SUPER(self), SP_TIMELINE_DRAWORDER, _spDrawOrderTimeline_dispose, _spDrawOrderTimeline_apply, _spDrawOrderTimeline_getPropertyId); + + CONST_CAST(int, self->framesCount) = framesCount; + CONST_CAST(float*, self->frames) = CALLOC(float, framesCount); + CONST_CAST(int**, self->drawOrders) = CALLOC(int*, framesCount); + CONST_CAST(int, self->slotsCount) = slotsCount; + + return self; +} + +void spDrawOrderTimeline_setFrame (spDrawOrderTimeline* self, int frameIndex, float time, const int* drawOrder) { + self->frames[frameIndex] = time; + + FREE(self->drawOrders[frameIndex]); + if (!drawOrder) + self->drawOrders[frameIndex] = 0; + else { + self->drawOrders[frameIndex] = MALLOC(int, self->slotsCount); + memcpy(CONST_CAST(int*, self->drawOrders[frameIndex]), drawOrder, self->slotsCount * sizeof(int)); + } +} + +/**/ + +static const int IKCONSTRAINT_PREV_TIME = -3, IKCONSTRAINT_PREV_MIX = -2, IKCONSTRAINT_PREV_BEND_DIRECTION = -1; +static const int IKCONSTRAINT_MIX = 1, IKCONSTRAINT_BEND_DIRECTION = 2; + +void _spIkConstraintTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, + spEvent** firedEvents, int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) { + int frame; + float frameTime, percent, mix; + float *frames; + int framesCount; + spIkConstraint* constraint; + spIkConstraintTimeline* self = (spIkConstraintTimeline*)timeline; + + constraint = skeleton->ikConstraints[self->ikConstraintIndex]; + + if (time < self->frames[0]) { + switch (pose) { + case SP_MIX_POSE_SETUP: + constraint->mix = constraint->data->mix; + constraint->bendDirection = constraint->data->bendDirection; + return; + case SP_MIX_POSE_CURRENT: + case SP_MIX_POSE_CURRENT_LAYERED: /* to appease compiler */ + constraint->mix += (constraint->data->mix - constraint->mix) * alpha; + constraint->bendDirection = constraint->data->bendDirection; + } + return; + } + + frames = self->frames; + framesCount = self->framesCount; + if (time >= frames[framesCount - IKCONSTRAINT_ENTRIES]) { /* Time is after last frame. */ + if (pose == SP_MIX_POSE_SETUP) { + constraint->mix = constraint->data->mix + (frames[framesCount + IKCONSTRAINT_PREV_MIX] - constraint->data->mix) * alpha; + constraint->bendDirection = direction == SP_MIX_DIRECTION_OUT ? constraint->data->bendDirection + : (int)frames[framesCount + IKCONSTRAINT_PREV_BEND_DIRECTION]; + } else { + constraint->mix += (frames[framesCount + IKCONSTRAINT_PREV_MIX] - constraint->mix) * alpha; + if (direction == SP_MIX_DIRECTION_IN) constraint->bendDirection = (int)frames[framesCount + IKCONSTRAINT_PREV_BEND_DIRECTION]; + } + return; + } + + /* Interpolate between the previous frame and the current frame. */ + frame = binarySearch(self->frames, self->framesCount, time, IKCONSTRAINT_ENTRIES); + mix = self->frames[frame + IKCONSTRAINT_PREV_MIX]; + frameTime = self->frames[frame]; + percent = spCurveTimeline_getCurvePercent(SUPER(self), frame / IKCONSTRAINT_ENTRIES - 1, 1 - (time - frameTime) / (self->frames[frame + IKCONSTRAINT_PREV_TIME] - frameTime)); + + if (pose == SP_MIX_POSE_SETUP) { + constraint->mix = constraint->data->mix + (mix + (frames[frame + IKCONSTRAINT_MIX] - mix) * percent - constraint->data->mix) * alpha; + constraint->bendDirection = direction == SP_MIX_DIRECTION_OUT ? constraint->data->bendDirection : (int)frames[frame + IKCONSTRAINT_PREV_BEND_DIRECTION]; + } else { + constraint->mix += (mix + (frames[frame + IKCONSTRAINT_MIX] - mix) * percent - constraint->mix) * alpha; + if (direction == SP_MIX_DIRECTION_IN) constraint->bendDirection = (int)frames[frame + IKCONSTRAINT_PREV_BEND_DIRECTION]; + } + + UNUSED(lastTime); + UNUSED(firedEvents); + UNUSED(eventsCount); +} + +int _spIkConstraintTimeline_getPropertyId (const spTimeline* timeline) { + return (SP_TIMELINE_IKCONSTRAINT << 24) + SUB_CAST(spIkConstraintTimeline, timeline)->ikConstraintIndex; +} + +spIkConstraintTimeline* spIkConstraintTimeline_create (int framesCount) { + return (spIkConstraintTimeline*)_spBaseTimeline_create(framesCount, SP_TIMELINE_IKCONSTRAINT, IKCONSTRAINT_ENTRIES, _spIkConstraintTimeline_apply, _spIkConstraintTimeline_getPropertyId); +} + +void spIkConstraintTimeline_setFrame (spIkConstraintTimeline* self, int frameIndex, float time, float mix, int bendDirection) { + frameIndex *= IKCONSTRAINT_ENTRIES; + self->frames[frameIndex] = time; + self->frames[frameIndex + IKCONSTRAINT_MIX] = mix; + self->frames[frameIndex + IKCONSTRAINT_BEND_DIRECTION] = (float)bendDirection; +} + +/**/ +static const int TRANSFORMCONSTRAINT_PREV_TIME = -5; +static const int TRANSFORMCONSTRAINT_PREV_ROTATE = -4; +static const int TRANSFORMCONSTRAINT_PREV_TRANSLATE = -3; +static const int TRANSFORMCONSTRAINT_PREV_SCALE = -2; +static const int TRANSFORMCONSTRAINT_PREV_SHEAR = -1; +static const int TRANSFORMCONSTRAINT_ROTATE = 1; +static const int TRANSFORMCONSTRAINT_TRANSLATE = 2; +static const int TRANSFORMCONSTRAINT_SCALE = 3; +static const int TRANSFORMCONSTRAINT_SHEAR = 4; + +void _spTransformConstraintTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, + spEvent** firedEvents, int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) { + int frame; + float frameTime, percent, rotate, translate, scale, shear; + spTransformConstraint* constraint; + spTransformConstraintTimeline* self = (spTransformConstraintTimeline*)timeline; + float *frames; + int framesCount; + + constraint = skeleton->transformConstraints[self->transformConstraintIndex]; + if (time < self->frames[0]) { + spTransformConstraintData* data = constraint->data; + switch (pose) { + case SP_MIX_POSE_SETUP: + constraint->rotateMix = data->rotateMix; + constraint->translateMix = data->translateMix; + constraint->scaleMix = data->scaleMix; + constraint->shearMix = data->shearMix; + return; + case SP_MIX_POSE_CURRENT: + case SP_MIX_POSE_CURRENT_LAYERED: /* to appease compiler */ + constraint->rotateMix += (data->rotateMix - constraint->rotateMix) * alpha; + constraint->translateMix += (data->translateMix - constraint->translateMix) * alpha; + constraint->scaleMix += (data->scaleMix - constraint->scaleMix) * alpha; + constraint->shearMix += (data->shearMix - constraint->shearMix) * alpha; + } + return; + return; + } + + frames = self->frames; + framesCount = self->framesCount; + if (time >= frames[framesCount - TRANSFORMCONSTRAINT_ENTRIES]) { /* Time is after last frame. */ + int i = framesCount; + rotate = frames[i + TRANSFORMCONSTRAINT_PREV_ROTATE]; + translate = frames[i + TRANSFORMCONSTRAINT_PREV_TRANSLATE]; + scale = frames[i + TRANSFORMCONSTRAINT_PREV_SCALE]; + shear = frames[i + TRANSFORMCONSTRAINT_PREV_SHEAR]; + } else { + /* Interpolate between the previous frame and the current frame. */ + frame = binarySearch(frames, framesCount, time, TRANSFORMCONSTRAINT_ENTRIES); + rotate = frames[frame + TRANSFORMCONSTRAINT_PREV_ROTATE]; + translate = frames[frame + TRANSFORMCONSTRAINT_PREV_TRANSLATE]; + scale = frames[frame + TRANSFORMCONSTRAINT_PREV_SCALE]; + shear = frames[frame + TRANSFORMCONSTRAINT_PREV_SHEAR]; + frameTime = frames[frame]; + percent = spCurveTimeline_getCurvePercent(SUPER(self), frame / TRANSFORMCONSTRAINT_ENTRIES - 1, + 1 - (time - frameTime) / (frames[frame + TRANSFORMCONSTRAINT_PREV_TIME] - frameTime)); + + rotate += (frames[frame + TRANSFORMCONSTRAINT_ROTATE] - rotate) * percent; + translate += (frames[frame + TRANSFORMCONSTRAINT_TRANSLATE] - translate) * percent; + scale += (frames[frame + TRANSFORMCONSTRAINT_SCALE] - scale) * percent; + shear += (frames[frame + TRANSFORMCONSTRAINT_SHEAR] - shear) * percent; + } + if (pose == SP_MIX_POSE_SETUP) { + spTransformConstraintData* data = constraint->data; + constraint->rotateMix = data->rotateMix + (rotate - data->rotateMix) * alpha; + constraint->translateMix = data->translateMix + (translate - data->translateMix) * alpha; + constraint->scaleMix = data->scaleMix + (scale - data->scaleMix) * alpha; + constraint->shearMix = data->shearMix + (shear - data->shearMix) * alpha; + } else { + constraint->rotateMix += (rotate - constraint->rotateMix) * alpha; + constraint->translateMix += (translate - constraint->translateMix) * alpha; + constraint->scaleMix += (scale - constraint->scaleMix) * alpha; + constraint->shearMix += (shear - constraint->shearMix) * alpha; + } + + UNUSED(lastTime); + UNUSED(firedEvents); + UNUSED(eventsCount); +} + +int _spTransformConstraintTimeline_getPropertyId (const spTimeline* timeline) { + return (SP_TIMELINE_TRANSFORMCONSTRAINT << 24) + SUB_CAST(spTransformConstraintTimeline, timeline)->transformConstraintIndex; +} + +spTransformConstraintTimeline* spTransformConstraintTimeline_create (int framesCount) { + return (spTransformConstraintTimeline*)_spBaseTimeline_create(framesCount, SP_TIMELINE_TRANSFORMCONSTRAINT, TRANSFORMCONSTRAINT_ENTRIES, _spTransformConstraintTimeline_apply, _spTransformConstraintTimeline_getPropertyId); +} + +void spTransformConstraintTimeline_setFrame (spTransformConstraintTimeline* self, int frameIndex, float time, float rotateMix, float translateMix, float scaleMix, float shearMix) { + frameIndex *= TRANSFORMCONSTRAINT_ENTRIES; + self->frames[frameIndex] = time; + self->frames[frameIndex + TRANSFORMCONSTRAINT_ROTATE] = rotateMix; + self->frames[frameIndex + TRANSFORMCONSTRAINT_TRANSLATE] = translateMix; + self->frames[frameIndex + TRANSFORMCONSTRAINT_SCALE] = scaleMix; + self->frames[frameIndex + TRANSFORMCONSTRAINT_SHEAR] = shearMix; +} + +/**/ + +static const int PATHCONSTRAINTPOSITION_PREV_TIME = -2; +static const int PATHCONSTRAINTPOSITION_PREV_VALUE = -1; +static const int PATHCONSTRAINTPOSITION_VALUE = 1; + +void _spPathConstraintPositionTimeline_apply(const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, + spEvent** firedEvents, int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) { + int frame; + float frameTime, percent, position; + spPathConstraint* constraint; + spPathConstraintPositionTimeline* self = (spPathConstraintPositionTimeline*)timeline; + float* frames; + int framesCount; + + constraint = skeleton->pathConstraints[self->pathConstraintIndex]; + if (time < self->frames[0]) { + switch (pose) { + case SP_MIX_POSE_SETUP: + constraint->position = constraint->data->position; + return; + case SP_MIX_POSE_CURRENT: + case SP_MIX_POSE_CURRENT_LAYERED: /* to appease compiler */ + constraint->position += (constraint->data->position - constraint->position) * alpha; + } + return; + } + + frames = self->frames; + framesCount = self->framesCount; + if (time >= frames[framesCount - PATHCONSTRAINTPOSITION_ENTRIES]) /* Time is after last frame. */ + position = frames[framesCount + PATHCONSTRAINTPOSITION_PREV_VALUE]; + else { + /* Interpolate between the previous frame and the current frame. */ + frame = binarySearch(frames, framesCount, time, PATHCONSTRAINTPOSITION_ENTRIES); + position = frames[frame + PATHCONSTRAINTPOSITION_PREV_VALUE]; + frameTime = frames[frame]; + percent = spCurveTimeline_getCurvePercent(SUPER(self), frame / PATHCONSTRAINTPOSITION_ENTRIES - 1, + 1 - (time - frameTime) / (frames[frame + PATHCONSTRAINTPOSITION_PREV_TIME] - frameTime)); + + position += (frames[frame + PATHCONSTRAINTPOSITION_VALUE] - position) * percent; + } + if (pose == SP_MIX_POSE_SETUP) + constraint->position = constraint->data->position + (position - constraint->data->position) * alpha; + else + constraint->position += (position - constraint->position) * alpha; + + UNUSED(lastTime); + UNUSED(firedEvents); + UNUSED(eventsCount); +} + +int _spPathConstraintPositionTimeline_getPropertyId (const spTimeline* timeline) { + return (SP_TIMELINE_PATHCONSTRAINTPOSITION << 24) + SUB_CAST(spPathConstraintPositionTimeline, timeline)->pathConstraintIndex; +} + +spPathConstraintPositionTimeline* spPathConstraintPositionTimeline_create (int framesCount) { + return (spPathConstraintPositionTimeline*)_spBaseTimeline_create(framesCount, SP_TIMELINE_PATHCONSTRAINTPOSITION, PATHCONSTRAINTPOSITION_ENTRIES, _spPathConstraintPositionTimeline_apply, _spPathConstraintPositionTimeline_getPropertyId); +} + +void spPathConstraintPositionTimeline_setFrame (spPathConstraintPositionTimeline* self, int frameIndex, float time, float value) { + frameIndex *= PATHCONSTRAINTPOSITION_ENTRIES; + self->frames[frameIndex] = time; + self->frames[frameIndex + PATHCONSTRAINTPOSITION_VALUE] = value; +} + +/**/ +static const int PATHCONSTRAINTSPACING_PREV_TIME = -2; +static const int PATHCONSTRAINTSPACING_PREV_VALUE = -1; +static const int PATHCONSTRAINTSPACING_VALUE = 1; + +void _spPathConstraintSpacingTimeline_apply(const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, + spEvent** firedEvents, int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) { + int frame; + float frameTime, percent, spacing; + spPathConstraint* constraint; + spPathConstraintSpacingTimeline* self = (spPathConstraintSpacingTimeline*)timeline; + float* frames; + int framesCount; + + constraint = skeleton->pathConstraints[self->pathConstraintIndex]; + if (time < self->frames[0]) { + switch (pose) { + case SP_MIX_POSE_SETUP: + constraint->spacing = constraint->data->spacing; + return; + case SP_MIX_POSE_CURRENT: + case SP_MIX_POSE_CURRENT_LAYERED: /* to appease compiler */ + constraint->spacing += (constraint->data->spacing - constraint->spacing) * alpha; + } + return; + } + + frames = self->frames; + framesCount = self->framesCount; + if (time >= frames[framesCount - PATHCONSTRAINTSPACING_ENTRIES]) /* Time is after last frame. */ + spacing = frames[framesCount + PATHCONSTRAINTSPACING_PREV_VALUE]; + else { + /* Interpolate between the previous frame and the current frame. */ + frame = binarySearch(frames, framesCount, time, PATHCONSTRAINTSPACING_ENTRIES); + spacing = frames[frame + PATHCONSTRAINTSPACING_PREV_VALUE]; + frameTime = frames[frame]; + percent = spCurveTimeline_getCurvePercent(SUPER(self), frame / PATHCONSTRAINTSPACING_ENTRIES - 1, + 1 - (time - frameTime) / (frames[frame + PATHCONSTRAINTSPACING_PREV_TIME] - frameTime)); + + spacing += (frames[frame + PATHCONSTRAINTSPACING_VALUE] - spacing) * percent; + } + + if (pose == SP_MIX_POSE_SETUP) + constraint->spacing = constraint->data->spacing + (spacing - constraint->data->spacing) * alpha; + else + constraint->spacing += (spacing - constraint->spacing) * alpha; + + UNUSED(lastTime); + UNUSED(firedEvents); + UNUSED(eventsCount); +} + +int _spPathConstraintSpacingTimeline_getPropertyId (const spTimeline* timeline) { + return (SP_TIMELINE_PATHCONSTRAINTSPACING << 24) + SUB_CAST(spPathConstraintSpacingTimeline, timeline)->pathConstraintIndex; +} + +spPathConstraintSpacingTimeline* spPathConstraintSpacingTimeline_create (int framesCount) { + return (spPathConstraintSpacingTimeline*)_spBaseTimeline_create(framesCount, SP_TIMELINE_PATHCONSTRAINTSPACING, PATHCONSTRAINTSPACING_ENTRIES, _spPathConstraintSpacingTimeline_apply, _spPathConstraintSpacingTimeline_getPropertyId); +} + +void spPathConstraintSpacingTimeline_setFrame (spPathConstraintSpacingTimeline* self, int frameIndex, float time, float value) { + frameIndex *= PATHCONSTRAINTSPACING_ENTRIES; + self->frames[frameIndex] = time; + self->frames[frameIndex + PATHCONSTRAINTSPACING_VALUE] = value; +} + +/**/ + +static const int PATHCONSTRAINTMIX_PREV_TIME = -3; +static const int PATHCONSTRAINTMIX_PREV_ROTATE = -2; +static const int PATHCONSTRAINTMIX_PREV_TRANSLATE = -1; +static const int PATHCONSTRAINTMIX_ROTATE = 1; +static const int PATHCONSTRAINTMIX_TRANSLATE = 2; + +void _spPathConstraintMixTimeline_apply(const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, + spEvent** firedEvents, int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) { + int frame; + float frameTime, percent, rotate, translate; + spPathConstraint* constraint; + spPathConstraintMixTimeline* self = (spPathConstraintMixTimeline*)timeline; + float* frames; + int framesCount; + + constraint = skeleton->pathConstraints[self->pathConstraintIndex]; + if (time < self->frames[0]) { + switch (pose) { + case SP_MIX_POSE_SETUP: + constraint->rotateMix = constraint->data->rotateMix; + constraint->translateMix = constraint->data->translateMix; + return; + case SP_MIX_POSE_CURRENT: + case SP_MIX_POSE_CURRENT_LAYERED: /* to appease compiler */ + constraint->rotateMix += (constraint->data->rotateMix - constraint->rotateMix) * alpha; + constraint->translateMix += (constraint->data->translateMix - constraint->translateMix) * alpha; + } + return; + } + + frames = self->frames; + framesCount = self->framesCount; + if (time >= frames[framesCount - PATHCONSTRAINTMIX_ENTRIES]) { /* Time is after last frame. */ + rotate = frames[framesCount + PATHCONSTRAINTMIX_PREV_ROTATE]; + translate = frames[framesCount + PATHCONSTRAINTMIX_PREV_TRANSLATE]; + } else { + /* Interpolate between the previous frame and the current frame. */ + frame = binarySearch(frames, framesCount, time, PATHCONSTRAINTMIX_ENTRIES); + rotate = frames[frame + PATHCONSTRAINTMIX_PREV_ROTATE]; + translate = frames[frame + PATHCONSTRAINTMIX_PREV_TRANSLATE]; + frameTime = frames[frame]; + percent = spCurveTimeline_getCurvePercent(SUPER(self), frame / PATHCONSTRAINTMIX_ENTRIES - 1, + 1 - (time - frameTime) / (frames[frame + PATHCONSTRAINTMIX_PREV_TIME] - frameTime)); + + rotate += (frames[frame + PATHCONSTRAINTMIX_ROTATE] - rotate) * percent; + translate += (frames[frame + PATHCONSTRAINTMIX_TRANSLATE] - translate) * percent; + } + + if (pose == SP_MIX_POSE_SETUP) { + constraint->rotateMix = constraint->data->rotateMix + (rotate - constraint->data->rotateMix) * alpha; + constraint->translateMix = constraint->data->translateMix + (translate - constraint->data->translateMix) * alpha; + } else { + constraint->rotateMix += (rotate - constraint->rotateMix) * alpha; + constraint->translateMix += (translate - constraint->translateMix) * alpha; + } + + UNUSED(lastTime); + UNUSED(firedEvents); + UNUSED(eventsCount); +} + +int _spPathConstraintMixTimeline_getPropertyId (const spTimeline* timeline) { + return (SP_TIMELINE_PATHCONSTRAINTMIX << 24) + SUB_CAST(spPathConstraintMixTimeline, timeline)->pathConstraintIndex; +} + +spPathConstraintMixTimeline* spPathConstraintMixTimeline_create (int framesCount) { + return (spPathConstraintMixTimeline*)_spBaseTimeline_create(framesCount, SP_TIMELINE_PATHCONSTRAINTMIX, PATHCONSTRAINTMIX_ENTRIES, _spPathConstraintMixTimeline_apply, _spPathConstraintMixTimeline_getPropertyId); +} + +void spPathConstraintMixTimeline_setFrame (spPathConstraintMixTimeline* self, int frameIndex, float time, float rotateMix, float translateMix) { + frameIndex *= PATHCONSTRAINTMIX_ENTRIES; + self->frames[frameIndex] = time; + self->frames[frameIndex + PATHCONSTRAINTMIX_ROTATE] = rotateMix; + self->frames[frameIndex + PATHCONSTRAINTMIX_TRANSLATE] = translateMix; +} diff --git a/spine-cpp/spine-cpp/src/spine/AnimationState.c b/spine-cpp/spine-cpp/src/spine/AnimationState.c new file mode 100644 index 000000000..42d3aff0a --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/AnimationState.c @@ -0,0 +1,932 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include +#include + +#define SUBSEQUENT 0 +#define FIRST 1 +#define DIP 2 +#define DIP_MIX 3 + +_SP_ARRAY_IMPLEMENT_TYPE(spTrackEntryArray, spTrackEntry*) + +static spAnimation* SP_EMPTY_ANIMATION = 0; +void spAnimationState_disposeStatics () { + if (SP_EMPTY_ANIMATION) spAnimation_dispose(SP_EMPTY_ANIMATION); + SP_EMPTY_ANIMATION = 0; +} + +/* Forward declaration of some "private" functions so we can keep + the same function order in C as we have method order in Java */ +void _spAnimationState_disposeTrackEntry (spTrackEntry* entry); +void _spAnimationState_disposeTrackEntries (spAnimationState* state, spTrackEntry* entry); +int /*boolean*/ _spAnimationState_updateMixingFrom (spAnimationState* self, spTrackEntry* entry, float delta); +float _spAnimationState_applyMixingFrom (spAnimationState* self, spTrackEntry* entry, spSkeleton* skeleton, spMixPose currentPose); +void _spAnimationState_applyRotateTimeline (spAnimationState* self, spTimeline* timeline, spSkeleton* skeleton, float time, float alpha, spMixPose pose, float* timelinesRotation, int i, int /*boolean*/ firstFrame); +void _spAnimationState_queueEvents (spAnimationState* self, spTrackEntry* entry, float animationTime); +void _spAnimationState_setCurrent (spAnimationState* self, int index, spTrackEntry* current, int /*boolean*/ interrupt); +spTrackEntry* _spAnimationState_expandToIndex (spAnimationState* self, int index); +spTrackEntry* _spAnimationState_trackEntry (spAnimationState* self, int trackIndex, spAnimation* animation, int /*boolean*/ loop, spTrackEntry* last); +void _spAnimationState_disposeNext (spAnimationState* self, spTrackEntry* entry); +void _spAnimationState_animationsChanged (spAnimationState* self); +float* _spAnimationState_resizeTimelinesRotation(spTrackEntry* entry, int newSize); +int* _spAnimationState_resizeTimelinesFirst(spTrackEntry* entry, int newSize); +void _spAnimationState_ensureCapacityPropertyIDs(spAnimationState* self, int capacity); +int _spAnimationState_addPropertyID(spAnimationState* self, int id); +spTrackEntry* _spTrackEntry_setTimelineData(spTrackEntry* self, spTrackEntry* to, spTrackEntryArray* mixingToArray, spAnimationState* state); + + +_spEventQueue* _spEventQueue_create (_spAnimationState* state) { + _spEventQueue *self = CALLOC(_spEventQueue, 1); + self->state = state; + self->objectsCount = 0; + self->objectsCapacity = 16; + self->objects = CALLOC(_spEventQueueItem, self->objectsCapacity); + self->drainDisabled = 0; + return self; +} + +void _spEventQueue_free (_spEventQueue* self) { + FREE(self->objects); + FREE(self); +} + +void _spEventQueue_ensureCapacity (_spEventQueue* self, int newElements) { + if (self->objectsCount + newElements > self->objectsCapacity) { + _spEventQueueItem* newObjects; + self->objectsCapacity <<= 1; + newObjects = CALLOC(_spEventQueueItem, self->objectsCapacity); + memcpy(newObjects, self->objects, sizeof(_spEventQueueItem) * self->objectsCount); + FREE(self->objects); + self->objects = newObjects; + } +} + +void _spEventQueue_addType (_spEventQueue* self, spEventType type) { + _spEventQueue_ensureCapacity(self, 1); + self->objects[self->objectsCount++].type = type; +} + +void _spEventQueue_addEntry (_spEventQueue* self, spTrackEntry* entry) { + _spEventQueue_ensureCapacity(self, 1); + self->objects[self->objectsCount++].entry = entry; +} + +void _spEventQueue_addEvent (_spEventQueue* self, spEvent* event) { + _spEventQueue_ensureCapacity(self, 1); + self->objects[self->objectsCount++].event = event; +} + +void _spEventQueue_start (_spEventQueue* self, spTrackEntry* entry) { + _spEventQueue_addType(self, SP_ANIMATION_START); + _spEventQueue_addEntry(self, entry); + self->state->animationsChanged = 1; +} + +void _spEventQueue_interrupt (_spEventQueue* self, spTrackEntry* entry) { + _spEventQueue_addType(self, SP_ANIMATION_INTERRUPT); + _spEventQueue_addEntry(self, entry); +} + +void _spEventQueue_end (_spEventQueue* self, spTrackEntry* entry) { + _spEventQueue_addType(self, SP_ANIMATION_END); + _spEventQueue_addEntry(self, entry); + self->state->animationsChanged = 1; +} + +void _spEventQueue_dispose (_spEventQueue* self, spTrackEntry* entry) { + _spEventQueue_addType(self, SP_ANIMATION_DISPOSE); + _spEventQueue_addEntry(self, entry); +} + +void _spEventQueue_complete (_spEventQueue* self, spTrackEntry* entry) { + _spEventQueue_addType(self, SP_ANIMATION_COMPLETE); + _spEventQueue_addEntry(self, entry); +} + +void _spEventQueue_event (_spEventQueue* self, spTrackEntry* entry, spEvent* event) { + _spEventQueue_addType(self, SP_ANIMATION_EVENT); + _spEventQueue_addEntry(self, entry); + _spEventQueue_addEvent(self, event); +} + +void _spEventQueue_clear (_spEventQueue* self) { + self->objectsCount = 0; +} + +void _spEventQueue_drain (_spEventQueue* self) { + int i; + if (self->drainDisabled) return; + self->drainDisabled = 1; + for (i = 0; i < self->objectsCount; i += 2) { + spEventType type = (spEventType)self->objects[i].type; + spTrackEntry* entry = self->objects[i+1].entry; + spEvent* event; + switch (type) { + case SP_ANIMATION_START: + case SP_ANIMATION_INTERRUPT: + case SP_ANIMATION_COMPLETE: + if (entry->listener) entry->listener(SUPER(self->state), type, entry, 0); + if (self->state->super.listener) self->state->super.listener(SUPER(self->state), type, entry, 0); + break; + case SP_ANIMATION_END: + if (entry->listener) entry->listener(SUPER(self->state), type, entry, 0); + if (self->state->super.listener) self->state->super.listener(SUPER(self->state), type, entry, 0); + /* Fall through. */ + case SP_ANIMATION_DISPOSE: + if (entry->listener) entry->listener(SUPER(self->state), SP_ANIMATION_DISPOSE, entry, 0); + if (self->state->super.listener) self->state->super.listener(SUPER(self->state), SP_ANIMATION_DISPOSE, entry, 0); + _spAnimationState_disposeTrackEntry(entry); + break; + case SP_ANIMATION_EVENT: + event = self->objects[i+2].event; + if (entry->listener) entry->listener(SUPER(self->state), type, entry, event); + if (self->state->super.listener) self->state->super.listener(SUPER(self->state), type, entry, event); + i++; + break; + } + } + _spEventQueue_clear(self); + + self->drainDisabled = 0; +} + +void _spAnimationState_disposeTrackEntry (spTrackEntry* entry) { + spIntArray_dispose(entry->timelineData); + spTrackEntryArray_dispose(entry->timelineDipMix); + FREE(entry->timelinesRotation); + FREE(entry); +} + +void _spAnimationState_disposeTrackEntries (spAnimationState* state, spTrackEntry* entry) { + while (entry) { + spTrackEntry* next = entry->next; + spTrackEntry* from = entry->mixingFrom; + while (from) { + spTrackEntry* nextFrom = from->mixingFrom; + if (entry->listener) entry->listener(state, SP_ANIMATION_DISPOSE, from, 0); + if (state->listener) state->listener(state, SP_ANIMATION_DISPOSE, from, 0); + _spAnimationState_disposeTrackEntry(from); + from = nextFrom; + } + if (entry->listener) entry->listener(state, SP_ANIMATION_DISPOSE, entry, 0); + if (state->listener) state->listener(state, SP_ANIMATION_DISPOSE, entry, 0); + _spAnimationState_disposeTrackEntry(entry); + entry = next; + } +} + +spAnimationState* spAnimationState_create (spAnimationStateData* data) { + _spAnimationState* internal; + spAnimationState* self; + + if (!SP_EMPTY_ANIMATION) { + SP_EMPTY_ANIMATION = (spAnimation*)1; /* dirty trick so we can recursively call spAnimation_create */ + SP_EMPTY_ANIMATION = spAnimation_create("", 0); + } + + internal = NEW(_spAnimationState); + self = SUPER(internal); + + CONST_CAST(spAnimationStateData*, self->data) = data; + self->timeScale = 1; + + internal->queue = _spEventQueue_create(internal); + internal->events = CALLOC(spEvent*, 128); + + internal->propertyIDs = CALLOC(int, 128); + internal->propertyIDsCapacity = 128; + + self->mixingTo = spTrackEntryArray_create(16); + + return self; +} + +void spAnimationState_dispose (spAnimationState* self) { + int i; + _spAnimationState* internal = SUB_CAST(_spAnimationState, self); + for (i = 0; i < self->tracksCount; i++) + _spAnimationState_disposeTrackEntries(self, self->tracks[i]); + FREE(self->tracks); + _spEventQueue_free(internal->queue); + FREE(internal->events); + FREE(internal->propertyIDs); + spTrackEntryArray_dispose(self->mixingTo); + FREE(internal); +} + +void spAnimationState_update (spAnimationState* self, float delta) { + int i, n; + _spAnimationState* internal = SUB_CAST(_spAnimationState, self); + delta *= self->timeScale; + for (i = 0, n = self->tracksCount; i < n; i++) { + float currentDelta; + spTrackEntry* current = self->tracks[i]; + spTrackEntry* next; + if (!current) continue; + + current->animationLast = current->nextAnimationLast; + current->trackLast = current->nextTrackLast; + + currentDelta = delta * current->timeScale; + + if (current->delay > 0) { + current->delay -= currentDelta; + if (current->delay > 0) continue; + currentDelta = -current->delay; + current->delay = 0; + } + + next = current->next; + if (next) { + /* When the next entry's delay is passed, change to the next entry, preserving leftover time. */ + float nextTime = current->trackLast - next->delay; + if (nextTime >= 0) { + next->delay = 0; + next->trackTime = nextTime + delta * next->timeScale; + current->trackTime += currentDelta; + _spAnimationState_setCurrent(self, i, next, 1); + while (next->mixingFrom) { + next->mixTime += currentDelta; + next = next->mixingFrom; + } + continue; + } + } else { + /* Clear the track when there is no next entry, the track end time is reached, and there is no mixingFrom. */ + if (current->trackLast >= current->trackEnd && current->mixingFrom == 0) { + self->tracks[i] = 0; + _spEventQueue_end(internal->queue, current); + _spAnimationState_disposeNext(self, current); + continue; + } + } + if (current->mixingFrom != 0 && _spAnimationState_updateMixingFrom(self, current, delta)) { + /* End mixing from entries once all have completed. */ + spTrackEntry* from = current->mixingFrom; + current->mixingFrom = 0; + while (from != 0) { + _spEventQueue_end(internal->queue, from); + from = from->mixingFrom; + } + } + + current->trackTime += currentDelta; + } + + _spEventQueue_drain(internal->queue); +} + +int /*boolean*/ _spAnimationState_updateMixingFrom (spAnimationState* self, spTrackEntry* to, float delta) { + spTrackEntry* from = to->mixingFrom; + int finished; + _spAnimationState* internal = SUB_CAST(_spAnimationState, self); + if (!from) return -1; + + finished = _spAnimationState_updateMixingFrom(self, from, delta); + + /* Require mixTime > 0 to ensure the mixing from entry was applied at least once. */ + if (to->mixTime > 0 && (to->mixTime >= to->mixDuration || to->timeScale == 0)) { + /* Require totalAlpha == 0 to ensure mixing is complete, unless mixDuration == 0 (the transition is a single frame). */ + if (from->totalAlpha == 0 || to->mixDuration == 0) { + to->mixingFrom = from->mixingFrom; + to->interruptAlpha = from->interruptAlpha; + _spEventQueue_end(internal->queue, from); + } + return finished; + } + + from->animationLast = from->nextAnimationLast; + from->trackLast = from->nextTrackLast; + from->trackTime += delta * from->timeScale; + to->mixTime += delta * to->timeScale; + return 0; +} + +int spAnimationState_apply (spAnimationState* self, spSkeleton* skeleton) { + _spAnimationState* internal = SUB_CAST(_spAnimationState, self); + spTrackEntry* current; + int i, ii, n; + float animationLast, animationTime; + int timelineCount; + spTimeline** timelines; + int /*boolean*/ firstFrame; + float* timelinesRotation; + spTimeline* timeline; + int applied = 0; + spMixPose currentPose; + spMixPose pose; + + if (internal->animationsChanged) _spAnimationState_animationsChanged(self); + + for (i = 0, n = self->tracksCount; i < n; i++) { + float mix; + current = self->tracks[i]; + if (!current || current->delay > 0) continue; + applied = -1; + currentPose = i == 0 ? SP_MIX_POSE_CURRENT : SP_MIX_POSE_CURRENT_LAYERED; + + /* Apply mixing from entries first. */ + mix = current->alpha; + if (current->mixingFrom) + mix *= _spAnimationState_applyMixingFrom(self, current, skeleton, currentPose); + else if (current->trackTime >= current->trackEnd && current->next == 0) + mix = 0; + + /* Apply current entry. */ + animationLast = current->animationLast; animationTime = spTrackEntry_getAnimationTime(current); + timelineCount = current->animation->timelinesCount; + timelines = current->animation->timelines; + if (mix == 1) { + for (ii = 0; ii < timelineCount; ii++) + spTimeline_apply(timelines[ii], skeleton, animationLast, animationTime, internal->events, &internal->eventsCount, 1, SP_MIX_POSE_SETUP, SP_MIX_DIRECTION_IN); + } else { + spIntArray* timelineData = current->timelineData; + + firstFrame = current->timelinesRotationCount == 0; + if (firstFrame) _spAnimationState_resizeTimelinesRotation(current, timelineCount << 1); + timelinesRotation = current->timelinesRotation; + + for (ii = 0; ii < timelineCount; ii++) { + timeline = timelines[ii]; + pose = timelineData->items[ii] >= FIRST ? SP_MIX_POSE_SETUP : currentPose; + if (timeline->type == SP_TIMELINE_ROTATE) + _spAnimationState_applyRotateTimeline(self, timeline, skeleton, animationTime, mix, pose, timelinesRotation, ii << 1, firstFrame); + else + spTimeline_apply(timeline, skeleton, animationLast, animationTime, internal->events, &internal->eventsCount, mix, pose, SP_MIX_DIRECTION_IN); + } + } + _spAnimationState_queueEvents(self, current, animationTime); + internal->eventsCount = 0; + current->nextAnimationLast = animationTime; + current->nextTrackLast = current->trackTime; + } + + _spEventQueue_drain(internal->queue); + return applied; +} + +float _spAnimationState_applyMixingFrom (spAnimationState* self, spTrackEntry* to, spSkeleton* skeleton, spMixPose currentPose) { + _spAnimationState* internal = SUB_CAST(_spAnimationState, self); + float mix; + spEvent** events; + int /*boolean*/ attachments; + int /*boolean*/ drawOrder; + float animationLast; + float animationTime; + int timelineCount; + spTimeline** timelines; + spIntArray* timelineData; + spTrackEntryArray* timelineDipMix; + float alphaDip; + float alphaMix; + float alpha; + int /*boolean*/ firstFrame; + float* timelinesRotation; + spMixPose pose; + int i; + spTrackEntry* dipMix; + + spTrackEntry* from = to->mixingFrom; + if (from->mixingFrom) _spAnimationState_applyMixingFrom(self, from, skeleton, currentPose); + + if (to->mixDuration == 0) /* Single frame mix to undo mixingFrom changes. */ + mix = 1; + else { + mix = to->mixTime / to->mixDuration; + if (mix > 1) mix = 1; + } + + events = mix < from->eventThreshold ? internal->events : 0; + attachments = mix < from->attachmentThreshold; + drawOrder = mix < from->drawOrderThreshold; + animationLast = from->animationLast; + animationTime = spTrackEntry_getAnimationTime(from); + timelineCount = from->animation->timelinesCount; + timelines = from->animation->timelines; + timelineData = from->timelineData; + timelineDipMix = from->timelineDipMix; + + firstFrame = from->timelinesRotationCount == 0; + if (firstFrame) _spAnimationState_resizeTimelinesRotation(from, timelineCount << 1); + timelinesRotation = from->timelinesRotation; + + alphaDip = from->alpha * to->interruptAlpha; alphaMix = alphaDip * (1 - mix); + from->totalAlpha = 0; + for (i = 0; i < timelineCount; i++) { + spTimeline* timeline = timelines[i]; + switch (timelineData->items[i]) { + case SUBSEQUENT: + if (!attachments && timeline->type == SP_TIMELINE_ATTACHMENT) continue; + if (!drawOrder && timeline->type == SP_TIMELINE_DRAWORDER) continue; + pose = currentPose; + alpha = alphaMix; + break; + case FIRST: + pose = SP_MIX_POSE_SETUP; + alpha = alphaMix; + break; + case DIP: + pose = SP_MIX_POSE_SETUP; + alpha = alphaDip; + break; + default: + pose = SP_MIX_POSE_SETUP; + alpha = alphaDip; + dipMix = timelineDipMix->items[i]; + alpha *= MAX(0, 1 - dipMix->mixTime / dipMix->mixDuration); + break; + } + from->totalAlpha += alpha; + if (timeline->type == SP_TIMELINE_ROTATE) + _spAnimationState_applyRotateTimeline(self, timeline, skeleton, animationTime, alpha, pose, timelinesRotation, i << 1, firstFrame); + else { + spTimeline_apply(timeline, skeleton, animationLast, animationTime, events, &internal->eventsCount, alpha, pose, SP_MIX_DIRECTION_OUT); + } + } + + + if (to->mixDuration > 0) _spAnimationState_queueEvents(self, from, animationTime); + internal->eventsCount = 0; + from->nextAnimationLast = animationTime; + from->nextTrackLast = from->trackTime; + + return mix; +} + +void _spAnimationState_applyRotateTimeline (spAnimationState* self, spTimeline* timeline, spSkeleton* skeleton, float time, float alpha, spMixPose pose, float* timelinesRotation, int i, int /*boolean*/ firstFrame) { + spRotateTimeline *rotateTimeline; + float *frames; + spBone* bone; + float r1, r2; + int frame; + float prevRotation; + float frameTime; + float percent; + float total, diff; + int /*boolean*/ current, dir; + + if (firstFrame) timelinesRotation[i] = 0; + + if (alpha == 1) { + spTimeline_apply(timeline, skeleton, 0, time, 0, 0, 1, pose, SP_MIX_DIRECTION_IN); + return; + } + + rotateTimeline = SUB_CAST(spRotateTimeline, timeline); + frames = rotateTimeline->frames; + bone = skeleton->bones[rotateTimeline->boneIndex]; + if (time < frames[0]) { + if (pose == SP_MIX_POSE_SETUP) { + bone->rotation = bone->data->rotation; + } + return; /* Time is before first frame. */ + } + + if (time >= frames[rotateTimeline->framesCount - ROTATE_ENTRIES]) /* Time is after last frame. */ + r2 = bone->data->rotation + frames[rotateTimeline->framesCount + ROTATE_PREV_ROTATION]; + else { + /* Interpolate between the previous frame and the current frame. */ + frame = _spCurveTimeline_binarySearch(frames, rotateTimeline->framesCount, time, ROTATE_ENTRIES); + prevRotation = frames[frame + ROTATE_PREV_ROTATION]; + frameTime = frames[frame]; + percent = spCurveTimeline_getCurvePercent(SUPER(rotateTimeline), (frame >> 1) - 1, + 1 - (time - frameTime) / (frames[frame + ROTATE_PREV_TIME] - frameTime)); + + r2 = frames[frame + ROTATE_ROTATION] - prevRotation; + r2 -= (16384 - (int)(16384.499999999996 - r2 / 360)) * 360; + r2 = prevRotation + r2 * percent + bone->data->rotation; + r2 -= (16384 - (int)(16384.499999999996 - r2 / 360)) * 360; + } + + /* Mix between rotations using the direction of the shortest route on the first frame while detecting crosses. */ + r1 = pose == SP_MIX_POSE_SETUP ? bone->data->rotation : bone->rotation; + diff = r2 - r1; + if (diff == 0) { + total = timelinesRotation[i]; + } else { + float lastTotal, lastDiff; + diff -= (16384 - (int)(16384.499999999996 - diff / 360)) * 360; + if (firstFrame) { + lastTotal = 0; + lastDiff = diff; + } else { + lastTotal = timelinesRotation[i]; /* Angle and direction of mix, including loops. */ + lastDiff = timelinesRotation[i + 1]; /* Difference between bones. */ + } + current = diff > 0; + dir = lastTotal >= 0; + /* Detect cross at 0 (not 180). */ + if (SIGNUM(lastDiff) != SIGNUM(diff) && ABS(lastDiff) <= 90) { + /* A cross after a 360 rotation is a loop. */ + if (ABS(lastTotal) > 180) lastTotal += 360 * SIGNUM(lastTotal); + dir = current; + } + total = diff + lastTotal - FMOD(lastTotal, 360); /* Store loops as part of lastTotal. */ + if (dir != current) total += 360 * SIGNUM(lastTotal); + timelinesRotation[i] = total; + } + timelinesRotation[i + 1] = diff; + r1 += total * alpha; + bone->rotation = r1 - (16384 - (int)(16384.499999999996 - r1 / 360)) * 360; +} + +void _spAnimationState_queueEvents (spAnimationState* self, spTrackEntry* entry, float animationTime) { + spEvent** events; + spEvent* event; + _spAnimationState* internal = SUB_CAST(_spAnimationState, self); + int i, n; + float animationStart = entry->animationStart, animationEnd = entry->animationEnd; + float duration = animationEnd - animationStart; + float trackLastWrapped = FMOD(entry->trackLast, duration); + + /* Queue events before complete. */ + events = internal->events; + for (i = 0, n = internal->eventsCount; i < n; i++) { + event = events[i]; + if (event->time < trackLastWrapped) break; + if (event->time > animationEnd) continue; /* Discard events outside animation start/end. */ + _spEventQueue_event(internal->queue, entry, event); + } + + /* Queue complete if completed a loop iteration or the animation. */ + if (entry->loop ? (trackLastWrapped > FMOD(entry->trackTime, duration)) + : (animationTime >= animationEnd && entry->animationLast < animationEnd)) { + _spEventQueue_complete(internal->queue, entry); + } + + /* Queue events after complete. */ + for (; i < n; i++) { + event = events[i]; + if (event->time < animationStart) continue; /* Discard events outside animation start/end. */ + _spEventQueue_event(internal->queue, entry, event); + } +} + +void spAnimationState_clearTracks (spAnimationState* self) { + _spAnimationState* internal = SUB_CAST(_spAnimationState, self); + int i, n, oldDrainDisabled; + oldDrainDisabled = internal->queue->drainDisabled; + internal->queue->drainDisabled = 1; + for (i = 0, n = self->tracksCount; i < n; i++) + spAnimationState_clearTrack(self, i); + self->tracksCount = 0; + internal->queue->drainDisabled = oldDrainDisabled; + _spEventQueue_drain(internal->queue); +} + +void spAnimationState_clearTrack (spAnimationState* self, int trackIndex) { + spTrackEntry* current; + spTrackEntry* entry; + spTrackEntry* from; + _spAnimationState* internal = SUB_CAST(_spAnimationState, self); + + if (trackIndex >= self->tracksCount) return; + current = self->tracks[trackIndex]; + if (!current) return; + + _spEventQueue_end(internal->queue, current); + + _spAnimationState_disposeNext(self, current); + + entry = current; + while (1) { + from = entry->mixingFrom; + if (!from) break; + _spEventQueue_end(internal->queue, from); + entry->mixingFrom = 0; + entry = from; + } + + self->tracks[current->trackIndex] = 0; + _spEventQueue_drain(internal->queue); +} + +void _spAnimationState_setCurrent (spAnimationState* self, int index, spTrackEntry* current, int /*boolean*/ interrupt) { + _spAnimationState* internal = SUB_CAST(_spAnimationState, self); + spTrackEntry* from = _spAnimationState_expandToIndex(self, index); + self->tracks[index] = current; + + if (from) { + if (interrupt) _spEventQueue_interrupt(internal->queue, from); + current->mixingFrom = from; + current->mixTime = 0; + + /* Store the interrupted mix percentage. */ + if (from->mixingFrom != 0 && from->mixDuration > 0) + current->interruptAlpha *= MIN(1, from->mixTime / from->mixDuration); + + from->timelinesRotationCount = 0; + } + + _spEventQueue_start(internal->queue, current); +} + +/** Set the current animation. Any queued animations are cleared. */ +spTrackEntry* spAnimationState_setAnimationByName (spAnimationState* self, int trackIndex, const char* animationName, + int/*bool*/loop) { + spAnimation* animation = spSkeletonData_findAnimation(self->data->skeletonData, animationName); + return spAnimationState_setAnimation(self, trackIndex, animation, loop); +} + +spTrackEntry* spAnimationState_setAnimation (spAnimationState* self, int trackIndex, spAnimation* animation, int/*bool*/loop) { + spTrackEntry* entry; + _spAnimationState* internal = SUB_CAST(_spAnimationState, self); + int interrupt = 1; + spTrackEntry* current = _spAnimationState_expandToIndex(self, trackIndex); + if (current) { + if (current->nextTrackLast == -1) { + /* Don't mix from an entry that was never applied. */ + self->tracks[trackIndex] = current->mixingFrom; + _spEventQueue_interrupt(internal->queue, current); + _spEventQueue_end(internal->queue, current); + _spAnimationState_disposeNext(self, current); + current = current->mixingFrom; + interrupt = 0; + } else + _spAnimationState_disposeNext(self, current); + } + entry = _spAnimationState_trackEntry(self, trackIndex, animation, loop, current); + _spAnimationState_setCurrent(self, trackIndex, entry, interrupt); + _spEventQueue_drain(internal->queue); + return entry; +} + +/** Adds an animation to be played delay seconds after the current or last queued animation, taking into account any mix + * duration. */ +spTrackEntry* spAnimationState_addAnimationByName (spAnimationState* self, int trackIndex, const char* animationName, + int/*bool*/loop, float delay) { + spAnimation* animation = spSkeletonData_findAnimation(self->data->skeletonData, animationName); + return spAnimationState_addAnimation(self, trackIndex, animation, loop, delay); +} + +spTrackEntry* spAnimationState_addAnimation (spAnimationState* self, int trackIndex, spAnimation* animation, int/*bool*/loop, + float delay) { + spTrackEntry* entry; + _spAnimationState* internal = SUB_CAST(_spAnimationState, self); + spTrackEntry* last = _spAnimationState_expandToIndex(self, trackIndex); + if (last) { + while (last->next) + last = last->next; + } + + entry = _spAnimationState_trackEntry(self, trackIndex, animation, loop, last); + + if (!last) { + _spAnimationState_setCurrent(self, trackIndex, entry, 1); + _spEventQueue_drain(internal->queue); + } else { + last->next = entry; + if (delay <= 0) { + float duration = last->animationEnd - last->animationStart; + if (duration != 0) + delay += duration * (1 + (int)(last->trackTime / duration)) - spAnimationStateData_getMix(self->data, last->animation, animation); + else + delay = 0; + } + } + + entry->delay = delay; + return entry; +} + +spTrackEntry* spAnimationState_setEmptyAnimation(spAnimationState* self, int trackIndex, float mixDuration) { + spTrackEntry* entry = spAnimationState_setAnimation(self, trackIndex, SP_EMPTY_ANIMATION, 0); + entry->mixDuration = mixDuration; + entry->trackEnd = mixDuration; + return entry; +} + +spTrackEntry* spAnimationState_addEmptyAnimation(spAnimationState* self, int trackIndex, float mixDuration, float delay) { + spTrackEntry* entry; + if (delay <= 0) delay -= mixDuration; + entry = spAnimationState_addAnimation(self, trackIndex, SP_EMPTY_ANIMATION, 0, delay); + entry->mixDuration = mixDuration; + entry->trackEnd = mixDuration; + return entry; +} + +void spAnimationState_setEmptyAnimations(spAnimationState* self, float mixDuration) { + int i, n, oldDrainDisabled; + spTrackEntry* current; + _spAnimationState* internal = SUB_CAST(_spAnimationState, self); + oldDrainDisabled = internal->queue->drainDisabled; + internal->queue->drainDisabled = 1; + for (i = 0, n = self->tracksCount; i < n; i++) { + current = self->tracks[i]; + if (current) spAnimationState_setEmptyAnimation(self, current->trackIndex, mixDuration); + } + internal->queue->drainDisabled = oldDrainDisabled; + _spEventQueue_drain(internal->queue); +} + +spTrackEntry* _spAnimationState_expandToIndex (spAnimationState* self, int index) { + spTrackEntry** newTracks; + if (index < self->tracksCount) return self->tracks[index]; + newTracks = CALLOC(spTrackEntry*, index + 1); + memcpy(newTracks, self->tracks, self->tracksCount * sizeof(spTrackEntry*)); + FREE(self->tracks); + self->tracks = newTracks; + self->tracksCount = index + 1; + return 0; +} + +spTrackEntry* _spAnimationState_trackEntry (spAnimationState* self, int trackIndex, spAnimation* animation, int /*boolean*/ loop, spTrackEntry* last) { + spTrackEntry* entry = NEW(spTrackEntry); + entry->trackIndex = trackIndex; + entry->animation = animation; + entry->loop = loop; + + entry->eventThreshold = 0; + entry->attachmentThreshold = 0; + entry->drawOrderThreshold = 0; + + entry->animationStart = 0; + entry->animationEnd = animation->duration; + entry->animationLast = -1; + entry->nextAnimationLast = -1; + + entry->delay = 0; + entry->trackTime = 0; + entry->trackLast = -1; + entry->nextTrackLast = -1; + entry->trackEnd = (float)INT_MAX; + entry->timeScale = 1; + + entry->alpha = 1; + entry->interruptAlpha = 1; + entry->mixTime = 0; + entry->mixDuration = !last ? 0 : spAnimationStateData_getMix(self->data, last->animation, animation); + + entry->timelineData = spIntArray_create(16); + entry->timelineDipMix = spTrackEntryArray_create(16); + return entry; +} + +void _spAnimationState_disposeNext (spAnimationState* self, spTrackEntry* entry) { + _spAnimationState* internal = SUB_CAST(_spAnimationState, self); + spTrackEntry* next = entry->next; + while (next) { + _spEventQueue_dispose(internal->queue, next); + next = next->next; + } + entry->next = 0; +} + +void _spAnimationState_animationsChanged (spAnimationState* self) { + _spAnimationState* internal = SUB_CAST(_spAnimationState, self); + int i, n; + spTrackEntry* entry; + spTrackEntryArray* mixingTo; + internal->animationsChanged = 0; + + internal->propertyIDsCount = 0; + i = 0; n = self->tracksCount; + + mixingTo = self->mixingTo; + + for (;i < n; i++) { + entry = self->tracks[i]; + if (entry != 0) _spTrackEntry_setTimelineData(entry, 0, mixingTo, self); + } +} + +float* _spAnimationState_resizeTimelinesRotation(spTrackEntry* entry, int newSize) { + if (entry->timelinesRotationCount != newSize) { + float* newTimelinesRotation = CALLOC(float, newSize); + FREE(entry->timelinesRotation); + entry->timelinesRotation = newTimelinesRotation; + entry->timelinesRotationCount = newSize; + } + return entry->timelinesRotation; +} + +void _spAnimationState_ensureCapacityPropertyIDs(spAnimationState* self, int capacity) { + _spAnimationState* internal = SUB_CAST(_spAnimationState, self); + if (internal->propertyIDsCapacity < capacity) { + int *newPropertyIDs = CALLOC(int, capacity << 1); + memcpy(newPropertyIDs, internal->propertyIDs, sizeof(int) * internal->propertyIDsCount); + FREE(internal->propertyIDs); + internal->propertyIDs = newPropertyIDs; + internal->propertyIDsCapacity = capacity << 1; + } +} + +int _spAnimationState_addPropertyID(spAnimationState* self, int id) { + int i, n; + _spAnimationState* internal = SUB_CAST(_spAnimationState, self); + + for (i = 0, n = internal->propertyIDsCount; i < n; i++) { + if (internal->propertyIDs[i] == id) return 0; + } + + _spAnimationState_ensureCapacityPropertyIDs(self, internal->propertyIDsCount + 1); + internal->propertyIDs[internal->propertyIDsCount] = id; + internal->propertyIDsCount++; + return 1; +} + +spTrackEntry* spAnimationState_getCurrent (spAnimationState* self, int trackIndex) { + if (trackIndex >= self->tracksCount) return 0; + return self->tracks[trackIndex]; +} + +void spAnimationState_clearListenerNotifications(spAnimationState* self) { + _spAnimationState* internal = SUB_CAST(_spAnimationState, self); + _spEventQueue_clear(internal->queue); +} + +float spTrackEntry_getAnimationTime (spTrackEntry* entry) { + if (entry->loop) { + float duration = entry->animationEnd - entry->animationStart; + if (duration == 0) return entry->animationStart; + return FMOD(entry->trackTime, duration) + entry->animationStart; + } + return MIN(entry->trackTime + entry->animationStart, entry->animationEnd); +} + +int /*boolean*/ _spTrackEntry_hasTimeline(spTrackEntry* self, int id) { + spTimeline** timelines = self->animation->timelines; + int i, n; + for (i = 0, n = self->animation->timelinesCount; i < n; i++) + if (spTimeline_getPropertyId(timelines[i]) == id) return 1; + return 0; +} + +spTrackEntry* _spTrackEntry_setTimelineData(spTrackEntry* self, spTrackEntry* to, spTrackEntryArray* mixingToArray, spAnimationState* state) { + spTrackEntry* lastEntry; + spTrackEntry** mixingTo; + int mixingToLast; + spTimeline** timelines; + int timelinesCount; + int* timelineData; + spTrackEntry** timelineDipMix; + int i, ii; + + if (to != 0) spTrackEntryArray_add(mixingToArray, to); + lastEntry = self->mixingFrom != 0 ? _spTrackEntry_setTimelineData(self->mixingFrom, self, mixingToArray, state) : self; + if (to != 0) spTrackEntryArray_pop(mixingToArray); + + mixingTo = mixingToArray->items; + mixingToLast = mixingToArray->size - 1; + timelines = self->animation->timelines; + timelinesCount = self->animation->timelinesCount; + timelineData = spIntArray_setSize(self->timelineData, timelinesCount)->items; + spTrackEntryArray_clear(self->timelineDipMix); + timelineDipMix = spTrackEntryArray_setSize(self->timelineDipMix, timelinesCount)->items; + + i = 0; + continue_outer: + for (; i < timelinesCount; i++) { + int id = spTimeline_getPropertyId(timelines[i]); + if (!_spAnimationState_addPropertyID(state, id)) + timelineData[i] = SUBSEQUENT; + else if (to == 0 || !_spTrackEntry_hasTimeline(to, id)) + timelineData[i] = FIRST; + else { + for (ii = mixingToLast; ii >= 0; ii--) { + spTrackEntry* entry = mixingTo[ii]; + if (!_spTrackEntry_hasTimeline(entry, id)) { + if (entry->mixDuration > 0) { + timelineData[i] = DIP_MIX; + timelineDipMix[i] = entry; + i++; + goto continue_outer; + } + } + break; + } + timelineData[i] = DIP; + } + } + return lastEntry; +} diff --git a/spine-cpp/spine-cpp/src/spine/AnimationStateData.c b/spine-cpp/spine-cpp/src/spine/AnimationStateData.c new file mode 100644 index 000000000..2aeb25add --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/AnimationStateData.c @@ -0,0 +1,151 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include + +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; +} diff --git a/spine-cpp/spine-cpp/src/spine/Array.c b/spine-cpp/spine-cpp/src/spine/Array.c new file mode 100644 index 000000000..03a32bc78 --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/Array.c @@ -0,0 +1,39 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include + +_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*) diff --git a/spine-cpp/spine-cpp/src/spine/Atlas.c b/spine-cpp/spine-cpp/src/spine/Atlas.c new file mode 100644 index 000000000..92437633f --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/Atlas.c @@ -0,0 +1,359 @@ +/****************************************************************************** +* Spine Runtimes Software License v2.5 +* +* Copyright (c) 2013-2016, Esoteric Software +* All rights reserved. +* +* You are granted a perpetual, non-exclusive, non-sublicensable, and +* non-transferable license to use, install, execute, and perform the Spine +* Runtimes software and derivative works solely for personal or internal +* use. Without the written permission of Esoteric Software (see Section 2 of +* the Spine Software License Agreement), you may not (a) modify, translate, +* adapt, or develop new applications using the Spine Runtimes or otherwise +* create derivative works or improvements of the Spine Runtimes or (b) remove, +* delete, alter, or obscure any trademarks or any copyright, trademark, patent, +* or other intellectual property or proprietary rights notices on or in the +* Software, including any copy thereof. Redistributions in binary or source +* form must include this license and terms. +* +* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +#include +#include +#include + +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 (isspace((unsigned char)*str->end) && 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); + region->rotate = equals(&str, "true"); + + 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; +} diff --git a/spine-cpp/spine-cpp/src/spine/AtlasAttachmentLoader.c b/spine-cpp/spine-cpp/src/spine/AtlasAttachmentLoader.c new file mode 100644 index 000000000..c4a613709 --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/AtlasAttachmentLoader.c @@ -0,0 +1,100 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include + +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->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(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; +} diff --git a/spine-cpp/spine-cpp/src/spine/Attachment.c b/spine-cpp/spine-cpp/src/spine/Attachment.c new file mode 100644 index 000000000..3dad43a69 --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/Attachment.c @@ -0,0 +1,57 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include +#include + +typedef struct _spAttachmentVtable { + void (*dispose) (spAttachment* self); +} _spAttachmentVtable; + +void _spAttachment_init (spAttachment* self, const char* name, spAttachmentType type, /**/ + void (*dispose) (spAttachment* self)) { + + CONST_CAST(_spAttachmentVtable*, self->vtable) = NEW(_spAttachmentVtable); + VTABLE(spAttachment, self) ->dispose = dispose; + + 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); +} + +void spAttachment_dispose (spAttachment* self) { + VTABLE(spAttachment, self) ->dispose(self); +} diff --git a/spine-cpp/spine-cpp/src/spine/AttachmentLoader.c b/spine-cpp/spine-cpp/src/spine/AttachmentLoader.c new file mode 100644 index 000000000..14cbd92ab --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/AttachmentLoader.c @@ -0,0 +1,98 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include +#include + +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); +} diff --git a/spine-cpp/spine-cpp/src/spine/Bone.c b/spine-cpp/spine-cpp/src/spine/Bone.c new file mode 100644 index 000000000..96d43cb6d --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/Bone.c @@ -0,0 +1,304 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include +#include +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; + + 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; + 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; + if (self->skeleton->flipX) { + x = -x; + la = -la; + lb = -lb; + } + if (self->skeleton->flipY != yDown) { + y = -y; + lc = -lc; + ld = -ld; + } + CONST_CAST(float, self->a) = la; + CONST_CAST(float, self->b) = lb; + CONST_CAST(float, self->c) = lc; + CONST_CAST(float, self->d) = ld; + CONST_CAST(float, self->worldX) = x + self->skeleton->x; + CONST_CAST(float, self->worldY) = y + 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; + zc = pc * cosine + pd * sine; + s = SQRT(za * za + zc * zc); + if (s > 0.00001f) s = 1 / s; + za *= s; + zc *= s; + s = SQRT(za * za + zc * zc); + 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; + if (self->data->transformMode != SP_TRANSFORMMODE_NOSCALEORREFLECTION ? pa * pd - pb * pc < 0 : self->skeleton->flipX != self->skeleton->flipY) { + zb = -zb; + zd = -zd; + } + 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; + return; + } + } + if (self->skeleton->flipX) { + CONST_CAST(float, self->a) = -self->a; + CONST_CAST(float, self->b) = -self->b; + } + if (self->skeleton->flipY != yDown) { + CONST_CAST(float, self->c) = -self->c; + CONST_CAST(float, self->d) = -self->d; + } +} + +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). + *

+ * 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; +} + +float spBone_localToWorldRotation (spBone* self, float localRotation) { + float sine, cosine; + 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; +} diff --git a/spine-cpp/spine-cpp/src/spine/BoneData.c b/spine-cpp/spine-cpp/src/spine/BoneData.c new file mode 100644 index 000000000..5933571ed --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/BoneData.c @@ -0,0 +1,48 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include + +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); +} diff --git a/spine-cpp/spine-cpp/src/spine/BoundingBoxAttachment.c b/spine-cpp/spine-cpp/src/spine/BoundingBoxAttachment.c new file mode 100644 index 000000000..f8b45f5c7 --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/BoundingBoxAttachment.c @@ -0,0 +1,47 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include + +void _spBoundingBoxAttachment_dispose (spAttachment* attachment) { + spBoundingBoxAttachment* self = SUB_CAST(spBoundingBoxAttachment, attachment); + + _spVertexAttachment_deinit(SUPER(self)); + + FREE(self); +} + +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); + return self; +} diff --git a/spine-cpp/spine-cpp/src/spine/ClippingAttachment.c b/spine-cpp/spine-cpp/src/spine/ClippingAttachment.c new file mode 100644 index 000000000..38ea8dd31 --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/ClippingAttachment.c @@ -0,0 +1,48 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include + +void _spClippingAttachment_dispose (spAttachment* attachment) { + spClippingAttachment* self = SUB_CAST(spClippingAttachment, attachment); + + _spVertexAttachment_deinit(SUPER(self)); + + FREE(self); +} + +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); + self->endSlot = 0; + return self; +} diff --git a/spine-cpp/spine-cpp/src/spine/Color.c b/spine-cpp/spine-cpp/src/spine/Color.c new file mode 100644 index 000000000..02168ee3c --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/Color.c @@ -0,0 +1,84 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include + +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; +} + +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; +} diff --git a/spine-cpp/spine-cpp/src/spine/Event.c b/spine-cpp/spine-cpp/src/spine/Event.c new file mode 100644 index 000000000..7c1435cef --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/Event.c @@ -0,0 +1,44 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include + +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); +} diff --git a/spine-cpp/spine-cpp/src/spine/EventData.c b/spine-cpp/spine-cpp/src/spine/EventData.c new file mode 100644 index 000000000..8b0014f78 --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/EventData.c @@ -0,0 +1,44 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include + +spEventData* spEventData_create (const char* name) { + spEventData* self = NEW(spEventData); + MALLOC_STR(self->name, name); + return self; +} + +void spEventData_dispose (spEventData* self) { + FREE(self->stringValue); + FREE(self->name); + FREE(self); +} diff --git a/spine-cpp/spine-cpp/src/spine/IkConstraint.c b/spine-cpp/spine-cpp/src/spine/IkConstraint.c new file mode 100644 index 000000000..1caab6379 --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/IkConstraint.c @@ -0,0 +1,208 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include +#include +#include + +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->mix = data->mix; + + 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->mix); + break; + case 2: + spIkConstraint_apply2(self->bones[0], self->bones[1], self->target->worldX, self->target->worldY, self->bendDirection, self->mix); + break; + } +} + +void spIkConstraint_apply1 (spBone* bone, float targetX, float targetY, float alpha) { + spBone* p = bone->parent; + float id, x, y, tx, ty, rotationIK; + if (!bone->appliedValid) spBone_updateAppliedTransform(bone); + id = 1 / (p->a * p->d - p->b * p->c); + x = targetX - p->worldX, y = targetY - p->worldY; + tx = (x * p->d - y * p->b) * id - bone->ax; ty = (y * p->a - x * p->c) * id - bone->ay; + rotationIK = ATAN2(ty, tx) * RAD_DEG - bone->ashearX - bone->arotation; + if (bone->ascaleX < 0) rotationIK += 180; + if (rotationIK > 180) rotationIK -= 360; + else if (rotationIK < -180) rotationIK += 360; + spBone_updateWorldTransformWith(bone, bone->ax, bone->ay, bone->arotation + rotationIK * alpha, bone->ascaleX, + bone->ascaleY, bone->ashearX, bone->ashearY); +} + +void spIkConstraint_apply2 (spBone* parent, spBone* child, float targetX, float targetY, int bendDir, float alpha) { + float px, py, psx, psy; + float cx, cy, csx, cwx, cwy; + int o1, o2, s2, u; + spBone* pp = parent->parent; + float tx, ty, dx, dy, l1, l2, a1, a2, r; + float id, x, y; + 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; 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; + } + id = 1 / (pp->a * pp->d - pp->b * pp->c); + x = targetX - pp->worldX; + y = targetY - pp->worldY; + tx = (x * pp->d - y * pp->b) * id - px; + ty = (y * pp->a - x * pp->c) * id - py; + x = cwx - pp->worldX; + y = cwy - pp->worldY; + dx = (x * pp->d - y * pp->b) * id - px; + dy = (y * pp->a - x * pp->c) * id - py; + l1 = SQRT(dx * dx + dy * dy); + l2 = child->data->length * csx; + if (u) { + float cosine, a, b; + l2 *= psx; + cosine = (tx * tx + ty * ty - l1 * l1 - l2 * l2) / (2 * l1 * l2); + if (cosine < -1) cosine = -1; + else if (cosine > 1) cosine = 1; + a2 = ACOS(cosine) * bendDir; + a = l1 + l2 * cosine; + b = l2 * SIN(a2); + a1 = ATAN2(ty * a - tx * b, tx * a + ty * b); + } else { + float a = psx * l2, b = psy * l2; + float aa = a * a, bb = b * b, ll = l1 * l1, dd = tx * tx + ty * ty, ta = ATAN2(ty, tx); + float c0 = bb * ll + aa * dd - aa * bb, c1 = -2 * bb * l1, c2 = bb - aa; + float 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, parent->ascaleX, 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); + } +} diff --git a/spine-cpp/spine-cpp/src/spine/IkConstraintData.c b/spine-cpp/spine-cpp/src/spine/IkConstraintData.c new file mode 100644 index 000000000..b557cc58f --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/IkConstraintData.c @@ -0,0 +1,46 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include + +spIkConstraintData* spIkConstraintData_create (const char* name) { + spIkConstraintData* self = NEW(spIkConstraintData); + MALLOC_STR(self->name, name); + self->bendDirection = 1; + self->mix = 1; + return self; +} + +void spIkConstraintData_dispose (spIkConstraintData* self) { + FREE(self->name); + FREE(self->bones); + FREE(self); +} diff --git a/spine-cpp/spine-cpp/src/spine/Json.c b/spine-cpp/spine-cpp/src/spine/Json.c new file mode 100644 index 000000000..6225ff00c --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/Json.c @@ -0,0 +1,426 @@ +/* + 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 +#include +#include /* strtod (C89), strtof (C99) */ +#include /* strcasecmp (4.4BSD - compatibility), _stricmp (_WIN32) */ +#include + +#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) { + char * endptr; + float n; + + /* Using strtod and strtof is slightly more permissive than RFC4627, + * accepting for example hex-encoded floating point, but either + * is often leagues faster than any manual implementation. + * + * We also already know that this starts with [-0-9] from parse_value. + */ +#if __STDC_VERSION__ >= 199901L + n = strtof(num, &endptr); +#else + n = (float)strtod( num, &endptr ); +#endif + /* ignore errno's ERANGE, which returns +/-HUGE_VAL */ + /* n is 0 on any other error */ + + if (endptr != num) { + /* Parse success, number found. */ + item->valueFloat = n; + item->valueInt = (int)n; + item->type = Json_Number; + return endptr; + } 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; +} diff --git a/spine-cpp/spine-cpp/src/spine/Json.h b/spine-cpp/spine-cpp/src/spine/Json.h new file mode 100644 index 000000000..078a5a715 --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/Json.h @@ -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_ */ diff --git a/spine-cpp/spine-cpp/src/spine/MeshAttachment.c b/spine-cpp/spine-cpp/src/spine/MeshAttachment.c new file mode 100644 index 000000000..b7a49bfdc --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/MeshAttachment.c @@ -0,0 +1,100 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include + +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); +} + +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); + return self; +} + +void spMeshAttachment_updateUVs (spMeshAttachment* self) { + int i; + float width = self->regionU2 - self->regionU, height = self->regionV2 - self->regionV; + int verticesLength = SUPER(self)->worldVerticesLength; + FREE(self->uvs); + self->uvs = MALLOC(float, verticesLength); + if (self->regionRotate) { + for (i = 0; i < verticesLength; i += 2) { + self->uvs[i] = self->regionU + self->regionUVs[i + 1] * width; + self->uvs[i + 1] = self->regionV + height - self->regionUVs[i] * height; + } + } else { + for (i = 0; i < verticesLength; i += 2) { + self->uvs[i] = self->regionU + self->regionUVs[i] * width; + self->uvs[i + 1] = self->regionV + 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; + } +} diff --git a/spine-cpp/spine-cpp/src/spine/PathAttachment.c b/spine-cpp/spine-cpp/src/spine/PathAttachment.c new file mode 100644 index 000000000..f81b3fd1c --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/PathAttachment.c @@ -0,0 +1,48 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include + +void _spPathAttachment_dispose (spAttachment* attachment) { + spPathAttachment* self = SUB_CAST(spPathAttachment, attachment); + + _spVertexAttachment_deinit(SUPER(self)); + + FREE(self->lengths); + FREE(self); +} + +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); + return self; +} diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraint.c b/spine-cpp/spine-cpp/src/spine/PathConstraint.c new file mode 100644 index 000000000..fd4373dce --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/PathConstraint.c @@ -0,0 +1,467 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include +#include + +#define PATHCONSTRAINT_NONE -1 +#define PATHCONSTRAINT_BEFORE -2 +#define PATHCONSTRAINT_AFTER -3 + +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; + spPathAttachment* attachment = (spPathAttachment*)self->target->attachment; + spPathConstraintData* data = self->data; + spSpacingMode spacingMode = data->spacingMode; + int lengthSpacing = spacingMode == SP_SPACING_MODE_LENGTH; + 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 || lengthSpacing) { + if (scale) { + if (self->lengthsCount != boneCount) { + if (self->lengths) FREE(self->lengths); + self->lengths = MALLOC(float, boneCount); + self->lengthsCount = boneCount; + } + lengths = self->lengths; + } + for (i = 0, n = spacesCount - 1; i < n;) { + spBone* bone = bones[i]; + setupLength = bone->data->length; + if (setupLength == 0) setupLength = 0.000000001f; + 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, spacingMode == SP_SPACING_MODE_PERCENT); + 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)) p = 0.0001f; + 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) 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 = 0; 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; + if (percentSpacing) { + for (i = 0; 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; +} diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraintData.c b/spine-cpp/spine-cpp/src/spine/PathConstraintData.c new file mode 100644 index 000000000..e0556cbe5 --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/PathConstraintData.c @@ -0,0 +1,44 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include + +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); +} diff --git a/spine-cpp/spine-cpp/src/spine/PointAttachment.c b/spine-cpp/spine-cpp/src/spine/PointAttachment.c new file mode 100644 index 000000000..9a0139663 --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/PointAttachment.c @@ -0,0 +1,61 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include + +void _spPointAttachment_dispose (spAttachment* attachment) { + spPathAttachment* self = SUB_CAST(spPathAttachment, attachment); + + _spVertexAttachment_deinit(SUPER(self)); + + FREE(self); +} + +spPointAttachment* spPointAttachment_create (const char* name) { + spPointAttachment* self = NEW(spPointAttachment); + _spVertexAttachment_init(SUPER(self)); + _spAttachment_init(SUPER(SUPER(self)), name, SP_ATTACHMENT_POINT, _spPointAttachment_dispose); + 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; +} diff --git a/spine-cpp/spine-cpp/src/spine/RegionAttachment.c b/spine-cpp/spine-cpp/src/spine/RegionAttachment.c new file mode 100644 index 000000000..56e981ede --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/RegionAttachment.c @@ -0,0 +1,130 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include + +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); +} + +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); + 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; +} diff --git a/spine-cpp/spine-cpp/src/spine/Skeleton.c b/spine-cpp/spine-cpp/src/spine/Skeleton.c new file mode 100644 index 000000000..7383b0c1d --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/Skeleton.c @@ -0,0 +1,583 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include +#include +#include + +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); + + 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->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; + _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); + 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; + _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) + bones[i]->sorted = 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->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 (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; +} + +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; +} diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonBinary.c b/spine-cpp/spine-cpp/src/spine/SkeletonBinary.c new file mode 100644 index 000000000..d4e06bc25 --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/SkeletonBinary.c @@ -0,0 +1,1095 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include +#include +#include +#include +#include "kvec.h" + +typedef struct { + const unsigned char* cursor; + const unsigned char* end; +} _dataInput; + +typedef struct { + const char* parent; + const char* skin; + int slotIndex; + spMeshAttachment* mesh; +} _spLinkedMesh; + +typedef struct { + spSkeletonBinary super; + int ownsLoader; + + int linkedMeshCount; + int linkedMeshCapacity; + _spLinkedMesh* linkedMeshes; +} _spSkeletonBinary; + +spSkeletonBinary* spSkeletonBinary_createWithLoader (spAttachmentLoader* attachmentLoader) { + spSkeletonBinary* self = SUPER(NEW(_spSkeletonBinary)); + self->scale = 1; + self->attachmentLoader = attachmentLoader; + return self; +} + +spSkeletonBinary* spSkeletonBinary_create (spAtlas* atlas) { + spAtlasAttachmentLoader* attachmentLoader = spAtlasAttachmentLoader_create(atlas); + spSkeletonBinary* self = spSkeletonBinary_createWithLoader(SUPER(attachmentLoader)); + SUB_CAST(_spSkeletonBinary, self)->ownsLoader = 1; + return self; +} + +void spSkeletonBinary_dispose (spSkeletonBinary* self) { + int i; + _spSkeletonBinary* internal = SUB_CAST(_spSkeletonBinary, self); + if (internal->ownsLoader) spAttachmentLoader_dispose(self->attachmentLoader); + for (i = 0; i < internal->linkedMeshCount; ++i) { + FREE(internal->linkedMeshes[i].parent); + FREE(internal->linkedMeshes[i].skin); + } + FREE(internal->linkedMeshes); + FREE(self->error); + FREE(self); +} + +void _spSkeletonBinary_setError (spSkeletonBinary* self, const char* value1, const char* value2) { + char message[256]; + int length; + FREE(self->error); + strcpy(message, value1); + length = (int)strlen(value1); + if (value2) strncat(message + length, value2, 255 - length); + MALLOC_STR(self->error, message); +} + +static unsigned char readByte (_dataInput* input) { + return *input->cursor++; +} + +static signed char readSByte (_dataInput* input) { + return (signed char)readByte(input); +} + +static int readBoolean (_dataInput* input) { + return readByte(input) != 0; +} + +static int readInt (_dataInput* input) { + int result = readByte(input); + result <<= 8; + result |= readByte(input); + result <<= 8; + result |= readByte(input); + result <<= 8; + result |= readByte(input); + return result; +} + +static int readVarint (_dataInput* input, int/*bool*/optimizePositive) { + unsigned char b = readByte(input); + int value = b & 0x7F; + if (b & 0x80) { + b = readByte(input); + value |= (b & 0x7F) << 7; + if (b & 0x80) { + b = readByte(input); + value |= (b & 0x7F) << 14; + if (b & 0x80) { + b = readByte(input); + value |= (b & 0x7F) << 21; + if (b & 0x80) value |= (readByte(input) & 0x7F) << 28; + } + } + } + if (!optimizePositive) value = (((unsigned int)value >> 1) ^ -(value & 1)); + return value; +} + +float readFloat (_dataInput* input) { + union { + int intValue; + float floatValue; + } intToFloat; + intToFloat.intValue = readInt(input); + return intToFloat.floatValue; +} + +char* readString (_dataInput* input) { + int length = readVarint(input, 1); + char* string; + if (length == 0) { + return 0; + } + string = MALLOC(char, length); + memcpy(string, input->cursor, length - 1); + input->cursor += length - 1; + string[length - 1] = '\0'; + return string; +} + +static void readColor (_dataInput* input, float *r, float *g, float *b, float *a) { + *r = readByte(input) / 255.0f; + *g = readByte(input) / 255.0f; + *b = readByte(input) / 255.0f; + *a = readByte(input) / 255.0f; +} + +#define ATTACHMENT_REGION 0 +#define ATTACHMENT_BOUNDING_BOX 1 +#define ATTACHMENT_MESH 2 +#define ATTACHMENT_LINKED_MESH 3 +#define ATTACHMENT_PATH 4 + +#define BLEND_MODE_NORMAL 0 +#define BLEND_MODE_ADDITIVE 1 +#define BLEND_MODE_MULTIPLY 2 +#define BLEND_MODE_SCREEN 3 + +#define CURVE_LINEAR 0 +#define CURVE_STEPPED 1 +#define CURVE_BEZIER 2 + +#define BONE_ROTATE 0 +#define BONE_TRANSLATE 1 +#define BONE_SCALE 2 +#define BONE_SHEAR 3 + +#define SLOT_ATTACHMENT 0 +#define SLOT_COLOR 1 +#define SLOT_TWO_COLOR 2 + +#define PATH_POSITION 0 +#define PATH_SPACING 1 +#define PATH_MIX 2 + +#define PATH_POSITION_FIXED 0 +#define PATH_POSITION_PERCENT 1 + +#define PATH_SPACING_LENGTH 0 +#define PATH_SPACING_FIXED 1 +#define PATH_SPACING_PERCENT 2 + +#define PATH_ROTATE_TANGENT 0 +#define PATH_ROTATE_CHAIN 1 +#define PATH_ROTATE_CHAIN_SCALE 2 + +static void readCurve (_dataInput* input, spCurveTimeline* timeline, int frameIndex) { + switch (readByte(input)) { + case CURVE_STEPPED: { + spCurveTimeline_setStepped(timeline, frameIndex); + break; + } + case CURVE_BEZIER: { + float cx1 = readFloat(input); + float cy1 = readFloat(input); + float cx2 = readFloat(input); + float cy2 = readFloat(input); + spCurveTimeline_setCurve(timeline, frameIndex, cx1, cy1, cx2, cy2); + break; + } + } +} + +static void _spSkeletonBinary_addLinkedMesh (spSkeletonBinary* self, spMeshAttachment* mesh, + const char* skin, int slotIndex, const char* parent) { + _spLinkedMesh* linkedMesh; + _spSkeletonBinary* internal = SUB_CAST(_spSkeletonBinary, self); + + if (internal->linkedMeshCount == internal->linkedMeshCapacity) { + _spLinkedMesh* linkedMeshes; + internal->linkedMeshCapacity *= 2; + if (internal->linkedMeshCapacity < 8) internal->linkedMeshCapacity = 8; + /* TODO Why not realloc? */ + linkedMeshes = MALLOC(_spLinkedMesh, internal->linkedMeshCapacity); + memcpy(linkedMeshes, internal->linkedMeshes, sizeof(_spLinkedMesh) * internal->linkedMeshCount); + FREE(internal->linkedMeshes); + internal->linkedMeshes = linkedMeshes; + } + + linkedMesh = internal->linkedMeshes + internal->linkedMeshCount++; + linkedMesh->mesh = mesh; + linkedMesh->skin = skin; + linkedMesh->slotIndex = slotIndex; + linkedMesh->parent = parent; +} + +static spAnimation* _spSkeletonBinary_readAnimation (spSkeletonBinary* self, const char* name, + _dataInput* input, spSkeletonData *skeletonData) { + kvec_t(spTimeline*) timelines; + float duration = 0; + int i, n, ii, nn, iii, nnn; + int frameIndex; + int drawOrderCount, eventCount; + spAnimation* animation; + + kv_init(timelines); + + /* Slot timelines. */ + for (i = 0, n = readVarint(input, 1); i < n; ++i) { + int slotIndex = readVarint(input, 1); + for (ii = 0, nn = readVarint(input, 1); ii < nn; ++ii) { + unsigned char timelineType = readByte(input); + int frameCount = readVarint(input, 1); + switch (timelineType) { + case SLOT_ATTACHMENT: { + spAttachmentTimeline* timeline = spAttachmentTimeline_create(frameCount); + timeline->slotIndex = slotIndex; + for (frameIndex = 0; frameIndex < frameCount; ++frameIndex) { + float time = readFloat(input); + const char* attachmentName = readString(input); + /* TODO Avoid copying of attachmentName inside */ + spAttachmentTimeline_setFrame(timeline, frameIndex, time, attachmentName); + FREE(attachmentName); + } + kv_push(spTimeline*, timelines, SUPER(timeline)); + duration = MAX(duration, timeline->frames[frameCount - 1]); + break; + } + case SLOT_COLOR: { + spColorTimeline* timeline = spColorTimeline_create(frameCount); + timeline->slotIndex = slotIndex; + for (frameIndex = 0; frameIndex < frameCount; ++frameIndex) { + float time = readFloat(input); + float r, g, b, a; + readColor(input, &r, &g, &b, &a); + spColorTimeline_setFrame(timeline, frameIndex, time, r, g, b, a); + if (frameIndex < frameCount - 1) readCurve(input, SUPER(timeline), frameIndex); + } + kv_push(spTimeline*, timelines, SUPER(SUPER(timeline))); + duration = MAX(duration, timeline->frames[(frameCount - 1) * COLOR_ENTRIES]); + break; + } + case SLOT_TWO_COLOR: { + spTwoColorTimeline* timeline = spTwoColorTimeline_create(frameCount); + timeline->slotIndex = slotIndex; + for (frameIndex = 0; frameIndex < frameCount; ++frameIndex) { + float time = readFloat(input); + float r, g, b, a; + float r2, g2, b2, a2; + readColor(input, &r, &g, &b, &a); + readColor(input, &a2, &r2, &g2, &b2); + spTwoColorTimeline_setFrame(timeline, frameIndex, time, r, g, b, a, r2, g2, b2); + if (frameIndex < frameCount - 1) readCurve(input, SUPER(timeline), frameIndex); + } + kv_push(spTimeline*, timelines, SUPER(SUPER(timeline))); + duration = MAX(duration, timeline->frames[(frameCount - 1) * TWOCOLOR_ENTRIES]); + break; + } + default: { + int i; + for (i = 0; i < kv_size(timelines); ++i) + spTimeline_dispose(kv_A(timelines, i)); + kv_destroy(timelines); + _spSkeletonBinary_setError(self, "Invalid timeline type for a slot: ", skeletonData->slots[slotIndex]->name); + return 0; + } + } + } + } + + /* Bone timelines. */ + for (i = 0, n = readVarint(input, 1); i < n; ++i) { + int boneIndex = readVarint(input, 1); + for (ii = 0, nn = readVarint(input, 1); ii < nn; ++ii) { + unsigned char timelineType = readByte(input); + int frameCount = readVarint(input, 1); + switch (timelineType) { + case BONE_ROTATE: { + spRotateTimeline *timeline = spRotateTimeline_create(frameCount); + timeline->boneIndex = boneIndex; + for (frameIndex = 0; frameIndex < frameCount; ++frameIndex) { + float time = readFloat(input); + float degrees = readFloat(input); + spRotateTimeline_setFrame(timeline, frameIndex, time, degrees); + if (frameIndex < frameCount - 1) readCurve(input, SUPER(timeline), frameIndex); + } + kv_push(spTimeline*, timelines, SUPER(SUPER(timeline))); + duration = MAX(duration, timeline->frames[(frameCount - 1) * ROTATE_ENTRIES]); + break; + } + case BONE_TRANSLATE: + case BONE_SCALE: + case BONE_SHEAR: { + float timelineScale = 1; + spTranslateTimeline *timeline = 0; + switch (timelineType) { + case BONE_SCALE: + timeline = spScaleTimeline_create(frameCount); + break; + case BONE_SHEAR: + timeline = spShearTimeline_create(frameCount); + break; + case BONE_TRANSLATE: + timeline = spTranslateTimeline_create(frameCount); + timelineScale = self->scale; + break; + default: + break; + } + timeline->boneIndex = boneIndex; + for (frameIndex = 0; frameIndex < frameCount; ++frameIndex) { + float time = readFloat(input); + float x = readFloat(input) * timelineScale; + float y = readFloat(input) * timelineScale; + spTranslateTimeline_setFrame(timeline, frameIndex, time, x, y); + if (frameIndex < frameCount - 1) readCurve(input, SUPER(timeline), frameIndex); + } + kv_push(spTimeline*, timelines, SUPER_CAST(spTimeline, timeline)); + duration = MAX(duration, timeline->frames[(frameCount - 1) * TRANSLATE_ENTRIES]); + break; + } + default: { + int i; + for (i = 0; i < kv_size(timelines); ++i) + spTimeline_dispose(kv_A(timelines, i)); + kv_destroy(timelines); + _spSkeletonBinary_setError(self, "Invalid timeline type for a bone: ", skeletonData->bones[boneIndex]->name); + return 0; + } + } + } + } + + /* IK constraint timelines. */ + for (i = 0, n = readVarint(input, 1); i < n; ++i) { + int index = readVarint(input, 1); + int frameCount = readVarint(input, 1); + spIkConstraintTimeline* timeline = spIkConstraintTimeline_create(frameCount); + timeline->ikConstraintIndex = index; + for (frameIndex = 0; frameIndex < frameCount; ++frameIndex) { + float time = readFloat(input); + float mix = readFloat(input); + signed char bendDirection = readSByte(input); + spIkConstraintTimeline_setFrame(timeline, frameIndex, time, mix, bendDirection); + if (frameIndex < frameCount - 1) readCurve(input, SUPER(timeline), frameIndex); + } + kv_push(spTimeline*, timelines, SUPER(SUPER(timeline))); + duration = MAX(duration, timeline->frames[(frameCount - 1) * IKCONSTRAINT_ENTRIES]); + } + + /* Transform constraint timelines. */ + for (i = 0, n = readVarint(input, 1); i < n; ++i) { + int index = readVarint(input, 1); + int frameCount = readVarint(input, 1); + spTransformConstraintTimeline* timeline = spTransformConstraintTimeline_create(frameCount); + timeline->transformConstraintIndex = index; + for (frameIndex = 0; frameIndex < frameCount; ++frameIndex) { + float time = readFloat(input); + float rotateMix = readFloat(input); + float translateMix = readFloat(input); + float scaleMix = readFloat(input); + float shearMix = readFloat(input); + spTransformConstraintTimeline_setFrame(timeline, frameIndex, time, rotateMix, translateMix, + scaleMix, shearMix); + if (frameIndex < frameCount - 1) readCurve(input, SUPER(timeline), frameIndex); + } + kv_push(spTimeline*, timelines, SUPER(SUPER(timeline))); + duration = MAX(duration, timeline->frames[(frameCount - 1) * TRANSFORMCONSTRAINT_ENTRIES]); + } + + /* Path constraint timelines. */ + for (i = 0, n = readVarint(input, 1); i < n; ++i) { + int index = readVarint(input, 1); + spPathConstraintData* data = skeletonData->pathConstraints[index]; + for (ii = 0, nn = readVarint(input, 1); ii < nn; ++ii) { + unsigned char timelineType = readByte(input); + int frameCount = readVarint(input, 1); + switch (timelineType) { + case PATH_POSITION: + case PATH_SPACING: { + spPathConstraintPositionTimeline* timeline = 0; + float timelineScale = 1; + if (timelineType == PATH_SPACING) { + timeline = (spPathConstraintPositionTimeline*)spPathConstraintSpacingTimeline_create(frameCount); + if (data->spacingMode == SP_SPACING_MODE_LENGTH || data->spacingMode == SP_SPACING_MODE_FIXED) + timelineScale = self->scale; + } else { + timeline = spPathConstraintPositionTimeline_create(frameCount); + if (data->positionMode == SP_POSITION_MODE_FIXED) + timelineScale = self->scale; + } + timeline->pathConstraintIndex = index; + for (frameIndex = 0; frameIndex < frameCount; ++frameIndex) { + float time = readFloat(input); + float value = readFloat(input) * timelineScale; + spPathConstraintPositionTimeline_setFrame(timeline, frameIndex, time, value); + if (frameIndex < frameCount - 1) readCurve(input, SUPER(timeline), frameIndex); + } + kv_push(spTimeline*, timelines, SUPER(SUPER(timeline))); + duration = MAX(duration, timeline->frames[(frameCount - 1) * PATHCONSTRAINTPOSITION_ENTRIES]); + break; + } + case PATH_MIX: { + spPathConstraintMixTimeline* timeline = spPathConstraintMixTimeline_create(frameCount); + timeline->pathConstraintIndex = index; + for (frameIndex = 0; frameIndex < frameCount; ++frameIndex) { + float time = readFloat(input); + float rotateMix = readFloat(input); + float translateMix = readFloat(input); + spPathConstraintMixTimeline_setFrame(timeline, frameIndex, time, rotateMix, translateMix); + if (frameIndex < frameCount - 1) readCurve(input, SUPER(timeline), frameIndex); + } + kv_push(spTimeline*, timelines, SUPER(SUPER(timeline))); + duration = MAX(duration, timeline->frames[(frameCount - 1) * PATHCONSTRAINTMIX_ENTRIES]); + } + } + } + } + + /* Deform timelines. */ + for (i = 0, n = readVarint(input, 1); i < n; ++i) { + spSkin* skin = skeletonData->skins[readVarint(input, 1)]; + for (ii = 0, nn = readVarint(input, 1); ii < nn; ++ii) { + int slotIndex = readVarint(input, 1); + for (iii = 0, nnn = readVarint(input, 1); iii < nnn; ++iii) { + float* tempDeform; + spDeformTimeline *timeline; + int weighted, deformLength; + const char* attachmentName = readString(input); + int frameCount; + + spVertexAttachment* attachment = SUB_CAST(spVertexAttachment, + spSkin_getAttachment(skin, slotIndex, attachmentName)); + if (!attachment) { + int i; + for (i = 0; i < kv_size(timelines); ++i) + spTimeline_dispose(kv_A(timelines, i)); + kv_destroy(timelines); + _spSkeletonBinary_setError(self, "Attachment not found: ", attachmentName); + FREE(attachmentName); + return 0; + } + FREE(attachmentName); + + weighted = attachment->bones != 0; + deformLength = weighted ? attachment->verticesCount / 3 * 2 : attachment->verticesCount; + tempDeform = MALLOC(float, deformLength); + + frameCount = readVarint(input, 1); + timeline = spDeformTimeline_create(frameCount, deformLength); + timeline->slotIndex = slotIndex; + timeline->attachment = SUPER(attachment); + + for (frameIndex = 0; frameIndex < frameCount; ++frameIndex) { + float time = readFloat(input); + float* deform; + int end = readVarint(input, 1); + if (!end) { + if (weighted) { + deform = tempDeform; + memset(deform, 0, sizeof(float) * deformLength); + } else + deform = attachment->vertices; + } else { + int v, start = readVarint(input, 1); + deform = tempDeform; + memset(deform, 0, sizeof(float) * start); + end += start; + if (self->scale == 1) { + for (v = start; v < end; ++v) + deform[v] = readFloat(input); + } else { + for (v = start; v < end; ++v) + deform[v] = readFloat(input) * self->scale; + } + memset(deform + v, 0, sizeof(float) * (deformLength - v)); + if (!weighted) { + float* vertices = attachment->vertices; + for (v = 0; v < deformLength; ++v) + deform[v] += vertices[v]; + } + } + spDeformTimeline_setFrame(timeline, frameIndex, time, deform); + if (frameIndex < frameCount - 1) readCurve(input, SUPER(timeline), frameIndex); + } + FREE(tempDeform); + + kv_push(spTimeline*, timelines, SUPER(SUPER(timeline))); + duration = MAX(duration, timeline->frames[frameCount - 1]); + } + } + } + + /* Draw order timeline. */ + drawOrderCount = readVarint(input, 1); + if (drawOrderCount) { + spDrawOrderTimeline* timeline = spDrawOrderTimeline_create(drawOrderCount, skeletonData->slotsCount); + for (i = 0; i < drawOrderCount; ++i) { + float time = readFloat(input); + int offsetCount = readVarint(input, 1); + int* drawOrder = MALLOC(int, skeletonData->slotsCount); + int* unchanged = MALLOC(int, skeletonData->slotsCount - offsetCount); + int originalIndex = 0, unchangedIndex = 0; + memset(drawOrder, -1, sizeof(int) * skeletonData->slotsCount); + for (ii = 0; ii < offsetCount; ++ii) { + int slotIndex = readVarint(input, 1); + /* Collect unchanged items. */ + while (originalIndex != slotIndex) + unchanged[unchangedIndex++] = originalIndex++; + /* Set changed items. */ + drawOrder[originalIndex + readVarint(input, 1)] = originalIndex; + ++originalIndex; + } + /* Collect remaining unchanged items. */ + while (originalIndex < skeletonData->slotsCount) + unchanged[unchangedIndex++] = originalIndex++; + /* Fill in unchanged items. */ + for (ii = skeletonData->slotsCount - 1; ii >= 0; ii--) + if (drawOrder[ii] == -1) drawOrder[ii] = unchanged[--unchangedIndex]; + FREE(unchanged); + /* TODO Avoid copying of drawOrder inside */ + spDrawOrderTimeline_setFrame(timeline, i, time, drawOrder); + FREE(drawOrder); + } + kv_push(spTimeline*, timelines, SUPER(timeline)); + duration = MAX(duration, timeline->frames[drawOrderCount - 1]); + } + + /* Event timeline. */ + eventCount = readVarint(input, 1); + if (eventCount) { + spEventTimeline* timeline = spEventTimeline_create(eventCount); + for (i = 0; i < eventCount; ++i) { + float time = readFloat(input); + spEventData* eventData = skeletonData->events[readVarint(input, 1)]; + spEvent* event = spEvent_create(time, eventData); + event->intValue = readVarint(input, 0); + event->floatValue = readFloat(input); + if (readBoolean(input)) + event->stringValue = readString(input); + else + MALLOC_STR(event->stringValue, eventData->stringValue); + spEventTimeline_setFrame(timeline, i, event); + } + kv_push(spTimeline*, timelines, SUPER(timeline)); + duration = MAX(duration, timeline->frames[eventCount - 1]); + } + + kv_trim(spTimeline*, timelines); + + animation = spAnimation_create(name, 0); + FREE(animation->timelines); + animation->duration = duration; + animation->timelinesCount = kv_size(timelines); + animation->timelines = kv_array(timelines); + return animation; +} + +static float* _readFloatArray(_dataInput *input, int n, float scale) { + float* array = MALLOC(float, n); + int i; + if (scale == 1) + for (i = 0; i < n; ++i) + array[i] = readFloat(input); + else + for (i = 0; i < n; ++i) + array[i] = readFloat(input) * scale; + return array; +} + +static short* _readShortArray(_dataInput *input, int *length) { + int n = readVarint(input, 1); + short* array = MALLOC(short, n); + int i; + *length = n; + for (i = 0; i < n; ++i) { + array[i] = readByte(input) << 8; + array[i] |= readByte(input); + } + return array; +} + +static void _readVertices(spSkeletonBinary* self, _dataInput* input, spVertexAttachment* attachment, + int vertexCount) { + int i, ii; + int verticesLength = vertexCount << 1; + kvec_t(float) weights; + kvec_t(int) bones; + + attachment->worldVerticesLength = verticesLength; + + if (!readBoolean(input)) { + attachment->verticesCount = verticesLength; + attachment->vertices = _readFloatArray(input, verticesLength, self->scale); + attachment->bonesCount = 0; + attachment->bones = 0; + return; + } + + kv_init(weights); + kv_resize(float, weights, verticesLength * 3 * 3); + + kv_init(bones); + kv_resize(int, bones, verticesLength * 3); + + for (i = 0; i < vertexCount; ++i) { + int boneCount = readVarint(input, 1); + kv_push(int, bones, boneCount); + for (ii = 0; ii < boneCount; ++ii) { + kv_push(int, bones, readVarint(input, 1)); + kv_push(float, weights, readFloat(input) * self->scale); + kv_push(float, weights, readFloat(input) * self->scale); + kv_push(float, weights, readFloat(input)); + } + } + + kv_trim(float, weights); + attachment->verticesCount = kv_size(weights); + attachment->vertices = kv_array(weights); + + kv_trim(int, bones); + attachment->bonesCount = kv_size(bones); + attachment->bones = kv_array(bones); +} + +spAttachment* spSkeletonBinary_readAttachment(spSkeletonBinary* self, _dataInput* input, + spSkin* skin, int slotIndex, const char* attachmentName, spSkeletonData* skeletonData, int/*bool*/ nonessential) { + int i; + spAttachmentType type; + const char* name = readString(input); + int freeName = name != 0; + if (!name) { + freeName = 0; + name = attachmentName; + } + + type = (spAttachmentType)readByte(input); + + switch (type) { + case SP_ATTACHMENT_REGION: { + const char* path = readString(input); + spAttachment* attachment; + spRegionAttachment* region; + if (!path) MALLOC_STR(path, name); + attachment = spAttachmentLoader_createAttachment(self->attachmentLoader, skin, type, name, path); + region = SUB_CAST(spRegionAttachment, attachment); + region->path = path; + region->rotation = readFloat(input); + region->x = readFloat(input) * self->scale; + region->y = readFloat(input) * self->scale; + region->scaleX = readFloat(input); + region->scaleY = readFloat(input); + region->width = readFloat(input) * self->scale; + region->height = readFloat(input) * self->scale; + readColor(input, ®ion->color.r, ®ion->color.g, ®ion->color.b, ®ion->color.a); + spRegionAttachment_updateOffset(region); + spAttachmentLoader_configureAttachment(self->attachmentLoader, attachment); + if (freeName) FREE(name); + return attachment; + } + case SP_ATTACHMENT_BOUNDING_BOX: { + int vertexCount = readVarint(input, 1); + spAttachment* attachment = spAttachmentLoader_createAttachment(self->attachmentLoader, skin, type, name, 0); + _readVertices(self, input, SUB_CAST(spVertexAttachment, attachment), vertexCount); + if (nonessential) readInt(input); /* Skip color. */ + spAttachmentLoader_configureAttachment(self->attachmentLoader, attachment); + if (freeName) FREE(name); + return attachment; + } + case SP_ATTACHMENT_MESH: { + int vertexCount; + spAttachment* attachment; + spMeshAttachment* mesh; + const char* path = readString(input); + if (!path) MALLOC_STR(path, name); + attachment = spAttachmentLoader_createAttachment(self->attachmentLoader, skin, type, name, path); + mesh = SUB_CAST(spMeshAttachment, attachment); + mesh->path = path; + readColor(input, &mesh->color.r, &mesh->color.g, &mesh->color.b, &mesh->color.a); + vertexCount = readVarint(input, 1); + mesh->regionUVs = _readFloatArray(input, vertexCount << 1, 1); + mesh->triangles = (unsigned short*)_readShortArray(input, &mesh->trianglesCount); + _readVertices(self, input, SUPER(mesh), vertexCount); + spMeshAttachment_updateUVs(mesh); + mesh->hullLength = readVarint(input, 1) << 1; + if (nonessential) { + mesh->edges = (int*)_readShortArray(input, &mesh->edgesCount); + mesh->width = readFloat(input) * self->scale; + mesh->height = readFloat(input) * self->scale; + } else { + mesh->edges = 0; + mesh->width = 0; + mesh->height = 0; + } + spAttachmentLoader_configureAttachment(self->attachmentLoader, attachment); + if (freeName) FREE(name); + return attachment; + } + case SP_ATTACHMENT_LINKED_MESH: { + const char* skinName; + const char* parent; + spAttachment* attachment; + spMeshAttachment* mesh; + const char* path = readString(input); + if (!path) MALLOC_STR(path, name); + attachment = spAttachmentLoader_createAttachment(self->attachmentLoader, skin, type, name, path); + mesh = SUB_CAST(spMeshAttachment, attachment); + mesh->path = path; + readColor(input, &mesh->color.r, &mesh->color.g, &mesh->color.b, &mesh->color.a); + skinName = readString(input); + parent = readString(input); + mesh->inheritDeform = readBoolean(input); + if (nonessential) { + mesh->width = readFloat(input) * self->scale; + mesh->height = readFloat(input) * self->scale; + } + _spSkeletonBinary_addLinkedMesh(self, mesh, skinName, slotIndex, parent); + if (freeName) FREE(name); + return attachment; + } + case SP_ATTACHMENT_PATH: { + spAttachment* attachment = spAttachmentLoader_createAttachment(self->attachmentLoader, skin, type, name, 0); + spPathAttachment* path = SUB_CAST(spPathAttachment, attachment); + int vertexCount = 0; + path->closed = readBoolean(input); + path->constantSpeed = readBoolean(input); + vertexCount = readVarint(input, 1); + _readVertices(self, input, SUPER(path), vertexCount); + path->lengthsLength = vertexCount / 3; + path->lengths = MALLOC(float, path->lengthsLength); + for (i = 0; i < path->lengthsLength; ++i) { + path->lengths[i] = readFloat(input) * self->scale; + } + if (nonessential) readInt(input); /* Skip color. */ + if (freeName) FREE(name); + return attachment; + } + case SP_ATTACHMENT_POINT: { + spAttachment* attachment = spAttachmentLoader_createAttachment(self->attachmentLoader, skin, type, name, 0); + spPointAttachment* point = SUB_CAST(spPointAttachment, attachment); + point->rotation = readFloat(input); + point->x = readFloat(input) * self->scale; + point->y = readFloat(input) * self->scale; + + if (nonessential) { + readColor(input, &point->color.r, &point->color.g, &point->color.b, &point->color.a); + } + return attachment; + } + case SP_ATTACHMENT_CLIPPING: { + int endSlotIndex = readVarint(input, 1); + int vertexCount = readVarint(input, 1); + spAttachment* attachment = spAttachmentLoader_createAttachment(self->attachmentLoader, skin, type, name, 0); + spClippingAttachment* clip = SUB_CAST(spClippingAttachment, attachment); + _readVertices(self, input, SUB_CAST(spVertexAttachment, attachment), vertexCount); + if (nonessential) readInt(input); /* Skip color. */ + clip->endSlot = skeletonData->slots[endSlotIndex]; + spAttachmentLoader_configureAttachment(self->attachmentLoader, attachment); + if (freeName) FREE(name); + return attachment; + } + } + + if (freeName) FREE(name); + return 0; +} + +spSkin* spSkeletonBinary_readSkin(spSkeletonBinary* self, _dataInput* input, + const char* skinName, spSkeletonData* skeletonData, int/*bool*/ nonessential) { + spSkin* skin; + int slotCount = readVarint(input, 1); + int i, ii, nn; + if (slotCount == 0) + return 0; + skin = spSkin_create(skinName); + for (i = 0; i < slotCount; ++i) { + int slotIndex = readVarint(input, 1); + for (ii = 0, nn = readVarint(input, 1); ii < nn; ++ii) { + const char* name = readString(input); + spAttachment* attachment = spSkeletonBinary_readAttachment(self, input, skin, slotIndex, name, skeletonData, nonessential); + if (attachment) spSkin_addAttachment(skin, slotIndex, name, attachment); + FREE(name); + } + } + return skin; +} + +spSkeletonData* spSkeletonBinary_readSkeletonDataFile (spSkeletonBinary* self, const char* path) { + int length; + spSkeletonData* skeletonData; + const char* binary = _spUtil_readFile(path, &length); + if (length == 0 || !binary) { + _spSkeletonBinary_setError(self, "Unable to read skeleton file: ", path); + return 0; + } + skeletonData = spSkeletonBinary_readSkeletonData(self, (unsigned char*)binary, length); + FREE(binary); + return skeletonData; +} + +spSkeletonData* spSkeletonBinary_readSkeletonData (spSkeletonBinary* self, const unsigned char* binary, + const int length) { + int i, ii, nonessential; + spSkeletonData* skeletonData; + _spSkeletonBinary* internal = SUB_CAST(_spSkeletonBinary, self); + + _dataInput* input = NEW(_dataInput); + input->cursor = binary; + input->end = binary + length; + + FREE(self->error); + CONST_CAST(char*, self->error) = 0; + internal->linkedMeshCount = 0; + + skeletonData = spSkeletonData_create(); + + skeletonData->hash = readString(input); + if (!strlen(skeletonData->hash)) { + FREE(skeletonData->hash); + skeletonData->hash = 0; + } + + skeletonData->version = readString(input); + if (!strlen(skeletonData->version)) { + FREE(skeletonData->version); + skeletonData->version = 0; + } + + skeletonData->width = readFloat(input); + skeletonData->height = readFloat(input); + + nonessential = readBoolean(input); + + if (nonessential) { + /* Skip images path & fps */ + readFloat(input); + FREE(readString(input)); + } + + /* Bones. */ + skeletonData->bonesCount = readVarint(input, 1); + skeletonData->bones = MALLOC(spBoneData*, skeletonData->bonesCount); + for (i = 0; i < skeletonData->bonesCount; ++i) { + spBoneData* data; + int mode; + const char* name = readString(input); + spBoneData* parent = i == 0 ? 0 : skeletonData->bones[readVarint(input, 1)]; + /* TODO Avoid copying of name */ + data = spBoneData_create(i, name, parent); + FREE(name); + data->rotation = readFloat(input); + data->x = readFloat(input) * self->scale; + data->y = readFloat(input) * self->scale; + data->scaleX = readFloat(input); + data->scaleY = readFloat(input); + data->shearX = readFloat(input); + data->shearY = readFloat(input); + data->length = readFloat(input) * self->scale; + mode = readVarint(input, 1); + switch (mode) { + case 0: data->transformMode = SP_TRANSFORMMODE_NORMAL; break; + case 1: data->transformMode = SP_TRANSFORMMODE_ONLYTRANSLATION; break; + case 2: data->transformMode = SP_TRANSFORMMODE_NOROTATIONORREFLECTION; break; + case 3: data->transformMode = SP_TRANSFORMMODE_NOSCALE; break; + case 4: data->transformMode = SP_TRANSFORMMODE_NOSCALEORREFLECTION; break; + } + if (nonessential) readInt(input); /* Skip bone color. */ + skeletonData->bones[i] = data; + } + + /* Slots. */ + skeletonData->slotsCount = readVarint(input, 1); + skeletonData->slots = MALLOC(spSlotData*, skeletonData->slotsCount); + for (i = 0; i < skeletonData->slotsCount; ++i) { + int r, g, b, a; + const char* slotName = readString(input); + spBoneData* boneData = skeletonData->bones[readVarint(input, 1)]; + /* TODO Avoid copying of slotName */ + spSlotData* slotData = spSlotData_create(i, slotName, boneData); + FREE(slotName); + readColor(input, &slotData->color.r, &slotData->color.g, &slotData->color.b, &slotData->color.a); + r = readByte(input); + g = readByte(input); + b = readByte(input); + a = readByte(input); + if (!(r == 0xff && g == 0xff && b == 0xff && a == 0xff)) { + slotData->darkColor = spColor_create(); + spColor_setFromFloats(slotData->darkColor, r / 255.0f, g / 255.0f, b / 255.0f, 1); + } + slotData->attachmentName = readString(input); + slotData->blendMode = (spBlendMode)readVarint(input, 1); + skeletonData->slots[i] = slotData; + } + + /* IK constraints. */ + skeletonData->ikConstraintsCount = readVarint(input, 1); + skeletonData->ikConstraints = MALLOC(spIkConstraintData*, skeletonData->ikConstraintsCount); + for (i = 0; i < skeletonData->ikConstraintsCount; ++i) { + const char* name = readString(input); + /* TODO Avoid copying of name */ + spIkConstraintData* data = spIkConstraintData_create(name); + data->order = readVarint(input, 1); + FREE(name); + data->bonesCount = readVarint(input, 1); + data->bones = MALLOC(spBoneData*, data->bonesCount); + for (ii = 0; ii < data->bonesCount; ++ii) + data->bones[ii] = skeletonData->bones[readVarint(input, 1)]; + data->target = skeletonData->bones[readVarint(input, 1)]; + data->mix = readFloat(input); + data->bendDirection = readSByte(input); + skeletonData->ikConstraints[i] = data; + } + + /* Transform constraints. */ + skeletonData->transformConstraintsCount = readVarint(input, 1); + skeletonData->transformConstraints = MALLOC( + spTransformConstraintData*, skeletonData->transformConstraintsCount); + for (i = 0; i < skeletonData->transformConstraintsCount; ++i) { + const char* name = readString(input); + /* TODO Avoid copying of name */ + spTransformConstraintData* data = spTransformConstraintData_create(name); + data->order = readVarint(input, 1); + FREE(name); + data->bonesCount = readVarint(input, 1); + CONST_CAST(spBoneData**, data->bones) = MALLOC(spBoneData*, data->bonesCount); + for (ii = 0; ii < data->bonesCount; ++ii) + data->bones[ii] = skeletonData->bones[readVarint(input, 1)]; + data->target = skeletonData->bones[readVarint(input, 1)]; + data->local = readBoolean(input); + data->relative = readBoolean(input); + data->offsetRotation = readFloat(input); + data->offsetX = readFloat(input) * self->scale; + data->offsetY = readFloat(input) * self->scale; + data->offsetScaleX = readFloat(input); + data->offsetScaleY = readFloat(input); + data->offsetShearY = readFloat(input); + data->rotateMix = readFloat(input); + data->translateMix = readFloat(input); + data->scaleMix = readFloat(input); + data->shearMix = readFloat(input); + skeletonData->transformConstraints[i] = data; + } + + /* Path constraints */ + skeletonData->pathConstraintsCount = readVarint(input, 1); + skeletonData->pathConstraints = MALLOC(spPathConstraintData*, skeletonData->pathConstraintsCount); + for (i = 0; i < skeletonData->pathConstraintsCount; ++i) { + const char* name = readString(input); + /* TODO Avoid copying of name */ + spPathConstraintData* data = spPathConstraintData_create(name); + data->order = readVarint(input, 1); + FREE(name); + data->bonesCount = readVarint(input, 1); + CONST_CAST(spBoneData**, data->bones) = MALLOC(spBoneData*, data->bonesCount); + for (ii = 0; ii < data->bonesCount; ++ii) + data->bones[ii] = skeletonData->bones[readVarint(input, 1)]; + data->target = skeletonData->slots[readVarint(input, 1)]; + data->positionMode = (spPositionMode)readVarint(input, 1); + data->spacingMode = (spSpacingMode)readVarint(input, 1); + data->rotateMode = (spRotateMode)readVarint(input, 1); + data->offsetRotation = readFloat(input); + data->position = readFloat(input); + if (data->positionMode == SP_POSITION_MODE_FIXED) data->position *= self->scale; + data->spacing = readFloat(input); + if (data->spacingMode == SP_SPACING_MODE_LENGTH || data->spacingMode == SP_SPACING_MODE_FIXED) data->spacing *= self->scale; + data->rotateMix = readFloat(input); + data->translateMix = readFloat(input); + skeletonData->pathConstraints[i] = data; + } + + /* Default skin. */ + skeletonData->defaultSkin = spSkeletonBinary_readSkin(self, input, "default", skeletonData, nonessential); + skeletonData->skinsCount = readVarint(input, 1); + + if (skeletonData->defaultSkin) + ++skeletonData->skinsCount; + + skeletonData->skins = MALLOC(spSkin*, skeletonData->skinsCount); + + if (skeletonData->defaultSkin) + skeletonData->skins[0] = skeletonData->defaultSkin; + + /* Skins. */ + for (i = skeletonData->defaultSkin ? 1 : 0; i < skeletonData->skinsCount; ++i) { + const char* skinName = readString(input); + /* TODO Avoid copying of skinName */ + skeletonData->skins[i] = spSkeletonBinary_readSkin(self, input, skinName, skeletonData, nonessential); + FREE(skinName); + } + + /* Linked meshes. */ + for (i = 0; i < internal->linkedMeshCount; ++i) { + _spLinkedMesh* linkedMesh = internal->linkedMeshes + i; + spSkin* skin = !linkedMesh->skin ? skeletonData->defaultSkin : spSkeletonData_findSkin(skeletonData, linkedMesh->skin); + spAttachment* parent; + if (!skin) { + FREE(input); + spSkeletonData_dispose(skeletonData); + _spSkeletonBinary_setError(self, "Skin not found: ", linkedMesh->skin); + return 0; + } + parent = spSkin_getAttachment(skin, linkedMesh->slotIndex, linkedMesh->parent); + if (!parent) { + FREE(input); + spSkeletonData_dispose(skeletonData); + _spSkeletonBinary_setError(self, "Parent mesh not found: ", linkedMesh->parent); + return 0; + } + spMeshAttachment_setParentMesh(linkedMesh->mesh, SUB_CAST(spMeshAttachment, parent)); + spMeshAttachment_updateUVs(linkedMesh->mesh); + spAttachmentLoader_configureAttachment(self->attachmentLoader, SUPER(SUPER(linkedMesh->mesh))); + } + + /* Events. */ + skeletonData->eventsCount = readVarint(input, 1); + skeletonData->events = MALLOC(spEventData*, skeletonData->eventsCount); + for (i = 0; i < skeletonData->eventsCount; ++i) { + const char* name = readString(input); + /* TODO Avoid copying of skinName */ + spEventData* eventData = spEventData_create(name); + FREE(name); + eventData->intValue = readVarint(input, 0); + eventData->floatValue = readFloat(input); + eventData->stringValue = readString(input); + skeletonData->events[i] = eventData; + } + + /* Animations. */ + skeletonData->animationsCount = readVarint(input, 1); + skeletonData->animations = MALLOC(spAnimation*, skeletonData->animationsCount); + for (i = 0; i < skeletonData->animationsCount; ++i) { + const char* name = readString(input); + spAnimation* animation = _spSkeletonBinary_readAnimation(self, name, input, skeletonData); + FREE(name); + if (!animation) { + FREE(input); + spSkeletonData_dispose(skeletonData); + return 0; + } + skeletonData->animations[i] = animation; + } + + FREE(input); + return skeletonData; +} diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonBounds.c b/spine-cpp/spine-cpp/src/spine/SkeletonBounds.c new file mode 100644 index 000000000..bb4eb40d0 --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/SkeletonBounds.c @@ -0,0 +1,205 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include +#include + +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; + + spSlot* slot = skeleton->slots[i]; + spAttachment* 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; +} diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonClipping.c b/spine-cpp/spine-cpp/src/spine/SkeletonClipping.c new file mode 100644 index 000000000..a46dea73e --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/SkeletonClipping.c @@ -0,0 +1,313 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include + +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 ua; + if (side2) { + spFloatArray_add(output, inputX2); + spFloatArray_add(output, inputY2); + continue; + } + c0 = inputY2 - inputY, c2 = inputX2 - inputX; + ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / (c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY)); + spFloatArray_add(output, edgeX + (edgeX2 - edgeX) * ua); + spFloatArray_add(output, edgeY + (edgeY2 - edgeY) * ua); + } else if (side2) { + float c0 = inputY2 - inputY, c2 = inputX2 - inputX; + float ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / (c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY)); + spFloatArray_add(output, edgeX + (edgeX2 - edgeX) * ua); + spFloatArray_add(output, edgeY + (edgeY2 - edgeY) * ua); + 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; + } + } + } +} diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonData.c b/spine-cpp/spine-cpp/src/spine/SkeletonData.c new file mode 100644 index 000000000..9db2c0306 --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/SkeletonData.c @@ -0,0 +1,147 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include +#include + +spSkeletonData* spSkeletonData_create () { + return NEW(spSkeletonData); +} + +void spSkeletonData_dispose (spSkeletonData* self) { + int i; + 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; +} diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonJson.c b/spine-cpp/spine-cpp/src/spine/SkeletonJson.c new file mode 100644 index 000000000..c6136c66c --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/SkeletonJson.c @@ -0,0 +1,1119 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include +#include +#include "Json.h" +#include +#include +#include + +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__) +#define strdup _strdup +#endif + +typedef struct { + const char* parent; + const char* skin; + int slotIndex; + spMeshAttachment* mesh; +} _spLinkedMesh; + +typedef struct { + spSkeletonJson super; + int ownsLoader; + + int linkedMeshCount; + int linkedMeshCapacity; + _spLinkedMesh* linkedMeshes; +} _spSkeletonJson; + +spSkeletonJson* spSkeletonJson_createWithLoader (spAttachmentLoader* attachmentLoader) { + spSkeletonJson* self = SUPER(NEW(_spSkeletonJson)); + self->scale = 1; + self->attachmentLoader = attachmentLoader; + return self; +} + +spSkeletonJson* spSkeletonJson_create (spAtlas* atlas) { + spAtlasAttachmentLoader* attachmentLoader = spAtlasAttachmentLoader_create(atlas); + spSkeletonJson* self = spSkeletonJson_createWithLoader(SUPER(attachmentLoader)); + SUB_CAST(_spSkeletonJson, self)->ownsLoader = 1; + return self; +} + +void spSkeletonJson_dispose (spSkeletonJson* self) { + _spSkeletonJson* internal = SUB_CAST(_spSkeletonJson, self); + if (internal->ownsLoader) spAttachmentLoader_dispose(self->attachmentLoader); + FREE(internal->linkedMeshes); + FREE(self->error); + FREE(self); +} + +void _spSkeletonJson_setError (spSkeletonJson* self, Json* root, const char* value1, const char* value2) { + char message[256]; + int length; + FREE(self->error); + strcpy(message, value1); + length = (int)strlen(value1); + if (value2) strncat(message + length, value2, 255 - length); + MALLOC_STR(self->error, message); + if (root) Json_dispose(root); +} + +static float toColor (const char* value, int index) { + char digits[3]; + char *error; + int color; + + if (strlen(value) / 2 < index) return -1; + value += index * 2; + + digits[0] = *value; + digits[1] = *(value + 1); + digits[2] = '\0'; + color = (int)strtoul(digits, &error, 16); + if (*error != 0) return -1; + return color / (float)255; +} + +static void readCurve (Json* frame, spCurveTimeline* timeline, int frameIndex) { + Json* curve = Json_getItem(frame, "curve"); + if (!curve) return; + if (curve->type == Json_String && strcmp(curve->valueString, "stepped") == 0) + spCurveTimeline_setStepped(timeline, frameIndex); + else if (curve->type == Json_Array) { + Json* child0 = curve->child; + Json* child1 = child0->next; + Json* child2 = child1->next; + Json* child3 = child2->next; + spCurveTimeline_setCurve(timeline, frameIndex, child0->valueFloat, child1->valueFloat, child2->valueFloat, + child3->valueFloat); + } +} + +static void _spSkeletonJson_addLinkedMesh (spSkeletonJson* self, spMeshAttachment* mesh, const char* skin, int slotIndex, + const char* parent) { + _spLinkedMesh* linkedMesh; + _spSkeletonJson* internal = SUB_CAST(_spSkeletonJson, self); + + if (internal->linkedMeshCount == internal->linkedMeshCapacity) { + _spLinkedMesh* linkedMeshes; + internal->linkedMeshCapacity *= 2; + if (internal->linkedMeshCapacity < 8) internal->linkedMeshCapacity = 8; + linkedMeshes = MALLOC(_spLinkedMesh, internal->linkedMeshCapacity); + memcpy(linkedMeshes, internal->linkedMeshes, sizeof(_spLinkedMesh) * internal->linkedMeshCount); + FREE(internal->linkedMeshes); + internal->linkedMeshes = linkedMeshes; + } + + linkedMesh = internal->linkedMeshes + internal->linkedMeshCount++; + linkedMesh->mesh = mesh; + linkedMesh->skin = skin; + linkedMesh->slotIndex = slotIndex; + linkedMesh->parent = parent; +} + +static spAnimation* _spSkeletonJson_readAnimation (spSkeletonJson* self, Json* root, spSkeletonData *skeletonData) { + int frameIndex; + spAnimation* animation; + Json* valueMap; + int timelinesCount = 0; + + Json* bones = Json_getItem(root, "bones"); + Json* slots = Json_getItem(root, "slots"); + Json* ik = Json_getItem(root, "ik"); + Json* transform = Json_getItem(root, "transform"); + Json* paths = Json_getItem(root, "paths"); + Json* deform = Json_getItem(root, "deform"); + Json* drawOrder = Json_getItem(root, "drawOrder"); + Json* events = Json_getItem(root, "events"); + Json *boneMap, *slotMap, *constraintMap; + if (!drawOrder) drawOrder = Json_getItem(root, "draworder"); + + for (boneMap = bones ? bones->child : 0; boneMap; boneMap = boneMap->next) + timelinesCount += boneMap->size; + for (slotMap = slots ? slots->child : 0; slotMap; slotMap = slotMap->next) + timelinesCount += slotMap->size; + timelinesCount += ik ? ik->size : 0; + timelinesCount += transform ? transform->size : 0; + for (constraintMap = paths ? paths->child : 0; constraintMap; constraintMap = constraintMap->next) + timelinesCount += constraintMap->size; + for (constraintMap = deform ? deform->child : 0; constraintMap; constraintMap = constraintMap->next) + for (slotMap = constraintMap->child; slotMap; slotMap = slotMap->next) + timelinesCount += slotMap->size; + if (drawOrder) ++timelinesCount; + if (events) ++timelinesCount; + + animation = spAnimation_create(root->name, timelinesCount); + animation->timelinesCount = 0; + + /* Slot timelines. */ + for (slotMap = slots ? slots->child : 0; slotMap; slotMap = slotMap->next) { + Json *timelineMap; + + int slotIndex = spSkeletonData_findSlotIndex(skeletonData, slotMap->name); + if (slotIndex == -1) { + spAnimation_dispose(animation); + _spSkeletonJson_setError(self, root, "Slot not found: ", slotMap->name); + return 0; + } + + for (timelineMap = slotMap->child; timelineMap; timelineMap = timelineMap->next) { + if (strcmp(timelineMap->name, "attachment") == 0) { + spAttachmentTimeline *timeline = spAttachmentTimeline_create(timelineMap->size); + timeline->slotIndex = slotIndex; + + for (valueMap = timelineMap->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) { + Json* name = Json_getItem(valueMap, "name"); + spAttachmentTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), + name->type == Json_NULL ? 0 : name->valueString); + } + animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); + animation->duration = MAX(animation->duration, timeline->frames[timelineMap->size - 1]); + + } else if (strcmp(timelineMap->name, "color") == 0) { + spColorTimeline *timeline = spColorTimeline_create(timelineMap->size); + timeline->slotIndex = slotIndex; + + for (valueMap = timelineMap->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) { + const char* s = Json_getString(valueMap, "color", 0); + spColorTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), toColor(s, 0), toColor(s, 1), toColor(s, 2), + toColor(s, 3)); + readCurve(valueMap, SUPER(timeline), frameIndex); + } + animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); + animation->duration = MAX(animation->duration, timeline->frames[(timelineMap->size - 1) * COLOR_ENTRIES]); + + } else if (strcmp(timelineMap->name, "twoColor") == 0) { + spTwoColorTimeline *timeline = spTwoColorTimeline_create(timelineMap->size); + timeline->slotIndex = slotIndex; + + for (valueMap = timelineMap->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) { + const char* s = Json_getString(valueMap, "light", 0); + const char* ds = Json_getString(valueMap, "dark", 0); + spTwoColorTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), toColor(s, 0), toColor(s, 1), toColor(s, 2), + toColor(s, 3), toColor(ds, 0), toColor(ds, 1), toColor(ds, 2)); + readCurve(valueMap, SUPER(timeline), frameIndex); + } + animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); + animation->duration = MAX(animation->duration, timeline->frames[(timelineMap->size - 1) * TWOCOLOR_ENTRIES]); + + } else { + spAnimation_dispose(animation); + _spSkeletonJson_setError(self, 0, "Invalid timeline type for a slot: ", timelineMap->name); + return 0; + } + } + } + + /* Bone timelines. */ + for (boneMap = bones ? bones->child : 0; boneMap; boneMap = boneMap->next) { + Json *timelineMap; + + int boneIndex = spSkeletonData_findBoneIndex(skeletonData, boneMap->name); + if (boneIndex == -1) { + spAnimation_dispose(animation); + _spSkeletonJson_setError(self, root, "Bone not found: ", boneMap->name); + return 0; + } + + for (timelineMap = boneMap->child; timelineMap; timelineMap = timelineMap->next) { + if (strcmp(timelineMap->name, "rotate") == 0) { + spRotateTimeline *timeline = spRotateTimeline_create(timelineMap->size); + timeline->boneIndex = boneIndex; + + for (valueMap = timelineMap->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) { + spRotateTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), Json_getFloat(valueMap, "angle", 0)); + readCurve(valueMap, SUPER(timeline), frameIndex); + } + animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); + animation->duration = MAX(animation->duration, timeline->frames[(timelineMap->size - 1) * ROTATE_ENTRIES]); + + } else { + int isScale = strcmp(timelineMap->name, "scale") == 0; + int isTranslate = strcmp(timelineMap->name, "translate") == 0; + int isShear = strcmp(timelineMap->name, "shear") == 0; + if (isScale || isTranslate || isShear) { + float timelineScale = isTranslate ? self->scale: 1; + spTranslateTimeline *timeline = 0; + if (isScale) timeline = spScaleTimeline_create(timelineMap->size); + else if (isTranslate) timeline = spTranslateTimeline_create(timelineMap->size); + else if (isShear) timeline = spShearTimeline_create(timelineMap->size); + timeline->boneIndex = boneIndex; + + for (valueMap = timelineMap->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) { + spTranslateTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), Json_getFloat(valueMap, "x", 0) * timelineScale, + Json_getFloat(valueMap, "y", 0) * timelineScale); + readCurve(valueMap, SUPER(timeline), frameIndex); + } + animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); + animation->duration = MAX(animation->duration, timeline->frames[(timelineMap->size - 1) * TRANSLATE_ENTRIES]); + + } else { + spAnimation_dispose(animation); + _spSkeletonJson_setError(self, 0, "Invalid timeline type for a bone: ", timelineMap->name); + return 0; + } + } + } + } + + /* IK constraint timelines. */ + for (constraintMap = ik ? ik->child : 0; constraintMap; constraintMap = constraintMap->next) { + spIkConstraintData* constraint = spSkeletonData_findIkConstraint(skeletonData, constraintMap->name); + spIkConstraintTimeline* timeline = spIkConstraintTimeline_create(constraintMap->size); + for (frameIndex = 0; frameIndex < skeletonData->ikConstraintsCount; ++frameIndex) { + if (constraint == skeletonData->ikConstraints[frameIndex]) { + timeline->ikConstraintIndex = frameIndex; + break; + } + } + for (valueMap = constraintMap->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) { + spIkConstraintTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), Json_getFloat(valueMap, "mix", 1), + Json_getInt(valueMap, "bendPositive", 1) ? 1 : -1); + readCurve(valueMap, SUPER(timeline), frameIndex); + } + animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); + animation->duration = MAX(animation->duration, timeline->frames[(constraintMap->size - 1) * IKCONSTRAINT_ENTRIES]); + } + + /* Transform constraint timelines. */ + for (constraintMap = transform ? transform->child : 0; constraintMap; constraintMap = constraintMap->next) { + spTransformConstraintData* constraint = spSkeletonData_findTransformConstraint(skeletonData, constraintMap->name); + spTransformConstraintTimeline* timeline = spTransformConstraintTimeline_create(constraintMap->size); + for (frameIndex = 0; frameIndex < skeletonData->transformConstraintsCount; ++frameIndex) { + if (constraint == skeletonData->transformConstraints[frameIndex]) { + timeline->transformConstraintIndex = frameIndex; + break; + } + } + for (valueMap = constraintMap->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) { + spTransformConstraintTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), Json_getFloat(valueMap, "rotateMix", 1), + Json_getFloat(valueMap, "translateMix", 1), Json_getFloat(valueMap, "scaleMix", 1), Json_getFloat(valueMap, "shearMix", 1)); + readCurve(valueMap, SUPER(timeline), frameIndex); + } + animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); + animation->duration = MAX(animation->duration, timeline->frames[(constraintMap->size - 1) * TRANSFORMCONSTRAINT_ENTRIES]); + } + + /** Path constraint timelines. */ + for(constraintMap = paths ? paths->child : 0; constraintMap; constraintMap = constraintMap->next ) { + int constraintIndex, i; + Json* timelineMap; + + spPathConstraintData* data = spSkeletonData_findPathConstraint(skeletonData, constraintMap->name); + if (!data) { + spAnimation_dispose(animation); + _spSkeletonJson_setError(self, root, "Path constraint not found: ", constraintMap->name); + return 0; + } + for (i = 0; i < skeletonData->pathConstraintsCount; i++) { + if (skeletonData->pathConstraints[i] == data) { + constraintIndex = i; + break; + } + } + + for (timelineMap = constraintMap->child; timelineMap; timelineMap = timelineMap->next) { + const char* timelineName = timelineMap->name; + if (strcmp(timelineName, "position") == 0 || strcmp(timelineName, "spacing") == 0) { + spPathConstraintPositionTimeline* timeline; + float timelineScale = 1; + if (strcmp(timelineName, "spacing") == 0) { + timeline = (spPathConstraintPositionTimeline*)spPathConstraintSpacingTimeline_create(timelineMap->size); + if (data->spacingMode == SP_SPACING_MODE_LENGTH || data->spacingMode == SP_SPACING_MODE_FIXED) timelineScale = self->scale; + } else { + timeline = spPathConstraintPositionTimeline_create(timelineMap->size); + if (data->positionMode == SP_POSITION_MODE_FIXED) timelineScale = self->scale; + } + timeline->pathConstraintIndex = constraintIndex; + for (valueMap = timelineMap->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) { + spPathConstraintPositionTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), Json_getFloat(valueMap, timelineName, 0) * timelineScale); + readCurve(valueMap, SUPER(timeline), frameIndex); + } + animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); + animation->duration = MAX(animation->duration, timeline->frames[(timelineMap->size - 1) * PATHCONSTRAINTPOSITION_ENTRIES]); + } else if (strcmp(timelineName, "mix") == 0) { + spPathConstraintMixTimeline* timeline = spPathConstraintMixTimeline_create(timelineMap->size); + timeline->pathConstraintIndex = constraintIndex; + for (valueMap = timelineMap->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) { + spPathConstraintMixTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), + Json_getFloat(valueMap, "rotateMix", 1), Json_getFloat(valueMap, "translateMix", 1)); + readCurve(valueMap, SUPER(timeline), frameIndex); + } + animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); + animation->duration = MAX(animation->duration, timeline->frames[(timelineMap->size - 1) * PATHCONSTRAINTMIX_ENTRIES]); + } + } + } + + /* Deform timelines. */ + for (constraintMap = deform ? deform->child : 0; constraintMap; constraintMap = constraintMap->next) { + spSkin* skin = spSkeletonData_findSkin(skeletonData, constraintMap->name); + for (slotMap = constraintMap->child; slotMap; slotMap = slotMap->next) { + int slotIndex = spSkeletonData_findSlotIndex(skeletonData, slotMap->name); + Json* timelineMap; + for (timelineMap = slotMap->child; timelineMap; timelineMap = timelineMap->next) { + float* tempDeform; + spDeformTimeline *timeline; + int weighted, deformLength; + + spVertexAttachment* attachment = SUB_CAST(spVertexAttachment, spSkin_getAttachment(skin, slotIndex, timelineMap->name)); + if (!attachment) { + spAnimation_dispose(animation); + _spSkeletonJson_setError(self, 0, "Attachment not found: ", timelineMap->name); + return 0; + } + weighted = attachment->bones != 0; + deformLength = weighted ? attachment->verticesCount / 3 * 2 : attachment->verticesCount; + tempDeform = MALLOC(float, deformLength); + + timeline = spDeformTimeline_create(timelineMap->size, deformLength); + timeline->slotIndex = slotIndex; + timeline->attachment = SUPER(attachment); + + for (valueMap = timelineMap->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) { + Json* vertices = Json_getItem(valueMap, "vertices"); + float* deform; + if (!vertices) { + if (weighted) { + deform = tempDeform; + memset(deform, 0, sizeof(float) * deformLength); + } else + deform = attachment->vertices; + } else { + int v, start = Json_getInt(valueMap, "offset", 0); + Json* vertex; + deform = tempDeform; + memset(deform, 0, sizeof(float) * start); + if (self->scale == 1) { + for (vertex = vertices->child, v = start; vertex; vertex = vertex->next, ++v) + deform[v] = vertex->valueFloat; + } else { + for (vertex = vertices->child, v = start; vertex; vertex = vertex->next, ++v) + deform[v] = vertex->valueFloat * self->scale; + } + memset(deform + v, 0, sizeof(float) * (deformLength - v)); + if (!weighted) { + float* vertices = attachment->vertices; + for (v = 0; v < deformLength; ++v) + deform[v] += vertices[v]; + } + } + spDeformTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), deform); + readCurve(valueMap, SUPER(timeline), frameIndex); + } + FREE(tempDeform); + + animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); + animation->duration = MAX(animation->duration, timeline->frames[timelineMap->size - 1]); + } + } + } + + /* Draw order timeline. */ + if (drawOrder) { + spDrawOrderTimeline* timeline = spDrawOrderTimeline_create(drawOrder->size, skeletonData->slotsCount); + for (valueMap = drawOrder->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) { + int ii; + int* drawOrder = 0; + Json* offsets = Json_getItem(valueMap, "offsets"); + if (offsets) { + Json* offsetMap; + int* unchanged = MALLOC(int, skeletonData->slotsCount - offsets->size); + int originalIndex = 0, unchangedIndex = 0; + + drawOrder = MALLOC(int, skeletonData->slotsCount); + for (ii = skeletonData->slotsCount - 1; ii >= 0; --ii) + drawOrder[ii] = -1; + + for (offsetMap = offsets->child; offsetMap; offsetMap = offsetMap->next) { + int slotIndex = spSkeletonData_findSlotIndex(skeletonData, Json_getString(offsetMap, "slot", 0)); + if (slotIndex == -1) { + spAnimation_dispose(animation); + _spSkeletonJson_setError(self, 0, "Slot not found: ", Json_getString(offsetMap, "slot", 0)); + return 0; + } + /* Collect unchanged items. */ + while (originalIndex != slotIndex) + unchanged[unchangedIndex++] = originalIndex++; + /* Set changed items. */ + drawOrder[originalIndex + Json_getInt(offsetMap, "offset", 0)] = originalIndex; + originalIndex++; + } + /* Collect remaining unchanged items. */ + while (originalIndex < skeletonData->slotsCount) + unchanged[unchangedIndex++] = originalIndex++; + /* Fill in unchanged items. */ + for (ii = skeletonData->slotsCount - 1; ii >= 0; ii--) + if (drawOrder[ii] == -1) drawOrder[ii] = unchanged[--unchangedIndex]; + FREE(unchanged); + } + spDrawOrderTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), drawOrder); + FREE(drawOrder); + } + animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); + animation->duration = MAX(animation->duration, timeline->frames[drawOrder->size - 1]); + } + + /* Event timeline. */ + if (events) { + spEventTimeline* timeline = spEventTimeline_create(events->size); + for (valueMap = events->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) { + spEvent* event; + const char* stringValue; + spEventData* eventData = spSkeletonData_findEvent(skeletonData, Json_getString(valueMap, "name", 0)); + if (!eventData) { + spAnimation_dispose(animation); + _spSkeletonJson_setError(self, 0, "Event not found: ", Json_getString(valueMap, "name", 0)); + return 0; + } + event = spEvent_create(Json_getFloat(valueMap, "time", 0), eventData); + event->intValue = Json_getInt(valueMap, "int", eventData->intValue); + event->floatValue = Json_getFloat(valueMap, "float", eventData->floatValue); + stringValue = Json_getString(valueMap, "string", eventData->stringValue); + if (stringValue) MALLOC_STR(event->stringValue, stringValue); + spEventTimeline_setFrame(timeline, frameIndex, event); + } + animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); + animation->duration = MAX(animation->duration, timeline->frames[events->size - 1]); + } + + return animation; +} + +static void _readVertices (spSkeletonJson* self, Json* attachmentMap, spVertexAttachment* attachment, int verticesLength) { + Json* entry; + float* vertices; + int i, n, nn, entrySize; + spFloatArray* weights; + spIntArray* bones; + + attachment->worldVerticesLength = verticesLength; + + entry = Json_getItem(attachmentMap, "vertices"); + entrySize = entry->size; + vertices = MALLOC(float, entrySize); + for (entry = entry->child, i = 0; entry; entry = entry->next, ++i) + vertices[i] = entry->valueFloat; + + if (verticesLength == entrySize) { + if (self->scale != 1) + for (i = 0; i < entrySize; ++i) + vertices[i] *= self->scale; + attachment->verticesCount = verticesLength; + attachment->vertices = vertices; + + attachment->bonesCount = 0; + attachment->bones = 0; + return; + } + + weights = spFloatArray_create(verticesLength * 3 * 3); + bones = spIntArray_create(verticesLength * 3); + + for (i = 0, n = entrySize; i < n;) { + int boneCount = (int)vertices[i++]; + spIntArray_add(bones, boneCount); + for (nn = i + boneCount * 4; i < nn; i += 4) { + spIntArray_add(bones, (int)vertices[i]); + spFloatArray_add(weights, vertices[i + 1] * self->scale); + spFloatArray_add(weights, vertices[i + 2] * self->scale); + spFloatArray_add(weights, vertices[i + 3]); + } + } + + attachment->verticesCount = weights->size; + attachment->vertices = weights->items; + FREE(weights); + attachment->bonesCount = bones->size; + attachment->bones = bones->items; + FREE(bones); + + FREE(vertices); +} + +spSkeletonData* spSkeletonJson_readSkeletonDataFile (spSkeletonJson* self, const char* path) { + int length; + spSkeletonData* skeletonData; + const char* json = _spUtil_readFile(path, &length); + if (length == 0 || !json) { + _spSkeletonJson_setError(self, 0, "Unable to read skeleton file: ", path); + return 0; + } + skeletonData = spSkeletonJson_readSkeletonData(self, json); + FREE(json); + return skeletonData; +} + +spSkeletonData* spSkeletonJson_readSkeletonData (spSkeletonJson* self, const char* json) { + int i, ii; + spSkeletonData* skeletonData; + Json *root, *skeleton, *bones, *boneMap, *ik, *transform, *path, *slots, *skins, *animations, *events; + char* oldLocale; + _spSkeletonJson* internal = SUB_CAST(_spSkeletonJson, self); + + FREE(self->error); + CONST_CAST(char*, self->error) = 0; + internal->linkedMeshCount = 0; + +#ifndef __ANDROID__ + oldLocale = strdup(setlocale(LC_NUMERIC, NULL)); + setlocale(LC_NUMERIC, "C"); +#endif + + root = Json_create(json); + +#ifndef __ANDROID__ + setlocale(LC_NUMERIC, oldLocale); + free(oldLocale); +#endif + + if (!root) { + _spSkeletonJson_setError(self, 0, "Invalid skeleton JSON: ", Json_getError()); + return 0; + } + + skeletonData = spSkeletonData_create(); + + skeleton = Json_getItem(root, "skeleton"); + if (skeleton) { + MALLOC_STR(skeletonData->hash, Json_getString(skeleton, "hash", 0)); + MALLOC_STR(skeletonData->version, Json_getString(skeleton, "spine", 0)); + skeletonData->width = Json_getFloat(skeleton, "width", 0); + skeletonData->height = Json_getFloat(skeleton, "height", 0); + } + + /* Bones. */ + bones = Json_getItem(root, "bones"); + skeletonData->bones = MALLOC(spBoneData*, bones->size); + for (boneMap = bones->child, i = 0; boneMap; boneMap = boneMap->next, ++i) { + spBoneData* data; + const char* transformMode; + + spBoneData* parent = 0; + const char* parentName = Json_getString(boneMap, "parent", 0); + if (parentName) { + parent = spSkeletonData_findBone(skeletonData, parentName); + if (!parent) { + spSkeletonData_dispose(skeletonData); + _spSkeletonJson_setError(self, root, "Parent bone not found: ", parentName); + return 0; + } + } + + data = spBoneData_create(skeletonData->bonesCount, Json_getString(boneMap, "name", 0), parent); + data->length = Json_getFloat(boneMap, "length", 0) * self->scale; + data->x = Json_getFloat(boneMap, "x", 0) * self->scale; + data->y = Json_getFloat(boneMap, "y", 0) * self->scale; + data->rotation = Json_getFloat(boneMap, "rotation", 0); + data->scaleX = Json_getFloat(boneMap, "scaleX", 1); + data->scaleY = Json_getFloat(boneMap, "scaleY", 1); + data->shearX = Json_getFloat(boneMap, "shearX", 0); + data->shearY = Json_getFloat(boneMap, "shearY", 0); + transformMode = Json_getString(boneMap, "transform", "normal"); + data->transformMode = SP_TRANSFORMMODE_NORMAL; + if (strcmp(transformMode, "normal") == 0) + data->transformMode = SP_TRANSFORMMODE_NORMAL; + if (strcmp(transformMode, "onlyTranslation") == 0) + data->transformMode = SP_TRANSFORMMODE_ONLYTRANSLATION; + if (strcmp(transformMode, "noRotationOrReflection") == 0) + data->transformMode = SP_TRANSFORMMODE_NOROTATIONORREFLECTION; + if (strcmp(transformMode, "noScale") == 0) + data->transformMode = SP_TRANSFORMMODE_NOSCALE; + if (strcmp(transformMode, "noScaleOrReflection") == 0) + data->transformMode = SP_TRANSFORMMODE_NOSCALEORREFLECTION; + + skeletonData->bones[i] = data; + skeletonData->bonesCount++; + } + + /* Slots. */ + slots = Json_getItem(root, "slots"); + if (slots) { + Json *slotMap; + skeletonData->slotsCount = slots->size; + skeletonData->slots = MALLOC(spSlotData*, slots->size); + for (slotMap = slots->child, i = 0; slotMap; slotMap = slotMap->next, ++i) { + spSlotData* data; + const char* color; + const char* dark; + Json *item; + + const char* boneName = Json_getString(slotMap, "bone", 0); + spBoneData* boneData = spSkeletonData_findBone(skeletonData, boneName); + if (!boneData) { + spSkeletonData_dispose(skeletonData); + _spSkeletonJson_setError(self, root, "Slot bone not found: ", boneName); + return 0; + } + + data = spSlotData_create(i, Json_getString(slotMap, "name", 0), boneData); + + color = Json_getString(slotMap, "color", 0); + if (color) { + spColor_setFromFloats(&data->color, + toColor(color, 0), + toColor(color, 1), + toColor(color, 2), + toColor(color, 3)); + } + + dark = Json_getString(slotMap, "dark", 0); + if (dark) { + data->darkColor = spColor_create(); + spColor_setFromFloats(data->darkColor, + toColor(dark, 0), + toColor(dark, 1), + toColor(dark, 2), + toColor(dark, 3)); + } + + item = Json_getItem(slotMap, "attachment"); + if (item) spSlotData_setAttachmentName(data, item->valueString); + + item = Json_getItem(slotMap, "blend"); + if (item) { + if (strcmp(item->valueString, "additive") == 0) + data->blendMode = SP_BLEND_MODE_ADDITIVE; + else if (strcmp(item->valueString, "multiply") == 0) + data->blendMode = SP_BLEND_MODE_MULTIPLY; + else if (strcmp(item->valueString, "screen") == 0) + data->blendMode = SP_BLEND_MODE_SCREEN; + } + + skeletonData->slots[i] = data; + } + } + + /* IK constraints. */ + ik = Json_getItem(root, "ik"); + if (ik) { + Json *constraintMap; + skeletonData->ikConstraintsCount = ik->size; + skeletonData->ikConstraints = MALLOC(spIkConstraintData*, ik->size); + for (constraintMap = ik->child, i = 0; constraintMap; constraintMap = constraintMap->next, ++i) { + const char* targetName; + + spIkConstraintData* data = spIkConstraintData_create(Json_getString(constraintMap, "name", 0)); + data->order = Json_getInt(constraintMap, "order", 0); + + boneMap = Json_getItem(constraintMap, "bones"); + data->bonesCount = boneMap->size; + data->bones = MALLOC(spBoneData*, boneMap->size); + for (boneMap = boneMap->child, ii = 0; boneMap; boneMap = boneMap->next, ++ii) { + data->bones[ii] = spSkeletonData_findBone(skeletonData, boneMap->valueString); + if (!data->bones[ii]) { + spSkeletonData_dispose(skeletonData); + _spSkeletonJson_setError(self, root, "IK bone not found: ", boneMap->valueString); + return 0; + } + } + + targetName = Json_getString(constraintMap, "target", 0); + data->target = spSkeletonData_findBone(skeletonData, targetName); + if (!data->target) { + spSkeletonData_dispose(skeletonData); + _spSkeletonJson_setError(self, root, "Target bone not found: ", boneMap->name); + return 0; + } + + data->bendDirection = Json_getInt(constraintMap, "bendPositive", 1) ? 1 : -1; + data->mix = Json_getFloat(constraintMap, "mix", 1); + + skeletonData->ikConstraints[i] = data; + } + } + + /* Transform constraints. */ + transform = Json_getItem(root, "transform"); + if (transform) { + Json *constraintMap; + skeletonData->transformConstraintsCount = transform->size; + skeletonData->transformConstraints = MALLOC(spTransformConstraintData*, transform->size); + for (constraintMap = transform->child, i = 0; constraintMap; constraintMap = constraintMap->next, ++i) { + const char* name; + + spTransformConstraintData* data = spTransformConstraintData_create(Json_getString(constraintMap, "name", 0)); + data->order = Json_getInt(constraintMap, "order", 0); + + boneMap = Json_getItem(constraintMap, "bones"); + data->bonesCount = boneMap->size; + CONST_CAST(spBoneData**, data->bones) = MALLOC(spBoneData*, boneMap->size); + for (boneMap = boneMap->child, ii = 0; boneMap; boneMap = boneMap->next, ++ii) { + data->bones[ii] = spSkeletonData_findBone(skeletonData, boneMap->valueString); + if (!data->bones[ii]) { + spSkeletonData_dispose(skeletonData); + _spSkeletonJson_setError(self, root, "Transform bone not found: ", boneMap->valueString); + return 0; + } + } + + name = Json_getString(constraintMap, "target", 0); + data->target = spSkeletonData_findBone(skeletonData, name); + if (!data->target) { + spSkeletonData_dispose(skeletonData); + _spSkeletonJson_setError(self, root, "Target bone not found: ", boneMap->name); + return 0; + } + + data->local = Json_getInt(constraintMap, "local", 0); + data->relative = Json_getInt(constraintMap, "relative", 0); + data->offsetRotation = Json_getFloat(constraintMap, "rotation", 0); + data->offsetX = Json_getFloat(constraintMap, "x", 0) * self->scale; + data->offsetY = Json_getFloat(constraintMap, "y", 0) * self->scale; + data->offsetScaleX = Json_getFloat(constraintMap, "scaleX", 0); + data->offsetScaleY = Json_getFloat(constraintMap, "scaleY", 0); + data->offsetShearY = Json_getFloat(constraintMap, "shearY", 0); + + data->rotateMix = Json_getFloat(constraintMap, "rotateMix", 1); + data->translateMix = Json_getFloat(constraintMap, "translateMix", 1); + data->scaleMix = Json_getFloat(constraintMap, "scaleMix", 1); + data->shearMix = Json_getFloat(constraintMap, "shearMix", 1); + + skeletonData->transformConstraints[i] = data; + } + } + + /* Path constraints */ + path = Json_getItem(root, "path"); + if (path) { + Json *constraintMap; + skeletonData->pathConstraintsCount = path->size; + skeletonData->pathConstraints = MALLOC(spPathConstraintData*, path->size); + for (constraintMap = path->child, i = 0; constraintMap; constraintMap = constraintMap->next, ++i) { + const char* name; + const char* item; + + spPathConstraintData* data = spPathConstraintData_create(Json_getString(constraintMap, "name", 0)); + data->order = Json_getInt(constraintMap, "order", 0); + + boneMap = Json_getItem(constraintMap, "bones"); + data->bonesCount = boneMap->size; + CONST_CAST(spBoneData**, data->bones) = MALLOC(spBoneData*, boneMap->size); + for (boneMap = boneMap->child, ii = 0; boneMap; boneMap = boneMap->next, ++ii) { + data->bones[ii] = spSkeletonData_findBone(skeletonData, boneMap->valueString); + if (!data->bones[ii]) { + spSkeletonData_dispose(skeletonData); + _spSkeletonJson_setError(self, root, "Path bone not found: ", boneMap->valueString); + return 0; + } + } + + name = Json_getString(constraintMap, "target", 0); + data->target = spSkeletonData_findSlot(skeletonData, name); + if (!data->target) { + spSkeletonData_dispose(skeletonData); + _spSkeletonJson_setError(self, root, "Target slot not found: ", boneMap->name); + return 0; + } + + item = Json_getString(constraintMap, "positionMode", "percent"); + if (strcmp(item, "fixed") == 0) data->positionMode = SP_POSITION_MODE_FIXED; + else if (strcmp(item, "percent") == 0) data->positionMode = SP_POSITION_MODE_PERCENT; + + item = Json_getString(constraintMap, "spacingMode", "length"); + if (strcmp(item, "length") == 0) data->spacingMode = SP_SPACING_MODE_LENGTH; + else if (strcmp(item, "fixed") == 0) data->spacingMode = SP_SPACING_MODE_FIXED; + else if (strcmp(item, "percent") == 0) data->spacingMode = SP_SPACING_MODE_PERCENT; + + item = Json_getString(constraintMap, "rotateMode", "tangent"); + if (strcmp(item, "tangent") == 0) data->rotateMode = SP_ROTATE_MODE_TANGENT; + else if (strcmp(item, "chain") == 0) data->rotateMode = SP_ROTATE_MODE_CHAIN; + else if (strcmp(item, "chainScale") == 0) data->rotateMode = SP_ROTATE_MODE_CHAIN_SCALE; + + data->offsetRotation = Json_getFloat(constraintMap, "rotation", 0); + data->position = Json_getFloat(constraintMap, "position", 0); + if (data->positionMode == SP_POSITION_MODE_FIXED) data->position *= self->scale; + data->spacing = Json_getFloat(constraintMap, "spacing", 0); + if (data->spacingMode == SP_SPACING_MODE_LENGTH || data->spacingMode == SP_SPACING_MODE_FIXED) data->spacing *= self->scale; + data->rotateMix = Json_getFloat(constraintMap, "rotateMix", 1); + data->translateMix = Json_getFloat(constraintMap, "translateMix", 1); + + skeletonData->pathConstraints[i] = data; + } + } + + /* Skins. */ + skins = Json_getItem(root, "skins"); + if (skins) { + Json *skinMap; + skeletonData->skins = MALLOC(spSkin*, skins->size); + for (skinMap = skins->child, i = 0; skinMap; skinMap = skinMap->next, ++i) { + Json *attachmentsMap; + Json *curves; + spSkin *skin = spSkin_create(skinMap->name); + + skeletonData->skins[skeletonData->skinsCount++] = skin; + if (strcmp(skinMap->name, "default") == 0) skeletonData->defaultSkin = skin; + + for (attachmentsMap = skinMap->child; attachmentsMap; attachmentsMap = attachmentsMap->next) { + int slotIndex = spSkeletonData_findSlotIndex(skeletonData, attachmentsMap->name); + Json *attachmentMap; + + for (attachmentMap = attachmentsMap->child; attachmentMap; attachmentMap = attachmentMap->next) { + spAttachment* attachment; + const char* skinAttachmentName = attachmentMap->name; + const char* attachmentName = Json_getString(attachmentMap, "name", skinAttachmentName); + const char* path = Json_getString(attachmentMap, "path", attachmentName); + const char* color; + Json* entry; + + const char* typeString = Json_getString(attachmentMap, "type", "region"); + spAttachmentType type; + if (strcmp(typeString, "region") == 0) + type = SP_ATTACHMENT_REGION; + else if (strcmp(typeString, "mesh") == 0) + type = SP_ATTACHMENT_MESH; + else if (strcmp(typeString, "linkedmesh") == 0) + type = SP_ATTACHMENT_LINKED_MESH; + else if (strcmp(typeString, "boundingbox") == 0) + type = SP_ATTACHMENT_BOUNDING_BOX; + else if (strcmp(typeString, "path") == 0) + type = SP_ATTACHMENT_PATH; + else if (strcmp(typeString, "clipping") == 0) + type = SP_ATTACHMENT_CLIPPING; + else { + spSkeletonData_dispose(skeletonData); + _spSkeletonJson_setError(self, root, "Unknown attachment type: ", typeString); + return 0; + } + + attachment = spAttachmentLoader_createAttachment(self->attachmentLoader, skin, type, attachmentName, path); + if (!attachment) { + if (self->attachmentLoader->error1) { + spSkeletonData_dispose(skeletonData); + _spSkeletonJson_setError(self, root, self->attachmentLoader->error1, self->attachmentLoader->error2); + return 0; + } + continue; + } + + switch (attachment->type) { + case SP_ATTACHMENT_REGION: { + spRegionAttachment* region = SUB_CAST(spRegionAttachment, attachment); + if (path) MALLOC_STR(region->path, path); + region->x = Json_getFloat(attachmentMap, "x", 0) * self->scale; + region->y = Json_getFloat(attachmentMap, "y", 0) * self->scale; + region->scaleX = Json_getFloat(attachmentMap, "scaleX", 1); + region->scaleY = Json_getFloat(attachmentMap, "scaleY", 1); + region->rotation = Json_getFloat(attachmentMap, "rotation", 0); + region->width = Json_getFloat(attachmentMap, "width", 32) * self->scale; + region->height = Json_getFloat(attachmentMap, "height", 32) * self->scale; + + color = Json_getString(attachmentMap, "color", 0); + if (color) { + spColor_setFromFloats(®ion->color, + toColor(color, 0), + toColor(color, 1), + toColor(color, 2), + toColor(color, 3)); + } + + spRegionAttachment_updateOffset(region); + + spAttachmentLoader_configureAttachment(self->attachmentLoader, attachment); + break; + } + case SP_ATTACHMENT_MESH: + case SP_ATTACHMENT_LINKED_MESH: { + spMeshAttachment* mesh = SUB_CAST(spMeshAttachment, attachment); + + MALLOC_STR(mesh->path, path); + + color = Json_getString(attachmentMap, "color", 0); + if (color) { + spColor_setFromFloats(&mesh->color, + toColor(color, 0), + toColor(color, 1), + toColor(color, 2), + toColor(color, 3)); + } + + mesh->width = Json_getFloat(attachmentMap, "width", 32) * self->scale; + mesh->height = Json_getFloat(attachmentMap, "height", 32) * self->scale; + + entry = Json_getItem(attachmentMap, "parent"); + if (!entry) { + int verticesLength; + entry = Json_getItem(attachmentMap, "triangles"); + mesh->trianglesCount = entry->size; + mesh->triangles = MALLOC(unsigned short, entry->size); + for (entry = entry->child, ii = 0; entry; entry = entry->next, ++ii) + mesh->triangles[ii] = (unsigned short)entry->valueInt; + + entry = Json_getItem(attachmentMap, "uvs"); + verticesLength = entry->size; + mesh->regionUVs = MALLOC(float, verticesLength); + for (entry = entry->child, ii = 0; entry; entry = entry->next, ++ii) + mesh->regionUVs[ii] = entry->valueFloat; + + _readVertices(self, attachmentMap, SUPER(mesh), verticesLength); + + spMeshAttachment_updateUVs(mesh); + + mesh->hullLength = Json_getInt(attachmentMap, "hull", 0); + + entry = Json_getItem(attachmentMap, "edges"); + if (entry) { + mesh->edgesCount = entry->size; + mesh->edges = MALLOC(int, entry->size); + for (entry = entry->child, ii = 0; entry; entry = entry->next, ++ii) + mesh->edges[ii] = entry->valueInt; + } + + spAttachmentLoader_configureAttachment(self->attachmentLoader, attachment); + } else { + mesh->inheritDeform = Json_getInt(attachmentMap, "deform", 1); + _spSkeletonJson_addLinkedMesh(self, SUB_CAST(spMeshAttachment, attachment), Json_getString(attachmentMap, "skin", 0), slotIndex, + entry->valueString); + } + break; + } + case SP_ATTACHMENT_BOUNDING_BOX: { + spBoundingBoxAttachment* box = SUB_CAST(spBoundingBoxAttachment, attachment); + int vertexCount = Json_getInt(attachmentMap, "vertexCount", 0) << 1; + _readVertices(self, attachmentMap, SUPER(box), vertexCount); + box->super.verticesCount = vertexCount; + spAttachmentLoader_configureAttachment(self->attachmentLoader, attachment); + break; + } + case SP_ATTACHMENT_PATH: { + spPathAttachment* path = SUB_CAST(spPathAttachment, attachment); + int vertexCount = 0; + path->closed = Json_getInt(attachmentMap, "closed", 0); + path->constantSpeed = Json_getInt(attachmentMap, "constantSpeed", 1); + vertexCount = Json_getInt(attachmentMap, "vertexCount", 0); + _readVertices(self, attachmentMap, SUPER(path), vertexCount << 1); + + path->lengthsLength = vertexCount / 3; + path->lengths = MALLOC(float, path->lengthsLength); + + curves = Json_getItem(attachmentMap, "lengths"); + for (curves = curves->child, ii = 0; curves; curves = curves->next, ++ii) { + path->lengths[ii] = curves->valueFloat * self->scale; + } + break; + } + case SP_ATTACHMENT_POINT: { + spPointAttachment* point = SUB_CAST(spPointAttachment, attachment); + point->x = Json_getFloat(attachmentMap, "x", 0) * self->scale; + point->y = Json_getFloat(attachmentMap, "y", 0) * self->scale; + point->rotation = Json_getFloat(attachmentMap, "rotation", 0); + + color = Json_getString(attachmentMap, "color", 0); + if (color) { + spColor_setFromFloats(&point->color, + toColor(color, 0), + toColor(color, 1), + toColor(color, 2), + toColor(color, 3)); + } + break; + } + case SP_ATTACHMENT_CLIPPING: { + spClippingAttachment* clip = SUB_CAST(spClippingAttachment, attachment); + int vertexCount = 0; + const char* end = Json_getString(attachmentMap, "end", 0); + if (end) { + spSlotData* slot = spSkeletonData_findSlot(skeletonData, end); + clip->endSlot = slot; + } + vertexCount = Json_getInt(attachmentMap, "vertexCount", 0) << 1; + _readVertices(self, attachmentMap, SUPER(clip), vertexCount); + spAttachmentLoader_configureAttachment(self->attachmentLoader, attachment); + break; + } + } + + spSkin_addAttachment(skin, slotIndex, skinAttachmentName, attachment); + } + } + } + } + + /* Linked meshes. */ + for (i = 0; i < internal->linkedMeshCount; i++) { + spAttachment* parent; + _spLinkedMesh* linkedMesh = internal->linkedMeshes + i; + spSkin* skin = !linkedMesh->skin ? skeletonData->defaultSkin : spSkeletonData_findSkin(skeletonData, linkedMesh->skin); + if (!skin) { + spSkeletonData_dispose(skeletonData); + _spSkeletonJson_setError(self, 0, "Skin not found: ", linkedMesh->skin); + return 0; + } + parent = spSkin_getAttachment(skin, linkedMesh->slotIndex, linkedMesh->parent); + if (!parent) { + spSkeletonData_dispose(skeletonData); + _spSkeletonJson_setError(self, 0, "Parent mesh not found: ", linkedMesh->parent); + return 0; + } + spMeshAttachment_setParentMesh(linkedMesh->mesh, SUB_CAST(spMeshAttachment, parent)); + spMeshAttachment_updateUVs(linkedMesh->mesh); + spAttachmentLoader_configureAttachment(self->attachmentLoader, SUPER(SUPER(linkedMesh->mesh))); + } + + /* Events. */ + events = Json_getItem(root, "events"); + if (events) { + Json *eventMap; + const char* stringValue; + skeletonData->eventsCount = events->size; + skeletonData->events = MALLOC(spEventData*, events->size); + for (eventMap = events->child, i = 0; eventMap; eventMap = eventMap->next, ++i) { + spEventData* eventData = spEventData_create(eventMap->name); + eventData->intValue = Json_getInt(eventMap, "int", 0); + eventData->floatValue = Json_getFloat(eventMap, "float", 0); + stringValue = Json_getString(eventMap, "string", 0); + if (stringValue) MALLOC_STR(eventData->stringValue, stringValue); + skeletonData->events[i] = eventData; + } + } + + /* Animations. */ + animations = Json_getItem(root, "animations"); + if (animations) { + Json *animationMap; + skeletonData->animations = MALLOC(spAnimation*, animations->size); + for (animationMap = animations->child; animationMap; animationMap = animationMap->next) { + spAnimation* animation = _spSkeletonJson_readAnimation(self, animationMap, skeletonData); + if (!animation) { + spSkeletonData_dispose(skeletonData); + return 0; + } + skeletonData->animations[skeletonData->animationsCount++] = animation; + } + } + + Json_dispose(root); + return skeletonData; +} diff --git a/spine-cpp/spine-cpp/src/spine/Skin.c b/spine-cpp/spine-cpp/src/spine/Skin.c new file mode 100644 index 000000000..91f2d21fe --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/Skin.c @@ -0,0 +1,106 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include + +_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); +} + +/**/ + +spSkin* spSkin_create (const char* name) { + spSkin* self = SUPER(NEW(_spSkin)); + MALLOC_STR(self->name, name); + 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; + } + + FREE(self->name); + FREE(self); +} + +void spSkin_addAttachment (spSkin* self, int slotIndex, const char* name, spAttachment* attachment) { + _Entry* newEntry = _Entry_create(slotIndex, name, attachment); + newEntry->next = SUB_CAST(_spSkin, self)->entries; + SUB_CAST(_spSkin, self)->entries = newEntry; +} + +spAttachment* spSkin_getAttachment (const spSkin* self, int slotIndex, const char* name) { + const _Entry* entry = SUB_CAST(_spSkin, self)->entries; + while (entry) { + if (entry->slotIndex == slotIndex && strcmp(entry->name, name) == 0) return entry->attachment; + entry = entry->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; + } +} diff --git a/spine-cpp/spine-cpp/src/spine/Slot.c b/spine-cpp/spine-cpp/src/spine/Slot.c new file mode 100644 index 000000000..eded60cff --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/Slot.c @@ -0,0 +1,82 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include + +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->attachmentVertices); + 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->attachmentVerticesCount = 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); + } +} diff --git a/spine-cpp/spine-cpp/src/spine/SlotData.c b/spine-cpp/spine-cpp/src/spine/SlotData.c new file mode 100644 index 000000000..a467c0fcb --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/SlotData.c @@ -0,0 +1,56 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include + +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; +} diff --git a/spine-cpp/spine-cpp/src/spine/TransformConstraint.c b/spine-cpp/spine-cpp/src/spine/TransformConstraint.c new file mode 100644 index 000000000..188d53e2f --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/TransformConstraint.c @@ -0,0 +1,273 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include +#include + +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); + } +} diff --git a/spine-cpp/spine-cpp/src/spine/TransformConstraintData.c b/spine-cpp/spine-cpp/src/spine/TransformConstraintData.c new file mode 100644 index 000000000..34064e0f8 --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/TransformConstraintData.c @@ -0,0 +1,44 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include + +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); +} diff --git a/spine-cpp/spine-cpp/src/spine/Triangulator.c b/spine-cpp/spine-cpp/src/spine/Triangulator.c new file mode 100644 index 000000000..16b69bc93 --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/Triangulator.c @@ -0,0 +1,361 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include +#include + +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, i = 0, next = 1; + int previousIndex, nextIndex; + 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; +} diff --git a/spine-cpp/spine-cpp/src/spine/VertexAttachment.c b/spine-cpp/spine-cpp/src/spine/VertexAttachment.c new file mode 100644 index 000000000..8b6dfea36 --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/VertexAttachment.c @@ -0,0 +1,114 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include + +/* FIXME this is not thread-safe */ +static int nextID = 0; + +void _spVertexAttachment_init (spVertexAttachment* attachment) { + attachment->id = (nextID++ & 65535) << 11; +} + +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* deform; + float* vertices; + int* bones; + + count += offset; + skeleton = slot->bone->skeleton; + deformLength = slot->attachmentVerticesCount; + deform = slot->attachmentVertices; + vertices = self->vertices; + bones = self->bones; + if (!bones) { + spBone* bone; + int v, w; + float x, y; + if (deformLength > 0) vertices = deform; + 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] + deform[f], vy = vertices[b + 1] + deform[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; + } + } + } +} diff --git a/spine-cpp/spine-cpp/src/spine/VertexEffect.c b/spine-cpp/spine-cpp/src/spine/VertexEffect.c new file mode 100644 index 000000000..68d4d1f68 --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/VertexEffect.c @@ -0,0 +1,98 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include + +void _spJitterVertexEffect_begin(spVertexEffect* self, spSkeleton* 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); +} + +void _spJitterVertexEffect_end(spVertexEffect* 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; + } +} + +void _spSwirlVertexEffect_end(spVertexEffect* 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); +} + diff --git a/spine-cpp/spine-cpp/src/spine/extension.c b/spine-cpp/spine-cpp/src/spine/extension.c new file mode 100644 index 000000000..e9937cca0 --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/extension.c @@ -0,0 +1,128 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include +#include + +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; +} + +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; +} diff --git a/spine-cpp/spine-cpp/src/spine/kvec.h b/spine-cpp/spine-cpp/src/spine/kvec.h new file mode 100644 index 000000000..f40e8bb95 --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/kvec.h @@ -0,0 +1,105 @@ +/* The MIT License + + Copyright (c) 2008, by Attractive Chaos + + Permission is hereby granted, free 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. +*/ + +/* + An example: + +#include "kvec.h" +int main() { + kvec_t(int) array; + kv_init(array); + kv_push(int, array, 10); // append + kv_a(int, array, 20) = 5; // dynamic + kv_A(array, 20) = 4; // static + kv_destroy(array); + return 0; +} +*/ + +/* + 2008-09-22 (0.1.0): + + * The initial version. + + 2017-19-18 (0.1.1): + + Spine Special Edition + * Made helper macros for alloc, free and memcpy, which can be overridden. + * Made these helpers point to the Spine C Runtime alloc and free functions by default + * Reimplemented kv_resize to use alloc and free instead of realloc + * Changed kv_push to use kv_resize instead of realloc + * Removed kv_pushp and kv_a macros because the weren't used + * Removed stdlib include +*/ + +#ifndef AC_KVEC_H +#define AC_KVEC_H + +#ifndef _kv_free +#define _kv_free(type, p) (FREE(p)) +#endif + +#ifndef _kv_alloc +#define _kv_alloc(type, s) ((type*)(MALLOC(type, (s)))) +#endif + +#ifndef _kv_copy +#define _kv_copy(type, d, s, n) memcpy((d), (s), sizeof(type) * (n)) +#endif + +#define kv_roundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x)) + +#define kvec_t(type) struct { size_t n, m; type *a; } +#define kv_init(v) ((v).n = (v).m = 0, (v).a = 0) +#define kv_destroy(v) _kv_free(type, (v).a) +#define kv_A(v, i) ((v).a[(i)]) +#define kv_array(v) ((v).a) +#define kv_pop(v) ((v).a[--(v).n]) +#define kv_size(v) ((v).n) +#define kv_max(v) ((v).m) + +#define kv_resize(type, v, s) do { \ + type* b = _kv_alloc(type, (s)); \ + if (((s) > 0) && ((v).m > 0)) \ + _kv_copy(type, b, (v).a, ((s) < (v).m)? (s) : (v).m); \ + _kv_free(type, (v).a); \ + (v).a = b; (v).m = (s); \ + } while (0) + +#define kv_trim(type, v) kv_resize(type, (v), kv_size(v)) + +#define kv_copy(type, v1, v0) do { \ + if ((v1).m < (v0).n) kv_resize(type, v1, (v0).n); \ + (v1).n = (v0).n; \ + _kv_copy(type, (v1).a, (v0).a, (v0).n); \ + } while (0) \ + +#define kv_push(type, v, x) do { \ + if ((v).n == (v).m) \ + kv_resize(type, (v), ((v).m? (v).m<<1 : 2)); \ + (v).a[(v).n++] = (x); \ + } while (0) + +#endif From 38f4fdde2834040680a7ae9a2131a357cc8c93f5 Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Fri, 29 Sep 2017 12:18:02 -0400 Subject: [PATCH 02/83] Okay, gonna do this properly. Will use spine-c AND spine-cpp in parallel. This will be good for benchmarking during and after development. --- spine-cpp/spine-cpp/include/spine/Animation.h | 588 ------- .../spine-cpp/include/spine/AnimationState.h | 185 -- .../include/spine/AnimationStateData.h | 77 - spine-cpp/spine-cpp/include/spine/Array.h | 133 -- spine-cpp/spine-cpp/include/spine/Atlas.h | 174 -- .../include/spine/AtlasAttachmentLoader.h | 58 - .../spine-cpp/include/spine/Attachment.h | 83 - .../include/spine/AttachmentLoader.h | 79 - spine-cpp/spine-cpp/include/spine/Bone.h | 127 -- spine-cpp/spine-cpp/include/spine/BoneData.h | 85 - .../include/spine/BoundingBoxAttachment.h | 59 - .../include/spine/ClippingAttachment.h | 61 - spine-cpp/spine-cpp/include/spine/Color.h | 78 - spine-cpp/spine-cpp/include/spine/Event.h | 72 - spine-cpp/spine-cpp/include/spine/EventData.h | 69 - .../spine-cpp/include/spine/IkConstraint.h | 87 - .../include/spine/IkConstraintData.h | 76 - .../spine-cpp/include/spine/MeshAttachment.h | 91 - .../spine-cpp/include/spine/PathAttachment.h | 63 - .../spine-cpp/include/spine/PathConstraint.h | 113 -- .../include/spine/PathConstraintData.h | 97 -- .../spine-cpp/include/spine/PointAttachment.h | 65 - .../include/spine/RegionAttachment.h | 75 - spine-cpp/spine-cpp/include/spine/Skeleton.h | 174 -- .../spine-cpp/include/spine/SkeletonBinary.h | 72 - .../spine-cpp/include/spine/SkeletonBounds.h | 113 -- .../include/spine/SkeletonClipping.h | 68 - .../spine-cpp/include/spine/SkeletonData.h | 117 -- .../spine-cpp/include/spine/SkeletonJson.h | 73 - spine-cpp/spine-cpp/include/spine/Skin.h | 95 - spine-cpp/spine-cpp/include/spine/Slot.h | 93 - spine-cpp/spine-cpp/include/spine/SlotData.h | 90 - .../include/spine/TransformConstraint.h | 81 - .../include/spine/TransformConstraintData.h | 87 - .../spine-cpp/include/spine/Triangulator.h | 63 - .../include/spine/VertexAttachment.h | 68 - .../spine-cpp/include/spine/VertexEffect.h | 85 - spine-cpp/spine-cpp/include/spine/dll.h | 48 - spine-cpp/spine-cpp/include/spine/extension.h | 318 ---- spine-cpp/spine-cpp/include/spine/spine.h | 63 - spine-cpp/spine-cpp/src/spine/Animation.c | 1529 ----------------- .../spine-cpp/src/spine/AnimationState.c | 932 ---------- .../spine-cpp/src/spine/AnimationStateData.c | 151 -- spine-cpp/spine-cpp/src/spine/Array.c | 39 - spine-cpp/spine-cpp/src/spine/Atlas.c | 359 ---- .../src/spine/AtlasAttachmentLoader.c | 100 -- spine-cpp/spine-cpp/src/spine/Attachment.c | 57 - .../spine-cpp/src/spine/AttachmentLoader.c | 98 -- spine-cpp/spine-cpp/src/spine/Bone.c | 304 ---- spine-cpp/spine-cpp/src/spine/BoneData.c | 48 - .../src/spine/BoundingBoxAttachment.c | 47 - .../spine-cpp/src/spine/ClippingAttachment.c | 48 - spine-cpp/spine-cpp/src/spine/Color.c | 84 - spine-cpp/spine-cpp/src/spine/Event.c | 44 - spine-cpp/spine-cpp/src/spine/EventData.c | 44 - spine-cpp/spine-cpp/src/spine/IkConstraint.c | 208 --- .../spine-cpp/src/spine/IkConstraintData.c | 46 - spine-cpp/spine-cpp/src/spine/Json.c | 426 ----- spine-cpp/spine-cpp/src/spine/Json.h | 83 - .../spine-cpp/src/spine/MeshAttachment.c | 100 -- .../spine-cpp/src/spine/PathAttachment.c | 48 - .../spine-cpp/src/spine/PathConstraint.c | 467 ----- .../spine-cpp/src/spine/PathConstraintData.c | 44 - .../spine-cpp/src/spine/PointAttachment.c | 61 - .../spine-cpp/src/spine/RegionAttachment.c | 130 -- spine-cpp/spine-cpp/src/spine/Skeleton.c | 583 ------- .../spine-cpp/src/spine/SkeletonBinary.c | 1095 ------------ .../spine-cpp/src/spine/SkeletonBounds.c | 205 --- .../spine-cpp/src/spine/SkeletonClipping.c | 313 ---- spine-cpp/spine-cpp/src/spine/SkeletonData.c | 147 -- spine-cpp/spine-cpp/src/spine/SkeletonJson.c | 1119 ------------ spine-cpp/spine-cpp/src/spine/Skin.c | 106 -- spine-cpp/spine-cpp/src/spine/Slot.c | 82 - spine-cpp/spine-cpp/src/spine/SlotData.c | 56 - .../spine-cpp/src/spine/TransformConstraint.c | 273 --- .../src/spine/TransformConstraintData.c | 44 - spine-cpp/spine-cpp/src/spine/Triangulator.c | 361 ---- .../spine-cpp/src/spine/VertexAttachment.c | 114 -- spine-cpp/spine-cpp/src/spine/VertexEffect.c | 98 -- spine-cpp/spine-cpp/src/spine/extension.c | 128 -- spine-cpp/spine-cpp/src/spine/kvec.h | 105 -- 81 files changed, 14629 deletions(-) delete mode 100644 spine-cpp/spine-cpp/include/spine/Animation.h delete mode 100644 spine-cpp/spine-cpp/include/spine/AnimationState.h delete mode 100644 spine-cpp/spine-cpp/include/spine/AnimationStateData.h delete mode 100644 spine-cpp/spine-cpp/include/spine/Array.h delete mode 100644 spine-cpp/spine-cpp/include/spine/Atlas.h delete mode 100644 spine-cpp/spine-cpp/include/spine/AtlasAttachmentLoader.h delete mode 100644 spine-cpp/spine-cpp/include/spine/Attachment.h delete mode 100644 spine-cpp/spine-cpp/include/spine/AttachmentLoader.h delete mode 100644 spine-cpp/spine-cpp/include/spine/Bone.h delete mode 100644 spine-cpp/spine-cpp/include/spine/BoneData.h delete mode 100644 spine-cpp/spine-cpp/include/spine/BoundingBoxAttachment.h delete mode 100644 spine-cpp/spine-cpp/include/spine/ClippingAttachment.h delete mode 100644 spine-cpp/spine-cpp/include/spine/Color.h delete mode 100644 spine-cpp/spine-cpp/include/spine/Event.h delete mode 100644 spine-cpp/spine-cpp/include/spine/EventData.h delete mode 100644 spine-cpp/spine-cpp/include/spine/IkConstraint.h delete mode 100644 spine-cpp/spine-cpp/include/spine/IkConstraintData.h delete mode 100644 spine-cpp/spine-cpp/include/spine/MeshAttachment.h delete mode 100644 spine-cpp/spine-cpp/include/spine/PathAttachment.h delete mode 100644 spine-cpp/spine-cpp/include/spine/PathConstraint.h delete mode 100644 spine-cpp/spine-cpp/include/spine/PathConstraintData.h delete mode 100644 spine-cpp/spine-cpp/include/spine/PointAttachment.h delete mode 100644 spine-cpp/spine-cpp/include/spine/RegionAttachment.h delete mode 100644 spine-cpp/spine-cpp/include/spine/Skeleton.h delete mode 100644 spine-cpp/spine-cpp/include/spine/SkeletonBinary.h delete mode 100644 spine-cpp/spine-cpp/include/spine/SkeletonBounds.h delete mode 100644 spine-cpp/spine-cpp/include/spine/SkeletonClipping.h delete mode 100644 spine-cpp/spine-cpp/include/spine/SkeletonData.h delete mode 100644 spine-cpp/spine-cpp/include/spine/SkeletonJson.h delete mode 100644 spine-cpp/spine-cpp/include/spine/Skin.h delete mode 100644 spine-cpp/spine-cpp/include/spine/Slot.h delete mode 100644 spine-cpp/spine-cpp/include/spine/SlotData.h delete mode 100644 spine-cpp/spine-cpp/include/spine/TransformConstraint.h delete mode 100644 spine-cpp/spine-cpp/include/spine/TransformConstraintData.h delete mode 100644 spine-cpp/spine-cpp/include/spine/Triangulator.h delete mode 100644 spine-cpp/spine-cpp/include/spine/VertexAttachment.h delete mode 100644 spine-cpp/spine-cpp/include/spine/VertexEffect.h delete mode 100644 spine-cpp/spine-cpp/include/spine/dll.h delete mode 100644 spine-cpp/spine-cpp/include/spine/extension.h delete mode 100644 spine-cpp/spine-cpp/include/spine/spine.h delete mode 100644 spine-cpp/spine-cpp/src/spine/Animation.c delete mode 100644 spine-cpp/spine-cpp/src/spine/AnimationState.c delete mode 100644 spine-cpp/spine-cpp/src/spine/AnimationStateData.c delete mode 100644 spine-cpp/spine-cpp/src/spine/Array.c delete mode 100644 spine-cpp/spine-cpp/src/spine/Atlas.c delete mode 100644 spine-cpp/spine-cpp/src/spine/AtlasAttachmentLoader.c delete mode 100644 spine-cpp/spine-cpp/src/spine/Attachment.c delete mode 100644 spine-cpp/spine-cpp/src/spine/AttachmentLoader.c delete mode 100644 spine-cpp/spine-cpp/src/spine/Bone.c delete mode 100644 spine-cpp/spine-cpp/src/spine/BoneData.c delete mode 100644 spine-cpp/spine-cpp/src/spine/BoundingBoxAttachment.c delete mode 100644 spine-cpp/spine-cpp/src/spine/ClippingAttachment.c delete mode 100644 spine-cpp/spine-cpp/src/spine/Color.c delete mode 100644 spine-cpp/spine-cpp/src/spine/Event.c delete mode 100644 spine-cpp/spine-cpp/src/spine/EventData.c delete mode 100644 spine-cpp/spine-cpp/src/spine/IkConstraint.c delete mode 100644 spine-cpp/spine-cpp/src/spine/IkConstraintData.c delete mode 100644 spine-cpp/spine-cpp/src/spine/Json.c delete mode 100644 spine-cpp/spine-cpp/src/spine/Json.h delete mode 100644 spine-cpp/spine-cpp/src/spine/MeshAttachment.c delete mode 100644 spine-cpp/spine-cpp/src/spine/PathAttachment.c delete mode 100644 spine-cpp/spine-cpp/src/spine/PathConstraint.c delete mode 100644 spine-cpp/spine-cpp/src/spine/PathConstraintData.c delete mode 100644 spine-cpp/spine-cpp/src/spine/PointAttachment.c delete mode 100644 spine-cpp/spine-cpp/src/spine/RegionAttachment.c delete mode 100644 spine-cpp/spine-cpp/src/spine/Skeleton.c delete mode 100644 spine-cpp/spine-cpp/src/spine/SkeletonBinary.c delete mode 100644 spine-cpp/spine-cpp/src/spine/SkeletonBounds.c delete mode 100644 spine-cpp/spine-cpp/src/spine/SkeletonClipping.c delete mode 100644 spine-cpp/spine-cpp/src/spine/SkeletonData.c delete mode 100644 spine-cpp/spine-cpp/src/spine/SkeletonJson.c delete mode 100644 spine-cpp/spine-cpp/src/spine/Skin.c delete mode 100644 spine-cpp/spine-cpp/src/spine/Slot.c delete mode 100644 spine-cpp/spine-cpp/src/spine/SlotData.c delete mode 100644 spine-cpp/spine-cpp/src/spine/TransformConstraint.c delete mode 100644 spine-cpp/spine-cpp/src/spine/TransformConstraintData.c delete mode 100644 spine-cpp/spine-cpp/src/spine/Triangulator.c delete mode 100644 spine-cpp/spine-cpp/src/spine/VertexAttachment.c delete mode 100644 spine-cpp/spine-cpp/src/spine/VertexEffect.c delete mode 100644 spine-cpp/spine-cpp/src/spine/extension.c delete mode 100644 spine-cpp/spine-cpp/src/spine/kvec.h diff --git a/spine-cpp/spine-cpp/include/spine/Animation.h b/spine-cpp/spine-cpp/include/spine/Animation.h deleted file mode 100644 index e47a835ce..000000000 --- a/spine-cpp/spine-cpp/include/spine/Animation.h +++ /dev/null @@ -1,588 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef SPINE_ANIMATION_H_ -#define SPINE_ANIMATION_H_ - -#include -#include -#include - -#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_POSE_SETUP, - SP_MIX_POSE_CURRENT, - SP_MIX_POSE_CURRENT_LAYERED -} spMixPose; - -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, spMixPose pose, 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, spMixPose pose, 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 = 3; - -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, int bendDirection); - -#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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/AnimationState.h b/spine-cpp/spine-cpp/include/spine/AnimationState.h deleted file mode 100644 index fe6ae515a..000000000 --- a/spine-cpp/spine-cpp/include/spine/AnimationState.h +++ /dev/null @@ -1,185 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef SPINE_ANIMATIONSTATE_H_ -#define SPINE_ANIMATIONSTATE_H_ - -#include -#include -#include -#include -#include - -#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; - spAnimationStateListener listener; - int trackIndex; - int /*boolean*/ loop; - float eventThreshold, attachmentThreshold, drawOrderThreshold; - float animationStart, animationEnd, animationLast, nextAnimationLast; - float delay, trackTime, trackLast, nextTrackLast, trackEnd, timeScale; - float alpha, mixTime, mixDuration, interruptAlpha, totalAlpha; - spIntArray* timelineData; - spTrackEntryArray* timelineDipMix; - float* timelinesRotation; - int timelinesRotationCount; - void* rendererObject; - void* userData; - -#ifdef __cplusplus - spTrackEntry() : - animation(0), - next(0), mixingFrom(0), - listener(0), - trackIndex(0), - loop(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), - timelineData(0), - timelineDipMix(0), - timelinesRotation(0), - timelinesRotationCount(0) { - } -#endif -}; - -struct spAnimationState { - spAnimationStateData* const data; - - int tracksCount; - spTrackEntry** tracks; - - spAnimationStateListener listener; - - float timeScale; - - spTrackEntryArray* mixingTo; - - void* rendererObject; - -#ifdef __cplusplus - spAnimationState() : - data(0), - tracksCount(0), - tracks(0), - listener(0), - timeScale(0), - mixingTo(0), - rendererObject(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(...) spAnimatinState_setEmptyAnimation(__VA_ARGS__) -#define AnimationState_addEmptyAnimation(...) spAnimatinState_addEmptyAnimation(__VA_ARGS__) -#define AnimationState_setEmptyAnimations(...) spAnimatinState_setEmptyAnimations(__VA_ARGS__) -#define AnimationState_getCurrent(...) spAnimationState_getCurrent(__VA_ARGS__) -#define AnimationState_clearListenerNotifications(...) spAnimatinState_clearListenerNotifications(__VA_ARGS__) -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* SPINE_ANIMATIONSTATE_H_ */ diff --git a/spine-cpp/spine-cpp/include/spine/AnimationStateData.h b/spine-cpp/spine-cpp/include/spine/AnimationStateData.h deleted file mode 100644 index 95f936e80..000000000 --- a/spine-cpp/spine-cpp/include/spine/AnimationStateData.h +++ /dev/null @@ -1,77 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef SPINE_ANIMATIONSTATEDATA_H_ -#define SPINE_ANIMATIONSTATEDATA_H_ - -#include -#include -#include - -#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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/Array.h b/spine-cpp/spine-cpp/include/spine/Array.h deleted file mode 100644 index 3beb08325..000000000 --- a/spine-cpp/spine-cpp/include/spine/Array.h +++ /dev/null @@ -1,133 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef SPINE_ARRAY_H -#define SPINE_ARRAY_H - -#include - -#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 */ diff --git a/spine-cpp/spine-cpp/include/spine/Atlas.h b/spine-cpp/spine-cpp/include/spine/Atlas.h deleted file mode 100644 index 7812e0440..000000000 --- a/spine-cpp/spine-cpp/include/spine/Atlas.h +++ /dev/null @@ -1,174 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef SPINE_ATLAS_H_ -#define SPINE_ATLAS_H_ - -#include - -#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/*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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/AtlasAttachmentLoader.h b/spine-cpp/spine-cpp/include/spine/AtlasAttachmentLoader.h deleted file mode 100644 index 6b9ed688e..000000000 --- a/spine-cpp/spine-cpp/include/spine/AtlasAttachmentLoader.h +++ /dev/null @@ -1,58 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef SPINE_ATLASATTACHMENTLOADER_H_ -#define SPINE_ATLASATTACHMENTLOADER_H_ - -#include -#include -#include - -#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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/Attachment.h b/spine-cpp/spine-cpp/include/spine/Attachment.h deleted file mode 100644 index 286a8bec4..000000000 --- a/spine-cpp/spine-cpp/include/spine/Attachment.h +++ /dev/null @@ -1,83 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef SPINE_ATTACHMENT_H_ -#define SPINE_ATTACHMENT_H_ - -#include - -#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; - struct spAttachmentLoader* attachmentLoader; - -#ifdef __cplusplus - spAttachment() : - name(0), - type(SP_ATTACHMENT_REGION), - vtable(0) { - } -#endif -} spAttachment; - -void spAttachment_dispose (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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/AttachmentLoader.h b/spine-cpp/spine-cpp/include/spine/AttachmentLoader.h deleted file mode 100644 index f0f556553..000000000 --- a/spine-cpp/spine-cpp/include/spine/AttachmentLoader.h +++ /dev/null @@ -1,79 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef SPINE_ATTACHMENTLOADER_H_ -#define SPINE_ATTACHMENTLOADER_H_ - -#include -#include -#include - -#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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/Bone.h b/spine-cpp/spine-cpp/include/spine/Bone.h deleted file mode 100644 index 12b2af928..000000000 --- a/spine-cpp/spine-cpp/include/spine/Bone.h +++ /dev/null @@ -1,127 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef SPINE_BONE_H_ -#define SPINE_BONE_H_ - -#include -#include - -#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; - -#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) { - } -#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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/BoneData.h b/spine-cpp/spine-cpp/include/spine/BoneData.h deleted file mode 100644 index d73162b2b..000000000 --- a/spine-cpp/spine-cpp/include/spine/BoneData.h +++ /dev/null @@ -1,85 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef SPINE_BONEDATA_H_ -#define SPINE_BONEDATA_H_ - -#include - -#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; - -#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) { - } -#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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/BoundingBoxAttachment.h b/spine-cpp/spine-cpp/include/spine/BoundingBoxAttachment.h deleted file mode 100644 index 2c9194b69..000000000 --- a/spine-cpp/spine-cpp/include/spine/BoundingBoxAttachment.h +++ /dev/null @@ -1,59 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef SPINE_BOUNDINGBOXATTACHMENT_H_ -#define SPINE_BOUNDINGBOXATTACHMENT_H_ - -#include -#include -#include -#include -#include - -#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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/ClippingAttachment.h b/spine-cpp/spine-cpp/include/spine/ClippingAttachment.h deleted file mode 100644 index 8683437c7..000000000 --- a/spine-cpp/spine-cpp/include/spine/ClippingAttachment.h +++ /dev/null @@ -1,61 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef SPINE_CLIPPINGATTACHMENT_H_ -#define SPINE_CLIPPINGATTACHMENT_H_ - -#include -#include -#include -#include -#include - -#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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/Color.h b/spine-cpp/spine-cpp/include/spine/Color.h deleted file mode 100644 index 272ba9552..000000000 --- a/spine-cpp/spine-cpp/include/spine/Color.h +++ /dev/null @@ -1,78 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef SPINE_COLOR_H_ -#define SPINE_COLOR_H_ - -#include - -#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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/Event.h b/spine-cpp/spine-cpp/include/spine/Event.h deleted file mode 100644 index c92b713de..000000000 --- a/spine-cpp/spine-cpp/include/spine/Event.h +++ /dev/null @@ -1,72 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef SPINE_EVENT_H_ -#define SPINE_EVENT_H_ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct spEvent { - spEventData* const data; - float const time; - int intValue; - float floatValue; - const char* stringValue; - -#ifdef __cplusplus - spEvent() : - data(0), - time(0), - intValue(0), - floatValue(0), - stringValue(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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/EventData.h b/spine-cpp/spine-cpp/include/spine/EventData.h deleted file mode 100644 index 70b955071..000000000 --- a/spine-cpp/spine-cpp/include/spine/EventData.h +++ /dev/null @@ -1,69 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef SPINE_EVENTDATA_H_ -#define SPINE_EVENTDATA_H_ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct spEventData { - const char* const name; - int intValue; - float floatValue; - const char* stringValue; - -#ifdef __cplusplus - spEventData() : - name(0), - intValue(0), - floatValue(0), - stringValue(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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/IkConstraint.h b/spine-cpp/spine-cpp/include/spine/IkConstraint.h deleted file mode 100644 index e5b0f7b72..000000000 --- a/spine-cpp/spine-cpp/include/spine/IkConstraint.h +++ /dev/null @@ -1,87 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef SPINE_IKCONSTRAINT_H_ -#define SPINE_IKCONSTRAINT_H_ - -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -struct spSkeleton; - -typedef struct spIkConstraint { - spIkConstraintData* const data; - - int bonesCount; - spBone** bones; - - spBone* target; - int bendDirection; - float mix; - -#ifdef __cplusplus - spIkConstraint() : - data(0), - bonesCount(0), - bones(0), - target(0), - bendDirection(0), - mix(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, float alpha); -SP_API void spIkConstraint_apply2 (spBone* parent, spBone* child, float targetX, float targetY, int bendDirection, 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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/IkConstraintData.h b/spine-cpp/spine-cpp/include/spine/IkConstraintData.h deleted file mode 100644 index fc3f3cc09..000000000 --- a/spine-cpp/spine-cpp/include/spine/IkConstraintData.h +++ /dev/null @@ -1,76 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef SPINE_IKCONSTRAINTDATA_H_ -#define SPINE_IKCONSTRAINTDATA_H_ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct spIkConstraintData { - const char* const name; - int order; - int bonesCount; - spBoneData** bones; - - spBoneData* target; - int bendDirection; - float mix; - -#ifdef __cplusplus - spIkConstraintData() : - name(0), - bonesCount(0), - bones(0), - target(0), - bendDirection(0), - mix(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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/MeshAttachment.h b/spine-cpp/spine-cpp/include/spine/MeshAttachment.h deleted file mode 100644 index 2876abfd5..000000000 --- a/spine-cpp/spine-cpp/include/spine/MeshAttachment.h +++ /dev/null @@ -1,91 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef SPINE_MESHATTACHMENT_H_ -#define SPINE_MESHATTACHMENT_H_ - -#include -#include -#include -#include -#include - -#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; - - const char* path; - - float* regionUVs; - float* uvs; - - int trianglesCount; - unsigned short* triangles; - - spColor color; - - int hullLength; - - spMeshAttachment* const parentMesh; - int/*bool*/inheritDeform; - - /* 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); - -#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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/PathAttachment.h b/spine-cpp/spine-cpp/include/spine/PathAttachment.h deleted file mode 100644 index a953924a1..000000000 --- a/spine-cpp/spine-cpp/include/spine/PathAttachment.h +++ /dev/null @@ -1,63 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef SPINE_PATHATTACHMENT_H_ -#define SPINE_PATHATTACHMENT_H_ - -#include -#include -#include -#include -#include - -#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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraint.h b/spine-cpp/spine-cpp/include/spine/PathConstraint.h deleted file mode 100644 index 9d0ec10be..000000000 --- a/spine-cpp/spine-cpp/include/spine/PathConstraint.h +++ /dev/null @@ -1,113 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef SPINE_PATHCONSTRAINT_H_ -#define SPINE_PATHCONSTRAINT_H_ - -#include -#include -#include -#include -#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]; - -#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) { - } -#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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraintData.h b/spine-cpp/spine-cpp/include/spine/PathConstraintData.h deleted file mode 100644 index 5a24cc37f..000000000 --- a/spine-cpp/spine-cpp/include/spine/PathConstraintData.h +++ /dev/null @@ -1,97 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef SPINE_PATHCONSTRAINTDATA_H_ -#define SPINE_PATHCONSTRAINTDATA_H_ - -#include -#include -#include - -#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 bonesCount; - spBoneData** const bones; - spSlotData* target; - spPositionMode positionMode; - spSpacingMode spacingMode; - spRotateMode rotateMode; - float offsetRotation; - float position, spacing, rotateMix, translateMix; - -#ifdef __cplusplus - spPathConstraintData() : - name(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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/PointAttachment.h b/spine-cpp/spine-cpp/include/spine/PointAttachment.h deleted file mode 100644 index da8df6cbb..000000000 --- a/spine-cpp/spine-cpp/include/spine/PointAttachment.h +++ /dev/null @@ -1,65 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef SPINE_POINTATTACHMENT_H_ -#define SPINE_POINTATTACHMENT_H_ - -#include -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct spPointAttachment { - spVertexAttachment 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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/RegionAttachment.h b/spine-cpp/spine-cpp/include/spine/RegionAttachment.h deleted file mode 100644 index 9e23d5bdf..000000000 --- a/spine-cpp/spine-cpp/include/spine/RegionAttachment.h +++ /dev/null @@ -1,75 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef SPINE_REGIONATTACHMENT_H_ -#define SPINE_REGIONATTACHMENT_H_ - -#include -#include -#include -#include - -#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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/Skeleton.h b/spine-cpp/spine-cpp/include/spine/Skeleton.h deleted file mode 100644 index 0df9fe076..000000000 --- a/spine-cpp/spine-cpp/include/spine/Skeleton.h +++ /dev/null @@ -1,174 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef SPINE_SKELETON_H_ -#define SPINE_SKELETON_H_ - -#include -#include -#include -#include -#include -#include -#include - -#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; - int/*bool*/flipX, flipY; - 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), - flipX(0), - flipY(0), - 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_*/ diff --git a/spine-cpp/spine-cpp/include/spine/SkeletonBinary.h b/spine-cpp/spine-cpp/include/spine/SkeletonBinary.h deleted file mode 100644 index 3d96a1da9..000000000 --- a/spine-cpp/spine-cpp/include/spine/SkeletonBinary.h +++ /dev/null @@ -1,72 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef SPINE_SKELETONBINARY_H_ -#define SPINE_SKELETONBINARY_H_ - -#include -#include -#include -#include -#include - -#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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/SkeletonBounds.h b/spine-cpp/spine-cpp/include/spine/SkeletonBounds.h deleted file mode 100644 index da435c0a7..000000000 --- a/spine-cpp/spine-cpp/include/spine/SkeletonBounds.h +++ /dev/null @@ -1,113 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef SPINE_SKELETONBOUNDS_H_ -#define SPINE_SKELETONBOUNDS_H_ - -#include -#include -#include - -#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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/SkeletonClipping.h b/spine-cpp/spine-cpp/include/spine/SkeletonClipping.h deleted file mode 100644 index 74f21fccb..000000000 --- a/spine-cpp/spine-cpp/include/spine/SkeletonClipping.h +++ /dev/null @@ -1,68 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef SPINE_SKELETONCLIPPING_H -#define SPINE_SKELETONCLIPPING_H - -#include -#include -#include -#include -#include - -#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 */ diff --git a/spine-cpp/spine-cpp/include/spine/SkeletonData.h b/spine-cpp/spine-cpp/include/spine/SkeletonData.h deleted file mode 100644 index 5cbf3e1d4..000000000 --- a/spine-cpp/spine-cpp/include/spine/SkeletonData.h +++ /dev/null @@ -1,117 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef SPINE_SKELETONDATA_H_ -#define SPINE_SKELETONDATA_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct spSkeletonData { - const char* version; - const char* hash; - float width, height; - - 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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/SkeletonJson.h b/spine-cpp/spine-cpp/include/spine/SkeletonJson.h deleted file mode 100644 index 96f1b86ec..000000000 --- a/spine-cpp/spine-cpp/include/spine/SkeletonJson.h +++ /dev/null @@ -1,73 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef SPINE_SKELETONJSON_H_ -#define SPINE_SKELETONJSON_H_ - -#include -#include -#include -#include -#include -#include - -#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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/Skin.h b/spine-cpp/spine-cpp/include/spine/Skin.h deleted file mode 100644 index 806cde877..000000000 --- a/spine-cpp/spine-cpp/include/spine/Skin.h +++ /dev/null @@ -1,95 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef SPINE_SKIN_H_ -#define SPINE_SKIN_H_ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -struct spSkeleton; - -typedef struct spSkin { - const char* const name; - -#ifdef __cplusplus - spSkin() : - name(0) { - } -#endif -} spSkin; - -/* Private structs, needed by Skeleton */ -typedef struct _Entry _Entry; -struct _Entry { - int slotIndex; - const char* name; - spAttachment* attachment; - _Entry* next; -}; - -typedef struct { - spSkin super; - _Entry* entries; -} _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_addAttachment (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); - -#ifdef SPINE_SHORT_NAMES -typedef spSkin Skin; -#define Skin_create(...) spSkin_create(__VA_ARGS__) -#define Skin_dispose(...) spSkin_dispose(__VA_ARGS__) -#define Skin_addAttachment(...) 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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/Slot.h b/spine-cpp/spine-cpp/include/spine/Slot.h deleted file mode 100644 index 04647689a..000000000 --- a/spine-cpp/spine-cpp/include/spine/Slot.h +++ /dev/null @@ -1,93 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef SPINE_SLOT_H_ -#define SPINE_SLOT_H_ - -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct spSlot { - spSlotData* const data; - spBone* const bone; - spColor color; - spColor* darkColor; - spAttachment* const attachment; - - int attachmentVerticesCapacity; - int attachmentVerticesCount; - float* attachmentVertices; - -#ifdef __cplusplus - spSlot() : - data(0), - bone(0), - color(), - darkColor(0), - attachment(0), - attachmentVerticesCapacity(0), - attachmentVerticesCount(0), - attachmentVertices(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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/SlotData.h b/spine-cpp/spine-cpp/include/spine/SlotData.h deleted file mode 100644 index 1e12da61a..000000000 --- a/spine-cpp/spine-cpp/include/spine/SlotData.h +++ /dev/null @@ -1,90 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef SPINE_SLOTDATA_H_ -#define SPINE_SLOTDATA_H_ - -#include -#include -#include - -#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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/TransformConstraint.h b/spine-cpp/spine-cpp/include/spine/TransformConstraint.h deleted file mode 100644 index 07721cf14..000000000 --- a/spine-cpp/spine-cpp/include/spine/TransformConstraint.h +++ /dev/null @@ -1,81 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef SPINE_TRANSFORMCONSTRAINT_H_ -#define SPINE_TRANSFORMCONSTRAINT_H_ - -#include -#include -#include - -#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; - -#ifdef __cplusplus - spTransformConstraint() : - data(0), - bonesCount(0), - bones(0), - target(0), - rotateMix(0), - translateMix(0), - scaleMix(0), - shearMix(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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h b/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h deleted file mode 100644 index 8e6c33ff7..000000000 --- a/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h +++ /dev/null @@ -1,87 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef SPINE_TRANSFORMCONSTRAINTDATA_H_ -#define SPINE_TRANSFORMCONSTRAINTDATA_H_ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct spTransformConstraintData { - const char* const name; - int order; - 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), - 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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/Triangulator.h b/spine-cpp/spine-cpp/include/spine/Triangulator.h deleted file mode 100644 index 69863b2f7..000000000 --- a/spine-cpp/spine-cpp/include/spine/Triangulator.h +++ /dev/null @@ -1,63 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef SPINE_TRIANGULATOR_H -#define SPINE_TRIANGULATOR_H - -#include -#include - -#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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/VertexAttachment.h b/spine-cpp/spine-cpp/include/spine/VertexAttachment.h deleted file mode 100644 index 7d232cc6e..000000000 --- a/spine-cpp/spine-cpp/include/spine/VertexAttachment.h +++ /dev/null @@ -1,68 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef SPINE_VERTEXATTACHMENT_H_ -#define SPINE_VERTEXATTACHMENT_H_ - -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct spVertexAttachment spVertexAttachment; -struct spVertexAttachment { - spAttachment super; - - int bonesCount; - int* bones; - - int verticesCount; - float* vertices; - - int worldVerticesLength; - - int id; -}; - -SP_API void spVertexAttachment_computeWorldVertices (spVertexAttachment* self, spSlot* slot, int start, int count, float* worldVertices, int offset, int stride); - -#ifdef SPINE_SHORT_NAMES -typedef spVertexAttachment VertexAttachment; -#define VertexAttachment_computeWorldVertices(...) spVertexAttachment_computeWorldVertices(__VA_ARGS__) -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* SPINE_VERTEXATTACHMENT_H_ */ diff --git a/spine-cpp/spine-cpp/include/spine/VertexEffect.h b/spine-cpp/spine-cpp/include/spine/VertexEffect.h deleted file mode 100644 index 4f670119b..000000000 --- a/spine-cpp/spine-cpp/include/spine/VertexEffect.h +++ /dev/null @@ -1,85 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef SPINE_VERTEXEFFECT_H_ -#define SPINE_VERTEXEFFECT_H_ - -#include -#include -#include - -#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_ */ diff --git a/spine-cpp/spine-cpp/include/spine/dll.h b/spine-cpp/spine-cpp/include/spine/dll.h deleted file mode 100644 index 02714ca45..000000000 --- a/spine-cpp/spine-cpp/include/spine/dll.h +++ /dev/null @@ -1,48 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, 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 - #define DLLIMPORT - #define DLLEXPORT -#endif - -#ifdef SPINEPLUGIN_API - #define SP_API SPINEPLUGIN_API -#else - #define SP_API -#endif - -#endif /* SPINE_SHAREDLIB_H */ diff --git a/spine-cpp/spine-cpp/include/spine/extension.h b/spine-cpp/spine-cpp/include/spine/extension.h deleted file mode 100644 index 0823b5667..000000000 --- a/spine-cpp/spine-cpp/include/spine/extension.h +++ /dev/null @@ -1,318 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, 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_ - -/* 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 PI 3.1415926535897932385f -#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: (A) > 0 ? 1 : 0) - -#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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#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 (); - -void _spSetMalloc (void* (*_malloc) (size_t size)); -void _spSetDebugMalloc (void* (*_malloc) (size_t size, const char* file, int line)); -void _spSetRealloc(void* (*_realloc) (void* ptr, size_t size)); -void _spSetFree (void (*_free) (void* ptr)); -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)); -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, spMixPose pose, 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, spMixPose pose, 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 - -#endif /* SPINE_EXTENSION_H_ */ diff --git a/spine-cpp/spine-cpp/include/spine/spine.h b/spine-cpp/spine-cpp/include/spine/spine.h deleted file mode 100644 index 5085ed8e3..000000000 --- a/spine-cpp/spine-cpp/include/spine/spine.h +++ /dev/null @@ -1,63 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef SPINE_SPINE_H_ -#define SPINE_SPINE_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#endif /* SPINE_SPINE_H_ */ diff --git a/spine-cpp/spine-cpp/src/spine/Animation.c b/spine-cpp/spine-cpp/src/spine/Animation.c deleted file mode 100644 index 0c2c7194f..000000000 --- a/spine-cpp/spine-cpp/src/spine/Animation.c +++ /dev/null @@ -1,1529 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#include -#include -#include -#include - -spAnimation* spAnimation_create (const char* name, int timelinesCount) { - spAnimation* self = NEW(spAnimation); - MALLOC_STR(self->name, name); - self->timelinesCount = timelinesCount; - self->timelines = MALLOC(spTimeline*, timelinesCount); - return self; -} - -void spAnimation_dispose (spAnimation* self) { - int i; - for (i = 0; i < self->timelinesCount; ++i) - spTimeline_dispose(self->timelines[i]); - FREE(self->timelines); - FREE(self->name); - FREE(self); -} - -void spAnimation_apply (const spAnimation* self, spSkeleton* skeleton, float lastTime, float time, int loop, spEvent** events, - int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) { - int i, n = self->timelinesCount; - - if (loop && self->duration) { - time = FMOD(time, self->duration); - if (lastTime > 0) lastTime = FMOD(lastTime, self->duration); - } - - for (i = 0; i < n; ++i) - spTimeline_apply(self->timelines[i], skeleton, lastTime, time, events, eventsCount, alpha, pose, direction); -} - -/**/ - -typedef struct _spTimelineVtable { - void (*apply) (const spTimeline* self, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents, - int* eventsCount, float alpha, spMixPose pose, spMixDirection direction); - int (*getPropertyId) (const spTimeline* self); - void (*dispose) (spTimeline* self); -} _spTimelineVtable; - -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, spMixPose pose, spMixDirection direction), - int (*getPropertyId) (const spTimeline* self)) { - CONST_CAST(spTimelineType, self->type) = type; - CONST_CAST(_spTimelineVtable*, self->vtable) = NEW(_spTimelineVtable); - VTABLE(spTimeline, self)->dispose = dispose; - VTABLE(spTimeline, self)->apply = apply; - VTABLE(spTimeline, self)->getPropertyId = getPropertyId; -} - -void _spTimeline_deinit (spTimeline* self) { - FREE(self->vtable); -} - -void spTimeline_dispose (spTimeline* self) { - VTABLE(spTimeline, self)->dispose(self); -} - -void spTimeline_apply (const spTimeline* self, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents, - int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) { - VTABLE(spTimeline, self)->apply(self, skeleton, lastTime, time, firedEvents, eventsCount, alpha, pose, direction); -} - -int spTimeline_getPropertyId (const spTimeline* self) { - return VTABLE(spTimeline, self)->getPropertyId(self); -} - -/**/ - -static const float CURVE_LINEAR = 0, CURVE_STEPPED = 1, CURVE_BEZIER = 2; -static const int BEZIER_SIZE = 10 * 2 - 1; - -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, spMixPose pose, spMixDirection direction), - int (*getPropertyId)(const spTimeline* self)) { - _spTimeline_init(SUPER(self), type, dispose, apply, getPropertyId); - self->curves = CALLOC(float, (framesCount - 1) * BEZIER_SIZE); -} - -void _spCurveTimeline_deinit (spCurveTimeline* self) { - _spTimeline_deinit(SUPER(self)); - FREE(self->curves); -} - -void spCurveTimeline_setLinear (spCurveTimeline* self, int frameIndex) { - self->curves[frameIndex * BEZIER_SIZE] = CURVE_LINEAR; -} - -void spCurveTimeline_setStepped (spCurveTimeline* self, int frameIndex) { - self->curves[frameIndex * BEZIER_SIZE] = CURVE_STEPPED; -} - -void spCurveTimeline_setCurve (spCurveTimeline* self, int frameIndex, float cx1, float cy1, float cx2, float cy2) { - float tmpx = (-cx1 * 2 + cx2) * 0.03f, tmpy = (-cy1 * 2 + cy2) * 0.03f; - float dddfx = ((cx1 - cx2) * 3 + 1) * 0.006f, dddfy = ((cy1 - cy2) * 3 + 1) * 0.006f; - float ddfx = tmpx * 2 + dddfx, ddfy = tmpy * 2 + dddfy; - float dfx = cx1 * 0.3f + tmpx + dddfx * 0.16666667f, dfy = cy1 * 0.3f + tmpy + dddfy * 0.16666667f; - float x = dfx, y = dfy; - - int i = frameIndex * BEZIER_SIZE, n = i + BEZIER_SIZE - 1; - self->curves[i++] = CURVE_BEZIER; - - for (; i < n; i += 2) { - self->curves[i] = x; - self->curves[i + 1] = y; - dfx += ddfx; - dfy += ddfy; - ddfx += dddfx; - ddfy += dddfy; - x += dfx; - y += dfy; - } -} - -float spCurveTimeline_getCurvePercent (const spCurveTimeline* self, int frameIndex, float percent) { - float x, y; - int i = frameIndex * BEZIER_SIZE, start, n; - float type = self->curves[i]; - percent = CLAMP(percent, 0, 1); - if (type == CURVE_LINEAR) return percent; - if (type == CURVE_STEPPED) return 0; - i++; - x = 0; - for (start = i, n = i + BEZIER_SIZE - 1; i < n; i += 2) { - x = self->curves[i]; - if (x >= percent) { - float prevX, prevY; - if (i == start) { - prevX = 0; - prevY = 0; - } else { - prevX = self->curves[i - 2]; - prevY = self->curves[i - 1]; - } - return prevY + (self->curves[i + 1] - prevY) * (percent - prevX) / (x - prevX); - } - } - y = self->curves[i - 1]; - return y + (1 - y) * (percent - x) / (1 - x); /* Last point is 1,1. */ -} - -/* @param target After the first and before the last entry. */ -static int binarySearch (float *values, int valuesLength, float target, int step) { - int low = 0, current; - int high = valuesLength / step - 2; - if (high == 0) return step; - current = high >> 1; - while (1) { - if (values[(current + 1) * step] <= target) - low = current + 1; - else - high = current; - if (low == high) return (low + 1) * step; - current = (low + high) >> 1; - } - return 0; -} - -int _spCurveTimeline_binarySearch (float *values, int valuesLength, float target, int step) { - return binarySearch(values, valuesLength, target, step); -} - -/* @param target After the first and before the last entry. */ -static int binarySearch1 (float *values, int valuesLength, float target) { - int low = 0, current; - int high = valuesLength - 2; - if (high == 0) return 1; - current = high >> 1; - while (1) { - if (values[(current + 1)] <= target) - low = current + 1; - else - high = current; - if (low == high) return low + 1; - current = (low + high) >> 1; - } - return 0; -} - -/**/ - -void _spBaseTimeline_dispose (spTimeline* timeline) { - struct spBaseTimeline* self = SUB_CAST(struct spBaseTimeline, timeline); - _spCurveTimeline_deinit(SUPER(self)); - FREE(self->frames); - FREE(self); -} - -/* Many timelines have structure identical to struct spBaseTimeline and extend spCurveTimeline. **/ -struct spBaseTimeline* _spBaseTimeline_create (int framesCount, spTimelineType type, int frameSize, /**/ - void (*apply) (const spTimeline* self, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents, - int* eventsCount, float alpha, spMixPose pose, spMixDirection direction), - int (*getPropertyId) (const spTimeline* self)) { - struct spBaseTimeline* self = NEW(struct spBaseTimeline); - _spCurveTimeline_init(SUPER(self), type, framesCount, _spBaseTimeline_dispose, apply, getPropertyId); - - CONST_CAST(int, self->framesCount) = framesCount * frameSize; - CONST_CAST(float*, self->frames) = CALLOC(float, self->framesCount); - - return self; -} - -/**/ - -void _spRotateTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents, - int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) { - spBone *bone; - int frame; - float prevRotation, frameTime, percent, r; - - spRotateTimeline* self = SUB_CAST(spRotateTimeline, timeline); - - bone = skeleton->bones[self->boneIndex]; - if (time < self->frames[0]) { - switch (pose) { - case SP_MIX_POSE_SETUP: - bone->rotation = bone->data->rotation; - return; - case SP_MIX_POSE_CURRENT: - case SP_MIX_POSE_CURRENT_LAYERED: /* to appease compiler */ - r = bone->data->rotation - bone->rotation; - r -= (16384 - (int)(16384.499999999996 - r / 360)) * 360; - bone->rotation += r * alpha; - } - return; - } - - if (time >= self->frames[self->framesCount - ROTATE_ENTRIES]) { /* Time is after last frame. */ - if (pose == SP_MIX_POSE_SETUP) - bone->rotation = bone->data->rotation + self->frames[self->framesCount + ROTATE_PREV_ROTATION] * alpha; - else { - r = bone->data->rotation + self->frames[self->framesCount + ROTATE_PREV_ROTATION] - bone->rotation; - r -= (16384 - (int)(16384.499999999996 - r / 360)) * 360; /* Wrap within -180 and 180. */ - bone->rotation += r * alpha; - } - return; - } - - /* Interpolate between the previous frame and the current frame. */ - frame = binarySearch(self->frames, self->framesCount, time, ROTATE_ENTRIES); - prevRotation = self->frames[frame + ROTATE_PREV_ROTATION]; - frameTime = self->frames[frame]; - percent = spCurveTimeline_getCurvePercent(SUPER(self), (frame >> 1) - 1, 1 - (time - frameTime) / (self->frames[frame + ROTATE_PREV_TIME] - frameTime)); - - r = self->frames[frame + ROTATE_ROTATION] - prevRotation; - r -= (16384 - (int)(16384.499999999996 - r / 360)) * 360; - r = prevRotation + r * percent; - if (pose == SP_MIX_POSE_SETUP) { - r -= (16384 - (int)(16384.499999999996 - r / 360)) * 360; - bone->rotation = bone->data->rotation + r * alpha; - } else { - r = bone->data->rotation + r - bone->rotation; - r -= (16384 - (int)(16384.499999999996 - r / 360)) * 360; - bone->rotation += r * alpha; - } - - UNUSED(lastTime); - UNUSED(firedEvents); - UNUSED(eventsCount); -} - -int _spRotateTimeline_getPropertyId (const spTimeline* timeline) { - return (SP_TIMELINE_ROTATE << 25) + SUB_CAST(spRotateTimeline, timeline)->boneIndex; -} - -spRotateTimeline* spRotateTimeline_create (int framesCount) { - return _spBaseTimeline_create(framesCount, SP_TIMELINE_ROTATE, ROTATE_ENTRIES, _spRotateTimeline_apply, _spRotateTimeline_getPropertyId); -} - -void spRotateTimeline_setFrame (spRotateTimeline* self, int frameIndex, float time, float degrees) { - frameIndex <<= 1; - self->frames[frameIndex] = time; - self->frames[frameIndex + ROTATE_ROTATION] = degrees; -} - -/**/ - -static const int TRANSLATE_PREV_TIME = -3, TRANSLATE_PREV_X = -2, TRANSLATE_PREV_Y = -1; -static const int TRANSLATE_X = 1, TRANSLATE_Y = 2; - -void _spTranslateTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, - spEvent** firedEvents, int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) { - spBone *bone; - int frame; - float frameTime, percent; - float x, y; - float *frames; - int framesCount; - - spTranslateTimeline* self = SUB_CAST(spTranslateTimeline, timeline); - - bone = skeleton->bones[self->boneIndex]; - if (time < self->frames[0]) { - switch (pose) { - case SP_MIX_POSE_SETUP: - bone->x = bone->data->x; - bone->y = bone->data->y; - return; - case SP_MIX_POSE_CURRENT: - case SP_MIX_POSE_CURRENT_LAYERED: /* to appease compiler */ - bone->x += (bone->data->x - bone->x) * alpha; - bone->y += (bone->data->y - bone->y) * alpha; - } - return; - } - - frames = self->frames; - framesCount = self->framesCount; - if (time >= frames[framesCount - TRANSLATE_ENTRIES]) { /* Time is after last frame. */ - x = frames[framesCount + TRANSLATE_PREV_X]; - y = frames[framesCount + TRANSLATE_PREV_Y]; - } else { - /* Interpolate between the previous frame and the current frame. */ - frame = binarySearch(frames, framesCount, time, TRANSLATE_ENTRIES); - x = frames[frame + TRANSLATE_PREV_X]; - y = frames[frame + TRANSLATE_PREV_Y]; - frameTime = frames[frame]; - percent = spCurveTimeline_getCurvePercent(SUPER(self), frame / TRANSLATE_ENTRIES - 1, - 1 - (time - frameTime) / (frames[frame + TRANSLATE_PREV_TIME] - frameTime)); - - x += (frames[frame + TRANSLATE_X] - x) * percent; - y += (frames[frame + TRANSLATE_Y] - y) * percent; - } - if (pose == SP_MIX_POSE_SETUP) { - bone->x = bone->data->x + x * alpha; - bone->y = bone->data->y + y * alpha; - } else { - bone->x += (bone->data->x + x - bone->x) * alpha; - bone->y += (bone->data->y + y - bone->y) * alpha; - } - - UNUSED(lastTime); - UNUSED(firedEvents); - UNUSED(eventsCount); -} - -int _spTranslateTimeline_getPropertyId (const spTimeline* self) { - return (SP_TIMELINE_TRANSLATE << 24) + SUB_CAST(spTranslateTimeline, self)->boneIndex; -} - -spTranslateTimeline* spTranslateTimeline_create (int framesCount) { - return _spBaseTimeline_create(framesCount, SP_TIMELINE_TRANSLATE, TRANSLATE_ENTRIES, _spTranslateTimeline_apply, _spTranslateTimeline_getPropertyId); -} - -void spTranslateTimeline_setFrame (spTranslateTimeline* self, int frameIndex, float time, float x, float y) { - frameIndex *= TRANSLATE_ENTRIES; - self->frames[frameIndex] = time; - self->frames[frameIndex + TRANSLATE_X] = x; - self->frames[frameIndex + TRANSLATE_Y] = y; -} - -/**/ - -void _spScaleTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents, - int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) { - spBone *bone; - int frame; - float frameTime, percent, x, y; - float *frames; - int framesCount; - - spScaleTimeline* self = SUB_CAST(spScaleTimeline, timeline); - - bone = skeleton->bones[self->boneIndex]; - if (time < self->frames[0]) { - switch (pose) { - case SP_MIX_POSE_SETUP: - bone->scaleX = bone->data->scaleX; - bone->scaleY = bone->data->scaleY; - return; - case SP_MIX_POSE_CURRENT: - case SP_MIX_POSE_CURRENT_LAYERED: /* to appease compiler */ - bone->scaleX += (bone->data->scaleX - bone->scaleX) * alpha; - bone->scaleY += (bone->data->scaleY - bone->scaleY) * alpha; - } - return; - } - - frames = self->frames; - framesCount = self->framesCount; - if (time >= frames[framesCount - TRANSLATE_ENTRIES]) { /* Time is after last frame. */ - x = frames[framesCount + TRANSLATE_PREV_X] * bone->data->scaleX; - y = frames[framesCount + TRANSLATE_PREV_Y] * bone->data->scaleY; - } else { - /* Interpolate between the previous frame and the current frame. */ - frame = binarySearch(frames, framesCount, time, TRANSLATE_ENTRIES); - x = frames[frame + TRANSLATE_PREV_X]; - y = frames[frame + TRANSLATE_PREV_Y]; - frameTime = frames[frame]; - percent = spCurveTimeline_getCurvePercent(SUPER(self), frame / TRANSLATE_ENTRIES - 1, - 1 - (time - frameTime) / (frames[frame + TRANSLATE_PREV_TIME] - frameTime)); - - x = (x + (frames[frame + TRANSLATE_X] - x) * percent) * bone->data->scaleX; - y = (y + (frames[frame + TRANSLATE_Y] - y) * percent) * bone->data->scaleY; - } - if (alpha == 1) { - bone->scaleX = x; - bone->scaleY = y; - } else { - float bx, by; - if (pose == SP_MIX_POSE_SETUP) { - bx = bone->data->scaleX; - by = bone->data->scaleY; - } else { - bx = bone->scaleX; - by = bone->scaleY; - } - /* Mixing out uses sign of setup or current pose, else use sign of key. */ - if (direction == SP_MIX_DIRECTION_OUT) { - x = ABS(x) * SIGNUM(bx); - y = ABS(y) * SIGNUM(by); - } else { - bx = ABS(bx) * SIGNUM(x); - by = ABS(by) * SIGNUM(y); - } - bone->scaleX = bx + (x - bx) * alpha; - bone->scaleY = by + (y - by) * alpha; - } - - UNUSED(lastTime); - UNUSED(firedEvents); - UNUSED(eventsCount); -} - -int _spScaleTimeline_getPropertyId (const spTimeline* timeline) { - return (SP_TIMELINE_SCALE << 24) + SUB_CAST(spScaleTimeline, timeline)->boneIndex; -} - -spScaleTimeline* spScaleTimeline_create (int framesCount) { - return _spBaseTimeline_create(framesCount, SP_TIMELINE_SCALE, TRANSLATE_ENTRIES, _spScaleTimeline_apply, _spScaleTimeline_getPropertyId); -} - -void spScaleTimeline_setFrame (spScaleTimeline* self, int frameIndex, float time, float x, float y) { - spTranslateTimeline_setFrame(self, frameIndex, time, x, y); -} - -/**/ - -void _spShearTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents, - int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) { - spBone *bone; - int frame; - float frameTime, percent, x, y; - float *frames; - int framesCount; - - spShearTimeline* self = SUB_CAST(spShearTimeline, timeline); - - bone = skeleton->bones[self->boneIndex]; - frames = self->frames; - framesCount = self->framesCount; - if (time < self->frames[0]) { - switch (pose) { - case SP_MIX_POSE_SETUP: - bone->shearX = bone->data->shearX; - bone->shearY = bone->data->shearY; - return; - case SP_MIX_POSE_CURRENT: - case SP_MIX_POSE_CURRENT_LAYERED: /* to appease compiler */ - bone->shearX += (bone->data->shearX - bone->shearX) * alpha; - bone->shearY += (bone->data->shearY - bone->shearY) * alpha; - } - return; - } - - if (time >= frames[framesCount - TRANSLATE_ENTRIES]) { /* Time is after last frame. */ - x = frames[framesCount + TRANSLATE_PREV_X]; - y = frames[framesCount + TRANSLATE_PREV_Y]; - } else { - /* Interpolate between the previous frame and the current frame. */ - frame = binarySearch(frames, framesCount, time, TRANSLATE_ENTRIES); - x = frames[frame + TRANSLATE_PREV_X]; - y = frames[frame + TRANSLATE_PREV_Y]; - frameTime = frames[frame]; - percent = spCurveTimeline_getCurvePercent(SUPER(self), frame / TRANSLATE_ENTRIES - 1, - 1 - (time - frameTime) / (frames[frame + TRANSLATE_PREV_TIME] - frameTime)); - - x = x + (frames[frame + TRANSLATE_X] - x) * percent; - y = y + (frames[frame + TRANSLATE_Y] - y) * percent; - } - if (pose == SP_MIX_POSE_SETUP) { - bone->shearX = bone->data->shearX + x * alpha; - bone->shearY = bone->data->shearY + y * alpha; - } else { - bone->shearX += (bone->data->shearX + x - bone->shearX) * alpha; - bone->shearY += (bone->data->shearY + y - bone->shearY) * alpha; - } - - UNUSED(lastTime); - UNUSED(firedEvents); - UNUSED(eventsCount); -} - -int _spShearTimeline_getPropertyId (const spTimeline* timeline) { - return (SP_TIMELINE_SHEAR << 24) + SUB_CAST(spShearTimeline, timeline)->boneIndex; -} - -spShearTimeline* spShearTimeline_create (int framesCount) { - return (spShearTimeline*)_spBaseTimeline_create(framesCount, SP_TIMELINE_SHEAR, 3, _spShearTimeline_apply, _spShearTimeline_getPropertyId); -} - -void spShearTimeline_setFrame (spShearTimeline* self, int frameIndex, float time, float x, float y) { - spTranslateTimeline_setFrame(self, frameIndex, time, x, y); -} - -/**/ - -static const int COLOR_PREV_TIME = -5, COLOR_PREV_R = -4, COLOR_PREV_G = -3, COLOR_PREV_B = -2, COLOR_PREV_A = -1; -static const int COLOR_R = 1, COLOR_G = 2, COLOR_B = 3, COLOR_A = 4; - -void _spColorTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents, - int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) { - spSlot *slot; - int frame; - float percent, frameTime; - float r, g, b, a; - spColor* color; - spColor* setup; - spColorTimeline* self = (spColorTimeline*)timeline; - slot = skeleton->slots[self->slotIndex]; - - if (time < self->frames[0]) { - switch (pose) { - case SP_MIX_POSE_SETUP: - spColor_setFromColor(&slot->color, &slot->data->color); - return; - case SP_MIX_POSE_CURRENT: - case SP_MIX_POSE_CURRENT_LAYERED: /* to appease compiler */ - color = &slot->color; - setup = &slot->data->color; - spColor_addFloats(color, (setup->r - color->r) * alpha, (setup->g - color->g) * alpha, (setup->b - color->b) * alpha, - (setup->a - color->a) * alpha); - } - return; - } - - if (time >= self->frames[self->framesCount - 5]) { /* Time is after last frame */ - int i = self->framesCount; - r = self->frames[i + COLOR_PREV_R]; - g = self->frames[i + COLOR_PREV_G]; - b = self->frames[i + COLOR_PREV_B]; - a = self->frames[i + COLOR_PREV_A]; - } else { - /* Interpolate between the previous frame and the current frame. */ - frame = binarySearch(self->frames, self->framesCount, time, COLOR_ENTRIES); - - r = self->frames[frame + COLOR_PREV_R]; - g = self->frames[frame + COLOR_PREV_G]; - b = self->frames[frame + COLOR_PREV_B]; - a = self->frames[frame + COLOR_PREV_A]; - - frameTime = self->frames[frame]; - percent = spCurveTimeline_getCurvePercent(SUPER(self), frame / COLOR_ENTRIES - 1, - 1 - (time - frameTime) / (self->frames[frame + COLOR_PREV_TIME] - frameTime)); - - r += (self->frames[frame + COLOR_R] - r) * percent; - g += (self->frames[frame + COLOR_G] - g) * percent; - b += (self->frames[frame + COLOR_B] - b) * percent; - a += (self->frames[frame + COLOR_A] - a) * percent; - } - if (alpha == 1) { - spColor_setFromFloats(&slot->color, r, g, b, a); - } else { - if (pose == SP_MIX_POSE_SETUP) { - spColor_setFromColor(&slot->color, &slot->data->color); - } - spColor_addFloats(&slot->color, (r - slot->color.r) * alpha, (g - slot->color.g) * alpha, (b - slot->color.b) * alpha, (a - slot->color.a) * alpha); - } - - UNUSED(lastTime); - UNUSED(firedEvents); - UNUSED(eventsCount); -} - -int _spColorTimeline_getPropertyId (const spTimeline* timeline) { - return (SP_TIMELINE_COLOR << 24) + SUB_CAST(spColorTimeline, timeline)->slotIndex; -} - -spColorTimeline* spColorTimeline_create (int framesCount) { - return (spColorTimeline*)_spBaseTimeline_create(framesCount, SP_TIMELINE_COLOR, 5, _spColorTimeline_apply, _spColorTimeline_getPropertyId); -} - -void spColorTimeline_setFrame (spColorTimeline* self, int frameIndex, float time, float r, float g, float b, float a) { - frameIndex *= COLOR_ENTRIES; - self->frames[frameIndex] = time; - self->frames[frameIndex + COLOR_R] = r; - self->frames[frameIndex + COLOR_G] = g; - self->frames[frameIndex + COLOR_B] = b; - self->frames[frameIndex + COLOR_A] = a; -} - -/**/ - -static const int TWOCOLOR_PREV_TIME = -8, TWOCOLOR_PREV_R = -7, TWOCOLOR_PREV_G = -6, TWOCOLOR_PREV_B = -5, TWOCOLOR_PREV_A = -4; -static const int TWOCOLOR_PREV_R2 = -3, TWOCOLOR_PREV_G2 = -2, TWOCOLOR_PREV_B2 = -1; -static const int TWOCOLOR_R = 1, TWOCOLOR_G = 2, TWOCOLOR_B = 3, TWOCOLOR_A = 4, TWOCOLOR_R2 = 5, TWOCOLOR_G2 = 6, TWOCOLOR_B2 = 7; - -void _spTwoColorTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents, - int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) { - spSlot *slot; - int frame; - float percent, frameTime; - float r, g, b, a, r2, g2, b2; - spColor* light; - spColor* dark; - spColor* setupLight; - spColor* setupDark; - spColorTimeline* self = (spColorTimeline*)timeline; - slot = skeleton->slots[self->slotIndex]; - - if (time < self->frames[0]) { - switch (pose) { - case SP_MIX_POSE_SETUP: - spColor_setFromColor(&slot->color, &slot->data->color); - spColor_setFromColor(slot->darkColor, slot->data->darkColor); - return; - case SP_MIX_POSE_CURRENT: - case SP_MIX_POSE_CURRENT_LAYERED: /* to appease compiler */ - light = &slot->color; - dark = slot->darkColor; - setupLight = &slot->data->color; - setupDark = slot->data->darkColor; - spColor_addFloats(light, (setupLight->r - light->r) * alpha, (setupLight->g - light->g) * alpha, (setupLight->b - light->b) * alpha, - (setupLight->a - light->a) * alpha); - spColor_addFloats(dark, (setupDark->r - dark->r) * alpha, (setupDark->g - dark->g) * alpha, (setupDark->b - dark->b) * alpha, 0); - } - return; - } - - if (time >= self->frames[self->framesCount - TWOCOLOR_ENTRIES]) { /* Time is after last frame */ - int i = self->framesCount; - r = self->frames[i + TWOCOLOR_PREV_R]; - g = self->frames[i + TWOCOLOR_PREV_G]; - b = self->frames[i + TWOCOLOR_PREV_B]; - a = self->frames[i + TWOCOLOR_PREV_A]; - r2 = self->frames[i + TWOCOLOR_PREV_R2]; - g2 = self->frames[i + TWOCOLOR_PREV_G2]; - b2 = self->frames[i + TWOCOLOR_PREV_B2]; - } else { - /* Interpolate between the previous frame and the current frame. */ - frame = binarySearch(self->frames, self->framesCount, time, TWOCOLOR_ENTRIES); - - r = self->frames[frame + TWOCOLOR_PREV_R]; - g = self->frames[frame + TWOCOLOR_PREV_G]; - b = self->frames[frame + TWOCOLOR_PREV_B]; - a = self->frames[frame + TWOCOLOR_PREV_A]; - r2 = self->frames[frame + TWOCOLOR_PREV_R2]; - g2 = self->frames[frame + TWOCOLOR_PREV_G2]; - b2 = self->frames[frame + TWOCOLOR_PREV_B2]; - - frameTime = self->frames[frame]; - percent = spCurveTimeline_getCurvePercent(SUPER(self), frame / TWOCOLOR_ENTRIES - 1, - 1 - (time - frameTime) / (self->frames[frame + TWOCOLOR_PREV_TIME] - frameTime)); - - r += (self->frames[frame + TWOCOLOR_R] - r) * percent; - g += (self->frames[frame + TWOCOLOR_G] - g) * percent; - b += (self->frames[frame + TWOCOLOR_B] - b) * percent; - a += (self->frames[frame + TWOCOLOR_A] - a) * percent; - r2 += (self->frames[frame + TWOCOLOR_R2] - r2) * percent; - g2 += (self->frames[frame + TWOCOLOR_G2] - g2) * percent; - b2 += (self->frames[frame + TWOCOLOR_B2] - b2) * percent; - } - if (alpha == 1) { - spColor_setFromFloats(&slot->color, r, g, b, a); - spColor_setFromFloats(slot->darkColor, r2, g2, b2, 1); - } else { - light = &slot->color; - dark = slot->darkColor; - if (pose == SP_MIX_POSE_SETUP) { - spColor_setFromColor(light, &slot->data->color); - spColor_setFromColor(dark, slot->data->darkColor); - } - spColor_addFloats(light, (r - light->r) * alpha, (g - light->g) * alpha, (b - light->b) * alpha, (a - light->a) * alpha); - spColor_addFloats(dark, (r2 - dark->r) * alpha, (g2 - dark->g) * alpha, (b2 - dark->b) * alpha, 0); - } - - UNUSED(lastTime); - UNUSED(firedEvents); - UNUSED(eventsCount); -} - -int _spTwoColorTimeline_getPropertyId (const spTimeline* timeline) { - return (SP_TIMELINE_TWOCOLOR << 24) + SUB_CAST(spTwoColorTimeline, timeline)->slotIndex; -} - -spTwoColorTimeline* spTwoColorTimeline_create (int framesCount) { - return (spTwoColorTimeline*)_spBaseTimeline_create(framesCount, SP_TIMELINE_TWOCOLOR, TWOCOLOR_ENTRIES, _spTwoColorTimeline_apply, _spTwoColorTimeline_getPropertyId); -} - -void spTwoColorTimeline_setFrame (spTwoColorTimeline* self, int frameIndex, float time, float r, float g, float b, float a, float r2, float g2, float b2) { - frameIndex *= TWOCOLOR_ENTRIES; - self->frames[frameIndex] = time; - self->frames[frameIndex + TWOCOLOR_R] = r; - self->frames[frameIndex + TWOCOLOR_G] = g; - self->frames[frameIndex + TWOCOLOR_B] = b; - self->frames[frameIndex + TWOCOLOR_A] = a; - self->frames[frameIndex + TWOCOLOR_R2] = r2; - self->frames[frameIndex + TWOCOLOR_G2] = g2; - self->frames[frameIndex + TWOCOLOR_B2] = b2; -} - -/**/ - -void _spAttachmentTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, - spEvent** firedEvents, int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) { - const char* attachmentName; - spAttachmentTimeline* self = (spAttachmentTimeline*)timeline; - int frameIndex; - spSlot* slot = skeleton->slots[self->slotIndex]; - - if (direction == SP_MIX_DIRECTION_OUT && pose == SP_MIX_POSE_SETUP) { - const char* attachmentName = slot->data->attachmentName; - spSlot_setAttachment(slot, attachmentName ? spSkeleton_getAttachmentForSlotIndex(skeleton, self->slotIndex, attachmentName) : 0); - return; - } - - if (time < self->frames[0]) { - if (pose == SP_MIX_POSE_SETUP) { - attachmentName = slot->data->attachmentName; - spSlot_setAttachment(skeleton->slots[self->slotIndex], - attachmentName ? spSkeleton_getAttachmentForSlotIndex(skeleton, self->slotIndex, attachmentName) : 0); - } - return; - } - - if (time >= self->frames[self->framesCount - 1]) - frameIndex = self->framesCount - 1; - else - frameIndex = binarySearch1(self->frames, self->framesCount, time) - 1; - - attachmentName = self->attachmentNames[frameIndex]; - spSlot_setAttachment(skeleton->slots[self->slotIndex], - attachmentName ? spSkeleton_getAttachmentForSlotIndex(skeleton, self->slotIndex, attachmentName) : 0); - - UNUSED(lastTime); - UNUSED(firedEvents); - UNUSED(eventsCount); - UNUSED(alpha); -} - -int _spAttachmentTimeline_getPropertyId (const spTimeline* timeline) { - return (SP_TIMELINE_ATTACHMENT << 24) + SUB_CAST(spAttachmentTimeline, timeline)->slotIndex; -} - -void _spAttachmentTimeline_dispose (spTimeline* timeline) { - spAttachmentTimeline* self = SUB_CAST(spAttachmentTimeline, timeline); - int i; - - _spTimeline_deinit(timeline); - - for (i = 0; i < self->framesCount; ++i) - FREE(self->attachmentNames[i]); - FREE(self->attachmentNames); - FREE(self->frames); - FREE(self); -} - -spAttachmentTimeline* spAttachmentTimeline_create (int framesCount) { - spAttachmentTimeline* self = NEW(spAttachmentTimeline); - _spTimeline_init(SUPER(self), SP_TIMELINE_ATTACHMENT, _spAttachmentTimeline_dispose, _spAttachmentTimeline_apply, _spAttachmentTimeline_getPropertyId); - - CONST_CAST(int, self->framesCount) = framesCount; - CONST_CAST(float*, self->frames) = CALLOC(float, framesCount); - CONST_CAST(char**, self->attachmentNames) = CALLOC(char*, framesCount); - - return self; -} - -void spAttachmentTimeline_setFrame (spAttachmentTimeline* self, int frameIndex, float time, const char* attachmentName) { - self->frames[frameIndex] = time; - - FREE(self->attachmentNames[frameIndex]); - if (attachmentName) - MALLOC_STR(self->attachmentNames[frameIndex], attachmentName); - else - self->attachmentNames[frameIndex] = 0; -} - -/**/ - -void _spDeformTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents, - int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) { - int frame, i, vertexCount; - float percent, frameTime; - const float* prevVertices; - const float* nextVertices; - float* frames; - int framesCount; - const float** frameVertices; - float* vertices; - spDeformTimeline* self = (spDeformTimeline*)timeline; - - spSlot *slot = skeleton->slots[self->slotIndex]; - - if (slot->attachment != self->attachment) { - if (!slot->attachment) return; - switch (slot->attachment->type) { - case SP_ATTACHMENT_MESH: { - spMeshAttachment* mesh = SUB_CAST(spMeshAttachment, slot->attachment); - if (!mesh->inheritDeform || mesh->parentMesh != (void*)self->attachment) return; - break; - } - default: - return; - } - } - - frames = self->frames; - framesCount = self->framesCount; - vertexCount = self->frameVerticesCount; - if (slot->attachmentVerticesCount < vertexCount) { - if (slot->attachmentVerticesCapacity < vertexCount) { - FREE(slot->attachmentVertices); - slot->attachmentVertices = MALLOC(float, vertexCount); - slot->attachmentVerticesCapacity = vertexCount; - } - } - slot->attachmentVerticesCount = vertexCount; - - frameVertices = self->frameVertices; - vertices = slot->attachmentVertices; - - if (time < frames[0]) { /* Time is before first frame. */ - spVertexAttachment* vertexAttachment = SUB_CAST(spVertexAttachment, slot->attachment); - switch (pose) { - case SP_MIX_POSE_SETUP: - if (!vertexAttachment->bones) { - memcpy(vertices, vertexAttachment->vertices, vertexCount * sizeof(float)); - } else { - for (i = 0; i < vertexCount; i++) vertices[i] = 0; - } - return; - case SP_MIX_POSE_CURRENT: - case SP_MIX_POSE_CURRENT_LAYERED: /* to appease compiler */ - if (alpha == 1) break; - if (!vertexAttachment->bones) { - float* setupVertices = vertexAttachment->vertices; - for (i = 0; i < vertexCount; i++) { - vertices[i] += (setupVertices[i] - vertices[i]) * alpha; - } - } else { - alpha = 1 - alpha; - for (i = 0; i < vertexCount; i++) { - vertices[i] *= alpha; - } - } - } - return; - } - - if (time >= frames[framesCount - 1]) { /* Time is after last frame. */ - const float* lastVertices = self->frameVertices[framesCount - 1]; - if (alpha == 1) { - /* Vertex positions or deform offsets, no alpha. */ - memcpy(vertices, lastVertices, vertexCount * sizeof(float)); - } else if (pose == SP_MIX_POSE_SETUP) { - spVertexAttachment* vertexAttachment = SUB_CAST(spVertexAttachment, slot->attachment); - if (!vertexAttachment->bones) { - /* Unweighted vertex positions, with alpha. */ - float* setupVertices = vertexAttachment->vertices; - for (i = 0; i < vertexCount; i++) { - float setup = setupVertices[i]; - vertices[i] = setup + (lastVertices[i] - setup) * alpha; - } - } else { - /* Weighted deform offsets, with alpha. */ - for (i = 0; i < vertexCount; i++) - vertices[i] = lastVertices[i] * alpha; - } - } else { - /* Vertex positions or deform offsets, with alpha. */ - for (i = 0; i < vertexCount; i++) - vertices[i] += (lastVertices[i] - vertices[i]) * alpha; - } - return; - } - - /* Interpolate between the previous frame and the current frame. */ - frame = binarySearch(frames, framesCount, time, 1); - prevVertices = frameVertices[frame - 1]; - nextVertices = frameVertices[frame]; - frameTime = frames[frame]; - percent = spCurveTimeline_getCurvePercent(SUPER(self), frame - 1, 1 - (time - frameTime) / (frames[frame - 1] - frameTime)); - - if (alpha == 1) { - /* Vertex positions or deform offsets, no alpha. */ - for (i = 0; i < vertexCount; i++) { - float prev = prevVertices[i]; - vertices[i] = prev + (nextVertices[i] - prev) * percent; - } - } else if (pose == SP_MIX_POSE_SETUP) { - spVertexAttachment* vertexAttachment = SUB_CAST(spVertexAttachment, slot->attachment); - if (!vertexAttachment->bones) { - /* Unweighted vertex positions, with alpha. */ - float* setupVertices = vertexAttachment->vertices; - for (i = 0; i < vertexCount; i++) { - float prev = prevVertices[i], setup = setupVertices[i]; - vertices[i] = setup + (prev + (nextVertices[i] - prev) * percent - setup) * alpha; - } - } else { - /* Weighted deform offsets, with alpha. */ - for (i = 0; i < vertexCount; i++) { - float prev = prevVertices[i]; - vertices[i] = (prev + (nextVertices[i] - prev) * percent) * alpha; - } - } - } else { - /* Vertex positions or deform offsets, with alpha. */ - for (i = 0; i < vertexCount; i++) { - float prev = prevVertices[i]; - vertices[i] += (prev + (nextVertices[i] - prev) * percent - vertices[i]) * alpha; - } - } - - UNUSED(lastTime); - UNUSED(firedEvents); - UNUSED(eventsCount); -} - -int _spDeformTimeline_getPropertyId (const spTimeline* timeline) { - return (SP_TIMELINE_DEFORM << 27) + SUB_CAST(spVertexAttachment, SUB_CAST(spDeformTimeline, timeline)->attachment)->id + SUB_CAST(spDeformTimeline, timeline)->slotIndex; -} - -void _spDeformTimeline_dispose (spTimeline* timeline) { - spDeformTimeline* self = SUB_CAST(spDeformTimeline, timeline); - int i; - - _spCurveTimeline_deinit(SUPER(self)); - - for (i = 0; i < self->framesCount; ++i) - FREE(self->frameVertices[i]); - FREE(self->frameVertices); - FREE(self->frames); - FREE(self); -} - -spDeformTimeline* spDeformTimeline_create (int framesCount, int frameVerticesCount) { - spDeformTimeline* self = NEW(spDeformTimeline); - _spCurveTimeline_init(SUPER(self), SP_TIMELINE_DEFORM, framesCount, _spDeformTimeline_dispose, _spDeformTimeline_apply, _spDeformTimeline_getPropertyId); - CONST_CAST(int, self->framesCount) = framesCount; - CONST_CAST(float*, self->frames) = CALLOC(float, self->framesCount); - CONST_CAST(float**, self->frameVertices) = CALLOC(float*, framesCount); - CONST_CAST(int, self->frameVerticesCount) = frameVerticesCount; - return self; -} - -void spDeformTimeline_setFrame (spDeformTimeline* self, int frameIndex, float time, float* vertices) { - self->frames[frameIndex] = time; - - FREE(self->frameVertices[frameIndex]); - if (!vertices) - self->frameVertices[frameIndex] = 0; - else { - self->frameVertices[frameIndex] = MALLOC(float, self->frameVerticesCount); - memcpy(CONST_CAST(float*, self->frameVertices[frameIndex]), vertices, self->frameVerticesCount * sizeof(float)); - } -} - - -/**/ - -/** Fires events for frames > lastTime and <= time. */ -void _spEventTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents, - int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) { - spEventTimeline* self = (spEventTimeline*)timeline; - int frame; - if (!firedEvents) return; - - if (lastTime > time) { /* Fire events after last time for looped animations. */ - _spEventTimeline_apply(timeline, skeleton, lastTime, (float)INT_MAX, firedEvents, eventsCount, alpha, pose, direction); - lastTime = -1; - } else if (lastTime >= self->frames[self->framesCount - 1]) /* Last time is after last frame. */ - return; - if (time < self->frames[0]) return; /* Time is before first frame. */ - - if (lastTime < self->frames[0]) - frame = 0; - else { - float frameTime; - frame = binarySearch1(self->frames, self->framesCount, lastTime); - frameTime = self->frames[frame]; - while (frame > 0) { /* Fire multiple events with the same frame. */ - if (self->frames[frame - 1] != frameTime) break; - frame--; - } - } - for (; frame < self->framesCount && time >= self->frames[frame]; ++frame) { - firedEvents[*eventsCount] = self->events[frame]; - (*eventsCount)++; - } -} - -int _spEventTimeline_getPropertyId (const spTimeline* timeline) { - return SP_TIMELINE_EVENT << 24; -} - -void _spEventTimeline_dispose (spTimeline* timeline) { - spEventTimeline* self = SUB_CAST(spEventTimeline, timeline); - int i; - - _spTimeline_deinit(timeline); - - for (i = 0; i < self->framesCount; ++i) - spEvent_dispose(self->events[i]); - FREE(self->events); - FREE(self->frames); - FREE(self); -} - -spEventTimeline* spEventTimeline_create (int framesCount) { - spEventTimeline* self = NEW(spEventTimeline); - _spTimeline_init(SUPER(self), SP_TIMELINE_EVENT, _spEventTimeline_dispose, _spEventTimeline_apply, _spEventTimeline_getPropertyId); - - CONST_CAST(int, self->framesCount) = framesCount; - CONST_CAST(float*, self->frames) = CALLOC(float, framesCount); - CONST_CAST(spEvent**, self->events) = CALLOC(spEvent*, framesCount); - - return self; -} - -void spEventTimeline_setFrame (spEventTimeline* self, int frameIndex, spEvent* event) { - self->frames[frameIndex] = event->time; - - FREE(self->events[frameIndex]); - self->events[frameIndex] = event; -} - -/**/ - -void _spDrawOrderTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, - spEvent** firedEvents, int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) { - int i; - int frame; - const int* drawOrderToSetupIndex; - spDrawOrderTimeline* self = (spDrawOrderTimeline*)timeline; - - if (direction == SP_MIX_DIRECTION_OUT && pose == SP_MIX_POSE_SETUP) { - memcpy(skeleton->drawOrder, skeleton->slots, self->slotsCount * sizeof(spSlot*)); - return; - } - - if (time < self->frames[0]) { - if (pose == SP_MIX_POSE_SETUP) memcpy(skeleton->drawOrder, skeleton->slots, self->slotsCount * sizeof(spSlot*)); - return; - } - - if (time >= self->frames[self->framesCount - 1]) /* Time is after last frame. */ - frame = self->framesCount - 1; - else - frame = binarySearch1(self->frames, self->framesCount, time) - 1; - - drawOrderToSetupIndex = self->drawOrders[frame]; - if (!drawOrderToSetupIndex) - memcpy(skeleton->drawOrder, skeleton->slots, self->slotsCount * sizeof(spSlot*)); - else { - for (i = 0; i < self->slotsCount; ++i) - skeleton->drawOrder[i] = skeleton->slots[drawOrderToSetupIndex[i]]; - } - - UNUSED(lastTime); - UNUSED(firedEvents); - UNUSED(eventsCount); - UNUSED(alpha); -} - -int _spDrawOrderTimeline_getPropertyId (const spTimeline* timeline) { - return SP_TIMELINE_DRAWORDER << 24; -} - -void _spDrawOrderTimeline_dispose (spTimeline* timeline) { - spDrawOrderTimeline* self = SUB_CAST(spDrawOrderTimeline, timeline); - int i; - - _spTimeline_deinit(timeline); - - for (i = 0; i < self->framesCount; ++i) - FREE(self->drawOrders[i]); - FREE(self->drawOrders); - FREE(self->frames); - FREE(self); -} - -spDrawOrderTimeline* spDrawOrderTimeline_create (int framesCount, int slotsCount) { - spDrawOrderTimeline* self = NEW(spDrawOrderTimeline); - _spTimeline_init(SUPER(self), SP_TIMELINE_DRAWORDER, _spDrawOrderTimeline_dispose, _spDrawOrderTimeline_apply, _spDrawOrderTimeline_getPropertyId); - - CONST_CAST(int, self->framesCount) = framesCount; - CONST_CAST(float*, self->frames) = CALLOC(float, framesCount); - CONST_CAST(int**, self->drawOrders) = CALLOC(int*, framesCount); - CONST_CAST(int, self->slotsCount) = slotsCount; - - return self; -} - -void spDrawOrderTimeline_setFrame (spDrawOrderTimeline* self, int frameIndex, float time, const int* drawOrder) { - self->frames[frameIndex] = time; - - FREE(self->drawOrders[frameIndex]); - if (!drawOrder) - self->drawOrders[frameIndex] = 0; - else { - self->drawOrders[frameIndex] = MALLOC(int, self->slotsCount); - memcpy(CONST_CAST(int*, self->drawOrders[frameIndex]), drawOrder, self->slotsCount * sizeof(int)); - } -} - -/**/ - -static const int IKCONSTRAINT_PREV_TIME = -3, IKCONSTRAINT_PREV_MIX = -2, IKCONSTRAINT_PREV_BEND_DIRECTION = -1; -static const int IKCONSTRAINT_MIX = 1, IKCONSTRAINT_BEND_DIRECTION = 2; - -void _spIkConstraintTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, - spEvent** firedEvents, int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) { - int frame; - float frameTime, percent, mix; - float *frames; - int framesCount; - spIkConstraint* constraint; - spIkConstraintTimeline* self = (spIkConstraintTimeline*)timeline; - - constraint = skeleton->ikConstraints[self->ikConstraintIndex]; - - if (time < self->frames[0]) { - switch (pose) { - case SP_MIX_POSE_SETUP: - constraint->mix = constraint->data->mix; - constraint->bendDirection = constraint->data->bendDirection; - return; - case SP_MIX_POSE_CURRENT: - case SP_MIX_POSE_CURRENT_LAYERED: /* to appease compiler */ - constraint->mix += (constraint->data->mix - constraint->mix) * alpha; - constraint->bendDirection = constraint->data->bendDirection; - } - return; - } - - frames = self->frames; - framesCount = self->framesCount; - if (time >= frames[framesCount - IKCONSTRAINT_ENTRIES]) { /* Time is after last frame. */ - if (pose == SP_MIX_POSE_SETUP) { - constraint->mix = constraint->data->mix + (frames[framesCount + IKCONSTRAINT_PREV_MIX] - constraint->data->mix) * alpha; - constraint->bendDirection = direction == SP_MIX_DIRECTION_OUT ? constraint->data->bendDirection - : (int)frames[framesCount + IKCONSTRAINT_PREV_BEND_DIRECTION]; - } else { - constraint->mix += (frames[framesCount + IKCONSTRAINT_PREV_MIX] - constraint->mix) * alpha; - if (direction == SP_MIX_DIRECTION_IN) constraint->bendDirection = (int)frames[framesCount + IKCONSTRAINT_PREV_BEND_DIRECTION]; - } - return; - } - - /* Interpolate between the previous frame and the current frame. */ - frame = binarySearch(self->frames, self->framesCount, time, IKCONSTRAINT_ENTRIES); - mix = self->frames[frame + IKCONSTRAINT_PREV_MIX]; - frameTime = self->frames[frame]; - percent = spCurveTimeline_getCurvePercent(SUPER(self), frame / IKCONSTRAINT_ENTRIES - 1, 1 - (time - frameTime) / (self->frames[frame + IKCONSTRAINT_PREV_TIME] - frameTime)); - - if (pose == SP_MIX_POSE_SETUP) { - constraint->mix = constraint->data->mix + (mix + (frames[frame + IKCONSTRAINT_MIX] - mix) * percent - constraint->data->mix) * alpha; - constraint->bendDirection = direction == SP_MIX_DIRECTION_OUT ? constraint->data->bendDirection : (int)frames[frame + IKCONSTRAINT_PREV_BEND_DIRECTION]; - } else { - constraint->mix += (mix + (frames[frame + IKCONSTRAINT_MIX] - mix) * percent - constraint->mix) * alpha; - if (direction == SP_MIX_DIRECTION_IN) constraint->bendDirection = (int)frames[frame + IKCONSTRAINT_PREV_BEND_DIRECTION]; - } - - UNUSED(lastTime); - UNUSED(firedEvents); - UNUSED(eventsCount); -} - -int _spIkConstraintTimeline_getPropertyId (const spTimeline* timeline) { - return (SP_TIMELINE_IKCONSTRAINT << 24) + SUB_CAST(spIkConstraintTimeline, timeline)->ikConstraintIndex; -} - -spIkConstraintTimeline* spIkConstraintTimeline_create (int framesCount) { - return (spIkConstraintTimeline*)_spBaseTimeline_create(framesCount, SP_TIMELINE_IKCONSTRAINT, IKCONSTRAINT_ENTRIES, _spIkConstraintTimeline_apply, _spIkConstraintTimeline_getPropertyId); -} - -void spIkConstraintTimeline_setFrame (spIkConstraintTimeline* self, int frameIndex, float time, float mix, int bendDirection) { - frameIndex *= IKCONSTRAINT_ENTRIES; - self->frames[frameIndex] = time; - self->frames[frameIndex + IKCONSTRAINT_MIX] = mix; - self->frames[frameIndex + IKCONSTRAINT_BEND_DIRECTION] = (float)bendDirection; -} - -/**/ -static const int TRANSFORMCONSTRAINT_PREV_TIME = -5; -static const int TRANSFORMCONSTRAINT_PREV_ROTATE = -4; -static const int TRANSFORMCONSTRAINT_PREV_TRANSLATE = -3; -static const int TRANSFORMCONSTRAINT_PREV_SCALE = -2; -static const int TRANSFORMCONSTRAINT_PREV_SHEAR = -1; -static const int TRANSFORMCONSTRAINT_ROTATE = 1; -static const int TRANSFORMCONSTRAINT_TRANSLATE = 2; -static const int TRANSFORMCONSTRAINT_SCALE = 3; -static const int TRANSFORMCONSTRAINT_SHEAR = 4; - -void _spTransformConstraintTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, - spEvent** firedEvents, int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) { - int frame; - float frameTime, percent, rotate, translate, scale, shear; - spTransformConstraint* constraint; - spTransformConstraintTimeline* self = (spTransformConstraintTimeline*)timeline; - float *frames; - int framesCount; - - constraint = skeleton->transformConstraints[self->transformConstraintIndex]; - if (time < self->frames[0]) { - spTransformConstraintData* data = constraint->data; - switch (pose) { - case SP_MIX_POSE_SETUP: - constraint->rotateMix = data->rotateMix; - constraint->translateMix = data->translateMix; - constraint->scaleMix = data->scaleMix; - constraint->shearMix = data->shearMix; - return; - case SP_MIX_POSE_CURRENT: - case SP_MIX_POSE_CURRENT_LAYERED: /* to appease compiler */ - constraint->rotateMix += (data->rotateMix - constraint->rotateMix) * alpha; - constraint->translateMix += (data->translateMix - constraint->translateMix) * alpha; - constraint->scaleMix += (data->scaleMix - constraint->scaleMix) * alpha; - constraint->shearMix += (data->shearMix - constraint->shearMix) * alpha; - } - return; - return; - } - - frames = self->frames; - framesCount = self->framesCount; - if (time >= frames[framesCount - TRANSFORMCONSTRAINT_ENTRIES]) { /* Time is after last frame. */ - int i = framesCount; - rotate = frames[i + TRANSFORMCONSTRAINT_PREV_ROTATE]; - translate = frames[i + TRANSFORMCONSTRAINT_PREV_TRANSLATE]; - scale = frames[i + TRANSFORMCONSTRAINT_PREV_SCALE]; - shear = frames[i + TRANSFORMCONSTRAINT_PREV_SHEAR]; - } else { - /* Interpolate between the previous frame and the current frame. */ - frame = binarySearch(frames, framesCount, time, TRANSFORMCONSTRAINT_ENTRIES); - rotate = frames[frame + TRANSFORMCONSTRAINT_PREV_ROTATE]; - translate = frames[frame + TRANSFORMCONSTRAINT_PREV_TRANSLATE]; - scale = frames[frame + TRANSFORMCONSTRAINT_PREV_SCALE]; - shear = frames[frame + TRANSFORMCONSTRAINT_PREV_SHEAR]; - frameTime = frames[frame]; - percent = spCurveTimeline_getCurvePercent(SUPER(self), frame / TRANSFORMCONSTRAINT_ENTRIES - 1, - 1 - (time - frameTime) / (frames[frame + TRANSFORMCONSTRAINT_PREV_TIME] - frameTime)); - - rotate += (frames[frame + TRANSFORMCONSTRAINT_ROTATE] - rotate) * percent; - translate += (frames[frame + TRANSFORMCONSTRAINT_TRANSLATE] - translate) * percent; - scale += (frames[frame + TRANSFORMCONSTRAINT_SCALE] - scale) * percent; - shear += (frames[frame + TRANSFORMCONSTRAINT_SHEAR] - shear) * percent; - } - if (pose == SP_MIX_POSE_SETUP) { - spTransformConstraintData* data = constraint->data; - constraint->rotateMix = data->rotateMix + (rotate - data->rotateMix) * alpha; - constraint->translateMix = data->translateMix + (translate - data->translateMix) * alpha; - constraint->scaleMix = data->scaleMix + (scale - data->scaleMix) * alpha; - constraint->shearMix = data->shearMix + (shear - data->shearMix) * alpha; - } else { - constraint->rotateMix += (rotate - constraint->rotateMix) * alpha; - constraint->translateMix += (translate - constraint->translateMix) * alpha; - constraint->scaleMix += (scale - constraint->scaleMix) * alpha; - constraint->shearMix += (shear - constraint->shearMix) * alpha; - } - - UNUSED(lastTime); - UNUSED(firedEvents); - UNUSED(eventsCount); -} - -int _spTransformConstraintTimeline_getPropertyId (const spTimeline* timeline) { - return (SP_TIMELINE_TRANSFORMCONSTRAINT << 24) + SUB_CAST(spTransformConstraintTimeline, timeline)->transformConstraintIndex; -} - -spTransformConstraintTimeline* spTransformConstraintTimeline_create (int framesCount) { - return (spTransformConstraintTimeline*)_spBaseTimeline_create(framesCount, SP_TIMELINE_TRANSFORMCONSTRAINT, TRANSFORMCONSTRAINT_ENTRIES, _spTransformConstraintTimeline_apply, _spTransformConstraintTimeline_getPropertyId); -} - -void spTransformConstraintTimeline_setFrame (spTransformConstraintTimeline* self, int frameIndex, float time, float rotateMix, float translateMix, float scaleMix, float shearMix) { - frameIndex *= TRANSFORMCONSTRAINT_ENTRIES; - self->frames[frameIndex] = time; - self->frames[frameIndex + TRANSFORMCONSTRAINT_ROTATE] = rotateMix; - self->frames[frameIndex + TRANSFORMCONSTRAINT_TRANSLATE] = translateMix; - self->frames[frameIndex + TRANSFORMCONSTRAINT_SCALE] = scaleMix; - self->frames[frameIndex + TRANSFORMCONSTRAINT_SHEAR] = shearMix; -} - -/**/ - -static const int PATHCONSTRAINTPOSITION_PREV_TIME = -2; -static const int PATHCONSTRAINTPOSITION_PREV_VALUE = -1; -static const int PATHCONSTRAINTPOSITION_VALUE = 1; - -void _spPathConstraintPositionTimeline_apply(const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, - spEvent** firedEvents, int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) { - int frame; - float frameTime, percent, position; - spPathConstraint* constraint; - spPathConstraintPositionTimeline* self = (spPathConstraintPositionTimeline*)timeline; - float* frames; - int framesCount; - - constraint = skeleton->pathConstraints[self->pathConstraintIndex]; - if (time < self->frames[0]) { - switch (pose) { - case SP_MIX_POSE_SETUP: - constraint->position = constraint->data->position; - return; - case SP_MIX_POSE_CURRENT: - case SP_MIX_POSE_CURRENT_LAYERED: /* to appease compiler */ - constraint->position += (constraint->data->position - constraint->position) * alpha; - } - return; - } - - frames = self->frames; - framesCount = self->framesCount; - if (time >= frames[framesCount - PATHCONSTRAINTPOSITION_ENTRIES]) /* Time is after last frame. */ - position = frames[framesCount + PATHCONSTRAINTPOSITION_PREV_VALUE]; - else { - /* Interpolate between the previous frame and the current frame. */ - frame = binarySearch(frames, framesCount, time, PATHCONSTRAINTPOSITION_ENTRIES); - position = frames[frame + PATHCONSTRAINTPOSITION_PREV_VALUE]; - frameTime = frames[frame]; - percent = spCurveTimeline_getCurvePercent(SUPER(self), frame / PATHCONSTRAINTPOSITION_ENTRIES - 1, - 1 - (time - frameTime) / (frames[frame + PATHCONSTRAINTPOSITION_PREV_TIME] - frameTime)); - - position += (frames[frame + PATHCONSTRAINTPOSITION_VALUE] - position) * percent; - } - if (pose == SP_MIX_POSE_SETUP) - constraint->position = constraint->data->position + (position - constraint->data->position) * alpha; - else - constraint->position += (position - constraint->position) * alpha; - - UNUSED(lastTime); - UNUSED(firedEvents); - UNUSED(eventsCount); -} - -int _spPathConstraintPositionTimeline_getPropertyId (const spTimeline* timeline) { - return (SP_TIMELINE_PATHCONSTRAINTPOSITION << 24) + SUB_CAST(spPathConstraintPositionTimeline, timeline)->pathConstraintIndex; -} - -spPathConstraintPositionTimeline* spPathConstraintPositionTimeline_create (int framesCount) { - return (spPathConstraintPositionTimeline*)_spBaseTimeline_create(framesCount, SP_TIMELINE_PATHCONSTRAINTPOSITION, PATHCONSTRAINTPOSITION_ENTRIES, _spPathConstraintPositionTimeline_apply, _spPathConstraintPositionTimeline_getPropertyId); -} - -void spPathConstraintPositionTimeline_setFrame (spPathConstraintPositionTimeline* self, int frameIndex, float time, float value) { - frameIndex *= PATHCONSTRAINTPOSITION_ENTRIES; - self->frames[frameIndex] = time; - self->frames[frameIndex + PATHCONSTRAINTPOSITION_VALUE] = value; -} - -/**/ -static const int PATHCONSTRAINTSPACING_PREV_TIME = -2; -static const int PATHCONSTRAINTSPACING_PREV_VALUE = -1; -static const int PATHCONSTRAINTSPACING_VALUE = 1; - -void _spPathConstraintSpacingTimeline_apply(const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, - spEvent** firedEvents, int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) { - int frame; - float frameTime, percent, spacing; - spPathConstraint* constraint; - spPathConstraintSpacingTimeline* self = (spPathConstraintSpacingTimeline*)timeline; - float* frames; - int framesCount; - - constraint = skeleton->pathConstraints[self->pathConstraintIndex]; - if (time < self->frames[0]) { - switch (pose) { - case SP_MIX_POSE_SETUP: - constraint->spacing = constraint->data->spacing; - return; - case SP_MIX_POSE_CURRENT: - case SP_MIX_POSE_CURRENT_LAYERED: /* to appease compiler */ - constraint->spacing += (constraint->data->spacing - constraint->spacing) * alpha; - } - return; - } - - frames = self->frames; - framesCount = self->framesCount; - if (time >= frames[framesCount - PATHCONSTRAINTSPACING_ENTRIES]) /* Time is after last frame. */ - spacing = frames[framesCount + PATHCONSTRAINTSPACING_PREV_VALUE]; - else { - /* Interpolate between the previous frame and the current frame. */ - frame = binarySearch(frames, framesCount, time, PATHCONSTRAINTSPACING_ENTRIES); - spacing = frames[frame + PATHCONSTRAINTSPACING_PREV_VALUE]; - frameTime = frames[frame]; - percent = spCurveTimeline_getCurvePercent(SUPER(self), frame / PATHCONSTRAINTSPACING_ENTRIES - 1, - 1 - (time - frameTime) / (frames[frame + PATHCONSTRAINTSPACING_PREV_TIME] - frameTime)); - - spacing += (frames[frame + PATHCONSTRAINTSPACING_VALUE] - spacing) * percent; - } - - if (pose == SP_MIX_POSE_SETUP) - constraint->spacing = constraint->data->spacing + (spacing - constraint->data->spacing) * alpha; - else - constraint->spacing += (spacing - constraint->spacing) * alpha; - - UNUSED(lastTime); - UNUSED(firedEvents); - UNUSED(eventsCount); -} - -int _spPathConstraintSpacingTimeline_getPropertyId (const spTimeline* timeline) { - return (SP_TIMELINE_PATHCONSTRAINTSPACING << 24) + SUB_CAST(spPathConstraintSpacingTimeline, timeline)->pathConstraintIndex; -} - -spPathConstraintSpacingTimeline* spPathConstraintSpacingTimeline_create (int framesCount) { - return (spPathConstraintSpacingTimeline*)_spBaseTimeline_create(framesCount, SP_TIMELINE_PATHCONSTRAINTSPACING, PATHCONSTRAINTSPACING_ENTRIES, _spPathConstraintSpacingTimeline_apply, _spPathConstraintSpacingTimeline_getPropertyId); -} - -void spPathConstraintSpacingTimeline_setFrame (spPathConstraintSpacingTimeline* self, int frameIndex, float time, float value) { - frameIndex *= PATHCONSTRAINTSPACING_ENTRIES; - self->frames[frameIndex] = time; - self->frames[frameIndex + PATHCONSTRAINTSPACING_VALUE] = value; -} - -/**/ - -static const int PATHCONSTRAINTMIX_PREV_TIME = -3; -static const int PATHCONSTRAINTMIX_PREV_ROTATE = -2; -static const int PATHCONSTRAINTMIX_PREV_TRANSLATE = -1; -static const int PATHCONSTRAINTMIX_ROTATE = 1; -static const int PATHCONSTRAINTMIX_TRANSLATE = 2; - -void _spPathConstraintMixTimeline_apply(const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, - spEvent** firedEvents, int* eventsCount, float alpha, spMixPose pose, spMixDirection direction) { - int frame; - float frameTime, percent, rotate, translate; - spPathConstraint* constraint; - spPathConstraintMixTimeline* self = (spPathConstraintMixTimeline*)timeline; - float* frames; - int framesCount; - - constraint = skeleton->pathConstraints[self->pathConstraintIndex]; - if (time < self->frames[0]) { - switch (pose) { - case SP_MIX_POSE_SETUP: - constraint->rotateMix = constraint->data->rotateMix; - constraint->translateMix = constraint->data->translateMix; - return; - case SP_MIX_POSE_CURRENT: - case SP_MIX_POSE_CURRENT_LAYERED: /* to appease compiler */ - constraint->rotateMix += (constraint->data->rotateMix - constraint->rotateMix) * alpha; - constraint->translateMix += (constraint->data->translateMix - constraint->translateMix) * alpha; - } - return; - } - - frames = self->frames; - framesCount = self->framesCount; - if (time >= frames[framesCount - PATHCONSTRAINTMIX_ENTRIES]) { /* Time is after last frame. */ - rotate = frames[framesCount + PATHCONSTRAINTMIX_PREV_ROTATE]; - translate = frames[framesCount + PATHCONSTRAINTMIX_PREV_TRANSLATE]; - } else { - /* Interpolate between the previous frame and the current frame. */ - frame = binarySearch(frames, framesCount, time, PATHCONSTRAINTMIX_ENTRIES); - rotate = frames[frame + PATHCONSTRAINTMIX_PREV_ROTATE]; - translate = frames[frame + PATHCONSTRAINTMIX_PREV_TRANSLATE]; - frameTime = frames[frame]; - percent = spCurveTimeline_getCurvePercent(SUPER(self), frame / PATHCONSTRAINTMIX_ENTRIES - 1, - 1 - (time - frameTime) / (frames[frame + PATHCONSTRAINTMIX_PREV_TIME] - frameTime)); - - rotate += (frames[frame + PATHCONSTRAINTMIX_ROTATE] - rotate) * percent; - translate += (frames[frame + PATHCONSTRAINTMIX_TRANSLATE] - translate) * percent; - } - - if (pose == SP_MIX_POSE_SETUP) { - constraint->rotateMix = constraint->data->rotateMix + (rotate - constraint->data->rotateMix) * alpha; - constraint->translateMix = constraint->data->translateMix + (translate - constraint->data->translateMix) * alpha; - } else { - constraint->rotateMix += (rotate - constraint->rotateMix) * alpha; - constraint->translateMix += (translate - constraint->translateMix) * alpha; - } - - UNUSED(lastTime); - UNUSED(firedEvents); - UNUSED(eventsCount); -} - -int _spPathConstraintMixTimeline_getPropertyId (const spTimeline* timeline) { - return (SP_TIMELINE_PATHCONSTRAINTMIX << 24) + SUB_CAST(spPathConstraintMixTimeline, timeline)->pathConstraintIndex; -} - -spPathConstraintMixTimeline* spPathConstraintMixTimeline_create (int framesCount) { - return (spPathConstraintMixTimeline*)_spBaseTimeline_create(framesCount, SP_TIMELINE_PATHCONSTRAINTMIX, PATHCONSTRAINTMIX_ENTRIES, _spPathConstraintMixTimeline_apply, _spPathConstraintMixTimeline_getPropertyId); -} - -void spPathConstraintMixTimeline_setFrame (spPathConstraintMixTimeline* self, int frameIndex, float time, float rotateMix, float translateMix) { - frameIndex *= PATHCONSTRAINTMIX_ENTRIES; - self->frames[frameIndex] = time; - self->frames[frameIndex + PATHCONSTRAINTMIX_ROTATE] = rotateMix; - self->frames[frameIndex + PATHCONSTRAINTMIX_TRANSLATE] = translateMix; -} diff --git a/spine-cpp/spine-cpp/src/spine/AnimationState.c b/spine-cpp/spine-cpp/src/spine/AnimationState.c deleted file mode 100644 index 42d3aff0a..000000000 --- a/spine-cpp/spine-cpp/src/spine/AnimationState.c +++ /dev/null @@ -1,932 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#include -#include -#include - -#define SUBSEQUENT 0 -#define FIRST 1 -#define DIP 2 -#define DIP_MIX 3 - -_SP_ARRAY_IMPLEMENT_TYPE(spTrackEntryArray, spTrackEntry*) - -static spAnimation* SP_EMPTY_ANIMATION = 0; -void spAnimationState_disposeStatics () { - if (SP_EMPTY_ANIMATION) spAnimation_dispose(SP_EMPTY_ANIMATION); - SP_EMPTY_ANIMATION = 0; -} - -/* Forward declaration of some "private" functions so we can keep - the same function order in C as we have method order in Java */ -void _spAnimationState_disposeTrackEntry (spTrackEntry* entry); -void _spAnimationState_disposeTrackEntries (spAnimationState* state, spTrackEntry* entry); -int /*boolean*/ _spAnimationState_updateMixingFrom (spAnimationState* self, spTrackEntry* entry, float delta); -float _spAnimationState_applyMixingFrom (spAnimationState* self, spTrackEntry* entry, spSkeleton* skeleton, spMixPose currentPose); -void _spAnimationState_applyRotateTimeline (spAnimationState* self, spTimeline* timeline, spSkeleton* skeleton, float time, float alpha, spMixPose pose, float* timelinesRotation, int i, int /*boolean*/ firstFrame); -void _spAnimationState_queueEvents (spAnimationState* self, spTrackEntry* entry, float animationTime); -void _spAnimationState_setCurrent (spAnimationState* self, int index, spTrackEntry* current, int /*boolean*/ interrupt); -spTrackEntry* _spAnimationState_expandToIndex (spAnimationState* self, int index); -spTrackEntry* _spAnimationState_trackEntry (spAnimationState* self, int trackIndex, spAnimation* animation, int /*boolean*/ loop, spTrackEntry* last); -void _spAnimationState_disposeNext (spAnimationState* self, spTrackEntry* entry); -void _spAnimationState_animationsChanged (spAnimationState* self); -float* _spAnimationState_resizeTimelinesRotation(spTrackEntry* entry, int newSize); -int* _spAnimationState_resizeTimelinesFirst(spTrackEntry* entry, int newSize); -void _spAnimationState_ensureCapacityPropertyIDs(spAnimationState* self, int capacity); -int _spAnimationState_addPropertyID(spAnimationState* self, int id); -spTrackEntry* _spTrackEntry_setTimelineData(spTrackEntry* self, spTrackEntry* to, spTrackEntryArray* mixingToArray, spAnimationState* state); - - -_spEventQueue* _spEventQueue_create (_spAnimationState* state) { - _spEventQueue *self = CALLOC(_spEventQueue, 1); - self->state = state; - self->objectsCount = 0; - self->objectsCapacity = 16; - self->objects = CALLOC(_spEventQueueItem, self->objectsCapacity); - self->drainDisabled = 0; - return self; -} - -void _spEventQueue_free (_spEventQueue* self) { - FREE(self->objects); - FREE(self); -} - -void _spEventQueue_ensureCapacity (_spEventQueue* self, int newElements) { - if (self->objectsCount + newElements > self->objectsCapacity) { - _spEventQueueItem* newObjects; - self->objectsCapacity <<= 1; - newObjects = CALLOC(_spEventQueueItem, self->objectsCapacity); - memcpy(newObjects, self->objects, sizeof(_spEventQueueItem) * self->objectsCount); - FREE(self->objects); - self->objects = newObjects; - } -} - -void _spEventQueue_addType (_spEventQueue* self, spEventType type) { - _spEventQueue_ensureCapacity(self, 1); - self->objects[self->objectsCount++].type = type; -} - -void _spEventQueue_addEntry (_spEventQueue* self, spTrackEntry* entry) { - _spEventQueue_ensureCapacity(self, 1); - self->objects[self->objectsCount++].entry = entry; -} - -void _spEventQueue_addEvent (_spEventQueue* self, spEvent* event) { - _spEventQueue_ensureCapacity(self, 1); - self->objects[self->objectsCount++].event = event; -} - -void _spEventQueue_start (_spEventQueue* self, spTrackEntry* entry) { - _spEventQueue_addType(self, SP_ANIMATION_START); - _spEventQueue_addEntry(self, entry); - self->state->animationsChanged = 1; -} - -void _spEventQueue_interrupt (_spEventQueue* self, spTrackEntry* entry) { - _spEventQueue_addType(self, SP_ANIMATION_INTERRUPT); - _spEventQueue_addEntry(self, entry); -} - -void _spEventQueue_end (_spEventQueue* self, spTrackEntry* entry) { - _spEventQueue_addType(self, SP_ANIMATION_END); - _spEventQueue_addEntry(self, entry); - self->state->animationsChanged = 1; -} - -void _spEventQueue_dispose (_spEventQueue* self, spTrackEntry* entry) { - _spEventQueue_addType(self, SP_ANIMATION_DISPOSE); - _spEventQueue_addEntry(self, entry); -} - -void _spEventQueue_complete (_spEventQueue* self, spTrackEntry* entry) { - _spEventQueue_addType(self, SP_ANIMATION_COMPLETE); - _spEventQueue_addEntry(self, entry); -} - -void _spEventQueue_event (_spEventQueue* self, spTrackEntry* entry, spEvent* event) { - _spEventQueue_addType(self, SP_ANIMATION_EVENT); - _spEventQueue_addEntry(self, entry); - _spEventQueue_addEvent(self, event); -} - -void _spEventQueue_clear (_spEventQueue* self) { - self->objectsCount = 0; -} - -void _spEventQueue_drain (_spEventQueue* self) { - int i; - if (self->drainDisabled) return; - self->drainDisabled = 1; - for (i = 0; i < self->objectsCount; i += 2) { - spEventType type = (spEventType)self->objects[i].type; - spTrackEntry* entry = self->objects[i+1].entry; - spEvent* event; - switch (type) { - case SP_ANIMATION_START: - case SP_ANIMATION_INTERRUPT: - case SP_ANIMATION_COMPLETE: - if (entry->listener) entry->listener(SUPER(self->state), type, entry, 0); - if (self->state->super.listener) self->state->super.listener(SUPER(self->state), type, entry, 0); - break; - case SP_ANIMATION_END: - if (entry->listener) entry->listener(SUPER(self->state), type, entry, 0); - if (self->state->super.listener) self->state->super.listener(SUPER(self->state), type, entry, 0); - /* Fall through. */ - case SP_ANIMATION_DISPOSE: - if (entry->listener) entry->listener(SUPER(self->state), SP_ANIMATION_DISPOSE, entry, 0); - if (self->state->super.listener) self->state->super.listener(SUPER(self->state), SP_ANIMATION_DISPOSE, entry, 0); - _spAnimationState_disposeTrackEntry(entry); - break; - case SP_ANIMATION_EVENT: - event = self->objects[i+2].event; - if (entry->listener) entry->listener(SUPER(self->state), type, entry, event); - if (self->state->super.listener) self->state->super.listener(SUPER(self->state), type, entry, event); - i++; - break; - } - } - _spEventQueue_clear(self); - - self->drainDisabled = 0; -} - -void _spAnimationState_disposeTrackEntry (spTrackEntry* entry) { - spIntArray_dispose(entry->timelineData); - spTrackEntryArray_dispose(entry->timelineDipMix); - FREE(entry->timelinesRotation); - FREE(entry); -} - -void _spAnimationState_disposeTrackEntries (spAnimationState* state, spTrackEntry* entry) { - while (entry) { - spTrackEntry* next = entry->next; - spTrackEntry* from = entry->mixingFrom; - while (from) { - spTrackEntry* nextFrom = from->mixingFrom; - if (entry->listener) entry->listener(state, SP_ANIMATION_DISPOSE, from, 0); - if (state->listener) state->listener(state, SP_ANIMATION_DISPOSE, from, 0); - _spAnimationState_disposeTrackEntry(from); - from = nextFrom; - } - if (entry->listener) entry->listener(state, SP_ANIMATION_DISPOSE, entry, 0); - if (state->listener) state->listener(state, SP_ANIMATION_DISPOSE, entry, 0); - _spAnimationState_disposeTrackEntry(entry); - entry = next; - } -} - -spAnimationState* spAnimationState_create (spAnimationStateData* data) { - _spAnimationState* internal; - spAnimationState* self; - - if (!SP_EMPTY_ANIMATION) { - SP_EMPTY_ANIMATION = (spAnimation*)1; /* dirty trick so we can recursively call spAnimation_create */ - SP_EMPTY_ANIMATION = spAnimation_create("", 0); - } - - internal = NEW(_spAnimationState); - self = SUPER(internal); - - CONST_CAST(spAnimationStateData*, self->data) = data; - self->timeScale = 1; - - internal->queue = _spEventQueue_create(internal); - internal->events = CALLOC(spEvent*, 128); - - internal->propertyIDs = CALLOC(int, 128); - internal->propertyIDsCapacity = 128; - - self->mixingTo = spTrackEntryArray_create(16); - - return self; -} - -void spAnimationState_dispose (spAnimationState* self) { - int i; - _spAnimationState* internal = SUB_CAST(_spAnimationState, self); - for (i = 0; i < self->tracksCount; i++) - _spAnimationState_disposeTrackEntries(self, self->tracks[i]); - FREE(self->tracks); - _spEventQueue_free(internal->queue); - FREE(internal->events); - FREE(internal->propertyIDs); - spTrackEntryArray_dispose(self->mixingTo); - FREE(internal); -} - -void spAnimationState_update (spAnimationState* self, float delta) { - int i, n; - _spAnimationState* internal = SUB_CAST(_spAnimationState, self); - delta *= self->timeScale; - for (i = 0, n = self->tracksCount; i < n; i++) { - float currentDelta; - spTrackEntry* current = self->tracks[i]; - spTrackEntry* next; - if (!current) continue; - - current->animationLast = current->nextAnimationLast; - current->trackLast = current->nextTrackLast; - - currentDelta = delta * current->timeScale; - - if (current->delay > 0) { - current->delay -= currentDelta; - if (current->delay > 0) continue; - currentDelta = -current->delay; - current->delay = 0; - } - - next = current->next; - if (next) { - /* When the next entry's delay is passed, change to the next entry, preserving leftover time. */ - float nextTime = current->trackLast - next->delay; - if (nextTime >= 0) { - next->delay = 0; - next->trackTime = nextTime + delta * next->timeScale; - current->trackTime += currentDelta; - _spAnimationState_setCurrent(self, i, next, 1); - while (next->mixingFrom) { - next->mixTime += currentDelta; - next = next->mixingFrom; - } - continue; - } - } else { - /* Clear the track when there is no next entry, the track end time is reached, and there is no mixingFrom. */ - if (current->trackLast >= current->trackEnd && current->mixingFrom == 0) { - self->tracks[i] = 0; - _spEventQueue_end(internal->queue, current); - _spAnimationState_disposeNext(self, current); - continue; - } - } - if (current->mixingFrom != 0 && _spAnimationState_updateMixingFrom(self, current, delta)) { - /* End mixing from entries once all have completed. */ - spTrackEntry* from = current->mixingFrom; - current->mixingFrom = 0; - while (from != 0) { - _spEventQueue_end(internal->queue, from); - from = from->mixingFrom; - } - } - - current->trackTime += currentDelta; - } - - _spEventQueue_drain(internal->queue); -} - -int /*boolean*/ _spAnimationState_updateMixingFrom (spAnimationState* self, spTrackEntry* to, float delta) { - spTrackEntry* from = to->mixingFrom; - int finished; - _spAnimationState* internal = SUB_CAST(_spAnimationState, self); - if (!from) return -1; - - finished = _spAnimationState_updateMixingFrom(self, from, delta); - - /* Require mixTime > 0 to ensure the mixing from entry was applied at least once. */ - if (to->mixTime > 0 && (to->mixTime >= to->mixDuration || to->timeScale == 0)) { - /* Require totalAlpha == 0 to ensure mixing is complete, unless mixDuration == 0 (the transition is a single frame). */ - if (from->totalAlpha == 0 || to->mixDuration == 0) { - to->mixingFrom = from->mixingFrom; - to->interruptAlpha = from->interruptAlpha; - _spEventQueue_end(internal->queue, from); - } - return finished; - } - - from->animationLast = from->nextAnimationLast; - from->trackLast = from->nextTrackLast; - from->trackTime += delta * from->timeScale; - to->mixTime += delta * to->timeScale; - return 0; -} - -int spAnimationState_apply (spAnimationState* self, spSkeleton* skeleton) { - _spAnimationState* internal = SUB_CAST(_spAnimationState, self); - spTrackEntry* current; - int i, ii, n; - float animationLast, animationTime; - int timelineCount; - spTimeline** timelines; - int /*boolean*/ firstFrame; - float* timelinesRotation; - spTimeline* timeline; - int applied = 0; - spMixPose currentPose; - spMixPose pose; - - if (internal->animationsChanged) _spAnimationState_animationsChanged(self); - - for (i = 0, n = self->tracksCount; i < n; i++) { - float mix; - current = self->tracks[i]; - if (!current || current->delay > 0) continue; - applied = -1; - currentPose = i == 0 ? SP_MIX_POSE_CURRENT : SP_MIX_POSE_CURRENT_LAYERED; - - /* Apply mixing from entries first. */ - mix = current->alpha; - if (current->mixingFrom) - mix *= _spAnimationState_applyMixingFrom(self, current, skeleton, currentPose); - else if (current->trackTime >= current->trackEnd && current->next == 0) - mix = 0; - - /* Apply current entry. */ - animationLast = current->animationLast; animationTime = spTrackEntry_getAnimationTime(current); - timelineCount = current->animation->timelinesCount; - timelines = current->animation->timelines; - if (mix == 1) { - for (ii = 0; ii < timelineCount; ii++) - spTimeline_apply(timelines[ii], skeleton, animationLast, animationTime, internal->events, &internal->eventsCount, 1, SP_MIX_POSE_SETUP, SP_MIX_DIRECTION_IN); - } else { - spIntArray* timelineData = current->timelineData; - - firstFrame = current->timelinesRotationCount == 0; - if (firstFrame) _spAnimationState_resizeTimelinesRotation(current, timelineCount << 1); - timelinesRotation = current->timelinesRotation; - - for (ii = 0; ii < timelineCount; ii++) { - timeline = timelines[ii]; - pose = timelineData->items[ii] >= FIRST ? SP_MIX_POSE_SETUP : currentPose; - if (timeline->type == SP_TIMELINE_ROTATE) - _spAnimationState_applyRotateTimeline(self, timeline, skeleton, animationTime, mix, pose, timelinesRotation, ii << 1, firstFrame); - else - spTimeline_apply(timeline, skeleton, animationLast, animationTime, internal->events, &internal->eventsCount, mix, pose, SP_MIX_DIRECTION_IN); - } - } - _spAnimationState_queueEvents(self, current, animationTime); - internal->eventsCount = 0; - current->nextAnimationLast = animationTime; - current->nextTrackLast = current->trackTime; - } - - _spEventQueue_drain(internal->queue); - return applied; -} - -float _spAnimationState_applyMixingFrom (spAnimationState* self, spTrackEntry* to, spSkeleton* skeleton, spMixPose currentPose) { - _spAnimationState* internal = SUB_CAST(_spAnimationState, self); - float mix; - spEvent** events; - int /*boolean*/ attachments; - int /*boolean*/ drawOrder; - float animationLast; - float animationTime; - int timelineCount; - spTimeline** timelines; - spIntArray* timelineData; - spTrackEntryArray* timelineDipMix; - float alphaDip; - float alphaMix; - float alpha; - int /*boolean*/ firstFrame; - float* timelinesRotation; - spMixPose pose; - int i; - spTrackEntry* dipMix; - - spTrackEntry* from = to->mixingFrom; - if (from->mixingFrom) _spAnimationState_applyMixingFrom(self, from, skeleton, currentPose); - - if (to->mixDuration == 0) /* Single frame mix to undo mixingFrom changes. */ - mix = 1; - else { - mix = to->mixTime / to->mixDuration; - if (mix > 1) mix = 1; - } - - events = mix < from->eventThreshold ? internal->events : 0; - attachments = mix < from->attachmentThreshold; - drawOrder = mix < from->drawOrderThreshold; - animationLast = from->animationLast; - animationTime = spTrackEntry_getAnimationTime(from); - timelineCount = from->animation->timelinesCount; - timelines = from->animation->timelines; - timelineData = from->timelineData; - timelineDipMix = from->timelineDipMix; - - firstFrame = from->timelinesRotationCount == 0; - if (firstFrame) _spAnimationState_resizeTimelinesRotation(from, timelineCount << 1); - timelinesRotation = from->timelinesRotation; - - alphaDip = from->alpha * to->interruptAlpha; alphaMix = alphaDip * (1 - mix); - from->totalAlpha = 0; - for (i = 0; i < timelineCount; i++) { - spTimeline* timeline = timelines[i]; - switch (timelineData->items[i]) { - case SUBSEQUENT: - if (!attachments && timeline->type == SP_TIMELINE_ATTACHMENT) continue; - if (!drawOrder && timeline->type == SP_TIMELINE_DRAWORDER) continue; - pose = currentPose; - alpha = alphaMix; - break; - case FIRST: - pose = SP_MIX_POSE_SETUP; - alpha = alphaMix; - break; - case DIP: - pose = SP_MIX_POSE_SETUP; - alpha = alphaDip; - break; - default: - pose = SP_MIX_POSE_SETUP; - alpha = alphaDip; - dipMix = timelineDipMix->items[i]; - alpha *= MAX(0, 1 - dipMix->mixTime / dipMix->mixDuration); - break; - } - from->totalAlpha += alpha; - if (timeline->type == SP_TIMELINE_ROTATE) - _spAnimationState_applyRotateTimeline(self, timeline, skeleton, animationTime, alpha, pose, timelinesRotation, i << 1, firstFrame); - else { - spTimeline_apply(timeline, skeleton, animationLast, animationTime, events, &internal->eventsCount, alpha, pose, SP_MIX_DIRECTION_OUT); - } - } - - - if (to->mixDuration > 0) _spAnimationState_queueEvents(self, from, animationTime); - internal->eventsCount = 0; - from->nextAnimationLast = animationTime; - from->nextTrackLast = from->trackTime; - - return mix; -} - -void _spAnimationState_applyRotateTimeline (spAnimationState* self, spTimeline* timeline, spSkeleton* skeleton, float time, float alpha, spMixPose pose, float* timelinesRotation, int i, int /*boolean*/ firstFrame) { - spRotateTimeline *rotateTimeline; - float *frames; - spBone* bone; - float r1, r2; - int frame; - float prevRotation; - float frameTime; - float percent; - float total, diff; - int /*boolean*/ current, dir; - - if (firstFrame) timelinesRotation[i] = 0; - - if (alpha == 1) { - spTimeline_apply(timeline, skeleton, 0, time, 0, 0, 1, pose, SP_MIX_DIRECTION_IN); - return; - } - - rotateTimeline = SUB_CAST(spRotateTimeline, timeline); - frames = rotateTimeline->frames; - bone = skeleton->bones[rotateTimeline->boneIndex]; - if (time < frames[0]) { - if (pose == SP_MIX_POSE_SETUP) { - bone->rotation = bone->data->rotation; - } - return; /* Time is before first frame. */ - } - - if (time >= frames[rotateTimeline->framesCount - ROTATE_ENTRIES]) /* Time is after last frame. */ - r2 = bone->data->rotation + frames[rotateTimeline->framesCount + ROTATE_PREV_ROTATION]; - else { - /* Interpolate between the previous frame and the current frame. */ - frame = _spCurveTimeline_binarySearch(frames, rotateTimeline->framesCount, time, ROTATE_ENTRIES); - prevRotation = frames[frame + ROTATE_PREV_ROTATION]; - frameTime = frames[frame]; - percent = spCurveTimeline_getCurvePercent(SUPER(rotateTimeline), (frame >> 1) - 1, - 1 - (time - frameTime) / (frames[frame + ROTATE_PREV_TIME] - frameTime)); - - r2 = frames[frame + ROTATE_ROTATION] - prevRotation; - r2 -= (16384 - (int)(16384.499999999996 - r2 / 360)) * 360; - r2 = prevRotation + r2 * percent + bone->data->rotation; - r2 -= (16384 - (int)(16384.499999999996 - r2 / 360)) * 360; - } - - /* Mix between rotations using the direction of the shortest route on the first frame while detecting crosses. */ - r1 = pose == SP_MIX_POSE_SETUP ? bone->data->rotation : bone->rotation; - diff = r2 - r1; - if (diff == 0) { - total = timelinesRotation[i]; - } else { - float lastTotal, lastDiff; - diff -= (16384 - (int)(16384.499999999996 - diff / 360)) * 360; - if (firstFrame) { - lastTotal = 0; - lastDiff = diff; - } else { - lastTotal = timelinesRotation[i]; /* Angle and direction of mix, including loops. */ - lastDiff = timelinesRotation[i + 1]; /* Difference between bones. */ - } - current = diff > 0; - dir = lastTotal >= 0; - /* Detect cross at 0 (not 180). */ - if (SIGNUM(lastDiff) != SIGNUM(diff) && ABS(lastDiff) <= 90) { - /* A cross after a 360 rotation is a loop. */ - if (ABS(lastTotal) > 180) lastTotal += 360 * SIGNUM(lastTotal); - dir = current; - } - total = diff + lastTotal - FMOD(lastTotal, 360); /* Store loops as part of lastTotal. */ - if (dir != current) total += 360 * SIGNUM(lastTotal); - timelinesRotation[i] = total; - } - timelinesRotation[i + 1] = diff; - r1 += total * alpha; - bone->rotation = r1 - (16384 - (int)(16384.499999999996 - r1 / 360)) * 360; -} - -void _spAnimationState_queueEvents (spAnimationState* self, spTrackEntry* entry, float animationTime) { - spEvent** events; - spEvent* event; - _spAnimationState* internal = SUB_CAST(_spAnimationState, self); - int i, n; - float animationStart = entry->animationStart, animationEnd = entry->animationEnd; - float duration = animationEnd - animationStart; - float trackLastWrapped = FMOD(entry->trackLast, duration); - - /* Queue events before complete. */ - events = internal->events; - for (i = 0, n = internal->eventsCount; i < n; i++) { - event = events[i]; - if (event->time < trackLastWrapped) break; - if (event->time > animationEnd) continue; /* Discard events outside animation start/end. */ - _spEventQueue_event(internal->queue, entry, event); - } - - /* Queue complete if completed a loop iteration or the animation. */ - if (entry->loop ? (trackLastWrapped > FMOD(entry->trackTime, duration)) - : (animationTime >= animationEnd && entry->animationLast < animationEnd)) { - _spEventQueue_complete(internal->queue, entry); - } - - /* Queue events after complete. */ - for (; i < n; i++) { - event = events[i]; - if (event->time < animationStart) continue; /* Discard events outside animation start/end. */ - _spEventQueue_event(internal->queue, entry, event); - } -} - -void spAnimationState_clearTracks (spAnimationState* self) { - _spAnimationState* internal = SUB_CAST(_spAnimationState, self); - int i, n, oldDrainDisabled; - oldDrainDisabled = internal->queue->drainDisabled; - internal->queue->drainDisabled = 1; - for (i = 0, n = self->tracksCount; i < n; i++) - spAnimationState_clearTrack(self, i); - self->tracksCount = 0; - internal->queue->drainDisabled = oldDrainDisabled; - _spEventQueue_drain(internal->queue); -} - -void spAnimationState_clearTrack (spAnimationState* self, int trackIndex) { - spTrackEntry* current; - spTrackEntry* entry; - spTrackEntry* from; - _spAnimationState* internal = SUB_CAST(_spAnimationState, self); - - if (trackIndex >= self->tracksCount) return; - current = self->tracks[trackIndex]; - if (!current) return; - - _spEventQueue_end(internal->queue, current); - - _spAnimationState_disposeNext(self, current); - - entry = current; - while (1) { - from = entry->mixingFrom; - if (!from) break; - _spEventQueue_end(internal->queue, from); - entry->mixingFrom = 0; - entry = from; - } - - self->tracks[current->trackIndex] = 0; - _spEventQueue_drain(internal->queue); -} - -void _spAnimationState_setCurrent (spAnimationState* self, int index, spTrackEntry* current, int /*boolean*/ interrupt) { - _spAnimationState* internal = SUB_CAST(_spAnimationState, self); - spTrackEntry* from = _spAnimationState_expandToIndex(self, index); - self->tracks[index] = current; - - if (from) { - if (interrupt) _spEventQueue_interrupt(internal->queue, from); - current->mixingFrom = from; - current->mixTime = 0; - - /* Store the interrupted mix percentage. */ - if (from->mixingFrom != 0 && from->mixDuration > 0) - current->interruptAlpha *= MIN(1, from->mixTime / from->mixDuration); - - from->timelinesRotationCount = 0; - } - - _spEventQueue_start(internal->queue, current); -} - -/** Set the current animation. Any queued animations are cleared. */ -spTrackEntry* spAnimationState_setAnimationByName (spAnimationState* self, int trackIndex, const char* animationName, - int/*bool*/loop) { - spAnimation* animation = spSkeletonData_findAnimation(self->data->skeletonData, animationName); - return spAnimationState_setAnimation(self, trackIndex, animation, loop); -} - -spTrackEntry* spAnimationState_setAnimation (spAnimationState* self, int trackIndex, spAnimation* animation, int/*bool*/loop) { - spTrackEntry* entry; - _spAnimationState* internal = SUB_CAST(_spAnimationState, self); - int interrupt = 1; - spTrackEntry* current = _spAnimationState_expandToIndex(self, trackIndex); - if (current) { - if (current->nextTrackLast == -1) { - /* Don't mix from an entry that was never applied. */ - self->tracks[trackIndex] = current->mixingFrom; - _spEventQueue_interrupt(internal->queue, current); - _spEventQueue_end(internal->queue, current); - _spAnimationState_disposeNext(self, current); - current = current->mixingFrom; - interrupt = 0; - } else - _spAnimationState_disposeNext(self, current); - } - entry = _spAnimationState_trackEntry(self, trackIndex, animation, loop, current); - _spAnimationState_setCurrent(self, trackIndex, entry, interrupt); - _spEventQueue_drain(internal->queue); - return entry; -} - -/** Adds an animation to be played delay seconds after the current or last queued animation, taking into account any mix - * duration. */ -spTrackEntry* spAnimationState_addAnimationByName (spAnimationState* self, int trackIndex, const char* animationName, - int/*bool*/loop, float delay) { - spAnimation* animation = spSkeletonData_findAnimation(self->data->skeletonData, animationName); - return spAnimationState_addAnimation(self, trackIndex, animation, loop, delay); -} - -spTrackEntry* spAnimationState_addAnimation (spAnimationState* self, int trackIndex, spAnimation* animation, int/*bool*/loop, - float delay) { - spTrackEntry* entry; - _spAnimationState* internal = SUB_CAST(_spAnimationState, self); - spTrackEntry* last = _spAnimationState_expandToIndex(self, trackIndex); - if (last) { - while (last->next) - last = last->next; - } - - entry = _spAnimationState_trackEntry(self, trackIndex, animation, loop, last); - - if (!last) { - _spAnimationState_setCurrent(self, trackIndex, entry, 1); - _spEventQueue_drain(internal->queue); - } else { - last->next = entry; - if (delay <= 0) { - float duration = last->animationEnd - last->animationStart; - if (duration != 0) - delay += duration * (1 + (int)(last->trackTime / duration)) - spAnimationStateData_getMix(self->data, last->animation, animation); - else - delay = 0; - } - } - - entry->delay = delay; - return entry; -} - -spTrackEntry* spAnimationState_setEmptyAnimation(spAnimationState* self, int trackIndex, float mixDuration) { - spTrackEntry* entry = spAnimationState_setAnimation(self, trackIndex, SP_EMPTY_ANIMATION, 0); - entry->mixDuration = mixDuration; - entry->trackEnd = mixDuration; - return entry; -} - -spTrackEntry* spAnimationState_addEmptyAnimation(spAnimationState* self, int trackIndex, float mixDuration, float delay) { - spTrackEntry* entry; - if (delay <= 0) delay -= mixDuration; - entry = spAnimationState_addAnimation(self, trackIndex, SP_EMPTY_ANIMATION, 0, delay); - entry->mixDuration = mixDuration; - entry->trackEnd = mixDuration; - return entry; -} - -void spAnimationState_setEmptyAnimations(spAnimationState* self, float mixDuration) { - int i, n, oldDrainDisabled; - spTrackEntry* current; - _spAnimationState* internal = SUB_CAST(_spAnimationState, self); - oldDrainDisabled = internal->queue->drainDisabled; - internal->queue->drainDisabled = 1; - for (i = 0, n = self->tracksCount; i < n; i++) { - current = self->tracks[i]; - if (current) spAnimationState_setEmptyAnimation(self, current->trackIndex, mixDuration); - } - internal->queue->drainDisabled = oldDrainDisabled; - _spEventQueue_drain(internal->queue); -} - -spTrackEntry* _spAnimationState_expandToIndex (spAnimationState* self, int index) { - spTrackEntry** newTracks; - if (index < self->tracksCount) return self->tracks[index]; - newTracks = CALLOC(spTrackEntry*, index + 1); - memcpy(newTracks, self->tracks, self->tracksCount * sizeof(spTrackEntry*)); - FREE(self->tracks); - self->tracks = newTracks; - self->tracksCount = index + 1; - return 0; -} - -spTrackEntry* _spAnimationState_trackEntry (spAnimationState* self, int trackIndex, spAnimation* animation, int /*boolean*/ loop, spTrackEntry* last) { - spTrackEntry* entry = NEW(spTrackEntry); - entry->trackIndex = trackIndex; - entry->animation = animation; - entry->loop = loop; - - entry->eventThreshold = 0; - entry->attachmentThreshold = 0; - entry->drawOrderThreshold = 0; - - entry->animationStart = 0; - entry->animationEnd = animation->duration; - entry->animationLast = -1; - entry->nextAnimationLast = -1; - - entry->delay = 0; - entry->trackTime = 0; - entry->trackLast = -1; - entry->nextTrackLast = -1; - entry->trackEnd = (float)INT_MAX; - entry->timeScale = 1; - - entry->alpha = 1; - entry->interruptAlpha = 1; - entry->mixTime = 0; - entry->mixDuration = !last ? 0 : spAnimationStateData_getMix(self->data, last->animation, animation); - - entry->timelineData = spIntArray_create(16); - entry->timelineDipMix = spTrackEntryArray_create(16); - return entry; -} - -void _spAnimationState_disposeNext (spAnimationState* self, spTrackEntry* entry) { - _spAnimationState* internal = SUB_CAST(_spAnimationState, self); - spTrackEntry* next = entry->next; - while (next) { - _spEventQueue_dispose(internal->queue, next); - next = next->next; - } - entry->next = 0; -} - -void _spAnimationState_animationsChanged (spAnimationState* self) { - _spAnimationState* internal = SUB_CAST(_spAnimationState, self); - int i, n; - spTrackEntry* entry; - spTrackEntryArray* mixingTo; - internal->animationsChanged = 0; - - internal->propertyIDsCount = 0; - i = 0; n = self->tracksCount; - - mixingTo = self->mixingTo; - - for (;i < n; i++) { - entry = self->tracks[i]; - if (entry != 0) _spTrackEntry_setTimelineData(entry, 0, mixingTo, self); - } -} - -float* _spAnimationState_resizeTimelinesRotation(spTrackEntry* entry, int newSize) { - if (entry->timelinesRotationCount != newSize) { - float* newTimelinesRotation = CALLOC(float, newSize); - FREE(entry->timelinesRotation); - entry->timelinesRotation = newTimelinesRotation; - entry->timelinesRotationCount = newSize; - } - return entry->timelinesRotation; -} - -void _spAnimationState_ensureCapacityPropertyIDs(spAnimationState* self, int capacity) { - _spAnimationState* internal = SUB_CAST(_spAnimationState, self); - if (internal->propertyIDsCapacity < capacity) { - int *newPropertyIDs = CALLOC(int, capacity << 1); - memcpy(newPropertyIDs, internal->propertyIDs, sizeof(int) * internal->propertyIDsCount); - FREE(internal->propertyIDs); - internal->propertyIDs = newPropertyIDs; - internal->propertyIDsCapacity = capacity << 1; - } -} - -int _spAnimationState_addPropertyID(spAnimationState* self, int id) { - int i, n; - _spAnimationState* internal = SUB_CAST(_spAnimationState, self); - - for (i = 0, n = internal->propertyIDsCount; i < n; i++) { - if (internal->propertyIDs[i] == id) return 0; - } - - _spAnimationState_ensureCapacityPropertyIDs(self, internal->propertyIDsCount + 1); - internal->propertyIDs[internal->propertyIDsCount] = id; - internal->propertyIDsCount++; - return 1; -} - -spTrackEntry* spAnimationState_getCurrent (spAnimationState* self, int trackIndex) { - if (trackIndex >= self->tracksCount) return 0; - return self->tracks[trackIndex]; -} - -void spAnimationState_clearListenerNotifications(spAnimationState* self) { - _spAnimationState* internal = SUB_CAST(_spAnimationState, self); - _spEventQueue_clear(internal->queue); -} - -float spTrackEntry_getAnimationTime (spTrackEntry* entry) { - if (entry->loop) { - float duration = entry->animationEnd - entry->animationStart; - if (duration == 0) return entry->animationStart; - return FMOD(entry->trackTime, duration) + entry->animationStart; - } - return MIN(entry->trackTime + entry->animationStart, entry->animationEnd); -} - -int /*boolean*/ _spTrackEntry_hasTimeline(spTrackEntry* self, int id) { - spTimeline** timelines = self->animation->timelines; - int i, n; - for (i = 0, n = self->animation->timelinesCount; i < n; i++) - if (spTimeline_getPropertyId(timelines[i]) == id) return 1; - return 0; -} - -spTrackEntry* _spTrackEntry_setTimelineData(spTrackEntry* self, spTrackEntry* to, spTrackEntryArray* mixingToArray, spAnimationState* state) { - spTrackEntry* lastEntry; - spTrackEntry** mixingTo; - int mixingToLast; - spTimeline** timelines; - int timelinesCount; - int* timelineData; - spTrackEntry** timelineDipMix; - int i, ii; - - if (to != 0) spTrackEntryArray_add(mixingToArray, to); - lastEntry = self->mixingFrom != 0 ? _spTrackEntry_setTimelineData(self->mixingFrom, self, mixingToArray, state) : self; - if (to != 0) spTrackEntryArray_pop(mixingToArray); - - mixingTo = mixingToArray->items; - mixingToLast = mixingToArray->size - 1; - timelines = self->animation->timelines; - timelinesCount = self->animation->timelinesCount; - timelineData = spIntArray_setSize(self->timelineData, timelinesCount)->items; - spTrackEntryArray_clear(self->timelineDipMix); - timelineDipMix = spTrackEntryArray_setSize(self->timelineDipMix, timelinesCount)->items; - - i = 0; - continue_outer: - for (; i < timelinesCount; i++) { - int id = spTimeline_getPropertyId(timelines[i]); - if (!_spAnimationState_addPropertyID(state, id)) - timelineData[i] = SUBSEQUENT; - else if (to == 0 || !_spTrackEntry_hasTimeline(to, id)) - timelineData[i] = FIRST; - else { - for (ii = mixingToLast; ii >= 0; ii--) { - spTrackEntry* entry = mixingTo[ii]; - if (!_spTrackEntry_hasTimeline(entry, id)) { - if (entry->mixDuration > 0) { - timelineData[i] = DIP_MIX; - timelineDipMix[i] = entry; - i++; - goto continue_outer; - } - } - break; - } - timelineData[i] = DIP; - } - } - return lastEntry; -} diff --git a/spine-cpp/spine-cpp/src/spine/AnimationStateData.c b/spine-cpp/spine-cpp/src/spine/AnimationStateData.c deleted file mode 100644 index 2aeb25add..000000000 --- a/spine-cpp/spine-cpp/src/spine/AnimationStateData.c +++ /dev/null @@ -1,151 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#include -#include - -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; -} diff --git a/spine-cpp/spine-cpp/src/spine/Array.c b/spine-cpp/spine-cpp/src/spine/Array.c deleted file mode 100644 index 03a32bc78..000000000 --- a/spine-cpp/spine-cpp/src/spine/Array.c +++ /dev/null @@ -1,39 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#include -#include - -_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*) diff --git a/spine-cpp/spine-cpp/src/spine/Atlas.c b/spine-cpp/spine-cpp/src/spine/Atlas.c deleted file mode 100644 index 92437633f..000000000 --- a/spine-cpp/spine-cpp/src/spine/Atlas.c +++ /dev/null @@ -1,359 +0,0 @@ -/****************************************************************************** -* Spine Runtimes Software License v2.5 -* -* Copyright (c) 2013-2016, Esoteric Software -* All rights reserved. -* -* You are granted a perpetual, non-exclusive, non-sublicensable, and -* non-transferable license to use, install, execute, and perform the Spine -* Runtimes software and derivative works solely for personal or internal -* use. Without the written permission of Esoteric Software (see Section 2 of -* the Spine Software License Agreement), you may not (a) modify, translate, -* adapt, or develop new applications using the Spine Runtimes or otherwise -* create derivative works or improvements of the Spine Runtimes or (b) remove, -* delete, alter, or obscure any trademarks or any copyright, trademark, patent, -* or other intellectual property or proprietary rights notices on or in the -* Software, including any copy thereof. Redistributions in binary or source -* form must include this license and terms. -* -* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE -* POSSIBILITY OF SUCH DAMAGE. -*****************************************************************************/ - -#include -#include -#include - -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 (isspace((unsigned char)*str->end) && 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); - region->rotate = equals(&str, "true"); - - 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; -} diff --git a/spine-cpp/spine-cpp/src/spine/AtlasAttachmentLoader.c b/spine-cpp/spine-cpp/src/spine/AtlasAttachmentLoader.c deleted file mode 100644 index c4a613709..000000000 --- a/spine-cpp/spine-cpp/src/spine/AtlasAttachmentLoader.c +++ /dev/null @@ -1,100 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#include -#include - -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->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(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; -} diff --git a/spine-cpp/spine-cpp/src/spine/Attachment.c b/spine-cpp/spine-cpp/src/spine/Attachment.c deleted file mode 100644 index 3dad43a69..000000000 --- a/spine-cpp/spine-cpp/src/spine/Attachment.c +++ /dev/null @@ -1,57 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#include -#include -#include - -typedef struct _spAttachmentVtable { - void (*dispose) (spAttachment* self); -} _spAttachmentVtable; - -void _spAttachment_init (spAttachment* self, const char* name, spAttachmentType type, /**/ - void (*dispose) (spAttachment* self)) { - - CONST_CAST(_spAttachmentVtable*, self->vtable) = NEW(_spAttachmentVtable); - VTABLE(spAttachment, self) ->dispose = dispose; - - 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); -} - -void spAttachment_dispose (spAttachment* self) { - VTABLE(spAttachment, self) ->dispose(self); -} diff --git a/spine-cpp/spine-cpp/src/spine/AttachmentLoader.c b/spine-cpp/spine-cpp/src/spine/AttachmentLoader.c deleted file mode 100644 index 14cbd92ab..000000000 --- a/spine-cpp/spine-cpp/src/spine/AttachmentLoader.c +++ /dev/null @@ -1,98 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#include -#include -#include - -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); -} diff --git a/spine-cpp/spine-cpp/src/spine/Bone.c b/spine-cpp/spine-cpp/src/spine/Bone.c deleted file mode 100644 index 96d43cb6d..000000000 --- a/spine-cpp/spine-cpp/src/spine/Bone.c +++ /dev/null @@ -1,304 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#include -#include -#include -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; - - 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; - 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; - if (self->skeleton->flipX) { - x = -x; - la = -la; - lb = -lb; - } - if (self->skeleton->flipY != yDown) { - y = -y; - lc = -lc; - ld = -ld; - } - CONST_CAST(float, self->a) = la; - CONST_CAST(float, self->b) = lb; - CONST_CAST(float, self->c) = lc; - CONST_CAST(float, self->d) = ld; - CONST_CAST(float, self->worldX) = x + self->skeleton->x; - CONST_CAST(float, self->worldY) = y + 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; - zc = pc * cosine + pd * sine; - s = SQRT(za * za + zc * zc); - if (s > 0.00001f) s = 1 / s; - za *= s; - zc *= s; - s = SQRT(za * za + zc * zc); - 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; - if (self->data->transformMode != SP_TRANSFORMMODE_NOSCALEORREFLECTION ? pa * pd - pb * pc < 0 : self->skeleton->flipX != self->skeleton->flipY) { - zb = -zb; - zd = -zd; - } - 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; - return; - } - } - if (self->skeleton->flipX) { - CONST_CAST(float, self->a) = -self->a; - CONST_CAST(float, self->b) = -self->b; - } - if (self->skeleton->flipY != yDown) { - CONST_CAST(float, self->c) = -self->c; - CONST_CAST(float, self->d) = -self->d; - } -} - -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). - *

- * 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; -} - -float spBone_localToWorldRotation (spBone* self, float localRotation) { - float sine, cosine; - 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; -} diff --git a/spine-cpp/spine-cpp/src/spine/BoneData.c b/spine-cpp/spine-cpp/src/spine/BoneData.c deleted file mode 100644 index 5933571ed..000000000 --- a/spine-cpp/spine-cpp/src/spine/BoneData.c +++ /dev/null @@ -1,48 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#include -#include - -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); -} diff --git a/spine-cpp/spine-cpp/src/spine/BoundingBoxAttachment.c b/spine-cpp/spine-cpp/src/spine/BoundingBoxAttachment.c deleted file mode 100644 index f8b45f5c7..000000000 --- a/spine-cpp/spine-cpp/src/spine/BoundingBoxAttachment.c +++ /dev/null @@ -1,47 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#include -#include - -void _spBoundingBoxAttachment_dispose (spAttachment* attachment) { - spBoundingBoxAttachment* self = SUB_CAST(spBoundingBoxAttachment, attachment); - - _spVertexAttachment_deinit(SUPER(self)); - - FREE(self); -} - -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); - return self; -} diff --git a/spine-cpp/spine-cpp/src/spine/ClippingAttachment.c b/spine-cpp/spine-cpp/src/spine/ClippingAttachment.c deleted file mode 100644 index 38ea8dd31..000000000 --- a/spine-cpp/spine-cpp/src/spine/ClippingAttachment.c +++ /dev/null @@ -1,48 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#include -#include - -void _spClippingAttachment_dispose (spAttachment* attachment) { - spClippingAttachment* self = SUB_CAST(spClippingAttachment, attachment); - - _spVertexAttachment_deinit(SUPER(self)); - - FREE(self); -} - -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); - self->endSlot = 0; - return self; -} diff --git a/spine-cpp/spine-cpp/src/spine/Color.c b/spine-cpp/spine-cpp/src/spine/Color.c deleted file mode 100644 index 02168ee3c..000000000 --- a/spine-cpp/spine-cpp/src/spine/Color.c +++ /dev/null @@ -1,84 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#include -#include - -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; -} - -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; -} diff --git a/spine-cpp/spine-cpp/src/spine/Event.c b/spine-cpp/spine-cpp/src/spine/Event.c deleted file mode 100644 index 7c1435cef..000000000 --- a/spine-cpp/spine-cpp/src/spine/Event.c +++ /dev/null @@ -1,44 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#include -#include - -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); -} diff --git a/spine-cpp/spine-cpp/src/spine/EventData.c b/spine-cpp/spine-cpp/src/spine/EventData.c deleted file mode 100644 index 8b0014f78..000000000 --- a/spine-cpp/spine-cpp/src/spine/EventData.c +++ /dev/null @@ -1,44 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#include -#include - -spEventData* spEventData_create (const char* name) { - spEventData* self = NEW(spEventData); - MALLOC_STR(self->name, name); - return self; -} - -void spEventData_dispose (spEventData* self) { - FREE(self->stringValue); - FREE(self->name); - FREE(self); -} diff --git a/spine-cpp/spine-cpp/src/spine/IkConstraint.c b/spine-cpp/spine-cpp/src/spine/IkConstraint.c deleted file mode 100644 index 1caab6379..000000000 --- a/spine-cpp/spine-cpp/src/spine/IkConstraint.c +++ /dev/null @@ -1,208 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#include -#include -#include -#include - -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->mix = data->mix; - - 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->mix); - break; - case 2: - spIkConstraint_apply2(self->bones[0], self->bones[1], self->target->worldX, self->target->worldY, self->bendDirection, self->mix); - break; - } -} - -void spIkConstraint_apply1 (spBone* bone, float targetX, float targetY, float alpha) { - spBone* p = bone->parent; - float id, x, y, tx, ty, rotationIK; - if (!bone->appliedValid) spBone_updateAppliedTransform(bone); - id = 1 / (p->a * p->d - p->b * p->c); - x = targetX - p->worldX, y = targetY - p->worldY; - tx = (x * p->d - y * p->b) * id - bone->ax; ty = (y * p->a - x * p->c) * id - bone->ay; - rotationIK = ATAN2(ty, tx) * RAD_DEG - bone->ashearX - bone->arotation; - if (bone->ascaleX < 0) rotationIK += 180; - if (rotationIK > 180) rotationIK -= 360; - else if (rotationIK < -180) rotationIK += 360; - spBone_updateWorldTransformWith(bone, bone->ax, bone->ay, bone->arotation + rotationIK * alpha, bone->ascaleX, - bone->ascaleY, bone->ashearX, bone->ashearY); -} - -void spIkConstraint_apply2 (spBone* parent, spBone* child, float targetX, float targetY, int bendDir, float alpha) { - float px, py, psx, psy; - float cx, cy, csx, cwx, cwy; - int o1, o2, s2, u; - spBone* pp = parent->parent; - float tx, ty, dx, dy, l1, l2, a1, a2, r; - float id, x, y; - 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; 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; - } - id = 1 / (pp->a * pp->d - pp->b * pp->c); - x = targetX - pp->worldX; - y = targetY - pp->worldY; - tx = (x * pp->d - y * pp->b) * id - px; - ty = (y * pp->a - x * pp->c) * id - py; - x = cwx - pp->worldX; - y = cwy - pp->worldY; - dx = (x * pp->d - y * pp->b) * id - px; - dy = (y * pp->a - x * pp->c) * id - py; - l1 = SQRT(dx * dx + dy * dy); - l2 = child->data->length * csx; - if (u) { - float cosine, a, b; - l2 *= psx; - cosine = (tx * tx + ty * ty - l1 * l1 - l2 * l2) / (2 * l1 * l2); - if (cosine < -1) cosine = -1; - else if (cosine > 1) cosine = 1; - a2 = ACOS(cosine) * bendDir; - a = l1 + l2 * cosine; - b = l2 * SIN(a2); - a1 = ATAN2(ty * a - tx * b, tx * a + ty * b); - } else { - float a = psx * l2, b = psy * l2; - float aa = a * a, bb = b * b, ll = l1 * l1, dd = tx * tx + ty * ty, ta = ATAN2(ty, tx); - float c0 = bb * ll + aa * dd - aa * bb, c1 = -2 * bb * l1, c2 = bb - aa; - float 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, parent->ascaleX, 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); - } -} diff --git a/spine-cpp/spine-cpp/src/spine/IkConstraintData.c b/spine-cpp/spine-cpp/src/spine/IkConstraintData.c deleted file mode 100644 index b557cc58f..000000000 --- a/spine-cpp/spine-cpp/src/spine/IkConstraintData.c +++ /dev/null @@ -1,46 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#include -#include - -spIkConstraintData* spIkConstraintData_create (const char* name) { - spIkConstraintData* self = NEW(spIkConstraintData); - MALLOC_STR(self->name, name); - self->bendDirection = 1; - self->mix = 1; - return self; -} - -void spIkConstraintData_dispose (spIkConstraintData* self) { - FREE(self->name); - FREE(self->bones); - FREE(self); -} diff --git a/spine-cpp/spine-cpp/src/spine/Json.c b/spine-cpp/spine-cpp/src/spine/Json.c deleted file mode 100644 index 6225ff00c..000000000 --- a/spine-cpp/spine-cpp/src/spine/Json.c +++ /dev/null @@ -1,426 +0,0 @@ -/* - 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 -#include -#include /* strtod (C89), strtof (C99) */ -#include /* strcasecmp (4.4BSD - compatibility), _stricmp (_WIN32) */ -#include - -#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) { - char * endptr; - float n; - - /* Using strtod and strtof is slightly more permissive than RFC4627, - * accepting for example hex-encoded floating point, but either - * is often leagues faster than any manual implementation. - * - * We also already know that this starts with [-0-9] from parse_value. - */ -#if __STDC_VERSION__ >= 199901L - n = strtof(num, &endptr); -#else - n = (float)strtod( num, &endptr ); -#endif - /* ignore errno's ERANGE, which returns +/-HUGE_VAL */ - /* n is 0 on any other error */ - - if (endptr != num) { - /* Parse success, number found. */ - item->valueFloat = n; - item->valueInt = (int)n; - item->type = Json_Number; - return endptr; - } 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; -} diff --git a/spine-cpp/spine-cpp/src/spine/Json.h b/spine-cpp/spine-cpp/src/spine/Json.h deleted file mode 100644 index 078a5a715..000000000 --- a/spine-cpp/spine-cpp/src/spine/Json.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - 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_ */ diff --git a/spine-cpp/spine-cpp/src/spine/MeshAttachment.c b/spine-cpp/spine-cpp/src/spine/MeshAttachment.c deleted file mode 100644 index b7a49bfdc..000000000 --- a/spine-cpp/spine-cpp/src/spine/MeshAttachment.c +++ /dev/null @@ -1,100 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#include -#include - -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); -} - -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); - return self; -} - -void spMeshAttachment_updateUVs (spMeshAttachment* self) { - int i; - float width = self->regionU2 - self->regionU, height = self->regionV2 - self->regionV; - int verticesLength = SUPER(self)->worldVerticesLength; - FREE(self->uvs); - self->uvs = MALLOC(float, verticesLength); - if (self->regionRotate) { - for (i = 0; i < verticesLength; i += 2) { - self->uvs[i] = self->regionU + self->regionUVs[i + 1] * width; - self->uvs[i + 1] = self->regionV + height - self->regionUVs[i] * height; - } - } else { - for (i = 0; i < verticesLength; i += 2) { - self->uvs[i] = self->regionU + self->regionUVs[i] * width; - self->uvs[i + 1] = self->regionV + 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; - } -} diff --git a/spine-cpp/spine-cpp/src/spine/PathAttachment.c b/spine-cpp/spine-cpp/src/spine/PathAttachment.c deleted file mode 100644 index f81b3fd1c..000000000 --- a/spine-cpp/spine-cpp/src/spine/PathAttachment.c +++ /dev/null @@ -1,48 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#include -#include - -void _spPathAttachment_dispose (spAttachment* attachment) { - spPathAttachment* self = SUB_CAST(spPathAttachment, attachment); - - _spVertexAttachment_deinit(SUPER(self)); - - FREE(self->lengths); - FREE(self); -} - -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); - return self; -} diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraint.c b/spine-cpp/spine-cpp/src/spine/PathConstraint.c deleted file mode 100644 index fd4373dce..000000000 --- a/spine-cpp/spine-cpp/src/spine/PathConstraint.c +++ /dev/null @@ -1,467 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#include -#include -#include - -#define PATHCONSTRAINT_NONE -1 -#define PATHCONSTRAINT_BEFORE -2 -#define PATHCONSTRAINT_AFTER -3 - -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; - spPathAttachment* attachment = (spPathAttachment*)self->target->attachment; - spPathConstraintData* data = self->data; - spSpacingMode spacingMode = data->spacingMode; - int lengthSpacing = spacingMode == SP_SPACING_MODE_LENGTH; - 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 || lengthSpacing) { - if (scale) { - if (self->lengthsCount != boneCount) { - if (self->lengths) FREE(self->lengths); - self->lengths = MALLOC(float, boneCount); - self->lengthsCount = boneCount; - } - lengths = self->lengths; - } - for (i = 0, n = spacesCount - 1; i < n;) { - spBone* bone = bones[i]; - setupLength = bone->data->length; - if (setupLength == 0) setupLength = 0.000000001f; - 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, spacingMode == SP_SPACING_MODE_PERCENT); - 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)) p = 0.0001f; - 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) 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 = 0; 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; - if (percentSpacing) { - for (i = 0; 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; -} diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraintData.c b/spine-cpp/spine-cpp/src/spine/PathConstraintData.c deleted file mode 100644 index e0556cbe5..000000000 --- a/spine-cpp/spine-cpp/src/spine/PathConstraintData.c +++ /dev/null @@ -1,44 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#include -#include - -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); -} diff --git a/spine-cpp/spine-cpp/src/spine/PointAttachment.c b/spine-cpp/spine-cpp/src/spine/PointAttachment.c deleted file mode 100644 index 9a0139663..000000000 --- a/spine-cpp/spine-cpp/src/spine/PointAttachment.c +++ /dev/null @@ -1,61 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#include -#include - -void _spPointAttachment_dispose (spAttachment* attachment) { - spPathAttachment* self = SUB_CAST(spPathAttachment, attachment); - - _spVertexAttachment_deinit(SUPER(self)); - - FREE(self); -} - -spPointAttachment* spPointAttachment_create (const char* name) { - spPointAttachment* self = NEW(spPointAttachment); - _spVertexAttachment_init(SUPER(self)); - _spAttachment_init(SUPER(SUPER(self)), name, SP_ATTACHMENT_POINT, _spPointAttachment_dispose); - 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; -} diff --git a/spine-cpp/spine-cpp/src/spine/RegionAttachment.c b/spine-cpp/spine-cpp/src/spine/RegionAttachment.c deleted file mode 100644 index 56e981ede..000000000 --- a/spine-cpp/spine-cpp/src/spine/RegionAttachment.c +++ /dev/null @@ -1,130 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#include -#include - -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); -} - -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); - 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; -} diff --git a/spine-cpp/spine-cpp/src/spine/Skeleton.c b/spine-cpp/spine-cpp/src/spine/Skeleton.c deleted file mode 100644 index 7383b0c1d..000000000 --- a/spine-cpp/spine-cpp/src/spine/Skeleton.c +++ /dev/null @@ -1,583 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#include -#include -#include -#include - -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); - - 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->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; - _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); - 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; - _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) - bones[i]->sorted = 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->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 (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; -} - -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; -} diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonBinary.c b/spine-cpp/spine-cpp/src/spine/SkeletonBinary.c deleted file mode 100644 index d4e06bc25..000000000 --- a/spine-cpp/spine-cpp/src/spine/SkeletonBinary.c +++ /dev/null @@ -1,1095 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#include -#include -#include -#include -#include -#include "kvec.h" - -typedef struct { - const unsigned char* cursor; - const unsigned char* end; -} _dataInput; - -typedef struct { - const char* parent; - const char* skin; - int slotIndex; - spMeshAttachment* mesh; -} _spLinkedMesh; - -typedef struct { - spSkeletonBinary super; - int ownsLoader; - - int linkedMeshCount; - int linkedMeshCapacity; - _spLinkedMesh* linkedMeshes; -} _spSkeletonBinary; - -spSkeletonBinary* spSkeletonBinary_createWithLoader (spAttachmentLoader* attachmentLoader) { - spSkeletonBinary* self = SUPER(NEW(_spSkeletonBinary)); - self->scale = 1; - self->attachmentLoader = attachmentLoader; - return self; -} - -spSkeletonBinary* spSkeletonBinary_create (spAtlas* atlas) { - spAtlasAttachmentLoader* attachmentLoader = spAtlasAttachmentLoader_create(atlas); - spSkeletonBinary* self = spSkeletonBinary_createWithLoader(SUPER(attachmentLoader)); - SUB_CAST(_spSkeletonBinary, self)->ownsLoader = 1; - return self; -} - -void spSkeletonBinary_dispose (spSkeletonBinary* self) { - int i; - _spSkeletonBinary* internal = SUB_CAST(_spSkeletonBinary, self); - if (internal->ownsLoader) spAttachmentLoader_dispose(self->attachmentLoader); - for (i = 0; i < internal->linkedMeshCount; ++i) { - FREE(internal->linkedMeshes[i].parent); - FREE(internal->linkedMeshes[i].skin); - } - FREE(internal->linkedMeshes); - FREE(self->error); - FREE(self); -} - -void _spSkeletonBinary_setError (spSkeletonBinary* self, const char* value1, const char* value2) { - char message[256]; - int length; - FREE(self->error); - strcpy(message, value1); - length = (int)strlen(value1); - if (value2) strncat(message + length, value2, 255 - length); - MALLOC_STR(self->error, message); -} - -static unsigned char readByte (_dataInput* input) { - return *input->cursor++; -} - -static signed char readSByte (_dataInput* input) { - return (signed char)readByte(input); -} - -static int readBoolean (_dataInput* input) { - return readByte(input) != 0; -} - -static int readInt (_dataInput* input) { - int result = readByte(input); - result <<= 8; - result |= readByte(input); - result <<= 8; - result |= readByte(input); - result <<= 8; - result |= readByte(input); - return result; -} - -static int readVarint (_dataInput* input, int/*bool*/optimizePositive) { - unsigned char b = readByte(input); - int value = b & 0x7F; - if (b & 0x80) { - b = readByte(input); - value |= (b & 0x7F) << 7; - if (b & 0x80) { - b = readByte(input); - value |= (b & 0x7F) << 14; - if (b & 0x80) { - b = readByte(input); - value |= (b & 0x7F) << 21; - if (b & 0x80) value |= (readByte(input) & 0x7F) << 28; - } - } - } - if (!optimizePositive) value = (((unsigned int)value >> 1) ^ -(value & 1)); - return value; -} - -float readFloat (_dataInput* input) { - union { - int intValue; - float floatValue; - } intToFloat; - intToFloat.intValue = readInt(input); - return intToFloat.floatValue; -} - -char* readString (_dataInput* input) { - int length = readVarint(input, 1); - char* string; - if (length == 0) { - return 0; - } - string = MALLOC(char, length); - memcpy(string, input->cursor, length - 1); - input->cursor += length - 1; - string[length - 1] = '\0'; - return string; -} - -static void readColor (_dataInput* input, float *r, float *g, float *b, float *a) { - *r = readByte(input) / 255.0f; - *g = readByte(input) / 255.0f; - *b = readByte(input) / 255.0f; - *a = readByte(input) / 255.0f; -} - -#define ATTACHMENT_REGION 0 -#define ATTACHMENT_BOUNDING_BOX 1 -#define ATTACHMENT_MESH 2 -#define ATTACHMENT_LINKED_MESH 3 -#define ATTACHMENT_PATH 4 - -#define BLEND_MODE_NORMAL 0 -#define BLEND_MODE_ADDITIVE 1 -#define BLEND_MODE_MULTIPLY 2 -#define BLEND_MODE_SCREEN 3 - -#define CURVE_LINEAR 0 -#define CURVE_STEPPED 1 -#define CURVE_BEZIER 2 - -#define BONE_ROTATE 0 -#define BONE_TRANSLATE 1 -#define BONE_SCALE 2 -#define BONE_SHEAR 3 - -#define SLOT_ATTACHMENT 0 -#define SLOT_COLOR 1 -#define SLOT_TWO_COLOR 2 - -#define PATH_POSITION 0 -#define PATH_SPACING 1 -#define PATH_MIX 2 - -#define PATH_POSITION_FIXED 0 -#define PATH_POSITION_PERCENT 1 - -#define PATH_SPACING_LENGTH 0 -#define PATH_SPACING_FIXED 1 -#define PATH_SPACING_PERCENT 2 - -#define PATH_ROTATE_TANGENT 0 -#define PATH_ROTATE_CHAIN 1 -#define PATH_ROTATE_CHAIN_SCALE 2 - -static void readCurve (_dataInput* input, spCurveTimeline* timeline, int frameIndex) { - switch (readByte(input)) { - case CURVE_STEPPED: { - spCurveTimeline_setStepped(timeline, frameIndex); - break; - } - case CURVE_BEZIER: { - float cx1 = readFloat(input); - float cy1 = readFloat(input); - float cx2 = readFloat(input); - float cy2 = readFloat(input); - spCurveTimeline_setCurve(timeline, frameIndex, cx1, cy1, cx2, cy2); - break; - } - } -} - -static void _spSkeletonBinary_addLinkedMesh (spSkeletonBinary* self, spMeshAttachment* mesh, - const char* skin, int slotIndex, const char* parent) { - _spLinkedMesh* linkedMesh; - _spSkeletonBinary* internal = SUB_CAST(_spSkeletonBinary, self); - - if (internal->linkedMeshCount == internal->linkedMeshCapacity) { - _spLinkedMesh* linkedMeshes; - internal->linkedMeshCapacity *= 2; - if (internal->linkedMeshCapacity < 8) internal->linkedMeshCapacity = 8; - /* TODO Why not realloc? */ - linkedMeshes = MALLOC(_spLinkedMesh, internal->linkedMeshCapacity); - memcpy(linkedMeshes, internal->linkedMeshes, sizeof(_spLinkedMesh) * internal->linkedMeshCount); - FREE(internal->linkedMeshes); - internal->linkedMeshes = linkedMeshes; - } - - linkedMesh = internal->linkedMeshes + internal->linkedMeshCount++; - linkedMesh->mesh = mesh; - linkedMesh->skin = skin; - linkedMesh->slotIndex = slotIndex; - linkedMesh->parent = parent; -} - -static spAnimation* _spSkeletonBinary_readAnimation (spSkeletonBinary* self, const char* name, - _dataInput* input, spSkeletonData *skeletonData) { - kvec_t(spTimeline*) timelines; - float duration = 0; - int i, n, ii, nn, iii, nnn; - int frameIndex; - int drawOrderCount, eventCount; - spAnimation* animation; - - kv_init(timelines); - - /* Slot timelines. */ - for (i = 0, n = readVarint(input, 1); i < n; ++i) { - int slotIndex = readVarint(input, 1); - for (ii = 0, nn = readVarint(input, 1); ii < nn; ++ii) { - unsigned char timelineType = readByte(input); - int frameCount = readVarint(input, 1); - switch (timelineType) { - case SLOT_ATTACHMENT: { - spAttachmentTimeline* timeline = spAttachmentTimeline_create(frameCount); - timeline->slotIndex = slotIndex; - for (frameIndex = 0; frameIndex < frameCount; ++frameIndex) { - float time = readFloat(input); - const char* attachmentName = readString(input); - /* TODO Avoid copying of attachmentName inside */ - spAttachmentTimeline_setFrame(timeline, frameIndex, time, attachmentName); - FREE(attachmentName); - } - kv_push(spTimeline*, timelines, SUPER(timeline)); - duration = MAX(duration, timeline->frames[frameCount - 1]); - break; - } - case SLOT_COLOR: { - spColorTimeline* timeline = spColorTimeline_create(frameCount); - timeline->slotIndex = slotIndex; - for (frameIndex = 0; frameIndex < frameCount; ++frameIndex) { - float time = readFloat(input); - float r, g, b, a; - readColor(input, &r, &g, &b, &a); - spColorTimeline_setFrame(timeline, frameIndex, time, r, g, b, a); - if (frameIndex < frameCount - 1) readCurve(input, SUPER(timeline), frameIndex); - } - kv_push(spTimeline*, timelines, SUPER(SUPER(timeline))); - duration = MAX(duration, timeline->frames[(frameCount - 1) * COLOR_ENTRIES]); - break; - } - case SLOT_TWO_COLOR: { - spTwoColorTimeline* timeline = spTwoColorTimeline_create(frameCount); - timeline->slotIndex = slotIndex; - for (frameIndex = 0; frameIndex < frameCount; ++frameIndex) { - float time = readFloat(input); - float r, g, b, a; - float r2, g2, b2, a2; - readColor(input, &r, &g, &b, &a); - readColor(input, &a2, &r2, &g2, &b2); - spTwoColorTimeline_setFrame(timeline, frameIndex, time, r, g, b, a, r2, g2, b2); - if (frameIndex < frameCount - 1) readCurve(input, SUPER(timeline), frameIndex); - } - kv_push(spTimeline*, timelines, SUPER(SUPER(timeline))); - duration = MAX(duration, timeline->frames[(frameCount - 1) * TWOCOLOR_ENTRIES]); - break; - } - default: { - int i; - for (i = 0; i < kv_size(timelines); ++i) - spTimeline_dispose(kv_A(timelines, i)); - kv_destroy(timelines); - _spSkeletonBinary_setError(self, "Invalid timeline type for a slot: ", skeletonData->slots[slotIndex]->name); - return 0; - } - } - } - } - - /* Bone timelines. */ - for (i = 0, n = readVarint(input, 1); i < n; ++i) { - int boneIndex = readVarint(input, 1); - for (ii = 0, nn = readVarint(input, 1); ii < nn; ++ii) { - unsigned char timelineType = readByte(input); - int frameCount = readVarint(input, 1); - switch (timelineType) { - case BONE_ROTATE: { - spRotateTimeline *timeline = spRotateTimeline_create(frameCount); - timeline->boneIndex = boneIndex; - for (frameIndex = 0; frameIndex < frameCount; ++frameIndex) { - float time = readFloat(input); - float degrees = readFloat(input); - spRotateTimeline_setFrame(timeline, frameIndex, time, degrees); - if (frameIndex < frameCount - 1) readCurve(input, SUPER(timeline), frameIndex); - } - kv_push(spTimeline*, timelines, SUPER(SUPER(timeline))); - duration = MAX(duration, timeline->frames[(frameCount - 1) * ROTATE_ENTRIES]); - break; - } - case BONE_TRANSLATE: - case BONE_SCALE: - case BONE_SHEAR: { - float timelineScale = 1; - spTranslateTimeline *timeline = 0; - switch (timelineType) { - case BONE_SCALE: - timeline = spScaleTimeline_create(frameCount); - break; - case BONE_SHEAR: - timeline = spShearTimeline_create(frameCount); - break; - case BONE_TRANSLATE: - timeline = spTranslateTimeline_create(frameCount); - timelineScale = self->scale; - break; - default: - break; - } - timeline->boneIndex = boneIndex; - for (frameIndex = 0; frameIndex < frameCount; ++frameIndex) { - float time = readFloat(input); - float x = readFloat(input) * timelineScale; - float y = readFloat(input) * timelineScale; - spTranslateTimeline_setFrame(timeline, frameIndex, time, x, y); - if (frameIndex < frameCount - 1) readCurve(input, SUPER(timeline), frameIndex); - } - kv_push(spTimeline*, timelines, SUPER_CAST(spTimeline, timeline)); - duration = MAX(duration, timeline->frames[(frameCount - 1) * TRANSLATE_ENTRIES]); - break; - } - default: { - int i; - for (i = 0; i < kv_size(timelines); ++i) - spTimeline_dispose(kv_A(timelines, i)); - kv_destroy(timelines); - _spSkeletonBinary_setError(self, "Invalid timeline type for a bone: ", skeletonData->bones[boneIndex]->name); - return 0; - } - } - } - } - - /* IK constraint timelines. */ - for (i = 0, n = readVarint(input, 1); i < n; ++i) { - int index = readVarint(input, 1); - int frameCount = readVarint(input, 1); - spIkConstraintTimeline* timeline = spIkConstraintTimeline_create(frameCount); - timeline->ikConstraintIndex = index; - for (frameIndex = 0; frameIndex < frameCount; ++frameIndex) { - float time = readFloat(input); - float mix = readFloat(input); - signed char bendDirection = readSByte(input); - spIkConstraintTimeline_setFrame(timeline, frameIndex, time, mix, bendDirection); - if (frameIndex < frameCount - 1) readCurve(input, SUPER(timeline), frameIndex); - } - kv_push(spTimeline*, timelines, SUPER(SUPER(timeline))); - duration = MAX(duration, timeline->frames[(frameCount - 1) * IKCONSTRAINT_ENTRIES]); - } - - /* Transform constraint timelines. */ - for (i = 0, n = readVarint(input, 1); i < n; ++i) { - int index = readVarint(input, 1); - int frameCount = readVarint(input, 1); - spTransformConstraintTimeline* timeline = spTransformConstraintTimeline_create(frameCount); - timeline->transformConstraintIndex = index; - for (frameIndex = 0; frameIndex < frameCount; ++frameIndex) { - float time = readFloat(input); - float rotateMix = readFloat(input); - float translateMix = readFloat(input); - float scaleMix = readFloat(input); - float shearMix = readFloat(input); - spTransformConstraintTimeline_setFrame(timeline, frameIndex, time, rotateMix, translateMix, - scaleMix, shearMix); - if (frameIndex < frameCount - 1) readCurve(input, SUPER(timeline), frameIndex); - } - kv_push(spTimeline*, timelines, SUPER(SUPER(timeline))); - duration = MAX(duration, timeline->frames[(frameCount - 1) * TRANSFORMCONSTRAINT_ENTRIES]); - } - - /* Path constraint timelines. */ - for (i = 0, n = readVarint(input, 1); i < n; ++i) { - int index = readVarint(input, 1); - spPathConstraintData* data = skeletonData->pathConstraints[index]; - for (ii = 0, nn = readVarint(input, 1); ii < nn; ++ii) { - unsigned char timelineType = readByte(input); - int frameCount = readVarint(input, 1); - switch (timelineType) { - case PATH_POSITION: - case PATH_SPACING: { - spPathConstraintPositionTimeline* timeline = 0; - float timelineScale = 1; - if (timelineType == PATH_SPACING) { - timeline = (spPathConstraintPositionTimeline*)spPathConstraintSpacingTimeline_create(frameCount); - if (data->spacingMode == SP_SPACING_MODE_LENGTH || data->spacingMode == SP_SPACING_MODE_FIXED) - timelineScale = self->scale; - } else { - timeline = spPathConstraintPositionTimeline_create(frameCount); - if (data->positionMode == SP_POSITION_MODE_FIXED) - timelineScale = self->scale; - } - timeline->pathConstraintIndex = index; - for (frameIndex = 0; frameIndex < frameCount; ++frameIndex) { - float time = readFloat(input); - float value = readFloat(input) * timelineScale; - spPathConstraintPositionTimeline_setFrame(timeline, frameIndex, time, value); - if (frameIndex < frameCount - 1) readCurve(input, SUPER(timeline), frameIndex); - } - kv_push(spTimeline*, timelines, SUPER(SUPER(timeline))); - duration = MAX(duration, timeline->frames[(frameCount - 1) * PATHCONSTRAINTPOSITION_ENTRIES]); - break; - } - case PATH_MIX: { - spPathConstraintMixTimeline* timeline = spPathConstraintMixTimeline_create(frameCount); - timeline->pathConstraintIndex = index; - for (frameIndex = 0; frameIndex < frameCount; ++frameIndex) { - float time = readFloat(input); - float rotateMix = readFloat(input); - float translateMix = readFloat(input); - spPathConstraintMixTimeline_setFrame(timeline, frameIndex, time, rotateMix, translateMix); - if (frameIndex < frameCount - 1) readCurve(input, SUPER(timeline), frameIndex); - } - kv_push(spTimeline*, timelines, SUPER(SUPER(timeline))); - duration = MAX(duration, timeline->frames[(frameCount - 1) * PATHCONSTRAINTMIX_ENTRIES]); - } - } - } - } - - /* Deform timelines. */ - for (i = 0, n = readVarint(input, 1); i < n; ++i) { - spSkin* skin = skeletonData->skins[readVarint(input, 1)]; - for (ii = 0, nn = readVarint(input, 1); ii < nn; ++ii) { - int slotIndex = readVarint(input, 1); - for (iii = 0, nnn = readVarint(input, 1); iii < nnn; ++iii) { - float* tempDeform; - spDeformTimeline *timeline; - int weighted, deformLength; - const char* attachmentName = readString(input); - int frameCount; - - spVertexAttachment* attachment = SUB_CAST(spVertexAttachment, - spSkin_getAttachment(skin, slotIndex, attachmentName)); - if (!attachment) { - int i; - for (i = 0; i < kv_size(timelines); ++i) - spTimeline_dispose(kv_A(timelines, i)); - kv_destroy(timelines); - _spSkeletonBinary_setError(self, "Attachment not found: ", attachmentName); - FREE(attachmentName); - return 0; - } - FREE(attachmentName); - - weighted = attachment->bones != 0; - deformLength = weighted ? attachment->verticesCount / 3 * 2 : attachment->verticesCount; - tempDeform = MALLOC(float, deformLength); - - frameCount = readVarint(input, 1); - timeline = spDeformTimeline_create(frameCount, deformLength); - timeline->slotIndex = slotIndex; - timeline->attachment = SUPER(attachment); - - for (frameIndex = 0; frameIndex < frameCount; ++frameIndex) { - float time = readFloat(input); - float* deform; - int end = readVarint(input, 1); - if (!end) { - if (weighted) { - deform = tempDeform; - memset(deform, 0, sizeof(float) * deformLength); - } else - deform = attachment->vertices; - } else { - int v, start = readVarint(input, 1); - deform = tempDeform; - memset(deform, 0, sizeof(float) * start); - end += start; - if (self->scale == 1) { - for (v = start; v < end; ++v) - deform[v] = readFloat(input); - } else { - for (v = start; v < end; ++v) - deform[v] = readFloat(input) * self->scale; - } - memset(deform + v, 0, sizeof(float) * (deformLength - v)); - if (!weighted) { - float* vertices = attachment->vertices; - for (v = 0; v < deformLength; ++v) - deform[v] += vertices[v]; - } - } - spDeformTimeline_setFrame(timeline, frameIndex, time, deform); - if (frameIndex < frameCount - 1) readCurve(input, SUPER(timeline), frameIndex); - } - FREE(tempDeform); - - kv_push(spTimeline*, timelines, SUPER(SUPER(timeline))); - duration = MAX(duration, timeline->frames[frameCount - 1]); - } - } - } - - /* Draw order timeline. */ - drawOrderCount = readVarint(input, 1); - if (drawOrderCount) { - spDrawOrderTimeline* timeline = spDrawOrderTimeline_create(drawOrderCount, skeletonData->slotsCount); - for (i = 0; i < drawOrderCount; ++i) { - float time = readFloat(input); - int offsetCount = readVarint(input, 1); - int* drawOrder = MALLOC(int, skeletonData->slotsCount); - int* unchanged = MALLOC(int, skeletonData->slotsCount - offsetCount); - int originalIndex = 0, unchangedIndex = 0; - memset(drawOrder, -1, sizeof(int) * skeletonData->slotsCount); - for (ii = 0; ii < offsetCount; ++ii) { - int slotIndex = readVarint(input, 1); - /* Collect unchanged items. */ - while (originalIndex != slotIndex) - unchanged[unchangedIndex++] = originalIndex++; - /* Set changed items. */ - drawOrder[originalIndex + readVarint(input, 1)] = originalIndex; - ++originalIndex; - } - /* Collect remaining unchanged items. */ - while (originalIndex < skeletonData->slotsCount) - unchanged[unchangedIndex++] = originalIndex++; - /* Fill in unchanged items. */ - for (ii = skeletonData->slotsCount - 1; ii >= 0; ii--) - if (drawOrder[ii] == -1) drawOrder[ii] = unchanged[--unchangedIndex]; - FREE(unchanged); - /* TODO Avoid copying of drawOrder inside */ - spDrawOrderTimeline_setFrame(timeline, i, time, drawOrder); - FREE(drawOrder); - } - kv_push(spTimeline*, timelines, SUPER(timeline)); - duration = MAX(duration, timeline->frames[drawOrderCount - 1]); - } - - /* Event timeline. */ - eventCount = readVarint(input, 1); - if (eventCount) { - spEventTimeline* timeline = spEventTimeline_create(eventCount); - for (i = 0; i < eventCount; ++i) { - float time = readFloat(input); - spEventData* eventData = skeletonData->events[readVarint(input, 1)]; - spEvent* event = spEvent_create(time, eventData); - event->intValue = readVarint(input, 0); - event->floatValue = readFloat(input); - if (readBoolean(input)) - event->stringValue = readString(input); - else - MALLOC_STR(event->stringValue, eventData->stringValue); - spEventTimeline_setFrame(timeline, i, event); - } - kv_push(spTimeline*, timelines, SUPER(timeline)); - duration = MAX(duration, timeline->frames[eventCount - 1]); - } - - kv_trim(spTimeline*, timelines); - - animation = spAnimation_create(name, 0); - FREE(animation->timelines); - animation->duration = duration; - animation->timelinesCount = kv_size(timelines); - animation->timelines = kv_array(timelines); - return animation; -} - -static float* _readFloatArray(_dataInput *input, int n, float scale) { - float* array = MALLOC(float, n); - int i; - if (scale == 1) - for (i = 0; i < n; ++i) - array[i] = readFloat(input); - else - for (i = 0; i < n; ++i) - array[i] = readFloat(input) * scale; - return array; -} - -static short* _readShortArray(_dataInput *input, int *length) { - int n = readVarint(input, 1); - short* array = MALLOC(short, n); - int i; - *length = n; - for (i = 0; i < n; ++i) { - array[i] = readByte(input) << 8; - array[i] |= readByte(input); - } - return array; -} - -static void _readVertices(spSkeletonBinary* self, _dataInput* input, spVertexAttachment* attachment, - int vertexCount) { - int i, ii; - int verticesLength = vertexCount << 1; - kvec_t(float) weights; - kvec_t(int) bones; - - attachment->worldVerticesLength = verticesLength; - - if (!readBoolean(input)) { - attachment->verticesCount = verticesLength; - attachment->vertices = _readFloatArray(input, verticesLength, self->scale); - attachment->bonesCount = 0; - attachment->bones = 0; - return; - } - - kv_init(weights); - kv_resize(float, weights, verticesLength * 3 * 3); - - kv_init(bones); - kv_resize(int, bones, verticesLength * 3); - - for (i = 0; i < vertexCount; ++i) { - int boneCount = readVarint(input, 1); - kv_push(int, bones, boneCount); - for (ii = 0; ii < boneCount; ++ii) { - kv_push(int, bones, readVarint(input, 1)); - kv_push(float, weights, readFloat(input) * self->scale); - kv_push(float, weights, readFloat(input) * self->scale); - kv_push(float, weights, readFloat(input)); - } - } - - kv_trim(float, weights); - attachment->verticesCount = kv_size(weights); - attachment->vertices = kv_array(weights); - - kv_trim(int, bones); - attachment->bonesCount = kv_size(bones); - attachment->bones = kv_array(bones); -} - -spAttachment* spSkeletonBinary_readAttachment(spSkeletonBinary* self, _dataInput* input, - spSkin* skin, int slotIndex, const char* attachmentName, spSkeletonData* skeletonData, int/*bool*/ nonessential) { - int i; - spAttachmentType type; - const char* name = readString(input); - int freeName = name != 0; - if (!name) { - freeName = 0; - name = attachmentName; - } - - type = (spAttachmentType)readByte(input); - - switch (type) { - case SP_ATTACHMENT_REGION: { - const char* path = readString(input); - spAttachment* attachment; - spRegionAttachment* region; - if (!path) MALLOC_STR(path, name); - attachment = spAttachmentLoader_createAttachment(self->attachmentLoader, skin, type, name, path); - region = SUB_CAST(spRegionAttachment, attachment); - region->path = path; - region->rotation = readFloat(input); - region->x = readFloat(input) * self->scale; - region->y = readFloat(input) * self->scale; - region->scaleX = readFloat(input); - region->scaleY = readFloat(input); - region->width = readFloat(input) * self->scale; - region->height = readFloat(input) * self->scale; - readColor(input, ®ion->color.r, ®ion->color.g, ®ion->color.b, ®ion->color.a); - spRegionAttachment_updateOffset(region); - spAttachmentLoader_configureAttachment(self->attachmentLoader, attachment); - if (freeName) FREE(name); - return attachment; - } - case SP_ATTACHMENT_BOUNDING_BOX: { - int vertexCount = readVarint(input, 1); - spAttachment* attachment = spAttachmentLoader_createAttachment(self->attachmentLoader, skin, type, name, 0); - _readVertices(self, input, SUB_CAST(spVertexAttachment, attachment), vertexCount); - if (nonessential) readInt(input); /* Skip color. */ - spAttachmentLoader_configureAttachment(self->attachmentLoader, attachment); - if (freeName) FREE(name); - return attachment; - } - case SP_ATTACHMENT_MESH: { - int vertexCount; - spAttachment* attachment; - spMeshAttachment* mesh; - const char* path = readString(input); - if (!path) MALLOC_STR(path, name); - attachment = spAttachmentLoader_createAttachment(self->attachmentLoader, skin, type, name, path); - mesh = SUB_CAST(spMeshAttachment, attachment); - mesh->path = path; - readColor(input, &mesh->color.r, &mesh->color.g, &mesh->color.b, &mesh->color.a); - vertexCount = readVarint(input, 1); - mesh->regionUVs = _readFloatArray(input, vertexCount << 1, 1); - mesh->triangles = (unsigned short*)_readShortArray(input, &mesh->trianglesCount); - _readVertices(self, input, SUPER(mesh), vertexCount); - spMeshAttachment_updateUVs(mesh); - mesh->hullLength = readVarint(input, 1) << 1; - if (nonessential) { - mesh->edges = (int*)_readShortArray(input, &mesh->edgesCount); - mesh->width = readFloat(input) * self->scale; - mesh->height = readFloat(input) * self->scale; - } else { - mesh->edges = 0; - mesh->width = 0; - mesh->height = 0; - } - spAttachmentLoader_configureAttachment(self->attachmentLoader, attachment); - if (freeName) FREE(name); - return attachment; - } - case SP_ATTACHMENT_LINKED_MESH: { - const char* skinName; - const char* parent; - spAttachment* attachment; - spMeshAttachment* mesh; - const char* path = readString(input); - if (!path) MALLOC_STR(path, name); - attachment = spAttachmentLoader_createAttachment(self->attachmentLoader, skin, type, name, path); - mesh = SUB_CAST(spMeshAttachment, attachment); - mesh->path = path; - readColor(input, &mesh->color.r, &mesh->color.g, &mesh->color.b, &mesh->color.a); - skinName = readString(input); - parent = readString(input); - mesh->inheritDeform = readBoolean(input); - if (nonessential) { - mesh->width = readFloat(input) * self->scale; - mesh->height = readFloat(input) * self->scale; - } - _spSkeletonBinary_addLinkedMesh(self, mesh, skinName, slotIndex, parent); - if (freeName) FREE(name); - return attachment; - } - case SP_ATTACHMENT_PATH: { - spAttachment* attachment = spAttachmentLoader_createAttachment(self->attachmentLoader, skin, type, name, 0); - spPathAttachment* path = SUB_CAST(spPathAttachment, attachment); - int vertexCount = 0; - path->closed = readBoolean(input); - path->constantSpeed = readBoolean(input); - vertexCount = readVarint(input, 1); - _readVertices(self, input, SUPER(path), vertexCount); - path->lengthsLength = vertexCount / 3; - path->lengths = MALLOC(float, path->lengthsLength); - for (i = 0; i < path->lengthsLength; ++i) { - path->lengths[i] = readFloat(input) * self->scale; - } - if (nonessential) readInt(input); /* Skip color. */ - if (freeName) FREE(name); - return attachment; - } - case SP_ATTACHMENT_POINT: { - spAttachment* attachment = spAttachmentLoader_createAttachment(self->attachmentLoader, skin, type, name, 0); - spPointAttachment* point = SUB_CAST(spPointAttachment, attachment); - point->rotation = readFloat(input); - point->x = readFloat(input) * self->scale; - point->y = readFloat(input) * self->scale; - - if (nonessential) { - readColor(input, &point->color.r, &point->color.g, &point->color.b, &point->color.a); - } - return attachment; - } - case SP_ATTACHMENT_CLIPPING: { - int endSlotIndex = readVarint(input, 1); - int vertexCount = readVarint(input, 1); - spAttachment* attachment = spAttachmentLoader_createAttachment(self->attachmentLoader, skin, type, name, 0); - spClippingAttachment* clip = SUB_CAST(spClippingAttachment, attachment); - _readVertices(self, input, SUB_CAST(spVertexAttachment, attachment), vertexCount); - if (nonessential) readInt(input); /* Skip color. */ - clip->endSlot = skeletonData->slots[endSlotIndex]; - spAttachmentLoader_configureAttachment(self->attachmentLoader, attachment); - if (freeName) FREE(name); - return attachment; - } - } - - if (freeName) FREE(name); - return 0; -} - -spSkin* spSkeletonBinary_readSkin(spSkeletonBinary* self, _dataInput* input, - const char* skinName, spSkeletonData* skeletonData, int/*bool*/ nonessential) { - spSkin* skin; - int slotCount = readVarint(input, 1); - int i, ii, nn; - if (slotCount == 0) - return 0; - skin = spSkin_create(skinName); - for (i = 0; i < slotCount; ++i) { - int slotIndex = readVarint(input, 1); - for (ii = 0, nn = readVarint(input, 1); ii < nn; ++ii) { - const char* name = readString(input); - spAttachment* attachment = spSkeletonBinary_readAttachment(self, input, skin, slotIndex, name, skeletonData, nonessential); - if (attachment) spSkin_addAttachment(skin, slotIndex, name, attachment); - FREE(name); - } - } - return skin; -} - -spSkeletonData* spSkeletonBinary_readSkeletonDataFile (spSkeletonBinary* self, const char* path) { - int length; - spSkeletonData* skeletonData; - const char* binary = _spUtil_readFile(path, &length); - if (length == 0 || !binary) { - _spSkeletonBinary_setError(self, "Unable to read skeleton file: ", path); - return 0; - } - skeletonData = spSkeletonBinary_readSkeletonData(self, (unsigned char*)binary, length); - FREE(binary); - return skeletonData; -} - -spSkeletonData* spSkeletonBinary_readSkeletonData (spSkeletonBinary* self, const unsigned char* binary, - const int length) { - int i, ii, nonessential; - spSkeletonData* skeletonData; - _spSkeletonBinary* internal = SUB_CAST(_spSkeletonBinary, self); - - _dataInput* input = NEW(_dataInput); - input->cursor = binary; - input->end = binary + length; - - FREE(self->error); - CONST_CAST(char*, self->error) = 0; - internal->linkedMeshCount = 0; - - skeletonData = spSkeletonData_create(); - - skeletonData->hash = readString(input); - if (!strlen(skeletonData->hash)) { - FREE(skeletonData->hash); - skeletonData->hash = 0; - } - - skeletonData->version = readString(input); - if (!strlen(skeletonData->version)) { - FREE(skeletonData->version); - skeletonData->version = 0; - } - - skeletonData->width = readFloat(input); - skeletonData->height = readFloat(input); - - nonessential = readBoolean(input); - - if (nonessential) { - /* Skip images path & fps */ - readFloat(input); - FREE(readString(input)); - } - - /* Bones. */ - skeletonData->bonesCount = readVarint(input, 1); - skeletonData->bones = MALLOC(spBoneData*, skeletonData->bonesCount); - for (i = 0; i < skeletonData->bonesCount; ++i) { - spBoneData* data; - int mode; - const char* name = readString(input); - spBoneData* parent = i == 0 ? 0 : skeletonData->bones[readVarint(input, 1)]; - /* TODO Avoid copying of name */ - data = spBoneData_create(i, name, parent); - FREE(name); - data->rotation = readFloat(input); - data->x = readFloat(input) * self->scale; - data->y = readFloat(input) * self->scale; - data->scaleX = readFloat(input); - data->scaleY = readFloat(input); - data->shearX = readFloat(input); - data->shearY = readFloat(input); - data->length = readFloat(input) * self->scale; - mode = readVarint(input, 1); - switch (mode) { - case 0: data->transformMode = SP_TRANSFORMMODE_NORMAL; break; - case 1: data->transformMode = SP_TRANSFORMMODE_ONLYTRANSLATION; break; - case 2: data->transformMode = SP_TRANSFORMMODE_NOROTATIONORREFLECTION; break; - case 3: data->transformMode = SP_TRANSFORMMODE_NOSCALE; break; - case 4: data->transformMode = SP_TRANSFORMMODE_NOSCALEORREFLECTION; break; - } - if (nonessential) readInt(input); /* Skip bone color. */ - skeletonData->bones[i] = data; - } - - /* Slots. */ - skeletonData->slotsCount = readVarint(input, 1); - skeletonData->slots = MALLOC(spSlotData*, skeletonData->slotsCount); - for (i = 0; i < skeletonData->slotsCount; ++i) { - int r, g, b, a; - const char* slotName = readString(input); - spBoneData* boneData = skeletonData->bones[readVarint(input, 1)]; - /* TODO Avoid copying of slotName */ - spSlotData* slotData = spSlotData_create(i, slotName, boneData); - FREE(slotName); - readColor(input, &slotData->color.r, &slotData->color.g, &slotData->color.b, &slotData->color.a); - r = readByte(input); - g = readByte(input); - b = readByte(input); - a = readByte(input); - if (!(r == 0xff && g == 0xff && b == 0xff && a == 0xff)) { - slotData->darkColor = spColor_create(); - spColor_setFromFloats(slotData->darkColor, r / 255.0f, g / 255.0f, b / 255.0f, 1); - } - slotData->attachmentName = readString(input); - slotData->blendMode = (spBlendMode)readVarint(input, 1); - skeletonData->slots[i] = slotData; - } - - /* IK constraints. */ - skeletonData->ikConstraintsCount = readVarint(input, 1); - skeletonData->ikConstraints = MALLOC(spIkConstraintData*, skeletonData->ikConstraintsCount); - for (i = 0; i < skeletonData->ikConstraintsCount; ++i) { - const char* name = readString(input); - /* TODO Avoid copying of name */ - spIkConstraintData* data = spIkConstraintData_create(name); - data->order = readVarint(input, 1); - FREE(name); - data->bonesCount = readVarint(input, 1); - data->bones = MALLOC(spBoneData*, data->bonesCount); - for (ii = 0; ii < data->bonesCount; ++ii) - data->bones[ii] = skeletonData->bones[readVarint(input, 1)]; - data->target = skeletonData->bones[readVarint(input, 1)]; - data->mix = readFloat(input); - data->bendDirection = readSByte(input); - skeletonData->ikConstraints[i] = data; - } - - /* Transform constraints. */ - skeletonData->transformConstraintsCount = readVarint(input, 1); - skeletonData->transformConstraints = MALLOC( - spTransformConstraintData*, skeletonData->transformConstraintsCount); - for (i = 0; i < skeletonData->transformConstraintsCount; ++i) { - const char* name = readString(input); - /* TODO Avoid copying of name */ - spTransformConstraintData* data = spTransformConstraintData_create(name); - data->order = readVarint(input, 1); - FREE(name); - data->bonesCount = readVarint(input, 1); - CONST_CAST(spBoneData**, data->bones) = MALLOC(spBoneData*, data->bonesCount); - for (ii = 0; ii < data->bonesCount; ++ii) - data->bones[ii] = skeletonData->bones[readVarint(input, 1)]; - data->target = skeletonData->bones[readVarint(input, 1)]; - data->local = readBoolean(input); - data->relative = readBoolean(input); - data->offsetRotation = readFloat(input); - data->offsetX = readFloat(input) * self->scale; - data->offsetY = readFloat(input) * self->scale; - data->offsetScaleX = readFloat(input); - data->offsetScaleY = readFloat(input); - data->offsetShearY = readFloat(input); - data->rotateMix = readFloat(input); - data->translateMix = readFloat(input); - data->scaleMix = readFloat(input); - data->shearMix = readFloat(input); - skeletonData->transformConstraints[i] = data; - } - - /* Path constraints */ - skeletonData->pathConstraintsCount = readVarint(input, 1); - skeletonData->pathConstraints = MALLOC(spPathConstraintData*, skeletonData->pathConstraintsCount); - for (i = 0; i < skeletonData->pathConstraintsCount; ++i) { - const char* name = readString(input); - /* TODO Avoid copying of name */ - spPathConstraintData* data = spPathConstraintData_create(name); - data->order = readVarint(input, 1); - FREE(name); - data->bonesCount = readVarint(input, 1); - CONST_CAST(spBoneData**, data->bones) = MALLOC(spBoneData*, data->bonesCount); - for (ii = 0; ii < data->bonesCount; ++ii) - data->bones[ii] = skeletonData->bones[readVarint(input, 1)]; - data->target = skeletonData->slots[readVarint(input, 1)]; - data->positionMode = (spPositionMode)readVarint(input, 1); - data->spacingMode = (spSpacingMode)readVarint(input, 1); - data->rotateMode = (spRotateMode)readVarint(input, 1); - data->offsetRotation = readFloat(input); - data->position = readFloat(input); - if (data->positionMode == SP_POSITION_MODE_FIXED) data->position *= self->scale; - data->spacing = readFloat(input); - if (data->spacingMode == SP_SPACING_MODE_LENGTH || data->spacingMode == SP_SPACING_MODE_FIXED) data->spacing *= self->scale; - data->rotateMix = readFloat(input); - data->translateMix = readFloat(input); - skeletonData->pathConstraints[i] = data; - } - - /* Default skin. */ - skeletonData->defaultSkin = spSkeletonBinary_readSkin(self, input, "default", skeletonData, nonessential); - skeletonData->skinsCount = readVarint(input, 1); - - if (skeletonData->defaultSkin) - ++skeletonData->skinsCount; - - skeletonData->skins = MALLOC(spSkin*, skeletonData->skinsCount); - - if (skeletonData->defaultSkin) - skeletonData->skins[0] = skeletonData->defaultSkin; - - /* Skins. */ - for (i = skeletonData->defaultSkin ? 1 : 0; i < skeletonData->skinsCount; ++i) { - const char* skinName = readString(input); - /* TODO Avoid copying of skinName */ - skeletonData->skins[i] = spSkeletonBinary_readSkin(self, input, skinName, skeletonData, nonessential); - FREE(skinName); - } - - /* Linked meshes. */ - for (i = 0; i < internal->linkedMeshCount; ++i) { - _spLinkedMesh* linkedMesh = internal->linkedMeshes + i; - spSkin* skin = !linkedMesh->skin ? skeletonData->defaultSkin : spSkeletonData_findSkin(skeletonData, linkedMesh->skin); - spAttachment* parent; - if (!skin) { - FREE(input); - spSkeletonData_dispose(skeletonData); - _spSkeletonBinary_setError(self, "Skin not found: ", linkedMesh->skin); - return 0; - } - parent = spSkin_getAttachment(skin, linkedMesh->slotIndex, linkedMesh->parent); - if (!parent) { - FREE(input); - spSkeletonData_dispose(skeletonData); - _spSkeletonBinary_setError(self, "Parent mesh not found: ", linkedMesh->parent); - return 0; - } - spMeshAttachment_setParentMesh(linkedMesh->mesh, SUB_CAST(spMeshAttachment, parent)); - spMeshAttachment_updateUVs(linkedMesh->mesh); - spAttachmentLoader_configureAttachment(self->attachmentLoader, SUPER(SUPER(linkedMesh->mesh))); - } - - /* Events. */ - skeletonData->eventsCount = readVarint(input, 1); - skeletonData->events = MALLOC(spEventData*, skeletonData->eventsCount); - for (i = 0; i < skeletonData->eventsCount; ++i) { - const char* name = readString(input); - /* TODO Avoid copying of skinName */ - spEventData* eventData = spEventData_create(name); - FREE(name); - eventData->intValue = readVarint(input, 0); - eventData->floatValue = readFloat(input); - eventData->stringValue = readString(input); - skeletonData->events[i] = eventData; - } - - /* Animations. */ - skeletonData->animationsCount = readVarint(input, 1); - skeletonData->animations = MALLOC(spAnimation*, skeletonData->animationsCount); - for (i = 0; i < skeletonData->animationsCount; ++i) { - const char* name = readString(input); - spAnimation* animation = _spSkeletonBinary_readAnimation(self, name, input, skeletonData); - FREE(name); - if (!animation) { - FREE(input); - spSkeletonData_dispose(skeletonData); - return 0; - } - skeletonData->animations[i] = animation; - } - - FREE(input); - return skeletonData; -} diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonBounds.c b/spine-cpp/spine-cpp/src/spine/SkeletonBounds.c deleted file mode 100644 index bb4eb40d0..000000000 --- a/spine-cpp/spine-cpp/src/spine/SkeletonBounds.c +++ /dev/null @@ -1,205 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#include -#include -#include - -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; - - spSlot* slot = skeleton->slots[i]; - spAttachment* 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; -} diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonClipping.c b/spine-cpp/spine-cpp/src/spine/SkeletonClipping.c deleted file mode 100644 index a46dea73e..000000000 --- a/spine-cpp/spine-cpp/src/spine/SkeletonClipping.c +++ /dev/null @@ -1,313 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#include -#include - -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 ua; - if (side2) { - spFloatArray_add(output, inputX2); - spFloatArray_add(output, inputY2); - continue; - } - c0 = inputY2 - inputY, c2 = inputX2 - inputX; - ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / (c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY)); - spFloatArray_add(output, edgeX + (edgeX2 - edgeX) * ua); - spFloatArray_add(output, edgeY + (edgeY2 - edgeY) * ua); - } else if (side2) { - float c0 = inputY2 - inputY, c2 = inputX2 - inputX; - float ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / (c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY)); - spFloatArray_add(output, edgeX + (edgeX2 - edgeX) * ua); - spFloatArray_add(output, edgeY + (edgeY2 - edgeY) * ua); - 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; - } - } - } -} diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonData.c b/spine-cpp/spine-cpp/src/spine/SkeletonData.c deleted file mode 100644 index 9db2c0306..000000000 --- a/spine-cpp/spine-cpp/src/spine/SkeletonData.c +++ /dev/null @@ -1,147 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#include -#include -#include - -spSkeletonData* spSkeletonData_create () { - return NEW(spSkeletonData); -} - -void spSkeletonData_dispose (spSkeletonData* self) { - int i; - 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; -} diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonJson.c b/spine-cpp/spine-cpp/src/spine/SkeletonJson.c deleted file mode 100644 index c6136c66c..000000000 --- a/spine-cpp/spine-cpp/src/spine/SkeletonJson.c +++ /dev/null @@ -1,1119 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#include -#include -#include -#include "Json.h" -#include -#include -#include - -#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__) -#define strdup _strdup -#endif - -typedef struct { - const char* parent; - const char* skin; - int slotIndex; - spMeshAttachment* mesh; -} _spLinkedMesh; - -typedef struct { - spSkeletonJson super; - int ownsLoader; - - int linkedMeshCount; - int linkedMeshCapacity; - _spLinkedMesh* linkedMeshes; -} _spSkeletonJson; - -spSkeletonJson* spSkeletonJson_createWithLoader (spAttachmentLoader* attachmentLoader) { - spSkeletonJson* self = SUPER(NEW(_spSkeletonJson)); - self->scale = 1; - self->attachmentLoader = attachmentLoader; - return self; -} - -spSkeletonJson* spSkeletonJson_create (spAtlas* atlas) { - spAtlasAttachmentLoader* attachmentLoader = spAtlasAttachmentLoader_create(atlas); - spSkeletonJson* self = spSkeletonJson_createWithLoader(SUPER(attachmentLoader)); - SUB_CAST(_spSkeletonJson, self)->ownsLoader = 1; - return self; -} - -void spSkeletonJson_dispose (spSkeletonJson* self) { - _spSkeletonJson* internal = SUB_CAST(_spSkeletonJson, self); - if (internal->ownsLoader) spAttachmentLoader_dispose(self->attachmentLoader); - FREE(internal->linkedMeshes); - FREE(self->error); - FREE(self); -} - -void _spSkeletonJson_setError (spSkeletonJson* self, Json* root, const char* value1, const char* value2) { - char message[256]; - int length; - FREE(self->error); - strcpy(message, value1); - length = (int)strlen(value1); - if (value2) strncat(message + length, value2, 255 - length); - MALLOC_STR(self->error, message); - if (root) Json_dispose(root); -} - -static float toColor (const char* value, int index) { - char digits[3]; - char *error; - int color; - - if (strlen(value) / 2 < index) return -1; - value += index * 2; - - digits[0] = *value; - digits[1] = *(value + 1); - digits[2] = '\0'; - color = (int)strtoul(digits, &error, 16); - if (*error != 0) return -1; - return color / (float)255; -} - -static void readCurve (Json* frame, spCurveTimeline* timeline, int frameIndex) { - Json* curve = Json_getItem(frame, "curve"); - if (!curve) return; - if (curve->type == Json_String && strcmp(curve->valueString, "stepped") == 0) - spCurveTimeline_setStepped(timeline, frameIndex); - else if (curve->type == Json_Array) { - Json* child0 = curve->child; - Json* child1 = child0->next; - Json* child2 = child1->next; - Json* child3 = child2->next; - spCurveTimeline_setCurve(timeline, frameIndex, child0->valueFloat, child1->valueFloat, child2->valueFloat, - child3->valueFloat); - } -} - -static void _spSkeletonJson_addLinkedMesh (spSkeletonJson* self, spMeshAttachment* mesh, const char* skin, int slotIndex, - const char* parent) { - _spLinkedMesh* linkedMesh; - _spSkeletonJson* internal = SUB_CAST(_spSkeletonJson, self); - - if (internal->linkedMeshCount == internal->linkedMeshCapacity) { - _spLinkedMesh* linkedMeshes; - internal->linkedMeshCapacity *= 2; - if (internal->linkedMeshCapacity < 8) internal->linkedMeshCapacity = 8; - linkedMeshes = MALLOC(_spLinkedMesh, internal->linkedMeshCapacity); - memcpy(linkedMeshes, internal->linkedMeshes, sizeof(_spLinkedMesh) * internal->linkedMeshCount); - FREE(internal->linkedMeshes); - internal->linkedMeshes = linkedMeshes; - } - - linkedMesh = internal->linkedMeshes + internal->linkedMeshCount++; - linkedMesh->mesh = mesh; - linkedMesh->skin = skin; - linkedMesh->slotIndex = slotIndex; - linkedMesh->parent = parent; -} - -static spAnimation* _spSkeletonJson_readAnimation (spSkeletonJson* self, Json* root, spSkeletonData *skeletonData) { - int frameIndex; - spAnimation* animation; - Json* valueMap; - int timelinesCount = 0; - - Json* bones = Json_getItem(root, "bones"); - Json* slots = Json_getItem(root, "slots"); - Json* ik = Json_getItem(root, "ik"); - Json* transform = Json_getItem(root, "transform"); - Json* paths = Json_getItem(root, "paths"); - Json* deform = Json_getItem(root, "deform"); - Json* drawOrder = Json_getItem(root, "drawOrder"); - Json* events = Json_getItem(root, "events"); - Json *boneMap, *slotMap, *constraintMap; - if (!drawOrder) drawOrder = Json_getItem(root, "draworder"); - - for (boneMap = bones ? bones->child : 0; boneMap; boneMap = boneMap->next) - timelinesCount += boneMap->size; - for (slotMap = slots ? slots->child : 0; slotMap; slotMap = slotMap->next) - timelinesCount += slotMap->size; - timelinesCount += ik ? ik->size : 0; - timelinesCount += transform ? transform->size : 0; - for (constraintMap = paths ? paths->child : 0; constraintMap; constraintMap = constraintMap->next) - timelinesCount += constraintMap->size; - for (constraintMap = deform ? deform->child : 0; constraintMap; constraintMap = constraintMap->next) - for (slotMap = constraintMap->child; slotMap; slotMap = slotMap->next) - timelinesCount += slotMap->size; - if (drawOrder) ++timelinesCount; - if (events) ++timelinesCount; - - animation = spAnimation_create(root->name, timelinesCount); - animation->timelinesCount = 0; - - /* Slot timelines. */ - for (slotMap = slots ? slots->child : 0; slotMap; slotMap = slotMap->next) { - Json *timelineMap; - - int slotIndex = spSkeletonData_findSlotIndex(skeletonData, slotMap->name); - if (slotIndex == -1) { - spAnimation_dispose(animation); - _spSkeletonJson_setError(self, root, "Slot not found: ", slotMap->name); - return 0; - } - - for (timelineMap = slotMap->child; timelineMap; timelineMap = timelineMap->next) { - if (strcmp(timelineMap->name, "attachment") == 0) { - spAttachmentTimeline *timeline = spAttachmentTimeline_create(timelineMap->size); - timeline->slotIndex = slotIndex; - - for (valueMap = timelineMap->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) { - Json* name = Json_getItem(valueMap, "name"); - spAttachmentTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), - name->type == Json_NULL ? 0 : name->valueString); - } - animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); - animation->duration = MAX(animation->duration, timeline->frames[timelineMap->size - 1]); - - } else if (strcmp(timelineMap->name, "color") == 0) { - spColorTimeline *timeline = spColorTimeline_create(timelineMap->size); - timeline->slotIndex = slotIndex; - - for (valueMap = timelineMap->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) { - const char* s = Json_getString(valueMap, "color", 0); - spColorTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), toColor(s, 0), toColor(s, 1), toColor(s, 2), - toColor(s, 3)); - readCurve(valueMap, SUPER(timeline), frameIndex); - } - animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); - animation->duration = MAX(animation->duration, timeline->frames[(timelineMap->size - 1) * COLOR_ENTRIES]); - - } else if (strcmp(timelineMap->name, "twoColor") == 0) { - spTwoColorTimeline *timeline = spTwoColorTimeline_create(timelineMap->size); - timeline->slotIndex = slotIndex; - - for (valueMap = timelineMap->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) { - const char* s = Json_getString(valueMap, "light", 0); - const char* ds = Json_getString(valueMap, "dark", 0); - spTwoColorTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), toColor(s, 0), toColor(s, 1), toColor(s, 2), - toColor(s, 3), toColor(ds, 0), toColor(ds, 1), toColor(ds, 2)); - readCurve(valueMap, SUPER(timeline), frameIndex); - } - animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); - animation->duration = MAX(animation->duration, timeline->frames[(timelineMap->size - 1) * TWOCOLOR_ENTRIES]); - - } else { - spAnimation_dispose(animation); - _spSkeletonJson_setError(self, 0, "Invalid timeline type for a slot: ", timelineMap->name); - return 0; - } - } - } - - /* Bone timelines. */ - for (boneMap = bones ? bones->child : 0; boneMap; boneMap = boneMap->next) { - Json *timelineMap; - - int boneIndex = spSkeletonData_findBoneIndex(skeletonData, boneMap->name); - if (boneIndex == -1) { - spAnimation_dispose(animation); - _spSkeletonJson_setError(self, root, "Bone not found: ", boneMap->name); - return 0; - } - - for (timelineMap = boneMap->child; timelineMap; timelineMap = timelineMap->next) { - if (strcmp(timelineMap->name, "rotate") == 0) { - spRotateTimeline *timeline = spRotateTimeline_create(timelineMap->size); - timeline->boneIndex = boneIndex; - - for (valueMap = timelineMap->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) { - spRotateTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), Json_getFloat(valueMap, "angle", 0)); - readCurve(valueMap, SUPER(timeline), frameIndex); - } - animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); - animation->duration = MAX(animation->duration, timeline->frames[(timelineMap->size - 1) * ROTATE_ENTRIES]); - - } else { - int isScale = strcmp(timelineMap->name, "scale") == 0; - int isTranslate = strcmp(timelineMap->name, "translate") == 0; - int isShear = strcmp(timelineMap->name, "shear") == 0; - if (isScale || isTranslate || isShear) { - float timelineScale = isTranslate ? self->scale: 1; - spTranslateTimeline *timeline = 0; - if (isScale) timeline = spScaleTimeline_create(timelineMap->size); - else if (isTranslate) timeline = spTranslateTimeline_create(timelineMap->size); - else if (isShear) timeline = spShearTimeline_create(timelineMap->size); - timeline->boneIndex = boneIndex; - - for (valueMap = timelineMap->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) { - spTranslateTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), Json_getFloat(valueMap, "x", 0) * timelineScale, - Json_getFloat(valueMap, "y", 0) * timelineScale); - readCurve(valueMap, SUPER(timeline), frameIndex); - } - animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); - animation->duration = MAX(animation->duration, timeline->frames[(timelineMap->size - 1) * TRANSLATE_ENTRIES]); - - } else { - spAnimation_dispose(animation); - _spSkeletonJson_setError(self, 0, "Invalid timeline type for a bone: ", timelineMap->name); - return 0; - } - } - } - } - - /* IK constraint timelines. */ - for (constraintMap = ik ? ik->child : 0; constraintMap; constraintMap = constraintMap->next) { - spIkConstraintData* constraint = spSkeletonData_findIkConstraint(skeletonData, constraintMap->name); - spIkConstraintTimeline* timeline = spIkConstraintTimeline_create(constraintMap->size); - for (frameIndex = 0; frameIndex < skeletonData->ikConstraintsCount; ++frameIndex) { - if (constraint == skeletonData->ikConstraints[frameIndex]) { - timeline->ikConstraintIndex = frameIndex; - break; - } - } - for (valueMap = constraintMap->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) { - spIkConstraintTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), Json_getFloat(valueMap, "mix", 1), - Json_getInt(valueMap, "bendPositive", 1) ? 1 : -1); - readCurve(valueMap, SUPER(timeline), frameIndex); - } - animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); - animation->duration = MAX(animation->duration, timeline->frames[(constraintMap->size - 1) * IKCONSTRAINT_ENTRIES]); - } - - /* Transform constraint timelines. */ - for (constraintMap = transform ? transform->child : 0; constraintMap; constraintMap = constraintMap->next) { - spTransformConstraintData* constraint = spSkeletonData_findTransformConstraint(skeletonData, constraintMap->name); - spTransformConstraintTimeline* timeline = spTransformConstraintTimeline_create(constraintMap->size); - for (frameIndex = 0; frameIndex < skeletonData->transformConstraintsCount; ++frameIndex) { - if (constraint == skeletonData->transformConstraints[frameIndex]) { - timeline->transformConstraintIndex = frameIndex; - break; - } - } - for (valueMap = constraintMap->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) { - spTransformConstraintTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), Json_getFloat(valueMap, "rotateMix", 1), - Json_getFloat(valueMap, "translateMix", 1), Json_getFloat(valueMap, "scaleMix", 1), Json_getFloat(valueMap, "shearMix", 1)); - readCurve(valueMap, SUPER(timeline), frameIndex); - } - animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); - animation->duration = MAX(animation->duration, timeline->frames[(constraintMap->size - 1) * TRANSFORMCONSTRAINT_ENTRIES]); - } - - /** Path constraint timelines. */ - for(constraintMap = paths ? paths->child : 0; constraintMap; constraintMap = constraintMap->next ) { - int constraintIndex, i; - Json* timelineMap; - - spPathConstraintData* data = spSkeletonData_findPathConstraint(skeletonData, constraintMap->name); - if (!data) { - spAnimation_dispose(animation); - _spSkeletonJson_setError(self, root, "Path constraint not found: ", constraintMap->name); - return 0; - } - for (i = 0; i < skeletonData->pathConstraintsCount; i++) { - if (skeletonData->pathConstraints[i] == data) { - constraintIndex = i; - break; - } - } - - for (timelineMap = constraintMap->child; timelineMap; timelineMap = timelineMap->next) { - const char* timelineName = timelineMap->name; - if (strcmp(timelineName, "position") == 0 || strcmp(timelineName, "spacing") == 0) { - spPathConstraintPositionTimeline* timeline; - float timelineScale = 1; - if (strcmp(timelineName, "spacing") == 0) { - timeline = (spPathConstraintPositionTimeline*)spPathConstraintSpacingTimeline_create(timelineMap->size); - if (data->spacingMode == SP_SPACING_MODE_LENGTH || data->spacingMode == SP_SPACING_MODE_FIXED) timelineScale = self->scale; - } else { - timeline = spPathConstraintPositionTimeline_create(timelineMap->size); - if (data->positionMode == SP_POSITION_MODE_FIXED) timelineScale = self->scale; - } - timeline->pathConstraintIndex = constraintIndex; - for (valueMap = timelineMap->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) { - spPathConstraintPositionTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), Json_getFloat(valueMap, timelineName, 0) * timelineScale); - readCurve(valueMap, SUPER(timeline), frameIndex); - } - animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); - animation->duration = MAX(animation->duration, timeline->frames[(timelineMap->size - 1) * PATHCONSTRAINTPOSITION_ENTRIES]); - } else if (strcmp(timelineName, "mix") == 0) { - spPathConstraintMixTimeline* timeline = spPathConstraintMixTimeline_create(timelineMap->size); - timeline->pathConstraintIndex = constraintIndex; - for (valueMap = timelineMap->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) { - spPathConstraintMixTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), - Json_getFloat(valueMap, "rotateMix", 1), Json_getFloat(valueMap, "translateMix", 1)); - readCurve(valueMap, SUPER(timeline), frameIndex); - } - animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); - animation->duration = MAX(animation->duration, timeline->frames[(timelineMap->size - 1) * PATHCONSTRAINTMIX_ENTRIES]); - } - } - } - - /* Deform timelines. */ - for (constraintMap = deform ? deform->child : 0; constraintMap; constraintMap = constraintMap->next) { - spSkin* skin = spSkeletonData_findSkin(skeletonData, constraintMap->name); - for (slotMap = constraintMap->child; slotMap; slotMap = slotMap->next) { - int slotIndex = spSkeletonData_findSlotIndex(skeletonData, slotMap->name); - Json* timelineMap; - for (timelineMap = slotMap->child; timelineMap; timelineMap = timelineMap->next) { - float* tempDeform; - spDeformTimeline *timeline; - int weighted, deformLength; - - spVertexAttachment* attachment = SUB_CAST(spVertexAttachment, spSkin_getAttachment(skin, slotIndex, timelineMap->name)); - if (!attachment) { - spAnimation_dispose(animation); - _spSkeletonJson_setError(self, 0, "Attachment not found: ", timelineMap->name); - return 0; - } - weighted = attachment->bones != 0; - deformLength = weighted ? attachment->verticesCount / 3 * 2 : attachment->verticesCount; - tempDeform = MALLOC(float, deformLength); - - timeline = spDeformTimeline_create(timelineMap->size, deformLength); - timeline->slotIndex = slotIndex; - timeline->attachment = SUPER(attachment); - - for (valueMap = timelineMap->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) { - Json* vertices = Json_getItem(valueMap, "vertices"); - float* deform; - if (!vertices) { - if (weighted) { - deform = tempDeform; - memset(deform, 0, sizeof(float) * deformLength); - } else - deform = attachment->vertices; - } else { - int v, start = Json_getInt(valueMap, "offset", 0); - Json* vertex; - deform = tempDeform; - memset(deform, 0, sizeof(float) * start); - if (self->scale == 1) { - for (vertex = vertices->child, v = start; vertex; vertex = vertex->next, ++v) - deform[v] = vertex->valueFloat; - } else { - for (vertex = vertices->child, v = start; vertex; vertex = vertex->next, ++v) - deform[v] = vertex->valueFloat * self->scale; - } - memset(deform + v, 0, sizeof(float) * (deformLength - v)); - if (!weighted) { - float* vertices = attachment->vertices; - for (v = 0; v < deformLength; ++v) - deform[v] += vertices[v]; - } - } - spDeformTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), deform); - readCurve(valueMap, SUPER(timeline), frameIndex); - } - FREE(tempDeform); - - animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); - animation->duration = MAX(animation->duration, timeline->frames[timelineMap->size - 1]); - } - } - } - - /* Draw order timeline. */ - if (drawOrder) { - spDrawOrderTimeline* timeline = spDrawOrderTimeline_create(drawOrder->size, skeletonData->slotsCount); - for (valueMap = drawOrder->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) { - int ii; - int* drawOrder = 0; - Json* offsets = Json_getItem(valueMap, "offsets"); - if (offsets) { - Json* offsetMap; - int* unchanged = MALLOC(int, skeletonData->slotsCount - offsets->size); - int originalIndex = 0, unchangedIndex = 0; - - drawOrder = MALLOC(int, skeletonData->slotsCount); - for (ii = skeletonData->slotsCount - 1; ii >= 0; --ii) - drawOrder[ii] = -1; - - for (offsetMap = offsets->child; offsetMap; offsetMap = offsetMap->next) { - int slotIndex = spSkeletonData_findSlotIndex(skeletonData, Json_getString(offsetMap, "slot", 0)); - if (slotIndex == -1) { - spAnimation_dispose(animation); - _spSkeletonJson_setError(self, 0, "Slot not found: ", Json_getString(offsetMap, "slot", 0)); - return 0; - } - /* Collect unchanged items. */ - while (originalIndex != slotIndex) - unchanged[unchangedIndex++] = originalIndex++; - /* Set changed items. */ - drawOrder[originalIndex + Json_getInt(offsetMap, "offset", 0)] = originalIndex; - originalIndex++; - } - /* Collect remaining unchanged items. */ - while (originalIndex < skeletonData->slotsCount) - unchanged[unchangedIndex++] = originalIndex++; - /* Fill in unchanged items. */ - for (ii = skeletonData->slotsCount - 1; ii >= 0; ii--) - if (drawOrder[ii] == -1) drawOrder[ii] = unchanged[--unchangedIndex]; - FREE(unchanged); - } - spDrawOrderTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), drawOrder); - FREE(drawOrder); - } - animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); - animation->duration = MAX(animation->duration, timeline->frames[drawOrder->size - 1]); - } - - /* Event timeline. */ - if (events) { - spEventTimeline* timeline = spEventTimeline_create(events->size); - for (valueMap = events->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) { - spEvent* event; - const char* stringValue; - spEventData* eventData = spSkeletonData_findEvent(skeletonData, Json_getString(valueMap, "name", 0)); - if (!eventData) { - spAnimation_dispose(animation); - _spSkeletonJson_setError(self, 0, "Event not found: ", Json_getString(valueMap, "name", 0)); - return 0; - } - event = spEvent_create(Json_getFloat(valueMap, "time", 0), eventData); - event->intValue = Json_getInt(valueMap, "int", eventData->intValue); - event->floatValue = Json_getFloat(valueMap, "float", eventData->floatValue); - stringValue = Json_getString(valueMap, "string", eventData->stringValue); - if (stringValue) MALLOC_STR(event->stringValue, stringValue); - spEventTimeline_setFrame(timeline, frameIndex, event); - } - animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); - animation->duration = MAX(animation->duration, timeline->frames[events->size - 1]); - } - - return animation; -} - -static void _readVertices (spSkeletonJson* self, Json* attachmentMap, spVertexAttachment* attachment, int verticesLength) { - Json* entry; - float* vertices; - int i, n, nn, entrySize; - spFloatArray* weights; - spIntArray* bones; - - attachment->worldVerticesLength = verticesLength; - - entry = Json_getItem(attachmentMap, "vertices"); - entrySize = entry->size; - vertices = MALLOC(float, entrySize); - for (entry = entry->child, i = 0; entry; entry = entry->next, ++i) - vertices[i] = entry->valueFloat; - - if (verticesLength == entrySize) { - if (self->scale != 1) - for (i = 0; i < entrySize; ++i) - vertices[i] *= self->scale; - attachment->verticesCount = verticesLength; - attachment->vertices = vertices; - - attachment->bonesCount = 0; - attachment->bones = 0; - return; - } - - weights = spFloatArray_create(verticesLength * 3 * 3); - bones = spIntArray_create(verticesLength * 3); - - for (i = 0, n = entrySize; i < n;) { - int boneCount = (int)vertices[i++]; - spIntArray_add(bones, boneCount); - for (nn = i + boneCount * 4; i < nn; i += 4) { - spIntArray_add(bones, (int)vertices[i]); - spFloatArray_add(weights, vertices[i + 1] * self->scale); - spFloatArray_add(weights, vertices[i + 2] * self->scale); - spFloatArray_add(weights, vertices[i + 3]); - } - } - - attachment->verticesCount = weights->size; - attachment->vertices = weights->items; - FREE(weights); - attachment->bonesCount = bones->size; - attachment->bones = bones->items; - FREE(bones); - - FREE(vertices); -} - -spSkeletonData* spSkeletonJson_readSkeletonDataFile (spSkeletonJson* self, const char* path) { - int length; - spSkeletonData* skeletonData; - const char* json = _spUtil_readFile(path, &length); - if (length == 0 || !json) { - _spSkeletonJson_setError(self, 0, "Unable to read skeleton file: ", path); - return 0; - } - skeletonData = spSkeletonJson_readSkeletonData(self, json); - FREE(json); - return skeletonData; -} - -spSkeletonData* spSkeletonJson_readSkeletonData (spSkeletonJson* self, const char* json) { - int i, ii; - spSkeletonData* skeletonData; - Json *root, *skeleton, *bones, *boneMap, *ik, *transform, *path, *slots, *skins, *animations, *events; - char* oldLocale; - _spSkeletonJson* internal = SUB_CAST(_spSkeletonJson, self); - - FREE(self->error); - CONST_CAST(char*, self->error) = 0; - internal->linkedMeshCount = 0; - -#ifndef __ANDROID__ - oldLocale = strdup(setlocale(LC_NUMERIC, NULL)); - setlocale(LC_NUMERIC, "C"); -#endif - - root = Json_create(json); - -#ifndef __ANDROID__ - setlocale(LC_NUMERIC, oldLocale); - free(oldLocale); -#endif - - if (!root) { - _spSkeletonJson_setError(self, 0, "Invalid skeleton JSON: ", Json_getError()); - return 0; - } - - skeletonData = spSkeletonData_create(); - - skeleton = Json_getItem(root, "skeleton"); - if (skeleton) { - MALLOC_STR(skeletonData->hash, Json_getString(skeleton, "hash", 0)); - MALLOC_STR(skeletonData->version, Json_getString(skeleton, "spine", 0)); - skeletonData->width = Json_getFloat(skeleton, "width", 0); - skeletonData->height = Json_getFloat(skeleton, "height", 0); - } - - /* Bones. */ - bones = Json_getItem(root, "bones"); - skeletonData->bones = MALLOC(spBoneData*, bones->size); - for (boneMap = bones->child, i = 0; boneMap; boneMap = boneMap->next, ++i) { - spBoneData* data; - const char* transformMode; - - spBoneData* parent = 0; - const char* parentName = Json_getString(boneMap, "parent", 0); - if (parentName) { - parent = spSkeletonData_findBone(skeletonData, parentName); - if (!parent) { - spSkeletonData_dispose(skeletonData); - _spSkeletonJson_setError(self, root, "Parent bone not found: ", parentName); - return 0; - } - } - - data = spBoneData_create(skeletonData->bonesCount, Json_getString(boneMap, "name", 0), parent); - data->length = Json_getFloat(boneMap, "length", 0) * self->scale; - data->x = Json_getFloat(boneMap, "x", 0) * self->scale; - data->y = Json_getFloat(boneMap, "y", 0) * self->scale; - data->rotation = Json_getFloat(boneMap, "rotation", 0); - data->scaleX = Json_getFloat(boneMap, "scaleX", 1); - data->scaleY = Json_getFloat(boneMap, "scaleY", 1); - data->shearX = Json_getFloat(boneMap, "shearX", 0); - data->shearY = Json_getFloat(boneMap, "shearY", 0); - transformMode = Json_getString(boneMap, "transform", "normal"); - data->transformMode = SP_TRANSFORMMODE_NORMAL; - if (strcmp(transformMode, "normal") == 0) - data->transformMode = SP_TRANSFORMMODE_NORMAL; - if (strcmp(transformMode, "onlyTranslation") == 0) - data->transformMode = SP_TRANSFORMMODE_ONLYTRANSLATION; - if (strcmp(transformMode, "noRotationOrReflection") == 0) - data->transformMode = SP_TRANSFORMMODE_NOROTATIONORREFLECTION; - if (strcmp(transformMode, "noScale") == 0) - data->transformMode = SP_TRANSFORMMODE_NOSCALE; - if (strcmp(transformMode, "noScaleOrReflection") == 0) - data->transformMode = SP_TRANSFORMMODE_NOSCALEORREFLECTION; - - skeletonData->bones[i] = data; - skeletonData->bonesCount++; - } - - /* Slots. */ - slots = Json_getItem(root, "slots"); - if (slots) { - Json *slotMap; - skeletonData->slotsCount = slots->size; - skeletonData->slots = MALLOC(spSlotData*, slots->size); - for (slotMap = slots->child, i = 0; slotMap; slotMap = slotMap->next, ++i) { - spSlotData* data; - const char* color; - const char* dark; - Json *item; - - const char* boneName = Json_getString(slotMap, "bone", 0); - spBoneData* boneData = spSkeletonData_findBone(skeletonData, boneName); - if (!boneData) { - spSkeletonData_dispose(skeletonData); - _spSkeletonJson_setError(self, root, "Slot bone not found: ", boneName); - return 0; - } - - data = spSlotData_create(i, Json_getString(slotMap, "name", 0), boneData); - - color = Json_getString(slotMap, "color", 0); - if (color) { - spColor_setFromFloats(&data->color, - toColor(color, 0), - toColor(color, 1), - toColor(color, 2), - toColor(color, 3)); - } - - dark = Json_getString(slotMap, "dark", 0); - if (dark) { - data->darkColor = spColor_create(); - spColor_setFromFloats(data->darkColor, - toColor(dark, 0), - toColor(dark, 1), - toColor(dark, 2), - toColor(dark, 3)); - } - - item = Json_getItem(slotMap, "attachment"); - if (item) spSlotData_setAttachmentName(data, item->valueString); - - item = Json_getItem(slotMap, "blend"); - if (item) { - if (strcmp(item->valueString, "additive") == 0) - data->blendMode = SP_BLEND_MODE_ADDITIVE; - else if (strcmp(item->valueString, "multiply") == 0) - data->blendMode = SP_BLEND_MODE_MULTIPLY; - else if (strcmp(item->valueString, "screen") == 0) - data->blendMode = SP_BLEND_MODE_SCREEN; - } - - skeletonData->slots[i] = data; - } - } - - /* IK constraints. */ - ik = Json_getItem(root, "ik"); - if (ik) { - Json *constraintMap; - skeletonData->ikConstraintsCount = ik->size; - skeletonData->ikConstraints = MALLOC(spIkConstraintData*, ik->size); - for (constraintMap = ik->child, i = 0; constraintMap; constraintMap = constraintMap->next, ++i) { - const char* targetName; - - spIkConstraintData* data = spIkConstraintData_create(Json_getString(constraintMap, "name", 0)); - data->order = Json_getInt(constraintMap, "order", 0); - - boneMap = Json_getItem(constraintMap, "bones"); - data->bonesCount = boneMap->size; - data->bones = MALLOC(spBoneData*, boneMap->size); - for (boneMap = boneMap->child, ii = 0; boneMap; boneMap = boneMap->next, ++ii) { - data->bones[ii] = spSkeletonData_findBone(skeletonData, boneMap->valueString); - if (!data->bones[ii]) { - spSkeletonData_dispose(skeletonData); - _spSkeletonJson_setError(self, root, "IK bone not found: ", boneMap->valueString); - return 0; - } - } - - targetName = Json_getString(constraintMap, "target", 0); - data->target = spSkeletonData_findBone(skeletonData, targetName); - if (!data->target) { - spSkeletonData_dispose(skeletonData); - _spSkeletonJson_setError(self, root, "Target bone not found: ", boneMap->name); - return 0; - } - - data->bendDirection = Json_getInt(constraintMap, "bendPositive", 1) ? 1 : -1; - data->mix = Json_getFloat(constraintMap, "mix", 1); - - skeletonData->ikConstraints[i] = data; - } - } - - /* Transform constraints. */ - transform = Json_getItem(root, "transform"); - if (transform) { - Json *constraintMap; - skeletonData->transformConstraintsCount = transform->size; - skeletonData->transformConstraints = MALLOC(spTransformConstraintData*, transform->size); - for (constraintMap = transform->child, i = 0; constraintMap; constraintMap = constraintMap->next, ++i) { - const char* name; - - spTransformConstraintData* data = spTransformConstraintData_create(Json_getString(constraintMap, "name", 0)); - data->order = Json_getInt(constraintMap, "order", 0); - - boneMap = Json_getItem(constraintMap, "bones"); - data->bonesCount = boneMap->size; - CONST_CAST(spBoneData**, data->bones) = MALLOC(spBoneData*, boneMap->size); - for (boneMap = boneMap->child, ii = 0; boneMap; boneMap = boneMap->next, ++ii) { - data->bones[ii] = spSkeletonData_findBone(skeletonData, boneMap->valueString); - if (!data->bones[ii]) { - spSkeletonData_dispose(skeletonData); - _spSkeletonJson_setError(self, root, "Transform bone not found: ", boneMap->valueString); - return 0; - } - } - - name = Json_getString(constraintMap, "target", 0); - data->target = spSkeletonData_findBone(skeletonData, name); - if (!data->target) { - spSkeletonData_dispose(skeletonData); - _spSkeletonJson_setError(self, root, "Target bone not found: ", boneMap->name); - return 0; - } - - data->local = Json_getInt(constraintMap, "local", 0); - data->relative = Json_getInt(constraintMap, "relative", 0); - data->offsetRotation = Json_getFloat(constraintMap, "rotation", 0); - data->offsetX = Json_getFloat(constraintMap, "x", 0) * self->scale; - data->offsetY = Json_getFloat(constraintMap, "y", 0) * self->scale; - data->offsetScaleX = Json_getFloat(constraintMap, "scaleX", 0); - data->offsetScaleY = Json_getFloat(constraintMap, "scaleY", 0); - data->offsetShearY = Json_getFloat(constraintMap, "shearY", 0); - - data->rotateMix = Json_getFloat(constraintMap, "rotateMix", 1); - data->translateMix = Json_getFloat(constraintMap, "translateMix", 1); - data->scaleMix = Json_getFloat(constraintMap, "scaleMix", 1); - data->shearMix = Json_getFloat(constraintMap, "shearMix", 1); - - skeletonData->transformConstraints[i] = data; - } - } - - /* Path constraints */ - path = Json_getItem(root, "path"); - if (path) { - Json *constraintMap; - skeletonData->pathConstraintsCount = path->size; - skeletonData->pathConstraints = MALLOC(spPathConstraintData*, path->size); - for (constraintMap = path->child, i = 0; constraintMap; constraintMap = constraintMap->next, ++i) { - const char* name; - const char* item; - - spPathConstraintData* data = spPathConstraintData_create(Json_getString(constraintMap, "name", 0)); - data->order = Json_getInt(constraintMap, "order", 0); - - boneMap = Json_getItem(constraintMap, "bones"); - data->bonesCount = boneMap->size; - CONST_CAST(spBoneData**, data->bones) = MALLOC(spBoneData*, boneMap->size); - for (boneMap = boneMap->child, ii = 0; boneMap; boneMap = boneMap->next, ++ii) { - data->bones[ii] = spSkeletonData_findBone(skeletonData, boneMap->valueString); - if (!data->bones[ii]) { - spSkeletonData_dispose(skeletonData); - _spSkeletonJson_setError(self, root, "Path bone not found: ", boneMap->valueString); - return 0; - } - } - - name = Json_getString(constraintMap, "target", 0); - data->target = spSkeletonData_findSlot(skeletonData, name); - if (!data->target) { - spSkeletonData_dispose(skeletonData); - _spSkeletonJson_setError(self, root, "Target slot not found: ", boneMap->name); - return 0; - } - - item = Json_getString(constraintMap, "positionMode", "percent"); - if (strcmp(item, "fixed") == 0) data->positionMode = SP_POSITION_MODE_FIXED; - else if (strcmp(item, "percent") == 0) data->positionMode = SP_POSITION_MODE_PERCENT; - - item = Json_getString(constraintMap, "spacingMode", "length"); - if (strcmp(item, "length") == 0) data->spacingMode = SP_SPACING_MODE_LENGTH; - else if (strcmp(item, "fixed") == 0) data->spacingMode = SP_SPACING_MODE_FIXED; - else if (strcmp(item, "percent") == 0) data->spacingMode = SP_SPACING_MODE_PERCENT; - - item = Json_getString(constraintMap, "rotateMode", "tangent"); - if (strcmp(item, "tangent") == 0) data->rotateMode = SP_ROTATE_MODE_TANGENT; - else if (strcmp(item, "chain") == 0) data->rotateMode = SP_ROTATE_MODE_CHAIN; - else if (strcmp(item, "chainScale") == 0) data->rotateMode = SP_ROTATE_MODE_CHAIN_SCALE; - - data->offsetRotation = Json_getFloat(constraintMap, "rotation", 0); - data->position = Json_getFloat(constraintMap, "position", 0); - if (data->positionMode == SP_POSITION_MODE_FIXED) data->position *= self->scale; - data->spacing = Json_getFloat(constraintMap, "spacing", 0); - if (data->spacingMode == SP_SPACING_MODE_LENGTH || data->spacingMode == SP_SPACING_MODE_FIXED) data->spacing *= self->scale; - data->rotateMix = Json_getFloat(constraintMap, "rotateMix", 1); - data->translateMix = Json_getFloat(constraintMap, "translateMix", 1); - - skeletonData->pathConstraints[i] = data; - } - } - - /* Skins. */ - skins = Json_getItem(root, "skins"); - if (skins) { - Json *skinMap; - skeletonData->skins = MALLOC(spSkin*, skins->size); - for (skinMap = skins->child, i = 0; skinMap; skinMap = skinMap->next, ++i) { - Json *attachmentsMap; - Json *curves; - spSkin *skin = spSkin_create(skinMap->name); - - skeletonData->skins[skeletonData->skinsCount++] = skin; - if (strcmp(skinMap->name, "default") == 0) skeletonData->defaultSkin = skin; - - for (attachmentsMap = skinMap->child; attachmentsMap; attachmentsMap = attachmentsMap->next) { - int slotIndex = spSkeletonData_findSlotIndex(skeletonData, attachmentsMap->name); - Json *attachmentMap; - - for (attachmentMap = attachmentsMap->child; attachmentMap; attachmentMap = attachmentMap->next) { - spAttachment* attachment; - const char* skinAttachmentName = attachmentMap->name; - const char* attachmentName = Json_getString(attachmentMap, "name", skinAttachmentName); - const char* path = Json_getString(attachmentMap, "path", attachmentName); - const char* color; - Json* entry; - - const char* typeString = Json_getString(attachmentMap, "type", "region"); - spAttachmentType type; - if (strcmp(typeString, "region") == 0) - type = SP_ATTACHMENT_REGION; - else if (strcmp(typeString, "mesh") == 0) - type = SP_ATTACHMENT_MESH; - else if (strcmp(typeString, "linkedmesh") == 0) - type = SP_ATTACHMENT_LINKED_MESH; - else if (strcmp(typeString, "boundingbox") == 0) - type = SP_ATTACHMENT_BOUNDING_BOX; - else if (strcmp(typeString, "path") == 0) - type = SP_ATTACHMENT_PATH; - else if (strcmp(typeString, "clipping") == 0) - type = SP_ATTACHMENT_CLIPPING; - else { - spSkeletonData_dispose(skeletonData); - _spSkeletonJson_setError(self, root, "Unknown attachment type: ", typeString); - return 0; - } - - attachment = spAttachmentLoader_createAttachment(self->attachmentLoader, skin, type, attachmentName, path); - if (!attachment) { - if (self->attachmentLoader->error1) { - spSkeletonData_dispose(skeletonData); - _spSkeletonJson_setError(self, root, self->attachmentLoader->error1, self->attachmentLoader->error2); - return 0; - } - continue; - } - - switch (attachment->type) { - case SP_ATTACHMENT_REGION: { - spRegionAttachment* region = SUB_CAST(spRegionAttachment, attachment); - if (path) MALLOC_STR(region->path, path); - region->x = Json_getFloat(attachmentMap, "x", 0) * self->scale; - region->y = Json_getFloat(attachmentMap, "y", 0) * self->scale; - region->scaleX = Json_getFloat(attachmentMap, "scaleX", 1); - region->scaleY = Json_getFloat(attachmentMap, "scaleY", 1); - region->rotation = Json_getFloat(attachmentMap, "rotation", 0); - region->width = Json_getFloat(attachmentMap, "width", 32) * self->scale; - region->height = Json_getFloat(attachmentMap, "height", 32) * self->scale; - - color = Json_getString(attachmentMap, "color", 0); - if (color) { - spColor_setFromFloats(®ion->color, - toColor(color, 0), - toColor(color, 1), - toColor(color, 2), - toColor(color, 3)); - } - - spRegionAttachment_updateOffset(region); - - spAttachmentLoader_configureAttachment(self->attachmentLoader, attachment); - break; - } - case SP_ATTACHMENT_MESH: - case SP_ATTACHMENT_LINKED_MESH: { - spMeshAttachment* mesh = SUB_CAST(spMeshAttachment, attachment); - - MALLOC_STR(mesh->path, path); - - color = Json_getString(attachmentMap, "color", 0); - if (color) { - spColor_setFromFloats(&mesh->color, - toColor(color, 0), - toColor(color, 1), - toColor(color, 2), - toColor(color, 3)); - } - - mesh->width = Json_getFloat(attachmentMap, "width", 32) * self->scale; - mesh->height = Json_getFloat(attachmentMap, "height", 32) * self->scale; - - entry = Json_getItem(attachmentMap, "parent"); - if (!entry) { - int verticesLength; - entry = Json_getItem(attachmentMap, "triangles"); - mesh->trianglesCount = entry->size; - mesh->triangles = MALLOC(unsigned short, entry->size); - for (entry = entry->child, ii = 0; entry; entry = entry->next, ++ii) - mesh->triangles[ii] = (unsigned short)entry->valueInt; - - entry = Json_getItem(attachmentMap, "uvs"); - verticesLength = entry->size; - mesh->regionUVs = MALLOC(float, verticesLength); - for (entry = entry->child, ii = 0; entry; entry = entry->next, ++ii) - mesh->regionUVs[ii] = entry->valueFloat; - - _readVertices(self, attachmentMap, SUPER(mesh), verticesLength); - - spMeshAttachment_updateUVs(mesh); - - mesh->hullLength = Json_getInt(attachmentMap, "hull", 0); - - entry = Json_getItem(attachmentMap, "edges"); - if (entry) { - mesh->edgesCount = entry->size; - mesh->edges = MALLOC(int, entry->size); - for (entry = entry->child, ii = 0; entry; entry = entry->next, ++ii) - mesh->edges[ii] = entry->valueInt; - } - - spAttachmentLoader_configureAttachment(self->attachmentLoader, attachment); - } else { - mesh->inheritDeform = Json_getInt(attachmentMap, "deform", 1); - _spSkeletonJson_addLinkedMesh(self, SUB_CAST(spMeshAttachment, attachment), Json_getString(attachmentMap, "skin", 0), slotIndex, - entry->valueString); - } - break; - } - case SP_ATTACHMENT_BOUNDING_BOX: { - spBoundingBoxAttachment* box = SUB_CAST(spBoundingBoxAttachment, attachment); - int vertexCount = Json_getInt(attachmentMap, "vertexCount", 0) << 1; - _readVertices(self, attachmentMap, SUPER(box), vertexCount); - box->super.verticesCount = vertexCount; - spAttachmentLoader_configureAttachment(self->attachmentLoader, attachment); - break; - } - case SP_ATTACHMENT_PATH: { - spPathAttachment* path = SUB_CAST(spPathAttachment, attachment); - int vertexCount = 0; - path->closed = Json_getInt(attachmentMap, "closed", 0); - path->constantSpeed = Json_getInt(attachmentMap, "constantSpeed", 1); - vertexCount = Json_getInt(attachmentMap, "vertexCount", 0); - _readVertices(self, attachmentMap, SUPER(path), vertexCount << 1); - - path->lengthsLength = vertexCount / 3; - path->lengths = MALLOC(float, path->lengthsLength); - - curves = Json_getItem(attachmentMap, "lengths"); - for (curves = curves->child, ii = 0; curves; curves = curves->next, ++ii) { - path->lengths[ii] = curves->valueFloat * self->scale; - } - break; - } - case SP_ATTACHMENT_POINT: { - spPointAttachment* point = SUB_CAST(spPointAttachment, attachment); - point->x = Json_getFloat(attachmentMap, "x", 0) * self->scale; - point->y = Json_getFloat(attachmentMap, "y", 0) * self->scale; - point->rotation = Json_getFloat(attachmentMap, "rotation", 0); - - color = Json_getString(attachmentMap, "color", 0); - if (color) { - spColor_setFromFloats(&point->color, - toColor(color, 0), - toColor(color, 1), - toColor(color, 2), - toColor(color, 3)); - } - break; - } - case SP_ATTACHMENT_CLIPPING: { - spClippingAttachment* clip = SUB_CAST(spClippingAttachment, attachment); - int vertexCount = 0; - const char* end = Json_getString(attachmentMap, "end", 0); - if (end) { - spSlotData* slot = spSkeletonData_findSlot(skeletonData, end); - clip->endSlot = slot; - } - vertexCount = Json_getInt(attachmentMap, "vertexCount", 0) << 1; - _readVertices(self, attachmentMap, SUPER(clip), vertexCount); - spAttachmentLoader_configureAttachment(self->attachmentLoader, attachment); - break; - } - } - - spSkin_addAttachment(skin, slotIndex, skinAttachmentName, attachment); - } - } - } - } - - /* Linked meshes. */ - for (i = 0; i < internal->linkedMeshCount; i++) { - spAttachment* parent; - _spLinkedMesh* linkedMesh = internal->linkedMeshes + i; - spSkin* skin = !linkedMesh->skin ? skeletonData->defaultSkin : spSkeletonData_findSkin(skeletonData, linkedMesh->skin); - if (!skin) { - spSkeletonData_dispose(skeletonData); - _spSkeletonJson_setError(self, 0, "Skin not found: ", linkedMesh->skin); - return 0; - } - parent = spSkin_getAttachment(skin, linkedMesh->slotIndex, linkedMesh->parent); - if (!parent) { - spSkeletonData_dispose(skeletonData); - _spSkeletonJson_setError(self, 0, "Parent mesh not found: ", linkedMesh->parent); - return 0; - } - spMeshAttachment_setParentMesh(linkedMesh->mesh, SUB_CAST(spMeshAttachment, parent)); - spMeshAttachment_updateUVs(linkedMesh->mesh); - spAttachmentLoader_configureAttachment(self->attachmentLoader, SUPER(SUPER(linkedMesh->mesh))); - } - - /* Events. */ - events = Json_getItem(root, "events"); - if (events) { - Json *eventMap; - const char* stringValue; - skeletonData->eventsCount = events->size; - skeletonData->events = MALLOC(spEventData*, events->size); - for (eventMap = events->child, i = 0; eventMap; eventMap = eventMap->next, ++i) { - spEventData* eventData = spEventData_create(eventMap->name); - eventData->intValue = Json_getInt(eventMap, "int", 0); - eventData->floatValue = Json_getFloat(eventMap, "float", 0); - stringValue = Json_getString(eventMap, "string", 0); - if (stringValue) MALLOC_STR(eventData->stringValue, stringValue); - skeletonData->events[i] = eventData; - } - } - - /* Animations. */ - animations = Json_getItem(root, "animations"); - if (animations) { - Json *animationMap; - skeletonData->animations = MALLOC(spAnimation*, animations->size); - for (animationMap = animations->child; animationMap; animationMap = animationMap->next) { - spAnimation* animation = _spSkeletonJson_readAnimation(self, animationMap, skeletonData); - if (!animation) { - spSkeletonData_dispose(skeletonData); - return 0; - } - skeletonData->animations[skeletonData->animationsCount++] = animation; - } - } - - Json_dispose(root); - return skeletonData; -} diff --git a/spine-cpp/spine-cpp/src/spine/Skin.c b/spine-cpp/spine-cpp/src/spine/Skin.c deleted file mode 100644 index 91f2d21fe..000000000 --- a/spine-cpp/spine-cpp/src/spine/Skin.c +++ /dev/null @@ -1,106 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#include -#include - -_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); -} - -/**/ - -spSkin* spSkin_create (const char* name) { - spSkin* self = SUPER(NEW(_spSkin)); - MALLOC_STR(self->name, name); - 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; - } - - FREE(self->name); - FREE(self); -} - -void spSkin_addAttachment (spSkin* self, int slotIndex, const char* name, spAttachment* attachment) { - _Entry* newEntry = _Entry_create(slotIndex, name, attachment); - newEntry->next = SUB_CAST(_spSkin, self)->entries; - SUB_CAST(_spSkin, self)->entries = newEntry; -} - -spAttachment* spSkin_getAttachment (const spSkin* self, int slotIndex, const char* name) { - const _Entry* entry = SUB_CAST(_spSkin, self)->entries; - while (entry) { - if (entry->slotIndex == slotIndex && strcmp(entry->name, name) == 0) return entry->attachment; - entry = entry->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; - } -} diff --git a/spine-cpp/spine-cpp/src/spine/Slot.c b/spine-cpp/spine-cpp/src/spine/Slot.c deleted file mode 100644 index eded60cff..000000000 --- a/spine-cpp/spine-cpp/src/spine/Slot.c +++ /dev/null @@ -1,82 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#include -#include - -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->attachmentVertices); - 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->attachmentVerticesCount = 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); - } -} diff --git a/spine-cpp/spine-cpp/src/spine/SlotData.c b/spine-cpp/spine-cpp/src/spine/SlotData.c deleted file mode 100644 index a467c0fcb..000000000 --- a/spine-cpp/spine-cpp/src/spine/SlotData.c +++ /dev/null @@ -1,56 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#include -#include - -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; -} diff --git a/spine-cpp/spine-cpp/src/spine/TransformConstraint.c b/spine-cpp/spine-cpp/src/spine/TransformConstraint.c deleted file mode 100644 index 188d53e2f..000000000 --- a/spine-cpp/spine-cpp/src/spine/TransformConstraint.c +++ /dev/null @@ -1,273 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#include -#include -#include - -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); - } -} diff --git a/spine-cpp/spine-cpp/src/spine/TransformConstraintData.c b/spine-cpp/spine-cpp/src/spine/TransformConstraintData.c deleted file mode 100644 index 34064e0f8..000000000 --- a/spine-cpp/spine-cpp/src/spine/TransformConstraintData.c +++ /dev/null @@ -1,44 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#include -#include - -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); -} diff --git a/spine-cpp/spine-cpp/src/spine/Triangulator.c b/spine-cpp/spine-cpp/src/spine/Triangulator.c deleted file mode 100644 index 16b69bc93..000000000 --- a/spine-cpp/spine-cpp/src/spine/Triangulator.c +++ /dev/null @@ -1,361 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#include -#include -#include - -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, i = 0, next = 1; - int previousIndex, nextIndex; - 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; -} diff --git a/spine-cpp/spine-cpp/src/spine/VertexAttachment.c b/spine-cpp/spine-cpp/src/spine/VertexAttachment.c deleted file mode 100644 index 8b6dfea36..000000000 --- a/spine-cpp/spine-cpp/src/spine/VertexAttachment.c +++ /dev/null @@ -1,114 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#include -#include - -/* FIXME this is not thread-safe */ -static int nextID = 0; - -void _spVertexAttachment_init (spVertexAttachment* attachment) { - attachment->id = (nextID++ & 65535) << 11; -} - -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* deform; - float* vertices; - int* bones; - - count += offset; - skeleton = slot->bone->skeleton; - deformLength = slot->attachmentVerticesCount; - deform = slot->attachmentVertices; - vertices = self->vertices; - bones = self->bones; - if (!bones) { - spBone* bone; - int v, w; - float x, y; - if (deformLength > 0) vertices = deform; - 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] + deform[f], vy = vertices[b + 1] + deform[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; - } - } - } -} diff --git a/spine-cpp/spine-cpp/src/spine/VertexEffect.c b/spine-cpp/spine-cpp/src/spine/VertexEffect.c deleted file mode 100644 index 68d4d1f68..000000000 --- a/spine-cpp/spine-cpp/src/spine/VertexEffect.c +++ /dev/null @@ -1,98 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#include -#include - -void _spJitterVertexEffect_begin(spVertexEffect* self, spSkeleton* 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); -} - -void _spJitterVertexEffect_end(spVertexEffect* 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; - } -} - -void _spSwirlVertexEffect_end(spVertexEffect* 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); -} - diff --git a/spine-cpp/spine-cpp/src/spine/extension.c b/spine-cpp/spine-cpp/src/spine/extension.c deleted file mode 100644 index e9937cca0..000000000 --- a/spine-cpp/spine-cpp/src/spine/extension.c +++ /dev/null @@ -1,128 +0,0 @@ -/****************************************************************************** - * Spine Runtimes Software License v2.5 - * - * Copyright (c) 2013-2016, Esoteric Software - * All rights reserved. - * - * You are granted a perpetual, non-exclusive, non-sublicensable, and - * non-transferable license to use, install, execute, and perform the Spine - * Runtimes software and derivative works solely for personal or internal - * use. Without the written permission of Esoteric Software (see Section 2 of - * the Spine Software License Agreement), you may not (a) modify, translate, - * adapt, or develop new applications using the Spine Runtimes or otherwise - * create derivative works or improvements of the Spine Runtimes or (b) remove, - * delete, alter, or obscure any trademarks or any copyright, trademark, patent, - * or other intellectual property or proprietary rights notices on or in the - * Software, including any copy thereof. Redistributions in binary or source - * form must include this license and terms. - * - * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#include -#include - -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; -} - -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; -} diff --git a/spine-cpp/spine-cpp/src/spine/kvec.h b/spine-cpp/spine-cpp/src/spine/kvec.h deleted file mode 100644 index f40e8bb95..000000000 --- a/spine-cpp/spine-cpp/src/spine/kvec.h +++ /dev/null @@ -1,105 +0,0 @@ -/* The MIT License - - Copyright (c) 2008, by Attractive Chaos - - Permission is hereby granted, free 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. -*/ - -/* - An example: - -#include "kvec.h" -int main() { - kvec_t(int) array; - kv_init(array); - kv_push(int, array, 10); // append - kv_a(int, array, 20) = 5; // dynamic - kv_A(array, 20) = 4; // static - kv_destroy(array); - return 0; -} -*/ - -/* - 2008-09-22 (0.1.0): - - * The initial version. - - 2017-19-18 (0.1.1): - - Spine Special Edition - * Made helper macros for alloc, free and memcpy, which can be overridden. - * Made these helpers point to the Spine C Runtime alloc and free functions by default - * Reimplemented kv_resize to use alloc and free instead of realloc - * Changed kv_push to use kv_resize instead of realloc - * Removed kv_pushp and kv_a macros because the weren't used - * Removed stdlib include -*/ - -#ifndef AC_KVEC_H -#define AC_KVEC_H - -#ifndef _kv_free -#define _kv_free(type, p) (FREE(p)) -#endif - -#ifndef _kv_alloc -#define _kv_alloc(type, s) ((type*)(MALLOC(type, (s)))) -#endif - -#ifndef _kv_copy -#define _kv_copy(type, d, s, n) memcpy((d), (s), sizeof(type) * (n)) -#endif - -#define kv_roundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x)) - -#define kvec_t(type) struct { size_t n, m; type *a; } -#define kv_init(v) ((v).n = (v).m = 0, (v).a = 0) -#define kv_destroy(v) _kv_free(type, (v).a) -#define kv_A(v, i) ((v).a[(i)]) -#define kv_array(v) ((v).a) -#define kv_pop(v) ((v).a[--(v).n]) -#define kv_size(v) ((v).n) -#define kv_max(v) ((v).m) - -#define kv_resize(type, v, s) do { \ - type* b = _kv_alloc(type, (s)); \ - if (((s) > 0) && ((v).m > 0)) \ - _kv_copy(type, b, (v).a, ((s) < (v).m)? (s) : (v).m); \ - _kv_free(type, (v).a); \ - (v).a = b; (v).m = (s); \ - } while (0) - -#define kv_trim(type, v) kv_resize(type, (v), kv_size(v)) - -#define kv_copy(type, v1, v0) do { \ - if ((v1).m < (v0).n) kv_resize(type, v1, (v0).n); \ - (v1).n = (v0).n; \ - _kv_copy(type, (v1).a, (v0).a, (v0).n); \ - } while (0) \ - -#define kv_push(type, v, x) do { \ - if ((v).n == (v).m) \ - kv_resize(type, (v), ((v).m? (v).m<<1 : 2)); \ - (v).a[(v).n++] = (x); \ - } while (0) - -#endif From b78c3680cdc56432ec977dea117aa8169271f8d2 Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Fri, 29 Sep 2017 13:59:08 -0400 Subject: [PATCH 03/83] Got my template in Xcode set up, hoo rah! Tested it out on some header files --- spine-cpp/spine-cpp/include/spine/BlendMode.h | 45 ++++++++++++++++++ spine-cpp/spine-cpp/include/spine/Updatable.h | 47 +++++++++++++++++++ 2 files changed, 92 insertions(+) create mode 100644 spine-cpp/spine-cpp/include/spine/BlendMode.h create mode 100644 spine-cpp/spine-cpp/include/spine/Updatable.h diff --git a/spine-cpp/spine-cpp/include/spine/BlendMode.h b/spine-cpp/spine-cpp/include/spine/BlendMode.h new file mode 100644 index 000000000..13ee4a0c2 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/BlendMode.h @@ -0,0 +1,45 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_BlendMode_h +#define Spine_BlendMode_h + +namespace Spine +{ + enum BlendMode + { + Normal = 0, + Additive, + Multiply, + Screen + }; +} + +#endif /* Spine_BlendMode_h */ diff --git a/spine-cpp/spine-cpp/include/spine/Updatable.h b/spine-cpp/spine-cpp/include/spine/Updatable.h new file mode 100644 index 000000000..a521ca72a --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/Updatable.h @@ -0,0 +1,47 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Updatable_h +#define Spine_Updatable_h + +namespace Spine +{ + class Updatable + { + public: + Updatable(); + + virtual ~Updatable(); + + virtual void update() = 0; + }; +} + +#endif /* Spine_Updatable_h */ From d67ac7120ccdd2f260b9e7f5b44a3c5de33b7262 Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Fri, 29 Sep 2017 18:25:00 -0400 Subject: [PATCH 04/83] wip --- spine-cpp/spine-cpp/include/spine/BoneData.h | 101 +++++++++++ .../include/spine/IkConstraintData.h | 78 +++++++++ .../spine-cpp/include/spine/TransformMode.h | 48 +++++ spine-cpp/spine-cpp/src/spine/BoneData.cpp | 165 ++++++++++++++++++ .../spine-cpp/src/spine/IkConstraintData.cpp | 101 +++++++++++ 5 files changed, 493 insertions(+) create mode 100644 spine-cpp/spine-cpp/include/spine/BoneData.h create mode 100644 spine-cpp/spine-cpp/include/spine/IkConstraintData.h create mode 100644 spine-cpp/spine-cpp/include/spine/TransformMode.h create mode 100644 spine-cpp/spine-cpp/src/spine/BoneData.cpp create mode 100644 spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp diff --git a/spine-cpp/spine-cpp/include/spine/BoneData.h b/spine-cpp/spine-cpp/include/spine/BoneData.h new file mode 100644 index 000000000..79467a035 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/BoneData.h @@ -0,0 +1,101 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_BoneData_h +#define Spine_BoneData_h + +#include + +#include + +namespace Spine +{ + class BoneData + { + public: + BoneData(int index, std::string name, BoneData* parent); + + /// The index of the bone in Skeleton.Bones + const int getIndex(); + + /// The name of the bone, which is unique within the skeleton. + const std::string& getName(); + + /// May be null. + const BoneData* getParent(); + + float getLength(); + void setLength(float inValue); + + /// Local X translation. + float getX(); + void setX(float inValue); + + /// Local Y translation. + float getY(); + void setY(float inValue); + + /// Local rotation. + float getRotation(); + void setRotation(float inValue); + + /// Local scaleX. + float getScaleX(); + void setScaleX(float inValue); + + /// Local scaleY. + float getScaleY(); + void setScaleY(float inValue); + + /// Local shearX. + float getShearX(); + void setShearX(float inValue); + + /// Local shearY. + float getShearY(); + void setShearY(float inValue); + + /// The transform mode for how parent world transforms affect this bone. + TransformMode getTransformMode(); + void setTransformMode(TransformMode inValue); + + private: + const int _index; + const std::string _name; + const BoneData* _parent; + float _length; + float _x, _y, _rotation, _scaleX, _scaleY, _shearX, _shearY; + TransformMode _transformMode; + + friend std::ostream& operator <<(std::ostream& os, const BoneData& ref); + }; +} + +#endif /* Spine_BoneData_h */ diff --git a/spine-cpp/spine-cpp/include/spine/IkConstraintData.h b/spine-cpp/spine-cpp/include/spine/IkConstraintData.h new file mode 100644 index 000000000..d4c089921 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/IkConstraintData.h @@ -0,0 +1,78 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_IkConstraintData_h +#define Spine_IkConstraintData_h + +#include +#include + +class BoneData; + +namespace Spine +{ + class IkConstraintData + { + public: + IkConstraintData(std::string name); + + /// The IK constraint's name, which is unique within the skeleton. + const std::string& getName(); + + int getOrder(); + void setOrder(int inValue); + + /// The bones that are constrained by this IK Constraint. + std::list& getBones(); + + /// The bone that is the IK target. + BoneData* getTarget(); + void setTarget(BoneData* inValue); + + /// Controls the bend direction of the IK bones, either 1 or -1. + int getBendDirection(); + void setBendDirection(int inValue); + + float getMix(); + void setMix(float inValue); + + private: + const std::string _name; + int _order; + std::list _bones; + BoneData* _target; + int _bendDirection; + float _mix; + + friend std::ostream& operator <<(std::ostream& os, const IkConstraintData& ref); + }; +} + +#endif /* Spine_IkConstraintData_h */ diff --git a/spine-cpp/spine-cpp/include/spine/TransformMode.h b/spine-cpp/spine-cpp/include/spine/TransformMode.h new file mode 100644 index 000000000..5af1b802f --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/TransformMode.h @@ -0,0 +1,48 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_TransformMode_h +#define Spine_TransformMode_h + +namespace Spine +{ + enum TransformMode + { + //0000 0 Flip Scale Rotation + Normal = 0, // 0000 + OnlyTranslation = 7, // 0111 + NoRotationOrReflection = 1, // 0001 + NoScale = 2, // 0010 + NoScaleOrReflection = 6, // 0110 + }; +} + +#endif /* Spine_TransformMode_h */ + diff --git a/spine-cpp/spine-cpp/src/spine/BoneData.cpp b/spine-cpp/spine-cpp/src/spine/BoneData.cpp new file mode 100644 index 000000000..f5d23e76c --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/BoneData.cpp @@ -0,0 +1,165 @@ +/****************************************************************************** +* Spine Runtimes Software License v2.5 +* +* Copyright (c) 2013-2016, Esoteric Software +* All rights reserved. +* +* You are granted a perpetual, non-exclusive, non-sublicensable, and +* non-transferable license to use, install, execute, and perform the Spine +* Runtimes software and derivative works solely for personal or internal +* use. Without the written permission of Esoteric Software (see Section 2 of +* the Spine Software License Agreement), you may not (a) modify, translate, +* adapt, or develop new applications using the Spine Runtimes or otherwise +* create derivative works or improvements of the Spine Runtimes or (b) remove, +* delete, alter, or obscure any trademarks or any copyright, trademark, patent, +* or other intellectual property or proprietary rights notices on or in the +* Software, including any copy thereof. Redistributions in binary or source +* form must include this license and terms. +* +* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +#include + +#include + +namespace Spine +{ + BoneData::BoneData(int index, std::string name, BoneData* parent) : + _index(index), + _name(name), + _parent(parent), + _length(0), + _x(0), + _y(0), + _rotation(0), + _scaleX(1), + _scaleY(1), + _shearX(0), + _shearY(0), + _transformMode(TransformMode::Normal) + { + assert(index < 0); + } + + const int BoneData::getIndex() + { + return _index; + } + + const std::string& BoneData::getName() + { + return _name; + } + + const BoneData* BoneData::getParent() + { + return _parent; + } + + float BoneData::getLength() + { + return _length; + } + + void BoneData::setLength(float inValue) + { + _length = inValue; + } + + float BoneData::getX() + { + return _x; + } + + void BoneData::setX(float inValue) + { + _x = inValue; + } + + float BoneData::getY() + { + return _y; + } + + void BoneData::setY(float inValue) + { + _y = inValue; + } + + float BoneData::getRotation() + { + return _rotation; + } + + void BoneData::setRotation(float inValue) + { + _rotation = inValue; + } + + float BoneData::getScaleX() + { + return _scaleX; + } + + void BoneData::setScaleX(float inValue) + { + _scaleX = inValue; + } + + float BoneData::getScaleY() + { + return _scaleY; + } + + void BoneData::setScaleY(float inValue) + { + _scaleY = inValue; + } + + float BoneData::getShearX() + { + return _shearX; + } + + void BoneData::setShearX(float inValue) + { + _shearX = inValue; + } + + float BoneData::getShearY() + { + return _shearY; + } + + void BoneData::setShearY(float inValue) + { + _shearY = inValue; + } + + TransformMode BoneData::getTransformMode() + { + return _transformMode; + } + + void BoneData::setTransformMode(TransformMode inValue) + { + _transformMode = inValue; + } + + std::ostream& operator <<(std::ostream& os, const BoneData& ref) + { + os << ref._name; + + return os; + } +} diff --git a/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp b/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp new file mode 100644 index 000000000..a241f7dec --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp @@ -0,0 +1,101 @@ +/****************************************************************************** +* Spine Runtimes Software License v2.5 +* +* Copyright (c) 2013-2016, Esoteric Software +* All rights reserved. +* +* You are granted a perpetual, non-exclusive, non-sublicensable, and +* non-transferable license to use, install, execute, and perform the Spine +* Runtimes software and derivative works solely for personal or internal +* use. Without the written permission of Esoteric Software (see Section 2 of +* the Spine Software License Agreement), you may not (a) modify, translate, +* adapt, or develop new applications using the Spine Runtimes or otherwise +* create derivative works or improvements of the Spine Runtimes or (b) remove, +* delete, alter, or obscure any trademarks or any copyright, trademark, patent, +* or other intellectual property or proprietary rights notices on or in the +* Software, including any copy thereof. Redistributions in binary or source +* form must include this license and terms. +* +* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +#include + +namespace Spine +{ + IkConstraintData::IkConstraintData(std::string name) : + _name(name), + _order(0), + _target(nullptr), + _bendDirection(1), + _mix(1) + { + // Empty + } + + const std::string& IkConstraintData::getName() + { + return _name; + } + + int IkConstraintData::getOrder() + { + return _order; + } + + void IkConstraintData::setOrder(int inValue) + { + _order = inValue; + } + + std::list& IkConstraintData::getBones() + { + return _bones; + } + + BoneData* IkConstraintData::getTarget() + { + return _target; + } + + void IkConstraintData::setTarget(BoneData* inValue) + { + _target = inValue; + } + + int IkConstraintData::getBendDirection() + { + return _bendDirection; + } + + void IkConstraintData::setBendDirection(int inValue) + { + _bendDirection = inValue; + } + + float IkConstraintData::getMix() + { + return _mix; + } + + void IkConstraintData::setMix(float inValue) + { + _mix = inValue; + } + + std::ostream& operator <<(std::ostream& os, const IkConstraintData& ref) + { + os << ref._name; + + return os; + } +} From 35d84fff30f1e4e7c54e3923fc909a4f616a97f1 Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Mon, 2 Oct 2017 17:23:50 -0400 Subject: [PATCH 05/83] wip --- spine-cpp/spine-cpp/include/spine/BlendMode.h | 8 +- .../spine-cpp/include/spine/Constraint.h | 49 +++++ spine-cpp/spine-cpp/include/spine/Event.h | 71 +++++++ spine-cpp/spine-cpp/include/spine/EventData.h | 68 +++++++ .../include/spine/IkConstraintData.h | 6 +- .../include/spine/PathConstraintData.h | 100 ++++++++++ .../spine-cpp/include/spine/PositionMode.h | 43 +++++ .../spine-cpp/include/spine/RotateMode.h | 44 +++++ spine-cpp/spine-cpp/include/spine/SlotData.h | 92 +++++++++ .../spine-cpp/include/spine/SpacingMode.h | 44 +++++ .../spine-cpp/include/spine/TransformMode.h | 10 +- spine-cpp/spine-cpp/src/spine/BoneData.cpp | 3 +- spine-cpp/spine-cpp/src/spine/Event.cpp | 93 +++++++++ spine-cpp/spine-cpp/src/spine/EventData.cpp | 88 +++++++++ .../spine-cpp/src/spine/IkConstraintData.cpp | 2 +- .../src/spine/PathConstraintData.cpp | 172 +++++++++++++++++ spine-cpp/spine-cpp/src/spine/SlotData.cpp | 177 ++++++++++++++++++ 17 files changed, 1056 insertions(+), 14 deletions(-) create mode 100644 spine-cpp/spine-cpp/include/spine/Constraint.h create mode 100644 spine-cpp/spine-cpp/include/spine/Event.h create mode 100644 spine-cpp/spine-cpp/include/spine/EventData.h create mode 100644 spine-cpp/spine-cpp/include/spine/PathConstraintData.h create mode 100644 spine-cpp/spine-cpp/include/spine/PositionMode.h create mode 100644 spine-cpp/spine-cpp/include/spine/RotateMode.h create mode 100644 spine-cpp/spine-cpp/include/spine/SlotData.h create mode 100644 spine-cpp/spine-cpp/include/spine/SpacingMode.h create mode 100644 spine-cpp/spine-cpp/src/spine/Event.cpp create mode 100644 spine-cpp/spine-cpp/src/spine/EventData.cpp create mode 100644 spine-cpp/spine-cpp/src/spine/PathConstraintData.cpp create mode 100644 spine-cpp/spine-cpp/src/spine/SlotData.cpp diff --git a/spine-cpp/spine-cpp/include/spine/BlendMode.h b/spine-cpp/spine-cpp/include/spine/BlendMode.h index 13ee4a0c2..0f0afa645 100644 --- a/spine-cpp/spine-cpp/include/spine/BlendMode.h +++ b/spine-cpp/spine-cpp/include/spine/BlendMode.h @@ -35,10 +35,10 @@ namespace Spine { enum BlendMode { - Normal = 0, - Additive, - Multiply, - Screen + BlendMode_Normal = 0, + BlendMode_Additive, + BlendMode_Multiply, + BlendMode_Screen }; } diff --git a/spine-cpp/spine-cpp/include/spine/Constraint.h b/spine-cpp/spine-cpp/include/spine/Constraint.h new file mode 100644 index 000000000..50d7d0977 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/Constraint.h @@ -0,0 +1,49 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Constraint_h +#define Spine_Constraint_h + +namespace Spine +{ + /// The interface for all constraints. + class Constraint : public Updatable + { + public: + Constraint(); + + virtual Constraint(); + + /// The ordinal for the order a skeleton's constraints will be applied. + virtual int getOrder() = 0; + }; +} + +#endif /* Spine_Constraint_h */ diff --git a/spine-cpp/spine-cpp/include/spine/Event.h b/spine-cpp/spine-cpp/include/spine/Event.h new file mode 100644 index 000000000..37d1acd6a --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/Event.h @@ -0,0 +1,71 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Event_h +#define Spine_Event_h + +#include + +namespace Spine +{ + class EventData; + + /// Stores the current pose values for an Event. + class Event + { + public: + Event(float time, const EventData& data); + + const EventData& getData(); + + /// The animation time this event was keyed. + float getTime(); + + int getIntValue(); + void setIntValue(int inValue); + + float getFloatValue(); + void setFloatValue(int inValue); + + std::string getStringValue(); + void setStringValue(std::string inValue); + + private: + const EventData& _data; + const float _time; + int _intValue; + float _floatValue; + std::string _stringValue; + + friend std::ostream& operator <<(std::ostream& os, const Event& ref); + }; +} + +#endif /* Spine_Event_h */ diff --git a/spine-cpp/spine-cpp/include/spine/EventData.h b/spine-cpp/spine-cpp/include/spine/EventData.h new file mode 100644 index 000000000..e26a44d7c --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/EventData.h @@ -0,0 +1,68 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_EventData_h +#define Spine_EventData_h + +#include + +namespace Spine +{ + /// Stores the setup pose values for an Event. + class EventData + { + public: + int _intValue; + float _floatValue; + std::string _stringValue; + + EventData(std::string name); + + /// The name of the event, which is unique within the skeleton. + const std::string& getName(); + + int getIntValue(); + void setIntValue(int inValue); + + float getFloatValue(); + void setFloatValue(float inValue); + + std::string getStringValue(); + void setStringValue(std::string inValue); + + private: + friend class Event; + const std::string _name; + + friend std::ostream& operator <<(std::ostream& os, const EventData& ref); + }; +} + +#endif /* Spine_EventData_h */ diff --git a/spine-cpp/spine-cpp/include/spine/IkConstraintData.h b/spine-cpp/spine-cpp/include/spine/IkConstraintData.h index d4c089921..ad0018068 100644 --- a/spine-cpp/spine-cpp/include/spine/IkConstraintData.h +++ b/spine-cpp/spine-cpp/include/spine/IkConstraintData.h @@ -32,7 +32,7 @@ #define Spine_IkConstraintData_h #include -#include +#include class BoneData; @@ -50,7 +50,7 @@ namespace Spine void setOrder(int inValue); /// The bones that are constrained by this IK Constraint. - std::list& getBones(); + std::vector& getBones(); /// The bone that is the IK target. BoneData* getTarget(); @@ -66,7 +66,7 @@ namespace Spine private: const std::string _name; int _order; - std::list _bones; + std::vector _bones; BoneData* _target; int _bendDirection; float _mix; diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraintData.h b/spine-cpp/spine-cpp/include/spine/PathConstraintData.h new file mode 100644 index 000000000..17f0b02d3 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/PathConstraintData.h @@ -0,0 +1,100 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_PathConstraintData_h +#define Spine_PathConstraintData_h + +#include +#include +#include + +#include +#include + +namespace Spine +{ + class BoneData; + class SlotData; + + class PathConstraintData + { + public: + PathConstraintData(std::string name); + + const std::string& getName(); + + int getOrder(); + void setOrder(int inValue); + + std::vector& getBones(); + + SlotData* getTarget(); + void setTarget(SlotData* inValue); + + PositionMode getPositionMode(); + void setPositionMode(PositionMode inValue); + + SpacingMode getSpacingMode(); + void setSpacingMode(SpacingMode inValue); + + RotateMode getRotateMode(); + void setRotateMode(RotateMode inValue); + + float getOffsetRotation(); + void setOffsetRotation(float inValue); + + float getPosition(); + void setPosition(float inValue); + + float getSpacing(); + void setSpacing(float inValue); + + float getRotateMix(); + void setRotateMix(float inValue); + + float getTranslateMix(); + void setTranslateMix(float inValue); + + private: + const std::string _name; + int _order; + std::vector _bones; + SlotData* _target; + PositionMode _positionMode; + SpacingMode _spacingMode; + RotateMode _rotateMode; + float _offsetRotation; + float _position, _spacing, _rotateMix, _translateMix; + + friend std::ostream& operator <<(std::ostream& os, const PathConstraintData& ref); + }; +} + +#endif /* Spine_PathConstraintData_h */ diff --git a/spine-cpp/spine-cpp/include/spine/PositionMode.h b/spine-cpp/spine-cpp/include/spine/PositionMode.h new file mode 100644 index 000000000..66a601cac --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/PositionMode.h @@ -0,0 +1,43 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_PositionMode_h +#define Spine_PositionMode_h + +namespace Spine +{ + enum PositionMode + { + PositionMode_Fixed = 0, + PositionMode_Percent + }; +} + +#endif /* Spine_PositionMode_h */ diff --git a/spine-cpp/spine-cpp/include/spine/RotateMode.h b/spine-cpp/spine-cpp/include/spine/RotateMode.h new file mode 100644 index 000000000..a8ccd6f97 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/RotateMode.h @@ -0,0 +1,44 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_RotateMode_h +#define Spine_RotateMode_h + +namespace Spine +{ + enum RotateMode + { + RotateMode_Tangent = 0, + RotateMode_Chain, + RotateMode_ChainScale + }; +} + +#endif /* Spine_RotateMode_h */ diff --git a/spine-cpp/spine-cpp/include/spine/SlotData.h b/spine-cpp/spine-cpp/include/spine/SlotData.h new file mode 100644 index 000000000..6eb358a40 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/SlotData.h @@ -0,0 +1,92 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_SlotData_h +#define Spine_SlotData_h + +#include + +#include + +namespace Spine +{ + class BoneData; + + class SlotData + { + public: + SlotData(int index, std::string name, const BoneData& boneData); + + const int getIndex(); + + const std::string& getName(); + + const BoneData& getBoneData(); + + float getR(); + void setR(float inValue); + float getG(); + void setG(float inValue); + float getB(); + void setB(float inValue); + float getA(); + void setA(float inValue); + + float getR2(); + void setR2(float inValue); + float getG2(); + void setG2(float inValue); + float getB2(); + void setB2(float inValue); + bool hasSecondColor(); + void setHasSecondColor(bool inValue); + + /// May be empty. + std::string getAttachmentName(); + void setAttachmentName(std::string inValue); + + BlendMode getBlendMode(); + void setBlendMode(BlendMode inValue); + + private: + const int _index; + const std::string _name; + const BoneData& _boneData; + float _r, _g, _b, _a; + float _r2, _g2, _b2; + bool _hasSecondColor; + std::string _attachmentName; + BlendMode _blendMode; + + friend std::ostream& operator <<(std::ostream& os, const SlotData& ref); + }; +} + +#endif /* Spine_SlotData_h */ diff --git a/spine-cpp/spine-cpp/include/spine/SpacingMode.h b/spine-cpp/spine-cpp/include/spine/SpacingMode.h new file mode 100644 index 000000000..76b2986b4 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/SpacingMode.h @@ -0,0 +1,44 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_SpacingMode_h +#define Spine_SpacingMode_h + +namespace Spine +{ + enum SpacingMode + { + SpacingMode_Length = 0, + SpacingMode_Fixed, + SpacingMode_Percent + }; +} + +#endif /* Spine_SpacingMode_h */ diff --git a/spine-cpp/spine-cpp/include/spine/TransformMode.h b/spine-cpp/spine-cpp/include/spine/TransformMode.h index 5af1b802f..35c1ae55b 100644 --- a/spine-cpp/spine-cpp/include/spine/TransformMode.h +++ b/spine-cpp/spine-cpp/include/spine/TransformMode.h @@ -36,11 +36,11 @@ namespace Spine enum TransformMode { //0000 0 Flip Scale Rotation - Normal = 0, // 0000 - OnlyTranslation = 7, // 0111 - NoRotationOrReflection = 1, // 0001 - NoScale = 2, // 0010 - NoScaleOrReflection = 6, // 0110 + TransformMode_Normal = 0, // 0000 + TransformMode_OnlyTranslation = 7, // 0111 + TransformMode_NoRotationOrReflection = 1, // 0001 + TransformMode_NoScale = 2, // 0010 + TransformMode_NoScaleOrReflection = 6, // 0110 }; } diff --git a/spine-cpp/spine-cpp/src/spine/BoneData.cpp b/spine-cpp/spine-cpp/src/spine/BoneData.cpp index f5d23e76c..17f508e1a 100644 --- a/spine-cpp/spine-cpp/src/spine/BoneData.cpp +++ b/spine-cpp/spine-cpp/src/spine/BoneData.cpp @@ -46,9 +46,10 @@ namespace Spine _scaleY(1), _shearX(0), _shearY(0), - _transformMode(TransformMode::Normal) + _transformMode(TransformMode_Normal) { assert(index < 0); + assert(_name.length() > 0); } const int BoneData::getIndex() diff --git a/spine-cpp/spine-cpp/src/spine/Event.cpp b/spine-cpp/spine-cpp/src/spine/Event.cpp new file mode 100644 index 000000000..548a32798 --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/Event.cpp @@ -0,0 +1,93 @@ +/****************************************************************************** +* Spine Runtimes Software License v2.5 +* +* Copyright (c) 2013-2016, Esoteric Software +* All rights reserved. +* +* You are granted a perpetual, non-exclusive, non-sublicensable, and +* non-transferable license to use, install, execute, and perform the Spine +* Runtimes software and derivative works solely for personal or internal +* use. Without the written permission of Esoteric Software (see Section 2 of +* the Spine Software License Agreement), you may not (a) modify, translate, +* adapt, or develop new applications using the Spine Runtimes or otherwise +* create derivative works or improvements of the Spine Runtimes or (b) remove, +* delete, alter, or obscure any trademarks or any copyright, trademark, patent, +* or other intellectual property or proprietary rights notices on or in the +* Software, including any copy thereof. Redistributions in binary or source +* form must include this license and terms. +* +* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +#include + +#include + +namespace Spine +{ + Event::Event(float time, const EventData& data) : + _time(time), + _data(data), + _intValue(0), + _floatValue(0), + _stringValue(0) + { + // Empty + } + + const EventData& Event::getData() + { + return _data; + } + + float Event::getTime() + { + return _time; + } + + int Event::getIntValue() + { + return _intValue; + } + + void Event::setIntValue(int inValue) + { + _intValue = inValue; + } + + float Event::getFloatValue() + { + return _floatValue; + } + + void Event::setFloatValue(int inValue) + { + _floatValue = inValue; + } + + std::string Event::getStringValue() + { + return _stringValue; + } + + void Event::setStringValue(std::string inValue) + { + _stringValue = inValue; + } + + std::ostream& operator <<(std::ostream& os, const Event& ref) + { + os << ref._data; + + return os; + } +} diff --git a/spine-cpp/spine-cpp/src/spine/EventData.cpp b/spine-cpp/spine-cpp/src/spine/EventData.cpp new file mode 100644 index 000000000..1f6438a09 --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/EventData.cpp @@ -0,0 +1,88 @@ +/****************************************************************************** +* Spine Runtimes Software License v2.5 +* +* Copyright (c) 2013-2016, Esoteric Software +* All rights reserved. +* +* You are granted a perpetual, non-exclusive, non-sublicensable, and +* non-transferable license to use, install, execute, and perform the Spine +* Runtimes software and derivative works solely for personal or internal +* use. Without the written permission of Esoteric Software (see Section 2 of +* the Spine Software License Agreement), you may not (a) modify, translate, +* adapt, or develop new applications using the Spine Runtimes or otherwise +* create derivative works or improvements of the Spine Runtimes or (b) remove, +* delete, alter, or obscure any trademarks or any copyright, trademark, patent, +* or other intellectual property or proprietary rights notices on or in the +* Software, including any copy thereof. Redistributions in binary or source +* form must include this license and terms. +* +* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +#include + +#include + +namespace Spine +{ + EventData::EventData(std::string name) : + _name(name), + _intValue(0), + _floatValue(0), + _stringValue() + { + assert(_name.length() > 0); + } + + /// The name of the event, which is unique within the skeleton. + const std::string& EventData::getName() + { + return _name; + } + + int EventData::getIntValue() + { + return _intValue; + } + + void EventData::setIntValue(int inValue) + { + _intValue = inValue; + } + + float EventData::getFloatValue() + { + return _floatValue; + } + + void EventData::setFloatValue(float inValue) + { + _floatValue = inValue; + } + + std::string EventData::getStringValue() + { + return _stringValue; + } + + void EventData::setStringValue(std::string inValue) + { + _stringValue = inValue; + } + + std::ostream& operator <<(std::ostream& os, const EventData& ref) + { + os << ref._name; + + return os; + } +} diff --git a/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp b/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp index a241f7dec..b8f3b9373 100644 --- a/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp +++ b/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp @@ -57,7 +57,7 @@ namespace Spine _order = inValue; } - std::list& IkConstraintData::getBones() + std::vector& IkConstraintData::getBones() { return _bones; } diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraintData.cpp b/spine-cpp/spine-cpp/src/spine/PathConstraintData.cpp new file mode 100644 index 000000000..71ae38541 --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/PathConstraintData.cpp @@ -0,0 +1,172 @@ +/****************************************************************************** +* Spine Runtimes Software License v2.5 +* +* Copyright (c) 2013-2016, Esoteric Software +* All rights reserved. +* +* You are granted a perpetual, non-exclusive, non-sublicensable, and +* non-transferable license to use, install, execute, and perform the Spine +* Runtimes software and derivative works solely for personal or internal +* use. Without the written permission of Esoteric Software (see Section 2 of +* the Spine Software License Agreement), you may not (a) modify, translate, +* adapt, or develop new applications using the Spine Runtimes or otherwise +* create derivative works or improvements of the Spine Runtimes or (b) remove, +* delete, alter, or obscure any trademarks or any copyright, trademark, patent, +* or other intellectual property or proprietary rights notices on or in the +* Software, including any copy thereof. Redistributions in binary or source +* form must include this license and terms. +* +* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +#include + +#include +#include + +#include + +namespace Spine +{ + PathConstraintData::PathConstraintData(std::string name) : + _name(name), + _order(0), + _target(nullptr), + _positionMode(PositionMode_Fixed), + _spacingMode(SpacingMode_Length), + _rotateMode(RotateMode_Tangent), + _offsetRotation(0), + _position(0), + _spacing(0), + _rotateMix(0), + _translateMix(0) + { + assert(_name.length() > 0); + } + + const std::string& PathConstraintData::getName() + { + return _name; + } + + int PathConstraintData::getOrder() + { + return _order; + } + + void PathConstraintData::setOrder(int inValue) + { + _order = inValue; + } + + std::vector& PathConstraintData::getBones() + { + return _bones; + } + + SlotData* PathConstraintData::getTarget() + { + return _target; + } + + void PathConstraintData::setTarget(SlotData* inValue) + { + _target = inValue; + } + + PositionMode PathConstraintData::getPositionMode() + { + return _positionMode; + } + + void PathConstraintData::setPositionMode(PositionMode inValue) + { + _positionMode = inValue; + } + + SpacingMode PathConstraintData::getSpacingMode() + { + return _spacingMode; + } + + void PathConstraintData::setSpacingMode(SpacingMode inValue) + { + _spacingMode = inValue; + } + + RotateMode PathConstraintData::getRotateMode() + { + return _rotateMode; + } + + void PathConstraintData::setRotateMode(RotateMode inValue) + { + _rotateMode = inValue; + } + + float PathConstraintData::getOffsetRotation() + { + return _offsetRotation; + } + + void PathConstraintData::setOffsetRotation(float inValue) + { + _offsetRotation = inValue; + } + + float PathConstraintData::getPosition() + { + return _position; + } + + void PathConstraintData::setPosition(float inValue) + { + _position = inValue; + } + + float PathConstraintData::getSpacing() + { + return _spacing; + } + + void PathConstraintData::setSpacing(float inValue) + { + _spacing = inValue; + } + + float PathConstraintData::getRotateMix() + { + return _rotateMix; + } + + void PathConstraintData::setRotateMix(float inValue) + { + _rotateMix = inValue; + } + + float PathConstraintData::getTranslateMix() + { + return _translateMix; + } + + void PathConstraintData::setTranslateMix(float inValue) + { + _translateMix = inValue; + } + + std::ostream& operator <<(std::ostream& os, const PathConstraintData& ref) + { + os << ref._name; + + return os; + } +} diff --git a/spine-cpp/spine-cpp/src/spine/SlotData.cpp b/spine-cpp/spine-cpp/src/spine/SlotData.cpp new file mode 100644 index 000000000..a8bf97ff7 --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/SlotData.cpp @@ -0,0 +1,177 @@ +/****************************************************************************** +* Spine Runtimes Software License v2.5 +* +* Copyright (c) 2013-2016, Esoteric Software +* All rights reserved. +* +* You are granted a perpetual, non-exclusive, non-sublicensable, and +* non-transferable license to use, install, execute, and perform the Spine +* Runtimes software and derivative works solely for personal or internal +* use. Without the written permission of Esoteric Software (see Section 2 of +* the Spine Software License Agreement), you may not (a) modify, translate, +* adapt, or develop new applications using the Spine Runtimes or otherwise +* create derivative works or improvements of the Spine Runtimes or (b) remove, +* delete, alter, or obscure any trademarks or any copyright, trademark, patent, +* or other intellectual property or proprietary rights notices on or in the +* Software, including any copy thereof. Redistributions in binary or source +* form must include this license and terms. +* +* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +#include + +#include + +namespace Spine +{ + SlotData::SlotData(int index, std::string name, const BoneData& boneData) : + _index(index), + _name(name), + _boneData(boneData), + _r(1), + _g(1), + _b(1), + _a(1), + _r2(0), + _g2(0), + _b2(0), + _hasSecondColor(false), + _attachmentName(), + _blendMode(BlendMode_Normal) + { + assert(_index >= 0); + assert(_name.length() > 0); + } + + const int SlotData::getIndex() + { + return _index; + } + + const std::string& SlotData::getName() + { + return _name; + } + + const BoneData& SlotData::getBoneData() + { + return _boneData; + } + + float SlotData::getR() + { + return _r; + } + + void SlotData::setR(float inValue) + { + _r = inValue; + } + + float SlotData::getG() + { + return _g; + } + + void SlotData::setG(float inValue) + { + _g = inValue; + } + + float SlotData::getB() + { + return _b; + } + + void SlotData::setB(float inValue) + { + _b = inValue; + } + + float SlotData::getA() + { + return _a; + } + + void SlotData::setA(float inValue) + { + _a = inValue; + } + + float SlotData::getR2() + { + return _r2; + } + + void SlotData::setR2(float inValue) + { + _r2 = inValue; + } + + float SlotData::getG2() + { + return _g2; + } + + void SlotData::setG2(float inValue) + { + _g2 = inValue; + } + + float SlotData::getB2() + { + return _b2; + } + + void SlotData::setB2(float inValue) + { + _b2 = inValue; + } + + bool SlotData::hasSecondColor() + { + return _hasSecondColor; + } + + void SlotData::setHasSecondColor(bool inValue) + { + _hasSecondColor = inValue; + } + + std::string SlotData::getAttachmentName() + { + return _attachmentName; + } + + void SlotData::setAttachmentName(std::string inValue) + { + _attachmentName = inValue; + } + + BlendMode SlotData::getBlendMode() + { + return _blendMode; + } + + void SlotData::setBlendMode(BlendMode inValue) + { + _blendMode = inValue; + } + + std::ostream& operator <<(std::ostream& os, const SlotData& ref) + { + os << ref._name; + + return os; + } +} From d173aa7e7d4f17bd1266af70701e1cda37993430 Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Tue, 3 Oct 2017 16:09:03 -0400 Subject: [PATCH 06/83] wip --- .../spine-cpp/include/spine/Attachment.h | 52 +++ spine-cpp/spine-cpp/include/spine/Bone.h | 395 ++++++++++++++++++ spine-cpp/spine-cpp/include/spine/Skin.h | 129 ++++++ spine-cpp/spine-cpp/include/spine/Slot.h | 98 +++++ .../include/spine/TransformConstraintData.h | 78 ++++ spine-cpp/spine-cpp/src/spine/Attachment.cpp | 53 +++ spine-cpp/spine-cpp/src/spine/Bone.cpp | 34 ++ spine-cpp/spine-cpp/src/spine/Skin.cpp | 34 ++ spine-cpp/spine-cpp/src/spine/Slot.cpp | 215 ++++++++++ .../src/spine/TransformConstraintData.cpp | 144 +++++++ 10 files changed, 1232 insertions(+) create mode 100644 spine-cpp/spine-cpp/include/spine/Attachment.h create mode 100644 spine-cpp/spine-cpp/include/spine/Bone.h create mode 100644 spine-cpp/spine-cpp/include/spine/Skin.h create mode 100644 spine-cpp/spine-cpp/include/spine/Slot.h create mode 100644 spine-cpp/spine-cpp/include/spine/TransformConstraintData.h create mode 100644 spine-cpp/spine-cpp/src/spine/Attachment.cpp create mode 100644 spine-cpp/spine-cpp/src/spine/Bone.cpp create mode 100644 spine-cpp/spine-cpp/src/spine/Skin.cpp create mode 100644 spine-cpp/spine-cpp/src/spine/Slot.cpp create mode 100644 spine-cpp/spine-cpp/src/spine/TransformConstraintData.cpp diff --git a/spine-cpp/spine-cpp/include/spine/Attachment.h b/spine-cpp/spine-cpp/include/spine/Attachment.h new file mode 100644 index 000000000..02a2f69d8 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/Attachment.h @@ -0,0 +1,52 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Attachment_h +#define Spine_Attachment_h + +#include + +namespace Spine +{ + class Attachment + { + public: + Attachment(std::string name); + + const std::string& getName(); + + private: + const std::string _name; + + friend std::ostream& operator <<(std::ostream& os, const Attachment& ref); + }; +} + +#endif /* Spine_Attachment_h */ diff --git a/spine-cpp/spine-cpp/include/spine/Bone.h b/spine-cpp/spine-cpp/include/spine/Bone.h new file mode 100644 index 000000000..d7e1b15e7 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/Bone.h @@ -0,0 +1,395 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Bone_h +#define Spine_Bone_h + +#include + +namespace Spine +{ + /// Stores a bone's current pose. + /// + /// A bone has a local transform which is used to compute its world transform. A bone also has an applied transform, which is a + /// local transform that can be applied to compute the world transform. The local transform and applied transform may differ if a + /// constraint or application code modifies the world transform after it was computed from the local transform. + /// + class Bone : public Updatable + { + public: + private: + static public bool yDown; + + internal BoneData data; + internal Skeleton skeleton; + internal Bone parent; + internal ExposedList children = new ExposedList(); + internal float x, y, rotation, scaleX, scaleY, shearX, shearY; + internal float ax, ay, arotation, ascaleX, ascaleY, ashearX, ashearY; + internal bool appliedValid; + + internal float a, b, worldX; + internal float c, d, worldY; + + // internal float worldSignX, worldSignY; + // public float WorldSignX { get { return worldSignX; } } + // public float WorldSignY { get { return worldSignY; } } + + internal bool sorted; + + public BoneData Data { get { return data; } } + public Skeleton Skeleton { get { return skeleton; } } + public Bone Parent { get { return parent; } } + public ExposedList Children { get { return children; } } + ///

The local X translation. + public float X { get { return x; } set { x = value; } } + /// The local Y translation. + public float Y { get { return y; } set { y = value; } } + /// The local rotation. + public float Rotation { get { return rotation; } set { rotation = value; } } + + /// The local scaleX. + public float ScaleX { get { return scaleX; } set { scaleX = value; } } + + /// The local scaleY. + public float ScaleY { get { return scaleY; } set { scaleY = value; } } + + /// The local shearX. + public float ShearX { get { return shearX; } set { shearX = value; } } + + /// The local shearY. + public float ShearY { get { return shearY; } set { shearY = value; } } + + /// The rotation, as calculated by any constraints. + public float AppliedRotation { get { return arotation; } set { arotation = value; } } + + /// The applied local x translation. + public float AX { get { return ax; } set { ax = value; } } + + /// The applied local y translation. + public float AY { get { return ay; } set { ay = value; } } + + /// The applied local scaleX. + public float AScaleX { get { return ascaleX; } set { ascaleX = value; } } + + /// The applied local scaleY. + public float AScaleY { get { return ascaleY; } set { ascaleY = value; } } + + /// The applied local shearX. + public float AShearX { get { return ashearX; } set { ashearX = value; } } + + /// The applied local shearY. + public float AShearY { get { return ashearY; } set { ashearY = value; } } + + public float A { get { return a; } } + public float B { get { return b; } } + public float C { get { return c; } } + public float D { get { return d; } } + + public float WorldX { get { return worldX; } } + public float WorldY { get { return worldY; } } + public float WorldRotationX { get { return MathUtils.Atan2(c, a) * MathUtils.RadDeg; } } + public float WorldRotationY { get { return MathUtils.Atan2(d, b) * MathUtils.RadDeg; } } + + /// Returns the magnitide (always positive) of the world scale X. + public float WorldScaleX { get { return (float)Math.Sqrt(a * a + c * c); } } + /// Returns the magnitide (always positive) of the world scale Y. + public float WorldScaleY { get { return (float)Math.Sqrt(b * b + d * d); } } + + /// May be null. + public Bone (BoneData data, Skeleton skeleton, Bone parent) { + if (data == null) throw new ArgumentNullException("data", "data cannot be null."); + if (skeleton == null) throw new ArgumentNullException("skeleton", "skeleton cannot be null."); + this.data = data; + this.skeleton = skeleton; + this.parent = parent; + SetToSetupPose(); + } + + /// Same as . This method exists for Bone to implement . + public void Update () { + UpdateWorldTransform(x, y, rotation, scaleX, scaleY, shearX, shearY); + } + + /// Computes the world transform using the parent bone and this bone's local transform. + public void UpdateWorldTransform () { + UpdateWorldTransform(x, y, rotation, scaleX, scaleY, shearX, shearY); + } + + /// Computes the world transform using the parent bone and the specified local transform. + public void UpdateWorldTransform (float x, float y, float rotation, float scaleX, float scaleY, float shearX, float shearY) { + ax = x; + ay = y; + arotation = rotation; + ascaleX = scaleX; + ascaleY = scaleY; + ashearX = shearX; + ashearY = shearY; + appliedValid = true; + Skeleton skeleton = this.skeleton; + + Bone parent = this.parent; + if (parent == null) { // Root bone. + float rotationY = rotation + 90 + shearY; + float la = MathUtils.CosDeg(rotation + shearX) * scaleX; + float lb = MathUtils.CosDeg(rotationY) * scaleY; + float lc = MathUtils.SinDeg(rotation + shearX) * scaleX; + float ld = MathUtils.SinDeg(rotationY) * scaleY; + if (skeleton.flipX) { + x = -x; + la = -la; + lb = -lb; + } + if (skeleton.flipY != yDown) { + y = -y; + lc = -lc; + ld = -ld; + } + a = la; + b = lb; + c = lc; + d = ld; + worldX = x + skeleton.x; + worldY = y + skeleton.y; + // worldSignX = Math.Sign(scaleX); + // worldSignY = Math.Sign(scaleY); + return; + } + + float pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d; + worldX = pa * x + pb * y + parent.worldX; + worldY = pc * x + pd * y + parent.worldY; + // worldSignX = parent.worldSignX * Math.Sign(scaleX); + // worldSignY = parent.worldSignY * Math.Sign(scaleY); + + switch (data.transformMode) { + case TransformMode.Normal: { + float rotationY = rotation + 90 + shearY; + float la = MathUtils.CosDeg(rotation + shearX) * scaleX; + float lb = MathUtils.CosDeg(rotationY) * scaleY; + float lc = MathUtils.SinDeg(rotation + shearX) * scaleX; + float ld = MathUtils.SinDeg(rotationY) * scaleY; + a = pa * la + pb * lc; + b = pa * lb + pb * ld; + c = pc * la + pd * lc; + d = pc * lb + pd * ld; + return; + } + case TransformMode.OnlyTranslation: { + float rotationY = rotation + 90 + shearY; + a = MathUtils.CosDeg(rotation + shearX) * scaleX; + b = MathUtils.CosDeg(rotationY) * scaleY; + c = MathUtils.SinDeg(rotation + shearX) * scaleX; + d = MathUtils.SinDeg(rotationY) * scaleY; + break; + } + case TransformMode.NoRotationOrReflection: { + float s = pa * pa + pc * pc, prx; + if (s > 0.0001f) { + s = Math.Abs(pa * pd - pb * pc) / s; + pb = pc * s; + pd = pa * s; + prx = MathUtils.Atan2(pc, pa) * MathUtils.RadDeg; + } else { + pa = 0; + pc = 0; + prx = 90 - MathUtils.Atan2(pd, pb) * MathUtils.RadDeg; + } + float rx = rotation + shearX - prx; + float ry = rotation + shearY - prx + 90; + float la = MathUtils.CosDeg(rx) * scaleX; + float lb = MathUtils.CosDeg(ry) * scaleY; + float lc = MathUtils.SinDeg(rx) * scaleX; + float ld = MathUtils.SinDeg(ry) * scaleY; + a = pa * la - pb * lc; + b = pa * lb - pb * ld; + c = pc * la + pd * lc; + d = pc * lb + pd * ld; + break; + } + case TransformMode.NoScale: + case TransformMode.NoScaleOrReflection: { + float cos = MathUtils.CosDeg(rotation), sin = MathUtils.SinDeg(rotation); + float za = pa * cos + pb * sin; + float zc = pc * cos + pd * sin; + float s = (float)Math.Sqrt(za * za + zc * zc); + if (s > 0.00001f) s = 1 / s; + za *= s; + zc *= s; + s = (float)Math.Sqrt(za * za + zc * zc); + float r = MathUtils.PI / 2 + MathUtils.Atan2(zc, za); + float zb = MathUtils.Cos(r) * s; + float zd = MathUtils.Sin(r) * s; + float la = MathUtils.CosDeg(shearX) * scaleX; + float lb = MathUtils.CosDeg(90 + shearY) * scaleY; + float lc = MathUtils.SinDeg(shearX) * scaleX; + float ld = MathUtils.SinDeg(90 + shearY) * scaleY; + if (data.transformMode != TransformMode.NoScaleOrReflection? pa * pd - pb* pc< 0 : skeleton.flipX != skeleton.flipY) { + zb = -zb; + zd = -zd; + } + a = za * la + zb * lc; + b = za * lb + zb * ld; + c = zc * la + zd * lc; + d = zc * lb + zd * ld; + return; + } + } + + if (skeleton.flipX) { + a = -a; + b = -b; + } + if (skeleton.flipY != Bone.yDown) { + c = -c; + d = -d; + } + } + + public void SetToSetupPose () { + BoneData data = this.data; + x = data.x; + y = data.y; + rotation = data.rotation; + scaleX = data.scaleX; + scaleY = data.scaleY; + shearX = data.shearX; + shearY = data.shearY; + } + + /// + /// 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).. + /// + /// Some information is ambiguous in the world transform, such as -1,-1 scale versus 180 rotation. + /// + internal void UpdateAppliedTransform () { + appliedValid = true; + Bone parent = this.parent; + if (parent == null) { + ax = worldX; + ay = worldY; + arotation = MathUtils.Atan2(c, a) * MathUtils.RadDeg; + ascaleX = (float)Math.Sqrt(a * a + c * c); + ascaleY = (float)Math.Sqrt(b * b + d * d); + ashearX = 0; + ashearY = MathUtils.Atan2(a * b + c * d, a * d - b * c) * MathUtils.RadDeg; + return; + } + float pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d; + float pid = 1 / (pa * pd - pb * pc); + float dx = worldX - parent.worldX, dy = worldY - parent.worldY; + ax = (dx * pd * pid - dy * pb * pid); + ay = (dy * pa * pid - dx * pc * pid); + float ia = pid * pd; + float id = pid * pa; + float ib = pid * pb; + float ic = pid * pc; + float ra = ia * a - ib * c; + float rb = ia * b - ib * d; + float rc = id * c - ic * a; + float rd = id * d - ic * b; + ashearX = 0; + ascaleX = (float)Math.Sqrt(ra * ra + rc * rc); + if (ascaleX > 0.0001f) { + float det = ra * rd - rb * rc; + ascaleY = det / ascaleX; + ashearY = MathUtils.Atan2(ra * rb + rc * rd, det) * MathUtils.RadDeg; + arotation = MathUtils.Atan2(rc, ra) * MathUtils.RadDeg; + } else { + ascaleX = 0; + ascaleY = (float)Math.Sqrt(rb * rb + rd * rd); + ashearY = 0; + arotation = 90 - MathUtils.Atan2(rd, rb) * MathUtils.RadDeg; + } + } + + public void WorldToLocal (float worldX, float worldY, out float localX, out float localY) { + float a = this.a, b = this.b, c = this.c, d = this.d; + float invDet = 1 / (a * d - b * c); + float x = worldX - this.worldX, y = worldY - this.worldY; + localX = (x * d * invDet - y * b * invDet); + localY = (y * a * invDet - x * c * invDet); + } + + public void LocalToWorld (float localX, float localY, out float worldX, out float worldY) { + worldX = localX * a + localY * b + this.worldX; + worldY = localX * c + localY * d + this.worldY; + } + + public float WorldToLocalRotationX { + get { + Bone parent = this.parent; + if (parent == null) return arotation; + float pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d, a = this.a, c = this.c; + return MathUtils.Atan2(pa * c - pc * a, pd * a - pb * c) * MathUtils.RadDeg; + } + } + + public float WorldToLocalRotationY { + get { + Bone parent = this.parent; + if (parent == null) return arotation; + float pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d, b = this.b, d = this.d; + return MathUtils.Atan2(pa * d - pc * b, pd * b - pb * d) * MathUtils.RadDeg; + } + } + + public float WorldToLocalRotation (float worldRotation) { + float sin = MathUtils.SinDeg(worldRotation), cos = MathUtils.CosDeg(worldRotation); + return MathUtils.Atan2(a * sin - c * cos, d * cos - b * sin) * MathUtils.RadDeg; + } + + public float LocalToWorldRotation (float localRotation) { + float sin = MathUtils.SinDeg(localRotation), cos = MathUtils.CosDeg(localRotation); + return MathUtils.Atan2(cos * c + sin * d, cos * a + sin * b) * MathUtils.RadDeg; + } + + /// + /// Rotates the world transform the specified amount and sets isAppliedValid to false. + /// + /// Degrees. + public void RotateWorld (float degrees) { + float a = this.a, b = this.b, c = this.c, d = this.d; + float cos = MathUtils.CosDeg(degrees), sin = MathUtils.SinDeg(degrees); + this.a = cos * a - sin * c; + this.b = cos * b - sin * d; + this.c = sin * a + cos * c; + this.d = sin * b + cos * d; + appliedValid = false; + } + + override public string ToString () { + return data.name; + } + }; +} + +#endif /* Spine_Bone_h */ diff --git a/spine-cpp/spine-cpp/include/spine/Skin.h b/spine-cpp/spine-cpp/include/spine/Skin.h new file mode 100644 index 000000000..1c6386964 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/Skin.h @@ -0,0 +1,129 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Skin_h +#define Spine_Skin_h + +namespace Spine +{ + /// Stores attachments by slot index and attachment name. + /// See SkeletonData::getDefaultSkin, Skeleton::getSkin, and + /// http://esotericsoftware.com/spine-runtime-skins in the Spine Runtimes Guide. + class Skin + { + public: + public std::string Name { get { return name; } } + public Dictionary Attachments { get { return attachments; } } + + public Skin (std::string name) { + if (name == null) throw new ArgumentNullException("name", "name cannot be null."); + this.name = name; + } + + /// Adds an attachment to the skin for the specified slot index and name. If the name already exists for the slot, the previous value is replaced. + public void AddAttachment (int slotIndex, std::string name, Attachment attachment) { + if (attachment == null) throw new ArgumentNullException("attachment", "attachment cannot be null."); + attachments[new AttachmentKeyTuple(slotIndex, name)] = attachment; + } + + /// Returns the attachment for the specified slot index and name, or null. + /// May be null. + public Attachment GetAttachment (int slotIndex, std::string name) { + Attachment attachment; + attachments.TryGetValue(new AttachmentKeyTuple(slotIndex, name), out attachment); + return attachment; + } + + /// Finds the skin keys for a given slot. The results are added to the passed List(names). + /// The target slotIndex. To find the slot index, use or + /// Found skin key names will be added to this list. + public void FindNamesForSlot (int slotIndex, List names) { + if (names == null) throw new ArgumentNullException("names", "names cannot be null."); + foreach (AttachmentKeyTuple key in attachments.Keys) + if (key.slotIndex == slotIndex) names.Add(key.name); + } + + /// Finds the attachments for a given slot. The results are added to the passed List(Attachment). + /// The target slotIndex. To find the slot index, use or + /// Found Attachments will be added to this list. + public void FindAttachmentsForSlot (int slotIndex, List attachments) { + if (attachments == null) throw new ArgumentNullException("attachments", "attachments cannot be null."); + foreach (KeyValuePair entry in this.attachments) + if (entry.Key.slotIndex == slotIndex) attachments.Add(entry.Value); + } + + override public std::string ToString () { + return name; + } + + private: + internal std::string name; + Dictionary attachments = new Dictionary(AttachmentKeyTupleComparer.Instance); + + /// Attach all attachments from this skin if the corresponding attachment from the old skin is currently attached. + internal void AttachAll (Skeleton skeleton, Skin oldSkin) { + foreach (KeyValuePair entry in oldSkin.attachments) { + int slotIndex = entry.Key.slotIndex; + Slot slot = skeleton.slots.Items[slotIndex]; + if (slot.Attachment == entry.Value) { + Attachment attachment = GetAttachment(slotIndex, entry.Key.name); + if (attachment != null) slot.Attachment = attachment; + } + } + } + + public struct AttachmentKeyTuple { + public readonly int slotIndex; + public readonly std::string name; + internal readonly int nameHashCode; + + public AttachmentKeyTuple (int slotIndex, std::string name) { + this.slotIndex = slotIndex; + this.name = name; + nameHashCode = this.name.GetHashCode(); + } + } + + // Avoids boxing in the dictionary. + class AttachmentKeyTupleComparer : IEqualityComparer { + internal static readonly AttachmentKeyTupleComparer Instance = new AttachmentKeyTupleComparer(); + + bool IEqualityComparer.Equals (AttachmentKeyTuple o1, AttachmentKeyTuple o2) { + return o1.slotIndex == o2.slotIndex && o1.nameHashCode == o2.nameHashCode && o1.name == o2.name; + } + + int IEqualityComparer.GetHashCode (AttachmentKeyTuple o) { + return o.slotIndex; + } + } + }; +} + +#endif /* Spine_Skin_h */ diff --git a/spine-cpp/spine-cpp/include/spine/Slot.h b/spine-cpp/spine-cpp/include/spine/Slot.h new file mode 100644 index 000000000..edce64ffa --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/Slot.h @@ -0,0 +1,98 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Slot_h +#define Spine_Slot_h + +#include +#include + +namespace Spine +{ + class SlotData; + class Bone; + class Skeleton; + class Attachment; + + class Slot + { + public: + Slot(SlotData& data, Bone& bone); + + void setToSetupPose(); + + const SlotData& getSlotData(); + const Bone& getBone(); + const Skeleton& getSkeleton(); + + float getR(); + void setR(float inValue); + float getG(); + void setG(float inValue); + float getB(); + void setB(float inValue); + float getA(); + void setA(float inValue); + + float getR2(); + void setR2(float inValue); + float getG2(); + void setG2(float inValue); + float getB2(); + void setB2(float inValue); + bool hasSecondColor(); + void setHasSecondColor(bool inValue); + + /// May be null. + Attachment* getAttachment(); + void setAttachment(Attachment* inValue); + + float getAttachmentTime(); + void setAttachmentTime(float inValue); + + std::vector& getAttachmentVertices(); + void setAttachmentVertices(std::vector inValue); + + private: + const SlotData& _slotData; + const Bone& _bone; + const Skeleton& _skeleton; + float _r, _g, _b, _a; + float _r2, _g2, _b2; + bool _hasSecondColor; + Attachment* _attachment; + float _attachmentTime; + std::vector _attachmentVertices; + + friend std::ostream& operator <<(std::ostream& os, const Slot& ref); + } +} + +#endif /* Spine_Slot_h */ diff --git a/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h b/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h new file mode 100644 index 000000000..5ce55ac79 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h @@ -0,0 +1,78 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_TransformConstraintData_h +#define Spine_TransformConstraintData_h + +#include +#include + +namespace Spine +{ + class BoneData; + + class TransformConstraintData + { + public: + TransformConstraintData(std::string name); + + const std::string& getName(); + int getOrder(); + std::vector& getBones(); + BoneData* getTarget(); + float getRotateMix(); + float getTranslateMix(); + float getScaleMix(); + float getShearMix(); + + float getOffsetRotation(); + float getOffsetX(); + float getOffsetY(); + float getOffsetScaleX(); + float getOffsetScaleY(); + float getOffsetShearY(); + + bool isRelative(); + bool isLocal(); + + private: + const std::string _name; + int _order; + std::vector _bones; + BoneData* _target; + float _rotateMix, _translateMix, _scaleMix, _shearMix; + float _offsetRotation, _offsetX, _offsetY, _offsetScaleX, _offsetScaleY, _offsetShearY; + bool _relative, _local; + + friend std::ostream& operator <<(std::ostream& os, const TransformConstraintData& ref); + }; +} + +#endif /* Spine_TransformConstraintData_h */ diff --git a/spine-cpp/spine-cpp/src/spine/Attachment.cpp b/spine-cpp/spine-cpp/src/spine/Attachment.cpp new file mode 100644 index 000000000..8ea383eea --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/Attachment.cpp @@ -0,0 +1,53 @@ +/****************************************************************************** +* Spine Runtimes Software License v2.5 +* +* Copyright (c) 2013-2016, Esoteric Software +* All rights reserved. +* +* You are granted a perpetual, non-exclusive, non-sublicensable, and +* non-transferable license to use, install, execute, and perform the Spine +* Runtimes software and derivative works solely for personal or internal +* use. Without the written permission of Esoteric Software (see Section 2 of +* the Spine Software License Agreement), you may not (a) modify, translate, +* adapt, or develop new applications using the Spine Runtimes or otherwise +* create derivative works or improvements of the Spine Runtimes or (b) remove, +* delete, alter, or obscure any trademarks or any copyright, trademark, patent, +* or other intellectual property or proprietary rights notices on or in the +* Software, including any copy thereof. Redistributions in binary or source +* form must include this license and terms. +* +* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +#include + +#include + +namespace Spine +{ + Attachment::Attachment(std::string name) : _name(name) + { + assert(_name.length() > 0); + } + + const std::string& Attachment::getName() + { + return _name; + } + + std::ostream& operator <<(std::ostream& os, const Attachment& ref) + { + os << ref._name; + + return os; + } +} diff --git a/spine-cpp/spine-cpp/src/spine/Bone.cpp b/spine-cpp/spine-cpp/src/spine/Bone.cpp new file mode 100644 index 000000000..bb4d2ccfe --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/Bone.cpp @@ -0,0 +1,34 @@ +/****************************************************************************** +* Spine Runtimes Software License v2.5 +* +* Copyright (c) 2013-2016, Esoteric Software +* All rights reserved. +* +* You are granted a perpetual, non-exclusive, non-sublicensable, and +* non-transferable license to use, install, execute, and perform the Spine +* Runtimes software and derivative works solely for personal or internal +* use. Without the written permission of Esoteric Software (see Section 2 of +* the Spine Software License Agreement), you may not (a) modify, translate, +* adapt, or develop new applications using the Spine Runtimes or otherwise +* create derivative works or improvements of the Spine Runtimes or (b) remove, +* delete, alter, or obscure any trademarks or any copyright, trademark, patent, +* or other intellectual property or proprietary rights notices on or in the +* Software, including any copy thereof. Redistributions in binary or source +* form must include this license and terms. +* +* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +namespace Spine +{ + // TODO +} diff --git a/spine-cpp/spine-cpp/src/spine/Skin.cpp b/spine-cpp/spine-cpp/src/spine/Skin.cpp new file mode 100644 index 000000000..bb4d2ccfe --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/Skin.cpp @@ -0,0 +1,34 @@ +/****************************************************************************** +* Spine Runtimes Software License v2.5 +* +* Copyright (c) 2013-2016, Esoteric Software +* All rights reserved. +* +* You are granted a perpetual, non-exclusive, non-sublicensable, and +* non-transferable license to use, install, execute, and perform the Spine +* Runtimes software and derivative works solely for personal or internal +* use. Without the written permission of Esoteric Software (see Section 2 of +* the Spine Software License Agreement), you may not (a) modify, translate, +* adapt, or develop new applications using the Spine Runtimes or otherwise +* create derivative works or improvements of the Spine Runtimes or (b) remove, +* delete, alter, or obscure any trademarks or any copyright, trademark, patent, +* or other intellectual property or proprietary rights notices on or in the +* Software, including any copy thereof. Redistributions in binary or source +* form must include this license and terms. +* +* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +namespace Spine +{ + // TODO +} diff --git a/spine-cpp/spine-cpp/src/spine/Slot.cpp b/spine-cpp/spine-cpp/src/spine/Slot.cpp new file mode 100644 index 000000000..5e0af36aa --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/Slot.cpp @@ -0,0 +1,215 @@ +/****************************************************************************** +* Spine Runtimes Software License v2.5 +* +* Copyright (c) 2013-2016, Esoteric Software +* All rights reserved. +* +* You are granted a perpetual, non-exclusive, non-sublicensable, and +* non-transferable license to use, install, execute, and perform the Spine +* Runtimes software and derivative works solely for personal or internal +* use. Without the written permission of Esoteric Software (see Section 2 of +* the Spine Software License Agreement), you may not (a) modify, translate, +* adapt, or develop new applications using the Spine Runtimes or otherwise +* create derivative works or improvements of the Spine Runtimes or (b) remove, +* delete, alter, or obscure any trademarks or any copyright, trademark, patent, +* or other intellectual property or proprietary rights notices on or in the +* Software, including any copy thereof. Redistributions in binary or source +* form must include this license and terms. +* +* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +#include + +#include +#include +#include +#include + +namespace Spine +{ + Slot::Slot(SlotData& data, Bone& bone) : + _slotData(data), + _bone(bone), + _skeleton(bone.getSkeletion()), + _r(1), + _g(1), + _b(1), + _a(1), + _r2(0), + _g2(0), + _b2(0), + _hasSecondColor(false), + _attachment(nullptr), + _attachmentTime(0) + { + setToSetupPose(); + } + + void Slot::setToSetupPose() + { + _r = _slotData.getR(); + _g = _slotData.getG(); + _b = _slotData.getB(); + _a = _slotData.getA(); + + std::string attachmentName = _slotData.getAttachmentName(); + if (attachmentName.length() > 0) + { + _attachment = nullptr; + setAttachment(_skeleton.getAttachment(_slotData.getIndex(), attachmentName)); + } + else + { + setAttachment(nullptr); + } + } + + const SlotData& Slot::getSlotData() + { + return _slotData; + } + + const Bone& Slot::getBone() + { + return _bone; + } + + const Skeleton& Slot::getSkeleton() + { + return _skeleton; + } + + float Slot::getR() + { + return _r; + } + + void Slot::setR(float inValue) + { + _r = inValue; + } + + float Slot::getG() + { + return _g; + } + + void Slot::setG(float inValue) + { + _g = inValue; + } + + float Slot::getB() + { + return _b; + } + + void Slot::setB(float inValue) + { + _b = inValue; + } + + float Slot::getA() + { + return _a; + } + + void Slot::setA(float inValue) + { + _a = inValue; + } + + float Slot::getR2() + { + return _r2; + } + + void Slot::setR2(float inValue) + { + _r2 = inValue; + } + + float Slot::getG2() + { + return _g2; + } + + void Slot::setG2(float inValue) + { + _g2 = inValue; + } + + float Slot::getB2() + { + return _b2; + } + + void Slot::setB2(float inValue) + { + _b2 = inValue; + } + + bool Slot::hasSecondColor() + { + return _hasSecondColor; + } + + void Slot::setHasSecondColor(bool inValue) + { + _hasSecondColor = inValue; + } + + Attachment* Slot::getAttachment() + { + return _attachment; + } + + void Slot::setAttachment(Attachment* inValue) + { + if (_attachment == inValue) + { + return; + } + + _attachment = inValue; + _attachmentTime = _skeleton.getTime(); + _attachmentVertices.clear(); + } + + float Slot::getAttachmentTime() + { + return _skeleton.getTime() - _attachmentTime; + } + + void Slot::setAttachmentTime(float inValue) + { + _attachmentTime = _skeleton.getTime() - inValue; + } + + std::vector& Slot::getAttachmentVertices() + { + return _attachmentVertices; + } + + void Slot::setAttachmentVertices(std::vector inValue) + { + _attachmentVertices = inValue; + } + + std::ostream& operator <<(std::ostream& os, const Slot& ref) + { + os << ref._slotData.getName(); + + return os; + } +} diff --git a/spine-cpp/spine-cpp/src/spine/TransformConstraintData.cpp b/spine-cpp/spine-cpp/src/spine/TransformConstraintData.cpp new file mode 100644 index 000000000..7d099b4e7 --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/TransformConstraintData.cpp @@ -0,0 +1,144 @@ +/****************************************************************************** +* Spine Runtimes Software License v2.5 +* +* Copyright (c) 2013-2016, Esoteric Software +* All rights reserved. +* +* You are granted a perpetual, non-exclusive, non-sublicensable, and +* non-transferable license to use, install, execute, and perform the Spine +* Runtimes software and derivative works solely for personal or internal +* use. Without the written permission of Esoteric Software (see Section 2 of +* the Spine Software License Agreement), you may not (a) modify, translate, +* adapt, or develop new applications using the Spine Runtimes or otherwise +* create derivative works or improvements of the Spine Runtimes or (b) remove, +* delete, alter, or obscure any trademarks or any copyright, trademark, patent, +* or other intellectual property or proprietary rights notices on or in the +* Software, including any copy thereof. Redistributions in binary or source +* form must include this license and terms. +* +* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +#include + +#include + +#include + +namespace Spine +{ + TransformConstraintData::TransformConstraintData(std::string name) : + _name(name), + _order(0), + _target(nullptr), + _rotateMix(0), + _translateMix(0), + _scaleMix(0), + _shearMix(0), + _offsetRotation(0), + _offsetX(0), + _offsetY(0), + _offsetScaleX(0), + _offsetScaleY(0), + _offsetShearY(0), + _relative(false), + _local(false) + { + assert(_name.length() > 0); + } + + const std::string& TransformConstraintData::getName() + { + return _name; + } + + int TransformConstraintData::getOrder() + { + return _order; + } + std::vector& TransformConstraintData::getBones() + { + return _bones; + } + + BoneData* TransformConstraintData::getTarget() + { + return _target; + } + + float TransformConstraintData::getRotateMix() + { + return _rotateMix; + } + + float TransformConstraintData::getTranslateMix() + { + return _translateMix; + } + + float TransformConstraintData::getScaleMix() + { + return _scaleMix; + } + + float TransformConstraintData::getShearMix() + { + return _shearMix; + } + + float TransformConstraintData::getOffsetRotation() + { + return _offsetRotation; + } + + float TransformConstraintData::getOffsetX() + { + return _offsetX; + } + + float TransformConstraintData::getOffsetY() + { + return _offsetY; + } + + float TransformConstraintData::getOffsetScaleX() + { + return _offsetScaleX; + } + + float TransformConstraintData::getOffsetScaleY() + { + return _offsetScaleY; + } + + float TransformConstraintData::getOffsetShearY() + { + return _offsetShearY; + } + + bool TransformConstraintData::isRelative() + { + return _relative; + } + + bool TransformConstraintData::isLocal() + { + return _local; + } + + std::ostream& operator <<(std::ostream& os, const TransformConstraintData& ref) + { + os << ref._name; + + return os; + } +} From 08af18e86efa00080f2c27df2c809d40b21d3c14 Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Tue, 3 Oct 2017 18:47:25 -0400 Subject: [PATCH 07/83] wip --- spine-cpp/spine-cpp/include/spine/Skin.h | 123 ++++++++++------------- spine-cpp/spine-cpp/src/spine/Skin.cpp | 102 ++++++++++++++++++- 2 files changed, 153 insertions(+), 72 deletions(-) diff --git a/spine-cpp/spine-cpp/include/spine/Skin.h b/spine-cpp/spine-cpp/include/spine/Skin.h index 1c6386964..910e2585e 100644 --- a/spine-cpp/spine-cpp/include/spine/Skin.h +++ b/spine-cpp/spine-cpp/include/spine/Skin.h @@ -31,97 +31,78 @@ #ifndef Spine_Skin_h #define Spine_Skin_h +#include +#include +#include + namespace Spine { + class Attachment; + class Skeleton; + + class AttachmentKey; + /// Stores attachments by slot index and attachment name. /// See SkeletonData::getDefaultSkin, Skeleton::getSkin, and /// http://esotericsoftware.com/spine-runtime-skins in the Spine Runtimes Guide. class Skin { public: - public std::string Name { get { return name; } } - public Dictionary Attachments { get { return attachments; } } + Skin(std::string name); - public Skin (std::string name) { - if (name == null) throw new ArgumentNullException("name", "name cannot be null."); - this.name = name; - } - - /// Adds an attachment to the skin for the specified slot index and name. If the name already exists for the slot, the previous value is replaced. - public void AddAttachment (int slotIndex, std::string name, Attachment attachment) { - if (attachment == null) throw new ArgumentNullException("attachment", "attachment cannot be null."); - attachments[new AttachmentKeyTuple(slotIndex, name)] = attachment; - } + /// Adds an attachment to the skin for the specified slot index and name. + /// If the name already exists for the slot, the previous value is replaced. + void addAttachment(int slotIndex, std::string name, Attachment* attachment); /// Returns the attachment for the specified slot index and name, or null. - /// May be null. - public Attachment GetAttachment (int slotIndex, std::string name) { - Attachment attachment; - attachments.TryGetValue(new AttachmentKeyTuple(slotIndex, name), out attachment); - return attachment; - } + Attachment* getAttachment(int slotIndex, std::string name); - /// Finds the skin keys for a given slot. The results are added to the passed List(names). - /// The target slotIndex. To find the slot index, use or - /// Found skin key names will be added to this list. - public void FindNamesForSlot (int slotIndex, List names) { - if (names == null) throw new ArgumentNullException("names", "names cannot be null."); - foreach (AttachmentKeyTuple key in attachments.Keys) - if (key.slotIndex == slotIndex) names.Add(key.name); - } + /// Finds the skin keys for a given slot. The results are added to the passed vector names. + /// @param slotIndex The target slotIndex. To find the slot index, use Skeleton::findSlotIndex or SkeletonData::findSlotIndex + /// @param names Found skin key names will be added to this vector. + void findNamesForSlot(int slotIndex, std::vector& names); /// Finds the attachments for a given slot. The results are added to the passed List(Attachment). - /// The target slotIndex. To find the slot index, use or - /// Found Attachments will be added to this list. - public void FindAttachmentsForSlot (int slotIndex, List attachments) { - if (attachments == null) throw new ArgumentNullException("attachments", "attachments cannot be null."); - foreach (KeyValuePair entry in this.attachments) - if (entry.Key.slotIndex == slotIndex) attachments.Add(entry.Value); - } + /// @param slotIndex The target slotIndex. To find the slot index, use Skeleton::findSlotIndex or SkeletonData::findSlotIndex + /// @param attachments Found Attachments will be added to this vector. + void findAttachmentsForSlot(int slotIndex, std::vector& attachments); - override public std::string ToString () { - return name; - } + const std::string& getName(); + std::unordered_map& getAttachments(); private: - internal std::string name; - Dictionary attachments = new Dictionary(AttachmentKeyTupleComparer.Instance); + const std::string _name; + std::unordered_map _attachments; /// Attach all attachments from this skin if the corresponding attachment from the old skin is currently attached. - internal void AttachAll (Skeleton skeleton, Skin oldSkin) { - foreach (KeyValuePair entry in oldSkin.attachments) { - int slotIndex = entry.Key.slotIndex; - Slot slot = skeleton.slots.Items[slotIndex]; - if (slot.Attachment == entry.Value) { - Attachment attachment = GetAttachment(slotIndex, entry.Key.name); - if (attachment != null) slot.Attachment = attachment; + void attachAll(Skeleton& skeleton, Skin& oldSkin); + + class AttachmentKey + { + public: + const int _slotIndex; + const std::string _name; + + AttachmentKey(int slotIndex, std::string name); + + bool operator==(const AttachmentKey &other) const; + }; + + friend std::ostream& operator <<(std::ostream& os, const Skin& ref); + + namespace std + { + template <> + struct hash + { + size_t operator()(const AttachmentKey& val) const + { + size_t h1 = hash{}(val._slotIndex); + size_t h2 = hash{}(val._name); + + return h1 ^ (h2 << 1); } - } - } - - public struct AttachmentKeyTuple { - public readonly int slotIndex; - public readonly std::string name; - internal readonly int nameHashCode; - - public AttachmentKeyTuple (int slotIndex, std::string name) { - this.slotIndex = slotIndex; - this.name = name; - nameHashCode = this.name.GetHashCode(); - } - } - - // Avoids boxing in the dictionary. - class AttachmentKeyTupleComparer : IEqualityComparer { - internal static readonly AttachmentKeyTupleComparer Instance = new AttachmentKeyTupleComparer(); - - bool IEqualityComparer.Equals (AttachmentKeyTuple o1, AttachmentKeyTuple o2) { - return o1.slotIndex == o2.slotIndex && o1.nameHashCode == o2.nameHashCode && o1.name == o2.name; - } - - int IEqualityComparer.GetHashCode (AttachmentKeyTuple o) { - return o.slotIndex; - } + }; } }; } diff --git a/spine-cpp/spine-cpp/src/spine/Skin.cpp b/spine-cpp/spine-cpp/src/spine/Skin.cpp index bb4d2ccfe..8ee4f916a 100644 --- a/spine-cpp/spine-cpp/src/spine/Skin.cpp +++ b/spine-cpp/spine-cpp/src/spine/Skin.cpp @@ -28,7 +28,107 @@ * POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ +#include + +#include + namespace Spine { - // TODO + Skin::Skin(std::string name) : _name(name) + { + assert(_name.length() > 0); + } + + void Skin::addAttachment(int slotIndex, std::string name, Attachment* attachment) + { + assert(attachment); + + _attachments[AttachmentKey(slotIndex, name)] = attachment; + } + + /// Returns the attachment for the specified slot index and name, or null. + Attachment* Skin::getAttachment(int slotIndex, std::string name) + { + std::iterator q = _attachments.find(AttachmentKey(slotIndex, name)); + + Attachment* ret = nullptr; + + if (q != _attachments.end()) + { + ret = q->second; + } + + return ret; + } + + struct sum + { + sum(int * t):total(t){}; + int * total; + + void operator()(AttachmentKey key) + { + *total+=element; + } + }; + + /// Finds the skin keys for a given slot. The results are added to the passed vector names. + /// @param slotIndex The target slotIndex. To find the slot index, use Skeleton::findSlotIndex or SkeletonData::findSlotIndex + /// @param names Found skin key names will be added to this vector. + void Skin::findNamesForSlot(int slotIndex, std::vector& names) + { + foreach (AttachmentKey key in attachments.Keys) + if (key.slotIndex == slotIndex) names.Add(key.name); + } + + /// Finds the attachments for a given slot. The results are added to the passed List(Attachment). + /// @param slotIndex The target slotIndex. To find the slot index, use Skeleton::findSlotIndex or SkeletonData::findSlotIndex + /// @param attachments Found Attachments will be added to this vector. + void Skin::findAttachmentsForSlot(int slotIndex, std::vector& attachments) + { + foreach (KeyValuePair entry in this.attachments) + if (entry.Key.slotIndex == slotIndex) attachments.Add(entry.Value); + } + + const std::string& Skin::getName() + { + // + } + + std::unordered_map& Skin::getAttachments() + { + // + } + + void Skin::attachAll(Skeleton& skeleton, Skin& oldSkin) + { + foreach (KeyValuePair entry in oldSkin.attachments) + { + int slotIndex = entry.Key.slotIndex; + Slot slot = skeleton.slots.Items[slotIndex]; + if (slot.Attachment == entry.Value) { + Attachment attachment = GetAttachment(slotIndex, entry.Key.name); + if (attachment != null) slot.Attachment = attachment; + } + } + } + + AttachmentKey::AttachmentKey(int slotIndex, std::string name) : + _slotIndex(slotIndex), + _name(name) + { + // Empty + } + + bool AttachmentKey::operator==(const AttachmentKey &other) const + { + return _slotIndex == other._slotIndex && _name == other._name; + } + + std::ostream& operator <<(std::ostream& os, const Skin& ref) + { + os << ref.getName(); + + return os; + } } From 20a27e91ece528e9b6726e49eab127b26b6cbdb9 Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Wed, 4 Oct 2017 10:52:45 -0400 Subject: [PATCH 08/83] README.md url update --- spine-cpp/README.md | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/spine-cpp/README.md b/spine-cpp/README.md index 03c7df908..ae59ae773 100644 --- a/spine-cpp/README.md +++ b/spine-cpp/README.md @@ -4,7 +4,7 @@ The spine-cpp runtime provides basic functionality to load and manipulate [Spine ## Licensing -This Spine Runtime may only be used for personal or internal use, typically to evaluate Spine before purchasing. If you would like to incorporate a Spine Runtime into your applications, distribute software containing a Spine Runtime, or modify a Spine Runtime, then you will need a valid [Spine license](https://esotericsoftware.com/spine-purchase). Please see the [Spine Runtimes Software License](https://github.com/EsotericSoftware/spine-runtimes/blob/master/LICENSE) for detailed information. +This Spine Runtime may only be used for personal or internal use, typically to evaluate Spine before purchasing. If you would like to incorporate a Spine Runtime into your applications, distribute software containing a Spine Runtime, or modify a Spine Runtime, then you will need a valid [Spine license](https://esotericsoftware.com/spine-purchase). Please see the [Spine Runtimes Software License](http://esotericsoftware.com/git/spine-runtimes/blob/LICENSE) for detailed information. The Spine Runtimes are developed with the intent to be used with data exported from Spine. By purchasing Spine, `Section 2` of the [Spine Software License](https://esotericsoftware.com/files/license.txt) grants the right to create and distribute derivative works of the Spine Runtimes. @@ -16,25 +16,29 @@ spine-cpp supports all Spine features. ## Setup -1. Download the Spine Runtimes source using [git](https://help.github.com/articles/set-up-git) or by downloading it [as a zip](https://github.com/EsotericSoftware/spine-runtimes/archive/3.6.zip). +1. Download the Spine Runtimes source using [git](https://help.github.com/articles/set-up-git) or by downloading it as a zip via the download button above. 1. Open the `spine-c.sln` Visual C++ 2010 Express project file. For other IDEs, you will need to create a new project and import the source. Alternatively, the contents of the `spine-c/spine-c/src` and `spine-c/spine-c/include` directories can be copied into your project. Be sure your header search is configured to find the contents of the `spine-c/spine-c/include` directory. Note that the includes use `spine/Xxx.h`, so the `spine` directory cannot be omitted when copying the files. -If `SPINE_SHORT_NAMES` is defined, the `sp` prefix for all structs and functions is optional. Only use this if the spine-c names won't cause a conflict. +If `SPINE_SHORT_NAMES` is defined, the `sp` prefix for all structs and functions is optional. Only use this if the spine-cpp names won't cause a conflict. ## Extension -Extending spine-c requires implementing three methods: +Extending spine-cpp requires implementing three methods: - `_spAtlasPage_createTexture` Loads a texture and stores it and its size in the `void* rendererObject`, `width` and `height` fields of an `spAtlasPage` struct. - `_spAtlasPage_disposeTexture` Disposes of a texture loaded with `_spAtlasPage_createTexture`. - `_spUtil_readFile` Reads a file. If this doesn't need to be customized, `_readFile` is provided which reads a file using `fopen`. -With these implemented, the spine-c API can then be used to load Spine animation data. Rendering is done by enumerating the slots for a skeleton and rendering the attachment for each slot. Each attachment has a `rendererObject` field that is set when the attachment is loaded. +With these implemented, the spine-cpp API can then be used to load Spine animation data. Rendering is done by enumerating the slots for a skeleton and rendering the attachment for each slot. Each attachment has a `rendererObject` field that is set when the attachment is loaded. For example, `AtlasAttachmentLoader` is typically used to load attachments when using a Spine texture atlas. When `AtlasAttachmentLoader` loads a `RegionAttachment`, the attachment's `void* rendererObject` is set to an `AtlasRegion`. Rendering code can then obtain the `AtlasRegion` from the attachment, get the `AtlasPage` it belongs to, and get the page's `void* rendererObject`. This is the renderer specific texture object set by `_spAtlasPage_createTexture`. Attachment loading can be [customized](http://esotericsoftware.com/spine-using-runtimes/#attachmentloader) if not using `AtlasAttachmentLoader` or to provider different renderer specific data. -[spine-sfml](https://github.com/EsotericSoftware/spine-runtimes/blob/master/spine-sfml/src/spine/spine-sfml.cpp#L39) serves as a simple example of extending spine-c. +[spine-sfml](../spine-sfml/src/spine/spine-sfml.cpp#L39) serves as a simple example of extending spine-c. -spine-c uses an OOP style of programming where each "class" is made up of a struct and a number of functions prefixed with the struct name. More detals about how this works are available in [extension.h](https://github.com/EsotericSoftware/spine-runtimes/blob/master/spine-c/spine-c/include/spine/extension.h#L2). This mechanism allows you to provide your own implementations for `spAttachmentLoader`, `spAttachment` and `spTimeline`, if necessary. +spine-cpp uses an OOP style of programming where each "class" is made up of a struct and a number of functions prefixed with the struct name. More detals about how this works are available in [extension.h](spine-c/include/spine/extension.h#L2). This mechanism allows you to provide your own implementations for `spAttachmentLoader`, `spAttachment` and `spTimeline`, if necessary. + +## Runtimes extending spine-cpp + +- Coming Soon! From 4b48dae7f57cb83e730d66266c09798c5ee1c324 Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Fri, 6 Oct 2017 16:35:51 -0400 Subject: [PATCH 09/83] wip --- spine-cpp/spine-cpp/include/spine/Skeleton.h | 39 +++++++ spine-cpp/spine-cpp/include/spine/Skin.h | 50 ++++----- spine-cpp/spine-cpp/src/spine/Skeleton.cpp | 34 ++++++ spine-cpp/spine-cpp/src/spine/Skin.cpp | 110 ++++++++++--------- 4 files changed, 153 insertions(+), 80 deletions(-) create mode 100644 spine-cpp/spine-cpp/include/spine/Skeleton.h create mode 100644 spine-cpp/spine-cpp/src/spine/Skeleton.cpp diff --git a/spine-cpp/spine-cpp/include/spine/Skeleton.h b/spine-cpp/spine-cpp/include/spine/Skeleton.h new file mode 100644 index 000000000..0ea3e5db1 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/Skeleton.h @@ -0,0 +1,39 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Skeleton_h +#define Spine_Skeleton_h + +namespace Spine +{ + // TODO +} + +#endif /* Spine_Skeleton_h */ diff --git a/spine-cpp/spine-cpp/include/spine/Skin.h b/spine-cpp/spine-cpp/include/spine/Skin.h index 910e2585e..7a8b0f31a 100644 --- a/spine-cpp/spine-cpp/include/spine/Skin.h +++ b/spine-cpp/spine-cpp/include/spine/Skin.h @@ -40,14 +40,23 @@ namespace Spine class Attachment; class Skeleton; - class AttachmentKey; - /// Stores attachments by slot index and attachment name. /// See SkeletonData::getDefaultSkin, Skeleton::getSkin, and /// http://esotericsoftware.com/spine-runtime-skins in the Spine Runtimes Guide. class Skin { public: + class AttachmentKey + { + public: + const int _slotIndex; + const std::string _name; + + AttachmentKey(int slotIndex, std::string name); + + bool operator==(const AttachmentKey &other) const; + }; + Skin(std::string name); /// Adds an attachment to the skin for the specified slot index and name. @@ -77,32 +86,21 @@ namespace Spine /// Attach all attachments from this skin if the corresponding attachment from the old skin is currently attached. void attachAll(Skeleton& skeleton, Skin& oldSkin); - class AttachmentKey - { - public: - const int _slotIndex; - const std::string _name; - - AttachmentKey(int slotIndex, std::string name); - - bool operator==(const AttachmentKey &other) const; - }; - friend std::ostream& operator <<(std::ostream& os, const Skin& ref); - - namespace std + }; +} + +namespace std +{ + template <> + struct hash + { + std::size_t operator()(const Spine::Skin::AttachmentKey& val) const { - template <> - struct hash - { - size_t operator()(const AttachmentKey& val) const - { - size_t h1 = hash{}(val._slotIndex); - size_t h2 = hash{}(val._name); - - return h1 ^ (h2 << 1); - } - }; + size_t h1 = hash{}(val._slotIndex); + size_t h2 = hash{}(val._name); + + return h1 ^ (h2 << 1); } }; } diff --git a/spine-cpp/spine-cpp/src/spine/Skeleton.cpp b/spine-cpp/spine-cpp/src/spine/Skeleton.cpp new file mode 100644 index 000000000..bb4d2ccfe --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/Skeleton.cpp @@ -0,0 +1,34 @@ +/****************************************************************************** +* Spine Runtimes Software License v2.5 +* +* Copyright (c) 2013-2016, Esoteric Software +* All rights reserved. +* +* You are granted a perpetual, non-exclusive, non-sublicensable, and +* non-transferable license to use, install, execute, and perform the Spine +* Runtimes software and derivative works solely for personal or internal +* use. Without the written permission of Esoteric Software (see Section 2 of +* the Spine Software License Agreement), you may not (a) modify, translate, +* adapt, or develop new applications using the Spine Runtimes or otherwise +* create derivative works or improvements of the Spine Runtimes or (b) remove, +* delete, alter, or obscure any trademarks or any copyright, trademark, patent, +* or other intellectual property or proprietary rights notices on or in the +* Software, including any copy thereof. Redistributions in binary or source +* form must include this license and terms. +* +* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +namespace Spine +{ + // TODO +} diff --git a/spine-cpp/spine-cpp/src/spine/Skin.cpp b/spine-cpp/spine-cpp/src/spine/Skin.cpp index 8ee4f916a..c4e9ab0d5 100644 --- a/spine-cpp/spine-cpp/src/spine/Skin.cpp +++ b/spine-cpp/spine-cpp/src/spine/Skin.cpp @@ -30,10 +30,27 @@ #include +#include +#include + +#include + #include namespace Spine { + Skin::AttachmentKey::AttachmentKey(int slotIndex, std::string name) : + _slotIndex(slotIndex), + _name(name) + { + // Empty + } + + bool Skin::AttachmentKey::operator==(const AttachmentKey &other) const + { + return _slotIndex == other._slotIndex && _name == other._name; + } + Skin::Skin(std::string name) : _name(name) { assert(_name.length() > 0); @@ -46,10 +63,9 @@ namespace Spine _attachments[AttachmentKey(slotIndex, name)] = attachment; } - /// Returns the attachment for the specified slot index and name, or null. Attachment* Skin::getAttachment(int slotIndex, std::string name) { - std::iterator q = _attachments.find(AttachmentKey(slotIndex, name)); + std::unordered_map::iterator q = _attachments.find(AttachmentKey(slotIndex, name)); Attachment* ret = nullptr; @@ -61,73 +77,59 @@ namespace Spine return ret; } - struct sum - { - sum(int * t):total(t){}; - int * total; - - void operator()(AttachmentKey key) - { - *total+=element; - } - }; - - /// Finds the skin keys for a given slot. The results are added to the passed vector names. - /// @param slotIndex The target slotIndex. To find the slot index, use Skeleton::findSlotIndex or SkeletonData::findSlotIndex - /// @param names Found skin key names will be added to this vector. void Skin::findNamesForSlot(int slotIndex, std::vector& names) { - foreach (AttachmentKey key in attachments.Keys) - if (key.slotIndex == slotIndex) names.Add(key.name); - } - - /// Finds the attachments for a given slot. The results are added to the passed List(Attachment). - /// @param slotIndex The target slotIndex. To find the slot index, use Skeleton::findSlotIndex or SkeletonData::findSlotIndex - /// @param attachments Found Attachments will be added to this vector. - void Skin::findAttachmentsForSlot(int slotIndex, std::vector& attachments) - { - foreach (KeyValuePair entry in this.attachments) - if (entry.Key.slotIndex == slotIndex) attachments.Add(entry.Value); - } - - const std::string& Skin::getName() - { - // - } - - std::unordered_map& Skin::getAttachments() - { - // - } - - void Skin::attachAll(Skeleton& skeleton, Skin& oldSkin) - { - foreach (KeyValuePair entry in oldSkin.attachments) + for (std::unordered_map::iterator i = _attachments.begin(); i != _attachments.end(); ++i) { - int slotIndex = entry.Key.slotIndex; - Slot slot = skeleton.slots.Items[slotIndex]; - if (slot.Attachment == entry.Value) { - Attachment attachment = GetAttachment(slotIndex, entry.Key.name); - if (attachment != null) slot.Attachment = attachment; + if (i->first._slotIndex == slotIndex) + { + names.push_back(i->first._name); } } } - AttachmentKey::AttachmentKey(int slotIndex, std::string name) : - _slotIndex(slotIndex), - _name(name) + void Skin::findAttachmentsForSlot(int slotIndex, std::vector& attachments) { - // Empty + for (std::unordered_map::iterator i = _attachments.begin(); i != _attachments.end(); ++i) + { + if (i->first._slotIndex == slotIndex) + { + attachments.push_back(i->second); + } + } } - bool AttachmentKey::operator==(const AttachmentKey &other) const + const std::string& Skin::getName() { - return _slotIndex == other._slotIndex && _name == other._name; + return _name; + } + + std::unordered_map& Skin::getAttachments() + { + return _attachments; + } + + void Skin::attachAll(Skeleton& skeleton, Skin& oldSkin) + { + for (std::unordered_map::iterator i = oldSkin.getAttachments().begin(); i != oldSkin.getAttachments().end(); ++i) + { + int slotIndex = i->first._slotIndex; + Slot* slot = skeleton.getSlots().at(slotIndex); + + if (slot->getAttachment() == i->second) + { + Attachment* attachment = nullptr; + if ((attachment = getAttachment(slotIndex, i->first._name))) + { + slot->setAttachment(attachment); + } + } + } } std::ostream& operator <<(std::ostream& os, const Skin& ref) { - os << ref.getName(); + os << ref._name; return os; } From 26eabbf1df23148867583b1fb13a342be3086e95 Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Sun, 8 Oct 2017 19:03:24 -0400 Subject: [PATCH 10/83] wip --- spine-cpp/spine-cpp/include/spine/Bone.h | 79 +- .../spine-cpp/include/spine/Constraint.h | 6 +- .../spine-cpp/include/spine/CurveTimeline.h | 77 ++ .../spine-cpp/include/spine/IkConstraint.h | 39 + spine-cpp/spine-cpp/include/spine/MathUtil.h | 44 ++ .../spine-cpp/include/spine/MixDirection.h | 46 ++ spine-cpp/spine-cpp/include/spine/MixPose.h | 51 ++ .../spine-cpp/include/spine/PathConstraint.h | 39 + .../spine-cpp/include/spine/RotateTimeline.h | 68 ++ spine-cpp/spine-cpp/include/spine/Skeleton.h | 746 +++++++++++++++++- .../spine-cpp/include/spine/SkeletonData.h | 39 + spine-cpp/spine-cpp/include/spine/Timeline.h | 68 ++ .../spine-cpp/include/spine/TimelineType.h | 56 ++ .../include/spine/TransformConstraint.h | 39 + spine-cpp/spine-cpp/src/spine/Bone.cpp | 9 +- spine-cpp/spine-cpp/src/spine/Constraint.cpp | 45 ++ .../spine-cpp/src/spine/CurveTimeline.cpp | 136 ++++ .../spine-cpp/src/spine/IkConstraint.cpp | 34 + .../spine-cpp/src/spine/PathConstraint.cpp | 34 + .../spine-cpp/src/spine/RotateTimeline.cpp | 139 ++++ spine-cpp/spine-cpp/src/spine/Skeleton.cpp | 11 + .../spine-cpp/src/spine/SkeletonData.cpp | 34 + spine-cpp/spine-cpp/src/spine/Timeline.cpp | 47 ++ .../src/spine/TransformConstraint.cpp | 34 + spine-cpp/spine-cpp/src/spine/Updatable.cpp | 44 ++ 25 files changed, 1922 insertions(+), 42 deletions(-) create mode 100644 spine-cpp/spine-cpp/include/spine/CurveTimeline.h create mode 100644 spine-cpp/spine-cpp/include/spine/IkConstraint.h create mode 100644 spine-cpp/spine-cpp/include/spine/MathUtil.h create mode 100644 spine-cpp/spine-cpp/include/spine/MixDirection.h create mode 100644 spine-cpp/spine-cpp/include/spine/MixPose.h create mode 100644 spine-cpp/spine-cpp/include/spine/PathConstraint.h create mode 100644 spine-cpp/spine-cpp/include/spine/RotateTimeline.h create mode 100644 spine-cpp/spine-cpp/include/spine/SkeletonData.h create mode 100644 spine-cpp/spine-cpp/include/spine/Timeline.h create mode 100644 spine-cpp/spine-cpp/include/spine/TimelineType.h create mode 100644 spine-cpp/spine-cpp/include/spine/TransformConstraint.h create mode 100644 spine-cpp/spine-cpp/src/spine/Constraint.cpp create mode 100644 spine-cpp/spine-cpp/src/spine/CurveTimeline.cpp create mode 100644 spine-cpp/spine-cpp/src/spine/IkConstraint.cpp create mode 100644 spine-cpp/spine-cpp/src/spine/PathConstraint.cpp create mode 100644 spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp create mode 100644 spine-cpp/spine-cpp/src/spine/SkeletonData.cpp create mode 100644 spine-cpp/spine-cpp/src/spine/Timeline.cpp create mode 100644 spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp create mode 100644 spine-cpp/spine-cpp/src/spine/Updatable.cpp diff --git a/spine-cpp/spine-cpp/include/spine/Bone.h b/spine-cpp/spine-cpp/include/spine/Bone.h index d7e1b15e7..b35dbdc87 100644 --- a/spine-cpp/spine-cpp/include/spine/Bone.h +++ b/spine-cpp/spine-cpp/include/spine/Bone.h @@ -43,69 +43,71 @@ namespace Spine /// class Bone : public Updatable { + friend class RotateTimeline; + public: private: static public bool yDown; - internal BoneData data; - internal Skeleton skeleton; - internal Bone parent; - internal ExposedList children = new ExposedList(); - internal float x, y, rotation, scaleX, scaleY, shearX, shearY; - internal float ax, ay, arotation, ascaleX, ascaleY, ashearX, ashearY; - internal bool appliedValid; + internal BoneData _data; + internal Skeleton _skeleton; + internal Bone _parent; + internal ExposedList _children = new ExposedList(); + internal float _x, _y, _rotation, _scaleX, _scaleY, _shearX, _shearY; + internal float _ax, _ay, _arotation, _ascaleX, _ascaleY, _ashearX, _ashearY; + internal bool _appliedValid; - internal float a, b, worldX; - internal float c, d, worldY; + internal float _a, _b, _worldX; + internal float _c, _d, _worldY; // internal float worldSignX, worldSignY; // public float WorldSignX { get { return worldSignX; } } // public float WorldSignY { get { return worldSignY; } } - internal bool sorted; + internal bool _sorted; public BoneData Data { get { return data; } } public Skeleton Skeleton { get { return skeleton; } } public Bone Parent { get { return parent; } } public ExposedList Children { get { return children; } } - /// The local X translation. + /// The local X translation. public float X { get { return x; } set { x = value; } } - /// The local Y translation. + /// The local Y translation. public float Y { get { return y; } set { y = value; } } - /// The local rotation. + /// The local rotation. public float Rotation { get { return rotation; } set { rotation = value; } } - /// The local scaleX. + /// The local scaleX. public float ScaleX { get { return scaleX; } set { scaleX = value; } } - /// The local scaleY. + /// The local scaleY. public float ScaleY { get { return scaleY; } set { scaleY = value; } } - /// The local shearX. + /// The local shearX. public float ShearX { get { return shearX; } set { shearX = value; } } - /// The local shearY. + /// The local shearY. public float ShearY { get { return shearY; } set { shearY = value; } } - /// The rotation, as calculated by any constraints. + /// The rotation, as calculated by any constraints. public float AppliedRotation { get { return arotation; } set { arotation = value; } } - /// The applied local x translation. + /// The applied local x translation. public float AX { get { return ax; } set { ax = value; } } - /// The applied local y translation. + /// The applied local y translation. public float AY { get { return ay; } set { ay = value; } } - /// The applied local scaleX. + /// The applied local scaleX. public float AScaleX { get { return ascaleX; } set { ascaleX = value; } } - /// The applied local scaleY. + /// The applied local scaleY. public float AScaleY { get { return ascaleY; } set { ascaleY = value; } } - /// The applied local shearX. + /// The applied local shearX. public float AShearX { get { return ashearX; } set { ashearX = value; } } - /// The applied local shearY. + /// The applied local shearY. public float AShearY { get { return ashearY; } set { ashearY = value; } } public float A { get { return a; } } @@ -118,12 +120,12 @@ namespace Spine public float WorldRotationX { get { return MathUtils.Atan2(c, a) * MathUtils.RadDeg; } } public float WorldRotationY { get { return MathUtils.Atan2(d, b) * MathUtils.RadDeg; } } - /// Returns the magnitide (always positive) of the world scale X. + /// Returns the magnitide (always positive) of the world scale X. public float WorldScaleX { get { return (float)Math.Sqrt(a * a + c * c); } } - /// Returns the magnitide (always positive) of the world scale Y. + /// Returns the magnitide (always positive) of the world scale Y. public float WorldScaleY { get { return (float)Math.Sqrt(b * b + d * d); } } - /// May be null. + /// @param parent May be null. public Bone (BoneData data, Skeleton skeleton, Bone parent) { if (data == null) throw new ArgumentNullException("data", "data cannot be null."); if (skeleton == null) throw new ArgumentNullException("skeleton", "skeleton cannot be null."); @@ -133,17 +135,17 @@ namespace Spine SetToSetupPose(); } - /// Same as . This method exists for Bone to implement . + /// Same as . This method exists for Bone to implement . public void Update () { UpdateWorldTransform(x, y, rotation, scaleX, scaleY, shearX, shearY); } - /// Computes the world transform using the parent bone and this bone's local transform. + /// Computes the world transform using the parent bone and this bone's local transform. public void UpdateWorldTransform () { UpdateWorldTransform(x, y, rotation, scaleX, scaleY, shearX, shearY); } - /// Computes the world transform using the parent bone and the specified local transform. + /// Computes the world transform using the parent bone and the specified local transform. public void UpdateWorldTransform (float x, float y, float rotation, float scaleX, float scaleY, float shearX, float shearY) { ax = x; ay = y; @@ -284,12 +286,12 @@ namespace Spine shearY = data.shearY; } - /// + /// /// 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).. /// /// Some information is ambiguous in the world transform, such as -1,-1 scale versus 180 rotation. - /// + /// internal void UpdateAppliedTransform () { appliedValid = true; Bone parent = this.parent; @@ -372,11 +374,12 @@ namespace Spine return MathUtils.Atan2(cos * c + sin * d, cos * a + sin * b) * MathUtils.RadDeg; } - /// + /// /// Rotates the world transform the specified amount and sets isAppliedValid to false. - /// - /// Degrees. - public void RotateWorld (float degrees) { + /// + /// @param degrees Degrees. + public void RotateWorld (float degrees) + { float a = this.a, b = this.b, c = this.c, d = this.d; float cos = MathUtils.CosDeg(degrees), sin = MathUtils.SinDeg(degrees); this.a = cos * a - sin * c; @@ -386,9 +389,7 @@ namespace Spine appliedValid = false; } - override public string ToString () { - return data.name; - } + friend std::ostream& operator <<(std::ostream& os, const Bone& ref); }; } diff --git a/spine-cpp/spine-cpp/include/spine/Constraint.h b/spine-cpp/spine-cpp/include/spine/Constraint.h index 50d7d0977..e0c910d51 100644 --- a/spine-cpp/spine-cpp/include/spine/Constraint.h +++ b/spine-cpp/spine-cpp/include/spine/Constraint.h @@ -31,6 +31,8 @@ #ifndef Spine_Constraint_h #define Spine_Constraint_h +#include + namespace Spine { /// The interface for all constraints. @@ -39,7 +41,9 @@ namespace Spine public: Constraint(); - virtual Constraint(); + virtual ~Constraint(); + + virtual void update() = 0; /// The ordinal for the order a skeleton's constraints will be applied. virtual int getOrder() = 0; diff --git a/spine-cpp/spine-cpp/include/spine/CurveTimeline.h b/spine-cpp/spine-cpp/include/spine/CurveTimeline.h new file mode 100644 index 000000000..323198f41 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/CurveTimeline.h @@ -0,0 +1,77 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_CurveTimeline_h +#define Spine_CurveTimeline_h + +#include + +#include +#include + +namespace Spine +{ + /// Base class for frames that use an interpolation bezier curve. + class CurveTimeline : public Timeline + { + public: + CurveTimeline(int frameCount); + + virtual void apply(Skeleton& skeleton, float lastTime, float time, std::vector& events, float alpha, MixPose pose, MixDirection direction) = 0; + + virtual int getPropertyId() = 0; + + int getFrameCount(); + + void setLinear(int frameIndex); + + void setStepped(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. + void setCurve(int frameIndex, float cx1, float cy1, float cx2, float cy2); + + float getCurvePercent(int frameIndex, float percent); + + float getCurveType(int frameIndex); + + protected: + static const float LINEAR; + static const float STEPPED; + static const float BEZIER; + static const int BEZIER_SIZE; + + private: + std::vector _curves; // type, x, y, ... + }; +} + +#endif /* Spine_CurveTimeline_h */ diff --git a/spine-cpp/spine-cpp/include/spine/IkConstraint.h b/spine-cpp/spine-cpp/include/spine/IkConstraint.h new file mode 100644 index 000000000..c0acf47be --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/IkConstraint.h @@ -0,0 +1,39 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_IkConstraint_h +#define Spine_IkConstraint_h + +namespace Spine +{ + // TODO +} + +#endif /* Spine_IkConstraint_h */ diff --git a/spine-cpp/spine-cpp/include/spine/MathUtil.h b/spine-cpp/spine-cpp/include/spine/MathUtil.h new file mode 100644 index 000000000..12d4a4ed5 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/MathUtil.h @@ -0,0 +1,44 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_MathUtil_h +#define Spine_MathUtil_h + +#include + +namespace Spine +{ + inline float clamp(float x, float lower, float upper) + { + return fminf(upper, fmaxf(x, lower)); + } +} + +#endif /* Spine_MathUtil_h */ diff --git a/spine-cpp/spine-cpp/include/spine/MixDirection.h b/spine-cpp/spine-cpp/include/spine/MixDirection.h new file mode 100644 index 000000000..637e61e2d --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/MixDirection.h @@ -0,0 +1,46 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_MixDirection_h +#define Spine_MixDirection_h + +namespace Spine +{ + /// + /// Indicates whether a timeline's alpha is mixing out over time toward 0 (the setup or current pose) or mixing in toward 1 (the timeline's pose). + /// See also Timeline::apply(Skeleton&, float, float, std::vector&, float, MixPose, MixDirection) + enum MixDirection + { + MixDirection_In = 0, + MixDirection_Out + }; +} + +#endif /* Spine_MixDirection_h */ diff --git a/spine-cpp/spine-cpp/include/spine/MixPose.h b/spine-cpp/spine-cpp/include/spine/MixPose.h new file mode 100644 index 000000000..70f08931c --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/MixPose.h @@ -0,0 +1,51 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_MixPose_h +#define Spine_MixPose_h + +namespace Spine +{ + /// + /// Controls how a timeline is mixed with the setup or current pose. + /// See also Timeline::apply(Skeleton&, float, float, std::vector&, float, MixPose, MixDirection) + enum MixPose + { + /// The timeline value is mixed with the setup pose (the current pose is not used). + MixPose_Setup = 0, + /// The timeline value is mixed with the current pose. The setup pose is used as the timeline value before the first key, + /// except for timelines which perform instant transitions, such as DrawOrderTimeline or AttachmentTimeline. + MixPose_Current, + /// The timeline value is mixed with the current pose. No change is made before the first key (the current pose is kept until the first key). + MixPose_CurrentLayered + }; +} + +#endif /* Spine_MixPose_h */ diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraint.h b/spine-cpp/spine-cpp/include/spine/PathConstraint.h new file mode 100644 index 000000000..374875876 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/PathConstraint.h @@ -0,0 +1,39 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_PathConstraint_h +#define Spine_PathConstraint_h + +namespace Spine +{ + // TODO +} + +#endif /* Spine_PathConstraint_h */ diff --git a/spine-cpp/spine-cpp/include/spine/RotateTimeline.h b/spine-cpp/spine-cpp/include/spine/RotateTimeline.h new file mode 100644 index 000000000..0c05a331d --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/RotateTimeline.h @@ -0,0 +1,68 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_RotateTimeline_h +#define Spine_RotateTimeline_h + +#include + +namespace Spine +{ + class RotateTimeline : public CurveTimeline + { + public: + static const int ENTRIES = 2; + + RotateTimeline(int frameCount); + + virtual void apply(Skeleton& skeleton, float lastTime, float time, std::vector& events, float alpha, MixPose pose, MixDirection direction); + + virtual int getPropertyId(); + + /// Sets the time and value of the specified keyframe. + void setFrame(int frameIndex, float time, float degrees); + + int getBoneIndex(); + void setBoneIndex(int inValue); + + std::vector& getFrames(); + void setFrames(std::vector inValue); + + private: + static const int PREV_TIME = -2; + static const int PREV_ROTATION = -1; + static const int ROTATION = 1; + + int _boneIndex; + std::vector _frames; // time, angle, ... + }; +} + +#endif /* Spine_RotateTimeline_h */ diff --git a/spine-cpp/spine-cpp/include/spine/Skeleton.h b/spine-cpp/spine-cpp/include/spine/Skeleton.h index 0ea3e5db1..b7dd1ca51 100644 --- a/spine-cpp/spine-cpp/include/spine/Skeleton.h +++ b/spine-cpp/spine-cpp/include/spine/Skeleton.h @@ -31,9 +31,753 @@ #ifndef Spine_Skeleton_h #define Spine_Skeleton_h +#include +#include + namespace Spine { - // TODO + class SkeletonData; + class Bone; + class Updatable; + class Slot; + class IkConstraint; + class PathConstraint; + class TransformConstraint; + class Skin; + + class Skeleton + { + public: + SkeletonData* getData(); + std::vector getBones(); + std::vector getUpdateCacheList(); + std::vector getSlots(); + std::vector getDrawOrder(); + std::vector getIkConstraints(); + std::vector getPathConstraints(); + std::vector getTransformConstraints(); + + Skin* getSkin { get { return skin; } set { skin = value; } } + float getR { get { return r; } set { r = value; } } + float getG { get { return g; } set { g = value; } } + float getB { get { return b; } set { b = value; } } + float getA { get { return a; } set { a = value; } } + float getTime { get { return time; } set { time = value; } } + float getX { get { return x; } set { x = value; } } + float getY { get { return y; } set { y = value; } } + bool getFlipX { get { return flipX; } set { flipX = value; } } + bool getFlipY { get { return flipY; } set { flipY = value; } } + + Bone* getRootBone() + { + return _bones.size() == 0 ? nullptr : _bones.at(0); + //get { return bones.Count == 0 ? null : bones.Items[0]; } + } + + Skeleton(const SkeletonData& data) + { + if (data == null) + { + throw new ArgumentNullException("data", "data cannot be null."); + } + + this.data = data; + + bones = new std::vector(data.bones.Count); + foreach (BoneData boneData in data.bones) + { + Bone bone; + if (boneData.parent == null) + { + bone = new Bone(boneData, this, null); + } + else + { + Bone parent = bones.Items[boneData.parent.index]; + bone = new Bone(boneData, this, parent); + parent.children.Add(bone); + } + bones.Add(bone); + } + + slots = new std::vector(data.slots.Count); + drawOrder = new std::vector(data.slots.Count); + foreach (SlotData slotData in data.slots) + { + Bone bone = bones.Items[slotData.boneData.index]; + Slot slot = new Slot(slotData, bone); + slots.Add(slot); + drawOrder.Add(slot); + } + + ikConstraints = new std::vector(data.ikConstraints.Count); + foreach (IkConstraintData ikConstraintData in data.ikConstraints) + ikConstraints.Add(new IkConstraint(ikConstraintData, this)); + + transformConstraints = new std::vector(data.transformConstraints.Count); + foreach (TransformConstraintData transformConstraintData in data.transformConstraints) + transformConstraints.Add(new TransformConstraint(transformConstraintData, this)); + + pathConstraints = new std::vector (data.pathConstraints.Count); + foreach (PathConstraintData pathConstraintData in data.pathConstraints) + pathConstraints.Add(new PathConstraint(pathConstraintData, this)); + + updateCache(); + updateWorldTransform(); + } + + ~Skeleton() + { + // TODO + } + + /// Caches information about bones and constraints. Must be called if bones, constraints or weighted path attachments are added + /// or removed. + void updateCache() + { + std::vector updateCache = this.updateCache; + updateCache.Clear(); + this.updateCacheReset.Clear(); + + std::vector bones = this.bones; + for (int i = 0, n = bones.Count; i < n; i++) + { + bones.Items[i].sorted = false; + } + + std::vector ikConstraints = this.ikConstraints; + var transformConstraints = this.transformConstraints; + var pathConstraints = this.pathConstraints; + int ikCount = IkConstraints.Count, transformCount = transformConstraints.Count, pathCount = pathConstraints.Count; + int constraintCount = ikCount + transformCount + pathCount; + //outer: + for (int i = 0; i < constraintCount; i++) + { + for (int ii = 0; ii < ikCount; ii++) + { + IkConstraint constraint = ikConstraints.Items[ii]; + if (constraint.data.order == i) + { + sortIkConstraint(constraint); + goto continue_outer; //continue outer; + } + } + for (int ii = 0; ii < transformCount; ii++) + { + TransformConstraint constraint = transformConstraints.Items[ii]; + if (constraint.data.order == i) + { + sortTransformConstraint(constraint); + goto continue_outer; //continue outer; + } + } + for (int ii = 0; ii < pathCount; ii++) + { + PathConstraint constraint = pathConstraints.Items[ii]; + if (constraint.data.order == i) + { + sortPathConstraint(constraint); + goto continue_outer; //continue outer; + } + } + continue_outer: {} + } + + for (int i = 0, n = bones.Count; i < n; i++) + { + sortBone(bones.Items[i]); + } + } + + /// updates the world transform for each bone and applies constraints. + void updateWorldTransform() + { + var updateCacheReset = this.updateCacheReset; + var updateCacheResetItems = updateCacheReset.Items; + for (int i = 0, n = updateCacheReset.Count; i < n; i++) + { + Bone bone = updateCacheResetItems[i]; + bone.ax = bone.x; + bone.ay = bone.y; + bone.arotation = bone.rotation; + bone.ascaleX = bone.scaleX; + bone.ascaleY = bone.scaleY; + bone.ashearX = bone.shearX; + bone.ashearY = bone.shearY; + bone.appliedValid = true; + } + + var updateItems = this.updateCache.Items; + for (int i = 0, n = updateCache.Count; i < n; i++) + { + updateItems[i].update(); + } + } + + /// Sets the bones, constraints, and slots to their setup pose values. + void setToSetupPose() + { + setBonesToSetupPose(); + setSlotsToSetupPose(); + } + + /// Sets the bones and constraints to their setup pose values. + void setBonesToSetupPose() + { + var bonesItems = this.bones.Items; + for (int i = 0, n = bones.Count; i < n; i++) + { + bonesItems[i].setToSetupPose(); + } + + var ikConstraintsItems = this.ikConstraints.Items; + for (int i = 0, n = ikConstraints.Count; i < n; i++) + { + IkConstraint constraint = ikConstraintsItems[i]; + constraint.bendDirection = constraint.data.bendDirection; + constraint.mix = constraint.data.mix; + } + + var transformConstraintsItems = this.transformConstraints.Items; + for (int i = 0, n = transformConstraints.Count; i < n; i++) + { + TransformConstraint constraint = transformConstraintsItems[i]; + TransformConstraintData constraintData = constraint.data; + constraint.rotateMix = constraintData.rotateMix; + constraint.translateMix = constraintData.translateMix; + constraint.scaleMix = constraintData.scaleMix; + constraint.shearMix = constraintData.shearMix; + } + + var pathConstraintItems = this.pathConstraints.Items; + for (int i = 0, n = pathConstraints.Count; i < n; i++) + { + PathConstraint constraint = pathConstraintItems[i]; + PathConstraintData constraintData = constraint.data; + constraint.position = constraintData.position; + constraint.spacing = constraintData.spacing; + constraint.rotateMix = constraintData.rotateMix; + constraint.translateMix = constraintData.translateMix; + } + } + + void setSlotsToSetupPose() + { + var slots = this.slots; + var slotsItems = slots.Items; + drawOrder.Clear(); + + for (int i = 0, n = slots.Count; i < n; i++) + { + drawOrder.Add(slotsItems[i]); + } + + for (int i = 0, n = slots.Count; i < n; i++) + { + slotsItems[i].setToSetupPose(); + } + } + + /// May be null. + Bone findBone(std::string boneName) + { + if (boneName == null) + { + throw new ArgumentNullException("boneName", "boneName cannot be null."); + } + + var bones = this.bones; + var bonesItems = bones.Items; + for (int i = 0, n = bones.Count; i < n; i++) + { + Bone bone = bonesItems[i]; + if (bone.data.name == boneName) + { + return bone; + } + } + + return null; + } + + /// -1 if the bone was not found. + int findBoneIndex(std::string boneName) + { + if (boneName == null) throw new ArgumentNullException("boneName", "boneName cannot be null."); + var bones = this.bones; + var bonesItems = bones.Items; + for (int i = 0, n = bones.Count; i < n; i++) + { + if (bonesItems[i].data.name == boneName) + { + return i; + } + } + + return -1; + } + + /// May be null. + Slot findSlot(std::string slotName) + { + if (slotName == null) + { + throw new ArgumentNullException("slotName", "slotName cannot be null."); + } + + var slots = this.slots; + var slotsItems = slots.Items; + for (int i = 0, n = slots.Count; i < n; i++) + { + Slot slot = slotsItems[i]; + if (slot.data.name == slotName) + { + return slot; + } + } + + return null; + } + + /// -1 if the bone was not found. + int findSlotIndex(std::string slotName) + { + if (slotName == null) + { + throw new ArgumentNullException("slotName", "slotName cannot be null."); + } + + var slots = this.slots; + var slotsItems = slots.Items; + for (int i = 0, n = slots.Count; i < n; i++) + { + if (slotsItems[i].data.name.Equals(slotName)) + { + return i; + } + } + + return -1; + } + + /// Sets a skin by name (see setSkin). + void setSkin(std::string skinName) + { + Skin foundSkin = data.FindSkin(skinName); + if (foundSkin == null) + { + throw new ArgumentException("Skin not found: " + skinName, "skinName"); + } + + setSkin(foundSkin); + } + + /// + /// 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. + /// After changing the skin, the visible attachments can be reset to those attached in the setup pose by calling + /// . + /// Also, often is called before the next time the + /// skeleton is rendered to allow any attachment keys in the current animation(s) to hide or show attachments from the new skin. + /// + /// @param newSkin May be null. + void setSkin(Skin newSkin) + { + if (newSkin != null) + { + if (skin != null) + { + newSkin.AttachAll(this, skin); + } + else + { + std::vector slots = this.slots; + for (int i = 0, n = slots.Count; i < n; i++) + { + Slot slot = slots.Items[i]; + std::string name = slot.data.attachmentName; + if (name != null) + { + Attachment attachment = newSkin.getAttachment(i, name); + if (attachment != null) + { + slot.Attachment = attachment; + } + } + } + } + } + + skin = newSkin; + } + + /// May be null. + Attachment getAttachment(std::string slotName, std::string attachmentName) + { + return getAttachment(data.findSlotIndex(slotName), attachmentName); + } + + /// May be null. + Attachment getAttachment(int slotIndex, std::string attachmentName) + { + if (attachmentName == null) + { + throw new ArgumentNullException("attachmentName", "attachmentName cannot be null."); + } + + if (skin != null) + { + Attachment attachment = skin.getAttachment(slotIndex, attachmentName); + if (attachment != null) + { + return attachment; + } + } + + return data.defaultSkin != null ? data.defaultSkin.getAttachment(slotIndex, attachmentName) : null; + } + + /// @param attachmentName May be null. + void setAttachment(std::string slotName, std::string attachmentName) + { + if (slotName == null) + { + throw new ArgumentNullException("slotName", "slotName cannot be null."); + } + + std::vector slots = this.slots; + for (int i = 0, n = slots.Count; i < n; i++) + { + Slot slot = slots.Items[i]; + if (slot.data.name == slotName) + { + Attachment attachment = null; + if (attachmentName != null) + { + attachment = getAttachment(i, attachmentName); + if (attachment == null) + { + throw new Exception("Attachment not found: " + attachmentName + ", for slot: " + slotName); + } + } + + slot.Attachment = attachment; + + return; + } + } + + throw new Exception("Slot not found: " + slotName); + } + + /// May be null. + IkConstraint findIkConstraint(std::string constraintName) + { + if (constraintName == null) + { + throw new ArgumentNullException("constraintName", "constraintName cannot be null."); + } + + std::vector ikConstraints = this.ikConstraints; + for (int i = 0, n = ikConstraints.Count; i < n; i++) + { + IkConstraint ikConstraint = ikConstraints.Items[i]; + if (ikConstraint.data.name == constraintName) return ikConstraint; + } + + return null; + } + + /// May be null. + TransformConstraint findTransformConstraint(std::string constraintName) + { + if (constraintName == null) + { + throw new ArgumentNullException("constraintName", "constraintName cannot be null."); + } + + std::vector transformConstraints = this.transformConstraints; + for (int i = 0, n = transformConstraints.Count; i < n; i++) + { + TransformConstraint transformConstraint = transformConstraints.Items[i]; + if (transformConstraint.data.name == constraintName) return transformConstraint; + } + + return null; + } + + /// May be null. + PathConstraint findPathConstraint(std::string constraintName) + { + if (constraintName == null) + { + throw new ArgumentNullException("constraintName", "constraintName cannot be null."); + } + + std::vector pathConstraints = this.pathConstraints; + for (int i = 0, n = pathConstraints.Count; i < n; i++) + { + PathConstraint constraint = pathConstraints.Items[i]; + if (constraint.data.name.Equals(constraintName)) return constraint; + } + + return null; + } + + void update(float delta) + { + time += delta; + } + + /// Returns the axis aligned bounding box (AABB) of the region and mesh attachments for the current pose. + /// @param x The horizontal distance between the skeleton origin and the left side of the AABB. + /// @param y The vertical distance between the skeleton origin and the bottom side of the AABB. + /// @param width The width of the AABB + /// @param height The height of the AABB. + /// @param vertexBuffer Reference to hold a float[]. May be a null reference. This method will assign it a new float[] with the appropriate size as needed. + void getBounds(out float x, out float y, out float width, out float height, ref float[] vertexBuffer) + { + float[] temp = vertexBuffer; + temp = temp ?? new float[8]; + var drawOrderItems = this.drawOrder.Items; + float minX = int.MaxValue, minY = int.MaxValue, maxX = int.MinValue, maxY = int.MinValue; + for (int i = 0, n = this.drawOrder.Count; i < n; i++) + { + Slot slot = drawOrderItems[i]; + int verticesLength = 0; + float[] vertices = null; + Attachment attachment = slot.attachment; + var regionAttachment = attachment as RegionAttachment; + if (regionAttachment != null) + { + verticesLength = 8; + vertices = temp; + if (vertices.Length < 8) vertices = temp = new float[8]; + regionAttachment.ComputeWorldVertices(slot.bone, temp, 0); + } + else + { + var meshAttachment = attachment as MeshAttachment; + if (meshAttachment != null) + { + MeshAttachment mesh = meshAttachment; + verticesLength = mesh.WorldVerticesLength; + vertices = temp; + if (vertices.Length < verticesLength) + { + vertices = temp = new float[verticesLength]; + } + + mesh.ComputeWorldVertices(slot, 0, verticesLength, temp, 0); + } + } + + if (vertices != null) + { + for (int ii = 0; ii < verticesLength; ii += 2) + { + float vx = vertices[ii], vy = vertices[ii + 1]; + minX = Math.Min(minX, vx); + minY = Math.Min(minY, vy); + maxX = Math.Max(maxX, vx); + maxY = Math.Max(maxY, vy); + } + } + } + + x = minX; + y = minY; + width = maxX - minX; + height = maxY - minY; + vertexBuffer = temp; + } + + private: + SkeletonData* _data; + std::vector _bones; + std::vector _slots; + std::vector _drawOrder; + std::vector _ikConstraints; + std::vector _transformConstraints; + std::vector _pathConstraints; + std::vector _updateCache = new std::vector(); + std::vector _updateCacheReset = new std::vector(); + Skin _skin; + float _r = 1, _g = 1, _b = 1, _a = 1; + float _time; + bool _flipX, _flipY; + float _x, _y; + + void sortIkConstraint(IkConstraint constraint) + { + Bone target = constraint.target; + sortBone(target); + + var constrained = constraint.bones; + Bone parent = constrained.Items[0]; + sortBone(parent); + + if (constrained.Count > 1) + { + Bone child = constrained.Items[constrained.Count - 1]; + if (!updateCache.Contains(child)) + { + updateCacheReset.Add(child); + } + } + + updateCache.Add(constraint); + + sortReset(parent.children); + constrained.Items[constrained.Count - 1].sorted = true; + } + + void sortPathConstraint(PathConstraint constraint) + { + Slot slot = constraint.target; + int slotIndex = slot.data.index; + Bone slotBone = slot.bone; + if (skin != null) + { + sortPathConstraintAttachment(skin, slotIndex, slotBone); + } + + if (data.defaultSkin != null && data.defaultSkin != skin) + { + sortPathConstraintAttachment(data.defaultSkin, slotIndex, slotBone); + } + + for (int ii = 0, nn = data.skins.Count; ii < nn; ii++) + { + sortPathConstraintAttachment(data.skins.Items[ii], slotIndex, slotBone); + } + + Attachment attachment = slot.attachment; + if (attachment is PathAttachment) + { + sortPathConstraintAttachment(attachment, slotBone); + } + + var constrained = constraint.bones; + int boneCount = constrained.Count; + for (int i = 0; i < boneCount; i++) + { + sortBone(constrained.Items[i]); + } + + updateCache.Add(constraint); + + for (int i = 0; i < boneCount; i++) + { + sortReset(constrained.Items[i].children); + } + + for (int i = 0; i < boneCount; i++) + { + constrained.Items[i].sorted = true; + } + } + + void sortTransformConstraint(TransformConstraint constraint) + { + sortBone(constraint.target); + + var constrained = constraint.bones; + int boneCount = constrained.Count; + if (constraint.data.local) + { + for (int i = 0; i < boneCount; i++) + { + Bone child = constrained.Items[i]; + sortBone(child.parent); + if (!updateCache.Contains(child)) + { + updateCacheReset.Add(child); + } + } + } + else + { + for (int i = 0; i < boneCount; i++) + { + sortBone(constrained.Items[i]); + } + } + + updateCache.Add(constraint); + + for (int i = 0; i < boneCount; i++) + { + sortReset(constrained.Items[i].children); + } + for (int i = 0; i < boneCount; i++) + { + constrained.Items[i].sorted = true; + } + } + + void sortPathConstraintAttachment(Skin skin, int slotIndex, Bone slotBone) + { + foreach (var entry in skin.Attachments) + { + if (entry.Key.slotIndex == slotIndex) + { + sortPathConstraintAttachment(entry.Value, slotBone); + } + } + } + + void sortPathConstraintAttachment(Attachment attachment, Bone slotBone) + { + if (!(attachment is PathAttachment)) return; + int[] pathBones = ((PathAttachment)attachment).bones; + if (pathBones == null) + { + sortBone(slotBone); + } + else + { + var bones = this.bones; + for (int i = 0, n = pathBones.Length; i < n;) + { + int nn = pathBones[i++]; + nn += i; + while (i < nn) + { + sortBone(bones.Items[pathBones[i++]]); + } + } + } + } + + void sortBone(Bone bone) + { + if (bone.sorted) + { + return; + } + + Bone parent = bone.parent; + if (parent != null) sortBone(parent); + bone.sorted = true; + updateCache.Add(bone); + } + + static void sortReset(std::vector& bones) + { + var bonesItems = bones.Items; + for (int i = 0, n = bones.Count; i < n; i++) + { + Bone bone = bonesItems[i]; + if (bone.sorted) + { + sortReset(bone.children); + } + + bone.sorted = false; + } + } + }; } #endif /* Spine_Skeleton_h */ diff --git a/spine-cpp/spine-cpp/include/spine/SkeletonData.h b/spine-cpp/spine-cpp/include/spine/SkeletonData.h new file mode 100644 index 000000000..37b27397f --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/SkeletonData.h @@ -0,0 +1,39 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_SkeletonData_h +#define Spine_SkeletonData_h + +namespace Spine +{ + // TODO +} + +#endif /* Spine_SkeletonData_h */ diff --git a/spine-cpp/spine-cpp/include/spine/Timeline.h b/spine-cpp/spine-cpp/include/spine/Timeline.h new file mode 100644 index 000000000..db09f8086 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/Timeline.h @@ -0,0 +1,68 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Timeline_h +#define Spine_Timeline_h + +#include +#include + +#include + +namespace Spine +{ + class Skeleton; + class Event; + + class Timeline + { + public: + Timeline(); + + virtual ~Timeline(); + + /// Sets the value(s) for the specified time. + /// @param skeleton The skeleton the timeline is being applied to. This provides access to the bones, slots, and other skeleton components the timeline may change. + /// @param lastTime lastTime The time this timeline was last applied. Timelines such as EventTimeline trigger only at specific times rather than every frame. In that case, the timeline triggers everything between lastTime (exclusive) and time (inclusive). + /// @param time The time within the animation. Most timelines find the key before and the key after this time so they can interpolate between the keys. + /// @param events If any events are fired, they are added to this list. Can be null to ignore firing events or if the timeline does not fire events. May be null. + /// @param alpha alpha 0 applies the current or setup pose value (depending on pose parameter). 1 applies the timeline + /// value. Between 0 and 1 applies a value between the current or setup pose and the timeline value. By adjusting + /// alpha over time, an animation can be mixed in or out. alpha can also be useful to + /// apply animations on top of each other (layered). + /// @param pose Controls how mixing is applied when alpha is than 1. + /// @param direction Indicates whether the timeline is mixing in or out. Used by timelines which perform instant transitions such as DrawOrderTimeline and AttachmentTimeline. + virtual void apply(Skeleton& skeleton, float lastTime, float time, std::vector& events, float alpha, MixPose pose, MixDirection direction) = 0; + + virtual int getPropertyId() = 0; + }; +} + +#endif /* Spine_Timeline_h */ diff --git a/spine-cpp/spine-cpp/include/spine/TimelineType.h b/spine-cpp/spine-cpp/include/spine/TimelineType.h new file mode 100644 index 000000000..06f085b6e --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/TimelineType.h @@ -0,0 +1,56 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_TimelineType_h +#define Spine_TimelineType_h + +namespace Spine +{ + enum TimelineType + { + TimelineType_Rotate = 0, + TimelineType_Translate, + TimelineType_Scale, + TimelineType_Shear, + TimelineType_Attachment, + TimelineType_Color, + TimelineType_Deform, + TimelineType_Event, + TimelineType_DrawOrder, + TimelineType_IkConstraint, + TimelineType_TransformConstraint, + TimelineType_PathConstraintPosition, + TimelineType_PathConstraintSpacing, + TimelineType_PathConstraintMix, + TimelineType_TwoColor + }; +} + +#endif /* Spine_TimelineType_h */ diff --git a/spine-cpp/spine-cpp/include/spine/TransformConstraint.h b/spine-cpp/spine-cpp/include/spine/TransformConstraint.h new file mode 100644 index 000000000..54a3585dd --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/TransformConstraint.h @@ -0,0 +1,39 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_TransformConstraint_h +#define Spine_TransformConstraint_h + +namespace Spine +{ + // TODO +} + +#endif /* Spine_TransformConstraint_h */ diff --git a/spine-cpp/spine-cpp/src/spine/Bone.cpp b/spine-cpp/spine-cpp/src/spine/Bone.cpp index bb4d2ccfe..246ca7413 100644 --- a/spine-cpp/spine-cpp/src/spine/Bone.cpp +++ b/spine-cpp/spine-cpp/src/spine/Bone.cpp @@ -28,7 +28,14 @@ * POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ +#include + namespace Spine { - // TODO + std::ostream& operator <<(std::ostream& os, const Bone& ref) + { + os << ref._data._name; + + return os; + } } diff --git a/spine-cpp/spine-cpp/src/spine/Constraint.cpp b/spine-cpp/spine-cpp/src/spine/Constraint.cpp new file mode 100644 index 000000000..e6e84bd6c --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/Constraint.cpp @@ -0,0 +1,45 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +namespace Spine +{ + Constraint::Constraint() + { + // Empty + } + + Constraint::~Constraint() + { + // Empty + } +} + diff --git a/spine-cpp/spine-cpp/src/spine/CurveTimeline.cpp b/spine-cpp/spine-cpp/src/spine/CurveTimeline.cpp new file mode 100644 index 000000000..de9f96e64 --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/CurveTimeline.cpp @@ -0,0 +1,136 @@ +/****************************************************************************** +* Spine Runtimes Software License v2.5 +* +* Copyright (c) 2013-2016, Esoteric Software +* All rights reserved. +* +* You are granted a perpetual, non-exclusive, non-sublicensable, and +* non-transferable license to use, install, execute, and perform the Spine +* Runtimes software and derivative works solely for personal or internal +* use. Without the written permission of Esoteric Software (see Section 2 of +* the Spine Software License Agreement), you may not (a) modify, translate, +* adapt, or develop new applications using the Spine Runtimes or otherwise +* create derivative works or improvements of the Spine Runtimes or (b) remove, +* delete, alter, or obscure any trademarks or any copyright, trademark, patent, +* or other intellectual property or proprietary rights notices on or in the +* Software, including any copy thereof. Redistributions in binary or source +* form must include this license and terms. +* +* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +#include + +#include + +namespace Spine +{ + const float CurveTimeline::LINEAR = 0; + const float CurveTimeline::STEPPED = 1; + const float CurveTimeline::BEZIER = 2; + const int CurveTimeline::BEZIER_SIZE = 10 * 2 - 1; + + CurveTimeline::CurveTimeline(int frameCount) + { + assert(frameCount > 0); + + _curves.reserve((frameCount - 1) * BEZIER_SIZE); + } + + int CurveTimeline::getFrameCount() + { + return _curves.size() / BEZIER_SIZE + 1; + } + + void CurveTimeline::setLinear(int frameIndex) + { + _curves[frameIndex * BEZIER_SIZE] = LINEAR; + } + + void CurveTimeline::setStepped(int frameIndex) + { + _curves[frameIndex * BEZIER_SIZE] = STEPPED; + } + + void CurveTimeline::setCurve(int frameIndex, float cx1, float cy1, float cx2, float cy2) + { + float tmpx = (-cx1 * 2 + cx2) * 0.03f, tmpy = (-cy1 * 2 + cy2) * 0.03f; + float dddfx = ((cx1 - cx2) * 3 + 1) * 0.006f, dddfy = ((cy1 - cy2) * 3 + 1) * 0.006f; + float ddfx = tmpx * 2 + dddfx, ddfy = tmpy * 2 + dddfy; + float dfx = cx1 * 0.3f + tmpx + dddfx * 0.16666667f, dfy = cy1 * 0.3f + tmpy + dddfy * 0.16666667f; + + int i = frameIndex * BEZIER_SIZE; + _curves[i++] = BEZIER; + + float x = dfx, y = dfy; + for (int n = i + BEZIER_SIZE - 1; i < n; i += 2) + { + _curves[i] = x; + _curves[i + 1] = y; + dfx += ddfx; + dfy += ddfy; + ddfx += dddfx; + ddfy += dddfy; + x += dfx; + y += dfy; + } + } + + float CurveTimeline::getCurvePercent(int frameIndex, float percent) + { + percent = clamp(percent, 0, 1); + int i = frameIndex * BEZIER_SIZE; + float type = _curves[i]; + + if (type == LINEAR) + { + return percent; + } + + if (type == STEPPED) + { + return 0; + } + + i++; + float x = 0; + for (int start = i, n = i + BEZIER_SIZE - 1; i < n; i += 2) + { + x = _curves[i]; + if (x >= percent) + { + float prevX, prevY; + if (i == start) + { + prevX = 0; + prevY = 0; + } + else + { + prevX = _curves[i - 2]; + prevY = _curves[i - 1]; + } + + return prevY + (_curves[i + 1] - prevY) * (percent - prevX) / (x - prevX); + } + } + + float y = _curves[i - 1]; + + return y + (1 - y) * (percent - x) / (1 - x); // Last point is 1,1. + } + + float CurveTimeline::getCurveType(int frameIndex) + { + return _curves[frameIndex * BEZIER_SIZE]; + } +} diff --git a/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp b/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp new file mode 100644 index 000000000..bb4d2ccfe --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp @@ -0,0 +1,34 @@ +/****************************************************************************** +* Spine Runtimes Software License v2.5 +* +* Copyright (c) 2013-2016, Esoteric Software +* All rights reserved. +* +* You are granted a perpetual, non-exclusive, non-sublicensable, and +* non-transferable license to use, install, execute, and perform the Spine +* Runtimes software and derivative works solely for personal or internal +* use. Without the written permission of Esoteric Software (see Section 2 of +* the Spine Software License Agreement), you may not (a) modify, translate, +* adapt, or develop new applications using the Spine Runtimes or otherwise +* create derivative works or improvements of the Spine Runtimes or (b) remove, +* delete, alter, or obscure any trademarks or any copyright, trademark, patent, +* or other intellectual property or proprietary rights notices on or in the +* Software, including any copy thereof. Redistributions in binary or source +* form must include this license and terms. +* +* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +namespace Spine +{ + // TODO +} diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp b/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp new file mode 100644 index 000000000..bb4d2ccfe --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp @@ -0,0 +1,34 @@ +/****************************************************************************** +* Spine Runtimes Software License v2.5 +* +* Copyright (c) 2013-2016, Esoteric Software +* All rights reserved. +* +* You are granted a perpetual, non-exclusive, non-sublicensable, and +* non-transferable license to use, install, execute, and perform the Spine +* Runtimes software and derivative works solely for personal or internal +* use. Without the written permission of Esoteric Software (see Section 2 of +* the Spine Software License Agreement), you may not (a) modify, translate, +* adapt, or develop new applications using the Spine Runtimes or otherwise +* create derivative works or improvements of the Spine Runtimes or (b) remove, +* delete, alter, or obscure any trademarks or any copyright, trademark, patent, +* or other intellectual property or proprietary rights notices on or in the +* Software, including any copy thereof. Redistributions in binary or source +* form must include this license and terms. +* +* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +namespace Spine +{ + // TODO +} diff --git a/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp b/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp new file mode 100644 index 000000000..87bdef551 --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp @@ -0,0 +1,139 @@ +/****************************************************************************** +* Spine Runtimes Software License v2.5 +* +* Copyright (c) 2013-2016, Esoteric Software +* All rights reserved. +* +* You are granted a perpetual, non-exclusive, non-sublicensable, and +* non-transferable license to use, install, execute, and perform the Spine +* Runtimes software and derivative works solely for personal or internal +* use. Without the written permission of Esoteric Software (see Section 2 of +* the Spine Software License Agreement), you may not (a) modify, translate, +* adapt, or develop new applications using the Spine Runtimes or otherwise +* create derivative works or improvements of the Spine Runtimes or (b) remove, +* delete, alter, or obscure any trademarks or any copyright, trademark, patent, +* or other intellectual property or proprietary rights notices on or in the +* Software, including any copy thereof. Redistributions in binary or source +* form must include this license and terms. +* +* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +#include + +#include +#include + +#include +#include + +namespace Spine +{ + RotateTimeline::RotateTimeline(int frameCount) : CurveTimeline(frameCount), _boneIndex(0) + { + _frames.reserve(frameCount << 1); + } + + void RotateTimeline::apply(Skeleton& skeleton, float lastTime, float time, std::vector& events, float alpha, MixPose pose, MixDirection direction) + { + Bone* bone = skeleton.getBones().at(_boneIndex); + + if (time < _frames[0]) + { + switch (pose) + { + case MixPose_Setup: + bone->_rotation = bone->_data->_rotation; + return; + case MixPose_Current: + float rr = bone->_data->_rotation - bone->_rotation; + rr -= (16384 - (int)(16384.499999999996 - rr / 360)) * 360; + bone->_rotation += rr * alpha; + return; + } + + return; + } + + if (time >= _frames[_frames.size() - ENTRIES]) + { + // Time is after last frame. + if (pose == MixPose_Setup) + { + bone->_rotation = bone->_data->_rotation + _frames[_frames.size() + PREV_ROTATION] * alpha; + } + else + { + float rr = bone->_data->_rotation + _frames[_frames.size() + PREV_ROTATION] - bone->_rotation; + rr -= (16384 - (int)(16384.499999999996 - rr / 360)) * 360; // Wrap within -180 and 180. + bone->_rotation += rr * alpha; + } + + return; + } + + // Interpolate between the previous frame and the current frame. + int frame = Animation::binarySearch(_frames, time, ENTRIES); + float prevRotation = _frames[frame + PREV_ROTATION]; + float frameTime = _frames[frame]; + float percent = getCurvePercent((frame >> 1) - 1, 1 - (time - frameTime) / (_frames[frame + PREV_TIME] - frameTime)); + + float r = _frames[frame + ROTATION] - prevRotation; + r -= (16384 - (int)(16384.499999999996 - r / 360)) * 360; + r = prevRotation + r * percent; + + if (pose == MixPose_Setup) + { + r -= (16384 - (int)(16384.499999999996 - r / 360)) * 360; + bone->_rotation = bone->_data->_rotation + r * alpha; + } + else + { + r = bone->_data->_rotation + r - bone->_rotation; + r -= (16384 - (int)(16384.499999999996 - r / 360)) * 360; + bone->_rotation += r * alpha; + } + } + + int RotateTimeline::getPropertyId() + { + return ((int)TimelineType_Rotate << 24) + _boneIndex; + } + + /// Sets the time and value of the specified keyframe. + void RotateTimeline::setFrame(int frameIndex, float time, float degrees) + { + frameIndex <<= 1; + _frames[frameIndex] = time; + _frames[frameIndex + ROTATION] = degrees; + } + + int RotateTimeline::getBoneIndex() + { + return _boneIndex; + } + + void RotateTimeline::setBoneIndex(int inValue) + { + _boneIndex = inValue; + } + + std::vector& RotateTimeline::getFrames() + { + return _frames; + } + + void RotateTimeline::setFrames(std::vector inValue) + { + _frames = inValue; + } +} diff --git a/spine-cpp/spine-cpp/src/spine/Skeleton.cpp b/spine-cpp/spine-cpp/src/spine/Skeleton.cpp index bb4d2ccfe..f8e34294a 100644 --- a/spine-cpp/spine-cpp/src/spine/Skeleton.cpp +++ b/spine-cpp/spine-cpp/src/spine/Skeleton.cpp @@ -28,6 +28,17 @@ * POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ +#include + +#include +#include +#include +#include +#include +#include +#include +#include + namespace Spine { // TODO diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonData.cpp b/spine-cpp/spine-cpp/src/spine/SkeletonData.cpp new file mode 100644 index 000000000..bb4d2ccfe --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/SkeletonData.cpp @@ -0,0 +1,34 @@ +/****************************************************************************** +* Spine Runtimes Software License v2.5 +* +* Copyright (c) 2013-2016, Esoteric Software +* All rights reserved. +* +* You are granted a perpetual, non-exclusive, non-sublicensable, and +* non-transferable license to use, install, execute, and perform the Spine +* Runtimes software and derivative works solely for personal or internal +* use. Without the written permission of Esoteric Software (see Section 2 of +* the Spine Software License Agreement), you may not (a) modify, translate, +* adapt, or develop new applications using the Spine Runtimes or otherwise +* create derivative works or improvements of the Spine Runtimes or (b) remove, +* delete, alter, or obscure any trademarks or any copyright, trademark, patent, +* or other intellectual property or proprietary rights notices on or in the +* Software, including any copy thereof. Redistributions in binary or source +* form must include this license and terms. +* +* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +namespace Spine +{ + // TODO +} diff --git a/spine-cpp/spine-cpp/src/spine/Timeline.cpp b/spine-cpp/spine-cpp/src/spine/Timeline.cpp new file mode 100644 index 000000000..39f4cc164 --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/Timeline.cpp @@ -0,0 +1,47 @@ +/****************************************************************************** +* Spine Runtimes Software License v2.5 +* +* Copyright (c) 2013-2016, Esoteric Software +* All rights reserved. +* +* You are granted a perpetual, non-exclusive, non-sublicensable, and +* non-transferable license to use, install, execute, and perform the Spine +* Runtimes software and derivative works solely for personal or internal +* use. Without the written permission of Esoteric Software (see Section 2 of +* the Spine Software License Agreement), you may not (a) modify, translate, +* adapt, or develop new applications using the Spine Runtimes or otherwise +* create derivative works or improvements of the Spine Runtimes or (b) remove, +* delete, alter, or obscure any trademarks or any copyright, trademark, patent, +* or other intellectual property or proprietary rights notices on or in the +* Software, including any copy thereof. Redistributions in binary or source +* form must include this license and terms. +* +* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +#include + +#include +#include + +namespace Spine +{ + Timeline::Timeline() + { + // Empty + } + + Timeline::~Timeline() + { + // Empty + } +} diff --git a/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp b/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp new file mode 100644 index 000000000..bb4d2ccfe --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp @@ -0,0 +1,34 @@ +/****************************************************************************** +* Spine Runtimes Software License v2.5 +* +* Copyright (c) 2013-2016, Esoteric Software +* All rights reserved. +* +* You are granted a perpetual, non-exclusive, non-sublicensable, and +* non-transferable license to use, install, execute, and perform the Spine +* Runtimes software and derivative works solely for personal or internal +* use. Without the written permission of Esoteric Software (see Section 2 of +* the Spine Software License Agreement), you may not (a) modify, translate, +* adapt, or develop new applications using the Spine Runtimes or otherwise +* create derivative works or improvements of the Spine Runtimes or (b) remove, +* delete, alter, or obscure any trademarks or any copyright, trademark, patent, +* or other intellectual property or proprietary rights notices on or in the +* Software, including any copy thereof. Redistributions in binary or source +* form must include this license and terms. +* +* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +namespace Spine +{ + // TODO +} diff --git a/spine-cpp/spine-cpp/src/spine/Updatable.cpp b/spine-cpp/spine-cpp/src/spine/Updatable.cpp new file mode 100644 index 000000000..d5a7f2ec3 --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/Updatable.cpp @@ -0,0 +1,44 @@ +/****************************************************************************** +* Spine Runtimes Software License v2.5 +* +* Copyright (c) 2013-2016, Esoteric Software +* All rights reserved. +* +* You are granted a perpetual, non-exclusive, non-sublicensable, and +* non-transferable license to use, install, execute, and perform the Spine +* Runtimes software and derivative works solely for personal or internal +* use. Without the written permission of Esoteric Software (see Section 2 of +* the Spine Software License Agreement), you may not (a) modify, translate, +* adapt, or develop new applications using the Spine Runtimes or otherwise +* create derivative works or improvements of the Spine Runtimes or (b) remove, +* delete, alter, or obscure any trademarks or any copyright, trademark, patent, +* or other intellectual property or proprietary rights notices on or in the +* Software, including any copy thereof. Redistributions in binary or source +* form must include this license and terms. +* +* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +#include + +namespace Spine +{ + Updatable::Updatable() + { + // Empty + } + + Updatable::~Updatable() + { + // Empty + } +} From fc09ed9745651448d428d565bb4e94d6fd8331d1 Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Fri, 13 Oct 2017 15:31:58 -0400 Subject: [PATCH 11/83] wip --- .../spine-cpp/include/spine/Attachment.h | 2 - spine-cpp/spine-cpp/include/spine/Bone.h | 2 - spine-cpp/spine-cpp/include/spine/BoneData.h | 2 - .../spine-cpp/include/spine/CurveTimeline.h | 6 +- spine-cpp/spine-cpp/include/spine/Event.h | 2 - spine-cpp/spine-cpp/include/spine/EventData.h | 2 - spine-cpp/spine-cpp/include/spine/HashMap.h | 352 ++++++++++++++++++ .../include/spine/IkConstraintData.h | 9 +- .../spine-cpp/include/spine/MixDirection.h | 2 +- spine-cpp/spine-cpp/include/spine/MixPose.h | 2 +- .../include/spine/PathConstraintData.h | 8 +- .../spine-cpp/include/spine/RotateTimeline.h | 8 +- .../spine-cpp/include/spine/SimpleArray.h | 187 ++++++++++ spine-cpp/spine-cpp/include/spine/Skeleton.h | 63 ++-- spine-cpp/spine-cpp/include/spine/Skin.h | 44 +-- spine-cpp/spine-cpp/include/spine/Slot.h | 13 +- spine-cpp/spine-cpp/include/spine/SlotData.h | 2 - spine-cpp/spine-cpp/include/spine/Timeline.h | 7 +- .../include/spine/TransformConstraintData.h | 9 +- spine-cpp/spine-cpp/src/spine/Attachment.cpp | 7 - spine-cpp/spine-cpp/src/spine/Bone.cpp | 7 +- spine-cpp/spine-cpp/src/spine/BoneData.cpp | 7 - spine-cpp/spine-cpp/src/spine/Event.cpp | 7 - spine-cpp/spine-cpp/src/spine/EventData.cpp | 7 - .../spine-cpp/src/spine/IkConstraintData.cpp | 9 +- .../src/spine/PathConstraintData.cpp | 9 +- .../spine-cpp/src/spine/RotateTimeline.cpp | 6 +- spine-cpp/spine-cpp/src/spine/Skin.cpp | 39 +- spine-cpp/spine-cpp/src/spine/Slot.cpp | 11 +- spine-cpp/spine-cpp/src/spine/SlotData.cpp | 7 - .../src/spine/TransformConstraintData.cpp | 9 +- 31 files changed, 645 insertions(+), 202 deletions(-) create mode 100755 spine-cpp/spine-cpp/include/spine/HashMap.h create mode 100644 spine-cpp/spine-cpp/include/spine/SimpleArray.h diff --git a/spine-cpp/spine-cpp/include/spine/Attachment.h b/spine-cpp/spine-cpp/include/spine/Attachment.h index 02a2f69d8..9f9f8460d 100644 --- a/spine-cpp/spine-cpp/include/spine/Attachment.h +++ b/spine-cpp/spine-cpp/include/spine/Attachment.h @@ -44,8 +44,6 @@ namespace Spine private: const std::string _name; - - friend std::ostream& operator <<(std::ostream& os, const Attachment& ref); }; } diff --git a/spine-cpp/spine-cpp/include/spine/Bone.h b/spine-cpp/spine-cpp/include/spine/Bone.h index b35dbdc87..3ddcfa48b 100644 --- a/spine-cpp/spine-cpp/include/spine/Bone.h +++ b/spine-cpp/spine-cpp/include/spine/Bone.h @@ -388,8 +388,6 @@ namespace Spine this.d = sin * b + cos * d; appliedValid = false; } - - friend std::ostream& operator <<(std::ostream& os, const Bone& ref); }; } diff --git a/spine-cpp/spine-cpp/include/spine/BoneData.h b/spine-cpp/spine-cpp/include/spine/BoneData.h index 79467a035..ef81b1e62 100644 --- a/spine-cpp/spine-cpp/include/spine/BoneData.h +++ b/spine-cpp/spine-cpp/include/spine/BoneData.h @@ -93,8 +93,6 @@ namespace Spine float _length; float _x, _y, _rotation, _scaleX, _scaleY, _shearX, _shearY; TransformMode _transformMode; - - friend std::ostream& operator <<(std::ostream& os, const BoneData& ref); }; } diff --git a/spine-cpp/spine-cpp/include/spine/CurveTimeline.h b/spine-cpp/spine-cpp/include/spine/CurveTimeline.h index 323198f41..24b3ad527 100644 --- a/spine-cpp/spine-cpp/include/spine/CurveTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/CurveTimeline.h @@ -32,8 +32,8 @@ #define Spine_CurveTimeline_h #include +#include -#include #include namespace Spine @@ -44,7 +44,7 @@ namespace Spine public: CurveTimeline(int frameCount); - virtual void apply(Skeleton& skeleton, float lastTime, float time, std::vector& events, float alpha, MixPose pose, MixDirection direction) = 0; + virtual void apply(Skeleton& skeleton, float lastTime, float time, SimpleArray& events, float alpha, MixPose pose, MixDirection direction) = 0; virtual int getPropertyId() = 0; @@ -70,7 +70,7 @@ namespace Spine static const int BEZIER_SIZE; private: - std::vector _curves; // type, x, y, ... + SimpleArray _curves; // type, x, y, ... }; } diff --git a/spine-cpp/spine-cpp/include/spine/Event.h b/spine-cpp/spine-cpp/include/spine/Event.h index 37d1acd6a..07d36999c 100644 --- a/spine-cpp/spine-cpp/include/spine/Event.h +++ b/spine-cpp/spine-cpp/include/spine/Event.h @@ -63,8 +63,6 @@ namespace Spine int _intValue; float _floatValue; std::string _stringValue; - - friend std::ostream& operator <<(std::ostream& os, const Event& ref); }; } diff --git a/spine-cpp/spine-cpp/include/spine/EventData.h b/spine-cpp/spine-cpp/include/spine/EventData.h index e26a44d7c..9705f5d89 100644 --- a/spine-cpp/spine-cpp/include/spine/EventData.h +++ b/spine-cpp/spine-cpp/include/spine/EventData.h @@ -60,8 +60,6 @@ namespace Spine private: friend class Event; const std::string _name; - - friend std::ostream& operator <<(std::ostream& os, const EventData& ref); }; } diff --git a/spine-cpp/spine-cpp/include/spine/HashMap.h b/spine-cpp/spine-cpp/include/spine/HashMap.h new file mode 100755 index 000000000..466970ca5 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/HashMap.h @@ -0,0 +1,352 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_HashMap_h +#define Spine_HashMap_h + +#include +#include + +namespace Spine +{ + template + class HashMap + { + private: + class Entry; + + public: + class Iterator + { + friend class HashMap; + + public: + Iterator(Entry* entry = NULL) : _entry(entry) + { + // Empty + } + + Iterator& operator++() + { + _entry = _entry->next; + return *this; + } + + Iterator& operator--() + { + _entry = _entry->prev; + return *this; + } + + bool operator==(const Iterator& p) const + { + return _entry == p._entry; + } + + bool operator!=(const Iterator& p) const + { + return _entry != p._entry; + } + + K& first() + { + return _entry->_key; + } + + V& second() + { + return _entry->_value; + } + + private: + Entry* _entry; + }; + + HashMap(int capacity) : _capacity(capacity), _hashFunction(), _header(), _trailer() + { + _hashTable = new Entry[capacity]; + for (int i = 0; i < _capacity; ++i) + { + _hashTable[i] = Entry(); + } + + _header.prev = &_header; + _header.next = &_trailer; + _trailer.prev = &_header; + _trailer.next = &_trailer; + _hashSize = 0; + } + + ~HashMap() + { + delete [] _hashTable; + + _hashSize = 0; + } + + size_t size() + { + return _hashSize; + } + + Iterator begin() + { + return Iterator(_header.next); + } + + Iterator end() + { + return Iterator(&_trailer); + } + + Iterator rbegin() + { + return Iterator(_trailer.prev); + } + + Iterator rend() + { + return Iterator(_header); + } + + Iterator insert(const K& key, const V& value) + { + Iterator iter = find(key); + + if (iter._entry != &_trailer) + { + return Iterator(&_trailer); + } + + size_t index = hash(key); + + Entry* entry = new Entry; + entry->_key = key; + entry->_value = value; + + _hashSize++; + + if (_header.next == (&_trailer)) + { + _hashTable[index].next = entry; + _hashTable[index].prev = entry; + _header.next = entry; + entry->prev = &_header; + entry->next = &_trailer; + _trailer.prev = entry; + + return Iterator(entry); + } + + if (_hashTable[index].next == NULL) + { + _hashTable[index].next = entry; + _hashTable[index].prev = entry; + if (index < hash(_header.next->_key)) + { + entry->next = _header.next; + entry->prev = &_header; + _header.next->prev = entry; + _header.next = entry; + } + else if (index > hash(_header.next->_key) && index < hash(_trailer.prev->_key)) + { + size_t prev_index = index; + + while (_hashTable[--prev_index].next != NULL) + { + // Empty + } + + entry->next = _hashTable[prev_index].prev->next; + entry->prev = _hashTable[prev_index].prev; + _hashTable[prev_index].prev->next = entry; + entry->next->prev = entry; + } + else + { + entry->next = &_trailer; + entry->prev = _trailer.prev; + _trailer.prev = entry; + entry->prev->next = entry; + } + + return Iterator(entry); + } + + if (index == hash(_header.next->_key)) + { + _header.next = entry; + entry->next = _hashTable[index].next; + entry->prev = &_header; + _hashTable[index].next->prev = entry; + _hashTable[index].next = entry; + } + else + { + entry->next = _hashTable[index].next; + entry->prev = _hashTable[index].next->prev; + entry->next->prev = entry; + entry->prev->next = entry; + _hashTable[index].next = entry; + } + + return Iterator(entry); + } + + Iterator find(const K& key) + { + const size_t index = hash(key); + Iterator iter(_hashTable[index].next); + + if (iter._entry != NULL) + { + for ( ; hash(iter._entry->_key) == index ; ++iter) + { + if (iter._entry->_key == key) + { + return iter; + } + } + } + + return Iterator(&_trailer); + } + + void erase(Iterator pos) + { + if (pos._entry != &_header && pos._entry != &_trailer) + { + size_t index = hash(pos._entry->_key); + + if (_hashTable[index].next == pos._entry && _hashTable[index].prev == pos._entry) + { + _hashTable[index].next = NULL; + _hashTable[index].prev = NULL; + + if (_header.next == pos._entry) + { + _header.next = pos._entry->next; + pos._entry->next->prev = &_header; + } + else if (_trailer.prev == pos._entry) + { + _trailer.prev = pos._entry->prev; + pos._entry->prev->next = &_trailer; + } + else + { + pos._entry->prev->next = pos._entry->next; + pos._entry->next->prev = pos._entry->prev; + } + + delete pos._entry; + } + else if (_hashTable[index].next == pos._entry) + { + _hashTable[index].next = pos._entry->next; + if (_header.next == pos._entry) + { + _header.next = pos._entry->next; + pos._entry->next->prev = &_header; + } + else + { + pos._entry->prev->next = pos._entry->next; + pos._entry->next->prev = pos._entry->prev; + } + + delete pos._entry; + } + else if (_hashTable[index].prev == pos._entry) + { + _hashTable[index].prev = pos._entry->prev; + if (_trailer.prev == pos._entry) + { + _trailer.prev = pos._entry->prev; + pos._entry->prev->next = &_trailer; + } + else + { + pos._entry->prev->next = pos._entry->next; + pos._entry->next->prev = pos._entry->prev; + } + + delete pos._entry; + } + else + { + pos._entry->prev->next = pos._entry->next; + pos._entry->next->prev = pos._entry->prev; + + delete pos._entry; + } + + _hashSize--; + } + } + + V operator[](const K& key) + { + Iterator iter = find(key); + + if (iter._entry != _trailer) + { + return iter._entry->_value; + } + + return V(); + } + + private: + class Entry + { + public: + K _key; + V _value; + Entry* next; + Entry* prev; + }; + + const H _hashFunction; + const int _capacity; + Entry* _hashTable; + Entry _header; + Entry _trailer; + size_t _hashSize; + + size_t hash(const K& key) + { + return _hashFunction(key) % _capacity; + } + }; +} + +#endif /* Spine_HashMap_h */ diff --git a/spine-cpp/spine-cpp/include/spine/IkConstraintData.h b/spine-cpp/spine-cpp/include/spine/IkConstraintData.h index ad0018068..0e54049a0 100644 --- a/spine-cpp/spine-cpp/include/spine/IkConstraintData.h +++ b/spine-cpp/spine-cpp/include/spine/IkConstraintData.h @@ -31,8 +31,9 @@ #ifndef Spine_IkConstraintData_h #define Spine_IkConstraintData_h +#include + #include -#include class BoneData; @@ -50,7 +51,7 @@ namespace Spine void setOrder(int inValue); /// The bones that are constrained by this IK Constraint. - std::vector& getBones(); + SimpleArray& getBones(); /// The bone that is the IK target. BoneData* getTarget(); @@ -66,12 +67,10 @@ namespace Spine private: const std::string _name; int _order; - std::vector _bones; + SimpleArray _bones; BoneData* _target; int _bendDirection; float _mix; - - friend std::ostream& operator <<(std::ostream& os, const IkConstraintData& ref); }; } diff --git a/spine-cpp/spine-cpp/include/spine/MixDirection.h b/spine-cpp/spine-cpp/include/spine/MixDirection.h index 637e61e2d..1400e1b3a 100644 --- a/spine-cpp/spine-cpp/include/spine/MixDirection.h +++ b/spine-cpp/spine-cpp/include/spine/MixDirection.h @@ -35,7 +35,7 @@ namespace Spine { /// /// Indicates whether a timeline's alpha is mixing out over time toward 0 (the setup or current pose) or mixing in toward 1 (the timeline's pose). - /// See also Timeline::apply(Skeleton&, float, float, std::vector&, float, MixPose, MixDirection) + /// See also Timeline::apply(Skeleton&, float, float, SimpleArray&, float, MixPose, MixDirection) enum MixDirection { MixDirection_In = 0, diff --git a/spine-cpp/spine-cpp/include/spine/MixPose.h b/spine-cpp/spine-cpp/include/spine/MixPose.h index 70f08931c..487165890 100644 --- a/spine-cpp/spine-cpp/include/spine/MixPose.h +++ b/spine-cpp/spine-cpp/include/spine/MixPose.h @@ -35,7 +35,7 @@ namespace Spine { /// /// Controls how a timeline is mixed with the setup or current pose. - /// See also Timeline::apply(Skeleton&, float, float, std::vector&, float, MixPose, MixDirection) + /// See also Timeline::apply(Skeleton&, float, float, SimpleArray&, float, MixPose, MixDirection) enum MixPose { /// The timeline value is mixed with the setup pose (the current pose is not used). diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraintData.h b/spine-cpp/spine-cpp/include/spine/PathConstraintData.h index 17f0b02d3..63c5ddcc6 100644 --- a/spine-cpp/spine-cpp/include/spine/PathConstraintData.h +++ b/spine-cpp/spine-cpp/include/spine/PathConstraintData.h @@ -34,9 +34,9 @@ #include #include #include +#include #include -#include namespace Spine { @@ -53,7 +53,7 @@ namespace Spine int getOrder(); void setOrder(int inValue); - std::vector& getBones(); + SimpleArray& getBones(); SlotData* getTarget(); void setTarget(SlotData* inValue); @@ -85,15 +85,13 @@ namespace Spine private: const std::string _name; int _order; - std::vector _bones; + SimpleArray _bones; SlotData* _target; PositionMode _positionMode; SpacingMode _spacingMode; RotateMode _rotateMode; float _offsetRotation; float _position, _spacing, _rotateMix, _translateMix; - - friend std::ostream& operator <<(std::ostream& os, const PathConstraintData& ref); }; } diff --git a/spine-cpp/spine-cpp/include/spine/RotateTimeline.h b/spine-cpp/spine-cpp/include/spine/RotateTimeline.h index 0c05a331d..41547f417 100644 --- a/spine-cpp/spine-cpp/include/spine/RotateTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/RotateTimeline.h @@ -42,7 +42,7 @@ namespace Spine RotateTimeline(int frameCount); - virtual void apply(Skeleton& skeleton, float lastTime, float time, std::vector& events, float alpha, MixPose pose, MixDirection direction); + virtual void apply(Skeleton& skeleton, float lastTime, float time, SimpleArray& events, float alpha, MixPose pose, MixDirection direction); virtual int getPropertyId(); @@ -52,8 +52,8 @@ namespace Spine int getBoneIndex(); void setBoneIndex(int inValue); - std::vector& getFrames(); - void setFrames(std::vector inValue); + SimpleArray& getFrames(); + void setFrames(SimpleArray inValue); private: static const int PREV_TIME = -2; @@ -61,7 +61,7 @@ namespace Spine static const int ROTATION = 1; int _boneIndex; - std::vector _frames; // time, angle, ... + SimpleArray _frames; // time, angle, ... }; } diff --git a/spine-cpp/spine-cpp/include/spine/SimpleArray.h b/spine-cpp/spine-cpp/include/spine/SimpleArray.h new file mode 100644 index 000000000..e544c8104 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/SimpleArray.h @@ -0,0 +1,187 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_SimpleArray_h +#define Spine_SimpleArray_h + +#include +#include + +namespace Spine +{ + template + class SimpleArray + { + public: + SimpleArray() : _size(0), _capacity(0), _buffer(nullptr) + { + // Empty + } + + SimpleArray(const SimpleArray& inArray) + { + _size = inArray._size; + _capacity = inArray._capacity; + if (_capacity) + { + _buffer = allocate(_capacity); + for (size_t i = 0; i < _size; ++i) + { + construct(_buffer + i, inArray._buffer[i]); + } + } + } + + ~SimpleArray() + { + clear(); + deallocate(_buffer); + } + + void push_back(const T& _value) + { + if (_size == _capacity) + { + reserve(); + } + + construct(_buffer + _size++, _value); + } + + void insert(size_t _index, const T& _value) + { + assert(_index < _size); + + if (_size == _capacity) + { + reserve(); + } + + for (size_t i = ++_size - 1; i > _index; --i) + { + construct(_buffer + i, _buffer[i - 1]); + destroy(_buffer + (i - 1)); + } + + construct(_buffer + _index, _value); + } + + void erase(size_t _index) + { + assert(_index < _size); + + --_size; + + if (_index != _size) + { + for (size_t i = _index; i < _size; ++i) + { + _buffer[i] = std::move(_buffer[i + 1]); + } + } + + destroy(_buffer + _size); + } + + void clear() + { + for (size_t i = 0; i < _size; ++i) + { + destroy(_buffer + (_size - 1 - i)); + } + + _size = 0; + } + + size_t size() const + { + return _size; + } + + T& operator[](size_t _index) + { + assert(_index < _size); + + return _buffer[_index]; + } + + void reserve(long inCapacity = -1) + { + size_t newCapacity = inCapacity != -1 ? inCapacity : _capacity ? _capacity * 2 : 1; + _buffer = static_cast(realloc(_buffer, newCapacity * sizeof(T))); + _capacity = newCapacity; + } + + T* begin() + { + return &_buffer[0]; + } + + T* end() + { + return &_buffer[_size]; + } + + private: + size_t _size; + size_t _capacity; + T* _buffer; + + T* allocate(size_t n) + { + assert(n > 0); + + void* ptr = malloc(n * sizeof(T)); + assert(ptr); + + return static_cast(ptr); + } + + void deallocate(T* buffer) + { + free(buffer); + } + + void construct(T* buffer, const T& val) + { + /// This is a placement new operator + /// which basically means we are contructing a new object + /// using pre-allocated memory + new (buffer) T(val); + } + + void destroy(T* buffer) + { + buffer->~T(); + } + }; +} + +#endif /* Spine_SimpleArray_h */ diff --git a/spine-cpp/spine-cpp/include/spine/Skeleton.h b/spine-cpp/spine-cpp/include/spine/Skeleton.h index b7dd1ca51..93ecaecc8 100644 --- a/spine-cpp/spine-cpp/include/spine/Skeleton.h +++ b/spine-cpp/spine-cpp/include/spine/Skeleton.h @@ -31,8 +31,9 @@ #ifndef Spine_Skeleton_h #define Spine_Skeleton_h +#include + #include -#include namespace Spine { @@ -49,13 +50,13 @@ namespace Spine { public: SkeletonData* getData(); - std::vector getBones(); - std::vector getUpdateCacheList(); - std::vector getSlots(); - std::vector getDrawOrder(); - std::vector getIkConstraints(); - std::vector getPathConstraints(); - std::vector getTransformConstraints(); + SimpleArray getBones(); + SimpleArray getUpdateCacheList(); + SimpleArray getSlots(); + SimpleArray getDrawOrder(); + SimpleArray getIkConstraints(); + SimpleArray getPathConstraints(); + SimpleArray getTransformConstraints(); Skin* getSkin { get { return skin; } set { skin = value; } } float getR { get { return r; } set { r = value; } } @@ -83,7 +84,7 @@ namespace Spine this.data = data; - bones = new std::vector(data.bones.Count); + bones = new SimpleArray(data.bones.Count); foreach (BoneData boneData in data.bones) { Bone bone; @@ -100,8 +101,8 @@ namespace Spine bones.Add(bone); } - slots = new std::vector(data.slots.Count); - drawOrder = new std::vector(data.slots.Count); + slots = new SimpleArray(data.slots.Count); + drawOrder = new SimpleArray(data.slots.Count); foreach (SlotData slotData in data.slots) { Bone bone = bones.Items[slotData.boneData.index]; @@ -110,15 +111,15 @@ namespace Spine drawOrder.Add(slot); } - ikConstraints = new std::vector(data.ikConstraints.Count); + ikConstraints = new SimpleArray(data.ikConstraints.Count); foreach (IkConstraintData ikConstraintData in data.ikConstraints) ikConstraints.Add(new IkConstraint(ikConstraintData, this)); - transformConstraints = new std::vector(data.transformConstraints.Count); + transformConstraints = new SimpleArray(data.transformConstraints.Count); foreach (TransformConstraintData transformConstraintData in data.transformConstraints) transformConstraints.Add(new TransformConstraint(transformConstraintData, this)); - pathConstraints = new std::vector (data.pathConstraints.Count); + pathConstraints = new SimpleArray (data.pathConstraints.Count); foreach (PathConstraintData pathConstraintData in data.pathConstraints) pathConstraints.Add(new PathConstraint(pathConstraintData, this)); @@ -135,17 +136,17 @@ namespace Spine /// or removed. void updateCache() { - std::vector updateCache = this.updateCache; + SimpleArray updateCache = this.updateCache; updateCache.Clear(); this.updateCacheReset.Clear(); - std::vector bones = this.bones; + SimpleArray bones = this.bones; for (int i = 0, n = bones.Count; i < n; i++) { bones.Items[i].sorted = false; } - std::vector ikConstraints = this.ikConstraints; + SimpleArray ikConstraints = this.ikConstraints; var transformConstraints = this.transformConstraints; var pathConstraints = this.pathConstraints; int ikCount = IkConstraints.Count, transformCount = transformConstraints.Count, pathCount = pathConstraints.Count; @@ -391,7 +392,7 @@ namespace Spine } else { - std::vector slots = this.slots; + SimpleArray slots = this.slots; for (int i = 0, n = slots.Count; i < n; i++) { Slot slot = slots.Items[i]; @@ -445,7 +446,7 @@ namespace Spine throw new ArgumentNullException("slotName", "slotName cannot be null."); } - std::vector slots = this.slots; + SimpleArray slots = this.slots; for (int i = 0, n = slots.Count; i < n; i++) { Slot slot = slots.Items[i]; @@ -478,7 +479,7 @@ namespace Spine throw new ArgumentNullException("constraintName", "constraintName cannot be null."); } - std::vector ikConstraints = this.ikConstraints; + SimpleArray ikConstraints = this.ikConstraints; for (int i = 0, n = ikConstraints.Count; i < n; i++) { IkConstraint ikConstraint = ikConstraints.Items[i]; @@ -496,7 +497,7 @@ namespace Spine throw new ArgumentNullException("constraintName", "constraintName cannot be null."); } - std::vector transformConstraints = this.transformConstraints; + SimpleArray transformConstraints = this.transformConstraints; for (int i = 0, n = transformConstraints.Count; i < n; i++) { TransformConstraint transformConstraint = transformConstraints.Items[i]; @@ -514,7 +515,7 @@ namespace Spine throw new ArgumentNullException("constraintName", "constraintName cannot be null."); } - std::vector pathConstraints = this.pathConstraints; + SimpleArray pathConstraints = this.pathConstraints; for (int i = 0, n = pathConstraints.Count; i < n; i++) { PathConstraint constraint = pathConstraints.Items[i]; @@ -594,14 +595,14 @@ namespace Spine private: SkeletonData* _data; - std::vector _bones; - std::vector _slots; - std::vector _drawOrder; - std::vector _ikConstraints; - std::vector _transformConstraints; - std::vector _pathConstraints; - std::vector _updateCache = new std::vector(); - std::vector _updateCacheReset = new std::vector(); + SimpleArray _bones; + SimpleArray _slots; + SimpleArray _drawOrder; + SimpleArray _ikConstraints; + SimpleArray _transformConstraints; + SimpleArray _pathConstraints; + SimpleArray _updateCache = new SimpleArray(); + SimpleArray _updateCacheReset = new SimpleArray(); Skin _skin; float _r = 1, _g = 1, _b = 1, _a = 1; float _time; @@ -763,7 +764,7 @@ namespace Spine updateCache.Add(bone); } - static void sortReset(std::vector& bones) + static void sortReset(SimpleArray& bones) { var bonesItems = bones.Items; for (int i = 0, n = bones.Count; i < n; i++) diff --git a/spine-cpp/spine-cpp/include/spine/Skin.h b/spine-cpp/spine-cpp/include/spine/Skin.h index 7a8b0f31a..72ee57f50 100644 --- a/spine-cpp/spine-cpp/include/spine/Skin.h +++ b/spine-cpp/spine-cpp/include/spine/Skin.h @@ -32,8 +32,10 @@ #define Spine_Skin_h #include -#include -#include +#include +#include + +struct HashAttachmentKey; namespace Spine { @@ -66,43 +68,37 @@ namespace Spine /// Returns the attachment for the specified slot index and name, or null. Attachment* getAttachment(int slotIndex, std::string name); - /// Finds the skin keys for a given slot. The results are added to the passed vector names. + /// Finds the skin keys for a given slot. The results are added to the passed array of names. /// @param slotIndex The target slotIndex. To find the slot index, use Skeleton::findSlotIndex or SkeletonData::findSlotIndex - /// @param names Found skin key names will be added to this vector. - void findNamesForSlot(int slotIndex, std::vector& names); + /// @param names Found skin key names will be added to this array. + void findNamesForSlot(int slotIndex, SimpleArray& names); - /// Finds the attachments for a given slot. The results are added to the passed List(Attachment). + /// Finds the attachments for a given slot. The results are added to the passed array of Attachments. /// @param slotIndex The target slotIndex. To find the slot index, use Skeleton::findSlotIndex or SkeletonData::findSlotIndex - /// @param attachments Found Attachments will be added to this vector. - void findAttachmentsForSlot(int slotIndex, std::vector& attachments); + /// @param attachments Found Attachments will be added to this array. + void findAttachmentsForSlot(int slotIndex, SimpleArray& attachments); const std::string& getName(); - std::unordered_map& getAttachments(); + HashMap& getAttachments(); private: const std::string _name; - std::unordered_map _attachments; + HashMap _attachments; /// Attach all attachments from this skin if the corresponding attachment from the old skin is currently attached. void attachAll(Skeleton& skeleton, Skin& oldSkin); - - friend std::ostream& operator <<(std::ostream& os, const Skin& ref); }; } -namespace std +struct HashAttachmentKey { - template <> - struct hash + std::size_t operator()(const Spine::Skin::AttachmentKey& val) const { - std::size_t operator()(const Spine::Skin::AttachmentKey& val) const - { - size_t h1 = hash{}(val._slotIndex); - size_t h2 = hash{}(val._name); - - return h1 ^ (h2 << 1); - } - }; -} + std::size_t h1 = std::hash{}(val._slotIndex); + std::size_t h2 = std::hash{}(val._name); + + return h1 ^ (h2 << 1); + } +}; #endif /* Spine_Skin_h */ diff --git a/spine-cpp/spine-cpp/include/spine/Slot.h b/spine-cpp/spine-cpp/include/spine/Slot.h index edce64ffa..2f2ae4bc4 100644 --- a/spine-cpp/spine-cpp/include/spine/Slot.h +++ b/spine-cpp/spine-cpp/include/spine/Slot.h @@ -31,8 +31,9 @@ #ifndef Spine_Slot_h #define Spine_Slot_h +#include + #include -#include namespace Spine { @@ -77,8 +78,8 @@ namespace Spine float getAttachmentTime(); void setAttachmentTime(float inValue); - std::vector& getAttachmentVertices(); - void setAttachmentVertices(std::vector inValue); + SimpleArray& getAttachmentVertices(); + void setAttachmentVertices(SimpleArray inValue); private: const SlotData& _slotData; @@ -89,10 +90,8 @@ namespace Spine bool _hasSecondColor; Attachment* _attachment; float _attachmentTime; - std::vector _attachmentVertices; - - friend std::ostream& operator <<(std::ostream& os, const Slot& ref); - } + SimpleArray _attachmentVertices; + }; } #endif /* Spine_Slot_h */ diff --git a/spine-cpp/spine-cpp/include/spine/SlotData.h b/spine-cpp/spine-cpp/include/spine/SlotData.h index 6eb358a40..e843d545c 100644 --- a/spine-cpp/spine-cpp/include/spine/SlotData.h +++ b/spine-cpp/spine-cpp/include/spine/SlotData.h @@ -84,8 +84,6 @@ namespace Spine bool _hasSecondColor; std::string _attachmentName; BlendMode _blendMode; - - friend std::ostream& operator <<(std::ostream& os, const SlotData& ref); }; } diff --git a/spine-cpp/spine-cpp/include/spine/Timeline.h b/spine-cpp/spine-cpp/include/spine/Timeline.h index db09f8086..f74944694 100644 --- a/spine-cpp/spine-cpp/include/spine/Timeline.h +++ b/spine-cpp/spine-cpp/include/spine/Timeline.h @@ -31,11 +31,10 @@ #ifndef Spine_Timeline_h #define Spine_Timeline_h +#include #include #include -#include - namespace Spine { class Skeleton; @@ -52,14 +51,14 @@ namespace Spine /// @param skeleton The skeleton the timeline is being applied to. This provides access to the bones, slots, and other skeleton components the timeline may change. /// @param lastTime lastTime The time this timeline was last applied. Timelines such as EventTimeline trigger only at specific times rather than every frame. In that case, the timeline triggers everything between lastTime (exclusive) and time (inclusive). /// @param time The time within the animation. Most timelines find the key before and the key after this time so they can interpolate between the keys. - /// @param events If any events are fired, they are added to this list. Can be null to ignore firing events or if the timeline does not fire events. May be null. + /// @param events If any events are fired, they are added to this array. Can be null to ignore firing events or if the timeline does not fire events. May be null. /// @param alpha alpha 0 applies the current or setup pose value (depending on pose parameter). 1 applies the timeline /// value. Between 0 and 1 applies a value between the current or setup pose and the timeline value. By adjusting /// alpha over time, an animation can be mixed in or out. alpha can also be useful to /// apply animations on top of each other (layered). /// @param pose Controls how mixing is applied when alpha is than 1. /// @param direction Indicates whether the timeline is mixing in or out. Used by timelines which perform instant transitions such as DrawOrderTimeline and AttachmentTimeline. - virtual void apply(Skeleton& skeleton, float lastTime, float time, std::vector& events, float alpha, MixPose pose, MixDirection direction) = 0; + virtual void apply(Skeleton& skeleton, float lastTime, float time, SimpleArray& events, float alpha, MixPose pose, MixDirection direction) = 0; virtual int getPropertyId() = 0; }; diff --git a/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h b/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h index 5ce55ac79..bd4f9bd1b 100644 --- a/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h +++ b/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h @@ -31,8 +31,9 @@ #ifndef Spine_TransformConstraintData_h #define Spine_TransformConstraintData_h +#include + #include -#include namespace Spine { @@ -45,7 +46,7 @@ namespace Spine const std::string& getName(); int getOrder(); - std::vector& getBones(); + SimpleArray& getBones(); BoneData* getTarget(); float getRotateMix(); float getTranslateMix(); @@ -65,13 +66,11 @@ namespace Spine private: const std::string _name; int _order; - std::vector _bones; + SimpleArray _bones; BoneData* _target; float _rotateMix, _translateMix, _scaleMix, _shearMix; float _offsetRotation, _offsetX, _offsetY, _offsetScaleX, _offsetScaleY, _offsetShearY; bool _relative, _local; - - friend std::ostream& operator <<(std::ostream& os, const TransformConstraintData& ref); }; } diff --git a/spine-cpp/spine-cpp/src/spine/Attachment.cpp b/spine-cpp/spine-cpp/src/spine/Attachment.cpp index 8ea383eea..fdd42ea70 100644 --- a/spine-cpp/spine-cpp/src/spine/Attachment.cpp +++ b/spine-cpp/spine-cpp/src/spine/Attachment.cpp @@ -43,11 +43,4 @@ namespace Spine { return _name; } - - std::ostream& operator <<(std::ostream& os, const Attachment& ref) - { - os << ref._name; - - return os; - } } diff --git a/spine-cpp/spine-cpp/src/spine/Bone.cpp b/spine-cpp/spine-cpp/src/spine/Bone.cpp index 246ca7413..001098b6f 100644 --- a/spine-cpp/spine-cpp/src/spine/Bone.cpp +++ b/spine-cpp/spine-cpp/src/spine/Bone.cpp @@ -32,10 +32,5 @@ namespace Spine { - std::ostream& operator <<(std::ostream& os, const Bone& ref) - { - os << ref._data._name; - - return os; - } + // TODO } diff --git a/spine-cpp/spine-cpp/src/spine/BoneData.cpp b/spine-cpp/spine-cpp/src/spine/BoneData.cpp index 17f508e1a..ed87124ff 100644 --- a/spine-cpp/spine-cpp/src/spine/BoneData.cpp +++ b/spine-cpp/spine-cpp/src/spine/BoneData.cpp @@ -156,11 +156,4 @@ namespace Spine { _transformMode = inValue; } - - std::ostream& operator <<(std::ostream& os, const BoneData& ref) - { - os << ref._name; - - return os; - } } diff --git a/spine-cpp/spine-cpp/src/spine/Event.cpp b/spine-cpp/spine-cpp/src/spine/Event.cpp index 548a32798..5f1458815 100644 --- a/spine-cpp/spine-cpp/src/spine/Event.cpp +++ b/spine-cpp/spine-cpp/src/spine/Event.cpp @@ -83,11 +83,4 @@ namespace Spine { _stringValue = inValue; } - - std::ostream& operator <<(std::ostream& os, const Event& ref) - { - os << ref._data; - - return os; - } } diff --git a/spine-cpp/spine-cpp/src/spine/EventData.cpp b/spine-cpp/spine-cpp/src/spine/EventData.cpp index 1f6438a09..e0eccf90b 100644 --- a/spine-cpp/spine-cpp/src/spine/EventData.cpp +++ b/spine-cpp/spine-cpp/src/spine/EventData.cpp @@ -78,11 +78,4 @@ namespace Spine { _stringValue = inValue; } - - std::ostream& operator <<(std::ostream& os, const EventData& ref) - { - os << ref._name; - - return os; - } } diff --git a/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp b/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp index b8f3b9373..36d16b307 100644 --- a/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp +++ b/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp @@ -57,7 +57,7 @@ namespace Spine _order = inValue; } - std::vector& IkConstraintData::getBones() + SimpleArray& IkConstraintData::getBones() { return _bones; } @@ -91,11 +91,4 @@ namespace Spine { _mix = inValue; } - - std::ostream& operator <<(std::ostream& os, const IkConstraintData& ref) - { - os << ref._name; - - return os; - } } diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraintData.cpp b/spine-cpp/spine-cpp/src/spine/PathConstraintData.cpp index 71ae38541..a9e1d07ef 100644 --- a/spine-cpp/spine-cpp/src/spine/PathConstraintData.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathConstraintData.cpp @@ -68,7 +68,7 @@ namespace Spine _order = inValue; } - std::vector& PathConstraintData::getBones() + SimpleArray& PathConstraintData::getBones() { return _bones; } @@ -162,11 +162,4 @@ namespace Spine { _translateMix = inValue; } - - std::ostream& operator <<(std::ostream& os, const PathConstraintData& ref) - { - os << ref._name; - - return os; - } } diff --git a/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp b/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp index 87bdef551..6d2302612 100644 --- a/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp @@ -43,7 +43,7 @@ namespace Spine _frames.reserve(frameCount << 1); } - void RotateTimeline::apply(Skeleton& skeleton, float lastTime, float time, std::vector& events, float alpha, MixPose pose, MixDirection direction) + void RotateTimeline::apply(Skeleton& skeleton, float lastTime, float time, SimpleArray& events, float alpha, MixPose pose, MixDirection direction) { Bone* bone = skeleton.getBones().at(_boneIndex); @@ -127,12 +127,12 @@ namespace Spine _boneIndex = inValue; } - std::vector& RotateTimeline::getFrames() + SimpleArray& RotateTimeline::getFrames() { return _frames; } - void RotateTimeline::setFrames(std::vector inValue) + void RotateTimeline::setFrames(SimpleArray inValue) { _frames = inValue; } diff --git a/spine-cpp/spine-cpp/src/spine/Skin.cpp b/spine-cpp/spine-cpp/src/spine/Skin.cpp index c4e9ab0d5..d0a8c2663 100644 --- a/spine-cpp/spine-cpp/src/spine/Skin.cpp +++ b/spine-cpp/spine-cpp/src/spine/Skin.cpp @@ -65,36 +65,36 @@ namespace Spine Attachment* Skin::getAttachment(int slotIndex, std::string name) { - std::unordered_map::iterator q = _attachments.find(AttachmentKey(slotIndex, name)); + HashMap::Iterator i = _attachments.find(AttachmentKey(slotIndex, name)); Attachment* ret = nullptr; - if (q != _attachments.end()) + if (i != _attachments.end()) { - ret = q->second; + ret = i.second(); } return ret; } - void Skin::findNamesForSlot(int slotIndex, std::vector& names) + void Skin::findNamesForSlot(int slotIndex, SimpleArray& names) { - for (std::unordered_map::iterator i = _attachments.begin(); i != _attachments.end(); ++i) + for (HashMap::Iterator i = _attachments.begin(); i != _attachments.end(); ++i) { - if (i->first._slotIndex == slotIndex) + if (i.first()._slotIndex == slotIndex) { - names.push_back(i->first._name); + names.push_back(i.first()._name); } } } - void Skin::findAttachmentsForSlot(int slotIndex, std::vector& attachments) + void Skin::findAttachmentsForSlot(int slotIndex, SimpleArray& attachments) { - for (std::unordered_map::iterator i = _attachments.begin(); i != _attachments.end(); ++i) + for (HashMap::Iterator i = _attachments.begin(); i != _attachments.end(); ++i) { - if (i->first._slotIndex == slotIndex) + if (i.first()._slotIndex == slotIndex) { - attachments.push_back(i->second); + attachments.push_back(i.second()); } } } @@ -104,33 +104,26 @@ namespace Spine return _name; } - std::unordered_map& Skin::getAttachments() + HashMap& Skin::getAttachments() { return _attachments; } void Skin::attachAll(Skeleton& skeleton, Skin& oldSkin) { - for (std::unordered_map::iterator i = oldSkin.getAttachments().begin(); i != oldSkin.getAttachments().end(); ++i) + for (HashMap::Iterator i = oldSkin.getAttachments().begin(); i != oldSkin.getAttachments().end(); ++i) { - int slotIndex = i->first._slotIndex; + int slotIndex = i.first()._slotIndex; Slot* slot = skeleton.getSlots().at(slotIndex); - if (slot->getAttachment() == i->second) + if (slot->getAttachment() == i.second()) { Attachment* attachment = nullptr; - if ((attachment = getAttachment(slotIndex, i->first._name))) + if ((attachment = getAttachment(slotIndex, i.first()._name))) { slot->setAttachment(attachment); } } } } - - std::ostream& operator <<(std::ostream& os, const Skin& ref) - { - os << ref._name; - - return os; - } } diff --git a/spine-cpp/spine-cpp/src/spine/Slot.cpp b/spine-cpp/spine-cpp/src/spine/Slot.cpp index 5e0af36aa..6b587cd5d 100644 --- a/spine-cpp/spine-cpp/src/spine/Slot.cpp +++ b/spine-cpp/spine-cpp/src/spine/Slot.cpp @@ -196,20 +196,13 @@ namespace Spine _attachmentTime = _skeleton.getTime() - inValue; } - std::vector& Slot::getAttachmentVertices() + SimpleArray& Slot::getAttachmentVertices() { return _attachmentVertices; } - void Slot::setAttachmentVertices(std::vector inValue) + void Slot::setAttachmentVertices(SimpleArray inValue) { _attachmentVertices = inValue; } - - std::ostream& operator <<(std::ostream& os, const Slot& ref) - { - os << ref._slotData.getName(); - - return os; - } } diff --git a/spine-cpp/spine-cpp/src/spine/SlotData.cpp b/spine-cpp/spine-cpp/src/spine/SlotData.cpp index a8bf97ff7..01eb96540 100644 --- a/spine-cpp/spine-cpp/src/spine/SlotData.cpp +++ b/spine-cpp/spine-cpp/src/spine/SlotData.cpp @@ -167,11 +167,4 @@ namespace Spine { _blendMode = inValue; } - - std::ostream& operator <<(std::ostream& os, const SlotData& ref) - { - os << ref._name; - - return os; - } } diff --git a/spine-cpp/spine-cpp/src/spine/TransformConstraintData.cpp b/spine-cpp/spine-cpp/src/spine/TransformConstraintData.cpp index 7d099b4e7..b3d0006fd 100644 --- a/spine-cpp/spine-cpp/src/spine/TransformConstraintData.cpp +++ b/spine-cpp/spine-cpp/src/spine/TransformConstraintData.cpp @@ -65,7 +65,7 @@ namespace Spine { return _order; } - std::vector& TransformConstraintData::getBones() + SimpleArray& TransformConstraintData::getBones() { return _bones; } @@ -134,11 +134,4 @@ namespace Spine { return _local; } - - std::ostream& operator <<(std::ostream& os, const TransformConstraintData& ref) - { - os << ref._name; - - return os; - } } From 210e492d79140fb54eee937aac3b6ee2735b8728 Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Sun, 15 Oct 2017 20:53:02 -0400 Subject: [PATCH 12/83] wip --- spine-cpp/spine-cpp/include/spine/Bone.h | 450 ++++----------- spine-cpp/spine-cpp/include/spine/MathUtil.h | 60 ++ spine-cpp/spine-cpp/src/spine/Bone.cpp | 565 ++++++++++++++++++- spine-cpp/spine-cpp/src/spine/MathUtil.cpp | 110 ++++ 4 files changed, 853 insertions(+), 332 deletions(-) create mode 100644 spine-cpp/spine-cpp/src/spine/MathUtil.cpp diff --git a/spine-cpp/spine-cpp/include/spine/Bone.h b/spine-cpp/spine-cpp/include/spine/Bone.h index 3ddcfa48b..9cc0b5d48 100644 --- a/spine-cpp/spine-cpp/include/spine/Bone.h +++ b/spine-cpp/spine-cpp/include/spine/Bone.h @@ -33,361 +33,149 @@ #include +#include + namespace Spine { + class BoneData; + class Skeleton; + /// Stores a bone's current pose. /// /// A bone has a local transform which is used to compute its world transform. A bone also has an applied transform, which is a /// local transform that can be applied to compute the world transform. The local transform and applied transform may differ if a /// constraint or application code modifies the world transform after it was computed from the local transform. - /// class Bone : public Updatable { friend class RotateTimeline; public: - private: - static public bool yDown; - - internal BoneData _data; - internal Skeleton _skeleton; - internal Bone _parent; - internal ExposedList _children = new ExposedList(); - internal float _x, _y, _rotation, _scaleX, _scaleY, _shearX, _shearY; - internal float _ax, _ay, _arotation, _ascaleX, _ascaleY, _ashearX, _ashearY; - internal bool _appliedValid; - - internal float _a, _b, _worldX; - internal float _c, _d, _worldY; - - // internal float worldSignX, worldSignY; - // public float WorldSignX { get { return worldSignX; } } - // public float WorldSignY { get { return worldSignY; } } - - internal bool _sorted; - - public BoneData Data { get { return data; } } - public Skeleton Skeleton { get { return skeleton; } } - public Bone Parent { get { return parent; } } - public ExposedList Children { get { return children; } } - /// The local X translation. - public float X { get { return x; } set { x = value; } } - /// The local Y translation. - public float Y { get { return y; } set { y = value; } } - /// The local rotation. - public float Rotation { get { return rotation; } set { rotation = value; } } - - /// The local scaleX. - public float ScaleX { get { return scaleX; } set { scaleX = value; } } - - /// The local scaleY. - public float ScaleY { get { return scaleY; } set { scaleY = value; } } - - /// The local shearX. - public float ShearX { get { return shearX; } set { shearX = value; } } - - /// The local shearY. - public float ShearY { get { return shearY; } set { shearY = value; } } - - /// The rotation, as calculated by any constraints. - public float AppliedRotation { get { return arotation; } set { arotation = value; } } - - /// The applied local x translation. - public float AX { get { return ax; } set { ax = value; } } - - /// The applied local y translation. - public float AY { get { return ay; } set { ay = value; } } - - /// The applied local scaleX. - public float AScaleX { get { return ascaleX; } set { ascaleX = value; } } - - /// The applied local scaleY. - public float AScaleY { get { return ascaleY; } set { ascaleY = value; } } - - /// The applied local shearX. - public float AShearX { get { return ashearX; } set { ashearX = value; } } - - /// The applied local shearY. - public float AShearY { get { return ashearY; } set { ashearY = value; } } - - public float A { get { return a; } } - public float B { get { return b; } } - public float C { get { return c; } } - public float D { get { return d; } } - - public float WorldX { get { return worldX; } } - public float WorldY { get { return worldY; } } - public float WorldRotationX { get { return MathUtils.Atan2(c, a) * MathUtils.RadDeg; } } - public float WorldRotationY { get { return MathUtils.Atan2(d, b) * MathUtils.RadDeg; } } - - /// Returns the magnitide (always positive) of the world scale X. - public float WorldScaleX { get { return (float)Math.Sqrt(a * a + c * c); } } - /// Returns the magnitide (always positive) of the world scale Y. - public float WorldScaleY { get { return (float)Math.Sqrt(b * b + d * d); } } - /// @param parent May be null. - public Bone (BoneData data, Skeleton skeleton, Bone parent) { - if (data == null) throw new ArgumentNullException("data", "data cannot be null."); - if (skeleton == null) throw new ArgumentNullException("skeleton", "skeleton cannot be null."); - this.data = data; - this.skeleton = skeleton; - this.parent = parent; - SetToSetupPose(); - } + Bone(BoneData& data, Skeleton& skeleton, Bone* parent); - /// Same as . This method exists for Bone to implement . - public void Update () { - UpdateWorldTransform(x, y, rotation, scaleX, scaleY, shearX, shearY); - } + /// Same as updateWorldTransform. This method exists for Bone to implement Spine::Updatable. + virtual void update(); /// Computes the world transform using the parent bone and this bone's local transform. - public void UpdateWorldTransform () { - UpdateWorldTransform(x, y, rotation, scaleX, scaleY, shearX, shearY); - } + void updateWorldTransform(); /// Computes the world transform using the parent bone and the specified local transform. - public void UpdateWorldTransform (float x, float y, float rotation, float scaleX, float scaleY, float shearX, float shearY) { - ax = x; - ay = y; - arotation = rotation; - ascaleX = scaleX; - ascaleY = scaleY; - ashearX = shearX; - ashearY = shearY; - appliedValid = true; - Skeleton skeleton = this.skeleton; - - Bone parent = this.parent; - if (parent == null) { // Root bone. - float rotationY = rotation + 90 + shearY; - float la = MathUtils.CosDeg(rotation + shearX) * scaleX; - float lb = MathUtils.CosDeg(rotationY) * scaleY; - float lc = MathUtils.SinDeg(rotation + shearX) * scaleX; - float ld = MathUtils.SinDeg(rotationY) * scaleY; - if (skeleton.flipX) { - x = -x; - la = -la; - lb = -lb; - } - if (skeleton.flipY != yDown) { - y = -y; - lc = -lc; - ld = -ld; - } - a = la; - b = lb; - c = lc; - d = ld; - worldX = x + skeleton.x; - worldY = y + skeleton.y; - // worldSignX = Math.Sign(scaleX); - // worldSignY = Math.Sign(scaleY); - return; - } - - float pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d; - worldX = pa * x + pb * y + parent.worldX; - worldY = pc * x + pd * y + parent.worldY; - // worldSignX = parent.worldSignX * Math.Sign(scaleX); - // worldSignY = parent.worldSignY * Math.Sign(scaleY); - - switch (data.transformMode) { - case TransformMode.Normal: { - float rotationY = rotation + 90 + shearY; - float la = MathUtils.CosDeg(rotation + shearX) * scaleX; - float lb = MathUtils.CosDeg(rotationY) * scaleY; - float lc = MathUtils.SinDeg(rotation + shearX) * scaleX; - float ld = MathUtils.SinDeg(rotationY) * scaleY; - a = pa * la + pb * lc; - b = pa * lb + pb * ld; - c = pc * la + pd * lc; - d = pc * lb + pd * ld; - return; - } - case TransformMode.OnlyTranslation: { - float rotationY = rotation + 90 + shearY; - a = MathUtils.CosDeg(rotation + shearX) * scaleX; - b = MathUtils.CosDeg(rotationY) * scaleY; - c = MathUtils.SinDeg(rotation + shearX) * scaleX; - d = MathUtils.SinDeg(rotationY) * scaleY; - break; - } - case TransformMode.NoRotationOrReflection: { - float s = pa * pa + pc * pc, prx; - if (s > 0.0001f) { - s = Math.Abs(pa * pd - pb * pc) / s; - pb = pc * s; - pd = pa * s; - prx = MathUtils.Atan2(pc, pa) * MathUtils.RadDeg; - } else { - pa = 0; - pc = 0; - prx = 90 - MathUtils.Atan2(pd, pb) * MathUtils.RadDeg; - } - float rx = rotation + shearX - prx; - float ry = rotation + shearY - prx + 90; - float la = MathUtils.CosDeg(rx) * scaleX; - float lb = MathUtils.CosDeg(ry) * scaleY; - float lc = MathUtils.SinDeg(rx) * scaleX; - float ld = MathUtils.SinDeg(ry) * scaleY; - a = pa * la - pb * lc; - b = pa * lb - pb * ld; - c = pc * la + pd * lc; - d = pc * lb + pd * ld; - break; - } - case TransformMode.NoScale: - case TransformMode.NoScaleOrReflection: { - float cos = MathUtils.CosDeg(rotation), sin = MathUtils.SinDeg(rotation); - float za = pa * cos + pb * sin; - float zc = pc * cos + pd * sin; - float s = (float)Math.Sqrt(za * za + zc * zc); - if (s > 0.00001f) s = 1 / s; - za *= s; - zc *= s; - s = (float)Math.Sqrt(za * za + zc * zc); - float r = MathUtils.PI / 2 + MathUtils.Atan2(zc, za); - float zb = MathUtils.Cos(r) * s; - float zd = MathUtils.Sin(r) * s; - float la = MathUtils.CosDeg(shearX) * scaleX; - float lb = MathUtils.CosDeg(90 + shearY) * scaleY; - float lc = MathUtils.SinDeg(shearX) * scaleX; - float ld = MathUtils.SinDeg(90 + shearY) * scaleY; - if (data.transformMode != TransformMode.NoScaleOrReflection? pa * pd - pb* pc< 0 : skeleton.flipX != skeleton.flipY) { - zb = -zb; - zd = -zd; - } - a = za * la + zb * lc; - b = za * lb + zb * ld; - c = zc * la + zd * lc; - d = zc * lb + zd * ld; - return; - } - } - - if (skeleton.flipX) { - a = -a; - b = -b; - } - if (skeleton.flipY != Bone.yDown) { - c = -c; - d = -d; - } - } + void updateWorldTransform(float x, float y, float rotation, float scaleX, float scaleY, float shearX, float shearY); - public void SetToSetupPose () { - BoneData data = this.data; - x = data.x; - y = data.y; - rotation = data.rotation; - scaleX = data.scaleX; - scaleY = data.scaleY; - shearX = data.shearX; - shearY = data.shearY; - } + void setToSetupPose(); + + void worldToLocal(float worldX, float worldY, float& outLocalX, float& outLocalY); + + void localToWorld(float localX, float localY, float& outWorldX, float& outWorldY); + + float worldToLocalRotation(float worldRotation); + + float localToWorldRotation(float localRotation); + + /// + /// Rotates the world transform the specified amount and sets isAppliedValid to false. + /// + /// @param degrees Degrees. + void rotateWorld(float degrees); + + float getWorldToLocalRotationX(); + + float getWorldToLocalRotationY(); + + BoneData& getData(); + Skeleton& getSkeleton(); + Bone* getParent(); + SimpleArray& getChildren(); + + /// The local X translation. + float getX(); + void setX(float inValue); + + /// The local Y translation. + float getY(); + void setY(float inValue); + + /// The local rotation. + float getRotation(); + void setRotation(float inValue); + + /// The local scaleX. + float getScaleX(); + void setScaleX(float inValue); + + /// The local scaleY. + float getScaleY(); + void setScaleY(float inValue); + + /// The local shearX. + float getShearX(); + void setShearX(float inValue); + + /// The local shearY. + float getShearY(); + void setShearY(float inValue); + + /// The rotation, as calculated by any constraints. + float getAppliedRotation(); + void setAppliedRotation(float inValue); + + /// The applied local x translation. + float getAX(); + void setAX(float inValue); + + /// The applied local y translation. + float getAY(); + void setAY(float inValue); + + /// The applied local scaleX. + float getAScaleX(); + void setAScaleX(float inValue); + + /// The applied local scaleY. + float getAScaleY(); + void setAScaleY(float inValue); + + /// The applied local shearX. + float getAShearX(); + void setAShearX(float inValue); + + /// The applied local shearY. + float getAShearY(); + void setAShearY(float inValue); + + float getA(); + float getB(); + float getC(); + float getD(); + + float getWorldX(); + float getWorldY(); + float getWorldRotationX(); + float getWorldRotationY(); + + /// Returns the magnitide (always positive) of the world scale X. + float getWorldScaleX(); + + /// Returns the magnitide (always positive) of the world scale Y. + float getWorldScaleY(); + + private: + BoneData& _data; + Skeleton& _skeleton; + Bone* _parent; + SimpleArray _children; + float _x, _y, _rotation, _scaleX, _scaleY, _shearX, _shearY; + float _ax, _ay, _arotation, _ascaleX, _ascaleY, _ashearX, _ashearY; + bool _appliedValid; + float _a, _b, _worldX; + float _c, _d, _worldY; + bool _sorted; - /// /// 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).. /// /// Some information is ambiguous in the world transform, such as -1,-1 scale versus 180 rotation. - /// - internal void UpdateAppliedTransform () { - appliedValid = true; - Bone parent = this.parent; - if (parent == null) { - ax = worldX; - ay = worldY; - arotation = MathUtils.Atan2(c, a) * MathUtils.RadDeg; - ascaleX = (float)Math.Sqrt(a * a + c * c); - ascaleY = (float)Math.Sqrt(b * b + d * d); - ashearX = 0; - ashearY = MathUtils.Atan2(a * b + c * d, a * d - b * c) * MathUtils.RadDeg; - return; - } - float pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d; - float pid = 1 / (pa * pd - pb * pc); - float dx = worldX - parent.worldX, dy = worldY - parent.worldY; - ax = (dx * pd * pid - dy * pb * pid); - ay = (dy * pa * pid - dx * pc * pid); - float ia = pid * pd; - float id = pid * pa; - float ib = pid * pb; - float ic = pid * pc; - float ra = ia * a - ib * c; - float rb = ia * b - ib * d; - float rc = id * c - ic * a; - float rd = id * d - ic * b; - ashearX = 0; - ascaleX = (float)Math.Sqrt(ra * ra + rc * rc); - if (ascaleX > 0.0001f) { - float det = ra * rd - rb * rc; - ascaleY = det / ascaleX; - ashearY = MathUtils.Atan2(ra * rb + rc * rd, det) * MathUtils.RadDeg; - arotation = MathUtils.Atan2(rc, ra) * MathUtils.RadDeg; - } else { - ascaleX = 0; - ascaleY = (float)Math.Sqrt(rb * rb + rd * rd); - ashearY = 0; - arotation = 90 - MathUtils.Atan2(rd, rb) * MathUtils.RadDeg; - } - } - - public void WorldToLocal (float worldX, float worldY, out float localX, out float localY) { - float a = this.a, b = this.b, c = this.c, d = this.d; - float invDet = 1 / (a * d - b * c); - float x = worldX - this.worldX, y = worldY - this.worldY; - localX = (x * d * invDet - y * b * invDet); - localY = (y * a * invDet - x * c * invDet); - } - - public void LocalToWorld (float localX, float localY, out float worldX, out float worldY) { - worldX = localX * a + localY * b + this.worldX; - worldY = localX * c + localY * d + this.worldY; - } - - public float WorldToLocalRotationX { - get { - Bone parent = this.parent; - if (parent == null) return arotation; - float pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d, a = this.a, c = this.c; - return MathUtils.Atan2(pa * c - pc * a, pd * a - pb * c) * MathUtils.RadDeg; - } - } - - public float WorldToLocalRotationY { - get { - Bone parent = this.parent; - if (parent == null) return arotation; - float pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d, b = this.b, d = this.d; - return MathUtils.Atan2(pa * d - pc * b, pd * b - pb * d) * MathUtils.RadDeg; - } - } - - public float WorldToLocalRotation (float worldRotation) { - float sin = MathUtils.SinDeg(worldRotation), cos = MathUtils.CosDeg(worldRotation); - return MathUtils.Atan2(a * sin - c * cos, d * cos - b * sin) * MathUtils.RadDeg; - } - - public float LocalToWorldRotation (float localRotation) { - float sin = MathUtils.SinDeg(localRotation), cos = MathUtils.CosDeg(localRotation); - return MathUtils.Atan2(cos * c + sin * d, cos * a + sin * b) * MathUtils.RadDeg; - } - - /// - /// Rotates the world transform the specified amount and sets isAppliedValid to false. - /// - /// @param degrees Degrees. - public void RotateWorld (float degrees) - { - float a = this.a, b = this.b, c = this.c, d = this.d; - float cos = MathUtils.CosDeg(degrees), sin = MathUtils.SinDeg(degrees); - this.a = cos * a - sin * c; - this.b = cos * b - sin * d; - this.c = sin * a + cos * c; - this.d = sin * b + cos * d; - appliedValid = false; - } + void updateAppliedTransform(); }; } diff --git a/spine-cpp/spine-cpp/include/spine/MathUtil.h b/spine-cpp/spine-cpp/include/spine/MathUtil.h index 12d4a4ed5..0eeb27f2c 100644 --- a/spine-cpp/spine-cpp/include/spine/MathUtil.h +++ b/spine-cpp/spine-cpp/include/spine/MathUtil.h @@ -32,9 +32,69 @@ #define Spine_MathUtil_h #include +#include + +#define SPINE_PI 3.1415927f +#define SPINE_PI_2 PI * 2 +#define RadDeg 180.0f / SPINE_PI +#define DegRad SPINE_PI / 180.0f +#define SIN_BITS 14 // 16KB. Adjust for accuracy. +#define SIN_MASK ~(-(1 << SIN_BITS)) +#define SIN_COUNT SIN_MASK + 1 +#define RadFull SPINE_PI * 2 +#define DegFull 360 +#define RadToIndex SIN_COUNT / RadFull +#define DegToIndex SIN_COUNT / DegFull namespace Spine { + inline bool areFloatsPracticallyEqual(float A, float B, float maxDiff = 0.0000000000000001f, float maxRelDiff = FLT_EPSILON) + { + // Check if the numbers are really close -- needed + // when comparing numbers near zero. + float diff = fabs(A - B); + if (diff <= maxDiff) + { + return true; + } + + A = fabs(A); + B = fabs(B); + + float largest = (B > A) ? B : A; + + if (diff <= largest * maxRelDiff) + { + return true; + } + + return false; + } + + class MathUtil + { + public: + static float SIN_TABLE[SIN_COUNT]; + + MathUtil(); + + /// Returns the sine in radians from a lookup table. + static float sin(float radians); + + /// Returns the cosine in radians from a lookup table. + static float cos(float radians); + + /// Returns the sine in radians from a lookup table. + static float sinDeg(float degrees); + + /// Returns the cosine in radians from a lookup table. + static float cosDeg(float degrees); + + /// Returns atan2 in radians, faster but less accurate than Math.Atan2. Average error of 0.00231 radians (0.1323 + /// degrees), largest error of 0.00488 radians (0.2796 degrees). + static float atan2(float y, float x); + }; + inline float clamp(float x, float lower, float upper) { return fminf(upper, fmaxf(x, lower)); diff --git a/spine-cpp/spine-cpp/src/spine/Bone.cpp b/spine-cpp/spine-cpp/src/spine/Bone.cpp index 001098b6f..21b275a6a 100644 --- a/spine-cpp/spine-cpp/src/spine/Bone.cpp +++ b/spine-cpp/spine-cpp/src/spine/Bone.cpp @@ -30,7 +30,570 @@ #include +#include +#include + +#include +#include + namespace Spine { - // TODO + Bone::Bone(BoneData& data, Skeleton& skeleton, Bone* parent) : Updatable(), + _data(data), + _skeleton(skeleton), + _parent(parent), + _x(0), + _y(0), + _rotation(0), + _scaleX(0), + _scaleY(0), + _shearX(0), + _shearY(0), + _ax(0), + _ay(0), + _arotation(0), + _ascaleX(0), + _ascaleY(0), + _ashearX(0), + _ashearY(0), + _appliedValid(false), + _a(0), + _b(0), + _worldX(0), + _c(0), + _d(0), + _worldY(0), + _sorted(false) + { + setToSetupPose(); + } + + void Bone::update() + { + updateWorldTransform(_x, _y, _rotation, _scaleX, _scaleY, _shearX, _shearY); + } + + void Bone::updateWorldTransform() + { + updateWorldTransform(_x, _y, _rotation, _scaleX, _scaleY, _shearX, _shearY); + } + + void Bone::updateWorldTransform(float x, float y, float rotation, float scaleX, float scaleY, float shearX, float shearY) + { + _ax = x; + _ay = y; + _arotation = rotation; + _ascaleX = scaleX; + _ascaleY = scaleY; + _ashearX = shearX; + _ashearY = shearY; + _appliedValid = true; + Skeleton& skeleton = _skeleton; + + Bone* parent = _parent; + if (!parent) + { + // Root bone. + float rotationY = rotation + 90 + shearY; + float la = MathUtil::cosDeg(rotation + shearX) * scaleX; + float lb = MathUtil::cosDeg(rotationY) * scaleY; + float lc = MathUtil::sinDeg(rotation + shearX) * scaleX; + float ld = MathUtil::sinDeg(rotationY) * scaleY; + if (_skeleton.isFlipX()) + { + x = -x; + la = -la; + lb = -lb; + } + + _a = la; + _b = lb; + _c = lc; + _d = ld; + _worldX = x + _skeleton.getX(); + _worldY = y + _skeleton.getY(); + + return; + } + + float pa = parent->_a; + float pb = parent->_b; + float pc = parent->_c; + float pd = parent->_d; + + _worldX = pa * x + pb * y + parent->_worldX; + _worldY = pc * x + pd * y + parent->_worldY; + + switch (_data.getTransformMode()) + { + case TransformMode_Normal: + { + float rotationY = rotation + 90 + shearY; + float la = MathUtil::cosDeg(rotation + shearX) * scaleX; + float lb = MathUtil::cosDeg(rotationY) * scaleY; + float lc = MathUtil::sinDeg(rotation + shearX) * scaleX; + float ld = MathUtil::sinDeg(rotationY) * scaleY; + _a = pa * la + pb * lc; + _b = pa * lb + pb * ld; + _c = pc * la + pd * lc; + _d = pc * lb + pd * ld; + + return; + } + case TransformMode_OnlyTranslation: + { + float rotationY = rotation + 90 + shearY; + _a = MathUtil::cosDeg(rotation + shearX) * scaleX; + _b = MathUtil::cosDeg(rotationY) * scaleY; + _c = MathUtil::sinDeg(rotation + shearX) * scaleX; + _d = MathUtil::sinDeg(rotationY) * scaleY; + + break; + } + case TransformMode_NoRotationOrReflection: + { + float s = pa * pa + pc * pc, prx; + if (s > 0.0001f) + { + s = fabs(pa * pd - pb * pc) / s; + pb = pc * s; + pd = pa * s; + prx = MathUtil::atan2(pc, pa) * RadDeg; + } + else + { + pa = 0; + pc = 0; + prx = 90 - MathUtil::atan2(pd, pb) * RadDeg; + } + float rx = rotation + shearX - prx; + float ry = rotation + shearY - prx + 90; + float la = MathUtil::cosDeg(rx) * scaleX; + float lb = MathUtil::cosDeg(ry) * scaleY; + float lc = MathUtil::sinDeg(rx) * scaleX; + float ld = MathUtil::sinDeg(ry) * scaleY; + + _a = pa * la - pb * lc; + _b = pa * lb - pb * ld; + _c = pc * la + pd * lc; + _d = pc * lb + pd * ld; + + break; + } + case TransformMode_NoScale: + case TransformMode_NoScaleOrReflection: + { + float cos = MathUtil::cosDeg(rotation); + float sin = MathUtil::sinDeg(rotation); + float za = pa * cos + pb * sin; + float zc = pc * cos + pd * sin; + float s = sqrt(za * za + zc * zc); + if (s > 0.00001f) + { + s = 1 / s; + } + + za *= s; + zc *= s; + s = sqrt(za * za + zc * zc); + float r = SPINE_PI / 2 + MathUtil::atan2(zc, za); + float zb = MathUtil::cos(r) * s; + float zd = MathUtil::sin(r) * s; + float la = MathUtil::cosDeg(shearX) * scaleX; + float lb = MathUtil::cosDeg(90 + shearY) * scaleY; + float lc = MathUtil::sinDeg(shearX) * scaleX; + float ld = MathUtil::sinDeg(90 + shearY) * scaleY; + + if (_data.getTransformMode() != TransformMode_NoScaleOrReflection ? pa * pd - pb * pc < 0 : _skeleton.isFlipX() != _skeleton.isFlipY()) + { + zb = -zb; + zd = -zd; + } + + _a = za * la + zb * lc; + _b = za * lb + zb * ld; + _c = zc * la + zd * lc; + _d = zc * lb + zd * ld; + + return; + } + } + + if (_skeleton.isFlipX()) + { + _a = -_a; + _b = -_b; + } + } + + void Bone::setToSetupPose() + { + BoneData& data = _data; + _x = data.getX(); + _y = data.getY(); + _rotation = data.getRotation(); + _scaleX = data.getScaleX(); + _scaleY = data.getScaleY(); + _shearX = data.getShearX(); + _shearY = data.getShearY(); + } + + void Bone::worldToLocal(float worldX, float worldY, float& outLocalX, float& outLocalY) + { + float a = _a; + float b = _b; + float c = _c; + float d = _d; + + float invDet = 1 / (a * d - b * c); + float x = worldX - _worldX; + float y = worldY - _worldY; + + outLocalX = (x * d * invDet - y * b * invDet); + outLocalY = (y * a * invDet - x * c * invDet); + } + + void Bone::localToWorld(float localX, float localY, float& outWorldX, float& outWorldY) + { + outWorldX = localX * _a + localY * _b + _worldX; + outWorldY = localX * _c + localY * _d + _worldY; + } + + float Bone::worldToLocalRotation(float worldRotation) + { + float sin = MathUtil::sinDeg(worldRotation); + float cos = MathUtil::cosDeg(worldRotation); + + return MathUtil::atan2(_a * sin - _c * cos, _d * cos - _b * sin) * RadDeg; + } + + float Bone::localToWorldRotation(float localRotation) + { + float sin = MathUtil::sinDeg(localRotation); + float cos = MathUtil::cosDeg(localRotation); + + return MathUtil::atan2(cos * _c + sin * _d, cos * _a + sin * _b) * RadDeg; + } + + void Bone::rotateWorld(float degrees) + { + float a = _a; + float b = _b; + float c = _c; + float d = _d; + + float cos = MathUtil::cosDeg(degrees); + float sin = MathUtil::sinDeg(degrees); + + _a = cos * a - sin * c; + _b = cos * b - sin * d; + _c = sin * a + cos * c; + _d = sin * b + cos * d; + + _appliedValid = false; + } + + float Bone::getWorldToLocalRotationX() + { + Bone* parent = _parent; + if (!parent) + { + return _arotation; + } + + float pa = parent->_a; + float pb = parent->_b; + float pc = parent->_c; + float pd = parent->_d; + float a = _a; + float c = _c; + + return MathUtil::atan2(pa * c - pc * a, pd * a - pb * c) * RadDeg; + } + + float Bone::getWorldToLocalRotationY() + { + Bone* parent = _parent; + if (!parent) + { + return _arotation; + } + + float pa = parent->_a; + float pb = parent->_b; + float pc = parent->_c; + float pd = parent->_d; + float b = _b; + float d = _d; + + return MathUtil::atan2(pa * d - pc * b, pd * b - pb * d) * RadDeg; + } + + BoneData& Bone::getData() + { + return _data; + } + + Skeleton& Bone::getSkeleton() + { + return _skeleton; + } + + Bone* Bone::getParent() + { + return _parent; + } + + SimpleArray& Bone::getChildren() + { + return _children; + } + + float Bone::getX() + { + return _x; + } + + void Bone::setX(float inValue) + { + _x = inValue; + } + + float Bone::getY() + { + return _y; + } + + void Bone::setY(float inValue) + { + _y = inValue; + } + + float Bone::getRotation() + { + return _rotation; + } + + void Bone::setRotation(float inValue) + { + _rotation = inValue; + } + + float Bone::getScaleX() + { + return _scaleX; + } + + void Bone::setScaleX(float inValue) + { + _scaleX = inValue; + } + + float Bone::getScaleY() + { + return _scaleY; + } + + void Bone::setScaleY(float inValue) + { + _scaleY = inValue; + } + + float Bone::getShearX() + { + return _shearX; + } + + void Bone::setShearX(float inValue) + { + _shearX = inValue; + } + + float Bone::getShearY() + { + return _shearY; + } + + void Bone::setShearY(float inValue) + { + _shearY = inValue; + } + + float Bone::getAppliedRotation() + { + return _arotation; + } + + void Bone::setAppliedRotation(float inValue) + { + _arotation = inValue; + } + + float Bone::getAX() + { + return _ax; + } + + void Bone::setAX(float inValue) + { + _ax = inValue; + } + + float Bone::getAY() + { + return _ay; + } + + void Bone::setAY(float inValue) + { + _ay = inValue; + } + + float Bone::getAScaleX() + { + return _ascaleX; + } + + void Bone::setAScaleX(float inValue) + { + _ascaleX = inValue; + } + + float Bone::getAScaleY() + { + return _ascaleY; + } + + void Bone::setAScaleY(float inValue) + { + _ascaleY = inValue; + } + + float Bone::getAShearX() + { + return _ashearX; + } + + void Bone::setAShearX(float inValue) + { + _ashearX = inValue; + } + + float Bone::getAShearY() + { + return _ashearY; + } + + void Bone::setAShearY(float inValue) + { + _ashearY = inValue; + } + + float Bone::getA() + { + return _a; + } + + float Bone::getB() + { + return _b; + } + + float Bone::getC() + { + return _c; + } + + float Bone::getD() + { + return _d; + } + + float Bone::getWorldX() + { + return _worldX; + } + + float Bone::getWorldY() + { + return _worldY; + } + + float Bone::getWorldRotationX() + { + return MathUtil::atan2(_c, _a) * RadDeg; + } + + float Bone::getWorldRotationY() + { + return MathUtil::atan2(_d, _b) * RadDeg; + } + + float Bone::getWorldScaleX() + { + return sqrt(_a * _a + _c * _c); + } + + float Bone::getWorldScaleY() + { + return sqrt(_b * _b + _d * _d); + } + + void Bone::updateAppliedTransform() + { + _appliedValid = true; + Bone* parent = _parent; + if (!parent) + { + _ax = _worldX; + _ay = _worldY; + _arotation = MathUtil::atan2(_c, _a) * RadDeg; + _ascaleX = sqrt(_a * _a + _c * _c); + _ascaleY = sqrt(_b * _b + _d * _d); + _ashearX = 0; + _ashearY = MathUtil::atan2(_a * _b + _c * _d, _a * _d - _b * _c) * RadDeg; + + return; + } + + float pa = parent->_a; + float pb = parent->_b; + float pc = parent->_c; + float pd = parent->_d; + + float pid = 1 / (pa * pd - pb * pc); + float dx = _worldX - parent->_worldX; + float dy = _worldY - parent->_worldY; + + _ax = (dx * pd * pid - dy * pb * pid); + _ay = (dy * pa * pid - dx * pc * pid); + + float ia = pid * pd; + float id = pid * pa; + float ib = pid * pb; + float ic = pid * pc; + + float ra = ia * _a - ib * _c; + float rb = ia * _b - ib * _d; + float rc = id * _c - ic * _a; + float rd = id * _d - ic * _b; + + _ashearX = 0; + _ascaleX = sqrt(ra * ra + rc * rc); + + if (_ascaleX > 0.0001f) + { + float det = ra * rd - rb * rc; + _ascaleY = det / _ascaleX; + _ashearY = MathUtil::atan2(ra * rb + rc * rd, det) * RadDeg; + _arotation = MathUtil::atan2(rc, ra) * RadDeg; + } + else + { + _ascaleX = 0; + _ascaleY = sqrt(rb * rb + rd * rd); + _ashearY = 0; + _arotation = 90 - MathUtil::atan2(rd, rb) * RadDeg; + } + } } diff --git a/spine-cpp/spine-cpp/src/spine/MathUtil.cpp b/spine-cpp/spine-cpp/src/spine/MathUtil.cpp new file mode 100644 index 000000000..ddcde2f1e --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/MathUtil.cpp @@ -0,0 +1,110 @@ +/****************************************************************************** +* Spine Runtimes Software License v2.5 +* +* Copyright (c) 2013-2016, Esoteric Software +* All rights reserved. +* +* You are granted a perpetual, non-exclusive, non-sublicensable, and +* non-transferable license to use, install, execute, and perform the Spine +* Runtimes software and derivative works solely for personal or internal +* use. Without the written permission of Esoteric Software (see Section 2 of +* the Spine Software License Agreement), you may not (a) modify, translate, +* adapt, or develop new applications using the Spine Runtimes or otherwise +* create derivative works or improvements of the Spine Runtimes or (b) remove, +* delete, alter, or obscure any trademarks or any copyright, trademark, patent, +* or other intellectual property or proprietary rights notices on or in the +* Software, including any copy thereof. Redistributions in binary or source +* form must include this license and terms. +* +* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +#include + +namespace Spine +{ + float MathUtil::SIN_TABLE[SIN_COUNT] = {0.0f}; + + MathUtil::MathUtil() + { + for (int i = 0; i < SIN_COUNT; ++i) + { + SIN_TABLE[i] = (float)sin((i + 0.5f) / SIN_COUNT * RadFull); + } + + for (int i = 0; i < 360; i += 90) + { + SIN_TABLE[(int)(i * DegToIndex) & SIN_MASK] = (float)sin(i * DegRad); + } + } + + /// Returns the sine in radians from a lookup table. + float MathUtil::sin(float radians) + { + return SIN_TABLE[(int)(radians * RadToIndex) & SIN_MASK]; + } + + /// Returns the cosine in radians from a lookup table. + float MathUtil::cos(float radians) + { + return SIN_TABLE[(int)((radians + SPINE_PI / 2) * RadToIndex) & SIN_MASK]; + } + + /// Returns the sine in radians from a lookup table. + float MathUtil::sinDeg(float degrees) + { + return SIN_TABLE[(int)(degrees * DegToIndex) & SIN_MASK]; + } + + /// Returns the cosine in radians from a lookup table. + float MathUtil::cosDeg(float degrees) + { + return SIN_TABLE[(int)((degrees + 90) * DegToIndex) & SIN_MASK]; + } + + /// Returns atan2 in radians, faster but less accurate than Math.Atan2. Average error of 0.00231 radians (0.1323 + /// degrees), largest error of 0.00488 radians (0.2796 degrees). + float MathUtil::atan2(float y, float x) + { + if (areFloatsPracticallyEqual(x, 0.0f)) + { + if (y > 0.0f) + { + return SPINE_PI / 2; + } + + if (areFloatsPracticallyEqual(y, 0.0f)) + { + return 0.0f; + } + + return -SPINE_PI / 2; + } + + float atan, z = y / x; + + if (fabs(z) < 1.0f) + { + atan = z / (1.0f + 0.28f * z * z); + if (x < 0.0f) + { + return atan + (y < 0.0f ? -SPINE_PI : SPINE_PI); + } + + return atan; + } + + atan = SPINE_PI / 2 - z / (z * z + 0.28f); + + return y < 0.0f ? atan - SPINE_PI : atan; + } +} From af243b49224fef7b5c34b5e2c3405734f93b9187 Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Mon, 16 Oct 2017 17:13:37 -0400 Subject: [PATCH 13/83] Return pair just like unordered_map --- spine-cpp/spine-cpp/include/spine/HashMap.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/spine-cpp/spine-cpp/include/spine/HashMap.h b/spine-cpp/spine-cpp/include/spine/HashMap.h index 466970ca5..e159e4d4a 100755 --- a/spine-cpp/spine-cpp/include/spine/HashMap.h +++ b/spine-cpp/spine-cpp/include/spine/HashMap.h @@ -89,7 +89,7 @@ namespace Spine Entry* _entry; }; - HashMap(int capacity) : _capacity(capacity), _hashFunction(), _header(), _trailer() + HashMap(size_t capacity) : _capacity(capacity), _hashFunction(), _header(), _trailer() { _hashTable = new Entry[capacity]; for (int i = 0; i < _capacity; ++i) @@ -136,13 +136,13 @@ namespace Spine return Iterator(_header); } - Iterator insert(const K& key, const V& value) + std::pair insert(const K& key, const V& value) { Iterator iter = find(key); if (iter._entry != &_trailer) { - return Iterator(&_trailer); + return std::make_pair(iter, false); } size_t index = hash(key); @@ -162,7 +162,7 @@ namespace Spine entry->next = &_trailer; _trailer.prev = entry; - return Iterator(entry); + return std::make_pair(Iterator(entry), true); } if (_hashTable[index].next == NULL) @@ -198,7 +198,7 @@ namespace Spine entry->prev->next = entry; } - return Iterator(entry); + return std::make_pair(Iterator(entry), true); } if (index == hash(_header.next->_key)) @@ -218,7 +218,7 @@ namespace Spine _hashTable[index].next = entry; } - return Iterator(entry); + return std::make_pair(Iterator(entry), true); } Iterator find(const K& key) @@ -336,7 +336,7 @@ namespace Spine }; const H _hashFunction; - const int _capacity; + const size_t _capacity; Entry* _hashTable; Entry _header; Entry _trailer; From 072ada4c5cb4eeafc2d38d40084fe80d08b7d84d Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Tue, 17 Oct 2017 18:05:43 -0400 Subject: [PATCH 14/83] wip --- spine-cpp/spine-cpp/include/spine/Bone.h | 6 + .../spine-cpp/include/spine/ContainerUtil.h | 73 ++ spine-cpp/spine-cpp/include/spine/HashMap.h | 10 +- spine-cpp/spine-cpp/include/spine/MathUtil.h | 2 + spine-cpp/spine-cpp/include/spine/RTTI.h | 75 ++ spine-cpp/spine-cpp/include/spine/Skeleton.h | 765 ++--------------- spine-cpp/spine-cpp/src/spine/Bone.cpp | 25 + .../spine-cpp/src/spine/IkConstraintData.cpp | 2 +- .../src/spine/PathConstraintData.cpp | 2 +- spine-cpp/spine-cpp/src/spine/RTTI.cpp | 71 ++ spine-cpp/spine-cpp/src/spine/Skeleton.cpp | 780 +++++++++++++++++- spine-cpp/spine-cpp/src/spine/Skin.cpp | 4 +- spine-cpp/spine-cpp/src/spine/Slot.cpp | 6 +- .../src/spine/TransformConstraintData.cpp | 2 +- 14 files changed, 1132 insertions(+), 691 deletions(-) create mode 100644 spine-cpp/spine-cpp/include/spine/ContainerUtil.h create mode 100644 spine-cpp/spine-cpp/include/spine/RTTI.h create mode 100644 spine-cpp/spine-cpp/src/spine/RTTI.cpp diff --git a/spine-cpp/spine-cpp/include/spine/Bone.h b/spine-cpp/spine-cpp/include/spine/Bone.h index 9cc0b5d48..1657b74a9 100644 --- a/spine-cpp/spine-cpp/include/spine/Bone.h +++ b/spine-cpp/spine-cpp/include/spine/Bone.h @@ -50,6 +50,10 @@ namespace Spine friend class RotateTimeline; public: + static void setYDown(bool inValue); + + static bool isYDown(); + /// @param parent May be null. Bone(BoneData& data, Skeleton& skeleton, Bone* parent); @@ -160,6 +164,8 @@ namespace Spine float getWorldScaleY(); private: + static bool yDown; + BoneData& _data; Skeleton& _skeleton; Bone* _parent; diff --git a/spine-cpp/spine-cpp/include/spine/ContainerUtil.h b/spine-cpp/spine-cpp/include/spine/ContainerUtil.h new file mode 100644 index 000000000..33156e7ef --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/ContainerUtil.h @@ -0,0 +1,73 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Attachment_h +#define Spine_Attachment_h + +#include +#include + +namespace Spine +{ + class ContainerUtil + { + public: + template + static void cleanUpSimpleArrayOfPointers(SimpleArray& items) + { + for (size_t i = 0; i < items.size(); ) + { + T* item = items[i]; + delete item; + + items.erase(i); + } + } + + template + static void cleanUpHashMapOfPointers(HashMap& hashMap) + { + for (typename HashMap::Iterator i = hashMap.begin(); i != hashMap.end(); ) + { + delete i.second(); + + i = hashMap.erase(i); + } + } + + private: + // ctor, copy ctor, and assignment should be private in a Singleton + ContainerUtil(); + ContainerUtil(const ContainerUtil&); + ContainerUtil& operator=(const ContainerUtil&); + }; +} + +#endif /* defined(__noctisgames__ContainerUtil__) */ diff --git a/spine-cpp/spine-cpp/include/spine/HashMap.h b/spine-cpp/spine-cpp/include/spine/HashMap.h index e159e4d4a..0eaff11df 100755 --- a/spine-cpp/spine-cpp/include/spine/HashMap.h +++ b/spine-cpp/spine-cpp/include/spine/HashMap.h @@ -147,7 +147,7 @@ namespace Spine size_t index = hash(key); - Entry* entry = new Entry; + Entry* entry = new Entry(); entry->_key = key; entry->_value = value; @@ -240,10 +240,12 @@ namespace Spine return Iterator(&_trailer); } - void erase(Iterator pos) + Iterator erase(Iterator pos) { if (pos._entry != &_header && pos._entry != &_trailer) { + Entry* next = pos._entry->next; + size_t index = hash(pos._entry->_key); if (_hashTable[index].next == pos._entry && _hashTable[index].prev == pos._entry) @@ -310,7 +312,11 @@ namespace Spine } _hashSize--; + + return Iterator(next); } + + return Iterator(&_trailer); } V operator[](const K& key) diff --git a/spine-cpp/spine-cpp/include/spine/MathUtil.h b/spine-cpp/spine-cpp/include/spine/MathUtil.h index 0eeb27f2c..a87a42d04 100644 --- a/spine-cpp/spine-cpp/include/spine/MathUtil.h +++ b/spine-cpp/spine-cpp/include/spine/MathUtil.h @@ -45,6 +45,8 @@ #define DegFull 360 #define RadToIndex SIN_COUNT / RadFull #define DegToIndex SIN_COUNT / DegFull +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) namespace Spine { diff --git a/spine-cpp/spine-cpp/include/spine/RTTI.h b/spine-cpp/spine-cpp/include/spine/RTTI.h new file mode 100644 index 000000000..79f413efa --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/RTTI.h @@ -0,0 +1,75 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_RTTI_h +#define Spine_RTTI_h + +#include + +namespace Spine +{ + class RTTI + { + public: + RTTI(const std::string& className); + + RTTI(const std::string& className, const RTTI& baseRTTI); + + const std::string& getClassName() const; + + bool isExactly(const RTTI& rtti) const; + + bool derivesFrom(const RTTI& rtti) const; + + private: + // Prevent copying + RTTI(const RTTI& obj); + RTTI& operator=(const RTTI& obj); + + const std::string m_className; + const RTTI *m_pBaseRTTI; + }; +} + +#define RTTI_DECL \ +public: \ +static const Spine::RTTI rtti; \ +virtual const Spine::RTTI& getRTTI(); + +#define RTTI_IMPL_NOPARENT(name) \ +const Spine::RTTI name::rtti(#name); \ +const Spine::RTTI& name::getRTTI() { return rtti; } + +#define RTTI_IMPL(name,parent) \ +const Spine::RTTI name::rtti(#name, parent::rtti); \ +const Spine::RTTI& name::getRTTI() { return rtti; } + +#endif /* Spine_RTTI_h */ + diff --git a/spine-cpp/spine-cpp/include/spine/Skeleton.h b/spine-cpp/spine-cpp/include/spine/Skeleton.h index 93ecaecc8..99022c939 100644 --- a/spine-cpp/spine-cpp/include/spine/Skeleton.h +++ b/spine-cpp/spine-cpp/include/spine/Skeleton.h @@ -32,8 +32,10 @@ #define Spine_Skeleton_h #include +#include #include +#include // std::numeric_limits namespace Spine { @@ -45,739 +47,142 @@ namespace Spine class PathConstraint; class TransformConstraint; class Skin; + class Attachment; class Skeleton { public: - SkeletonData* getData(); - SimpleArray getBones(); - SimpleArray getUpdateCacheList(); - SimpleArray getSlots(); - SimpleArray getDrawOrder(); - SimpleArray getIkConstraints(); - SimpleArray getPathConstraints(); - SimpleArray getTransformConstraints(); - - Skin* getSkin { get { return skin; } set { skin = value; } } - float getR { get { return r; } set { r = value; } } - float getG { get { return g; } set { g = value; } } - float getB { get { return b; } set { b = value; } } - float getA { get { return a; } set { a = value; } } - float getTime { get { return time; } set { time = value; } } - float getX { get { return x; } set { x = value; } } - float getY { get { return y; } set { y = value; } } - bool getFlipX { get { return flipX; } set { flipX = value; } } - bool getFlipY { get { return flipY; } set { flipY = value; } } - - Bone* getRootBone() - { - return _bones.size() == 0 ? nullptr : _bones.at(0); - //get { return bones.Count == 0 ? null : bones.Items[0]; } - } - - Skeleton(const SkeletonData& data) - { - if (data == null) - { - throw new ArgumentNullException("data", "data cannot be null."); - } - - this.data = data; - - bones = new SimpleArray(data.bones.Count); - foreach (BoneData boneData in data.bones) - { - Bone bone; - if (boneData.parent == null) - { - bone = new Bone(boneData, this, null); - } - else - { - Bone parent = bones.Items[boneData.parent.index]; - bone = new Bone(boneData, this, parent); - parent.children.Add(bone); - } - bones.Add(bone); - } - - slots = new SimpleArray(data.slots.Count); - drawOrder = new SimpleArray(data.slots.Count); - foreach (SlotData slotData in data.slots) - { - Bone bone = bones.Items[slotData.boneData.index]; - Slot slot = new Slot(slotData, bone); - slots.Add(slot); - drawOrder.Add(slot); - } - - ikConstraints = new SimpleArray(data.ikConstraints.Count); - foreach (IkConstraintData ikConstraintData in data.ikConstraints) - ikConstraints.Add(new IkConstraint(ikConstraintData, this)); - - transformConstraints = new SimpleArray(data.transformConstraints.Count); - foreach (TransformConstraintData transformConstraintData in data.transformConstraints) - transformConstraints.Add(new TransformConstraint(transformConstraintData, this)); - - pathConstraints = new SimpleArray (data.pathConstraints.Count); - foreach (PathConstraintData pathConstraintData in data.pathConstraints) - pathConstraints.Add(new PathConstraint(pathConstraintData, this)); - - updateCache(); - updateWorldTransform(); - } - - ~Skeleton() - { - // TODO - } + Skeleton(SkeletonData& data); /// Caches information about bones and constraints. Must be called if bones, constraints or weighted path attachments are added /// or removed. - void updateCache() - { - SimpleArray updateCache = this.updateCache; - updateCache.Clear(); - this.updateCacheReset.Clear(); - - SimpleArray bones = this.bones; - for (int i = 0, n = bones.Count; i < n; i++) - { - bones.Items[i].sorted = false; - } - - SimpleArray ikConstraints = this.ikConstraints; - var transformConstraints = this.transformConstraints; - var pathConstraints = this.pathConstraints; - int ikCount = IkConstraints.Count, transformCount = transformConstraints.Count, pathCount = pathConstraints.Count; - int constraintCount = ikCount + transformCount + pathCount; - //outer: - for (int i = 0; i < constraintCount; i++) - { - for (int ii = 0; ii < ikCount; ii++) - { - IkConstraint constraint = ikConstraints.Items[ii]; - if (constraint.data.order == i) - { - sortIkConstraint(constraint); - goto continue_outer; //continue outer; - } - } - for (int ii = 0; ii < transformCount; ii++) - { - TransformConstraint constraint = transformConstraints.Items[ii]; - if (constraint.data.order == i) - { - sortTransformConstraint(constraint); - goto continue_outer; //continue outer; - } - } - for (int ii = 0; ii < pathCount; ii++) - { - PathConstraint constraint = pathConstraints.Items[ii]; - if (constraint.data.order == i) - { - sortPathConstraint(constraint); - goto continue_outer; //continue outer; - } - } - continue_outer: {} - } - - for (int i = 0, n = bones.Count; i < n; i++) - { - sortBone(bones.Items[i]); - } - } + void updateCache(); - /// updates the world transform for each bone and applies constraints. - void updateWorldTransform() - { - var updateCacheReset = this.updateCacheReset; - var updateCacheResetItems = updateCacheReset.Items; - for (int i = 0, n = updateCacheReset.Count; i < n; i++) - { - Bone bone = updateCacheResetItems[i]; - bone.ax = bone.x; - bone.ay = bone.y; - bone.arotation = bone.rotation; - bone.ascaleX = bone.scaleX; - bone.ascaleY = bone.scaleY; - bone.ashearX = bone.shearX; - bone.ashearY = bone.shearY; - bone.appliedValid = true; - } - - var updateItems = this.updateCache.Items; - for (int i = 0, n = updateCache.Count; i < n; i++) - { - updateItems[i].update(); - } - } + /// Updates the world transform for each bone and applies constraints. + void updateWorldTransform(); /// Sets the bones, constraints, and slots to their setup pose values. - void setToSetupPose() - { - setBonesToSetupPose(); - setSlotsToSetupPose(); - } + void setToSetupPose(); /// Sets the bones and constraints to their setup pose values. - void setBonesToSetupPose() - { - var bonesItems = this.bones.Items; - for (int i = 0, n = bones.Count; i < n; i++) - { - bonesItems[i].setToSetupPose(); - } - - var ikConstraintsItems = this.ikConstraints.Items; - for (int i = 0, n = ikConstraints.Count; i < n; i++) - { - IkConstraint constraint = ikConstraintsItems[i]; - constraint.bendDirection = constraint.data.bendDirection; - constraint.mix = constraint.data.mix; - } - - var transformConstraintsItems = this.transformConstraints.Items; - for (int i = 0, n = transformConstraints.Count; i < n; i++) - { - TransformConstraint constraint = transformConstraintsItems[i]; - TransformConstraintData constraintData = constraint.data; - constraint.rotateMix = constraintData.rotateMix; - constraint.translateMix = constraintData.translateMix; - constraint.scaleMix = constraintData.scaleMix; - constraint.shearMix = constraintData.shearMix; - } - - var pathConstraintItems = this.pathConstraints.Items; - for (int i = 0, n = pathConstraints.Count; i < n; i++) - { - PathConstraint constraint = pathConstraintItems[i]; - PathConstraintData constraintData = constraint.data; - constraint.position = constraintData.position; - constraint.spacing = constraintData.spacing; - constraint.rotateMix = constraintData.rotateMix; - constraint.translateMix = constraintData.translateMix; - } - } + void setBonesToSetupPose(); - void setSlotsToSetupPose() - { - var slots = this.slots; - var slotsItems = slots.Items; - drawOrder.Clear(); - - for (int i = 0, n = slots.Count; i < n; i++) - { - drawOrder.Add(slotsItems[i]); - } - - for (int i = 0, n = slots.Count; i < n; i++) - { - slotsItems[i].setToSetupPose(); - } - } + void setSlotsToSetupPose(); - /// May be null. - Bone findBone(std::string boneName) - { - if (boneName == null) - { - throw new ArgumentNullException("boneName", "boneName cannot be null."); - } - - var bones = this.bones; - var bonesItems = bones.Items; - for (int i = 0, n = bones.Count; i < n; i++) - { - Bone bone = bonesItems[i]; - if (bone.data.name == boneName) - { - return bone; - } - } - - return null; - } + /// @return May be NULL. + Bone* findBone(std::string boneName); - /// -1 if the bone was not found. - int findBoneIndex(std::string boneName) - { - if (boneName == null) throw new ArgumentNullException("boneName", "boneName cannot be null."); - var bones = this.bones; - var bonesItems = bones.Items; - for (int i = 0, n = bones.Count; i < n; i++) - { - if (bonesItems[i].data.name == boneName) - { - return i; - } - } - - return -1; - } + /// @return -1 if the bone was not found. + int findBoneIndex(std::string boneName); - /// May be null. - Slot findSlot(std::string slotName) - { - if (slotName == null) - { - throw new ArgumentNullException("slotName", "slotName cannot be null."); - } - - var slots = this.slots; - var slotsItems = slots.Items; - for (int i = 0, n = slots.Count; i < n; i++) - { - Slot slot = slotsItems[i]; - if (slot.data.name == slotName) - { - return slot; - } - } - - return null; - } + /// @return May be NULL. + Slot* findSlot(std::string slotName); - /// -1 if the bone was not found. - int findSlotIndex(std::string slotName) - { - if (slotName == null) - { - throw new ArgumentNullException("slotName", "slotName cannot be null."); - } - - var slots = this.slots; - var slotsItems = slots.Items; - for (int i = 0, n = slots.Count; i < n; i++) - { - if (slotsItems[i].data.name.Equals(slotName)) - { - return i; - } - } - - return -1; - } + /// @return -1 if the bone was not found. + int findSlotIndex(std::string slotName); /// Sets a skin by name (see setSkin). - void setSkin(std::string skinName) - { - Skin foundSkin = data.FindSkin(skinName); - if (foundSkin == null) - { - throw new ArgumentException("Skin not found: " + skinName, "skinName"); - } - - setSkin(foundSkin); - } + void setSkin(std::string skinName); + /// 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. + /// After changing the skin, the visible attachments can be reset to those attached in the setup pose by calling + /// See Skeleton::setSlotsToSetupPose() + /// Also, often AnimationState::Apply(Skeleton&) is called before the next time the + /// skeleton is rendered to allow any attachment keys in the current animation(s) to hide or show attachments from the new skin. /// - /// 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. - /// After changing the skin, the visible attachments can be reset to those attached in the setup pose by calling - /// . - /// Also, often is called before the next time the - /// skeleton is rendered to allow any attachment keys in the current animation(s) to hide or show attachments from the new skin. - /// - /// @param newSkin May be null. - void setSkin(Skin newSkin) - { - if (newSkin != null) - { - if (skin != null) - { - newSkin.AttachAll(this, skin); - } - else - { - SimpleArray slots = this.slots; - for (int i = 0, n = slots.Count; i < n; i++) - { - Slot slot = slots.Items[i]; - std::string name = slot.data.attachmentName; - if (name != null) - { - Attachment attachment = newSkin.getAttachment(i, name); - if (attachment != null) - { - slot.Attachment = attachment; - } - } - } - } - } - - skin = newSkin; - } + /// @param newSkin May be NULL. + void setSkin(Skin newSkin); - /// May be null. - Attachment getAttachment(std::string slotName, std::string attachmentName) - { - return getAttachment(data.findSlotIndex(slotName), attachmentName); - } + /// @return May be NULL. + Attachment* getAttachment(std::string slotName, std::string attachmentName); - /// May be null. - Attachment getAttachment(int slotIndex, std::string attachmentName) - { - if (attachmentName == null) - { - throw new ArgumentNullException("attachmentName", "attachmentName cannot be null."); - } - - if (skin != null) - { - Attachment attachment = skin.getAttachment(slotIndex, attachmentName); - if (attachment != null) - { - return attachment; - } - } - - return data.defaultSkin != null ? data.defaultSkin.getAttachment(slotIndex, attachmentName) : null; - } + /// @return May be NULL. + Attachment* getAttachment(int slotIndex, std::string attachmentName); - /// @param attachmentName May be null. - void setAttachment(std::string slotName, std::string attachmentName) - { - if (slotName == null) - { - throw new ArgumentNullException("slotName", "slotName cannot be null."); - } - - SimpleArray slots = this.slots; - for (int i = 0, n = slots.Count; i < n; i++) - { - Slot slot = slots.Items[i]; - if (slot.data.name == slotName) - { - Attachment attachment = null; - if (attachmentName != null) - { - attachment = getAttachment(i, attachmentName); - if (attachment == null) - { - throw new Exception("Attachment not found: " + attachmentName + ", for slot: " + slotName); - } - } - - slot.Attachment = attachment; - - return; - } - } - - throw new Exception("Slot not found: " + slotName); - } + /// @param attachmentName May be empty. + void setAttachment(std::string slotName, std::string attachmentName); - /// May be null. - IkConstraint findIkConstraint(std::string constraintName) - { - if (constraintName == null) - { - throw new ArgumentNullException("constraintName", "constraintName cannot be null."); - } - - SimpleArray ikConstraints = this.ikConstraints; - for (int i = 0, n = ikConstraints.Count; i < n; i++) - { - IkConstraint ikConstraint = ikConstraints.Items[i]; - if (ikConstraint.data.name == constraintName) return ikConstraint; - } - - return null; - } + /// @return May be NULL. + IkConstraint* findIkConstraint(std::string constraintName); - /// May be null. - TransformConstraint findTransformConstraint(std::string constraintName) - { - if (constraintName == null) - { - throw new ArgumentNullException("constraintName", "constraintName cannot be null."); - } - - SimpleArray transformConstraints = this.transformConstraints; - for (int i = 0, n = transformConstraints.Count; i < n; i++) - { - TransformConstraint transformConstraint = transformConstraints.Items[i]; - if (transformConstraint.data.name == constraintName) return transformConstraint; - } - - return null; - } + /// @return May be NULL. + TransformConstraint* findTransformConstraint(std::string constraintName); - /// May be null. - PathConstraint findPathConstraint(std::string constraintName) - { - if (constraintName == null) - { - throw new ArgumentNullException("constraintName", "constraintName cannot be null."); - } - - SimpleArray pathConstraints = this.pathConstraints; - for (int i = 0, n = pathConstraints.Count; i < n; i++) - { - PathConstraint constraint = pathConstraints.Items[i]; - if (constraint.data.name.Equals(constraintName)) return constraint; - } - - return null; - } + /// @return May be NULL. + PathConstraint* findPathConstraint(std::string constraintName); - void update(float delta) - { - time += delta; - } + void update(float delta); /// Returns the axis aligned bounding box (AABB) of the region and mesh attachments for the current pose. /// @param x The horizontal distance between the skeleton origin and the left side of the AABB. /// @param y The vertical distance between the skeleton origin and the bottom side of the AABB. /// @param width The width of the AABB /// @param height The height of the AABB. - /// @param vertexBuffer Reference to hold a float[]. May be a null reference. This method will assign it a new float[] with the appropriate size as needed. - void getBounds(out float x, out float y, out float width, out float height, ref float[] vertexBuffer) - { - float[] temp = vertexBuffer; - temp = temp ?? new float[8]; - var drawOrderItems = this.drawOrder.Items; - float minX = int.MaxValue, minY = int.MaxValue, maxX = int.MinValue, maxY = int.MinValue; - for (int i = 0, n = this.drawOrder.Count; i < n; i++) - { - Slot slot = drawOrderItems[i]; - int verticesLength = 0; - float[] vertices = null; - Attachment attachment = slot.attachment; - var regionAttachment = attachment as RegionAttachment; - if (regionAttachment != null) - { - verticesLength = 8; - vertices = temp; - if (vertices.Length < 8) vertices = temp = new float[8]; - regionAttachment.ComputeWorldVertices(slot.bone, temp, 0); - } - else - { - var meshAttachment = attachment as MeshAttachment; - if (meshAttachment != null) - { - MeshAttachment mesh = meshAttachment; - verticesLength = mesh.WorldVerticesLength; - vertices = temp; - if (vertices.Length < verticesLength) - { - vertices = temp = new float[verticesLength]; - } - - mesh.ComputeWorldVertices(slot, 0, verticesLength, temp, 0); - } - } - - if (vertices != null) - { - for (int ii = 0; ii < verticesLength; ii += 2) - { - float vx = vertices[ii], vy = vertices[ii + 1]; - minX = Math.Min(minX, vx); - minY = Math.Min(minY, vy); - maxX = Math.Max(maxX, vx); - maxY = Math.Max(maxY, vy); - } - } - } - - x = minX; - y = minY; - width = maxX - minX; - height = maxY - minY; - vertexBuffer = temp; - } + /// @param vertexBuffer Reference to hold a SimpleArray of floats. This method will assign it with new floats as needed. + void getBounds(float& outX, float& outY, float& outWidth, float& outHeight, SimpleArray& vertexBuffer); + + Bone* getRootBone(); + + const SkeletonData& getData(); + SimpleArray& getBones(); + SimpleArray& getUpdateCacheList(); + SimpleArray& getSlots(); + SimpleArray& getDrawOrder(); + SimpleArray& getIkConstraints(); + SimpleArray& getPathConstraints(); + SimpleArray& getTransformConstraints(); + + Skin* getSkin(); + void setSkin(Skin* inValue); + float getR(); + void setR(float inValue); + float getG(); + void setG(float inValue); + float getB(); + void setB(float inValue); + float getA(); + void setA(float inValue); + float getTime(); + void setTime(float inValue); + float getX(); + void setX(float inValue); + float getY(); + void setY(float inValue); + bool getFlipX(); + void setFlipX(float inValue); + bool getFlipY(); + void setFlipY(float inValue); private: - SkeletonData* _data; + const SkeletonData& _data; SimpleArray _bones; SimpleArray _slots; SimpleArray _drawOrder; SimpleArray _ikConstraints; SimpleArray _transformConstraints; SimpleArray _pathConstraints; - SimpleArray _updateCache = new SimpleArray(); - SimpleArray _updateCacheReset = new SimpleArray(); - Skin _skin; + SimpleArray _updateCache; + SimpleArray _updateCacheReset; + Skin* _skin; float _r = 1, _g = 1, _b = 1, _a = 1; float _time; bool _flipX, _flipY; float _x, _y; - void sortIkConstraint(IkConstraint constraint) - { - Bone target = constraint.target; - sortBone(target); - - var constrained = constraint.bones; - Bone parent = constrained.Items[0]; - sortBone(parent); - - if (constrained.Count > 1) - { - Bone child = constrained.Items[constrained.Count - 1]; - if (!updateCache.Contains(child)) - { - updateCacheReset.Add(child); - } - } - - updateCache.Add(constraint); - - sortReset(parent.children); - constrained.Items[constrained.Count - 1].sorted = true; - } + void sortIkConstraint(IkConstraint constraint); - void sortPathConstraint(PathConstraint constraint) - { - Slot slot = constraint.target; - int slotIndex = slot.data.index; - Bone slotBone = slot.bone; - if (skin != null) - { - sortPathConstraintAttachment(skin, slotIndex, slotBone); - } - - if (data.defaultSkin != null && data.defaultSkin != skin) - { - sortPathConstraintAttachment(data.defaultSkin, slotIndex, slotBone); - } - - for (int ii = 0, nn = data.skins.Count; ii < nn; ii++) - { - sortPathConstraintAttachment(data.skins.Items[ii], slotIndex, slotBone); - } - - Attachment attachment = slot.attachment; - if (attachment is PathAttachment) - { - sortPathConstraintAttachment(attachment, slotBone); - } - - var constrained = constraint.bones; - int boneCount = constrained.Count; - for (int i = 0; i < boneCount; i++) - { - sortBone(constrained.Items[i]); - } - - updateCache.Add(constraint); - - for (int i = 0; i < boneCount; i++) - { - sortReset(constrained.Items[i].children); - } - - for (int i = 0; i < boneCount; i++) - { - constrained.Items[i].sorted = true; - } - } + void sortPathConstraint(PathConstraint constraint); - void sortTransformConstraint(TransformConstraint constraint) - { - sortBone(constraint.target); - - var constrained = constraint.bones; - int boneCount = constrained.Count; - if (constraint.data.local) - { - for (int i = 0; i < boneCount; i++) - { - Bone child = constrained.Items[i]; - sortBone(child.parent); - if (!updateCache.Contains(child)) - { - updateCacheReset.Add(child); - } - } - } - else - { - for (int i = 0; i < boneCount; i++) - { - sortBone(constrained.Items[i]); - } - } - - updateCache.Add(constraint); - - for (int i = 0; i < boneCount; i++) - { - sortReset(constrained.Items[i].children); - } - for (int i = 0; i < boneCount; i++) - { - constrained.Items[i].sorted = true; - } - } + void sortTransformConstraint(TransformConstraint constraint); - void sortPathConstraintAttachment(Skin skin, int slotIndex, Bone slotBone) - { - foreach (var entry in skin.Attachments) - { - if (entry.Key.slotIndex == slotIndex) - { - sortPathConstraintAttachment(entry.Value, slotBone); - } - } - } + void sortPathConstraintAttachment(Skin skin, int slotIndex, Bone slotBone); - void sortPathConstraintAttachment(Attachment attachment, Bone slotBone) - { - if (!(attachment is PathAttachment)) return; - int[] pathBones = ((PathAttachment)attachment).bones; - if (pathBones == null) - { - sortBone(slotBone); - } - else - { - var bones = this.bones; - for (int i = 0, n = pathBones.Length; i < n;) - { - int nn = pathBones[i++]; - nn += i; - while (i < nn) - { - sortBone(bones.Items[pathBones[i++]]); - } - } - } - } + void sortPathConstraintAttachment(Attachment attachment, Bone slotBone); - void sortBone(Bone bone) - { - if (bone.sorted) - { - return; - } - - Bone parent = bone.parent; - if (parent != null) sortBone(parent); - bone.sorted = true; - updateCache.Add(bone); - } + void sortBone(Bone bone); - static void sortReset(SimpleArray& bones) - { - var bonesItems = bones.Items; - for (int i = 0, n = bones.Count; i < n; i++) - { - Bone bone = bonesItems[i]; - if (bone.sorted) - { - sortReset(bone.children); - } - - bone.sorted = false; - } - } + static void sortReset(SimpleArray& bones); }; } diff --git a/spine-cpp/spine-cpp/src/spine/Bone.cpp b/spine-cpp/spine-cpp/src/spine/Bone.cpp index 21b275a6a..1e3882573 100644 --- a/spine-cpp/spine-cpp/src/spine/Bone.cpp +++ b/spine-cpp/spine-cpp/src/spine/Bone.cpp @@ -38,6 +38,18 @@ namespace Spine { + bool Bone::yDown = false; + + void Bone::setYDown(bool inValue) + { + yDown = inValue; + } + + bool Bone::isYDown() + { + return yDown; + } + Bone::Bone(BoneData& data, Skeleton& skeleton, Bone* parent) : Updatable(), _data(data), _skeleton(skeleton), @@ -106,6 +118,13 @@ namespace Spine lb = -lb; } + if (_skeleton.isFlipY() != Bone::isYDown()) + { + y = -y; + lc = -lc; + ld = -ld; + } + _a = la; _b = lb; _c = lc; @@ -224,6 +243,12 @@ namespace Spine _a = -_a; _b = -_b; } + + if (skeleton.isFlipY() != Bone::isYDown()) + { + c = -c; + d = -d; + } } void Bone::setToSetupPose() diff --git a/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp b/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp index 36d16b307..70158d296 100644 --- a/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp +++ b/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp @@ -35,7 +35,7 @@ namespace Spine IkConstraintData::IkConstraintData(std::string name) : _name(name), _order(0), - _target(nullptr), + _target(NULL), _bendDirection(1), _mix(1) { diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraintData.cpp b/spine-cpp/spine-cpp/src/spine/PathConstraintData.cpp index a9e1d07ef..9a82bcbf5 100644 --- a/spine-cpp/spine-cpp/src/spine/PathConstraintData.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathConstraintData.cpp @@ -40,7 +40,7 @@ namespace Spine PathConstraintData::PathConstraintData(std::string name) : _name(name), _order(0), - _target(nullptr), + _target(NULL), _positionMode(PositionMode_Fixed), _spacingMode(SpacingMode_Length), _rotateMode(RotateMode_Tangent), diff --git a/spine-cpp/spine-cpp/src/spine/RTTI.cpp b/spine-cpp/spine-cpp/src/spine/RTTI.cpp new file mode 100644 index 000000000..3905c9d6b --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/RTTI.cpp @@ -0,0 +1,71 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include + +namespace Spine +{ + RTTI::RTTI(const std::string& className) : m_className(className), m_pBaseRTTI(nullptr) + { + // Empty + } + + RTTI::RTTI(const std::string& className, const RTTI& baseRTTI) : m_className(className), m_pBaseRTTI(&baseRTTI) + { + // Empty + } + + const std::string& RTTI::getClassName() const + { + return m_className; + } + + bool RTTI::isExactly(const RTTI& rtti) const + { + return (this == &rtti); + } + + bool RTTI::derivesFrom(const RTTI& rtti) const + { + const RTTI * pCompare = this; + + while (pCompare) + { + if (pCompare == &rtti) + { + return true; + } + + pCompare = pCompare->m_pBaseRTTI; + } + + return false; + } +} diff --git a/spine-cpp/spine-cpp/src/spine/Skeleton.cpp b/spine-cpp/spine-cpp/src/spine/Skeleton.cpp index f8e34294a..ad4b6976d 100644 --- a/spine-cpp/spine-cpp/src/spine/Skeleton.cpp +++ b/spine-cpp/spine-cpp/src/spine/Skeleton.cpp @@ -38,8 +38,786 @@ #include #include #include +#include namespace Spine { - // TODO + Skeleton::Skeleton(SkeletonData& data) : _data(data) + { + _bones.reserve(_data->getBones().size()); + bones = new SimpleArray(data.bones.Count); + foreach (BoneData boneData in data.bones) + { + Bone bone; + if (boneData.parent == NULL) + { + bone = new Bone(boneData, this, NULL); + } + else + { + Bone parent = bones.Items[boneData.parent.index]; + bone = new Bone(boneData, this, parent); + parent.children.Add(bone); + } + + bones.Add(bone); + } + + slots = new SimpleArray(data.slots.Count); + drawOrder = new SimpleArray(data.slots.Count); + foreach (SlotData slotData in data.slots) + { + Bone bone = bones.Items[slotData.boneData.index]; + Slot slot = new Slot(slotData, bone); + slots.Add(slot); + drawOrder.Add(slot); + } + + ikConstraints = new SimpleArray(data.ikConstraints.Count); + foreach (IkConstraintData ikConstraintData in data.ikConstraints) + ikConstraints.Add(new IkConstraint(ikConstraintData, this)); + + transformConstraints = new SimpleArray(data.transformConstraints.Count); + foreach (TransformConstraintData transformConstraintData in data.transformConstraints) + transformConstraints.Add(new TransformConstraint(transformConstraintData, this)); + + pathConstraints = new SimpleArray (data.pathConstraints.Count); + foreach (PathConstraintData pathConstraintData in data.pathConstraints) + pathConstraints.Add(new PathConstraint(pathConstraintData, this)); + + updateCache(); + updateWorldTransform(); + } + + void Skeleton::updateCache() + { + SimpleArray updateCache = _updateCache; + updateCache.Clear(); + _updateCacheReset.Clear(); + + SimpleArray bones = _bones; + for (int i = 0, n = bones.Count; i < n; ++i) + { + bones.Items[i].sorted = false; + } + + SimpleArray ikConstraints = _ikConstraints; + var transformConstraints = _transformConstraints; + var pathConstraints = _pathConstraints; + int ikCount = IkConstraints.Count, transformCount = transformConstraints.Count, pathCount = pathConstraints.Count; + int constraintCount = ikCount + transformCount + pathCount; + //outer: + for (int i = 0; i < constraintCount; ++i) + { + for (int ii = 0; ii < ikCount; ++ii) + { + IkConstraint constraint = ikConstraints.Items[ii]; + if (constraint.data.order == i) + { + sortIkConstraint(constraint); + goto continue_outer; //continue outer; + } + } + for (int ii = 0; ii < transformCount; ++ii) + { + TransformConstraint constraint = transformConstraints.Items[ii]; + if (constraint.data.order == i) + { + sortTransformConstraint(constraint); + goto continue_outer; //continue outer; + } + } + for (int ii = 0; ii < pathCount; ++ii) + { + PathConstraint constraint = pathConstraints.Items[ii]; + if (constraint.data.order == i) + { + sortPathConstraint(constraint); + goto continue_outer; //continue outer; + } + } + continue_outer: {} + } + + for (int i = 0, n = bones.Count; i < n; ++i) + { + sortBone(bones.Items[i]); + } + } + + void Skeleton::updateWorldTransform() + { + var updateCacheReset = _updateCacheReset; + var updateCacheResetItems = updateCacheReset.Items; + for (int i = 0, n = updateCacheReset.Count; i < n; ++i) + { + Bone bone = updateCacheResetItems[i]; + bone.ax = bone.x; + bone.ay = bone.y; + bone.arotation = bone.rotation; + bone.ascaleX = bone.scaleX; + bone.ascaleY = bone.scaleY; + bone.ashearX = bone.shearX; + bone.ashearY = bone.shearY; + bone.appliedValid = true; + } + + var updateItems = _updateCache.Items; + for (int i = 0, n = updateCache.Count; i < n; ++i) + { + updateItems[i].update(); + } + } + + void Skeleton::setToSetupPose() + { + setBonesToSetupPose(); + setSlotsToSetupPose(); + } + + void Skeleton::setBonesToSetupPose() + { + var bonesItems = _bones.Items; + for (int i = 0, n = bones.Count; i < n; ++i) + { + bonesItems[i].setToSetupPose(); + } + + var ikConstraintsItems = _ikConstraints.Items; + for (int i = 0, n = ikConstraints.Count; i < n; ++i) + { + IkConstraint constraint = ikConstraintsItems[i]; + constraint.bendDirection = constraint.data.bendDirection; + constraint.mix = constraint.data.mix; + } + + var transformConstraintsItems = _transformConstraints.Items; + for (int i = 0, n = transformConstraints.Count; i < n; ++i) + { + TransformConstraint constraint = transformConstraintsItems[i]; + TransformConstraintData constraintData = constraint.data; + constraint.rotateMix = constraintData.rotateMix; + constraint.translateMix = constraintData.translateMix; + constraint.scaleMix = constraintData.scaleMix; + constraint.shearMix = constraintData.shearMix; + } + + var pathConstraintItems = _pathConstraints.Items; + for (int i = 0, n = pathConstraints.Count; i < n; ++i) + { + PathConstraint constraint = pathConstraintItems[i]; + PathConstraintData constraintData = constraint.data; + constraint.position = constraintData.position; + constraint.spacing = constraintData.spacing; + constraint.rotateMix = constraintData.rotateMix; + constraint.translateMix = constraintData.translateMix; + } + } + + void Skeleton::setSlotsToSetupPose() + { + var slots = _slots; + var slotsItems = slots.Items; + drawOrder.Clear(); + for (int i = 0, n = slots.Count; i < n; ++i) + { + drawOrder.Add(slotsItems[i]); + } + + for (int i = 0, n = slots.Count; i < n; ++i) + { + slotsItems[i].setToSetupPose(); + } + } + + Bone* Skeleton::findBone(std::string boneName) + { + assert(boneName.length() > 0); + + var bones = _bones; + var bonesItems = bones.Items; + for (int i = 0, n = bones.Count; i < n; ++i) + { + Bone bone = bonesItems[i]; + if (bone.data.name == boneName) + { + return bone; + } + } + + return NULL; + } + + int Skeleton::findBoneIndex(std::string boneName) + { + assert(boneName.length() > 0); + + var bones = _bones; + var bonesItems = bones.Items; + for (int i = 0, n = bones.Count; i < n; ++i) + { + if (bonesItems[i].data.name == boneName) + { + return i; + } + } + + return -1; + } + + Slot* Skeleton::findSlot(std::string slotName) + { + assert(slotName.length() > 0); + + var slots = _slots; + var slotsItems = slots.Items; + for (int i = 0, n = slots.Count; i < n; ++i) + { + Slot slot = slotsItems[i]; + if (slot.data.name == slotName) + { + return slot; + } + } + + return NULL; + } + + int Skeleton::findSlotIndex(std::string slotName) + { + assert(slotName.length() > 0); + + var slots = _slots; + var slotsItems = slots.Items; + for (int i = 0, n = slots.Count; i < n; ++i) + { + if (slotsItems[i].data.name.Equals(slotName)) + { + return i; + } + } + + return -1; + } + + void Skeleton::setSkin(std::string skinName) + { + Skin foundSkin = data.FindSkin(skinName); + + assert(foundSkin != NULL); + + setSkin(foundSkin); + } + + void Skeleton::setSkin(Skin newSkin) + { + if (newSkin != NULL) + { + if (skin != NULL) + { + newSkin.AttachAll(this, skin); + } + else + { + SimpleArray slots = _slots; + for (int i = 0, n = slots.Count; i < n; ++i) + { + Slot slot = slots.Items[i]; + std::string name = slot.data.attachmentName; + if (name != NULL) + { + Attachment attachment = newSkin.getAttachment(i, name); + if (attachment != NULL) + { + slot.Attachment = attachment; + } + } + } + } + } + skin = newSkin; + } + + Attachment* Skeleton::getAttachment(std::string slotName, std::string attachmentName) + { + return getAttachment(data.findSlotIndex(slotName), attachmentName); + } + + Attachment* Skeleton::getAttachment(int slotIndex, std::string attachmentName) + { + assert(attachmentName.length() > 0); + + if (skin != NULL) + { + Attachment attachment = skin.getAttachment(slotIndex, attachmentName); + if (attachment != NULL) + { + return attachment; + } + } + + return data.defaultSkin != NULL ? data.defaultSkin.getAttachment(slotIndex, attachmentName) : NULL; + } + + void Skeleton::setAttachment(std::string slotName, std::string attachmentName) + { + assert(slotName.length() > 0); + + SimpleArray slots = _slots; + for (int i = 0, n = slots.Count; i < n; ++i) + { + Slot slot = slots.Items[i]; + if (slot.data.name == slotName) + { + Attachment attachment = NULL; + if (attachmentName != NULL) + { + attachment = getAttachment(i, attachmentName); + + assert(attachment != NULL); + } + + slot.Attachment = attachment; + + return; + } + } + + printf("Slot not found: %s" + slotName.c_str()); + + assert(false); + } + + IkConstraint* Skeleton::findIkConstraint(std::string constraintName) + { + assert(constraintName.length() > 0); + + SimpleArray ikConstraints = _ikConstraints; + for (int i = 0, n = ikConstraints.Count; i < n; ++i) + { + IkConstraint ikConstraint = ikConstraints.Items[i]; + if (ikConstraint.data.name == constraintName) + { + return ikConstraint; + } + } + return NULL; + } + + TransformConstraint* Skeleton::findTransformConstraint(std::string constraintName) + { + assert(constraintName.length() > 0); + + SimpleArray transformConstraints = _transformConstraints; + for (int i = 0, n = transformConstraints.Count; i < n; ++i) + { + TransformConstraint transformConstraint = transformConstraints.Items[i]; + if (transformConstraint.data.name == constraintName) + { + return transformConstraint; + } + } + + return NULL; + } + + PathConstraint* Skeleton::findPathConstraint(std::string constraintName) + { + assert(constraintName.length() > 0); + + SimpleArray pathConstraints = _pathConstraints; + for (int i = 0, n = pathConstraints.Count; i < n; ++i) + { + PathConstraint constraint = pathConstraints.Items[i]; + if (constraint.data.name.Equals(constraintName)) + { + return constraint; + } + } + + return NULL; + } + + void Skeleton::update(float delta) + { + _time += delta; + } + + void Skeleton::getBounds(float& outX, float& outY, float& outWidth, float& outHeight, SimpleArray& vertexBuffer) + { + float minX = std::numeric_limits::max(); + float minY = std::numeric_limits::max(); + float maxX = std::numeric_limits::min(); + float maxY = std::numeric_limits::min(); + + for (Slot* i = _drawOrder.begin(); i != _drawOrder.end(); ++i) + { + Slot* slot = i; + int verticesLength = 0; + Attachment* attachment = slot->getAttachment(); + + if (attachment != NULL && attachment->getRTTI().derivesFrom(RegionAttachment::rtti)) + { + RegionAttachment* regionAttachment = static_cast(attachment); + + verticesLength = 8; + if (vertexBuffer.size() < 8) + { + vertexBuffer.reserve(8); + } + regionAttachment->computeWorldVertices(slot->getBone(), vertexBuffer, 0); + } + else if (attachment != NULL && attachment->getRTTI().derivesFrom(MeshAttachment::rtti)) + { + MeshAttachment* mesh = static_cast(attachment); + + verticesLength = mesh->getWorldVerticesLength(); + if (vertexBuffer.size() < verticesLength) + { + vertexBuffer.reserve(verticesLength); + } + + mesh->computeWorldVertices(slot, 0, verticesLength, vertexBuffer, 0); + } + + for (int ii = 0; ii < verticesLength; ii += 2) + { + float vx = vertexBuffer[ii]; + float vy = vertexBuffer[ii + 1]; + + minX = MIN(minX, vx); + minY = MIN(minY, vy); + maxX = MAX(maxX, vx); + maxY = MAX(maxY, vy); + } + } + + x = minX; + y = minY; + width = maxX - minX; + height = maxY - minY; + } + + Bone* Skeleton::getRootBone() + { + return _bones.size() == 0 ? NULL : &_bones[0]; + } + + const SkeletonData& Skeleton::getData() + { + return _data; + } + + SimpleArray& Skeleton::getBones() + { + return _bones; + } + + SimpleArray& Skeleton::getUpdateCacheList() + { + return _updateCache; + } + + SimpleArray& Skeleton::getSlots() + { + return _slots; + } + + SimpleArray& Skeleton::getDrawOrder() + { + return _drawOrder; + } + + SimpleArray& Skeleton::getIkConstraints() + { + return _ikConstraints; + } + + SimpleArray& Skeleton::getPathConstraints() + { + return _pathConstraints; + } + + SimpleArray& Skeleton::getTransformConstraints() + { + return _transformConstraints; + } + + Skin* Skeleton::getSkin() + { + return _skin; + } + + void Skeleton::setSkin(Skin* inValue) + { + _skin = inValue; + } + + float Skeleton::getR() + { + return _r; + } + + void Skeleton::setR(float inValue) + { + _r = inValue; + } + + float Skeleton::getG() + { + return _g; + } + + void Skeleton::setG(float inValue) + { + _g = inValue; + } + + float Skeleton::getB() + { + return _b; + } + + void Skeleton::setB(float inValue) + { + _b = inValue; + } + + float Skeleton::getA() + { + return _a; + } + + void Skeleton::setA(float inValue) + { + _a = inValue; + } + + float Skeleton::getTime() + { + return _time; + } + + void Skeleton::setTime(float inValue) + { + _time = inValue; + } + + float Skeleton::getX() + { + return _x; + } + + void Skeleton::setX(float inValue) + { + _x = inValue; + } + + float Skeleton::getY() + { + return _y; + } + + void Skeleton::setY(float inValue) + { + _y = inValue; + } + + bool Skeleton::getFlipX() + { + return _flipX; + } + + void Skeleton::setFlipX(float inValue) + { + _flipX = inValue; + } + + bool Skeleton::getFlipY() + { + return _flipY; + } + + void Skeleton::setFlipY(float inValue) + { + _flipY = inValue; + } + + void Skeleton::sortIkConstraint(IkConstraint constraint) + { + Bone target = constraint.target; + sortBone(target); + + var constrained = constraint.bones; + Bone parent = constrained.Items[0]; + sortBone(parent); + + if (constrained.Count > 1) + { + Bone child = constrained.Items[constrained.Count - 1]; + if (!updateCache.Contains(child)) + { + updateCacheReset.Add(child); + } + } + + updateCache.Add(constraint); + + sortReset(parent.children); + constrained.Items[constrained.Count - 1].sorted = true; + } + + void Skeleton::sortPathConstraint(PathConstraint constraint) + { + Slot slot = constraint.target; + int slotIndex = slot.data.index; + Bone slotBone = slot.bone; + + if (skin != NULL) + { + sortPathConstraintAttachment(skin, slotIndex, slotBone); + } + + if (data.defaultSkin != NULL && data.defaultSkin != skin) + { + sortPathConstraintAttachment(data.defaultSkin, slotIndex, slotBone); + } + + for (int ii = 0, nn = data.skins.Count; ii < nn; ++ii) + { + sortPathConstraintAttachment(data.skins.Items[ii], slotIndex, slotBone); + } + + Attachment attachment = slot.attachment; + if (attachment is PathAttachment) + { + sortPathConstraintAttachment(attachment, slotBone); + } + + var constrained = constraint.bones; + int boneCount = constrained.Count; + for (int i = 0; i < boneCount; ++i) + { + sortBone(constrained.Items[i]); + } + + updateCache.Add(constraint); + + for (int i = 0; i < boneCount; ++i) + { + sortReset(constrained.Items[i].children); + } + + for (int i = 0; i < boneCount; ++i) + { + constrained.Items[i].sorted = true; + } + } + + void Skeleton::sortTransformConstraint(TransformConstraint constraint) + { + sortBone(constraint.target); + + var constrained = constraint.bones; + int boneCount = constrained.Count; + if (constraint.data.local) + { + for (int i = 0; i < boneCount; ++i) + { + Bone child = constrained.Items[i]; + sortBone(child.parent); + if (!updateCache.Contains(child)) + { + updateCacheReset.Add(child); + } + } + } + else + { + for (int i = 0; i < boneCount; ++i) + { + sortBone(constrained.Items[i]); + } + } + + updateCache.Add(constraint); + + for (int i = 0; i < boneCount; ++i) + { + sortReset(constrained.Items[i].children); + } + for (int i = 0; i < boneCount; ++i) + { + constrained.Items[i].sorted = true; + } + } + + void Skeleton::sortPathConstraintAttachment(Skin skin, int slotIndex, Bone slotBone) + { + foreach (var entry in skin.Attachments) + { + if (entry.Key.slotIndex == slotIndex) + { + sortPathConstraintAttachment(entry.Value, slotBone); + } + } + } + + void Skeleton::sortPathConstraintAttachment(Attachment attachment, Bone slotBone) + { + if (!(attachment is PathAttachment)) + { + return; + } + + int[] pathBones = ((PathAttachment)attachment).bones; + if (pathBones == NULL) + { + sortBone(slotBone); + } + else + { + var bones = _bones; + for (int i = 0, n = pathBones.Length; i < n;) + { + int nn = pathBones[i++]; + nn += i; + while (i < nn) + { + sortBone(bones.Items[pathBones[i++]]); + } + } + } + } + + void Skeleton::sortBone(Bone bone) + { + if (bone.sorted) + { + return; + } + + Bone parent = bone.parent; + if (parent != NULL) + { + sortBone(parent); + } + + bone.sorted = true; + updateCache.Add(bone); + } + + void Skeleton::sortReset(SimpleArray& bones) + { + for (Bone* i = bones.begin(); i != bones.end(); ++i) + { + Bone* bone = i; + if (bone->isSorted()) + { + sortReset(bone->getChildren()); + } + + bone->setSorted(false); + } + } } diff --git a/spine-cpp/spine-cpp/src/spine/Skin.cpp b/spine-cpp/spine-cpp/src/spine/Skin.cpp index d0a8c2663..949ac6504 100644 --- a/spine-cpp/spine-cpp/src/spine/Skin.cpp +++ b/spine-cpp/spine-cpp/src/spine/Skin.cpp @@ -67,7 +67,7 @@ namespace Spine { HashMap::Iterator i = _attachments.find(AttachmentKey(slotIndex, name)); - Attachment* ret = nullptr; + Attachment* ret = NULL; if (i != _attachments.end()) { @@ -118,7 +118,7 @@ namespace Spine if (slot->getAttachment() == i.second()) { - Attachment* attachment = nullptr; + Attachment* attachment = NULL; if ((attachment = getAttachment(slotIndex, i.first()._name))) { slot->setAttachment(attachment); diff --git a/spine-cpp/spine-cpp/src/spine/Slot.cpp b/spine-cpp/spine-cpp/src/spine/Slot.cpp index 6b587cd5d..c9ee69fb1 100644 --- a/spine-cpp/spine-cpp/src/spine/Slot.cpp +++ b/spine-cpp/spine-cpp/src/spine/Slot.cpp @@ -49,7 +49,7 @@ namespace Spine _g2(0), _b2(0), _hasSecondColor(false), - _attachment(nullptr), + _attachment(NULL), _attachmentTime(0) { setToSetupPose(); @@ -65,12 +65,12 @@ namespace Spine std::string attachmentName = _slotData.getAttachmentName(); if (attachmentName.length() > 0) { - _attachment = nullptr; + _attachment = NULL; setAttachment(_skeleton.getAttachment(_slotData.getIndex(), attachmentName)); } else { - setAttachment(nullptr); + setAttachment(NULL); } } diff --git a/spine-cpp/spine-cpp/src/spine/TransformConstraintData.cpp b/spine-cpp/spine-cpp/src/spine/TransformConstraintData.cpp index b3d0006fd..d67e2e1b9 100644 --- a/spine-cpp/spine-cpp/src/spine/TransformConstraintData.cpp +++ b/spine-cpp/spine-cpp/src/spine/TransformConstraintData.cpp @@ -39,7 +39,7 @@ namespace Spine TransformConstraintData::TransformConstraintData(std::string name) : _name(name), _order(0), - _target(nullptr), + _target(NULL), _rotateMix(0), _translateMix(0), _scaleMix(0), From 30dc2c08c60c9875a6bf0545d2aad00065f02c7c Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Thu, 19 Oct 2017 15:36:38 -0400 Subject: [PATCH 15/83] Wip --- spine-cpp/spine-cpp/include/spine/HashMap.h | 2 +- spine-cpp/spine-cpp/include/spine/Skeleton.h | 12 ++--- spine-cpp/spine-cpp/include/spine/Skin.h | 10 +++- spine-cpp/spine-cpp/src/spine/Skeleton.cpp | 49 ++++++++++++++------ 4 files changed, 49 insertions(+), 24 deletions(-) diff --git a/spine-cpp/spine-cpp/include/spine/HashMap.h b/spine-cpp/spine-cpp/include/spine/HashMap.h index 0eaff11df..d7828c2fc 100755 --- a/spine-cpp/spine-cpp/include/spine/HashMap.h +++ b/spine-cpp/spine-cpp/include/spine/HashMap.h @@ -89,7 +89,7 @@ namespace Spine Entry* _entry; }; - HashMap(size_t capacity) : _capacity(capacity), _hashFunction(), _header(), _trailer() + HashMap(size_t capacity = 65535) : _capacity(capacity), _hashFunction(), _header(), _trailer() { _hashTable = new Entry[capacity]; for (int i = 0; i < _capacity; ++i) diff --git a/spine-cpp/spine-cpp/include/spine/Skeleton.h b/spine-cpp/spine-cpp/include/spine/Skeleton.h index 99022c939..07bfd9e3b 100644 --- a/spine-cpp/spine-cpp/include/spine/Skeleton.h +++ b/spine-cpp/spine-cpp/include/spine/Skeleton.h @@ -120,7 +120,7 @@ namespace Spine /// @param width The width of the AABB /// @param height The height of the AABB. /// @param vertexBuffer Reference to hold a SimpleArray of floats. This method will assign it with new floats as needed. - void getBounds(float& outX, float& outY, float& outWidth, float& outHeight, SimpleArray& vertexBuffer); + void getBounds(float& outX, float& outY, float& outWidth, float& outHeight, SimpleArray& outVertexBuffer); Bone* getRootBone(); @@ -170,15 +170,15 @@ namespace Spine bool _flipX, _flipY; float _x, _y; - void sortIkConstraint(IkConstraint constraint); + void sortIkConstraint(IkConstraint* constraint); - void sortPathConstraint(PathConstraint constraint); + void sortPathConstraint(PathConstraint* constraint); - void sortTransformConstraint(TransformConstraint constraint); + void sortTransformConstraint(TransformConstraint* constraint); - void sortPathConstraintAttachment(Skin skin, int slotIndex, Bone slotBone); + void sortPathConstraintAttachment(Skin* skin, int slotIndex, Bone* slotBone); - void sortPathConstraintAttachment(Attachment attachment, Bone slotBone); + void sortPathConstraintAttachment(Attachment* attachment, Bone* slotBone); void sortBone(Bone bone); diff --git a/spine-cpp/spine-cpp/include/spine/Skin.h b/spine-cpp/spine-cpp/include/spine/Skin.h index 72ee57f50..b0f858f39 100644 --- a/spine-cpp/spine-cpp/include/spine/Skin.h +++ b/spine-cpp/spine-cpp/include/spine/Skin.h @@ -94,8 +94,14 @@ struct HashAttachmentKey { std::size_t operator()(const Spine::Skin::AttachmentKey& val) const { - std::size_t h1 = std::hash{}(val._slotIndex); - std::size_t h2 = std::hash{}(val._name); + std::size_t h1 = static_castgetBones().size()); - bones = new SimpleArray(data.bones.Count); + _bones.reserve(_data.getBones().size()); + foreach (BoneData boneData in data.bones) { Bone bone; @@ -63,8 +74,9 @@ namespace Spine bones.Add(bone); } - slots = new SimpleArray(data.slots.Count); - drawOrder = new SimpleArray(data.slots.Count); + _slots.reserve(_data.getSlots().size()); + _drawOrder.reserve(_data.getSlots().size()); + foreach (SlotData slotData in data.slots) { Bone bone = bones.Items[slotData.boneData.index]; @@ -74,16 +86,23 @@ namespace Spine } ikConstraints = new SimpleArray(data.ikConstraints.Count); + foreach (IkConstraintData ikConstraintData in data.ikConstraints) - ikConstraints.Add(new IkConstraint(ikConstraintData, this)); + { + ikConstraints.Add(new IkConstraint(ikConstraintData, this)); + } transformConstraints = new SimpleArray(data.transformConstraints.Count); foreach (TransformConstraintData transformConstraintData in data.transformConstraints) - transformConstraints.Add(new TransformConstraint(transformConstraintData, this)); + { + transformConstraints.Add(new TransformConstraint(transformConstraintData, this)); + } pathConstraints = new SimpleArray (data.pathConstraints.Count); foreach (PathConstraintData pathConstraintData in data.pathConstraints) - pathConstraints.Add(new PathConstraint(pathConstraintData, this)); + { + pathConstraints.Add(new PathConstraint(pathConstraintData, this)); + } updateCache(); updateWorldTransform(); @@ -443,7 +462,7 @@ namespace Spine _time += delta; } - void Skeleton::getBounds(float& outX, float& outY, float& outWidth, float& outHeight, SimpleArray& vertexBuffer) + void Skeleton::getBounds(float& outX, float& outY, float& outWidth, float& outHeight, SimpleArray& outVertexBuffer) { float minX = std::numeric_limits::max(); float minY = std::numeric_limits::max(); @@ -643,7 +662,7 @@ namespace Spine _flipY = inValue; } - void Skeleton::sortIkConstraint(IkConstraint constraint) + void Skeleton::sortIkConstraint(IkConstraint* constraint) { Bone target = constraint.target; sortBone(target); @@ -667,7 +686,7 @@ namespace Spine constrained.Items[constrained.Count - 1].sorted = true; } - void Skeleton::sortPathConstraint(PathConstraint constraint) + void Skeleton::sortPathConstraint(PathConstraint* constraint) { Slot slot = constraint.target; int slotIndex = slot.data.index; @@ -714,7 +733,7 @@ namespace Spine } } - void Skeleton::sortTransformConstraint(TransformConstraint constraint) + void Skeleton::sortTransformConstraint(TransformConstraint* constraint) { sortBone(constraint.target); @@ -752,7 +771,7 @@ namespace Spine } } - void Skeleton::sortPathConstraintAttachment(Skin skin, int slotIndex, Bone slotBone) + void Skeleton::sortPathConstraintAttachment(Skin* skin, int slotIndex, Bone* slotBone) { foreach (var entry in skin.Attachments) { @@ -763,7 +782,7 @@ namespace Spine } } - void Skeleton::sortPathConstraintAttachment(Attachment attachment, Bone slotBone) + void Skeleton::sortPathConstraintAttachment(Attachment* attachment, Bone* slotBone) { if (!(attachment is PathAttachment)) { @@ -790,7 +809,7 @@ namespace Spine } } - void Skeleton::sortBone(Bone bone) + void Skeleton::sortBone(Bone* bone) { if (bone.sorted) { From 9129d64100763334573fde31de9509b334ed50fe Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Sat, 21 Oct 2017 11:34:38 -0400 Subject: [PATCH 16/83] wip --- spine-cpp/spine-cpp/include/spine/Bone.h | 8 +- spine-cpp/spine-cpp/include/spine/BoneData.h | 2 +- .../spine-cpp/include/spine/ContainerUtil.h | 4 +- .../spine-cpp/include/spine/CurveTimeline.h | 6 +- .../include/spine/IkConstraintData.h | 6 +- .../spine-cpp/include/spine/MixDirection.h | 2 +- spine-cpp/spine-cpp/include/spine/MixPose.h | 2 +- .../include/spine/PathConstraintData.h | 6 +- .../spine-cpp/include/spine/RotateTimeline.h | 8 +- spine-cpp/spine-cpp/include/spine/Skeleton.h | 46 +-- .../spine-cpp/include/spine/SkeletonData.h | 121 +++++++- spine-cpp/spine-cpp/include/spine/Skin.h | 8 +- spine-cpp/spine-cpp/include/spine/Slot.h | 10 +- spine-cpp/spine-cpp/include/spine/Timeline.h | 6 +- .../include/spine/TransformConstraintData.h | 6 +- .../include/spine/{SimpleArray.h => Vector.h} | 16 +- spine-cpp/spine-cpp/src/spine/Bone.cpp | 2 +- .../spine-cpp/src/spine/IkConstraintData.cpp | 2 +- .../src/spine/PathConstraintData.cpp | 2 +- spine-cpp/spine-cpp/src/spine/RTTI.cpp | 2 +- .../spine-cpp/src/spine/RotateTimeline.cpp | 6 +- spine-cpp/spine-cpp/src/spine/Skeleton.cpp | 42 +-- .../spine-cpp/src/spine/SkeletonData.cpp | 265 +++++++++++++++++- spine-cpp/spine-cpp/src/spine/Skin.cpp | 4 +- spine-cpp/spine-cpp/src/spine/Slot.cpp | 4 +- .../src/spine/TransformConstraintData.cpp | 2 +- 26 files changed, 485 insertions(+), 103 deletions(-) rename spine-cpp/spine-cpp/include/spine/{SimpleArray.h => Vector.h} (94%) diff --git a/spine-cpp/spine-cpp/include/spine/Bone.h b/spine-cpp/spine-cpp/include/spine/Bone.h index 1657b74a9..e189750b2 100644 --- a/spine-cpp/spine-cpp/include/spine/Bone.h +++ b/spine-cpp/spine-cpp/include/spine/Bone.h @@ -33,7 +33,7 @@ #include -#include +#include namespace Spine { @@ -54,7 +54,7 @@ namespace Spine static bool isYDown(); - /// @param parent May be null. + /// @param parent May be NULL. Bone(BoneData& data, Skeleton& skeleton, Bone* parent); /// Same as updateWorldTransform. This method exists for Bone to implement Spine::Updatable. @@ -89,7 +89,7 @@ namespace Spine BoneData& getData(); Skeleton& getSkeleton(); Bone* getParent(); - SimpleArray& getChildren(); + Vector& getChildren(); /// The local X translation. float getX(); @@ -169,7 +169,7 @@ namespace Spine BoneData& _data; Skeleton& _skeleton; Bone* _parent; - SimpleArray _children; + Vector _children; float _x, _y, _rotation, _scaleX, _scaleY, _shearX, _shearY; float _ax, _ay, _arotation, _ascaleX, _ascaleY, _ashearX, _ashearY; bool _appliedValid; diff --git a/spine-cpp/spine-cpp/include/spine/BoneData.h b/spine-cpp/spine-cpp/include/spine/BoneData.h index ef81b1e62..292f4a4c4 100644 --- a/spine-cpp/spine-cpp/include/spine/BoneData.h +++ b/spine-cpp/spine-cpp/include/spine/BoneData.h @@ -48,7 +48,7 @@ namespace Spine /// The name of the bone, which is unique within the skeleton. const std::string& getName(); - /// May be null. + /// May be NULL. const BoneData* getParent(); float getLength(); diff --git a/spine-cpp/spine-cpp/include/spine/ContainerUtil.h b/spine-cpp/spine-cpp/include/spine/ContainerUtil.h index 33156e7ef..ecc52e168 100644 --- a/spine-cpp/spine-cpp/include/spine/ContainerUtil.h +++ b/spine-cpp/spine-cpp/include/spine/ContainerUtil.h @@ -31,7 +31,7 @@ #ifndef Spine_Attachment_h #define Spine_Attachment_h -#include +#include #include namespace Spine @@ -40,7 +40,7 @@ namespace Spine { public: template - static void cleanUpSimpleArrayOfPointers(SimpleArray& items) + static void cleanUpVectorOfPointers(Vector& items) { for (size_t i = 0; i < items.size(); ) { diff --git a/spine-cpp/spine-cpp/include/spine/CurveTimeline.h b/spine-cpp/spine-cpp/include/spine/CurveTimeline.h index 24b3ad527..ccf3b1f86 100644 --- a/spine-cpp/spine-cpp/include/spine/CurveTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/CurveTimeline.h @@ -32,7 +32,7 @@ #define Spine_CurveTimeline_h #include -#include +#include #include @@ -44,7 +44,7 @@ namespace Spine public: CurveTimeline(int frameCount); - virtual void apply(Skeleton& skeleton, float lastTime, float time, SimpleArray& events, float alpha, MixPose pose, MixDirection direction) = 0; + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) = 0; virtual int getPropertyId() = 0; @@ -70,7 +70,7 @@ namespace Spine static const int BEZIER_SIZE; private: - SimpleArray _curves; // type, x, y, ... + Vector _curves; // type, x, y, ... }; } diff --git a/spine-cpp/spine-cpp/include/spine/IkConstraintData.h b/spine-cpp/spine-cpp/include/spine/IkConstraintData.h index 0e54049a0..4f231f711 100644 --- a/spine-cpp/spine-cpp/include/spine/IkConstraintData.h +++ b/spine-cpp/spine-cpp/include/spine/IkConstraintData.h @@ -31,7 +31,7 @@ #ifndef Spine_IkConstraintData_h #define Spine_IkConstraintData_h -#include +#include #include @@ -51,7 +51,7 @@ namespace Spine void setOrder(int inValue); /// The bones that are constrained by this IK Constraint. - SimpleArray& getBones(); + Vector& getBones(); /// The bone that is the IK target. BoneData* getTarget(); @@ -67,7 +67,7 @@ namespace Spine private: const std::string _name; int _order; - SimpleArray _bones; + Vector _bones; BoneData* _target; int _bendDirection; float _mix; diff --git a/spine-cpp/spine-cpp/include/spine/MixDirection.h b/spine-cpp/spine-cpp/include/spine/MixDirection.h index 1400e1b3a..ab14a3823 100644 --- a/spine-cpp/spine-cpp/include/spine/MixDirection.h +++ b/spine-cpp/spine-cpp/include/spine/MixDirection.h @@ -35,7 +35,7 @@ namespace Spine { /// /// Indicates whether a timeline's alpha is mixing out over time toward 0 (the setup or current pose) or mixing in toward 1 (the timeline's pose). - /// See also Timeline::apply(Skeleton&, float, float, SimpleArray&, float, MixPose, MixDirection) + /// See also Timeline::apply(Skeleton&, float, float, Vector&, float, MixPose, MixDirection) enum MixDirection { MixDirection_In = 0, diff --git a/spine-cpp/spine-cpp/include/spine/MixPose.h b/spine-cpp/spine-cpp/include/spine/MixPose.h index 487165890..f95fce969 100644 --- a/spine-cpp/spine-cpp/include/spine/MixPose.h +++ b/spine-cpp/spine-cpp/include/spine/MixPose.h @@ -35,7 +35,7 @@ namespace Spine { /// /// Controls how a timeline is mixed with the setup or current pose. - /// See also Timeline::apply(Skeleton&, float, float, SimpleArray&, float, MixPose, MixDirection) + /// See also Timeline::apply(Skeleton&, float, float, Vector&, float, MixPose, MixDirection) enum MixPose { /// The timeline value is mixed with the setup pose (the current pose is not used). diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraintData.h b/spine-cpp/spine-cpp/include/spine/PathConstraintData.h index 63c5ddcc6..4acdf4513 100644 --- a/spine-cpp/spine-cpp/include/spine/PathConstraintData.h +++ b/spine-cpp/spine-cpp/include/spine/PathConstraintData.h @@ -34,7 +34,7 @@ #include #include #include -#include +#include #include @@ -53,7 +53,7 @@ namespace Spine int getOrder(); void setOrder(int inValue); - SimpleArray& getBones(); + Vector& getBones(); SlotData* getTarget(); void setTarget(SlotData* inValue); @@ -85,7 +85,7 @@ namespace Spine private: const std::string _name; int _order; - SimpleArray _bones; + Vector _bones; SlotData* _target; PositionMode _positionMode; SpacingMode _spacingMode; diff --git a/spine-cpp/spine-cpp/include/spine/RotateTimeline.h b/spine-cpp/spine-cpp/include/spine/RotateTimeline.h index 41547f417..9b2ff0403 100644 --- a/spine-cpp/spine-cpp/include/spine/RotateTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/RotateTimeline.h @@ -42,7 +42,7 @@ namespace Spine RotateTimeline(int frameCount); - virtual void apply(Skeleton& skeleton, float lastTime, float time, SimpleArray& events, float alpha, MixPose pose, MixDirection direction); + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); virtual int getPropertyId(); @@ -52,8 +52,8 @@ namespace Spine int getBoneIndex(); void setBoneIndex(int inValue); - SimpleArray& getFrames(); - void setFrames(SimpleArray inValue); + Vector& getFrames(); + void setFrames(Vector inValue); private: static const int PREV_TIME = -2; @@ -61,7 +61,7 @@ namespace Spine static const int ROTATION = 1; int _boneIndex; - SimpleArray _frames; // time, angle, ... + Vector _frames; // time, angle, ... }; } diff --git a/spine-cpp/spine-cpp/include/spine/Skeleton.h b/spine-cpp/spine-cpp/include/spine/Skeleton.h index 07bfd9e3b..cbc6cdfbd 100644 --- a/spine-cpp/spine-cpp/include/spine/Skeleton.h +++ b/spine-cpp/spine-cpp/include/spine/Skeleton.h @@ -31,7 +31,7 @@ #ifndef Spine_Skeleton_h #define Spine_Skeleton_h -#include +#include #include #include @@ -115,23 +115,23 @@ namespace Spine void update(float delta); /// Returns the axis aligned bounding box (AABB) of the region and mesh attachments for the current pose. - /// @param x The horizontal distance between the skeleton origin and the left side of the AABB. - /// @param y The vertical distance between the skeleton origin and the bottom side of the AABB. - /// @param width The width of the AABB - /// @param height The height of the AABB. - /// @param vertexBuffer Reference to hold a SimpleArray of floats. This method will assign it with new floats as needed. - void getBounds(float& outX, float& outY, float& outWidth, float& outHeight, SimpleArray& outVertexBuffer); + /// @param outX The horizontal distance between the skeleton origin and the left side of the AABB. + /// @param outY The vertical distance between the skeleton origin and the bottom side of the AABB. + /// @param outWidth The width of the AABB + /// @param outHeight The height of the AABB. + /// @param outVertexBuffer Reference to hold a Vector of floats. This method will assign it with new floats as needed. + void getBounds(float& outX, float& outY, float& outWidth, float& outHeight, Vector& outVertexBuffer); Bone* getRootBone(); const SkeletonData& getData(); - SimpleArray& getBones(); - SimpleArray& getUpdateCacheList(); - SimpleArray& getSlots(); - SimpleArray& getDrawOrder(); - SimpleArray& getIkConstraints(); - SimpleArray& getPathConstraints(); - SimpleArray& getTransformConstraints(); + Vector& getBones(); + Vector& getUpdateCacheList(); + Vector& getSlots(); + Vector& getDrawOrder(); + Vector& getIkConstraints(); + Vector& getPathConstraints(); + Vector& getTransformConstraints(); Skin* getSkin(); void setSkin(Skin* inValue); @@ -156,14 +156,14 @@ namespace Spine private: const SkeletonData& _data; - SimpleArray _bones; - SimpleArray _slots; - SimpleArray _drawOrder; - SimpleArray _ikConstraints; - SimpleArray _transformConstraints; - SimpleArray _pathConstraints; - SimpleArray _updateCache; - SimpleArray _updateCacheReset; + Vector _bones; + Vector _slots; + Vector _drawOrder; + Vector _ikConstraints; + Vector _transformConstraints; + Vector _pathConstraints; + Vector _updateCache; + Vector _updateCacheReset; Skin* _skin; float _r = 1, _g = 1, _b = 1, _a = 1; float _time; @@ -182,7 +182,7 @@ namespace Spine void sortBone(Bone bone); - static void sortReset(SimpleArray& bones); + static void sortReset(Vector& bones); }; } diff --git a/spine-cpp/spine-cpp/include/spine/SkeletonData.h b/spine-cpp/spine-cpp/include/spine/SkeletonData.h index 37b27397f..4508d537a 100644 --- a/spine-cpp/spine-cpp/include/spine/SkeletonData.h +++ b/spine-cpp/spine-cpp/include/spine/SkeletonData.h @@ -31,9 +31,128 @@ #ifndef Spine_SkeletonData_h #define Spine_SkeletonData_h +#include + +#include + namespace Spine { - // TODO + class BoneData; + class SlotData; + class Skin; + class EventData; + class Animation; + class IkConstraintData; + class TransformConstraintData; + class PathConstraintData; + + /// Stores the setup pose and all of the stateless data for a skeleton. + class SkeletonData + { + public: + SkeletonData(); + + /// Finds a bone by comparing each bone's name. + /// It is more efficient to cache the results of this method than to call it multiple times. + /// @return May be NULL. + BoneData* findBone(std::string boneName); + + /// @return -1 if the bone was not found. + int findBoneIndex(std::string boneName); + + /// @return May be NULL. + SlotData* findSlot(std::string slotName); + + /// @return -1 if the slot was not found. + int findSlotIndex(std::string slotName); + + /// @return May be NULL. + Skin* findSkin(std::string skinName); + + /// @return May be NULL. + EventData* findEvent(std::string eventDataName); + + /// @return May be NULL. + Animation* findAnimation(std::string animationName); + + /// @return May be NULL. + IkConstraintData* findIkConstraint(std::string constraintName); + + /// @return May be NULL. + TransformConstraintData* findTransformConstraint(std::string constraintName); + + /// @return May be NULL. + PathConstraintData* findPathConstraint(std::string constraintName); + + /// @return -1 if the path constraint was not found. + int findPathConstraintIndex(std::string pathConstraintName); + + std::string getName(); + void setName(std::string inValue); + + /// The skeleton's bones, sorted parent first. The root bone is always the first bone. + Vector& getBones(); + + Vector& getSlots(); + + /// All skins, including the default skin. + Vector& getSkins(); + void setSkins(Vector& inValue); + + /// The skeleton's default skin. + /// By default this skin contains all attachments that were not in a skin in Spine. + /// + /// @return May be NULL. + Skin* getDefaultSkin(); + void setDefaultSkin(Skin* inValue); + + Vector& getEvents(); + void setEvents(Vector& inValue); + Vector& getAnimations(); + void setAnimations(Vector& inValue); + Vector& getIkConstraints(); + void setIkConstraints(Vector& inValue); + Vector& getTransformConstraints(); + void setTransformConstraints(Vector& inValue); + Vector& getPathConstraints(); + void setPathConstraints(Vector& inValue); + + float getWidth(); + void setWidth(float inValue); + float getHeight(); + void setHeight(float inValue); + + /// The Spine version used to export this data, or NULL. + std::string getVersion(); + void setVersion(std::string inValue); + std::string getHash(); + void setHash(std::string inValue); + std::string getImagesPath(); + void setImagesPath(std::string inValue); + + /// The dopesheet FPS in Spine. Available only when nonessential data was exported. + float getFps(); + void setFps(float inValue); + + private: + std::string _name; + Vector _bones; // Ordered parents first + Vector _slots; // Setup pose draw order. + Vector _skins; + Skin* _defaultSkin; + Vector _events; + Vector _animations; + Vector _ikConstraints; + Vector _transformConstraints; + Vector _pathConstraints; + float _width, _height; + std::string _version; + std::string _hash; + + // Nonessential. + float _fps; + std::string _imagesPath; + }; } #endif /* Spine_SkeletonData_h */ diff --git a/spine-cpp/spine-cpp/include/spine/Skin.h b/spine-cpp/spine-cpp/include/spine/Skin.h index b0f858f39..b6f36dd9c 100644 --- a/spine-cpp/spine-cpp/include/spine/Skin.h +++ b/spine-cpp/spine-cpp/include/spine/Skin.h @@ -33,7 +33,7 @@ #include #include -#include +#include struct HashAttachmentKey; @@ -65,18 +65,18 @@ namespace Spine /// If the name already exists for the slot, the previous value is replaced. void addAttachment(int slotIndex, std::string name, Attachment* attachment); - /// Returns the attachment for the specified slot index and name, or null. + /// Returns the attachment for the specified slot index and name, or NULL. Attachment* getAttachment(int slotIndex, std::string name); /// Finds the skin keys for a given slot. The results are added to the passed array of names. /// @param slotIndex The target slotIndex. To find the slot index, use Skeleton::findSlotIndex or SkeletonData::findSlotIndex /// @param names Found skin key names will be added to this array. - void findNamesForSlot(int slotIndex, SimpleArray& names); + void findNamesForSlot(int slotIndex, Vector& names); /// Finds the attachments for a given slot. The results are added to the passed array of Attachments. /// @param slotIndex The target slotIndex. To find the slot index, use Skeleton::findSlotIndex or SkeletonData::findSlotIndex /// @param attachments Found Attachments will be added to this array. - void findAttachmentsForSlot(int slotIndex, SimpleArray& attachments); + void findAttachmentsForSlot(int slotIndex, Vector& attachments); const std::string& getName(); HashMap& getAttachments(); diff --git a/spine-cpp/spine-cpp/include/spine/Slot.h b/spine-cpp/spine-cpp/include/spine/Slot.h index 2f2ae4bc4..767373056 100644 --- a/spine-cpp/spine-cpp/include/spine/Slot.h +++ b/spine-cpp/spine-cpp/include/spine/Slot.h @@ -31,7 +31,7 @@ #ifndef Spine_Slot_h #define Spine_Slot_h -#include +#include #include @@ -71,15 +71,15 @@ namespace Spine bool hasSecondColor(); void setHasSecondColor(bool inValue); - /// May be null. + /// May be NULL. Attachment* getAttachment(); void setAttachment(Attachment* inValue); float getAttachmentTime(); void setAttachmentTime(float inValue); - SimpleArray& getAttachmentVertices(); - void setAttachmentVertices(SimpleArray inValue); + Vector& getAttachmentVertices(); + void setAttachmentVertices(Vector inValue); private: const SlotData& _slotData; @@ -90,7 +90,7 @@ namespace Spine bool _hasSecondColor; Attachment* _attachment; float _attachmentTime; - SimpleArray _attachmentVertices; + Vector _attachmentVertices; }; } diff --git a/spine-cpp/spine-cpp/include/spine/Timeline.h b/spine-cpp/spine-cpp/include/spine/Timeline.h index f74944694..056ba8d39 100644 --- a/spine-cpp/spine-cpp/include/spine/Timeline.h +++ b/spine-cpp/spine-cpp/include/spine/Timeline.h @@ -31,7 +31,7 @@ #ifndef Spine_Timeline_h #define Spine_Timeline_h -#include +#include #include #include @@ -51,14 +51,14 @@ namespace Spine /// @param skeleton The skeleton the timeline is being applied to. This provides access to the bones, slots, and other skeleton components the timeline may change. /// @param lastTime lastTime The time this timeline was last applied. Timelines such as EventTimeline trigger only at specific times rather than every frame. In that case, the timeline triggers everything between lastTime (exclusive) and time (inclusive). /// @param time The time within the animation. Most timelines find the key before and the key after this time so they can interpolate between the keys. - /// @param events If any events are fired, they are added to this array. Can be null to ignore firing events or if the timeline does not fire events. May be null. + /// @param events If any events are fired, they are added to this array. Can be NULL to ignore firing events or if the timeline does not fire events. May be NULL. /// @param alpha alpha 0 applies the current or setup pose value (depending on pose parameter). 1 applies the timeline /// value. Between 0 and 1 applies a value between the current or setup pose and the timeline value. By adjusting /// alpha over time, an animation can be mixed in or out. alpha can also be useful to /// apply animations on top of each other (layered). /// @param pose Controls how mixing is applied when alpha is than 1. /// @param direction Indicates whether the timeline is mixing in or out. Used by timelines which perform instant transitions such as DrawOrderTimeline and AttachmentTimeline. - virtual void apply(Skeleton& skeleton, float lastTime, float time, SimpleArray& events, float alpha, MixPose pose, MixDirection direction) = 0; + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) = 0; virtual int getPropertyId() = 0; }; diff --git a/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h b/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h index bd4f9bd1b..eb978ad6c 100644 --- a/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h +++ b/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h @@ -31,7 +31,7 @@ #ifndef Spine_TransformConstraintData_h #define Spine_TransformConstraintData_h -#include +#include #include @@ -46,7 +46,7 @@ namespace Spine const std::string& getName(); int getOrder(); - SimpleArray& getBones(); + Vector& getBones(); BoneData* getTarget(); float getRotateMix(); float getTranslateMix(); @@ -66,7 +66,7 @@ namespace Spine private: const std::string _name; int _order; - SimpleArray _bones; + Vector _bones; BoneData* _target; float _rotateMix, _translateMix, _scaleMix, _shearMix; float _offsetRotation, _offsetX, _offsetY, _offsetScaleX, _offsetScaleY, _offsetShearY; diff --git a/spine-cpp/spine-cpp/include/spine/SimpleArray.h b/spine-cpp/spine-cpp/include/spine/Vector.h similarity index 94% rename from spine-cpp/spine-cpp/include/spine/SimpleArray.h rename to spine-cpp/spine-cpp/include/spine/Vector.h index e544c8104..df2e18e7d 100644 --- a/spine-cpp/spine-cpp/include/spine/SimpleArray.h +++ b/spine-cpp/spine-cpp/include/spine/Vector.h @@ -28,8 +28,8 @@ * POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -#ifndef Spine_SimpleArray_h -#define Spine_SimpleArray_h +#ifndef Spine_Vector_h +#define Spine_Vector_h #include #include @@ -37,19 +37,19 @@ namespace Spine { template - class SimpleArray + class Vector { public: - SimpleArray() : _size(0), _capacity(0), _buffer(nullptr) + Vector() : _size(0), _capacity(0), _buffer(NULL) { // Empty } - SimpleArray(const SimpleArray& inArray) + Vector(const Vector& inArray) { _size = inArray._size; _capacity = inArray._capacity; - if (_capacity) + if (_capacity > 0) { _buffer = allocate(_capacity); for (size_t i = 0; i < _size; ++i) @@ -59,7 +59,7 @@ namespace Spine } } - ~SimpleArray() + ~Vector() { clear(); deallocate(_buffer); @@ -184,4 +184,4 @@ namespace Spine }; } -#endif /* Spine_SimpleArray_h */ +#endif /* Spine_Vector_h */ diff --git a/spine-cpp/spine-cpp/src/spine/Bone.cpp b/spine-cpp/spine-cpp/src/spine/Bone.cpp index 1e3882573..a2dacdbe8 100644 --- a/spine-cpp/spine-cpp/src/spine/Bone.cpp +++ b/spine-cpp/spine-cpp/src/spine/Bone.cpp @@ -369,7 +369,7 @@ namespace Spine return _parent; } - SimpleArray& Bone::getChildren() + Vector& Bone::getChildren() { return _children; } diff --git a/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp b/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp index 70158d296..4f84d1f83 100644 --- a/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp +++ b/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp @@ -57,7 +57,7 @@ namespace Spine _order = inValue; } - SimpleArray& IkConstraintData::getBones() + Vector& IkConstraintData::getBones() { return _bones; } diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraintData.cpp b/spine-cpp/spine-cpp/src/spine/PathConstraintData.cpp index 9a82bcbf5..f3ef57df7 100644 --- a/spine-cpp/spine-cpp/src/spine/PathConstraintData.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathConstraintData.cpp @@ -68,7 +68,7 @@ namespace Spine _order = inValue; } - SimpleArray& PathConstraintData::getBones() + Vector& PathConstraintData::getBones() { return _bones; } diff --git a/spine-cpp/spine-cpp/src/spine/RTTI.cpp b/spine-cpp/spine-cpp/src/spine/RTTI.cpp index 3905c9d6b..9d271f894 100644 --- a/spine-cpp/spine-cpp/src/spine/RTTI.cpp +++ b/spine-cpp/spine-cpp/src/spine/RTTI.cpp @@ -32,7 +32,7 @@ namespace Spine { - RTTI::RTTI(const std::string& className) : m_className(className), m_pBaseRTTI(nullptr) + RTTI::RTTI(const std::string& className) : m_className(className), m_pBaseRTTI(NULL) { // Empty } diff --git a/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp b/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp index 6d2302612..b77b60858 100644 --- a/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp @@ -43,7 +43,7 @@ namespace Spine _frames.reserve(frameCount << 1); } - void RotateTimeline::apply(Skeleton& skeleton, float lastTime, float time, SimpleArray& events, float alpha, MixPose pose, MixDirection direction) + void RotateTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) { Bone* bone = skeleton.getBones().at(_boneIndex); @@ -127,12 +127,12 @@ namespace Spine _boneIndex = inValue; } - SimpleArray& RotateTimeline::getFrames() + Vector& RotateTimeline::getFrames() { return _frames; } - void RotateTimeline::setFrames(SimpleArray inValue) + void RotateTimeline::setFrames(Vector inValue) { _frames = inValue; } diff --git a/spine-cpp/spine-cpp/src/spine/Skeleton.cpp b/spine-cpp/spine-cpp/src/spine/Skeleton.cpp index 0807ea2d0..88eefbd5a 100644 --- a/spine-cpp/spine-cpp/src/spine/Skeleton.cpp +++ b/spine-cpp/spine-cpp/src/spine/Skeleton.cpp @@ -57,7 +57,7 @@ namespace Spine { _bones.reserve(_data.getBones().size()); - foreach (BoneData boneData in data.bones) + foreach (BoneData boneData in _data.getBones()) { Bone bone; if (boneData.parent == NULL) @@ -85,20 +85,20 @@ namespace Spine drawOrder.Add(slot); } - ikConstraints = new SimpleArray(data.ikConstraints.Count); + ikConstraints = new Vector(data.ikConstraints.Count); foreach (IkConstraintData ikConstraintData in data.ikConstraints) { ikConstraints.Add(new IkConstraint(ikConstraintData, this)); } - transformConstraints = new SimpleArray(data.transformConstraints.Count); + transformConstraints = new Vector(data.transformConstraints.Count); foreach (TransformConstraintData transformConstraintData in data.transformConstraints) { transformConstraints.Add(new TransformConstraint(transformConstraintData, this)); } - pathConstraints = new SimpleArray (data.pathConstraints.Count); + pathConstraints = new Vector (data.pathConstraints.Count); foreach (PathConstraintData pathConstraintData in data.pathConstraints) { pathConstraints.Add(new PathConstraint(pathConstraintData, this)); @@ -110,17 +110,17 @@ namespace Spine void Skeleton::updateCache() { - SimpleArray updateCache = _updateCache; + Vector updateCache = _updateCache; updateCache.Clear(); _updateCacheReset.Clear(); - SimpleArray bones = _bones; + Vector bones = _bones; for (int i = 0, n = bones.Count; i < n; ++i) { bones.Items[i].sorted = false; } - SimpleArray ikConstraints = _ikConstraints; + Vector ikConstraints = _ikConstraints; var transformConstraints = _transformConstraints; var pathConstraints = _pathConstraints; int ikCount = IkConstraints.Count, transformCount = transformConstraints.Count, pathCount = pathConstraints.Count; @@ -338,7 +338,7 @@ namespace Spine } else { - SimpleArray slots = _slots; + Vector slots = _slots; for (int i = 0, n = slots.Count; i < n; ++i) { Slot slot = slots.Items[i]; @@ -382,7 +382,7 @@ namespace Spine { assert(slotName.length() > 0); - SimpleArray slots = _slots; + Vector slots = _slots; for (int i = 0, n = slots.Count; i < n; ++i) { Slot slot = slots.Items[i]; @@ -411,7 +411,7 @@ namespace Spine { assert(constraintName.length() > 0); - SimpleArray ikConstraints = _ikConstraints; + Vector ikConstraints = _ikConstraints; for (int i = 0, n = ikConstraints.Count; i < n; ++i) { IkConstraint ikConstraint = ikConstraints.Items[i]; @@ -427,7 +427,7 @@ namespace Spine { assert(constraintName.length() > 0); - SimpleArray transformConstraints = _transformConstraints; + Vector transformConstraints = _transformConstraints; for (int i = 0, n = transformConstraints.Count; i < n; ++i) { TransformConstraint transformConstraint = transformConstraints.Items[i]; @@ -444,7 +444,7 @@ namespace Spine { assert(constraintName.length() > 0); - SimpleArray pathConstraints = _pathConstraints; + Vector pathConstraints = _pathConstraints; for (int i = 0, n = pathConstraints.Count; i < n; ++i) { PathConstraint constraint = pathConstraints.Items[i]; @@ -462,7 +462,7 @@ namespace Spine _time += delta; } - void Skeleton::getBounds(float& outX, float& outY, float& outWidth, float& outHeight, SimpleArray& outVertexBuffer) + void Skeleton::getBounds(float& outX, float& outY, float& outWidth, float& outHeight, Vector& outVertexBuffer) { float minX = std::numeric_limits::max(); float minY = std::numeric_limits::max(); @@ -527,37 +527,37 @@ namespace Spine return _data; } - SimpleArray& Skeleton::getBones() + Vector& Skeleton::getBones() { return _bones; } - SimpleArray& Skeleton::getUpdateCacheList() + Vector& Skeleton::getUpdateCacheList() { return _updateCache; } - SimpleArray& Skeleton::getSlots() + Vector& Skeleton::getSlots() { return _slots; } - SimpleArray& Skeleton::getDrawOrder() + Vector& Skeleton::getDrawOrder() { return _drawOrder; } - SimpleArray& Skeleton::getIkConstraints() + Vector& Skeleton::getIkConstraints() { return _ikConstraints; } - SimpleArray& Skeleton::getPathConstraints() + Vector& Skeleton::getPathConstraints() { return _pathConstraints; } - SimpleArray& Skeleton::getTransformConstraints() + Vector& Skeleton::getTransformConstraints() { return _transformConstraints; } @@ -826,7 +826,7 @@ namespace Spine updateCache.Add(bone); } - void Skeleton::sortReset(SimpleArray& bones) + void Skeleton::sortReset(Vector& bones) { for (Bone* i = bones.begin(); i != bones.end(); ++i) { diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonData.cpp b/spine-cpp/spine-cpp/src/spine/SkeletonData.cpp index bb4d2ccfe..bd5cac04d 100644 --- a/spine-cpp/spine-cpp/src/spine/SkeletonData.cpp +++ b/spine-cpp/spine-cpp/src/spine/SkeletonData.cpp @@ -28,7 +28,270 @@ * POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + namespace Spine { - // TODO + SkeletonData::SkeletonData() : + _defaultSkin(NULL), + _width(0), + _height(0), + _fps(0) + { + // Empty + } + + BoneData* SkeletonData::findBone(std::string boneName) + { + assert(boneName.length() > 0); + + for (BoneData** i = _bones.begin(); i != _bones.end(); ++i) + { + BoneData* boneData = (*i); + if (boneData->getName() == boneName) + { + return boneData; + } + } + + return NULL; + } + + int SkeletonData::findBoneIndex(std::string boneName) + { + assert(boneName.length() > 0); + + var bones = this.bones; + var bonesItems = bones.Items; + for (int i = 0, n = bones.Count; i < n; ++i) + { + if (bonesItems[i].name == boneName) + { + return i; + } + } + + return -1; + } + + /// Use a template findWithName method instead to reduce redundant data container traversal code + SlotData* SkeletonData::findSlot(std::string slotName) + { + assert(slotName.length() > 0); + + Vector slots = this.slots; + for (int i = 0, n = slots.Count; i < n; ++i) + { + SlotData slot = slots.Items[i]; + if (slot.name == slotName) + { + return slot; + } + } + + return NULL; + } + + int SkeletonData::findSlotIndex(std::string slotName) + { + assert(slotName.length() > 0); + + Vector slots = this.slots; + for (int i = 0, n = slots.Count; i < n; ++i) + { + if (slots.Items[i].name == slotName) + { + return i; + } + } + + return -1; + } + + Skin* SkeletonData::findSkin(std::string skinName) + { + assert(skinName.length() > 0); + + foreach (Skin skin in skins) + { + if (skin.name == skinName) + { + return skin; + } + } + + return NULL; + } + + EventData* SkeletonData::findEvent(std::string eventDataName) + { + assert(eventDataName.length() > 0); + + foreach (EventData eventData in events) + { + if (eventData.name == eventDataName) + { + return eventData; + } + } + + return NULL; + } + + Animation* SkeletonData::findAnimation(std::string animationName) + { + assert(animationName.length() > 0); + + Vector animations = this.animations; + for (int i = 0, n = animations.Count; i < n; ++i) + { + Animation animation = animations.Items[i]; + if (animation.name == animationName) + { + return animation; + } + } + + return NULL; + } + + IkConstraintData* SkeletonData::findIkConstraint(std::string constraintName) + { + assert(constraintName.length() > 0); + + Vector ikConstraints = this.ikConstraints; + for (int i = 0, n = ikConstraints.Count; i < n; ++i) + { + IkConstraintData ikConstraint = ikConstraints.Items[i]; + if (ikConstraint.name == constraintName) + { + return ikConstraint; + } + } + + return NULL; + } + + TransformConstraintData* SkeletonData::findTransformConstraint(std::string constraintName) + { + assert(constraintName.length() > 0); + + Vector transformConstraints = this.transformConstraints; + for (int i = 0, n = transformConstraints.Count; i < n; ++i) + { + TransformConstraintData transformConstraint = transformConstraints.Items[i]; + if (transformConstraint.name == constraintName) + { + return transformConstraint; + } + } + + return NULL; + } + + PathConstraintData* SkeletonData::findPathConstraint(std::string constraintName) + { + assert(constraintName.length() > 0); + + Vector pathConstraints = this.pathConstraints; + for (int i = 0, n = pathConstraints.Count; i < n; ++i) + { + PathConstraintData constraint = pathConstraints.Items[i]; + if (constraint.name.Equals(constraintName)) + { + return constraint; + } + } + + return NULL; + } + + int SkeletonData::findPathConstraintIndex(std::string pathConstraintName) + { + assert(pathConstraintName.length() > 0); + + Vector pathConstraints = this.pathConstraints; + for (int i = 0, n = pathConstraints.Count; i < n; ++i) + { + if (pathConstraints.Items[i].name.Equals(pathConstraintName)) + { + return i; + } + } + + return -1; + } + + std::string SkeletonData::getName() { return _name; } + + void SkeletonData::setName(std::string inValue) { _name = inValue; } + + Vector& SkeletonData::getBones() { return _bones; } + + Vector& SkeletonData::getSlots() { return _slots; } + + Vector& SkeletonData::getSkins() { return _skins; } + + void SkeletonData::setSkins(Vector& inValue) { _skins = inValue; } + + Skin* SkeletonData::getDefaultSkin() { return _defaultSkin; } + + void SkeletonData::setDefaultSkin(Skin* inValue) { _defaultSkin = inValue; } + + Vector& SkeletonData::getEvents() { return _events; } + + void SkeletonData::setEvents(Vector& inValue) { _events = inValue; } + + Vector& SkeletonData::getAnimations() { return _animations; } + + void SkeletonData::setAnimations(Vector& inValue) { _animations = inValue; } + + Vector& SkeletonData::getIkConstraints() { return _ikConstraints; } + + void SkeletonData::setIkConstraints(Vector& inValue) { _ikConstraints = inValue; } + + Vector& SkeletonData::getTransformConstraints() { return _transformConstraints; } + + void SkeletonData::setTransformConstraints(Vector& inValue) { _transformConstraints = inValue; } + + Vector& SkeletonData::getPathConstraints() { return _pathConstraints; } + + void SkeletonData::setPathConstraints(Vector& inValue) { _pathConstraints = inValue; } + + float SkeletonData::getWidth() { return _width; } + + void SkeletonData::setWidth(float inValue) { _width = inValue; } + + float SkeletonData::getHeight() { return _height; } + + void SkeletonData::setHeight(float inValue) { _height = inValue; } + + /// The Spine version used to export this data, or NULL. + std::string SkeletonData::getVersion() { return _version; } + + void SkeletonData::setVersion(std::string inValue) { _version = inValue; } + + std::string SkeletonData::getHash() { return _hash; } + + void SkeletonData::setHash(std::string inValue) { _hash = inValue; } + + std::string SkeletonData::getImagesPath() { return _imagesPath; } + + void SkeletonData::setImagesPath(std::string inValue) { _imagesPath = inValue; } + + /// The dopesheet FPS in Spine. Available only when nonessential data was exported. + float SkeletonData::getFps { return _fps; } + + void SkeletonData::setFps(float inValue) { _fps = inValue; } } diff --git a/spine-cpp/spine-cpp/src/spine/Skin.cpp b/spine-cpp/spine-cpp/src/spine/Skin.cpp index 949ac6504..291ded0bf 100644 --- a/spine-cpp/spine-cpp/src/spine/Skin.cpp +++ b/spine-cpp/spine-cpp/src/spine/Skin.cpp @@ -77,7 +77,7 @@ namespace Spine return ret; } - void Skin::findNamesForSlot(int slotIndex, SimpleArray& names) + void Skin::findNamesForSlot(int slotIndex, Vector& names) { for (HashMap::Iterator i = _attachments.begin(); i != _attachments.end(); ++i) { @@ -88,7 +88,7 @@ namespace Spine } } - void Skin::findAttachmentsForSlot(int slotIndex, SimpleArray& attachments) + void Skin::findAttachmentsForSlot(int slotIndex, Vector& attachments) { for (HashMap::Iterator i = _attachments.begin(); i != _attachments.end(); ++i) { diff --git a/spine-cpp/spine-cpp/src/spine/Slot.cpp b/spine-cpp/spine-cpp/src/spine/Slot.cpp index c9ee69fb1..e4bc6b1e7 100644 --- a/spine-cpp/spine-cpp/src/spine/Slot.cpp +++ b/spine-cpp/spine-cpp/src/spine/Slot.cpp @@ -196,12 +196,12 @@ namespace Spine _attachmentTime = _skeleton.getTime() - inValue; } - SimpleArray& Slot::getAttachmentVertices() + Vector& Slot::getAttachmentVertices() { return _attachmentVertices; } - void Slot::setAttachmentVertices(SimpleArray inValue) + void Slot::setAttachmentVertices(Vector inValue) { _attachmentVertices = inValue; } diff --git a/spine-cpp/spine-cpp/src/spine/TransformConstraintData.cpp b/spine-cpp/spine-cpp/src/spine/TransformConstraintData.cpp index d67e2e1b9..6a9942c32 100644 --- a/spine-cpp/spine-cpp/src/spine/TransformConstraintData.cpp +++ b/spine-cpp/spine-cpp/src/spine/TransformConstraintData.cpp @@ -65,7 +65,7 @@ namespace Spine { return _order; } - SimpleArray& TransformConstraintData::getBones() + Vector& TransformConstraintData::getBones() { return _bones; } From d7a569d47d3f6613f360d3855698dedb4060ae3b Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Sun, 22 Oct 2017 21:08:29 -0400 Subject: [PATCH 17/83] wip --- .../spine-cpp/include/spine/Attachment.h | 4 + spine-cpp/spine-cpp/include/spine/Bone.h | 4 +- spine-cpp/spine-cpp/include/spine/BoneData.h | 6 +- .../spine-cpp/include/spine/ContainerUtil.h | 41 ++ .../spine-cpp/include/spine/IkConstraint.h | 50 +- .../include/spine/IkConstraintData.h | 4 +- spine-cpp/spine-cpp/include/spine/MathUtil.h | 2 +- .../spine-cpp/include/spine/PathConstraint.h | 67 +- spine-cpp/spine-cpp/include/spine/Skeleton.h | 4 +- spine-cpp/spine-cpp/include/spine/SlotData.h | 4 +- .../include/spine/TransformConstraint.h | 53 +- .../include/spine/TransformConstraintData.h | 2 + .../include/spine/VertexAttachment.h | 83 +++ spine-cpp/spine-cpp/src/spine/Attachment.cpp | 2 + spine-cpp/spine-cpp/src/spine/Bone.cpp | 14 +- spine-cpp/spine-cpp/src/spine/BoneData.cpp | 2 +- .../spine-cpp/src/spine/CurveTimeline.cpp | 2 +- .../spine-cpp/src/spine/IkConstraint.cpp | 328 +++++++++- .../spine-cpp/src/spine/IkConstraintData.cpp | 2 + .../spine-cpp/src/spine/PathConstraint.cpp | 601 +++++++++++++++++- spine-cpp/spine-cpp/src/spine/Skeleton.cpp | 77 ++- .../spine-cpp/src/spine/SkeletonData.cpp | 302 ++++----- spine-cpp/spine-cpp/src/spine/Skin.cpp | 2 +- .../src/spine/TransformConstraint.cpp | 416 +++++++++++- .../spine-cpp/src/spine/VertexAttachment.cpp | 163 +++++ 25 files changed, 2014 insertions(+), 221 deletions(-) create mode 100644 spine-cpp/spine-cpp/include/spine/VertexAttachment.h create mode 100644 spine-cpp/spine-cpp/src/spine/VertexAttachment.cpp diff --git a/spine-cpp/spine-cpp/include/spine/Attachment.h b/spine-cpp/spine-cpp/include/spine/Attachment.h index 9f9f8460d..fdf5a1a58 100644 --- a/spine-cpp/spine-cpp/include/spine/Attachment.h +++ b/spine-cpp/spine-cpp/include/spine/Attachment.h @@ -31,12 +31,16 @@ #ifndef Spine_Attachment_h #define Spine_Attachment_h +#include + #include namespace Spine { class Attachment { + RTTI_DECL; + public: Attachment(std::string name); diff --git a/spine-cpp/spine-cpp/include/spine/Bone.h b/spine-cpp/spine-cpp/include/spine/Bone.h index e189750b2..46c04d3a5 100644 --- a/spine-cpp/spine-cpp/include/spine/Bone.h +++ b/spine-cpp/spine-cpp/include/spine/Bone.h @@ -48,6 +48,8 @@ namespace Spine class Bone : public Updatable { friend class RotateTimeline; + friend class IkConstraint; + friend class TransformConstraint; public: static void setYDown(bool inValue); @@ -55,7 +57,7 @@ namespace Spine static bool isYDown(); /// @param parent May be NULL. - Bone(BoneData& data, Skeleton& skeleton, Bone* parent); + Bone(BoneData& data, Skeleton& skeleton, Bone* parent = NULL); /// Same as updateWorldTransform. This method exists for Bone to implement Spine::Updatable. virtual void update(); diff --git a/spine-cpp/spine-cpp/include/spine/BoneData.h b/spine-cpp/spine-cpp/include/spine/BoneData.h index 292f4a4c4..9710eda27 100644 --- a/spine-cpp/spine-cpp/include/spine/BoneData.h +++ b/spine-cpp/spine-cpp/include/spine/BoneData.h @@ -40,7 +40,7 @@ namespace Spine class BoneData { public: - BoneData(int index, std::string name, BoneData* parent); + BoneData(int index, std::string name, BoneData* parent = NULL); /// The index of the bone in Skeleton.Bones const int getIndex(); @@ -49,7 +49,7 @@ namespace Spine const std::string& getName(); /// May be NULL. - const BoneData* getParent(); + BoneData* getParent(); float getLength(); void setLength(float inValue); @@ -89,7 +89,7 @@ namespace Spine private: const int _index; const std::string _name; - const BoneData* _parent; + BoneData* _parent; float _length; float _x, _y, _rotation, _scaleX, _scaleY, _shearX, _shearY; TransformMode _transformMode; diff --git a/spine-cpp/spine-cpp/include/spine/ContainerUtil.h b/spine-cpp/spine-cpp/include/spine/ContainerUtil.h index ecc52e168..11d8e34e6 100644 --- a/spine-cpp/spine-cpp/include/spine/ContainerUtil.h +++ b/spine-cpp/spine-cpp/include/spine/ContainerUtil.h @@ -34,11 +34,52 @@ #include #include +#include +#include + namespace Spine { class ContainerUtil { public: + /// Finds an item by comparing each item's name. + /// It is more efficient to cache the results of this method than to call it multiple times. + /// @return May be NULL. + template + static T* findWithName(Vector& items, std::string name) + { + assert(name.length() > 0); + + for (typename T* i = items.begin(); i != items.end(); ++i) + { + T* item = (*i); + if (item->getName() == name) + { + return item; + } + } + + return NULL; + } + + /// @return -1 if the item was not found. + template + static int findIndexWithName(Vector& items, std::string name) + { + assert(name.length() > 0); + + for (size_t i = 0, size_t len = items.size(); i < len; ++i) + { + T* item = items[i]; + if (item->getName() == name) + { + return i; + } + } + + return -1; + } + template static void cleanUpVectorOfPointers(Vector& items) { diff --git a/spine-cpp/spine-cpp/include/spine/IkConstraint.h b/spine-cpp/spine-cpp/include/spine/IkConstraint.h index c0acf47be..b7359ea7b 100644 --- a/spine-cpp/spine-cpp/include/spine/IkConstraint.h +++ b/spine-cpp/spine-cpp/include/spine/IkConstraint.h @@ -31,9 +31,57 @@ #ifndef Spine_IkConstraint_h #define Spine_IkConstraint_h +#include + +#include + namespace Spine { - // TODO + class IkConstraintData; + class Skeleton; + class Bone; + + class IkConstraint : public Constraint + { + public: + /// Adjusts the bone rotation so the tip is as close to the target position as possible. The target is specified + /// in the world coordinate system. + static void apply(Bone& bone, float targetX, float targetY, float alpha); + + /// Adjusts the parent and child bone rotations so the tip of the child is as close to the target position as + /// possible. The target is specified in the world coordinate system. + /// @param child A direct descendant of the parent bone. + static void apply(Bone& parent, Bone& child, float targetX, float targetY, int bendDir, float alpha); + + IkConstraint(IkConstraintData& data, Skeleton& skeleton); + + /// Applies the constraint to the constrained bones. + void apply(); + + virtual void update(); + + virtual int getOrder(); + + IkConstraintData& getData(); + + Vector& getBones(); + + Bone* getTarget(); + void setTarget(Bone* inValue); + + int getBendDirection(); + void setBendDirection(int inValue); + + float getMix(); + void setMix(float inValue); + + private: + IkConstraintData& _data; + Vector _bones; + Bone* _target; + float _mix; + int _bendDirection; + }; } #endif /* Spine_IkConstraint_h */ diff --git a/spine-cpp/spine-cpp/include/spine/IkConstraintData.h b/spine-cpp/spine-cpp/include/spine/IkConstraintData.h index 4f231f711..521101734 100644 --- a/spine-cpp/spine-cpp/include/spine/IkConstraintData.h +++ b/spine-cpp/spine-cpp/include/spine/IkConstraintData.h @@ -35,10 +35,10 @@ #include -class BoneData; - namespace Spine { + class BoneData; + class IkConstraintData { public: diff --git a/spine-cpp/spine-cpp/include/spine/MathUtil.h b/spine-cpp/spine-cpp/include/spine/MathUtil.h index a87a42d04..bc9bc5851 100644 --- a/spine-cpp/spine-cpp/include/spine/MathUtil.h +++ b/spine-cpp/spine-cpp/include/spine/MathUtil.h @@ -35,7 +35,7 @@ #include #define SPINE_PI 3.1415927f -#define SPINE_PI_2 PI * 2 +#define SPINE_PI_2 SPINE_PI * 2 #define RadDeg 180.0f / SPINE_PI #define DegRad SPINE_PI / 180.0f #define SIN_BITS 14 // 16KB. Adjust for accuracy. diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraint.h b/spine-cpp/spine-cpp/include/spine/PathConstraint.h index 374875876..464622a3d 100644 --- a/spine-cpp/spine-cpp/include/spine/PathConstraint.h +++ b/spine-cpp/spine-cpp/include/spine/PathConstraint.h @@ -31,9 +31,74 @@ #ifndef Spine_PathConstraint_h #define Spine_PathConstraint_h +#include + +#include + namespace Spine { - // TODO + class PathConstraintData; + class Skeleton; + class PathAttachment; + class Bone; + class Slot; + + class PathConstraint : public Constraint + { + PathConstraint(PathConstraintData& data, Skeleton& skeleton); + + /// Applies the constraint to the constrained bones. + void apply(); + + virtual void update(); + + virtual int getOrder(); + + float getPosition(); + void setPosition(float inValue); + + float getSpacing(); + void setSpacing(float inValue); + + float getRotateMix(); + void setRotateMix(float inValue); + + float getTranslateMix(); + void setTranslateMix(float inValue); + + Vector& getBones(); + + Slot* getTarget(); + void setTarget(Slot* inValue); + + PathConstraintData& getData(); + + private: + static const float EPSILON; + static const int NONE; + static const int BEFORE; + static const int AFTER; + + PathConstraintData& _data; + Vector _bones; + Slot* _target; + float _position, _spacing, _rotateMix, _translateMix; + + Vector _spaces; + Vector _positions; + Vector _world; + Vector _curves; + Vector _lengths; + Vector _segments; + + Vector computeWorldPositions(PathAttachment& path, int spacesCount, bool tangents, bool percentPosition, bool percentSpacing); + + static void addBeforePosition(float p, Vector& temp, int i, Vector& output, int o); + + static void addAfterPosition(float p, Vector& temp, int i, Vector& output, int o); + + static void addCurvePosition(float p, float x1, float y1, float cx1, float cy1, float cx2, float cy2, float x2, float y2, Vector& output, int o, bool tangents); + }; } #endif /* Spine_PathConstraint_h */ diff --git a/spine-cpp/spine-cpp/include/spine/Skeleton.h b/spine-cpp/spine-cpp/include/spine/Skeleton.h index cbc6cdfbd..5c4f3e782 100644 --- a/spine-cpp/spine-cpp/include/spine/Skeleton.h +++ b/spine-cpp/spine-cpp/include/spine/Skeleton.h @@ -54,6 +54,8 @@ namespace Spine public: Skeleton(SkeletonData& data); + ~Skeleton(); + /// Caches information about bones and constraints. Must be called if bones, constraints or weighted path attachments are added /// or removed. void updateCache(); @@ -155,7 +157,7 @@ namespace Spine void setFlipY(float inValue); private: - const SkeletonData& _data; + SkeletonData& _data; Vector _bones; Vector _slots; Vector _drawOrder; diff --git a/spine-cpp/spine-cpp/include/spine/SlotData.h b/spine-cpp/spine-cpp/include/spine/SlotData.h index e843d545c..310cf1fd5 100644 --- a/spine-cpp/spine-cpp/include/spine/SlotData.h +++ b/spine-cpp/spine-cpp/include/spine/SlotData.h @@ -48,7 +48,7 @@ namespace Spine const std::string& getName(); - const BoneData& getBoneData(); + BoneData& getBoneData(); float getR(); void setR(float inValue); @@ -78,7 +78,7 @@ namespace Spine private: const int _index; const std::string _name; - const BoneData& _boneData; + BoneData& _boneData; float _r, _g, _b, _a; float _r2, _g2, _b2; bool _hasSecondColor; diff --git a/spine-cpp/spine-cpp/include/spine/TransformConstraint.h b/spine-cpp/spine-cpp/include/spine/TransformConstraint.h index 54a3585dd..550988911 100644 --- a/spine-cpp/spine-cpp/include/spine/TransformConstraint.h +++ b/spine-cpp/spine-cpp/include/spine/TransformConstraint.h @@ -31,9 +31,60 @@ #ifndef Spine_TransformConstraint_h #define Spine_TransformConstraint_h +#include + +#include + namespace Spine { - // TODO + class TransformConstraintData; + class Skeleton; + class Bone; + + class TransformConstraint : public Constraint + { + public: + TransformConstraint(TransformConstraintData& data, Skeleton& skeleton); + + void apply(); + + virtual void update(); + + virtual int getOrder(); + + TransformConstraintData& getData(); + + Vector& getBones(); + + Bone* getTarget(); + void setTarget(Bone* inValue); + + float getRotateMix(); + void setRotateMix(float inValue); + + float getTranslateMix(); + void setTranslateMix(float inValue); + + float getScaleMix(); + void setScaleMix(float inValue); + + float getShearMix(); + void setShearMix(float inValue); + + private: + TransformConstraintData& _data; + Vector _bones; + Bone* _target; + float _rotateMix, _translateMix, _scaleMix, _shearMix; + + void applyAbsoluteWorld(); + + void applyRelativeWorld(); + + void applyAbsoluteLocal(); + + void applyRelativeLocal(); + }; } #endif /* Spine_TransformConstraint_h */ diff --git a/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h b/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h index eb978ad6c..c74bc25bc 100644 --- a/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h +++ b/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h @@ -41,6 +41,8 @@ namespace Spine class TransformConstraintData { + friend class TransformConstraint; + public: TransformConstraintData(std::string name); diff --git a/spine-cpp/spine-cpp/include/spine/VertexAttachment.h b/spine-cpp/spine-cpp/include/spine/VertexAttachment.h new file mode 100644 index 000000000..18b5fc81c --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/VertexAttachment.h @@ -0,0 +1,83 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_VertexAttachment_h +#define Spine_VertexAttachment_h + +#include + +#include + +namespace Spine +{ + class Slot; + + /// An attachment with vertices that are transformed by one or more bones and can be deformed by a slot's vertices. + class VertexAttachment : Attachment + { + public: + VertexAttachment(std::string name); + + void computeWorldVertices(Slot& slot, Vector& worldVertices); + + /// Transforms local vertices to world coordinates. + /// @param start The index of the first Vertices value to transform. Each vertex has 2 values, x and y. + /// @param count The number of world vertex values to output. Must be less than or equal to WorldVerticesLength - start. + /// @param worldVertices The output world vertices. Must have a length greater than or equal to offset + count. + /// @param offset The worldVertices index to begin writing values. + /// @param stride The number of worldVertices entries between the value pairs written. + void computeWorldVertices(Slot& slot, int start, int count, Vector& worldVertices, int offset, int stride = 2); + + /// @return true if a deform originally applied to the specified attachment should be applied to this attachment. + virtual bool applyDeform(VertexAttachment* sourceAttachment); + + /// Gets a unique ID for this attachment. + int getId(); + + Vector getBones(); + void setBones(Vector inValue); + + Vector getVertices(); + void setVertices(Vector inValue); + + int getWorldVerticesLength(); + void setWorldVerticesLength(int inValue); + + private: + const int _id; + Vector _bones; + Vector _vertices; + int _worldVerticesLength; + + static int getNextID(); + }; +} + +#endif /* Spine_VertexAttachment_h */ diff --git a/spine-cpp/spine-cpp/src/spine/Attachment.cpp b/spine-cpp/spine-cpp/src/spine/Attachment.cpp index fdd42ea70..829f8c7d6 100644 --- a/spine-cpp/spine-cpp/src/spine/Attachment.cpp +++ b/spine-cpp/spine-cpp/src/spine/Attachment.cpp @@ -43,4 +43,6 @@ namespace Spine { return _name; } + + RTTI_IMPL_NOPARENT(Attachment); } diff --git a/spine-cpp/spine-cpp/src/spine/Bone.cpp b/spine-cpp/spine-cpp/src/spine/Bone.cpp index a2dacdbe8..f4fe9ed59 100644 --- a/spine-cpp/spine-cpp/src/spine/Bone.cpp +++ b/spine-cpp/spine-cpp/src/spine/Bone.cpp @@ -111,14 +111,14 @@ namespace Spine float lb = MathUtil::cosDeg(rotationY) * scaleY; float lc = MathUtil::sinDeg(rotation + shearX) * scaleX; float ld = MathUtil::sinDeg(rotationY) * scaleY; - if (_skeleton.isFlipX()) + if (_skeleton.getFlipX()) { x = -x; la = -la; lb = -lb; } - if (_skeleton.isFlipY() != Bone::isYDown()) + if (_skeleton.getFlipY() != Bone::isYDown()) { y = -y; lc = -lc; @@ -223,7 +223,7 @@ namespace Spine float lc = MathUtil::sinDeg(shearX) * scaleX; float ld = MathUtil::sinDeg(90 + shearY) * scaleY; - if (_data.getTransformMode() != TransformMode_NoScaleOrReflection ? pa * pd - pb * pc < 0 : _skeleton.isFlipX() != _skeleton.isFlipY()) + if (_data.getTransformMode() != TransformMode_NoScaleOrReflection ? pa * pd - pb * pc < 0 : _skeleton.getFlipX() != _skeleton.getFlipY()) { zb = -zb; zd = -zd; @@ -238,16 +238,16 @@ namespace Spine } } - if (_skeleton.isFlipX()) + if (_skeleton.getFlipX()) { _a = -_a; _b = -_b; } - if (skeleton.isFlipY() != Bone::isYDown()) + if (skeleton.getFlipY() != Bone::isYDown()) { - c = -c; - d = -d; + _c = -_c; + _d = -_d; } } diff --git a/spine-cpp/spine-cpp/src/spine/BoneData.cpp b/spine-cpp/spine-cpp/src/spine/BoneData.cpp index ed87124ff..47278ea6e 100644 --- a/spine-cpp/spine-cpp/src/spine/BoneData.cpp +++ b/spine-cpp/spine-cpp/src/spine/BoneData.cpp @@ -62,7 +62,7 @@ namespace Spine return _name; } - const BoneData* BoneData::getParent() + BoneData* BoneData::getParent() { return _parent; } diff --git a/spine-cpp/spine-cpp/src/spine/CurveTimeline.cpp b/spine-cpp/spine-cpp/src/spine/CurveTimeline.cpp index de9f96e64..67c0435cf 100644 --- a/spine-cpp/spine-cpp/src/spine/CurveTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/CurveTimeline.cpp @@ -48,7 +48,7 @@ namespace Spine int CurveTimeline::getFrameCount() { - return _curves.size() / BEZIER_SIZE + 1; + return static_cast(_curves.size() / BEZIER_SIZE + 1); } void CurveTimeline::setLinear(int frameIndex) diff --git a/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp b/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp index bb4d2ccfe..73e68082d 100644 --- a/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp +++ b/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp @@ -28,7 +28,333 @@ * POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ +#include + +#include +#include +#include + +#include +#include + namespace Spine { - // TODO + void IkConstraint::apply(Bone& bone, float targetX, float targetY, float alpha) + { + if (!bone._appliedValid) + { + bone.updateAppliedTransform(); + } + + Bone* parent = bone.getParent(); + Bone p = *parent; + + float id = 1 / (p._a * p._d - p._b * p._c); + float x = targetX - p._worldX, y = targetY - p._worldY; + float tx = (x * p._d - y * p._b) * id - bone._ax, ty = (y * p._a - x * p._c) * id - bone._ay; + float rotationIK = (float)atan2(ty, tx) * RadDeg - bone._ashearX - bone._arotation; + + if (bone._ascaleX < 0) + { + rotationIK += 180; + } + + if (rotationIK > 180) + { + rotationIK -= 360; + } + else if (rotationIK < -180) + { + rotationIK += 360; + } + + bone.updateWorldTransform(bone._ax, bone._ay, bone._arotation + rotationIK * alpha, bone._ascaleX, bone._ascaleY, bone._ashearX, bone._ashearY); + } + + void IkConstraint::apply(Bone& parent, Bone& child, float targetX, float targetY, int bendDir, float alpha) + { + if (areFloatsPracticallyEqual(alpha, 0)) + { + child.updateWorldTransform(); + + return; + } + + if (!parent._appliedValid) + { + parent.updateAppliedTransform(); + } + + if (!child._appliedValid) + { + child.updateAppliedTransform(); + } + + float px = parent._ax; + float py = parent._ay; + float psx = parent._ascaleX; + float psy = parent._ascaleY; + float csx = child._ascaleX; + + int os1, os2, s2; + if (psx < 0) + { + psx = -psx; + os1 = 180; + s2 = -1; + } + else + { + os1 = 0; + s2 = 1; + } + + if (psy < 0) + { + psy = -psy; + s2 = -s2; + } + + if (csx < 0) + { + csx = -csx; + os2 = 180; + } + else + { + os2 = 0; + } + + float cx = child._ax; + float cy; + float cwx; + float cwy; + float a = parent._a; + float b = parent._b; + float c = parent._c; + float d = parent._d; + + bool u = fabs(psx - psy) <= 0.0001f; + if (!u) + { + cy = 0; + cwx = a * cx + parent._worldX; + cwy = c * cx + parent._worldY; + } + else + { + cy = child._ay; + cwx = a * cx + b * cy + parent._worldX; + cwy = c * cx + d * cy + parent._worldY; + } + + Bone* parentparent = parent._parent; + Bone pp = *parentparent; + + a = pp._a; + b = pp._b; + c = pp._c; + d = pp._d; + + float id = 1 / (a * d - b * c), x = targetX - pp._worldX, y = targetY - pp._worldY; + float tx = (x * d - y * b) * id - px, ty = (y * a - x * c) * id - py; + x = cwx - pp._worldX; + y = cwy - pp._worldY; + float dx = (x * d - y * b) * id - px, dy = (y * a - x * c) * id - py; + float l1 = (float)sqrt(dx * dx + dy * dy), l2 = child._data.getLength() * csx, a1, a2; + if (u) + { + l2 *= psx; + float cos = (tx * tx + ty * ty - l1 * l1 - l2 * l2) / (2 * l1 * l2); + if (cos < -1) + { + cos = -1; + } + else if (cos > 1) + { + cos = 1; + } + + a2 = (float)acos(cos) * bendDir; + a = l1 + l2 * cos; + b = l2 * (float)sin(a2); + a1 = (float)atan2(ty * a - tx * b, tx * a + ty * b); + } + else + { + a = psx * l2; + b = psy * l2; + float aa = a * a, bb = b * b, dd = tx * tx + ty * ty, ta = (float)atan2(ty, tx); + c = bb * l1 * l1 + aa * dd - aa * bb; + float c1 = -2 * bb * l1, c2 = bb - aa; + d = c1 * c1 - 4 * c2 * c; + if (d >= 0) + { + float q = (float)sqrt(d); + if (c1 < 0) q = -q; + q = -(c1 + q) / 2; + float r0 = q / c2, r1 = c / q; + float r = fabs(r0) < fabs(r1) ? r0 : r1; + if (r * r <= dd) + { + y = (float)sqrt(dd - r * r) * bendDir; + a1 = ta - (float)atan2(y, r); + a2 = (float)atan2(y / psy, (r - l1) / psx); + + float os = (float)atan2(cy, cx) * s2; + float rotation = parent._arotation; + a1 = (a1 - os) * RadDeg + os1 - rotation; + if (a1 > 180) + { + a1 -= 360; + } + else if (a1 < -180) + { + a1 += 360; + } + + parent.updateWorldTransform(px, py, rotation + a1 * alpha, parent._scaleX, parent._ascaleY, 0, 0); + rotation = child._arotation; + a2 = ((a2 + os) * RadDeg - child._ashearX) * s2 + os2 - rotation; + + if (a2 > 180) + { + a2 -= 360; + } + else if (a2 < -180) + { + a2 += 360; + } + + child.updateWorldTransform(cx, cy, rotation + a2 * alpha, child._ascaleX, child._ascaleY, child._ashearX, child._ashearY); + + return; + } + } + + float minAngle = SPINE_PI, minX = l1 - a, minDist = minX * minX, minY = 0; + float maxAngle = 0, maxX = l1 + a, maxDist = maxX * maxX, maxY = 0; + c = -a * l1 / (aa - bb); + if (c >= -1 && c <= 1) + { + c = (float)acos(c); + x = a * (float)cos(c) + l1; + y = b * (float)sin(c); + d = x * x + y * y; + + if (d < minDist) + { + minAngle = c; + minDist = d; + minX = x; + minY = y; + } + + if (d > maxDist) + { + maxAngle = c; + maxDist = d; + maxX = x; + maxY = y; + } + } + + if (dd <= (minDist + maxDist) / 2) + { + a1 = ta - (float)atan2(minY * bendDir, minX); + a2 = minAngle * bendDir; + } + else + { + a1 = ta - (float)atan2(maxY * bendDir, maxX); + a2 = maxAngle * bendDir; + } + } + } + + IkConstraint::IkConstraint(IkConstraintData& data, Skeleton& skeleton) : Constraint(), + _data(data), + _mix(data.getMix()), + _bendDirection(data.getBendDirection()), + _target(skeleton.findBone(data.getTarget()->getName())) + { + _bones.reserve(_data.getBones().size()); + for (BoneData** i = _data.getBones().begin(); i != _data.getBones().end(); ++i) + { + BoneData* boneData = (*i); + + _bones.push_back(skeleton.findBone(boneData->getName())); + } + } + + /// Applies the constraint to the constrained bones. + void IkConstraint::apply() + { + update(); + } + + void IkConstraint::update() + { + switch (_bones.size()) + { + case 1: + { + Bone* bone0 = _bones[0]; + apply(*bone0, _target->getWorldX(), _target->getWorldY(), _mix); + } + break; + case 2: + { + Bone* bone0 = _bones[0]; + Bone* bone1 = _bones[1]; + apply(*bone0, *bone1, _target->getWorldX(), _target->getWorldY(), _bendDirection, _mix); + } + break; + } + } + + int IkConstraint::getOrder() + { + return _data.getOrder(); + } + + IkConstraintData& IkConstraint::getData() + { + return _data; + } + + Vector& IkConstraint::getBones() + { + return _bones; + } + + Bone* IkConstraint::getTarget() + { + return _target; + } + + void IkConstraint::setTarget(Bone* inValue) + { + _target = inValue; + } + + int IkConstraint::getBendDirection() + { + return _bendDirection; + } + + void IkConstraint::setBendDirection(int inValue) + { + _bendDirection = inValue; + } + + float IkConstraint::getMix() + { + return _mix; + } + + void IkConstraint::setMix(float inValue) + { + _mix = inValue; + } } diff --git a/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp b/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp index 4f84d1f83..13378993f 100644 --- a/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp +++ b/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp @@ -30,6 +30,8 @@ #include +#include + namespace Spine { IkConstraintData::IkConstraintData(std::string name) : diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp b/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp index bb4d2ccfe..32e688782 100644 --- a/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp @@ -28,7 +28,606 @@ * POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + namespace Spine { - // TODO + const float PathConstraint::EPSILON = 0.00001f; + const int PathConstraint::NONE = -1; + const int PathConstraint::BEFORE = -2; + const int PathConstraint::AFTER = -3; + + PathConstraint::PathConstraint(PathConstraintData& data, Skeleton& skeleton) : Constraint(), + _data(data), + _position(data.getPosition()), + _spacing(data.getSpacing()), + _rotateMix(data.getRotateMix()), + _translateMix(data.getTranslateMix()), + _target(skeleton.findSlot(data.getTarget()->getName())) + { + _bones.reserve(_data.getBones().size()); + for (BoneData** i = _data.getBones().begin(); i != _data.getBones().end(); ++i) + { + BoneData* boneData = (*i); + + _bones.push_back(skeleton.findBone(boneData->getName())); + } + + _segments.reserve(10); + } + + void PathConstraint::apply() + { + update(); + } + + void PathConstraint::update() + { + Attachment* baseAttachment = _target->getAttachment(); + if (baseAttachment == NULL || !baseAttachment->getRTTI().derivesFrom(PathAttachment::rtti)) + { + return; + } + + PathAttachment* attachment = static_cast(baseAttachment); + + float rotateMix = _rotateMix; + float translateMix = _translateMix; + bool translate = translateMix > 0; + bool rotate = rotateMix > 0; + if (!translate && !rotate) + { + return; + } + + PathConstraintData data = _data; + SpacingMode spacingMode = data.spacingMode; + bool lengthSpacing = spacingMode == SpacingMode.Length; + RotateMode rotateMode = data.rotateMode; + bool tangents = rotateMode == RotateMode_Tangent, scale = rotateMode == RotateMode_ChainScale; + int boneCount = _bones.Count, spacesCount = tangents ? boneCount : boneCount + 1; + Bone[] bonesItems = _bones.Items; + Vector spaces = _spaces.Resize(spacesCount), lengths = NULL; + float spacing = _spacing; + if (scale || lengthSpacing) + { + if (scale) + { + lengths = _lengths.Resize(boneCount); + } + + for (int i = 0, n = spacesCount - 1; i < n;) + { + Bone bone = bonesItems[i]; + float setupLength = bone.data.length; + if (setupLength < PathConstraint.EPSILON) + { + if (scale) + { + lengths.Items[i] = 0; + } + spaces.Items[++i] = 0; + } + else + { + float x = setupLength * bone.a, y = setupLength * bone.c; + float length = (float)Math.Sqrt(x * x + y * y); + if (scale) + { + lengths.Items[i] = length; + } + spaces.Items[++i] = (lengthSpacing ? setupLength + spacing : spacing) * length / setupLength; + } + } + } + else + { + for (int i = 1; i < spacesCount; ++i) + { + spaces.Items[i] = spacing; + } + } + + float[] positions = computeWorldPositions(attachment, spacesCount, tangents, data.positionMode == PositionMode_Percent, spacingMode == SpacingMode_Percent); + float boneX = positions[0], boneY = positions[1], offsetRotation = data.offsetRotation; + bool tip; + if (offsetRotation == 0) + { + tip = rotateMode == RotateMode_Chain; + } + else + { + tip = false; + Bone p = target.bone; + offsetRotation *= p.a * p.d - p.b * p.c > 0 ? DegRad : -DegRad; + } + + for (int i = 0, p = 3; i < boneCount; i++, p += 3) + { + Bone bone = bonesItems[i]; + bone.worldX += (boneX - bone.worldX) * translateMix; + bone.worldY += (boneY - bone.worldY) * translateMix; + float x = positions[p], y = positions[p + 1], dx = x - boneX, dy = y - boneY; + if (scale) + { + float length = lengths.Items[i]; + if (length >= PathConstraint.EPSILON) + { + float s = ((float)Math.Sqrt(dx * dx + dy * dy) / length - 1) * rotateMix + 1; + bone.a *= s; + bone.c *= s; + } + } + + boneX = x; + boneY = y; + + if (rotate) + { + float a = bone.a, b = bone.b, c = bone.c, d = bone.d, r, cos, sin; + if (tangents) + { + r = positions[p - 1]; + } + else if (spaces.Items[i + 1] < PathConstraint.EPSILON) + { + r = positions[p + 2]; + } + else + { + r = MathUtil::atan2(dy, dx); + } + + r -= MathUtil::atan2(c, a); + + if (tip) + { + cos = MathUtil::cos(r); + sin = MathUtil::sin(r); + float length = bone.data.length; + boneX += (length * (cos * a - sin * c) - dx) * rotateMix; + boneY += (length * (sin * a + cos * c) - dy) * rotateMix; + } + else + { + r += offsetRotation; + } + + if (r > SPINE_PI) + { + r -= SPINE_PI_2; + } + else if (r < -SPINE_PI) + { + r += SPINE_PI_2; + } + + r *= rotateMix; + cos = MathUtil::cos(r); + sin = MathUtil::sin(r); + bone.a = cos * a - sin * c; + bone.b = cos * b - sin * d; + bone.c = sin * a + cos * c; + bone.d = sin * b + cos * d; + } + bone.appliedValid = false; + } + } + + int PathConstraint::getOrder() + { + return _data.getOrder(); + } + + float PathConstraint::getPosition() + { + return _position; + } + + void PathConstraint::setPosition(float inValue) + { + _position = inValue; + } + + float PathConstraint::getSpacing() + { + return _spacing; + } + + void PathConstraint::setSpacing(float inValue) + { + _spacing = inValue; + } + + float PathConstraint::getRotateMix() + { + return _rotateMix; + } + + void PathConstraint::setRotateMix(float inValue) + { + _rotateMix = inValue; + } + + float PathConstraint::getTranslateMix() + { + return _translateMix; + } + + void PathConstraint::setTranslateMix(float inValue) + { + _translateMix = inValue; + } + + Vector& PathConstraint::getBones() + { + return _bones; + } + + Slot* PathConstraint::getTarget() + { + return _target; + } + + void PathConstraint::setTarget(Slot* inValue) + { + _target = inValue; + } + + PathConstraintData& PathConstraint::getData() + { + return _data; + } + + Vector PathConstraint::computeWorldPositions(PathAttachment& path, int spacesCount, bool tangents, bool percentPosition, bool percentSpacing) + { + Slot target = *_target; + float position = _position; + float[] spacesItems = _spaces.Items, output = _positions.Resize(spacesCount * 3 + 2).Items, world; + bool closed = path.Closed; + int verticesLength = path.WorldVerticesLength, curveCount = verticesLength / 6, prevCurve = NONE; + + float pathLength; + if (!path.ConstantSpeed) + { + float[] lengths = path.Lengths; + curveCount -= closed ? 1 : 2; + pathLength = lengths[curveCount]; + if (percentPosition) + { + position *= pathLength; + } + + if (percentSpacing) + { + for (int i = 0; i < spacesCount; ++i) + { + spacesItems[i] *= pathLength; + } + } + + world = _world.Resize(8).Items; + for (int i = 0, o = 0, curve = 0; i < spacesCount; i++, o += 3) + { + float space = spacesItems[i]; + position += space; + float p = position; + + if (closed) + { + p %= pathLength; + if (p < 0) + { + p += pathLength; + } + curve = 0; + } + else if (p < 0) + { + if (prevCurve != BEFORE) + { + prevCurve = BEFORE; + path.ComputeWorldVertices(target, 2, 4, world, 0); + } + + addBeforePosition(p, world, 0, output, o); + + continue; + } + else if (p > pathLength) + { + if (prevCurve != AFTER) + { + prevCurve = AFTER; + path.ComputeWorldVertices(target, verticesLength - 6, 4, world, 0); + } + + addAfterPosition(p - pathLength, world, 0, output, 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) + { + path.ComputeWorldVertices(target, verticesLength - 4, 4, world, 0); + path.ComputeWorldVertices(target, 0, 4, world, 4); + } + else + { + path.ComputeWorldVertices(target, curve * 6 + 2, 8, world, 0); + } + } + + addCurvePosition(p, world[0], world[1], world[2], world[3], world[4], world[5], world[6], world[7], output, o, tangents || (i > 0 && space < EPSILON)); + } + return output; + } + + // World vertices. + if (closed) + { + verticesLength += 2; + world = _world.Resize(verticesLength).Items; + path.ComputeWorldVertices(target, 2, verticesLength - 4, world, 0); + path.ComputeWorldVertices(target, 0, 2, world, verticesLength - 4); + world[verticesLength - 2] = world[0]; + world[verticesLength - 1] = world[1]; + } + else + { + curveCount--; + verticesLength -= 4; + world = _world.Resize(verticesLength).Items; + path.ComputeWorldVertices(target, 2, verticesLength, world, 0); + } + + // Curve lengths. + float[] curves = _curves.Resize(curveCount).Items; + pathLength = 0; + float x1 = world[0], y1 = world[1], cx1 = 0, cy1 = 0, cx2 = 0, cy2 = 0, x2 = 0, y2 = 0; + float tmpx, tmpy, dddfx, dddfy, ddfx, ddfy, dfx, dfy; + for (int 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 += (float)Math.Sqrt(dfx * dfx + dfy * dfy); + dfx += ddfx; + dfy += ddfy; + ddfx += dddfx; + ddfy += dddfy; + pathLength += (float)Math.Sqrt(dfx * dfx + dfy * dfy); + dfx += ddfx; + dfy += ddfy; + pathLength += (float)Math.Sqrt(dfx * dfx + dfy * dfy); + dfx += ddfx + dddfx; + dfy += ddfy + dddfy; + pathLength += (float)Math.Sqrt(dfx * dfx + dfy * dfy); + curves[i] = pathLength; + x1 = x2; + y1 = y2; + } + + if (percentPosition) + { + position *= pathLength; + } + + if (percentSpacing) + { + for (int i = 0; i < spacesCount; ++i) + { + spacesItems[i] *= pathLength; + } + } + + float[] segments = _segments; + float curveLength = 0; + for (int i = 0, o = 0, curve = 0, segment = 0; i < spacesCount; i++, o += 3) + { + float space = spacesItems[i]; + position += space; + float p = position; + + if (closed) + { + p %= pathLength; + if (p < 0) + { + p += pathLength; + } + curve = 0; + } + else if (p < 0) + { + addBeforePosition(p, world, 0, output, o); + continue; + } + else if (p > pathLength) + { + addAfterPosition(p - pathLength, world, verticesLength - 4, output, 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) + { + prevCurve = curve; + int 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 = (float)Math.Sqrt(dfx * dfx + dfy * dfy); + segments[0] = curveLength; + for (ii = 1; ii < 8; ii++) + { + dfx += ddfx; + dfy += ddfy; + ddfx += dddfx; + ddfy += dddfy; + curveLength += (float)Math.Sqrt(dfx * dfx + dfy * dfy); + segments[ii] = curveLength; + } + dfx += ddfx; + dfy += ddfy; + curveLength += (float)Math.Sqrt(dfx * dfx + dfy * dfy); + segments[8] = curveLength; + dfx += ddfx + dddfx; + dfy += ddfy + dddfy; + curveLength += (float)Math.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, output, o, tangents || (i > 0 && space < EPSILON)); + } + + return output; + } + + void PathConstraint::addBeforePosition(float p, Vector& temp, int i, Vector& output, int o) + { + float x1 = temp[i]; + float y1 = temp[i + 1]; + float dx = temp[i + 2] - x1; + float dy = temp[i + 3] - y1; + float r = MathUtil::atan2(dy, dx); + + output[o] = x1 + p * MathUtil::cos(r); + output[o + 1] = y1 + p * MathUtil::sin(r); + output[o + 2] = r; + } + + void PathConstraint::addAfterPosition(float p, Vector& temp, int i, Vector& output, int o) + { + float x1 = temp[i + 2]; + float y1 = temp[i + 3]; + float dx = x1 - temp[i]; + float dy = y1 - temp[i + 1]; + float r = MathUtil::atan2(dy, dx); + output[o] = x1 + p * MathUtil::cos(r); + output[o + 1] = y1 + p * MathUtil::sin(r); + output[o + 2] = r; + } + + void PathConstraint::addCurvePosition(float p, float x1, float y1, float cx1, float cy1, float cx2, float cy2, float x2, float y2, Vector& output, int o, bool tangents) + { + if (p < EPSILON || float.IsNaN(p)) + { + p = EPSILON; + } + + float tt = p * p, ttt = tt * p, u = 1 - p, uu = u * u, uuu = uu * u; + float ut = u * p, ut3 = ut * 3, uut3 = u * ut3, utt3 = ut3 * p; + float x = x1 * uuu + cx1 * uut3 + cx2 * utt3 + x2 * ttt, y = y1 * uuu + cy1 * uut3 + cy2 * utt3 + y2 * ttt; + output[o] = x; + output[o + 1] = y; + if (tangents) + { + output[o + 2] = (float)Math.Atan2(y - (y1 * uu + cy1 * ut * 2 + cy2 * tt), x - (x1 * uu + cx1 * ut * 2 + cx2 * tt)); + } + } } diff --git a/spine-cpp/spine-cpp/src/spine/Skeleton.cpp b/spine-cpp/spine-cpp/src/spine/Skeleton.cpp index 88eefbd5a..aeae9606c 100644 --- a/spine-cpp/spine-cpp/src/spine/Skeleton.cpp +++ b/spine-cpp/spine-cpp/src/spine/Skeleton.cpp @@ -40,6 +40,14 @@ #include #include +#include +#include +#include +#include +#include + +#include + namespace Spine { Skeleton::Skeleton(SkeletonData& data) : @@ -56,61 +64,78 @@ namespace Spine _y(0) { _bones.reserve(_data.getBones().size()); - - foreach (BoneData boneData in _data.getBones()) + for (BoneData** i = _data.getBones().begin(); i != _data.getBones().end(); ++i) { - Bone bone; - if (boneData.parent == NULL) + BoneData* data = (*i); + + Bone* bone; + if (data->getParent() == NULL) { - bone = new Bone(boneData, this, NULL); + bone = new Bone(*data, *this, NULL); } else { - Bone parent = bones.Items[boneData.parent.index]; - bone = new Bone(boneData, this, parent); - parent.children.Add(bone); + Bone* parent = _bones[data->getParent()->getIndex()]; + bone = new Bone(*data, *this, parent); + parent->getChildren().push_back(bone); } - bones.Add(bone); + _bones.push_back(bone); } _slots.reserve(_data.getSlots().size()); _drawOrder.reserve(_data.getSlots().size()); - - foreach (SlotData slotData in data.slots) + for (SlotData** i = _data.getSlots().begin(); i != _data.getSlots().end(); ++i) { - Bone bone = bones.Items[slotData.boneData.index]; - Slot slot = new Slot(slotData, bone); - slots.Add(slot); - drawOrder.Add(slot); + SlotData* data = (*i); + + Bone* bone = _bones[data->getBoneData().getIndex()]; + Slot* slot = new Slot(*data, *bone); + + _slots.push_back(slot); + _drawOrder.push_back(slot); } - ikConstraints = new Vector(data.ikConstraints.Count); - - foreach (IkConstraintData ikConstraintData in data.ikConstraints) + _ikConstraints.reserve(_data.getIkConstraints().size()); + for (IkConstraintData** i = _data.getIkConstraints().begin(); i != _data.getIkConstraints().end(); ++i) { - ikConstraints.Add(new IkConstraint(ikConstraintData, this)); + IkConstraintData* data = (*i); + + _ikConstraints.push_back(new IkConstraint(*data, *this)); } - transformConstraints = new Vector(data.transformConstraints.Count); - foreach (TransformConstraintData transformConstraintData in data.transformConstraints) + _transformConstraints.reserve(_data.getTransformConstraints().size()); + for (TransformConstraintData** i = _data.getTransformConstraints().begin(); i != _data.getTransformConstraints().end(); ++i) { - transformConstraints.Add(new TransformConstraint(transformConstraintData, this)); + TransformConstraintData* data = (*i); + + _transformConstraints.push_back(new TransformConstraint(*data, *this)); } - pathConstraints = new Vector (data.pathConstraints.Count); - foreach (PathConstraintData pathConstraintData in data.pathConstraints) + _pathConstraints.reserve(_data.getPathConstraints().size()); + for (PathConstraintData** i = _data.getPathConstraints().begin(); i != _data.getPathConstraints().end(); ++i) { - pathConstraints.Add(new PathConstraint(pathConstraintData, this)); + PathConstraintData* data = (*i); + + _pathConstraints.push_back(new PathConstraint(*data, *this)); } updateCache(); updateWorldTransform(); } + Skeleton::~Skeleton() + { + ContainerUtil::cleanUpVectorOfPointers(_bones); + ContainerUtil::cleanUpVectorOfPointers(_slots); + ContainerUtil::cleanUpVectorOfPointers(_ikConstraints); + ContainerUtil::cleanUpVectorOfPointers(_transformConstraints); + ContainerUtil::cleanUpVectorOfPointers(_pathConstraints); + } + void Skeleton::updateCache() { - Vector updateCache = _updateCache; + Vector updateCache = _updateCache; updateCache.Clear(); _updateCacheReset.Clear(); diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonData.cpp b/spine-cpp/spine-cpp/src/spine/SkeletonData.cpp index bd5cac04d..201359534 100644 --- a/spine-cpp/spine-cpp/src/spine/SkeletonData.cpp +++ b/spine-cpp/spine-cpp/src/spine/SkeletonData.cpp @@ -39,6 +39,8 @@ #include #include +#include + #include namespace Spine @@ -54,244 +56,206 @@ namespace Spine BoneData* SkeletonData::findBone(std::string boneName) { - assert(boneName.length() > 0); - - for (BoneData** i = _bones.begin(); i != _bones.end(); ++i) - { - BoneData* boneData = (*i); - if (boneData->getName() == boneName) - { - return boneData; - } - } - - return NULL; + return ContainerUtil::findWithName(_bones, boneName); } int SkeletonData::findBoneIndex(std::string boneName) { - assert(boneName.length() > 0); - - var bones = this.bones; - var bonesItems = bones.Items; - for (int i = 0, n = bones.Count; i < n; ++i) - { - if (bonesItems[i].name == boneName) - { - return i; - } - } - - return -1; + return ContainerUtil::findIndexWithName(_bones, boneName); } - /// Use a template findWithName method instead to reduce redundant data container traversal code SlotData* SkeletonData::findSlot(std::string slotName) { - assert(slotName.length() > 0); - - Vector slots = this.slots; - for (int i = 0, n = slots.Count; i < n; ++i) - { - SlotData slot = slots.Items[i]; - if (slot.name == slotName) - { - return slot; - } - } - - return NULL; + return ContainerUtil::findWithName(_slots, slotName); } int SkeletonData::findSlotIndex(std::string slotName) { - assert(slotName.length() > 0); - - Vector slots = this.slots; - for (int i = 0, n = slots.Count; i < n; ++i) - { - if (slots.Items[i].name == slotName) - { - return i; - } - } - - return -1; + return ContainerUtil::findIndexWithName(_slots, slotName); } Skin* SkeletonData::findSkin(std::string skinName) { - assert(skinName.length() > 0); - - foreach (Skin skin in skins) - { - if (skin.name == skinName) - { - return skin; - } - } - - return NULL; + return ContainerUtil::findWithName(_skins, skinName); } EventData* SkeletonData::findEvent(std::string eventDataName) { - assert(eventDataName.length() > 0); - - foreach (EventData eventData in events) - { - if (eventData.name == eventDataName) - { - return eventData; - } - } - - return NULL; + return ContainerUtil::findWithName(_events, eventDataName); } Animation* SkeletonData::findAnimation(std::string animationName) { - assert(animationName.length() > 0); - - Vector animations = this.animations; - for (int i = 0, n = animations.Count; i < n; ++i) - { - Animation animation = animations.Items[i]; - if (animation.name == animationName) - { - return animation; - } - } - - return NULL; + return ContainerUtil::findWithName(_animations, animationName); } IkConstraintData* SkeletonData::findIkConstraint(std::string constraintName) { - assert(constraintName.length() > 0); - - Vector ikConstraints = this.ikConstraints; - for (int i = 0, n = ikConstraints.Count; i < n; ++i) - { - IkConstraintData ikConstraint = ikConstraints.Items[i]; - if (ikConstraint.name == constraintName) - { - return ikConstraint; - } - } - - return NULL; + return ContainerUtil::findWithName(_ikConstraints, constraintName); } TransformConstraintData* SkeletonData::findTransformConstraint(std::string constraintName) { - assert(constraintName.length() > 0); - - Vector transformConstraints = this.transformConstraints; - for (int i = 0, n = transformConstraints.Count; i < n; ++i) - { - TransformConstraintData transformConstraint = transformConstraints.Items[i]; - if (transformConstraint.name == constraintName) - { - return transformConstraint; - } - } - - return NULL; + return ContainerUtil::findWithName(_transformConstraints, constraintName); } PathConstraintData* SkeletonData::findPathConstraint(std::string constraintName) { - assert(constraintName.length() > 0); - - Vector pathConstraints = this.pathConstraints; - for (int i = 0, n = pathConstraints.Count; i < n; ++i) - { - PathConstraintData constraint = pathConstraints.Items[i]; - if (constraint.name.Equals(constraintName)) - { - return constraint; - } - } - - return NULL; + return ContainerUtil::findWithName(_pathConstraints, constraintName); } int SkeletonData::findPathConstraintIndex(std::string pathConstraintName) { - assert(pathConstraintName.length() > 0); - - Vector pathConstraints = this.pathConstraints; - for (int i = 0, n = pathConstraints.Count; i < n; ++i) - { - if (pathConstraints.Items[i].name.Equals(pathConstraintName)) - { - return i; - } - } - - return -1; + return ContainerUtil::findIndexWithName(_pathConstraints, pathConstraintName); } - std::string SkeletonData::getName() { return _name; } + std::string SkeletonData::getName() + { + return _name; + } - void SkeletonData::setName(std::string inValue) { _name = inValue; } + void SkeletonData::setName(std::string inValue) + { + _name = inValue; + } - Vector& SkeletonData::getBones() { return _bones; } + Vector& SkeletonData::getBones() + { + return _bones; + } - Vector& SkeletonData::getSlots() { return _slots; } + Vector& SkeletonData::getSlots() + { + return _slots; + } - Vector& SkeletonData::getSkins() { return _skins; } + Vector& SkeletonData::getSkins() + { + return _skins; + } - void SkeletonData::setSkins(Vector& inValue) { _skins = inValue; } + void SkeletonData::setSkins(Vector& inValue) + { + _skins = inValue; + } - Skin* SkeletonData::getDefaultSkin() { return _defaultSkin; } + Skin* SkeletonData::getDefaultSkin() + { + return _defaultSkin; + } - void SkeletonData::setDefaultSkin(Skin* inValue) { _defaultSkin = inValue; } + void SkeletonData::setDefaultSkin(Skin* inValue) + { + _defaultSkin = inValue; + } - Vector& SkeletonData::getEvents() { return _events; } + Vector& SkeletonData::getEvents() + { + return _events; + } - void SkeletonData::setEvents(Vector& inValue) { _events = inValue; } + void SkeletonData::setEvents(Vector& inValue) + { + _events = inValue; + } - Vector& SkeletonData::getAnimations() { return _animations; } + Vector& SkeletonData::getAnimations() + { + return _animations; + } - void SkeletonData::setAnimations(Vector& inValue) { _animations = inValue; } + void SkeletonData::setAnimations(Vector& inValue) + { + _animations = inValue; + } - Vector& SkeletonData::getIkConstraints() { return _ikConstraints; } + Vector& SkeletonData::getIkConstraints() + { + return _ikConstraints; + } - void SkeletonData::setIkConstraints(Vector& inValue) { _ikConstraints = inValue; } + void SkeletonData::setIkConstraints(Vector& inValue) + { + _ikConstraints = inValue; + } - Vector& SkeletonData::getTransformConstraints() { return _transformConstraints; } + Vector& SkeletonData::getTransformConstraints() + { + return _transformConstraints; + } - void SkeletonData::setTransformConstraints(Vector& inValue) { _transformConstraints = inValue; } + void SkeletonData::setTransformConstraints(Vector& inValue) + { + _transformConstraints = inValue; + } - Vector& SkeletonData::getPathConstraints() { return _pathConstraints; } + Vector& SkeletonData::getPathConstraints() + { + return _pathConstraints; + } - void SkeletonData::setPathConstraints(Vector& inValue) { _pathConstraints = inValue; } + void SkeletonData::setPathConstraints(Vector& inValue) + { + _pathConstraints = inValue; + } - float SkeletonData::getWidth() { return _width; } + float SkeletonData::getWidth() + { + return _width; + } - void SkeletonData::setWidth(float inValue) { _width = inValue; } + void SkeletonData::setWidth(float inValue) + { + _width = inValue; + } - float SkeletonData::getHeight() { return _height; } + float SkeletonData::getHeight() + { + return _height; + } - void SkeletonData::setHeight(float inValue) { _height = inValue; } + void SkeletonData::setHeight(float inValue) + { + _height = inValue; + } - /// The Spine version used to export this data, or NULL. - std::string SkeletonData::getVersion() { return _version; } + std::string SkeletonData::getVersion() + { + return _version; + } - void SkeletonData::setVersion(std::string inValue) { _version = inValue; } + void SkeletonData::setVersion(std::string inValue) + { + _version = inValue; + } - std::string SkeletonData::getHash() { return _hash; } + std::string SkeletonData::getHash() + { + return _hash; + } - void SkeletonData::setHash(std::string inValue) { _hash = inValue; } + void SkeletonData::setHash(std::string inValue) + { + _hash = inValue; + } - std::string SkeletonData::getImagesPath() { return _imagesPath; } + std::string SkeletonData::getImagesPath() + { + return _imagesPath; + } - void SkeletonData::setImagesPath(std::string inValue) { _imagesPath = inValue; } + void SkeletonData::setImagesPath(std::string inValue) + { + _imagesPath = inValue; + } - /// The dopesheet FPS in Spine. Available only when nonessential data was exported. - float SkeletonData::getFps { return _fps; } + float SkeletonData::getFps() + { + return _fps; + } - void SkeletonData::setFps(float inValue) { _fps = inValue; } + void SkeletonData::setFps(float inValue) + { + _fps = inValue; + } } diff --git a/spine-cpp/spine-cpp/src/spine/Skin.cpp b/spine-cpp/spine-cpp/src/spine/Skin.cpp index 291ded0bf..d2b8c7259 100644 --- a/spine-cpp/spine-cpp/src/spine/Skin.cpp +++ b/spine-cpp/spine-cpp/src/spine/Skin.cpp @@ -114,7 +114,7 @@ namespace Spine for (HashMap::Iterator i = oldSkin.getAttachments().begin(); i != oldSkin.getAttachments().end(); ++i) { int slotIndex = i.first()._slotIndex; - Slot* slot = skeleton.getSlots().at(slotIndex); + Slot* slot = skeleton.getSlots()[slotIndex]; if (slot->getAttachment() == i.second()) { diff --git a/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp b/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp index bb4d2ccfe..06669c000 100644 --- a/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp +++ b/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp @@ -28,7 +28,421 @@ * POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ +#include + +#include +#include +#include + +#include +#include + namespace Spine { - // TODO + TransformConstraint::TransformConstraint(TransformConstraintData& data, Skeleton& skeleton) : Constraint(), + _data(data), + _rotateMix(data.getRotateMix()), + _translateMix(data.getTranslateMix()), + _scaleMix(data.getScaleMix()), + _shearMix(data.getShearMix()), + _target(skeleton.findBone(data.getTarget()->getName())) + { + _bones.reserve(_data.getBones().size()); + for (BoneData** i = _data.getBones().begin(); i != _data.getBones().end(); ++i) + { + BoneData* boneData = (*i); + + _bones.push_back(skeleton.findBone(boneData->getName())); + } + } + + void TransformConstraint::apply() + { + update(); + } + + void TransformConstraint::update() + { + if (_data.isLocal()) + { + if (_data.isRelative()) + { + applyRelativeLocal(); + } + else + { + applyAbsoluteLocal(); + } + } + else + { + if (_data.isRelative()) + { + applyRelativeWorld(); + } + else + { + applyAbsoluteWorld(); + } + } + } + + int TransformConstraint::getOrder() + { + return _data.getOrder(); + } + + TransformConstraintData& TransformConstraint::getData() + { + return _data; + } + + Vector& TransformConstraint::getBones() + { + return _bones; + } + + Bone* TransformConstraint::getTarget() + { + return _target; + } + + void TransformConstraint::setTarget(Bone* inValue) + { + _target = inValue; + } + + float TransformConstraint::getRotateMix() + { + return _rotateMix; + } + + void TransformConstraint::setRotateMix(float inValue) + { + _rotateMix = inValue; + } + + float TransformConstraint::getTranslateMix() + { + return _translateMix; + } + + void TransformConstraint::setTranslateMix(float inValue) + { + _translateMix = inValue; + } + + float TransformConstraint::getScaleMix() + { + return _scaleMix; + } + + void TransformConstraint::setScaleMix(float inValue) + { + _scaleMix = inValue; + } + + float TransformConstraint::getShearMix() + { + return _shearMix; + } + + void TransformConstraint::setShearMix(float inValue) + { + _shearMix = inValue; + } + + void TransformConstraint::applyAbsoluteWorld() + { + float rotateMix = _rotateMix, translateMix = _translateMix, scaleMix = _scaleMix, shearMix = _shearMix; + Bone target = *_target; + float ta = target._a, tb = target._b, tc = target._c, td = target._d; + float degRadReflect = ta * td - tb * tc > 0 ? DegRad : -DegRad; + float offsetRotation = _data._offsetRotation * degRadReflect, offsetShearY = _data._offsetShearY * degRadReflect; + + for (Bone** i = _bones.begin(); i != _bones.end(); ++i) + { + Bone* item = (*i); + Bone& bone = *item; + + bool modified = false; + + if (rotateMix != 0) + { + float a = bone._a, b = bone._b, c = bone._c, d = bone._d; + float r = MathUtil::atan2(tc, ta) - MathUtil::atan2(c, a) + offsetRotation; + if (r > SPINE_PI) + { + r -= SPINE_PI_2; + } + else if (r < -SPINE_PI) + { + r += SPINE_PI_2; + } + + r *= rotateMix; + float cos = MathUtil::cos(r), sin = MathUtil::sin(r); + bone._a = cos * a - sin * c; + bone._b = cos * b - sin * d; + bone._c = sin * a + cos * c; + bone._d = sin * b + cos * d; + modified = true; + } + + if (translateMix != 0) + { + float tx, ty; + target.localToWorld(_data._offsetX, _data._offsetY, tx, ty); + bone._worldX += (tx - bone._worldX) * translateMix; + bone._worldY += (ty - bone._worldY) * translateMix; + modified = true; + } + + if (scaleMix > 0) + { + float s = (float)sqrt(bone._a * bone._a + bone._c * bone._c); + + if (s > 0.00001f) + { + s = (s + ((float)sqrt(ta * ta + tc * tc) - s + _data._offsetScaleX) * scaleMix) / s; + } + bone._a *= s; + bone._c *= s; + s = (float)sqrt(bone._b * bone._b + bone._d * bone._d); + + if (s > 0.00001f) + { + s = (s + ((float)sqrt(tb * tb + td * td) - s + _data._offsetScaleY) * scaleMix) / s; + } + bone._b *= s; + bone._d *= s; + modified = true; + } + + if (shearMix > 0) + { + float b = bone._b, d = bone._d; + float by = MathUtil::atan2(d, b); + float r = MathUtil::atan2(td, tb) - MathUtil::atan2(tc, ta) - (by - MathUtil::atan2(bone._c, bone._a)); + if (r > SPINE_PI) + { + r -= SPINE_PI_2; + } + else if (r < -SPINE_PI) + { + r += SPINE_PI_2; + } + + r = by + (r + offsetShearY) * shearMix; + float s = (float)sqrt(b * b + d * d); + bone._b = MathUtil::cos(r) * s; + bone._d = MathUtil::sin(r) * s; + modified = true; + } + + if (modified) + { + bone._appliedValid = false; + } + } + } + + void TransformConstraint::applyRelativeWorld() + { + float rotateMix = _rotateMix, translateMix = _translateMix, scaleMix = _scaleMix, shearMix = _shearMix; + Bone target = *_target; + float ta = target._a, tb = target._b, tc = target._c, td = target._d; + float degRadReflect = ta * td - tb * tc > 0 ? DegRad : -DegRad; + float offsetRotation = _data._offsetRotation * degRadReflect, offsetShearY = _data._offsetShearY * degRadReflect; + for (Bone** i = _bones.begin(); i != _bones.end(); ++i) + { + Bone* item = (*i); + Bone& bone = *item; + + bool modified = false; + + if (rotateMix != 0) + { + float a = bone._a, b = bone._b, c = bone._c, d = bone._d; + float r = MathUtil::atan2(tc, ta) + offsetRotation; + if (r > SPINE_PI) + { + r -= SPINE_PI_2; + } + else if (r < -SPINE_PI) + { + r += SPINE_PI_2; + } + + r *= rotateMix; + float cos = MathUtil::cos(r), sin = MathUtil::sin(r); + bone._a = cos * a - sin * c; + bone._b = cos * b - sin * d; + bone._c = sin * a + cos * c; + bone._d = sin * b + cos * d; + modified = true; + } + + if (translateMix != 0) + { + float tx, ty; + target.localToWorld(_data._offsetX, _data._offsetY, tx, ty); + bone._worldX += tx * translateMix; + bone._worldY += ty * translateMix; + modified = true; + } + + if (scaleMix > 0) + { + float s = ((float)sqrt(ta * ta + tc * tc) - 1 + _data._offsetScaleX) * scaleMix + 1; + bone._a *= s; + bone._c *= s; + s = ((float)sqrt(tb * tb + td * td) - 1 + _data._offsetScaleY) * scaleMix + 1; + bone._b *= s; + bone._d *= s; + modified = true; + } + + if (shearMix > 0) + { + float r = MathUtil::atan2(td, tb) - MathUtil::atan2(tc, ta); + if (r > SPINE_PI) + { + r -= SPINE_PI_2; + } + else if (r < -SPINE_PI) + { + r += SPINE_PI_2; + } + + float b = bone._b, d = bone._d; + r = MathUtil::atan2(d, b) + (r - SPINE_PI / 2 + offsetShearY) * shearMix; + float s = (float)sqrt(b * b + d * d); + bone._b = MathUtil::cos(r) * s; + bone._d = MathUtil::sin(r) * s; + modified = true; + } + + if (modified) + { + bone._appliedValid = false; + } + } + } + + void TransformConstraint::applyAbsoluteLocal() + { + float rotateMix = _rotateMix, translateMix = _translateMix, scaleMix = _scaleMix, shearMix = _shearMix; + Bone target = *_target; + if (!target._appliedValid) + { + target.updateAppliedTransform(); + } + + for (Bone** i = _bones.begin(); i != _bones.end(); ++i) + { + Bone* item = (*i); + Bone& bone = *item; + + if (!bone._appliedValid) + { + bone.updateAppliedTransform(); + } + + float rotation = bone._arotation; + if (rotateMix != 0) + { + float r = target._arotation - rotation + _data._offsetRotation; + r -= (16384 - (int)(16384.499999999996 - r / 360)) * 360; + rotation += r * rotateMix; + } + + float x = bone._ax, y = bone._ay; + if (translateMix != 0) + { + x += (target._ax - x + _data._offsetX) * translateMix; + y += (target._ay - y + _data._offsetY) * translateMix; + } + + float scaleX = bone._ascaleX, scaleY = bone._ascaleY; + if (scaleMix > 0) + { + if (scaleX > 0.00001f) + { + scaleX = (scaleX + (target._ascaleX - scaleX + _data._offsetScaleX) * scaleMix) / scaleX; + } + + if (scaleY > 0.00001f) + { + scaleY = (scaleY + (target._ascaleY - scaleY + _data._offsetScaleY) * scaleMix) / scaleY; + } + } + + float shearY = bone._ashearY; + if (shearMix > 0) + { + float r = target._ashearY - shearY + _data._offsetShearY; + r -= (16384 - (int)(16384.499999999996 - r / 360)) * 360; + bone._shearY += r * shearMix; + } + + bone.updateWorldTransform(x, y, rotation, scaleX, scaleY, bone._ashearX, shearY); + } + } + + void TransformConstraint::applyRelativeLocal() + { + float rotateMix = _rotateMix, translateMix = _translateMix, scaleMix = _scaleMix, shearMix = _shearMix; + Bone target = *_target; + if (!target._appliedValid) + { + target.updateAppliedTransform(); + } + + for (Bone** i = _bones.begin(); i != _bones.end(); ++i) + { + Bone* item = (*i); + Bone& bone = *item; + + if (!bone._appliedValid) + { + bone.updateAppliedTransform(); + } + + float rotation = bone._arotation; + if (rotateMix != 0) + { + rotation += (target._arotation + _data._offsetRotation) * rotateMix; + } + + float x = bone._ax, y = bone._ay; + if (translateMix != 0) + { + x += (target._ax + _data._offsetX) * translateMix; + y += (target._ay + _data._offsetY) * translateMix; + } + + float scaleX = bone._ascaleX, scaleY = bone._ascaleY; + if (scaleMix > 0) + { + if (scaleX > 0.00001f) + { + scaleX *= ((target._ascaleX - 1 + data.offsetScaleX) * scaleMix) + 1; + } + + if (scaleY > 0.00001f) + { + scaleY *= ((target._ascaleY - 1 + data.offsetScaleY) * scaleMix) + 1; + } + } + + float shearY = bone._ashearY; + if (shearMix > 0) + { + shearY += (target._ashearY + data.offsetShearY) * shearMix; + } + + bone.updateWorldTransform(x, y, rotation, scaleX, scaleY, bone._ashearX, shearY); + } + } } diff --git a/spine-cpp/spine-cpp/src/spine/VertexAttachment.cpp b/spine-cpp/spine-cpp/src/spine/VertexAttachment.cpp new file mode 100644 index 000000000..02819a18f --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/VertexAttachment.cpp @@ -0,0 +1,163 @@ +/****************************************************************************** +* Spine Runtimes Software License v2.5 +* +* Copyright (c) 2013-2016, Esoteric Software +* All rights reserved. +* +* You are granted a perpetual, non-exclusive, non-sublicensable, and +* non-transferable license to use, install, execute, and perform the Spine +* Runtimes software and derivative works solely for personal or internal +* use. Without the written permission of Esoteric Software (see Section 2 of +* the Spine Software License Agreement), you may not (a) modify, translate, +* adapt, or develop new applications using the Spine Runtimes or otherwise +* create derivative works or improvements of the Spine Runtimes or (b) remove, +* delete, alter, or obscure any trademarks or any copyright, trademark, patent, +* or other intellectual property or proprietary rights notices on or in the +* Software, including any copy thereof. Redistributions in binary or source +* form must include this license and terms. +* +* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +#include + +#include + +namespace Spine +{ + VertexAttachment::VertexAttachment(std::string name) : Attachment(name), _id(getNextID()), _worldVerticesLength(0) + { + // Empty + } + + void VertexAttachment::computeWorldVertices(Slot& slot, Vector& worldVertices) + { + computeWorldVertices(slot, 0, _worldVerticesLength, worldVertices, 0); + } + + void VertexAttachment::computeWorldVertices(Slot& slot, int start, int count, Vector& worldVertices, int offset, int stride) + { + count = offset + (count >> 1) * stride; + Skeleton skeleton = slot.bone.skeleton; + var deformArray = slot.attachmentVertices; + Vector vertices = _vertices; + Vector bones = _bones; + if (bones == NULL) + { + if (deformArray.Count > 0) vertices = deformArray.Items; + Bone bone = slot.bone; + float x = bone.worldX, y = bone.worldY; + float a = bone.a, b = bone.b, c = bone.c, d = bone.d; + for (int vv = start, w = offset; w < count; vv += 2, w += stride) + { + float vx = vertices[vv], vy = vertices[vv + 1]; + worldVertices[w] = vx * a + vy * b + x; + worldVertices[w + 1] = vx * c + vy * d + y; + } + return; + } + + int v = 0, skip = 0; + for (int i = 0; i < start; i += 2) + { + int n = bones[v]; + v += n + 1; + skip += n; + } + + var skeletonBones = skeleton.bones.Items; + if (deformArray.Count == 0) + { + for (int 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) + { + Bone 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 + { + Vector deform = deformArray.Items; + for (int 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) + { + Bone bone = skeletonBones[bones[v]]; + float vx = vertices[b] + deform[f], vy = vertices[b + 1] + deform[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; + } + } + } + + bool VertexAttachment::applyDeform(VertexAttachment* sourceAttachment) + { + return this == sourceAttachment; + } + + int VertexAttachment::getId() + { + return _id; + } + + Vector VertexAttachment::getBones() + { + return _bones; + } + + void VertexAttachment::setBones(Vector inValue) + { + _bones = inValue; + } + + Vector VertexAttachment::getVertices() + { + return _vertices; + } + + void VertexAttachment::setVertices(Vector inValue) + { + _vertices = inValue; + } + + int VertexAttachment::getWorldVerticesLength() + { + return _worldVerticesLength; + } + + void VertexAttachment::setWorldVerticesLength(int inValue) + { + _worldVerticesLength = inValue; + } + + int VertexAttachment::getNextID() + { + static int nextID = 0; + + return (nextID++ & 65535) << 11; + } +} From 873b4d397f56a765bccbba295cf188fd9b8998b2 Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Tue, 24 Oct 2017 20:54:27 -0400 Subject: [PATCH 18/83] wip --- spine-cpp/spine-cpp/include/spine/Bone.h | 1 + spine-cpp/spine-cpp/include/spine/BoneData.h | 2 + .../spine-cpp/include/spine/PathAttachment.h | 60 +++++++++++++++++++ spine-cpp/spine-cpp/include/spine/Slot.h | 14 +++-- .../spine-cpp/src/spine/PathAttachment.cpp | 34 +++++++++++ .../spine-cpp/src/spine/RotateTimeline.cpp | 29 ++++++--- spine-cpp/spine-cpp/src/spine/Slot.cpp | 6 +- .../spine-cpp/src/spine/VertexAttachment.cpp | 56 ++++++++++------- 8 files changed, 163 insertions(+), 39 deletions(-) create mode 100644 spine-cpp/spine-cpp/include/spine/PathAttachment.h create mode 100644 spine-cpp/spine-cpp/src/spine/PathAttachment.cpp diff --git a/spine-cpp/spine-cpp/include/spine/Bone.h b/spine-cpp/spine-cpp/include/spine/Bone.h index 46c04d3a5..a0b61867e 100644 --- a/spine-cpp/spine-cpp/include/spine/Bone.h +++ b/spine-cpp/spine-cpp/include/spine/Bone.h @@ -50,6 +50,7 @@ namespace Spine friend class RotateTimeline; friend class IkConstraint; friend class TransformConstraint; + friend class VertexAttachment; public: static void setYDown(bool inValue); diff --git a/spine-cpp/spine-cpp/include/spine/BoneData.h b/spine-cpp/spine-cpp/include/spine/BoneData.h index 9710eda27..e5d82ef31 100644 --- a/spine-cpp/spine-cpp/include/spine/BoneData.h +++ b/spine-cpp/spine-cpp/include/spine/BoneData.h @@ -39,6 +39,8 @@ namespace Spine { class BoneData { + friend class RotateTimeline; + public: BoneData(int index, std::string name, BoneData* parent = NULL); diff --git a/spine-cpp/spine-cpp/include/spine/PathAttachment.h b/spine-cpp/spine-cpp/include/spine/PathAttachment.h new file mode 100644 index 000000000..5eda9a360 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/PathAttachment.h @@ -0,0 +1,60 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_PathAttachment_h +#define Spine_PathAttachment_h + +#include + +namespace Spine +{ + class PathAttachment : public VertexAttachment + { + public: + PathAttachment(std::string name) : VertexAttachment(name) + { + // Empty + } + + /// The length in the setup pose from the start of the path to the end of each curve. + float[] Lengths { return lengths; } + set { lengths = value; } + bool Closed { return closed; } + set { closed = value; } + bool ConstantSpeed { return constantSpeed; } + set { constantSpeed = value; } + + private: + float[] lengths; + bool closed, constantSpeed; + }; +} + +#endif /* Spine_PathAttachment_h */ diff --git a/spine-cpp/spine-cpp/include/spine/Slot.h b/spine-cpp/spine-cpp/include/spine/Slot.h index 767373056..f9472c9da 100644 --- a/spine-cpp/spine-cpp/include/spine/Slot.h +++ b/spine-cpp/spine-cpp/include/spine/Slot.h @@ -44,14 +44,16 @@ namespace Spine class Slot { + friend class VertexAttachment; + public: Slot(SlotData& data, Bone& bone); void setToSetupPose(); - const SlotData& getSlotData(); - const Bone& getBone(); - const Skeleton& getSkeleton(); + SlotData& getSlotData(); + Bone& getBone(); + Skeleton& getSkeleton(); float getR(); void setR(float inValue); @@ -82,9 +84,9 @@ namespace Spine void setAttachmentVertices(Vector inValue); private: - const SlotData& _slotData; - const Bone& _bone; - const Skeleton& _skeleton; + SlotData& _slotData; + Bone& _bone; + Skeleton& _skeleton; float _r, _g, _b, _a; float _r2, _g2, _b2; bool _hasSecondColor; diff --git a/spine-cpp/spine-cpp/src/spine/PathAttachment.cpp b/spine-cpp/spine-cpp/src/spine/PathAttachment.cpp new file mode 100644 index 000000000..bb4d2ccfe --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/PathAttachment.cpp @@ -0,0 +1,34 @@ +/****************************************************************************** +* Spine Runtimes Software License v2.5 +* +* Copyright (c) 2013-2016, Esoteric Software +* All rights reserved. +* +* You are granted a perpetual, non-exclusive, non-sublicensable, and +* non-transferable license to use, install, execute, and perform the Spine +* Runtimes software and derivative works solely for personal or internal +* use. Without the written permission of Esoteric Software (see Section 2 of +* the Spine Software License Agreement), you may not (a) modify, translate, +* adapt, or develop new applications using the Spine Runtimes or otherwise +* create derivative works or improvements of the Spine Runtimes or (b) remove, +* delete, alter, or obscure any trademarks or any copyright, trademark, patent, +* or other intellectual property or proprietary rights notices on or in the +* Software, including any copy thereof. Redistributions in binary or source +* form must include this license and terms. +* +* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +namespace Spine +{ + // TODO +} diff --git a/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp b/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp index b77b60858..1d2cb4bde 100644 --- a/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp @@ -34,7 +34,9 @@ #include #include +#include #include +#include namespace Spine { @@ -45,20 +47,29 @@ namespace Spine void RotateTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) { - Bone* bone = skeleton.getBones().at(_boneIndex); + Bone* bone = skeleton.getBones()[_boneIndex]; if (time < _frames[0]) { switch (pose) { case MixPose_Setup: - bone->_rotation = bone->_data->_rotation; - return; + { + bone->_rotation = bone->_data._rotation; + break; + } case MixPose_Current: - float rr = bone->_data->_rotation - bone->_rotation; + { + float rr = bone->_data._rotation - bone->_rotation; rr -= (16384 - (int)(16384.499999999996 - rr / 360)) * 360; bone->_rotation += rr * alpha; - return; + break; + } + case MixPose_CurrentLayered: + { + // TODO? + break; + } } return; @@ -69,11 +80,11 @@ namespace Spine // Time is after last frame. if (pose == MixPose_Setup) { - bone->_rotation = bone->_data->_rotation + _frames[_frames.size() + PREV_ROTATION] * alpha; + bone->_rotation = bone->_data._rotation + _frames[_frames.size() + PREV_ROTATION] * alpha; } else { - float rr = bone->_data->_rotation + _frames[_frames.size() + PREV_ROTATION] - bone->_rotation; + float rr = bone->_data._rotation + _frames[_frames.size() + PREV_ROTATION] - bone->_rotation; rr -= (16384 - (int)(16384.499999999996 - rr / 360)) * 360; // Wrap within -180 and 180. bone->_rotation += rr * alpha; } @@ -94,11 +105,11 @@ namespace Spine if (pose == MixPose_Setup) { r -= (16384 - (int)(16384.499999999996 - r / 360)) * 360; - bone->_rotation = bone->_data->_rotation + r * alpha; + bone->_rotation = bone->_data._rotation + r * alpha; } else { - r = bone->_data->_rotation + r - bone->_rotation; + r = bone->_data._rotation + r - bone->_rotation; r -= (16384 - (int)(16384.499999999996 - r / 360)) * 360; bone->_rotation += r * alpha; } diff --git a/spine-cpp/spine-cpp/src/spine/Slot.cpp b/spine-cpp/spine-cpp/src/spine/Slot.cpp index e4bc6b1e7..fa9e1f5d8 100644 --- a/spine-cpp/spine-cpp/src/spine/Slot.cpp +++ b/spine-cpp/spine-cpp/src/spine/Slot.cpp @@ -74,17 +74,17 @@ namespace Spine } } - const SlotData& Slot::getSlotData() + SlotData& Slot::getSlotData() { return _slotData; } - const Bone& Slot::getBone() + Bone& Slot::getBone() { return _bone; } - const Skeleton& Slot::getSkeleton() + Skeleton& Slot::getSkeleton() { return _skeleton; } diff --git a/spine-cpp/spine-cpp/src/spine/VertexAttachment.cpp b/spine-cpp/spine-cpp/src/spine/VertexAttachment.cpp index 02819a18f..7581d360b 100644 --- a/spine-cpp/spine-cpp/src/spine/VertexAttachment.cpp +++ b/spine-cpp/spine-cpp/src/spine/VertexAttachment.cpp @@ -32,6 +32,9 @@ #include +#include +#include + namespace Spine { VertexAttachment::VertexAttachment(std::string name) : Attachment(name), _id(getNextID()), _worldVerticesLength(0) @@ -47,19 +50,25 @@ namespace Spine void VertexAttachment::computeWorldVertices(Slot& slot, int start, int count, Vector& worldVertices, int offset, int stride) { count = offset + (count >> 1) * stride; - Skeleton skeleton = slot.bone.skeleton; - var deformArray = slot.attachmentVertices; - Vector vertices = _vertices; - Vector bones = _bones; - if (bones == NULL) + Skeleton& skeleton = slot._bone._skeleton; + Vector& deformArray = slot.getAttachmentVertices(); + Vector& vertices = _vertices; + Vector& bones = _bones; + if (bones.size() == 0) { - if (deformArray.Count > 0) vertices = deformArray.Items; - Bone bone = slot.bone; - float x = bone.worldX, y = bone.worldY; - float a = bone.a, b = bone.b, c = bone.c, d = bone.d; + if (deformArray.size() > 0) + { + vertices = deformArray; + } + + Bone& bone = slot._bone; + float x = bone._worldX; + float y = bone._worldY; + float a = bone._a, b = bone._b, c = bone._c, d = bone._d; for (int vv = start, w = offset; w < count; vv += 2, w += stride) { - float vx = vertices[vv], vy = vertices[vv + 1]; + float vx = vertices[vv]; + float vy = vertices[vv + 1]; worldVertices[w] = vx * a + vy * b + x; worldVertices[w + 1] = vx * c + vy * d + y; } @@ -74,8 +83,8 @@ namespace Spine skip += n; } - var skeletonBones = skeleton.bones.Items; - if (deformArray.Count == 0) + Vector& skeletonBones = skeleton.getBones(); + if (deformArray.size() == 0) { for (int w = offset, b = skip * 3; w < count; w += stride) { @@ -84,10 +93,13 @@ namespace Spine n += v; for (; v < n; v++, b += 3) { - Bone 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; + Bone* boneP = skeletonBones[bones[v]]; + Bone bone = *boneP; + float vx = vertices[b]; + float vy = vertices[b + 1]; + float 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; @@ -95,7 +107,6 @@ namespace Spine } else { - Vector deform = deformArray.Items; for (int w = offset, b = skip * 3, f = skip << 1; w < count; w += stride) { float wx = 0, wy = 0; @@ -103,10 +114,13 @@ namespace Spine n += v; for (; v < n; v++, b += 3, f += 2) { - Bone bone = skeletonBones[bones[v]]; - float vx = vertices[b] + deform[f], vy = vertices[b + 1] + deform[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; + Bone* boneP = skeletonBones[bones[v]]; + Bone bone = *boneP; + float vx = vertices[b] + deformArray[f]; + float vy = vertices[b + 1] + deformArray[f + 1]; + float 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; From 87a18e22b8496089e0ae0b458624b5ff97930cf0 Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Sun, 29 Oct 2017 20:54:08 -0400 Subject: [PATCH 19/83] wip Almost ready to implement file loading --- spine-cpp/spine-cpp/include/spine/Animation.h | 82 ++++ spine-cpp/spine-cpp/include/spine/Bone.h | 4 + .../spine-cpp/include/spine/Constraint.h | 2 + .../spine-cpp/include/spine/ContainerUtil.h | 50 +- .../spine-cpp/include/spine/CurveTimeline.h | 2 + spine-cpp/spine-cpp/include/spine/EventData.h | 10 +- .../spine-cpp/include/spine/IkConstraint.h | 6 +- .../include/spine/IkConstraintData.h | 3 + spine-cpp/spine-cpp/include/spine/MathUtil.h | 15 +- .../spine-cpp/include/spine/MeshAttachment.h | 143 ++++++ .../spine-cpp/include/spine/PathAttachment.h | 24 +- .../spine-cpp/include/spine/PathConstraint.h | 5 + .../include/spine/PathConstraintData.h | 3 + .../include/spine/RegionAttachment.h | 192 ++++++++ .../spine-cpp/include/spine/RotateTimeline.h | 2 + spine-cpp/spine-cpp/include/spine/Skeleton.h | 13 +- .../spine-cpp/include/spine/SkeletonData.h | 2 + spine-cpp/spine-cpp/include/spine/Skin.h | 46 +- spine-cpp/spine-cpp/include/spine/Slot.h | 5 +- spine-cpp/spine-cpp/include/spine/SlotData.h | 2 +- spine-cpp/spine-cpp/include/spine/Timeline.h | 3 + .../include/spine/TransformConstraint.h | 4 + .../include/spine/TransformConstraintData.h | 1 + spine-cpp/spine-cpp/include/spine/Updatable.h | 4 + spine-cpp/spine-cpp/include/spine/Vector.h | 54 ++- .../include/spine/VertexAttachment.h | 8 +- spine-cpp/spine-cpp/src/spine/Animation.cpp | 166 +++++++ spine-cpp/spine-cpp/src/spine/Bone.cpp | 2 + spine-cpp/spine-cpp/src/spine/Constraint.cpp | 3 +- .../spine-cpp/src/spine/CurveTimeline.cpp | 2 + spine-cpp/spine-cpp/src/spine/Event.cpp | 2 +- .../spine-cpp/src/spine/IkConstraint.cpp | 2 + .../spine-cpp/src/spine/MeshAttachment.cpp | 36 ++ .../spine-cpp/src/spine/PathAttachment.cpp | 39 +- .../spine-cpp/src/spine/PathConstraint.cpp | 229 +++++---- .../spine-cpp/src/spine/RegionAttachment.cpp | 36 ++ .../spine-cpp/src/spine/RotateTimeline.cpp | 2 + spine-cpp/spine-cpp/src/spine/Skeleton.cpp | 457 +++++++++--------- .../spine-cpp/src/spine/SkeletonData.cpp | 6 +- spine-cpp/spine-cpp/src/spine/Skin.cpp | 8 +- spine-cpp/spine-cpp/src/spine/Slot.cpp | 20 +- spine-cpp/spine-cpp/src/spine/SlotData.cpp | 4 +- spine-cpp/spine-cpp/src/spine/Timeline.cpp | 2 + .../src/spine/TransformConstraint.cpp | 8 +- spine-cpp/spine-cpp/src/spine/Updatable.cpp | 2 + .../spine-cpp/src/spine/VertexAttachment.cpp | 6 +- 46 files changed, 1260 insertions(+), 457 deletions(-) create mode 100644 spine-cpp/spine-cpp/include/spine/Animation.h create mode 100644 spine-cpp/spine-cpp/include/spine/MeshAttachment.h create mode 100644 spine-cpp/spine-cpp/include/spine/RegionAttachment.h create mode 100644 spine-cpp/spine-cpp/src/spine/Animation.cpp create mode 100644 spine-cpp/spine-cpp/src/spine/MeshAttachment.cpp create mode 100644 spine-cpp/spine-cpp/src/spine/RegionAttachment.cpp diff --git a/spine-cpp/spine-cpp/include/spine/Animation.h b/spine-cpp/spine-cpp/include/spine/Animation.h new file mode 100644 index 000000000..581d8cc34 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/Animation.h @@ -0,0 +1,82 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Animation_h +#define Spine_Animation_h + +#include +#include +#include + +#include + +namespace Spine +{ + class Timeline; + class Skeleton; + class Event; + + class Animation + { + friend class RotateTimeline; + + public: + Animation(std::string name, Vector& timelines, float duration); + + /// Applies all the animation's timelines to the specified skeleton. + /// See also Timeline::apply(Skeleton&, float, float, Vector, float, MixPose, MixDirection) + void apply(Skeleton& skeleton, float lastTime, float time, bool loop, Vector& events, float alpha, MixPose pose, MixDirection direction); + + std::string getName(); + + Vector getTimelines(); + + void setTimelines(Vector inValue); + + float getDuration(); + + void setDuration(float inValue); + + private: + Vector _timelines; + float _duration; + std::string _name; + + /// @param target After the first and before the last entry. + static int binarySearch(Vector& values, float target, int step); + + /// @param target After the first and before the last entry. + static int binarySearch(Vector& values, float target); + + static int linearSearch(Vector& values, float target, int step); + }; +} + +#endif /* Spine_Animation_h */ diff --git a/spine-cpp/spine-cpp/include/spine/Bone.h b/spine-cpp/spine-cpp/include/spine/Bone.h index a0b61867e..5cf390cad 100644 --- a/spine-cpp/spine-cpp/include/spine/Bone.h +++ b/spine-cpp/spine-cpp/include/spine/Bone.h @@ -47,10 +47,14 @@ namespace Spine /// constraint or application code modifies the world transform after it was computed from the local transform. class Bone : public Updatable { + RTTI_DECL; + friend class RotateTimeline; friend class IkConstraint; friend class TransformConstraint; friend class VertexAttachment; + friend class PathConstraint; + friend class Skeleton; public: static void setYDown(bool inValue); diff --git a/spine-cpp/spine-cpp/include/spine/Constraint.h b/spine-cpp/spine-cpp/include/spine/Constraint.h index e0c910d51..aa0122c34 100644 --- a/spine-cpp/spine-cpp/include/spine/Constraint.h +++ b/spine-cpp/spine-cpp/include/spine/Constraint.h @@ -38,6 +38,8 @@ namespace Spine /// The interface for all constraints. class Constraint : public Updatable { + RTTI_DECL; + public: Constraint(); diff --git a/spine-cpp/spine-cpp/include/spine/ContainerUtil.h b/spine-cpp/spine-cpp/include/spine/ContainerUtil.h index 11d8e34e6..fd415d42a 100644 --- a/spine-cpp/spine-cpp/include/spine/ContainerUtil.h +++ b/spine-cpp/spine-cpp/include/spine/ContainerUtil.h @@ -28,8 +28,8 @@ * POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -#ifndef Spine_Attachment_h -#define Spine_Attachment_h +#ifndef Spine_ContainerUtil_h +#define Spine_ContainerUtil_h #include #include @@ -50,7 +50,7 @@ namespace Spine { assert(name.length() > 0); - for (typename T* i = items.begin(); i != items.end(); ++i) + for (T** i = items.begin(); i != items.end(); ++i) { T* item = (*i); if (item->getName() == name) @@ -68,12 +68,50 @@ namespace Spine { assert(name.length() > 0); - for (size_t i = 0, size_t len = items.size(); i < len; ++i) + for (size_t i = 0, len = items.size(); i < len; ++i) { T* item = items[i]; if (item->getName() == name) { - return i; + return static_cast(i); + } + } + + return -1; + } + + /// Finds an item by comparing each item's name. + /// It is more efficient to cache the results of this method than to call it multiple times. + /// @return May be NULL. + template + static T* findWithDataName(Vector& items, std::string name) + { + assert(name.length() > 0); + + for (T** i = items.begin(); i != items.end(); ++i) + { + T* item = (*i); + if (item->getData().getName() == name) + { + return item; + } + } + + return NULL; + } + + /// @return -1 if the item was not found. + template + static int findIndexWithDataName(Vector& items, std::string name) + { + assert(name.length() > 0); + + for (size_t i = 0, len = items.size(); i < len; ++i) + { + T* item = items[i]; + if (item->getData().getName() == name) + { + return static_cast(i); } } @@ -111,4 +149,4 @@ namespace Spine }; } -#endif /* defined(__noctisgames__ContainerUtil__) */ +#endif /* Spine_ContainerUtil_h */ diff --git a/spine-cpp/spine-cpp/include/spine/CurveTimeline.h b/spine-cpp/spine-cpp/include/spine/CurveTimeline.h index ccf3b1f86..a5222e31e 100644 --- a/spine-cpp/spine-cpp/include/spine/CurveTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/CurveTimeline.h @@ -41,6 +41,8 @@ namespace Spine /// Base class for frames that use an interpolation bezier curve. class CurveTimeline : public Timeline { + RTTI_DECL; + public: CurveTimeline(int frameCount); diff --git a/spine-cpp/spine-cpp/include/spine/EventData.h b/spine-cpp/spine-cpp/include/spine/EventData.h index 9705f5d89..4f9982d1b 100644 --- a/spine-cpp/spine-cpp/include/spine/EventData.h +++ b/spine-cpp/spine-cpp/include/spine/EventData.h @@ -38,11 +38,9 @@ namespace Spine /// Stores the setup pose values for an Event. class EventData { - public: - int _intValue; - float _floatValue; - std::string _stringValue; + friend class Event; + public: EventData(std::string name); /// The name of the event, which is unique within the skeleton. @@ -58,8 +56,10 @@ namespace Spine void setStringValue(std::string inValue); private: - friend class Event; const std::string _name; + int _intValue; + float _floatValue; + std::string _stringValue; }; } diff --git a/spine-cpp/spine-cpp/include/spine/IkConstraint.h b/spine-cpp/spine-cpp/include/spine/IkConstraint.h index b7359ea7b..c09f8c7cd 100644 --- a/spine-cpp/spine-cpp/include/spine/IkConstraint.h +++ b/spine-cpp/spine-cpp/include/spine/IkConstraint.h @@ -43,6 +43,10 @@ namespace Spine class IkConstraint : public Constraint { + friend class Skeleton; + + RTTI_DECL; + public: /// Adjusts the bone rotation so the tip is as close to the target position as possible. The target is specified /// in the world coordinate system. @@ -78,9 +82,9 @@ namespace Spine private: IkConstraintData& _data; Vector _bones; - Bone* _target; float _mix; int _bendDirection; + Bone* _target; }; } diff --git a/spine-cpp/spine-cpp/include/spine/IkConstraintData.h b/spine-cpp/spine-cpp/include/spine/IkConstraintData.h index 521101734..0b516aa7e 100644 --- a/spine-cpp/spine-cpp/include/spine/IkConstraintData.h +++ b/spine-cpp/spine-cpp/include/spine/IkConstraintData.h @@ -41,6 +41,9 @@ namespace Spine class IkConstraintData { + friend class IkConstraint; + friend class Skeleton; + public: IkConstraintData(std::string name); diff --git a/spine-cpp/spine-cpp/include/spine/MathUtil.h b/spine-cpp/spine-cpp/include/spine/MathUtil.h index bc9bc5851..24dd4641c 100644 --- a/spine-cpp/spine-cpp/include/spine/MathUtil.h +++ b/spine-cpp/spine-cpp/include/spine/MathUtil.h @@ -73,11 +73,14 @@ namespace Spine return false; } + inline float clamp(float x, float lower, float upper) + { + return fminf(upper, fmaxf(x, lower)); + } + class MathUtil { public: - static float SIN_TABLE[SIN_COUNT]; - MathUtil(); /// Returns the sine in radians from a lookup table. @@ -95,12 +98,10 @@ namespace Spine /// Returns atan2 in radians, faster but less accurate than Math.Atan2. Average error of 0.00231 radians (0.1323 /// degrees), largest error of 0.00488 radians (0.2796 degrees). static float atan2(float y, float x); - }; - inline float clamp(float x, float lower, float upper) - { - return fminf(upper, fmaxf(x, lower)); - } + private: + static float SIN_TABLE[SIN_COUNT]; + }; } #endif /* Spine_MathUtil_h */ diff --git a/spine-cpp/spine-cpp/include/spine/MeshAttachment.h b/spine-cpp/spine-cpp/include/spine/MeshAttachment.h new file mode 100644 index 000000000..52f916689 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/MeshAttachment.h @@ -0,0 +1,143 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_MeshAttachment_h +#define Spine_MeshAttachment_h + +#include + +namespace Spine +{ + /// Attachment that displays a texture region using a mesh. + class MeshAttachment : public VertexAttachment + { + RTTI_DECL; + + public: + public int HullLength { get { return _hulllength; } set { _hulllength = value; } } + public float[] RegionUVs { get { return _regionUVs; } set { _regionUVs = value; } } + /// The UV pair for each vertex, normalized within the entire texture. + public float[] UVs { get { return _uvs; } set { _uvs = value; } } + public int[] Triangles { get { return _triangles; } set { _triangles = value; } } + + public float R { get { return r; } set { r = value; } } + public float G { get { return g; } set { g = value; } } + public float B { get { return b; } set { b = value; } } + public float A { get { return a; } set { a = value; } } + + public string Path { get; set; } + public object RendererObject; //public Object RendererObject { get; set; } + public float RegionU { get; set; } + public float RegionV { get; set; } + public float RegionU2 { get; set; } + public float RegionV2 { get; set; } + public bool RegionRotate { get; set; } + public float RegionOffsetX { get { return _regionOffsetX; } set { _regionOffsetX = value; } } + public float RegionOffsetY { get { return _regionOffsetY; } set { _regionOffsetY = value; } } // Pixels stripped from the bottom left, unrotated. + public float RegionWidth { get { return _regionWidth; } set { _regionWidth = value; } } + public float RegionHeight { get { return _regionHeight; } set { _regionHeight = value; } } // Unrotated, stripped size. + public float RegionOriginalWidth { get { return _regionOriginalWidth; } set { _regionOriginalWidth = value; } } + public float RegionOriginalHeight { get { return _regionOriginalHeight; } set { _regionOriginalHeight = value; } } // Unrotated, unstripped size. + + public bool InheritDeform { get { return _inheritDeform; } set { _inheritDeform = value; } } + + public MeshAttachment ParentMesh { + get { return _parentMesh; } + set { + _parentMesh = value; + if (value != null) { + bones = value.bones; + vertices = value.vertices; + worldVerticesLength = value.worldVerticesLength; + _regionUVs = value._regionUVs; + _triangles = value._triangles; + HullLength = value.HullLength; + Edges = value.Edges; + Width = value.Width; + Height = value.Height; + } + } + } + + // Nonessential. + public int[] Edges { get; set; } + public float Width { get; set; } + public float Height { get; set; } + + public MeshAttachment (string name) : VertexAttachment(name) + { + // Empty + } + + public void updateUVs() + { + float u = RegionU, v = RegionV, width = RegionU2 - RegionU, height = RegionV2 - RegionV; + if (_uvs == null || _uvs.Length != _regionUVs.Length) + { + _uvs = new float[_regionUVs.Length]; + } + + float[] _uvs = _uvs; + if (_regionRotate) + { + for (int i = 0, n = _uvs.Length; i < n; i += 2) + { + _uvs[i] = u + _regionUVs[i + 1] * width; + _uvs[i + 1] = v + height - _regionUVs[i] * height; + } + } + else + { + for (int i = 0, n = _uvs.Length; i < n; i += 2) + { + _uvs[i] = u + _regionUVs[i] * width; + _uvs[i + 1] = v + _regionUVs[i + 1] * height; + } + } + } + + virtual bool applyDeform(VertexAttachment* sourceAttachment) + { + return this == sourceAttachment || (_inheritDeform && _parentMesh == sourceAttachment); + } + + private: + float _regionOffsetX, _regionOffsetY, _regionWidth, _regionHeight, _regionOriginalWidth, _regionOriginalHeight; + MeshAttachment* _parentMesh; + float[] _uvs, _regionUVs; + int[] _triangles; + float r = 1, g = 1, b = 1, a = 1; + int _hulllength; + bool _inheritDeform; + bool _regionRotate; + } +} + +#endif /* Spine_MeshAttachment_h */ diff --git a/spine-cpp/spine-cpp/include/spine/PathAttachment.h b/spine-cpp/spine-cpp/include/spine/PathAttachment.h index 5eda9a360..6f0e53993 100644 --- a/spine-cpp/spine-cpp/include/spine/PathAttachment.h +++ b/spine-cpp/spine-cpp/include/spine/PathAttachment.h @@ -37,23 +37,23 @@ namespace Spine { class PathAttachment : public VertexAttachment { + RTTI_DECL; + public: - PathAttachment(std::string name) : VertexAttachment(name) - { - // Empty - } + PathAttachment(std::string name); /// The length in the setup pose from the start of the path to the end of each curve. - float[] Lengths { return lengths; } - set { lengths = value; } - bool Closed { return closed; } - set { closed = value; } - bool ConstantSpeed { return constantSpeed; } - set { constantSpeed = value; } + Vector& getLengths(); + void setLengths(Vector inValue); + bool isClosed(); + void setClosed(bool inValue); + bool isConstantSpeed(); + void setConstantSpeed(bool inValue); private: - float[] lengths; - bool closed, constantSpeed; + Vector _lengths; + bool _closed; + bool _constantSpeed; }; } diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraint.h b/spine-cpp/spine-cpp/include/spine/PathConstraint.h index 464622a3d..7f6440c48 100644 --- a/spine-cpp/spine-cpp/include/spine/PathConstraint.h +++ b/spine-cpp/spine-cpp/include/spine/PathConstraint.h @@ -45,6 +45,11 @@ namespace Spine class PathConstraint : public Constraint { + friend class Skeleton; + + RTTI_DECL; + + public: PathConstraint(PathConstraintData& data, Skeleton& skeleton); /// Applies the constraint to the constrained bones. diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraintData.h b/spine-cpp/spine-cpp/include/spine/PathConstraintData.h index 4acdf4513..fc7a77d16 100644 --- a/spine-cpp/spine-cpp/include/spine/PathConstraintData.h +++ b/spine-cpp/spine-cpp/include/spine/PathConstraintData.h @@ -45,6 +45,9 @@ namespace Spine class PathConstraintData { + friend class PathConstraint; + friend class Skeleton; + public: PathConstraintData(std::string name); diff --git a/spine-cpp/spine-cpp/include/spine/RegionAttachment.h b/spine-cpp/spine-cpp/include/spine/RegionAttachment.h new file mode 100644 index 000000000..6e513d3da --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/RegionAttachment.h @@ -0,0 +1,192 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_RegionAttachment_h +#define Spine_RegionAttachment_h + +#include + +#include +#include + +#include + +namespace Spine +{ + class Bone; + + /// Attachment that displays a texture region. + class RegionAttachment : public Attachment + { + RTTI_DECL; + + public: + const int BLX = 0; + const int BLY = 1; + const int ULX = 2; + const int ULY = 3; + const int URX = 4; + const int URY = 5; + const int BRX = 6; + const int BRY = 7; + + float X { get { return x; } set { x = value; } } + float Y { get { return y; } set { y = value; } } + float Rotation { get { return _rotation; } set { _rotation = value; } } + float ScaleX { get { return scaleX; } set { scaleX = value; } } + float ScaleY { get { return scaleY; } set { scaleY = value; } } + float Width { get { return width; } set { width = value; } } + float Height { get { return height; } set { height = value; } } + + float R { get { return r; } set { r = value; } } + float G { get { return g; } set { g = value; } } + float B { get { return b; } set { b = value; } } + float A { get { return a; } set { a = value; } } + + std::string Path { get; set; } + object RendererObject; //object RendererObject { get; set; } + float RegionOffsetX { get { return _regionOffsetX; } set { _regionOffsetX = value; } } + float RegionOffsetY { get { return _regionOffsetY; } set { _regionOffsetY = value; } } // Pixels stripped from the bottom left, unrotated. + float RegionWidth { get { return _regionWidth; } set { _regionWidth = value; } } + float RegionHeight { get { return _regionHeight; } set { _regionHeight = value; } } // Unrotated, stripped size. + float RegionOriginalWidth { get { return _regionOriginalWidth; } set { _regionOriginalWidth = value; } } + float RegionOriginalHeight { get { return _regionOriginalHeight; } set { _regionOriginalHeight = value; } } // Unrotated, unstripped size. + + float[] Offset { get { return _offset; } } + float[] UVs { get { return _uvs; } } + + RegionAttachment (std::string name) : Attachment(name) + { + // Empty + } + + void updateOffset() + { + float regionScaleX = _width / _regionOriginalWidth * _scaleX; + float regionScaleY = _height / _regionOriginalHeight * _scaleY; + float localX = -_width / 2 * _scaleX + _regionOffsetX * regionScaleX; + float localY = -_height / 2 * _scaleY + _regionOffsetY * regionScaleY; + float localX2 = localX + _regionWidth * regionScaleX; + float localY2 = localY + _regionHeight * regionScaleY; + float cos = MathUtil::cosDeg(_rotation); + float sin = MathUtil::sinDeg(_rotation); + float localXCos = localX * cos + _x; + float localXSin = localX * sin; + float localYCos = localY * cos + _y; + float localYSin = localY * sin; + float localX2Cos = localX2 * cos + _x; + float localX2Sin = localX2 * sin; + float localY2Cos = localY2 * cos + _y; + float localY2Sin = localY2 * sin; + + _offset[BLX] = localXCos - localYSin; + _offset[BLY] = localYCos + localXSin; + _offset[ULX] = localXCos - localY2Sin; + _offset[ULY] = localY2Cos + localXSin; + _offset[URX] = localX2Cos - localY2Sin; + _offset[URY] = localY2Cos + localX2Sin; + _offset[BRX] = localX2Cos - localYSin; + _offset[BRY] = localYCos + localX2Sin; + } + + void setUVs(float u, float v, float u2, float v2, bool rotate) + { + if (rotate) + { + _uvs[URX] = u; + _uvs[URY] = v2; + _uvs[BRX] = u; + _uvs[BRY] = v; + _uvs[BLX] = u2; + _uvs[BLY] = v; + _uvs[ULX] = u2; + _uvs[ULY] = v2; + } + else + { + _uvs[ULX] = u; + _uvs[ULY] = v2; + _uvs[URX] = u; + _uvs[URY] = v; + _uvs[BRX] = u2; + _uvs[BRY] = v; + _uvs[BLX] = u2; + _uvs[BLY] = v2; + } + } + + /// Transforms the attachment's four vertices to world coordinates. + /// @param bone The parent bone. + /// @param worldVertices The output world vertices. Must have a length greater than or equal to offset + 8. + /// @param offset The worldVertices index to begin writing values. + /// @param stride The number of worldVertices entries between the value pairs written. + void computeWorldVertices(Bone& bone, Vector worldVertices, int offset, int stride = 2) + { + assert(worldVertices.size() >= 8); + + float[] vertexOffset = _offset; + float bwx = bone.worldX, bwy = bone.worldY; + float a = bone.a, b = bone.b, c = bone.c, d = bone.d; + float offsetX, offsetY; + + offsetX = vertexOffset[BRX]; // 0 + offsetY = vertexOffset[BRY]; // 1 + worldVertices[offset] = offsetX * a + offsetY * b + bwx; // bl + worldVertices[offset + 1] = offsetX * c + offsetY * d + bwy; + offset += stride; + + offsetX = vertexOffset[BLX]; // 2 + offsetY = vertexOffset[BLY]; // 3 + worldVertices[offset] = offsetX * a + offsetY * b + bwx; // ul + worldVertices[offset + 1] = offsetX * c + offsetY * d + bwy; + offset += stride; + + offsetX = vertexOffset[ULX]; // 4 + offsetY = vertexOffset[ULY]; // 5 + worldVertices[offset] = offsetX * a + offsetY * b + bwx; // ur + worldVertices[offset + 1] = offsetX * c + offsetY * d + bwy; + offset += stride; + + offsetX = vertexOffset[URX]; // 6 + offsetY = vertexOffset[URY]; // 7 + worldVertices[offset] = offsetX * a + offsetY * b + bwx; // br + worldVertices[offset + 1] = offsetX * c + offsetY * d + bwy; + } + + private: + float _x, _y, _rotation, _scaleX = 1, _scaleY = 1, _width, _height; + float _regionOffsetX, _regionOffsetY, _regionWidth, _regionHeight, _regionOriginalWidth, _regionOriginalHeight; + float[] _offset = new float[8]; + float[] _uvs = new float[8]; + float r = 1, g = 1, b = 1, a = 1; + } +} + +#endif /* Spine_RegionAttachment_h */ diff --git a/spine-cpp/spine-cpp/include/spine/RotateTimeline.h b/spine-cpp/spine-cpp/include/spine/RotateTimeline.h index 9b2ff0403..dcc013b71 100644 --- a/spine-cpp/spine-cpp/include/spine/RotateTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/RotateTimeline.h @@ -37,6 +37,8 @@ namespace Spine { class RotateTimeline : public CurveTimeline { + RTTI_DECL; + public: static const int ENTRIES = 2; diff --git a/spine-cpp/spine-cpp/include/spine/Skeleton.h b/spine-cpp/spine-cpp/include/spine/Skeleton.h index 5c4f3e782..9e3eb9583 100644 --- a/spine-cpp/spine-cpp/include/spine/Skeleton.h +++ b/spine-cpp/spine-cpp/include/spine/Skeleton.h @@ -90,11 +90,11 @@ namespace Spine /// If there was no old skin, each slot's setup mode attachment is attached from the new skin. /// After changing the skin, the visible attachments can be reset to those attached in the setup pose by calling /// See Skeleton::setSlotsToSetupPose() - /// Also, often AnimationState::Apply(Skeleton&) is called before the next time the + /// Also, often AnimationState::apply(Skeleton&) is called before the next time the /// skeleton is rendered to allow any attachment keys in the current animation(s) to hide or show attachments from the new skin. /// /// @param newSkin May be NULL. - void setSkin(Skin newSkin); + void setSkin(Skin* newSkin); /// @return May be NULL. Attachment* getAttachment(std::string slotName, std::string attachmentName); @@ -136,7 +136,6 @@ namespace Spine Vector& getTransformConstraints(); Skin* getSkin(); - void setSkin(Skin* inValue); float getR(); void setR(float inValue); float getG(); @@ -167,7 +166,7 @@ namespace Spine Vector _updateCache; Vector _updateCacheReset; Skin* _skin; - float _r = 1, _g = 1, _b = 1, _a = 1; + float _r, _g, _b, _a; float _time; bool _flipX, _flipY; float _x, _y; @@ -178,11 +177,11 @@ namespace Spine void sortTransformConstraint(TransformConstraint* constraint); - void sortPathConstraintAttachment(Skin* skin, int slotIndex, Bone* slotBone); + void sortPathConstraintAttachment(Skin* skin, int slotIndex, Bone& slotBone); - void sortPathConstraintAttachment(Attachment* attachment, Bone* slotBone); + void sortPathConstraintAttachment(Attachment* attachment, Bone& slotBone); - void sortBone(Bone bone); + void sortBone(Bone* bone); static void sortReset(Vector& bones); }; diff --git a/spine-cpp/spine-cpp/include/spine/SkeletonData.h b/spine-cpp/spine-cpp/include/spine/SkeletonData.h index 4508d537a..44e467edc 100644 --- a/spine-cpp/spine-cpp/include/spine/SkeletonData.h +++ b/spine-cpp/spine-cpp/include/spine/SkeletonData.h @@ -49,6 +49,8 @@ namespace Spine /// Stores the setup pose and all of the stateless data for a skeleton. class SkeletonData { + friend class Skeleton; + public: SkeletonData(); diff --git a/spine-cpp/spine-cpp/include/spine/Skin.h b/spine-cpp/spine-cpp/include/spine/Skin.h index b6f36dd9c..37f7ea64a 100644 --- a/spine-cpp/spine-cpp/include/spine/Skin.h +++ b/spine-cpp/spine-cpp/include/spine/Skin.h @@ -35,8 +35,6 @@ #include #include -struct HashAttachmentKey; - namespace Spine { class Attachment; @@ -47,18 +45,37 @@ namespace Spine /// http://esotericsoftware.com/spine-runtime-skins in the Spine Runtimes Guide. class Skin { + friend class Skeleton; + public: class AttachmentKey { - public: - const int _slotIndex; - const std::string _name; + public: + int _slotIndex; + std::string _name; - AttachmentKey(int slotIndex, std::string name); + AttachmentKey(int slotIndex = 0, std::string name = ""); bool operator==(const AttachmentKey &other) const; }; + struct HashAttachmentKey + { + std::size_t operator()(const Spine::Skin::AttachmentKey& val) const + { + std::size_t h1 = val._slotIndex; + + std::size_t h2 = 7; + size_t strlen = val._name.length(); + for (int i = 0; i < strlen; ++i) + { + h2 = h2 * 31 + val._name.at(i); + } + + return h1 ^ (h2 << 1); + } + }; + Skin(std::string name); /// Adds an attachment to the skin for the specified slot index and name. @@ -90,21 +107,4 @@ namespace Spine }; } -struct HashAttachmentKey -{ - std::size_t operator()(const Spine::Skin::AttachmentKey& val) const - { - std::size_t h1 = static_cast inValue); private: - SlotData& _slotData; + SlotData& _data; Bone& _bone; Skeleton& _skeleton; float _r, _g, _b, _a; diff --git a/spine-cpp/spine-cpp/include/spine/SlotData.h b/spine-cpp/spine-cpp/include/spine/SlotData.h index 310cf1fd5..0fe231984 100644 --- a/spine-cpp/spine-cpp/include/spine/SlotData.h +++ b/spine-cpp/spine-cpp/include/spine/SlotData.h @@ -42,7 +42,7 @@ namespace Spine class SlotData { public: - SlotData(int index, std::string name, const BoneData& boneData); + SlotData(int index, std::string name, BoneData& boneData); const int getIndex(); diff --git a/spine-cpp/spine-cpp/include/spine/Timeline.h b/spine-cpp/spine-cpp/include/spine/Timeline.h index 056ba8d39..b00db7b28 100644 --- a/spine-cpp/spine-cpp/include/spine/Timeline.h +++ b/spine-cpp/spine-cpp/include/spine/Timeline.h @@ -31,6 +31,7 @@ #ifndef Spine_Timeline_h #define Spine_Timeline_h +#include #include #include #include @@ -42,6 +43,8 @@ namespace Spine class Timeline { + RTTI_DECL; + public: Timeline(); diff --git a/spine-cpp/spine-cpp/include/spine/TransformConstraint.h b/spine-cpp/spine-cpp/include/spine/TransformConstraint.h index 550988911..262c3a210 100644 --- a/spine-cpp/spine-cpp/include/spine/TransformConstraint.h +++ b/spine-cpp/spine-cpp/include/spine/TransformConstraint.h @@ -43,6 +43,10 @@ namespace Spine class TransformConstraint : public Constraint { + friend class Skeleton; + + RTTI_DECL; + public: TransformConstraint(TransformConstraintData& data, Skeleton& skeleton); diff --git a/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h b/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h index c74bc25bc..d3a5aebb3 100644 --- a/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h +++ b/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h @@ -42,6 +42,7 @@ namespace Spine class TransformConstraintData { friend class TransformConstraint; + friend class Skeleton; public: TransformConstraintData(std::string name); diff --git a/spine-cpp/spine-cpp/include/spine/Updatable.h b/spine-cpp/spine-cpp/include/spine/Updatable.h index a521ca72a..fac634191 100644 --- a/spine-cpp/spine-cpp/include/spine/Updatable.h +++ b/spine-cpp/spine-cpp/include/spine/Updatable.h @@ -31,10 +31,14 @@ #ifndef Spine_Updatable_h #define Spine_Updatable_h +#include + namespace Spine { class Updatable { + RTTI_DECL; + public: Updatable(); diff --git a/spine-cpp/spine-cpp/include/spine/Vector.h b/spine-cpp/spine-cpp/include/spine/Vector.h index df2e18e7d..8fc232098 100644 --- a/spine-cpp/spine-cpp/include/spine/Vector.h +++ b/spine-cpp/spine-cpp/include/spine/Vector.h @@ -65,43 +65,56 @@ namespace Spine deallocate(_buffer); } - void push_back(const T& _value) + bool contains(const T& inValue) { - if (_size == _capacity) + for (size_t i = 0; i < _size; ++i) { - reserve(); + if (_buffer[i] == inValue) + { + return true; + } } - construct(_buffer + _size++, _value); + return false; } - void insert(size_t _index, const T& _value) + void push_back(const T& inValue) { - assert(_index < _size); + if (_size == _capacity) + { + reserve(); + } + + construct(_buffer + _size++, inValue); + } + + void insert(size_t inIndex, const T& inValue) + { + assert(inIndex < _size); if (_size == _capacity) { reserve(); } - for (size_t i = ++_size - 1; i > _index; --i) + for (size_t i = ++_size - 1; i > inIndex; --i) { construct(_buffer + i, _buffer[i - 1]); destroy(_buffer + (i - 1)); } - construct(_buffer + _index, _value); + construct(_buffer + inIndex, inValue); } - void erase(size_t _index) + void erase(size_t inIndex) { - assert(_index < _size); + assert(inIndex < _size); --_size; - if (_index != _size) + if (inIndex != _size) { - for (size_t i = _index; i < _size; ++i) + for (size_t i = inIndex; i < _size; ++i) { _buffer[i] = std::move(_buffer[i + 1]); } @@ -125,18 +138,21 @@ namespace Spine return _size; } - T& operator[](size_t _index) + T& operator[](size_t inIndex) { - assert(_index < _size); + assert(inIndex < _size); - return _buffer[_index]; + return _buffer[inIndex]; } - void reserve(long inCapacity = -1) + void reserve(size_t inCapacity = 0) { - size_t newCapacity = inCapacity != -1 ? inCapacity : _capacity ? _capacity * 2 : 1; - _buffer = static_cast(realloc(_buffer, newCapacity * sizeof(T))); - _capacity = newCapacity; + size_t newCapacity = inCapacity > 0 ? inCapacity : _capacity > 0 ? _capacity * 2 : 1; + if (newCapacity > _capacity) + { + _buffer = static_cast(realloc(_buffer, newCapacity * sizeof(T))); + _capacity = newCapacity; + } } T* begin() diff --git a/spine-cpp/spine-cpp/include/spine/VertexAttachment.h b/spine-cpp/spine-cpp/include/spine/VertexAttachment.h index 18b5fc81c..ba047dfe8 100644 --- a/spine-cpp/spine-cpp/include/spine/VertexAttachment.h +++ b/spine-cpp/spine-cpp/include/spine/VertexAttachment.h @@ -40,8 +40,10 @@ namespace Spine class Slot; /// An attachment with vertices that are transformed by one or more bones and can be deformed by a slot's vertices. - class VertexAttachment : Attachment + class VertexAttachment : public Attachment { + RTTI_DECL; + public: VertexAttachment(std::string name); @@ -61,10 +63,10 @@ namespace Spine /// Gets a unique ID for this attachment. int getId(); - Vector getBones(); + Vector& getBones(); void setBones(Vector inValue); - Vector getVertices(); + Vector& getVertices(); void setVertices(Vector inValue); int getWorldVerticesLength(); diff --git a/spine-cpp/spine-cpp/src/spine/Animation.cpp b/spine-cpp/spine-cpp/src/spine/Animation.cpp new file mode 100644 index 000000000..3cbc2e63c --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/Animation.cpp @@ -0,0 +1,166 @@ +/****************************************************************************** +* Spine Runtimes Software License v2.5 +* +* Copyright (c) 2013-2016, Esoteric Software +* All rights reserved. +* +* You are granted a perpetual, non-exclusive, non-sublicensable, and +* non-transferable license to use, install, execute, and perform the Spine +* Runtimes software and derivative works solely for personal or internal +* use. Without the written permission of Esoteric Software (see Section 2 of +* the Spine Software License Agreement), you may not (a) modify, translate, +* adapt, or develop new applications using the Spine Runtimes or otherwise +* create derivative works or improvements of the Spine Runtimes or (b) remove, +* delete, alter, or obscure any trademarks or any copyright, trademark, patent, +* or other intellectual property or proprietary rights notices on or in the +* Software, including any copy thereof. Redistributions in binary or source +* form must include this license and terms. +* +* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include /* fmod */ + +namespace Spine +{ + Animation::Animation(std::string name, Vector& timelines, float duration) : + _name(name), + _timelines(timelines), + _duration(duration) + { + assert(_name.length() > 0); + } + + void Animation::apply(Skeleton& skeleton, float lastTime, float time, bool loop, Vector& events, float alpha, MixPose pose, MixDirection direction) + { + if (loop && _duration != 0) + { + time = fmod(time, _duration); + if (lastTime > 0) + { + lastTime = fmod(lastTime, _duration); + } + } + + for (int i = 0, n = static_cast(_timelines.size()); i < n; ++i) + { + _timelines[i]->apply(skeleton, lastTime, time, events, alpha, pose, direction); + } + } + + std::string Animation::getName() + { + return _name; + } + + Vector Animation::getTimelines() + { + return _timelines; + } + + void Animation::setTimelines(Vector inValue) + { + _timelines = inValue; + } + + float Animation::getDuration() + { + return _duration; + } + + void Animation::setDuration(float inValue) + { + _duration = inValue; + } + + int Animation::binarySearch(Vector& values, float target, int step) + { + int low = 0; + int size = static_cast(values.size()); + int high = size / step - 2; + if (high == 0) + { + return step; + } + + int current = (int)(static_cast(high) >> 1); + while (true) + { + if (values[(current + 1) * step] <= target) + { + low = current + 1; + } + else + { + high = current; + } + + if (low == high) + { + return (low + 1) * step; + } + + current = (int)(static_cast(low + high) >> 1); + } + } + + int Animation::binarySearch(Vector& values, float target) + { + int low = 0; + int size = static_cast(values.size()); + int high = size - 2; + if (high == 0) + { + return 1; + } + + int current = (int)(static_cast(high) >> 1); + while (true) + { + if (values[(current + 1)] <= target) + { + low = current + 1; + } + else + { + high = current; + } + + if (low == high) + { + return (low + 1); + } + + current = (int)(static_cast(low + high) >> 1); + } + } + + int Animation::linearSearch(Vector& values, float target, int step) + { + for (int i = 0, last = static_cast(values.size()) - step; i <= last; i += step) + { + if (values[i] > target) + { + return i; + } + } + + return -1; + } +} diff --git a/spine-cpp/spine-cpp/src/spine/Bone.cpp b/spine-cpp/spine-cpp/src/spine/Bone.cpp index f4fe9ed59..bb8dcc004 100644 --- a/spine-cpp/spine-cpp/src/spine/Bone.cpp +++ b/spine-cpp/spine-cpp/src/spine/Bone.cpp @@ -621,4 +621,6 @@ namespace Spine _arotation = 90 - MathUtil::atan2(rd, rb) * RadDeg; } } + + RTTI_IMPL(Bone, Updatable); } diff --git a/spine-cpp/spine-cpp/src/spine/Constraint.cpp b/spine-cpp/spine-cpp/src/spine/Constraint.cpp index e6e84bd6c..ae6a8d749 100644 --- a/spine-cpp/spine-cpp/src/spine/Constraint.cpp +++ b/spine-cpp/spine-cpp/src/spine/Constraint.cpp @@ -41,5 +41,6 @@ namespace Spine { // Empty } + + RTTI_IMPL(Constraint, Updatable); } - diff --git a/spine-cpp/spine-cpp/src/spine/CurveTimeline.cpp b/spine-cpp/spine-cpp/src/spine/CurveTimeline.cpp index 67c0435cf..9735c76dc 100644 --- a/spine-cpp/spine-cpp/src/spine/CurveTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/CurveTimeline.cpp @@ -133,4 +133,6 @@ namespace Spine { return _curves[frameIndex * BEZIER_SIZE]; } + + RTTI_IMPL(CurveTimeline, Timeline); } diff --git a/spine-cpp/spine-cpp/src/spine/Event.cpp b/spine-cpp/spine-cpp/src/spine/Event.cpp index 5f1458815..ca9abdbbd 100644 --- a/spine-cpp/spine-cpp/src/spine/Event.cpp +++ b/spine-cpp/spine-cpp/src/spine/Event.cpp @@ -39,7 +39,7 @@ namespace Spine _data(data), _intValue(0), _floatValue(0), - _stringValue(0) + _stringValue() { // Empty } diff --git a/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp b/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp index 73e68082d..1bf6cdb74 100644 --- a/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp +++ b/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp @@ -357,4 +357,6 @@ namespace Spine { _mix = inValue; } + + RTTI_IMPL(IkConstraint, Constraint); } diff --git a/spine-cpp/spine-cpp/src/spine/MeshAttachment.cpp b/spine-cpp/spine-cpp/src/spine/MeshAttachment.cpp new file mode 100644 index 000000000..42159e2c9 --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/MeshAttachment.cpp @@ -0,0 +1,36 @@ + /****************************************************************************** +* Spine Runtimes Software License v2.5 +* +* Copyright (c) 2013-2016, Esoteric Software +* All rights reserved. +* +* You are granted a perpetual, non-exclusive, non-sublicensable, and +* non-transferable license to use, install, execute, and perform the Spine +* Runtimes software and derivative works solely for personal or internal +* use. Without the written permission of Esoteric Software (see Section 2 of +* the Spine Software License Agreement), you may not (a) modify, translate, +* adapt, or develop new applications using the Spine Runtimes or otherwise +* create derivative works or improvements of the Spine Runtimes or (b) remove, +* delete, alter, or obscure any trademarks or any copyright, trademark, patent, +* or other intellectual property or proprietary rights notices on or in the +* Software, including any copy thereof. Redistributions in binary or source +* form must include this license and terms. +* +* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +#include + +namespace Spine +{ + RTTI_IMPL(MeshAttachment, VertexAttachment); +} diff --git a/spine-cpp/spine-cpp/src/spine/PathAttachment.cpp b/spine-cpp/spine-cpp/src/spine/PathAttachment.cpp index bb4d2ccfe..d7d57ccd9 100644 --- a/spine-cpp/spine-cpp/src/spine/PathAttachment.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathAttachment.cpp @@ -28,7 +28,44 @@ * POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ +#include + namespace Spine { - // TODO + PathAttachment::PathAttachment(std::string name) : VertexAttachment(name) + { + // Empty + } + + Vector& PathAttachment::getLengths() + { + return _lengths; + } + + void PathAttachment::setLengths(Vector inValue) + { + _lengths = inValue; + } + + bool PathAttachment::isClosed() + { + return _closed; + } + + void PathAttachment::setClosed(bool inValue) + { + _closed = inValue; + } + + bool PathAttachment::isConstantSpeed() + { + return _constantSpeed; + } + + void PathAttachment::setConstantSpeed(bool inValue) + { + _constantSpeed = inValue; + } + + RTTI_IMPL(PathAttachment, VertexAttachment); } diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp b/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp index 32e688782..6efbbb7be 100644 --- a/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp @@ -94,42 +94,45 @@ namespace Spine } PathConstraintData data = _data; - SpacingMode spacingMode = data.spacingMode; - bool lengthSpacing = spacingMode == SpacingMode.Length; - RotateMode rotateMode = data.rotateMode; + SpacingMode spacingMode = data._spacingMode; + bool lengthSpacing = spacingMode == SpacingMode_Length; + RotateMode rotateMode = data._rotateMode; bool tangents = rotateMode == RotateMode_Tangent, scale = rotateMode == RotateMode_ChainScale; - int boneCount = _bones.Count, spacesCount = tangents ? boneCount : boneCount + 1; - Bone[] bonesItems = _bones.Items; - Vector spaces = _spaces.Resize(spacesCount), lengths = NULL; + size_t boneCount = _bones.size(); + int spacesCount = static_cast(tangents ? boneCount : boneCount + 1); + _spaces.reserve(spacesCount); float spacing = _spacing; if (scale || lengthSpacing) { if (scale) { - lengths = _lengths.Resize(boneCount); + _lengths.reserve(boneCount); } for (int i = 0, n = spacesCount - 1; i < n;) { - Bone bone = bonesItems[i]; - float setupLength = bone.data.length; - if (setupLength < PathConstraint.EPSILON) + Bone* boneP = _bones[i]; + Bone bone = *boneP; + float setupLength = bone._data.getLength(); + if (setupLength < PathConstraint::EPSILON) { if (scale) { - lengths.Items[i] = 0; + _lengths[i] = 0; } - spaces.Items[++i] = 0; + _spaces[++i] = 0; } else { - float x = setupLength * bone.a, y = setupLength * bone.c; - float length = (float)Math.Sqrt(x * x + y * y); + float x = setupLength * bone._a; + float y = setupLength * bone._c; + float length = (float)sqrt(x * x + y * y); if (scale) { - lengths.Items[i] = length; + _lengths[i] = length; } - spaces.Items[++i] = (lengthSpacing ? setupLength + spacing : spacing) * length / setupLength; + + _spaces[++i] = (lengthSpacing ? setupLength + spacing : spacing) * length / setupLength; } } } @@ -137,12 +140,14 @@ namespace Spine { for (int i = 1; i < spacesCount; ++i) { - spaces.Items[i] = spacing; + _spaces[i] = spacing; } } - float[] positions = computeWorldPositions(attachment, spacesCount, tangents, data.positionMode == PositionMode_Percent, spacingMode == SpacingMode_Percent); - float boneX = positions[0], boneY = positions[1], offsetRotation = data.offsetRotation; + Vector positions = computeWorldPositions(*attachment, spacesCount, tangents, data.getPositionMode() == PositionMode_Percent, spacingMode == SpacingMode_Percent); + float boneX = positions[0]; + float boneY = positions[1]; + float offsetRotation = data.getOffsetRotation(); bool tip; if (offsetRotation == 0) { @@ -151,24 +156,28 @@ namespace Spine else { tip = false; - Bone p = target.bone; - offsetRotation *= p.a * p.d - p.b * p.c > 0 ? DegRad : -DegRad; + Bone p = _target->getBone(); + offsetRotation *= p.getA() * p.getD() - p.getB() * p.getC() > 0 ? DegRad : -DegRad; } for (int i = 0, p = 3; i < boneCount; i++, p += 3) { - Bone bone = bonesItems[i]; - bone.worldX += (boneX - bone.worldX) * translateMix; - bone.worldY += (boneY - bone.worldY) * translateMix; - float x = positions[p], y = positions[p + 1], dx = x - boneX, dy = y - boneY; + Bone* boneP = _bones[i]; + Bone bone = *boneP; + bone._worldX += (boneX - bone._worldX) * translateMix; + bone._worldY += (boneY - bone._worldY) * translateMix; + float x = positions[p]; + float y = positions[p + 1]; + float dx = x - boneX; + float dy = y - boneY; if (scale) { - float length = lengths.Items[i]; - if (length >= PathConstraint.EPSILON) + float length = _lengths[i]; + if (length >= PathConstraint::EPSILON) { - float s = ((float)Math.Sqrt(dx * dx + dy * dy) / length - 1) * rotateMix + 1; - bone.a *= s; - bone.c *= s; + float s = ((float)sqrt(dx * dx + dy * dy) / length - 1) * rotateMix + 1; + bone._a *= s; + bone._c *= s; } } @@ -177,12 +186,12 @@ namespace Spine if (rotate) { - float a = bone.a, b = bone.b, c = bone.c, d = bone.d, r, cos, sin; + float a = bone._a, b = bone._b, c = bone._c, d = bone._d, r, cos, sin; if (tangents) { r = positions[p - 1]; } - else if (spaces.Items[i + 1] < PathConstraint.EPSILON) + else if (_spaces[i + 1] < PathConstraint::EPSILON) { r = positions[p + 2]; } @@ -197,7 +206,7 @@ namespace Spine { cos = MathUtil::cos(r); sin = MathUtil::sin(r); - float length = bone.data.length; + float length = bone._data.getLength(); boneX += (length * (cos * a - sin * c) - dx) * rotateMix; boneY += (length * (sin * a + cos * c) - dy) * rotateMix; } @@ -218,12 +227,13 @@ namespace Spine r *= rotateMix; cos = MathUtil::cos(r); sin = MathUtil::sin(r); - bone.a = cos * a - sin * c; - bone.b = cos * b - sin * d; - bone.c = sin * a + cos * c; - bone.d = sin * b + cos * d; + bone._a = cos * a - sin * c; + bone._b = cos * b - sin * d; + bone._c = sin * a + cos * c; + bone._d = sin * b + cos * d; } - bone.appliedValid = false; + + bone._appliedValid = false; } } @@ -296,14 +306,18 @@ namespace Spine { Slot target = *_target; float position = _position; - float[] spacesItems = _spaces.Items, output = _positions.Resize(spacesCount * 3 + 2).Items, world; - bool closed = path.Closed; - int verticesLength = path.WorldVerticesLength, curveCount = verticesLength / 6, prevCurve = NONE; +// float[] spacesItems = _spaces.Items; +// float[] output = _positions.Resize(spacesCount * 3 + 2).Items; + _positions.reserve(spacesCount * 3 + 2); + bool closed = path.isClosed(); + int verticesLength = path.getWorldVerticesLength(); + int curveCount = verticesLength / 6; + int prevCurve = NONE; float pathLength; - if (!path.ConstantSpeed) + if (!path.isConstantSpeed()) { - float[] lengths = path.Lengths; + Vector& lengths = path.getLengths(); curveCount -= closed ? 1 : 2; pathLength = lengths[curveCount]; if (percentPosition) @@ -315,20 +329,21 @@ namespace Spine { for (int i = 0; i < spacesCount; ++i) { - spacesItems[i] *= pathLength; + _spaces[i] *= pathLength; } } - world = _world.Resize(8).Items; + _world.reserve(8); for (int i = 0, o = 0, curve = 0; i < spacesCount; i++, o += 3) { - float space = spacesItems[i]; + float space = _spaces[i]; position += space; float p = position; if (closed) { - p %= pathLength; + p = fmod(p, pathLength); + if (p < 0) { p += pathLength; @@ -340,10 +355,10 @@ namespace Spine if (prevCurve != BEFORE) { prevCurve = BEFORE; - path.ComputeWorldVertices(target, 2, 4, world, 0); + path.computeWorldVertices(target, 2, 4, _world, 0); } - addBeforePosition(p, world, 0, output, o); + addBeforePosition(p, _world, 0, _positions, o); continue; } @@ -352,10 +367,10 @@ namespace Spine if (prevCurve != AFTER) { prevCurve = AFTER; - path.ComputeWorldVertices(target, verticesLength - 6, 4, world, 0); + path.computeWorldVertices(target, verticesLength - 6, 4, _world, 0); } - addAfterPosition(p - pathLength, world, 0, output, o); + addAfterPosition(p - pathLength, _world, 0, _positions, o); continue; } @@ -386,51 +401,51 @@ namespace Spine prevCurve = curve; if (closed && curve == curveCount) { - path.ComputeWorldVertices(target, verticesLength - 4, 4, world, 0); - path.ComputeWorldVertices(target, 0, 4, world, 4); + path.computeWorldVertices(target, verticesLength - 4, 4, _world, 0); + path.computeWorldVertices(target, 0, 4, _world, 4); } else { - path.ComputeWorldVertices(target, curve * 6 + 2, 8, world, 0); + path.computeWorldVertices(target, curve * 6 + 2, 8, _world, 0); } } - addCurvePosition(p, world[0], world[1], world[2], world[3], world[4], world[5], world[6], world[7], output, o, tangents || (i > 0 && space < EPSILON)); + addCurvePosition(p, _world[0], _world[1], _world[2], _world[3], _world[4], _world[5], _world[6], _world[7], _positions, o, tangents || (i > 0 && space < EPSILON)); } - return output; + return _world; } // World vertices. if (closed) { verticesLength += 2; - world = _world.Resize(verticesLength).Items; - path.ComputeWorldVertices(target, 2, verticesLength - 4, world, 0); - path.ComputeWorldVertices(target, 0, 2, world, verticesLength - 4); - world[verticesLength - 2] = world[0]; - world[verticesLength - 1] = world[1]; + _world.reserve(verticesLength); + path.computeWorldVertices(target, 2, verticesLength - 4, _world, 0); + path.computeWorldVertices(target, 0, 2, _world, verticesLength - 4); + _world[verticesLength - 2] = _world[0]; + _world[verticesLength - 1] = _world[1]; } else { curveCount--; verticesLength -= 4; - world = _world.Resize(verticesLength).Items; - path.ComputeWorldVertices(target, 2, verticesLength, world, 0); + _world.reserve(verticesLength); + path.computeWorldVertices(target, 2, verticesLength, _world, 0); } // Curve lengths. - float[] curves = _curves.Resize(curveCount).Items; + _curves.reserve(curveCount); pathLength = 0; - float x1 = world[0], y1 = world[1], cx1 = 0, cy1 = 0, cx2 = 0, cy2 = 0, x2 = 0, y2 = 0; + float x1 = _world[0], y1 = _world[1], cx1 = 0, cy1 = 0, cx2 = 0, cy2 = 0, x2 = 0, y2 = 0; float tmpx, tmpy, dddfx, dddfy, ddfx, ddfy, dfx, dfy; for (int 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]; + 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; @@ -439,19 +454,19 @@ namespace Spine ddfy = tmpy * 2 + dddfy; dfx = (cx1 - x1) * 0.75f + tmpx + dddfx * 0.16666667f; dfy = (cy1 - y1) * 0.75f + tmpy + dddfy * 0.16666667f; - pathLength += (float)Math.Sqrt(dfx * dfx + dfy * dfy); + pathLength += (float)sqrt(dfx * dfx + dfy * dfy); dfx += ddfx; dfy += ddfy; ddfx += dddfx; ddfy += dddfy; - pathLength += (float)Math.Sqrt(dfx * dfx + dfy * dfy); + pathLength += (float)sqrt(dfx * dfx + dfy * dfy); dfx += ddfx; dfy += ddfy; - pathLength += (float)Math.Sqrt(dfx * dfx + dfy * dfy); + pathLength += (float)sqrt(dfx * dfx + dfy * dfy); dfx += ddfx + dddfx; dfy += ddfy + dddfy; - pathLength += (float)Math.Sqrt(dfx * dfx + dfy * dfy); - curves[i] = pathLength; + pathLength += (float)sqrt(dfx * dfx + dfy * dfy); + _curves[i] = pathLength; x1 = x2; y1 = y2; } @@ -465,21 +480,21 @@ namespace Spine { for (int i = 0; i < spacesCount; ++i) { - spacesItems[i] *= pathLength; + _spaces[i] *= pathLength; } } - float[] segments = _segments; float curveLength = 0; for (int i = 0, o = 0, curve = 0, segment = 0; i < spacesCount; i++, o += 3) { - float space = spacesItems[i]; + float space = _spaces[i]; position += space; float p = position; if (closed) { - p %= pathLength; + p = fmod(p, pathLength); + if (p < 0) { p += pathLength; @@ -488,19 +503,19 @@ namespace Spine } else if (p < 0) { - addBeforePosition(p, world, 0, output, o); + addBeforePosition(p, _world, 0, _positions, o); continue; } else if (p > pathLength) { - addAfterPosition(p - pathLength, world, verticesLength - 4, output, o); + addAfterPosition(p - pathLength, _world, verticesLength - 4, _positions, o); continue; } // Determine curve containing position. for (;; curve++) { - float length = curves[curve]; + float length = _curves[curve]; if (p > length) { continue; @@ -512,7 +527,7 @@ namespace Spine } else { - float prev = curves[curve - 1]; + float prev = _curves[curve - 1]; p = (p - prev) / (length - prev); } break; @@ -523,14 +538,14 @@ namespace Spine { prevCurve = curve; int 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]; + 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; @@ -539,25 +554,25 @@ namespace Spine ddfy = tmpy * 2 + dddfy; dfx = (cx1 - x1) * 0.3f + tmpx + dddfx * 0.16666667f; dfy = (cy1 - y1) * 0.3f + tmpy + dddfy * 0.16666667f; - curveLength = (float)Math.Sqrt(dfx * dfx + dfy * dfy); - segments[0] = curveLength; + curveLength = (float)sqrt(dfx * dfx + dfy * dfy); + _segments[0] = curveLength; for (ii = 1; ii < 8; ii++) { dfx += ddfx; dfy += ddfy; ddfx += dddfx; ddfy += dddfy; - curveLength += (float)Math.Sqrt(dfx * dfx + dfy * dfy); - segments[ii] = curveLength; + curveLength += (float)sqrt(dfx * dfx + dfy * dfy); + _segments[ii] = curveLength; } dfx += ddfx; dfy += ddfy; - curveLength += (float)Math.Sqrt(dfx * dfx + dfy * dfy); - segments[8] = curveLength; + curveLength += (float)sqrt(dfx * dfx + dfy * dfy); + _segments[8] = curveLength; dfx += ddfx + dddfx; dfy += ddfy + dddfy; - curveLength += (float)Math.Sqrt(dfx * dfx + dfy * dfy); - segments[9] = curveLength; + curveLength += (float)sqrt(dfx * dfx + dfy * dfy); + _segments[9] = curveLength; segment = 0; } @@ -565,7 +580,7 @@ namespace Spine p *= curveLength; for (;; segment++) { - float length = segments[segment]; + float length = _segments[segment]; if (p > length) { continue; @@ -577,15 +592,15 @@ namespace Spine } else { - float prev = segments[segment - 1]; + float prev = _segments[segment - 1]; p = segment + (p - prev) / (length - prev); } break; } - addCurvePosition(p * 0.1f, x1, y1, cx1, cy1, cx2, cy2, x2, y2, output, o, tangents || (i > 0 && space < EPSILON)); + addCurvePosition(p * 0.1f, x1, y1, cx1, cy1, cx2, cy2, x2, y2, _positions, o, tangents || (i > 0 && space < EPSILON)); } - return output; + return _positions; } void PathConstraint::addBeforePosition(float p, Vector& temp, int i, Vector& output, int o) @@ -615,7 +630,7 @@ namespace Spine void PathConstraint::addCurvePosition(float p, float x1, float y1, float cx1, float cy1, float cx2, float cy2, float x2, float y2, Vector& output, int o, bool tangents) { - if (p < EPSILON || float.IsNaN(p)) + if (p < EPSILON || isnan(p)) { p = EPSILON; } @@ -627,7 +642,9 @@ namespace Spine output[o + 1] = y; if (tangents) { - output[o + 2] = (float)Math.Atan2(y - (y1 * uu + cy1 * ut * 2 + cy2 * tt), x - (x1 * uu + cx1 * ut * 2 + cx2 * tt)); + output[o + 2] = (float)atan2(y - (y1 * uu + cy1 * ut * 2 + cy2 * tt), x - (x1 * uu + cx1 * ut * 2 + cx2 * tt)); } } + + RTTI_IMPL(PathConstraint, Constraint); } diff --git a/spine-cpp/spine-cpp/src/spine/RegionAttachment.cpp b/spine-cpp/spine-cpp/src/spine/RegionAttachment.cpp new file mode 100644 index 000000000..b5b78a49e --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/RegionAttachment.cpp @@ -0,0 +1,36 @@ +/****************************************************************************** +* Spine Runtimes Software License v2.5 +* +* Copyright (c) 2013-2016, Esoteric Software +* All rights reserved. +* +* You are granted a perpetual, non-exclusive, non-sublicensable, and +* non-transferable license to use, install, execute, and perform the Spine +* Runtimes software and derivative works solely for personal or internal +* use. Without the written permission of Esoteric Software (see Section 2 of +* the Spine Software License Agreement), you may not (a) modify, translate, +* adapt, or develop new applications using the Spine Runtimes or otherwise +* create derivative works or improvements of the Spine Runtimes or (b) remove, +* delete, alter, or obscure any trademarks or any copyright, trademark, patent, +* or other intellectual property or proprietary rights notices on or in the +* Software, including any copy thereof. Redistributions in binary or source +* form must include this license and terms. +* +* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +#include + +namespace Spine +{ + RTTI_IMPL(RegionAttachment, Attachment); +} diff --git a/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp b/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp index 1d2cb4bde..b58b14988 100644 --- a/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp @@ -147,4 +147,6 @@ namespace Spine { _frames = inValue; } + + RTTI_IMPL(RotateTimeline, CurveTimeline); } diff --git a/spine-cpp/spine-cpp/src/spine/Skeleton.cpp b/spine-cpp/spine-cpp/src/spine/Skeleton.cpp index aeae9606c..2d6a85fdc 100644 --- a/spine-cpp/spine-cpp/src/spine/Skeleton.cpp +++ b/spine-cpp/spine-cpp/src/spine/Skeleton.cpp @@ -45,6 +45,9 @@ #include #include #include +#include +#include +#include #include @@ -135,81 +138,101 @@ namespace Spine void Skeleton::updateCache() { - Vector updateCache = _updateCache; - updateCache.Clear(); - _updateCacheReset.Clear(); + _updateCache.clear(); + _updateCacheReset.clear(); - Vector bones = _bones; - for (int i = 0, n = bones.Count; i < n; ++i) + for (int i = 0, n = static_cast(_bones.size()); i < n; ++i) { - bones.Items[i].sorted = false; + _bones[i]->_sorted = false; } - Vector ikConstraints = _ikConstraints; - var transformConstraints = _transformConstraints; - var pathConstraints = _pathConstraints; - int ikCount = IkConstraints.Count, transformCount = transformConstraints.Count, pathCount = pathConstraints.Count; + int ikCount = static_cast(_ikConstraints.size()); + int transformCount = static_cast(_transformConstraints.size()); + int pathCount = static_cast(_pathConstraints.size()); + int constraintCount = ikCount + transformCount + pathCount; - //outer: + for (int i = 0; i < constraintCount; ++i) { + bool gotoNextConstraintCount = false; + for (int ii = 0; ii < ikCount; ++ii) { - IkConstraint constraint = ikConstraints.Items[ii]; - if (constraint.data.order == i) + IkConstraint* constraint = _ikConstraints[ii]; + if (constraint->getData().getOrder() == i) { sortIkConstraint(constraint); - goto continue_outer; //continue outer; + + gotoNextConstraintCount = true; + break; } } + + if (gotoNextConstraintCount) + { + break; + } + for (int ii = 0; ii < transformCount; ++ii) { - TransformConstraint constraint = transformConstraints.Items[ii]; - if (constraint.data.order == i) + TransformConstraint* constraint = _transformConstraints[ii]; + if (constraint->getData().getOrder() == i) { sortTransformConstraint(constraint); - goto continue_outer; //continue outer; + + gotoNextConstraintCount = true; + break; } } + + if (gotoNextConstraintCount) + { + break; + } + for (int ii = 0; ii < pathCount; ++ii) { - PathConstraint constraint = pathConstraints.Items[ii]; - if (constraint.data.order == i) + PathConstraint* constraint = _pathConstraints[ii]; + if (constraint->getData().getOrder() == i) { sortPathConstraint(constraint); - goto continue_outer; //continue outer; + + gotoNextConstraintCount = true; + break; } } - continue_outer: {} + + if (gotoNextConstraintCount) + { + break; + } } - for (int i = 0, n = bones.Count; i < n; ++i) + for (int i = 0, n = static_cast(_bones.size()); i < n; ++i) { - sortBone(bones.Items[i]); + sortBone(_bones[i]); } } void Skeleton::updateWorldTransform() { - var updateCacheReset = _updateCacheReset; - var updateCacheResetItems = updateCacheReset.Items; - for (int i = 0, n = updateCacheReset.Count; i < n; ++i) + for (int i = 0, n = static_cast(_updateCacheReset.size()); i < n; ++i) { - Bone bone = updateCacheResetItems[i]; - bone.ax = bone.x; - bone.ay = bone.y; - bone.arotation = bone.rotation; - bone.ascaleX = bone.scaleX; - bone.ascaleY = bone.scaleY; - bone.ashearX = bone.shearX; - bone.ashearY = bone.shearY; - bone.appliedValid = true; + Bone* boneP = _updateCacheReset[i]; + Bone bone = *boneP; + bone._ax = bone._x; + bone._ay = bone._y; + bone._arotation = bone._rotation; + bone._ascaleX = bone._scaleX; + bone._ascaleY = bone._scaleY; + bone._ashearX = bone._shearX; + bone._ashearY = bone._shearY; + bone._appliedValid = true; } - var updateItems = _updateCache.Items; - for (int i = 0, n = updateCache.Count; i < n; ++i) + for (int i = 0, n = static_cast(_updateCache.size()); i < n; ++i) { - updateItems[i].update(); + _updateCache[i]->update(); } } @@ -221,213 +244,164 @@ namespace Spine void Skeleton::setBonesToSetupPose() { - var bonesItems = _bones.Items; - for (int i = 0, n = bones.Count; i < n; ++i) + for (int i = 0, n = static_cast(_bones.size()); i < n; ++i) { - bonesItems[i].setToSetupPose(); + _bones[i]->setToSetupPose(); } - var ikConstraintsItems = _ikConstraints.Items; - for (int i = 0, n = ikConstraints.Count; i < n; ++i) + for (int i = 0, n = static_cast(_ikConstraints.size()); i < n; ++i) { - IkConstraint constraint = ikConstraintsItems[i]; - constraint.bendDirection = constraint.data.bendDirection; - constraint.mix = constraint.data.mix; + IkConstraint* constraintP = _ikConstraints[i]; + IkConstraint constraint = *constraintP; + + constraint._bendDirection = constraint._data._bendDirection; + constraint._mix = constraint._data._mix; } - var transformConstraintsItems = _transformConstraints.Items; - for (int i = 0, n = transformConstraints.Count; i < n; ++i) + for (int i = 0, n = static_cast(_transformConstraints.size()); i < n; ++i) { - TransformConstraint constraint = transformConstraintsItems[i]; - TransformConstraintData constraintData = constraint.data; - constraint.rotateMix = constraintData.rotateMix; - constraint.translateMix = constraintData.translateMix; - constraint.scaleMix = constraintData.scaleMix; - constraint.shearMix = constraintData.shearMix; + TransformConstraint* constraintP = _transformConstraints[i]; + TransformConstraint constraint = *constraintP; + TransformConstraintData& constraintData = constraint._data; + + constraint._rotateMix = constraintData._rotateMix; + constraint._translateMix = constraintData._translateMix; + constraint._scaleMix = constraintData._scaleMix; + constraint._shearMix = constraintData._shearMix; } - var pathConstraintItems = _pathConstraints.Items; - for (int i = 0, n = pathConstraints.Count; i < n; ++i) + for (int i = 0, n = static_cast(_pathConstraints.size()); i < n; ++i) { - PathConstraint constraint = pathConstraintItems[i]; - PathConstraintData constraintData = constraint.data; - constraint.position = constraintData.position; - constraint.spacing = constraintData.spacing; - constraint.rotateMix = constraintData.rotateMix; - constraint.translateMix = constraintData.translateMix; + PathConstraint* constraintP = _pathConstraints[i]; + PathConstraint constraint = *constraintP; + PathConstraintData& constraintData = constraint._data; + + constraint._position = constraintData._position; + constraint._spacing = constraintData._spacing; + constraint._rotateMix = constraintData._rotateMix; + constraint._translateMix = constraintData._translateMix; } } void Skeleton::setSlotsToSetupPose() { - var slots = _slots; - var slotsItems = slots.Items; - drawOrder.Clear(); - for (int i = 0, n = slots.Count; i < n; ++i) + _drawOrder.clear(); + for (int i = 0, n = static_cast(_slots.size()); i < n; ++i) { - drawOrder.Add(slotsItems[i]); + _drawOrder.push_back(_slots[i]); } - for (int i = 0, n = slots.Count; i < n; ++i) + for (int i = 0, n = static_cast(_slots.size()); i < n; ++i) { - slotsItems[i].setToSetupPose(); + _slots[i]->setToSetupPose(); } } Bone* Skeleton::findBone(std::string boneName) { - assert(boneName.length() > 0); - - var bones = _bones; - var bonesItems = bones.Items; - for (int i = 0, n = bones.Count; i < n; ++i) - { - Bone bone = bonesItems[i]; - if (bone.data.name == boneName) - { - return bone; - } - } - - return NULL; + return ContainerUtil::findWithDataName(_bones, boneName); } int Skeleton::findBoneIndex(std::string boneName) { - assert(boneName.length() > 0); - - var bones = _bones; - var bonesItems = bones.Items; - for (int i = 0, n = bones.Count; i < n; ++i) - { - if (bonesItems[i].data.name == boneName) - { - return i; - } - } - - return -1; + return ContainerUtil::findIndexWithDataName(_bones, boneName); } Slot* Skeleton::findSlot(std::string slotName) { - assert(slotName.length() > 0); - - var slots = _slots; - var slotsItems = slots.Items; - for (int i = 0, n = slots.Count; i < n; ++i) - { - Slot slot = slotsItems[i]; - if (slot.data.name == slotName) - { - return slot; - } - } - - return NULL; + return ContainerUtil::findWithDataName(_slots, slotName); } int Skeleton::findSlotIndex(std::string slotName) { - assert(slotName.length() > 0); - - var slots = _slots; - var slotsItems = slots.Items; - for (int i = 0, n = slots.Count; i < n; ++i) - { - if (slotsItems[i].data.name.Equals(slotName)) - { - return i; - } - } - - return -1; + return ContainerUtil::findIndexWithDataName(_slots, slotName); } void Skeleton::setSkin(std::string skinName) { - Skin foundSkin = data.FindSkin(skinName); + Skin* foundSkin = _data.findSkin(skinName); assert(foundSkin != NULL); setSkin(foundSkin); } - void Skeleton::setSkin(Skin newSkin) + void Skeleton::setSkin(Skin* newSkin) { if (newSkin != NULL) { - if (skin != NULL) + if (_skin != NULL) { - newSkin.AttachAll(this, skin); + Skeleton& thisRef = *this; + newSkin->attachAll(thisRef, *_skin); } else { - Vector slots = _slots; - for (int i = 0, n = slots.Count; i < n; ++i) + for (int i = 0, n = static_cast(_slots.size()); i < n; ++i) { - Slot slot = slots.Items[i]; - std::string name = slot.data.attachmentName; - if (name != NULL) + Slot* slotP = _slots[i]; + Slot slot = *slotP; + std::string name = slot._data.getAttachmentName(); + if (name.length() > 0) { - Attachment attachment = newSkin.getAttachment(i, name); + Attachment* attachment = newSkin->getAttachment(i, name); if (attachment != NULL) { - slot.Attachment = attachment; + slot.setAttachment(attachment); } } } } } - skin = newSkin; + + _skin = newSkin; } Attachment* Skeleton::getAttachment(std::string slotName, std::string attachmentName) { - return getAttachment(data.findSlotIndex(slotName), attachmentName); + return getAttachment(_data.findSlotIndex(slotName), attachmentName); } Attachment* Skeleton::getAttachment(int slotIndex, std::string attachmentName) { assert(attachmentName.length() > 0); - if (skin != NULL) + if (_skin != NULL) { - Attachment attachment = skin.getAttachment(slotIndex, attachmentName); + Attachment* attachment = _skin->getAttachment(slotIndex, attachmentName); if (attachment != NULL) { return attachment; } } - return data.defaultSkin != NULL ? data.defaultSkin.getAttachment(slotIndex, attachmentName) : NULL; + return _data.getDefaultSkin() != NULL ? _data.getDefaultSkin()->getAttachment(slotIndex, attachmentName) : NULL; } void Skeleton::setAttachment(std::string slotName, std::string attachmentName) { assert(slotName.length() > 0); - Vector slots = _slots; - for (int i = 0, n = slots.Count; i < n; ++i) + for (int i = 0, n = static_cast(_slots.size()); i < n; ++i) { - Slot slot = slots.Items[i]; - if (slot.data.name == slotName) + Slot* slot = _slots[i]; + if (slot->_data.getName() == slotName) { - Attachment attachment = NULL; - if (attachmentName != NULL) + Attachment* attachment = NULL; + if (attachmentName.length() > 0) { attachment = getAttachment(i, attachmentName); assert(attachment != NULL); } - slot.Attachment = attachment; + slot->setAttachment(attachment); return; } } - printf("Slot not found: %s" + slotName.c_str()); + printf("Slot not found: %s", slotName.c_str()); assert(false); } @@ -436,11 +410,10 @@ namespace Spine { assert(constraintName.length() > 0); - Vector ikConstraints = _ikConstraints; - for (int i = 0, n = ikConstraints.Count; i < n; ++i) + for (int i = 0, n = static_cast(_ikConstraints.size()); i < n; ++i) { - IkConstraint ikConstraint = ikConstraints.Items[i]; - if (ikConstraint.data.name == constraintName) + IkConstraint* ikConstraint = _ikConstraints[i]; + if (ikConstraint->_data.getName() == constraintName) { return ikConstraint; } @@ -452,11 +425,10 @@ namespace Spine { assert(constraintName.length() > 0); - Vector transformConstraints = _transformConstraints; - for (int i = 0, n = transformConstraints.Count; i < n; ++i) + for (int i = 0, n = static_cast(_transformConstraints.size()); i < n; ++i) { - TransformConstraint transformConstraint = transformConstraints.Items[i]; - if (transformConstraint.data.name == constraintName) + TransformConstraint* transformConstraint = _transformConstraints[i]; + if (transformConstraint->_data.getName() == constraintName) { return transformConstraint; } @@ -469,11 +441,10 @@ namespace Spine { assert(constraintName.length() > 0); - Vector pathConstraints = _pathConstraints; - for (int i = 0, n = pathConstraints.Count; i < n; ++i) + for (int i = 0, n = static_cast(_pathConstraints.size()); i < n; ++i) { - PathConstraint constraint = pathConstraints.Items[i]; - if (constraint.data.name.Equals(constraintName)) + PathConstraint* constraint = _pathConstraints[i]; + if (constraint->_data.getName() == constraintName) { return constraint; } @@ -494,40 +465,40 @@ namespace Spine float maxX = std::numeric_limits::min(); float maxY = std::numeric_limits::min(); - for (Slot* i = _drawOrder.begin(); i != _drawOrder.end(); ++i) + for (Slot** i = _drawOrder.begin(); i != _drawOrder.end(); ++i) { - Slot* slot = i; + Slot* slot = (*i); int verticesLength = 0; Attachment* attachment = slot->getAttachment(); if (attachment != NULL && attachment->getRTTI().derivesFrom(RegionAttachment::rtti)) { RegionAttachment* regionAttachment = static_cast(attachment); - + verticesLength = 8; - if (vertexBuffer.size() < 8) + if (outVertexBuffer.size() < 8) { - vertexBuffer.reserve(8); + outVertexBuffer.reserve(8); } - regionAttachment->computeWorldVertices(slot->getBone(), vertexBuffer, 0); + regionAttachment->computeWorldVertices(slot->getBone(), outVertexBuffer, 0); } else if (attachment != NULL && attachment->getRTTI().derivesFrom(MeshAttachment::rtti)) { MeshAttachment* mesh = static_cast(attachment); - + verticesLength = mesh->getWorldVerticesLength(); - if (vertexBuffer.size() < verticesLength) + if (outVertexBuffer.size() < verticesLength) { - vertexBuffer.reserve(verticesLength); + outVertexBuffer.reserve(verticesLength); } - - mesh->computeWorldVertices(slot, 0, verticesLength, vertexBuffer, 0); + + mesh->computeWorldVertices(slot, 0, verticesLength, outVertexBuffer, 0); } for (int ii = 0; ii < verticesLength; ii += 2) { - float vx = vertexBuffer[ii]; - float vy = vertexBuffer[ii + 1]; + float vx = outVertexBuffer[ii]; + float vy = outVertexBuffer[ii + 1]; minX = MIN(minX, vx); minY = MIN(minY, vy); @@ -536,15 +507,15 @@ namespace Spine } } - x = minX; - y = minY; - width = maxX - minX; - height = maxY - minY; + outX = minX; + outY = minY; + outWidth = maxX - minX; + outHeight = maxY - minY; } Bone* Skeleton::getRootBone() { - return _bones.size() == 0 ? NULL : &_bones[0]; + return _bones.size() == 0 ? NULL : _bones[0]; } const SkeletonData& Skeleton::getData() @@ -592,11 +563,6 @@ namespace Spine return _skin; } - void Skeleton::setSkin(Skin* inValue) - { - _skin = inValue; - } - float Skeleton::getR() { return _r; @@ -689,90 +655,90 @@ namespace Spine void Skeleton::sortIkConstraint(IkConstraint* constraint) { - Bone target = constraint.target; + Bone* target = constraint->getTarget(); sortBone(target); - var constrained = constraint.bones; - Bone parent = constrained.Items[0]; + Vector& constrained = constraint->getBones(); + Bone* parent = constrained[0]; sortBone(parent); - if (constrained.Count > 1) + if (constrained.size() > 1) { - Bone child = constrained.Items[constrained.Count - 1]; - if (!updateCache.Contains(child)) + Bone* child = constrained[constrained.size() - 1]; + if (!_updateCache.contains(child)) { - updateCacheReset.Add(child); + _updateCacheReset.push_back(child); } } - updateCache.Add(constraint); + _updateCache.push_back(constraint); - sortReset(parent.children); - constrained.Items[constrained.Count - 1].sorted = true; + sortReset(parent->getChildren()); + constrained[constrained.size() - 1]->_sorted = true; } void Skeleton::sortPathConstraint(PathConstraint* constraint) { - Slot slot = constraint.target; - int slotIndex = slot.data.index; - Bone slotBone = slot.bone; + Slot* slot = constraint->getTarget(); + int slotIndex = slot->_data.getIndex(); + Bone& slotBone = slot->_bone; - if (skin != NULL) + if (_skin != NULL) { - sortPathConstraintAttachment(skin, slotIndex, slotBone); + sortPathConstraintAttachment(_skin, slotIndex, slotBone); } - if (data.defaultSkin != NULL && data.defaultSkin != skin) + if (_data._defaultSkin != NULL && _data._defaultSkin != _skin) { - sortPathConstraintAttachment(data.defaultSkin, slotIndex, slotBone); + sortPathConstraintAttachment(_data._defaultSkin, slotIndex, slotBone); } - for (int ii = 0, nn = data.skins.Count; ii < nn; ++ii) + for (int ii = 0, nn = static_cast(_data._skins.size()); ii < nn; ++ii) { - sortPathConstraintAttachment(data.skins.Items[ii], slotIndex, slotBone); + sortPathConstraintAttachment(_data._skins[ii], slotIndex, slotBone); } - Attachment attachment = slot.attachment; - if (attachment is PathAttachment) + Attachment* attachment = slot->_attachment; + if (attachment != NULL && attachment->getRTTI().derivesFrom(PathAttachment::rtti)) { sortPathConstraintAttachment(attachment, slotBone); } - var constrained = constraint.bones; - int boneCount = constrained.Count; + Vector& constrained = constraint->getBones(); + int boneCount = static_cast(constrained.size()); for (int i = 0; i < boneCount; ++i) { - sortBone(constrained.Items[i]); + sortBone(constrained[i]); } - updateCache.Add(constraint); + _updateCache.push_back(constraint); for (int i = 0; i < boneCount; ++i) { - sortReset(constrained.Items[i].children); + sortReset(constrained[i]->getChildren()); } for (int i = 0; i < boneCount; ++i) { - constrained.Items[i].sorted = true; + constrained[i]->_sorted = true; } } void Skeleton::sortTransformConstraint(TransformConstraint* constraint) { - sortBone(constraint.target); + sortBone(constraint->getTarget()); - var constrained = constraint.bones; - int boneCount = constrained.Count; - if (constraint.data.local) + Vector& constrained = constraint->getBones(); + int boneCount = static_cast(constrained.size()); + if (constraint->_data.isLocal()) { for (int i = 0; i < boneCount; ++i) { - Bone child = constrained.Items[i]; - sortBone(child.parent); - if (!updateCache.Contains(child)) + Bone* child = constrained[i]; + sortBone(child->getParent()); + if (!_updateCache.contains(child)) { - updateCacheReset.Add(child); + _updateCacheReset.push_back(child); } } } @@ -780,55 +746,61 @@ namespace Spine { for (int i = 0; i < boneCount; ++i) { - sortBone(constrained.Items[i]); + sortBone(constrained[i]); } } - updateCache.Add(constraint); + _updateCache.push_back(constraint); for (int i = 0; i < boneCount; ++i) { - sortReset(constrained.Items[i].children); + sortReset(constrained[i]->getChildren()); } + for (int i = 0; i < boneCount; ++i) { - constrained.Items[i].sorted = true; + constrained[i]->_sorted = true; } } - void Skeleton::sortPathConstraintAttachment(Skin* skin, int slotIndex, Bone* slotBone) + void Skeleton::sortPathConstraintAttachment(Skin* skin, int slotIndex, Bone& slotBone) { - foreach (var entry in skin.Attachments) + HashMap& attachments = skin->getAttachments(); + + for (typename HashMap::Iterator i = attachments.begin(); i != attachments.end(); ++i) { - if (entry.Key.slotIndex == slotIndex) + Skin::AttachmentKey key = i.first(); + if (key._slotIndex == slotIndex) { - sortPathConstraintAttachment(entry.Value, slotBone); + Attachment* value = i.second(); + sortPathConstraintAttachment(value, slotBone); } } } - void Skeleton::sortPathConstraintAttachment(Attachment* attachment, Bone* slotBone) + void Skeleton::sortPathConstraintAttachment(Attachment* attachment, Bone& slotBone) { - if (!(attachment is PathAttachment)) + if (attachment == NULL || attachment->getRTTI().derivesFrom(PathAttachment::rtti)) { return; } - int[] pathBones = ((PathAttachment)attachment).bones; - if (pathBones == NULL) + PathAttachment* pathAttachment = static_cast(attachment); + Vector& pathBonesRef = pathAttachment->getBones(); + Vector pathBones = pathBonesRef; + if (pathBones.size() == 0) { - sortBone(slotBone); + sortBone(&slotBone); } else { - var bones = _bones; - for (int i = 0, n = pathBones.Length; i < n;) + for (int i = 0, n = static_cast(pathBones.size()); i < n;) { int nn = pathBones[i++]; nn += i; while (i < nn) { - sortBone(bones.Items[pathBones[i++]]); + sortBone(_bones[pathBones[i++]]); } } } @@ -836,32 +808,35 @@ namespace Spine void Skeleton::sortBone(Bone* bone) { - if (bone.sorted) + assert(bone != NULL); + + if (bone->_sorted) { return; } - Bone parent = bone.parent; + Bone* parent = bone->_parent; if (parent != NULL) { sortBone(parent); } - bone.sorted = true; - updateCache.Add(bone); + bone->_sorted = true; + + _updateCache.push_back(bone); } void Skeleton::sortReset(Vector& bones) { - for (Bone* i = bones.begin(); i != bones.end(); ++i) + for (Bone** i = bones.begin(); i != bones.end(); ++i) { - Bone* bone = i; - if (bone->isSorted()) + Bone* bone = (*i); + if (bone->_sorted) { sortReset(bone->getChildren()); } - bone->setSorted(false); + bone->_sorted = false; } } } diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonData.cpp b/spine-cpp/spine-cpp/src/spine/SkeletonData.cpp index 201359534..3a3367743 100644 --- a/spine-cpp/spine-cpp/src/spine/SkeletonData.cpp +++ b/spine-cpp/spine-cpp/src/spine/SkeletonData.cpp @@ -46,10 +46,14 @@ namespace Spine { SkeletonData::SkeletonData() : + _name(), _defaultSkin(NULL), _width(0), _height(0), - _fps(0) + _version(), + _hash(), + _fps(0), + _imagesPath() { // Empty } diff --git a/spine-cpp/spine-cpp/src/spine/Skin.cpp b/spine-cpp/spine-cpp/src/spine/Skin.cpp index d2b8c7259..d3dec3573 100644 --- a/spine-cpp/spine-cpp/src/spine/Skin.cpp +++ b/spine-cpp/spine-cpp/src/spine/Skin.cpp @@ -60,7 +60,7 @@ namespace Spine { assert(attachment); - _attachments[AttachmentKey(slotIndex, name)] = attachment; + _attachments.insert(AttachmentKey(slotIndex, name), attachment); } Attachment* Skin::getAttachment(int slotIndex, std::string name) @@ -104,17 +104,19 @@ namespace Spine return _name; } - HashMap& Skin::getAttachments() + HashMap& Skin::getAttachments() { return _attachments; } void Skin::attachAll(Skeleton& skeleton, Skin& oldSkin) { + Vector& slots = skeleton.getSlots(); + for (HashMap::Iterator i = oldSkin.getAttachments().begin(); i != oldSkin.getAttachments().end(); ++i) { int slotIndex = i.first()._slotIndex; - Slot* slot = skeleton.getSlots()[slotIndex]; + Slot* slot = slots[slotIndex]; if (slot->getAttachment() == i.second()) { diff --git a/spine-cpp/spine-cpp/src/spine/Slot.cpp b/spine-cpp/spine-cpp/src/spine/Slot.cpp index fa9e1f5d8..d245533ad 100644 --- a/spine-cpp/spine-cpp/src/spine/Slot.cpp +++ b/spine-cpp/spine-cpp/src/spine/Slot.cpp @@ -38,9 +38,9 @@ namespace Spine { Slot::Slot(SlotData& data, Bone& bone) : - _slotData(data), + _data(data), _bone(bone), - _skeleton(bone.getSkeletion()), + _skeleton(bone.getSkeleton()), _r(1), _g(1), _b(1), @@ -57,16 +57,16 @@ namespace Spine void Slot::setToSetupPose() { - _r = _slotData.getR(); - _g = _slotData.getG(); - _b = _slotData.getB(); - _a = _slotData.getA(); + _r = _data.getR(); + _g = _data.getG(); + _b = _data.getB(); + _a = _data.getA(); - std::string attachmentName = _slotData.getAttachmentName(); + std::string attachmentName = _data.getAttachmentName(); if (attachmentName.length() > 0) { _attachment = NULL; - setAttachment(_skeleton.getAttachment(_slotData.getIndex(), attachmentName)); + setAttachment(_skeleton.getAttachment(_data.getIndex(), attachmentName)); } else { @@ -74,9 +74,9 @@ namespace Spine } } - SlotData& Slot::getSlotData() + SlotData& Slot::getData() { - return _slotData; + return _data; } Bone& Slot::getBone() diff --git a/spine-cpp/spine-cpp/src/spine/SlotData.cpp b/spine-cpp/spine-cpp/src/spine/SlotData.cpp index 01eb96540..327327cbb 100644 --- a/spine-cpp/spine-cpp/src/spine/SlotData.cpp +++ b/spine-cpp/spine-cpp/src/spine/SlotData.cpp @@ -34,7 +34,7 @@ namespace Spine { - SlotData::SlotData(int index, std::string name, const BoneData& boneData) : + SlotData::SlotData(int index, std::string name, BoneData& boneData) : _index(index), _name(name), _boneData(boneData), @@ -63,7 +63,7 @@ namespace Spine return _name; } - const BoneData& SlotData::getBoneData() + BoneData& SlotData::getBoneData() { return _boneData; } diff --git a/spine-cpp/spine-cpp/src/spine/Timeline.cpp b/spine-cpp/spine-cpp/src/spine/Timeline.cpp index 39f4cc164..64044ca08 100644 --- a/spine-cpp/spine-cpp/src/spine/Timeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/Timeline.cpp @@ -44,4 +44,6 @@ namespace Spine { // Empty } + + RTTI_IMPL_NOPARENT(Timeline); } diff --git a/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp b/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp index 06669c000..6a956c071 100644 --- a/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp +++ b/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp @@ -427,22 +427,24 @@ namespace Spine { if (scaleX > 0.00001f) { - scaleX *= ((target._ascaleX - 1 + data.offsetScaleX) * scaleMix) + 1; + scaleX *= ((target._ascaleX - 1 + _data._offsetScaleX) * scaleMix) + 1; } if (scaleY > 0.00001f) { - scaleY *= ((target._ascaleY - 1 + data.offsetScaleY) * scaleMix) + 1; + scaleY *= ((target._ascaleY - 1 + _data._offsetScaleY) * scaleMix) + 1; } } float shearY = bone._ashearY; if (shearMix > 0) { - shearY += (target._ashearY + data.offsetShearY) * shearMix; + shearY += (target._ashearY + _data._offsetShearY) * shearMix; } bone.updateWorldTransform(x, y, rotation, scaleX, scaleY, bone._ashearX, shearY); } } + + RTTI_IMPL(TransformConstraint, Constraint); } diff --git a/spine-cpp/spine-cpp/src/spine/Updatable.cpp b/spine-cpp/spine-cpp/src/spine/Updatable.cpp index d5a7f2ec3..810c959a8 100644 --- a/spine-cpp/spine-cpp/src/spine/Updatable.cpp +++ b/spine-cpp/spine-cpp/src/spine/Updatable.cpp @@ -41,4 +41,6 @@ namespace Spine { // Empty } + + RTTI_IMPL_NOPARENT(Updatable); } diff --git a/spine-cpp/spine-cpp/src/spine/VertexAttachment.cpp b/spine-cpp/spine-cpp/src/spine/VertexAttachment.cpp index 7581d360b..a101b5fa4 100644 --- a/spine-cpp/spine-cpp/src/spine/VertexAttachment.cpp +++ b/spine-cpp/spine-cpp/src/spine/VertexAttachment.cpp @@ -138,7 +138,7 @@ namespace Spine return _id; } - Vector VertexAttachment::getBones() + Vector& VertexAttachment::getBones() { return _bones; } @@ -148,7 +148,7 @@ namespace Spine _bones = inValue; } - Vector VertexAttachment::getVertices() + Vector& VertexAttachment::getVertices() { return _vertices; } @@ -174,4 +174,6 @@ namespace Spine return (nextID++ & 65535) << 11; } + + RTTI_IMPL(VertexAttachment, Attachment); } From 51f3306a7216e739229163bab31ccf5203cf396e Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Thu, 2 Nov 2017 13:41:56 -0400 Subject: [PATCH 20/83] Temporarily commenting out some sections so I can build --- .../spine-cpp/include/spine/MeshAttachment.h | 196 ++++++------ .../include/spine/RegionAttachment.h | 280 +++++++++--------- spine-cpp/spine-cpp/src/spine/Skeleton.cpp | 4 +- 3 files changed, 240 insertions(+), 240 deletions(-) diff --git a/spine-cpp/spine-cpp/include/spine/MeshAttachment.h b/spine-cpp/spine-cpp/include/spine/MeshAttachment.h index 52f916689..27fdccdd3 100644 --- a/spine-cpp/spine-cpp/include/spine/MeshAttachment.h +++ b/spine-cpp/spine-cpp/include/spine/MeshAttachment.h @@ -40,104 +40,104 @@ namespace Spine { RTTI_DECL; - public: - public int HullLength { get { return _hulllength; } set { _hulllength = value; } } - public float[] RegionUVs { get { return _regionUVs; } set { _regionUVs = value; } } - /// The UV pair for each vertex, normalized within the entire texture. - public float[] UVs { get { return _uvs; } set { _uvs = value; } } - public int[] Triangles { get { return _triangles; } set { _triangles = value; } } - - public float R { get { return r; } set { r = value; } } - public float G { get { return g; } set { g = value; } } - public float B { get { return b; } set { b = value; } } - public float A { get { return a; } set { a = value; } } - - public string Path { get; set; } - public object RendererObject; //public Object RendererObject { get; set; } - public float RegionU { get; set; } - public float RegionV { get; set; } - public float RegionU2 { get; set; } - public float RegionV2 { get; set; } - public bool RegionRotate { get; set; } - public float RegionOffsetX { get { return _regionOffsetX; } set { _regionOffsetX = value; } } - public float RegionOffsetY { get { return _regionOffsetY; } set { _regionOffsetY = value; } } // Pixels stripped from the bottom left, unrotated. - public float RegionWidth { get { return _regionWidth; } set { _regionWidth = value; } } - public float RegionHeight { get { return _regionHeight; } set { _regionHeight = value; } } // Unrotated, stripped size. - public float RegionOriginalWidth { get { return _regionOriginalWidth; } set { _regionOriginalWidth = value; } } - public float RegionOriginalHeight { get { return _regionOriginalHeight; } set { _regionOriginalHeight = value; } } // Unrotated, unstripped size. - - public bool InheritDeform { get { return _inheritDeform; } set { _inheritDeform = value; } } - - public MeshAttachment ParentMesh { - get { return _parentMesh; } - set { - _parentMesh = value; - if (value != null) { - bones = value.bones; - vertices = value.vertices; - worldVerticesLength = value.worldVerticesLength; - _regionUVs = value._regionUVs; - _triangles = value._triangles; - HullLength = value.HullLength; - Edges = value.Edges; - Width = value.Width; - Height = value.Height; - } - } - } - - // Nonessential. - public int[] Edges { get; set; } - public float Width { get; set; } - public float Height { get; set; } - - public MeshAttachment (string name) : VertexAttachment(name) - { - // Empty - } - - public void updateUVs() - { - float u = RegionU, v = RegionV, width = RegionU2 - RegionU, height = RegionV2 - RegionV; - if (_uvs == null || _uvs.Length != _regionUVs.Length) - { - _uvs = new float[_regionUVs.Length]; - } - - float[] _uvs = _uvs; - if (_regionRotate) - { - for (int i = 0, n = _uvs.Length; i < n; i += 2) - { - _uvs[i] = u + _regionUVs[i + 1] * width; - _uvs[i + 1] = v + height - _regionUVs[i] * height; - } - } - else - { - for (int i = 0, n = _uvs.Length; i < n; i += 2) - { - _uvs[i] = u + _regionUVs[i] * width; - _uvs[i + 1] = v + _regionUVs[i + 1] * height; - } - } - } - - virtual bool applyDeform(VertexAttachment* sourceAttachment) - { - return this == sourceAttachment || (_inheritDeform && _parentMesh == sourceAttachment); - } - - private: - float _regionOffsetX, _regionOffsetY, _regionWidth, _regionHeight, _regionOriginalWidth, _regionOriginalHeight; - MeshAttachment* _parentMesh; - float[] _uvs, _regionUVs; - int[] _triangles; - float r = 1, g = 1, b = 1, a = 1; - int _hulllength; - bool _inheritDeform; - bool _regionRotate; - } +// public: +// public int HullLength { get { return _hulllength; } set { _hulllength = value; } } +// public float[] RegionUVs { get { return _regionUVs; } set { _regionUVs = value; } } +// /// The UV pair for each vertex, normalized within the entire texture. +// public float[] UVs { get { return _uvs; } set { _uvs = value; } } +// public int[] Triangles { get { return _triangles; } set { _triangles = value; } } +// +// public float R { get { return r; } set { r = value; } } +// public float G { get { return g; } set { g = value; } } +// public float B { get { return b; } set { b = value; } } +// public float A { get { return a; } set { a = value; } } +// +// public string Path { get; set; } +// public object RendererObject; //public Object RendererObject { get; set; } +// public float RegionU { get; set; } +// public float RegionV { get; set; } +// public float RegionU2 { get; set; } +// public float RegionV2 { get; set; } +// public bool RegionRotate { get; set; } +// public float RegionOffsetX { get { return _regionOffsetX; } set { _regionOffsetX = value; } } +// public float RegionOffsetY { get { return _regionOffsetY; } set { _regionOffsetY = value; } } // Pixels stripped from the bottom left, unrotated. +// public float RegionWidth { get { return _regionWidth; } set { _regionWidth = value; } } +// public float RegionHeight { get { return _regionHeight; } set { _regionHeight = value; } } // Unrotated, stripped size. +// public float RegionOriginalWidth { get { return _regionOriginalWidth; } set { _regionOriginalWidth = value; } } +// public float RegionOriginalHeight { get { return _regionOriginalHeight; } set { _regionOriginalHeight = value; } } // Unrotated, unstripped size. +// +// public bool InheritDeform { get { return _inheritDeform; } set { _inheritDeform = value; } } +// +// public MeshAttachment ParentMesh { +// get { return _parentMesh; } +// set { +// _parentMesh = value; +// if (value != null) { +// bones = value.bones; +// vertices = value.vertices; +// worldVerticesLength = value.worldVerticesLength; +// _regionUVs = value._regionUVs; +// _triangles = value._triangles; +// HullLength = value.HullLength; +// Edges = value.Edges; +// Width = value.Width; +// Height = value.Height; +// } +// } +// } +// +// // Nonessential. +// public int[] Edges { get; set; } +// public float Width { get; set; } +// public float Height { get; set; } +// +// public MeshAttachment (string name) : VertexAttachment(name) +// { +// // Empty +// } +// +// public void updateUVs() +// { +// float u = RegionU, v = RegionV, width = RegionU2 - RegionU, height = RegionV2 - RegionV; +// if (_uvs == null || _uvs.Length != _regionUVs.Length) +// { +// _uvs = new float[_regionUVs.Length]; +// } +// +// float[] _uvs = _uvs; +// if (_regionRotate) +// { +// for (int i = 0, n = _uvs.Length; i < n; i += 2) +// { +// _uvs[i] = u + _regionUVs[i + 1] * width; +// _uvs[i + 1] = v + height - _regionUVs[i] * height; +// } +// } +// else +// { +// for (int i = 0, n = _uvs.Length; i < n; i += 2) +// { +// _uvs[i] = u + _regionUVs[i] * width; +// _uvs[i + 1] = v + _regionUVs[i + 1] * height; +// } +// } +// } +// +// virtual bool applyDeform(VertexAttachment* sourceAttachment) +// { +// return this == sourceAttachment || (_inheritDeform && _parentMesh == sourceAttachment); +// } +// +// private: +// float _regionOffsetX, _regionOffsetY, _regionWidth, _regionHeight, _regionOriginalWidth, _regionOriginalHeight; +// MeshAttachment* _parentMesh; +// float[] _uvs, _regionUVs; +// int[] _triangles; +// float r = 1, g = 1, b = 1, a = 1; +// int _hulllength; +// bool _inheritDeform; +// bool _regionRotate; + }; } #endif /* Spine_MeshAttachment_h */ diff --git a/spine-cpp/spine-cpp/include/spine/RegionAttachment.h b/spine-cpp/spine-cpp/include/spine/RegionAttachment.h index 6e513d3da..5a994730d 100644 --- a/spine-cpp/spine-cpp/include/spine/RegionAttachment.h +++ b/spine-cpp/spine-cpp/include/spine/RegionAttachment.h @@ -47,146 +47,146 @@ namespace Spine { RTTI_DECL; - public: - const int BLX = 0; - const int BLY = 1; - const int ULX = 2; - const int ULY = 3; - const int URX = 4; - const int URY = 5; - const int BRX = 6; - const int BRY = 7; - - float X { get { return x; } set { x = value; } } - float Y { get { return y; } set { y = value; } } - float Rotation { get { return _rotation; } set { _rotation = value; } } - float ScaleX { get { return scaleX; } set { scaleX = value; } } - float ScaleY { get { return scaleY; } set { scaleY = value; } } - float Width { get { return width; } set { width = value; } } - float Height { get { return height; } set { height = value; } } - - float R { get { return r; } set { r = value; } } - float G { get { return g; } set { g = value; } } - float B { get { return b; } set { b = value; } } - float A { get { return a; } set { a = value; } } - - std::string Path { get; set; } - object RendererObject; //object RendererObject { get; set; } - float RegionOffsetX { get { return _regionOffsetX; } set { _regionOffsetX = value; } } - float RegionOffsetY { get { return _regionOffsetY; } set { _regionOffsetY = value; } } // Pixels stripped from the bottom left, unrotated. - float RegionWidth { get { return _regionWidth; } set { _regionWidth = value; } } - float RegionHeight { get { return _regionHeight; } set { _regionHeight = value; } } // Unrotated, stripped size. - float RegionOriginalWidth { get { return _regionOriginalWidth; } set { _regionOriginalWidth = value; } } - float RegionOriginalHeight { get { return _regionOriginalHeight; } set { _regionOriginalHeight = value; } } // Unrotated, unstripped size. - - float[] Offset { get { return _offset; } } - float[] UVs { get { return _uvs; } } - - RegionAttachment (std::string name) : Attachment(name) - { - // Empty - } - - void updateOffset() - { - float regionScaleX = _width / _regionOriginalWidth * _scaleX; - float regionScaleY = _height / _regionOriginalHeight * _scaleY; - float localX = -_width / 2 * _scaleX + _regionOffsetX * regionScaleX; - float localY = -_height / 2 * _scaleY + _regionOffsetY * regionScaleY; - float localX2 = localX + _regionWidth * regionScaleX; - float localY2 = localY + _regionHeight * regionScaleY; - float cos = MathUtil::cosDeg(_rotation); - float sin = MathUtil::sinDeg(_rotation); - float localXCos = localX * cos + _x; - float localXSin = localX * sin; - float localYCos = localY * cos + _y; - float localYSin = localY * sin; - float localX2Cos = localX2 * cos + _x; - float localX2Sin = localX2 * sin; - float localY2Cos = localY2 * cos + _y; - float localY2Sin = localY2 * sin; - - _offset[BLX] = localXCos - localYSin; - _offset[BLY] = localYCos + localXSin; - _offset[ULX] = localXCos - localY2Sin; - _offset[ULY] = localY2Cos + localXSin; - _offset[URX] = localX2Cos - localY2Sin; - _offset[URY] = localY2Cos + localX2Sin; - _offset[BRX] = localX2Cos - localYSin; - _offset[BRY] = localYCos + localX2Sin; - } - - void setUVs(float u, float v, float u2, float v2, bool rotate) - { - if (rotate) - { - _uvs[URX] = u; - _uvs[URY] = v2; - _uvs[BRX] = u; - _uvs[BRY] = v; - _uvs[BLX] = u2; - _uvs[BLY] = v; - _uvs[ULX] = u2; - _uvs[ULY] = v2; - } - else - { - _uvs[ULX] = u; - _uvs[ULY] = v2; - _uvs[URX] = u; - _uvs[URY] = v; - _uvs[BRX] = u2; - _uvs[BRY] = v; - _uvs[BLX] = u2; - _uvs[BLY] = v2; - } - } - - /// Transforms the attachment's four vertices to world coordinates. - /// @param bone The parent bone. - /// @param worldVertices The output world vertices. Must have a length greater than or equal to offset + 8. - /// @param offset The worldVertices index to begin writing values. - /// @param stride The number of worldVertices entries between the value pairs written. - void computeWorldVertices(Bone& bone, Vector worldVertices, int offset, int stride = 2) - { - assert(worldVertices.size() >= 8); - - float[] vertexOffset = _offset; - float bwx = bone.worldX, bwy = bone.worldY; - float a = bone.a, b = bone.b, c = bone.c, d = bone.d; - float offsetX, offsetY; - - offsetX = vertexOffset[BRX]; // 0 - offsetY = vertexOffset[BRY]; // 1 - worldVertices[offset] = offsetX * a + offsetY * b + bwx; // bl - worldVertices[offset + 1] = offsetX * c + offsetY * d + bwy; - offset += stride; - - offsetX = vertexOffset[BLX]; // 2 - offsetY = vertexOffset[BLY]; // 3 - worldVertices[offset] = offsetX * a + offsetY * b + bwx; // ul - worldVertices[offset + 1] = offsetX * c + offsetY * d + bwy; - offset += stride; - - offsetX = vertexOffset[ULX]; // 4 - offsetY = vertexOffset[ULY]; // 5 - worldVertices[offset] = offsetX * a + offsetY * b + bwx; // ur - worldVertices[offset + 1] = offsetX * c + offsetY * d + bwy; - offset += stride; - - offsetX = vertexOffset[URX]; // 6 - offsetY = vertexOffset[URY]; // 7 - worldVertices[offset] = offsetX * a + offsetY * b + bwx; // br - worldVertices[offset + 1] = offsetX * c + offsetY * d + bwy; - } - - private: - float _x, _y, _rotation, _scaleX = 1, _scaleY = 1, _width, _height; - float _regionOffsetX, _regionOffsetY, _regionWidth, _regionHeight, _regionOriginalWidth, _regionOriginalHeight; - float[] _offset = new float[8]; - float[] _uvs = new float[8]; - float r = 1, g = 1, b = 1, a = 1; - } +// public: +// const int BLX = 0; +// const int BLY = 1; +// const int ULX = 2; +// const int ULY = 3; +// const int URX = 4; +// const int URY = 5; +// const int BRX = 6; +// const int BRY = 7; +// +// float X { get { return x; } set { x = value; } } +// float Y { get { return y; } set { y = value; } } +// float Rotation { get { return _rotation; } set { _rotation = value; } } +// float ScaleX { get { return scaleX; } set { scaleX = value; } } +// float ScaleY { get { return scaleY; } set { scaleY = value; } } +// float Width { get { return width; } set { width = value; } } +// float Height { get { return height; } set { height = value; } } +// +// float R { get { return r; } set { r = value; } } +// float G { get { return g; } set { g = value; } } +// float B { get { return b; } set { b = value; } } +// float A { get { return a; } set { a = value; } } +// +// std::string Path { get; set; } +// object RendererObject; //object RendererObject { get; set; } +// float RegionOffsetX { get { return _regionOffsetX; } set { _regionOffsetX = value; } } +// float RegionOffsetY { get { return _regionOffsetY; } set { _regionOffsetY = value; } } // Pixels stripped from the bottom left, unrotated. +// float RegionWidth { get { return _regionWidth; } set { _regionWidth = value; } } +// float RegionHeight { get { return _regionHeight; } set { _regionHeight = value; } } // Unrotated, stripped size. +// float RegionOriginalWidth { get { return _regionOriginalWidth; } set { _regionOriginalWidth = value; } } +// float RegionOriginalHeight { get { return _regionOriginalHeight; } set { _regionOriginalHeight = value; } } // Unrotated, unstripped size. +// +// float[] Offset { get { return _offset; } } +// float[] UVs { get { return _uvs; } } +// +// RegionAttachment (std::string name) : Attachment(name) +// { +// // Empty +// } +// +// void updateOffset() +// { +// float regionScaleX = _width / _regionOriginalWidth * _scaleX; +// float regionScaleY = _height / _regionOriginalHeight * _scaleY; +// float localX = -_width / 2 * _scaleX + _regionOffsetX * regionScaleX; +// float localY = -_height / 2 * _scaleY + _regionOffsetY * regionScaleY; +// float localX2 = localX + _regionWidth * regionScaleX; +// float localY2 = localY + _regionHeight * regionScaleY; +// float cos = MathUtil::cosDeg(_rotation); +// float sin = MathUtil::sinDeg(_rotation); +// float localXCos = localX * cos + _x; +// float localXSin = localX * sin; +// float localYCos = localY * cos + _y; +// float localYSin = localY * sin; +// float localX2Cos = localX2 * cos + _x; +// float localX2Sin = localX2 * sin; +// float localY2Cos = localY2 * cos + _y; +// float localY2Sin = localY2 * sin; +// +// _offset[BLX] = localXCos - localYSin; +// _offset[BLY] = localYCos + localXSin; +// _offset[ULX] = localXCos - localY2Sin; +// _offset[ULY] = localY2Cos + localXSin; +// _offset[URX] = localX2Cos - localY2Sin; +// _offset[URY] = localY2Cos + localX2Sin; +// _offset[BRX] = localX2Cos - localYSin; +// _offset[BRY] = localYCos + localX2Sin; +// } +// +// void setUVs(float u, float v, float u2, float v2, bool rotate) +// { +// if (rotate) +// { +// _uvs[URX] = u; +// _uvs[URY] = v2; +// _uvs[BRX] = u; +// _uvs[BRY] = v; +// _uvs[BLX] = u2; +// _uvs[BLY] = v; +// _uvs[ULX] = u2; +// _uvs[ULY] = v2; +// } +// else +// { +// _uvs[ULX] = u; +// _uvs[ULY] = v2; +// _uvs[URX] = u; +// _uvs[URY] = v; +// _uvs[BRX] = u2; +// _uvs[BRY] = v; +// _uvs[BLX] = u2; +// _uvs[BLY] = v2; +// } +// } +// +// /// Transforms the attachment's four vertices to world coordinates. +// /// @param bone The parent bone. +// /// @param worldVertices The output world vertices. Must have a length greater than or equal to offset + 8. +// /// @param offset The worldVertices index to begin writing values. +// /// @param stride The number of worldVertices entries between the value pairs written. +// void computeWorldVertices(Bone& bone, Vector worldVertices, int offset, int stride = 2) +// { +// assert(worldVertices.size() >= 8); +// +// float[] vertexOffset = _offset; +// float bwx = bone.worldX, bwy = bone.worldY; +// float a = bone.a, b = bone.b, c = bone.c, d = bone.d; +// float offsetX, offsetY; +// +// offsetX = vertexOffset[BRX]; // 0 +// offsetY = vertexOffset[BRY]; // 1 +// worldVertices[offset] = offsetX * a + offsetY * b + bwx; // bl +// worldVertices[offset + 1] = offsetX * c + offsetY * d + bwy; +// offset += stride; +// +// offsetX = vertexOffset[BLX]; // 2 +// offsetY = vertexOffset[BLY]; // 3 +// worldVertices[offset] = offsetX * a + offsetY * b + bwx; // ul +// worldVertices[offset + 1] = offsetX * c + offsetY * d + bwy; +// offset += stride; +// +// offsetX = vertexOffset[ULX]; // 4 +// offsetY = vertexOffset[ULY]; // 5 +// worldVertices[offset] = offsetX * a + offsetY * b + bwx; // ur +// worldVertices[offset + 1] = offsetX * c + offsetY * d + bwy; +// offset += stride; +// +// offsetX = vertexOffset[URX]; // 6 +// offsetY = vertexOffset[URY]; // 7 +// worldVertices[offset] = offsetX * a + offsetY * b + bwx; // br +// worldVertices[offset + 1] = offsetX * c + offsetY * d + bwy; +// } +// +// private: +// float _x, _y, _rotation, _scaleX = 1, _scaleY = 1, _width, _height; +// float _regionOffsetX, _regionOffsetY, _regionWidth, _regionHeight, _regionOriginalWidth, _regionOriginalHeight; +// float[] _offset = new float[8]; +// float[] _uvs = new float[8]; +// float r = 1, g = 1, b = 1, a = 1; + }; } #endif /* Spine_RegionAttachment_h */ diff --git a/spine-cpp/spine-cpp/src/spine/Skeleton.cpp b/spine-cpp/spine-cpp/src/spine/Skeleton.cpp index 2d6a85fdc..f6e898b3b 100644 --- a/spine-cpp/spine-cpp/src/spine/Skeleton.cpp +++ b/spine-cpp/spine-cpp/src/spine/Skeleton.cpp @@ -480,7 +480,7 @@ namespace Spine { outVertexBuffer.reserve(8); } - regionAttachment->computeWorldVertices(slot->getBone(), outVertexBuffer, 0); +// regionAttachment->computeWorldVertices(slot->getBone(), outVertexBuffer, 0); } else if (attachment != NULL && attachment->getRTTI().derivesFrom(MeshAttachment::rtti)) { @@ -492,7 +492,7 @@ namespace Spine outVertexBuffer.reserve(verticesLength); } - mesh->computeWorldVertices(slot, 0, verticesLength, outVertexBuffer, 0); +// mesh->computeWorldVertices(slot, 0, verticesLength, outVertexBuffer, 0); } for (int ii = 0; ii < verticesLength; ii += 2) From 04e0556c4eeb4739e3dca9ec8e915daf5c016367 Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Mon, 6 Nov 2017 11:47:08 -0500 Subject: [PATCH 21/83] Removing section of HashMap that didn't seem to work at all... --- spine-cpp/spine-cpp/include/spine/HashMap.h | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/spine-cpp/spine-cpp/include/spine/HashMap.h b/spine-cpp/spine-cpp/include/spine/HashMap.h index d7828c2fc..50fbbdf5b 100755 --- a/spine-cpp/spine-cpp/include/spine/HashMap.h +++ b/spine-cpp/spine-cpp/include/spine/HashMap.h @@ -176,20 +176,6 @@ namespace Spine _header.next->prev = entry; _header.next = entry; } - else if (index > hash(_header.next->_key) && index < hash(_trailer.prev->_key)) - { - size_t prev_index = index; - - while (_hashTable[--prev_index].next != NULL) - { - // Empty - } - - entry->next = _hashTable[prev_index].prev->next; - entry->prev = _hashTable[prev_index].prev; - _hashTable[prev_index].prev->next = entry; - entry->next->prev = entry; - } else { entry->next = &_trailer; From 7c2b6b827131590f54eb50f42b22156390cd9613 Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Mon, 6 Nov 2017 16:54:39 -0500 Subject: [PATCH 22/83] wip --- .../spine-cpp/include/spine/MeshAttachment.h | 84 +++++++++---------- 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/spine-cpp/spine-cpp/include/spine/MeshAttachment.h b/spine-cpp/spine-cpp/include/spine/MeshAttachment.h index 27fdccdd3..e6e1b7b48 100644 --- a/spine-cpp/spine-cpp/include/spine/MeshAttachment.h +++ b/spine-cpp/spine-cpp/include/spine/MeshAttachment.h @@ -40,35 +40,35 @@ namespace Spine { RTTI_DECL; -// public: -// public int HullLength { get { return _hulllength; } set { _hulllength = value; } } -// public float[] RegionUVs { get { return _regionUVs; } set { _regionUVs = value; } } + public: +// int HullLength { get { return _hulllength; } set { _hulllength = value; } } +// float[] RegionUVs { get { return _regionUVs; } set { _regionUVs = value; } } // /// The UV pair for each vertex, normalized within the entire texture. -// public float[] UVs { get { return _uvs; } set { _uvs = value; } } -// public int[] Triangles { get { return _triangles; } set { _triangles = value; } } +// float[] UVs { get { return _uvs; } set { _uvs = value; } } +// int[] Triangles { get { return _triangles; } set { _triangles = value; } } // -// public float R { get { return r; } set { r = value; } } -// public float G { get { return g; } set { g = value; } } -// public float B { get { return b; } set { b = value; } } -// public float A { get { return a; } set { a = value; } } +// float R { get { return r; } set { r = value; } } +// float G { get { return g; } set { g = value; } } +// float B { get { return b; } set { b = value; } } +// float A { get { return a; } set { a = value; } } // -// public string Path { get; set; } -// public object RendererObject; //public Object RendererObject { get; set; } -// public float RegionU { get; set; } -// public float RegionV { get; set; } -// public float RegionU2 { get; set; } -// public float RegionV2 { get; set; } -// public bool RegionRotate { get; set; } -// public float RegionOffsetX { get { return _regionOffsetX; } set { _regionOffsetX = value; } } -// public float RegionOffsetY { get { return _regionOffsetY; } set { _regionOffsetY = value; } } // Pixels stripped from the bottom left, unrotated. -// public float RegionWidth { get { return _regionWidth; } set { _regionWidth = value; } } -// public float RegionHeight { get { return _regionHeight; } set { _regionHeight = value; } } // Unrotated, stripped size. -// public float RegionOriginalWidth { get { return _regionOriginalWidth; } set { _regionOriginalWidth = value; } } -// public float RegionOriginalHeight { get { return _regionOriginalHeight; } set { _regionOriginalHeight = value; } } // Unrotated, unstripped size. +// string Path { get; set; } +// object RendererObject; //Object RendererObject { get; set; } +// float RegionU { get; set; } +// float RegionV { get; set; } +// float RegionU2 { get; set; } +// float RegionV2 { get; set; } +// bool RegionRotate { get; set; } +// float RegionOffsetX { get { return _regionOffsetX; } set { _regionOffsetX = value; } } +// float RegionOffsetY { get { return _regionOffsetY; } set { _regionOffsetY = value; } } // Pixels stripped from the bottom left, unrotated. +// float RegionWidth { get { return _regionWidth; } set { _regionWidth = value; } } +// float RegionHeight { get { return _regionHeight; } set { _regionHeight = value; } } // Unrotated, stripped size. +// float RegionOriginalWidth { get { return _regionOriginalWidth; } set { _regionOriginalWidth = value; } } +// float RegionOriginalHeight { get { return _regionOriginalHeight; } set { _regionOriginalHeight = value; } } // Unrotated, unstripped size. // -// public bool InheritDeform { get { return _inheritDeform; } set { _inheritDeform = value; } } +// bool InheritDeform { get { return _inheritDeform; } set { _inheritDeform = value; } } // -// public MeshAttachment ParentMesh { +// MeshAttachment ParentMesh { // get { return _parentMesh; } // set { // _parentMesh = value; @@ -87,16 +87,16 @@ namespace Spine // } // // // Nonessential. -// public int[] Edges { get; set; } -// public float Width { get; set; } -// public float Height { get; set; } +// int[] Edges { get; set; } +// float Width { get; set; } +// float Height { get; set; } // -// public MeshAttachment (string name) : VertexAttachment(name) +// MeshAttachment (string name) : VertexAttachment(name) // { // // Empty // } // -// public void updateUVs() +// void updateUVs() // { // float u = RegionU, v = RegionV, width = RegionU2 - RegionU, height = RegionV2 - RegionV; // if (_uvs == null || _uvs.Length != _regionUVs.Length) @@ -122,21 +122,21 @@ namespace Spine // } // } // } -// -// virtual bool applyDeform(VertexAttachment* sourceAttachment) -// { -// return this == sourceAttachment || (_inheritDeform && _parentMesh == sourceAttachment); -// } -// -// private: -// float _regionOffsetX, _regionOffsetY, _regionWidth, _regionHeight, _regionOriginalWidth, _regionOriginalHeight; -// MeshAttachment* _parentMesh; + + virtual bool applyDeform(VertexAttachment* sourceAttachment) + { + return this == sourceAttachment || (_inheritDeform && _parentMesh == sourceAttachment); + } + + private: + float _regionOffsetX, _regionOffsetY, _regionWidth, _regionHeight, _regionOriginalWidth, _regionOriginalHeight; + MeshAttachment* _parentMesh; // float[] _uvs, _regionUVs; // int[] _triangles; -// float r = 1, g = 1, b = 1, a = 1; -// int _hulllength; -// bool _inheritDeform; -// bool _regionRotate; + float _r = 1, _g = 1, _b = 1, _a = 1; + int _hulllength; + bool _inheritDeform; + bool _regionRotate; }; } From a3172ec5849eae35c03f1a458fa3455120562826 Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Tue, 7 Nov 2017 16:08:16 -0500 Subject: [PATCH 23/83] Use swap instead of move (std::move was introduced in C++11) --- spine-cpp/spine-cpp/include/spine/Vector.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spine-cpp/spine-cpp/include/spine/Vector.h b/spine-cpp/spine-cpp/include/spine/Vector.h index 8fc232098..bd7bdef48 100644 --- a/spine-cpp/spine-cpp/include/spine/Vector.h +++ b/spine-cpp/spine-cpp/include/spine/Vector.h @@ -116,7 +116,7 @@ namespace Spine { for (size_t i = inIndex; i < _size; ++i) { - _buffer[i] = std::move(_buffer[i + 1]); + _buffer[i] = std::swap(_buffer[i + 1]); } } From 818d58053196b4694331a0453507956342521f42 Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Tue, 7 Nov 2017 17:01:54 -0500 Subject: [PATCH 24/83] Whoops, apparently I do not know how to use swap --- spine-cpp/spine-cpp/include/spine/Vector.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spine-cpp/spine-cpp/include/spine/Vector.h b/spine-cpp/spine-cpp/include/spine/Vector.h index bd7bdef48..233c77d02 100644 --- a/spine-cpp/spine-cpp/include/spine/Vector.h +++ b/spine-cpp/spine-cpp/include/spine/Vector.h @@ -116,7 +116,7 @@ namespace Spine { for (size_t i = inIndex; i < _size; ++i) { - _buffer[i] = std::swap(_buffer[i + 1]); + std::swap(_buffer[i], _buffer[i + 1]); } } From c20f4a5c79ec8f65b82c105822c7c40292e3684d Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Wed, 8 Nov 2017 17:20:30 -0500 Subject: [PATCH 25/83] Forgot to add #include --- spine-cpp/spine-cpp/include/spine/Vector.h | 1 + 1 file changed, 1 insertion(+) diff --git a/spine-cpp/spine-cpp/include/spine/Vector.h b/spine-cpp/spine-cpp/include/spine/Vector.h index 233c77d02..f45d0580e 100644 --- a/spine-cpp/spine-cpp/include/spine/Vector.h +++ b/spine-cpp/spine-cpp/include/spine/Vector.h @@ -31,6 +31,7 @@ #ifndef Spine_Vector_h #define Spine_Vector_h +#include #include #include From e91a12cff1633639260c8ac603ebf2032af101b3 Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Thu, 9 Nov 2017 11:04:29 -0500 Subject: [PATCH 26/83] wip --- spine-cpp/spine-cpp/include/spine/Bone.h | 1 + .../spine-cpp/include/spine/MeshAttachment.h | 34 ++++--- .../include/spine/RegionAttachment.h | 96 +++++++------------ .../spine-cpp/src/spine/RegionAttachment.cpp | 43 +++++++++ spine-cpp/spine-cpp/src/spine/Skeleton.cpp | 4 +- 5 files changed, 99 insertions(+), 79 deletions(-) diff --git a/spine-cpp/spine-cpp/include/spine/Bone.h b/spine-cpp/spine-cpp/include/spine/Bone.h index 5cf390cad..ac20652c0 100644 --- a/spine-cpp/spine-cpp/include/spine/Bone.h +++ b/spine-cpp/spine-cpp/include/spine/Bone.h @@ -55,6 +55,7 @@ namespace Spine friend class VertexAttachment; friend class PathConstraint; friend class Skeleton; + friend class RegionAttachment; public: static void setYDown(bool inValue); diff --git a/spine-cpp/spine-cpp/include/spine/MeshAttachment.h b/spine-cpp/spine-cpp/include/spine/MeshAttachment.h index e6e1b7b48..fee9b9abf 100644 --- a/spine-cpp/spine-cpp/include/spine/MeshAttachment.h +++ b/spine-cpp/spine-cpp/include/spine/MeshAttachment.h @@ -33,6 +33,8 @@ #include +#include + namespace Spine { /// Attachment that displays a texture region using a mesh. @@ -42,18 +44,18 @@ namespace Spine public: // int HullLength { get { return _hulllength; } set { _hulllength = value; } } -// float[] RegionUVs { get { return _regionUVs; } set { _regionUVs = value; } } +// Vector& RegionUVs { get { return _regionUVs; } set { _regionUVs = value; } } // /// The UV pair for each vertex, normalized within the entire texture. -// float[] UVs { get { return _uvs; } set { _uvs = value; } } -// int[] Triangles { get { return _triangles; } set { _triangles = value; } } +// Vector& UVs { get { return _uvs; } set { _uvs = value; } } +// Vector& Triangles { get { return _triangles; } set { _triangles = value; } } // // float R { get { return r; } set { r = value; } } // float G { get { return g; } set { g = value; } } // float B { get { return b; } set { b = value; } } // float A { get { return a; } set { a = value; } } // -// string Path { get; set; } -// object RendererObject; //Object RendererObject { get; set; } +// std::string Path { get; set; } +// void* RendererObject; //Object RendererObject { get; set; } // float RegionU { get; set; } // float RegionV { get; set; } // float RegionU2 { get; set; } @@ -87,15 +89,15 @@ namespace Spine // } // // // Nonessential. -// int[] Edges { get; set; } +// Vector& Edges { get; set; } // float Width { get; set; } // float Height { get; set; } -// -// MeshAttachment (string name) : VertexAttachment(name) -// { -// // Empty -// } -// + + MeshAttachment(std::string name) : VertexAttachment(name) + { + // Empty + } + // void updateUVs() // { // float u = RegionU, v = RegionV, width = RegionU2 - RegionU, height = RegionV2 - RegionV; @@ -104,7 +106,7 @@ namespace Spine // _uvs = new float[_regionUVs.Length]; // } // -// float[] _uvs = _uvs; +// Vector _uvs = _uvs; // if (_regionRotate) // { // for (int i = 0, n = _uvs.Length; i < n; i += 2) @@ -131,8 +133,10 @@ namespace Spine private: float _regionOffsetX, _regionOffsetY, _regionWidth, _regionHeight, _regionOriginalWidth, _regionOriginalHeight; MeshAttachment* _parentMesh; -// float[] _uvs, _regionUVs; -// int[] _triangles; + Vector _uvs; + Vector _regionUVs; + Vector _triangles; + Vector _edges; float _r = 1, _g = 1, _b = 1, _a = 1; int _hulllength; bool _inheritDeform; diff --git a/spine-cpp/spine-cpp/include/spine/RegionAttachment.h b/spine-cpp/spine-cpp/include/spine/RegionAttachment.h index 5a994730d..b8641b8f6 100644 --- a/spine-cpp/spine-cpp/include/spine/RegionAttachment.h +++ b/spine-cpp/spine-cpp/include/spine/RegionAttachment.h @@ -38,6 +38,8 @@ #include +#define NUM_UVS 8 + namespace Spine { class Bone; @@ -47,16 +49,7 @@ namespace Spine { RTTI_DECL; -// public: -// const int BLX = 0; -// const int BLY = 1; -// const int ULX = 2; -// const int ULY = 3; -// const int URX = 4; -// const int URY = 5; -// const int BRX = 6; -// const int BRY = 7; -// + public: // float X { get { return x; } set { x = value; } } // float Y { get { return y; } set { y = value; } } // float Rotation { get { return _rotation; } set { _rotation = value; } } @@ -71,7 +64,7 @@ namespace Spine // float A { get { return a; } set { a = value; } } // // std::string Path { get; set; } -// object RendererObject; //object RendererObject { get; set; } +// void* RendererObject; //object RendererObject { get; set; } // float RegionOffsetX { get { return _regionOffsetX; } set { _regionOffsetX = value; } } // float RegionOffsetY { get { return _regionOffsetY; } set { _regionOffsetY = value; } } // Pixels stripped from the bottom left, unrotated. // float RegionWidth { get { return _regionWidth; } set { _regionWidth = value; } } @@ -79,14 +72,15 @@ namespace Spine // float RegionOriginalWidth { get { return _regionOriginalWidth; } set { _regionOriginalWidth = value; } } // float RegionOriginalHeight { get { return _regionOriginalHeight; } set { _regionOriginalHeight = value; } } // Unrotated, unstripped size. // -// float[] Offset { get { return _offset; } } -// float[] UVs { get { return _uvs; } } -// -// RegionAttachment (std::string name) : Attachment(name) -// { -// // Empty -// } +// Vector& Offset { get { return _offset; } } +// Vector& UVs { get { return _uvs; } } // + RegionAttachment(std::string name) : Attachment(name) + { + _offset.reserve(NUM_UVS); + _uvs.reserve(NUM_UVS); + } +// // void updateOffset() // { // float regionScaleX = _width / _regionOriginalWidth * _scaleX; @@ -142,50 +136,28 @@ namespace Spine // } // } // -// /// Transforms the attachment's four vertices to world coordinates. -// /// @param bone The parent bone. -// /// @param worldVertices The output world vertices. Must have a length greater than or equal to offset + 8. -// /// @param offset The worldVertices index to begin writing values. -// /// @param stride The number of worldVertices entries between the value pairs written. -// void computeWorldVertices(Bone& bone, Vector worldVertices, int offset, int stride = 2) -// { -// assert(worldVertices.size() >= 8); -// -// float[] vertexOffset = _offset; -// float bwx = bone.worldX, bwy = bone.worldY; -// float a = bone.a, b = bone.b, c = bone.c, d = bone.d; -// float offsetX, offsetY; -// -// offsetX = vertexOffset[BRX]; // 0 -// offsetY = vertexOffset[BRY]; // 1 -// worldVertices[offset] = offsetX * a + offsetY * b + bwx; // bl -// worldVertices[offset + 1] = offsetX * c + offsetY * d + bwy; -// offset += stride; -// -// offsetX = vertexOffset[BLX]; // 2 -// offsetY = vertexOffset[BLY]; // 3 -// worldVertices[offset] = offsetX * a + offsetY * b + bwx; // ul -// worldVertices[offset + 1] = offsetX * c + offsetY * d + bwy; -// offset += stride; -// -// offsetX = vertexOffset[ULX]; // 4 -// offsetY = vertexOffset[ULY]; // 5 -// worldVertices[offset] = offsetX * a + offsetY * b + bwx; // ur -// worldVertices[offset + 1] = offsetX * c + offsetY * d + bwy; -// offset += stride; -// -// offsetX = vertexOffset[URX]; // 6 -// offsetY = vertexOffset[URY]; // 7 -// worldVertices[offset] = offsetX * a + offsetY * b + bwx; // br -// worldVertices[offset + 1] = offsetX * c + offsetY * d + bwy; -// } -// -// private: -// float _x, _y, _rotation, _scaleX = 1, _scaleY = 1, _width, _height; -// float _regionOffsetX, _regionOffsetY, _regionWidth, _regionHeight, _regionOriginalWidth, _regionOriginalHeight; -// float[] _offset = new float[8]; -// float[] _uvs = new float[8]; -// float r = 1, g = 1, b = 1, a = 1; + /// Transforms the attachment's four vertices to world coordinates. + /// @param bone The parent bone. + /// @param worldVertices The output world vertices. Must have a length greater than or equal to offset + 8. + /// @param offset The worldVertices index to begin writing values. + /// @param stride The number of worldVertices entries between the value pairs written. + void computeWorldVertices(Bone& bone, Vector& worldVertices, int offset, int stride = 2); + + private: + static const int BLX; + static const int BLY; + static const int ULX; + static const int ULY; + static const int URX; + static const int URY; + static const int BRX; + static const int BRY; + + float _x, _y, _rotation, _scaleX = 1, _scaleY = 1, _width, _height; + float _regionOffsetX, _regionOffsetY, _regionWidth, _regionHeight, _regionOriginalWidth, _regionOriginalHeight; + Vector _offset; + Vector _uvs; + float r = 1, g = 1, b = 1, a = 1; }; } diff --git a/spine-cpp/spine-cpp/src/spine/RegionAttachment.cpp b/spine-cpp/spine-cpp/src/spine/RegionAttachment.cpp index b5b78a49e..962999af9 100644 --- a/spine-cpp/spine-cpp/src/spine/RegionAttachment.cpp +++ b/spine-cpp/spine-cpp/src/spine/RegionAttachment.cpp @@ -30,7 +30,50 @@ #include +#include + namespace Spine { + const int RegionAttachment::BLX = 0; + const int RegionAttachment::BLY = 1; + const int RegionAttachment::ULX = 2; + const int RegionAttachment::ULY = 3; + const int RegionAttachment::URX = 4; + const int RegionAttachment::URY = 5; + const int RegionAttachment::BRX = 6; + const int RegionAttachment::BRY = 7; + + void RegionAttachment::computeWorldVertices(Bone& bone, Vector& worldVertices, int offset, int stride) + { + assert(worldVertices.size() >= (offset + 8)); + + float bwx = bone._worldX, bwy = bone._worldY; + float a = bone._a, b = bone._b, c = bone._c, d = bone._d; + float offsetX, offsetY; + + offsetX = _offset[BRX]; // 0 + offsetY = _offset[BRY]; // 1 + worldVertices[offset] = offsetX * a + offsetY * b + bwx; // bl + worldVertices[offset + 1] = offsetX * c + offsetY * d + bwy; + offset += stride; + + offsetX = _offset[BLX]; // 2 + offsetY = _offset[BLY]; // 3 + worldVertices[offset] = offsetX * a + offsetY * b + bwx; // ul + worldVertices[offset + 1] = offsetX * c + offsetY * d + bwy; + offset += stride; + + offsetX = _offset[ULX]; // 4 + offsetY = _offset[ULY]; // 5 + worldVertices[offset] = offsetX * a + offsetY * b + bwx; // ur + worldVertices[offset + 1] = offsetX * c + offsetY * d + bwy; + offset += stride; + + offsetX = _offset[URX]; // 6 + offsetY = _offset[URY]; // 7 + worldVertices[offset] = offsetX * a + offsetY * b + bwx; // br + worldVertices[offset + 1] = offsetX * c + offsetY * d + bwy; + } + RTTI_IMPL(RegionAttachment, Attachment); } diff --git a/spine-cpp/spine-cpp/src/spine/Skeleton.cpp b/spine-cpp/spine-cpp/src/spine/Skeleton.cpp index f6e898b3b..783ddda3b 100644 --- a/spine-cpp/spine-cpp/src/spine/Skeleton.cpp +++ b/spine-cpp/spine-cpp/src/spine/Skeleton.cpp @@ -480,7 +480,7 @@ namespace Spine { outVertexBuffer.reserve(8); } -// regionAttachment->computeWorldVertices(slot->getBone(), outVertexBuffer, 0); + regionAttachment->computeWorldVertices(slot->getBone(), outVertexBuffer, 0); } else if (attachment != NULL && attachment->getRTTI().derivesFrom(MeshAttachment::rtti)) { @@ -492,7 +492,7 @@ namespace Spine outVertexBuffer.reserve(verticesLength); } -// mesh->computeWorldVertices(slot, 0, verticesLength, outVertexBuffer, 0); + mesh->computeWorldVertices(*slot, 0, verticesLength, outVertexBuffer, 0); } for (int ii = 0; ii < verticesLength; ii += 2) From 7983a6e7437fc08813acb67b4de0ea1ea303bbc5 Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Thu, 9 Nov 2017 12:01:17 -0500 Subject: [PATCH 27/83] Adding CMakeLists.txt and fixing some compiler warnings --- spine-cpp/CMakeLists.txt | 9 +++++++++ spine-cpp/spine-cpp/include/spine/HashMap.h | 8 ++++++-- spine-cpp/spine-cpp/src/spine/Animation.cpp | 4 ++-- spine-cpp/spine-cpp/src/spine/Event.cpp | 2 +- spine-cpp/spine-cpp/src/spine/PathConstraint.cpp | 4 ++-- spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp | 4 ++-- 6 files changed, 22 insertions(+), 9 deletions(-) create mode 100644 spine-cpp/CMakeLists.txt diff --git a/spine-cpp/CMakeLists.txt b/spine-cpp/CMakeLists.txt new file mode 100644 index 000000000..844051a33 --- /dev/null +++ b/spine-cpp/CMakeLists.txt @@ -0,0 +1,9 @@ +include_directories(include) +file(GLOB INCLUDES "spine-cpp/include/**/*.h") +file(GLOB SOURCES "spine-cpp/src/**/*.cpp") + +set(CMAKE_CPP_FLAGS "${CMAKE_CPP_FLAGS} -Wall -std=c++03 -pedantic") +add_library(spine-cpp STATIC ${SOURCES} ${INCLUDES}) +target_include_directories(spine-cpp PUBLIC spine-cpp/include) +install(TARGETS spine-cpp DESTINATION dist/lib) +install(FILES ${INCLUDES} DESTINATION dist/include) \ No newline at end of file diff --git a/spine-cpp/spine-cpp/include/spine/HashMap.h b/spine-cpp/spine-cpp/include/spine/HashMap.h index 50fbbdf5b..f146d39b7 100755 --- a/spine-cpp/spine-cpp/include/spine/HashMap.h +++ b/spine-cpp/spine-cpp/include/spine/HashMap.h @@ -89,7 +89,12 @@ namespace Spine Entry* _entry; }; - HashMap(size_t capacity = 65535) : _capacity(capacity), _hashFunction(), _header(), _trailer() + HashMap(size_t capacity = 65535) : + _hashFunction(), + _capacity(capacity), + _header(), + _trailer(), + _hashSize(0) { _hashTable = new Entry[capacity]; for (int i = 0; i < _capacity; ++i) @@ -101,7 +106,6 @@ namespace Spine _header.next = &_trailer; _trailer.prev = &_header; _trailer.next = &_trailer; - _hashSize = 0; } ~HashMap() diff --git a/spine-cpp/spine-cpp/src/spine/Animation.cpp b/spine-cpp/spine-cpp/src/spine/Animation.cpp index 3cbc2e63c..96b625dcb 100644 --- a/spine-cpp/spine-cpp/src/spine/Animation.cpp +++ b/spine-cpp/spine-cpp/src/spine/Animation.cpp @@ -40,9 +40,9 @@ namespace Spine { Animation::Animation(std::string name, Vector& timelines, float duration) : - _name(name), _timelines(timelines), - _duration(duration) + _duration(duration), + _name(name) { assert(_name.length() > 0); } diff --git a/spine-cpp/spine-cpp/src/spine/Event.cpp b/spine-cpp/spine-cpp/src/spine/Event.cpp index ca9abdbbd..09ba067b2 100644 --- a/spine-cpp/spine-cpp/src/spine/Event.cpp +++ b/spine-cpp/spine-cpp/src/spine/Event.cpp @@ -35,8 +35,8 @@ namespace Spine { Event::Event(float time, const EventData& data) : - _time(time), _data(data), + _time(time), _intValue(0), _floatValue(0), _stringValue() diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp b/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp index 6efbbb7be..33a29256e 100644 --- a/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp @@ -52,11 +52,11 @@ namespace Spine PathConstraint::PathConstraint(PathConstraintData& data, Skeleton& skeleton) : Constraint(), _data(data), + _target(skeleton.findSlot(data.getTarget()->getName())), _position(data.getPosition()), _spacing(data.getSpacing()), _rotateMix(data.getRotateMix()), - _translateMix(data.getTranslateMix()), - _target(skeleton.findSlot(data.getTarget()->getName())) + _translateMix(data.getTranslateMix()) { _bones.reserve(_data.getBones().size()); for (BoneData** i = _data.getBones().begin(); i != _data.getBones().end(); ++i) diff --git a/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp b/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp index 6a956c071..a1b5865f2 100644 --- a/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp +++ b/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp @@ -41,11 +41,11 @@ namespace Spine { TransformConstraint::TransformConstraint(TransformConstraintData& data, Skeleton& skeleton) : Constraint(), _data(data), + _target(skeleton.findBone(data.getTarget()->getName())), _rotateMix(data.getRotateMix()), _translateMix(data.getTranslateMix()), _scaleMix(data.getScaleMix()), - _shearMix(data.getShearMix()), - _target(skeleton.findBone(data.getTarget()->getName())) + _shearMix(data.getShearMix()) { _bones.reserve(_data.getBones().size()); for (BoneData** i = _data.getBones().begin(); i != _data.getBones().end(); ++i) From 2a00853fe28f8d5a3660fc51e4c59a00d77bb0f9 Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Thu, 9 Nov 2017 12:19:03 -0500 Subject: [PATCH 28/83] Forgot some cpp flags -fno-exceptions -fno-rtti --- spine-cpp/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spine-cpp/CMakeLists.txt b/spine-cpp/CMakeLists.txt index 844051a33..b5d0c99ba 100644 --- a/spine-cpp/CMakeLists.txt +++ b/spine-cpp/CMakeLists.txt @@ -2,7 +2,7 @@ include_directories(include) file(GLOB INCLUDES "spine-cpp/include/**/*.h") file(GLOB SOURCES "spine-cpp/src/**/*.cpp") -set(CMAKE_CPP_FLAGS "${CMAKE_CPP_FLAGS} -Wall -std=c++03 -pedantic") +set(CMAKE_CPP_FLAGS "${CMAKE_CPP_FLAGS} -Wall -std=c++03 -pedantic -fno-exceptions -fno-rtti") add_library(spine-cpp STATIC ${SOURCES} ${INCLUDES}) target_include_directories(spine-cpp PUBLIC spine-cpp/include) install(TARGETS spine-cpp DESTINATION dist/lib) From 175365a0390f94c603707509c7f6e0666ed15d19 Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Sun, 12 Nov 2017 11:21:25 -0500 Subject: [PATCH 29/83] wip --- .../spine-cpp/include/spine/MeshAttachment.h | 178 +++++----- .../include/spine/RegionAttachment.h | 153 ++++---- .../include/spine/VertexAttachment.h | 6 +- spine-cpp/spine-cpp/src/spine/Attachment.cpp | 4 +- spine-cpp/spine-cpp/src/spine/Bone.cpp | 4 +- spine-cpp/spine-cpp/src/spine/Constraint.cpp | 4 +- .../spine-cpp/src/spine/CurveTimeline.cpp | 4 +- .../spine-cpp/src/spine/IkConstraint.cpp | 4 +- .../spine-cpp/src/spine/MeshAttachment.cpp | 331 ++++++++++++++++++ .../spine-cpp/src/spine/PathAttachment.cpp | 4 +- .../spine-cpp/src/spine/PathConstraint.cpp | 4 +- .../spine-cpp/src/spine/RegionAttachment.cpp | 267 +++++++++++++- .../spine-cpp/src/spine/RotateTimeline.cpp | 4 +- spine-cpp/spine-cpp/src/spine/Timeline.cpp | 4 +- .../src/spine/TransformConstraint.cpp | 4 +- spine-cpp/spine-cpp/src/spine/Updatable.cpp | 4 +- .../spine-cpp/src/spine/VertexAttachment.cpp | 6 +- 17 files changed, 782 insertions(+), 203 deletions(-) diff --git a/spine-cpp/spine-cpp/include/spine/MeshAttachment.h b/spine-cpp/spine-cpp/include/spine/MeshAttachment.h index fee9b9abf..821c73dd9 100644 --- a/spine-cpp/spine-cpp/include/spine/MeshAttachment.h +++ b/spine-cpp/spine-cpp/include/spine/MeshAttachment.h @@ -35,6 +35,8 @@ #include +#include + namespace Spine { /// Attachment that displays a texture region using a mesh. @@ -43,92 +45,88 @@ namespace Spine RTTI_DECL; public: -// int HullLength { get { return _hulllength; } set { _hulllength = value; } } -// Vector& RegionUVs { get { return _regionUVs; } set { _regionUVs = value; } } -// /// The UV pair for each vertex, normalized within the entire texture. -// Vector& UVs { get { return _uvs; } set { _uvs = value; } } -// Vector& Triangles { get { return _triangles; } set { _triangles = value; } } -// -// float R { get { return r; } set { r = value; } } -// float G { get { return g; } set { g = value; } } -// float B { get { return b; } set { b = value; } } -// float A { get { return a; } set { a = value; } } -// -// std::string Path { get; set; } -// void* RendererObject; //Object RendererObject { get; set; } -// float RegionU { get; set; } -// float RegionV { get; set; } -// float RegionU2 { get; set; } -// float RegionV2 { get; set; } -// bool RegionRotate { get; set; } -// float RegionOffsetX { get { return _regionOffsetX; } set { _regionOffsetX = value; } } -// float RegionOffsetY { get { return _regionOffsetY; } set { _regionOffsetY = value; } } // Pixels stripped from the bottom left, unrotated. -// float RegionWidth { get { return _regionWidth; } set { _regionWidth = value; } } -// float RegionHeight { get { return _regionHeight; } set { _regionHeight = value; } } // Unrotated, stripped size. -// float RegionOriginalWidth { get { return _regionOriginalWidth; } set { _regionOriginalWidth = value; } } -// float RegionOriginalHeight { get { return _regionOriginalHeight; } set { _regionOriginalHeight = value; } } // Unrotated, unstripped size. -// -// bool InheritDeform { get { return _inheritDeform; } set { _inheritDeform = value; } } -// -// MeshAttachment ParentMesh { -// get { return _parentMesh; } -// set { -// _parentMesh = value; -// if (value != null) { -// bones = value.bones; -// vertices = value.vertices; -// worldVerticesLength = value.worldVerticesLength; -// _regionUVs = value._regionUVs; -// _triangles = value._triangles; -// HullLength = value.HullLength; -// Edges = value.Edges; -// Width = value.Width; -// Height = value.Height; -// } -// } -// } -// -// // Nonessential. -// Vector& Edges { get; set; } -// float Width { get; set; } -// float Height { get; set; } + MeshAttachment(std::string name); - MeshAttachment(std::string name) : VertexAttachment(name) - { - // Empty - } + void updateUVs(); -// void updateUVs() -// { -// float u = RegionU, v = RegionV, width = RegionU2 - RegionU, height = RegionV2 - RegionV; -// if (_uvs == null || _uvs.Length != _regionUVs.Length) -// { -// _uvs = new float[_regionUVs.Length]; -// } -// -// Vector _uvs = _uvs; -// if (_regionRotate) -// { -// for (int i = 0, n = _uvs.Length; i < n; i += 2) -// { -// _uvs[i] = u + _regionUVs[i + 1] * width; -// _uvs[i + 1] = v + height - _regionUVs[i] * height; -// } -// } -// else -// { -// for (int i = 0, n = _uvs.Length; i < n; i += 2) -// { -// _uvs[i] = u + _regionUVs[i] * width; -// _uvs[i + 1] = v + _regionUVs[i + 1] * height; -// } -// } -// } - - virtual bool applyDeform(VertexAttachment* sourceAttachment) - { - return this == sourceAttachment || (_inheritDeform && _parentMesh == sourceAttachment); - } + virtual bool applyDeform(VertexAttachment* sourceAttachment); + + int getHullLength(); + void setHullLength(float inValue); + + Vector& getRegionUVs(); + void setRegionUVs(Vector& inValue); + + /// The UV pair for each vertex, normalized within the entire texture. See also MeshAttachment::updateUVs + Vector& getUVs(); + void setUVs(Vector& inValue); + + Vector& getTriangles(); + void setTriangles(Vector& inValue); + + float getR(); + void setR(float inValue); + float getG(); + void setG(float inValue); + float getB(); + void setB(float inValue); + float getA(); + void setA(float inValue); + + std::string getPath(); + void setPath(std::string inValue); + void* getRendererObject(); + void setRendererObject(void* inValue); + + float getRegionU(); + void setRegionU(float inValue); + + float getRegionV(); + void setRegionV(float inValue); + + float getRegionU2(); + void setRegionU2(float inValue); + + float getRegionV2(); + void setRegionV2(float inValue); + + bool getRegionRotate(); + void setRegionRotate(float inValue); + + float getRegionOffsetX(); + void setRegionOffsetX(float inValue); + + // Pixels stripped from the bottom left, unrotated. + float getRegionOffsetY(); + void setRegionOffsetY(float inValue); + + float getRegionWidth(); + void setRegionWidth(float inValue); + + // Unrotated, stripped size. + float getRegionHeight(); + void setRegionHeight(float inValue); + + float getRegionOriginalWidth(); + void setRegionOriginalWidth(float inValue); + + // Unrotated, unstripped size. + float getRegionOriginalHeight(); + void setRegionOriginalHeight(float inValue); + + bool getInheritDeform(); + void setInheritDeform(bool inValue); + + MeshAttachment* getParentMesh(); + void setParentMesh(MeshAttachment* inValue); + + // Nonessential. + Vector& getEdges(); + void setEdges(Vector& inValue); + float getWidth(); + void setWidth(float inValue); + float getHeight(); + void setHeight(float inValue); private: float _regionOffsetX, _regionOffsetY, _regionWidth, _regionHeight, _regionOriginalWidth, _regionOriginalHeight; @@ -137,8 +135,16 @@ namespace Spine Vector _regionUVs; Vector _triangles; Vector _edges; - float _r = 1, _g = 1, _b = 1, _a = 1; - int _hulllength; + void* _rendererObject; + std::string _path; + float _regionU; + float _regionV; + float _regionU2; + float _regionV2; + float _width; + float _height; + float _r, _g, _b, _a; + int _hullLength; bool _inheritDeform; bool _regionRotate; }; diff --git a/spine-cpp/spine-cpp/include/spine/RegionAttachment.h b/spine-cpp/spine-cpp/include/spine/RegionAttachment.h index b8641b8f6..c85c0be1c 100644 --- a/spine-cpp/spine-cpp/include/spine/RegionAttachment.h +++ b/spine-cpp/spine-cpp/include/spine/RegionAttachment.h @@ -34,9 +34,8 @@ #include #include -#include -#include +#include #define NUM_UVS 8 @@ -50,92 +49,12 @@ namespace Spine RTTI_DECL; public: -// float X { get { return x; } set { x = value; } } -// float Y { get { return y; } set { y = value; } } -// float Rotation { get { return _rotation; } set { _rotation = value; } } -// float ScaleX { get { return scaleX; } set { scaleX = value; } } -// float ScaleY { get { return scaleY; } set { scaleY = value; } } -// float Width { get { return width; } set { width = value; } } -// float Height { get { return height; } set { height = value; } } -// -// float R { get { return r; } set { r = value; } } -// float G { get { return g; } set { g = value; } } -// float B { get { return b; } set { b = value; } } -// float A { get { return a; } set { a = value; } } -// -// std::string Path { get; set; } -// void* RendererObject; //object RendererObject { get; set; } -// float RegionOffsetX { get { return _regionOffsetX; } set { _regionOffsetX = value; } } -// float RegionOffsetY { get { return _regionOffsetY; } set { _regionOffsetY = value; } } // Pixels stripped from the bottom left, unrotated. -// float RegionWidth { get { return _regionWidth; } set { _regionWidth = value; } } -// float RegionHeight { get { return _regionHeight; } set { _regionHeight = value; } } // Unrotated, stripped size. -// float RegionOriginalWidth { get { return _regionOriginalWidth; } set { _regionOriginalWidth = value; } } -// float RegionOriginalHeight { get { return _regionOriginalHeight; } set { _regionOriginalHeight = value; } } // Unrotated, unstripped size. -// -// Vector& Offset { get { return _offset; } } -// Vector& UVs { get { return _uvs; } } -// - RegionAttachment(std::string name) : Attachment(name) - { - _offset.reserve(NUM_UVS); - _uvs.reserve(NUM_UVS); - } -// -// void updateOffset() -// { -// float regionScaleX = _width / _regionOriginalWidth * _scaleX; -// float regionScaleY = _height / _regionOriginalHeight * _scaleY; -// float localX = -_width / 2 * _scaleX + _regionOffsetX * regionScaleX; -// float localY = -_height / 2 * _scaleY + _regionOffsetY * regionScaleY; -// float localX2 = localX + _regionWidth * regionScaleX; -// float localY2 = localY + _regionHeight * regionScaleY; -// float cos = MathUtil::cosDeg(_rotation); -// float sin = MathUtil::sinDeg(_rotation); -// float localXCos = localX * cos + _x; -// float localXSin = localX * sin; -// float localYCos = localY * cos + _y; -// float localYSin = localY * sin; -// float localX2Cos = localX2 * cos + _x; -// float localX2Sin = localX2 * sin; -// float localY2Cos = localY2 * cos + _y; -// float localY2Sin = localY2 * sin; -// -// _offset[BLX] = localXCos - localYSin; -// _offset[BLY] = localYCos + localXSin; -// _offset[ULX] = localXCos - localY2Sin; -// _offset[ULY] = localY2Cos + localXSin; -// _offset[URX] = localX2Cos - localY2Sin; -// _offset[URY] = localY2Cos + localX2Sin; -// _offset[BRX] = localX2Cos - localYSin; -// _offset[BRY] = localYCos + localX2Sin; -// } -// -// void setUVs(float u, float v, float u2, float v2, bool rotate) -// { -// if (rotate) -// { -// _uvs[URX] = u; -// _uvs[URY] = v2; -// _uvs[BRX] = u; -// _uvs[BRY] = v; -// _uvs[BLX] = u2; -// _uvs[BLY] = v; -// _uvs[ULX] = u2; -// _uvs[ULY] = v2; -// } -// else -// { -// _uvs[ULX] = u; -// _uvs[ULY] = v2; -// _uvs[URX] = u; -// _uvs[URY] = v; -// _uvs[BRX] = u2; -// _uvs[BRY] = v; -// _uvs[BLX] = u2; -// _uvs[BLY] = v2; -// } -// } -// + RegionAttachment(std::string name); + + void updateOffset(); + + void setUVs(float u, float v, float u2, float v2, bool rotate); + /// Transforms the attachment's four vertices to world coordinates. /// @param bone The parent bone. /// @param worldVertices The output world vertices. Must have a length greater than or equal to offset + 8. @@ -143,6 +62,56 @@ namespace Spine /// @param stride The number of worldVertices entries between the value pairs written. void computeWorldVertices(Bone& bone, Vector& worldVertices, int offset, int stride = 2); + float getX(); + void setX(float inValue); + float getY(); + void setY(float inValue); + float getRotation(); + void setRotation(float inValue); + float getScaleX(); + void setScaleX(float inValue); + float getScaleY(); + void setScaleY(float inValue); + float getWidth(); + void setWidth(float inValue); + float getHeight(); + void setHeight(float inValue); + + float getR(); + void setR(float inValue); + float getG(); + void setG(float inValue); + float getB(); + void setB(float inValue); + float getA(); + void setA(float inValue); + + std::string getPath(); + void setPath(std::string inValue); + void* getRendererObject(); + void setRendererObject(void* inValue); + float getRegionOffsetX(); + void setRegionOffsetX(float inValue); + + // Pixels stripped from the bottom left, unrotated. + float getRegionOffsetY(); + void setRegionOffsetY(float inValue); + float getRegionWidth(); + void setRegionWidth(float inValue); + + // Unrotated, stripped size. + float getRegionHeight(); + void setRegionHeight(float inValue); + float getRegionOriginalWidth(); + void setRegionOriginalWidth(float inValue); + + // Unrotated, unstripped size. + float getRegionOriginalHeight(); + void setRegionOriginalHeight(float inValue); + + Vector& getOffset(); + Vector& getUVs(); + private: static const int BLX; static const int BLY; @@ -157,7 +126,13 @@ namespace Spine float _regionOffsetX, _regionOffsetY, _regionWidth, _regionHeight, _regionOriginalWidth, _regionOriginalHeight; Vector _offset; Vector _uvs; - float r = 1, g = 1, b = 1, a = 1; + void* _rendererObject; + std::string _path; + float _regionU; + float _regionV; + float _regionU2; + float _regionV2; + float _r, _g, _b, _a; }; } diff --git a/spine-cpp/spine-cpp/include/spine/VertexAttachment.h b/spine-cpp/spine-cpp/include/spine/VertexAttachment.h index ba047dfe8..6405015f6 100644 --- a/spine-cpp/spine-cpp/include/spine/VertexAttachment.h +++ b/spine-cpp/spine-cpp/include/spine/VertexAttachment.h @@ -72,12 +72,14 @@ namespace Spine int getWorldVerticesLength(); void setWorldVerticesLength(int inValue); - private: - const int _id; + protected: Vector _bones; Vector _vertices; int _worldVerticesLength; + private: + const int _id; + static int getNextID(); }; } diff --git a/spine-cpp/spine-cpp/src/spine/Attachment.cpp b/spine-cpp/spine-cpp/src/spine/Attachment.cpp index 829f8c7d6..74a734f27 100644 --- a/spine-cpp/spine-cpp/src/spine/Attachment.cpp +++ b/spine-cpp/spine-cpp/src/spine/Attachment.cpp @@ -34,6 +34,8 @@ namespace Spine { + RTTI_IMPL_NOPARENT(Attachment); + Attachment::Attachment(std::string name) : _name(name) { assert(_name.length() > 0); @@ -43,6 +45,4 @@ namespace Spine { return _name; } - - RTTI_IMPL_NOPARENT(Attachment); } diff --git a/spine-cpp/spine-cpp/src/spine/Bone.cpp b/spine-cpp/spine-cpp/src/spine/Bone.cpp index bb8dcc004..71e119c95 100644 --- a/spine-cpp/spine-cpp/src/spine/Bone.cpp +++ b/spine-cpp/spine-cpp/src/spine/Bone.cpp @@ -38,6 +38,8 @@ namespace Spine { + RTTI_IMPL(Bone, Updatable); + bool Bone::yDown = false; void Bone::setYDown(bool inValue) @@ -621,6 +623,4 @@ namespace Spine _arotation = 90 - MathUtil::atan2(rd, rb) * RadDeg; } } - - RTTI_IMPL(Bone, Updatable); } diff --git a/spine-cpp/spine-cpp/src/spine/Constraint.cpp b/spine-cpp/spine-cpp/src/spine/Constraint.cpp index ae6a8d749..bad9d1a0b 100644 --- a/spine-cpp/spine-cpp/src/spine/Constraint.cpp +++ b/spine-cpp/spine-cpp/src/spine/Constraint.cpp @@ -32,6 +32,8 @@ namespace Spine { + RTTI_IMPL(Constraint, Updatable); + Constraint::Constraint() { // Empty @@ -41,6 +43,4 @@ namespace Spine { // Empty } - - RTTI_IMPL(Constraint, Updatable); } diff --git a/spine-cpp/spine-cpp/src/spine/CurveTimeline.cpp b/spine-cpp/spine-cpp/src/spine/CurveTimeline.cpp index 9735c76dc..ea4047eb2 100644 --- a/spine-cpp/spine-cpp/src/spine/CurveTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/CurveTimeline.cpp @@ -34,6 +34,8 @@ namespace Spine { + RTTI_IMPL(CurveTimeline, Timeline); + const float CurveTimeline::LINEAR = 0; const float CurveTimeline::STEPPED = 1; const float CurveTimeline::BEZIER = 2; @@ -133,6 +135,4 @@ namespace Spine { return _curves[frameIndex * BEZIER_SIZE]; } - - RTTI_IMPL(CurveTimeline, Timeline); } diff --git a/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp b/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp index 1bf6cdb74..8064b31a5 100644 --- a/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp +++ b/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp @@ -39,6 +39,8 @@ namespace Spine { + RTTI_IMPL(IkConstraint, Constraint); + void IkConstraint::apply(Bone& bone, float targetX, float targetY, float alpha) { if (!bone._appliedValid) @@ -357,6 +359,4 @@ namespace Spine { _mix = inValue; } - - RTTI_IMPL(IkConstraint, Constraint); } diff --git a/spine-cpp/spine-cpp/src/spine/MeshAttachment.cpp b/spine-cpp/spine-cpp/src/spine/MeshAttachment.cpp index 42159e2c9..6d928a6c3 100644 --- a/spine-cpp/spine-cpp/src/spine/MeshAttachment.cpp +++ b/spine-cpp/spine-cpp/src/spine/MeshAttachment.cpp @@ -33,4 +33,335 @@ namespace Spine { RTTI_IMPL(MeshAttachment, VertexAttachment); + + MeshAttachment::MeshAttachment(std::string name) : VertexAttachment(name), + _regionOffsetX(0), + _regionOffsetY(0), + _regionWidth(0), + _regionHeight(0), + _regionOriginalWidth(0), + _regionOriginalHeight(0), + _parentMesh(NULL), + _rendererObject(NULL), + _path(), + _regionU(0), + _regionV(0), + _regionU2(0), + _regionV2(0), + _width(0), + _height(0), + _r(1), + _g(1), + _b(1), + _a(1), + _hullLength(0), + _inheritDeform(false), + _regionRotate(false) + { + // Empty + } + + void MeshAttachment::updateUVs() + { + float u = _regionU, v = _regionV, width = _regionU2 - _regionU, height = _regionV2 - _regionV; + if (_uvs.size() != _regionUVs.size()) + { + _uvs.reserve(_regionUVs.size()); + } + + + if (_regionRotate) + { + for (size_t i = 0, n = _uvs.size(); i < n; i += 2) + { + _uvs[i] = u + _regionUVs[i + 1] * width; + _uvs[i + 1] = v + height - _regionUVs[i] * height; + } + } + else + { + for (size_t i = 0, n = _uvs.size(); i < n; i += 2) + { + _uvs[i] = u + _regionUVs[i] * width; + _uvs[i + 1] = v + _regionUVs[i + 1] * height; + } + } + } + + bool MeshAttachment::applyDeform(VertexAttachment* sourceAttachment) + { + return this == sourceAttachment || (_inheritDeform && _parentMesh == sourceAttachment); + } + + int MeshAttachment::getHullLength() + { + return _hullLength; + } + + void MeshAttachment::setHullLength(float inValue) + { + _hullLength = inValue; + } + + Vector& MeshAttachment::getRegionUVs() + { + return _regionUVs; + } + + void MeshAttachment::setRegionUVs(Vector& inValue) + { + _regionUVs = inValue; + } + + Vector& MeshAttachment::getUVs() + { + return _uvs; + } + + void MeshAttachment::setUVs(Vector& inValue) + { + _uvs = inValue; + } + + Vector& MeshAttachment::getTriangles() + { + return _triangles; + } + + void MeshAttachment::setTriangles(Vector& inValue) + { + _triangles = inValue; + } + + float MeshAttachment::getR() + { + return _r; + } + + void MeshAttachment::setR(float inValue) + { + _r = inValue; + } + + float MeshAttachment::getG() + { + return _g; + } + + void MeshAttachment::setG(float inValue) + { + _g = inValue; + } + + float MeshAttachment::getB() + { + return _b; + } + + void MeshAttachment::setB(float inValue) + { + _b = inValue; + } + + float MeshAttachment::getA() + { + return _a; + } + + void MeshAttachment::setA(float inValue) + { + _a = inValue; + } + + std::string MeshAttachment::getPath() + { + return _path; + } + + void MeshAttachment::setPath(std::string inValue) + { + _path = inValue; + } + + void* MeshAttachment::getRendererObject() + { + return _rendererObject; + } + + void MeshAttachment::setRendererObject(void* inValue) + { + _rendererObject = inValue; + } + + float MeshAttachment::getRegionU() + { + return _regionU; + } + + void MeshAttachment::setRegionU(float inValue) + { + _regionU = inValue; + } + + float MeshAttachment::getRegionV() + { + return _regionV; + } + + void MeshAttachment::setRegionV(float inValue) + { + _regionV = inValue; + } + + float MeshAttachment::getRegionU2() + { + return _regionU2; + } + + void MeshAttachment::setRegionU2(float inValue) + { + _regionU2 = inValue; + } + + float MeshAttachment::getRegionV2() + { + return _regionV2; + } + + void MeshAttachment::setRegionV2(float inValue) + { + _regionV2 = inValue; + } + + bool MeshAttachment::getRegionRotate() + { + return _regionRotate; + } + + void MeshAttachment::setRegionRotate(float inValue) + { + _regionRotate = inValue; + } + + float MeshAttachment::getRegionOffsetX() + { + return _regionOffsetX; + } + + void MeshAttachment::setRegionOffsetX(float inValue) + { + _regionOffsetX = inValue; + } + + float MeshAttachment::getRegionOffsetY() + { + return _regionOffsetY; + } + + void MeshAttachment::setRegionOffsetY(float inValue) + { + _regionOffsetY = inValue; + } + + float MeshAttachment::getRegionWidth() + { + return _regionWidth; + } + + void MeshAttachment::setRegionWidth(float inValue) + { + _regionWidth = inValue; + } + + float MeshAttachment::getRegionHeight() + { + return _regionHeight; + } + + void MeshAttachment::setRegionHeight(float inValue) + { + _regionHeight = inValue; + } + + float MeshAttachment::getRegionOriginalWidth() + { + return _regionOriginalWidth; + } + + void MeshAttachment::setRegionOriginalWidth(float inValue) + { + _regionOriginalWidth = inValue; + } + + float MeshAttachment::getRegionOriginalHeight() + { + return _regionOriginalHeight; + } + + void MeshAttachment::setRegionOriginalHeight(float inValue) + { + _regionOriginalHeight = inValue; + } + + bool MeshAttachment::getInheritDeform() + { + return _inheritDeform; + } + + void MeshAttachment::setInheritDeform(bool inValue) + { + _inheritDeform = inValue; + } + + MeshAttachment* MeshAttachment::getParentMesh() + { + return _parentMesh; + } + + void MeshAttachment::setParentMesh(MeshAttachment* inValue) + { + _parentMesh = inValue; + if (inValue != NULL) + { + _bones = inValue->_bones; + _vertices = inValue->_vertices; + _worldVerticesLength = inValue->_worldVerticesLength; + _regionUVs = inValue->_regionUVs; + _triangles = inValue->_triangles; + _hullLength = inValue->_hullLength; + _edges = inValue->_edges; + _width = inValue->_width; + _height = inValue->_height; + } + } + + Vector& MeshAttachment::getEdges() + { + return _edges; + } + + void MeshAttachment::setEdges(Vector& inValue) + { + _edges = inValue; + } + + float MeshAttachment::getWidth() + { + return _width; + } + + void MeshAttachment::setWidth(float inValue) + { + _width = inValue; + } + + float MeshAttachment::getHeight() + { + return _height; + } + + void MeshAttachment::setHeight(float inValue) + { + _height = inValue; + } } diff --git a/spine-cpp/spine-cpp/src/spine/PathAttachment.cpp b/spine-cpp/spine-cpp/src/spine/PathAttachment.cpp index d7d57ccd9..54bd9337b 100644 --- a/spine-cpp/spine-cpp/src/spine/PathAttachment.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathAttachment.cpp @@ -32,6 +32,8 @@ namespace Spine { + RTTI_IMPL(PathAttachment, VertexAttachment); + PathAttachment::PathAttachment(std::string name) : VertexAttachment(name) { // Empty @@ -66,6 +68,4 @@ namespace Spine { _constantSpeed = inValue; } - - RTTI_IMPL(PathAttachment, VertexAttachment); } diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp b/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp index 33a29256e..df73d6195 100644 --- a/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp @@ -45,6 +45,8 @@ namespace Spine { + RTTI_IMPL(PathConstraint, Constraint); + const float PathConstraint::EPSILON = 0.00001f; const int PathConstraint::NONE = -1; const int PathConstraint::BEFORE = -2; @@ -645,6 +647,4 @@ namespace Spine output[o + 2] = (float)atan2(y - (y1 * uu + cy1 * ut * 2 + cy2 * tt), x - (x1 * uu + cx1 * ut * 2 + cx2 * tt)); } } - - RTTI_IMPL(PathConstraint, Constraint); } diff --git a/spine-cpp/spine-cpp/src/spine/RegionAttachment.cpp b/spine-cpp/spine-cpp/src/spine/RegionAttachment.cpp index 962999af9..310a4619b 100644 --- a/spine-cpp/spine-cpp/src/spine/RegionAttachment.cpp +++ b/spine-cpp/spine-cpp/src/spine/RegionAttachment.cpp @@ -32,8 +32,14 @@ #include +#include + +#include + namespace Spine { + RTTI_IMPL(RegionAttachment, Attachment); + const int RegionAttachment::BLX = 0; const int RegionAttachment::BLY = 1; const int RegionAttachment::ULX = 2; @@ -43,6 +49,67 @@ namespace Spine const int RegionAttachment::BRX = 6; const int RegionAttachment::BRY = 7; + RegionAttachment::RegionAttachment(std::string name) : Attachment(name) + { + _offset.reserve(NUM_UVS); + _uvs.reserve(NUM_UVS); + } + + void RegionAttachment::updateOffset() + { + float regionScaleX = _width / _regionOriginalWidth * _scaleX; + float regionScaleY = _height / _regionOriginalHeight * _scaleY; + float localX = -_width / 2 * _scaleX + _regionOffsetX * regionScaleX; + float localY = -_height / 2 * _scaleY + _regionOffsetY * regionScaleY; + float localX2 = localX + _regionWidth * regionScaleX; + float localY2 = localY + _regionHeight * regionScaleY; + float cos = MathUtil::cosDeg(_rotation); + float sin = MathUtil::sinDeg(_rotation); + float localXCos = localX * cos + _x; + float localXSin = localX * sin; + float localYCos = localY * cos + _y; + float localYSin = localY * sin; + float localX2Cos = localX2 * cos + _x; + float localX2Sin = localX2 * sin; + float localY2Cos = localY2 * cos + _y; + float localY2Sin = localY2 * sin; + + _offset[BLX] = localXCos - localYSin; + _offset[BLY] = localYCos + localXSin; + _offset[ULX] = localXCos - localY2Sin; + _offset[ULY] = localY2Cos + localXSin; + _offset[URX] = localX2Cos - localY2Sin; + _offset[URY] = localY2Cos + localX2Sin; + _offset[BRX] = localX2Cos - localYSin; + _offset[BRY] = localYCos + localX2Sin; + } + + void RegionAttachment::setUVs(float u, float v, float u2, float v2, bool rotate) + { + if (rotate) + { + _uvs[URX] = u; + _uvs[URY] = v2; + _uvs[BRX] = u; + _uvs[BRY] = v; + _uvs[BLX] = u2; + _uvs[BLY] = v; + _uvs[ULX] = u2; + _uvs[ULY] = v2; + } + else + { + _uvs[ULX] = u; + _uvs[ULY] = v2; + _uvs[URX] = u; + _uvs[URY] = v; + _uvs[BRX] = u2; + _uvs[BRY] = v; + _uvs[BLX] = u2; + _uvs[BLY] = v2; + } + } + void RegionAttachment::computeWorldVertices(Bone& bone, Vector& worldVertices, int offset, int stride) { assert(worldVertices.size() >= (offset + 8)); @@ -75,5 +142,203 @@ namespace Spine worldVertices[offset + 1] = offsetX * c + offsetY * d + bwy; } - RTTI_IMPL(RegionAttachment, Attachment); + float RegionAttachment::getX() + { + return _x; + } + + void RegionAttachment::setX(float inValue) + { + _x = inValue; + } + + float RegionAttachment::getY() + { + return _y; + } + + void RegionAttachment::setY(float inValue) + { + _y = inValue; + } + + float RegionAttachment::getRotation() + { + return _rotation; + } + + void RegionAttachment::setRotation(float inValue) + { + _rotation = inValue; + } + + float RegionAttachment::getScaleX() + { + return _scaleX; + } + + void RegionAttachment::setScaleX(float inValue) + { + _scaleX = inValue; + } + + float RegionAttachment::getScaleY() + { + return _scaleY; + } + + void RegionAttachment::setScaleY(float inValue) + { + _scaleY = inValue; + } + + float RegionAttachment::getWidth() + { + return _width; + } + + void RegionAttachment::setWidth(float inValue) + { + _width = inValue; + } + + float RegionAttachment::getHeight() + { + return _height; + } + + void RegionAttachment::setHeight(float inValue) + { + _height = inValue; + } + + float RegionAttachment::getR() + { + return _r; + } + + void RegionAttachment::setR(float inValue) + { + _r = inValue; + } + + float RegionAttachment::getG() + { + return _g; + } + + void RegionAttachment::setG(float inValue) + { + _g = inValue; + } + + float RegionAttachment::getB() + { + return _b; + } + + void RegionAttachment::setB(float inValue) + { + _b = inValue; + } + + float RegionAttachment::getA() + { + return _a; + } + + void RegionAttachment::setA(float inValue) + { + _a = inValue; + } + + std::string RegionAttachment::getPath() + { + return _path; + } + + void RegionAttachment::setPath(std::string inValue) + { + _path = inValue; + } + + void* RegionAttachment::getRendererObject() + { + return _rendererObject; + } + + void RegionAttachment::setRendererObject(void* inValue) + { + _rendererObject = inValue; + } + + float RegionAttachment::getRegionOffsetX() + { + return _regionOffsetX; + } + + void RegionAttachment::setRegionOffsetX(float inValue) + { + _regionOffsetX = inValue; + } + + float RegionAttachment::getRegionOffsetY() + { + return _regionOffsetY; + } + + void RegionAttachment::setRegionOffsetY(float inValue) + { + _regionOffsetY = inValue; + } + + float RegionAttachment::getRegionWidth() + { + return _regionWidth; + } + + void RegionAttachment::setRegionWidth(float inValue) + { + _regionWidth = inValue; + } + + float RegionAttachment::getRegionHeight() + { + return _regionHeight; + } + + void RegionAttachment::setRegionHeight(float inValue) + { + _regionHeight = inValue; + } + + float RegionAttachment::getRegionOriginalWidth() + { + return _regionOriginalWidth; + } + + void RegionAttachment::setRegionOriginalWidth(float inValue) + { + _regionOriginalWidth = inValue; + } + + float RegionAttachment::getRegionOriginalHeight() + { + return _regionOriginalHeight; + } + + void RegionAttachment::setRegionOriginalHeight(float inValue) + { + _regionOriginalHeight = inValue; + } + + Vector& RegionAttachment::getOffset() + { + return _offset; + } + + Vector& RegionAttachment::getUVs() + { + return _uvs; + } } diff --git a/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp b/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp index b58b14988..8561c77ee 100644 --- a/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp @@ -40,6 +40,8 @@ namespace Spine { + RTTI_IMPL(RotateTimeline, CurveTimeline); + RotateTimeline::RotateTimeline(int frameCount) : CurveTimeline(frameCount), _boneIndex(0) { _frames.reserve(frameCount << 1); @@ -147,6 +149,4 @@ namespace Spine { _frames = inValue; } - - RTTI_IMPL(RotateTimeline, CurveTimeline); } diff --git a/spine-cpp/spine-cpp/src/spine/Timeline.cpp b/spine-cpp/spine-cpp/src/spine/Timeline.cpp index 64044ca08..6dac2f210 100644 --- a/spine-cpp/spine-cpp/src/spine/Timeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/Timeline.cpp @@ -35,6 +35,8 @@ namespace Spine { + RTTI_IMPL_NOPARENT(Timeline); + Timeline::Timeline() { // Empty @@ -44,6 +46,4 @@ namespace Spine { // Empty } - - RTTI_IMPL_NOPARENT(Timeline); } diff --git a/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp b/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp index a1b5865f2..6ff042820 100644 --- a/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp +++ b/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp @@ -39,6 +39,8 @@ namespace Spine { + RTTI_IMPL(TransformConstraint, Constraint); + TransformConstraint::TransformConstraint(TransformConstraintData& data, Skeleton& skeleton) : Constraint(), _data(data), _target(skeleton.findBone(data.getTarget()->getName())), @@ -445,6 +447,4 @@ namespace Spine bone.updateWorldTransform(x, y, rotation, scaleX, scaleY, bone._ashearX, shearY); } } - - RTTI_IMPL(TransformConstraint, Constraint); } diff --git a/spine-cpp/spine-cpp/src/spine/Updatable.cpp b/spine-cpp/spine-cpp/src/spine/Updatable.cpp index 810c959a8..598955a9a 100644 --- a/spine-cpp/spine-cpp/src/spine/Updatable.cpp +++ b/spine-cpp/spine-cpp/src/spine/Updatable.cpp @@ -32,6 +32,8 @@ namespace Spine { + RTTI_IMPL_NOPARENT(Updatable); + Updatable::Updatable() { // Empty @@ -41,6 +43,4 @@ namespace Spine { // Empty } - - RTTI_IMPL_NOPARENT(Updatable); } diff --git a/spine-cpp/spine-cpp/src/spine/VertexAttachment.cpp b/spine-cpp/spine-cpp/src/spine/VertexAttachment.cpp index a101b5fa4..36410d0d4 100644 --- a/spine-cpp/spine-cpp/src/spine/VertexAttachment.cpp +++ b/spine-cpp/spine-cpp/src/spine/VertexAttachment.cpp @@ -37,7 +37,9 @@ namespace Spine { - VertexAttachment::VertexAttachment(std::string name) : Attachment(name), _id(getNextID()), _worldVerticesLength(0) + RTTI_IMPL(VertexAttachment, Attachment); + + VertexAttachment::VertexAttachment(std::string name) : Attachment(name), _worldVerticesLength(0), _id(getNextID()) { // Empty } @@ -174,6 +176,4 @@ namespace Spine return (nextID++ & 65535) << 11; } - - RTTI_IMPL(VertexAttachment, Attachment); } From d80a00ead6abbd4b6f0e2105b3d90fdde58d26a1 Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Sun, 12 Nov 2017 17:27:09 -0500 Subject: [PATCH 30/83] wip --- spine-cpp/spine-cpp/include/spine/Animation.h | 2 + .../include/spine/AnimationStateData.h | 93 +++++ .../include/spine/AtlasAttachmentLoader.h | 132 +++++++ .../include/spine/AttachmentLoader.h | 70 ++++ .../include/spine/AttachmentTimeline.h | 122 +++++++ .../spine-cpp/include/spine/AttachmentType.h | 48 +++ spine-cpp/spine-cpp/include/spine/Bone.h | 1 + .../include/spine/BoundingBoxAttachment.h | 47 +++ .../include/spine/ClippingAttachment.h | 55 +++ .../spine-cpp/include/spine/ColorTimeline.h | 143 ++++++++ .../spine-cpp/include/spine/DeformTimeline.h | 186 ++++++++++ .../include/spine/DrawOrderTimeline.h | 100 +++++ .../spine-cpp/include/spine/EventTimeline.h | 94 +++++ spine-cpp/spine-cpp/include/spine/HashMap.h | 2 +- .../include/spine/IkConstraintTimeline.h | 115 ++++++ .../include/spine/PathConstraintMixTimeline.h | 114 ++++++ .../spine/PathConstraintPositionTimeline.h | 102 ++++++ .../spine/PathConstraintSpacingTimeline.h | 87 +++++ .../spine-cpp/include/spine/PointAttachment.h | 71 ++++ .../spine-cpp/include/spine/ScaleTimeline.h | 111 ++++++ .../spine-cpp/include/spine/ShearTimeline.h | 94 +++++ spine-cpp/spine-cpp/include/spine/Skin.h | 14 +- .../spine/TransformConstraintTimeline.h | 131 +++++++ .../include/spine/TranslateTimeline.h | 129 +++++++ .../spine-cpp/include/spine/Triangulator.h | 342 ++++++++++++++++++ .../include/spine/TwoColorTimeline.h | 183 ++++++++++ .../src/spine/AnimationStateData.cpp | 119 ++++++ .../src/spine/AtlasAttachmentLoader.cpp | 36 ++ .../spine-cpp/src/spine/AttachmentLoader.cpp | 36 ++ .../src/spine/AttachmentTimeline.cpp | 42 +++ .../src/spine/BoundingBoxAttachment.cpp | 41 +++ .../src/spine/ClippingAttachment.cpp | 53 +++ .../spine-cpp/src/spine/ColorTimeline.cpp | 36 ++ .../spine-cpp/src/spine/DeformTimeline.cpp | 36 ++ .../spine-cpp/src/spine/DrawOrderTimeline.cpp | 36 ++ .../spine-cpp/src/spine/EventTimeline.cpp | 36 ++ .../src/spine/IkConstraintTimeline.cpp | 36 ++ .../src/spine/PathConstraintMixTimeline.cpp | 36 ++ .../spine/PathConstraintPositionTimeline.cpp | 36 ++ .../spine/PathConstraintSpacingTimeline.cpp | 36 ++ .../spine-cpp/src/spine/PointAttachment.cpp | 90 +++++ .../spine-cpp/src/spine/RotateTimeline.cpp | 1 - .../spine-cpp/src/spine/ScaleTimeline.cpp | 36 ++ .../spine-cpp/src/spine/ShearTimeline.cpp | 36 ++ spine-cpp/spine-cpp/src/spine/Skin.cpp | 7 + .../src/spine/TransformConstraintTimeline.cpp | 37 ++ .../spine-cpp/src/spine/TranslateTimeline.cpp | 36 ++ .../spine-cpp/src/spine/Triangulator.cpp | 34 ++ .../spine-cpp/src/spine/TwoColorTimeline.cpp | 36 ++ 49 files changed, 3501 insertions(+), 15 deletions(-) create mode 100644 spine-cpp/spine-cpp/include/spine/AnimationStateData.h create mode 100644 spine-cpp/spine-cpp/include/spine/AtlasAttachmentLoader.h create mode 100644 spine-cpp/spine-cpp/include/spine/AttachmentLoader.h create mode 100644 spine-cpp/spine-cpp/include/spine/AttachmentTimeline.h create mode 100644 spine-cpp/spine-cpp/include/spine/AttachmentType.h create mode 100644 spine-cpp/spine-cpp/include/spine/BoundingBoxAttachment.h create mode 100644 spine-cpp/spine-cpp/include/spine/ClippingAttachment.h create mode 100644 spine-cpp/spine-cpp/include/spine/ColorTimeline.h create mode 100644 spine-cpp/spine-cpp/include/spine/DeformTimeline.h create mode 100644 spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h create mode 100644 spine-cpp/spine-cpp/include/spine/EventTimeline.h create mode 100644 spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h create mode 100644 spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h create mode 100644 spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h create mode 100644 spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h create mode 100644 spine-cpp/spine-cpp/include/spine/PointAttachment.h create mode 100644 spine-cpp/spine-cpp/include/spine/ScaleTimeline.h create mode 100644 spine-cpp/spine-cpp/include/spine/ShearTimeline.h create mode 100644 spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h create mode 100644 spine-cpp/spine-cpp/include/spine/TranslateTimeline.h create mode 100644 spine-cpp/spine-cpp/include/spine/Triangulator.h create mode 100644 spine-cpp/spine-cpp/include/spine/TwoColorTimeline.h create mode 100644 spine-cpp/spine-cpp/src/spine/AnimationStateData.cpp create mode 100644 spine-cpp/spine-cpp/src/spine/AtlasAttachmentLoader.cpp create mode 100644 spine-cpp/spine-cpp/src/spine/AttachmentLoader.cpp create mode 100644 spine-cpp/spine-cpp/src/spine/AttachmentTimeline.cpp create mode 100644 spine-cpp/spine-cpp/src/spine/BoundingBoxAttachment.cpp create mode 100644 spine-cpp/spine-cpp/src/spine/ClippingAttachment.cpp create mode 100644 spine-cpp/spine-cpp/src/spine/ColorTimeline.cpp create mode 100644 spine-cpp/spine-cpp/src/spine/DeformTimeline.cpp create mode 100644 spine-cpp/spine-cpp/src/spine/DrawOrderTimeline.cpp create mode 100644 spine-cpp/spine-cpp/src/spine/EventTimeline.cpp create mode 100644 spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp create mode 100644 spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp create mode 100644 spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp create mode 100644 spine-cpp/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp create mode 100644 spine-cpp/spine-cpp/src/spine/PointAttachment.cpp create mode 100644 spine-cpp/spine-cpp/src/spine/ScaleTimeline.cpp create mode 100644 spine-cpp/spine-cpp/src/spine/ShearTimeline.cpp create mode 100644 spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp create mode 100644 spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp create mode 100644 spine-cpp/spine-cpp/src/spine/Triangulator.cpp create mode 100644 spine-cpp/spine-cpp/src/spine/TwoColorTimeline.cpp diff --git a/spine-cpp/spine-cpp/include/spine/Animation.h b/spine-cpp/spine-cpp/include/spine/Animation.h index 581d8cc34..39196235c 100644 --- a/spine-cpp/spine-cpp/include/spine/Animation.h +++ b/spine-cpp/spine-cpp/include/spine/Animation.h @@ -46,6 +46,8 @@ namespace Spine class Animation { friend class RotateTimeline; + friend class TranslateTimeline; + friend class AnimationStateData; public: Animation(std::string name, Vector& timelines, float duration); diff --git a/spine-cpp/spine-cpp/include/spine/AnimationStateData.h b/spine-cpp/spine-cpp/include/spine/AnimationStateData.h new file mode 100644 index 000000000..961ed7617 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/AnimationStateData.h @@ -0,0 +1,93 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_AnimationStateData_h +#define Spine_AnimationStateData_h + +#include + +#include +#include + +namespace Spine +{ + class SkeletonData; + class Animation; + + /// Stores mix (crossfade) durations to be applied when AnimationState animations are changed. + class AnimationStateData + { + public: + /// The SkeletonData to look up animations when they are specified by name. + SkeletonData& getSkeletonData(); + + /// The mix duration to use when no mix duration has been specifically defined between two animations. + float getDefaultMix(); + void setDefaultMix(float inValue); + + AnimationStateData(SkeletonData& skeletonData); + + /// Sets a mix duration by animation names. + void setMix(std::string fromName, std::string toName, float duration); + + /// Sets a mix duration when changing from the specified animation to the other. + /// See TrackEntry.MixDuration. + void setMix(Animation& from, Animation& to, float duration); + + /// + /// The mix duration to use when changing from the specified animation to the other, + /// or the DefaultMix if no mix duration has been set. + /// + float getMix(Animation& from, Animation& to); + + private: + class AnimationPair + { + public: + Animation& _a1; + Animation& _a2; + + AnimationPair(Animation& a1, Animation& a2); + + bool operator==(const AnimationPair &other) const; + }; + + struct HashAnimationPair + { + std::size_t operator()(const Spine::AnimationStateData::AnimationPair& val) const; + }; + + SkeletonData& _skeletonData; + float _defaultMix; + HashMap _animationToMixTime; + }; +} + +#endif /* Spine_AnimationStateData_h */ diff --git a/spine-cpp/spine-cpp/include/spine/AtlasAttachmentLoader.h b/spine-cpp/spine-cpp/include/spine/AtlasAttachmentLoader.h new file mode 100644 index 000000000..6c00de203 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/AtlasAttachmentLoader.h @@ -0,0 +1,132 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_AtlasAttachmentLoader_h +#define Spine_AtlasAttachmentLoader_h + +#include + +namespace Spine +{ + /// + /// An AttachmentLoader that configures attachments using texture regions from an Atlas. + /// See http://esotericsoftware.com/spine-loading-skeleton-data#JSON-and-binary-data about Loading Skeleton Data in the Spine Runtimes Guide. + /// + class AtlasAttachmentLoader : public AttachmentLoader + { + RTTI_DECL; + + public: + private: + Vector atlasArray; + + public AtlasAttachmentLoader (params Atlas[] atlasArray) + { + if (atlasArray == NULL) throw new ArgumentNullException("atlas array cannot be NULL."); + _atlasArray = atlasArray; + } + + public RegionAttachment newRegionAttachment(Skin skin, std::string name, std::string path) + { + AtlasRegion* region = findRegion(path); + if (region == NULL) throw new ArgumentException(std::string.Format("Region not found in atlas: {0} (region attachment: {1})", path, name)); + RegionAttachment attachment = new RegionAttachment(name); + attachment.RendererObject = region; + attachment.SetUVs(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 attachment; + } + + public MeshAttachment newMeshAttachment(Skin skin, std::string name, std::string path) + { + AtlasRegion region = findRegion(path); + if (region == NULL) throw new ArgumentException(std::string.Format("Region not found in atlas: {0} (region attachment: {1})", path, name)); + + MeshAttachment attachment = new MeshAttachment(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.regionOffsetX = region.offsetX; + attachment.regionOffsetY = region.offsetY; + attachment.regionWidth = region.width; + attachment.regionHeight = region.height; + attachment.regionOriginalWidth = region.originalWidth; + attachment.regionOriginalHeight = region.originalHeight; + + return attachment; + } + + public BoundingBoxAttachment NewBoundingBoxAttachment (Skin skin, std::string name) + { + return new BoundingBoxAttachment(name); + } + + public PathAttachment newPathAttachment(Skin skin, std::string name) + { + return new PathAttachment(name); + } + + public PointAttachment newPointAttachment(Skin skin, std::string name) + { + return new PointAttachment(name); + } + + public ClippingAttachment newClippingAttachment(Skin skin, std::string name) + { + return new ClippingAttachment(name); + } + + public AtlasRegion findRegion (std::string name) + { + AtlasRegion region; + + for (int i = 0; i < atlasArray.Length; i++) + { + region = atlasArray[i].findRegion(name); + if (region != NULL) + { + return region; + } + } + + return NULL; + } + } +} + +#endif /* Spine_AtlasAttachmentLoader_h */ diff --git a/spine-cpp/spine-cpp/include/spine/AttachmentLoader.h b/spine-cpp/spine-cpp/include/spine/AttachmentLoader.h new file mode 100644 index 000000000..aa9373314 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/AttachmentLoader.h @@ -0,0 +1,70 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_AttachmentLoader_h +#define Spine_AttachmentLoader_h + +#include + +#include + +namespace Spine +{ + class RegionAttachment; + class MeshAttachment; + class BoundingBoxAttachment; + class PathAttachment; + class PointAttachment; + class ClippingAttachment; + class Skin; + + class AttachmentLoader + { + RTTI_DECL; + + /// @return May be NULL to not load any attachment. + virtual RegionAttachment* newRegionAttachment(Skin& skin, std::string name, std::string path) = 0; + + /// @return May be NULL to not load any attachment. + virtual MeshAttachment* newMeshAttachment(Skin& skin, std::string name, std::string path) = 0; + + /// @return May be NULL to not load any attachment. + virtual BoundingBoxAttachment* NewBoundingBoxAttachment(Skin& skin, std::string name) = 0; + + /// @return May be NULL to not load any attachment + virtual PathAttachment* newPathAttachment(Skin& skin, std::string name) = 0; + + virtual PointAttachment* newPointAttachment(Skin& skin, std::string name) = 0; + + virtual ClippingAttachment* newClippingAttachment(Skin& skin, std::string name) = 0; + } +} + +#endif /* Spine_AttachmentLoader_h */ diff --git a/spine-cpp/spine-cpp/include/spine/AttachmentTimeline.h b/spine-cpp/spine-cpp/include/spine/AttachmentTimeline.h new file mode 100644 index 000000000..8f026e5cd --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/AttachmentTimeline.h @@ -0,0 +1,122 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_AttachmentTimeline_h +#define Spine_AttachmentTimeline_h + +#include + +#include +#include +#include + +#include + +namespace Spine +{ + class Skeleton; + class Event; + + class AttachmentTimeline : public Timeline + { + RTTI_DECL; + + public: + AttachmentTimeline(int frameCount) + { + _frames.reserve(frameCount); + _attachmentNames.reserve(frameCount); + } + + virtual int getPropertyId() + { + return ((int)TimelineType_Attachment << 24) + slotIndex; + } + + /// Sets the time and value of the specified keyframe. + void setFrame(int frameIndex, float time, std::string attachmentName) + { + frames[frameIndex] = time; + attachmentNames[frameIndex] = attachmentName; + } + + void apply(Skeleton& skeleton, float lastTime, float time, Vector firedEvents, float alpha, MixPose pose, MixDirection direction) + { + std::string attachmentName; + Slot slot = skeleton.slots.Items[slotIndex]; + if (direction == MixDirection_Out && pose == MixPose_Setup) + { + attachmentName = slot.data.attachmentName; + slot.Attachment = attachmentName == NULL ? NULL : skeleton.getAttachment(slotIndex, attachmentName); + return; + } + + float[] frames = _frames; + if (time < frames[0]) + { + // Time is before first frame. + if (pose == MixPose_Setup) + { + attachmentName = slot.data.attachmentName; + slot.Attachment = attachmentName == NULL ? NULL : skeleton.getAttachment(slotIndex, attachmentName); + } + return; + } + + int frameIndex; + if (time >= frames[frames.Length - 1]) // Time is after last frame. + { + frameIndex = frames.Length - 1; + } + else + { + frameIndex = Animation::binarySearch(frames, time, 1) - 1; + } + + attachmentName = attachmentNames[frameIndex]; + slot.Attachment = attachmentName == NULL ? NULL : skeleton.getAttachment(slotIndex, attachmentName); + } + + int getSlotIndex() { return _slotIndex; } + void setSlotIndex(int inValue) { _slotIndex = inValue; } + Vector& getFrames() { return _frames; } + void setFrames(Vector& inValue) { _frames = inValue; } // time, ... + Vector getAttachmentNames() { return _attachmentNames; } + set { attachmentNames = inValue; } + int getFrameCount() { return frames.Length; } + + private: + int _slotIndex; + Vector _frames; + Vector _attachmentNames; + } +} + +#endif /* Spine_AttachmentTimeline_h */ diff --git a/spine-cpp/spine-cpp/include/spine/AttachmentType.h b/spine-cpp/spine-cpp/include/spine/AttachmentType.h new file mode 100644 index 000000000..3799207cd --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/AttachmentType.h @@ -0,0 +1,48 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_AttachmentType_h +#define Spine_AttachmentType_h + +namespace Spine +{ + enum AttachmentType + { + AttachmentType_Region, + AttachmentType_Boundingbox, + AttachmentType_Mesh, + AttachmentType_Linkedmesh, + AttachmentType_Path, + AttachmentType_Point, + AttachmentType_Clipping + }; +} + +#endif /* Spine_AttachmentType_h */ diff --git a/spine-cpp/spine-cpp/include/spine/Bone.h b/spine-cpp/spine-cpp/include/spine/Bone.h index ac20652c0..9900324be 100644 --- a/spine-cpp/spine-cpp/include/spine/Bone.h +++ b/spine-cpp/spine-cpp/include/spine/Bone.h @@ -56,6 +56,7 @@ namespace Spine friend class PathConstraint; friend class Skeleton; friend class RegionAttachment; + friend class PointAttachment; public: static void setYDown(bool inValue); diff --git a/spine-cpp/spine-cpp/include/spine/BoundingBoxAttachment.h b/spine-cpp/spine-cpp/include/spine/BoundingBoxAttachment.h new file mode 100644 index 000000000..996af9f94 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/BoundingBoxAttachment.h @@ -0,0 +1,47 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_BoundingBoxAttachment_h +#define Spine_BoundingBoxAttachment_h + +#include + +namespace Spine +{ + /// Attachment that has a polygon for bounds checking. + class BoundingBoxAttachment : public VertexAttachment + { + RTTI_DECL; + + BoundingBoxAttachment(std::string name); + }; +} + +#endif /* Spine_BoundingBoxAttachment_h */ diff --git a/spine-cpp/spine-cpp/include/spine/ClippingAttachment.h b/spine-cpp/spine-cpp/include/spine/ClippingAttachment.h new file mode 100644 index 000000000..bd9c7ebf2 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/ClippingAttachment.h @@ -0,0 +1,55 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_ClippingAttachment_h +#define Spine_ClippingAttachment_h + +#include + +namespace Spine +{ + class SlotData; + + class ClippingAttachment : public VertexAttachment + { + RTTI_DECL; + + public: + ClippingAttachment(std::string name); + + SlotData* getEndSlot(); + void setEndSlot(SlotData* inValue); + + private: + SlotData* _endSlot; + }; +} + +#endif /* Spine_ClippingAttachment_h */ diff --git a/spine-cpp/spine-cpp/include/spine/ColorTimeline.h b/spine-cpp/spine-cpp/include/spine/ColorTimeline.h new file mode 100644 index 000000000..e48bb81c4 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/ColorTimeline.h @@ -0,0 +1,143 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_ColorTimeline_h +#define Spine_ColorTimeline_h + +#include + +namespace Spine +{ + class ColorTimeline : public CurveTimeline + { + RTTI_DECL; + + public const int ENTRIES = 5; + protected const int PREV_TIME = -5, PREV_R = -4, PREV_G = -3, PREV_B = -2, PREV_A = -1; + protected const int R = 1, G = 2, B = 3, A = 4; + + internal int slotIndex; + internal float[] frames; + + public int SlotIndex { return slotIndex; } set { slotIndex = inValue; } + public float[] Frames { return frames; } set { frames = inValue; } // time, r, g, b, a, ... + + override public int PropertyId { + get { return ((int)TimelineType.Color << 24) + slotIndex; } + } + + public ColorTimeline (int frameCount) + : base(frameCount) { + frames = new float[frameCount * ENTRIES]; + } + + /// Sets the time and value of the specified keyframe. + public void SetFrame (int frameIndex, float time, float r, float g, float b, float a) { + frameIndex *= ENTRIES; + frames[frameIndex] = time; + frames[frameIndex + R] = r; + frames[frameIndex + G] = g; + frames[frameIndex + B] = b; + frames[frameIndex + A] = a; + } + + override public void Apply (Skeleton skeleton, float lastTime, float time, Vector firedEvents, float alpha, MixPose pose, MixDirection direction) { + Slot slot = skeleton.slots.Items[slotIndex]; + float[] frames = _frames; + if (time < frames[0]) { + var slotData = slot.data; + switch (pose) { + case MixPose_Setup: + slot.r = slotData.r; + slot.g = slotData.g; + slot.b = slotData.b; + slot.a = slotData.a; + return; + case MixPose_Current: + slot.r += (slot.r - slotData.r) * alpha; + slot.g += (slot.g - slotData.g) * alpha; + slot.b += (slot.b - slotData.b) * alpha; + slot.a += (slot.a - slotData.a) * alpha; + return; + } + return; + } + + float r, g, b, a; + if (time >= frames[frames.Length - ENTRIES]) { // Time is after last frame. + int i = frames.Length; + r = frames[i + PREV_R]; + g = frames[i + PREV_G]; + b = frames[i + PREV_B]; + a = frames[i + PREV_A]; + } else { + // Interpolate between the previous frame and the current frame. + int frame = Animation.BinarySearch(frames, time, ENTRIES); + r = frames[frame + PREV_R]; + g = frames[frame + PREV_G]; + b = frames[frame + PREV_B]; + a = frames[frame + PREV_A]; + float frameTime = frames[frame]; + float percent = GetCurvePercent(frame / ENTRIES - 1, + 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime)); + + r += (frames[frame + R] - r) * percent; + g += (frames[frame + G] - g) * percent; + b += (frames[frame + B] - b) * percent; + a += (frames[frame + A] - a) * percent; + } + if (alpha == 1) { + slot.r = r; + slot.g = g; + slot.b = b; + slot.a = a; + } else { + float br, bg, bb, ba; + if (pose == MixPose_Setup) { + br = slot.data.r; + bg = slot.data.g; + bb = slot.data.b; + ba = slot.data.a; + } else { + br = slot.r; + bg = slot.g; + bb = slot.b; + ba = slot.a; + } + slot.r = br + ((r - br) * alpha); + slot.g = bg + ((g - bg) * alpha); + slot.b = bb + ((b - bb) * alpha); + slot.a = ba + ((a - ba) * alpha); + } + } + } +} + +#endif /* Spine_ColorTimeline_h */ diff --git a/spine-cpp/spine-cpp/include/spine/DeformTimeline.h b/spine-cpp/spine-cpp/include/spine/DeformTimeline.h new file mode 100644 index 000000000..bf12cbfe8 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/DeformTimeline.h @@ -0,0 +1,186 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_DeformTimeline_h +#define Spine_DeformTimeline_h + +#include + +namespace Spine +{ + class DeformTimeline : CurveTimeline + { + RTTI_DECL; + + internal int slotIndex; + internal float[] frames; + internal float[][] frameVertices; + internal VertexAttachment attachment; + + public int SlotIndex { return slotIndex; } set { slotIndex = inValue; } + public float[] Frames { return frames; } set { frames = inValue; } // time, ... + public float[][] Vertices { return frameVertices; } set { frameVertices = inValue; } + public VertexAttachment Attachment { return attachment; } set { attachment = inValue; } + + override public int PropertyId { + get { return ((int)TimelineType.Deform << 24) + attachment.id + slotIndex; } + } + + public DeformTimeline (int frameCount) + : base(frameCount) { + frames = new float[frameCount]; + frameVertices = new float[frameCount][]; + } + + /// Sets the time and value of the specified keyframe. + public void SetFrame (int frameIndex, float time, float[] vertices) { + frames[frameIndex] = time; + frameVertices[frameIndex] = vertices; + } + + override public void Apply (Skeleton skeleton, float lastTime, float time, Vector firedEvents, float alpha, MixPose pose, MixDirection direction) { + Slot slot = skeleton.slots.Items[slotIndex]; + VertexAttachment vertexAttachment = slot.attachment as VertexAttachment; + if (vertexAttachment == NULL || !vertexAttachment.ApplyDeform(attachment)) return; + + var verticesArray = slot.attachmentVertices; + if (verticesArray.Count == 0) alpha = 1; + + float[][] frameVertices = _frameVertices; + int vertexCount = frameVertices[0].Length; + float[] frames = _frames; + float[] vertices; + + if (time < frames[0]) { + + switch (pose) { + case MixPose_Setup: + verticesArray.Clear(); + return; + case MixPose_Current: + if (alpha == 1) { + verticesArray.Clear(); + return; + } + + // verticesArray.SetSize(vertexCount) // Ensure size and preemptively set count. + if (verticesArray.Capacity < vertexCount) verticesArray.Capacity = vertexCount; + verticesArray.Count = vertexCount; + vertices = verticesArray.Items; + + if (vertexAttachment.bones == NULL) { + // Unweighted vertex positions. + float[] setupVertices = vertexAttachment.vertices; + for (int i = 0; i < vertexCount; i++) + vertices[i] += (setupVertices[i] - vertices[i]) * alpha; + } else { + // Weighted deform offsets. + alpha = 1 - alpha; + for (int i = 0; i < vertexCount; i++) + vertices[i] *= alpha; + } + return; + default: + return; + } + + } + + // verticesArray.SetSize(vertexCount) // Ensure size and preemptively set count. + if (verticesArray.Capacity < vertexCount) verticesArray.Capacity = vertexCount; + verticesArray.Count = vertexCount; + vertices = verticesArray.Items; + + if (time >= frames[frames.Length - 1]) { // Time is after last frame. + float[] lastVertices = frameVertices[frames.Length - 1]; + if (alpha == 1) { + // Vertex positions or deform offsets, no alpha. + Array.Copy(lastVertices, 0, vertices, 0, vertexCount); + } else if (pose == MixPose_Setup) { + if (vertexAttachment.bones == NULL) { + // Unweighted vertex positions, with alpha. + float[] setupVertices = vertexAttachment.vertices; + for (int i = 0; i < vertexCount; i++) { + float setup = setupVertices[i]; + vertices[i] = setup + (lastVertices[i] - setup) * alpha; + } + } else { + // Weighted deform offsets, with alpha. + for (int i = 0; i < vertexCount; i++) + vertices[i] = lastVertices[i] * alpha; + } + } else { + // Vertex positions or deform offsets, with alpha. + for (int i = 0; i < vertexCount; i++) + vertices[i] += (lastVertices[i] - vertices[i]) * alpha; + } + return; + } + + // Interpolate between the previous frame and the current frame. + int frame = Animation.BinarySearch(frames, time); + float[] prevVertices = frameVertices[frame - 1]; + float[] nextVertices = frameVertices[frame]; + float frameTime = frames[frame]; + float percent = GetCurvePercent(frame - 1, 1 - (time - frameTime) / (frames[frame - 1] - frameTime)); + + if (alpha == 1) { + // Vertex positions or deform offsets, no alpha. + for (int i = 0; i < vertexCount; i++) { + float prev = prevVertices[i]; + vertices[i] = prev + (nextVertices[i] - prev) * percent; + } + } else if (pose == MixPose_Setup) { + if (vertexAttachment.bones == NULL) { + // Unweighted vertex positions, with alpha. + var setupVertices = vertexAttachment.vertices; + for (int i = 0; i < vertexCount; i++) { + float prev = prevVertices[i], setup = setupVertices[i]; + vertices[i] = setup + (prev + (nextVertices[i] - prev) * percent - setup) * alpha; + } + } else { + // Weighted deform offsets, with alpha. + for (int i = 0; i < vertexCount; i++) { + float prev = prevVertices[i]; + vertices[i] = (prev + (nextVertices[i] - prev) * percent) * alpha; + } + } + } else { + // Vertex positions or deform offsets, with alpha. + for (int i = 0; i < vertexCount; i++) { + float prev = prevVertices[i]; + vertices[i] += (prev + (nextVertices[i] - prev) * percent - vertices[i]) * alpha; + } + } + } + } +} + +#endif /* Spine_DeformTimeline_h */ diff --git a/spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h b/spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h new file mode 100644 index 000000000..06e251fe5 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h @@ -0,0 +1,100 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_DrawOrderTimeline_h +#define Spine_DrawOrderTimeline_h + +#include + +namespace Spine +{ + class DrawOrderTimeline : public Timeline + { + RTTI_DECL; + + internal float[] frames; + private int[][] drawOrders; + + public float[] Frames { return frames; } set { frames = inValue; } // time, ... + public int[][] DrawOrders { return drawOrders; } set { drawOrders = inValue; } + public int FrameCount { return frames.Length; } + + public int PropertyId { + get { return ((int)TimelineType.DrawOrder << 24); } + } + + public DrawOrderTimeline (int frameCount) { + frames = new float[frameCount]; + drawOrders = new int[frameCount][]; + } + + /// Sets the time and value of the specified keyframe. + /// May be NULL to use bind pose draw order. + public void SetFrame (int frameIndex, float time, int[] drawOrder) { + frames[frameIndex] = time; + drawOrders[frameIndex] = drawOrder; + } + + public void Apply (Skeleton skeleton, float lastTime, float time, Vector firedEvents, float alpha, MixPose pose, MixDirection direction) { + Vector drawOrder = skeleton.drawOrder; + Vector slots = skeleton.slots; + if (direction == MixDirection_Out && pose == MixPose_Setup) { + Array.Copy(slots.Items, 0, drawOrder.Items, 0, slots.Count); + return; + } + + float[] frames = _frames; + if (time < frames[0]) { + if (pose == MixPose_Setup) Array.Copy(slots.Items, 0, drawOrder.Items, 0, slots.Count); + return; + } + + int frame; + if (time >= frames[frames.Length - 1]) // Time is after last frame. + frame = frames.Length - 1; + else + frame = Animation.BinarySearch(frames, time) - 1; + + int[] drawOrderToSetupIndex = drawOrders[frame]; + if (drawOrderToSetupIndex == NULL) { + drawOrder.Clear(); + for (int i = 0, n = slots.Count; i < n; i++) + drawOrder.Add(slots.Items[i]); + } else { + var drawOrderItems = drawOrder.Items; + var slotsItems = slots.Items; + for (int i = 0, n = drawOrderToSetupIndex.Length; i < n; i++) + drawOrderItems[i] = slotsItems[drawOrderToSetupIndex[i]]; + } + } + }; +} + +#endif /* Spine_DrawOrderTimeline_h */ diff --git a/spine-cpp/spine-cpp/include/spine/EventTimeline.h b/spine-cpp/spine-cpp/include/spine/EventTimeline.h new file mode 100644 index 000000000..23f70cf90 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/EventTimeline.h @@ -0,0 +1,94 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_EventTimeline_h +#define Spine_EventTimeline_h + +#include + +namespace Spine +{ + class EventTimeline : public Timeline + { + RTTI_DECL; + + internal float[] frames; + private Event[] events; + + public float[] Frames { return frames; } set { frames = inValue; } // time, ... + public Event[] Events { return events; } set { events = inValue; } + public int FrameCount { return frames.Length; } + + public int PropertyId { + get { return ((int)TimelineType.Event << 24); } + } + + public EventTimeline (int frameCount) { + frames = new float[frameCount]; + events = new Event[frameCount]; + } + + /// Sets the time and value of the specified keyframe. + public void SetFrame (int frameIndex, Event e) { + frames[frameIndex] = e.Time; + events[frameIndex] = e; + } + + /// Fires events for frames > lastTime and <= time. + public void Apply (Skeleton skeleton, float lastTime, float time, Vector firedEvents, float alpha, MixPose pose, MixDirection direction) { + if (firedEvents == NULL) return; + float[] frames = _frames; + int frameCount = frames.Length; + + if (lastTime > time) { // Fire events after last time for looped animations. + Apply(skeleton, lastTime, int.MaxValue, firedEvents, alpha, pose, direction); + lastTime = -1f; + } else if (lastTime >= frames[frameCount - 1]) // Last time is after last frame. + return; + if (time < frames[0]) return; // Time is before first frame. + + int frame; + if (lastTime < frames[0]) + frame = 0; + else { + frame = Animation.BinarySearch(frames, lastTime); + float frameTime = frames[frame]; + while (frame > 0) { // Fire multiple events with the same frame. + if (frames[frame - 1] != frameTime) break; + frame--; + } + } + for (; frame < frameCount && time >= frames[frame]; frame++) + firedEvents.Add(events[frame]); + } + }; +} + +#endif /* Spine_EventTimeline_h */ diff --git a/spine-cpp/spine-cpp/include/spine/HashMap.h b/spine-cpp/spine-cpp/include/spine/HashMap.h index f146d39b7..ee38a9aee 100755 --- a/spine-cpp/spine-cpp/include/spine/HashMap.h +++ b/spine-cpp/spine-cpp/include/spine/HashMap.h @@ -153,7 +153,7 @@ namespace Spine Entry* entry = new Entry(); entry->_key = key; - entry->_value = value; + entry->_value = inValue; _hashSize++; diff --git a/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h b/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h new file mode 100644 index 000000000..2716c75eb --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h @@ -0,0 +1,115 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_IkConstraintTimeline_h +#define Spine_IkConstraintTimeline_h + +#include + +namespace Spine +{ + class IkConstraintTimeline : public CurveTimeline + { + RTTI_DECL; + + public const int ENTRIES = 3; + private const int PREV_TIME = -3, PREV_MIX = -2, PREV_BEND_DIRECTION = -1; + private const int MIX = 1, BEND_DIRECTION = 2; + + internal int ikConstraintIndex; + internal float[] frames; + + public int IkConstraintIndex { return ikConstraintIndex; } set { ikConstraintIndex = inValue; } + public float[] Frames { return frames; } set { frames = inValue; } // time, mix, bendDirection, ... + + override public int PropertyId { + get { return ((int)TimelineType.IkConstraint << 24) + ikConstraintIndex; } + } + + public IkConstraintTimeline (int frameCount) + : base(frameCount) { + frames = new float[frameCount * ENTRIES]; + } + + /// Sets the time, mix and bend direction of the specified keyframe. + public void SetFrame (int frameIndex, float time, float mix, int bendDirection) { + frameIndex *= ENTRIES; + frames[frameIndex] = time; + frames[frameIndex + MIX] = mix; + frames[frameIndex + BEND_DIRECTION] = bendDirection; + } + + override public void Apply (Skeleton skeleton, float lastTime, float time, Vector firedEvents, float alpha, MixPose pose, MixDirection direction) { + IkConstraint constraint = skeleton.ikConstraints.Items[ikConstraintIndex]; + float[] frames = _frames; + if (time < frames[0]) { + switch (pose) { + case MixPose_Setup: + constraint.mix = constraint.data.mix; + constraint.bendDirection = constraint.data.bendDirection; + return; + case MixPose_Current: + constraint.mix += (constraint.data.mix - constraint.mix) * alpha; + constraint.bendDirection = constraint.data.bendDirection; + return; + } + return; + } + + if (time >= frames[frames.Length - ENTRIES]) { // Time is after last frame. + if (pose == MixPose_Setup) { + constraint.mix = constraint.data.mix + (frames[frames.Length + PREV_MIX] - constraint.data.mix) * alpha; + constraint.bendDirection = direction == MixDirection_Out ? constraint.data.bendDirection + : (int)frames[frames.Length + PREV_BEND_DIRECTION]; + } else { + constraint.mix += (frames[frames.Length + PREV_MIX] - constraint.mix) * alpha; + if (direction == MixDirection_In) constraint.bendDirection = (int)frames[frames.Length + PREV_BEND_DIRECTION]; + } + return; + } + + // Interpolate between the previous frame and the current frame. + int frame = Animation.BinarySearch(frames, time, ENTRIES); + float mix = frames[frame + PREV_MIX]; + float frameTime = frames[frame]; + float percent = GetCurvePercent(frame / ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime)); + + if (pose == MixPose_Setup) { + constraint.mix = constraint.data.mix + (mix + (frames[frame + MIX] - mix) * percent - constraint.data.mix) * alpha; + constraint.bendDirection = direction == MixDirection_Out ? constraint.data.bendDirection : (int)frames[frame + PREV_BEND_DIRECTION]; + } else { + constraint.mix += (mix + (frames[frame + MIX] - mix) * percent - constraint.mix) * alpha; + if (direction == MixDirection_In) constraint.bendDirection = (int)frames[frame + PREV_BEND_DIRECTION]; + } + } + }; +} + +#endif /* Spine_IkConstraintTimeline_h */ diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h b/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h new file mode 100644 index 000000000..ca6d8960d --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h @@ -0,0 +1,114 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_PathConstraintMixTimeline_h +#define Spine_PathConstraintMixTimeline_h + +#include + +namespace Spine +{ + class PathConstraintMixTimeline : public CurveTimeline + { + RTTI_DECL; + + public const int ENTRIES = 3; + private const int PREV_TIME = -3, PREV_ROTATE = -2, PREV_TRANSLATE = -1; + private const int ROTATE = 1, TRANSLATE = 2; + + internal int pathConstraintIndex; + internal float[] frames; + + public int PathConstraintIndex { return pathConstraintIndex; } set { pathConstraintIndex = inValue; } + public float[] Frames { return frames; } set { frames = inValue; } // time, rotate mix, translate mix, ... + + override public int PropertyId { + get { return ((int)TimelineType.PathConstraintMix << 24) + pathConstraintIndex; } + } + + public PathConstraintMixTimeline (int frameCount) + : base(frameCount) { + frames = new float[frameCount * ENTRIES]; + } + + /// Sets the time and mixes of the specified keyframe. + public void SetFrame (int frameIndex, float time, float rotateMix, float translateMix) { + frameIndex *= ENTRIES; + frames[frameIndex] = time; + frames[frameIndex + ROTATE] = rotateMix; + frames[frameIndex + TRANSLATE] = translateMix; + } + + override public void Apply (Skeleton skeleton, float lastTime, float time, Vector firedEvents, float alpha, MixPose pose, MixDirection direction) { + PathConstraint constraint = skeleton.pathConstraints.Items[pathConstraintIndex]; + float[] frames = _frames; + if (time < frames[0]) { + switch (pose) { + case MixPose_Setup: + constraint.rotateMix = constraint.data.rotateMix; + constraint.translateMix = constraint.data.translateMix; + return; + case MixPose_Current: + constraint.rotateMix += (constraint.data.rotateMix - constraint.rotateMix) * alpha; + constraint.translateMix += (constraint.data.translateMix - constraint.translateMix) * alpha; + return; + } + return; + } + + float rotate, translate; + if (time >= frames[frames.Length - ENTRIES]) { // Time is after last frame. + rotate = frames[frames.Length + PREV_ROTATE]; + translate = frames[frames.Length + PREV_TRANSLATE]; + } else { + // Interpolate between the previous frame and the current frame. + int frame = Animation.BinarySearch(frames, time, ENTRIES); + rotate = frames[frame + PREV_ROTATE]; + translate = frames[frame + PREV_TRANSLATE]; + float frameTime = frames[frame]; + float percent = GetCurvePercent(frame / ENTRIES - 1, + 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime)); + + rotate += (frames[frame + ROTATE] - rotate) * percent; + translate += (frames[frame + TRANSLATE] - translate) * percent; + } + + if (pose == MixPose_Setup) { + constraint.rotateMix = constraint.data.rotateMix + (rotate - constraint.data.rotateMix) * alpha; + constraint.translateMix = constraint.data.translateMix + (translate - constraint.data.translateMix) * alpha; + } else { + constraint.rotateMix += (rotate - constraint.rotateMix) * alpha; + constraint.translateMix += (translate - constraint.translateMix) * alpha; + } + } + } +} + +#endif /* Spine_PathConstraintMixTimeline_h */ diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h b/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h new file mode 100644 index 000000000..8ac0319bd --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h @@ -0,0 +1,102 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_PathConstraintPositionTimeline_h +#define Spine_PathConstraintPositionTimeline_h + +#include + +namespace Spine +{ + class PathConstraintPositionTimeline : public CurveTimeline + { + public const int ENTRIES = 2; + protected const int PREV_TIME = -2, PREV_VALUE = -1; + protected const int VALUE = 1; + + internal int pathConstraintIndex; + internal float[] frames; + + override public int PropertyId { + get { return ((int)TimelineType.PathConstraintPosition << 24) + pathConstraintIndex; } + } + + public PathConstraintPositionTimeline (int frameCount) + : base(frameCount) { + frames = new float[frameCount * ENTRIES]; + } + + public int PathConstraintIndex { return pathConstraintIndex; } set { pathConstraintIndex = inValue; } + public float[] Frames { return frames; } set { frames = inValue; } // time, position, ... + + /// Sets the time and value of the specified keyframe. + public void SetFrame (int frameIndex, float time, float value) { + frameIndex *= ENTRIES; + frames[frameIndex] = time; + frames[frameIndex + VALUE] = inValue; + } + + override public void Apply (Skeleton skeleton, float lastTime, float time, Vector firedEvents, float alpha, MixPose pose, MixDirection direction) { + PathConstraint constraint = skeleton.pathConstraints.Items[pathConstraintIndex]; + float[] frames = _frames; + if (time < frames[0]) { + switch (pose) { + case MixPose_Setup: + constraint.position = constraint.data.position; + return; + case MixPose_Current: + constraint.position += (constraint.data.position - constraint.position) * alpha; + return; + } + return; + } + + float position; + if (time >= frames[frames.Length - ENTRIES]) // Time is after last frame. + position = frames[frames.Length + PREV_VALUE]; + else { + // Interpolate between the previous frame and the current frame. + int frame = Animation.BinarySearch(frames, time, ENTRIES); + position = frames[frame + PREV_VALUE]; + float frameTime = frames[frame]; + float percent = GetCurvePercent(frame / ENTRIES - 1, + 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime)); + + position += (frames[frame + VALUE] - position) * percent; + } + if (pose == MixPose_Setup) + constraint.position = constraint.data.position + (position - constraint.data.position) * alpha; + else + constraint.position += (position - constraint.position) * alpha; + } + } +} + +#endif /* Spine_PathConstraintPositionTimeline_h */ diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h b/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h new file mode 100644 index 000000000..594008426 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h @@ -0,0 +1,87 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_PathConstraintSpacingTimeline_h +#define Spine_PathConstraintSpacingTimeline_h + +#include + +namespace Spine +{ + class PathConstraintSpacingTimeline : public PathConstraintPositionTimeline + { + RTTI_DECL; + + override public int PropertyId { + get { return ((int)TimelineType.PathConstraintSpacing << 24) + pathConstraintIndex; } + } + + public PathConstraintSpacingTimeline (int frameCount) + : base(frameCount) { + } + + override public void Apply (Skeleton skeleton, float lastTime, float time, Vector firedEvents, float alpha, MixPose pose, MixDirection direction) { + PathConstraint constraint = skeleton.pathConstraints.Items[pathConstraintIndex]; + float[] frames = _frames; + if (time < frames[0]) { + switch (pose) { + case MixPose_Setup: + constraint.spacing = constraint.data.spacing; + return; + case MixPose_Current: + constraint.spacing += (constraint.data.spacing - constraint.spacing) * alpha; + return; + } + return; + } + + float spacing; + if (time >= frames[frames.Length - ENTRIES]) // Time is after last frame. + spacing = frames[frames.Length + PREV_VALUE]; + else { + // Interpolate between the previous frame and the current frame. + int frame = Animation.BinarySearch(frames, time, ENTRIES); + spacing = frames[frame + PREV_VALUE]; + float frameTime = frames[frame]; + float percent = GetCurvePercent(frame / ENTRIES - 1, + 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime)); + + spacing += (frames[frame + VALUE] - spacing) * percent; + } + + if (pose == MixPose_Setup) + constraint.spacing = constraint.data.spacing + (spacing - constraint.data.spacing) * alpha; + else + constraint.spacing += (spacing - constraint.spacing) * alpha; + } + } +} + +#endif /* Spine_PathConstraintSpacingTimeline_h */ diff --git a/spine-cpp/spine-cpp/include/spine/PointAttachment.h b/spine-cpp/spine-cpp/include/spine/PointAttachment.h new file mode 100644 index 000000000..c51c130d9 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/PointAttachment.h @@ -0,0 +1,71 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_PointAttachment_h +#define Spine_PointAttachment_h + +#include + +namespace Spine +{ + class Bone; + + /// + /// An attachment which is a single point and a rotation. This can be used to spawn projectiles, particles, etc. A bone can be + /// used in similar ways, but a PointAttachment is slightly less expensive to compute and can be hidden, shown, and placed in a + /// skin. + /// + /// See http://esotericsoftware.com/spine-point-attachments for Point Attachments in the Spine User Guide. + /// + class PointAttachment : public Attachment + { + RTTI_DECL; + + PointAttachment(std::string name); + + void computeWorldPosition(Bone& bone, float& ox, float& oy); + + float computeWorldRotation(Bone& bone); + + float getX(); + void setX(float inValue); + + float getY(); + void setY(float inValue); + + float getRotation(); + void setRotation(float inValue); + + private: + float _x, _y, _rotation; + } +} + +#endif /* Spine_PointAttachment_h */ diff --git a/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h b/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h new file mode 100644 index 000000000..32b92f499 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h @@ -0,0 +1,111 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_ScaleTimeline_h +#define Spine_ScaleTimeline_h + +#include + +namespace Spine +{ + class ScaleTimeline : public TranslateTimeline + { + RTTI_DECL; + + override public int PropertyId { + get { return ((int)TimelineType.Scale << 24) + boneIndex; } + } + + public ScaleTimeline (int frameCount) + : base(frameCount) { + } + + override public void Apply (Skeleton skeleton, float lastTime, float time, Vector firedEvents, float alpha, MixPose pose, MixDirection direction) { + Bone bone = skeleton.bones.Items[boneIndex]; + + float[] frames = _frames; + if (time < frames[0]) { + switch (pose) { + case MixPose_Setup: + bone.scaleX = bone.data.scaleX; + bone.scaleY = bone.data.scaleY; + return; + case MixPose_Current: + bone.scaleX += (bone.data.scaleX - bone.scaleX) * alpha; + bone.scaleY += (bone.data.scaleY - bone.scaleY) * alpha; + return; + } + return; + } + + float x, y; + if (time >= frames[frames.Length - ENTRIES]) { // Time is after last frame. + x = frames[frames.Length + PREV_X] * bone.data.scaleX; + y = frames[frames.Length + PREV_Y] * bone.data.scaleY; + } else { + // Interpolate between the previous frame and the current frame. + int frame = Animation.BinarySearch(frames, time, ENTRIES); + x = frames[frame + PREV_X]; + y = frames[frame + PREV_Y]; + float frameTime = frames[frame]; + float percent = GetCurvePercent(frame / ENTRIES - 1, + 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime)); + + x = (x + (frames[frame + X] - x) * percent) * bone.data.scaleX; + y = (y + (frames[frame + Y] - y) * percent) * bone.data.scaleY; + } + if (alpha == 1) { + bone.scaleX = x; + bone.scaleY = y; + } else { + float bx, by; + if (pose == MixPose_Setup) { + bx = bone.data.scaleX; + by = bone.data.scaleY; + } else { + bx = bone.scaleX; + by = bone.scaleY; + } + // Mixing out uses sign of setup or current pose, else use sign of key. + if (direction == MixDirection_Out) { + x = (x >= 0 ? x : -x) * (bx >= 0 ? 1 : -1); + y = (y >= 0 ? y : -y) * (by >= 0 ? 1 : -1); + } else { + bx = (bx >= 0 ? bx : -bx) * (x >= 0 ? 1 : -1); + by = (by >= 0 ? by : -by) * (y >= 0 ? 1 : -1); + } + bone.scaleX = bx + (x - bx) * alpha; + bone.scaleY = by + (y - by) * alpha; + } + } + } +} + +#endif /* Spine_ScaleTimeline_h */ diff --git a/spine-cpp/spine-cpp/include/spine/ShearTimeline.h b/spine-cpp/spine-cpp/include/spine/ShearTimeline.h new file mode 100644 index 000000000..39087ff9d --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/ShearTimeline.h @@ -0,0 +1,94 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_ShearTimeline_h +#define Spine_ShearTimeline_h + +#include + +namespace Spine +{ + class ShearTimeline : public TranslateTimeline + { + RTTI_DECL; + + override public int PropertyId { + get { return ((int)TimelineType.Shear << 24) + boneIndex; } + } + + public ShearTimeline (int frameCount) + : base(frameCount) { + } + + override public void Apply (Skeleton skeleton, float lastTime, float time, Vector firedEvents, float alpha, MixPose pose, MixDirection direction) { + Bone bone = skeleton.bones.Items[boneIndex]; + float[] frames = _frames; + if (time < frames[0]) { + switch (pose) { + case MixPose_Setup: + bone.shearX = bone.data.shearX; + bone.shearY = bone.data.shearY; + return; + case MixPose_Current: + bone.shearX += (bone.data.shearX - bone.shearX) * alpha; + bone.shearY += (bone.data.shearY - bone.shearY) * alpha; + return; + } + return; + } + + float x, y; + if (time >= frames[frames.Length - ENTRIES]) { // Time is after last frame. + x = frames[frames.Length + PREV_X]; + y = frames[frames.Length + PREV_Y]; + } else { + // Interpolate between the previous frame and the current frame. + int frame = Animation.BinarySearch(frames, time, ENTRIES); + x = frames[frame + PREV_X]; + y = frames[frame + PREV_Y]; + float frameTime = frames[frame]; + float percent = GetCurvePercent(frame / ENTRIES - 1, + 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime)); + + x = x + (frames[frame + X] - x) * percent; + y = y + (frames[frame + Y] - y) * percent; + } + if (pose == MixPose_Setup) { + bone.shearX = bone.data.shearX + x * alpha; + bone.shearY = bone.data.shearY + y * alpha; + } else { + bone.shearX += (bone.data.shearX + x - bone.shearX) * alpha; + bone.shearY += (bone.data.shearY + y - bone.shearY) * alpha; + } + } + } +} + +#endif /* Spine_ShearTimeline_h */ diff --git a/spine-cpp/spine-cpp/include/spine/Skin.h b/spine-cpp/spine-cpp/include/spine/Skin.h index 37f7ea64a..4ec62317d 100644 --- a/spine-cpp/spine-cpp/include/spine/Skin.h +++ b/spine-cpp/spine-cpp/include/spine/Skin.h @@ -61,19 +61,7 @@ namespace Spine struct HashAttachmentKey { - std::size_t operator()(const Spine::Skin::AttachmentKey& val) const - { - std::size_t h1 = val._slotIndex; - - std::size_t h2 = 7; - size_t strlen = val._name.length(); - for (int i = 0; i < strlen; ++i) - { - h2 = h2 * 31 + val._name.at(i); - } - - return h1 ^ (h2 << 1); - } + std::size_t operator()(const Spine::Skin::AttachmentKey& val) const; }; Skin(std::string name); diff --git a/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h b/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h new file mode 100644 index 000000000..142e444c8 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h @@ -0,0 +1,131 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_TransformConstraintTimeline_h +#define Spine_TransformConstraintTimeline_h + +#include + +namespace Spine +{ + class TransformConstraintTimeline : public CurveTimeline + { + RTTI_DECL; + + public const int ENTRIES = 5; + private const int PREV_TIME = -5, PREV_ROTATE = -4, PREV_TRANSLATE = -3, PREV_SCALE = -2, PREV_SHEAR = -1; + private const int ROTATE = 1, TRANSLATE = 2, SCALE = 3, SHEAR = 4; + + internal int transformConstraintIndex; + internal float[] frames; + + public int TransformConstraintIndex { return transformConstraintIndex; } set { transformConstraintIndex = inValue; } + public float[] Frames { return frames; } set { frames = inValue; } // time, rotate mix, translate mix, scale mix, shear mix, ... + + override public int PropertyId { + get { return ((int)TimelineType.TransformConstraint << 24) + transformConstraintIndex; } + } + + public TransformConstraintTimeline (int frameCount) + : base(frameCount) { + frames = new float[frameCount * ENTRIES]; + } + + public void SetFrame (int frameIndex, float time, float rotateMix, float translateMix, float scaleMix, float shearMix) { + frameIndex *= ENTRIES; + frames[frameIndex] = time; + frames[frameIndex + ROTATE] = rotateMix; + frames[frameIndex + TRANSLATE] = translateMix; + frames[frameIndex + SCALE] = scaleMix; + frames[frameIndex + SHEAR] = shearMix; + } + + override public void Apply (Skeleton skeleton, float lastTime, float time, Vector firedEvents, float alpha, MixPose pose, MixDirection direction) { + TransformConstraint constraint = skeleton.transformConstraints.Items[transformConstraintIndex]; + float[] frames = _frames; + if (time < frames[0]) { + var data = constraint.data; + switch (pose) { + case MixPose_Setup: + constraint.rotateMix = data.rotateMix; + constraint.translateMix = data.translateMix; + constraint.scaleMix = data.scaleMix; + constraint.shearMix = data.shearMix; + return; + case MixPose_Current: + constraint.rotateMix += (data.rotateMix - constraint.rotateMix) * alpha; + constraint.translateMix += (data.translateMix - constraint.translateMix) * alpha; + constraint.scaleMix += (data.scaleMix - constraint.scaleMix) * alpha; + constraint.shearMix += (data.shearMix - constraint.shearMix) * alpha; + return; + } + return; + } + + float rotate, translate, scale, shear; + if (time >= frames[frames.Length - ENTRIES]) { // Time is after last frame. + int i = frames.Length; + rotate = frames[i + PREV_ROTATE]; + translate = frames[i + PREV_TRANSLATE]; + scale = frames[i + PREV_SCALE]; + shear = frames[i + PREV_SHEAR]; + } else { + // Interpolate between the previous frame and the current frame. + int frame = Animation.BinarySearch(frames, time, ENTRIES); + rotate = frames[frame + PREV_ROTATE]; + translate = frames[frame + PREV_TRANSLATE]; + scale = frames[frame + PREV_SCALE]; + shear = frames[frame + PREV_SHEAR]; + float frameTime = frames[frame]; + float percent = GetCurvePercent(frame / ENTRIES - 1, + 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime)); + + rotate += (frames[frame + ROTATE] - rotate) * percent; + translate += (frames[frame + TRANSLATE] - translate) * percent; + scale += (frames[frame + SCALE] - scale) * percent; + shear += (frames[frame + SHEAR] - shear) * percent; + } + if (pose == MixPose_Setup) { + TransformConstraintData data = constraint.data; + constraint.rotateMix = data.rotateMix + (rotate - data.rotateMix) * alpha; + constraint.translateMix = data.translateMix + (translate - data.translateMix) * alpha; + constraint.scaleMix = data.scaleMix + (scale - data.scaleMix) * alpha; + constraint.shearMix = data.shearMix + (shear - data.shearMix) * alpha; + } else { + constraint.rotateMix += (rotate - constraint.rotateMix) * alpha; + constraint.translateMix += (translate - constraint.translateMix) * alpha; + constraint.scaleMix += (scale - constraint.scaleMix) * alpha; + constraint.shearMix += (shear - constraint.shearMix) * alpha; + } + } + } +} + +#endif /* Spine_TransformConstraintTimeline_h */ diff --git a/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h b/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h new file mode 100644 index 000000000..ad7fb78b7 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h @@ -0,0 +1,129 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_TranslateTimeline_h +#define Spine_TranslateTimeline_h + +#include + +#include +#include + +namespace Spine +{ + class TranslateTimeline : public CurveTimeline + { + RTTI_DECL; + + public const int ENTRIES = 3; + protected const int PREV_TIME = -3, PREV_X = -2, PREV_Y = -1; + protected const int X = 1, Y = 2; + + internal int boneIndex; + internal float[] frames; + + public int getBoneIndex { return boneIndex; } set { boneIndex = inValue; } + public Vector getFrames { return frames; } set { frames = inValue; } // time, value, value, ... + + virtual int getPropertyId() + { + return ((int)TimelineType_Translate << 24) + boneIndex; + } + + public TranslateTimeline(int frameCount) : CurveTimeline(frameCount) + { + frames = new float[frameCount * ENTRIES]; + } + + /// Sets the time and value of the specified keyframe. + public void setFrame(int frameIndex, float time, float x, float y) + { + frameIndex *= ENTRIES; + frames[frameIndex] = time; + frames[frameIndex + X] = x; + frames[frameIndex + Y] = y; + } + + override public void apply(Skeleton skeleton, float lastTime, float time, Vector firedEvents, float alpha, MixPose pose, MixDirection direction) + { + Bone bone = skeleton.bones.Items[boneIndex]; + + float[] frames = _frames; + if (time < frames[0]) + { + switch (pose) + { + case MixPose_Setup: + bone.x = bone.data.x; + bone.y = bone.data.y; + return; + case MixPose_Current: + bone.x += (bone.data.x - bone.x) * alpha; + bone.y += (bone.data.y - bone.y) * alpha; + return; + } + return; + } + + float x, y; + if (time >= frames[frames.Length - ENTRIES]) + { + // Time is after last frame. + x = frames[frames.Length + PREV_X]; + y = frames[frames.Length + PREV_Y]; + } + else + { + // Interpolate between the previous frame and the current frame. + int frame = Animation::binarySearch(frames, time, ENTRIES); + x = frames[frame + PREV_X]; + y = frames[frame + PREV_Y]; + float frameTime = frames[frame]; + float percent = GetCurvePercent(frame / ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime)); + + x += (frames[frame + X] - x) * percent; + y += (frames[frame + Y] - y) * percent; + } + + if (pose == MixPose_Setup) + { + bone.x = bone.data.x + x * alpha; + bone.y = bone.data.y + y * alpha; + } + else + { + bone.x += (bone.data.x + x - bone.x) * alpha; + bone.y += (bone.data.y + y - bone.y) * alpha; + } + } + } +} + +#endif /* Spine_TranslateTimeline_h */ diff --git a/spine-cpp/spine-cpp/include/spine/Triangulator.h b/spine-cpp/spine-cpp/include/spine/Triangulator.h new file mode 100644 index 000000000..8c252f075 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/Triangulator.h @@ -0,0 +1,342 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Triangulator_h +#define Spine_Triangulator_h + +#include + +namespace Spine +{ + class Triangulator + { + public: + public Vector triangulate(Vector& verticesArray) + { + var vertices = verticesArray.Items; + int vertexCount = verticesArray.Count >> 1; + + var indicesArray = _indicesArray; + indicesArray.Clear(); + int[] indices = indicesArray.Resize(vertexCount).Items; + for (int i = 0; i < vertexCount; i++) + { + indices[i] = i; + } + + var isConcaveArray = _isConcaveArray; + bool[] isConcave = isConcaveArray.Resize(vertexCount).Items; + for (int i = 0, n = vertexCount; i < n; ++i) + { + isConcave[i] = isConcave(i, vertexCount, vertices, indices); + } + + var triangles = _triangles; + triangles.Clear(); + triangles.EnsureCapacity(Math.Max(0, vertexCount - 2) << 2); + + while (vertexCount > 3) + { + // Find ear tip. + int previous = vertexCount - 1, i = 0, next = 1; + + // outer: + while (true) + { + 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 (int ii = (next + 1) % vertexCount; ii != previous; ii = (ii + 1) % vertexCount) + { + if (!isConcave[ii]) continue; + int v = indices[ii] << 1; + float 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 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; + } + + // Cut ear tip. + triangles.Add(indices[(vertexCount + i - 1) % vertexCount]); + triangles.Add(indices[i]); + triangles.Add(indices[(i + 1) % vertexCount]); + indicesArray.RemoveAt(i); + isConcaveArray.RemoveAt(i); + vertexCount--; + + int previousIndex = (vertexCount + i - 1) % vertexCount; + int nextIndex = i == vertexCount ? 0 : i; + isConcave[previousIndex] = isConcave(previousIndex, vertexCount, vertices, indices); + isConcave[nextIndex] = isConcave(nextIndex, vertexCount, vertices, indices); + } + + if (vertexCount == 3) + { + triangles.Add(indices[2]); + triangles.Add(indices[0]); + triangles.Add(indices[1]); + } + + return triangles; + } + + public Vector> decompose(Vector& verticesArray, Vector& triangles) + { + var vertices = verticesArray.Items; + var convexPolygons = _convexPolygons; + for (int i = 0, n = convexPolygons.Count; i < n; i++) + { + polygonPool.Free(convexPolygons.Items[i]); + } + convexPolygons.Clear(); + + var convexPolygonsIndices = _convexPolygonsIndices; + for (int i = 0, n = convexPolygonsIndices.Count; i < n; i++) + { + polygonIndicesPool.Free(convexPolygonsIndices.Items[i]); + } + convexPolygonsIndices.Clear(); + + var polygonIndices = polygonIndicesPool.Obtain(); + polygonIndices.Clear(); + + var polygon = polygonPool.Obtain(); + polygon.Clear(); + + // Merge subsequent triangles if they form a triangle fan. + int fanBaseIndex = -1, lastwinding = 0; + int[] trianglesItems = triangles.Items; + for (int i = 0, n = triangles.Count; 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]; + + // If the base of the last triangle is the same as this triangle, check if they form a convex polygon (triangle fan). + var merged = false; + if (fanBaseIndex == t1) + { + int o = polygon.Count - 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) + { + polygon.Add(x3); + polygon.Add(y3); + polygonIndices.Add(t3); + merged = true; + } + } + + // Otherwise make this triangle the new base. + if (!merged) + { + if (polygon.Count > 0) + { + convexPolygons.Add(polygon); + convexPolygonsIndices.Add(polygonIndices); + } + else + { + polygonPool.Free(polygon); + polygonIndicesPool.Free(polygonIndices); + } + + polygon = polygonPool.Obtain(); + polygon.Clear(); + polygon.Add(x1); + polygon.Add(y1); + polygon.Add(x2); + polygon.Add(y2); + polygon.Add(x3); + polygon.Add(y3); + polygonIndices = polygonIndicesPool.Obtain(); + polygonIndices.Clear(); + polygonIndices.Add(t1); + polygonIndices.Add(t2); + polygonIndices.Add(t3); + lastwinding = winding(x1, y1, x2, y2, x3, y3); + fanBaseIndex = t1; + } + } + + if (polygon.Count > 0) + { + convexPolygons.Add(polygon); + convexPolygonsIndices.Add(polygonIndices); + } + + // Go through the list of polygons and try to merge the remaining triangles with the found triangle fans. + for (int i = 0, n = convexPolygons.Count; i < n; ++i) + { + polygonIndices = convexPolygonsIndices.Items[i]; + if (polygonIndices.Count == 0) continue; + int firstIndex = polygonIndices.Items[0]; + int lastIndex = polygonIndices.Items[polygonIndices.Count - 1]; + + polygon = convexPolygons.Items[i]; + int o = polygon.Count - 4; + float[] p = polygon.Items; + float prevPrevX = p[o], prevPrevY = p[o + 1]; + float prevX = p[o + 2], prevY = p[o + 3]; + float firstX = p[0], firstY = p[1]; + float secondX = p[2], secondY = p[3]; + int winding = winding(prevPrevX, prevPrevY, prevX, prevY, firstX, firstY); + + for (int ii = 0; ii < n; ii++) + { + if (ii == i) + { + continue; + } + + var otherIndices = convexPolygonsIndices.Items[ii]; + + if (otherIndices.Count != 3) + { + continue; + } + + int otherFirstIndex = otherIndices.Items[0]; + int otherSecondIndex = otherIndices.Items[1]; + int otherLastIndex = otherIndices.Items[2]; + + var otherPoly = convexPolygons.Items[ii]; + float x3 = otherPoly.Items[otherPoly.Count - 2], y3 = otherPoly.Items[otherPoly.Count - 1]; + + if (otherFirstIndex != firstIndex || otherSecondIndex != lastIndex) + { + continue; + } + + int winding1 = winding(prevPrevX, prevPrevY, prevX, prevY, x3, y3); + int winding2 = winding(x3, y3, firstX, firstY, secondX, secondY); + if (winding1 == winding && winding2 == winding) + { + otherPoly.Clear(); + otherIndices.Clear(); + polygon.Add(x3); + polygon.Add(y3); + polygonIndices.Add(otherLastIndex); + prevPrevX = prevX; + prevPrevY = prevY; + prevX = x3; + prevY = y3; + ii = 0; + } + } + } + + // Remove empty polygons that resulted from the merge step above. + for (int i = convexPolygons.Count - 1; i >= 0; --i) + { + polygon = convexPolygons.Items[i]; + if (polygon.Count == 0) + { + convexPolygons.RemoveAt(i); + polygonPool.Free(polygon); + polygonIndices = convexPolygonsIndices.Items[i]; + convexPolygonsIndices.RemoveAt(i); + polygonIndicesPool.Free(polygonIndices); + } + } + + return convexPolygons; + } + + private: + Vector> convexPolygons; + Vector> convexPolygonsIndices; + + Vector indicesArray; + Vector isConcaveArray; + Vector triangles; + + Pool> polygonPool; + Pool> polygonIndicesPool; + + static bool isConcave(int index, int vertexCount, Vector vertices, Vector 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 bool 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 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; + } + }; +} + +#endif /* Spine_Triangulator_h */ diff --git a/spine-cpp/spine-cpp/include/spine/TwoColorTimeline.h b/spine-cpp/spine-cpp/include/spine/TwoColorTimeline.h new file mode 100644 index 000000000..07af223cd --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/TwoColorTimeline.h @@ -0,0 +1,183 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_TwoColorTimeline_h +#define Spine_TwoColorTimeline_h + +#include + +namespace Spine +{ + class TwoColorTimeline : public CurveTimeline + { + RTTI_DECL; + + public const int ENTRIES = 8; + protected const int PREV_TIME = -8, PREV_R = -7, PREV_G = -6, PREV_B = -5, PREV_A = -4; + protected const int PREV_R2 = -3, PREV_G2 = -2, PREV_B2 = -1; + protected const int R = 1, G = 2, B = 3, A = 4, R2 = 5, G2 = 6, B2 = 7; + + internal float[] frames; // time, r, g, b, a, r2, g2, b2, ... + public float[] Frames { return frames; } + + internal int slotIndex; + public int SlotIndex { + get { return slotIndex; } + set { + if (value < 0) throw new ArgumentOutOfRangeException("index must be >= 0."); + slotIndex = inValue; + } + } + + override public int PropertyId { + get { return ((int)TimelineType.TwoColor << 24) + slotIndex; } + } + + public TwoColorTimeline (int frameCount) : + base(frameCount) { + frames = new float[frameCount * ENTRIES]; + } + + /// Sets the time and value of the specified keyframe. + public void SetFrame (int frameIndex, float time, float r, float g, float b, float a, float r2, float g2, float b2) { + frameIndex *= ENTRIES; + frames[frameIndex] = time; + frames[frameIndex + R] = r; + frames[frameIndex + G] = g; + frames[frameIndex + B] = b; + frames[frameIndex + A] = a; + frames[frameIndex + R2] = r2; + frames[frameIndex + G2] = g2; + frames[frameIndex + B2] = b2; + } + + override public void Apply (Skeleton skeleton, float lastTime, float time, Vector firedEvents, float alpha, MixPose pose, MixDirection direction) { + Slot slot = skeleton.slots.Items[slotIndex]; + float[] frames = _frames; + if (time < frames[0]) { // Time is before first frame. + var slotData = slot.data; + switch (pose) { + case MixPose_Setup: + // slot.color.set(slot.data.color); + // slot.darkColor.set(slot.data.darkColor); + slot.r = slotData.r; + slot.g = slotData.g; + slot.b = slotData.b; + slot.a = slotData.a; + slot.r2 = slotData.r2; + slot.g2 = slotData.g2; + slot.b2 = slotData.b2; + return; + case MixPose_Current: + slot.r += (slot.r - slotData.r) * alpha; + slot.g += (slot.g - slotData.g) * alpha; + slot.b += (slot.b - slotData.b) * alpha; + slot.a += (slot.a - slotData.a) * alpha; + slot.r2 += (slot.r2 - slotData.r2) * alpha; + slot.g2 += (slot.g2 - slotData.g2) * alpha; + slot.b2 += (slot.b2 - slotData.b2) * alpha; + return; + } + return; + } + + float r, g, b, a, r2, g2, b2; + if (time >= frames[frames.Length - ENTRIES]) { // Time is after last frame. + int i = frames.Length; + r = frames[i + PREV_R]; + g = frames[i + PREV_G]; + b = frames[i + PREV_B]; + a = frames[i + PREV_A]; + r2 = frames[i + PREV_R2]; + g2 = frames[i + PREV_G2]; + b2 = frames[i + PREV_B2]; + } else { + // Interpolate between the previous frame and the current frame. + int frame = Animation.BinarySearch(frames, time, ENTRIES); + r = frames[frame + PREV_R]; + g = frames[frame + PREV_G]; + b = frames[frame + PREV_B]; + a = frames[frame + PREV_A]; + r2 = frames[frame + PREV_R2]; + g2 = frames[frame + PREV_G2]; + b2 = frames[frame + PREV_B2]; + float frameTime = frames[frame]; + float percent = GetCurvePercent(frame / ENTRIES - 1, + 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime)); + + r += (frames[frame + R] - r) * percent; + g += (frames[frame + G] - g) * percent; + b += (frames[frame + B] - b) * percent; + a += (frames[frame + A] - a) * percent; + r2 += (frames[frame + R2] - r2) * percent; + g2 += (frames[frame + G2] - g2) * percent; + b2 += (frames[frame + B2] - b2) * percent; + } + if (alpha == 1) { + slot.r = r; + slot.g = g; + slot.b = b; + slot.a = a; + slot.r2 = r2; + slot.g2 = g2; + slot.b2 = b2; + } else { + float br, bg, bb, ba, br2, bg2, bb2; + if (pose == MixPose_Setup) { + br = slot.data.r; + bg = slot.data.g; + bb = slot.data.b; + ba = slot.data.a; + br2 = slot.data.r2; + bg2 = slot.data.g2; + bb2 = slot.data.b2; + } else { + br = slot.r; + bg = slot.g; + bb = slot.b; + ba = slot.a; + br2 = slot.r2; + bg2 = slot.g2; + bb2 = slot.b2; + } + slot.r = br + ((r - br) * alpha); + slot.g = bg + ((g - bg) * alpha); + slot.b = bb + ((b - bb) * alpha); + slot.a = ba + ((a - ba) * alpha); + slot.r2 = br2 + ((r2 - br2) * alpha); + slot.g2 = bg2 + ((g2 - bg2) * alpha); + slot.b2 = bb2 + ((b2 - bb2) * alpha); + } + } + + } +} + +#endif /* Spine_TwoColorTimeline_h */ diff --git a/spine-cpp/spine-cpp/src/spine/AnimationStateData.cpp b/spine-cpp/spine-cpp/src/spine/AnimationStateData.cpp new file mode 100644 index 000000000..de8ed8159 --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/AnimationStateData.cpp @@ -0,0 +1,119 @@ +/****************************************************************************** +* Spine Runtimes Software License v2.5 +* +* Copyright (c) 2013-2016, Esoteric Software +* All rights reserved. +* +* You are granted a perpetual, non-exclusive, non-sublicensable, and +* non-transferable license to use, install, execute, and perform the Spine +* Runtimes software and derivative works solely for personal or internal +* use. Without the written permission of Esoteric Software (see Section 2 of +* the Spine Software License Agreement), you may not (a) modify, translate, +* adapt, or develop new applications using the Spine Runtimes or otherwise +* create derivative works or improvements of the Spine Runtimes or (b) remove, +* delete, alter, or obscure any trademarks or any copyright, trademark, patent, +* or other intellectual property or proprietary rights notices on or in the +* Software, including any copy thereof. Redistributions in binary or source +* form must include this license and terms. +* +* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +#include + +#include +#include + +namespace Spine +{ + AnimationStateData::AnimationStateData(SkeletonData& skeletonData) : _skeletonData(skeletonData) + { + // Empty + } + + void AnimationStateData::setMix(std::string fromName, std::string toName, float duration) + { + Animation* from = _skeletonData.findAnimation(fromName); + assert(from != NULL); + + Animation* to = _skeletonData.findAnimation(toName); + assert(to != NULL); + + setMix(*from, *to, duration); + } + + void AnimationStateData::setMix(Animation& from, Animation& to, float duration) + { + AnimationPair key(from, to); + HashMap::Iterator i = _animationToMixTime.find(key); + _animationToMixTime.erase(i); + _animationToMixTime.insert(key, duration); + } + + float AnimationStateData::getMix(Animation& from, Animation& to) + { + AnimationPair key(from, to); + + HashMap::Iterator i = _animationToMixTime.find(key); + + if (i != _animationToMixTime.end()) + { + return i.second(); + } + + return _defaultMix; + } + + SkeletonData& AnimationStateData::getSkeletonData() + { + return _skeletonData; + } + + float AnimationStateData::getDefaultMix() + { + return _defaultMix; + } + + void AnimationStateData::setDefaultMix(float inValue) + { + _defaultMix = inValue; + } + + AnimationStateData::AnimationPair::AnimationPair(Animation& a1, Animation& a2) : _a1(a1), _a2(a2) + { + // Empty + } + + bool AnimationStateData::AnimationPair::operator==(const AnimationPair &other) const + { + return _a1._name == other._a1._name && _a2._name == other._a2._name; + } + + std::size_t AnimationStateData::HashAnimationPair::operator()(const Spine::AnimationStateData::AnimationPair& val) const + { + std::size_t h1 = 7; + size_t strlen = val._a1._name.length(); + for (int i = 0; i < strlen; ++i) + { + h1 = h1 * 31 + val._a1._name.at(i); + } + + std::size_t h2 = 7; + strlen = val._a2._name.length(); + for (int i = 0; i < strlen; ++i) + { + h2 = h2 * 31 + val._a2._name.at(i); + } + + return (((h1 << 5) + h1) ^ h2); + } +} diff --git a/spine-cpp/spine-cpp/src/spine/AtlasAttachmentLoader.cpp b/spine-cpp/spine-cpp/src/spine/AtlasAttachmentLoader.cpp new file mode 100644 index 000000000..1daf02530 --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/AtlasAttachmentLoader.cpp @@ -0,0 +1,36 @@ +/****************************************************************************** +* Spine Runtimes Software License v2.5 +* +* Copyright (c) 2013-2016, Esoteric Software +* All rights reserved. +* +* You are granted a perpetual, non-exclusive, non-sublicensable, and +* non-transferable license to use, install, execute, and perform the Spine +* Runtimes software and derivative works solely for personal or internal +* use. Without the written permission of Esoteric Software (see Section 2 of +* the Spine Software License Agreement), you may not (a) modify, translate, +* adapt, or develop new applications using the Spine Runtimes or otherwise +* create derivative works or improvements of the Spine Runtimes or (b) remove, +* delete, alter, or obscure any trademarks or any copyright, trademark, patent, +* or other intellectual property or proprietary rights notices on or in the +* Software, including any copy thereof. Redistributions in binary or source +* form must include this license and terms. +* +* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +#include + +namespace Spine +{ + RTTI_IMPL(AtlasAttachmentLoader, AttachmentLoader); +} diff --git a/spine-cpp/spine-cpp/src/spine/AttachmentLoader.cpp b/spine-cpp/spine-cpp/src/spine/AttachmentLoader.cpp new file mode 100644 index 000000000..bfe43d75f --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/AttachmentLoader.cpp @@ -0,0 +1,36 @@ +/****************************************************************************** +* Spine Runtimes Software License v2.5 +* +* Copyright (c) 2013-2016, Esoteric Software +* All rights reserved. +* +* You are granted a perpetual, non-exclusive, non-sublicensable, and +* non-transferable license to use, install, execute, and perform the Spine +* Runtimes software and derivative works solely for personal or internal +* use. Without the written permission of Esoteric Software (see Section 2 of +* the Spine Software License Agreement), you may not (a) modify, translate, +* adapt, or develop new applications using the Spine Runtimes or otherwise +* create derivative works or improvements of the Spine Runtimes or (b) remove, +* delete, alter, or obscure any trademarks or any copyright, trademark, patent, +* or other intellectual property or proprietary rights notices on or in the +* Software, including any copy thereof. Redistributions in binary or source +* form must include this license and terms. +* +* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +#include + +namespace Spine +{ + RTTI_IMPL_NOPARENT(AttachmentLoader); +} diff --git a/spine-cpp/spine-cpp/src/spine/AttachmentTimeline.cpp b/spine-cpp/spine-cpp/src/spine/AttachmentTimeline.cpp new file mode 100644 index 000000000..e91dce772 --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/AttachmentTimeline.cpp @@ -0,0 +1,42 @@ +/****************************************************************************** +* Spine Runtimes Software License v2.5 +* +* Copyright (c) 2013-2016, Esoteric Software +* All rights reserved. +* +* You are granted a perpetual, non-exclusive, non-sublicensable, and +* non-transferable license to use, install, execute, and perform the Spine +* Runtimes software and derivative works solely for personal or internal +* use. Without the written permission of Esoteric Software (see Section 2 of +* the Spine Software License Agreement), you may not (a) modify, translate, +* adapt, or develop new applications using the Spine Runtimes or otherwise +* create derivative works or improvements of the Spine Runtimes or (b) remove, +* delete, alter, or obscure any trademarks or any copyright, trademark, patent, +* or other intellectual property or proprietary rights notices on or in the +* Software, including any copy thereof. Redistributions in binary or source +* form must include this license and terms. +* +* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +#include + +#include +#include + +#include +#include + +namespace Spine +{ + RTTI_IMPL(AttachmentTimeline, Timeline); +} diff --git a/spine-cpp/spine-cpp/src/spine/BoundingBoxAttachment.cpp b/spine-cpp/spine-cpp/src/spine/BoundingBoxAttachment.cpp new file mode 100644 index 000000000..ffa7f7355 --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/BoundingBoxAttachment.cpp @@ -0,0 +1,41 @@ +/****************************************************************************** +* Spine Runtimes Software License v2.5 +* +* Copyright (c) 2013-2016, Esoteric Software +* All rights reserved. +* +* You are granted a perpetual, non-exclusive, non-sublicensable, and +* non-transferable license to use, install, execute, and perform the Spine +* Runtimes software and derivative works solely for personal or internal +* use. Without the written permission of Esoteric Software (see Section 2 of +* the Spine Software License Agreement), you may not (a) modify, translate, +* adapt, or develop new applications using the Spine Runtimes or otherwise +* create derivative works or improvements of the Spine Runtimes or (b) remove, +* delete, alter, or obscure any trademarks or any copyright, trademark, patent, +* or other intellectual property or proprietary rights notices on or in the +* Software, including any copy thereof. Redistributions in binary or source +* form must include this license and terms. +* +* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +#include + +namespace Spine +{ + RTTI_IMPL(BoundingBoxAttachment, VertexAttachment); + + BoundingBoxAttachment::BoundingBoxAttachment(std::string name) : VertexAttachment(name) + { + // Empty + } +} diff --git a/spine-cpp/spine-cpp/src/spine/ClippingAttachment.cpp b/spine-cpp/spine-cpp/src/spine/ClippingAttachment.cpp new file mode 100644 index 000000000..c87de561c --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/ClippingAttachment.cpp @@ -0,0 +1,53 @@ +/****************************************************************************** +* Spine Runtimes Software License v2.5 +* +* Copyright (c) 2013-2016, Esoteric Software +* All rights reserved. +* +* You are granted a perpetual, non-exclusive, non-sublicensable, and +* non-transferable license to use, install, execute, and perform the Spine +* Runtimes software and derivative works solely for personal or internal +* use. Without the written permission of Esoteric Software (see Section 2 of +* the Spine Software License Agreement), you may not (a) modify, translate, +* adapt, or develop new applications using the Spine Runtimes or otherwise +* create derivative works or improvements of the Spine Runtimes or (b) remove, +* delete, alter, or obscure any trademarks or any copyright, trademark, patent, +* or other intellectual property or proprietary rights notices on or in the +* Software, including any copy thereof. Redistributions in binary or source +* form must include this license and terms. +* +* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +#include + +#include + +namespace Spine +{ + RTTI_IMPL(ClippingAttachment, VertexAttachment); + + ClippingAttachment::ClippingAttachment(std::string name) : VertexAttachment(name) + { + // Empty + } + + SlotData* ClippingAttachment::getEndSlot() + { + return _endSlot; + } + + void ClippingAttachment::setEndSlot(SlotData* inValue) + { + _endSlot = inValue; + } +} diff --git a/spine-cpp/spine-cpp/src/spine/ColorTimeline.cpp b/spine-cpp/spine-cpp/src/spine/ColorTimeline.cpp new file mode 100644 index 000000000..e1a2c4ff4 --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/ColorTimeline.cpp @@ -0,0 +1,36 @@ +/****************************************************************************** +* Spine Runtimes Software License v2.5 +* +* Copyright (c) 2013-2016, Esoteric Software +* All rights reserved. +* +* You are granted a perpetual, non-exclusive, non-sublicensable, and +* non-transferable license to use, install, execute, and perform the Spine +* Runtimes software and derivative works solely for personal or internal +* use. Without the written permission of Esoteric Software (see Section 2 of +* the Spine Software License Agreement), you may not (a) modify, translate, +* adapt, or develop new applications using the Spine Runtimes or otherwise +* create derivative works or improvements of the Spine Runtimes or (b) remove, +* delete, alter, or obscure any trademarks or any copyright, trademark, patent, +* or other intellectual property or proprietary rights notices on or in the +* Software, including any copy thereof. Redistributions in binary or source +* form must include this license and terms. +* +* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +#include + +namespace Spine +{ + RTTI_IMPL(ColorTimeline, CurveTimeline); +} diff --git a/spine-cpp/spine-cpp/src/spine/DeformTimeline.cpp b/spine-cpp/spine-cpp/src/spine/DeformTimeline.cpp new file mode 100644 index 000000000..42e9be963 --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/DeformTimeline.cpp @@ -0,0 +1,36 @@ +/****************************************************************************** +* Spine Runtimes Software License v2.5 +* +* Copyright (c) 2013-2016, Esoteric Software +* All rights reserved. +* +* You are granted a perpetual, non-exclusive, non-sublicensable, and +* non-transferable license to use, install, execute, and perform the Spine +* Runtimes software and derivative works solely for personal or internal +* use. Without the written permission of Esoteric Software (see Section 2 of +* the Spine Software License Agreement), you may not (a) modify, translate, +* adapt, or develop new applications using the Spine Runtimes or otherwise +* create derivative works or improvements of the Spine Runtimes or (b) remove, +* delete, alter, or obscure any trademarks or any copyright, trademark, patent, +* or other intellectual property or proprietary rights notices on or in the +* Software, including any copy thereof. Redistributions in binary or source +* form must include this license and terms. +* +* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +#include + +namespace Spine +{ + RTTI_IMPL(DeformTimeline, CurveTimeline); +} diff --git a/spine-cpp/spine-cpp/src/spine/DrawOrderTimeline.cpp b/spine-cpp/spine-cpp/src/spine/DrawOrderTimeline.cpp new file mode 100644 index 000000000..9ed5c7e7f --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/DrawOrderTimeline.cpp @@ -0,0 +1,36 @@ +/****************************************************************************** +* Spine Runtimes Software License v2.5 +* +* Copyright (c) 2013-2016, Esoteric Software +* All rights reserved. +* +* You are granted a perpetual, non-exclusive, non-sublicensable, and +* non-transferable license to use, install, execute, and perform the Spine +* Runtimes software and derivative works solely for personal or internal +* use. Without the written permission of Esoteric Software (see Section 2 of +* the Spine Software License Agreement), you may not (a) modify, translate, +* adapt, or develop new applications using the Spine Runtimes or otherwise +* create derivative works or improvements of the Spine Runtimes or (b) remove, +* delete, alter, or obscure any trademarks or any copyright, trademark, patent, +* or other intellectual property or proprietary rights notices on or in the +* Software, including any copy thereof. Redistributions in binary or source +* form must include this license and terms. +* +* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +#include + +namespace Spine +{ + RTTI_IMPL(DrawOrderTimeline, Timeline); +} diff --git a/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp b/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp new file mode 100644 index 000000000..ef4e0e8a5 --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp @@ -0,0 +1,36 @@ +/****************************************************************************** +* Spine Runtimes Software License v2.5 +* +* Copyright (c) 2013-2016, Esoteric Software +* All rights reserved. +* +* You are granted a perpetual, non-exclusive, non-sublicensable, and +* non-transferable license to use, install, execute, and perform the Spine +* Runtimes software and derivative works solely for personal or internal +* use. Without the written permission of Esoteric Software (see Section 2 of +* the Spine Software License Agreement), you may not (a) modify, translate, +* adapt, or develop new applications using the Spine Runtimes or otherwise +* create derivative works or improvements of the Spine Runtimes or (b) remove, +* delete, alter, or obscure any trademarks or any copyright, trademark, patent, +* or other intellectual property or proprietary rights notices on or in the +* Software, including any copy thereof. Redistributions in binary or source +* form must include this license and terms. +* +* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +#include + +namespace Spine +{ + RTTI_IMPL(EventTimeline, Timeline); +} diff --git a/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp b/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp new file mode 100644 index 000000000..19755ad12 --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp @@ -0,0 +1,36 @@ +/****************************************************************************** +* Spine Runtimes Software License v2.5 +* +* Copyright (c) 2013-2016, Esoteric Software +* All rights reserved. +* +* You are granted a perpetual, non-exclusive, non-sublicensable, and +* non-transferable license to use, install, execute, and perform the Spine +* Runtimes software and derivative works solely for personal or internal +* use. Without the written permission of Esoteric Software (see Section 2 of +* the Spine Software License Agreement), you may not (a) modify, translate, +* adapt, or develop new applications using the Spine Runtimes or otherwise +* create derivative works or improvements of the Spine Runtimes or (b) remove, +* delete, alter, or obscure any trademarks or any copyright, trademark, patent, +* or other intellectual property or proprietary rights notices on or in the +* Software, including any copy thereof. Redistributions in binary or source +* form must include this license and terms. +* +* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +#include + +namespace Spine +{ + RTTI_IMPL(IkConstraintTimeline, CurveTimeline); +} diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp b/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp new file mode 100644 index 000000000..bd849f29d --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp @@ -0,0 +1,36 @@ +/****************************************************************************** +* Spine Runtimes Software License v2.5 +* +* Copyright (c) 2013-2016, Esoteric Software +* All rights reserved. +* +* You are granted a perpetual, non-exclusive, non-sublicensable, and +* non-transferable license to use, install, execute, and perform the Spine +* Runtimes software and derivative works solely for personal or internal +* use. Without the written permission of Esoteric Software (see Section 2 of +* the Spine Software License Agreement), you may not (a) modify, translate, +* adapt, or develop new applications using the Spine Runtimes or otherwise +* create derivative works or improvements of the Spine Runtimes or (b) remove, +* delete, alter, or obscure any trademarks or any copyright, trademark, patent, +* or other intellectual property or proprietary rights notices on or in the +* Software, including any copy thereof. Redistributions in binary or source +* form must include this license and terms. +* +* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +#include + +namespace Spine +{ + RTTI_IMPL(PathConstraintMixTimeline, CurveTimeline); +} diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp b/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp new file mode 100644 index 000000000..0d944901e --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp @@ -0,0 +1,36 @@ +/****************************************************************************** +* Spine Runtimes Software License v2.5 +* +* Copyright (c) 2013-2016, Esoteric Software +* All rights reserved. +* +* You are granted a perpetual, non-exclusive, non-sublicensable, and +* non-transferable license to use, install, execute, and perform the Spine +* Runtimes software and derivative works solely for personal or internal +* use. Without the written permission of Esoteric Software (see Section 2 of +* the Spine Software License Agreement), you may not (a) modify, translate, +* adapt, or develop new applications using the Spine Runtimes or otherwise +* create derivative works or improvements of the Spine Runtimes or (b) remove, +* delete, alter, or obscure any trademarks or any copyright, trademark, patent, +* or other intellectual property or proprietary rights notices on or in the +* Software, including any copy thereof. Redistributions in binary or source +* form must include this license and terms. +* +* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +#include + +namespace Spine +{ + RTTI_IMPL(PathConstraintPositionTimeline, CurveTimeline); +} diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp b/spine-cpp/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp new file mode 100644 index 000000000..f9becd25c --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp @@ -0,0 +1,36 @@ +/****************************************************************************** +* Spine Runtimes Software License v2.5 +* +* Copyright (c) 2013-2016, Esoteric Software +* All rights reserved. +* +* You are granted a perpetual, non-exclusive, non-sublicensable, and +* non-transferable license to use, install, execute, and perform the Spine +* Runtimes software and derivative works solely for personal or internal +* use. Without the written permission of Esoteric Software (see Section 2 of +* the Spine Software License Agreement), you may not (a) modify, translate, +* adapt, or develop new applications using the Spine Runtimes or otherwise +* create derivative works or improvements of the Spine Runtimes or (b) remove, +* delete, alter, or obscure any trademarks or any copyright, trademark, patent, +* or other intellectual property or proprietary rights notices on or in the +* Software, including any copy thereof. Redistributions in binary or source +* form must include this license and terms. +* +* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +#include + +namespace Spine +{ + RTTI_IMPL(PathConstraintSpacingTimeline, PathConstraintPositionTimeline); +} diff --git a/spine-cpp/spine-cpp/src/spine/PointAttachment.cpp b/spine-cpp/spine-cpp/src/spine/PointAttachment.cpp new file mode 100644 index 000000000..d309c8d48 --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/PointAttachment.cpp @@ -0,0 +1,90 @@ +/****************************************************************************** +* Spine Runtimes Software License v2.5 +* +* Copyright (c) 2013-2016, Esoteric Software +* All rights reserved. +* +* You are granted a perpetual, non-exclusive, non-sublicensable, and +* non-transferable license to use, install, execute, and perform the Spine +* Runtimes software and derivative works solely for personal or internal +* use. Without the written permission of Esoteric Software (see Section 2 of +* the Spine Software License Agreement), you may not (a) modify, translate, +* adapt, or develop new applications using the Spine Runtimes or otherwise +* create derivative works or improvements of the Spine Runtimes or (b) remove, +* delete, alter, or obscure any trademarks or any copyright, trademark, patent, +* or other intellectual property or proprietary rights notices on or in the +* Software, including any copy thereof. Redistributions in binary or source +* form must include this license and terms. +* +* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +#include + +#include + +#include + +namespace Spine +{ + RTTI_IMPL(PointAttachment, Attachment); + + PointAttachment::PointAttachment(std::string name) : Attachment(name) + { + // Empty + } + + void PointAttachment::computeWorldPosition(Bone& bone, float& ox, float& oy) + { + bone.localToWorld(_x, _y, ox, oy); + } + + float PointAttachment::computeWorldRotation(Bone& bone) + { + float cos = MathUtil::cosDeg(_rotation); + float sin = MathUtil::sinDeg(_rotation); + float ix = cos * bone._a + sin * bone._b; + float iy = cos * bone._c + sin * bone._d; + + return MathUtil::atan2(iy, ix) * RadDeg; + } + + float PointAttachment::getX() + { + return _x; + } + + void PointAttachment::setX(float inValue) + { + _x = inValue; + } + + float PointAttachment::getY() + { + return _y; + } + + void PointAttachment::setY(float inValue) + { + _y = inValue; + } + + float PointAttachment::getRotation() + { + return _rotation; + } + + void PointAttachment::setRotation(float inValue) + { + _rotation = inValue; + } +} diff --git a/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp b/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp index 8561c77ee..acfeb7db1 100644 --- a/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp @@ -122,7 +122,6 @@ namespace Spine return ((int)TimelineType_Rotate << 24) + _boneIndex; } - /// Sets the time and value of the specified keyframe. void RotateTimeline::setFrame(int frameIndex, float time, float degrees) { frameIndex <<= 1; diff --git a/spine-cpp/spine-cpp/src/spine/ScaleTimeline.cpp b/spine-cpp/spine-cpp/src/spine/ScaleTimeline.cpp new file mode 100644 index 000000000..50c06453c --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/ScaleTimeline.cpp @@ -0,0 +1,36 @@ +/****************************************************************************** +* Spine Runtimes Software License v2.5 +* +* Copyright (c) 2013-2016, Esoteric Software +* All rights reserved. +* +* You are granted a perpetual, non-exclusive, non-sublicensable, and +* non-transferable license to use, install, execute, and perform the Spine +* Runtimes software and derivative works solely for personal or internal +* use. Without the written permission of Esoteric Software (see Section 2 of +* the Spine Software License Agreement), you may not (a) modify, translate, +* adapt, or develop new applications using the Spine Runtimes or otherwise +* create derivative works or improvements of the Spine Runtimes or (b) remove, +* delete, alter, or obscure any trademarks or any copyright, trademark, patent, +* or other intellectual property or proprietary rights notices on or in the +* Software, including any copy thereof. Redistributions in binary or source +* form must include this license and terms. +* +* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +#include + +namespace Spine +{ + RTTI_IMPL(ScaleTimeline, TranslateTimeline); +} diff --git a/spine-cpp/spine-cpp/src/spine/ShearTimeline.cpp b/spine-cpp/spine-cpp/src/spine/ShearTimeline.cpp new file mode 100644 index 000000000..b81a4442f --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/ShearTimeline.cpp @@ -0,0 +1,36 @@ +/****************************************************************************** +* Spine Runtimes Software License v2.5 +* +* Copyright (c) 2013-2016, Esoteric Software +* All rights reserved. +* +* You are granted a perpetual, non-exclusive, non-sublicensable, and +* non-transferable license to use, install, execute, and perform the Spine +* Runtimes software and derivative works solely for personal or internal +* use. Without the written permission of Esoteric Software (see Section 2 of +* the Spine Software License Agreement), you may not (a) modify, translate, +* adapt, or develop new applications using the Spine Runtimes or otherwise +* create derivative works or improvements of the Spine Runtimes or (b) remove, +* delete, alter, or obscure any trademarks or any copyright, trademark, patent, +* or other intellectual property or proprietary rights notices on or in the +* Software, including any copy thereof. Redistributions in binary or source +* form must include this license and terms. +* +* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +#include + +namespace Spine +{ + RTTI_IMPL(ShearTimeline, TranslateTimeline); +} diff --git a/spine-cpp/spine-cpp/src/spine/Skin.cpp b/spine-cpp/spine-cpp/src/spine/Skin.cpp index d3dec3573..522e34e02 100644 --- a/spine-cpp/spine-cpp/src/spine/Skin.cpp +++ b/spine-cpp/spine-cpp/src/spine/Skin.cpp @@ -51,6 +51,13 @@ namespace Spine return _slotIndex == other._slotIndex && _name == other._name; } + std::size_t Skin::HashAttachmentKey::operator()(const Spine::Skin::AttachmentKey& val) const + { + std::size_t h1 = val._slotIndex; + + return h1; + } + Skin::Skin(std::string name) : _name(name) { assert(_name.length() > 0); diff --git a/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp b/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp new file mode 100644 index 000000000..a4fe5dd3a --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp @@ -0,0 +1,37 @@ +/****************************************************************************** +* Spine Runtimes Software License v2.5 +* +* Copyright (c) 2013-2016, Esoteric Software +* All rights reserved. +* +* You are granted a perpetual, non-exclusive, non-sublicensable, and +* non-transferable license to use, install, execute, and perform the Spine +* Runtimes software and derivative works solely for personal or internal +* use. Without the written permission of Esoteric Software (see Section 2 of +* the Spine Software License Agreement), you may not (a) modify, translate, +* adapt, or develop new applications using the Spine Runtimes or otherwise +* create derivative works or improvements of the Spine Runtimes or (b) remove, +* delete, alter, or obscure any trademarks or any copyright, trademark, patent, +* or other intellectual property or proprietary rights notices on or in the +* Software, including any copy thereof. Redistributions in binary or source +* form must include this license and terms. +* +* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +#include + +namespace Spine +{ + RTTI_IMPL(TransformConstraintTimeline, CurveTimeline); +} + diff --git a/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp b/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp new file mode 100644 index 000000000..5de311b78 --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp @@ -0,0 +1,36 @@ +/****************************************************************************** +* Spine Runtimes Software License v2.5 +* +* Copyright (c) 2013-2016, Esoteric Software +* All rights reserved. +* +* You are granted a perpetual, non-exclusive, non-sublicensable, and +* non-transferable license to use, install, execute, and perform the Spine +* Runtimes software and derivative works solely for personal or internal +* use. Without the written permission of Esoteric Software (see Section 2 of +* the Spine Software License Agreement), you may not (a) modify, translate, +* adapt, or develop new applications using the Spine Runtimes or otherwise +* create derivative works or improvements of the Spine Runtimes or (b) remove, +* delete, alter, or obscure any trademarks or any copyright, trademark, patent, +* or other intellectual property or proprietary rights notices on or in the +* Software, including any copy thereof. Redistributions in binary or source +* form must include this license and terms. +* +* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +#include + +namespace Spine +{ + RTTI_IMPL(TranslateTimeline, CurveTimeline); +} diff --git a/spine-cpp/spine-cpp/src/spine/Triangulator.cpp b/spine-cpp/spine-cpp/src/spine/Triangulator.cpp new file mode 100644 index 000000000..bb4d2ccfe --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/Triangulator.cpp @@ -0,0 +1,34 @@ +/****************************************************************************** +* Spine Runtimes Software License v2.5 +* +* Copyright (c) 2013-2016, Esoteric Software +* All rights reserved. +* +* You are granted a perpetual, non-exclusive, non-sublicensable, and +* non-transferable license to use, install, execute, and perform the Spine +* Runtimes software and derivative works solely for personal or internal +* use. Without the written permission of Esoteric Software (see Section 2 of +* the Spine Software License Agreement), you may not (a) modify, translate, +* adapt, or develop new applications using the Spine Runtimes or otherwise +* create derivative works or improvements of the Spine Runtimes or (b) remove, +* delete, alter, or obscure any trademarks or any copyright, trademark, patent, +* or other intellectual property or proprietary rights notices on or in the +* Software, including any copy thereof. Redistributions in binary or source +* form must include this license and terms. +* +* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +namespace Spine +{ + // TODO +} diff --git a/spine-cpp/spine-cpp/src/spine/TwoColorTimeline.cpp b/spine-cpp/spine-cpp/src/spine/TwoColorTimeline.cpp new file mode 100644 index 000000000..0e15ae88a --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/TwoColorTimeline.cpp @@ -0,0 +1,36 @@ +/****************************************************************************** +* Spine Runtimes Software License v2.5 +* +* Copyright (c) 2013-2016, Esoteric Software +* All rights reserved. +* +* You are granted a perpetual, non-exclusive, non-sublicensable, and +* non-transferable license to use, install, execute, and perform the Spine +* Runtimes software and derivative works solely for personal or internal +* use. Without the written permission of Esoteric Software (see Section 2 of +* the Spine Software License Agreement), you may not (a) modify, translate, +* adapt, or develop new applications using the Spine Runtimes or otherwise +* create derivative works or improvements of the Spine Runtimes or (b) remove, +* delete, alter, or obscure any trademarks or any copyright, trademark, patent, +* or other intellectual property or proprietary rights notices on or in the +* Software, including any copy thereof. Redistributions in binary or source +* form must include this license and terms. +* +* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +#include + +namespace Spine +{ + RTTI_IMPL(TwoColorTimeline, CurveTimeline); +} From 9c1f7ff9bf6d93f0921569d584ab930ac23a4811 Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Mon, 13 Nov 2017 16:07:42 -0500 Subject: [PATCH 31/83] Fixing a flaw I found in Vector copy constructor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit _buffer wasn’t being initialized if the incoming vector had a zero size --- spine-cpp/spine-cpp/include/spine/Vector.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/spine-cpp/spine-cpp/include/spine/Vector.h b/spine-cpp/spine-cpp/include/spine/Vector.h index f45d0580e..30de79e6e 100644 --- a/spine-cpp/spine-cpp/include/spine/Vector.h +++ b/spine-cpp/spine-cpp/include/spine/Vector.h @@ -46,10 +46,8 @@ namespace Spine // Empty } - Vector(const Vector& inArray) + Vector(const Vector& inArray) : _size(inArray._size), _capacity(inArray._capacity), _buffer(NULL) { - _size = inArray._size; - _capacity = inArray._capacity; if (_capacity > 0) { _buffer = allocate(_capacity); From cd8d9501170b7fcd1d67b7177163ea0ff83078a0 Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Mon, 13 Nov 2017 17:02:15 -0500 Subject: [PATCH 32/83] Fixing some mistakes in HashMap --- spine-cpp/spine-cpp/include/spine/HashMap.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/spine-cpp/spine-cpp/include/spine/HashMap.h b/spine-cpp/spine-cpp/include/spine/HashMap.h index ee38a9aee..26dd90bf1 100755 --- a/spine-cpp/spine-cpp/include/spine/HashMap.h +++ b/spine-cpp/spine-cpp/include/spine/HashMap.h @@ -31,8 +31,7 @@ #ifndef Spine_HashMap_h #define Spine_HashMap_h -#include -#include +#include namespace Spine { @@ -153,7 +152,7 @@ namespace Spine Entry* entry = new Entry(); entry->_key = key; - entry->_value = inValue; + entry->_value = value; _hashSize++; From bfbb48c1c2c3b4f5ebc7a60c864ff98f09a1a73c Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Mon, 13 Nov 2017 17:55:36 -0500 Subject: [PATCH 33/83] Adding Pool class to be used inside the Triangulator --- spine-cpp/spine-cpp/include/spine/Pool.h | 81 +++++++++++++++++++ .../spine-cpp/include/spine/Triangulator.h | 15 ++-- 2 files changed, 89 insertions(+), 7 deletions(-) create mode 100644 spine-cpp/spine-cpp/include/spine/Pool.h diff --git a/spine-cpp/spine-cpp/include/spine/Pool.h b/spine-cpp/spine-cpp/include/spine/Pool.h new file mode 100644 index 000000000..83e78a6fb --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/Pool.h @@ -0,0 +1,81 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Pool_h +#define Spine_Pool_h + +#include +#include + +namespace Spine +{ + template + class Pool + { + public: + Pool() + { + // Empty + } + + ~Pool() + { + ContainerUtil::cleanUpVectorOfPointers(_objects); + } + + T* obtain() + { + if (_objects.size() > 0) + { + T** object = _objects.begin(); + _objects.erase(0); + + return *object; + } + else + { + return new T(); + } + } + + void free(T* object) + { + if (!_objects.contains(object)) + { + _objects.push_back(object); + } + } + + private: + Vector _objects; + }; +} + +#endif /* Spine_Pool_h */ diff --git a/spine-cpp/spine-cpp/include/spine/Triangulator.h b/spine-cpp/spine-cpp/include/spine/Triangulator.h index 8c252f075..7b2288124 100644 --- a/spine-cpp/spine-cpp/include/spine/Triangulator.h +++ b/spine-cpp/spine-cpp/include/spine/Triangulator.h @@ -32,6 +32,7 @@ #define Spine_Triangulator_h #include +#include namespace Spine { @@ -305,15 +306,15 @@ namespace Spine } private: - Vector> convexPolygons; - Vector> convexPolygonsIndices; + Vector> _convexPolygons; + Vector> _convexPolygonsIndices; - Vector indicesArray; - Vector isConcaveArray; - Vector triangles; + Vector _indicesArray; + Vector _isConcaveArray; + Vector _triangles; - Pool> polygonPool; - Pool> polygonIndicesPool; + Pool> _polygonPool; + Pool> _polygonIndicesPool; static bool isConcave(int index, int vertexCount, Vector vertices, Vector indices) { From 0b6c8411b7fcd5425a5018d5ccc4415523efb6ac Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Tue, 14 Nov 2017 20:15:56 -0500 Subject: [PATCH 34/83] wip --- .../spine-cpp/include/spine/Triangulator.h | 298 +----------------- .../spine-cpp/src/spine/Triangulator.cpp | 294 ++++++++++++++++- 2 files changed, 303 insertions(+), 289 deletions(-) diff --git a/spine-cpp/spine-cpp/include/spine/Triangulator.h b/spine-cpp/spine-cpp/include/spine/Triangulator.h index 7b2288124..ea9074580 100644 --- a/spine-cpp/spine-cpp/include/spine/Triangulator.h +++ b/spine-cpp/spine-cpp/include/spine/Triangulator.h @@ -39,304 +39,26 @@ namespace Spine class Triangulator { public: - public Vector triangulate(Vector& verticesArray) - { - var vertices = verticesArray.Items; - int vertexCount = verticesArray.Count >> 1; - - var indicesArray = _indicesArray; - indicesArray.Clear(); - int[] indices = indicesArray.Resize(vertexCount).Items; - for (int i = 0; i < vertexCount; i++) - { - indices[i] = i; - } - - var isConcaveArray = _isConcaveArray; - bool[] isConcave = isConcaveArray.Resize(vertexCount).Items; - for (int i = 0, n = vertexCount; i < n; ++i) - { - isConcave[i] = isConcave(i, vertexCount, vertices, indices); - } - - var triangles = _triangles; - triangles.Clear(); - triangles.EnsureCapacity(Math.Max(0, vertexCount - 2) << 2); - - while (vertexCount > 3) - { - // Find ear tip. - int previous = vertexCount - 1, i = 0, next = 1; - - // outer: - while (true) - { - 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 (int ii = (next + 1) % vertexCount; ii != previous; ii = (ii + 1) % vertexCount) - { - if (!isConcave[ii]) continue; - int v = indices[ii] << 1; - float 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 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; - } - - // Cut ear tip. - triangles.Add(indices[(vertexCount + i - 1) % vertexCount]); - triangles.Add(indices[i]); - triangles.Add(indices[(i + 1) % vertexCount]); - indicesArray.RemoveAt(i); - isConcaveArray.RemoveAt(i); - vertexCount--; - - int previousIndex = (vertexCount + i - 1) % vertexCount; - int nextIndex = i == vertexCount ? 0 : i; - isConcave[previousIndex] = isConcave(previousIndex, vertexCount, vertices, indices); - isConcave[nextIndex] = isConcave(nextIndex, vertexCount, vertices, indices); - } - - if (vertexCount == 3) - { - triangles.Add(indices[2]); - triangles.Add(indices[0]); - triangles.Add(indices[1]); - } - - return triangles; - } + Vector triangulate(Vector& vertices); - public Vector> decompose(Vector& verticesArray, Vector& triangles) - { - var vertices = verticesArray.Items; - var convexPolygons = _convexPolygons; - for (int i = 0, n = convexPolygons.Count; i < n; i++) - { - polygonPool.Free(convexPolygons.Items[i]); - } - convexPolygons.Clear(); - - var convexPolygonsIndices = _convexPolygonsIndices; - for (int i = 0, n = convexPolygonsIndices.Count; i < n; i++) - { - polygonIndicesPool.Free(convexPolygonsIndices.Items[i]); - } - convexPolygonsIndices.Clear(); - - var polygonIndices = polygonIndicesPool.Obtain(); - polygonIndices.Clear(); - - var polygon = polygonPool.Obtain(); - polygon.Clear(); - - // Merge subsequent triangles if they form a triangle fan. - int fanBaseIndex = -1, lastwinding = 0; - int[] trianglesItems = triangles.Items; - for (int i = 0, n = triangles.Count; 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]; - - // If the base of the last triangle is the same as this triangle, check if they form a convex polygon (triangle fan). - var merged = false; - if (fanBaseIndex == t1) - { - int o = polygon.Count - 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) - { - polygon.Add(x3); - polygon.Add(y3); - polygonIndices.Add(t3); - merged = true; - } - } - - // Otherwise make this triangle the new base. - if (!merged) - { - if (polygon.Count > 0) - { - convexPolygons.Add(polygon); - convexPolygonsIndices.Add(polygonIndices); - } - else - { - polygonPool.Free(polygon); - polygonIndicesPool.Free(polygonIndices); - } - - polygon = polygonPool.Obtain(); - polygon.Clear(); - polygon.Add(x1); - polygon.Add(y1); - polygon.Add(x2); - polygon.Add(y2); - polygon.Add(x3); - polygon.Add(y3); - polygonIndices = polygonIndicesPool.Obtain(); - polygonIndices.Clear(); - polygonIndices.Add(t1); - polygonIndices.Add(t2); - polygonIndices.Add(t3); - lastwinding = winding(x1, y1, x2, y2, x3, y3); - fanBaseIndex = t1; - } - } - - if (polygon.Count > 0) - { - convexPolygons.Add(polygon); - convexPolygonsIndices.Add(polygonIndices); - } - - // Go through the list of polygons and try to merge the remaining triangles with the found triangle fans. - for (int i = 0, n = convexPolygons.Count; i < n; ++i) - { - polygonIndices = convexPolygonsIndices.Items[i]; - if (polygonIndices.Count == 0) continue; - int firstIndex = polygonIndices.Items[0]; - int lastIndex = polygonIndices.Items[polygonIndices.Count - 1]; - - polygon = convexPolygons.Items[i]; - int o = polygon.Count - 4; - float[] p = polygon.Items; - float prevPrevX = p[o], prevPrevY = p[o + 1]; - float prevX = p[o + 2], prevY = p[o + 3]; - float firstX = p[0], firstY = p[1]; - float secondX = p[2], secondY = p[3]; - int winding = winding(prevPrevX, prevPrevY, prevX, prevY, firstX, firstY); - - for (int ii = 0; ii < n; ii++) - { - if (ii == i) - { - continue; - } - - var otherIndices = convexPolygonsIndices.Items[ii]; - - if (otherIndices.Count != 3) - { - continue; - } - - int otherFirstIndex = otherIndices.Items[0]; - int otherSecondIndex = otherIndices.Items[1]; - int otherLastIndex = otherIndices.Items[2]; - - var otherPoly = convexPolygons.Items[ii]; - float x3 = otherPoly.Items[otherPoly.Count - 2], y3 = otherPoly.Items[otherPoly.Count - 1]; - - if (otherFirstIndex != firstIndex || otherSecondIndex != lastIndex) - { - continue; - } - - int winding1 = winding(prevPrevX, prevPrevY, prevX, prevY, x3, y3); - int winding2 = winding(x3, y3, firstX, firstY, secondX, secondY); - if (winding1 == winding && winding2 == winding) - { - otherPoly.Clear(); - otherIndices.Clear(); - polygon.Add(x3); - polygon.Add(y3); - polygonIndices.Add(otherLastIndex); - prevPrevX = prevX; - prevPrevY = prevY; - prevX = x3; - prevY = y3; - ii = 0; - } - } - } - - // Remove empty polygons that resulted from the merge step above. - for (int i = convexPolygons.Count - 1; i >= 0; --i) - { - polygon = convexPolygons.Items[i]; - if (polygon.Count == 0) - { - convexPolygons.RemoveAt(i); - polygonPool.Free(polygon); - polygonIndices = convexPolygonsIndices.Items[i]; - convexPolygonsIndices.RemoveAt(i); - polygonIndicesPool.Free(polygonIndices); - } - } - - return convexPolygons; - } + Vector > decompose(Vector& vertices, Vector& triangles); private: - Vector> _convexPolygons; - Vector> _convexPolygonsIndices; + Vector > _convexPolygons; + Vector > _convexPolygonsIndices; - Vector _indicesArray; + Vector _indices; Vector _isConcaveArray; Vector _triangles; - Pool> _polygonPool; - Pool> _polygonIndicesPool; + Pool > _polygonPool; + Pool > _polygonIndicesPool; - static bool isConcave(int index, int vertexCount, Vector vertices, Vector 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 bool isConcave(int index, int vertexCount, Vector& vertices, Vector& indices); - static bool 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 bool positiveArea(float p1x, float p1y, float p2x, float p2y, float p3x, float p3y); - 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; - } + static int winding(float p1x, float p1y, float p2x, float p2y, float p3x, float p3y); }; } diff --git a/spine-cpp/spine-cpp/src/spine/Triangulator.cpp b/spine-cpp/spine-cpp/src/spine/Triangulator.cpp index bb4d2ccfe..15455ea46 100644 --- a/spine-cpp/spine-cpp/src/spine/Triangulator.cpp +++ b/spine-cpp/spine-cpp/src/spine/Triangulator.cpp @@ -28,7 +28,299 @@ * POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ +#include + +#include + namespace Spine { - // TODO + Vector Triangulator::triangulate(Vector& vertices) + { + int vertexCount = static_cast(vertices.size() >> 1); + + Vector& indices = _indices; + indices.clear(); + indices.reserve(vertexCount); + for (int i = 0; i < vertexCount; ++i) + { + indices[i] = i; + } + + Vector& isConcaveArray = _isConcaveArray; + isConcaveArray.reserve(vertexCount); + for (int i = 0, n = vertexCount; i < n; ++i) + { + isConcaveArray[i] = isConcave(i, vertexCount, vertices, indices); + } + + Vector& triangles = _triangles; + triangles.clear(); + triangles.reserve(MAX(0, vertexCount - 2) << 2); + + while (vertexCount > 3) + { + // Find ear tip. + int previous = vertexCount - 1, i = 0, next = 1; + + // outer: + while (true) + { + if (!isConcaveArray[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 (int ii = (next + 1) % vertexCount; ii != previous; ii = (ii + 1) % vertexCount) + { + if (!isConcaveArray[ii]) + { + continue; + } + + int v = indices[ii] << 1; + float 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 outer; + } + } + } + } + break; + } + break_outer: + + if (next == 0) + { + do + { + if (!isConcaveArray[i]) + { + break; + } + i--; + } while (i > 0); + break; + } + + previous = i; + i = next; + next = (next + 1) % vertexCount; + } + + // Cut ear tip. + triangles.push_back(indices[(vertexCount + i - 1) % vertexCount]); + triangles.push_back(indices[i]); + triangles.push_back(indices[(i + 1) % vertexCount]); + indices.RemoveAt(i); + isConcaveArray.RemoveAt(i); + vertexCount--; + + int previousIndex = (vertexCount + i - 1) % vertexCount; + int nextIndex = i == vertexCount ? 0 : i; + isConcaveArray[previousIndex] = isConcave(previousIndex, vertexCount, vertices, indices); + isConcaveArray[nextIndex] = isConcave(nextIndex, vertexCount, vertices, indices); + } + + if (vertexCount == 3) + { + triangles.push_back(indices[2]); + triangles.push_back(indices[0]); + triangles.push_back(indices[1]); + } + + return triangles; + } + + Vector > Triangulator::decompose(Vector& vertices, Vector& triangles) + { + Vector >& convexPolygons = _convexPolygons; + for (int i = 0, n = convexPolygons.size(); i < n; ++i) + { + polygonPool.Free(convexPolygons[i]); + } + convexPolygons.Clear(); + + Vector >& convexPolygonsIndices = _convexPolygonsIndices; + for (int i = 0, n = convexPolygonsIndices.size(); i < n; ++i) + { + _polygonIndicesPool.free(convexPolygonsIndices[i]); + } + convexPolygonsIndices.clear(); + + var polygonIndices = _polygonIndicesPool.Obtain(); + polygonIndices.Clear(); + + var polygon = polygonPool.Obtain(); + polygon.Clear(); + + // Merge subsequent triangles if they form a triangle fan. + int fanBaseIndex = -1, lastwinding = 0; + int[] trianglesItems = triangles.Items; + for (int i = 0, n = triangles.Count; 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]; + + // If the base of the last triangle is the same as this triangle, check if they form a convex polygon (triangle fan). + var merged = false; + if (fanBaseIndex == t1) + { + int o = polygon.Count - 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) + { + polygon.Add(x3); + polygon.Add(y3); + polygonIndices.Add(t3); + merged = true; + } + } + + // Otherwise make this triangle the new base. + if (!merged) + { + if (polygon.Count > 0) + { + convexPolygons.Add(polygon); + convexPolygonsIndices.Add(polygonIndices); + } + else + { + polygonPool.Free(polygon); + _polygonIndicesPool.Free(polygonIndices); + } + + polygon = polygonPool.Obtain(); + polygon.Clear(); + polygon.Add(x1); + polygon.Add(y1); + polygon.Add(x2); + polygon.Add(y2); + polygon.Add(x3); + polygon.Add(y3); + polygonIndices = _polygonIndicesPool.obtain(); + polygonIndices.Clear(); + polygonIndices.Add(t1); + polygonIndices.Add(t2); + polygonIndices.Add(t3); + lastwinding = winding(x1, y1, x2, y2, x3, y3); + fanBaseIndex = t1; + } + } + + if (polygon.Count > 0) + { + convexPolygons.Add(polygon); + convexPolygonsIndices.Add(polygonIndices); + } + + // Go through the list of polygons and try to merge the remaining triangles with the found triangle fans. + for (int i = 0, n = convexPolygons.Count; i < n; ++i) + { + polygonIndices = convexPolygonsIndices.Items[i]; + if (polygonIndices.Count == 0) continue; + int firstIndex = polygonIndices.Items[0]; + int lastIndex = polygonIndices.Items[polygonIndices.Count - 1]; + + polygon = convexPolygons.Items[i]; + int o = polygon.Count - 4; + float[] p = polygon.Items; + float prevPrevX = p[o], prevPrevY = p[o + 1]; + float prevX = p[o + 2], prevY = p[o + 3]; + float firstX = p[0], firstY = p[1]; + float secondX = p[2], secondY = p[3]; + int winding = winding(prevPrevX, prevPrevY, prevX, prevY, firstX, firstY); + + for (int ii = 0; ii < n; ++ii) + { + if (ii == i) + { + continue; + } + + var otherIndices = convexPolygonsIndices.Items[ii]; + + if (otherIndices.Count != 3) + { + continue; + } + + int otherFirstIndex = otherIndices.Items[0]; + int otherSecondIndex = otherIndices.Items[1]; + int otherLastIndex = otherIndices.Items[2]; + + var otherPoly = convexPolygons.Items[ii]; + float x3 = otherPoly.Items[otherPoly.Count - 2], y3 = otherPoly.Items[otherPoly.Count - 1]; + + if (otherFirstIndex != firstIndex || otherSecondIndex != lastIndex) + { + continue; + } + + int winding1 = winding(prevPrevX, prevPrevY, prevX, prevY, x3, y3); + int winding2 = winding(x3, y3, firstX, firstY, secondX, secondY); + if (winding1 == winding && winding2 == winding) + { + otherPoly.Clear(); + otherIndices.Clear(); + polygon.Add(x3); + polygon.Add(y3); + polygonIndices.Add(otherLastIndex); + prevPrevX = prevX; + prevPrevY = prevY; + prevX = x3; + prevY = y3; + ii = 0; + } + } + } + + // Remove empty polygons that resulted from the merge step above. + for (int i = convexPolygons.Count - 1; i >= 0; --i) + { + polygon = convexPolygons.Items[i]; + if (polygon.Count == 0) + { + convexPolygons.RemoveAt(i); + polygonPool.Free(polygon); + polygonIndices = convexPolygonsIndices.Items[i]; + convexPolygonsIndices.RemoveAt(i); + _polygonIndicesPool.Free(polygonIndices); + } + } + + return convexPolygons; + } + + bool Triangulator::isConcave(int index, int vertexCount, Vector& vertices, Vector& 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]); + } + + bool Triangulator::positiveArea(float p1x, float p1y, float p2x, float p2y, float p3x, float p3y) + { + return p1x * (p3y - p2y) + p2x * (p1y - p3y) + p3x * (p2y - p1y) >= 0; + } + + int Triangulator::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; + } } From 949eb159447cfef231224c68481c7188cc5cbf7c Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Wed, 15 Nov 2017 19:07:09 -0500 Subject: [PATCH 35/83] wip --- spine-cpp/spine-cpp/include/spine/Atlas.h | 107 ++++++++++++ .../include/spine/AtlasAttachmentLoader.h | 39 +++-- .../spine-cpp/include/spine/Triangulator.h | 8 +- spine-cpp/spine-cpp/src/spine/Atlas.cpp | 39 +++++ .../spine-cpp/src/spine/Triangulator.cpp | 159 +++++++++--------- 5 files changed, 253 insertions(+), 99 deletions(-) create mode 100644 spine-cpp/spine-cpp/include/spine/Atlas.h create mode 100644 spine-cpp/spine-cpp/src/spine/Atlas.cpp diff --git a/spine-cpp/spine-cpp/include/spine/Atlas.h b/spine-cpp/spine-cpp/include/spine/Atlas.h new file mode 100644 index 000000000..8ffe4b41e --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/Atlas.h @@ -0,0 +1,107 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Atlas_h +#define Spine_Atlas_h + +#include + +#include + +namespace Spine +{ + enum Format + { + Format_Alpha, + Format_Intensity, + Format_LuminanceAlpha, + Format_RGB565, + Format_RGBA4444, + Format_RGB888, + Format_RGBA8888 + }; + + enum TextureFilter + { + TextureFilter_Nearest, + TextureFilter_Linear, + TextureFilter_MipMap, + TextureFilter_MipMapNearestNearest, + TextureFilter_MipMapLinearNearest, + TextureFilter_MipMapNearestLinear, + TextureFilter_MipMapLinearLinear + }; + + enum TextureWrap + { + TextureWrap_MirroredRepeat, + TextureWrap_ClampToEdge, + TextureWrap_Repeat + }; + + class AtlasPage + { + public: + std::string name; + Format format; + TextureFilter minFilter; + TextureFilter magFilter; + TextureWrap uWrap; + TextureWrap vWrap; + void* rendererObject; + int width, height; + }; + + class AtlasRegion + { + public: + AtlasPage page; + std::string name; + int x, y, width, height; + float u, v, u2, v2; + float offsetX, offsetY; + int originalWidth, originalHeight; + int index; + bool rotate; + Vector splits; + Vector pads; + }; + + class Atlas + { + public: + /// Returns the first region found with the specified name. This method uses string comparison to find the region, so the result + /// should be cached rather than calling this method multiple times. + /// @return The region, or NULL. + AtlasRegion* findRegion(std::string name); + }; +} + +#endif /* Spine_Atlas_h */ diff --git a/spine-cpp/spine-cpp/include/spine/AtlasAttachmentLoader.h b/spine-cpp/spine-cpp/include/spine/AtlasAttachmentLoader.h index 6c00de203..a2521cf73 100644 --- a/spine-cpp/spine-cpp/include/spine/AtlasAttachmentLoader.h +++ b/spine-cpp/spine-cpp/include/spine/AtlasAttachmentLoader.h @@ -33,8 +33,12 @@ #include +#include + namespace Spine { + class Atlas; + /// /// An AttachmentLoader that configures attachments using texture regions from an Atlas. /// See http://esotericsoftware.com/spine-loading-skeleton-data#JSON-and-binary-data about Loading Skeleton Data in the Spine Runtimes Guide. @@ -44,16 +48,12 @@ namespace Spine RTTI_DECL; public: - private: - Vector atlasArray; - - public AtlasAttachmentLoader (params Atlas[] atlasArray) + AtlasAttachmentLoader (Vector& inAtlasArray) : _atlasArray(inAtlasArray) { - if (atlasArray == NULL) throw new ArgumentNullException("atlas array cannot be NULL."); - _atlasArray = atlasArray; + // Empty } - public RegionAttachment newRegionAttachment(Skin skin, std::string name, std::string path) + RegionAttachment newRegionAttachment(Skin skin, std::string name, std::string path) { AtlasRegion* region = findRegion(path); if (region == NULL) throw new ArgumentException(std::string.Format("Region not found in atlas: {0} (region attachment: {1})", path, name)); @@ -69,7 +69,7 @@ namespace Spine return attachment; } - public MeshAttachment newMeshAttachment(Skin skin, std::string name, std::string path) + MeshAttachment newMeshAttachment(Skin skin, std::string name, std::string path) { AtlasRegion region = findRegion(path); if (region == NULL) throw new ArgumentException(std::string.Format("Region not found in atlas: {0} (region attachment: {1})", path, name)); @@ -91,41 +91,44 @@ namespace Spine return attachment; } - public BoundingBoxAttachment NewBoundingBoxAttachment (Skin skin, std::string name) + BoundingBoxAttachment NewBoundingBoxAttachment (Skin skin, std::string name) { return new BoundingBoxAttachment(name); } - public PathAttachment newPathAttachment(Skin skin, std::string name) + PathAttachment newPathAttachment(Skin skin, std::string name) { return new PathAttachment(name); } - public PointAttachment newPointAttachment(Skin skin, std::string name) + PointAttachment newPointAttachment(Skin skin, std::string name) { return new PointAttachment(name); } - public ClippingAttachment newClippingAttachment(Skin skin, std::string name) + ClippingAttachment newClippingAttachment(Skin skin, std::string name) { return new ClippingAttachment(name); } - public AtlasRegion findRegion (std::string name) + AtlasRegion* findRegion(std::string name) { - AtlasRegion region; + AtlasRegion* ret; - for (int i = 0; i < atlasArray.Length; i++) + for (int i = 0; i < _atlasArray.size(); i++) { - region = atlasArray[i].findRegion(name); - if (region != NULL) + ret = _atlasArray[i]->findRegion(name); + if (ret != NULL) { - return region; + return ret; } } return NULL; } + + private: + Vector _atlasArray; } } diff --git a/spine-cpp/spine-cpp/include/spine/Triangulator.h b/spine-cpp/spine-cpp/include/spine/Triangulator.h index ea9074580..1b41a6c3d 100644 --- a/spine-cpp/spine-cpp/include/spine/Triangulator.h +++ b/spine-cpp/spine-cpp/include/spine/Triangulator.h @@ -39,13 +39,13 @@ namespace Spine class Triangulator { public: - Vector triangulate(Vector& vertices); + Vector& triangulate(Vector& vertices); - Vector > decompose(Vector& vertices, Vector& triangles); + Vector* > decompose(Vector& vertices, Vector& triangles); private: - Vector > _convexPolygons; - Vector > _convexPolygonsIndices; + Vector* > _convexPolygons; + Vector* > _convexPolygonsIndices; Vector _indices; Vector _isConcaveArray; diff --git a/spine-cpp/spine-cpp/src/spine/Atlas.cpp b/spine-cpp/spine-cpp/src/spine/Atlas.cpp new file mode 100644 index 000000000..6984d7232 --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/Atlas.cpp @@ -0,0 +1,39 @@ +/****************************************************************************** +* Spine Runtimes Software License v2.5 +* +* Copyright (c) 2013-2016, Esoteric Software +* All rights reserved. +* +* You are granted a perpetual, non-exclusive, non-sublicensable, and +* non-transferable license to use, install, execute, and perform the Spine +* Runtimes software and derivative works solely for personal or internal +* use. Without the written permission of Esoteric Software (see Section 2 of +* the Spine Software License Agreement), you may not (a) modify, translate, +* adapt, or develop new applications using the Spine Runtimes or otherwise +* create derivative works or improvements of the Spine Runtimes or (b) remove, +* delete, alter, or obscure any trademarks or any copyright, trademark, patent, +* or other intellectual property or proprietary rights notices on or in the +* Software, including any copy thereof. Redistributions in binary or source +* form must include this license and terms. +* +* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +#include + +namespace Spine +{ + AtlasRegion* Atlas::findRegion(std::string name) + { + return NULL; + } +} diff --git a/spine-cpp/spine-cpp/src/spine/Triangulator.cpp b/spine-cpp/spine-cpp/src/spine/Triangulator.cpp index 15455ea46..4b5983dc9 100644 --- a/spine-cpp/spine-cpp/src/spine/Triangulator.cpp +++ b/spine-cpp/spine-cpp/src/spine/Triangulator.cpp @@ -34,7 +34,7 @@ namespace Spine { - Vector Triangulator::triangulate(Vector& vertices) + Vector& Triangulator::triangulate(Vector& vertices) { int vertexCount = static_cast(vertices.size() >> 1); @@ -79,7 +79,7 @@ namespace Spine } int v = indices[ii] << 1; - float vx = vertices[v], vy = vertices[v + 1]; + float& vx = vertices[v], vy = vertices[v + 1]; if (positiveArea(p3x, p3y, p1x, p1y, vx, vy)) { if (positiveArea(p1x, p1y, p2x, p2y, vx, vy)) @@ -117,8 +117,8 @@ namespace Spine triangles.push_back(indices[(vertexCount + i - 1) % vertexCount]); triangles.push_back(indices[i]); triangles.push_back(indices[(i + 1) % vertexCount]); - indices.RemoveAt(i); - isConcaveArray.RemoveAt(i); + indices.erase(i); + isConcaveArray.erase(i); vertexCount--; int previousIndex = (vertexCount + i - 1) % vertexCount; @@ -137,51 +137,52 @@ namespace Spine return triangles; } - Vector > Triangulator::decompose(Vector& vertices, Vector& triangles) + Vector* > Triangulator::decompose(Vector& vertices, Vector& triangles) { - Vector >& convexPolygons = _convexPolygons; - for (int i = 0, n = convexPolygons.size(); i < n; ++i) + Vector* >&convexPolygons = _convexPolygons; + for (size_t i = 0, n = convexPolygons.size(); i < n; ++i) { - polygonPool.Free(convexPolygons[i]); + _polygonPool.free(convexPolygons[i]); } - convexPolygons.Clear(); + convexPolygons.clear(); - Vector >& convexPolygonsIndices = _convexPolygonsIndices; - for (int i = 0, n = convexPolygonsIndices.size(); i < n; ++i) + Vector* > convexPolygonsIndices = _convexPolygonsIndices; + for (size_t i = 0, n = convexPolygonsIndices.size(); i < n; ++i) { _polygonIndicesPool.free(convexPolygonsIndices[i]); } convexPolygonsIndices.clear(); - var polygonIndices = _polygonIndicesPool.Obtain(); - polygonIndices.Clear(); + Vector* polygonIndicesP = _polygonIndicesPool.obtain(); + Vector& polygonIndices = *polygonIndicesP; + polygonIndices.clear(); - var polygon = polygonPool.Obtain(); - polygon.Clear(); + Vector* polygonP = _polygonPool.obtain(); + Vector& polygon = *polygonP; + polygon.clear(); // Merge subsequent triangles if they form a triangle fan. int fanBaseIndex = -1, lastwinding = 0; - int[] trianglesItems = triangles.Items; - for (int i = 0, n = triangles.Count; i < n; i += 3) + for (size_t i = 0, n = triangles.size(); i < n; i += 3) { - int t1 = trianglesItems[i] << 1, t2 = trianglesItems[i + 1] << 1, t3 = trianglesItems[i + 2] << 1; + int t1 = triangles[i] << 1, t2 = triangles[i + 1] << 1, t3 = triangles[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]; // If the base of the last triangle is the same as this triangle, check if they form a convex polygon (triangle fan). - var merged = false; + bool merged = false; if (fanBaseIndex == t1) { - int o = polygon.Count - 4; - float[] p = polygon.Items; + size_t o = polygon.size() - 4; + Vector& p = polygon; 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) { - polygon.Add(x3); - polygon.Add(y3); - polygonIndices.Add(t3); + polygon.push_back(x3); + polygon.push_back(y3); + polygonIndices.push_back(t3); merged = true; } } @@ -189,57 +190,59 @@ namespace Spine // Otherwise make this triangle the new base. if (!merged) { - if (polygon.Count > 0) + if (polygon.size() > 0) { - convexPolygons.Add(polygon); - convexPolygonsIndices.Add(polygonIndices); + convexPolygons.push_back(&polygon); + convexPolygonsIndices.push_back(&polygonIndices); } else { - polygonPool.Free(polygon); - _polygonIndicesPool.Free(polygonIndices); + _polygonPool.free(&polygon); + _polygonIndicesPool.free(&polygonIndices); } - polygon = polygonPool.Obtain(); - polygon.Clear(); - polygon.Add(x1); - polygon.Add(y1); - polygon.Add(x2); - polygon.Add(y2); - polygon.Add(x3); - polygon.Add(y3); - polygonIndices = _polygonIndicesPool.obtain(); - polygonIndices.Clear(); - polygonIndices.Add(t1); - polygonIndices.Add(t2); - polygonIndices.Add(t3); + polygon = *_polygonPool.obtain(); + polygon.clear(); + polygon.push_back(x1); + polygon.push_back(y1); + polygon.push_back(x2); + polygon.push_back(y2); + polygon.push_back(x3); + polygon.push_back(y3); + polygonIndices = *_polygonIndicesPool.obtain(); + polygonIndices.clear(); + polygonIndices.push_back(t1); + polygonIndices.push_back(t2); + polygonIndices.push_back(t3); lastwinding = winding(x1, y1, x2, y2, x3, y3); fanBaseIndex = t1; } } - if (polygon.Count > 0) + if (polygon.size() > 0) { - convexPolygons.Add(polygon); - convexPolygonsIndices.Add(polygonIndices); + convexPolygons.push_back(&polygon); + convexPolygonsIndices.push_back(&polygonIndices); } // Go through the list of polygons and try to merge the remaining triangles with the found triangle fans. - for (int i = 0, n = convexPolygons.Count; i < n; ++i) + for (size_t i = 0, n = convexPolygons.size(); i < n; ++i) { - polygonIndices = convexPolygonsIndices.Items[i]; - if (polygonIndices.Count == 0) continue; - int firstIndex = polygonIndices.Items[0]; - int lastIndex = polygonIndices.Items[polygonIndices.Count - 1]; + polygonIndicesP = convexPolygonsIndices[i]; + polygonIndices = *polygonIndicesP; - polygon = convexPolygons.Items[i]; - int o = polygon.Count - 4; - float[] p = polygon.Items; + if (polygonIndices.size() == 0) continue; + int firstIndex = polygonIndices[0]; + int lastIndex = polygonIndices[polygonIndices.size() - 1]; + + polygon = *convexPolygons[i]; + size_t o = polygon.size() - 4; + Vector& p = polygon; float prevPrevX = p[o], prevPrevY = p[o + 1]; float prevX = p[o + 2], prevY = p[o + 3]; float firstX = p[0], firstY = p[1]; float secondX = p[2], secondY = p[3]; - int winding = winding(prevPrevX, prevPrevY, prevX, prevY, firstX, firstY); + int winding0 = winding(prevPrevX, prevPrevY, prevX, prevY, firstX, firstY); for (int ii = 0; ii < n; ++ii) { @@ -248,19 +251,22 @@ namespace Spine continue; } - var otherIndices = convexPolygonsIndices.Items[ii]; + Vector* otherIndicesP = convexPolygonsIndices[ii]; + Vector& otherIndices = *otherIndicesP; - if (otherIndices.Count != 3) + if (otherIndices.size() != 3) { continue; } - int otherFirstIndex = otherIndices.Items[0]; - int otherSecondIndex = otherIndices.Items[1]; - int otherLastIndex = otherIndices.Items[2]; + int otherFirstIndex = otherIndices[0]; + int otherSecondIndex = otherIndices[1]; + int otherLastIndex = otherIndices[2]; - var otherPoly = convexPolygons.Items[ii]; - float x3 = otherPoly.Items[otherPoly.Count - 2], y3 = otherPoly.Items[otherPoly.Count - 1]; + Vector* otherPolyP = convexPolygons[ii]; + Vector& otherPoly = *otherPolyP; + + float x3 = otherPoly[otherPoly.size() - 2], y3 = otherPoly[otherPoly.size() - 1]; if (otherFirstIndex != firstIndex || otherSecondIndex != lastIndex) { @@ -269,13 +275,13 @@ namespace Spine int winding1 = winding(prevPrevX, prevPrevY, prevX, prevY, x3, y3); int winding2 = winding(x3, y3, firstX, firstY, secondX, secondY); - if (winding1 == winding && winding2 == winding) + if (winding1 == winding0 && winding2 == winding0) { - otherPoly.Clear(); - otherIndices.Clear(); - polygon.Add(x3); - polygon.Add(y3); - polygonIndices.Add(otherLastIndex); + otherPoly.clear(); + otherIndices.clear(); + polygon.push_back(x3); + polygon.push_back(y3); + polygonIndices.push_back(otherLastIndex); prevPrevX = prevX; prevPrevY = prevY; prevX = x3; @@ -286,16 +292,16 @@ namespace Spine } // Remove empty polygons that resulted from the merge step above. - for (int i = convexPolygons.Count - 1; i >= 0; --i) + for (int i = static_cast(convexPolygons.size()) - 1; i >= 0; --i) { - polygon = convexPolygons.Items[i]; - if (polygon.Count == 0) + polygon = *convexPolygons[i]; + if (polygon.size() == 0) { - convexPolygons.RemoveAt(i); - polygonPool.Free(polygon); - polygonIndices = convexPolygonsIndices.Items[i]; - convexPolygonsIndices.RemoveAt(i); - _polygonIndicesPool.Free(polygonIndices); + convexPolygons.erase(i); + _polygonPool.free(&polygon); + polygonIndices = *convexPolygonsIndices[i]; + convexPolygonsIndices.erase(i); + _polygonIndicesPool.free(&polygonIndices); } } @@ -308,8 +314,7 @@ namespace Spine 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]); + return !positiveArea(vertices[previous], vertices[previous + 1], vertices[current], vertices[current + 1], vertices[next], vertices[next + 1]); } bool Triangulator::positiveArea(float p1x, float p1y, float p2x, float p2y, float p3x, float p3y) From c4b7df2c2c6149a30679b9718dfd1627bd2b2394 Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Thu, 16 Nov 2017 14:02:39 -0500 Subject: [PATCH 36/83] The power of commenting stuff out! --- .../include/spine/AnimationStateData.h | 10 +- .../include/spine/AtlasAttachmentLoader.h | 148 ++++----- .../include/spine/AttachmentLoader.h | 2 +- .../include/spine/AttachmentTimeline.h | 114 +++---- .../spine-cpp/include/spine/ColorTimeline.h | 198 ++++++------ .../spine-cpp/include/spine/DeformTimeline.h | 284 +++++++++--------- .../include/spine/DrawOrderTimeline.h | 110 +++---- .../spine-cpp/include/spine/EventTimeline.h | 98 +++--- .../include/spine/IkConstraintTimeline.h | 140 ++++----- .../include/spine/PathConstraintMixTimeline.h | 140 ++++----- .../spine/PathConstraintPositionTimeline.h | 120 ++++---- .../spine/PathConstraintSpacingTimeline.h | 86 +++--- .../spine-cpp/include/spine/PointAttachment.h | 3 +- .../spine-cpp/include/spine/ScaleTimeline.h | 134 ++++----- .../spine-cpp/include/spine/ShearTimeline.h | 100 +++--- .../spine/TransformConstraintTimeline.h | 174 +++++------ .../include/spine/TranslateTimeline.h | 164 +++++----- .../include/spine/TwoColorTimeline.h | 277 +++++++++-------- .../src/spine/AnimationStateData.cpp | 27 +- 19 files changed, 1167 insertions(+), 1162 deletions(-) diff --git a/spine-cpp/spine-cpp/include/spine/AnimationStateData.h b/spine-cpp/spine-cpp/include/spine/AnimationStateData.h index 961ed7617..d0b785094 100644 --- a/spine-cpp/spine-cpp/include/spine/AnimationStateData.h +++ b/spine-cpp/spine-cpp/include/spine/AnimationStateData.h @@ -59,22 +59,22 @@ namespace Spine /// Sets a mix duration when changing from the specified animation to the other. /// See TrackEntry.MixDuration. - void setMix(Animation& from, Animation& to, float duration); + void setMix(Animation* from, Animation* to, float duration); /// /// The mix duration to use when changing from the specified animation to the other, /// or the DefaultMix if no mix duration has been set. /// - float getMix(Animation& from, Animation& to); + float getMix(Animation* from, Animation* to); private: class AnimationPair { public: - Animation& _a1; - Animation& _a2; + Animation* _a1; + Animation* _a2; - AnimationPair(Animation& a1, Animation& a2); + AnimationPair(Animation* a1 = NULL, Animation* a2 = NULL); bool operator==(const AnimationPair &other) const; }; diff --git a/spine-cpp/spine-cpp/include/spine/AtlasAttachmentLoader.h b/spine-cpp/spine-cpp/include/spine/AtlasAttachmentLoader.h index a2521cf73..d8f820111 100644 --- a/spine-cpp/spine-cpp/include/spine/AtlasAttachmentLoader.h +++ b/spine-cpp/spine-cpp/include/spine/AtlasAttachmentLoader.h @@ -53,83 +53,83 @@ namespace Spine // Empty } - RegionAttachment newRegionAttachment(Skin skin, std::string name, std::string path) - { - AtlasRegion* region = findRegion(path); - if (region == NULL) throw new ArgumentException(std::string.Format("Region not found in atlas: {0} (region attachment: {1})", path, name)); - RegionAttachment attachment = new RegionAttachment(name); - attachment.RendererObject = region; - attachment.SetUVs(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 attachment; - } - - MeshAttachment newMeshAttachment(Skin skin, std::string name, std::string path) - { - AtlasRegion region = findRegion(path); - if (region == NULL) throw new ArgumentException(std::string.Format("Region not found in atlas: {0} (region attachment: {1})", path, name)); - - MeshAttachment attachment = new MeshAttachment(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.regionOffsetX = region.offsetX; - attachment.regionOffsetY = region.offsetY; - attachment.regionWidth = region.width; - attachment.regionHeight = region.height; - attachment.regionOriginalWidth = region.originalWidth; - attachment.regionOriginalHeight = region.originalHeight; - - return attachment; - } - - BoundingBoxAttachment NewBoundingBoxAttachment (Skin skin, std::string name) - { - return new BoundingBoxAttachment(name); - } - - PathAttachment newPathAttachment(Skin skin, std::string name) - { - return new PathAttachment(name); - } - - PointAttachment newPointAttachment(Skin skin, std::string name) - { - return new PointAttachment(name); - } - - ClippingAttachment newClippingAttachment(Skin skin, std::string name) - { - return new ClippingAttachment(name); - } - - AtlasRegion* findRegion(std::string name) - { - AtlasRegion* ret; - - for (int i = 0; i < _atlasArray.size(); i++) - { - ret = _atlasArray[i]->findRegion(name); - if (ret != NULL) - { - return ret; - } - } - - return NULL; - } +// RegionAttachment newRegionAttachment(Skin skin, std::string name, std::string path) +// { +// AtlasRegion* region = findRegion(path); +// if (region == NULL) throw new ArgumentException(std::string.Format("Region not found in atlas: {0} (region attachment: {1})", path, name)); +// RegionAttachment attachment = new RegionAttachment(name); +// attachment.RendererObject = region; +// attachment.SetUVs(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 attachment; +// } +// +// MeshAttachment newMeshAttachment(Skin skin, std::string name, std::string path) +// { +// AtlasRegion region = findRegion(path); +// if (region == NULL) throw new ArgumentException(std::string.Format("Region not found in atlas: {0} (region attachment: {1})", path, name)); +// +// MeshAttachment attachment = new MeshAttachment(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.regionOffsetX = region.offsetX; +// attachment.regionOffsetY = region.offsetY; +// attachment.regionWidth = region.width; +// attachment.regionHeight = region.height; +// attachment.regionOriginalWidth = region.originalWidth; +// attachment.regionOriginalHeight = region.originalHeight; +// +// return attachment; +// } +// +// BoundingBoxAttachment NewBoundingBoxAttachment (Skin skin, std::string name) +// { +// return new BoundingBoxAttachment(name); +// } +// +// PathAttachment newPathAttachment(Skin skin, std::string name) +// { +// return new PathAttachment(name); +// } +// +// PointAttachment newPointAttachment(Skin skin, std::string name) +// { +// return new PointAttachment(name); +// } +// +// ClippingAttachment newClippingAttachment(Skin skin, std::string name) +// { +// return new ClippingAttachment(name); +// } +// +// AtlasRegion* findRegion(std::string name) +// { +// AtlasRegion* ret; +// +// for (int i = 0; i < _atlasArray.size(); i++) +// { +// ret = _atlasArray[i]->findRegion(name); +// if (ret != NULL) +// { +// return ret; +// } +// } +// +// return NULL; +// } private: Vector _atlasArray; - } + }; } #endif /* Spine_AtlasAttachmentLoader_h */ diff --git a/spine-cpp/spine-cpp/include/spine/AttachmentLoader.h b/spine-cpp/spine-cpp/include/spine/AttachmentLoader.h index aa9373314..b04b5f929 100644 --- a/spine-cpp/spine-cpp/include/spine/AttachmentLoader.h +++ b/spine-cpp/spine-cpp/include/spine/AttachmentLoader.h @@ -64,7 +64,7 @@ namespace Spine virtual PointAttachment* newPointAttachment(Skin& skin, std::string name) = 0; virtual ClippingAttachment* newClippingAttachment(Skin& skin, std::string name) = 0; - } + }; } #endif /* Spine_AttachmentLoader_h */ diff --git a/spine-cpp/spine-cpp/include/spine/AttachmentTimeline.h b/spine-cpp/spine-cpp/include/spine/AttachmentTimeline.h index 8f026e5cd..8268b47d1 100644 --- a/spine-cpp/spine-cpp/include/spine/AttachmentTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/AttachmentTimeline.h @@ -55,68 +55,68 @@ namespace Spine _attachmentNames.reserve(frameCount); } - virtual int getPropertyId() - { - return ((int)TimelineType_Attachment << 24) + slotIndex; - } - - /// Sets the time and value of the specified keyframe. - void setFrame(int frameIndex, float time, std::string attachmentName) - { - frames[frameIndex] = time; - attachmentNames[frameIndex] = attachmentName; - } - - void apply(Skeleton& skeleton, float lastTime, float time, Vector firedEvents, float alpha, MixPose pose, MixDirection direction) - { - std::string attachmentName; - Slot slot = skeleton.slots.Items[slotIndex]; - if (direction == MixDirection_Out && pose == MixPose_Setup) - { - attachmentName = slot.data.attachmentName; - slot.Attachment = attachmentName == NULL ? NULL : skeleton.getAttachment(slotIndex, attachmentName); - return; - } - - float[] frames = _frames; - if (time < frames[0]) - { - // Time is before first frame. - if (pose == MixPose_Setup) - { - attachmentName = slot.data.attachmentName; - slot.Attachment = attachmentName == NULL ? NULL : skeleton.getAttachment(slotIndex, attachmentName); - } - return; - } - - int frameIndex; - if (time >= frames[frames.Length - 1]) // Time is after last frame. - { - frameIndex = frames.Length - 1; - } - else - { - frameIndex = Animation::binarySearch(frames, time, 1) - 1; - } - - attachmentName = attachmentNames[frameIndex]; - slot.Attachment = attachmentName == NULL ? NULL : skeleton.getAttachment(slotIndex, attachmentName); - } - - int getSlotIndex() { return _slotIndex; } - void setSlotIndex(int inValue) { _slotIndex = inValue; } - Vector& getFrames() { return _frames; } - void setFrames(Vector& inValue) { _frames = inValue; } // time, ... - Vector getAttachmentNames() { return _attachmentNames; } - set { attachmentNames = inValue; } - int getFrameCount() { return frames.Length; } +// virtual int getPropertyId() +// { +// return ((int)TimelineType_Attachment << 24) + slotIndex; +// } +// +// /// Sets the time and value of the specified keyframe. +// void setFrame(int frameIndex, float time, std::string attachmentName) +// { +// frames[frameIndex] = time; +// attachmentNames[frameIndex] = attachmentName; +// } +// +// void apply(Skeleton& skeleton, float lastTime, float time, Vector firedEvents, float alpha, MixPose pose, MixDirection direction) +// { +// std::string attachmentName; +// Slot slot = skeleton.slots.Items[slotIndex]; +// if (direction == MixDirection_Out && pose == MixPose_Setup) +// { +// attachmentName = slot.data.attachmentName; +// slot.Attachment = attachmentName == NULL ? NULL : skeleton.getAttachment(slotIndex, attachmentName); +// return; +// } +// +// float[] frames = _frames; +// if (time < frames[0]) +// { +// // Time is before first frame. +// if (pose == MixPose_Setup) +// { +// attachmentName = slot.data.attachmentName; +// slot.Attachment = attachmentName == NULL ? NULL : skeleton.getAttachment(slotIndex, attachmentName); +// } +// return; +// } +// +// int frameIndex; +// if (time >= frames[frames.Length - 1]) // Time is after last frame. +// { +// frameIndex = frames.Length - 1; +// } +// else +// { +// frameIndex = Animation::binarySearch(frames, time, 1) - 1; +// } +// +// attachmentName = attachmentNames[frameIndex]; +// slot.Attachment = attachmentName == NULL ? NULL : skeleton.getAttachment(slotIndex, attachmentName); +// } +// +// int getSlotIndex() { return _slotIndex; } +// void setSlotIndex(int inValue) { _slotIndex = inValue; } +// Vector& getFrames() { return _frames; } +// void setFrames(Vector& inValue) { _frames = inValue; } // time, ... +// Vector getAttachmentNames() { return _attachmentNames; } +// set { attachmentNames = inValue; } +// int getFrameCount() { return frames.Length; } private: int _slotIndex; Vector _frames; Vector _attachmentNames; - } + }; } #endif /* Spine_AttachmentTimeline_h */ diff --git a/spine-cpp/spine-cpp/include/spine/ColorTimeline.h b/spine-cpp/spine-cpp/include/spine/ColorTimeline.h index e48bb81c4..8da2c5700 100644 --- a/spine-cpp/spine-cpp/include/spine/ColorTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/ColorTimeline.h @@ -39,105 +39,105 @@ namespace Spine { RTTI_DECL; - public const int ENTRIES = 5; - protected const int PREV_TIME = -5, PREV_R = -4, PREV_G = -3, PREV_B = -2, PREV_A = -1; - protected const int R = 1, G = 2, B = 3, A = 4; - - internal int slotIndex; - internal float[] frames; - - public int SlotIndex { return slotIndex; } set { slotIndex = inValue; } - public float[] Frames { return frames; } set { frames = inValue; } // time, r, g, b, a, ... - - override public int PropertyId { - get { return ((int)TimelineType.Color << 24) + slotIndex; } - } - - public ColorTimeline (int frameCount) - : base(frameCount) { - frames = new float[frameCount * ENTRIES]; - } - - /// Sets the time and value of the specified keyframe. - public void SetFrame (int frameIndex, float time, float r, float g, float b, float a) { - frameIndex *= ENTRIES; - frames[frameIndex] = time; - frames[frameIndex + R] = r; - frames[frameIndex + G] = g; - frames[frameIndex + B] = b; - frames[frameIndex + A] = a; - } - - override public void Apply (Skeleton skeleton, float lastTime, float time, Vector firedEvents, float alpha, MixPose pose, MixDirection direction) { - Slot slot = skeleton.slots.Items[slotIndex]; - float[] frames = _frames; - if (time < frames[0]) { - var slotData = slot.data; - switch (pose) { - case MixPose_Setup: - slot.r = slotData.r; - slot.g = slotData.g; - slot.b = slotData.b; - slot.a = slotData.a; - return; - case MixPose_Current: - slot.r += (slot.r - slotData.r) * alpha; - slot.g += (slot.g - slotData.g) * alpha; - slot.b += (slot.b - slotData.b) * alpha; - slot.a += (slot.a - slotData.a) * alpha; - return; - } - return; - } - - float r, g, b, a; - if (time >= frames[frames.Length - ENTRIES]) { // Time is after last frame. - int i = frames.Length; - r = frames[i + PREV_R]; - g = frames[i + PREV_G]; - b = frames[i + PREV_B]; - a = frames[i + PREV_A]; - } else { - // Interpolate between the previous frame and the current frame. - int frame = Animation.BinarySearch(frames, time, ENTRIES); - r = frames[frame + PREV_R]; - g = frames[frame + PREV_G]; - b = frames[frame + PREV_B]; - a = frames[frame + PREV_A]; - float frameTime = frames[frame]; - float percent = GetCurvePercent(frame / ENTRIES - 1, - 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime)); - - r += (frames[frame + R] - r) * percent; - g += (frames[frame + G] - g) * percent; - b += (frames[frame + B] - b) * percent; - a += (frames[frame + A] - a) * percent; - } - if (alpha == 1) { - slot.r = r; - slot.g = g; - slot.b = b; - slot.a = a; - } else { - float br, bg, bb, ba; - if (pose == MixPose_Setup) { - br = slot.data.r; - bg = slot.data.g; - bb = slot.data.b; - ba = slot.data.a; - } else { - br = slot.r; - bg = slot.g; - bb = slot.b; - ba = slot.a; - } - slot.r = br + ((r - br) * alpha); - slot.g = bg + ((g - bg) * alpha); - slot.b = bb + ((b - bb) * alpha); - slot.a = ba + ((a - ba) * alpha); - } - } - } +// public const int ENTRIES = 5; +// protected const int PREV_TIME = -5, PREV_R = -4, PREV_G = -3, PREV_B = -2, PREV_A = -1; +// protected const int R = 1, G = 2, B = 3, A = 4; +// +// internal int slotIndex; +// internal float[] frames; +// +// public int SlotIndex { return slotIndex; } set { slotIndex = inValue; } +// public float[] Frames { return frames; } set { frames = inValue; } // time, r, g, b, a, ... +// +// override public int PropertyId { +// get { return ((int)TimelineType.Color << 24) + slotIndex; } +// } +// +// public ColorTimeline (int frameCount) +// : base(frameCount) { +// frames = new float[frameCount * ENTRIES]; +// } +// +// /// Sets the time and value of the specified keyframe. +// public void SetFrame (int frameIndex, float time, float r, float g, float b, float a) { +// frameIndex *= ENTRIES; +// frames[frameIndex] = time; +// frames[frameIndex + R] = r; +// frames[frameIndex + G] = g; +// frames[frameIndex + B] = b; +// frames[frameIndex + A] = a; +// } +// +// override public void Apply (Skeleton skeleton, float lastTime, float time, Vector firedEvents, float alpha, MixPose pose, MixDirection direction) { +// Slot slot = skeleton.slots.Items[slotIndex]; +// float[] frames = _frames; +// if (time < frames[0]) { +// var slotData = slot.data; +// switch (pose) { +// case MixPose_Setup: +// slot.r = slotData.r; +// slot.g = slotData.g; +// slot.b = slotData.b; +// slot.a = slotData.a; +// return; +// case MixPose_Current: +// slot.r += (slot.r - slotData.r) * alpha; +// slot.g += (slot.g - slotData.g) * alpha; +// slot.b += (slot.b - slotData.b) * alpha; +// slot.a += (slot.a - slotData.a) * alpha; +// return; +// } +// return; +// } +// +// float r, g, b, a; +// if (time >= frames[frames.Length - ENTRIES]) { // Time is after last frame. +// int i = frames.Length; +// r = frames[i + PREV_R]; +// g = frames[i + PREV_G]; +// b = frames[i + PREV_B]; +// a = frames[i + PREV_A]; +// } else { +// // Interpolate between the previous frame and the current frame. +// int frame = Animation.BinarySearch(frames, time, ENTRIES); +// r = frames[frame + PREV_R]; +// g = frames[frame + PREV_G]; +// b = frames[frame + PREV_B]; +// a = frames[frame + PREV_A]; +// float frameTime = frames[frame]; +// float percent = GetCurvePercent(frame / ENTRIES - 1, +// 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime)); +// +// r += (frames[frame + R] - r) * percent; +// g += (frames[frame + G] - g) * percent; +// b += (frames[frame + B] - b) * percent; +// a += (frames[frame + A] - a) * percent; +// } +// if (alpha == 1) { +// slot.r = r; +// slot.g = g; +// slot.b = b; +// slot.a = a; +// } else { +// float br, bg, bb, ba; +// if (pose == MixPose_Setup) { +// br = slot.data.r; +// bg = slot.data.g; +// bb = slot.data.b; +// ba = slot.data.a; +// } else { +// br = slot.r; +// bg = slot.g; +// bb = slot.b; +// ba = slot.a; +// } +// slot.r = br + ((r - br) * alpha); +// slot.g = bg + ((g - bg) * alpha); +// slot.b = bb + ((b - bb) * alpha); +// slot.a = ba + ((a - ba) * alpha); +// } +// } + }; } #endif /* Spine_ColorTimeline_h */ diff --git a/spine-cpp/spine-cpp/include/spine/DeformTimeline.h b/spine-cpp/spine-cpp/include/spine/DeformTimeline.h index bf12cbfe8..90d768b34 100644 --- a/spine-cpp/spine-cpp/include/spine/DeformTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/DeformTimeline.h @@ -39,148 +39,148 @@ namespace Spine { RTTI_DECL; - internal int slotIndex; - internal float[] frames; - internal float[][] frameVertices; - internal VertexAttachment attachment; - - public int SlotIndex { return slotIndex; } set { slotIndex = inValue; } - public float[] Frames { return frames; } set { frames = inValue; } // time, ... - public float[][] Vertices { return frameVertices; } set { frameVertices = inValue; } - public VertexAttachment Attachment { return attachment; } set { attachment = inValue; } - - override public int PropertyId { - get { return ((int)TimelineType.Deform << 24) + attachment.id + slotIndex; } - } - - public DeformTimeline (int frameCount) - : base(frameCount) { - frames = new float[frameCount]; - frameVertices = new float[frameCount][]; - } - - /// Sets the time and value of the specified keyframe. - public void SetFrame (int frameIndex, float time, float[] vertices) { - frames[frameIndex] = time; - frameVertices[frameIndex] = vertices; - } - - override public void Apply (Skeleton skeleton, float lastTime, float time, Vector firedEvents, float alpha, MixPose pose, MixDirection direction) { - Slot slot = skeleton.slots.Items[slotIndex]; - VertexAttachment vertexAttachment = slot.attachment as VertexAttachment; - if (vertexAttachment == NULL || !vertexAttachment.ApplyDeform(attachment)) return; - - var verticesArray = slot.attachmentVertices; - if (verticesArray.Count == 0) alpha = 1; - - float[][] frameVertices = _frameVertices; - int vertexCount = frameVertices[0].Length; - float[] frames = _frames; - float[] vertices; - - if (time < frames[0]) { - - switch (pose) { - case MixPose_Setup: - verticesArray.Clear(); - return; - case MixPose_Current: - if (alpha == 1) { - verticesArray.Clear(); - return; - } - - // verticesArray.SetSize(vertexCount) // Ensure size and preemptively set count. - if (verticesArray.Capacity < vertexCount) verticesArray.Capacity = vertexCount; - verticesArray.Count = vertexCount; - vertices = verticesArray.Items; - - if (vertexAttachment.bones == NULL) { - // Unweighted vertex positions. - float[] setupVertices = vertexAttachment.vertices; - for (int i = 0; i < vertexCount; i++) - vertices[i] += (setupVertices[i] - vertices[i]) * alpha; - } else { - // Weighted deform offsets. - alpha = 1 - alpha; - for (int i = 0; i < vertexCount; i++) - vertices[i] *= alpha; - } - return; - default: - return; - } - - } - - // verticesArray.SetSize(vertexCount) // Ensure size and preemptively set count. - if (verticesArray.Capacity < vertexCount) verticesArray.Capacity = vertexCount; - verticesArray.Count = vertexCount; - vertices = verticesArray.Items; - - if (time >= frames[frames.Length - 1]) { // Time is after last frame. - float[] lastVertices = frameVertices[frames.Length - 1]; - if (alpha == 1) { - // Vertex positions or deform offsets, no alpha. - Array.Copy(lastVertices, 0, vertices, 0, vertexCount); - } else if (pose == MixPose_Setup) { - if (vertexAttachment.bones == NULL) { - // Unweighted vertex positions, with alpha. - float[] setupVertices = vertexAttachment.vertices; - for (int i = 0; i < vertexCount; i++) { - float setup = setupVertices[i]; - vertices[i] = setup + (lastVertices[i] - setup) * alpha; - } - } else { - // Weighted deform offsets, with alpha. - for (int i = 0; i < vertexCount; i++) - vertices[i] = lastVertices[i] * alpha; - } - } else { - // Vertex positions or deform offsets, with alpha. - for (int i = 0; i < vertexCount; i++) - vertices[i] += (lastVertices[i] - vertices[i]) * alpha; - } - return; - } - - // Interpolate between the previous frame and the current frame. - int frame = Animation.BinarySearch(frames, time); - float[] prevVertices = frameVertices[frame - 1]; - float[] nextVertices = frameVertices[frame]; - float frameTime = frames[frame]; - float percent = GetCurvePercent(frame - 1, 1 - (time - frameTime) / (frames[frame - 1] - frameTime)); - - if (alpha == 1) { - // Vertex positions or deform offsets, no alpha. - for (int i = 0; i < vertexCount; i++) { - float prev = prevVertices[i]; - vertices[i] = prev + (nextVertices[i] - prev) * percent; - } - } else if (pose == MixPose_Setup) { - if (vertexAttachment.bones == NULL) { - // Unweighted vertex positions, with alpha. - var setupVertices = vertexAttachment.vertices; - for (int i = 0; i < vertexCount; i++) { - float prev = prevVertices[i], setup = setupVertices[i]; - vertices[i] = setup + (prev + (nextVertices[i] - prev) * percent - setup) * alpha; - } - } else { - // Weighted deform offsets, with alpha. - for (int i = 0; i < vertexCount; i++) { - float prev = prevVertices[i]; - vertices[i] = (prev + (nextVertices[i] - prev) * percent) * alpha; - } - } - } else { - // Vertex positions or deform offsets, with alpha. - for (int i = 0; i < vertexCount; i++) { - float prev = prevVertices[i]; - vertices[i] += (prev + (nextVertices[i] - prev) * percent - vertices[i]) * alpha; - } - } - } - } +// internal int slotIndex; +// internal float[] frames; +// internal float[][] frameVertices; +// internal VertexAttachment attachment; +// +// public int SlotIndex { return slotIndex; } set { slotIndex = inValue; } +// public float[] Frames { return frames; } set { frames = inValue; } // time, ... +// public float[][] Vertices { return frameVertices; } set { frameVertices = inValue; } +// public VertexAttachment Attachment { return attachment; } set { attachment = inValue; } +// +// override public int PropertyId { +// get { return ((int)TimelineType.Deform << 24) + attachment.id + slotIndex; } +// } +// +// public DeformTimeline (int frameCount) +// : base(frameCount) { +// frames = new float[frameCount]; +// frameVertices = new float[frameCount][]; +// } +// +// /// Sets the time and value of the specified keyframe. +// public void SetFrame (int frameIndex, float time, float[] vertices) { +// frames[frameIndex] = time; +// frameVertices[frameIndex] = vertices; +// } +// +// override public void Apply (Skeleton skeleton, float lastTime, float time, Vector firedEvents, float alpha, MixPose pose, MixDirection direction) { +// Slot slot = skeleton.slots.Items[slotIndex]; +// VertexAttachment vertexAttachment = slot.attachment as VertexAttachment; +// if (vertexAttachment == NULL || !vertexAttachment.ApplyDeform(attachment)) return; +// +// var verticesArray = slot.attachmentVertices; +// if (verticesArray.Count == 0) alpha = 1; +// +// float[][] frameVertices = _frameVertices; +// int vertexCount = frameVertices[0].Length; +// float[] frames = _frames; +// float[] vertices; +// +// if (time < frames[0]) { +// +// switch (pose) { +// case MixPose_Setup: +// verticesArray.Clear(); +// return; +// case MixPose_Current: +// if (alpha == 1) { +// verticesArray.Clear(); +// return; +// } +// +// // verticesArray.SetSize(vertexCount) // Ensure size and preemptively set count. +// if (verticesArray.Capacity < vertexCount) verticesArray.Capacity = vertexCount; +// verticesArray.Count = vertexCount; +// vertices = verticesArray.Items; +// +// if (vertexAttachment.bones == NULL) { +// // Unweighted vertex positions. +// float[] setupVertices = vertexAttachment.vertices; +// for (int i = 0; i < vertexCount; i++) +// vertices[i] += (setupVertices[i] - vertices[i]) * alpha; +// } else { +// // Weighted deform offsets. +// alpha = 1 - alpha; +// for (int i = 0; i < vertexCount; i++) +// vertices[i] *= alpha; +// } +// return; +// default: +// return; +// } +// +// } +// +// // verticesArray.SetSize(vertexCount) // Ensure size and preemptively set count. +// if (verticesArray.Capacity < vertexCount) verticesArray.Capacity = vertexCount; +// verticesArray.Count = vertexCount; +// vertices = verticesArray.Items; +// +// if (time >= frames[frames.Length - 1]) { // Time is after last frame. +// float[] lastVertices = frameVertices[frames.Length - 1]; +// if (alpha == 1) { +// // Vertex positions or deform offsets, no alpha. +// Array.Copy(lastVertices, 0, vertices, 0, vertexCount); +// } else if (pose == MixPose_Setup) { +// if (vertexAttachment.bones == NULL) { +// // Unweighted vertex positions, with alpha. +// float[] setupVertices = vertexAttachment.vertices; +// for (int i = 0; i < vertexCount; i++) { +// float setup = setupVertices[i]; +// vertices[i] = setup + (lastVertices[i] - setup) * alpha; +// } +// } else { +// // Weighted deform offsets, with alpha. +// for (int i = 0; i < vertexCount; i++) +// vertices[i] = lastVertices[i] * alpha; +// } +// } else { +// // Vertex positions or deform offsets, with alpha. +// for (int i = 0; i < vertexCount; i++) +// vertices[i] += (lastVertices[i] - vertices[i]) * alpha; +// } +// return; +// } +// +// // Interpolate between the previous frame and the current frame. +// int frame = Animation.BinarySearch(frames, time); +// float[] prevVertices = frameVertices[frame - 1]; +// float[] nextVertices = frameVertices[frame]; +// float frameTime = frames[frame]; +// float percent = GetCurvePercent(frame - 1, 1 - (time - frameTime) / (frames[frame - 1] - frameTime)); +// +// if (alpha == 1) { +// // Vertex positions or deform offsets, no alpha. +// for (int i = 0; i < vertexCount; i++) { +// float prev = prevVertices[i]; +// vertices[i] = prev + (nextVertices[i] - prev) * percent; +// } +// } else if (pose == MixPose_Setup) { +// if (vertexAttachment.bones == NULL) { +// // Unweighted vertex positions, with alpha. +// var setupVertices = vertexAttachment.vertices; +// for (int i = 0; i < vertexCount; i++) { +// float prev = prevVertices[i], setup = setupVertices[i]; +// vertices[i] = setup + (prev + (nextVertices[i] - prev) * percent - setup) * alpha; +// } +// } else { +// // Weighted deform offsets, with alpha. +// for (int i = 0; i < vertexCount; i++) { +// float prev = prevVertices[i]; +// vertices[i] = (prev + (nextVertices[i] - prev) * percent) * alpha; +// } +// } +// } else { +// // Vertex positions or deform offsets, with alpha. +// for (int i = 0; i < vertexCount; i++) { +// float prev = prevVertices[i]; +// vertices[i] += (prev + (nextVertices[i] - prev) * percent - vertices[i]) * alpha; +// } +// } +// } + }; } #endif /* Spine_DeformTimeline_h */ diff --git a/spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h b/spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h index 06e251fe5..487f619a7 100644 --- a/spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h @@ -39,61 +39,61 @@ namespace Spine { RTTI_DECL; - internal float[] frames; - private int[][] drawOrders; - - public float[] Frames { return frames; } set { frames = inValue; } // time, ... - public int[][] DrawOrders { return drawOrders; } set { drawOrders = inValue; } - public int FrameCount { return frames.Length; } - - public int PropertyId { - get { return ((int)TimelineType.DrawOrder << 24); } - } - - public DrawOrderTimeline (int frameCount) { - frames = new float[frameCount]; - drawOrders = new int[frameCount][]; - } - - /// Sets the time and value of the specified keyframe. - /// May be NULL to use bind pose draw order. - public void SetFrame (int frameIndex, float time, int[] drawOrder) { - frames[frameIndex] = time; - drawOrders[frameIndex] = drawOrder; - } - - public void Apply (Skeleton skeleton, float lastTime, float time, Vector firedEvents, float alpha, MixPose pose, MixDirection direction) { - Vector drawOrder = skeleton.drawOrder; - Vector slots = skeleton.slots; - if (direction == MixDirection_Out && pose == MixPose_Setup) { - Array.Copy(slots.Items, 0, drawOrder.Items, 0, slots.Count); - return; - } - - float[] frames = _frames; - if (time < frames[0]) { - if (pose == MixPose_Setup) Array.Copy(slots.Items, 0, drawOrder.Items, 0, slots.Count); - return; - } - - int frame; - if (time >= frames[frames.Length - 1]) // Time is after last frame. - frame = frames.Length - 1; - else - frame = Animation.BinarySearch(frames, time) - 1; - - int[] drawOrderToSetupIndex = drawOrders[frame]; - if (drawOrderToSetupIndex == NULL) { - drawOrder.Clear(); - for (int i = 0, n = slots.Count; i < n; i++) - drawOrder.Add(slots.Items[i]); - } else { - var drawOrderItems = drawOrder.Items; - var slotsItems = slots.Items; - for (int i = 0, n = drawOrderToSetupIndex.Length; i < n; i++) - drawOrderItems[i] = slotsItems[drawOrderToSetupIndex[i]]; - } - } +// internal float[] frames; +// private int[][] drawOrders; +// +// public float[] Frames { return frames; } set { frames = inValue; } // time, ... +// public int[][] DrawOrders { return drawOrders; } set { drawOrders = inValue; } +// public int FrameCount { return frames.Length; } +// +// public int PropertyId { +// get { return ((int)TimelineType.DrawOrder << 24); } +// } +// +// public DrawOrderTimeline (int frameCount) { +// frames = new float[frameCount]; +// drawOrders = new int[frameCount][]; +// } +// +// /// Sets the time and value of the specified keyframe. +// /// May be NULL to use bind pose draw order. +// public void SetFrame (int frameIndex, float time, int[] drawOrder) { +// frames[frameIndex] = time; +// drawOrders[frameIndex] = drawOrder; +// } +// +// public void Apply (Skeleton skeleton, float lastTime, float time, Vector firedEvents, float alpha, MixPose pose, MixDirection direction) { +// Vector drawOrder = skeleton.drawOrder; +// Vector slots = skeleton.slots; +// if (direction == MixDirection_Out && pose == MixPose_Setup) { +// Array.Copy(slots.Items, 0, drawOrder.Items, 0, slots.Count); +// return; +// } +// +// float[] frames = _frames; +// if (time < frames[0]) { +// if (pose == MixPose_Setup) Array.Copy(slots.Items, 0, drawOrder.Items, 0, slots.Count); +// return; +// } +// +// int frame; +// if (time >= frames[frames.Length - 1]) // Time is after last frame. +// frame = frames.Length - 1; +// else +// frame = Animation.BinarySearch(frames, time) - 1; +// +// int[] drawOrderToSetupIndex = drawOrders[frame]; +// if (drawOrderToSetupIndex == NULL) { +// drawOrder.Clear(); +// for (int i = 0, n = slots.Count; i < n; i++) +// drawOrder.Add(slots.Items[i]); +// } else { +// var drawOrderItems = drawOrder.Items; +// var slotsItems = slots.Items; +// for (int i = 0, n = drawOrderToSetupIndex.Length; i < n; i++) +// drawOrderItems[i] = slotsItems[drawOrderToSetupIndex[i]]; +// } +// } }; } diff --git a/spine-cpp/spine-cpp/include/spine/EventTimeline.h b/spine-cpp/spine-cpp/include/spine/EventTimeline.h index 23f70cf90..8fe56819e 100644 --- a/spine-cpp/spine-cpp/include/spine/EventTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/EventTimeline.h @@ -39,55 +39,55 @@ namespace Spine { RTTI_DECL; - internal float[] frames; - private Event[] events; - - public float[] Frames { return frames; } set { frames = inValue; } // time, ... - public Event[] Events { return events; } set { events = inValue; } - public int FrameCount { return frames.Length; } - - public int PropertyId { - get { return ((int)TimelineType.Event << 24); } - } - - public EventTimeline (int frameCount) { - frames = new float[frameCount]; - events = new Event[frameCount]; - } - - /// Sets the time and value of the specified keyframe. - public void SetFrame (int frameIndex, Event e) { - frames[frameIndex] = e.Time; - events[frameIndex] = e; - } - - /// Fires events for frames > lastTime and <= time. - public void Apply (Skeleton skeleton, float lastTime, float time, Vector firedEvents, float alpha, MixPose pose, MixDirection direction) { - if (firedEvents == NULL) return; - float[] frames = _frames; - int frameCount = frames.Length; - - if (lastTime > time) { // Fire events after last time for looped animations. - Apply(skeleton, lastTime, int.MaxValue, firedEvents, alpha, pose, direction); - lastTime = -1f; - } else if (lastTime >= frames[frameCount - 1]) // Last time is after last frame. - return; - if (time < frames[0]) return; // Time is before first frame. - - int frame; - if (lastTime < frames[0]) - frame = 0; - else { - frame = Animation.BinarySearch(frames, lastTime); - float frameTime = frames[frame]; - while (frame > 0) { // Fire multiple events with the same frame. - if (frames[frame - 1] != frameTime) break; - frame--; - } - } - for (; frame < frameCount && time >= frames[frame]; frame++) - firedEvents.Add(events[frame]); - } +// internal float[] frames; +// private Event[] events; +// +// public float[] Frames { return frames; } set { frames = inValue; } // time, ... +// public Event[] Events { return events; } set { events = inValue; } +// public int FrameCount { return frames.Length; } +// +// public int PropertyId { +// get { return ((int)TimelineType.Event << 24); } +// } +// +// public EventTimeline (int frameCount) { +// frames = new float[frameCount]; +// events = new Event[frameCount]; +// } +// +// /// Sets the time and value of the specified keyframe. +// public void SetFrame (int frameIndex, Event e) { +// frames[frameIndex] = e.Time; +// events[frameIndex] = e; +// } +// +// /// Fires events for frames > lastTime and <= time. +// public void Apply (Skeleton skeleton, float lastTime, float time, Vector firedEvents, float alpha, MixPose pose, MixDirection direction) { +// if (firedEvents == NULL) return; +// float[] frames = _frames; +// int frameCount = frames.Length; +// +// if (lastTime > time) { // Fire events after last time for looped animations. +// Apply(skeleton, lastTime, int.MaxValue, firedEvents, alpha, pose, direction); +// lastTime = -1f; +// } else if (lastTime >= frames[frameCount - 1]) // Last time is after last frame. +// return; +// if (time < frames[0]) return; // Time is before first frame. +// +// int frame; +// if (lastTime < frames[0]) +// frame = 0; +// else { +// frame = Animation.BinarySearch(frames, lastTime); +// float frameTime = frames[frame]; +// while (frame > 0) { // Fire multiple events with the same frame. +// if (frames[frame - 1] != frameTime) break; +// frame--; +// } +// } +// for (; frame < frameCount && time >= frames[frame]; frame++) +// firedEvents.Add(events[frame]); +// } }; } diff --git a/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h b/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h index 2716c75eb..b7605da11 100644 --- a/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h @@ -39,76 +39,76 @@ namespace Spine { RTTI_DECL; - public const int ENTRIES = 3; - private const int PREV_TIME = -3, PREV_MIX = -2, PREV_BEND_DIRECTION = -1; - private const int MIX = 1, BEND_DIRECTION = 2; - - internal int ikConstraintIndex; - internal float[] frames; - - public int IkConstraintIndex { return ikConstraintIndex; } set { ikConstraintIndex = inValue; } - public float[] Frames { return frames; } set { frames = inValue; } // time, mix, bendDirection, ... - - override public int PropertyId { - get { return ((int)TimelineType.IkConstraint << 24) + ikConstraintIndex; } - } - - public IkConstraintTimeline (int frameCount) - : base(frameCount) { - frames = new float[frameCount * ENTRIES]; - } - - /// Sets the time, mix and bend direction of the specified keyframe. - public void SetFrame (int frameIndex, float time, float mix, int bendDirection) { - frameIndex *= ENTRIES; - frames[frameIndex] = time; - frames[frameIndex + MIX] = mix; - frames[frameIndex + BEND_DIRECTION] = bendDirection; - } - - override public void Apply (Skeleton skeleton, float lastTime, float time, Vector firedEvents, float alpha, MixPose pose, MixDirection direction) { - IkConstraint constraint = skeleton.ikConstraints.Items[ikConstraintIndex]; - float[] frames = _frames; - if (time < frames[0]) { - switch (pose) { - case MixPose_Setup: - constraint.mix = constraint.data.mix; - constraint.bendDirection = constraint.data.bendDirection; - return; - case MixPose_Current: - constraint.mix += (constraint.data.mix - constraint.mix) * alpha; - constraint.bendDirection = constraint.data.bendDirection; - return; - } - return; - } - - if (time >= frames[frames.Length - ENTRIES]) { // Time is after last frame. - if (pose == MixPose_Setup) { - constraint.mix = constraint.data.mix + (frames[frames.Length + PREV_MIX] - constraint.data.mix) * alpha; - constraint.bendDirection = direction == MixDirection_Out ? constraint.data.bendDirection - : (int)frames[frames.Length + PREV_BEND_DIRECTION]; - } else { - constraint.mix += (frames[frames.Length + PREV_MIX] - constraint.mix) * alpha; - if (direction == MixDirection_In) constraint.bendDirection = (int)frames[frames.Length + PREV_BEND_DIRECTION]; - } - return; - } - - // Interpolate between the previous frame and the current frame. - int frame = Animation.BinarySearch(frames, time, ENTRIES); - float mix = frames[frame + PREV_MIX]; - float frameTime = frames[frame]; - float percent = GetCurvePercent(frame / ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime)); - - if (pose == MixPose_Setup) { - constraint.mix = constraint.data.mix + (mix + (frames[frame + MIX] - mix) * percent - constraint.data.mix) * alpha; - constraint.bendDirection = direction == MixDirection_Out ? constraint.data.bendDirection : (int)frames[frame + PREV_BEND_DIRECTION]; - } else { - constraint.mix += (mix + (frames[frame + MIX] - mix) * percent - constraint.mix) * alpha; - if (direction == MixDirection_In) constraint.bendDirection = (int)frames[frame + PREV_BEND_DIRECTION]; - } - } +// public const int ENTRIES = 3; +// private const int PREV_TIME = -3, PREV_MIX = -2, PREV_BEND_DIRECTION = -1; +// private const int MIX = 1, BEND_DIRECTION = 2; +// +// internal int ikConstraintIndex; +// internal float[] frames; +// +// public int IkConstraintIndex { return ikConstraintIndex; } set { ikConstraintIndex = inValue; } +// public float[] Frames { return frames; } set { frames = inValue; } // time, mix, bendDirection, ... +// +// override public int PropertyId { +// get { return ((int)TimelineType.IkConstraint << 24) + ikConstraintIndex; } +// } +// +// public IkConstraintTimeline (int frameCount) +// : base(frameCount) { +// frames = new float[frameCount * ENTRIES]; +// } +// +// /// Sets the time, mix and bend direction of the specified keyframe. +// public void SetFrame (int frameIndex, float time, float mix, int bendDirection) { +// frameIndex *= ENTRIES; +// frames[frameIndex] = time; +// frames[frameIndex + MIX] = mix; +// frames[frameIndex + BEND_DIRECTION] = bendDirection; +// } +// +// override public void Apply (Skeleton skeleton, float lastTime, float time, Vector firedEvents, float alpha, MixPose pose, MixDirection direction) { +// IkConstraint constraint = skeleton.ikConstraints.Items[ikConstraintIndex]; +// float[] frames = _frames; +// if (time < frames[0]) { +// switch (pose) { +// case MixPose_Setup: +// constraint.mix = constraint.data.mix; +// constraint.bendDirection = constraint.data.bendDirection; +// return; +// case MixPose_Current: +// constraint.mix += (constraint.data.mix - constraint.mix) * alpha; +// constraint.bendDirection = constraint.data.bendDirection; +// return; +// } +// return; +// } +// +// if (time >= frames[frames.Length - ENTRIES]) { // Time is after last frame. +// if (pose == MixPose_Setup) { +// constraint.mix = constraint.data.mix + (frames[frames.Length + PREV_MIX] - constraint.data.mix) * alpha; +// constraint.bendDirection = direction == MixDirection_Out ? constraint.data.bendDirection +// : (int)frames[frames.Length + PREV_BEND_DIRECTION]; +// } else { +// constraint.mix += (frames[frames.Length + PREV_MIX] - constraint.mix) * alpha; +// if (direction == MixDirection_In) constraint.bendDirection = (int)frames[frames.Length + PREV_BEND_DIRECTION]; +// } +// return; +// } +// +// // Interpolate between the previous frame and the current frame. +// int frame = Animation.BinarySearch(frames, time, ENTRIES); +// float mix = frames[frame + PREV_MIX]; +// float frameTime = frames[frame]; +// float percent = GetCurvePercent(frame / ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime)); +// +// if (pose == MixPose_Setup) { +// constraint.mix = constraint.data.mix + (mix + (frames[frame + MIX] - mix) * percent - constraint.data.mix) * alpha; +// constraint.bendDirection = direction == MixDirection_Out ? constraint.data.bendDirection : (int)frames[frame + PREV_BEND_DIRECTION]; +// } else { +// constraint.mix += (mix + (frames[frame + MIX] - mix) * percent - constraint.mix) * alpha; +// if (direction == MixDirection_In) constraint.bendDirection = (int)frames[frame + PREV_BEND_DIRECTION]; +// } +// } }; } diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h b/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h index ca6d8960d..a218bde35 100644 --- a/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h @@ -39,76 +39,76 @@ namespace Spine { RTTI_DECL; - public const int ENTRIES = 3; - private const int PREV_TIME = -3, PREV_ROTATE = -2, PREV_TRANSLATE = -1; - private const int ROTATE = 1, TRANSLATE = 2; - - internal int pathConstraintIndex; - internal float[] frames; - - public int PathConstraintIndex { return pathConstraintIndex; } set { pathConstraintIndex = inValue; } - public float[] Frames { return frames; } set { frames = inValue; } // time, rotate mix, translate mix, ... - - override public int PropertyId { - get { return ((int)TimelineType.PathConstraintMix << 24) + pathConstraintIndex; } - } - - public PathConstraintMixTimeline (int frameCount) - : base(frameCount) { - frames = new float[frameCount * ENTRIES]; - } - - /// Sets the time and mixes of the specified keyframe. - public void SetFrame (int frameIndex, float time, float rotateMix, float translateMix) { - frameIndex *= ENTRIES; - frames[frameIndex] = time; - frames[frameIndex + ROTATE] = rotateMix; - frames[frameIndex + TRANSLATE] = translateMix; - } - - override public void Apply (Skeleton skeleton, float lastTime, float time, Vector firedEvents, float alpha, MixPose pose, MixDirection direction) { - PathConstraint constraint = skeleton.pathConstraints.Items[pathConstraintIndex]; - float[] frames = _frames; - if (time < frames[0]) { - switch (pose) { - case MixPose_Setup: - constraint.rotateMix = constraint.data.rotateMix; - constraint.translateMix = constraint.data.translateMix; - return; - case MixPose_Current: - constraint.rotateMix += (constraint.data.rotateMix - constraint.rotateMix) * alpha; - constraint.translateMix += (constraint.data.translateMix - constraint.translateMix) * alpha; - return; - } - return; - } - - float rotate, translate; - if (time >= frames[frames.Length - ENTRIES]) { // Time is after last frame. - rotate = frames[frames.Length + PREV_ROTATE]; - translate = frames[frames.Length + PREV_TRANSLATE]; - } else { - // Interpolate between the previous frame and the current frame. - int frame = Animation.BinarySearch(frames, time, ENTRIES); - rotate = frames[frame + PREV_ROTATE]; - translate = frames[frame + PREV_TRANSLATE]; - float frameTime = frames[frame]; - float percent = GetCurvePercent(frame / ENTRIES - 1, - 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime)); - - rotate += (frames[frame + ROTATE] - rotate) * percent; - translate += (frames[frame + TRANSLATE] - translate) * percent; - } - - if (pose == MixPose_Setup) { - constraint.rotateMix = constraint.data.rotateMix + (rotate - constraint.data.rotateMix) * alpha; - constraint.translateMix = constraint.data.translateMix + (translate - constraint.data.translateMix) * alpha; - } else { - constraint.rotateMix += (rotate - constraint.rotateMix) * alpha; - constraint.translateMix += (translate - constraint.translateMix) * alpha; - } - } - } +// public const int ENTRIES = 3; +// private const int PREV_TIME = -3, PREV_ROTATE = -2, PREV_TRANSLATE = -1; +// private const int ROTATE = 1, TRANSLATE = 2; +// +// internal int pathConstraintIndex; +// internal float[] frames; +// +// public int PathConstraintIndex { return pathConstraintIndex; } set { pathConstraintIndex = inValue; } +// public float[] Frames { return frames; } set { frames = inValue; } // time, rotate mix, translate mix, ... +// +// override public int PropertyId { +// get { return ((int)TimelineType.PathConstraintMix << 24) + pathConstraintIndex; } +// } +// +// public PathConstraintMixTimeline (int frameCount) +// : base(frameCount) { +// frames = new float[frameCount * ENTRIES]; +// } +// +// /// Sets the time and mixes of the specified keyframe. +// public void SetFrame (int frameIndex, float time, float rotateMix, float translateMix) { +// frameIndex *= ENTRIES; +// frames[frameIndex] = time; +// frames[frameIndex + ROTATE] = rotateMix; +// frames[frameIndex + TRANSLATE] = translateMix; +// } +// +// override public void Apply (Skeleton skeleton, float lastTime, float time, Vector firedEvents, float alpha, MixPose pose, MixDirection direction) { +// PathConstraint constraint = skeleton.pathConstraints.Items[pathConstraintIndex]; +// float[] frames = _frames; +// if (time < frames[0]) { +// switch (pose) { +// case MixPose_Setup: +// constraint.rotateMix = constraint.data.rotateMix; +// constraint.translateMix = constraint.data.translateMix; +// return; +// case MixPose_Current: +// constraint.rotateMix += (constraint.data.rotateMix - constraint.rotateMix) * alpha; +// constraint.translateMix += (constraint.data.translateMix - constraint.translateMix) * alpha; +// return; +// } +// return; +// } +// +// float rotate, translate; +// if (time >= frames[frames.Length - ENTRIES]) { // Time is after last frame. +// rotate = frames[frames.Length + PREV_ROTATE]; +// translate = frames[frames.Length + PREV_TRANSLATE]; +// } else { +// // Interpolate between the previous frame and the current frame. +// int frame = Animation.BinarySearch(frames, time, ENTRIES); +// rotate = frames[frame + PREV_ROTATE]; +// translate = frames[frame + PREV_TRANSLATE]; +// float frameTime = frames[frame]; +// float percent = GetCurvePercent(frame / ENTRIES - 1, +// 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime)); +// +// rotate += (frames[frame + ROTATE] - rotate) * percent; +// translate += (frames[frame + TRANSLATE] - translate) * percent; +// } +// +// if (pose == MixPose_Setup) { +// constraint.rotateMix = constraint.data.rotateMix + (rotate - constraint.data.rotateMix) * alpha; +// constraint.translateMix = constraint.data.translateMix + (translate - constraint.data.translateMix) * alpha; +// } else { +// constraint.rotateMix += (rotate - constraint.rotateMix) * alpha; +// constraint.translateMix += (translate - constraint.translateMix) * alpha; +// } +// } + }; } #endif /* Spine_PathConstraintMixTimeline_h */ diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h b/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h index 8ac0319bd..1197aad93 100644 --- a/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h @@ -37,66 +37,68 @@ namespace Spine { class PathConstraintPositionTimeline : public CurveTimeline { - public const int ENTRIES = 2; - protected const int PREV_TIME = -2, PREV_VALUE = -1; - protected const int VALUE = 1; + RTTI_DECL; - internal int pathConstraintIndex; - internal float[] frames; - - override public int PropertyId { - get { return ((int)TimelineType.PathConstraintPosition << 24) + pathConstraintIndex; } - } - - public PathConstraintPositionTimeline (int frameCount) - : base(frameCount) { - frames = new float[frameCount * ENTRIES]; - } - - public int PathConstraintIndex { return pathConstraintIndex; } set { pathConstraintIndex = inValue; } - public float[] Frames { return frames; } set { frames = inValue; } // time, position, ... - - /// Sets the time and value of the specified keyframe. - public void SetFrame (int frameIndex, float time, float value) { - frameIndex *= ENTRIES; - frames[frameIndex] = time; - frames[frameIndex + VALUE] = inValue; - } - - override public void Apply (Skeleton skeleton, float lastTime, float time, Vector firedEvents, float alpha, MixPose pose, MixDirection direction) { - PathConstraint constraint = skeleton.pathConstraints.Items[pathConstraintIndex]; - float[] frames = _frames; - if (time < frames[0]) { - switch (pose) { - case MixPose_Setup: - constraint.position = constraint.data.position; - return; - case MixPose_Current: - constraint.position += (constraint.data.position - constraint.position) * alpha; - return; - } - return; - } - - float position; - if (time >= frames[frames.Length - ENTRIES]) // Time is after last frame. - position = frames[frames.Length + PREV_VALUE]; - else { - // Interpolate between the previous frame and the current frame. - int frame = Animation.BinarySearch(frames, time, ENTRIES); - position = frames[frame + PREV_VALUE]; - float frameTime = frames[frame]; - float percent = GetCurvePercent(frame / ENTRIES - 1, - 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime)); - - position += (frames[frame + VALUE] - position) * percent; - } - if (pose == MixPose_Setup) - constraint.position = constraint.data.position + (position - constraint.data.position) * alpha; - else - constraint.position += (position - constraint.position) * alpha; - } - } +// public const int ENTRIES = 2; +// protected const int PREV_TIME = -2, PREV_VALUE = -1; +// protected const int VALUE = 1; +// +// internal int pathConstraintIndex; +// internal float[] frames; +// +// override public int PropertyId { +// get { return ((int)TimelineType.PathConstraintPosition << 24) + pathConstraintIndex; } +// } +// +// public PathConstraintPositionTimeline (int frameCount) +// : base(frameCount) { +// frames = new float[frameCount * ENTRIES]; +// } +// +// public int PathConstraintIndex { return pathConstraintIndex; } set { pathConstraintIndex = inValue; } +// public float[] Frames { return frames; } set { frames = inValue; } // time, position, ... +// +// /// Sets the time and value of the specified keyframe. +// public void SetFrame (int frameIndex, float time, float value) { +// frameIndex *= ENTRIES; +// frames[frameIndex] = time; +// frames[frameIndex + VALUE] = inValue; +// } +// +// override public void Apply (Skeleton skeleton, float lastTime, float time, Vector firedEvents, float alpha, MixPose pose, MixDirection direction) { +// PathConstraint constraint = skeleton.pathConstraints.Items[pathConstraintIndex]; +// float[] frames = _frames; +// if (time < frames[0]) { +// switch (pose) { +// case MixPose_Setup: +// constraint.position = constraint.data.position; +// return; +// case MixPose_Current: +// constraint.position += (constraint.data.position - constraint.position) * alpha; +// return; +// } +// return; +// } +// +// float position; +// if (time >= frames[frames.Length - ENTRIES]) // Time is after last frame. +// position = frames[frames.Length + PREV_VALUE]; +// else { +// // Interpolate between the previous frame and the current frame. +// int frame = Animation.BinarySearch(frames, time, ENTRIES); +// position = frames[frame + PREV_VALUE]; +// float frameTime = frames[frame]; +// float percent = GetCurvePercent(frame / ENTRIES - 1, +// 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime)); +// +// position += (frames[frame + VALUE] - position) * percent; +// } +// if (pose == MixPose_Setup) +// constraint.position = constraint.data.position + (position - constraint.data.position) * alpha; +// else +// constraint.position += (position - constraint.position) * alpha; +// } + }; } #endif /* Spine_PathConstraintPositionTimeline_h */ diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h b/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h index 594008426..75969f1a3 100644 --- a/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h @@ -39,49 +39,49 @@ namespace Spine { RTTI_DECL; - override public int PropertyId { - get { return ((int)TimelineType.PathConstraintSpacing << 24) + pathConstraintIndex; } - } - - public PathConstraintSpacingTimeline (int frameCount) - : base(frameCount) { - } - - override public void Apply (Skeleton skeleton, float lastTime, float time, Vector firedEvents, float alpha, MixPose pose, MixDirection direction) { - PathConstraint constraint = skeleton.pathConstraints.Items[pathConstraintIndex]; - float[] frames = _frames; - if (time < frames[0]) { - switch (pose) { - case MixPose_Setup: - constraint.spacing = constraint.data.spacing; - return; - case MixPose_Current: - constraint.spacing += (constraint.data.spacing - constraint.spacing) * alpha; - return; - } - return; - } - - float spacing; - if (time >= frames[frames.Length - ENTRIES]) // Time is after last frame. - spacing = frames[frames.Length + PREV_VALUE]; - else { - // Interpolate between the previous frame and the current frame. - int frame = Animation.BinarySearch(frames, time, ENTRIES); - spacing = frames[frame + PREV_VALUE]; - float frameTime = frames[frame]; - float percent = GetCurvePercent(frame / ENTRIES - 1, - 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime)); - - spacing += (frames[frame + VALUE] - spacing) * percent; - } - - if (pose == MixPose_Setup) - constraint.spacing = constraint.data.spacing + (spacing - constraint.data.spacing) * alpha; - else - constraint.spacing += (spacing - constraint.spacing) * alpha; - } - } +// override public int PropertyId { +// get { return ((int)TimelineType.PathConstraintSpacing << 24) + pathConstraintIndex; } +// } +// +// public PathConstraintSpacingTimeline (int frameCount) +// : base(frameCount) { +// } +// +// override public void Apply (Skeleton skeleton, float lastTime, float time, Vector firedEvents, float alpha, MixPose pose, MixDirection direction) { +// PathConstraint constraint = skeleton.pathConstraints.Items[pathConstraintIndex]; +// float[] frames = _frames; +// if (time < frames[0]) { +// switch (pose) { +// case MixPose_Setup: +// constraint.spacing = constraint.data.spacing; +// return; +// case MixPose_Current: +// constraint.spacing += (constraint.data.spacing - constraint.spacing) * alpha; +// return; +// } +// return; +// } +// +// float spacing; +// if (time >= frames[frames.Length - ENTRIES]) // Time is after last frame. +// spacing = frames[frames.Length + PREV_VALUE]; +// else { +// // Interpolate between the previous frame and the current frame. +// int frame = Animation.BinarySearch(frames, time, ENTRIES); +// spacing = frames[frame + PREV_VALUE]; +// float frameTime = frames[frame]; +// float percent = GetCurvePercent(frame / ENTRIES - 1, +// 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime)); +// +// spacing += (frames[frame + VALUE] - spacing) * percent; +// } +// +// if (pose == MixPose_Setup) +// constraint.spacing = constraint.data.spacing + (spacing - constraint.data.spacing) * alpha; +// else +// constraint.spacing += (spacing - constraint.spacing) * alpha; +// } + }; } #endif /* Spine_PathConstraintSpacingTimeline_h */ diff --git a/spine-cpp/spine-cpp/include/spine/PointAttachment.h b/spine-cpp/spine-cpp/include/spine/PointAttachment.h index c51c130d9..6738021a7 100644 --- a/spine-cpp/spine-cpp/include/spine/PointAttachment.h +++ b/spine-cpp/spine-cpp/include/spine/PointAttachment.h @@ -48,6 +48,7 @@ namespace Spine { RTTI_DECL; + public: PointAttachment(std::string name); void computeWorldPosition(Bone& bone, float& ox, float& oy); @@ -65,7 +66,7 @@ namespace Spine private: float _x, _y, _rotation; - } + }; } #endif /* Spine_PointAttachment_h */ diff --git a/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h b/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h index 32b92f499..00e10e325 100644 --- a/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h @@ -39,73 +39,73 @@ namespace Spine { RTTI_DECL; - override public int PropertyId { - get { return ((int)TimelineType.Scale << 24) + boneIndex; } - } - - public ScaleTimeline (int frameCount) - : base(frameCount) { - } - - override public void Apply (Skeleton skeleton, float lastTime, float time, Vector firedEvents, float alpha, MixPose pose, MixDirection direction) { - Bone bone = skeleton.bones.Items[boneIndex]; - - float[] frames = _frames; - if (time < frames[0]) { - switch (pose) { - case MixPose_Setup: - bone.scaleX = bone.data.scaleX; - bone.scaleY = bone.data.scaleY; - return; - case MixPose_Current: - bone.scaleX += (bone.data.scaleX - bone.scaleX) * alpha; - bone.scaleY += (bone.data.scaleY - bone.scaleY) * alpha; - return; - } - return; - } - - float x, y; - if (time >= frames[frames.Length - ENTRIES]) { // Time is after last frame. - x = frames[frames.Length + PREV_X] * bone.data.scaleX; - y = frames[frames.Length + PREV_Y] * bone.data.scaleY; - } else { - // Interpolate between the previous frame and the current frame. - int frame = Animation.BinarySearch(frames, time, ENTRIES); - x = frames[frame + PREV_X]; - y = frames[frame + PREV_Y]; - float frameTime = frames[frame]; - float percent = GetCurvePercent(frame / ENTRIES - 1, - 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime)); - - x = (x + (frames[frame + X] - x) * percent) * bone.data.scaleX; - y = (y + (frames[frame + Y] - y) * percent) * bone.data.scaleY; - } - if (alpha == 1) { - bone.scaleX = x; - bone.scaleY = y; - } else { - float bx, by; - if (pose == MixPose_Setup) { - bx = bone.data.scaleX; - by = bone.data.scaleY; - } else { - bx = bone.scaleX; - by = bone.scaleY; - } - // Mixing out uses sign of setup or current pose, else use sign of key. - if (direction == MixDirection_Out) { - x = (x >= 0 ? x : -x) * (bx >= 0 ? 1 : -1); - y = (y >= 0 ? y : -y) * (by >= 0 ? 1 : -1); - } else { - bx = (bx >= 0 ? bx : -bx) * (x >= 0 ? 1 : -1); - by = (by >= 0 ? by : -by) * (y >= 0 ? 1 : -1); - } - bone.scaleX = bx + (x - bx) * alpha; - bone.scaleY = by + (y - by) * alpha; - } - } - } +// override public int PropertyId { +// get { return ((int)TimelineType.Scale << 24) + boneIndex; } +// } +// +// public ScaleTimeline (int frameCount) +// : base(frameCount) { +// } +// +// override public void Apply (Skeleton skeleton, float lastTime, float time, Vector firedEvents, float alpha, MixPose pose, MixDirection direction) { +// Bone bone = skeleton.bones.Items[boneIndex]; +// +// float[] frames = _frames; +// if (time < frames[0]) { +// switch (pose) { +// case MixPose_Setup: +// bone.scaleX = bone.data.scaleX; +// bone.scaleY = bone.data.scaleY; +// return; +// case MixPose_Current: +// bone.scaleX += (bone.data.scaleX - bone.scaleX) * alpha; +// bone.scaleY += (bone.data.scaleY - bone.scaleY) * alpha; +// return; +// } +// return; +// } +// +// float x, y; +// if (time >= frames[frames.Length - ENTRIES]) { // Time is after last frame. +// x = frames[frames.Length + PREV_X] * bone.data.scaleX; +// y = frames[frames.Length + PREV_Y] * bone.data.scaleY; +// } else { +// // Interpolate between the previous frame and the current frame. +// int frame = Animation.BinarySearch(frames, time, ENTRIES); +// x = frames[frame + PREV_X]; +// y = frames[frame + PREV_Y]; +// float frameTime = frames[frame]; +// float percent = GetCurvePercent(frame / ENTRIES - 1, +// 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime)); +// +// x = (x + (frames[frame + X] - x) * percent) * bone.data.scaleX; +// y = (y + (frames[frame + Y] - y) * percent) * bone.data.scaleY; +// } +// if (alpha == 1) { +// bone.scaleX = x; +// bone.scaleY = y; +// } else { +// float bx, by; +// if (pose == MixPose_Setup) { +// bx = bone.data.scaleX; +// by = bone.data.scaleY; +// } else { +// bx = bone.scaleX; +// by = bone.scaleY; +// } +// // Mixing out uses sign of setup or current pose, else use sign of key. +// if (direction == MixDirection_Out) { +// x = (x >= 0 ? x : -x) * (bx >= 0 ? 1 : -1); +// y = (y >= 0 ? y : -y) * (by >= 0 ? 1 : -1); +// } else { +// bx = (bx >= 0 ? bx : -bx) * (x >= 0 ? 1 : -1); +// by = (by >= 0 ? by : -by) * (y >= 0 ? 1 : -1); +// } +// bone.scaleX = bx + (x - bx) * alpha; +// bone.scaleY = by + (y - by) * alpha; +// } +// } + }; } #endif /* Spine_ScaleTimeline_h */ diff --git a/spine-cpp/spine-cpp/include/spine/ShearTimeline.h b/spine-cpp/spine-cpp/include/spine/ShearTimeline.h index 39087ff9d..1b367e2c2 100644 --- a/spine-cpp/spine-cpp/include/spine/ShearTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/ShearTimeline.h @@ -39,56 +39,56 @@ namespace Spine { RTTI_DECL; - override public int PropertyId { - get { return ((int)TimelineType.Shear << 24) + boneIndex; } - } - - public ShearTimeline (int frameCount) - : base(frameCount) { - } - - override public void Apply (Skeleton skeleton, float lastTime, float time, Vector firedEvents, float alpha, MixPose pose, MixDirection direction) { - Bone bone = skeleton.bones.Items[boneIndex]; - float[] frames = _frames; - if (time < frames[0]) { - switch (pose) { - case MixPose_Setup: - bone.shearX = bone.data.shearX; - bone.shearY = bone.data.shearY; - return; - case MixPose_Current: - bone.shearX += (bone.data.shearX - bone.shearX) * alpha; - bone.shearY += (bone.data.shearY - bone.shearY) * alpha; - return; - } - return; - } - - float x, y; - if (time >= frames[frames.Length - ENTRIES]) { // Time is after last frame. - x = frames[frames.Length + PREV_X]; - y = frames[frames.Length + PREV_Y]; - } else { - // Interpolate between the previous frame and the current frame. - int frame = Animation.BinarySearch(frames, time, ENTRIES); - x = frames[frame + PREV_X]; - y = frames[frame + PREV_Y]; - float frameTime = frames[frame]; - float percent = GetCurvePercent(frame / ENTRIES - 1, - 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime)); - - x = x + (frames[frame + X] - x) * percent; - y = y + (frames[frame + Y] - y) * percent; - } - if (pose == MixPose_Setup) { - bone.shearX = bone.data.shearX + x * alpha; - bone.shearY = bone.data.shearY + y * alpha; - } else { - bone.shearX += (bone.data.shearX + x - bone.shearX) * alpha; - bone.shearY += (bone.data.shearY + y - bone.shearY) * alpha; - } - } - } +// override public int PropertyId { +// get { return ((int)TimelineType.Shear << 24) + boneIndex; } +// } +// +// public ShearTimeline (int frameCount) +// : base(frameCount) { +// } +// +// override public void Apply (Skeleton skeleton, float lastTime, float time, Vector firedEvents, float alpha, MixPose pose, MixDirection direction) { +// Bone bone = skeleton.bones.Items[boneIndex]; +// float[] frames = _frames; +// if (time < frames[0]) { +// switch (pose) { +// case MixPose_Setup: +// bone.shearX = bone.data.shearX; +// bone.shearY = bone.data.shearY; +// return; +// case MixPose_Current: +// bone.shearX += (bone.data.shearX - bone.shearX) * alpha; +// bone.shearY += (bone.data.shearY - bone.shearY) * alpha; +// return; +// } +// return; +// } +// +// float x, y; +// if (time >= frames[frames.Length - ENTRIES]) { // Time is after last frame. +// x = frames[frames.Length + PREV_X]; +// y = frames[frames.Length + PREV_Y]; +// } else { +// // Interpolate between the previous frame and the current frame. +// int frame = Animation.BinarySearch(frames, time, ENTRIES); +// x = frames[frame + PREV_X]; +// y = frames[frame + PREV_Y]; +// float frameTime = frames[frame]; +// float percent = GetCurvePercent(frame / ENTRIES - 1, +// 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime)); +// +// x = x + (frames[frame + X] - x) * percent; +// y = y + (frames[frame + Y] - y) * percent; +// } +// if (pose == MixPose_Setup) { +// bone.shearX = bone.data.shearX + x * alpha; +// bone.shearY = bone.data.shearY + y * alpha; +// } else { +// bone.shearX += (bone.data.shearX + x - bone.shearX) * alpha; +// bone.shearY += (bone.data.shearY + y - bone.shearY) * alpha; +// } +// } + }; } #endif /* Spine_ShearTimeline_h */ diff --git a/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h b/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h index 142e444c8..d46b817f7 100644 --- a/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h @@ -39,93 +39,93 @@ namespace Spine { RTTI_DECL; - public const int ENTRIES = 5; - private const int PREV_TIME = -5, PREV_ROTATE = -4, PREV_TRANSLATE = -3, PREV_SCALE = -2, PREV_SHEAR = -1; - private const int ROTATE = 1, TRANSLATE = 2, SCALE = 3, SHEAR = 4; - - internal int transformConstraintIndex; - internal float[] frames; - - public int TransformConstraintIndex { return transformConstraintIndex; } set { transformConstraintIndex = inValue; } - public float[] Frames { return frames; } set { frames = inValue; } // time, rotate mix, translate mix, scale mix, shear mix, ... - - override public int PropertyId { - get { return ((int)TimelineType.TransformConstraint << 24) + transformConstraintIndex; } - } - - public TransformConstraintTimeline (int frameCount) - : base(frameCount) { - frames = new float[frameCount * ENTRIES]; - } - - public void SetFrame (int frameIndex, float time, float rotateMix, float translateMix, float scaleMix, float shearMix) { - frameIndex *= ENTRIES; - frames[frameIndex] = time; - frames[frameIndex + ROTATE] = rotateMix; - frames[frameIndex + TRANSLATE] = translateMix; - frames[frameIndex + SCALE] = scaleMix; - frames[frameIndex + SHEAR] = shearMix; - } - - override public void Apply (Skeleton skeleton, float lastTime, float time, Vector firedEvents, float alpha, MixPose pose, MixDirection direction) { - TransformConstraint constraint = skeleton.transformConstraints.Items[transformConstraintIndex]; - float[] frames = _frames; - if (time < frames[0]) { - var data = constraint.data; - switch (pose) { - case MixPose_Setup: - constraint.rotateMix = data.rotateMix; - constraint.translateMix = data.translateMix; - constraint.scaleMix = data.scaleMix; - constraint.shearMix = data.shearMix; - return; - case MixPose_Current: - constraint.rotateMix += (data.rotateMix - constraint.rotateMix) * alpha; - constraint.translateMix += (data.translateMix - constraint.translateMix) * alpha; - constraint.scaleMix += (data.scaleMix - constraint.scaleMix) * alpha; - constraint.shearMix += (data.shearMix - constraint.shearMix) * alpha; - return; - } - return; - } - - float rotate, translate, scale, shear; - if (time >= frames[frames.Length - ENTRIES]) { // Time is after last frame. - int i = frames.Length; - rotate = frames[i + PREV_ROTATE]; - translate = frames[i + PREV_TRANSLATE]; - scale = frames[i + PREV_SCALE]; - shear = frames[i + PREV_SHEAR]; - } else { - // Interpolate between the previous frame and the current frame. - int frame = Animation.BinarySearch(frames, time, ENTRIES); - rotate = frames[frame + PREV_ROTATE]; - translate = frames[frame + PREV_TRANSLATE]; - scale = frames[frame + PREV_SCALE]; - shear = frames[frame + PREV_SHEAR]; - float frameTime = frames[frame]; - float percent = GetCurvePercent(frame / ENTRIES - 1, - 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime)); - - rotate += (frames[frame + ROTATE] - rotate) * percent; - translate += (frames[frame + TRANSLATE] - translate) * percent; - scale += (frames[frame + SCALE] - scale) * percent; - shear += (frames[frame + SHEAR] - shear) * percent; - } - if (pose == MixPose_Setup) { - TransformConstraintData data = constraint.data; - constraint.rotateMix = data.rotateMix + (rotate - data.rotateMix) * alpha; - constraint.translateMix = data.translateMix + (translate - data.translateMix) * alpha; - constraint.scaleMix = data.scaleMix + (scale - data.scaleMix) * alpha; - constraint.shearMix = data.shearMix + (shear - data.shearMix) * alpha; - } else { - constraint.rotateMix += (rotate - constraint.rotateMix) * alpha; - constraint.translateMix += (translate - constraint.translateMix) * alpha; - constraint.scaleMix += (scale - constraint.scaleMix) * alpha; - constraint.shearMix += (shear - constraint.shearMix) * alpha; - } - } - } +// public const int ENTRIES = 5; +// private const int PREV_TIME = -5, PREV_ROTATE = -4, PREV_TRANSLATE = -3, PREV_SCALE = -2, PREV_SHEAR = -1; +// private const int ROTATE = 1, TRANSLATE = 2, SCALE = 3, SHEAR = 4; +// +// internal int transformConstraintIndex; +// internal float[] frames; +// +// public int TransformConstraintIndex { return transformConstraintIndex; } set { transformConstraintIndex = inValue; } +// public float[] Frames { return frames; } set { frames = inValue; } // time, rotate mix, translate mix, scale mix, shear mix, ... +// +// override public int PropertyId { +// get { return ((int)TimelineType.TransformConstraint << 24) + transformConstraintIndex; } +// } +// +// public TransformConstraintTimeline (int frameCount) +// : base(frameCount) { +// frames = new float[frameCount * ENTRIES]; +// } +// +// public void SetFrame (int frameIndex, float time, float rotateMix, float translateMix, float scaleMix, float shearMix) { +// frameIndex *= ENTRIES; +// frames[frameIndex] = time; +// frames[frameIndex + ROTATE] = rotateMix; +// frames[frameIndex + TRANSLATE] = translateMix; +// frames[frameIndex + SCALE] = scaleMix; +// frames[frameIndex + SHEAR] = shearMix; +// } +// +// override public void Apply (Skeleton skeleton, float lastTime, float time, Vector firedEvents, float alpha, MixPose pose, MixDirection direction) { +// TransformConstraint constraint = skeleton.transformConstraints.Items[transformConstraintIndex]; +// float[] frames = _frames; +// if (time < frames[0]) { +// var data = constraint.data; +// switch (pose) { +// case MixPose_Setup: +// constraint.rotateMix = data.rotateMix; +// constraint.translateMix = data.translateMix; +// constraint.scaleMix = data.scaleMix; +// constraint.shearMix = data.shearMix; +// return; +// case MixPose_Current: +// constraint.rotateMix += (data.rotateMix - constraint.rotateMix) * alpha; +// constraint.translateMix += (data.translateMix - constraint.translateMix) * alpha; +// constraint.scaleMix += (data.scaleMix - constraint.scaleMix) * alpha; +// constraint.shearMix += (data.shearMix - constraint.shearMix) * alpha; +// return; +// } +// return; +// } +// +// float rotate, translate, scale, shear; +// if (time >= frames[frames.Length - ENTRIES]) { // Time is after last frame. +// int i = frames.Length; +// rotate = frames[i + PREV_ROTATE]; +// translate = frames[i + PREV_TRANSLATE]; +// scale = frames[i + PREV_SCALE]; +// shear = frames[i + PREV_SHEAR]; +// } else { +// // Interpolate between the previous frame and the current frame. +// int frame = Animation.BinarySearch(frames, time, ENTRIES); +// rotate = frames[frame + PREV_ROTATE]; +// translate = frames[frame + PREV_TRANSLATE]; +// scale = frames[frame + PREV_SCALE]; +// shear = frames[frame + PREV_SHEAR]; +// float frameTime = frames[frame]; +// float percent = GetCurvePercent(frame / ENTRIES - 1, +// 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime)); +// +// rotate += (frames[frame + ROTATE] - rotate) * percent; +// translate += (frames[frame + TRANSLATE] - translate) * percent; +// scale += (frames[frame + SCALE] - scale) * percent; +// shear += (frames[frame + SHEAR] - shear) * percent; +// } +// if (pose == MixPose_Setup) { +// TransformConstraintData data = constraint.data; +// constraint.rotateMix = data.rotateMix + (rotate - data.rotateMix) * alpha; +// constraint.translateMix = data.translateMix + (translate - data.translateMix) * alpha; +// constraint.scaleMix = data.scaleMix + (scale - data.scaleMix) * alpha; +// constraint.shearMix = data.shearMix + (shear - data.shearMix) * alpha; +// } else { +// constraint.rotateMix += (rotate - constraint.rotateMix) * alpha; +// constraint.translateMix += (translate - constraint.translateMix) * alpha; +// constraint.scaleMix += (scale - constraint.scaleMix) * alpha; +// constraint.shearMix += (shear - constraint.shearMix) * alpha; +// } +// } + }; } #endif /* Spine_TransformConstraintTimeline_h */ diff --git a/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h b/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h index ad7fb78b7..ca6a0ce9d 100644 --- a/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h @@ -42,88 +42,88 @@ namespace Spine { RTTI_DECL; - public const int ENTRIES = 3; - protected const int PREV_TIME = -3, PREV_X = -2, PREV_Y = -1; - protected const int X = 1, Y = 2; - - internal int boneIndex; - internal float[] frames; - - public int getBoneIndex { return boneIndex; } set { boneIndex = inValue; } - public Vector getFrames { return frames; } set { frames = inValue; } // time, value, value, ... - - virtual int getPropertyId() - { - return ((int)TimelineType_Translate << 24) + boneIndex; - } - - public TranslateTimeline(int frameCount) : CurveTimeline(frameCount) - { - frames = new float[frameCount * ENTRIES]; - } - - /// Sets the time and value of the specified keyframe. - public void setFrame(int frameIndex, float time, float x, float y) - { - frameIndex *= ENTRIES; - frames[frameIndex] = time; - frames[frameIndex + X] = x; - frames[frameIndex + Y] = y; - } - - override public void apply(Skeleton skeleton, float lastTime, float time, Vector firedEvents, float alpha, MixPose pose, MixDirection direction) - { - Bone bone = skeleton.bones.Items[boneIndex]; - - float[] frames = _frames; - if (time < frames[0]) - { - switch (pose) - { - case MixPose_Setup: - bone.x = bone.data.x; - bone.y = bone.data.y; - return; - case MixPose_Current: - bone.x += (bone.data.x - bone.x) * alpha; - bone.y += (bone.data.y - bone.y) * alpha; - return; - } - return; - } - - float x, y; - if (time >= frames[frames.Length - ENTRIES]) - { - // Time is after last frame. - x = frames[frames.Length + PREV_X]; - y = frames[frames.Length + PREV_Y]; - } - else - { - // Interpolate between the previous frame and the current frame. - int frame = Animation::binarySearch(frames, time, ENTRIES); - x = frames[frame + PREV_X]; - y = frames[frame + PREV_Y]; - float frameTime = frames[frame]; - float percent = GetCurvePercent(frame / ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime)); - - x += (frames[frame + X] - x) * percent; - y += (frames[frame + Y] - y) * percent; - } - - if (pose == MixPose_Setup) - { - bone.x = bone.data.x + x * alpha; - bone.y = bone.data.y + y * alpha; - } - else - { - bone.x += (bone.data.x + x - bone.x) * alpha; - bone.y += (bone.data.y + y - bone.y) * alpha; - } - } - } +// public const int ENTRIES = 3; +// protected const int PREV_TIME = -3, PREV_X = -2, PREV_Y = -1; +// protected const int X = 1, Y = 2; +// +// internal int boneIndex; +// internal float[] frames; +// +// public int getBoneIndex { return boneIndex; } set { boneIndex = inValue; } +// public Vector getFrames { return frames; } set { frames = inValue; } // time, value, value, ... +// +// virtual int getPropertyId() +// { +// return ((int)TimelineType_Translate << 24) + boneIndex; +// } +// +// public TranslateTimeline(int frameCount) : CurveTimeline(frameCount) +// { +// frames = new float[frameCount * ENTRIES]; +// } +// +// /// Sets the time and value of the specified keyframe. +// public void setFrame(int frameIndex, float time, float x, float y) +// { +// frameIndex *= ENTRIES; +// frames[frameIndex] = time; +// frames[frameIndex + X] = x; +// frames[frameIndex + Y] = y; +// } +// +// override public void apply(Skeleton skeleton, float lastTime, float time, Vector firedEvents, float alpha, MixPose pose, MixDirection direction) +// { +// Bone bone = skeleton.bones.Items[boneIndex]; +// +// float[] frames = _frames; +// if (time < frames[0]) +// { +// switch (pose) +// { +// case MixPose_Setup: +// bone.x = bone.data.x; +// bone.y = bone.data.y; +// return; +// case MixPose_Current: +// bone.x += (bone.data.x - bone.x) * alpha; +// bone.y += (bone.data.y - bone.y) * alpha; +// return; +// } +// return; +// } +// +// float x, y; +// if (time >= frames[frames.Length - ENTRIES]) +// { +// // Time is after last frame. +// x = frames[frames.Length + PREV_X]; +// y = frames[frames.Length + PREV_Y]; +// } +// else +// { +// // Interpolate between the previous frame and the current frame. +// int frame = Animation::binarySearch(frames, time, ENTRIES); +// x = frames[frame + PREV_X]; +// y = frames[frame + PREV_Y]; +// float frameTime = frames[frame]; +// float percent = GetCurvePercent(frame / ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime)); +// +// x += (frames[frame + X] - x) * percent; +// y += (frames[frame + Y] - y) * percent; +// } +// +// if (pose == MixPose_Setup) +// { +// bone.x = bone.data.x + x * alpha; +// bone.y = bone.data.y + y * alpha; +// } +// else +// { +// bone.x += (bone.data.x + x - bone.x) * alpha; +// bone.y += (bone.data.y + y - bone.y) * alpha; +// } +// } + }; } #endif /* Spine_TranslateTimeline_h */ diff --git a/spine-cpp/spine-cpp/include/spine/TwoColorTimeline.h b/spine-cpp/spine-cpp/include/spine/TwoColorTimeline.h index 07af223cd..befea9f94 100644 --- a/spine-cpp/spine-cpp/include/spine/TwoColorTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/TwoColorTimeline.h @@ -39,145 +39,144 @@ namespace Spine { RTTI_DECL; - public const int ENTRIES = 8; - protected const int PREV_TIME = -8, PREV_R = -7, PREV_G = -6, PREV_B = -5, PREV_A = -4; - protected const int PREV_R2 = -3, PREV_G2 = -2, PREV_B2 = -1; - protected const int R = 1, G = 2, B = 3, A = 4, R2 = 5, G2 = 6, B2 = 7; - - internal float[] frames; // time, r, g, b, a, r2, g2, b2, ... - public float[] Frames { return frames; } - - internal int slotIndex; - public int SlotIndex { - get { return slotIndex; } - set { - if (value < 0) throw new ArgumentOutOfRangeException("index must be >= 0."); - slotIndex = inValue; - } - } - - override public int PropertyId { - get { return ((int)TimelineType.TwoColor << 24) + slotIndex; } - } - - public TwoColorTimeline (int frameCount) : - base(frameCount) { - frames = new float[frameCount * ENTRIES]; - } - - /// Sets the time and value of the specified keyframe. - public void SetFrame (int frameIndex, float time, float r, float g, float b, float a, float r2, float g2, float b2) { - frameIndex *= ENTRIES; - frames[frameIndex] = time; - frames[frameIndex + R] = r; - frames[frameIndex + G] = g; - frames[frameIndex + B] = b; - frames[frameIndex + A] = a; - frames[frameIndex + R2] = r2; - frames[frameIndex + G2] = g2; - frames[frameIndex + B2] = b2; - } - - override public void Apply (Skeleton skeleton, float lastTime, float time, Vector firedEvents, float alpha, MixPose pose, MixDirection direction) { - Slot slot = skeleton.slots.Items[slotIndex]; - float[] frames = _frames; - if (time < frames[0]) { // Time is before first frame. - var slotData = slot.data; - switch (pose) { - case MixPose_Setup: - // slot.color.set(slot.data.color); - // slot.darkColor.set(slot.data.darkColor); - slot.r = slotData.r; - slot.g = slotData.g; - slot.b = slotData.b; - slot.a = slotData.a; - slot.r2 = slotData.r2; - slot.g2 = slotData.g2; - slot.b2 = slotData.b2; - return; - case MixPose_Current: - slot.r += (slot.r - slotData.r) * alpha; - slot.g += (slot.g - slotData.g) * alpha; - slot.b += (slot.b - slotData.b) * alpha; - slot.a += (slot.a - slotData.a) * alpha; - slot.r2 += (slot.r2 - slotData.r2) * alpha; - slot.g2 += (slot.g2 - slotData.g2) * alpha; - slot.b2 += (slot.b2 - slotData.b2) * alpha; - return; - } - return; - } - - float r, g, b, a, r2, g2, b2; - if (time >= frames[frames.Length - ENTRIES]) { // Time is after last frame. - int i = frames.Length; - r = frames[i + PREV_R]; - g = frames[i + PREV_G]; - b = frames[i + PREV_B]; - a = frames[i + PREV_A]; - r2 = frames[i + PREV_R2]; - g2 = frames[i + PREV_G2]; - b2 = frames[i + PREV_B2]; - } else { - // Interpolate between the previous frame and the current frame. - int frame = Animation.BinarySearch(frames, time, ENTRIES); - r = frames[frame + PREV_R]; - g = frames[frame + PREV_G]; - b = frames[frame + PREV_B]; - a = frames[frame + PREV_A]; - r2 = frames[frame + PREV_R2]; - g2 = frames[frame + PREV_G2]; - b2 = frames[frame + PREV_B2]; - float frameTime = frames[frame]; - float percent = GetCurvePercent(frame / ENTRIES - 1, - 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime)); - - r += (frames[frame + R] - r) * percent; - g += (frames[frame + G] - g) * percent; - b += (frames[frame + B] - b) * percent; - a += (frames[frame + A] - a) * percent; - r2 += (frames[frame + R2] - r2) * percent; - g2 += (frames[frame + G2] - g2) * percent; - b2 += (frames[frame + B2] - b2) * percent; - } - if (alpha == 1) { - slot.r = r; - slot.g = g; - slot.b = b; - slot.a = a; - slot.r2 = r2; - slot.g2 = g2; - slot.b2 = b2; - } else { - float br, bg, bb, ba, br2, bg2, bb2; - if (pose == MixPose_Setup) { - br = slot.data.r; - bg = slot.data.g; - bb = slot.data.b; - ba = slot.data.a; - br2 = slot.data.r2; - bg2 = slot.data.g2; - bb2 = slot.data.b2; - } else { - br = slot.r; - bg = slot.g; - bb = slot.b; - ba = slot.a; - br2 = slot.r2; - bg2 = slot.g2; - bb2 = slot.b2; - } - slot.r = br + ((r - br) * alpha); - slot.g = bg + ((g - bg) * alpha); - slot.b = bb + ((b - bb) * alpha); - slot.a = ba + ((a - ba) * alpha); - slot.r2 = br2 + ((r2 - br2) * alpha); - slot.g2 = bg2 + ((g2 - bg2) * alpha); - slot.b2 = bb2 + ((b2 - bb2) * alpha); - } - } - - } +// public const int ENTRIES = 8; +// protected const int PREV_TIME = -8, PREV_R = -7, PREV_G = -6, PREV_B = -5, PREV_A = -4; +// protected const int PREV_R2 = -3, PREV_G2 = -2, PREV_B2 = -1; +// protected const int R = 1, G = 2, B = 3, A = 4, R2 = 5, G2 = 6, B2 = 7; +// +// internal float[] frames; // time, r, g, b, a, r2, g2, b2, ... +// public float[] Frames { return frames; } +// +// internal int slotIndex; +// public int SlotIndex { +// get { return slotIndex; } +// set { +// if (value < 0) throw new ArgumentOutOfRangeException("index must be >= 0."); +// slotIndex = inValue; +// } +// } +// +// override public int PropertyId { +// get { return ((int)TimelineType.TwoColor << 24) + slotIndex; } +// } +// +// public TwoColorTimeline (int frameCount) : +// base(frameCount) { +// frames = new float[frameCount * ENTRIES]; +// } +// +// /// Sets the time and value of the specified keyframe. +// public void SetFrame (int frameIndex, float time, float r, float g, float b, float a, float r2, float g2, float b2) { +// frameIndex *= ENTRIES; +// frames[frameIndex] = time; +// frames[frameIndex + R] = r; +// frames[frameIndex + G] = g; +// frames[frameIndex + B] = b; +// frames[frameIndex + A] = a; +// frames[frameIndex + R2] = r2; +// frames[frameIndex + G2] = g2; +// frames[frameIndex + B2] = b2; +// } +// +// override public void Apply (Skeleton skeleton, float lastTime, float time, Vector firedEvents, float alpha, MixPose pose, MixDirection direction) { +// Slot slot = skeleton.slots.Items[slotIndex]; +// float[] frames = _frames; +// if (time < frames[0]) { // Time is before first frame. +// var slotData = slot.data; +// switch (pose) { +// case MixPose_Setup: +// // slot.color.set(slot.data.color); +// // slot.darkColor.set(slot.data.darkColor); +// slot.r = slotData.r; +// slot.g = slotData.g; +// slot.b = slotData.b; +// slot.a = slotData.a; +// slot.r2 = slotData.r2; +// slot.g2 = slotData.g2; +// slot.b2 = slotData.b2; +// return; +// case MixPose_Current: +// slot.r += (slot.r - slotData.r) * alpha; +// slot.g += (slot.g - slotData.g) * alpha; +// slot.b += (slot.b - slotData.b) * alpha; +// slot.a += (slot.a - slotData.a) * alpha; +// slot.r2 += (slot.r2 - slotData.r2) * alpha; +// slot.g2 += (slot.g2 - slotData.g2) * alpha; +// slot.b2 += (slot.b2 - slotData.b2) * alpha; +// return; +// } +// return; +// } +// +// float r, g, b, a, r2, g2, b2; +// if (time >= frames[frames.Length - ENTRIES]) { // Time is after last frame. +// int i = frames.Length; +// r = frames[i + PREV_R]; +// g = frames[i + PREV_G]; +// b = frames[i + PREV_B]; +// a = frames[i + PREV_A]; +// r2 = frames[i + PREV_R2]; +// g2 = frames[i + PREV_G2]; +// b2 = frames[i + PREV_B2]; +// } else { +// // Interpolate between the previous frame and the current frame. +// int frame = Animation.BinarySearch(frames, time, ENTRIES); +// r = frames[frame + PREV_R]; +// g = frames[frame + PREV_G]; +// b = frames[frame + PREV_B]; +// a = frames[frame + PREV_A]; +// r2 = frames[frame + PREV_R2]; +// g2 = frames[frame + PREV_G2]; +// b2 = frames[frame + PREV_B2]; +// float frameTime = frames[frame]; +// float percent = GetCurvePercent(frame / ENTRIES - 1, +// 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime)); +// +// r += (frames[frame + R] - r) * percent; +// g += (frames[frame + G] - g) * percent; +// b += (frames[frame + B] - b) * percent; +// a += (frames[frame + A] - a) * percent; +// r2 += (frames[frame + R2] - r2) * percent; +// g2 += (frames[frame + G2] - g2) * percent; +// b2 += (frames[frame + B2] - b2) * percent; +// } +// if (alpha == 1) { +// slot.r = r; +// slot.g = g; +// slot.b = b; +// slot.a = a; +// slot.r2 = r2; +// slot.g2 = g2; +// slot.b2 = b2; +// } else { +// float br, bg, bb, ba, br2, bg2, bb2; +// if (pose == MixPose_Setup) { +// br = slot.data.r; +// bg = slot.data.g; +// bb = slot.data.b; +// ba = slot.data.a; +// br2 = slot.data.r2; +// bg2 = slot.data.g2; +// bb2 = slot.data.b2; +// } else { +// br = slot.r; +// bg = slot.g; +// bb = slot.b; +// ba = slot.a; +// br2 = slot.r2; +// bg2 = slot.g2; +// bb2 = slot.b2; +// } +// slot.r = br + ((r - br) * alpha); +// slot.g = bg + ((g - bg) * alpha); +// slot.b = bb + ((b - bb) * alpha); +// slot.a = ba + ((a - ba) * alpha); +// slot.r2 = br2 + ((r2 - br2) * alpha); +// slot.g2 = bg2 + ((g2 - bg2) * alpha); +// slot.b2 = bb2 + ((b2 - bb2) * alpha); +// } +// } + }; } #endif /* Spine_TwoColorTimeline_h */ diff --git a/spine-cpp/spine-cpp/src/spine/AnimationStateData.cpp b/spine-cpp/spine-cpp/src/spine/AnimationStateData.cpp index de8ed8159..e1902824e 100644 --- a/spine-cpp/spine-cpp/src/spine/AnimationStateData.cpp +++ b/spine-cpp/spine-cpp/src/spine/AnimationStateData.cpp @@ -43,24 +43,27 @@ namespace Spine void AnimationStateData::setMix(std::string fromName, std::string toName, float duration) { Animation* from = _skeletonData.findAnimation(fromName); - assert(from != NULL); - Animation* to = _skeletonData.findAnimation(toName); - assert(to != NULL); - setMix(*from, *to, duration); + setMix(from, to, duration); } - void AnimationStateData::setMix(Animation& from, Animation& to, float duration) + void AnimationStateData::setMix(Animation* from, Animation* to, float duration) { + assert(from != NULL); + assert(to != NULL); + AnimationPair key(from, to); HashMap::Iterator i = _animationToMixTime.find(key); _animationToMixTime.erase(i); _animationToMixTime.insert(key, duration); } - float AnimationStateData::getMix(Animation& from, Animation& to) + float AnimationStateData::getMix(Animation* from, Animation* to) { + assert(from != NULL); + assert(to != NULL); + AnimationPair key(from, to); HashMap::Iterator i = _animationToMixTime.find(key); @@ -88,30 +91,30 @@ namespace Spine _defaultMix = inValue; } - AnimationStateData::AnimationPair::AnimationPair(Animation& a1, Animation& a2) : _a1(a1), _a2(a2) + AnimationStateData::AnimationPair::AnimationPair(Animation* a1, Animation* a2) : _a1(a1), _a2(a2) { // Empty } bool AnimationStateData::AnimationPair::operator==(const AnimationPair &other) const { - return _a1._name == other._a1._name && _a2._name == other._a2._name; + return _a1->_name == other._a1->_name && _a2->_name == other._a2->_name; } std::size_t AnimationStateData::HashAnimationPair::operator()(const Spine::AnimationStateData::AnimationPair& val) const { std::size_t h1 = 7; - size_t strlen = val._a1._name.length(); + size_t strlen = val._a1->_name.length(); for (int i = 0; i < strlen; ++i) { - h1 = h1 * 31 + val._a1._name.at(i); + h1 = h1 * 31 + val._a1->_name.at(i); } std::size_t h2 = 7; - strlen = val._a2._name.length(); + strlen = val._a2->_name.length(); for (int i = 0; i < strlen; ++i) { - h2 = h2 * 31 + val._a2._name.at(i); + h2 = h2 * 31 + val._a2->_name.at(i); } return (((h1 << 5) + h1) ^ h2); From 5bba269f1385da6adb75eb4a2b6bc9be096a64ed Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Sun, 19 Nov 2017 19:01:30 -0500 Subject: [PATCH 37/83] Changing RTTI to SPINE_RTTI and RTTI.h/cpp to SpineRTTI.h/cpp --- .../include/spine/AtlasAttachmentLoader.h | 2 +- .../spine-cpp/include/spine/Attachment.h | 4 +- .../include/spine/AttachmentLoader.h | 4 +- .../include/spine/AttachmentTimeline.h | 2 +- spine-cpp/spine-cpp/include/spine/Bone.h | 2 +- .../include/spine/BoundingBoxAttachment.h | 2 +- .../include/spine/ClippingAttachment.h | 2 +- .../spine-cpp/include/spine/ColorTimeline.h | 2 +- .../spine-cpp/include/spine/Constraint.h | 2 +- .../spine-cpp/include/spine/CurveTimeline.h | 2 +- .../spine-cpp/include/spine/DeformTimeline.h | 2 +- .../include/spine/DrawOrderTimeline.h | 2 +- .../spine-cpp/include/spine/EventTimeline.h | 2 +- .../spine-cpp/include/spine/IkConstraint.h | 2 +- .../include/spine/IkConstraintTimeline.h | 2 +- .../spine-cpp/include/spine/MeshAttachment.h | 2 +- .../spine-cpp/include/spine/PathAttachment.h | 2 +- .../spine-cpp/include/spine/PathConstraint.h | 2 +- .../include/spine/PathConstraintMixTimeline.h | 2 +- .../spine/PathConstraintPositionTimeline.h | 2 +- .../spine/PathConstraintSpacingTimeline.h | 2 +- .../spine-cpp/include/spine/PointAttachment.h | 2 +- .../include/spine/RegionAttachment.h | 2 +- .../spine-cpp/include/spine/RotateTimeline.h | 2 +- .../spine-cpp/include/spine/ScaleTimeline.h | 2 +- .../spine-cpp/include/spine/ShearTimeline.h | 2 +- .../include/spine/{RTTI.h => SpineRTTI.h} | 40 +++++++++---------- spine-cpp/spine-cpp/include/spine/Timeline.h | 4 +- .../include/spine/TransformConstraint.h | 2 +- .../spine/TransformConstraintTimeline.h | 2 +- .../include/spine/TranslateTimeline.h | 2 +- .../include/spine/TwoColorTimeline.h | 2 +- spine-cpp/spine-cpp/include/spine/Updatable.h | 4 +- .../include/spine/VertexAttachment.h | 2 +- .../src/spine/AtlasAttachmentLoader.cpp | 2 +- spine-cpp/spine-cpp/src/spine/Attachment.cpp | 2 +- .../spine-cpp/src/spine/AttachmentLoader.cpp | 2 +- .../src/spine/AttachmentTimeline.cpp | 2 +- spine-cpp/spine-cpp/src/spine/Bone.cpp | 2 +- .../src/spine/BoundingBoxAttachment.cpp | 2 +- .../src/spine/ClippingAttachment.cpp | 2 +- .../spine-cpp/src/spine/ColorTimeline.cpp | 2 +- spine-cpp/spine-cpp/src/spine/Constraint.cpp | 2 +- .../spine-cpp/src/spine/CurveTimeline.cpp | 2 +- .../spine-cpp/src/spine/DeformTimeline.cpp | 2 +- .../spine-cpp/src/spine/DrawOrderTimeline.cpp | 2 +- .../spine-cpp/src/spine/EventTimeline.cpp | 2 +- .../spine-cpp/src/spine/IkConstraint.cpp | 2 +- .../src/spine/IkConstraintTimeline.cpp | 2 +- .../spine-cpp/src/spine/MeshAttachment.cpp | 2 +- .../spine-cpp/src/spine/PathAttachment.cpp | 2 +- .../spine-cpp/src/spine/PathConstraint.cpp | 4 +- .../src/spine/PathConstraintMixTimeline.cpp | 2 +- .../spine/PathConstraintPositionTimeline.cpp | 2 +- .../spine/PathConstraintSpacingTimeline.cpp | 2 +- .../spine-cpp/src/spine/PointAttachment.cpp | 2 +- .../spine-cpp/src/spine/RegionAttachment.cpp | 2 +- .../spine-cpp/src/spine/RotateTimeline.cpp | 2 +- .../spine-cpp/src/spine/ScaleTimeline.cpp | 2 +- .../spine-cpp/src/spine/ShearTimeline.cpp | 2 +- spine-cpp/spine-cpp/src/spine/Skeleton.cpp | 8 ++-- .../src/spine/{RTTI.cpp => SpineRTTI.cpp} | 16 ++++---- spine-cpp/spine-cpp/src/spine/Timeline.cpp | 2 +- .../src/spine/TransformConstraint.cpp | 2 +- .../src/spine/TransformConstraintTimeline.cpp | 2 +- .../spine-cpp/src/spine/TranslateTimeline.cpp | 2 +- .../spine-cpp/src/spine/TwoColorTimeline.cpp | 2 +- spine-cpp/spine-cpp/src/spine/Updatable.cpp | 2 +- .../spine-cpp/src/spine/VertexAttachment.cpp | 2 +- 69 files changed, 103 insertions(+), 103 deletions(-) rename spine-cpp/spine-cpp/include/spine/{RTTI.h => SpineRTTI.h} (69%) rename spine-cpp/spine-cpp/src/spine/{RTTI.cpp => SpineRTTI.cpp} (79%) diff --git a/spine-cpp/spine-cpp/include/spine/AtlasAttachmentLoader.h b/spine-cpp/spine-cpp/include/spine/AtlasAttachmentLoader.h index d8f820111..a226f36a6 100644 --- a/spine-cpp/spine-cpp/include/spine/AtlasAttachmentLoader.h +++ b/spine-cpp/spine-cpp/include/spine/AtlasAttachmentLoader.h @@ -45,7 +45,7 @@ namespace Spine /// class AtlasAttachmentLoader : public AttachmentLoader { - RTTI_DECL; + SPINE_RTTI_DECL; public: AtlasAttachmentLoader (Vector& inAtlasArray) : _atlasArray(inAtlasArray) diff --git a/spine-cpp/spine-cpp/include/spine/Attachment.h b/spine-cpp/spine-cpp/include/spine/Attachment.h index fdf5a1a58..48c9e2cc1 100644 --- a/spine-cpp/spine-cpp/include/spine/Attachment.h +++ b/spine-cpp/spine-cpp/include/spine/Attachment.h @@ -31,7 +31,7 @@ #ifndef Spine_Attachment_h #define Spine_Attachment_h -#include +#include #include @@ -39,7 +39,7 @@ namespace Spine { class Attachment { - RTTI_DECL; + SPINE_RTTI_DECL; public: Attachment(std::string name); diff --git a/spine-cpp/spine-cpp/include/spine/AttachmentLoader.h b/spine-cpp/spine-cpp/include/spine/AttachmentLoader.h index b04b5f929..7712e4cc1 100644 --- a/spine-cpp/spine-cpp/include/spine/AttachmentLoader.h +++ b/spine-cpp/spine-cpp/include/spine/AttachmentLoader.h @@ -31,7 +31,7 @@ #ifndef Spine_AttachmentLoader_h #define Spine_AttachmentLoader_h -#include +#include #include @@ -47,7 +47,7 @@ namespace Spine class AttachmentLoader { - RTTI_DECL; + SPINE_RTTI_DECL; /// @return May be NULL to not load any attachment. virtual RegionAttachment* newRegionAttachment(Skin& skin, std::string name, std::string path) = 0; diff --git a/spine-cpp/spine-cpp/include/spine/AttachmentTimeline.h b/spine-cpp/spine-cpp/include/spine/AttachmentTimeline.h index 8268b47d1..31267ada8 100644 --- a/spine-cpp/spine-cpp/include/spine/AttachmentTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/AttachmentTimeline.h @@ -46,7 +46,7 @@ namespace Spine class AttachmentTimeline : public Timeline { - RTTI_DECL; + SPINE_RTTI_DECL; public: AttachmentTimeline(int frameCount) diff --git a/spine-cpp/spine-cpp/include/spine/Bone.h b/spine-cpp/spine-cpp/include/spine/Bone.h index 9900324be..7ae7813e9 100644 --- a/spine-cpp/spine-cpp/include/spine/Bone.h +++ b/spine-cpp/spine-cpp/include/spine/Bone.h @@ -47,7 +47,7 @@ namespace Spine /// constraint or application code modifies the world transform after it was computed from the local transform. class Bone : public Updatable { - RTTI_DECL; + SPINE_RTTI_DECL; friend class RotateTimeline; friend class IkConstraint; diff --git a/spine-cpp/spine-cpp/include/spine/BoundingBoxAttachment.h b/spine-cpp/spine-cpp/include/spine/BoundingBoxAttachment.h index 996af9f94..1ad9f13d0 100644 --- a/spine-cpp/spine-cpp/include/spine/BoundingBoxAttachment.h +++ b/spine-cpp/spine-cpp/include/spine/BoundingBoxAttachment.h @@ -38,7 +38,7 @@ namespace Spine /// Attachment that has a polygon for bounds checking. class BoundingBoxAttachment : public VertexAttachment { - RTTI_DECL; + SPINE_RTTI_DECL; BoundingBoxAttachment(std::string name); }; diff --git a/spine-cpp/spine-cpp/include/spine/ClippingAttachment.h b/spine-cpp/spine-cpp/include/spine/ClippingAttachment.h index bd9c7ebf2..6ee27813d 100644 --- a/spine-cpp/spine-cpp/include/spine/ClippingAttachment.h +++ b/spine-cpp/spine-cpp/include/spine/ClippingAttachment.h @@ -39,7 +39,7 @@ namespace Spine class ClippingAttachment : public VertexAttachment { - RTTI_DECL; + SPINE_RTTI_DECL; public: ClippingAttachment(std::string name); diff --git a/spine-cpp/spine-cpp/include/spine/ColorTimeline.h b/spine-cpp/spine-cpp/include/spine/ColorTimeline.h index 8da2c5700..c12c54f1c 100644 --- a/spine-cpp/spine-cpp/include/spine/ColorTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/ColorTimeline.h @@ -37,7 +37,7 @@ namespace Spine { class ColorTimeline : public CurveTimeline { - RTTI_DECL; + SPINE_RTTI_DECL; // public const int ENTRIES = 5; // protected const int PREV_TIME = -5, PREV_R = -4, PREV_G = -3, PREV_B = -2, PREV_A = -1; diff --git a/spine-cpp/spine-cpp/include/spine/Constraint.h b/spine-cpp/spine-cpp/include/spine/Constraint.h index aa0122c34..18d45cece 100644 --- a/spine-cpp/spine-cpp/include/spine/Constraint.h +++ b/spine-cpp/spine-cpp/include/spine/Constraint.h @@ -38,7 +38,7 @@ namespace Spine /// The interface for all constraints. class Constraint : public Updatable { - RTTI_DECL; + SPINE_RTTI_DECL; public: Constraint(); diff --git a/spine-cpp/spine-cpp/include/spine/CurveTimeline.h b/spine-cpp/spine-cpp/include/spine/CurveTimeline.h index a5222e31e..38f489b26 100644 --- a/spine-cpp/spine-cpp/include/spine/CurveTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/CurveTimeline.h @@ -41,7 +41,7 @@ namespace Spine /// Base class for frames that use an interpolation bezier curve. class CurveTimeline : public Timeline { - RTTI_DECL; + SPINE_RTTI_DECL; public: CurveTimeline(int frameCount); diff --git a/spine-cpp/spine-cpp/include/spine/DeformTimeline.h b/spine-cpp/spine-cpp/include/spine/DeformTimeline.h index 90d768b34..6e4aa3512 100644 --- a/spine-cpp/spine-cpp/include/spine/DeformTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/DeformTimeline.h @@ -37,7 +37,7 @@ namespace Spine { class DeformTimeline : CurveTimeline { - RTTI_DECL; + SPINE_RTTI_DECL; // internal int slotIndex; // internal float[] frames; diff --git a/spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h b/spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h index 487f619a7..97648b8a7 100644 --- a/spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h @@ -37,7 +37,7 @@ namespace Spine { class DrawOrderTimeline : public Timeline { - RTTI_DECL; + SPINE_RTTI_DECL; // internal float[] frames; // private int[][] drawOrders; diff --git a/spine-cpp/spine-cpp/include/spine/EventTimeline.h b/spine-cpp/spine-cpp/include/spine/EventTimeline.h index 8fe56819e..67313e7dc 100644 --- a/spine-cpp/spine-cpp/include/spine/EventTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/EventTimeline.h @@ -37,7 +37,7 @@ namespace Spine { class EventTimeline : public Timeline { - RTTI_DECL; + SPINE_RTTI_DECL; // internal float[] frames; // private Event[] events; diff --git a/spine-cpp/spine-cpp/include/spine/IkConstraint.h b/spine-cpp/spine-cpp/include/spine/IkConstraint.h index c09f8c7cd..b40f06867 100644 --- a/spine-cpp/spine-cpp/include/spine/IkConstraint.h +++ b/spine-cpp/spine-cpp/include/spine/IkConstraint.h @@ -45,7 +45,7 @@ namespace Spine { friend class Skeleton; - RTTI_DECL; + SPINE_RTTI_DECL; public: /// Adjusts the bone rotation so the tip is as close to the target position as possible. The target is specified diff --git a/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h b/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h index b7605da11..ac04b035d 100644 --- a/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h @@ -37,7 +37,7 @@ namespace Spine { class IkConstraintTimeline : public CurveTimeline { - RTTI_DECL; + SPINE_RTTI_DECL; // public const int ENTRIES = 3; // private const int PREV_TIME = -3, PREV_MIX = -2, PREV_BEND_DIRECTION = -1; diff --git a/spine-cpp/spine-cpp/include/spine/MeshAttachment.h b/spine-cpp/spine-cpp/include/spine/MeshAttachment.h index 821c73dd9..dee544d61 100644 --- a/spine-cpp/spine-cpp/include/spine/MeshAttachment.h +++ b/spine-cpp/spine-cpp/include/spine/MeshAttachment.h @@ -42,7 +42,7 @@ namespace Spine /// Attachment that displays a texture region using a mesh. class MeshAttachment : public VertexAttachment { - RTTI_DECL; + SPINE_RTTI_DECL; public: MeshAttachment(std::string name); diff --git a/spine-cpp/spine-cpp/include/spine/PathAttachment.h b/spine-cpp/spine-cpp/include/spine/PathAttachment.h index 6f0e53993..a261daad8 100644 --- a/spine-cpp/spine-cpp/include/spine/PathAttachment.h +++ b/spine-cpp/spine-cpp/include/spine/PathAttachment.h @@ -37,7 +37,7 @@ namespace Spine { class PathAttachment : public VertexAttachment { - RTTI_DECL; + SPINE_RTTI_DECL; public: PathAttachment(std::string name); diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraint.h b/spine-cpp/spine-cpp/include/spine/PathConstraint.h index 7f6440c48..e7cf63721 100644 --- a/spine-cpp/spine-cpp/include/spine/PathConstraint.h +++ b/spine-cpp/spine-cpp/include/spine/PathConstraint.h @@ -47,7 +47,7 @@ namespace Spine { friend class Skeleton; - RTTI_DECL; + SPINE_RTTI_DECL; public: PathConstraint(PathConstraintData& data, Skeleton& skeleton); diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h b/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h index a218bde35..c27619e0a 100644 --- a/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h @@ -37,7 +37,7 @@ namespace Spine { class PathConstraintMixTimeline : public CurveTimeline { - RTTI_DECL; + SPINE_RTTI_DECL; // public const int ENTRIES = 3; // private const int PREV_TIME = -3, PREV_ROTATE = -2, PREV_TRANSLATE = -1; diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h b/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h index 1197aad93..5d58d5eb6 100644 --- a/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h @@ -37,7 +37,7 @@ namespace Spine { class PathConstraintPositionTimeline : public CurveTimeline { - RTTI_DECL; + SPINE_RTTI_DECL; // public const int ENTRIES = 2; // protected const int PREV_TIME = -2, PREV_VALUE = -1; diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h b/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h index 75969f1a3..5ff6892a5 100644 --- a/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h @@ -37,7 +37,7 @@ namespace Spine { class PathConstraintSpacingTimeline : public PathConstraintPositionTimeline { - RTTI_DECL; + SPINE_RTTI_DECL; // override public int PropertyId { // get { return ((int)TimelineType.PathConstraintSpacing << 24) + pathConstraintIndex; } diff --git a/spine-cpp/spine-cpp/include/spine/PointAttachment.h b/spine-cpp/spine-cpp/include/spine/PointAttachment.h index 6738021a7..cb9385f2b 100644 --- a/spine-cpp/spine-cpp/include/spine/PointAttachment.h +++ b/spine-cpp/spine-cpp/include/spine/PointAttachment.h @@ -46,7 +46,7 @@ namespace Spine /// class PointAttachment : public Attachment { - RTTI_DECL; + SPINE_RTTI_DECL; public: PointAttachment(std::string name); diff --git a/spine-cpp/spine-cpp/include/spine/RegionAttachment.h b/spine-cpp/spine-cpp/include/spine/RegionAttachment.h index c85c0be1c..9151691c0 100644 --- a/spine-cpp/spine-cpp/include/spine/RegionAttachment.h +++ b/spine-cpp/spine-cpp/include/spine/RegionAttachment.h @@ -46,7 +46,7 @@ namespace Spine /// Attachment that displays a texture region. class RegionAttachment : public Attachment { - RTTI_DECL; + SPINE_RTTI_DECL; public: RegionAttachment(std::string name); diff --git a/spine-cpp/spine-cpp/include/spine/RotateTimeline.h b/spine-cpp/spine-cpp/include/spine/RotateTimeline.h index dcc013b71..ff1fb3ae7 100644 --- a/spine-cpp/spine-cpp/include/spine/RotateTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/RotateTimeline.h @@ -37,7 +37,7 @@ namespace Spine { class RotateTimeline : public CurveTimeline { - RTTI_DECL; + SPINE_RTTI_DECL; public: static const int ENTRIES = 2; diff --git a/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h b/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h index 00e10e325..075fb9b9c 100644 --- a/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h @@ -37,7 +37,7 @@ namespace Spine { class ScaleTimeline : public TranslateTimeline { - RTTI_DECL; + SPINE_RTTI_DECL; // override public int PropertyId { // get { return ((int)TimelineType.Scale << 24) + boneIndex; } diff --git a/spine-cpp/spine-cpp/include/spine/ShearTimeline.h b/spine-cpp/spine-cpp/include/spine/ShearTimeline.h index 1b367e2c2..b04c4156d 100644 --- a/spine-cpp/spine-cpp/include/spine/ShearTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/ShearTimeline.h @@ -37,7 +37,7 @@ namespace Spine { class ShearTimeline : public TranslateTimeline { - RTTI_DECL; + SPINE_RTTI_DECL; // override public int PropertyId { // get { return ((int)TimelineType.Shear << 24) + boneIndex; } diff --git a/spine-cpp/spine-cpp/include/spine/RTTI.h b/spine-cpp/spine-cpp/include/spine/SpineRTTI.h similarity index 69% rename from spine-cpp/spine-cpp/include/spine/RTTI.h rename to spine-cpp/spine-cpp/include/spine/SpineRTTI.h index 79f413efa..9cf985ae8 100644 --- a/spine-cpp/spine-cpp/include/spine/RTTI.h +++ b/spine-cpp/spine-cpp/include/spine/SpineRTTI.h @@ -28,48 +28,48 @@ * POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -#ifndef Spine_RTTI_h -#define Spine_RTTI_h +#ifndef Spine_SPINE_RTTI_h +#define Spine_SPINE_RTTI_h #include namespace Spine { - class RTTI + class SPINE_RTTI { public: - RTTI(const std::string& className); + SPINE_RTTI(const std::string& className); - RTTI(const std::string& className, const RTTI& baseRTTI); + SPINE_RTTI(const std::string& className, const SPINE_RTTI& baseSPINE_RTTI); const std::string& getClassName() const; - bool isExactly(const RTTI& rtti) const; + bool isExactly(const SPINE_RTTI& rtti) const; - bool derivesFrom(const RTTI& rtti) const; + bool derivesFrom(const SPINE_RTTI& rtti) const; private: // Prevent copying - RTTI(const RTTI& obj); - RTTI& operator=(const RTTI& obj); + SPINE_RTTI(const SPINE_RTTI& obj); + SPINE_RTTI& operator=(const SPINE_RTTI& obj); const std::string m_className; - const RTTI *m_pBaseRTTI; + const SPINE_RTTI *m_pBaseSPINE_RTTI; }; } -#define RTTI_DECL \ +#define SPINE_RTTI_DECL \ public: \ -static const Spine::RTTI rtti; \ -virtual const Spine::RTTI& getRTTI(); +static const Spine::SPINE_RTTI rtti; \ +virtual const Spine::SPINE_RTTI& getSPINE_RTTI(); -#define RTTI_IMPL_NOPARENT(name) \ -const Spine::RTTI name::rtti(#name); \ -const Spine::RTTI& name::getRTTI() { return rtti; } +#define SPINE_RTTI_IMPL_NOPARENT(name) \ +const Spine::SPINE_RTTI name::rtti(#name); \ +const Spine::SPINE_RTTI& name::getSPINE_RTTI() { return rtti; } -#define RTTI_IMPL(name,parent) \ -const Spine::RTTI name::rtti(#name, parent::rtti); \ -const Spine::RTTI& name::getRTTI() { return rtti; } +#define SPINE_RTTI_IMPL(name,parent) \ +const Spine::SPINE_RTTI name::rtti(#name, parent::rtti); \ +const Spine::SPINE_RTTI& name::getSPINE_RTTI() { return rtti; } -#endif /* Spine_RTTI_h */ +#endif /* Spine_SPINE_RTTI_h */ diff --git a/spine-cpp/spine-cpp/include/spine/Timeline.h b/spine-cpp/spine-cpp/include/spine/Timeline.h index b00db7b28..0160e371a 100644 --- a/spine-cpp/spine-cpp/include/spine/Timeline.h +++ b/spine-cpp/spine-cpp/include/spine/Timeline.h @@ -31,7 +31,7 @@ #ifndef Spine_Timeline_h #define Spine_Timeline_h -#include +#include #include #include #include @@ -43,7 +43,7 @@ namespace Spine class Timeline { - RTTI_DECL; + SPINE_RTTI_DECL; public: Timeline(); diff --git a/spine-cpp/spine-cpp/include/spine/TransformConstraint.h b/spine-cpp/spine-cpp/include/spine/TransformConstraint.h index 262c3a210..c2036d4ab 100644 --- a/spine-cpp/spine-cpp/include/spine/TransformConstraint.h +++ b/spine-cpp/spine-cpp/include/spine/TransformConstraint.h @@ -45,7 +45,7 @@ namespace Spine { friend class Skeleton; - RTTI_DECL; + SPINE_RTTI_DECL; public: TransformConstraint(TransformConstraintData& data, Skeleton& skeleton); diff --git a/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h b/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h index d46b817f7..00debb06d 100644 --- a/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h @@ -37,7 +37,7 @@ namespace Spine { class TransformConstraintTimeline : public CurveTimeline { - RTTI_DECL; + SPINE_RTTI_DECL; // public const int ENTRIES = 5; // private const int PREV_TIME = -5, PREV_ROTATE = -4, PREV_TRANSLATE = -3, PREV_SCALE = -2, PREV_SHEAR = -1; diff --git a/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h b/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h index ca6a0ce9d..8abccc9e2 100644 --- a/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h @@ -40,7 +40,7 @@ namespace Spine { class TranslateTimeline : public CurveTimeline { - RTTI_DECL; + SPINE_RTTI_DECL; // public const int ENTRIES = 3; // protected const int PREV_TIME = -3, PREV_X = -2, PREV_Y = -1; diff --git a/spine-cpp/spine-cpp/include/spine/TwoColorTimeline.h b/spine-cpp/spine-cpp/include/spine/TwoColorTimeline.h index befea9f94..8d814439f 100644 --- a/spine-cpp/spine-cpp/include/spine/TwoColorTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/TwoColorTimeline.h @@ -37,7 +37,7 @@ namespace Spine { class TwoColorTimeline : public CurveTimeline { - RTTI_DECL; + SPINE_RTTI_DECL; // public const int ENTRIES = 8; // protected const int PREV_TIME = -8, PREV_R = -7, PREV_G = -6, PREV_B = -5, PREV_A = -4; diff --git a/spine-cpp/spine-cpp/include/spine/Updatable.h b/spine-cpp/spine-cpp/include/spine/Updatable.h index fac634191..cb36e863e 100644 --- a/spine-cpp/spine-cpp/include/spine/Updatable.h +++ b/spine-cpp/spine-cpp/include/spine/Updatable.h @@ -31,13 +31,13 @@ #ifndef Spine_Updatable_h #define Spine_Updatable_h -#include +#include namespace Spine { class Updatable { - RTTI_DECL; + SPINE_RTTI_DECL; public: Updatable(); diff --git a/spine-cpp/spine-cpp/include/spine/VertexAttachment.h b/spine-cpp/spine-cpp/include/spine/VertexAttachment.h index 6405015f6..7c7841bd0 100644 --- a/spine-cpp/spine-cpp/include/spine/VertexAttachment.h +++ b/spine-cpp/spine-cpp/include/spine/VertexAttachment.h @@ -42,7 +42,7 @@ namespace Spine /// An attachment with vertices that are transformed by one or more bones and can be deformed by a slot's vertices. class VertexAttachment : public Attachment { - RTTI_DECL; + SPINE_RTTI_DECL; public: VertexAttachment(std::string name); diff --git a/spine-cpp/spine-cpp/src/spine/AtlasAttachmentLoader.cpp b/spine-cpp/spine-cpp/src/spine/AtlasAttachmentLoader.cpp index 1daf02530..0d5a99aca 100644 --- a/spine-cpp/spine-cpp/src/spine/AtlasAttachmentLoader.cpp +++ b/spine-cpp/spine-cpp/src/spine/AtlasAttachmentLoader.cpp @@ -32,5 +32,5 @@ namespace Spine { - RTTI_IMPL(AtlasAttachmentLoader, AttachmentLoader); + SPINE_RTTI_IMPL(AtlasAttachmentLoader, AttachmentLoader); } diff --git a/spine-cpp/spine-cpp/src/spine/Attachment.cpp b/spine-cpp/spine-cpp/src/spine/Attachment.cpp index 74a734f27..93107e041 100644 --- a/spine-cpp/spine-cpp/src/spine/Attachment.cpp +++ b/spine-cpp/spine-cpp/src/spine/Attachment.cpp @@ -34,7 +34,7 @@ namespace Spine { - RTTI_IMPL_NOPARENT(Attachment); + SPINE_RTTI_IMPL_NOPARENT(Attachment); Attachment::Attachment(std::string name) : _name(name) { diff --git a/spine-cpp/spine-cpp/src/spine/AttachmentLoader.cpp b/spine-cpp/spine-cpp/src/spine/AttachmentLoader.cpp index bfe43d75f..04c5e3979 100644 --- a/spine-cpp/spine-cpp/src/spine/AttachmentLoader.cpp +++ b/spine-cpp/spine-cpp/src/spine/AttachmentLoader.cpp @@ -32,5 +32,5 @@ namespace Spine { - RTTI_IMPL_NOPARENT(AttachmentLoader); + SPINE_RTTI_IMPL_NOPARENT(AttachmentLoader); } diff --git a/spine-cpp/spine-cpp/src/spine/AttachmentTimeline.cpp b/spine-cpp/spine-cpp/src/spine/AttachmentTimeline.cpp index e91dce772..cc562fd80 100644 --- a/spine-cpp/spine-cpp/src/spine/AttachmentTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/AttachmentTimeline.cpp @@ -38,5 +38,5 @@ namespace Spine { - RTTI_IMPL(AttachmentTimeline, Timeline); + SPINE_RTTI_IMPL(AttachmentTimeline, Timeline); } diff --git a/spine-cpp/spine-cpp/src/spine/Bone.cpp b/spine-cpp/spine-cpp/src/spine/Bone.cpp index 71e119c95..7ad89853c 100644 --- a/spine-cpp/spine-cpp/src/spine/Bone.cpp +++ b/spine-cpp/spine-cpp/src/spine/Bone.cpp @@ -38,7 +38,7 @@ namespace Spine { - RTTI_IMPL(Bone, Updatable); + SPINE_RTTI_IMPL(Bone, Updatable); bool Bone::yDown = false; diff --git a/spine-cpp/spine-cpp/src/spine/BoundingBoxAttachment.cpp b/spine-cpp/spine-cpp/src/spine/BoundingBoxAttachment.cpp index ffa7f7355..df7a70934 100644 --- a/spine-cpp/spine-cpp/src/spine/BoundingBoxAttachment.cpp +++ b/spine-cpp/spine-cpp/src/spine/BoundingBoxAttachment.cpp @@ -32,7 +32,7 @@ namespace Spine { - RTTI_IMPL(BoundingBoxAttachment, VertexAttachment); + SPINE_RTTI_IMPL(BoundingBoxAttachment, VertexAttachment); BoundingBoxAttachment::BoundingBoxAttachment(std::string name) : VertexAttachment(name) { diff --git a/spine-cpp/spine-cpp/src/spine/ClippingAttachment.cpp b/spine-cpp/spine-cpp/src/spine/ClippingAttachment.cpp index c87de561c..1ad21ba86 100644 --- a/spine-cpp/spine-cpp/src/spine/ClippingAttachment.cpp +++ b/spine-cpp/spine-cpp/src/spine/ClippingAttachment.cpp @@ -34,7 +34,7 @@ namespace Spine { - RTTI_IMPL(ClippingAttachment, VertexAttachment); + SPINE_RTTI_IMPL(ClippingAttachment, VertexAttachment); ClippingAttachment::ClippingAttachment(std::string name) : VertexAttachment(name) { diff --git a/spine-cpp/spine-cpp/src/spine/ColorTimeline.cpp b/spine-cpp/spine-cpp/src/spine/ColorTimeline.cpp index e1a2c4ff4..e53c26b97 100644 --- a/spine-cpp/spine-cpp/src/spine/ColorTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/ColorTimeline.cpp @@ -32,5 +32,5 @@ namespace Spine { - RTTI_IMPL(ColorTimeline, CurveTimeline); + SPINE_RTTI_IMPL(ColorTimeline, CurveTimeline); } diff --git a/spine-cpp/spine-cpp/src/spine/Constraint.cpp b/spine-cpp/spine-cpp/src/spine/Constraint.cpp index bad9d1a0b..206c93b5e 100644 --- a/spine-cpp/spine-cpp/src/spine/Constraint.cpp +++ b/spine-cpp/spine-cpp/src/spine/Constraint.cpp @@ -32,7 +32,7 @@ namespace Spine { - RTTI_IMPL(Constraint, Updatable); + SPINE_RTTI_IMPL(Constraint, Updatable); Constraint::Constraint() { diff --git a/spine-cpp/spine-cpp/src/spine/CurveTimeline.cpp b/spine-cpp/spine-cpp/src/spine/CurveTimeline.cpp index ea4047eb2..5d0e58401 100644 --- a/spine-cpp/spine-cpp/src/spine/CurveTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/CurveTimeline.cpp @@ -34,7 +34,7 @@ namespace Spine { - RTTI_IMPL(CurveTimeline, Timeline); + SPINE_RTTI_IMPL(CurveTimeline, Timeline); const float CurveTimeline::LINEAR = 0; const float CurveTimeline::STEPPED = 1; diff --git a/spine-cpp/spine-cpp/src/spine/DeformTimeline.cpp b/spine-cpp/spine-cpp/src/spine/DeformTimeline.cpp index 42e9be963..fb99c6d33 100644 --- a/spine-cpp/spine-cpp/src/spine/DeformTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/DeformTimeline.cpp @@ -32,5 +32,5 @@ namespace Spine { - RTTI_IMPL(DeformTimeline, CurveTimeline); + SPINE_RTTI_IMPL(DeformTimeline, CurveTimeline); } diff --git a/spine-cpp/spine-cpp/src/spine/DrawOrderTimeline.cpp b/spine-cpp/spine-cpp/src/spine/DrawOrderTimeline.cpp index 9ed5c7e7f..34f9c9b14 100644 --- a/spine-cpp/spine-cpp/src/spine/DrawOrderTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/DrawOrderTimeline.cpp @@ -32,5 +32,5 @@ namespace Spine { - RTTI_IMPL(DrawOrderTimeline, Timeline); + SPINE_RTTI_IMPL(DrawOrderTimeline, Timeline); } diff --git a/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp b/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp index ef4e0e8a5..dc6ee5246 100644 --- a/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp @@ -32,5 +32,5 @@ namespace Spine { - RTTI_IMPL(EventTimeline, Timeline); + SPINE_RTTI_IMPL(EventTimeline, Timeline); } diff --git a/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp b/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp index 8064b31a5..4c6c0e8c5 100644 --- a/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp +++ b/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp @@ -39,7 +39,7 @@ namespace Spine { - RTTI_IMPL(IkConstraint, Constraint); + SPINE_RTTI_IMPL(IkConstraint, Constraint); void IkConstraint::apply(Bone& bone, float targetX, float targetY, float alpha) { diff --git a/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp b/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp index 19755ad12..603b48c06 100644 --- a/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp @@ -32,5 +32,5 @@ namespace Spine { - RTTI_IMPL(IkConstraintTimeline, CurveTimeline); + SPINE_RTTI_IMPL(IkConstraintTimeline, CurveTimeline); } diff --git a/spine-cpp/spine-cpp/src/spine/MeshAttachment.cpp b/spine-cpp/spine-cpp/src/spine/MeshAttachment.cpp index 6d928a6c3..09793ad9a 100644 --- a/spine-cpp/spine-cpp/src/spine/MeshAttachment.cpp +++ b/spine-cpp/spine-cpp/src/spine/MeshAttachment.cpp @@ -32,7 +32,7 @@ namespace Spine { - RTTI_IMPL(MeshAttachment, VertexAttachment); + SPINE_RTTI_IMPL(MeshAttachment, VertexAttachment); MeshAttachment::MeshAttachment(std::string name) : VertexAttachment(name), _regionOffsetX(0), diff --git a/spine-cpp/spine-cpp/src/spine/PathAttachment.cpp b/spine-cpp/spine-cpp/src/spine/PathAttachment.cpp index 54bd9337b..f997e67a0 100644 --- a/spine-cpp/spine-cpp/src/spine/PathAttachment.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathAttachment.cpp @@ -32,7 +32,7 @@ namespace Spine { - RTTI_IMPL(PathAttachment, VertexAttachment); + SPINE_RTTI_IMPL(PathAttachment, VertexAttachment); PathAttachment::PathAttachment(std::string name) : VertexAttachment(name) { diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp b/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp index df73d6195..5d90c2ea7 100644 --- a/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp @@ -45,7 +45,7 @@ namespace Spine { - RTTI_IMPL(PathConstraint, Constraint); + SPINE_RTTI_IMPL(PathConstraint, Constraint); const float PathConstraint::EPSILON = 0.00001f; const int PathConstraint::NONE = -1; @@ -79,7 +79,7 @@ namespace Spine void PathConstraint::update() { Attachment* baseAttachment = _target->getAttachment(); - if (baseAttachment == NULL || !baseAttachment->getRTTI().derivesFrom(PathAttachment::rtti)) + if (baseAttachment == NULL || !baseAttachment->getSPINE_RTTI().derivesFrom(PathAttachment::rtti)) { return; } diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp b/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp index bd849f29d..515c7bf17 100644 --- a/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp @@ -32,5 +32,5 @@ namespace Spine { - RTTI_IMPL(PathConstraintMixTimeline, CurveTimeline); + SPINE_RTTI_IMPL(PathConstraintMixTimeline, CurveTimeline); } diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp b/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp index 0d944901e..ca033cd55 100644 --- a/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp @@ -32,5 +32,5 @@ namespace Spine { - RTTI_IMPL(PathConstraintPositionTimeline, CurveTimeline); + SPINE_RTTI_IMPL(PathConstraintPositionTimeline, CurveTimeline); } diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp b/spine-cpp/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp index f9becd25c..7a9f5567f 100644 --- a/spine-cpp/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp @@ -32,5 +32,5 @@ namespace Spine { - RTTI_IMPL(PathConstraintSpacingTimeline, PathConstraintPositionTimeline); + SPINE_RTTI_IMPL(PathConstraintSpacingTimeline, PathConstraintPositionTimeline); } diff --git a/spine-cpp/spine-cpp/src/spine/PointAttachment.cpp b/spine-cpp/spine-cpp/src/spine/PointAttachment.cpp index d309c8d48..b6b93c2ec 100644 --- a/spine-cpp/spine-cpp/src/spine/PointAttachment.cpp +++ b/spine-cpp/spine-cpp/src/spine/PointAttachment.cpp @@ -36,7 +36,7 @@ namespace Spine { - RTTI_IMPL(PointAttachment, Attachment); + SPINE_RTTI_IMPL(PointAttachment, Attachment); PointAttachment::PointAttachment(std::string name) : Attachment(name) { diff --git a/spine-cpp/spine-cpp/src/spine/RegionAttachment.cpp b/spine-cpp/spine-cpp/src/spine/RegionAttachment.cpp index 310a4619b..0ebbb8a41 100644 --- a/spine-cpp/spine-cpp/src/spine/RegionAttachment.cpp +++ b/spine-cpp/spine-cpp/src/spine/RegionAttachment.cpp @@ -38,7 +38,7 @@ namespace Spine { - RTTI_IMPL(RegionAttachment, Attachment); + SPINE_RTTI_IMPL(RegionAttachment, Attachment); const int RegionAttachment::BLX = 0; const int RegionAttachment::BLY = 1; diff --git a/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp b/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp index acfeb7db1..448d88134 100644 --- a/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp @@ -40,7 +40,7 @@ namespace Spine { - RTTI_IMPL(RotateTimeline, CurveTimeline); + SPINE_RTTI_IMPL(RotateTimeline, CurveTimeline); RotateTimeline::RotateTimeline(int frameCount) : CurveTimeline(frameCount), _boneIndex(0) { diff --git a/spine-cpp/spine-cpp/src/spine/ScaleTimeline.cpp b/spine-cpp/spine-cpp/src/spine/ScaleTimeline.cpp index 50c06453c..2da55b080 100644 --- a/spine-cpp/spine-cpp/src/spine/ScaleTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/ScaleTimeline.cpp @@ -32,5 +32,5 @@ namespace Spine { - RTTI_IMPL(ScaleTimeline, TranslateTimeline); + SPINE_RTTI_IMPL(ScaleTimeline, TranslateTimeline); } diff --git a/spine-cpp/spine-cpp/src/spine/ShearTimeline.cpp b/spine-cpp/spine-cpp/src/spine/ShearTimeline.cpp index b81a4442f..13d19abda 100644 --- a/spine-cpp/spine-cpp/src/spine/ShearTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/ShearTimeline.cpp @@ -32,5 +32,5 @@ namespace Spine { - RTTI_IMPL(ShearTimeline, TranslateTimeline); + SPINE_RTTI_IMPL(ShearTimeline, TranslateTimeline); } diff --git a/spine-cpp/spine-cpp/src/spine/Skeleton.cpp b/spine-cpp/spine-cpp/src/spine/Skeleton.cpp index 783ddda3b..454940d22 100644 --- a/spine-cpp/spine-cpp/src/spine/Skeleton.cpp +++ b/spine-cpp/spine-cpp/src/spine/Skeleton.cpp @@ -471,7 +471,7 @@ namespace Spine int verticesLength = 0; Attachment* attachment = slot->getAttachment(); - if (attachment != NULL && attachment->getRTTI().derivesFrom(RegionAttachment::rtti)) + if (attachment != NULL && attachment->getSPINE_RTTI().derivesFrom(RegionAttachment::rtti)) { RegionAttachment* regionAttachment = static_cast(attachment); @@ -482,7 +482,7 @@ namespace Spine } regionAttachment->computeWorldVertices(slot->getBone(), outVertexBuffer, 0); } - else if (attachment != NULL && attachment->getRTTI().derivesFrom(MeshAttachment::rtti)) + else if (attachment != NULL && attachment->getSPINE_RTTI().derivesFrom(MeshAttachment::rtti)) { MeshAttachment* mesh = static_cast(attachment); @@ -699,7 +699,7 @@ namespace Spine } Attachment* attachment = slot->_attachment; - if (attachment != NULL && attachment->getRTTI().derivesFrom(PathAttachment::rtti)) + if (attachment != NULL && attachment->getSPINE_RTTI().derivesFrom(PathAttachment::rtti)) { sortPathConstraintAttachment(attachment, slotBone); } @@ -780,7 +780,7 @@ namespace Spine void Skeleton::sortPathConstraintAttachment(Attachment* attachment, Bone& slotBone) { - if (attachment == NULL || attachment->getRTTI().derivesFrom(PathAttachment::rtti)) + if (attachment == NULL || attachment->getSPINE_RTTI().derivesFrom(PathAttachment::rtti)) { return; } diff --git a/spine-cpp/spine-cpp/src/spine/RTTI.cpp b/spine-cpp/spine-cpp/src/spine/SpineRTTI.cpp similarity index 79% rename from spine-cpp/spine-cpp/src/spine/RTTI.cpp rename to spine-cpp/spine-cpp/src/spine/SpineRTTI.cpp index 9d271f894..e5fc40ec4 100644 --- a/spine-cpp/spine-cpp/src/spine/RTTI.cpp +++ b/spine-cpp/spine-cpp/src/spine/SpineRTTI.cpp @@ -28,33 +28,33 @@ * POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -#include +#include namespace Spine { - RTTI::RTTI(const std::string& className) : m_className(className), m_pBaseRTTI(NULL) + SPINE_RTTI::SPINE_RTTI(const std::string& className) : m_className(className), m_pBaseSPINE_RTTI(NULL) { // Empty } - RTTI::RTTI(const std::string& className, const RTTI& baseRTTI) : m_className(className), m_pBaseRTTI(&baseRTTI) + SPINE_RTTI::SPINE_RTTI(const std::string& className, const SPINE_RTTI& baseSPINE_RTTI) : m_className(className), m_pBaseSPINE_RTTI(&baseSPINE_RTTI) { // Empty } - const std::string& RTTI::getClassName() const + const std::string& SPINE_RTTI::getClassName() const { return m_className; } - bool RTTI::isExactly(const RTTI& rtti) const + bool SPINE_RTTI::isExactly(const SPINE_RTTI& rtti) const { return (this == &rtti); } - bool RTTI::derivesFrom(const RTTI& rtti) const + bool SPINE_RTTI::derivesFrom(const SPINE_RTTI& rtti) const { - const RTTI * pCompare = this; + const SPINE_RTTI * pCompare = this; while (pCompare) { @@ -63,7 +63,7 @@ namespace Spine return true; } - pCompare = pCompare->m_pBaseRTTI; + pCompare = pCompare->m_pBaseSPINE_RTTI; } return false; diff --git a/spine-cpp/spine-cpp/src/spine/Timeline.cpp b/spine-cpp/spine-cpp/src/spine/Timeline.cpp index 6dac2f210..ddd0d5fe6 100644 --- a/spine-cpp/spine-cpp/src/spine/Timeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/Timeline.cpp @@ -35,7 +35,7 @@ namespace Spine { - RTTI_IMPL_NOPARENT(Timeline); + SPINE_RTTI_IMPL_NOPARENT(Timeline); Timeline::Timeline() { diff --git a/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp b/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp index 6ff042820..04cd07a1c 100644 --- a/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp +++ b/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp @@ -39,7 +39,7 @@ namespace Spine { - RTTI_IMPL(TransformConstraint, Constraint); + SPINE_RTTI_IMPL(TransformConstraint, Constraint); TransformConstraint::TransformConstraint(TransformConstraintData& data, Skeleton& skeleton) : Constraint(), _data(data), diff --git a/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp b/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp index a4fe5dd3a..daceecc8a 100644 --- a/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp @@ -32,6 +32,6 @@ namespace Spine { - RTTI_IMPL(TransformConstraintTimeline, CurveTimeline); + SPINE_RTTI_IMPL(TransformConstraintTimeline, CurveTimeline); } diff --git a/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp b/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp index 5de311b78..97c43cfce 100644 --- a/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp @@ -32,5 +32,5 @@ namespace Spine { - RTTI_IMPL(TranslateTimeline, CurveTimeline); + SPINE_RTTI_IMPL(TranslateTimeline, CurveTimeline); } diff --git a/spine-cpp/spine-cpp/src/spine/TwoColorTimeline.cpp b/spine-cpp/spine-cpp/src/spine/TwoColorTimeline.cpp index 0e15ae88a..45adf3def 100644 --- a/spine-cpp/spine-cpp/src/spine/TwoColorTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/TwoColorTimeline.cpp @@ -32,5 +32,5 @@ namespace Spine { - RTTI_IMPL(TwoColorTimeline, CurveTimeline); + SPINE_RTTI_IMPL(TwoColorTimeline, CurveTimeline); } diff --git a/spine-cpp/spine-cpp/src/spine/Updatable.cpp b/spine-cpp/spine-cpp/src/spine/Updatable.cpp index 598955a9a..e40d01725 100644 --- a/spine-cpp/spine-cpp/src/spine/Updatable.cpp +++ b/spine-cpp/spine-cpp/src/spine/Updatable.cpp @@ -32,7 +32,7 @@ namespace Spine { - RTTI_IMPL_NOPARENT(Updatable); + SPINE_RTTI_IMPL_NOPARENT(Updatable); Updatable::Updatable() { diff --git a/spine-cpp/spine-cpp/src/spine/VertexAttachment.cpp b/spine-cpp/spine-cpp/src/spine/VertexAttachment.cpp index 36410d0d4..e16de993e 100644 --- a/spine-cpp/spine-cpp/src/spine/VertexAttachment.cpp +++ b/spine-cpp/spine-cpp/src/spine/VertexAttachment.cpp @@ -37,7 +37,7 @@ namespace Spine { - RTTI_IMPL(VertexAttachment, Attachment); + SPINE_RTTI_IMPL(VertexAttachment, Attachment); VertexAttachment::VertexAttachment(std::string name) : Attachment(name), _worldVerticesLength(0), _id(getNextID()) { From 91225fe9e3c123c4b9fac3ce5a9a24e33f12f02a Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Thu, 23 Nov 2017 19:21:04 -0500 Subject: [PATCH 38/83] Getting there! --- spine-cpp/spine-cpp/include/spine/Atlas.h | 63 ++- .../spine-cpp/include/spine/ContainerUtil.h | 15 +- spine-cpp/spine-cpp/include/spine/Extension.h | 56 +++ spine-cpp/spine-cpp/include/spine/Pool.h | 6 +- spine-cpp/spine-cpp/include/spine/Vector.h | 9 +- spine-cpp/spine-cpp/src/spine/Atlas.cpp | 416 ++++++++++++++++-- spine-cpp/spine-cpp/src/spine/Extension.cpp | 73 +++ spine-cpp/spine-cpp/src/spine/Skeleton.cpp | 25 +- 8 files changed, 611 insertions(+), 52 deletions(-) create mode 100644 spine-cpp/spine-cpp/include/spine/Extension.h create mode 100644 spine-cpp/spine-cpp/src/spine/Extension.cpp diff --git a/spine-cpp/spine-cpp/include/spine/Atlas.h b/spine-cpp/spine-cpp/include/spine/Atlas.h index 8ffe4b41e..a809c4b25 100644 --- a/spine-cpp/spine-cpp/include/spine/Atlas.h +++ b/spine-cpp/spine-cpp/include/spine/Atlas.h @@ -32,6 +32,7 @@ #define Spine_Atlas_h #include +#include #include @@ -77,12 +78,14 @@ namespace Spine TextureWrap vWrap; void* rendererObject; int width, height; + + AtlasPage(std::string inName) : name(inName) {} }; class AtlasRegion { public: - AtlasPage page; + AtlasPage* page; std::string name; int x, y, width, height; float u, v, u2, v2; @@ -94,14 +97,70 @@ namespace Spine Vector pads; }; + class TextureLoader + { + public: + virtual void load(AtlasPage page, std::string path) = 0; + virtual void unload(void* texture) = 0; + }; + class Atlas { public: - /// Returns the first region found with the specified name. This method uses string comparison to find the region, so the result + Atlas(const char* path, TextureLoader& textureLoader); + + Atlas(const char* data, int length, const char* dir, TextureLoader& textureLoader); + + ~Atlas(); + + void flipV(); + + /// Returns the first region found with the specified name. This method uses std::string comparison to find the region, so the result /// should be cached rather than calling this method multiple times. /// @return The region, or NULL. AtlasRegion* findRegion(std::string name); + + void dispose(); + + private: + Vector _pages; + Vector _regions; + TextureLoader& _textureLoader; + + void load(const char* begin, int length, const char* dir); + + class Str + { + public: + const char* begin; + const char* end; + }; + + static void trim(Str* str); + + /// Tokenize string without modification. Returns 0 on failure + static int readLine(const char** begin, const char* end, Str* str); + + /// Moves str->begin past the first occurence of c. Returns 0 on failure + static int beginPast(Str* str, char c); + + /// Returns 0 on failure + static int readValue(const char** begin, const char* end, Str* str); + + /// 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[]); + + static char* mallocString(Str* str); + + static int indexOf(const char** array, int count, Str* str); + + static int equals(Str* str, const char* other); + + static int toInt(Str* str); + + static Atlas* abortAtlas(Atlas* atlas); }; } #endif /* Spine_Atlas_h */ + diff --git a/spine-cpp/spine-cpp/include/spine/ContainerUtil.h b/spine-cpp/spine-cpp/include/spine/ContainerUtil.h index fd415d42a..641e9621c 100644 --- a/spine-cpp/spine-cpp/include/spine/ContainerUtil.h +++ b/spine-cpp/spine-cpp/include/spine/ContainerUtil.h @@ -33,6 +33,7 @@ #include #include +#include #include #include @@ -124,23 +125,13 @@ namespace Spine for (size_t i = 0; i < items.size(); ) { T* item = items[i]; - delete item; + + FREE(item); items.erase(i); } } - template - static void cleanUpHashMapOfPointers(HashMap& hashMap) - { - for (typename HashMap::Iterator i = hashMap.begin(); i != hashMap.end(); ) - { - delete i.second(); - - i = hashMap.erase(i); - } - } - private: // ctor, copy ctor, and assignment should be private in a Singleton ContainerUtil(); diff --git a/spine-cpp/spine-cpp/include/spine/Extension.h b/spine-cpp/spine-cpp/include/spine/Extension.h new file mode 100644 index 000000000..770749a25 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/Extension.h @@ -0,0 +1,56 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Extension_h +#define Spine_Extension_h + +/* All allocation uses these. */ +#define MALLOC(TYPE,COUNT) ((TYPE*)spineAlloc(sizeof(TYPE) * (COUNT), __FILE__, __LINE__)) +#define REALLOC(PTR,TYPE,COUNT) ((TYPE*)spineRealloc(PTR, sizeof(TYPE) * (COUNT), __FILE__, __LINE__)) + +/* Frees memory. Can be used on const types. */ +#define FREE(VALUE) spineFree((void*)VALUE) + +#include + +namespace Spine +{ + /// Implement this function to use your own memory allocator. + void* spineAlloc(size_t size, const char* file, int line); + + void* spineRealloc(void* ptr, size_t size, const char* file, int line); + + /// If you implement spineAlloc, you should also implement this function. + void spineFree(void* mem); + + char* spineReadFile(const char* path, int* length); +} + +#endif /* Spine_Extension_h */ diff --git a/spine-cpp/spine-cpp/include/spine/Pool.h b/spine-cpp/spine-cpp/include/spine/Pool.h index 83e78a6fb..096821476 100644 --- a/spine-cpp/spine-cpp/include/spine/Pool.h +++ b/spine-cpp/spine-cpp/include/spine/Pool.h @@ -33,6 +33,7 @@ #include #include +#include namespace Spine { @@ -61,7 +62,10 @@ namespace Spine } else { - return new T(); + T* ret = MALLOC(T, 1); + new (ret) T(); + + return ret; } } diff --git a/spine-cpp/spine-cpp/include/spine/Vector.h b/spine-cpp/spine-cpp/include/spine/Vector.h index 30de79e6e..11467a7af 100644 --- a/spine-cpp/spine-cpp/include/spine/Vector.h +++ b/spine-cpp/spine-cpp/include/spine/Vector.h @@ -31,6 +31,8 @@ #ifndef Spine_Vector_h #define Spine_Vector_h +#include + #include #include #include @@ -149,7 +151,7 @@ namespace Spine size_t newCapacity = inCapacity > 0 ? inCapacity : _capacity > 0 ? _capacity * 2 : 1; if (newCapacity > _capacity) { - _buffer = static_cast(realloc(_buffer, newCapacity * sizeof(T))); + _buffer = REALLOC(_buffer, T, newCapacity); _capacity = newCapacity; } } @@ -173,10 +175,11 @@ namespace Spine { assert(n > 0); - void* ptr = malloc(n * sizeof(T)); + T* ptr = MALLOC(T, n); + assert(ptr); - return static_cast(ptr); + return ptr; } void deallocate(T* buffer) diff --git a/spine-cpp/spine-cpp/src/spine/Atlas.cpp b/spine-cpp/spine-cpp/src/spine/Atlas.cpp index 6984d7232..1ceca89b7 100644 --- a/spine-cpp/spine-cpp/src/spine/Atlas.cpp +++ b/spine-cpp/spine-cpp/src/spine/Atlas.cpp @@ -1,39 +1,399 @@ /****************************************************************************** -* Spine Runtimes Software License v2.5 -* -* Copyright (c) 2013-2016, Esoteric Software -* All rights reserved. -* -* You are granted a perpetual, non-exclusive, non-sublicensable, and -* non-transferable license to use, install, execute, and perform the Spine -* Runtimes software and derivative works solely for personal or internal -* use. Without the written permission of Esoteric Software (see Section 2 of -* the Spine Software License Agreement), you may not (a) modify, translate, -* adapt, or develop new applications using the Spine Runtimes or otherwise -* create derivative works or improvements of the Spine Runtimes or (b) remove, -* delete, alter, or obscure any trademarks or any copyright, trademark, patent, -* or other intellectual property or proprietary rights notices on or in the -* Software, including any copy thereof. Redistributions in binary or source -* form must include this license and terms. -* -* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE -* POSSIBILITY OF SUCH DAMAGE. -*****************************************************************************/ + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ #include +#include + namespace Spine { + Atlas::Atlas(const char* path, TextureLoader& textureLoader) : _textureLoader(textureLoader) + { + int dirLength; + char *dir; + int length; + const char* data; + + /* 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 = spineReadFile(path, &length); + if (data) + { + load(data, length, dir); + } + + FREE(data); + FREE(dir); + } + + Atlas::Atlas(const char* data, int length, const char* dir, TextureLoader& textureLoader) : _textureLoader(textureLoader) + { + load(data, length, dir); + } + + Atlas::~Atlas() + { + ContainerUtil::cleanUpVectorOfPointers(_pages); + ContainerUtil::cleanUpVectorOfPointers(_regions); + } + + void Atlas::flipV() + { + for (size_t i = 0, n = _regions.size(); i < n; ++i) + { + AtlasRegion* regionP = _regions[i]; + AtlasRegion region = *regionP; + region.v = 1 - region.v; + region.v2 = 1 - region.v2; + } + } + AtlasRegion* Atlas::findRegion(std::string name) { + for (size_t i = 0, n = _regions.size(); i < n; ++i) + { + if (_regions[i]->name == name) + { + return _regions[i]; + } + } + return NULL; } + + void Atlas::dispose() + { + for (size_t i = 0, n = _pages.size(); i < n; ++i) + { + _textureLoader.unload(_pages[i]->rendererObject); + } + } + + void Atlas::load(const char* begin, int length, const char* dir) + { + static const char* formatNames[] = { "", "Alpha", "Intensity", "LuminanceAlpha", "RGB565", "RGBA4444", "RGB888", "RGBA8888" }; + static const char* textureFilterNames[] = { "", "Nearest", "Linear", "MipMap", "MipMapNearestNearest", "MipMapLinearNearest", + "MipMapNearestLinear", "MipMapLinearLinear" }; + + int count; + const char* end = begin + length; + int dirLength = (int)strlen(dir); + int needsSlash = dirLength > 0 && dir[dirLength - 1] != '/' && dir[dirLength - 1] != '\\'; + + AtlasPage *page = 0; + Str str; + Str tuple[4]; + + 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); + + AtlasPage* page = MALLOC(AtlasPage, 1); + new (page) AtlasPage(std::string(name)); + + FREE(name); + + assert(readTuple(&begin, end, tuple) == 2); + + /* size is only optional for an atlas packed with an old TexturePacker. */ + page->width = toInt(tuple); + page->height = toInt(tuple + 1); + assert(readTuple(&begin, end, tuple)); + + page->format = (Format)indexOf(formatNames, 8, tuple); + + assert(readTuple(&begin, end, tuple)); + page->minFilter = (TextureFilter)indexOf(textureFilterNames, 8, tuple); + page->magFilter = (TextureFilter)indexOf(textureFilterNames, 8, tuple + 1); + + assert(readValue(&begin, end, &str)); + + page->uWrap = TextureWrap_ClampToEdge; + page->vWrap = TextureWrap_ClampToEdge; + if (!equals(&str, "none")) + { + if (str.end - str.begin == 1) + { + if (*str.begin == 'x') + { + page->uWrap = TextureWrap_Repeat; + } + else if (*str.begin == 'y') + { + page->vWrap = TextureWrap_Repeat; + } + } + else if (equals(&str, "xy")) + { + page->uWrap = TextureWrap_Repeat; + page->vWrap = TextureWrap_Repeat; + } + } + + _textureLoader.load(*page, std::string(path)); + + FREE(path); + + _pages.push_back(page); + } + else + { + AtlasRegion* region = MALLOC(AtlasRegion, 1); + new (region) AtlasRegion(); + + region->page = page; + region->name = mallocString(&str); + + assert(readValue(&begin, end, &str)); + region->rotate = equals(&str, "true"); + + assert(readTuple(&begin, end, tuple) == 2); + region->x = toInt(tuple); + region->y = toInt(tuple + 1); + + assert(readTuple(&begin, end, tuple) == 2); + 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); + assert(count); + + if (count == 4) + { + /* split is optional */ + region->splits.reserve(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); + assert(count); + + if (count == 4) + { + /* pad is optional, but only present with splits */ + region->pads.reserve(4); + region->pads[0] = toInt(tuple); + region->pads[1] = toInt(tuple + 1); + region->pads[2] = toInt(tuple + 2); + region->pads[3] = toInt(tuple + 3); + + assert(readTuple(&begin, end, tuple)); + } + } + + region->originalWidth = toInt(tuple); + region->originalHeight = toInt(tuple + 1); + + readTuple(&begin, end, tuple); + region->offsetX = toInt(tuple); + region->offsetY = toInt(tuple + 1); + + assert(readValue(&begin, end, &str)); + + region->index = toInt(&str); + + _regions.push_back(region); + } + } + } + + void Atlas::trim(Str* str) + { + while (isspace((unsigned char)*str->begin) && str->begin < str->end) + { + (str->begin)++; + } + + if (str->begin == str->end) + { + return; + } + + str->end--; + + while (isspace((unsigned char)*str->end) && str->end >= str->begin) + { + str->end--; + } + + str->end++; + } + + int Atlas::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; + } + + int Atlas::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; + } + + int Atlas::readValue(const char** begin, const char* end, Str* str) + { + readLine(begin, end, str); + if (!beginPast(str, ':')) + { + return 0; + } + + trim(str); + return 1; + } + + int Atlas::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; + } + + char* Atlas::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; + } + + int Atlas::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; + } + + int Atlas::equals(Str* str, const char* other) + { + return strncmp(other, str->begin, str->end - str->begin) == 0; + } + + int Atlas::toInt(Str* str) + { + return (int)strtol(str->begin, (char**)&str->end, 10); + } } diff --git a/spine-cpp/spine-cpp/src/spine/Extension.cpp b/spine-cpp/spine-cpp/src/spine/Extension.cpp new file mode 100644 index 000000000..dd52dc6fe --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/Extension.cpp @@ -0,0 +1,73 @@ +/****************************************************************************** +* Spine Runtimes Software License v2.5 +* +* Copyright (c) 2013-2016, Esoteric Software +* All rights reserved. +* +* You are granted a perpetual, non-exclusive, non-sublicensable, and +* non-transferable license to use, install, execute, and perform the Spine +* Runtimes software and derivative works solely for personal or internal +* use. Without the written permission of Esoteric Software (see Section 2 of +* the Spine Software License Agreement), you may not (a) modify, translate, +* adapt, or develop new applications using the Spine Runtimes or otherwise +* create derivative works or improvements of the Spine Runtimes or (b) remove, +* delete, alter, or obscure any trademarks or any copyright, trademark, patent, +* or other intellectual property or proprietary rights notices on or in the +* Software, including any copy thereof. Redistributions in binary or source +* form must include this license and terms. +* +* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +#include + +//#include +#include + +namespace Spine +{ + void* spineAlloc(size_t size, const char* file, int line) + { + //printf("spineAlloc size: %lu, file: %s, line: %d \n", size, file, line); + + return malloc(size); + } + + void* spineRealloc(void* ptr, size_t size, const char* file, int line) + { + //printf("spineRealloc size: %lu, file: %s, line: %d \n", size, file, line); + + return realloc(ptr, size); + } + + void spineFree(void* mem) + { + free(mem); + } + + char* spineReadFile(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; + } +} diff --git a/spine-cpp/spine-cpp/src/spine/Skeleton.cpp b/spine-cpp/spine-cpp/src/spine/Skeleton.cpp index 454940d22..d5cf4ce62 100644 --- a/spine-cpp/spine-cpp/src/spine/Skeleton.cpp +++ b/spine-cpp/spine-cpp/src/spine/Skeleton.cpp @@ -50,6 +50,7 @@ #include #include +#include namespace Spine { @@ -74,12 +75,14 @@ namespace Spine Bone* bone; if (data->getParent() == NULL) { - bone = new Bone(*data, *this, NULL); + bone = MALLOC(Bone, 1); + new (bone) Bone(*data, *this, NULL); } else { Bone* parent = _bones[data->getParent()->getIndex()]; - bone = new Bone(*data, *this, parent); + bone = MALLOC(Bone, 1); + new (bone) Bone(*data, *this, parent); parent->getChildren().push_back(bone); } @@ -93,7 +96,8 @@ namespace Spine SlotData* data = (*i); Bone* bone = _bones[data->getBoneData().getIndex()]; - Slot* slot = new Slot(*data, *bone); + Slot* slot = MALLOC(Slot, 1); + new (slot) Slot(*data, *bone); _slots.push_back(slot); _drawOrder.push_back(slot); @@ -104,7 +108,10 @@ namespace Spine { IkConstraintData* data = (*i); - _ikConstraints.push_back(new IkConstraint(*data, *this)); + IkConstraint* constraint = MALLOC(IkConstraint, 1); + new (constraint) IkConstraint(*data, *this); + + _ikConstraints.push_back(constraint); } _transformConstraints.reserve(_data.getTransformConstraints().size()); @@ -112,7 +119,10 @@ namespace Spine { TransformConstraintData* data = (*i); - _transformConstraints.push_back(new TransformConstraint(*data, *this)); + TransformConstraint* constraint = MALLOC(TransformConstraint, 1); + new (constraint) TransformConstraint(*data, *this); + + _transformConstraints.push_back(constraint); } _pathConstraints.reserve(_data.getPathConstraints().size()); @@ -120,7 +130,10 @@ namespace Spine { PathConstraintData* data = (*i); - _pathConstraints.push_back(new PathConstraint(*data, *this)); + PathConstraint* constraint = MALLOC(PathConstraint, 1); + new (constraint) PathConstraint(*data, *this); + + _pathConstraints.push_back(constraint); } updateCache(); From b02c2aaaa4034751f66d8736f64410611ad39556 Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Fri, 24 Nov 2017 17:34:14 -0500 Subject: [PATCH 39/83] wip --- .../spine-cpp/include/spine/ContainerUtil.h | 2 +- spine-cpp/spine-cpp/include/spine/Extension.h | 3 +++ spine-cpp/spine-cpp/include/spine/HashMap.h | 21 +++++++++---------- spine-cpp/spine-cpp/include/spine/Vector.h | 2 +- 4 files changed, 15 insertions(+), 13 deletions(-) diff --git a/spine-cpp/spine-cpp/include/spine/ContainerUtil.h b/spine-cpp/spine-cpp/include/spine/ContainerUtil.h index 641e9621c..6f9b85245 100644 --- a/spine-cpp/spine-cpp/include/spine/ContainerUtil.h +++ b/spine-cpp/spine-cpp/include/spine/ContainerUtil.h @@ -126,7 +126,7 @@ namespace Spine { T* item = items[i]; - FREE(item); + DESTROY(T, item); items.erase(i); } diff --git a/spine-cpp/spine-cpp/include/spine/Extension.h b/spine-cpp/spine-cpp/include/spine/Extension.h index 770749a25..d5633d8bc 100644 --- a/spine-cpp/spine-cpp/include/spine/Extension.h +++ b/spine-cpp/spine-cpp/include/spine/Extension.h @@ -38,6 +38,9 @@ /* Frees memory. Can be used on const types. */ #define FREE(VALUE) spineFree((void*)VALUE) +/* Call destructor and then frees memory. Can be used on const types. */ +#define DESTROY(TYPE,VALUE) VALUE->~TYPE(); spineFree((void*)VALUE) + #include namespace Spine diff --git a/spine-cpp/spine-cpp/include/spine/HashMap.h b/spine-cpp/spine-cpp/include/spine/HashMap.h index 26dd90bf1..372131a11 100755 --- a/spine-cpp/spine-cpp/include/spine/HashMap.h +++ b/spine-cpp/spine-cpp/include/spine/HashMap.h @@ -31,7 +31,7 @@ #ifndef Spine_HashMap_h #define Spine_HashMap_h -#include +#include namespace Spine { @@ -95,10 +95,10 @@ namespace Spine _trailer(), _hashSize(0) { - _hashTable = new Entry[capacity]; + _hashTable.reserve(capacity); for (int i = 0; i < _capacity; ++i) { - _hashTable[i] = Entry(); + _hashTable.push_back(Entry()); } _header.prev = &_header; @@ -109,8 +109,6 @@ namespace Spine ~HashMap() { - delete [] _hashTable; - _hashSize = 0; } @@ -150,7 +148,8 @@ namespace Spine size_t index = hash(key); - Entry* entry = new Entry(); + Entry* entry = MALLOC(Entry, 1); + new (entry) Entry(); entry->_key = key; entry->_value = value; @@ -258,7 +257,7 @@ namespace Spine pos._entry->next->prev = pos._entry->prev; } - delete pos._entry; + DESTROY(Entry, pos._entry); } else if (_hashTable[index].next == pos._entry) { @@ -274,7 +273,7 @@ namespace Spine pos._entry->next->prev = pos._entry->prev; } - delete pos._entry; + DESTROY(Entry, pos._entry); } else if (_hashTable[index].prev == pos._entry) { @@ -290,14 +289,14 @@ namespace Spine pos._entry->next->prev = pos._entry->prev; } - delete pos._entry; + DESTROY(Entry, pos._entry); } else { pos._entry->prev->next = pos._entry->next; pos._entry->next->prev = pos._entry->prev; - delete pos._entry; + DESTROY(Entry, pos._entry); } _hashSize--; @@ -332,7 +331,7 @@ namespace Spine const H _hashFunction; const size_t _capacity; - Entry* _hashTable; + Vector _hashTable; Entry _header; Entry _trailer; size_t _hashSize; diff --git a/spine-cpp/spine-cpp/include/spine/Vector.h b/spine-cpp/spine-cpp/include/spine/Vector.h index 11467a7af..ec25ecb84 100644 --- a/spine-cpp/spine-cpp/include/spine/Vector.h +++ b/spine-cpp/spine-cpp/include/spine/Vector.h @@ -184,7 +184,7 @@ namespace Spine void deallocate(T* buffer) { - free(buffer); + FREE(buffer); } void construct(T* buffer, const T& val) From 107c18e237269838dc09ab0d295a25882dde865b Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Fri, 24 Nov 2017 18:13:14 -0500 Subject: [PATCH 40/83] Closer still. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit So here is what I have left: 1. Implement the Timeline classes (from Animation) 2. Implement AnimationState 3. Implement SkeletonJson 4. Implement SkeletonBinary Seems like a lot, but most of the file IO stuff is going to get more or less ripped directly from the C runtime, so I’m actually pretty close I think! --- .../include/spine/AtlasAttachmentLoader.h | 92 +++----------- .../include/spine/AttachmentLoader.h | 8 +- .../spine-cpp/include/spine/MeshAttachment.h | 2 + .../include/spine/RegionAttachment.h | 2 + spine-cpp/spine-cpp/src/spine/Atlas.cpp | 11 +- .../src/spine/AtlasAttachmentLoader.cpp | 113 ++++++++++++++++++ .../spine-cpp/src/spine/AttachmentLoader.cpp | 18 +++ .../spine-cpp/src/spine/IkConstraint.cpp | 4 +- .../spine-cpp/src/spine/PathConstraint.cpp | 8 +- spine-cpp/spine-cpp/src/spine/Skeleton.cpp | 10 +- .../src/spine/TransformConstraint.cpp | 8 +- .../spine-cpp/src/spine/VertexAttachment.cpp | 4 +- 12 files changed, 180 insertions(+), 100 deletions(-) diff --git a/spine-cpp/spine-cpp/include/spine/AtlasAttachmentLoader.h b/spine-cpp/spine-cpp/include/spine/AtlasAttachmentLoader.h index a226f36a6..2805482af 100644 --- a/spine-cpp/spine-cpp/include/spine/AtlasAttachmentLoader.h +++ b/spine-cpp/spine-cpp/include/spine/AtlasAttachmentLoader.h @@ -38,6 +38,7 @@ namespace Spine { class Atlas; + class AtlasRegion; /// /// An AttachmentLoader that configures attachments using texture regions from an Atlas. @@ -48,84 +49,21 @@ namespace Spine SPINE_RTTI_DECL; public: - AtlasAttachmentLoader (Vector& inAtlasArray) : _atlasArray(inAtlasArray) - { - // Empty - } + AtlasAttachmentLoader(Vector& inAtlasArray); -// RegionAttachment newRegionAttachment(Skin skin, std::string name, std::string path) -// { -// AtlasRegion* region = findRegion(path); -// if (region == NULL) throw new ArgumentException(std::string.Format("Region not found in atlas: {0} (region attachment: {1})", path, name)); -// RegionAttachment attachment = new RegionAttachment(name); -// attachment.RendererObject = region; -// attachment.SetUVs(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 attachment; -// } -// -// MeshAttachment newMeshAttachment(Skin skin, std::string name, std::string path) -// { -// AtlasRegion region = findRegion(path); -// if (region == NULL) throw new ArgumentException(std::string.Format("Region not found in atlas: {0} (region attachment: {1})", path, name)); -// -// MeshAttachment attachment = new MeshAttachment(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.regionOffsetX = region.offsetX; -// attachment.regionOffsetY = region.offsetY; -// attachment.regionWidth = region.width; -// attachment.regionHeight = region.height; -// attachment.regionOriginalWidth = region.originalWidth; -// attachment.regionOriginalHeight = region.originalHeight; -// -// return attachment; -// } -// -// BoundingBoxAttachment NewBoundingBoxAttachment (Skin skin, std::string name) -// { -// return new BoundingBoxAttachment(name); -// } -// -// PathAttachment newPathAttachment(Skin skin, std::string name) -// { -// return new PathAttachment(name); -// } -// -// PointAttachment newPointAttachment(Skin skin, std::string name) -// { -// return new PointAttachment(name); -// } -// -// ClippingAttachment newClippingAttachment(Skin skin, std::string name) -// { -// return new ClippingAttachment(name); -// } -// -// AtlasRegion* findRegion(std::string name) -// { -// AtlasRegion* ret; -// -// for (int i = 0; i < _atlasArray.size(); i++) -// { -// ret = _atlasArray[i]->findRegion(name); -// if (ret != NULL) -// { -// return ret; -// } -// } -// -// return NULL; -// } + virtual RegionAttachment* newRegionAttachment(Skin& skin, std::string name, std::string path); + + virtual MeshAttachment* newMeshAttachment(Skin& skin, std::string name, std::string path); + + virtual BoundingBoxAttachment* newBoundingBoxAttachment(Skin& skin, std::string name); + + virtual PathAttachment* newPathAttachment(Skin& skin, std::string name); + + virtual PointAttachment* newPointAttachment(Skin& skin, std::string name); + + virtual ClippingAttachment* newClippingAttachment(Skin& skin, std::string name); + + AtlasRegion* findRegion(std::string name); private: Vector _atlasArray; diff --git a/spine-cpp/spine-cpp/include/spine/AttachmentLoader.h b/spine-cpp/spine-cpp/include/spine/AttachmentLoader.h index 7712e4cc1..e194e019b 100644 --- a/spine-cpp/spine-cpp/include/spine/AttachmentLoader.h +++ b/spine-cpp/spine-cpp/include/spine/AttachmentLoader.h @@ -37,18 +37,22 @@ namespace Spine { + class Skin; class RegionAttachment; class MeshAttachment; class BoundingBoxAttachment; class PathAttachment; class PointAttachment; class ClippingAttachment; - class Skin; class AttachmentLoader { SPINE_RTTI_DECL; + AttachmentLoader(); + + virtual ~AttachmentLoader(); + /// @return May be NULL to not load any attachment. virtual RegionAttachment* newRegionAttachment(Skin& skin, std::string name, std::string path) = 0; @@ -56,7 +60,7 @@ namespace Spine virtual MeshAttachment* newMeshAttachment(Skin& skin, std::string name, std::string path) = 0; /// @return May be NULL to not load any attachment. - virtual BoundingBoxAttachment* NewBoundingBoxAttachment(Skin& skin, std::string name) = 0; + virtual BoundingBoxAttachment* newBoundingBoxAttachment(Skin& skin, std::string name) = 0; /// @return May be NULL to not load any attachment virtual PathAttachment* newPathAttachment(Skin& skin, std::string name) = 0; diff --git a/spine-cpp/spine-cpp/include/spine/MeshAttachment.h b/spine-cpp/spine-cpp/include/spine/MeshAttachment.h index dee544d61..c29e93fb4 100644 --- a/spine-cpp/spine-cpp/include/spine/MeshAttachment.h +++ b/spine-cpp/spine-cpp/include/spine/MeshAttachment.h @@ -44,6 +44,8 @@ namespace Spine { SPINE_RTTI_DECL; + friend class AtlasAttachmentLoader; + public: MeshAttachment(std::string name); diff --git a/spine-cpp/spine-cpp/include/spine/RegionAttachment.h b/spine-cpp/spine-cpp/include/spine/RegionAttachment.h index 9151691c0..780c5b8ce 100644 --- a/spine-cpp/spine-cpp/include/spine/RegionAttachment.h +++ b/spine-cpp/spine-cpp/include/spine/RegionAttachment.h @@ -48,6 +48,8 @@ namespace Spine { SPINE_RTTI_DECL; + friend class AtlasAttachmentLoader; + public: RegionAttachment(std::string name); diff --git a/spine-cpp/spine-cpp/src/spine/Atlas.cpp b/spine-cpp/spine-cpp/src/spine/Atlas.cpp index 1ceca89b7..8a9db562a 100644 --- a/spine-cpp/spine-cpp/src/spine/Atlas.cpp +++ b/spine-cpp/spine-cpp/src/spine/Atlas.cpp @@ -77,7 +77,7 @@ namespace Spine for (size_t i = 0, n = _regions.size(); i < n; ++i) { AtlasRegion* regionP = _regions[i]; - AtlasRegion region = *regionP; + AtlasRegion& region = *regionP; region.v = 1 - region.v; region.v2 = 1 - region.v2; } @@ -284,7 +284,11 @@ namespace Spine int Atlas::readLine(const char** begin, const char* end, Str* str) { - if (*begin == end) return 0; + if (*begin == end) + { + return 0; + } + str->begin = *begin; /* Find next delimiter. */ @@ -307,7 +311,8 @@ namespace Spine int Atlas::beginPast(Str* str, char c) { const char* begin = str->begin; - while (1) { + while (1) + { char lastSkippedChar = *begin; if (begin == str->end) { diff --git a/spine-cpp/spine-cpp/src/spine/AtlasAttachmentLoader.cpp b/spine-cpp/spine-cpp/src/spine/AtlasAttachmentLoader.cpp index 0d5a99aca..bea6e30e7 100644 --- a/spine-cpp/spine-cpp/src/spine/AtlasAttachmentLoader.cpp +++ b/spine-cpp/spine-cpp/src/spine/AtlasAttachmentLoader.cpp @@ -30,7 +30,120 @@ #include +#include +#include +#include +#include +#include +#include +#include + +#include + namespace Spine { SPINE_RTTI_IMPL(AtlasAttachmentLoader, AttachmentLoader); + + AtlasAttachmentLoader::AtlasAttachmentLoader(Vector& inAtlasArray) : AttachmentLoader(), _atlasArray(inAtlasArray) + { + // Empty + } + + RegionAttachment* AtlasAttachmentLoader::newRegionAttachment(Skin& skin, std::string name, std::string path) + { + AtlasRegion* regionP = findRegion(path); + assert(regionP != NULL); + + AtlasRegion& region = *regionP; + + RegionAttachment* attachmentP = MALLOC(RegionAttachment, 1); + new (attachmentP) RegionAttachment(name); + + RegionAttachment& attachment = *attachmentP; + attachment._rendererObject = regionP; + attachment.setUVs(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 attachmentP; + } + + MeshAttachment* AtlasAttachmentLoader::newMeshAttachment(Skin& skin, std::string name, std::string path) + { + AtlasRegion* regionP = findRegion(path); + assert(regionP != NULL); + + AtlasRegion& region = *regionP; + + MeshAttachment* attachmentP = MALLOC(MeshAttachment, 1); + new (attachmentP) MeshAttachment(name); + + MeshAttachment& attachment = *attachmentP; + attachment._rendererObject = regionP; + attachment._regionU = region.u; + attachment._regionV = region.v; + attachment._regionU2 = region.u2; + attachment._regionV2 = region.v2; + attachment._regionRotate = 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 attachmentP; + } + + BoundingBoxAttachment* AtlasAttachmentLoader::newBoundingBoxAttachment(Skin& skin, std::string name) + { + BoundingBoxAttachment* attachmentP = MALLOC(BoundingBoxAttachment, 1); + new (attachmentP) BoundingBoxAttachment(name); + + return attachmentP; + } + + PathAttachment* AtlasAttachmentLoader::newPathAttachment(Skin& skin, std::string name) + { + PathAttachment* attachmentP = MALLOC(PathAttachment, 1); + new (attachmentP) PathAttachment(name); + + return attachmentP; + } + + PointAttachment* AtlasAttachmentLoader::newPointAttachment(Skin& skin, std::string name) + { + PointAttachment* attachmentP = MALLOC(PointAttachment, 1); + new (attachmentP) PointAttachment(name); + + return attachmentP; + } + + ClippingAttachment* AtlasAttachmentLoader::newClippingAttachment(Skin& skin, std::string name) + { + ClippingAttachment* attachmentP = MALLOC(ClippingAttachment, 1); + new (attachmentP) ClippingAttachment(name); + + return attachmentP; + } + + AtlasRegion* AtlasAttachmentLoader::findRegion(std::string name) + { + AtlasRegion* ret; + + for (int i = 0; i < _atlasArray.size(); i++) + { + ret = _atlasArray[i]->findRegion(name); + if (ret != NULL) + { + return ret; + } + } + + return NULL; + } } diff --git a/spine-cpp/spine-cpp/src/spine/AttachmentLoader.cpp b/spine-cpp/spine-cpp/src/spine/AttachmentLoader.cpp index 04c5e3979..af55271f2 100644 --- a/spine-cpp/spine-cpp/src/spine/AttachmentLoader.cpp +++ b/spine-cpp/spine-cpp/src/spine/AttachmentLoader.cpp @@ -30,7 +30,25 @@ #include +#include +#include +#include +#include +#include +#include +#include + namespace Spine { SPINE_RTTI_IMPL_NOPARENT(AttachmentLoader); + + AttachmentLoader::AttachmentLoader() + { + // Empty + } + + AttachmentLoader::~AttachmentLoader() + { + // Empty + } } diff --git a/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp b/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp index 4c6c0e8c5..f0838c6af 100644 --- a/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp +++ b/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp @@ -49,7 +49,7 @@ namespace Spine } Bone* parent = bone.getParent(); - Bone p = *parent; + Bone& p = *parent; float id = 1 / (p._a * p._d - p._b * p._c); float x = targetX - p._worldX, y = targetY - p._worldY; @@ -151,7 +151,7 @@ namespace Spine } Bone* parentparent = parent._parent; - Bone pp = *parentparent; + Bone& pp = *parentparent; a = pp._a; b = pp._b; diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp b/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp index 5d90c2ea7..c44a495ba 100644 --- a/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp @@ -114,7 +114,7 @@ namespace Spine for (int i = 0, n = spacesCount - 1; i < n;) { Bone* boneP = _bones[i]; - Bone bone = *boneP; + Bone& bone = *boneP; float setupLength = bone._data.getLength(); if (setupLength < PathConstraint::EPSILON) { @@ -165,7 +165,7 @@ namespace Spine for (int i = 0, p = 3; i < boneCount; i++, p += 3) { Bone* boneP = _bones[i]; - Bone bone = *boneP; + Bone& bone = *boneP; bone._worldX += (boneX - bone._worldX) * translateMix; bone._worldY += (boneY - bone._worldY) * translateMix; float x = positions[p]; @@ -306,10 +306,8 @@ namespace Spine Vector PathConstraint::computeWorldPositions(PathAttachment& path, int spacesCount, bool tangents, bool percentPosition, bool percentSpacing) { - Slot target = *_target; + Slot& target = *_target; float position = _position; -// float[] spacesItems = _spaces.Items; -// float[] output = _positions.Resize(spacesCount * 3 + 2).Items; _positions.reserve(spacesCount * 3 + 2); bool closed = path.isClosed(); int verticesLength = path.getWorldVerticesLength(); diff --git a/spine-cpp/spine-cpp/src/spine/Skeleton.cpp b/spine-cpp/spine-cpp/src/spine/Skeleton.cpp index d5cf4ce62..b295f83d7 100644 --- a/spine-cpp/spine-cpp/src/spine/Skeleton.cpp +++ b/spine-cpp/spine-cpp/src/spine/Skeleton.cpp @@ -232,7 +232,7 @@ namespace Spine for (int i = 0, n = static_cast(_updateCacheReset.size()); i < n; ++i) { Bone* boneP = _updateCacheReset[i]; - Bone bone = *boneP; + Bone& bone = *boneP; bone._ax = bone._x; bone._ay = bone._y; bone._arotation = bone._rotation; @@ -265,7 +265,7 @@ namespace Spine for (int i = 0, n = static_cast(_ikConstraints.size()); i < n; ++i) { IkConstraint* constraintP = _ikConstraints[i]; - IkConstraint constraint = *constraintP; + IkConstraint& constraint = *constraintP; constraint._bendDirection = constraint._data._bendDirection; constraint._mix = constraint._data._mix; @@ -274,7 +274,7 @@ namespace Spine for (int i = 0, n = static_cast(_transformConstraints.size()); i < n; ++i) { TransformConstraint* constraintP = _transformConstraints[i]; - TransformConstraint constraint = *constraintP; + TransformConstraint& constraint = *constraintP; TransformConstraintData& constraintData = constraint._data; constraint._rotateMix = constraintData._rotateMix; @@ -286,7 +286,7 @@ namespace Spine for (int i = 0, n = static_cast(_pathConstraints.size()); i < n; ++i) { PathConstraint* constraintP = _pathConstraints[i]; - PathConstraint constraint = *constraintP; + PathConstraint& constraint = *constraintP; PathConstraintData& constraintData = constraint._data; constraint._position = constraintData._position; @@ -353,7 +353,7 @@ namespace Spine for (int i = 0, n = static_cast(_slots.size()); i < n; ++i) { Slot* slotP = _slots[i]; - Slot slot = *slotP; + Slot& slot = *slotP; std::string name = slot._data.getAttachmentName(); if (name.length() > 0) { diff --git a/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp b/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp index 04cd07a1c..166713279 100644 --- a/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp +++ b/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp @@ -157,7 +157,7 @@ namespace Spine void TransformConstraint::applyAbsoluteWorld() { float rotateMix = _rotateMix, translateMix = _translateMix, scaleMix = _scaleMix, shearMix = _shearMix; - Bone target = *_target; + Bone& target = *_target; float ta = target._a, tb = target._b, tc = target._c, td = target._d; float degRadReflect = ta * td - tb * tc > 0 ? DegRad : -DegRad; float offsetRotation = _data._offsetRotation * degRadReflect, offsetShearY = _data._offsetShearY * degRadReflect; @@ -252,7 +252,7 @@ namespace Spine void TransformConstraint::applyRelativeWorld() { float rotateMix = _rotateMix, translateMix = _translateMix, scaleMix = _scaleMix, shearMix = _shearMix; - Bone target = *_target; + Bone& target = *_target; float ta = target._a, tb = target._b, tc = target._c, td = target._d; float degRadReflect = ta * td - tb * tc > 0 ? DegRad : -DegRad; float offsetRotation = _data._offsetRotation * degRadReflect, offsetShearY = _data._offsetShearY * degRadReflect; @@ -335,7 +335,7 @@ namespace Spine void TransformConstraint::applyAbsoluteLocal() { float rotateMix = _rotateMix, translateMix = _translateMix, scaleMix = _scaleMix, shearMix = _shearMix; - Bone target = *_target; + Bone& target = *_target; if (!target._appliedValid) { target.updateAppliedTransform(); @@ -395,7 +395,7 @@ namespace Spine void TransformConstraint::applyRelativeLocal() { float rotateMix = _rotateMix, translateMix = _translateMix, scaleMix = _scaleMix, shearMix = _shearMix; - Bone target = *_target; + Bone& target = *_target; if (!target._appliedValid) { target.updateAppliedTransform(); diff --git a/spine-cpp/spine-cpp/src/spine/VertexAttachment.cpp b/spine-cpp/spine-cpp/src/spine/VertexAttachment.cpp index e16de993e..9968a77ce 100644 --- a/spine-cpp/spine-cpp/src/spine/VertexAttachment.cpp +++ b/spine-cpp/spine-cpp/src/spine/VertexAttachment.cpp @@ -96,7 +96,7 @@ namespace Spine for (; v < n; v++, b += 3) { Bone* boneP = skeletonBones[bones[v]]; - Bone bone = *boneP; + Bone& bone = *boneP; float vx = vertices[b]; float vy = vertices[b + 1]; float weight = vertices[b + 2]; @@ -117,7 +117,7 @@ namespace Spine for (; v < n; v++, b += 3, f += 2) { Bone* boneP = skeletonBones[bones[v]]; - Bone bone = *boneP; + Bone& bone = *boneP; float vx = vertices[b] + deformArray[f]; float vy = vertices[b + 1] + deformArray[f + 1]; float weight = vertices[b + 2]; From 11acfef70556c333f614883aecfa7cb1e4a13325 Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Fri, 24 Nov 2017 20:50:16 -0500 Subject: [PATCH 41/83] fixing compile error --- spine-cpp/spine-cpp/src/spine/Atlas.cpp | 126 ++++++++++++------------ 1 file changed, 64 insertions(+), 62 deletions(-) diff --git a/spine-cpp/spine-cpp/src/spine/Atlas.cpp b/spine-cpp/spine-cpp/src/spine/Atlas.cpp index 8a9db562a..7b317c2d6 100644 --- a/spine-cpp/spine-cpp/src/spine/Atlas.cpp +++ b/spine-cpp/spine-cpp/src/spine/Atlas.cpp @@ -32,6 +32,8 @@ #include +#include + namespace Spine { Atlas::Atlas(const char* path, TextureLoader& textureLoader) : _textureLoader(textureLoader) @@ -40,7 +42,7 @@ namespace Spine char *dir; int length; const char* data; - + /* Get directory from atlas path. */ const char* lastForwardSlash = strrchr(path, '/'); const char* lastBackwardSlash = strrchr(path, '\\'); @@ -50,28 +52,28 @@ namespace Spine dir = MALLOC(char, dirLength + 1); memcpy(dir, path, dirLength); dir[dirLength] = '\0'; - + data = spineReadFile(path, &length); if (data) { load(data, length, dir); } - + FREE(data); FREE(dir); } - + Atlas::Atlas(const char* data, int length, const char* dir, TextureLoader& textureLoader) : _textureLoader(textureLoader) { load(data, length, dir); } - + Atlas::~Atlas() { ContainerUtil::cleanUpVectorOfPointers(_pages); ContainerUtil::cleanUpVectorOfPointers(_regions); } - + void Atlas::flipV() { for (size_t i = 0, n = _regions.size(); i < n; ++i) @@ -82,7 +84,7 @@ namespace Spine region.v2 = 1 - region.v2; } } - + AtlasRegion* Atlas::findRegion(std::string name) { for (size_t i = 0, n = _regions.size(); i < n; ++i) @@ -92,10 +94,10 @@ namespace Spine return _regions[i]; } } - + return NULL; } - + void Atlas::dispose() { for (size_t i = 0, n = _pages.size(); i < n; ++i) @@ -103,22 +105,22 @@ namespace Spine _textureLoader.unload(_pages[i]->rendererObject); } } - + void Atlas::load(const char* begin, int length, const char* dir) { static const char* formatNames[] = { "", "Alpha", "Intensity", "LuminanceAlpha", "RGB565", "RGBA4444", "RGB888", "RGBA8888" }; static const char* textureFilterNames[] = { "", "Nearest", "Linear", "MipMap", "MipMapNearestNearest", "MipMapLinearNearest", "MipMapNearestLinear", "MipMapLinearLinear" }; - + int count; const char* end = begin + length; int dirLength = (int)strlen(dir); int needsSlash = dirLength > 0 && dir[dirLength - 1] != '/' && dir[dirLength - 1] != '\\'; - + AtlasPage *page = 0; Str str; Str tuple[4]; - + while (readLine(&begin, end, &str)) { if (str.end - str.begin == 0) @@ -135,27 +137,27 @@ namespace Spine path[dirLength] = '/'; } strcpy(path + dirLength + needsSlash, name); - + AtlasPage* page = MALLOC(AtlasPage, 1); new (page) AtlasPage(std::string(name)); - + FREE(name); - + assert(readTuple(&begin, end, tuple) == 2); - + /* size is only optional for an atlas packed with an old TexturePacker. */ page->width = toInt(tuple); page->height = toInt(tuple + 1); assert(readTuple(&begin, end, tuple)); - + page->format = (Format)indexOf(formatNames, 8, tuple); - + assert(readTuple(&begin, end, tuple)); page->minFilter = (TextureFilter)indexOf(textureFilterNames, 8, tuple); page->magFilter = (TextureFilter)indexOf(textureFilterNames, 8, tuple + 1); - + assert(readValue(&begin, end, &str)); - + page->uWrap = TextureWrap_ClampToEdge; page->vWrap = TextureWrap_ClampToEdge; if (!equals(&str, "none")) @@ -177,32 +179,32 @@ namespace Spine page->vWrap = TextureWrap_Repeat; } } - + _textureLoader.load(*page, std::string(path)); - + FREE(path); - + _pages.push_back(page); } else { AtlasRegion* region = MALLOC(AtlasRegion, 1); new (region) AtlasRegion(); - + region->page = page; region->name = mallocString(&str); - + assert(readValue(&begin, end, &str)); region->rotate = equals(&str, "true"); - + assert(readTuple(&begin, end, tuple) == 2); region->x = toInt(tuple); region->y = toInt(tuple + 1); - + assert(readTuple(&begin, end, tuple) == 2); 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) @@ -215,10 +217,10 @@ namespace Spine region->u2 = (region->x + region->width) / (float)page->width; region->v2 = (region->y + region->height) / (float)page->height; } - + count = readTuple(&begin, end, tuple); assert(count); - + if (count == 4) { /* split is optional */ @@ -227,10 +229,10 @@ namespace Spine region->splits[1] = toInt(tuple + 1); region->splits[2] = toInt(tuple + 2); region->splits[3] = toInt(tuple + 3); - + count = readTuple(&begin, end, tuple); assert(count); - + if (count == 4) { /* pad is optional, but only present with splits */ @@ -239,75 +241,75 @@ namespace Spine region->pads[1] = toInt(tuple + 1); region->pads[2] = toInt(tuple + 2); region->pads[3] = toInt(tuple + 3); - + assert(readTuple(&begin, end, tuple)); } } - + region->originalWidth = toInt(tuple); region->originalHeight = toInt(tuple + 1); - + readTuple(&begin, end, tuple); region->offsetX = toInt(tuple); region->offsetY = toInt(tuple + 1); - + assert(readValue(&begin, end, &str)); - + region->index = toInt(&str); - + _regions.push_back(region); } } } - + void Atlas::trim(Str* str) { while (isspace((unsigned char)*str->begin) && str->begin < str->end) { (str->begin)++; } - + if (str->begin == str->end) { return; } - + str->end--; - + while (isspace((unsigned char)*str->end) && str->end >= str->begin) { str->end--; } - + str->end++; } - + int Atlas::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; } - + int Atlas::beginPast(Str* str, char c) { const char* begin = str->begin; @@ -327,7 +329,7 @@ namespace Spine str->begin = begin; return 1; } - + int Atlas::readValue(const char** begin, const char* end, Str* str) { readLine(begin, end, str); @@ -335,11 +337,11 @@ namespace Spine { return 0; } - + trim(str); return 1; } - + int Atlas::readTuple(const char** begin, const char* end, Str tuple[]) { int i; @@ -349,7 +351,7 @@ namespace Spine { return 0; } - + for (i = 0; i < 3; ++i) { tuple[i].begin = str.begin; @@ -357,18 +359,18 @@ namespace Spine { 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; } - + char* Atlas::mallocString(Str* str) { int length = (int)(str->end - str->begin); @@ -377,7 +379,7 @@ namespace Spine string[length] = '\0'; return string; } - + int Atlas::indexOf(const char** array, int count, Str* str) { int length = (int)(str->end - str->begin); @@ -391,12 +393,12 @@ namespace Spine } return 0; } - + int Atlas::equals(Str* str, const char* other) { return strncmp(other, str->begin, str->end - str->begin) == 0; } - + int Atlas::toInt(Str* str) { return (int)strtol(str->begin, (char**)&str->end, 10); From dfa1c2ecebfe141c6cf0f09f7e4446c8ee8d090f Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Sat, 25 Nov 2017 12:29:10 -0500 Subject: [PATCH 42/83] Getting some boiler plate out of the way. --- spine-cpp/spine-cpp/include/spine/Animation.h | 15 ++ .../include/spine/AttachmentTimeline.h | 76 ++------- .../spine-cpp/include/spine/ColorTimeline.h | 122 +++------------ .../spine-cpp/include/spine/DeformTimeline.h | 4 + .../include/spine/DrawOrderTimeline.h | 4 + .../spine-cpp/include/spine/EventTimeline.h | 4 + .../include/spine/IkConstraintTimeline.h | 4 + .../include/spine/PathConstraintMixTimeline.h | 4 + .../spine/PathConstraintPositionTimeline.h | 4 + .../spine/PathConstraintSpacingTimeline.h | 4 + .../spine-cpp/include/spine/ScaleTimeline.h | 4 + .../spine-cpp/include/spine/ShearTimeline.h | 4 + spine-cpp/spine-cpp/include/spine/Skeleton.h | 15 ++ spine-cpp/spine-cpp/include/spine/Slot.h | 15 ++ spine-cpp/spine-cpp/include/spine/SlotData.h | 15 ++ .../spine/TransformConstraintTimeline.h | 4 + .../include/spine/TranslateTimeline.h | 4 + .../include/spine/TwoColorTimeline.h | 4 + .../src/spine/AttachmentTimeline.cpp | 93 +++++++++++ .../spine-cpp/src/spine/ColorTimeline.cpp | 144 ++++++++++++++++++ .../spine-cpp/src/spine/DeformTimeline.cpp | 18 +++ .../spine-cpp/src/spine/DrawOrderTimeline.cpp | 18 +++ .../spine-cpp/src/spine/EventTimeline.cpp | 18 +++ .../src/spine/IkConstraintTimeline.cpp | 18 +++ .../src/spine/PathConstraintMixTimeline.cpp | 18 +++ .../spine/PathConstraintPositionTimeline.cpp | 18 +++ .../spine/PathConstraintSpacingTimeline.cpp | 18 +++ .../spine-cpp/src/spine/ScaleTimeline.cpp | 18 +++ .../spine-cpp/src/spine/ShearTimeline.cpp | 18 +++ .../src/spine/TransformConstraintTimeline.cpp | 19 ++- .../spine-cpp/src/spine/TranslateTimeline.cpp | 18 +++ .../spine-cpp/src/spine/TwoColorTimeline.cpp | 18 +++ 32 files changed, 600 insertions(+), 160 deletions(-) diff --git a/spine-cpp/spine-cpp/include/spine/Animation.h b/spine-cpp/spine-cpp/include/spine/Animation.h index 39196235c..06a8ec4bf 100644 --- a/spine-cpp/spine-cpp/include/spine/Animation.h +++ b/spine-cpp/spine-cpp/include/spine/Animation.h @@ -49,6 +49,21 @@ namespace Spine friend class TranslateTimeline; friend class AnimationStateData; + friend class AttachmentTimeline; + friend class ColorTimeline; + friend class DeformTimeline; + friend class DrawOrderTimeline; + friend class EventTimeline; + friend class IkConstraintTimeline; + friend class PathConstraintMixTimeline; + friend class PathConstraintPositionTimeline; + friend class PathConstraintSpacingTimeline; + friend class ScaleTimeline; + friend class ShearTimeline; + friend class TransformConstraintTimeline; + friend class TranslateTimeline; + friend class TwoColorTimeline; + public: Animation(std::string name, Vector& timelines, float duration); diff --git a/spine-cpp/spine-cpp/include/spine/AttachmentTimeline.h b/spine-cpp/spine-cpp/include/spine/AttachmentTimeline.h index 31267ada8..b43daf303 100644 --- a/spine-cpp/spine-cpp/include/spine/AttachmentTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/AttachmentTimeline.h @@ -49,68 +49,22 @@ namespace Spine SPINE_RTTI_DECL; public: - AttachmentTimeline(int frameCount) - { - _frames.reserve(frameCount); - _attachmentNames.reserve(frameCount); - } + AttachmentTimeline(int frameCount); -// virtual int getPropertyId() -// { -// return ((int)TimelineType_Attachment << 24) + slotIndex; -// } -// -// /// Sets the time and value of the specified keyframe. -// void setFrame(int frameIndex, float time, std::string attachmentName) -// { -// frames[frameIndex] = time; -// attachmentNames[frameIndex] = attachmentName; -// } -// -// void apply(Skeleton& skeleton, float lastTime, float time, Vector firedEvents, float alpha, MixPose pose, MixDirection direction) -// { -// std::string attachmentName; -// Slot slot = skeleton.slots.Items[slotIndex]; -// if (direction == MixDirection_Out && pose == MixPose_Setup) -// { -// attachmentName = slot.data.attachmentName; -// slot.Attachment = attachmentName == NULL ? NULL : skeleton.getAttachment(slotIndex, attachmentName); -// return; -// } -// -// float[] frames = _frames; -// if (time < frames[0]) -// { -// // Time is before first frame. -// if (pose == MixPose_Setup) -// { -// attachmentName = slot.data.attachmentName; -// slot.Attachment = attachmentName == NULL ? NULL : skeleton.getAttachment(slotIndex, attachmentName); -// } -// return; -// } -// -// int frameIndex; -// if (time >= frames[frames.Length - 1]) // Time is after last frame. -// { -// frameIndex = frames.Length - 1; -// } -// else -// { -// frameIndex = Animation::binarySearch(frames, time, 1) - 1; -// } -// -// attachmentName = attachmentNames[frameIndex]; -// slot.Attachment = attachmentName == NULL ? NULL : skeleton.getAttachment(slotIndex, attachmentName); -// } -// -// int getSlotIndex() { return _slotIndex; } -// void setSlotIndex(int inValue) { _slotIndex = inValue; } -// Vector& getFrames() { return _frames; } -// void setFrames(Vector& inValue) { _frames = inValue; } // time, ... -// Vector getAttachmentNames() { return _attachmentNames; } -// set { attachmentNames = inValue; } -// int getFrameCount() { return frames.Length; } + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); + + virtual int getPropertyId(); + + /// Sets the time and value of the specified keyframe. + void setFrame(int frameIndex, float time, std::string attachmentName); + + int getSlotIndex(); + void setSlotIndex(int inValue); + Vector& getFrames(); + void setFrames(Vector& inValue); // time, ... + Vector getAttachmentNames(); + void setAttachmentNames(Vector& inValue); + int getFrameCount(); private: int _slotIndex; diff --git a/spine-cpp/spine-cpp/include/spine/ColorTimeline.h b/spine-cpp/spine-cpp/include/spine/ColorTimeline.h index c12c54f1c..268e619c2 100644 --- a/spine-cpp/spine-cpp/include/spine/ColorTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/ColorTimeline.h @@ -39,104 +39,30 @@ namespace Spine { SPINE_RTTI_DECL; -// public const int ENTRIES = 5; -// protected const int PREV_TIME = -5, PREV_R = -4, PREV_G = -3, PREV_B = -2, PREV_A = -1; -// protected const int R = 1, G = 2, B = 3, A = 4; -// -// internal int slotIndex; -// internal float[] frames; -// -// public int SlotIndex { return slotIndex; } set { slotIndex = inValue; } -// public float[] Frames { return frames; } set { frames = inValue; } // time, r, g, b, a, ... -// -// override public int PropertyId { -// get { return ((int)TimelineType.Color << 24) + slotIndex; } -// } -// -// public ColorTimeline (int frameCount) -// : base(frameCount) { -// frames = new float[frameCount * ENTRIES]; -// } -// -// /// Sets the time and value of the specified keyframe. -// public void SetFrame (int frameIndex, float time, float r, float g, float b, float a) { -// frameIndex *= ENTRIES; -// frames[frameIndex] = time; -// frames[frameIndex + R] = r; -// frames[frameIndex + G] = g; -// frames[frameIndex + B] = b; -// frames[frameIndex + A] = a; -// } -// -// override public void Apply (Skeleton skeleton, float lastTime, float time, Vector firedEvents, float alpha, MixPose pose, MixDirection direction) { -// Slot slot = skeleton.slots.Items[slotIndex]; -// float[] frames = _frames; -// if (time < frames[0]) { -// var slotData = slot.data; -// switch (pose) { -// case MixPose_Setup: -// slot.r = slotData.r; -// slot.g = slotData.g; -// slot.b = slotData.b; -// slot.a = slotData.a; -// return; -// case MixPose_Current: -// slot.r += (slot.r - slotData.r) * alpha; -// slot.g += (slot.g - slotData.g) * alpha; -// slot.b += (slot.b - slotData.b) * alpha; -// slot.a += (slot.a - slotData.a) * alpha; -// return; -// } -// return; -// } -// -// float r, g, b, a; -// if (time >= frames[frames.Length - ENTRIES]) { // Time is after last frame. -// int i = frames.Length; -// r = frames[i + PREV_R]; -// g = frames[i + PREV_G]; -// b = frames[i + PREV_B]; -// a = frames[i + PREV_A]; -// } else { -// // Interpolate between the previous frame and the current frame. -// int frame = Animation.BinarySearch(frames, time, ENTRIES); -// r = frames[frame + PREV_R]; -// g = frames[frame + PREV_G]; -// b = frames[frame + PREV_B]; -// a = frames[frame + PREV_A]; -// float frameTime = frames[frame]; -// float percent = GetCurvePercent(frame / ENTRIES - 1, -// 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime)); -// -// r += (frames[frame + R] - r) * percent; -// g += (frames[frame + G] - g) * percent; -// b += (frames[frame + B] - b) * percent; -// a += (frames[frame + A] - a) * percent; -// } -// if (alpha == 1) { -// slot.r = r; -// slot.g = g; -// slot.b = b; -// slot.a = a; -// } else { -// float br, bg, bb, ba; -// if (pose == MixPose_Setup) { -// br = slot.data.r; -// bg = slot.data.g; -// bb = slot.data.b; -// ba = slot.data.a; -// } else { -// br = slot.r; -// bg = slot.g; -// bb = slot.b; -// ba = slot.a; -// } -// slot.r = br + ((r - br) * alpha); -// slot.g = bg + ((g - bg) * alpha); -// slot.b = bb + ((b - bb) * alpha); -// slot.a = ba + ((a - ba) * alpha); -// } -// } + public: + static const int ENTRIES; + + ColorTimeline (int frameCount); + + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); + + virtual int getPropertyId(); + + /// Sets the time and value of the specified keyframe. + void setFrame(int frameIndex, float time, float r, float g, float b, float a); + + int getSlotIndex(); + void setSlotIndex(int inValue); + Vector& getFrames(); + void setFrames(Vector& inValue); // time, r, g, b, a, ... + + protected: + static const int PREV_TIME, PREV_R, PREV_G, PREV_B, PREV_A; + static const int R, G, B, A; + + private: + int _slotIndex; + Vector _frames; }; } diff --git a/spine-cpp/spine-cpp/include/spine/DeformTimeline.h b/spine-cpp/spine-cpp/include/spine/DeformTimeline.h index 6e4aa3512..db7fe976b 100644 --- a/spine-cpp/spine-cpp/include/spine/DeformTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/DeformTimeline.h @@ -39,6 +39,10 @@ namespace Spine { SPINE_RTTI_DECL; + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); + + virtual int getPropertyId(); + // internal int slotIndex; // internal float[] frames; // internal float[][] frameVertices; diff --git a/spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h b/spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h index 97648b8a7..cf72ff56b 100644 --- a/spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h @@ -39,6 +39,10 @@ namespace Spine { SPINE_RTTI_DECL; + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); + + virtual int getPropertyId(); + // internal float[] frames; // private int[][] drawOrders; // diff --git a/spine-cpp/spine-cpp/include/spine/EventTimeline.h b/spine-cpp/spine-cpp/include/spine/EventTimeline.h index 67313e7dc..72b071fdf 100644 --- a/spine-cpp/spine-cpp/include/spine/EventTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/EventTimeline.h @@ -39,6 +39,10 @@ namespace Spine { SPINE_RTTI_DECL; + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); + + virtual int getPropertyId(); + // internal float[] frames; // private Event[] events; // diff --git a/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h b/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h index ac04b035d..204efcc6f 100644 --- a/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h @@ -39,6 +39,10 @@ namespace Spine { SPINE_RTTI_DECL; + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); + + virtual int getPropertyId(); + // public const int ENTRIES = 3; // private const int PREV_TIME = -3, PREV_MIX = -2, PREV_BEND_DIRECTION = -1; // private const int MIX = 1, BEND_DIRECTION = 2; diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h b/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h index c27619e0a..199a26e76 100644 --- a/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h @@ -39,6 +39,10 @@ namespace Spine { SPINE_RTTI_DECL; + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); + + virtual int getPropertyId(); + // public const int ENTRIES = 3; // private const int PREV_TIME = -3, PREV_ROTATE = -2, PREV_TRANSLATE = -1; // private const int ROTATE = 1, TRANSLATE = 2; diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h b/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h index 5d58d5eb6..1f85a96eb 100644 --- a/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h @@ -39,6 +39,10 @@ namespace Spine { SPINE_RTTI_DECL; + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); + + virtual int getPropertyId(); + // public const int ENTRIES = 2; // protected const int PREV_TIME = -2, PREV_VALUE = -1; // protected const int VALUE = 1; diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h b/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h index 5ff6892a5..210326437 100644 --- a/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h @@ -39,6 +39,10 @@ namespace Spine { SPINE_RTTI_DECL; + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); + + virtual int getPropertyId(); + // override public int PropertyId { // get { return ((int)TimelineType.PathConstraintSpacing << 24) + pathConstraintIndex; } // } diff --git a/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h b/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h index 075fb9b9c..f369890df 100644 --- a/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h @@ -39,6 +39,10 @@ namespace Spine { SPINE_RTTI_DECL; + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); + + virtual int getPropertyId(); + // override public int PropertyId { // get { return ((int)TimelineType.Scale << 24) + boneIndex; } // } diff --git a/spine-cpp/spine-cpp/include/spine/ShearTimeline.h b/spine-cpp/spine-cpp/include/spine/ShearTimeline.h index b04c4156d..ddf02f09d 100644 --- a/spine-cpp/spine-cpp/include/spine/ShearTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/ShearTimeline.h @@ -39,6 +39,10 @@ namespace Spine { SPINE_RTTI_DECL; + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); + + virtual int getPropertyId(); + // override public int PropertyId { // get { return ((int)TimelineType.Shear << 24) + boneIndex; } // } diff --git a/spine-cpp/spine-cpp/include/spine/Skeleton.h b/spine-cpp/spine-cpp/include/spine/Skeleton.h index 9e3eb9583..03ff33d5c 100644 --- a/spine-cpp/spine-cpp/include/spine/Skeleton.h +++ b/spine-cpp/spine-cpp/include/spine/Skeleton.h @@ -51,6 +51,21 @@ namespace Spine class Skeleton { + friend class AttachmentTimeline; + friend class ColorTimeline; + friend class DeformTimeline; + friend class DrawOrderTimeline; + friend class EventTimeline; + friend class IkConstraintTimeline; + friend class PathConstraintMixTimeline; + friend class PathConstraintPositionTimeline; + friend class PathConstraintSpacingTimeline; + friend class ScaleTimeline; + friend class ShearTimeline; + friend class TransformConstraintTimeline; + friend class TranslateTimeline; + friend class TwoColorTimeline; + public: Skeleton(SkeletonData& data); diff --git a/spine-cpp/spine-cpp/include/spine/Slot.h b/spine-cpp/spine-cpp/include/spine/Slot.h index 07af110d5..26fd37f9a 100644 --- a/spine-cpp/spine-cpp/include/spine/Slot.h +++ b/spine-cpp/spine-cpp/include/spine/Slot.h @@ -47,6 +47,21 @@ namespace Spine friend class VertexAttachment; friend class Skeleton; + friend class AttachmentTimeline; + friend class ColorTimeline; + friend class DeformTimeline; + friend class DrawOrderTimeline; + friend class EventTimeline; + friend class IkConstraintTimeline; + friend class PathConstraintMixTimeline; + friend class PathConstraintPositionTimeline; + friend class PathConstraintSpacingTimeline; + friend class ScaleTimeline; + friend class ShearTimeline; + friend class TransformConstraintTimeline; + friend class TranslateTimeline; + friend class TwoColorTimeline; + public: Slot(SlotData& data, Bone& bone); diff --git a/spine-cpp/spine-cpp/include/spine/SlotData.h b/spine-cpp/spine-cpp/include/spine/SlotData.h index 0fe231984..02dbaac4a 100644 --- a/spine-cpp/spine-cpp/include/spine/SlotData.h +++ b/spine-cpp/spine-cpp/include/spine/SlotData.h @@ -41,6 +41,21 @@ namespace Spine class SlotData { + friend class AttachmentTimeline; + friend class ColorTimeline; + friend class DeformTimeline; + friend class DrawOrderTimeline; + friend class EventTimeline; + friend class IkConstraintTimeline; + friend class PathConstraintMixTimeline; + friend class PathConstraintPositionTimeline; + friend class PathConstraintSpacingTimeline; + friend class ScaleTimeline; + friend class ShearTimeline; + friend class TransformConstraintTimeline; + friend class TranslateTimeline; + friend class TwoColorTimeline; + public: SlotData(int index, std::string name, BoneData& boneData); diff --git a/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h b/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h index 00debb06d..4df5190ba 100644 --- a/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h @@ -39,6 +39,10 @@ namespace Spine { SPINE_RTTI_DECL; + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); + + virtual int getPropertyId(); + // public const int ENTRIES = 5; // private const int PREV_TIME = -5, PREV_ROTATE = -4, PREV_TRANSLATE = -3, PREV_SCALE = -2, PREV_SHEAR = -1; // private const int ROTATE = 1, TRANSLATE = 2, SCALE = 3, SHEAR = 4; diff --git a/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h b/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h index 8abccc9e2..40a5e191c 100644 --- a/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h @@ -42,6 +42,10 @@ namespace Spine { SPINE_RTTI_DECL; + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); + + virtual int getPropertyId(); + // public const int ENTRIES = 3; // protected const int PREV_TIME = -3, PREV_X = -2, PREV_Y = -1; // protected const int X = 1, Y = 2; diff --git a/spine-cpp/spine-cpp/include/spine/TwoColorTimeline.h b/spine-cpp/spine-cpp/include/spine/TwoColorTimeline.h index 8d814439f..0943967e5 100644 --- a/spine-cpp/spine-cpp/include/spine/TwoColorTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/TwoColorTimeline.h @@ -39,6 +39,10 @@ namespace Spine { SPINE_RTTI_DECL; + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); + + virtual int getPropertyId(); + // public const int ENTRIES = 8; // protected const int PREV_TIME = -8, PREV_R = -7, PREV_G = -6, PREV_B = -5, PREV_A = -4; // protected const int PREV_R2 = -3, PREV_G2 = -2, PREV_B2 = -1; diff --git a/spine-cpp/spine-cpp/src/spine/AttachmentTimeline.cpp b/spine-cpp/spine-cpp/src/spine/AttachmentTimeline.cpp index cc562fd80..5535f0242 100644 --- a/spine-cpp/spine-cpp/src/spine/AttachmentTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/AttachmentTimeline.cpp @@ -35,8 +35,101 @@ #include #include +#include +#include namespace Spine { SPINE_RTTI_IMPL(AttachmentTimeline, Timeline); + + AttachmentTimeline::AttachmentTimeline(int frameCount) + { + _frames.reserve(frameCount); + _attachmentNames.reserve(frameCount); + } + + void AttachmentTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) + { + assert(_slotIndex < skeleton._slots.size()); + + std::string attachmentName; + Slot* slotP = skeleton._slots[_slotIndex]; + Slot& slot = *slotP; + if (direction == MixDirection_Out && pose == MixPose_Setup) + { + attachmentName = slot._data._attachmentName; + slot._attachment = attachmentName.length() == 0 ? NULL : skeleton.getAttachment(_slotIndex, attachmentName); + return; + } + + if (time < _frames[0]) + { + // Time is before first frame. + if (pose == MixPose_Setup) + { + attachmentName = slot._data._attachmentName; + slot._attachment = attachmentName.length() == 0 ? NULL : skeleton.getAttachment(_slotIndex, attachmentName); + } + return; + } + + int frameIndex; + if (time >= _frames[_frames.size() - 1]) // Time is after last frame. + { + frameIndex = static_cast(_frames.size()) - 1; + } + else + { + frameIndex = Animation::binarySearch(_frames, time, 1) - 1; + } + + attachmentName = _attachmentNames[frameIndex]; + slot._attachment = attachmentName.length() == 0 ? NULL : skeleton.getAttachment(_slotIndex, attachmentName); + } + + int AttachmentTimeline::getPropertyId() + { + return ((int)TimelineType_Attachment << 24) + _slotIndex; + } + + void AttachmentTimeline::setFrame(int frameIndex, float time, std::string attachmentName) + { + _frames[frameIndex] = time; + _attachmentNames[frameIndex] = attachmentName; + } + + int AttachmentTimeline::getSlotIndex() + { + return _slotIndex; + } + + void AttachmentTimeline::setSlotIndex(int inValue) + { + _slotIndex = inValue; + } + + Vector& AttachmentTimeline::getFrames() + { + return _frames; + } + + void AttachmentTimeline::setFrames(Vector& inValue) + { + _frames = inValue; + } + + Vector AttachmentTimeline::getAttachmentNames() + { + return _attachmentNames; + } + + void AttachmentTimeline::setAttachmentNames(Vector& inValue) + { + _attachmentNames = inValue; + } + + int AttachmentTimeline::getFrameCount() + { + return static_cast(_frames.size()); + } } diff --git a/spine-cpp/spine-cpp/src/spine/ColorTimeline.cpp b/spine-cpp/spine-cpp/src/spine/ColorTimeline.cpp index e53c26b97..13d425d27 100644 --- a/spine-cpp/spine-cpp/src/spine/ColorTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/ColorTimeline.cpp @@ -30,7 +30,151 @@ #include +#include +#include + +#include +#include +#include +#include + namespace Spine { SPINE_RTTI_IMPL(ColorTimeline, CurveTimeline); + + const int ColorTimeline::ENTRIES = 5; + const int ColorTimeline::PREV_TIME = -5; + const int ColorTimeline::PREV_R = -4; + const int ColorTimeline::PREV_G = -3; + const int ColorTimeline::PREV_B = -2; + const int ColorTimeline::PREV_A = -1; + const int ColorTimeline::R = 1; + const int ColorTimeline::G = 2; + const int ColorTimeline::B = 3; + const int ColorTimeline::A = 4; + + ColorTimeline::ColorTimeline(int frameCount) : CurveTimeline(frameCount) + { + _frames.reserve(frameCount * ENTRIES); + } + + void ColorTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) + { + Slot* slotP = skeleton._slots[_slotIndex]; + Slot& slot = *slotP; + if (time < _frames[0]) + { + SlotData& slotData = slot._data; + switch (pose) + { + case MixPose_Setup: + slot._r = slotData._r; + slot._g = slotData._g; + slot._b = slotData._b; + slot._a = slotData._a; + return; + case MixPose_Current: + slot._r += (slot._r - slotData._r) * alpha; + slot._g += (slot._g - slotData._g) * alpha; + slot._b += (slot._b - slotData._b) * alpha; + slot._a += (slot._a - slotData._a) * alpha; + return; + case MixPose_CurrentLayered: + default: + return; + } + } + + float r, g, b, a; + if (time >= _frames[_frames.size() - ENTRIES]) + { + // Time is after last frame. + int i = static_cast(_frames.size()); + r = _frames[i + PREV_R]; + g = _frames[i + PREV_G]; + b = _frames[i + PREV_B]; + a = _frames[i + PREV_A]; + } + else + { + // Interpolate between the previous frame and the current frame. + int frame = Animation::binarySearch(_frames, time, ENTRIES); + r = _frames[frame + PREV_R]; + g = _frames[frame + PREV_G]; + b = _frames[frame + PREV_B]; + a = _frames[frame + PREV_A]; + float frameTime = _frames[frame]; + float percent = getCurvePercent(frame / ENTRIES - 1, 1 - (time - frameTime) / (_frames[frame + PREV_TIME] - frameTime)); + + r += (_frames[frame + R] - r) * percent; + g += (_frames[frame + G] - g) * percent; + b += (_frames[frame + B] - b) * percent; + a += (_frames[frame + A] - a) * percent; + } + + if (alpha == 1) + { + slot._r = r; + slot._g = g; + slot._b = b; + slot._a = a; + } + else + { + float br, bg, bb, ba; + if (pose == MixPose_Setup) + { + br = slot._data._r; + bg = slot._data._g; + bb = slot._data._b; + ba = slot._data._a; + } + else + { + br = slot._r; + bg = slot._g; + bb = slot._b; + ba = slot._a; + } + slot._r = br + ((r - br) * alpha); + slot._g = bg + ((g - bg) * alpha); + slot._b = bb + ((b - bb) * alpha); + slot._a = ba + ((a - ba) * alpha); + } + } + + int ColorTimeline::getPropertyId() + { + return ((int)TimelineType_Color << 24) + _slotIndex; + } + + void ColorTimeline::setFrame(int frameIndex, float time, float r, float g, float b, float a) + { + frameIndex *= ENTRIES; + _frames[frameIndex] = time; + _frames[frameIndex + R] = r; + _frames[frameIndex + G] = g; + _frames[frameIndex + B] = b; + _frames[frameIndex + A] = a; + } + + int ColorTimeline::getSlotIndex() + { + return _slotIndex; + } + + void ColorTimeline::setSlotIndex(int inValue) + { + _slotIndex = inValue; + } + + Vector& ColorTimeline::getFrames() + { + return _frames; + } + + void ColorTimeline::setFrames(Vector& inValue) + { + _frames = inValue; + } } diff --git a/spine-cpp/spine-cpp/src/spine/DeformTimeline.cpp b/spine-cpp/spine-cpp/src/spine/DeformTimeline.cpp index fb99c6d33..34a3c487b 100644 --- a/spine-cpp/spine-cpp/src/spine/DeformTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/DeformTimeline.cpp @@ -30,7 +30,25 @@ #include +#include +#include + +#include +#include +#include +#include + namespace Spine { SPINE_RTTI_IMPL(DeformTimeline, CurveTimeline); + + void DeformTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) + { + // TODO + } + + int DeformTimeline::getPropertyId() + { + return 0; + } } diff --git a/spine-cpp/spine-cpp/src/spine/DrawOrderTimeline.cpp b/spine-cpp/spine-cpp/src/spine/DrawOrderTimeline.cpp index 34f9c9b14..d8eceb2da 100644 --- a/spine-cpp/spine-cpp/src/spine/DrawOrderTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/DrawOrderTimeline.cpp @@ -30,7 +30,25 @@ #include +#include +#include + +#include +#include +#include +#include + namespace Spine { SPINE_RTTI_IMPL(DrawOrderTimeline, Timeline); + + void DrawOrderTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) + { + // TODO + } + + int DrawOrderTimeline::getPropertyId() + { + return 0; + } } diff --git a/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp b/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp index dc6ee5246..7d1b0bb9f 100644 --- a/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp @@ -30,7 +30,25 @@ #include +#include +#include + +#include +#include +#include +#include + namespace Spine { SPINE_RTTI_IMPL(EventTimeline, Timeline); + + void EventTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) + { + // TODO + } + + int EventTimeline::getPropertyId() + { + return 0; + } } diff --git a/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp b/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp index 603b48c06..71c49bc1f 100644 --- a/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp @@ -30,7 +30,25 @@ #include +#include +#include + +#include +#include +#include +#include + namespace Spine { SPINE_RTTI_IMPL(IkConstraintTimeline, CurveTimeline); + + void IkConstraintTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) + { + // TODO + } + + int IkConstraintTimeline::getPropertyId() + { + return 0; + } } diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp b/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp index 515c7bf17..60cc7923c 100644 --- a/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp @@ -30,7 +30,25 @@ #include +#include +#include + +#include +#include +#include +#include + namespace Spine { SPINE_RTTI_IMPL(PathConstraintMixTimeline, CurveTimeline); + + void PathConstraintMixTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) + { + // TODO + } + + int PathConstraintMixTimeline::getPropertyId() + { + return 0; + } } diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp b/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp index ca033cd55..ec680b528 100644 --- a/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp @@ -30,7 +30,25 @@ #include +#include +#include + +#include +#include +#include +#include + namespace Spine { SPINE_RTTI_IMPL(PathConstraintPositionTimeline, CurveTimeline); + + void PathConstraintPositionTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) + { + // TODO + } + + int PathConstraintPositionTimeline::getPropertyId() + { + return 0; + } } diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp b/spine-cpp/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp index 7a9f5567f..131b9d9cd 100644 --- a/spine-cpp/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp @@ -30,7 +30,25 @@ #include +#include +#include + +#include +#include +#include +#include + namespace Spine { SPINE_RTTI_IMPL(PathConstraintSpacingTimeline, PathConstraintPositionTimeline); + + void PathConstraintSpacingTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) + { + // TODO + } + + int PathConstraintSpacingTimeline::getPropertyId() + { + return 0; + } } diff --git a/spine-cpp/spine-cpp/src/spine/ScaleTimeline.cpp b/spine-cpp/spine-cpp/src/spine/ScaleTimeline.cpp index 2da55b080..84e1401d1 100644 --- a/spine-cpp/spine-cpp/src/spine/ScaleTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/ScaleTimeline.cpp @@ -30,7 +30,25 @@ #include +#include +#include + +#include +#include +#include +#include + namespace Spine { SPINE_RTTI_IMPL(ScaleTimeline, TranslateTimeline); + + void ScaleTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) + { + // TODO + } + + int ScaleTimeline::getPropertyId() + { + return 0; + } } diff --git a/spine-cpp/spine-cpp/src/spine/ShearTimeline.cpp b/spine-cpp/spine-cpp/src/spine/ShearTimeline.cpp index 13d19abda..04b8ad8e8 100644 --- a/spine-cpp/spine-cpp/src/spine/ShearTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/ShearTimeline.cpp @@ -30,7 +30,25 @@ #include +#include +#include + +#include +#include +#include +#include + namespace Spine { SPINE_RTTI_IMPL(ShearTimeline, TranslateTimeline); + + void ShearTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) + { + // TODO + } + + int ShearTimeline::getPropertyId() + { + return 0; + } } diff --git a/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp b/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp index daceecc8a..578734cb8 100644 --- a/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp @@ -30,8 +30,25 @@ #include +#include +#include + +#include +#include +#include +#include + namespace Spine { SPINE_RTTI_IMPL(TransformConstraintTimeline, CurveTimeline); + + void TransformConstraintTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) + { + // TODO + } + + int TransformConstraintTimeline::getPropertyId() + { + return 0; + } } - diff --git a/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp b/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp index 97c43cfce..34d8b1b14 100644 --- a/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp @@ -30,7 +30,25 @@ #include +#include +#include + +#include +#include +#include +#include + namespace Spine { SPINE_RTTI_IMPL(TranslateTimeline, CurveTimeline); + + void TranslateTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) + { + // TODO + } + + int TranslateTimeline::getPropertyId() + { + return 0; + } } diff --git a/spine-cpp/spine-cpp/src/spine/TwoColorTimeline.cpp b/spine-cpp/spine-cpp/src/spine/TwoColorTimeline.cpp index 45adf3def..afd005f6e 100644 --- a/spine-cpp/spine-cpp/src/spine/TwoColorTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/TwoColorTimeline.cpp @@ -30,7 +30,25 @@ #include +#include +#include + +#include +#include +#include +#include + namespace Spine { SPINE_RTTI_IMPL(TwoColorTimeline, CurveTimeline); + + void TwoColorTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) + { + // TODO + } + + int TwoColorTimeline::getPropertyId() + { + return 0; + } } From 6b585ae151df9b45e3f89ef82c53ad494830a790 Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Sat, 25 Nov 2017 12:44:57 -0500 Subject: [PATCH 43/83] blah --- spine-cpp/spine-cpp/include/spine/DeformTimeline.h | 2 +- spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h | 2 +- spine-cpp/spine-cpp/include/spine/EventTimeline.h | 2 +- spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h | 2 +- spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h | 2 +- .../spine-cpp/include/spine/PathConstraintPositionTimeline.h | 2 +- .../spine-cpp/include/spine/PathConstraintSpacingTimeline.h | 2 +- spine-cpp/spine-cpp/include/spine/ScaleTimeline.h | 2 +- spine-cpp/spine-cpp/include/spine/ShearTimeline.h | 2 +- spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h | 2 +- spine-cpp/spine-cpp/include/spine/TwoColorTimeline.h | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/spine-cpp/spine-cpp/include/spine/DeformTimeline.h b/spine-cpp/spine-cpp/include/spine/DeformTimeline.h index db7fe976b..7319e4b23 100644 --- a/spine-cpp/spine-cpp/include/spine/DeformTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/DeformTimeline.h @@ -149,7 +149,7 @@ namespace Spine // } // // // Interpolate between the previous frame and the current frame. -// int frame = Animation.BinarySearch(frames, time); +// int frame = Animation::binarySearch(frames, time); // float[] prevVertices = frameVertices[frame - 1]; // float[] nextVertices = frameVertices[frame]; // float frameTime = frames[frame]; diff --git a/spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h b/spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h index cf72ff56b..b05fb161b 100644 --- a/spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h @@ -84,7 +84,7 @@ namespace Spine // if (time >= frames[frames.Length - 1]) // Time is after last frame. // frame = frames.Length - 1; // else -// frame = Animation.BinarySearch(frames, time) - 1; +// frame = Animation::binarySearch(frames, time) - 1; // // int[] drawOrderToSetupIndex = drawOrders[frame]; // if (drawOrderToSetupIndex == NULL) { diff --git a/spine-cpp/spine-cpp/include/spine/EventTimeline.h b/spine-cpp/spine-cpp/include/spine/EventTimeline.h index 72b071fdf..e0c2859bc 100644 --- a/spine-cpp/spine-cpp/include/spine/EventTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/EventTimeline.h @@ -82,7 +82,7 @@ namespace Spine // if (lastTime < frames[0]) // frame = 0; // else { -// frame = Animation.BinarySearch(frames, lastTime); +// frame = Animation::binarySearch(frames, lastTime); // float frameTime = frames[frame]; // while (frame > 0) { // Fire multiple events with the same frame. // if (frames[frame - 1] != frameTime) break; diff --git a/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h b/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h index 204efcc6f..69b3a1ac5 100644 --- a/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h @@ -100,7 +100,7 @@ namespace Spine // } // // // Interpolate between the previous frame and the current frame. -// int frame = Animation.BinarySearch(frames, time, ENTRIES); +// int frame = Animation::binarySearch(frames, time, ENTRIES); // float mix = frames[frame + PREV_MIX]; // float frameTime = frames[frame]; // float percent = GetCurvePercent(frame / ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime)); diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h b/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h index 199a26e76..5514ab8f6 100644 --- a/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h @@ -93,7 +93,7 @@ namespace Spine // translate = frames[frames.Length + PREV_TRANSLATE]; // } else { // // Interpolate between the previous frame and the current frame. -// int frame = Animation.BinarySearch(frames, time, ENTRIES); +// int frame = Animation::binarySearch(frames, time, ENTRIES); // rotate = frames[frame + PREV_ROTATE]; // translate = frames[frame + PREV_TRANSLATE]; // float frameTime = frames[frame]; diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h b/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h index 1f85a96eb..91fc2d252 100644 --- a/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h @@ -89,7 +89,7 @@ namespace Spine // position = frames[frames.Length + PREV_VALUE]; // else { // // Interpolate between the previous frame and the current frame. -// int frame = Animation.BinarySearch(frames, time, ENTRIES); +// int frame = Animation::binarySearch(frames, time, ENTRIES); // position = frames[frame + PREV_VALUE]; // float frameTime = frames[frame]; // float percent = GetCurvePercent(frame / ENTRIES - 1, diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h b/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h index 210326437..41c6cf8ce 100644 --- a/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h @@ -71,7 +71,7 @@ namespace Spine // spacing = frames[frames.Length + PREV_VALUE]; // else { // // Interpolate between the previous frame and the current frame. -// int frame = Animation.BinarySearch(frames, time, ENTRIES); +// int frame = Animation::binarySearch(frames, time, ENTRIES); // spacing = frames[frame + PREV_VALUE]; // float frameTime = frames[frame]; // float percent = GetCurvePercent(frame / ENTRIES - 1, diff --git a/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h b/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h index f369890df..af06c888c 100644 --- a/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h @@ -75,7 +75,7 @@ namespace Spine // y = frames[frames.Length + PREV_Y] * bone.data.scaleY; // } else { // // Interpolate between the previous frame and the current frame. -// int frame = Animation.BinarySearch(frames, time, ENTRIES); +// int frame = Animation::binarySearch(frames, time, ENTRIES); // x = frames[frame + PREV_X]; // y = frames[frame + PREV_Y]; // float frameTime = frames[frame]; diff --git a/spine-cpp/spine-cpp/include/spine/ShearTimeline.h b/spine-cpp/spine-cpp/include/spine/ShearTimeline.h index ddf02f09d..585c7ed5a 100644 --- a/spine-cpp/spine-cpp/include/spine/ShearTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/ShearTimeline.h @@ -74,7 +74,7 @@ namespace Spine // y = frames[frames.Length + PREV_Y]; // } else { // // Interpolate between the previous frame and the current frame. -// int frame = Animation.BinarySearch(frames, time, ENTRIES); +// int frame = Animation::binarySearch(frames, time, ENTRIES); // x = frames[frame + PREV_X]; // y = frames[frame + PREV_Y]; // float frameTime = frames[frame]; diff --git a/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h b/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h index 4df5190ba..b53d19d76 100644 --- a/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h @@ -102,7 +102,7 @@ namespace Spine // shear = frames[i + PREV_SHEAR]; // } else { // // Interpolate between the previous frame and the current frame. -// int frame = Animation.BinarySearch(frames, time, ENTRIES); +// int frame = Animation::binarySearch(frames, time, ENTRIES); // rotate = frames[frame + PREV_ROTATE]; // translate = frames[frame + PREV_TRANSLATE]; // scale = frames[frame + PREV_SCALE]; diff --git a/spine-cpp/spine-cpp/include/spine/TwoColorTimeline.h b/spine-cpp/spine-cpp/include/spine/TwoColorTimeline.h index 0943967e5..c855f0586 100644 --- a/spine-cpp/spine-cpp/include/spine/TwoColorTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/TwoColorTimeline.h @@ -124,7 +124,7 @@ namespace Spine // b2 = frames[i + PREV_B2]; // } else { // // Interpolate between the previous frame and the current frame. -// int frame = Animation.BinarySearch(frames, time, ENTRIES); +// int frame = Animation::binarySearch(frames, time, ENTRIES); // r = frames[frame + PREV_R]; // g = frames[frame + PREV_G]; // b = frames[frame + PREV_B]; From 24a38110497dc0816357f2c12c755e698468ee90 Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Sat, 25 Nov 2017 12:53:49 -0500 Subject: [PATCH 44/83] NDK compiler was fussing about the location of the #include line; needs to be first. --- spine-cpp/spine-cpp/include/spine/ContainerUtil.h | 2 +- spine-cpp/spine-cpp/include/spine/HashMap.h | 1 + spine-cpp/spine-cpp/include/spine/Pool.h | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/spine-cpp/spine-cpp/include/spine/ContainerUtil.h b/spine-cpp/spine-cpp/include/spine/ContainerUtil.h index 6f9b85245..053a56634 100644 --- a/spine-cpp/spine-cpp/include/spine/ContainerUtil.h +++ b/spine-cpp/spine-cpp/include/spine/ContainerUtil.h @@ -31,9 +31,9 @@ #ifndef Spine_ContainerUtil_h #define Spine_ContainerUtil_h +#include #include #include -#include #include #include diff --git a/spine-cpp/spine-cpp/include/spine/HashMap.h b/spine-cpp/spine-cpp/include/spine/HashMap.h index 372131a11..b6882b04c 100755 --- a/spine-cpp/spine-cpp/include/spine/HashMap.h +++ b/spine-cpp/spine-cpp/include/spine/HashMap.h @@ -31,6 +31,7 @@ #ifndef Spine_HashMap_h #define Spine_HashMap_h +#include #include namespace Spine diff --git a/spine-cpp/spine-cpp/include/spine/Pool.h b/spine-cpp/spine-cpp/include/spine/Pool.h index 096821476..3ea37cff3 100644 --- a/spine-cpp/spine-cpp/include/spine/Pool.h +++ b/spine-cpp/spine-cpp/include/spine/Pool.h @@ -31,9 +31,9 @@ #ifndef Spine_Pool_h #define Spine_Pool_h +#include #include #include -#include namespace Spine { From 5411125c93d49cfa7bb91f5fa5cdc3e4c1a80d18 Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Sat, 25 Nov 2017 14:04:49 -0500 Subject: [PATCH 45/83] wip, these timeline classes are all pretty much the same, so this is going pretty quickly. --- .../spine-cpp/include/spine/DeformTimeline.h | 165 ++----------- .../include/spine/DrawOrderTimeline.h | 71 ++---- .../spine-cpp/include/spine/EventTimeline.h | 7 +- .../include/spine/IkConstraintTimeline.h | 32 ++- .../include/spine/PathConstraintMixTimeline.h | 14 +- .../spine/PathConstraintPositionTimeline.h | 33 +-- .../spine/PathConstraintSpacingTimeline.h | 11 +- .../spine-cpp/include/spine/ScaleTimeline.h | 4 - .../spine-cpp/include/spine/ShearTimeline.h | 5 +- spine-cpp/spine-cpp/include/spine/SpineRTTI.h | 6 +- .../spine/TransformConstraintTimeline.h | 19 +- .../include/spine/TranslateTimeline.h | 9 +- .../include/spine/TwoColorTimeline.h | 10 +- .../include/spine/VertexAttachment.h | 2 + .../src/spine/AttachmentTimeline.cpp | 2 +- .../spine-cpp/src/spine/ColorTimeline.cpp | 2 +- .../spine-cpp/src/spine/DeformTimeline.cpp | 218 +++++++++++++++++- .../spine-cpp/src/spine/DrawOrderTimeline.cpp | 94 +++++++- .../spine-cpp/src/spine/EventTimeline.cpp | 2 +- .../src/spine/IkConstraintTimeline.cpp | 14 +- .../spine-cpp/src/spine/PathConstraint.cpp | 2 +- .../src/spine/PathConstraintMixTimeline.cpp | 2 +- .../spine/PathConstraintPositionTimeline.cpp | 12 +- .../spine/PathConstraintSpacingTimeline.cpp | 7 +- .../spine-cpp/src/spine/ScaleTimeline.cpp | 2 +- .../spine-cpp/src/spine/ShearTimeline.cpp | 2 +- spine-cpp/spine-cpp/src/spine/Skeleton.cpp | 8 +- .../src/spine/TransformConstraintTimeline.cpp | 13 +- .../spine-cpp/src/spine/TranslateTimeline.cpp | 2 +- .../spine-cpp/src/spine/TwoColorTimeline.cpp | 2 +- 30 files changed, 471 insertions(+), 301 deletions(-) diff --git a/spine-cpp/spine-cpp/include/spine/DeformTimeline.h b/spine-cpp/spine-cpp/include/spine/DeformTimeline.h index 7319e4b23..faf3f848e 100644 --- a/spine-cpp/spine-cpp/include/spine/DeformTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/DeformTimeline.h @@ -35,155 +35,36 @@ namespace Spine { - class DeformTimeline : CurveTimeline + class VertexAttachment; + + class DeformTimeline : public CurveTimeline { SPINE_RTTI_DECL; + public: + DeformTimeline(int frameCount); + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); virtual int getPropertyId(); -// internal int slotIndex; -// internal float[] frames; -// internal float[][] frameVertices; -// internal VertexAttachment attachment; -// -// public int SlotIndex { return slotIndex; } set { slotIndex = inValue; } -// public float[] Frames { return frames; } set { frames = inValue; } // time, ... -// public float[][] Vertices { return frameVertices; } set { frameVertices = inValue; } -// public VertexAttachment Attachment { return attachment; } set { attachment = inValue; } -// -// override public int PropertyId { -// get { return ((int)TimelineType.Deform << 24) + attachment.id + slotIndex; } -// } -// -// public DeformTimeline (int frameCount) -// : base(frameCount) { -// frames = new float[frameCount]; -// frameVertices = new float[frameCount][]; -// } -// -// /// Sets the time and value of the specified keyframe. -// public void SetFrame (int frameIndex, float time, float[] vertices) { -// frames[frameIndex] = time; -// frameVertices[frameIndex] = vertices; -// } -// -// override public void Apply (Skeleton skeleton, float lastTime, float time, Vector firedEvents, float alpha, MixPose pose, MixDirection direction) { -// Slot slot = skeleton.slots.Items[slotIndex]; -// VertexAttachment vertexAttachment = slot.attachment as VertexAttachment; -// if (vertexAttachment == NULL || !vertexAttachment.ApplyDeform(attachment)) return; -// -// var verticesArray = slot.attachmentVertices; -// if (verticesArray.Count == 0) alpha = 1; -// -// float[][] frameVertices = _frameVertices; -// int vertexCount = frameVertices[0].Length; -// float[] frames = _frames; -// float[] vertices; -// -// if (time < frames[0]) { -// -// switch (pose) { -// case MixPose_Setup: -// verticesArray.Clear(); -// return; -// case MixPose_Current: -// if (alpha == 1) { -// verticesArray.Clear(); -// return; -// } -// -// // verticesArray.SetSize(vertexCount) // Ensure size and preemptively set count. -// if (verticesArray.Capacity < vertexCount) verticesArray.Capacity = vertexCount; -// verticesArray.Count = vertexCount; -// vertices = verticesArray.Items; -// -// if (vertexAttachment.bones == NULL) { -// // Unweighted vertex positions. -// float[] setupVertices = vertexAttachment.vertices; -// for (int i = 0; i < vertexCount; i++) -// vertices[i] += (setupVertices[i] - vertices[i]) * alpha; -// } else { -// // Weighted deform offsets. -// alpha = 1 - alpha; -// for (int i = 0; i < vertexCount; i++) -// vertices[i] *= alpha; -// } -// return; -// default: -// return; -// } -// -// } -// -// // verticesArray.SetSize(vertexCount) // Ensure size and preemptively set count. -// if (verticesArray.Capacity < vertexCount) verticesArray.Capacity = vertexCount; -// verticesArray.Count = vertexCount; -// vertices = verticesArray.Items; -// -// if (time >= frames[frames.Length - 1]) { // Time is after last frame. -// float[] lastVertices = frameVertices[frames.Length - 1]; -// if (alpha == 1) { -// // Vertex positions or deform offsets, no alpha. -// Array.Copy(lastVertices, 0, vertices, 0, vertexCount); -// } else if (pose == MixPose_Setup) { -// if (vertexAttachment.bones == NULL) { -// // Unweighted vertex positions, with alpha. -// float[] setupVertices = vertexAttachment.vertices; -// for (int i = 0; i < vertexCount; i++) { -// float setup = setupVertices[i]; -// vertices[i] = setup + (lastVertices[i] - setup) * alpha; -// } -// } else { -// // Weighted deform offsets, with alpha. -// for (int i = 0; i < vertexCount; i++) -// vertices[i] = lastVertices[i] * alpha; -// } -// } else { -// // Vertex positions or deform offsets, with alpha. -// for (int i = 0; i < vertexCount; i++) -// vertices[i] += (lastVertices[i] - vertices[i]) * alpha; -// } -// return; -// } -// -// // Interpolate between the previous frame and the current frame. -// int frame = Animation::binarySearch(frames, time); -// float[] prevVertices = frameVertices[frame - 1]; -// float[] nextVertices = frameVertices[frame]; -// float frameTime = frames[frame]; -// float percent = GetCurvePercent(frame - 1, 1 - (time - frameTime) / (frames[frame - 1] - frameTime)); -// -// if (alpha == 1) { -// // Vertex positions or deform offsets, no alpha. -// for (int i = 0; i < vertexCount; i++) { -// float prev = prevVertices[i]; -// vertices[i] = prev + (nextVertices[i] - prev) * percent; -// } -// } else if (pose == MixPose_Setup) { -// if (vertexAttachment.bones == NULL) { -// // Unweighted vertex positions, with alpha. -// var setupVertices = vertexAttachment.vertices; -// for (int i = 0; i < vertexCount; i++) { -// float prev = prevVertices[i], setup = setupVertices[i]; -// vertices[i] = setup + (prev + (nextVertices[i] - prev) * percent - setup) * alpha; -// } -// } else { -// // Weighted deform offsets, with alpha. -// for (int i = 0; i < vertexCount; i++) { -// float prev = prevVertices[i]; -// vertices[i] = (prev + (nextVertices[i] - prev) * percent) * alpha; -// } -// } -// } else { -// // Vertex positions or deform offsets, with alpha. -// for (int i = 0; i < vertexCount; i++) { -// float prev = prevVertices[i]; -// vertices[i] += (prev + (nextVertices[i] - prev) * percent - vertices[i]) * alpha; -// } -// } -// } + /// Sets the time and value of the specified keyframe. + void setFrame(int frameIndex, float time, Vector& vertices); + + int getSlotIndex(); + void setSlotIndex(int inValue); + Vector& getFrames(); + void setFrames(Vector& inValue); // time, ... + Vector< Vector >& getVertices(); + void setVertices(Vector< Vector >& inValue); + VertexAttachment* getAttachment(); + void setAttachment(VertexAttachment* inValue); + + private: + int _slotIndex; + Vector _frames; + Vector< Vector > _frameVertices; + VertexAttachment* _attachment; }; } diff --git a/spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h b/spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h index b05fb161b..ac1ea0623 100644 --- a/spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h @@ -38,66 +38,27 @@ namespace Spine class DrawOrderTimeline : public Timeline { SPINE_RTTI_DECL; + + public: + DrawOrderTimeline(int frameCount); virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); virtual int getPropertyId(); -// internal float[] frames; -// private int[][] drawOrders; -// -// public float[] Frames { return frames; } set { frames = inValue; } // time, ... -// public int[][] DrawOrders { return drawOrders; } set { drawOrders = inValue; } -// public int FrameCount { return frames.Length; } -// -// public int PropertyId { -// get { return ((int)TimelineType.DrawOrder << 24); } -// } -// -// public DrawOrderTimeline (int frameCount) { -// frames = new float[frameCount]; -// drawOrders = new int[frameCount][]; -// } -// -// /// Sets the time and value of the specified keyframe. -// /// May be NULL to use bind pose draw order. -// public void SetFrame (int frameIndex, float time, int[] drawOrder) { -// frames[frameIndex] = time; -// drawOrders[frameIndex] = drawOrder; -// } -// -// public void Apply (Skeleton skeleton, float lastTime, float time, Vector firedEvents, float alpha, MixPose pose, MixDirection direction) { -// Vector drawOrder = skeleton.drawOrder; -// Vector slots = skeleton.slots; -// if (direction == MixDirection_Out && pose == MixPose_Setup) { -// Array.Copy(slots.Items, 0, drawOrder.Items, 0, slots.Count); -// return; -// } -// -// float[] frames = _frames; -// if (time < frames[0]) { -// if (pose == MixPose_Setup) Array.Copy(slots.Items, 0, drawOrder.Items, 0, slots.Count); -// return; -// } -// -// int frame; -// if (time >= frames[frames.Length - 1]) // Time is after last frame. -// frame = frames.Length - 1; -// else -// frame = Animation::binarySearch(frames, time) - 1; -// -// int[] drawOrderToSetupIndex = drawOrders[frame]; -// if (drawOrderToSetupIndex == NULL) { -// drawOrder.Clear(); -// for (int i = 0, n = slots.Count; i < n; i++) -// drawOrder.Add(slots.Items[i]); -// } else { -// var drawOrderItems = drawOrder.Items; -// var slotsItems = slots.Items; -// for (int i = 0, n = drawOrderToSetupIndex.Length; i < n; i++) -// drawOrderItems[i] = slotsItems[drawOrderToSetupIndex[i]]; -// } -// } + /// Sets the time and value of the specified keyframe. + /// @param drawOrder May be NULL to use bind pose draw order + void setFrame(int frameIndex, float time, Vector& drawOrder); + + Vector& getFrames(); + void setFrames(Vector& inValue); // time, ... + Vector< Vector >& getDrawOrders(); + void setDrawOrders(Vector< Vector >& inValue); + int getFrameCount(); + + private: + Vector _frames; + Vector< Vector > _drawOrders; }; } diff --git a/spine-cpp/spine-cpp/include/spine/EventTimeline.h b/spine-cpp/spine-cpp/include/spine/EventTimeline.h index e0c2859bc..1013a26e7 100644 --- a/spine-cpp/spine-cpp/include/spine/EventTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/EventTimeline.h @@ -49,10 +49,7 @@ namespace Spine // public float[] Frames { return frames; } set { frames = inValue; } // time, ... // public Event[] Events { return events; } set { events = inValue; } // public int FrameCount { return frames.Length; } -// -// public int PropertyId { -// get { return ((int)TimelineType.Event << 24); } -// } +// // // public EventTimeline (int frameCount) { // frames = new float[frameCount]; @@ -60,7 +57,7 @@ namespace Spine // } // // /// Sets the time and value of the specified keyframe. -// public void SetFrame (int frameIndex, Event e) { +// public void setFrame (int frameIndex, Event e) { // frames[frameIndex] = e.Time; // events[frameIndex] = e; // } diff --git a/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h b/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h index 69b3a1ac5..7b44c8f04 100644 --- a/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h @@ -39,31 +39,29 @@ namespace Spine { SPINE_RTTI_DECL; + public: + static const int ENTRIES; + + IkConstraintTimeline(int frameCount); + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); virtual int getPropertyId(); -// public const int ENTRIES = 3; -// private const int PREV_TIME = -3, PREV_MIX = -2, PREV_BEND_DIRECTION = -1; -// private const int MIX = 1, BEND_DIRECTION = 2; -// -// internal int ikConstraintIndex; -// internal float[] frames; -// + private: + static const int PREV_TIME, PREV_MIX, PREV_BEND_DIRECTION; + static const int MIX, BEND_DIRECTION; + + Vector _frames; + int _ikConstraintIndex; + // public int IkConstraintIndex { return ikConstraintIndex; } set { ikConstraintIndex = inValue; } // public float[] Frames { return frames; } set { frames = inValue; } // time, mix, bendDirection, ... -// -// override public int PropertyId { -// get { return ((int)TimelineType.IkConstraint << 24) + ikConstraintIndex; } -// } -// -// public IkConstraintTimeline (int frameCount) -// : base(frameCount) { -// frames = new float[frameCount * ENTRIES]; -// } +// +// // // /// Sets the time, mix and bend direction of the specified keyframe. -// public void SetFrame (int frameIndex, float time, float mix, int bendDirection) { +// public void setFrame (int frameIndex, float time, float mix, int bendDirection) { // frameIndex *= ENTRIES; // frames[frameIndex] = time; // frames[frameIndex + MIX] = mix; diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h b/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h index 5514ab8f6..030ae5fb3 100644 --- a/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h @@ -39,23 +39,23 @@ namespace Spine { SPINE_RTTI_DECL; + public: virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); virtual int getPropertyId(); + private: + int _pathConstraintIndex; + // public const int ENTRIES = 3; // private const int PREV_TIME = -3, PREV_ROTATE = -2, PREV_TRANSLATE = -1; // private const int ROTATE = 1, TRANSLATE = 2; -// -// internal int pathConstraintIndex; +// // internal float[] frames; // // public int PathConstraintIndex { return pathConstraintIndex; } set { pathConstraintIndex = inValue; } // public float[] Frames { return frames; } set { frames = inValue; } // time, rotate mix, translate mix, ... -// -// override public int PropertyId { -// get { return ((int)TimelineType.PathConstraintMix << 24) + pathConstraintIndex; } -// } +// // // public PathConstraintMixTimeline (int frameCount) // : base(frameCount) { @@ -63,7 +63,7 @@ namespace Spine // } // // /// Sets the time and mixes of the specified keyframe. -// public void SetFrame (int frameIndex, float time, float rotateMix, float translateMix) { +// public void setFrame (int frameIndex, float time, float rotateMix, float translateMix) { // frameIndex *= ENTRIES; // frames[frameIndex] = time; // frames[frameIndex + ROTATE] = rotateMix; diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h b/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h index 91fc2d252..12c0cffa0 100644 --- a/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h @@ -39,31 +39,32 @@ namespace Spine { SPINE_RTTI_DECL; + public: + static const int ENTRIES; + + PathConstraintPositionTimeline(int frameCount); + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); virtual int getPropertyId(); -// public const int ENTRIES = 2; -// protected const int PREV_TIME = -2, PREV_VALUE = -1; -// protected const int VALUE = 1; -// -// internal int pathConstraintIndex; -// internal float[] frames; -// -// override public int PropertyId { -// get { return ((int)TimelineType.PathConstraintPosition << 24) + pathConstraintIndex; } -// } -// -// public PathConstraintPositionTimeline (int frameCount) -// : base(frameCount) { -// frames = new float[frameCount * ENTRIES]; -// } + protected: + static const int PREV_TIME, PREV_VALUE; + static const int VALUE; + + Vector _frames; + int _pathConstraintIndex; + + +// +// +// // // public int PathConstraintIndex { return pathConstraintIndex; } set { pathConstraintIndex = inValue; } // public float[] Frames { return frames; } set { frames = inValue; } // time, position, ... // // /// Sets the time and value of the specified keyframe. -// public void SetFrame (int frameIndex, float time, float value) { +// public void setFrame (int frameIndex, float time, float value) { // frameIndex *= ENTRIES; // frames[frameIndex] = time; // frames[frameIndex + VALUE] = inValue; diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h b/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h index 41c6cf8ce..35c974bff 100644 --- a/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h @@ -39,18 +39,13 @@ namespace Spine { SPINE_RTTI_DECL; + public: + PathConstraintSpacingTimeline(int frameCount); + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); virtual int getPropertyId(); -// override public int PropertyId { -// get { return ((int)TimelineType.PathConstraintSpacing << 24) + pathConstraintIndex; } -// } -// -// public PathConstraintSpacingTimeline (int frameCount) -// : base(frameCount) { -// } -// // override public void Apply (Skeleton skeleton, float lastTime, float time, Vector firedEvents, float alpha, MixPose pose, MixDirection direction) { // PathConstraint constraint = skeleton.pathConstraints.Items[pathConstraintIndex]; // float[] frames = _frames; diff --git a/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h b/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h index af06c888c..dd6db7e65 100644 --- a/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h @@ -43,10 +43,6 @@ namespace Spine virtual int getPropertyId(); -// override public int PropertyId { -// get { return ((int)TimelineType.Scale << 24) + boneIndex; } -// } -// // public ScaleTimeline (int frameCount) // : base(frameCount) { // } diff --git a/spine-cpp/spine-cpp/include/spine/ShearTimeline.h b/spine-cpp/spine-cpp/include/spine/ShearTimeline.h index 585c7ed5a..74a440876 100644 --- a/spine-cpp/spine-cpp/include/spine/ShearTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/ShearTimeline.h @@ -39,14 +39,11 @@ namespace Spine { SPINE_RTTI_DECL; + public: virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); virtual int getPropertyId(); -// override public int PropertyId { -// get { return ((int)TimelineType.Shear << 24) + boneIndex; } -// } -// // public ShearTimeline (int frameCount) // : base(frameCount) { // } diff --git a/spine-cpp/spine-cpp/include/spine/SpineRTTI.h b/spine-cpp/spine-cpp/include/spine/SpineRTTI.h index 9cf985ae8..4ed9806bc 100644 --- a/spine-cpp/spine-cpp/include/spine/SpineRTTI.h +++ b/spine-cpp/spine-cpp/include/spine/SpineRTTI.h @@ -61,15 +61,15 @@ namespace Spine #define SPINE_RTTI_DECL \ public: \ static const Spine::SPINE_RTTI rtti; \ -virtual const Spine::SPINE_RTTI& getSPINE_RTTI(); +virtual const Spine::SPINE_RTTI& getRTTI(); #define SPINE_RTTI_IMPL_NOPARENT(name) \ const Spine::SPINE_RTTI name::rtti(#name); \ -const Spine::SPINE_RTTI& name::getSPINE_RTTI() { return rtti; } +const Spine::SPINE_RTTI& name::getRTTI() { return rtti; } #define SPINE_RTTI_IMPL(name,parent) \ const Spine::SPINE_RTTI name::rtti(#name, parent::rtti); \ -const Spine::SPINE_RTTI& name::getSPINE_RTTI() { return rtti; } +const Spine::SPINE_RTTI& name::getRTTI() { return rtti; } #endif /* Spine_SPINE_RTTI_h */ diff --git a/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h b/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h index b53d19d76..6990e1aa3 100644 --- a/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h @@ -39,30 +39,31 @@ namespace Spine { SPINE_RTTI_DECL; + public: + static const int ENTRIES; + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); virtual int getPropertyId(); -// public const int ENTRIES = 5; -// private const int PREV_TIME = -5, PREV_ROTATE = -4, PREV_TRANSLATE = -3, PREV_SCALE = -2, PREV_SHEAR = -1; -// private const int ROTATE = 1, TRANSLATE = 2, SCALE = 3, SHEAR = 4; -// -// internal int transformConstraintIndex; + private: + static const int PREV_TIME, PREV_ROTATE, PREV_TRANSLATE, PREV_SCALE, PREV_SHEAR; + static const int ROTATE, TRANSLATE, SCALE, SHEAR; + + int _transformConstraintIndex; + // internal float[] frames; // // public int TransformConstraintIndex { return transformConstraintIndex; } set { transformConstraintIndex = inValue; } // public float[] Frames { return frames; } set { frames = inValue; } // time, rotate mix, translate mix, scale mix, shear mix, ... // -// override public int PropertyId { -// get { return ((int)TimelineType.TransformConstraint << 24) + transformConstraintIndex; } -// } // // public TransformConstraintTimeline (int frameCount) // : base(frameCount) { // frames = new float[frameCount * ENTRIES]; // } // -// public void SetFrame (int frameIndex, float time, float rotateMix, float translateMix, float scaleMix, float shearMix) { +// public void setFrame (int frameIndex, float time, float rotateMix, float translateMix, float scaleMix, float shearMix) { // frameIndex *= ENTRIES; // frames[frameIndex] = time; // frames[frameIndex + ROTATE] = rotateMix; diff --git a/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h b/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h index 40a5e191c..cd48f40b4 100644 --- a/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h @@ -42,24 +42,23 @@ namespace Spine { SPINE_RTTI_DECL; + public: virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); virtual int getPropertyId(); + protected: + int _boneIndex; + // public const int ENTRIES = 3; // protected const int PREV_TIME = -3, PREV_X = -2, PREV_Y = -1; // protected const int X = 1, Y = 2; // -// internal int boneIndex; // internal float[] frames; // // public int getBoneIndex { return boneIndex; } set { boneIndex = inValue; } // public Vector getFrames { return frames; } set { frames = inValue; } // time, value, value, ... // -// virtual int getPropertyId() -// { -// return ((int)TimelineType_Translate << 24) + boneIndex; -// } // // public TranslateTimeline(int frameCount) : CurveTimeline(frameCount) // { diff --git a/spine-cpp/spine-cpp/include/spine/TwoColorTimeline.h b/spine-cpp/spine-cpp/include/spine/TwoColorTimeline.h index c855f0586..df61adeb9 100644 --- a/spine-cpp/spine-cpp/include/spine/TwoColorTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/TwoColorTimeline.h @@ -39,10 +39,14 @@ namespace Spine { SPINE_RTTI_DECL; + public: virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); virtual int getPropertyId(); + private: + int _slotIndex; + // public const int ENTRIES = 8; // protected const int PREV_TIME = -8, PREV_R = -7, PREV_G = -6, PREV_B = -5, PREV_A = -4; // protected const int PREV_R2 = -3, PREV_G2 = -2, PREV_B2 = -1; @@ -51,7 +55,6 @@ namespace Spine // internal float[] frames; // time, r, g, b, a, r2, g2, b2, ... // public float[] Frames { return frames; } // -// internal int slotIndex; // public int SlotIndex { // get { return slotIndex; } // set { @@ -60,9 +63,6 @@ namespace Spine // } // } // -// override public int PropertyId { -// get { return ((int)TimelineType.TwoColor << 24) + slotIndex; } -// } // // public TwoColorTimeline (int frameCount) : // base(frameCount) { @@ -70,7 +70,7 @@ namespace Spine // } // // /// Sets the time and value of the specified keyframe. -// public void SetFrame (int frameIndex, float time, float r, float g, float b, float a, float r2, float g2, float b2) { +// public void setFrame (int frameIndex, float time, float r, float g, float b, float a, float r2, float g2, float b2) { // frameIndex *= ENTRIES; // frames[frameIndex] = time; // frames[frameIndex + R] = r; diff --git a/spine-cpp/spine-cpp/include/spine/VertexAttachment.h b/spine-cpp/spine-cpp/include/spine/VertexAttachment.h index 7c7841bd0..935601df3 100644 --- a/spine-cpp/spine-cpp/include/spine/VertexAttachment.h +++ b/spine-cpp/spine-cpp/include/spine/VertexAttachment.h @@ -44,6 +44,8 @@ namespace Spine { SPINE_RTTI_DECL; + friend class DeformTimeline; + public: VertexAttachment(std::string name); diff --git a/spine-cpp/spine-cpp/src/spine/AttachmentTimeline.cpp b/spine-cpp/spine-cpp/src/spine/AttachmentTimeline.cpp index 5535f0242..0fe3f9114 100644 --- a/spine-cpp/spine-cpp/src/spine/AttachmentTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/AttachmentTimeline.cpp @@ -42,7 +42,7 @@ namespace Spine { SPINE_RTTI_IMPL(AttachmentTimeline, Timeline); - AttachmentTimeline::AttachmentTimeline(int frameCount) + AttachmentTimeline::AttachmentTimeline(int frameCount) : Timeline(), _slotIndex(0) { _frames.reserve(frameCount); _attachmentNames.reserve(frameCount); diff --git a/spine-cpp/spine-cpp/src/spine/ColorTimeline.cpp b/spine-cpp/spine-cpp/src/spine/ColorTimeline.cpp index 13d425d27..6968fbe75 100644 --- a/spine-cpp/spine-cpp/src/spine/ColorTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/ColorTimeline.cpp @@ -53,7 +53,7 @@ namespace Spine const int ColorTimeline::B = 3; const int ColorTimeline::A = 4; - ColorTimeline::ColorTimeline(int frameCount) : CurveTimeline(frameCount) + ColorTimeline::ColorTimeline(int frameCount) : CurveTimeline(frameCount), _slotIndex(0) { _frames.reserve(frameCount * ENTRIES); } diff --git a/spine-cpp/spine-cpp/src/spine/DeformTimeline.cpp b/spine-cpp/spine-cpp/src/spine/DeformTimeline.cpp index 34a3c487b..b9fb2c5ef 100644 --- a/spine-cpp/spine-cpp/src/spine/DeformTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/DeformTimeline.cpp @@ -33,6 +33,8 @@ #include #include +#include + #include #include #include @@ -42,13 +44,225 @@ namespace Spine { SPINE_RTTI_IMPL(DeformTimeline, CurveTimeline); + DeformTimeline::DeformTimeline(int frameCount) : CurveTimeline(frameCount), _slotIndex(0), _attachment(NULL) + { + _frames.reserve(frameCount); + _frameVertices.reserve(frameCount); + } + void DeformTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) { - // TODO + Slot* slotP = skeleton._slots[_slotIndex]; + Slot& slot = *slotP; + + if (slot._attachment == NULL || !slot._attachment->getRTTI().derivesFrom(VertexAttachment::rtti)) + { + return; + } + + VertexAttachment* vertexAttachment = static_cast(slot._attachment); + if (!vertexAttachment->applyDeform(_attachment)) + { + return; + } + + Vector& vertices = slot._attachmentVertices; + if (vertices.size() == 0) + { + alpha = 1; + } + + int vertexCount = static_cast(_frameVertices[0].size()); + + if (time < _frames[0]) + { + switch (pose) + { + case MixPose_Setup: + vertices.clear(); + return; + case MixPose_Current: + if (alpha == 1) + { + vertices.clear(); + return; + } + + // Ensure size and preemptively set count. + vertices.reserve(vertexCount); + + if (vertexAttachment->_bones.size() == 0) + { + // Unweighted vertex positions. + Vector& setupVertices = vertexAttachment->_vertices; + for (int i = 0; i < vertexCount; ++i) + { + vertices[i] += (setupVertices[i] - vertices[i]) * alpha; + } + } + else + { + // Weighted deform offsets. + alpha = 1 - alpha; + for (int i = 0; i < vertexCount; ++i) + { + vertices[i] *= alpha; + } + } + return; + default: + return; + } + } + + // Ensure size and preemptively set count. + vertices.reserve(vertexCount); + + if (time >= _frames[_frames.size() - 1]) + { + // Time is after last frame. + Vector& lastVertices = _frameVertices[_frames.size() - 1]; + if (alpha == 1) + { + // Vertex positions or deform offsets, no alpha. + vertices.clear(); + for (int i = 0; i < vertexCount; ++i) + { + float vertex = lastVertices[i]; + vertices.push_back(vertex); + } + } + else if (pose == MixPose_Setup) + { + if (vertexAttachment->_bones.size() == 0) + { + // Unweighted vertex positions, with alpha. + Vector& setupVertices = vertexAttachment->_vertices; + for (int i = 0; i < vertexCount; i++) + { + float setup = setupVertices[i]; + vertices[i] = setup + (lastVertices[i] - setup) * alpha; + } + } + else + { + // Weighted deform offsets, with alpha. + for (int i = 0; i < vertexCount; ++i) + { + vertices[i] = lastVertices[i] * alpha; + } + } + } + else + { + // Vertex positions or deform offsets, with alpha. + for (int i = 0; i < vertexCount; ++i) + { + vertices[i] += (lastVertices[i] - vertices[i]) * alpha; + } + } + return; + } + + // Interpolate between the previous frame and the current frame. + int frame = Animation::binarySearch(_frames, time); + Vector& prevVertices = _frameVertices[frame - 1]; + Vector& nextVertices = _frameVertices[frame]; + float frameTime = _frames[frame]; + float percent = getCurvePercent(frame - 1, 1 - (time - frameTime) / (_frames[frame - 1] - frameTime)); + + if (alpha == 1) + { + // Vertex positions or deform offsets, no alpha. + for (int i = 0; i < vertexCount; ++i) + { + float prev = prevVertices[i]; + vertices[i] = prev + (nextVertices[i] - prev) * percent; + } + } + else if (pose == MixPose_Setup) + { + if (vertexAttachment->_bones.size() == 0) + { + // Unweighted vertex positions, with alpha. + Vector& setupVertices = vertexAttachment->_vertices; + for (int i = 0; i < vertexCount; ++i) + { + float prev = prevVertices[i], setup = setupVertices[i]; + vertices[i] = setup + (prev + (nextVertices[i] - prev) * percent - setup) * alpha; + } + } + else + { + // Weighted deform offsets, with alpha. + for (int i = 0; i < vertexCount; ++i) + { + float prev = prevVertices[i]; + vertices[i] = (prev + (nextVertices[i] - prev) * percent) * alpha; + } + } + } + else + { + // Vertex positions or deform offsets, with alpha. + for (int i = 0; i < vertexCount; ++i) + { + float prev = prevVertices[i]; + vertices[i] += (prev + (nextVertices[i] - prev) * percent - vertices[i]) * alpha; + } + } } int DeformTimeline::getPropertyId() { - return 0; + assert(_attachment != NULL); + + return ((int)TimelineType_Deform << 24) + _attachment->_id + _slotIndex; + } + + void DeformTimeline::setFrame(int frameIndex, float time, Vector& vertices) + { + _frames[frameIndex] = time; + _frameVertices[frameIndex] = vertices; + } + + int DeformTimeline::getSlotIndex() + { + return _slotIndex; + } + + void DeformTimeline::setSlotIndex(int inValue) + { + _slotIndex = inValue; + } + + Vector& DeformTimeline::getFrames() + { + return _frames; + } + + void DeformTimeline::setFrames(Vector& inValue) + { + _frames = inValue; + } + + Vector< Vector >& DeformTimeline::getVertices() + { + return _frameVertices; + } + + void DeformTimeline::setVertices(Vector< Vector >& inValue) + { + _frameVertices = inValue; + } + + VertexAttachment* DeformTimeline::getAttachment() + { + return _attachment; + } + + void DeformTimeline::setAttachment(VertexAttachment* inValue) + { + _attachment = inValue; } } diff --git a/spine-cpp/spine-cpp/src/spine/DrawOrderTimeline.cpp b/spine-cpp/spine-cpp/src/spine/DrawOrderTimeline.cpp index d8eceb2da..bb84bcdf5 100644 --- a/spine-cpp/spine-cpp/src/spine/DrawOrderTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/DrawOrderTimeline.cpp @@ -42,13 +42,103 @@ namespace Spine { SPINE_RTTI_IMPL(DrawOrderTimeline, Timeline); + DrawOrderTimeline::DrawOrderTimeline(int frameCount) : Timeline() + { + _frames.reserve(frameCount); + _drawOrders.reserve(frameCount); + } + void DrawOrderTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) { - // TODO + Vector& drawOrder = skeleton._drawOrder; + Vector& slots = skeleton._slots; + if (direction == MixDirection_Out && pose == MixPose_Setup) + { + drawOrder.clear(); + drawOrder.reserve(slots.size()); + for (int i = 0, n = static_cast(slots.size()); i < n; ++i) + { + drawOrder.push_back(slots[i]); + } + return; + } + + if (time < _frames[0]) + { + if (pose == MixPose_Setup) + { + drawOrder.clear(); + drawOrder.reserve(slots.size()); + for (int i = 0, n = static_cast(slots.size()); i < n; ++i) + { + drawOrder.push_back(slots[i]); + } + } + return; + } + + int frame; + if (time >= _frames[_frames.size() - 1]) + { + // Time is after last frame. + frame = static_cast(_frames.size()) - 1; + } + else + { + frame = Animation::binarySearch(_frames, time) - 1; + } + + Vector& drawOrderToSetupIndex = _drawOrders[frame]; + if (drawOrderToSetupIndex.size() == 0) + { + drawOrder.clear(); + for (int i = 0, n = static_cast(slots.size()); i < n; ++i) + { + drawOrder.push_back(slots[i]); + } + } + else + { + for (int i = 0, n = static_cast(drawOrderToSetupIndex.size()); i < n; ++i) + { + drawOrder[i] = slots[drawOrderToSetupIndex[i]]; + } + } } int DrawOrderTimeline::getPropertyId() { - return 0; + return ((int)TimelineType_DrawOrder << 24); + } + + void DrawOrderTimeline::setFrame(int frameIndex, float time, Vector& drawOrder) + { + _frames[frameIndex] = time; + _drawOrders[frameIndex] = drawOrder; + } + + Vector& DrawOrderTimeline::getFrames() + { + return _frames; + } + + void DrawOrderTimeline::setFrames(Vector& inValue) + { + _frames = inValue; + } + + Vector< Vector >& DrawOrderTimeline::getDrawOrders() + { + return _drawOrders; + } + + void DrawOrderTimeline::setDrawOrders(Vector< Vector >& inValue) + { + _drawOrders = inValue; + } + + int DrawOrderTimeline::getFrameCount() + { + return static_cast(_frames.size()); } } diff --git a/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp b/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp index 7d1b0bb9f..bcd78be19 100644 --- a/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp @@ -49,6 +49,6 @@ namespace Spine int EventTimeline::getPropertyId() { - return 0; + return ((int)TimelineType_Event << 24); } } diff --git a/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp b/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp index 71c49bc1f..a2886f8f3 100644 --- a/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp @@ -42,6 +42,18 @@ namespace Spine { SPINE_RTTI_IMPL(IkConstraintTimeline, CurveTimeline); + const int IkConstraintTimeline::ENTRIES = 3; + const int IkConstraintTimeline::PREV_TIME = -3; + const int IkConstraintTimeline::PREV_MIX = -2; + const int IkConstraintTimeline::PREV_BEND_DIRECTION = -1; + const int IkConstraintTimeline::MIX = 1; + const int IkConstraintTimeline::BEND_DIRECTION = 2; + + IkConstraintTimeline::IkConstraintTimeline(int frameCount) : CurveTimeline(frameCount), _ikConstraintIndex(0) + { + _frames.reserve(frameCount * ENTRIES); + } + void IkConstraintTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) { // TODO @@ -49,6 +61,6 @@ namespace Spine int IkConstraintTimeline::getPropertyId() { - return 0; + return ((int)TimelineType_IkConstraint << 24) + _ikConstraintIndex; } } diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp b/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp index c44a495ba..7dbef8438 100644 --- a/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp @@ -79,7 +79,7 @@ namespace Spine void PathConstraint::update() { Attachment* baseAttachment = _target->getAttachment(); - if (baseAttachment == NULL || !baseAttachment->getSPINE_RTTI().derivesFrom(PathAttachment::rtti)) + if (baseAttachment == NULL || !baseAttachment->getRTTI().derivesFrom(PathAttachment::rtti)) { return; } diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp b/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp index 60cc7923c..65c4c2998 100644 --- a/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp @@ -49,6 +49,6 @@ namespace Spine int PathConstraintMixTimeline::getPropertyId() { - return 0; + return ((int)TimelineType_PathConstraintMix << 24) + _pathConstraintIndex; } } diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp b/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp index ec680b528..4e6f70d66 100644 --- a/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp @@ -42,6 +42,16 @@ namespace Spine { SPINE_RTTI_IMPL(PathConstraintPositionTimeline, CurveTimeline); + const int PathConstraintPositionTimeline::ENTRIES = 2; + const int PathConstraintPositionTimeline::PREV_TIME = -2; + const int PathConstraintPositionTimeline::PREV_VALUE = -1; + const int PathConstraintPositionTimeline::VALUE = 1; + + PathConstraintPositionTimeline::PathConstraintPositionTimeline(int frameCount) : CurveTimeline(frameCount) + { + _frames.reserve(frameCount * ENTRIES); + } + void PathConstraintPositionTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) { // TODO @@ -49,6 +59,6 @@ namespace Spine int PathConstraintPositionTimeline::getPropertyId() { - return 0; + return ((int)TimelineType_PathConstraintPosition << 24) + _pathConstraintIndex; } } diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp b/spine-cpp/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp index 131b9d9cd..17c5ac2aa 100644 --- a/spine-cpp/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp @@ -42,6 +42,11 @@ namespace Spine { SPINE_RTTI_IMPL(PathConstraintSpacingTimeline, PathConstraintPositionTimeline); + PathConstraintSpacingTimeline::PathConstraintSpacingTimeline(int frameCount) : PathConstraintPositionTimeline(frameCount) + { + // Empty + } + void PathConstraintSpacingTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) { // TODO @@ -49,6 +54,6 @@ namespace Spine int PathConstraintSpacingTimeline::getPropertyId() { - return 0; + return ((int)TimelineType_PathConstraintSpacing << 24) + _pathConstraintIndex; } } diff --git a/spine-cpp/spine-cpp/src/spine/ScaleTimeline.cpp b/spine-cpp/spine-cpp/src/spine/ScaleTimeline.cpp index 84e1401d1..3151759eb 100644 --- a/spine-cpp/spine-cpp/src/spine/ScaleTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/ScaleTimeline.cpp @@ -49,6 +49,6 @@ namespace Spine int ScaleTimeline::getPropertyId() { - return 0; + return ((int)TimelineType_Scale << 24) + _boneIndex; } } diff --git a/spine-cpp/spine-cpp/src/spine/ShearTimeline.cpp b/spine-cpp/spine-cpp/src/spine/ShearTimeline.cpp index 04b8ad8e8..132967ea8 100644 --- a/spine-cpp/spine-cpp/src/spine/ShearTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/ShearTimeline.cpp @@ -49,6 +49,6 @@ namespace Spine int ShearTimeline::getPropertyId() { - return 0; + return ((int)TimelineType_Shear << 24) + _boneIndex; } } diff --git a/spine-cpp/spine-cpp/src/spine/Skeleton.cpp b/spine-cpp/spine-cpp/src/spine/Skeleton.cpp index b295f83d7..0221175f8 100644 --- a/spine-cpp/spine-cpp/src/spine/Skeleton.cpp +++ b/spine-cpp/spine-cpp/src/spine/Skeleton.cpp @@ -484,7 +484,7 @@ namespace Spine int verticesLength = 0; Attachment* attachment = slot->getAttachment(); - if (attachment != NULL && attachment->getSPINE_RTTI().derivesFrom(RegionAttachment::rtti)) + if (attachment != NULL && attachment->getRTTI().derivesFrom(RegionAttachment::rtti)) { RegionAttachment* regionAttachment = static_cast(attachment); @@ -495,7 +495,7 @@ namespace Spine } regionAttachment->computeWorldVertices(slot->getBone(), outVertexBuffer, 0); } - else if (attachment != NULL && attachment->getSPINE_RTTI().derivesFrom(MeshAttachment::rtti)) + else if (attachment != NULL && attachment->getRTTI().derivesFrom(MeshAttachment::rtti)) { MeshAttachment* mesh = static_cast(attachment); @@ -712,7 +712,7 @@ namespace Spine } Attachment* attachment = slot->_attachment; - if (attachment != NULL && attachment->getSPINE_RTTI().derivesFrom(PathAttachment::rtti)) + if (attachment != NULL && attachment->getRTTI().derivesFrom(PathAttachment::rtti)) { sortPathConstraintAttachment(attachment, slotBone); } @@ -793,7 +793,7 @@ namespace Spine void Skeleton::sortPathConstraintAttachment(Attachment* attachment, Bone& slotBone) { - if (attachment == NULL || attachment->getSPINE_RTTI().derivesFrom(PathAttachment::rtti)) + if (attachment == NULL || attachment->getRTTI().derivesFrom(PathAttachment::rtti)) { return; } diff --git a/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp b/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp index 578734cb8..33335732f 100644 --- a/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp @@ -42,6 +42,17 @@ namespace Spine { SPINE_RTTI_IMPL(TransformConstraintTimeline, CurveTimeline); + const int TransformConstraintTimeline::ENTRIES = 5; + const int TransformConstraintTimeline::PREV_TIME = -5; + const int TransformConstraintTimeline::PREV_ROTATE = -4; + const int TransformConstraintTimeline::PREV_TRANSLATE = -3; + const int TransformConstraintTimeline::PREV_SCALE = -2; + const int TransformConstraintTimeline::PREV_SHEAR = -1; + const int TransformConstraintTimeline::ROTATE = 1; + const int TransformConstraintTimeline::TRANSLATE = 2; + const int TransformConstraintTimeline::SCALE = 3; + const int TransformConstraintTimeline::SHEAR = 4; + void TransformConstraintTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) { // TODO @@ -49,6 +60,6 @@ namespace Spine int TransformConstraintTimeline::getPropertyId() { - return 0; + return ((int)TimelineType_TransformConstraint << 24) + _transformConstraintIndex; } } diff --git a/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp b/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp index 34d8b1b14..05afdad26 100644 --- a/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp @@ -49,6 +49,6 @@ namespace Spine int TranslateTimeline::getPropertyId() { - return 0; + return ((int)TimelineType_Translate << 24) + _boneIndex; } } diff --git a/spine-cpp/spine-cpp/src/spine/TwoColorTimeline.cpp b/spine-cpp/spine-cpp/src/spine/TwoColorTimeline.cpp index afd005f6e..1062f481a 100644 --- a/spine-cpp/spine-cpp/src/spine/TwoColorTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/TwoColorTimeline.cpp @@ -49,6 +49,6 @@ namespace Spine int TwoColorTimeline::getPropertyId() { - return 0; + return ((int)TimelineType_TwoColor << 24) + _slotIndex; } } From 19687d9957fd5869ca3661cdd2f698e6a7f58b35 Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Sat, 25 Nov 2017 15:09:37 -0500 Subject: [PATCH 46/83] wip, forgot about SkeletonBounds and SkeletonClipping --- .../include/spine/ClippingAttachment.h | 2 + .../spine-cpp/include/spine/EventTimeline.h | 2 +- .../spine-cpp/include/spine/SkeletonBounds.h | 112 +++++++ .../include/spine/SkeletonClipping.h | 76 +++++ spine-cpp/spine-cpp/include/spine/Slot.h | 1 + spine-cpp/spine-cpp/include/spine/Vector.h | 13 + .../spine-cpp/src/spine/SkeletonBounds.cpp | 267 ++++++++++++++++ .../spine-cpp/src/spine/SkeletonClipping.cpp | 293 ++++++++++++++++++ 8 files changed, 765 insertions(+), 1 deletion(-) create mode 100644 spine-cpp/spine-cpp/include/spine/SkeletonBounds.h create mode 100644 spine-cpp/spine-cpp/include/spine/SkeletonClipping.h create mode 100644 spine-cpp/spine-cpp/src/spine/SkeletonBounds.cpp create mode 100644 spine-cpp/spine-cpp/src/spine/SkeletonClipping.cpp diff --git a/spine-cpp/spine-cpp/include/spine/ClippingAttachment.h b/spine-cpp/spine-cpp/include/spine/ClippingAttachment.h index 6ee27813d..6b117c374 100644 --- a/spine-cpp/spine-cpp/include/spine/ClippingAttachment.h +++ b/spine-cpp/spine-cpp/include/spine/ClippingAttachment.h @@ -41,6 +41,8 @@ namespace Spine { SPINE_RTTI_DECL; + friend class SkeletonClipping; + public: ClippingAttachment(std::string name); diff --git a/spine-cpp/spine-cpp/include/spine/EventTimeline.h b/spine-cpp/spine-cpp/include/spine/EventTimeline.h index 1013a26e7..4a844cbd7 100644 --- a/spine-cpp/spine-cpp/include/spine/EventTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/EventTimeline.h @@ -87,7 +87,7 @@ namespace Spine // } // } // for (; frame < frameCount && time >= frames[frame]; frame++) -// firedEvents.Add(events[frame]); +// firedEvents.push_back(events[frame]); // } }; } diff --git a/spine-cpp/spine-cpp/include/spine/SkeletonBounds.h b/spine-cpp/spine-cpp/include/spine/SkeletonBounds.h new file mode 100644 index 000000000..432342a1f --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/SkeletonBounds.h @@ -0,0 +1,112 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_SkeletonBounds_h +#define Spine_SkeletonBounds_h + +#include + +namespace Spine +{ + class Skeleton; + class BoundingBoxAttachment; + + class Polygon; + + /// + /// Collects each BoundingBoxAttachment that is visible and computes the world vertices for its polygon. + /// The polygon vertices are provided along with convenience methods for doing hit detection. + /// + class SkeletonBounds + { + public: + SkeletonBounds(); + + /// + /// Clears any previous polygons, finds all visible bounding box attachments, + /// and computes the world vertices for each bounding box's polygon. + /// @param skeleton The skeleton. + /// @param updateAabb + /// If true, the axis aligned bounding box containing all the polygons is computed. + /// If false, the SkeletonBounds AABB methods will always return true. + /// + void update(Skeleton& skeleton, bool updateAabb); + + /// Returns true if the axis aligned bounding box contains the point. + bool aabbcontainsPoint(float x, float y); + + /// Returns true if the axis aligned bounding box intersects the line segment. + bool aabbintersectsSegment(float x1, float y1, float x2, float y2); + + /// Returns true if the axis aligned bounding box intersects the axis aligned bounding box of the specified bounds. + bool aabbIntersectsSkeleton(SkeletonBounds bounds); + + /// Returns true if the polygon contains the point. + bool containsPoint(Polygon polygon, float x, float y); + + /// Returns the first bounding box attachment that contains the point, or NULL. When doing many checks, it is usually more + /// efficient to only call this method if {@link #aabbcontainsPoint(float, float)} returns true. + BoundingBoxAttachment* containsPoint(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 {@link #aabbintersectsSegment(float, float, float, float)} returns true. + BoundingBoxAttachment* intersectsSegment(float x1, float y1, float x2, float y2); + + /// Returns true if the polygon contains the line segment. + bool intersectsSegment(Polygon* polygon, float x1, float y1, float x2, float y2); + + Polygon* getPolygon(BoundingBoxAttachment* attachment); + + float getWidth(); + float getHeight(); + + private: + Vector _polygonPool; + Vector _boundingBoxes; + Vector _polygons; + float _minX, _minY, _maxX, _maxY; + + void aabbCompute(); + }; + + class Polygon + { + public: + Vector _vertices; + int _count; + + Polygon() : _count(0) + { + _vertices.reserve(16); + } + }; +} + +#endif /* Spine_SkeletonBounds_h */ diff --git a/spine-cpp/spine-cpp/include/spine/SkeletonClipping.h b/spine-cpp/spine-cpp/include/spine/SkeletonClipping.h new file mode 100644 index 000000000..4effd5ede --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/SkeletonClipping.h @@ -0,0 +1,76 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_SkeletonClipping_h +#define Spine_SkeletonClipping_h + +#include +#include + +namespace Spine +{ + class Slot; + class ClippingAttachment; + + class SkeletonClipping + { + public: + SkeletonClipping(); + + int clipStart(Slot& slot, ClippingAttachment* clip); + + void clipEnd(Slot& slot); + + void clipEnd(); + + void clipTriangles(Vector& vertices, int verticesLength, Vector& triangles, int trianglesLength, Vector& uvs); + + bool isClipping(); + + private: + Triangulator _triangulator; + Vector _clippingPolygon; + Vector _clipOutput; + Vector _clippedVertices; + Vector _clippedTriangles; + Vector _clippedUVs; + Vector _scratch; + ClippingAttachment* _clipAttachment; + Vector< Vector > _clippingPolygons; + + /** Clips the input triangle against the convex, clockwise clipping area. If the triangle lies entirely within the clipping + * area, false is returned. The clipping area must duplicate the first vertex at the end of the vertices list. */ + bool clip(float x1, float y1, float x2, float y2, float x3, float y3, Vector& clippingArea, Vector& output); + + static void makeClockwise(Vector& polygon); + }; +} + +#endif /* Spine_SkeletonClipping_h */ diff --git a/spine-cpp/spine-cpp/include/spine/Slot.h b/spine-cpp/spine-cpp/include/spine/Slot.h index 26fd37f9a..dc55390e2 100644 --- a/spine-cpp/spine-cpp/include/spine/Slot.h +++ b/spine-cpp/spine-cpp/include/spine/Slot.h @@ -46,6 +46,7 @@ namespace Spine { friend class VertexAttachment; friend class Skeleton; + friend class SkeletonClipping; friend class AttachmentTimeline; friend class ColorTimeline; diff --git a/spine-cpp/spine-cpp/include/spine/Vector.h b/spine-cpp/spine-cpp/include/spine/Vector.h index ec25ecb84..8fc87c490 100644 --- a/spine-cpp/spine-cpp/include/spine/Vector.h +++ b/spine-cpp/spine-cpp/include/spine/Vector.h @@ -79,6 +79,19 @@ namespace Spine return false; } + int indexOf(const T& inValue) + { + for (size_t i = 0; i < _size; ++i) + { + if (_buffer[i] == inValue) + { + return static_cast(i); + } + } + + return -1; + } + void push_back(const T& inValue) { if (_size == _capacity) diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonBounds.cpp b/spine-cpp/spine-cpp/src/spine/SkeletonBounds.cpp new file mode 100644 index 000000000..f4b1a4ce3 --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/SkeletonBounds.cpp @@ -0,0 +1,267 @@ +/****************************************************************************** +* Spine Runtimes Software License v2.5 +* +* Copyright (c) 2013-2016, Esoteric Software +* All rights reserved. +* +* You are granted a perpetual, non-exclusive, non-sublicensable, and +* non-transferable license to use, install, execute, and perform the Spine +* Runtimes software and derivative works solely for personal or internal +* use. Without the written permission of Esoteric Software (see Section 2 of +* the Spine Software License Agreement), you may not (a) modify, translate, +* adapt, or develop new applications using the Spine Runtimes or otherwise +* create derivative works or improvements of the Spine Runtimes or (b) remove, +* delete, alter, or obscure any trademarks or any copyright, trademark, patent, +* or other intellectual property or proprietary rights notices on or in the +* Software, including any copy thereof. Redistributions in binary or source +* form must include this license and terms. +* +* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +#include + +#include +#include + +namespace Spine +{ + SkeletonBounds::SkeletonBounds() : _minX(0), _minY(0), _maxX(0), _maxY(0) + { + // Empty + } + + void SkeletonBounds::update(Skeleton& skeleton, bool updateAabb) + { +// Vector slots = skeleton._slots; +// int slotCount = slots.Count; +// +// _boundingBoxes.clear(); +// for (int i = 0, n = _polygons.size(); i < n; ++i) +// { +// _polygonPool.push_back(_polygons[i]); +// } +// +// _polygons.clear(); +// +// for (int i = 0; i < slotCount; i++) +// { +// Slot slot = slots.Items[i]; +// BoundingBoxAttachment boundingBox = slot.attachment as BoundingBoxAttachment; +// if (boundingBox == NULL) +// { +// continue; +// } +// _boundingBoxes.push_back(boundingBox); +// +// Polygon* polygonP = NULL; +// int poolCount = _polygonPool.size(); +// if (poolCount > 0) +// { +// polygonP = _polygonPool[poolCount - 1]; +// _polygonPool.erase(poolCount - 1); +// } +// else +// { +// polygonP = new Polygon(); +// } +// +// _polygons.push_back(polygonP); +// +// Polygon& polygon = *polygonP; +// +// int count = boundingBox.worldVerticesLength; +// polygon._count = count; +// if (polygon._vertices.size() < count) +// { +// polygon._vertices.reserve(count); +// } +// boundingBox.computeWorldVertices(slot, polygon._vertices); +// } +// +// if (updateAabb) +// { +// aabbCompute(); +// } +// else +// { +// minX = int.MinValue; +// minY = int.MinValue; +// maxX = int.MaxValue; +// maxY = int.MaxValue; +// } + } + + bool SkeletonBounds::aabbcontainsPoint(float x, float y) + { + return x >= _minX && x <= _maxX && y >= _minY && y <= _maxY; + } + + bool SkeletonBounds::aabbintersectsSegment(float x1, float y1, float x2, float y2) + { + float minX = _minX; + float minY = _minY; + float maxX = _maxX; + float maxY = _maxY; + + if ((x1 <= minX && x2 <= minX) || (y1 <= minY && y2 <= minY) || (x1 >= maxX && x2 >= maxX) || (y1 >= maxY && y2 >= maxY)) + { + return false; + } + + float m = (y2 - y1) / (x2 - x1); + float y = m * (minX - x1) + y1; + if (y > minY && y < maxY) + { + return true; + } + y = m * (maxX - x1) + y1; + if (y > minY && y < maxY) + { + return true; + } + float x = (minY - y1) / m + x1; + if (x > minX && x < maxX) + { + return true; + } + x = (maxY - y1) / m + x1; + if (x > minX && x < maxX) + { + return true; + } + return false; + } + + bool SkeletonBounds::aabbIntersectsSkeleton(SkeletonBounds bounds) + { + return _minX < bounds._maxX && _maxX > bounds._minX && _minY < bounds._maxY && _maxY > bounds._minY; + } + + bool SkeletonBounds::containsPoint(Polygon polygon, float x, float y) + { +// float[] vertices = polygon.Vertices; +// int nn = polygon.Count; +// +// int prevIndex = nn - 2; + bool inside = false; +// for (int ii = 0; ii < nn; ii += 2) +// { +// float vertexY = vertices[ii + 1]; +// float prevY = vertices[prevIndex + 1]; +// if ((vertexY < y && prevY >= y) || (prevY < y && vertexY >= y)) +// { +// float vertexX = vertices[ii]; +// if (vertexX + (y - vertexY) / (prevY - vertexY) * (vertices[prevIndex] - vertexX) < x) +// { +// inside = !inside; +// } +// } +// prevIndex = ii; +// } + return inside; + } + + BoundingBoxAttachment* SkeletonBounds::containsPoint(float x, float y) + { +// for (int i = 0, n = _polygons.size(); i < n; ++i) +// { +// if (containsPoint(_polygons[i], x, y)) +// { +// return _boundingBoxes[i]; +// } +// } + return NULL; + } + + BoundingBoxAttachment* SkeletonBounds::intersectsSegment(float x1, float y1, float x2, float y2) + { +// for (int i = 0, n = _polygons.size(); i < n; ++i) +// { +// if (intersectsSegment(_polygons[i], x1, y1, x2, y2)) +// { +// return _boundingBoxes[i]; +// } +// } + return NULL; + } + + bool SkeletonBounds::intersectsSegment(Polygon* polygon, float x1, float y1, float x2, float y2) + { +// Vector& vertices = polygon->_vertices; +// int nn = polygon.Count; +// +// float width12 = x1 - x2, height12 = y1 - y2; +// float det1 = x1 * y2 - y1 * x2; +// float x3 = vertices[nn - 2], y3 = vertices[nn - 1]; +// for (int ii = 0; ii < nn; ii += 2) +// { +// float x4 = vertices[ii], y4 = vertices[ii + 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 true; +// } +// } +// x3 = x4; +// y3 = y4; +// } + return false; + } + + Polygon* SkeletonBounds::getPolygon(BoundingBoxAttachment* attachment) + { + int index = _boundingBoxes.indexOf(attachment); + + return index == -1 ? NULL : _polygons[index]; + } + + float SkeletonBounds::getWidth() + { + return _maxX - _minX; + } + + float SkeletonBounds::getHeight() + { + return _maxY - _minY; + } + + void SkeletonBounds::aabbCompute() + { +// float minX = int.MaxValue, minY = int.MaxValue, maxX = int.MinValue, maxY = int.MinValue; +// for (int i = 0, n = _polygons.size(); i < n; i++) +// { +// Polygon* polygon = _polygons[i]; +// Vector& vertices = polygon->_vertices; +// for (int ii = 0, nn = polygon.Count; ii < nn; ii += 2) +// { +// float x = vertices[ii]; +// float y = vertices[ii + 1]; +// minX = Math.Min(minX, x); +// minY = Math.Min(minY, y); +// maxX = Math.Max(maxX, x); +// maxY = Math.Max(maxY, y); +// } +// } +// _minX = minX; +// _minY = minY; +// _maxX = maxX; +// _maxY = maxY; + } +} + diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonClipping.cpp b/spine-cpp/spine-cpp/src/spine/SkeletonClipping.cpp new file mode 100644 index 000000000..c3684bfb3 --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/SkeletonClipping.cpp @@ -0,0 +1,293 @@ +/****************************************************************************** +* Spine Runtimes Software License v2.5 +* +* Copyright (c) 2013-2016, Esoteric Software +* All rights reserved. +* +* You are granted a perpetual, non-exclusive, non-sublicensable, and +* non-transferable license to use, install, execute, and perform the Spine +* Runtimes software and derivative works solely for personal or internal +* use. Without the written permission of Esoteric Software (see Section 2 of +* the Spine Software License Agreement), you may not (a) modify, translate, +* adapt, or develop new applications using the Spine Runtimes or otherwise +* create derivative works or improvements of the Spine Runtimes or (b) remove, +* delete, alter, or obscure any trademarks or any copyright, trademark, patent, +* or other intellectual property or proprietary rights notices on or in the +* Software, including any copy thereof. Redistributions in binary or source +* form must include this license and terms. +* +* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +#include + +#include +#include + +namespace Spine +{ + SkeletonClipping::SkeletonClipping() + { + _clipOutput.reserve(128); + _clippedVertices.reserve(128); + _clippedTriangles.reserve(128); + _clippedUVs.reserve(128); + } + + int SkeletonClipping::clipStart(Slot& slot, ClippingAttachment* clip) + { +// if (clipAttachment != NULL) return 0; +// clipAttachment = clip; +// +// int n = clip.worldVerticesLength; +// float[] vertices = clippingPolygon.Resize(n).Items; +// clip.ComputeWorldVertices(slot, 0, n, vertices, 0, 2); +// makeClockwise(clippingPolygon); +// clippingPolygons = triangulator.Decompose(clippingPolygon, triangulator.Triangulate(clippingPolygon)); +// foreach (var polygon in clippingPolygons) { +// makeClockwise(polygon); +// polygon.push_back(polygon.Items[0]); +// polygon.push_back(polygon.Items[1]); +// } + return static_cast(_clippingPolygons.size()); + } + + void SkeletonClipping::clipEnd(Slot& slot) + { + if (_clipAttachment != NULL && _clipAttachment->_endSlot == &slot._data) + { + clipEnd(); + } + } + + void SkeletonClipping::clipEnd() + { + if (_clipAttachment == NULL) + { + return; + } + + _clipAttachment = NULL; + _clippingPolygons.clear(); + _clippedVertices.clear(); + _clippedTriangles.clear(); + _clippingPolygon.clear(); + } + + void SkeletonClipping::clipTriangles(Vector& vertices, int verticesLength, Vector& triangles, int trianglesLength, Vector& uvs) + { +// Vector clipOutput = _clipOutput, clippedVertices = _clippedVertices; +// var clippedTriangles = _clippedTriangles; +// var polygons = clippingPolygons.Items; +// int polygonsCount = clippingPolygons.Count; +// +// int index = 0; +// clippedVertices.Clear(); +// clippedUVs.Clear(); +// clippedTriangles.Clear(); +// //outer: +// for (int i = 0; i < trianglesLength; i += 3) { +// int vertexOffset = triangles[i] << 1; +// float x1 = vertices[vertexOffset], y1 = vertices[vertexOffset + 1]; +// float u1 = uvs[vertexOffset], v1 = uvs[vertexOffset + 1]; +// +// vertexOffset = triangles[i + 1] << 1; +// float x2 = vertices[vertexOffset], y2 = vertices[vertexOffset + 1]; +// float u2 = uvs[vertexOffset], v2 = uvs[vertexOffset + 1]; +// +// vertexOffset = triangles[i + 2] << 1; +// float x3 = vertices[vertexOffset], y3 = vertices[vertexOffset + 1]; +// float u3 = uvs[vertexOffset], v3 = uvs[vertexOffset + 1]; +// +// for (int p = 0; p < polygonsCount; p++) { +// int s = clippedVertices.Count; +// if (clip(x1, y1, x2, y2, x3, y3, polygons[p], clipOutput)) { +// int clipOutputLength = clipOutput.Count; +// if (clipOutputLength == 0) continue; +// float d0 = y2 - y3, d1 = x3 - x2, d2 = x1 - x3, d4 = y3 - y1; +// float d = 1 / (d0 * d2 + d1 * (y1 - y3)); +// +// int clipOutputCount = clipOutputLength >> 1; +// float[] clipOutputItems = clipOutput.Items; +// float[] clippedVerticesItems = clippedVertices.Resize(s + clipOutputCount * 2).Items; +// float[] clippedUVsItems = clippedUVs.Resize(s + clipOutputCount * 2).Items; +// for (int ii = 0; ii < clipOutputLength; ii += 2) { +// float x = clipOutputItems[ii], y = clipOutputItems[ii + 1]; +// clippedVerticesItems[s] = x; +// clippedVerticesItems[s + 1] = y; +// float c0 = x - x3, c1 = y - y3; +// float a = (d0 * c0 + d1 * c1) * d; +// float b = (d4 * c0 + d2 * c1) * d; +// float 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.Count; +// int[] clippedTrianglesItems = clippedTriangles.Resize(s + 3 * (clipOutputCount - 2)).Items; +// clipOutputCount--; +// for (int ii = 1; ii < clipOutputCount; ii++) { +// clippedTrianglesItems[s] = index; +// clippedTrianglesItems[s + 1] = index + ii; +// clippedTrianglesItems[s + 2] = index + ii + 1; +// s += 3; +// } +// index += clipOutputCount + 1; +// } +// else { +// float[] clippedVerticesItems = clippedVertices.Resize(s + 3 * 2).Items; +// float[] clippedUVsItems = clippedUVs.Resize(s + 3 * 2).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.Count; +// int[] clippedTrianglesItems = clippedTriangles.Resize(s + 3).Items; +// clippedTrianglesItems[s] = index; +// clippedTrianglesItems[s + 1] = index + 1; +// clippedTrianglesItems[s + 2] = index + 2; +// index += 3; +// break; //continue outer; +// } +// } +// } + } + + bool SkeletonClipping::isClipping() + { + return _clipAttachment != NULL; + } + + bool SkeletonClipping::clip(float x1, float y1, float x2, float y2, float x3, float y3, Vector& clippingArea, Vector& output) + { +// var originalOutput = output; + bool clipped = false; +// +// // Avoid copy at the end. +// Vector input = NULL; +// if (clippingArea.Count % 4 >= 2) { +// input = output; +// output = scratch; +// } else { +// input = scratch; +// } +// +// input.Clear(); +// input.push_back(x1); +// input.push_back(y1); +// input.push_back(x2); +// input.push_back(y2); +// input.push_back(x3); +// input.push_back(y3); +// input.push_back(x1); +// input.push_back(y1); +// output.Clear(); +// +// Vector clippingVertices = clippingArea.Items; +// int clippingVerticesLast = clippingArea.Count - 4; +// for (int i = 0; ; i += 2) { +// float edgeX = clippingVertices[i], edgeY = clippingVertices[i + 1]; +// float edgeX2 = clippingVertices[i + 2], edgeY2 = clippingVertices[i + 3]; +// float deltaX = edgeX - edgeX2, deltaY = edgeY - edgeY2; +// +// Vector inputVertices = input.Items; +// int inputVerticesLength = input.Count - 2, outputStart = output.Count; +// for (int ii = 0; ii < inputVerticesLength; ii += 2) { +// float inputX = inputVertices[ii], inputY = inputVertices[ii + 1]; +// float inputX2 = inputVertices[ii + 2], inputY2 = inputVertices[ii + 3]; +// bool side2 = deltaX * (inputY2 - edgeY2) - deltaY * (inputX2 - edgeX2) > 0; +// if (deltaX * (inputY - edgeY2) - deltaY * (inputX - edgeX2) > 0) { +// if (side2) { // v1 inside, v2 inside +// output.push_back(inputX2); +// output.push_back(inputY2); +// continue; +// } +// // v1 inside, v2 outside +// float c0 = inputY2 - inputY, c2 = inputX2 - inputX; +// float ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / (c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY)); +// output.push_back(edgeX + (edgeX2 - edgeX) * ua); +// output.push_back(edgeY + (edgeY2 - edgeY) * ua); +// } +// else if (side2) { // v1 outside, v2 inside +// float c0 = inputY2 - inputY, c2 = inputX2 - inputX; +// float ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / (c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY)); +// output.push_back(edgeX + (edgeX2 - edgeX) * ua); +// output.push_back(edgeY + (edgeY2 - edgeY) * ua); +// output.push_back(inputX2); +// output.push_back(inputY2); +// } +// clipped = true; +// } +// +// if (outputStart == output.Count) { // All edges outside. +// originalOutput.Clear(); +// return true; +// } +// +// output.push_back(output.Items[0]); +// output.push_back(output.Items[1]); +// +// if (i == clippingVerticesLast) break; +// var temp = output; +// output = input; +// output.Clear(); +// input = temp; +// } +// +// if (originalOutput != output) { +// originalOutput.Clear(); +// for (int i = 0, n = output.Count - 2; i < n; i++) { +// originalOutput.push_back(output.Items[i]); +// } +// } else { +// originalOutput.Resize(originalOutput.Count - 2); +// } + + return clipped; + } + + void SkeletonClipping::makeClockwise(Vector& polygon) + { +// Vector vertices = polygon.Items; +// int verticeslength = polygon.Count; +// +// float area = vertices[verticeslength - 2] * vertices[1] - vertices[0] * vertices[verticeslength - 1], p1x, p1y, p2x, p2y; +// for (int 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 (int 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; +// } + } +} From 8b5340042578ef611d40148559b4e580301601eb Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Sat, 25 Nov 2017 17:47:43 -0500 Subject: [PATCH 47/83] wip --- .../include/spine/AtlasAttachmentLoader.h | 2 +- .../spine-cpp/include/spine/Attachment.h | 4 +- .../include/spine/AttachmentLoader.h | 4 +- .../include/spine/AttachmentTimeline.h | 2 +- spine-cpp/spine-cpp/include/spine/Bone.h | 2 +- .../include/spine/BoundingBoxAttachment.h | 2 +- .../include/spine/ClippingAttachment.h | 2 +- .../spine-cpp/include/spine/ColorTimeline.h | 2 +- .../spine-cpp/include/spine/Constraint.h | 2 +- .../spine-cpp/include/spine/CurveTimeline.h | 2 +- .../spine-cpp/include/spine/DeformTimeline.h | 2 +- .../include/spine/DrawOrderTimeline.h | 2 +- .../spine-cpp/include/spine/EventTimeline.h | 2 +- .../spine-cpp/include/spine/IkConstraint.h | 2 +- .../include/spine/IkConstraintTimeline.h | 2 +- .../spine-cpp/include/spine/MeshAttachment.h | 2 +- .../spine-cpp/include/spine/PathAttachment.h | 2 +- .../spine-cpp/include/spine/PathConstraint.h | 2 +- .../include/spine/PathConstraintMixTimeline.h | 2 +- .../spine/PathConstraintPositionTimeline.h | 2 +- .../spine/PathConstraintSpacingTimeline.h | 2 +- .../spine-cpp/include/spine/PointAttachment.h | 2 +- .../include/spine/{SpineRTTI.h => RTTI.h} | 40 +-- .../include/spine/RegionAttachment.h | 2 +- .../spine-cpp/include/spine/RotateTimeline.h | 2 +- .../spine-cpp/include/spine/ScaleTimeline.h | 2 +- .../spine-cpp/include/spine/ShearTimeline.h | 2 +- spine-cpp/spine-cpp/include/spine/Skeleton.h | 3 + .../spine-cpp/include/spine/SkeletonBounds.h | 2 +- .../include/spine/SkeletonClipping.h | 2 +- spine-cpp/spine-cpp/include/spine/Slot.h | 1 + spine-cpp/spine-cpp/include/spine/Timeline.h | 4 +- .../include/spine/TransformConstraint.h | 2 +- .../spine/TransformConstraintTimeline.h | 2 +- .../include/spine/TranslateTimeline.h | 2 +- .../include/spine/TwoColorTimeline.h | 2 +- spine-cpp/spine-cpp/include/spine/Updatable.h | 4 +- .../include/spine/VertexAttachment.h | 2 +- .../src/spine/AtlasAttachmentLoader.cpp | 2 +- spine-cpp/spine-cpp/src/spine/Attachment.cpp | 2 +- .../spine-cpp/src/spine/AttachmentLoader.cpp | 2 +- .../src/spine/AttachmentTimeline.cpp | 2 +- spine-cpp/spine-cpp/src/spine/Bone.cpp | 2 +- .../src/spine/BoundingBoxAttachment.cpp | 2 +- .../src/spine/ClippingAttachment.cpp | 2 +- .../spine-cpp/src/spine/ColorTimeline.cpp | 2 +- spine-cpp/spine-cpp/src/spine/Constraint.cpp | 2 +- .../spine-cpp/src/spine/CurveTimeline.cpp | 2 +- .../spine-cpp/src/spine/DeformTimeline.cpp | 2 +- .../spine-cpp/src/spine/DrawOrderTimeline.cpp | 2 +- .../spine-cpp/src/spine/EventTimeline.cpp | 2 +- .../spine-cpp/src/spine/IkConstraint.cpp | 2 +- .../src/spine/IkConstraintTimeline.cpp | 2 +- .../spine-cpp/src/spine/MeshAttachment.cpp | 2 +- .../spine-cpp/src/spine/PathAttachment.cpp | 2 +- .../spine-cpp/src/spine/PathConstraint.cpp | 2 +- .../src/spine/PathConstraintMixTimeline.cpp | 2 +- .../spine/PathConstraintPositionTimeline.cpp | 2 +- .../spine/PathConstraintSpacingTimeline.cpp | 2 +- .../spine-cpp/src/spine/PointAttachment.cpp | 2 +- .../src/spine/{SpineRTTI.cpp => RTTI.cpp} | 16 +- .../spine-cpp/src/spine/RegionAttachment.cpp | 2 +- .../spine-cpp/src/spine/RotateTimeline.cpp | 2 +- .../spine-cpp/src/spine/ScaleTimeline.cpp | 2 +- .../spine-cpp/src/spine/ShearTimeline.cpp | 2 +- .../spine-cpp/src/spine/SkeletonBounds.cpp | 277 +++++++++--------- .../spine-cpp/src/spine/SkeletonClipping.cpp | 202 ++++++++----- spine-cpp/spine-cpp/src/spine/Timeline.cpp | 2 +- .../src/spine/TransformConstraint.cpp | 2 +- .../src/spine/TransformConstraintTimeline.cpp | 2 +- .../spine-cpp/src/spine/TranslateTimeline.cpp | 2 +- .../spine-cpp/src/spine/TwoColorTimeline.cpp | 2 +- spine-cpp/spine-cpp/src/spine/Updatable.cpp | 2 +- .../spine-cpp/src/spine/VertexAttachment.cpp | 2 +- 74 files changed, 371 insertions(+), 312 deletions(-) rename spine-cpp/spine-cpp/include/spine/{SpineRTTI.h => RTTI.h} (69%) rename spine-cpp/spine-cpp/src/spine/{SpineRTTI.cpp => RTTI.cpp} (79%) diff --git a/spine-cpp/spine-cpp/include/spine/AtlasAttachmentLoader.h b/spine-cpp/spine-cpp/include/spine/AtlasAttachmentLoader.h index 2805482af..440b5ac5b 100644 --- a/spine-cpp/spine-cpp/include/spine/AtlasAttachmentLoader.h +++ b/spine-cpp/spine-cpp/include/spine/AtlasAttachmentLoader.h @@ -46,7 +46,7 @@ namespace Spine /// class AtlasAttachmentLoader : public AttachmentLoader { - SPINE_RTTI_DECL; + RTTI_DECL; public: AtlasAttachmentLoader(Vector& inAtlasArray); diff --git a/spine-cpp/spine-cpp/include/spine/Attachment.h b/spine-cpp/spine-cpp/include/spine/Attachment.h index 48c9e2cc1..fdf5a1a58 100644 --- a/spine-cpp/spine-cpp/include/spine/Attachment.h +++ b/spine-cpp/spine-cpp/include/spine/Attachment.h @@ -31,7 +31,7 @@ #ifndef Spine_Attachment_h #define Spine_Attachment_h -#include +#include #include @@ -39,7 +39,7 @@ namespace Spine { class Attachment { - SPINE_RTTI_DECL; + RTTI_DECL; public: Attachment(std::string name); diff --git a/spine-cpp/spine-cpp/include/spine/AttachmentLoader.h b/spine-cpp/spine-cpp/include/spine/AttachmentLoader.h index e194e019b..91f59705e 100644 --- a/spine-cpp/spine-cpp/include/spine/AttachmentLoader.h +++ b/spine-cpp/spine-cpp/include/spine/AttachmentLoader.h @@ -31,7 +31,7 @@ #ifndef Spine_AttachmentLoader_h #define Spine_AttachmentLoader_h -#include +#include #include @@ -47,7 +47,7 @@ namespace Spine class AttachmentLoader { - SPINE_RTTI_DECL; + RTTI_DECL; AttachmentLoader(); diff --git a/spine-cpp/spine-cpp/include/spine/AttachmentTimeline.h b/spine-cpp/spine-cpp/include/spine/AttachmentTimeline.h index b43daf303..07460f6d3 100644 --- a/spine-cpp/spine-cpp/include/spine/AttachmentTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/AttachmentTimeline.h @@ -46,7 +46,7 @@ namespace Spine class AttachmentTimeline : public Timeline { - SPINE_RTTI_DECL; + RTTI_DECL; public: AttachmentTimeline(int frameCount); diff --git a/spine-cpp/spine-cpp/include/spine/Bone.h b/spine-cpp/spine-cpp/include/spine/Bone.h index 7ae7813e9..9900324be 100644 --- a/spine-cpp/spine-cpp/include/spine/Bone.h +++ b/spine-cpp/spine-cpp/include/spine/Bone.h @@ -47,7 +47,7 @@ namespace Spine /// constraint or application code modifies the world transform after it was computed from the local transform. class Bone : public Updatable { - SPINE_RTTI_DECL; + RTTI_DECL; friend class RotateTimeline; friend class IkConstraint; diff --git a/spine-cpp/spine-cpp/include/spine/BoundingBoxAttachment.h b/spine-cpp/spine-cpp/include/spine/BoundingBoxAttachment.h index 1ad9f13d0..996af9f94 100644 --- a/spine-cpp/spine-cpp/include/spine/BoundingBoxAttachment.h +++ b/spine-cpp/spine-cpp/include/spine/BoundingBoxAttachment.h @@ -38,7 +38,7 @@ namespace Spine /// Attachment that has a polygon for bounds checking. class BoundingBoxAttachment : public VertexAttachment { - SPINE_RTTI_DECL; + RTTI_DECL; BoundingBoxAttachment(std::string name); }; diff --git a/spine-cpp/spine-cpp/include/spine/ClippingAttachment.h b/spine-cpp/spine-cpp/include/spine/ClippingAttachment.h index 6b117c374..f0f913ecc 100644 --- a/spine-cpp/spine-cpp/include/spine/ClippingAttachment.h +++ b/spine-cpp/spine-cpp/include/spine/ClippingAttachment.h @@ -39,7 +39,7 @@ namespace Spine class ClippingAttachment : public VertexAttachment { - SPINE_RTTI_DECL; + RTTI_DECL; friend class SkeletonClipping; diff --git a/spine-cpp/spine-cpp/include/spine/ColorTimeline.h b/spine-cpp/spine-cpp/include/spine/ColorTimeline.h index 268e619c2..178e4f13e 100644 --- a/spine-cpp/spine-cpp/include/spine/ColorTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/ColorTimeline.h @@ -37,7 +37,7 @@ namespace Spine { class ColorTimeline : public CurveTimeline { - SPINE_RTTI_DECL; + RTTI_DECL; public: static const int ENTRIES; diff --git a/spine-cpp/spine-cpp/include/spine/Constraint.h b/spine-cpp/spine-cpp/include/spine/Constraint.h index 18d45cece..aa0122c34 100644 --- a/spine-cpp/spine-cpp/include/spine/Constraint.h +++ b/spine-cpp/spine-cpp/include/spine/Constraint.h @@ -38,7 +38,7 @@ namespace Spine /// The interface for all constraints. class Constraint : public Updatable { - SPINE_RTTI_DECL; + RTTI_DECL; public: Constraint(); diff --git a/spine-cpp/spine-cpp/include/spine/CurveTimeline.h b/spine-cpp/spine-cpp/include/spine/CurveTimeline.h index 38f489b26..a5222e31e 100644 --- a/spine-cpp/spine-cpp/include/spine/CurveTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/CurveTimeline.h @@ -41,7 +41,7 @@ namespace Spine /// Base class for frames that use an interpolation bezier curve. class CurveTimeline : public Timeline { - SPINE_RTTI_DECL; + RTTI_DECL; public: CurveTimeline(int frameCount); diff --git a/spine-cpp/spine-cpp/include/spine/DeformTimeline.h b/spine-cpp/spine-cpp/include/spine/DeformTimeline.h index faf3f848e..1500b77e5 100644 --- a/spine-cpp/spine-cpp/include/spine/DeformTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/DeformTimeline.h @@ -39,7 +39,7 @@ namespace Spine class DeformTimeline : public CurveTimeline { - SPINE_RTTI_DECL; + RTTI_DECL; public: DeformTimeline(int frameCount); diff --git a/spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h b/spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h index ac1ea0623..60ab70a08 100644 --- a/spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h @@ -37,7 +37,7 @@ namespace Spine { class DrawOrderTimeline : public Timeline { - SPINE_RTTI_DECL; + RTTI_DECL; public: DrawOrderTimeline(int frameCount); diff --git a/spine-cpp/spine-cpp/include/spine/EventTimeline.h b/spine-cpp/spine-cpp/include/spine/EventTimeline.h index 4a844cbd7..e88d50b1a 100644 --- a/spine-cpp/spine-cpp/include/spine/EventTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/EventTimeline.h @@ -37,7 +37,7 @@ namespace Spine { class EventTimeline : public Timeline { - SPINE_RTTI_DECL; + RTTI_DECL; virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); diff --git a/spine-cpp/spine-cpp/include/spine/IkConstraint.h b/spine-cpp/spine-cpp/include/spine/IkConstraint.h index b40f06867..c09f8c7cd 100644 --- a/spine-cpp/spine-cpp/include/spine/IkConstraint.h +++ b/spine-cpp/spine-cpp/include/spine/IkConstraint.h @@ -45,7 +45,7 @@ namespace Spine { friend class Skeleton; - SPINE_RTTI_DECL; + RTTI_DECL; public: /// Adjusts the bone rotation so the tip is as close to the target position as possible. The target is specified diff --git a/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h b/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h index 7b44c8f04..6ab6d35c6 100644 --- a/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h @@ -37,7 +37,7 @@ namespace Spine { class IkConstraintTimeline : public CurveTimeline { - SPINE_RTTI_DECL; + RTTI_DECL; public: static const int ENTRIES; diff --git a/spine-cpp/spine-cpp/include/spine/MeshAttachment.h b/spine-cpp/spine-cpp/include/spine/MeshAttachment.h index c29e93fb4..c4c25a7c5 100644 --- a/spine-cpp/spine-cpp/include/spine/MeshAttachment.h +++ b/spine-cpp/spine-cpp/include/spine/MeshAttachment.h @@ -42,7 +42,7 @@ namespace Spine /// Attachment that displays a texture region using a mesh. class MeshAttachment : public VertexAttachment { - SPINE_RTTI_DECL; + RTTI_DECL; friend class AtlasAttachmentLoader; diff --git a/spine-cpp/spine-cpp/include/spine/PathAttachment.h b/spine-cpp/spine-cpp/include/spine/PathAttachment.h index a261daad8..6f0e53993 100644 --- a/spine-cpp/spine-cpp/include/spine/PathAttachment.h +++ b/spine-cpp/spine-cpp/include/spine/PathAttachment.h @@ -37,7 +37,7 @@ namespace Spine { class PathAttachment : public VertexAttachment { - SPINE_RTTI_DECL; + RTTI_DECL; public: PathAttachment(std::string name); diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraint.h b/spine-cpp/spine-cpp/include/spine/PathConstraint.h index e7cf63721..7f6440c48 100644 --- a/spine-cpp/spine-cpp/include/spine/PathConstraint.h +++ b/spine-cpp/spine-cpp/include/spine/PathConstraint.h @@ -47,7 +47,7 @@ namespace Spine { friend class Skeleton; - SPINE_RTTI_DECL; + RTTI_DECL; public: PathConstraint(PathConstraintData& data, Skeleton& skeleton); diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h b/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h index 030ae5fb3..65d286470 100644 --- a/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h @@ -37,7 +37,7 @@ namespace Spine { class PathConstraintMixTimeline : public CurveTimeline { - SPINE_RTTI_DECL; + RTTI_DECL; public: virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h b/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h index 12c0cffa0..72734d4d8 100644 --- a/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h @@ -37,7 +37,7 @@ namespace Spine { class PathConstraintPositionTimeline : public CurveTimeline { - SPINE_RTTI_DECL; + RTTI_DECL; public: static const int ENTRIES; diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h b/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h index 35c974bff..a0fa2b9fb 100644 --- a/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h @@ -37,7 +37,7 @@ namespace Spine { class PathConstraintSpacingTimeline : public PathConstraintPositionTimeline { - SPINE_RTTI_DECL; + RTTI_DECL; public: PathConstraintSpacingTimeline(int frameCount); diff --git a/spine-cpp/spine-cpp/include/spine/PointAttachment.h b/spine-cpp/spine-cpp/include/spine/PointAttachment.h index cb9385f2b..6738021a7 100644 --- a/spine-cpp/spine-cpp/include/spine/PointAttachment.h +++ b/spine-cpp/spine-cpp/include/spine/PointAttachment.h @@ -46,7 +46,7 @@ namespace Spine /// class PointAttachment : public Attachment { - SPINE_RTTI_DECL; + RTTI_DECL; public: PointAttachment(std::string name); diff --git a/spine-cpp/spine-cpp/include/spine/SpineRTTI.h b/spine-cpp/spine-cpp/include/spine/RTTI.h similarity index 69% rename from spine-cpp/spine-cpp/include/spine/SpineRTTI.h rename to spine-cpp/spine-cpp/include/spine/RTTI.h index 4ed9806bc..79f413efa 100644 --- a/spine-cpp/spine-cpp/include/spine/SpineRTTI.h +++ b/spine-cpp/spine-cpp/include/spine/RTTI.h @@ -28,48 +28,48 @@ * POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -#ifndef Spine_SPINE_RTTI_h -#define Spine_SPINE_RTTI_h +#ifndef Spine_RTTI_h +#define Spine_RTTI_h #include namespace Spine { - class SPINE_RTTI + class RTTI { public: - SPINE_RTTI(const std::string& className); + RTTI(const std::string& className); - SPINE_RTTI(const std::string& className, const SPINE_RTTI& baseSPINE_RTTI); + RTTI(const std::string& className, const RTTI& baseRTTI); const std::string& getClassName() const; - bool isExactly(const SPINE_RTTI& rtti) const; + bool isExactly(const RTTI& rtti) const; - bool derivesFrom(const SPINE_RTTI& rtti) const; + bool derivesFrom(const RTTI& rtti) const; private: // Prevent copying - SPINE_RTTI(const SPINE_RTTI& obj); - SPINE_RTTI& operator=(const SPINE_RTTI& obj); + RTTI(const RTTI& obj); + RTTI& operator=(const RTTI& obj); const std::string m_className; - const SPINE_RTTI *m_pBaseSPINE_RTTI; + const RTTI *m_pBaseRTTI; }; } -#define SPINE_RTTI_DECL \ +#define RTTI_DECL \ public: \ -static const Spine::SPINE_RTTI rtti; \ -virtual const Spine::SPINE_RTTI& getRTTI(); +static const Spine::RTTI rtti; \ +virtual const Spine::RTTI& getRTTI(); -#define SPINE_RTTI_IMPL_NOPARENT(name) \ -const Spine::SPINE_RTTI name::rtti(#name); \ -const Spine::SPINE_RTTI& name::getRTTI() { return rtti; } +#define RTTI_IMPL_NOPARENT(name) \ +const Spine::RTTI name::rtti(#name); \ +const Spine::RTTI& name::getRTTI() { return rtti; } -#define SPINE_RTTI_IMPL(name,parent) \ -const Spine::SPINE_RTTI name::rtti(#name, parent::rtti); \ -const Spine::SPINE_RTTI& name::getRTTI() { return rtti; } +#define RTTI_IMPL(name,parent) \ +const Spine::RTTI name::rtti(#name, parent::rtti); \ +const Spine::RTTI& name::getRTTI() { return rtti; } -#endif /* Spine_SPINE_RTTI_h */ +#endif /* Spine_RTTI_h */ diff --git a/spine-cpp/spine-cpp/include/spine/RegionAttachment.h b/spine-cpp/spine-cpp/include/spine/RegionAttachment.h index 780c5b8ce..5fd982652 100644 --- a/spine-cpp/spine-cpp/include/spine/RegionAttachment.h +++ b/spine-cpp/spine-cpp/include/spine/RegionAttachment.h @@ -46,7 +46,7 @@ namespace Spine /// Attachment that displays a texture region. class RegionAttachment : public Attachment { - SPINE_RTTI_DECL; + RTTI_DECL; friend class AtlasAttachmentLoader; diff --git a/spine-cpp/spine-cpp/include/spine/RotateTimeline.h b/spine-cpp/spine-cpp/include/spine/RotateTimeline.h index ff1fb3ae7..dcc013b71 100644 --- a/spine-cpp/spine-cpp/include/spine/RotateTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/RotateTimeline.h @@ -37,7 +37,7 @@ namespace Spine { class RotateTimeline : public CurveTimeline { - SPINE_RTTI_DECL; + RTTI_DECL; public: static const int ENTRIES = 2; diff --git a/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h b/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h index dd6db7e65..d0ce306d3 100644 --- a/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h @@ -37,7 +37,7 @@ namespace Spine { class ScaleTimeline : public TranslateTimeline { - SPINE_RTTI_DECL; + RTTI_DECL; virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); diff --git a/spine-cpp/spine-cpp/include/spine/ShearTimeline.h b/spine-cpp/spine-cpp/include/spine/ShearTimeline.h index 74a440876..1916fd8f4 100644 --- a/spine-cpp/spine-cpp/include/spine/ShearTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/ShearTimeline.h @@ -37,7 +37,7 @@ namespace Spine { class ShearTimeline : public TranslateTimeline { - SPINE_RTTI_DECL; + RTTI_DECL; public: virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); diff --git a/spine-cpp/spine-cpp/include/spine/Skeleton.h b/spine-cpp/spine-cpp/include/spine/Skeleton.h index 03ff33d5c..a7bd84ce9 100644 --- a/spine-cpp/spine-cpp/include/spine/Skeleton.h +++ b/spine-cpp/spine-cpp/include/spine/Skeleton.h @@ -51,6 +51,9 @@ namespace Spine class Skeleton { + friend class SkeletonBounds; + friend class SkeletonClipping; + friend class AttachmentTimeline; friend class ColorTimeline; friend class DeformTimeline; diff --git a/spine-cpp/spine-cpp/include/spine/SkeletonBounds.h b/spine-cpp/spine-cpp/include/spine/SkeletonBounds.h index 432342a1f..424bc2a7f 100644 --- a/spine-cpp/spine-cpp/include/spine/SkeletonBounds.h +++ b/spine-cpp/spine-cpp/include/spine/SkeletonBounds.h @@ -69,7 +69,7 @@ namespace Spine bool aabbIntersectsSkeleton(SkeletonBounds bounds); /// Returns true if the polygon contains the point. - bool containsPoint(Polygon polygon, float x, float y); + bool containsPoint(Polygon* polygon, float x, float y); /// Returns the first bounding box attachment that contains the point, or NULL. When doing many checks, it is usually more /// efficient to only call this method if {@link #aabbcontainsPoint(float, float)} returns true. diff --git a/spine-cpp/spine-cpp/include/spine/SkeletonClipping.h b/spine-cpp/spine-cpp/include/spine/SkeletonClipping.h index 4effd5ede..7a5cde4cd 100644 --- a/spine-cpp/spine-cpp/include/spine/SkeletonClipping.h +++ b/spine-cpp/spine-cpp/include/spine/SkeletonClipping.h @@ -63,7 +63,7 @@ namespace Spine Vector _clippedUVs; Vector _scratch; ClippingAttachment* _clipAttachment; - Vector< Vector > _clippingPolygons; + Vector< Vector* > _clippingPolygons; /** Clips the input triangle against the convex, clockwise clipping area. If the triangle lies entirely within the clipping * area, false is returned. The clipping area must duplicate the first vertex at the end of the vertices list. */ diff --git a/spine-cpp/spine-cpp/include/spine/Slot.h b/spine-cpp/spine-cpp/include/spine/Slot.h index dc55390e2..780db4425 100644 --- a/spine-cpp/spine-cpp/include/spine/Slot.h +++ b/spine-cpp/spine-cpp/include/spine/Slot.h @@ -46,6 +46,7 @@ namespace Spine { friend class VertexAttachment; friend class Skeleton; + friend class SkeletonBounds; friend class SkeletonClipping; friend class AttachmentTimeline; diff --git a/spine-cpp/spine-cpp/include/spine/Timeline.h b/spine-cpp/spine-cpp/include/spine/Timeline.h index 0160e371a..b00db7b28 100644 --- a/spine-cpp/spine-cpp/include/spine/Timeline.h +++ b/spine-cpp/spine-cpp/include/spine/Timeline.h @@ -31,7 +31,7 @@ #ifndef Spine_Timeline_h #define Spine_Timeline_h -#include +#include #include #include #include @@ -43,7 +43,7 @@ namespace Spine class Timeline { - SPINE_RTTI_DECL; + RTTI_DECL; public: Timeline(); diff --git a/spine-cpp/spine-cpp/include/spine/TransformConstraint.h b/spine-cpp/spine-cpp/include/spine/TransformConstraint.h index c2036d4ab..262c3a210 100644 --- a/spine-cpp/spine-cpp/include/spine/TransformConstraint.h +++ b/spine-cpp/spine-cpp/include/spine/TransformConstraint.h @@ -45,7 +45,7 @@ namespace Spine { friend class Skeleton; - SPINE_RTTI_DECL; + RTTI_DECL; public: TransformConstraint(TransformConstraintData& data, Skeleton& skeleton); diff --git a/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h b/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h index 6990e1aa3..e4486d197 100644 --- a/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h @@ -37,7 +37,7 @@ namespace Spine { class TransformConstraintTimeline : public CurveTimeline { - SPINE_RTTI_DECL; + RTTI_DECL; public: static const int ENTRIES; diff --git a/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h b/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h index cd48f40b4..6faac140a 100644 --- a/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h @@ -40,7 +40,7 @@ namespace Spine { class TranslateTimeline : public CurveTimeline { - SPINE_RTTI_DECL; + RTTI_DECL; public: virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); diff --git a/spine-cpp/spine-cpp/include/spine/TwoColorTimeline.h b/spine-cpp/spine-cpp/include/spine/TwoColorTimeline.h index df61adeb9..d70375d34 100644 --- a/spine-cpp/spine-cpp/include/spine/TwoColorTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/TwoColorTimeline.h @@ -37,7 +37,7 @@ namespace Spine { class TwoColorTimeline : public CurveTimeline { - SPINE_RTTI_DECL; + RTTI_DECL; public: virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); diff --git a/spine-cpp/spine-cpp/include/spine/Updatable.h b/spine-cpp/spine-cpp/include/spine/Updatable.h index cb36e863e..fac634191 100644 --- a/spine-cpp/spine-cpp/include/spine/Updatable.h +++ b/spine-cpp/spine-cpp/include/spine/Updatable.h @@ -31,13 +31,13 @@ #ifndef Spine_Updatable_h #define Spine_Updatable_h -#include +#include namespace Spine { class Updatable { - SPINE_RTTI_DECL; + RTTI_DECL; public: Updatable(); diff --git a/spine-cpp/spine-cpp/include/spine/VertexAttachment.h b/spine-cpp/spine-cpp/include/spine/VertexAttachment.h index 935601df3..33a6fed53 100644 --- a/spine-cpp/spine-cpp/include/spine/VertexAttachment.h +++ b/spine-cpp/spine-cpp/include/spine/VertexAttachment.h @@ -42,7 +42,7 @@ namespace Spine /// An attachment with vertices that are transformed by one or more bones and can be deformed by a slot's vertices. class VertexAttachment : public Attachment { - SPINE_RTTI_DECL; + RTTI_DECL; friend class DeformTimeline; diff --git a/spine-cpp/spine-cpp/src/spine/AtlasAttachmentLoader.cpp b/spine-cpp/spine-cpp/src/spine/AtlasAttachmentLoader.cpp index bea6e30e7..0d03bc337 100644 --- a/spine-cpp/spine-cpp/src/spine/AtlasAttachmentLoader.cpp +++ b/spine-cpp/spine-cpp/src/spine/AtlasAttachmentLoader.cpp @@ -42,7 +42,7 @@ namespace Spine { - SPINE_RTTI_IMPL(AtlasAttachmentLoader, AttachmentLoader); + RTTI_IMPL(AtlasAttachmentLoader, AttachmentLoader); AtlasAttachmentLoader::AtlasAttachmentLoader(Vector& inAtlasArray) : AttachmentLoader(), _atlasArray(inAtlasArray) { diff --git a/spine-cpp/spine-cpp/src/spine/Attachment.cpp b/spine-cpp/spine-cpp/src/spine/Attachment.cpp index 93107e041..74a734f27 100644 --- a/spine-cpp/spine-cpp/src/spine/Attachment.cpp +++ b/spine-cpp/spine-cpp/src/spine/Attachment.cpp @@ -34,7 +34,7 @@ namespace Spine { - SPINE_RTTI_IMPL_NOPARENT(Attachment); + RTTI_IMPL_NOPARENT(Attachment); Attachment::Attachment(std::string name) : _name(name) { diff --git a/spine-cpp/spine-cpp/src/spine/AttachmentLoader.cpp b/spine-cpp/spine-cpp/src/spine/AttachmentLoader.cpp index af55271f2..93e848ab7 100644 --- a/spine-cpp/spine-cpp/src/spine/AttachmentLoader.cpp +++ b/spine-cpp/spine-cpp/src/spine/AttachmentLoader.cpp @@ -40,7 +40,7 @@ namespace Spine { - SPINE_RTTI_IMPL_NOPARENT(AttachmentLoader); + RTTI_IMPL_NOPARENT(AttachmentLoader); AttachmentLoader::AttachmentLoader() { diff --git a/spine-cpp/spine-cpp/src/spine/AttachmentTimeline.cpp b/spine-cpp/spine-cpp/src/spine/AttachmentTimeline.cpp index 0fe3f9114..c923a4508 100644 --- a/spine-cpp/spine-cpp/src/spine/AttachmentTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/AttachmentTimeline.cpp @@ -40,7 +40,7 @@ namespace Spine { - SPINE_RTTI_IMPL(AttachmentTimeline, Timeline); + RTTI_IMPL(AttachmentTimeline, Timeline); AttachmentTimeline::AttachmentTimeline(int frameCount) : Timeline(), _slotIndex(0) { diff --git a/spine-cpp/spine-cpp/src/spine/Bone.cpp b/spine-cpp/spine-cpp/src/spine/Bone.cpp index 7ad89853c..71e119c95 100644 --- a/spine-cpp/spine-cpp/src/spine/Bone.cpp +++ b/spine-cpp/spine-cpp/src/spine/Bone.cpp @@ -38,7 +38,7 @@ namespace Spine { - SPINE_RTTI_IMPL(Bone, Updatable); + RTTI_IMPL(Bone, Updatable); bool Bone::yDown = false; diff --git a/spine-cpp/spine-cpp/src/spine/BoundingBoxAttachment.cpp b/spine-cpp/spine-cpp/src/spine/BoundingBoxAttachment.cpp index df7a70934..ffa7f7355 100644 --- a/spine-cpp/spine-cpp/src/spine/BoundingBoxAttachment.cpp +++ b/spine-cpp/spine-cpp/src/spine/BoundingBoxAttachment.cpp @@ -32,7 +32,7 @@ namespace Spine { - SPINE_RTTI_IMPL(BoundingBoxAttachment, VertexAttachment); + RTTI_IMPL(BoundingBoxAttachment, VertexAttachment); BoundingBoxAttachment::BoundingBoxAttachment(std::string name) : VertexAttachment(name) { diff --git a/spine-cpp/spine-cpp/src/spine/ClippingAttachment.cpp b/spine-cpp/spine-cpp/src/spine/ClippingAttachment.cpp index 1ad21ba86..c87de561c 100644 --- a/spine-cpp/spine-cpp/src/spine/ClippingAttachment.cpp +++ b/spine-cpp/spine-cpp/src/spine/ClippingAttachment.cpp @@ -34,7 +34,7 @@ namespace Spine { - SPINE_RTTI_IMPL(ClippingAttachment, VertexAttachment); + RTTI_IMPL(ClippingAttachment, VertexAttachment); ClippingAttachment::ClippingAttachment(std::string name) : VertexAttachment(name) { diff --git a/spine-cpp/spine-cpp/src/spine/ColorTimeline.cpp b/spine-cpp/spine-cpp/src/spine/ColorTimeline.cpp index 6968fbe75..e7d49f9aa 100644 --- a/spine-cpp/spine-cpp/src/spine/ColorTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/ColorTimeline.cpp @@ -40,7 +40,7 @@ namespace Spine { - SPINE_RTTI_IMPL(ColorTimeline, CurveTimeline); + RTTI_IMPL(ColorTimeline, CurveTimeline); const int ColorTimeline::ENTRIES = 5; const int ColorTimeline::PREV_TIME = -5; diff --git a/spine-cpp/spine-cpp/src/spine/Constraint.cpp b/spine-cpp/spine-cpp/src/spine/Constraint.cpp index 206c93b5e..bad9d1a0b 100644 --- a/spine-cpp/spine-cpp/src/spine/Constraint.cpp +++ b/spine-cpp/spine-cpp/src/spine/Constraint.cpp @@ -32,7 +32,7 @@ namespace Spine { - SPINE_RTTI_IMPL(Constraint, Updatable); + RTTI_IMPL(Constraint, Updatable); Constraint::Constraint() { diff --git a/spine-cpp/spine-cpp/src/spine/CurveTimeline.cpp b/spine-cpp/spine-cpp/src/spine/CurveTimeline.cpp index 5d0e58401..ea4047eb2 100644 --- a/spine-cpp/spine-cpp/src/spine/CurveTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/CurveTimeline.cpp @@ -34,7 +34,7 @@ namespace Spine { - SPINE_RTTI_IMPL(CurveTimeline, Timeline); + RTTI_IMPL(CurveTimeline, Timeline); const float CurveTimeline::LINEAR = 0; const float CurveTimeline::STEPPED = 1; diff --git a/spine-cpp/spine-cpp/src/spine/DeformTimeline.cpp b/spine-cpp/spine-cpp/src/spine/DeformTimeline.cpp index b9fb2c5ef..ac2a981fe 100644 --- a/spine-cpp/spine-cpp/src/spine/DeformTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/DeformTimeline.cpp @@ -42,7 +42,7 @@ namespace Spine { - SPINE_RTTI_IMPL(DeformTimeline, CurveTimeline); + RTTI_IMPL(DeformTimeline, CurveTimeline); DeformTimeline::DeformTimeline(int frameCount) : CurveTimeline(frameCount), _slotIndex(0), _attachment(NULL) { diff --git a/spine-cpp/spine-cpp/src/spine/DrawOrderTimeline.cpp b/spine-cpp/spine-cpp/src/spine/DrawOrderTimeline.cpp index bb84bcdf5..6561db060 100644 --- a/spine-cpp/spine-cpp/src/spine/DrawOrderTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/DrawOrderTimeline.cpp @@ -40,7 +40,7 @@ namespace Spine { - SPINE_RTTI_IMPL(DrawOrderTimeline, Timeline); + RTTI_IMPL(DrawOrderTimeline, Timeline); DrawOrderTimeline::DrawOrderTimeline(int frameCount) : Timeline() { diff --git a/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp b/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp index bcd78be19..2e6f69b03 100644 --- a/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp @@ -40,7 +40,7 @@ namespace Spine { - SPINE_RTTI_IMPL(EventTimeline, Timeline); + RTTI_IMPL(EventTimeline, Timeline); void EventTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) { diff --git a/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp b/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp index f0838c6af..0359854d8 100644 --- a/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp +++ b/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp @@ -39,7 +39,7 @@ namespace Spine { - SPINE_RTTI_IMPL(IkConstraint, Constraint); + RTTI_IMPL(IkConstraint, Constraint); void IkConstraint::apply(Bone& bone, float targetX, float targetY, float alpha) { diff --git a/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp b/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp index a2886f8f3..a8c89f715 100644 --- a/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp @@ -40,7 +40,7 @@ namespace Spine { - SPINE_RTTI_IMPL(IkConstraintTimeline, CurveTimeline); + RTTI_IMPL(IkConstraintTimeline, CurveTimeline); const int IkConstraintTimeline::ENTRIES = 3; const int IkConstraintTimeline::PREV_TIME = -3; diff --git a/spine-cpp/spine-cpp/src/spine/MeshAttachment.cpp b/spine-cpp/spine-cpp/src/spine/MeshAttachment.cpp index 09793ad9a..6d928a6c3 100644 --- a/spine-cpp/spine-cpp/src/spine/MeshAttachment.cpp +++ b/spine-cpp/spine-cpp/src/spine/MeshAttachment.cpp @@ -32,7 +32,7 @@ namespace Spine { - SPINE_RTTI_IMPL(MeshAttachment, VertexAttachment); + RTTI_IMPL(MeshAttachment, VertexAttachment); MeshAttachment::MeshAttachment(std::string name) : VertexAttachment(name), _regionOffsetX(0), diff --git a/spine-cpp/spine-cpp/src/spine/PathAttachment.cpp b/spine-cpp/spine-cpp/src/spine/PathAttachment.cpp index f997e67a0..54bd9337b 100644 --- a/spine-cpp/spine-cpp/src/spine/PathAttachment.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathAttachment.cpp @@ -32,7 +32,7 @@ namespace Spine { - SPINE_RTTI_IMPL(PathAttachment, VertexAttachment); + RTTI_IMPL(PathAttachment, VertexAttachment); PathAttachment::PathAttachment(std::string name) : VertexAttachment(name) { diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp b/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp index 7dbef8438..6075736c3 100644 --- a/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp @@ -45,7 +45,7 @@ namespace Spine { - SPINE_RTTI_IMPL(PathConstraint, Constraint); + RTTI_IMPL(PathConstraint, Constraint); const float PathConstraint::EPSILON = 0.00001f; const int PathConstraint::NONE = -1; diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp b/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp index 65c4c2998..772eb4e4f 100644 --- a/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp @@ -40,7 +40,7 @@ namespace Spine { - SPINE_RTTI_IMPL(PathConstraintMixTimeline, CurveTimeline); + RTTI_IMPL(PathConstraintMixTimeline, CurveTimeline); void PathConstraintMixTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) { diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp b/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp index 4e6f70d66..2a1d2949b 100644 --- a/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp @@ -40,7 +40,7 @@ namespace Spine { - SPINE_RTTI_IMPL(PathConstraintPositionTimeline, CurveTimeline); + RTTI_IMPL(PathConstraintPositionTimeline, CurveTimeline); const int PathConstraintPositionTimeline::ENTRIES = 2; const int PathConstraintPositionTimeline::PREV_TIME = -2; diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp b/spine-cpp/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp index 17c5ac2aa..474930d7e 100644 --- a/spine-cpp/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp @@ -40,7 +40,7 @@ namespace Spine { - SPINE_RTTI_IMPL(PathConstraintSpacingTimeline, PathConstraintPositionTimeline); + RTTI_IMPL(PathConstraintSpacingTimeline, PathConstraintPositionTimeline); PathConstraintSpacingTimeline::PathConstraintSpacingTimeline(int frameCount) : PathConstraintPositionTimeline(frameCount) { diff --git a/spine-cpp/spine-cpp/src/spine/PointAttachment.cpp b/spine-cpp/spine-cpp/src/spine/PointAttachment.cpp index b6b93c2ec..d309c8d48 100644 --- a/spine-cpp/spine-cpp/src/spine/PointAttachment.cpp +++ b/spine-cpp/spine-cpp/src/spine/PointAttachment.cpp @@ -36,7 +36,7 @@ namespace Spine { - SPINE_RTTI_IMPL(PointAttachment, Attachment); + RTTI_IMPL(PointAttachment, Attachment); PointAttachment::PointAttachment(std::string name) : Attachment(name) { diff --git a/spine-cpp/spine-cpp/src/spine/SpineRTTI.cpp b/spine-cpp/spine-cpp/src/spine/RTTI.cpp similarity index 79% rename from spine-cpp/spine-cpp/src/spine/SpineRTTI.cpp rename to spine-cpp/spine-cpp/src/spine/RTTI.cpp index e5fc40ec4..9d271f894 100644 --- a/spine-cpp/spine-cpp/src/spine/SpineRTTI.cpp +++ b/spine-cpp/spine-cpp/src/spine/RTTI.cpp @@ -28,33 +28,33 @@ * POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ -#include +#include namespace Spine { - SPINE_RTTI::SPINE_RTTI(const std::string& className) : m_className(className), m_pBaseSPINE_RTTI(NULL) + RTTI::RTTI(const std::string& className) : m_className(className), m_pBaseRTTI(NULL) { // Empty } - SPINE_RTTI::SPINE_RTTI(const std::string& className, const SPINE_RTTI& baseSPINE_RTTI) : m_className(className), m_pBaseSPINE_RTTI(&baseSPINE_RTTI) + RTTI::RTTI(const std::string& className, const RTTI& baseRTTI) : m_className(className), m_pBaseRTTI(&baseRTTI) { // Empty } - const std::string& SPINE_RTTI::getClassName() const + const std::string& RTTI::getClassName() const { return m_className; } - bool SPINE_RTTI::isExactly(const SPINE_RTTI& rtti) const + bool RTTI::isExactly(const RTTI& rtti) const { return (this == &rtti); } - bool SPINE_RTTI::derivesFrom(const SPINE_RTTI& rtti) const + bool RTTI::derivesFrom(const RTTI& rtti) const { - const SPINE_RTTI * pCompare = this; + const RTTI * pCompare = this; while (pCompare) { @@ -63,7 +63,7 @@ namespace Spine return true; } - pCompare = pCompare->m_pBaseSPINE_RTTI; + pCompare = pCompare->m_pBaseRTTI; } return false; diff --git a/spine-cpp/spine-cpp/src/spine/RegionAttachment.cpp b/spine-cpp/spine-cpp/src/spine/RegionAttachment.cpp index 0ebbb8a41..310a4619b 100644 --- a/spine-cpp/spine-cpp/src/spine/RegionAttachment.cpp +++ b/spine-cpp/spine-cpp/src/spine/RegionAttachment.cpp @@ -38,7 +38,7 @@ namespace Spine { - SPINE_RTTI_IMPL(RegionAttachment, Attachment); + RTTI_IMPL(RegionAttachment, Attachment); const int RegionAttachment::BLX = 0; const int RegionAttachment::BLY = 1; diff --git a/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp b/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp index 448d88134..acfeb7db1 100644 --- a/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp @@ -40,7 +40,7 @@ namespace Spine { - SPINE_RTTI_IMPL(RotateTimeline, CurveTimeline); + RTTI_IMPL(RotateTimeline, CurveTimeline); RotateTimeline::RotateTimeline(int frameCount) : CurveTimeline(frameCount), _boneIndex(0) { diff --git a/spine-cpp/spine-cpp/src/spine/ScaleTimeline.cpp b/spine-cpp/spine-cpp/src/spine/ScaleTimeline.cpp index 3151759eb..f431f589c 100644 --- a/spine-cpp/spine-cpp/src/spine/ScaleTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/ScaleTimeline.cpp @@ -40,7 +40,7 @@ namespace Spine { - SPINE_RTTI_IMPL(ScaleTimeline, TranslateTimeline); + RTTI_IMPL(ScaleTimeline, TranslateTimeline); void ScaleTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) { diff --git a/spine-cpp/spine-cpp/src/spine/ShearTimeline.cpp b/spine-cpp/spine-cpp/src/spine/ShearTimeline.cpp index 132967ea8..1f114c972 100644 --- a/spine-cpp/spine-cpp/src/spine/ShearTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/ShearTimeline.cpp @@ -40,7 +40,7 @@ namespace Spine { - SPINE_RTTI_IMPL(ShearTimeline, TranslateTimeline); + RTTI_IMPL(ShearTimeline, TranslateTimeline); void ShearTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) { diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonBounds.cpp b/spine-cpp/spine-cpp/src/spine/SkeletonBounds.cpp index f4b1a4ce3..217c75deb 100644 --- a/spine-cpp/spine-cpp/src/spine/SkeletonBounds.cpp +++ b/spine-cpp/spine-cpp/src/spine/SkeletonBounds.cpp @@ -33,6 +33,9 @@ #include #include +#include +#include + namespace Spine { SkeletonBounds::SkeletonBounds() : _minX(0), _minY(0), _maxX(0), _maxY(0) @@ -42,63 +45,65 @@ namespace Spine void SkeletonBounds::update(Skeleton& skeleton, bool updateAabb) { -// Vector slots = skeleton._slots; -// int slotCount = slots.Count; -// -// _boundingBoxes.clear(); -// for (int i = 0, n = _polygons.size(); i < n; ++i) -// { -// _polygonPool.push_back(_polygons[i]); -// } -// -// _polygons.clear(); -// -// for (int i = 0; i < slotCount; i++) -// { -// Slot slot = slots.Items[i]; -// BoundingBoxAttachment boundingBox = slot.attachment as BoundingBoxAttachment; -// if (boundingBox == NULL) -// { -// continue; -// } -// _boundingBoxes.push_back(boundingBox); -// -// Polygon* polygonP = NULL; -// int poolCount = _polygonPool.size(); -// if (poolCount > 0) -// { -// polygonP = _polygonPool[poolCount - 1]; -// _polygonPool.erase(poolCount - 1); -// } -// else -// { -// polygonP = new Polygon(); -// } -// -// _polygons.push_back(polygonP); -// -// Polygon& polygon = *polygonP; -// -// int count = boundingBox.worldVerticesLength; -// polygon._count = count; -// if (polygon._vertices.size() < count) -// { -// polygon._vertices.reserve(count); -// } -// boundingBox.computeWorldVertices(slot, polygon._vertices); -// } -// -// if (updateAabb) -// { -// aabbCompute(); -// } -// else -// { -// minX = int.MinValue; -// minY = int.MinValue; -// maxX = int.MaxValue; -// maxY = int.MaxValue; -// } + Vector& slots = skeleton._slots; + int slotCount = static_cast(slots.size()); + + _boundingBoxes.clear(); + for (int i = 0, n = static_cast(_polygons.size()); i < n; ++i) + { + _polygonPool.push_back(_polygons[i]); + } + + _polygons.clear(); + + for (int i = 0; i < slotCount; i++) + { + Slot* slot = slots[i]; + Attachment* attachment = slot->_attachment; + if (attachment == NULL || !attachment->getRTTI().derivesFrom(BoundingBoxAttachment::rtti)) + { + continue; + } + BoundingBoxAttachment* boundingBox = static_cast(attachment); + _boundingBoxes.push_back(boundingBox); + + Polygon* polygonP = NULL; + int poolCount = static_cast(_polygonPool.size()); + if (poolCount > 0) + { + polygonP = _polygonPool[poolCount - 1]; + _polygonPool.erase(poolCount - 1); + } + else + { + Polygon* polygonP = MALLOC(Polygon, 1); + new (polygonP) Polygon(); + } + + _polygons.push_back(polygonP); + + Polygon& polygon = *polygonP; + + int count = boundingBox->getWorldVerticesLength(); + polygon._count = count; + if (polygon._vertices.size() < count) + { + polygon._vertices.reserve(count); + } + boundingBox->computeWorldVertices(*slot, polygon._vertices); + } + + if (updateAabb) + { + aabbCompute(); + } + else + { + _minX = std::numeric_limits::min(); + _minY = std::numeric_limits::min(); + _maxX = std::numeric_limits::max(); + _maxY = std::numeric_limits::max(); + } } bool SkeletonBounds::aabbcontainsPoint(float x, float y) @@ -147,80 +152,82 @@ namespace Spine return _minX < bounds._maxX && _maxX > bounds._minX && _minY < bounds._maxY && _maxY > bounds._minY; } - bool SkeletonBounds::containsPoint(Polygon polygon, float x, float y) + bool SkeletonBounds::containsPoint(Polygon* polygon, float x, float y) { -// float[] vertices = polygon.Vertices; -// int nn = polygon.Count; -// -// int prevIndex = nn - 2; + Vector& vertices = polygon->_vertices; + int nn = polygon->_count; + + int prevIndex = nn - 2; bool inside = false; -// for (int ii = 0; ii < nn; ii += 2) -// { -// float vertexY = vertices[ii + 1]; -// float prevY = vertices[prevIndex + 1]; -// if ((vertexY < y && prevY >= y) || (prevY < y && vertexY >= y)) -// { -// float vertexX = vertices[ii]; -// if (vertexX + (y - vertexY) / (prevY - vertexY) * (vertices[prevIndex] - vertexX) < x) -// { -// inside = !inside; -// } -// } -// prevIndex = ii; -// } + for (int ii = 0; ii < nn; ii += 2) + { + float vertexY = vertices[ii + 1]; + float prevY = vertices[prevIndex + 1]; + if ((vertexY < y && prevY >= y) || (prevY < y && vertexY >= y)) + { + float vertexX = vertices[ii]; + if (vertexX + (y - vertexY) / (prevY - vertexY) * (vertices[prevIndex] - vertexX) < x) + { + inside = !inside; + } + } + prevIndex = ii; + } return inside; } BoundingBoxAttachment* SkeletonBounds::containsPoint(float x, float y) { -// for (int i = 0, n = _polygons.size(); i < n; ++i) -// { -// if (containsPoint(_polygons[i], x, y)) -// { -// return _boundingBoxes[i]; -// } -// } + for (int i = 0, n = static_cast(_polygons.size()); i < n; ++i) + { + if (containsPoint(_polygons[i], x, y)) + { + return _boundingBoxes[i]; + } + } + return NULL; } BoundingBoxAttachment* SkeletonBounds::intersectsSegment(float x1, float y1, float x2, float y2) { -// for (int i = 0, n = _polygons.size(); i < n; ++i) -// { -// if (intersectsSegment(_polygons[i], x1, y1, x2, y2)) -// { -// return _boundingBoxes[i]; -// } -// } + for (int i = 0, n = static_cast(_polygons.size()); i < n; ++i) + { + if (intersectsSegment(_polygons[i], x1, y1, x2, y2)) + { + return _boundingBoxes[i]; + } + } return NULL; } bool SkeletonBounds::intersectsSegment(Polygon* polygon, float x1, float y1, float x2, float y2) { -// Vector& vertices = polygon->_vertices; -// int nn = polygon.Count; -// -// float width12 = x1 - x2, height12 = y1 - y2; -// float det1 = x1 * y2 - y1 * x2; -// float x3 = vertices[nn - 2], y3 = vertices[nn - 1]; -// for (int ii = 0; ii < nn; ii += 2) -// { -// float x4 = vertices[ii], y4 = vertices[ii + 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 true; -// } -// } -// x3 = x4; -// y3 = y4; -// } + Vector& vertices = polygon->_vertices; + int nn = polygon->_count; + + float width12 = x1 - x2, height12 = y1 - y2; + float det1 = x1 * y2 - y1 * x2; + float x3 = vertices[nn - 2], y3 = vertices[nn - 1]; + for (int ii = 0; ii < nn; ii += 2) + { + float x4 = vertices[ii], y4 = vertices[ii + 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 true; + } + } + x3 = x4; + y3 = y4; + } + return false; } @@ -243,25 +250,29 @@ namespace Spine void SkeletonBounds::aabbCompute() { -// float minX = int.MaxValue, minY = int.MaxValue, maxX = int.MinValue, maxY = int.MinValue; -// for (int i = 0, n = _polygons.size(); i < n; i++) -// { -// Polygon* polygon = _polygons[i]; -// Vector& vertices = polygon->_vertices; -// for (int ii = 0, nn = polygon.Count; ii < nn; ii += 2) -// { -// float x = vertices[ii]; -// float y = vertices[ii + 1]; -// minX = Math.Min(minX, x); -// minY = Math.Min(minY, y); -// maxX = Math.Max(maxX, x); -// maxY = Math.Max(maxY, y); -// } -// } -// _minX = minX; -// _minY = minY; -// _maxX = maxX; -// _maxY = maxY; + float minX = std::numeric_limits::min(); + float minY = std::numeric_limits::min(); + float maxX = std::numeric_limits::max(); + float maxY = std::numeric_limits::max(); + + for (int i = 0, n = static_cast(_polygons.size()); i < n; ++i) + { + Polygon* polygon = _polygons[i]; + Vector& vertices = polygon->_vertices; + for (int ii = 0, nn = polygon->_count; ii < nn; ii += 2) + { + float x = vertices[ii]; + float y = vertices[ii + 1]; + minX = MIN(minX, x); + minY = MIN(minY, y); + maxX = MAX(maxX, x); + maxY = MAX(maxY, y); + } + } + _minX = minX; + _minY = minY; + _maxX = maxX; + _maxY = maxY; } } diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonClipping.cpp b/spine-cpp/spine-cpp/src/spine/SkeletonClipping.cpp index c3684bfb3..5132b8b88 100644 --- a/spine-cpp/spine-cpp/src/spine/SkeletonClipping.cpp +++ b/spine-cpp/spine-cpp/src/spine/SkeletonClipping.cpp @@ -45,19 +45,28 @@ namespace Spine int SkeletonClipping::clipStart(Slot& slot, ClippingAttachment* clip) { -// if (clipAttachment != NULL) return 0; -// clipAttachment = clip; -// -// int n = clip.worldVerticesLength; -// float[] vertices = clippingPolygon.Resize(n).Items; -// clip.ComputeWorldVertices(slot, 0, n, vertices, 0, 2); -// makeClockwise(clippingPolygon); -// clippingPolygons = triangulator.Decompose(clippingPolygon, triangulator.Triangulate(clippingPolygon)); -// foreach (var polygon in clippingPolygons) { -// makeClockwise(polygon); -// polygon.push_back(polygon.Items[0]); -// polygon.push_back(polygon.Items[1]); -// } + if (_clipAttachment != NULL) + { + return 0; + } + + _clipAttachment = clip; + + int n = clip->getWorldVerticesLength(); + _clippingPolygon.reserve(n); + clip->computeWorldVertices(slot, 0, n, _clippingPolygon, 0, 2); + makeClockwise(_clippingPolygon); + _clippingPolygons = _triangulator.decompose(_clippingPolygon, _triangulator.triangulate(_clippingPolygon)); + + for (Vector** i = _clippingPolygons.begin(); i != _clippingPolygons.end(); ++i) + { + Vector* polygonP = (*i); + Vector& polygon = *polygonP; + makeClockwise(polygon); + polygon.push_back(polygon[0]); + polygon.push_back(polygon[1]); + } + return static_cast(_clippingPolygons.size()); } @@ -85,34 +94,41 @@ namespace Spine void SkeletonClipping::clipTriangles(Vector& vertices, int verticesLength, Vector& triangles, int trianglesLength, Vector& uvs) { -// Vector clipOutput = _clipOutput, clippedVertices = _clippedVertices; -// var clippedTriangles = _clippedTriangles; -// var polygons = clippingPolygons.Items; -// int polygonsCount = clippingPolygons.Count; -// -// int index = 0; -// clippedVertices.Clear(); -// clippedUVs.Clear(); -// clippedTriangles.Clear(); -// //outer: -// for (int i = 0; i < trianglesLength; i += 3) { -// int vertexOffset = triangles[i] << 1; -// float x1 = vertices[vertexOffset], y1 = vertices[vertexOffset + 1]; -// float u1 = uvs[vertexOffset], v1 = uvs[vertexOffset + 1]; -// -// vertexOffset = triangles[i + 1] << 1; -// float x2 = vertices[vertexOffset], y2 = vertices[vertexOffset + 1]; -// float u2 = uvs[vertexOffset], v2 = uvs[vertexOffset + 1]; -// -// vertexOffset = triangles[i + 2] << 1; -// float x3 = vertices[vertexOffset], y3 = vertices[vertexOffset + 1]; -// float u3 = uvs[vertexOffset], v3 = uvs[vertexOffset + 1]; -// -// for (int p = 0; p < polygonsCount; p++) { -// int s = clippedVertices.Count; -// if (clip(x1, y1, x2, y2, x3, y3, polygons[p], clipOutput)) { + Vector& clipOutput = _clipOutput, clippedVertices = _clippedVertices; + Vector& clippedTriangles = _clippedTriangles; + Vector< Vector* >& polygons = _clippingPolygons; + int polygonsCount = _clippingPolygons.size(); + + int index = 0; + clippedVertices.clear(); + _clippedUVs.clear(); + clippedTriangles.clear(); + + //outer: + for (int i = 0; i < trianglesLength; i += 3) + { + int vertexOffset = triangles[i] << 1; + float x1 = vertices[vertexOffset], y1 = vertices[vertexOffset + 1]; + float u1 = uvs[vertexOffset], v1 = uvs[vertexOffset + 1]; + + vertexOffset = triangles[i + 1] << 1; + float x2 = vertices[vertexOffset], y2 = vertices[vertexOffset + 1]; + float u2 = uvs[vertexOffset], v2 = uvs[vertexOffset + 1]; + + vertexOffset = triangles[i + 2] << 1; + float x3 = vertices[vertexOffset], y3 = vertices[vertexOffset + 1]; + float u3 = uvs[vertexOffset], v3 = uvs[vertexOffset + 1]; + + for (int p = 0; p < polygonsCount; p++) + { + int s = clippedVertices.size(); +// if (clip(x1, y1, x2, y2, x3, y3, polygons[p], clipOutput)) +// { // int clipOutputLength = clipOutput.Count; -// if (clipOutputLength == 0) continue; +// if (clipOutputLength == 0) +// { +// continue; +// } // float d0 = y2 - y3, d1 = x3 - x2, d2 = x1 - x3, d4 = y3 - y1; // float d = 1 / (d0 * d2 + d1 * (y1 - y3)); // @@ -120,7 +136,8 @@ namespace Spine // float[] clipOutputItems = clipOutput.Items; // float[] clippedVerticesItems = clippedVertices.Resize(s + clipOutputCount * 2).Items; // float[] clippedUVsItems = clippedUVs.Resize(s + clipOutputCount * 2).Items; -// for (int ii = 0; ii < clipOutputLength; ii += 2) { +// for (int ii = 0; ii < clipOutputLength; ii += 2) +// { // float x = clipOutputItems[ii], y = clipOutputItems[ii + 1]; // clippedVerticesItems[s] = x; // clippedVerticesItems[s + 1] = y; @@ -136,7 +153,8 @@ namespace Spine // s = clippedTriangles.Count; // int[] clippedTrianglesItems = clippedTriangles.Resize(s + 3 * (clipOutputCount - 2)).Items; // clipOutputCount--; -// for (int ii = 1; ii < clipOutputCount; ii++) { +// for (int ii = 1; ii < clipOutputCount; ii++) +// { // clippedTrianglesItems[s] = index; // clippedTrianglesItems[s + 1] = index + ii; // clippedTrianglesItems[s + 2] = index + ii + 1; @@ -144,7 +162,8 @@ namespace Spine // } // index += clipOutputCount + 1; // } -// else { +// else +// { // float[] clippedVerticesItems = clippedVertices.Resize(s + 3 * 2).Items; // float[] clippedUVsItems = clippedUVs.Resize(s + 3 * 2).Items; // clippedVerticesItems[s] = x1; @@ -169,8 +188,8 @@ namespace Spine // index += 3; // break; //continue outer; // } -// } -// } + } + } } bool SkeletonClipping::isClipping() @@ -180,15 +199,18 @@ namespace Spine bool SkeletonClipping::clip(float x1, float y1, float x2, float y2, float x3, float y3, Vector& clippingArea, Vector& output) { -// var originalOutput = output; + Vector originalOutput = output; bool clipped = false; // // // Avoid copy at the end. // Vector input = NULL; -// if (clippingArea.Count % 4 >= 2) { +// if (clippingArea.Count % 4 >= 2) +// { // input = output; // output = scratch; -// } else { +// } +// else +// { // input = scratch; // } // @@ -205,19 +227,24 @@ namespace Spine // // Vector clippingVertices = clippingArea.Items; // int clippingVerticesLast = clippingArea.Count - 4; -// for (int i = 0; ; i += 2) { +// for (int i = 0; ; i += 2) +// { // float edgeX = clippingVertices[i], edgeY = clippingVertices[i + 1]; // float edgeX2 = clippingVertices[i + 2], edgeY2 = clippingVertices[i + 3]; // float deltaX = edgeX - edgeX2, deltaY = edgeY - edgeY2; // // Vector inputVertices = input.Items; // int inputVerticesLength = input.Count - 2, outputStart = output.Count; -// for (int ii = 0; ii < inputVerticesLength; ii += 2) { +// for (int ii = 0; ii < inputVerticesLength; ii += 2) +// { // float inputX = inputVertices[ii], inputY = inputVertices[ii + 1]; // float inputX2 = inputVertices[ii + 2], inputY2 = inputVertices[ii + 3]; // bool side2 = deltaX * (inputY2 - edgeY2) - deltaY * (inputX2 - edgeX2) > 0; -// if (deltaX * (inputY - edgeY2) - deltaY * (inputX - edgeX2) > 0) { -// if (side2) { // v1 inside, v2 inside +// if (deltaX * (inputY - edgeY2) - deltaY * (inputX - edgeX2) > 0) +// { +// if (side2) +// { +// // v1 inside, v2 inside // output.push_back(inputX2); // output.push_back(inputY2); // continue; @@ -228,7 +255,9 @@ namespace Spine // output.push_back(edgeX + (edgeX2 - edgeX) * ua); // output.push_back(edgeY + (edgeY2 - edgeY) * ua); // } -// else if (side2) { // v1 outside, v2 inside +// else if (side2) +// { +// // v1 outside, v2 inside // float c0 = inputY2 - inputY, c2 = inputX2 - inputX; // float ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / (c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY)); // output.push_back(edgeX + (edgeX2 - edgeX) * ua); @@ -239,7 +268,9 @@ namespace Spine // clipped = true; // } // -// if (outputStart == output.Count) { // All edges outside. +// if (outputStart == output.Count) +// { +// // All edges outside. // originalOutput.Clear(); // return true; // } @@ -247,19 +278,26 @@ namespace Spine // output.push_back(output.Items[0]); // output.push_back(output.Items[1]); // -// if (i == clippingVerticesLast) break; +// if (i == clippingVerticesLast) +// { +// break; +// } // var temp = output; // output = input; // output.Clear(); // input = temp; // } // -// if (originalOutput != output) { +// if (originalOutput != output) +// { // originalOutput.Clear(); -// for (int i = 0, n = output.Count - 2; i < n; i++) { +// for (int i = 0, n = output.Count - 2; i < n; i++) +// { // originalOutput.push_back(output.Items[i]); // } -// } else { +// } +// else +// { // originalOutput.Resize(originalOutput.Count - 2); // } @@ -268,26 +306,32 @@ namespace Spine void SkeletonClipping::makeClockwise(Vector& polygon) { -// Vector vertices = polygon.Items; -// int verticeslength = polygon.Count; -// -// float area = vertices[verticeslength - 2] * vertices[1] - vertices[0] * vertices[verticeslength - 1], p1x, p1y, p2x, p2y; -// for (int 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 (int 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 verticeslength = static_cast(polygon.size()); + + float area = polygon[verticeslength - 2] * polygon[1] - polygon[0] * polygon[verticeslength - 1], p1x, p1y, p2x, p2y; + + for (int i = 0, n = verticeslength - 3; i < n; i += 2) + { + p1x = polygon[i]; + p1y = polygon[i + 1]; + p2x = polygon[i + 2]; + p2y = polygon[i + 3]; + area += p1x * p2y - p2x * p1y; + } + + if (area < 0) + { + return; + } + + for (int i = 0, lastX = verticeslength - 2, n = verticeslength >> 1; i < n; i += 2) + { + float x = polygon[i], y = polygon[i + 1]; + int other = lastX - i; + polygon[i] = polygon[other]; + polygon[i + 1] = polygon[other + 1]; + polygon[other] = x; + polygon[other + 1] = y; + } } } diff --git a/spine-cpp/spine-cpp/src/spine/Timeline.cpp b/spine-cpp/spine-cpp/src/spine/Timeline.cpp index ddd0d5fe6..6dac2f210 100644 --- a/spine-cpp/spine-cpp/src/spine/Timeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/Timeline.cpp @@ -35,7 +35,7 @@ namespace Spine { - SPINE_RTTI_IMPL_NOPARENT(Timeline); + RTTI_IMPL_NOPARENT(Timeline); Timeline::Timeline() { diff --git a/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp b/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp index 166713279..3f970e502 100644 --- a/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp +++ b/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp @@ -39,7 +39,7 @@ namespace Spine { - SPINE_RTTI_IMPL(TransformConstraint, Constraint); + RTTI_IMPL(TransformConstraint, Constraint); TransformConstraint::TransformConstraint(TransformConstraintData& data, Skeleton& skeleton) : Constraint(), _data(data), diff --git a/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp b/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp index 33335732f..01914067f 100644 --- a/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp @@ -40,7 +40,7 @@ namespace Spine { - SPINE_RTTI_IMPL(TransformConstraintTimeline, CurveTimeline); + RTTI_IMPL(TransformConstraintTimeline, CurveTimeline); const int TransformConstraintTimeline::ENTRIES = 5; const int TransformConstraintTimeline::PREV_TIME = -5; diff --git a/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp b/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp index 05afdad26..f7ae4abbe 100644 --- a/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp @@ -40,7 +40,7 @@ namespace Spine { - SPINE_RTTI_IMPL(TranslateTimeline, CurveTimeline); + RTTI_IMPL(TranslateTimeline, CurveTimeline); void TranslateTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) { diff --git a/spine-cpp/spine-cpp/src/spine/TwoColorTimeline.cpp b/spine-cpp/spine-cpp/src/spine/TwoColorTimeline.cpp index 1062f481a..9f092c488 100644 --- a/spine-cpp/spine-cpp/src/spine/TwoColorTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/TwoColorTimeline.cpp @@ -40,7 +40,7 @@ namespace Spine { - SPINE_RTTI_IMPL(TwoColorTimeline, CurveTimeline); + RTTI_IMPL(TwoColorTimeline, CurveTimeline); void TwoColorTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) { diff --git a/spine-cpp/spine-cpp/src/spine/Updatable.cpp b/spine-cpp/spine-cpp/src/spine/Updatable.cpp index e40d01725..598955a9a 100644 --- a/spine-cpp/spine-cpp/src/spine/Updatable.cpp +++ b/spine-cpp/spine-cpp/src/spine/Updatable.cpp @@ -32,7 +32,7 @@ namespace Spine { - SPINE_RTTI_IMPL_NOPARENT(Updatable); + RTTI_IMPL_NOPARENT(Updatable); Updatable::Updatable() { diff --git a/spine-cpp/spine-cpp/src/spine/VertexAttachment.cpp b/spine-cpp/spine-cpp/src/spine/VertexAttachment.cpp index 9968a77ce..6cfa69a34 100644 --- a/spine-cpp/spine-cpp/src/spine/VertexAttachment.cpp +++ b/spine-cpp/spine-cpp/src/spine/VertexAttachment.cpp @@ -37,7 +37,7 @@ namespace Spine { - SPINE_RTTI_IMPL(VertexAttachment, Attachment); + RTTI_IMPL(VertexAttachment, Attachment); VertexAttachment::VertexAttachment(std::string name) : Attachment(name), _worldVerticesLength(0), _id(getNextID()) { From 3038a90cc594784815a00b033965ffba995ec05c Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Sun, 26 Nov 2017 11:46:06 -0500 Subject: [PATCH 48/83] Timelines are done. --- spine-cpp/spine-cpp/include/spine/Bone.h | 3 + spine-cpp/spine-cpp/include/spine/BoneData.h | 3 + .../spine-cpp/include/spine/EventTimeline.h | 61 +--- .../spine-cpp/include/spine/IkConstraint.h | 1 + .../include/spine/IkConstraintData.h | 1 + .../include/spine/IkConstraintTimeline.h | 60 +--- .../spine-cpp/include/spine/PathConstraint.h | 3 + .../include/spine/PathConstraintData.h | 3 + .../include/spine/PathConstraintMixTimeline.h | 75 +--- .../spine/PathConstraintPositionTimeline.h | 52 +-- .../spine/PathConstraintSpacingTimeline.h | 35 -- .../spine-cpp/include/spine/ScaleTimeline.h | 66 +--- .../spine-cpp/include/spine/ShearTimeline.h | 48 +-- .../include/spine/TransformConstraint.h | 1 + .../include/spine/TransformConstraintData.h | 1 + .../spine/TransformConstraintTimeline.h | 84 +---- .../include/spine/TranslateTimeline.h | 90 +---- .../include/spine/TwoColorTimeline.h | 151 +------- spine-cpp/spine-cpp/include/spine/Vector.h | 62 +++- .../spine-cpp/src/spine/EventTimeline.cpp | 67 +++- .../src/spine/IkConstraintTimeline.cpp | 70 +++- .../src/spine/PathConstraintMixTimeline.cpp | 74 +++- .../spine/PathConstraintPositionTimeline.cpp | 54 ++- .../spine/PathConstraintSpacingTimeline.cpp | 46 ++- .../spine-cpp/src/spine/ScaleTimeline.cpp | 82 ++++- .../spine-cpp/src/spine/ShearTimeline.cpp | 60 +++- .../spine-cpp/src/spine/SkeletonClipping.cpp | 338 +++++++++--------- .../src/spine/TransformConstraintTimeline.cpp | 86 ++++- .../spine-cpp/src/spine/TranslateTimeline.cpp | 74 +++- .../spine-cpp/src/spine/TwoColorTimeline.cpp | 158 +++++++- 30 files changed, 1074 insertions(+), 835 deletions(-) diff --git a/spine-cpp/spine-cpp/include/spine/Bone.h b/spine-cpp/spine-cpp/include/spine/Bone.h index 9900324be..a2bdae9e3 100644 --- a/spine-cpp/spine-cpp/include/spine/Bone.h +++ b/spine-cpp/spine-cpp/include/spine/Bone.h @@ -57,6 +57,9 @@ namespace Spine friend class Skeleton; friend class RegionAttachment; friend class PointAttachment; + friend class ScaleTimeline; + friend class ShearTimeline; + friend class TranslateTimeline; public: static void setYDown(bool inValue); diff --git a/spine-cpp/spine-cpp/include/spine/BoneData.h b/spine-cpp/spine-cpp/include/spine/BoneData.h index e5d82ef31..2d2ce3da6 100644 --- a/spine-cpp/spine-cpp/include/spine/BoneData.h +++ b/spine-cpp/spine-cpp/include/spine/BoneData.h @@ -40,6 +40,9 @@ namespace Spine class BoneData { friend class RotateTimeline; + friend class ScaleTimeline; + friend class ShearTimeline; + friend class TranslateTimeline; public: BoneData(int index, std::string name, BoneData* parent = NULL); diff --git a/spine-cpp/spine-cpp/include/spine/EventTimeline.h b/spine-cpp/spine-cpp/include/spine/EventTimeline.h index e88d50b1a..b1512327e 100644 --- a/spine-cpp/spine-cpp/include/spine/EventTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/EventTimeline.h @@ -39,56 +39,25 @@ namespace Spine { RTTI_DECL; + public: + EventTimeline(int frameCount); + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); virtual int getPropertyId(); -// internal float[] frames; -// private Event[] events; -// -// public float[] Frames { return frames; } set { frames = inValue; } // time, ... -// public Event[] Events { return events; } set { events = inValue; } -// public int FrameCount { return frames.Length; } -// -// -// public EventTimeline (int frameCount) { -// frames = new float[frameCount]; -// events = new Event[frameCount]; -// } -// -// /// Sets the time and value of the specified keyframe. -// public void setFrame (int frameIndex, Event e) { -// frames[frameIndex] = e.Time; -// events[frameIndex] = e; -// } -// -// /// Fires events for frames > lastTime and <= time. -// public void Apply (Skeleton skeleton, float lastTime, float time, Vector firedEvents, float alpha, MixPose pose, MixDirection direction) { -// if (firedEvents == NULL) return; -// float[] frames = _frames; -// int frameCount = frames.Length; -// -// if (lastTime > time) { // Fire events after last time for looped animations. -// Apply(skeleton, lastTime, int.MaxValue, firedEvents, alpha, pose, direction); -// lastTime = -1f; -// } else if (lastTime >= frames[frameCount - 1]) // Last time is after last frame. -// return; -// if (time < frames[0]) return; // Time is before first frame. -// -// int frame; -// if (lastTime < frames[0]) -// frame = 0; -// else { -// frame = Animation::binarySearch(frames, lastTime); -// float frameTime = frames[frame]; -// while (frame > 0) { // Fire multiple events with the same frame. -// if (frames[frame - 1] != frameTime) break; -// frame--; -// } -// } -// for (; frame < frameCount && time >= frames[frame]; frame++) -// firedEvents.push_back(events[frame]); -// } + /// Sets the time and value of the specified keyframe. + void setFrame(int frameIndex, Event* e); + + Vector getFrames(); + void setFrames(Vector& inValue); + Vector& getEvents(); + void setEvents(Vector& inValue); + int getFrameCount(); + + private: + Vector _frames; + Vector _events; }; } diff --git a/spine-cpp/spine-cpp/include/spine/IkConstraint.h b/spine-cpp/spine-cpp/include/spine/IkConstraint.h index c09f8c7cd..387efb900 100644 --- a/spine-cpp/spine-cpp/include/spine/IkConstraint.h +++ b/spine-cpp/spine-cpp/include/spine/IkConstraint.h @@ -44,6 +44,7 @@ namespace Spine class IkConstraint : public Constraint { friend class Skeleton; + friend class IkConstraintTimeline; RTTI_DECL; diff --git a/spine-cpp/spine-cpp/include/spine/IkConstraintData.h b/spine-cpp/spine-cpp/include/spine/IkConstraintData.h index 0b516aa7e..9edc33bf0 100644 --- a/spine-cpp/spine-cpp/include/spine/IkConstraintData.h +++ b/spine-cpp/spine-cpp/include/spine/IkConstraintData.h @@ -43,6 +43,7 @@ namespace Spine { friend class IkConstraint; friend class Skeleton; + friend class IkConstraintTimeline; public: IkConstraintData(std::string name); diff --git a/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h b/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h index 6ab6d35c6..fe570146b 100644 --- a/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h @@ -48,69 +48,15 @@ namespace Spine virtual int getPropertyId(); + /// Sets the time, mix and bend direction of the specified keyframe. + void setFrame (int frameIndex, float time, float mix, int bendDirection); + private: static const int PREV_TIME, PREV_MIX, PREV_BEND_DIRECTION; static const int MIX, BEND_DIRECTION; Vector _frames; int _ikConstraintIndex; - -// public int IkConstraintIndex { return ikConstraintIndex; } set { ikConstraintIndex = inValue; } -// public float[] Frames { return frames; } set { frames = inValue; } // time, mix, bendDirection, ... -// -// -// -// /// Sets the time, mix and bend direction of the specified keyframe. -// public void setFrame (int frameIndex, float time, float mix, int bendDirection) { -// frameIndex *= ENTRIES; -// frames[frameIndex] = time; -// frames[frameIndex + MIX] = mix; -// frames[frameIndex + BEND_DIRECTION] = bendDirection; -// } -// -// override public void Apply (Skeleton skeleton, float lastTime, float time, Vector firedEvents, float alpha, MixPose pose, MixDirection direction) { -// IkConstraint constraint = skeleton.ikConstraints.Items[ikConstraintIndex]; -// float[] frames = _frames; -// if (time < frames[0]) { -// switch (pose) { -// case MixPose_Setup: -// constraint.mix = constraint.data.mix; -// constraint.bendDirection = constraint.data.bendDirection; -// return; -// case MixPose_Current: -// constraint.mix += (constraint.data.mix - constraint.mix) * alpha; -// constraint.bendDirection = constraint.data.bendDirection; -// return; -// } -// return; -// } -// -// if (time >= frames[frames.Length - ENTRIES]) { // Time is after last frame. -// if (pose == MixPose_Setup) { -// constraint.mix = constraint.data.mix + (frames[frames.Length + PREV_MIX] - constraint.data.mix) * alpha; -// constraint.bendDirection = direction == MixDirection_Out ? constraint.data.bendDirection -// : (int)frames[frames.Length + PREV_BEND_DIRECTION]; -// } else { -// constraint.mix += (frames[frames.Length + PREV_MIX] - constraint.mix) * alpha; -// if (direction == MixDirection_In) constraint.bendDirection = (int)frames[frames.Length + PREV_BEND_DIRECTION]; -// } -// return; -// } -// -// // Interpolate between the previous frame and the current frame. -// int frame = Animation::binarySearch(frames, time, ENTRIES); -// float mix = frames[frame + PREV_MIX]; -// float frameTime = frames[frame]; -// float percent = GetCurvePercent(frame / ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime)); -// -// if (pose == MixPose_Setup) { -// constraint.mix = constraint.data.mix + (mix + (frames[frame + MIX] - mix) * percent - constraint.data.mix) * alpha; -// constraint.bendDirection = direction == MixDirection_Out ? constraint.data.bendDirection : (int)frames[frame + PREV_BEND_DIRECTION]; -// } else { -// constraint.mix += (mix + (frames[frame + MIX] - mix) * percent - constraint.mix) * alpha; -// if (direction == MixDirection_In) constraint.bendDirection = (int)frames[frame + PREV_BEND_DIRECTION]; -// } -// } }; } diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraint.h b/spine-cpp/spine-cpp/include/spine/PathConstraint.h index 7f6440c48..a88e5a4cc 100644 --- a/spine-cpp/spine-cpp/include/spine/PathConstraint.h +++ b/spine-cpp/spine-cpp/include/spine/PathConstraint.h @@ -46,6 +46,9 @@ namespace Spine class PathConstraint : public Constraint { friend class Skeleton; + friend class PathConstraintMixTimeline; + friend class PathConstraintPositionTimeline; + friend class PathConstraintSpacingTimeline; RTTI_DECL; diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraintData.h b/spine-cpp/spine-cpp/include/spine/PathConstraintData.h index fc7a77d16..8a41880f2 100644 --- a/spine-cpp/spine-cpp/include/spine/PathConstraintData.h +++ b/spine-cpp/spine-cpp/include/spine/PathConstraintData.h @@ -47,6 +47,9 @@ namespace Spine { friend class PathConstraint; friend class Skeleton; + friend class PathConstraintMixTimeline; + friend class PathConstraintPositionTimeline; + friend class PathConstraintSpacingTimeline; public: PathConstraintData(std::string name); diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h b/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h index 65d286470..96f0bd1a8 100644 --- a/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h @@ -40,78 +40,23 @@ namespace Spine RTTI_DECL; public: + static const int ENTRIES; + + PathConstraintMixTimeline(int frameCount); + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); virtual int getPropertyId(); private: + static const int PREV_TIME, PREV_ROTATE, PREV_TRANSLATE; + static const int ROTATE, TRANSLATE; + + Vector _frames; int _pathConstraintIndex; -// public const int ENTRIES = 3; -// private const int PREV_TIME = -3, PREV_ROTATE = -2, PREV_TRANSLATE = -1; -// private const int ROTATE = 1, TRANSLATE = 2; -// -// internal float[] frames; -// -// public int PathConstraintIndex { return pathConstraintIndex; } set { pathConstraintIndex = inValue; } -// public float[] Frames { return frames; } set { frames = inValue; } // time, rotate mix, translate mix, ... -// -// -// public PathConstraintMixTimeline (int frameCount) -// : base(frameCount) { -// frames = new float[frameCount * ENTRIES]; -// } -// -// /// Sets the time and mixes of the specified keyframe. -// public void setFrame (int frameIndex, float time, float rotateMix, float translateMix) { -// frameIndex *= ENTRIES; -// frames[frameIndex] = time; -// frames[frameIndex + ROTATE] = rotateMix; -// frames[frameIndex + TRANSLATE] = translateMix; -// } -// -// override public void Apply (Skeleton skeleton, float lastTime, float time, Vector firedEvents, float alpha, MixPose pose, MixDirection direction) { -// PathConstraint constraint = skeleton.pathConstraints.Items[pathConstraintIndex]; -// float[] frames = _frames; -// if (time < frames[0]) { -// switch (pose) { -// case MixPose_Setup: -// constraint.rotateMix = constraint.data.rotateMix; -// constraint.translateMix = constraint.data.translateMix; -// return; -// case MixPose_Current: -// constraint.rotateMix += (constraint.data.rotateMix - constraint.rotateMix) * alpha; -// constraint.translateMix += (constraint.data.translateMix - constraint.translateMix) * alpha; -// return; -// } -// return; -// } -// -// float rotate, translate; -// if (time >= frames[frames.Length - ENTRIES]) { // Time is after last frame. -// rotate = frames[frames.Length + PREV_ROTATE]; -// translate = frames[frames.Length + PREV_TRANSLATE]; -// } else { -// // Interpolate between the previous frame and the current frame. -// int frame = Animation::binarySearch(frames, time, ENTRIES); -// rotate = frames[frame + PREV_ROTATE]; -// translate = frames[frame + PREV_TRANSLATE]; -// float frameTime = frames[frame]; -// float percent = GetCurvePercent(frame / ENTRIES - 1, -// 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime)); -// -// rotate += (frames[frame + ROTATE] - rotate) * percent; -// translate += (frames[frame + TRANSLATE] - translate) * percent; -// } -// -// if (pose == MixPose_Setup) { -// constraint.rotateMix = constraint.data.rotateMix + (rotate - constraint.data.rotateMix) * alpha; -// constraint.translateMix = constraint.data.translateMix + (translate - constraint.data.translateMix) * alpha; -// } else { -// constraint.rotateMix += (rotate - constraint.rotateMix) * alpha; -// constraint.translateMix += (translate - constraint.translateMix) * alpha; -// } -// } + /// Sets the time and mixes of the specified keyframe. + void setFrame(int frameIndex, float time, float rotateMix, float translateMix); }; } diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h b/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h index 72734d4d8..ab6839e1f 100644 --- a/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h @@ -48,61 +48,15 @@ namespace Spine virtual int getPropertyId(); + /// Sets the time and value of the specified keyframe. + void setFrame(int frameIndex, float time, float value); + protected: static const int PREV_TIME, PREV_VALUE; static const int VALUE; Vector _frames; int _pathConstraintIndex; - - -// -// -// -// -// public int PathConstraintIndex { return pathConstraintIndex; } set { pathConstraintIndex = inValue; } -// public float[] Frames { return frames; } set { frames = inValue; } // time, position, ... -// -// /// Sets the time and value of the specified keyframe. -// public void setFrame (int frameIndex, float time, float value) { -// frameIndex *= ENTRIES; -// frames[frameIndex] = time; -// frames[frameIndex + VALUE] = inValue; -// } -// -// override public void Apply (Skeleton skeleton, float lastTime, float time, Vector firedEvents, float alpha, MixPose pose, MixDirection direction) { -// PathConstraint constraint = skeleton.pathConstraints.Items[pathConstraintIndex]; -// float[] frames = _frames; -// if (time < frames[0]) { -// switch (pose) { -// case MixPose_Setup: -// constraint.position = constraint.data.position; -// return; -// case MixPose_Current: -// constraint.position += (constraint.data.position - constraint.position) * alpha; -// return; -// } -// return; -// } -// -// float position; -// if (time >= frames[frames.Length - ENTRIES]) // Time is after last frame. -// position = frames[frames.Length + PREV_VALUE]; -// else { -// // Interpolate between the previous frame and the current frame. -// int frame = Animation::binarySearch(frames, time, ENTRIES); -// position = frames[frame + PREV_VALUE]; -// float frameTime = frames[frame]; -// float percent = GetCurvePercent(frame / ENTRIES - 1, -// 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime)); -// -// position += (frames[frame + VALUE] - position) * percent; -// } -// if (pose == MixPose_Setup) -// constraint.position = constraint.data.position + (position - constraint.data.position) * alpha; -// else -// constraint.position += (position - constraint.position) * alpha; -// } }; } diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h b/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h index a0fa2b9fb..fb959a55a 100644 --- a/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h @@ -45,41 +45,6 @@ namespace Spine virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); virtual int getPropertyId(); - -// override public void Apply (Skeleton skeleton, float lastTime, float time, Vector firedEvents, float alpha, MixPose pose, MixDirection direction) { -// PathConstraint constraint = skeleton.pathConstraints.Items[pathConstraintIndex]; -// float[] frames = _frames; -// if (time < frames[0]) { -// switch (pose) { -// case MixPose_Setup: -// constraint.spacing = constraint.data.spacing; -// return; -// case MixPose_Current: -// constraint.spacing += (constraint.data.spacing - constraint.spacing) * alpha; -// return; -// } -// return; -// } -// -// float spacing; -// if (time >= frames[frames.Length - ENTRIES]) // Time is after last frame. -// spacing = frames[frames.Length + PREV_VALUE]; -// else { -// // Interpolate between the previous frame and the current frame. -// int frame = Animation::binarySearch(frames, time, ENTRIES); -// spacing = frames[frame + PREV_VALUE]; -// float frameTime = frames[frame]; -// float percent = GetCurvePercent(frame / ENTRIES - 1, -// 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime)); -// -// spacing += (frames[frame + VALUE] - spacing) * percent; -// } -// -// if (pose == MixPose_Setup) -// constraint.spacing = constraint.data.spacing + (spacing - constraint.data.spacing) * alpha; -// else -// constraint.spacing += (spacing - constraint.spacing) * alpha; -// } }; } diff --git a/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h b/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h index d0ce306d3..12f941f42 100644 --- a/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h @@ -39,72 +39,12 @@ namespace Spine { RTTI_DECL; + public: + ScaleTimeline(int frameCount); + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); virtual int getPropertyId(); - -// public ScaleTimeline (int frameCount) -// : base(frameCount) { -// } -// -// override public void Apply (Skeleton skeleton, float lastTime, float time, Vector firedEvents, float alpha, MixPose pose, MixDirection direction) { -// Bone bone = skeleton.bones.Items[boneIndex]; -// -// float[] frames = _frames; -// if (time < frames[0]) { -// switch (pose) { -// case MixPose_Setup: -// bone.scaleX = bone.data.scaleX; -// bone.scaleY = bone.data.scaleY; -// return; -// case MixPose_Current: -// bone.scaleX += (bone.data.scaleX - bone.scaleX) * alpha; -// bone.scaleY += (bone.data.scaleY - bone.scaleY) * alpha; -// return; -// } -// return; -// } -// -// float x, y; -// if (time >= frames[frames.Length - ENTRIES]) { // Time is after last frame. -// x = frames[frames.Length + PREV_X] * bone.data.scaleX; -// y = frames[frames.Length + PREV_Y] * bone.data.scaleY; -// } else { -// // Interpolate between the previous frame and the current frame. -// int frame = Animation::binarySearch(frames, time, ENTRIES); -// x = frames[frame + PREV_X]; -// y = frames[frame + PREV_Y]; -// float frameTime = frames[frame]; -// float percent = GetCurvePercent(frame / ENTRIES - 1, -// 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime)); -// -// x = (x + (frames[frame + X] - x) * percent) * bone.data.scaleX; -// y = (y + (frames[frame + Y] - y) * percent) * bone.data.scaleY; -// } -// if (alpha == 1) { -// bone.scaleX = x; -// bone.scaleY = y; -// } else { -// float bx, by; -// if (pose == MixPose_Setup) { -// bx = bone.data.scaleX; -// by = bone.data.scaleY; -// } else { -// bx = bone.scaleX; -// by = bone.scaleY; -// } -// // Mixing out uses sign of setup or current pose, else use sign of key. -// if (direction == MixDirection_Out) { -// x = (x >= 0 ? x : -x) * (bx >= 0 ? 1 : -1); -// y = (y >= 0 ? y : -y) * (by >= 0 ? 1 : -1); -// } else { -// bx = (bx >= 0 ? bx : -bx) * (x >= 0 ? 1 : -1); -// by = (by >= 0 ? by : -by) * (y >= 0 ? 1 : -1); -// } -// bone.scaleX = bx + (x - bx) * alpha; -// bone.scaleY = by + (y - by) * alpha; -// } -// } }; } diff --git a/spine-cpp/spine-cpp/include/spine/ShearTimeline.h b/spine-cpp/spine-cpp/include/spine/ShearTimeline.h index 1916fd8f4..5618a6529 100644 --- a/spine-cpp/spine-cpp/include/spine/ShearTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/ShearTimeline.h @@ -40,55 +40,11 @@ namespace Spine RTTI_DECL; public: + ShearTimeline(int frameCount); + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); virtual int getPropertyId(); - -// public ShearTimeline (int frameCount) -// : base(frameCount) { -// } -// -// override public void Apply (Skeleton skeleton, float lastTime, float time, Vector firedEvents, float alpha, MixPose pose, MixDirection direction) { -// Bone bone = skeleton.bones.Items[boneIndex]; -// float[] frames = _frames; -// if (time < frames[0]) { -// switch (pose) { -// case MixPose_Setup: -// bone.shearX = bone.data.shearX; -// bone.shearY = bone.data.shearY; -// return; -// case MixPose_Current: -// bone.shearX += (bone.data.shearX - bone.shearX) * alpha; -// bone.shearY += (bone.data.shearY - bone.shearY) * alpha; -// return; -// } -// return; -// } -// -// float x, y; -// if (time >= frames[frames.Length - ENTRIES]) { // Time is after last frame. -// x = frames[frames.Length + PREV_X]; -// y = frames[frames.Length + PREV_Y]; -// } else { -// // Interpolate between the previous frame and the current frame. -// int frame = Animation::binarySearch(frames, time, ENTRIES); -// x = frames[frame + PREV_X]; -// y = frames[frame + PREV_Y]; -// float frameTime = frames[frame]; -// float percent = GetCurvePercent(frame / ENTRIES - 1, -// 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime)); -// -// x = x + (frames[frame + X] - x) * percent; -// y = y + (frames[frame + Y] - y) * percent; -// } -// if (pose == MixPose_Setup) { -// bone.shearX = bone.data.shearX + x * alpha; -// bone.shearY = bone.data.shearY + y * alpha; -// } else { -// bone.shearX += (bone.data.shearX + x - bone.shearX) * alpha; -// bone.shearY += (bone.data.shearY + y - bone.shearY) * alpha; -// } -// } }; } diff --git a/spine-cpp/spine-cpp/include/spine/TransformConstraint.h b/spine-cpp/spine-cpp/include/spine/TransformConstraint.h index 262c3a210..7c5061f60 100644 --- a/spine-cpp/spine-cpp/include/spine/TransformConstraint.h +++ b/spine-cpp/spine-cpp/include/spine/TransformConstraint.h @@ -44,6 +44,7 @@ namespace Spine class TransformConstraint : public Constraint { friend class Skeleton; + friend class TransformConstraintTimeline; RTTI_DECL; diff --git a/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h b/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h index d3a5aebb3..603175d4f 100644 --- a/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h +++ b/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h @@ -43,6 +43,7 @@ namespace Spine { friend class TransformConstraint; friend class Skeleton; + friend class TransformConstraintTimeline; public: TransformConstraintData(std::string name); diff --git a/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h b/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h index e4486d197..6065d4727 100644 --- a/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h @@ -42,94 +42,20 @@ namespace Spine public: static const int ENTRIES; + TransformConstraintTimeline(int frameCount); + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); virtual int getPropertyId(); + void setFrame(int frameIndex, float time, float rotateMix, float translateMix, float scaleMix, float shearMix); + private: static const int PREV_TIME, PREV_ROTATE, PREV_TRANSLATE, PREV_SCALE, PREV_SHEAR; static const int ROTATE, TRANSLATE, SCALE, SHEAR; + Vector _frames; int _transformConstraintIndex; - -// internal float[] frames; -// -// public int TransformConstraintIndex { return transformConstraintIndex; } set { transformConstraintIndex = inValue; } -// public float[] Frames { return frames; } set { frames = inValue; } // time, rotate mix, translate mix, scale mix, shear mix, ... -// -// -// public TransformConstraintTimeline (int frameCount) -// : base(frameCount) { -// frames = new float[frameCount * ENTRIES]; -// } -// -// public void setFrame (int frameIndex, float time, float rotateMix, float translateMix, float scaleMix, float shearMix) { -// frameIndex *= ENTRIES; -// frames[frameIndex] = time; -// frames[frameIndex + ROTATE] = rotateMix; -// frames[frameIndex + TRANSLATE] = translateMix; -// frames[frameIndex + SCALE] = scaleMix; -// frames[frameIndex + SHEAR] = shearMix; -// } -// -// override public void Apply (Skeleton skeleton, float lastTime, float time, Vector firedEvents, float alpha, MixPose pose, MixDirection direction) { -// TransformConstraint constraint = skeleton.transformConstraints.Items[transformConstraintIndex]; -// float[] frames = _frames; -// if (time < frames[0]) { -// var data = constraint.data; -// switch (pose) { -// case MixPose_Setup: -// constraint.rotateMix = data.rotateMix; -// constraint.translateMix = data.translateMix; -// constraint.scaleMix = data.scaleMix; -// constraint.shearMix = data.shearMix; -// return; -// case MixPose_Current: -// constraint.rotateMix += (data.rotateMix - constraint.rotateMix) * alpha; -// constraint.translateMix += (data.translateMix - constraint.translateMix) * alpha; -// constraint.scaleMix += (data.scaleMix - constraint.scaleMix) * alpha; -// constraint.shearMix += (data.shearMix - constraint.shearMix) * alpha; -// return; -// } -// return; -// } -// -// float rotate, translate, scale, shear; -// if (time >= frames[frames.Length - ENTRIES]) { // Time is after last frame. -// int i = frames.Length; -// rotate = frames[i + PREV_ROTATE]; -// translate = frames[i + PREV_TRANSLATE]; -// scale = frames[i + PREV_SCALE]; -// shear = frames[i + PREV_SHEAR]; -// } else { -// // Interpolate between the previous frame and the current frame. -// int frame = Animation::binarySearch(frames, time, ENTRIES); -// rotate = frames[frame + PREV_ROTATE]; -// translate = frames[frame + PREV_TRANSLATE]; -// scale = frames[frame + PREV_SCALE]; -// shear = frames[frame + PREV_SHEAR]; -// float frameTime = frames[frame]; -// float percent = GetCurvePercent(frame / ENTRIES - 1, -// 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime)); -// -// rotate += (frames[frame + ROTATE] - rotate) * percent; -// translate += (frames[frame + TRANSLATE] - translate) * percent; -// scale += (frames[frame + SCALE] - scale) * percent; -// shear += (frames[frame + SHEAR] - shear) * percent; -// } -// if (pose == MixPose_Setup) { -// TransformConstraintData data = constraint.data; -// constraint.rotateMix = data.rotateMix + (rotate - data.rotateMix) * alpha; -// constraint.translateMix = data.translateMix + (translate - data.translateMix) * alpha; -// constraint.scaleMix = data.scaleMix + (scale - data.scaleMix) * alpha; -// constraint.shearMix = data.shearMix + (shear - data.shearMix) * alpha; -// } else { -// constraint.rotateMix += (rotate - constraint.rotateMix) * alpha; -// constraint.translateMix += (translate - constraint.translateMix) * alpha; -// constraint.scaleMix += (scale - constraint.scaleMix) * alpha; -// constraint.shearMix += (shear - constraint.shearMix) * alpha; -// } -// } }; } diff --git a/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h b/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h index 6faac140a..d661f9d3f 100644 --- a/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h @@ -43,89 +43,23 @@ namespace Spine RTTI_DECL; public: + static const int ENTRIES; + + TranslateTimeline(int frameCount); + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); virtual int getPropertyId(); - protected: - int _boneIndex; + /// Sets the time and value of the specified keyframe. + void setFrame(int frameIndex, float time, float x, float y); -// public const int ENTRIES = 3; -// protected const int PREV_TIME = -3, PREV_X = -2, PREV_Y = -1; -// protected const int X = 1, Y = 2; -// -// internal float[] frames; -// -// public int getBoneIndex { return boneIndex; } set { boneIndex = inValue; } -// public Vector getFrames { return frames; } set { frames = inValue; } // time, value, value, ... -// -// -// public TranslateTimeline(int frameCount) : CurveTimeline(frameCount) -// { -// frames = new float[frameCount * ENTRIES]; -// } -// -// /// Sets the time and value of the specified keyframe. -// public void setFrame(int frameIndex, float time, float x, float y) -// { -// frameIndex *= ENTRIES; -// frames[frameIndex] = time; -// frames[frameIndex + X] = x; -// frames[frameIndex + Y] = y; -// } -// -// override public void apply(Skeleton skeleton, float lastTime, float time, Vector firedEvents, float alpha, MixPose pose, MixDirection direction) -// { -// Bone bone = skeleton.bones.Items[boneIndex]; -// -// float[] frames = _frames; -// if (time < frames[0]) -// { -// switch (pose) -// { -// case MixPose_Setup: -// bone.x = bone.data.x; -// bone.y = bone.data.y; -// return; -// case MixPose_Current: -// bone.x += (bone.data.x - bone.x) * alpha; -// bone.y += (bone.data.y - bone.y) * alpha; -// return; -// } -// return; -// } -// -// float x, y; -// if (time >= frames[frames.Length - ENTRIES]) -// { -// // Time is after last frame. -// x = frames[frames.Length + PREV_X]; -// y = frames[frames.Length + PREV_Y]; -// } -// else -// { -// // Interpolate between the previous frame and the current frame. -// int frame = Animation::binarySearch(frames, time, ENTRIES); -// x = frames[frame + PREV_X]; -// y = frames[frame + PREV_Y]; -// float frameTime = frames[frame]; -// float percent = GetCurvePercent(frame / ENTRIES - 1, 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime)); -// -// x += (frames[frame + X] - x) * percent; -// y += (frames[frame + Y] - y) * percent; -// } -// -// if (pose == MixPose_Setup) -// { -// bone.x = bone.data.x + x * alpha; -// bone.y = bone.data.y + y * alpha; -// } -// else -// { -// bone.x += (bone.data.x + x - bone.x) * alpha; -// bone.y += (bone.data.y + y - bone.y) * alpha; -// } -// } + protected: + static const int PREV_TIME, PREV_X, PREV_Y; + static const int X, Y; + + Vector _frames; + int _boneIndex; }; } diff --git a/spine-cpp/spine-cpp/include/spine/TwoColorTimeline.h b/spine-cpp/spine-cpp/include/spine/TwoColorTimeline.h index d70375d34..ceb23848f 100644 --- a/spine-cpp/spine-cpp/include/spine/TwoColorTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/TwoColorTimeline.h @@ -40,146 +40,27 @@ namespace Spine RTTI_DECL; public: + static const int ENTRIES; + + TwoColorTimeline(int frameCount); + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); virtual int getPropertyId(); - private: - int _slotIndex; + /// Sets the time and value of the specified keyframe. + void setFrame(int frameIndex, float time, float r, float g, float b, float a, float r2, float g2, float b2); -// public const int ENTRIES = 8; -// protected const int PREV_TIME = -8, PREV_R = -7, PREV_G = -6, PREV_B = -5, PREV_A = -4; -// protected const int PREV_R2 = -3, PREV_G2 = -2, PREV_B2 = -1; -// protected const int R = 1, G = 2, B = 3, A = 4, R2 = 5, G2 = 6, B2 = 7; -// -// internal float[] frames; // time, r, g, b, a, r2, g2, b2, ... -// public float[] Frames { return frames; } -// -// public int SlotIndex { -// get { return slotIndex; } -// set { -// if (value < 0) throw new ArgumentOutOfRangeException("index must be >= 0."); -// slotIndex = inValue; -// } -// } -// -// -// public TwoColorTimeline (int frameCount) : -// base(frameCount) { -// frames = new float[frameCount * ENTRIES]; -// } -// -// /// Sets the time and value of the specified keyframe. -// public void setFrame (int frameIndex, float time, float r, float g, float b, float a, float r2, float g2, float b2) { -// frameIndex *= ENTRIES; -// frames[frameIndex] = time; -// frames[frameIndex + R] = r; -// frames[frameIndex + G] = g; -// frames[frameIndex + B] = b; -// frames[frameIndex + A] = a; -// frames[frameIndex + R2] = r2; -// frames[frameIndex + G2] = g2; -// frames[frameIndex + B2] = b2; -// } -// -// override public void Apply (Skeleton skeleton, float lastTime, float time, Vector firedEvents, float alpha, MixPose pose, MixDirection direction) { -// Slot slot = skeleton.slots.Items[slotIndex]; -// float[] frames = _frames; -// if (time < frames[0]) { // Time is before first frame. -// var slotData = slot.data; -// switch (pose) { -// case MixPose_Setup: -// // slot.color.set(slot.data.color); -// // slot.darkColor.set(slot.data.darkColor); -// slot.r = slotData.r; -// slot.g = slotData.g; -// slot.b = slotData.b; -// slot.a = slotData.a; -// slot.r2 = slotData.r2; -// slot.g2 = slotData.g2; -// slot.b2 = slotData.b2; -// return; -// case MixPose_Current: -// slot.r += (slot.r - slotData.r) * alpha; -// slot.g += (slot.g - slotData.g) * alpha; -// slot.b += (slot.b - slotData.b) * alpha; -// slot.a += (slot.a - slotData.a) * alpha; -// slot.r2 += (slot.r2 - slotData.r2) * alpha; -// slot.g2 += (slot.g2 - slotData.g2) * alpha; -// slot.b2 += (slot.b2 - slotData.b2) * alpha; -// return; -// } -// return; -// } -// -// float r, g, b, a, r2, g2, b2; -// if (time >= frames[frames.Length - ENTRIES]) { // Time is after last frame. -// int i = frames.Length; -// r = frames[i + PREV_R]; -// g = frames[i + PREV_G]; -// b = frames[i + PREV_B]; -// a = frames[i + PREV_A]; -// r2 = frames[i + PREV_R2]; -// g2 = frames[i + PREV_G2]; -// b2 = frames[i + PREV_B2]; -// } else { -// // Interpolate between the previous frame and the current frame. -// int frame = Animation::binarySearch(frames, time, ENTRIES); -// r = frames[frame + PREV_R]; -// g = frames[frame + PREV_G]; -// b = frames[frame + PREV_B]; -// a = frames[frame + PREV_A]; -// r2 = frames[frame + PREV_R2]; -// g2 = frames[frame + PREV_G2]; -// b2 = frames[frame + PREV_B2]; -// float frameTime = frames[frame]; -// float percent = GetCurvePercent(frame / ENTRIES - 1, -// 1 - (time - frameTime) / (frames[frame + PREV_TIME] - frameTime)); -// -// r += (frames[frame + R] - r) * percent; -// g += (frames[frame + G] - g) * percent; -// b += (frames[frame + B] - b) * percent; -// a += (frames[frame + A] - a) * percent; -// r2 += (frames[frame + R2] - r2) * percent; -// g2 += (frames[frame + G2] - g2) * percent; -// b2 += (frames[frame + B2] - b2) * percent; -// } -// if (alpha == 1) { -// slot.r = r; -// slot.g = g; -// slot.b = b; -// slot.a = a; -// slot.r2 = r2; -// slot.g2 = g2; -// slot.b2 = b2; -// } else { -// float br, bg, bb, ba, br2, bg2, bb2; -// if (pose == MixPose_Setup) { -// br = slot.data.r; -// bg = slot.data.g; -// bb = slot.data.b; -// ba = slot.data.a; -// br2 = slot.data.r2; -// bg2 = slot.data.g2; -// bb2 = slot.data.b2; -// } else { -// br = slot.r; -// bg = slot.g; -// bb = slot.b; -// ba = slot.a; -// br2 = slot.r2; -// bg2 = slot.g2; -// bb2 = slot.b2; -// } -// slot.r = br + ((r - br) * alpha); -// slot.g = bg + ((g - bg) * alpha); -// slot.b = bb + ((b - bb) * alpha); -// slot.a = ba + ((a - ba) * alpha); -// slot.r2 = br2 + ((r2 - br2) * alpha); -// slot.g2 = bg2 + ((g2 - bg2) * alpha); -// slot.b2 = bb2 + ((b2 - bb2) * alpha); -// } -// } + int getSlotIndex(); + void setSlotIndex(int inValue); + + private: + static const int PREV_TIME, PREV_R, PREV_G, PREV_B, PREV_A; + static const int PREV_R2, PREV_G2, PREV_B2; + static const int R, G, B, A, R2, G2, B2; + + Vector _frames; // time, r, g, b, a, r2, g2, b2, ... + int _slotIndex; }; } diff --git a/spine-cpp/spine-cpp/include/spine/Vector.h b/spine-cpp/spine-cpp/include/spine/Vector.h index 8fc87c490..9ae06e982 100644 --- a/spine-cpp/spine-cpp/include/spine/Vector.h +++ b/spine-cpp/spine-cpp/include/spine/Vector.h @@ -48,18 +48,53 @@ namespace Spine // Empty } - Vector(const Vector& inArray) : _size(inArray._size), _capacity(inArray._capacity), _buffer(NULL) + Vector(const Vector& inVector) : _size(inVector._size), _capacity(inVector._capacity), _buffer(NULL) { if (_capacity > 0) { _buffer = allocate(_capacity); for (size_t i = 0; i < _size; ++i) { - construct(_buffer + i, inArray._buffer[i]); + construct(_buffer + i, inVector._buffer[i]); } } } + Vector(Vector& inVector) : _size(inVector._size), _capacity(inVector._capacity), _buffer(NULL) + { + if (_capacity > 0) + { + _buffer = allocate(_capacity); + for (size_t i = 0; i < _size; ++i) + { + construct(_buffer + i, inVector._buffer[i]); + } + } + } + + Vector& operator=(Vector& inVector) + { + if (this != &inVector) + { + clear(); + deallocate(_buffer); + + _size = inVector._size; + _capacity = inVector._capacity; + + if (_capacity > 0) + { + _buffer = allocate(_capacity); + for (size_t i = 0; i < _size; ++i) + { + construct(_buffer + i, inVector._buffer[i]); + } + } + } + + return *this; + } + ~Vector() { clear(); @@ -179,6 +214,29 @@ namespace Spine return &_buffer[_size]; } + friend bool operator==(Vector& lhs, Vector& rhs) + { + if (lhs.size() != rhs.size()) + { + return false; + } + + for (int i = 0, n = static_cast(lhs.size()); i < n; ++i) + { + if (lhs[i] != rhs[i]) + { + return false; + } + } + + return true; + } + + friend bool operator!=(Vector& lhs, Vector& rhs) + { + return !(lhs == rhs); + } + private: size_t _size; size_t _capacity; diff --git a/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp b/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp index 2e6f69b03..87ab7a814 100644 --- a/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp @@ -37,18 +37,83 @@ #include #include #include +#include namespace Spine { RTTI_IMPL(EventTimeline, Timeline); + EventTimeline::EventTimeline(int frameCount) : Timeline() + { + _frames.reserve(frameCount); + _events.reserve(frameCount); + } + void EventTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) { - // TODO + if (events.size() == 0) + { + return; + } + + int frameCount = static_cast(_frames.size()); + + if (lastTime > time) + { + // Fire events after last time for looped animations. + apply(skeleton, lastTime, std::numeric_limits::max(), events, alpha, pose, direction); + lastTime = -1.0f; + } + else if (lastTime >= _frames[frameCount - 1]) // Last time is after last frame. + { + return; + } + + if (time < _frames[0]) + { + return; // Time is before first frame. + } + + int frame; + if (lastTime < _frames[0]) + { + frame = 0; + } + else + { + frame = Animation::binarySearch(_frames, lastTime); + float frameTime = _frames[frame]; + while (frame > 0) + { + // Fire multiple events with the same frame. + if (_frames[frame - 1] != frameTime) + { + break; + } + frame--; + } + } + + for (; frame < frameCount && time >= _frames[frame]; ++frame) + { + events.push_back(_events[frame]); + } } int EventTimeline::getPropertyId() { return ((int)TimelineType_Event << 24); } + + void EventTimeline::setFrame(int frameIndex, Event* e) + { + _frames[frameIndex] = e->getTime(); + _events[frameIndex] = e; + } + + Vector EventTimeline::getFrames() { return _frames; } + void EventTimeline::setFrames(Vector& inValue) { _frames = inValue; } // time, ... + Vector& EventTimeline::getEvents() { return _events; } + void EventTimeline::setEvents(Vector& inValue) { _events = inValue; } + int EventTimeline::getFrameCount() { return static_cast(_frames.size()); } } diff --git a/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp b/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp index a8c89f715..2b05750e3 100644 --- a/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp @@ -37,6 +37,8 @@ #include #include #include +#include +#include namespace Spine { @@ -56,11 +58,77 @@ namespace Spine void IkConstraintTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) { - // TODO + IkConstraint* constraintP = skeleton._ikConstraints[_ikConstraintIndex]; + IkConstraint& constraint = *constraintP; + if (time < _frames[0]) + { + switch (pose) + { + case MixPose_Setup: + constraint._mix = constraint._data._mix; + constraint._bendDirection = constraint._data._bendDirection; + return; + case MixPose_Current: + constraint._mix += (constraint._data._mix - constraint._mix) * alpha; + constraint._bendDirection = constraint._data._bendDirection; + return; + case MixPose_CurrentLayered: + default: + return; + } + } + + if (time >= _frames[_frames.size() - ENTRIES]) + { + // Time is after last frame. + if (pose == MixPose_Setup) + { + constraint._mix = constraint._data._mix + (_frames[_frames.size() + PREV_MIX] - constraint._data._mix) * alpha; + constraint._bendDirection = direction == MixDirection_Out ? constraint._data._bendDirection + : (int)_frames[_frames.size() + PREV_BEND_DIRECTION]; + } + else + { + constraint._mix += (_frames[_frames.size() + PREV_MIX] - constraint._mix) * alpha; + if (direction == MixDirection_In) + { + constraint._bendDirection = (int)_frames[_frames.size() + PREV_BEND_DIRECTION]; + } + } + return; + } + + // Interpolate between the previous frame and the current frame. + int frame = Animation::binarySearch(_frames, time, ENTRIES); + float mix = _frames[frame + PREV_MIX]; + float frameTime = _frames[frame]; + float percent = getCurvePercent(frame / ENTRIES - 1, 1 - (time - frameTime) / (_frames[frame + PREV_TIME] - frameTime)); + + if (pose == MixPose_Setup) + { + constraint._mix = constraint._data._mix + (mix + (_frames[frame + MIX] - mix) * percent - constraint._data._mix) * alpha; + constraint._bendDirection = direction == MixDirection_Out ? constraint._data._bendDirection : (int)_frames[frame + PREV_BEND_DIRECTION]; + } + else + { + constraint._mix += (mix + (_frames[frame + MIX] - mix) * percent - constraint._mix) * alpha; + if (direction == MixDirection_In) + { + constraint._bendDirection = (int)_frames[frame + PREV_BEND_DIRECTION]; + } + } } int IkConstraintTimeline::getPropertyId() { return ((int)TimelineType_IkConstraint << 24) + _ikConstraintIndex; } + + void IkConstraintTimeline::setFrame(int frameIndex, float time, float mix, int bendDirection) + { + frameIndex *= ENTRIES; + _frames[frameIndex] = time; + _frames[frameIndex + MIX] = mix; + _frames[frameIndex + BEND_DIRECTION] = bendDirection; + } } diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp b/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp index 772eb4e4f..394ecf48e 100644 --- a/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp @@ -37,18 +37,90 @@ #include #include #include +#include +#include namespace Spine { RTTI_IMPL(PathConstraintMixTimeline, CurveTimeline); + const int PathConstraintMixTimeline::ENTRIES = 3; + const int PathConstraintMixTimeline::PREV_TIME = -3; + const int PathConstraintMixTimeline::PREV_ROTATE = -2; + const int PathConstraintMixTimeline::PREV_TRANSLATE = -1; + const int PathConstraintMixTimeline::ROTATE = 1; + const int PathConstraintMixTimeline::TRANSLATE = 2; + + PathConstraintMixTimeline::PathConstraintMixTimeline(int frameCount) : CurveTimeline(frameCount), _pathConstraintIndex(0) + { + _frames.reserve(frameCount * ENTRIES); + } + void PathConstraintMixTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) { - // TODO + PathConstraint* constraintP = skeleton._pathConstraints[_pathConstraintIndex]; + PathConstraint& constraint = *constraintP; + if (time < _frames[0]) + { + switch (pose) + { + case MixPose_Setup: + constraint._rotateMix = constraint._data._rotateMix; + constraint._translateMix = constraint._data._translateMix; + return; + case MixPose_Current: + constraint._rotateMix += (constraint._data._rotateMix - constraint._rotateMix) * alpha; + constraint._translateMix += (constraint._data._translateMix - constraint._translateMix) * alpha; + return; + case MixPose_CurrentLayered: + default: + return; + } + } + + float rotate, translate; + if (time >= _frames[_frames.size() - ENTRIES]) + { + // Time is after last frame. + rotate = _frames[_frames.size() + PREV_ROTATE]; + translate = _frames[_frames.size() + PREV_TRANSLATE]; + } + else + { + // Interpolate between the previous frame and the current frame. + int frame = Animation::binarySearch(_frames, time, ENTRIES); + rotate = _frames[frame + PREV_ROTATE]; + translate = _frames[frame + PREV_TRANSLATE]; + float frameTime = _frames[frame]; + float percent = getCurvePercent(frame / ENTRIES - 1, + 1 - (time - frameTime) / (_frames[frame + PREV_TIME] - frameTime)); + + rotate += (_frames[frame + ROTATE] - rotate) * percent; + translate += (_frames[frame + TRANSLATE] - translate) * percent; + } + + if (pose == MixPose_Setup) + { + constraint._rotateMix = constraint._data._rotateMix + (rotate - constraint._data._rotateMix) * alpha; + constraint._translateMix = constraint._data._translateMix + (translate - constraint._data._translateMix) * alpha; + } + else + { + constraint._rotateMix += (rotate - constraint._rotateMix) * alpha; + constraint._translateMix += (translate - constraint._translateMix) * alpha; + } } int PathConstraintMixTimeline::getPropertyId() { return ((int)TimelineType_PathConstraintMix << 24) + _pathConstraintIndex; } + + void PathConstraintMixTimeline::setFrame(int frameIndex, float time, float rotateMix, float translateMix) + { + frameIndex *= ENTRIES; + _frames[frameIndex] = time; + _frames[frameIndex + ROTATE] = rotateMix; + _frames[frameIndex + TRANSLATE] = translateMix; + } } diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp b/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp index 2a1d2949b..75b423ee9 100644 --- a/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp @@ -37,6 +37,8 @@ #include #include #include +#include +#include namespace Spine { @@ -47,18 +49,66 @@ namespace Spine const int PathConstraintPositionTimeline::PREV_VALUE = -1; const int PathConstraintPositionTimeline::VALUE = 1; - PathConstraintPositionTimeline::PathConstraintPositionTimeline(int frameCount) : CurveTimeline(frameCount) + PathConstraintPositionTimeline::PathConstraintPositionTimeline(int frameCount) : CurveTimeline(frameCount), _pathConstraintIndex(0) { _frames.reserve(frameCount * ENTRIES); } void PathConstraintPositionTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) { - // TODO + PathConstraint* constraintP = skeleton._pathConstraints[_pathConstraintIndex]; + PathConstraint& constraint = *constraintP; + if (time < _frames[0]) + { + switch (pose) + { + case MixPose_Setup: + constraint._position = constraint._data._position; + return; + case MixPose_Current: + constraint._position += (constraint._data._position - constraint._position) * alpha; + return; + case MixPose_CurrentLayered: + default: + return; + } + } + + float position; + if (time >= _frames[_frames.size() - ENTRIES]) // Time is after last frame. + { + position = _frames[_frames.size() + PREV_VALUE]; + } + else + { + // Interpolate between the previous frame and the current frame. + int frame = Animation::binarySearch(_frames, time, ENTRIES); + position = _frames[frame + PREV_VALUE]; + float frameTime = _frames[frame]; + float percent = getCurvePercent(frame / ENTRIES - 1, + 1 - (time - frameTime) / (_frames[frame + PREV_TIME] - frameTime)); + + position += (_frames[frame + VALUE] - position) * percent; + } + if (pose == MixPose_Setup) + { + constraint._position = constraint._data._position + (position - constraint._data._position) * alpha; + } + else + { + constraint._position += (position - constraint._position) * alpha; + } } int PathConstraintPositionTimeline::getPropertyId() { return ((int)TimelineType_PathConstraintPosition << 24) + _pathConstraintIndex; } + + void PathConstraintPositionTimeline::setFrame(int frameIndex, float time, float value) + { + frameIndex *= ENTRIES; + _frames[frameIndex] = time; + _frames[frameIndex + VALUE] = value; + } } diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp b/spine-cpp/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp index 474930d7e..7d4713585 100644 --- a/spine-cpp/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp @@ -37,6 +37,8 @@ #include #include #include +#include +#include namespace Spine { @@ -49,7 +51,49 @@ namespace Spine void PathConstraintSpacingTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) { - // TODO + PathConstraint* constraintP = skeleton._pathConstraints[_pathConstraintIndex]; + PathConstraint& constraint = *constraintP; + if (time < _frames[0]) + { + switch (pose) + { + case MixPose_Setup: + constraint._spacing = constraint._data._spacing; + return; + case MixPose_Current: + constraint._spacing += (constraint._data._spacing - constraint._spacing) * alpha; + return; + case MixPose_CurrentLayered: + default: + return; + } + } + + float spacing; + if (time >= _frames[_frames.size() - ENTRIES]) // Time is after last frame. + { + spacing = _frames[_frames.size() + PREV_VALUE]; + } + else + { + // Interpolate between the previous frame and the current frame. + int frame = Animation::binarySearch(_frames, time, ENTRIES); + spacing = _frames[frame + PREV_VALUE]; + float frameTime = _frames[frame]; + float percent = getCurvePercent(frame / ENTRIES - 1, + 1 - (time - frameTime) / (_frames[frame + PREV_TIME] - frameTime)); + + spacing += (_frames[frame + VALUE] - spacing) * percent; + } + + if (pose == MixPose_Setup) + { + constraint._spacing = constraint._data._spacing + (spacing - constraint._data._spacing) * alpha; + } + else + { + constraint._spacing += (spacing - constraint._spacing) * alpha; + } } int PathConstraintSpacingTimeline::getPropertyId() diff --git a/spine-cpp/spine-cpp/src/spine/ScaleTimeline.cpp b/spine-cpp/spine-cpp/src/spine/ScaleTimeline.cpp index f431f589c..0be6f9347 100644 --- a/spine-cpp/spine-cpp/src/spine/ScaleTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/ScaleTimeline.cpp @@ -37,14 +37,94 @@ #include #include #include +#include +#include namespace Spine { RTTI_IMPL(ScaleTimeline, TranslateTimeline); + ScaleTimeline::ScaleTimeline(int frameCount) : TranslateTimeline(frameCount) + { + // Empty + } + void ScaleTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) { - // TODO + Bone* boneP = skeleton._bones[_boneIndex]; + Bone& bone = *boneP; + + if (time < _frames[0]) + { + switch (pose) + { + case MixPose_Setup: + bone._scaleX = bone._data._scaleX; + bone._scaleY = bone._data._scaleY; + return; + case MixPose_Current: + bone._scaleX += (bone._data._scaleX - bone._scaleX) * alpha; + bone._scaleY += (bone._data._scaleY - bone._scaleY) * alpha; + return; + case MixPose_CurrentLayered: + default: + return; + } + } + + float x, y; + if (time >= _frames[_frames.size() - ENTRIES]) + { + // Time is after last frame. + x = _frames[_frames.size() + PREV_X] * bone._data._scaleX; + y = _frames[_frames.size() + PREV_Y] * bone._data._scaleY; + } + else + { + // Interpolate between the previous frame and the current frame. + int frame = Animation::binarySearch(_frames, time, ENTRIES); + x = _frames[frame + PREV_X]; + y = _frames[frame + PREV_Y]; + float frameTime = _frames[frame]; + float percent = getCurvePercent(frame / ENTRIES - 1, + 1 - (time - frameTime) / (_frames[frame + PREV_TIME] - frameTime)); + + x = (x + (_frames[frame + X] - x) * percent) * bone._data._scaleX; + y = (y + (_frames[frame + Y] - y) * percent) * bone._data._scaleY; + } + + if (alpha == 1) + { + bone._scaleX = x; + bone._scaleY = y; + } + else + { + float bx, by; + if (pose == MixPose_Setup) + { + bx = bone._data._scaleX; + by = bone._data._scaleY; + } + else + { + bx = bone._scaleX; + by = bone._scaleY; + } + // Mixing out uses sign of setup or current pose, else use sign of key. + if (direction == MixDirection_Out) + { + x = (x >= 0 ? x : -x) * (bx >= 0 ? 1 : -1); + y = (y >= 0 ? y : -y) * (by >= 0 ? 1 : -1); + } + else + { + bx = (bx >= 0 ? bx : -bx) * (x >= 0 ? 1 : -1); + by = (by >= 0 ? by : -by) * (y >= 0 ? 1 : -1); + } + bone._scaleX = bx + (x - bx) * alpha; + bone._scaleY = by + (y - by) * alpha; + } } int ScaleTimeline::getPropertyId() diff --git a/spine-cpp/spine-cpp/src/spine/ShearTimeline.cpp b/spine-cpp/spine-cpp/src/spine/ShearTimeline.cpp index 1f114c972..4b142eccc 100644 --- a/spine-cpp/spine-cpp/src/spine/ShearTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/ShearTimeline.cpp @@ -37,14 +37,72 @@ #include #include #include +#include +#include namespace Spine { RTTI_IMPL(ShearTimeline, TranslateTimeline); + ShearTimeline::ShearTimeline(int frameCount) : TranslateTimeline(frameCount) + { + // Empty + } + void ShearTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) { - // TODO + Bone* boneP = skeleton._bones[_boneIndex]; + Bone& bone = *boneP; + + if (time < _frames[0]) + { + switch (pose) + { + case MixPose_Setup: + bone._shearX = bone._data._shearX; + bone._shearY = bone._data._shearY; + return; + case MixPose_Current: + bone._shearX += (bone._data._shearX - bone._shearX) * alpha; + bone._shearY += (bone._data._shearY - bone._shearY) * alpha; + return; + case MixPose_CurrentLayered: + default: + return; + } + } + + float x, y; + if (time >= _frames[_frames.size() - ENTRIES]) + { + // Time is after last frame. + x = _frames[_frames.size() + PREV_X]; + y = _frames[_frames.size() + PREV_Y]; + } + else + { + // Interpolate between the previous frame and the current frame. + int frame = Animation::binarySearch(_frames, time, ENTRIES); + x = _frames[frame + PREV_X]; + y = _frames[frame + PREV_Y]; + float frameTime = _frames[frame]; + float percent = getCurvePercent(frame / ENTRIES - 1, + 1 - (time - frameTime) / (_frames[frame + PREV_TIME] - frameTime)); + + x = x + (_frames[frame + X] - x) * percent; + y = y + (_frames[frame + Y] - y) * percent; + } + + if (pose == MixPose_Setup) + { + bone._shearX = bone._data._shearX + x * alpha; + bone._shearY = bone._data._shearY + y * alpha; + } + else + { + bone._shearX += (bone._data._shearX + x - bone._shearX) * alpha; + bone._shearY += (bone._data._shearY + y - bone._shearY) * alpha; + } } int ShearTimeline::getPropertyId() diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonClipping.cpp b/spine-cpp/spine-cpp/src/spine/SkeletonClipping.cpp index 5132b8b88..3ca3d9dbd 100644 --- a/spine-cpp/spine-cpp/src/spine/SkeletonClipping.cpp +++ b/spine-cpp/spine-cpp/src/spine/SkeletonClipping.cpp @@ -56,7 +56,9 @@ namespace Spine _clippingPolygon.reserve(n); clip->computeWorldVertices(slot, 0, n, _clippingPolygon, 0, 2); makeClockwise(_clippingPolygon); - _clippingPolygons = _triangulator.decompose(_clippingPolygon, _triangulator.triangulate(_clippingPolygon)); + Vector< Vector* > clippingPolygons = _triangulator.decompose(_clippingPolygon, _triangulator.triangulate(_clippingPolygon)); + + _clippingPolygons = clippingPolygons; for (Vector** i = _clippingPolygons.begin(); i != _clippingPolygons.end(); ++i) { @@ -97,14 +99,13 @@ namespace Spine Vector& clipOutput = _clipOutput, clippedVertices = _clippedVertices; Vector& clippedTriangles = _clippedTriangles; Vector< Vector* >& polygons = _clippingPolygons; - int polygonsCount = _clippingPolygons.size(); + int polygonsCount = static_cast(_clippingPolygons.size()); int index = 0; clippedVertices.clear(); _clippedUVs.clear(); clippedTriangles.clear(); - //outer: for (int i = 0; i < trianglesLength; i += 3) { int vertexOffset = triangles[i] << 1; @@ -121,73 +122,72 @@ namespace Spine for (int p = 0; p < polygonsCount; p++) { - int s = clippedVertices.size(); -// if (clip(x1, y1, x2, y2, x3, y3, polygons[p], clipOutput)) -// { -// int clipOutputLength = clipOutput.Count; -// if (clipOutputLength == 0) -// { -// continue; -// } -// float d0 = y2 - y3, d1 = x3 - x2, d2 = x1 - x3, d4 = y3 - y1; -// float d = 1 / (d0 * d2 + d1 * (y1 - y3)); -// -// int clipOutputCount = clipOutputLength >> 1; -// float[] clipOutputItems = clipOutput.Items; -// float[] clippedVerticesItems = clippedVertices.Resize(s + clipOutputCount * 2).Items; -// float[] clippedUVsItems = clippedUVs.Resize(s + clipOutputCount * 2).Items; -// for (int ii = 0; ii < clipOutputLength; ii += 2) -// { -// float x = clipOutputItems[ii], y = clipOutputItems[ii + 1]; -// clippedVerticesItems[s] = x; -// clippedVerticesItems[s + 1] = y; -// float c0 = x - x3, c1 = y - y3; -// float a = (d0 * c0 + d1 * c1) * d; -// float b = (d4 * c0 + d2 * c1) * d; -// float 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.Count; -// int[] clippedTrianglesItems = clippedTriangles.Resize(s + 3 * (clipOutputCount - 2)).Items; -// clipOutputCount--; -// for (int ii = 1; ii < clipOutputCount; ii++) -// { -// clippedTrianglesItems[s] = index; -// clippedTrianglesItems[s + 1] = index + ii; -// clippedTrianglesItems[s + 2] = index + ii + 1; -// s += 3; -// } -// index += clipOutputCount + 1; -// } -// else -// { -// float[] clippedVerticesItems = clippedVertices.Resize(s + 3 * 2).Items; -// float[] clippedUVsItems = clippedUVs.Resize(s + 3 * 2).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.Count; -// int[] clippedTrianglesItems = clippedTriangles.Resize(s + 3).Items; -// clippedTrianglesItems[s] = index; -// clippedTrianglesItems[s + 1] = index + 1; -// clippedTrianglesItems[s + 2] = index + 2; -// index += 3; -// break; //continue outer; -// } + int s = static_cast(clippedVertices.size()); + if (clip(x1, y1, x2, y2, x3, y3, *polygons[p], clipOutput)) + { + int clipOutputLength = static_cast(clipOutput.size()); + if (clipOutputLength == 0) + { + continue; + } + float d0 = y2 - y3, d1 = x3 - x2, d2 = x1 - x3, d4 = y3 - y1; + float d = 1 / (d0 * d2 + d1 * (y1 - y3)); + + int clipOutputCount = clipOutputLength >> 1; + clippedVertices.reserve(s + clipOutputCount * 2); + _clippedUVs.reserve(s + clipOutputCount * 2); + for (int ii = 0; ii < clipOutputLength; ii += 2) + { + float x = clipOutput[ii], y = clipOutput[ii + 1]; + clippedVertices[s] = x; + clippedVertices[s + 1] = y; + float c0 = x - x3, c1 = y - y3; + float a = (d0 * c0 + d1 * c1) * d; + float b = (d4 * c0 + d2 * c1) * d; + float c = 1 - a - b; + _clippedUVs[s] = u1 * a + u2 * b + u3 * c; + _clippedUVs[s + 1] = v1 * a + v2 * b + v3 * c; + s += 2; + } + + s = static_cast(clippedTriangles.size()); + clippedTriangles.reserve(s + 3 * (clipOutputCount - 2)); + clipOutputCount--; + for (int ii = 1; ii < clipOutputCount; ii++) + { + clippedTriangles[s] = index; + clippedTriangles[s + 1] = index + ii; + clippedTriangles[s + 2] = index + ii + 1; + s += 3; + } + index += clipOutputCount + 1; + } + else + { + clippedVertices.reserve(s + 3 * 2); + _clippedUVs.reserve(s + 3 * 2); + clippedVertices[s] = x1; + clippedVertices[s + 1] = y1; + clippedVertices[s + 2] = x2; + clippedVertices[s + 3] = y2; + clippedVertices[s + 4] = x3; + clippedVertices[s + 5] = y3; + + _clippedUVs[s] = u1; + _clippedUVs[s + 1] = v1; + _clippedUVs[s + 2] = u2; + _clippedUVs[s + 3] = v2; + _clippedUVs[s + 4] = u3; + _clippedUVs[s + 5] = v3; + + s = static_cast(clippedTriangles.size()); + clippedTriangles.reserve(s + 3); + clippedTriangles[s] = index; + clippedTriangles[s + 1] = index + 1; + clippedTriangles[s + 2] = index + 2; + index += 3; + break; + } } } } @@ -201,105 +201,105 @@ namespace Spine { Vector originalOutput = output; bool clipped = false; -// -// // Avoid copy at the end. -// Vector input = NULL; -// if (clippingArea.Count % 4 >= 2) -// { -// input = output; -// output = scratch; -// } -// else -// { -// input = scratch; -// } -// -// input.Clear(); -// input.push_back(x1); -// input.push_back(y1); -// input.push_back(x2); -// input.push_back(y2); -// input.push_back(x3); -// input.push_back(y3); -// input.push_back(x1); -// input.push_back(y1); -// output.Clear(); -// -// Vector clippingVertices = clippingArea.Items; -// int clippingVerticesLast = clippingArea.Count - 4; -// for (int i = 0; ; i += 2) -// { -// float edgeX = clippingVertices[i], edgeY = clippingVertices[i + 1]; -// float edgeX2 = clippingVertices[i + 2], edgeY2 = clippingVertices[i + 3]; -// float deltaX = edgeX - edgeX2, deltaY = edgeY - edgeY2; -// -// Vector inputVertices = input.Items; -// int inputVerticesLength = input.Count - 2, outputStart = output.Count; -// for (int ii = 0; ii < inputVerticesLength; ii += 2) -// { -// float inputX = inputVertices[ii], inputY = inputVertices[ii + 1]; -// float inputX2 = inputVertices[ii + 2], inputY2 = inputVertices[ii + 3]; -// bool side2 = deltaX * (inputY2 - edgeY2) - deltaY * (inputX2 - edgeX2) > 0; -// if (deltaX * (inputY - edgeY2) - deltaY * (inputX - edgeX2) > 0) -// { -// if (side2) -// { -// // v1 inside, v2 inside -// output.push_back(inputX2); -// output.push_back(inputY2); -// continue; -// } -// // v1 inside, v2 outside -// float c0 = inputY2 - inputY, c2 = inputX2 - inputX; -// float ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / (c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY)); -// output.push_back(edgeX + (edgeX2 - edgeX) * ua); -// output.push_back(edgeY + (edgeY2 - edgeY) * ua); -// } -// else if (side2) -// { -// // v1 outside, v2 inside -// float c0 = inputY2 - inputY, c2 = inputX2 - inputX; -// float ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / (c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY)); -// output.push_back(edgeX + (edgeX2 - edgeX) * ua); -// output.push_back(edgeY + (edgeY2 - edgeY) * ua); -// output.push_back(inputX2); -// output.push_back(inputY2); -// } -// clipped = true; -// } -// -// if (outputStart == output.Count) -// { -// // All edges outside. -// originalOutput.Clear(); -// return true; -// } -// -// output.push_back(output.Items[0]); -// output.push_back(output.Items[1]); -// -// if (i == clippingVerticesLast) -// { -// break; -// } -// var temp = output; -// output = input; -// output.Clear(); -// input = temp; -// } -// -// if (originalOutput != output) -// { -// originalOutput.Clear(); -// for (int i = 0, n = output.Count - 2; i < n; i++) -// { -// originalOutput.push_back(output.Items[i]); -// } -// } -// else -// { -// originalOutput.Resize(originalOutput.Count - 2); -// } + + // Avoid copy at the end. + Vector input; + if (clippingArea.size() % 4 >= 2) + { + input = output; + output = _scratch; + } + else + { + input = _scratch; + } + + input.clear(); + input.push_back(x1); + input.push_back(y1); + input.push_back(x2); + input.push_back(y2); + input.push_back(x3); + input.push_back(y3); + input.push_back(x1); + input.push_back(y1); + output.clear(); + + Vector clippingVertices = clippingArea; + int clippingVerticesLast = static_cast(clippingArea.size()) - 4; + for (int i = 0; ; i += 2) + { + float edgeX = clippingVertices[i], edgeY = clippingVertices[i + 1]; + float edgeX2 = clippingVertices[i + 2], edgeY2 = clippingVertices[i + 3]; + float deltaX = edgeX - edgeX2, deltaY = edgeY - edgeY2; + + Vector inputVertices = input; + int inputVerticesLength = static_cast(input.size()) - 2, outputStart = static_cast(output.size()); + for (int ii = 0; ii < inputVerticesLength; ii += 2) + { + float inputX = inputVertices[ii], inputY = inputVertices[ii + 1]; + float inputX2 = inputVertices[ii + 2], inputY2 = inputVertices[ii + 3]; + bool side2 = deltaX * (inputY2 - edgeY2) - deltaY * (inputX2 - edgeX2) > 0; + if (deltaX * (inputY - edgeY2) - deltaY * (inputX - edgeX2) > 0) + { + if (side2) + { + // v1 inside, v2 inside + output.push_back(inputX2); + output.push_back(inputY2); + continue; + } + // v1 inside, v2 outside + float c0 = inputY2 - inputY, c2 = inputX2 - inputX; + float ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / (c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY)); + output.push_back(edgeX + (edgeX2 - edgeX) * ua); + output.push_back(edgeY + (edgeY2 - edgeY) * ua); + } + else if (side2) + { + // v1 outside, v2 inside + float c0 = inputY2 - inputY, c2 = inputX2 - inputX; + float ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / (c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY)); + output.push_back(edgeX + (edgeX2 - edgeX) * ua); + output.push_back(edgeY + (edgeY2 - edgeY) * ua); + output.push_back(inputX2); + output.push_back(inputY2); + } + clipped = true; + } + + if (outputStart == output.size()) + { + // All edges outside. + originalOutput.clear(); + return true; + } + + output.push_back(output[0]); + output.push_back(output[1]); + + if (i == clippingVerticesLast) + { + break; + } + Vector temp = output; + output = input; + output.clear(); + input = temp; + } + + if (originalOutput != output) + { + originalOutput.clear(); + for (int i = 0, n = static_cast(output.size()) - 2; i < n; ++i) + { + originalOutput.push_back(output[i]); + } + } + else + { + originalOutput.reserve(originalOutput.size() - 2); + } return clipped; } diff --git a/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp b/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp index 01914067f..bb4769cce 100644 --- a/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp @@ -37,6 +37,8 @@ #include #include #include +#include +#include namespace Spine { @@ -53,13 +55,95 @@ namespace Spine const int TransformConstraintTimeline::SCALE = 3; const int TransformConstraintTimeline::SHEAR = 4; + TransformConstraintTimeline::TransformConstraintTimeline(int frameCount) : CurveTimeline(frameCount), _transformConstraintIndex(0) + { + _frames.reserve(frameCount * ENTRIES); + } + void TransformConstraintTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) { - // TODO + TransformConstraint* constraintP = skeleton._transformConstraints[_transformConstraintIndex]; + TransformConstraint& constraint = *constraintP; + + if (time < _frames[0]) + { + switch (pose) + { + case MixPose_Setup: + constraint._rotateMix = constraint._data._rotateMix; + constraint._translateMix = constraint._data._translateMix; + constraint._scaleMix = constraint._data._scaleMix; + constraint._shearMix = constraint._data._shearMix; + return; + case MixPose_Current: + constraint._rotateMix += (constraint._data._rotateMix - constraint._rotateMix) * alpha; + constraint._translateMix += (constraint._data._translateMix - constraint._translateMix) * alpha; + constraint._scaleMix += (constraint._data._scaleMix - constraint._scaleMix) * alpha; + constraint._shearMix += (constraint._data._shearMix - constraint._shearMix) * alpha; + return; + case MixPose_CurrentLayered: + default: + return; + } + } + + float rotate, translate, scale, shear; + if (time >= _frames[_frames.size() - ENTRIES]) + { + // Time is after last frame. + int i = static_cast(_frames.size()); + rotate = _frames[i + PREV_ROTATE]; + translate = _frames[i + PREV_TRANSLATE]; + scale = _frames[i + PREV_SCALE]; + shear = _frames[i + PREV_SHEAR]; + } + else + { + // Interpolate between the previous frame and the current frame. + int frame = Animation::binarySearch(_frames, time, ENTRIES); + rotate = _frames[frame + PREV_ROTATE]; + translate = _frames[frame + PREV_TRANSLATE]; + scale = _frames[frame + PREV_SCALE]; + shear = _frames[frame + PREV_SHEAR]; + float frameTime = _frames[frame]; + float percent = getCurvePercent(frame / ENTRIES - 1, + 1 - (time - frameTime) / (_frames[frame + PREV_TIME] - frameTime)); + + rotate += (_frames[frame + ROTATE] - rotate) * percent; + translate += (_frames[frame + TRANSLATE] - translate) * percent; + scale += (_frames[frame + SCALE] - scale) * percent; + shear += (_frames[frame + SHEAR] - shear) * percent; + } + + if (pose == MixPose_Setup) + { + TransformConstraintData& data = constraint._data; + constraint._rotateMix = data._rotateMix + (rotate - data._rotateMix) * alpha; + constraint._translateMix = data._translateMix + (translate - data._translateMix) * alpha; + constraint._scaleMix = data._scaleMix + (scale - data._scaleMix) * alpha; + constraint._shearMix = data._shearMix + (shear - data._shearMix) * alpha; + } + else + { + constraint._rotateMix += (rotate - constraint._rotateMix) * alpha; + constraint._translateMix += (translate - constraint._translateMix) * alpha; + constraint._scaleMix += (scale - constraint._scaleMix) * alpha; + constraint._shearMix += (shear - constraint._shearMix) * alpha; + } } int TransformConstraintTimeline::getPropertyId() { return ((int)TimelineType_TransformConstraint << 24) + _transformConstraintIndex; } + + void TransformConstraintTimeline::setFrame(int frameIndex, float time, float rotateMix, float translateMix, float scaleMix, float shearMix) + { + frameIndex *= ENTRIES; + _frames[frameIndex] = time; + _frames[frameIndex + ROTATE] = rotateMix; + _frames[frameIndex + TRANSLATE] = translateMix; + _frames[frameIndex + SCALE] = scaleMix; + _frames[frameIndex + SHEAR] = shearMix; + } } diff --git a/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp b/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp index f7ae4abbe..1a886f7d1 100644 --- a/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp @@ -37,18 +37,90 @@ #include #include #include +#include +#include namespace Spine { RTTI_IMPL(TranslateTimeline, CurveTimeline); + const int TranslateTimeline::ENTRIES = 3; + const int TranslateTimeline::PREV_TIME = -3; + const int TranslateTimeline::PREV_X = -2; + const int TranslateTimeline::PREV_Y = -1; + const int TranslateTimeline::X = 1; + const int TranslateTimeline::Y = 2; + + TranslateTimeline::TranslateTimeline(int frameCount) : CurveTimeline(frameCount), _boneIndex(0) + { + _frames.reserve(frameCount * ENTRIES); + } + void TranslateTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) { - // TODO + Bone* boneP = skeleton._bones[_boneIndex]; + Bone& bone = *boneP; + + if (time < _frames[0]) + { + switch (pose) + { + case MixPose_Setup: + bone._x = bone._data._x; + bone._y = bone._data._y; + return; + case MixPose_Current: + bone._x += (bone._data._x - bone._x) * alpha; + bone._y += (bone._data._y - bone._y) * alpha; + return; + case MixPose_CurrentLayered: + default: + return; + } + } + + float x, y; + if (time >= _frames[_frames.size() - ENTRIES]) + { + // Time is after last frame. + x = _frames[_frames.size() + PREV_X]; + y = _frames[_frames.size() + PREV_Y]; + } + else + { + // Interpolate between the previous frame and the current frame. + int frame = Animation::binarySearch(_frames, time, ENTRIES); + x = _frames[frame + PREV_X]; + y = _frames[frame + PREV_Y]; + float frameTime = _frames[frame]; + float percent = getCurvePercent(frame / ENTRIES - 1, 1 - (time - frameTime) / (_frames[frame + PREV_TIME] - frameTime)); + + x += (_frames[frame + X] - x) * percent; + y += (_frames[frame + Y] - y) * percent; + } + + if (pose == MixPose_Setup) + { + bone._x = bone._data._x + x * alpha; + bone._y = bone._data._y + y * alpha; + } + else + { + bone._x += (bone._data._x + x - bone._x) * alpha; + bone._y += (bone._data._y + y - bone._y) * alpha; + } } int TranslateTimeline::getPropertyId() { return ((int)TimelineType_Translate << 24) + _boneIndex; } + + void TranslateTimeline::setFrame(int frameIndex, float time, float x, float y) + { + frameIndex *= ENTRIES; + _frames[frameIndex] = time; + _frames[frameIndex + X] = x; + _frames[frameIndex + Y] = y; + } } diff --git a/spine-cpp/spine-cpp/src/spine/TwoColorTimeline.cpp b/spine-cpp/spine-cpp/src/spine/TwoColorTimeline.cpp index 9f092c488..9003487b4 100644 --- a/spine-cpp/spine-cpp/src/spine/TwoColorTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/TwoColorTimeline.cpp @@ -42,13 +42,169 @@ namespace Spine { RTTI_IMPL(TwoColorTimeline, CurveTimeline); + const int TwoColorTimeline::ENTRIES = 8; + const int TwoColorTimeline::PREV_TIME = -8; + const int TwoColorTimeline::PREV_R = -7; + const int TwoColorTimeline::PREV_G = -6; + const int TwoColorTimeline::PREV_B = -5; + const int TwoColorTimeline::PREV_A = -4; + const int TwoColorTimeline::PREV_R2 = -3; + const int TwoColorTimeline::PREV_G2 = -2; + const int TwoColorTimeline::PREV_B2 = -1; + const int TwoColorTimeline::R = 1; + const int TwoColorTimeline::G = 2; + const int TwoColorTimeline::B = 3; + const int TwoColorTimeline::A = 4; + const int TwoColorTimeline::R2 = 5; + const int TwoColorTimeline::G2 = 6; + const int TwoColorTimeline::B2 = 7; + + TwoColorTimeline::TwoColorTimeline(int frameCount) : CurveTimeline(frameCount) + { + _frames.reserve(frameCount * ENTRIES); + } + void TwoColorTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) { - // TODO + Slot* slotP = skeleton._slots[_slotIndex]; + Slot& slot = *slotP; + + if (time < _frames[0]) + { + // Time is before first frame. + switch (pose) + { + case MixPose_Setup: + slot._r = slot._data._r; + slot._g = slot._data._g; + slot._b = slot._data._b; + slot._a = slot._data._a; + slot._r2 = slot._data._r2; + slot._g2 = slot._data._g2; + slot._b2 = slot._data._b2; + return; + case MixPose_Current: + slot._r += (slot._r - slot._data._r) * alpha; + slot._g += (slot._g - slot._data._g) * alpha; + slot._b += (slot._b - slot._data._b) * alpha; + slot._a += (slot._a - slot._data._a) * alpha; + slot._r2 += (slot._r2 - slot._data._r2) * alpha; + slot._g2 += (slot._g2 - slot._data._g2) * alpha; + slot._b2 += (slot._b2 - slot._data._b2) * alpha; + return; + case MixPose_CurrentLayered: + default: + return; + } + } + + float r, g, b, a, r2, g2, b2; + if (time >= _frames[_frames.size() - ENTRIES]) + { + // Time is after last frame. + int i = static_cast(_frames.size()); + r = _frames[i + PREV_R]; + g = _frames[i + PREV_G]; + b = _frames[i + PREV_B]; + a = _frames[i + PREV_A]; + r2 = _frames[i + PREV_R2]; + g2 = _frames[i + PREV_G2]; + b2 = _frames[i + PREV_B2]; + } + else + { + // Interpolate between the previous frame and the current frame. + int frame = Animation::binarySearch(_frames, time, ENTRIES); + r = _frames[frame + PREV_R]; + g = _frames[frame + PREV_G]; + b = _frames[frame + PREV_B]; + a = _frames[frame + PREV_A]; + r2 = _frames[frame + PREV_R2]; + g2 = _frames[frame + PREV_G2]; + b2 = _frames[frame + PREV_B2]; + float frameTime = _frames[frame]; + float percent = getCurvePercent(frame / ENTRIES - 1, + 1 - (time - frameTime) / (_frames[frame + PREV_TIME] - frameTime)); + + r += (_frames[frame + R] - r) * percent; + g += (_frames[frame + G] - g) * percent; + b += (_frames[frame + B] - b) * percent; + a += (_frames[frame + A] - a) * percent; + r2 += (_frames[frame + R2] - r2) * percent; + g2 += (_frames[frame + G2] - g2) * percent; + b2 += (_frames[frame + B2] - b2) * percent; + } + + if (alpha == 1) + { + slot._r = r; + slot._g = g; + slot._b = b; + slot._a = a; + slot._r2 = r2; + slot._g2 = g2; + slot._b2 = b2; + } + else + { + float br, bg, bb, ba, br2, bg2, bb2; + if (pose == MixPose_Setup) + { + br = slot._data._r; + bg = slot._data._g; + bb = slot._data._b; + ba = slot._data._a; + br2 = slot._data._r2; + bg2 = slot._data._g2; + bb2 = slot._data._b2; + } + else + { + br = slot._r; + bg = slot._g; + bb = slot._b; + ba = slot._a; + br2 = slot._r2; + bg2 = slot._g2; + bb2 = slot._b2; + } + + slot._r = br + ((r - br) * alpha); + slot._g = bg + ((g - bg) * alpha); + slot._b = bb + ((b - bb) * alpha); + slot._a = ba + ((a - ba) * alpha); + slot._r2 = br2 + ((r2 - br2) * alpha); + slot._g2 = bg2 + ((g2 - bg2) * alpha); + slot._b2 = bb2 + ((b2 - bb2) * alpha); + } } int TwoColorTimeline::getPropertyId() { return ((int)TimelineType_TwoColor << 24) + _slotIndex; } + + void TwoColorTimeline::setFrame(int frameIndex, float time, float r, float g, float b, float a, float r2, float g2, float b2) + { + frameIndex *= ENTRIES; + _frames[frameIndex] = time; + _frames[frameIndex + R] = r; + _frames[frameIndex + G] = g; + _frames[frameIndex + B] = b; + _frames[frameIndex + A] = a; + _frames[frameIndex + R2] = r2; + _frames[frameIndex + G2] = g2; + _frames[frameIndex + B2] = b2; + } + + int TwoColorTimeline::getSlotIndex() + { + return _slotIndex; + } + + void TwoColorTimeline::setSlotIndex(int inValue) + { + assert(inValue >= 0); + _slotIndex = inValue; + } } From 676b67b60618ee7136042ecc7b9e7689d4983505 Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Sun, 26 Nov 2017 11:58:07 -0500 Subject: [PATCH 49/83] Adding in the final files, just gotta implement them. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit And then of course, once these final 4 classes are implemented, I’ll have to write the Unit Tests, which I’ll more or less just copy from spine-c --- .../spine-cpp/include/spine/AnimationState.h | 1011 +++++++++++++++++ spine-cpp/spine-cpp/include/spine/Json.h | 39 + .../spine-cpp/include/spine/SkeletonBinary.h | 39 + .../spine-cpp/include/spine/SkeletonJson.h | 39 + .../spine-cpp/src/spine/AnimationState.cpp | 34 + spine-cpp/spine-cpp/src/spine/Json.cpp | 34 + .../spine-cpp/src/spine/SkeletonBinary.cpp | 34 + .../spine-cpp/src/spine/SkeletonJson.cpp | 34 + 8 files changed, 1264 insertions(+) create mode 100644 spine-cpp/spine-cpp/include/spine/AnimationState.h create mode 100644 spine-cpp/spine-cpp/include/spine/Json.h create mode 100644 spine-cpp/spine-cpp/include/spine/SkeletonBinary.h create mode 100644 spine-cpp/spine-cpp/include/spine/SkeletonJson.h create mode 100644 spine-cpp/spine-cpp/src/spine/AnimationState.cpp create mode 100644 spine-cpp/spine-cpp/src/spine/Json.cpp create mode 100644 spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp create mode 100644 spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp diff --git a/spine-cpp/spine-cpp/include/spine/AnimationState.h b/spine-cpp/spine-cpp/include/spine/AnimationState.h new file mode 100644 index 000000000..180103086 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/AnimationState.h @@ -0,0 +1,1011 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_AnimationState_h +#define Spine_AnimationState_h + +namespace Spine +{ + /// State for the playback of an animation + class TrackEntry + { +// internal Animation animation; +// +// internal TrackEntry next, mixingFrom; +// internal int trackIndex; +// +// internal bool loop; +// internal float eventThreshold, attachmentThreshold, drawOrderThreshold; +// internal float animationStart, animationEnd, animationLast, nextAnimationLast; +// internal float delay, trackTime, trackLast, nextTrackLast, trackEnd, timeScale = 1f; +// internal float alpha, mixTime, mixDuration, interruptAlpha, totalAlpha; +// internal readonly ExposedList timelineData = new ExposedList(); +// internal readonly ExposedList timelineDipMix = new ExposedList(); +// internal readonly ExposedList timelinesRotation = new ExposedList(); +// +// void reset () +// { +// next = null; +// mixingFrom = null; +// animation = null; +// timelineData.Clear(); +// timelineDipMix.Clear(); +// timelinesRotation.Clear(); +// +// Start = null; +// Interrupt = null; +// End = null; +// Dispose = null; +// Complete = null; +// Event = null; +// } +// +// /// Sets the timeline data. +// /// May be null. +// internal TrackEntry SetTimelineData (TrackEntry to, ExposedList mixingToArray, HashSet propertyIDs) { +// if (to != null) mixingToArray.Add(to); +// var lastEntry = mixingFrom != null ? mixingFrom.SetTimelineData(this, mixingToArray, propertyIDs) : this; +// if (to != null) mixingToArray.Pop(); +// +// var mixingTo = mixingToArray.Items; +// int mixingToLast = mixingToArray.Count - 1; +// var timelines = animation.timelines.Items; +// int timelinesCount = animation.timelines.Count; +// var timelineDataItems = timelineData.Resize(timelinesCount).Items; // timelineData.setSize(timelinesCount); +// timelineDipMix.Clear(); +// var timelineDipMixItems = timelineDipMix.Resize(timelinesCount).Items; //timelineDipMix.setSize(timelinesCount); +// +// // outer: +// for (int i = 0; i < timelinesCount; i++) { +// int id = timelines[i].PropertyId; +// if (!propertyIDs.Add(id)) { +// timelineDataItems[i] = AnimationState.Subsequent; +// } else if (to == null || !to.HasTimeline(id)) { +// timelineDataItems[i] = AnimationState.First; +// } else { +// for (int ii = mixingToLast; ii >= 0; ii--) { +// var entry = mixingTo[ii]; +// if (!entry.HasTimeline(id)) { +// if (entry.mixDuration > 0) { +// timelineDataItems[i] = AnimationState.DipMix; +// timelineDipMixItems[i] = entry; +// goto continue_outer; // continue outer; +// } +// break; +// } +// } +// timelineDataItems[i] = AnimationState.Dip; +// } +// continue_outer: {} +// } +// return lastEntry; +// } +// +// bool HasTimeline (int id) { +// var timelines = animation.timelines.Items; +// for (int i = 0, n = animation.timelines.Count; i < n; i++) +// if (timelines[i].PropertyId == id) return true; +// return false; +// } +// +// /// The index of the track where this entry is either current or queued. +// public int TrackIndex { get { return trackIndex; } } +// +// /// The animation to apply for this track entry. +// public Animation Animation { get { return animation; } } +// +// /// +// /// If true, the animation will repeat. If false, it will not, instead its last frame is applied if played beyond its duration. +// public bool Loop { get { return loop; } set { loop = value; } } +// +// /// +// /// Seconds to postpone playing the animation. When a track entry is the current track entry, delay postpones incrementing +// /// the track time. When a track entry is queued, delay is the time from the start of the previous animation to when the +// /// track entry will become the current track entry. +// public float Delay { get { return delay; } set { delay = value; } } +// +// /// +// /// Current time in seconds this track entry has been the current track entry. The track time determines +// /// . The track time can be set to start the animation at a time other than 0, without affecting looping. +// public float TrackTime { get { return trackTime; } set { trackTime = value; } } +// +// /// +// /// The track time in seconds when this animation will be removed from the track. Defaults to the animation duration for +// /// non-looping animations and to for looping animations. If the track end time is reached and no +// /// other animations are queued for playback, and mixing from any previous animations is complete, properties keyed by the animation, +// /// are set to the setup pose and the track is cleared. +// /// +// /// It may be desired to use to mix the properties back to the +// /// setup pose over time, rather than have it happen instantly. +// /// +// public float TrackEnd { get { return trackEnd; } set { trackEnd = value; } } +// +// /// +// /// Seconds when this animation starts, both initially and after looping. Defaults to 0. +// /// +// /// When changing the animation start time, it often makes sense to set to the same value to +// /// prevent timeline keys before the start time from triggering. +// /// +// public float AnimationStart { get { return animationStart; } set { animationStart = value; } } +// +// /// +// /// Seconds for the last frame of this animation. Non-looping animations won't play past this time. Looping animations will +// /// loop back to at this time. Defaults to the animation duration. +// public float AnimationEnd { get { return animationEnd; } set { animationEnd = value; } } +// +// /// +// /// The time in seconds this animation was last applied. Some timelines use this for one-time triggers. Eg, when this +// /// animation is applied, event timelines will fire all events between the animation last time (exclusive) and animation time +// /// (inclusive). Defaults to -1 to ensure triggers on frame 0 happen the first time this animation is applied. +// public float AnimationLast { +// get { return animationLast; } +// set { +// animationLast = value; +// nextAnimationLast = value; +// } +// } +// +// /// +// /// Uses to compute the animation time between . and +// /// . When the track time is 0, the animation time is equal to the animation start time. +// /// +// public float AnimationTime { +// get { +// if (loop) { +// float duration = animationEnd - animationStart; +// if (duration == 0) return animationStart; +// return (trackTime % duration) + animationStart; +// } +// return Math.Min(trackTime + animationStart, animationEnd); +// } +// } +// +// /// +// /// Multiplier for the delta time when the animation state is updated, causing time for this animation to play slower or +// /// faster. Defaults to 1. +// /// +// public float TimeScale { get { return timeScale; } set { timeScale = value; } } +// +// /// +// /// Values less than 1 mix this animation with the last skeleton pose. Defaults to 1, which overwrites the last skeleton pose with +// /// this animation. +// /// +// /// Typically track 0 is used to completely pose the skeleton, then alpha can be used on higher tracks. It doesn't make sense +// /// to use alpha on track 0 if the skeleton pose is from the last frame render. +// /// +// public float Alpha { get { return alpha; } set { alpha = value; } } +// +// /// +// /// When the mix percentage (mix time / mix duration) is less than the event threshold, event timelines for the animation +// /// being mixed out will be applied. Defaults to 0, so event timelines are not applied for an animation being mixed out. +// public float EventThreshold { get { return eventThreshold; } set { eventThreshold = value; } } +// +// /// +// /// When the mix percentage (mix time / mix duration) is less than the attachment threshold, attachment timelines for the +// /// animation being mixed out will be applied. Defaults to 0, so attachment timelines are not applied for an animation being +// /// mixed out. +// public float AttachmentThreshold { get { return attachmentThreshold; } set { attachmentThreshold = value; } } +// +// /// +// /// When the mix percentage (mix time / mix duration) is less than the draw order threshold, draw order timelines for the +// /// animation being mixed out will be applied. Defaults to 0, so draw order timelines are not applied for an animation being +// /// mixed out. +// /// +// public float DrawOrderThreshold { get { return drawOrderThreshold; } set { drawOrderThreshold = value; } } +// +// /// +// /// The animation queued to start after this animation, or null. +// public TrackEntry Next { get { return next; } } +// +// /// +// /// Returns true if at least one loop has been completed. +// public bool IsComplete { +// get { return trackTime >= animationEnd - animationStart; } +// } +// +// /// +// /// Seconds from 0 to the mix duration when mixing from the previous animation to this animation. May be slightly more than +// /// when the mix is complete. +// public float MixTime { get { return mixTime; } set { mixTime = value; } } +// +// /// +// /// Seconds for mixing from the previous animation to this animation. Defaults to the value provided by +// /// based on the animation before this animation (if any). +// /// +// /// The mix duration can be set manually rather than use the value from AnimationStateData.GetMix. +// /// In that case, the mixDuration must be set before is next called. +// /// +// /// When using with a +// /// delay less than or equal to 0, note the is set using the mix duration from the +// /// +// /// +// /// +// public float MixDuration { get { return mixDuration; } set { mixDuration = value; } } +// +// /// +// /// The track entry for the previous animation when mixing from the previous animation to this animation, or null if no +// /// mixing is currently occuring. When mixing from multiple animations, MixingFrom makes up a linked list. +// public TrackEntry MixingFrom { get { return mixingFrom; } } +// +// public event AnimationState.TrackEntryDelegate Start, Interrupt, End, Dispose, Complete; +// public event AnimationState.TrackEntryEventDelegate Event; +// internal void OnStart () { if (Start != null) Start(this); } +// internal void OnInterrupt () { if (Interrupt != null) Interrupt(this); } +// internal void OnEnd () { if (End != null) End(this); } +// internal void OnDispose () { if (Dispose != null) Dispose(this); } +// internal void OnComplete () { if (Complete != null) Complete(this); } +// internal void OnEvent (Event e) { if (Event != null) Event(this, e); } +// +// /// +// /// Resets the rotation directions for mixing this entry's rotate timelines. This can be useful to avoid bones rotating the +// /// long way around when using and starting animations on other tracks. +// /// +// /// Mixing involves finding a rotation between two others, which has two possible solutions: the short way or the long way around. +// /// The two rotations likely change over time, so which direction is the short or long way also changes. +// /// If the short way was always chosen, bones would flip to the other side when that direction became the long way. +// /// TrackEntry chooses the short way the first time it is applied and remembers that direction. +// public void ResetRotationDirections () { +// timelinesRotation.Clear(); +// } +// +// override public string ToString () { +// return animation == null ? "" : animation.name; +// } + }; + + class EventQueue + { +// private readonly List eventQueueEntries = new List(); +// internal bool drainDisabled; +// +// private readonly AnimationState state; +// private readonly Pool trackEntryPool; +// internal event Action AnimationsChanged; +// +// internal EventQueue (AnimationState state, Action HandleAnimationsChanged, Pool trackEntryPool) { +// this.state = state; +// this.AnimationsChanged += HandleAnimationsChanged; +// this.trackEntryPool = trackEntryPool; +// } +// +// struct EventQueueEntry { +// public EventType type; +// public TrackEntry entry; +// public Event e; +// +// public EventQueueEntry (EventType eventType, TrackEntry trackEntry, Event e = null) { +// this.type = eventType; +// this.entry = trackEntry; +// this.e = e; +// } +// } +// +// enum EventType { +// Start, Interrupt, End, Dispose, Complete, Event +// } +// +// internal void Start (TrackEntry entry) { +// eventQueueEntries.Add(new EventQueueEntry(EventType.Start, entry)); +// if (AnimationsChanged != null) AnimationsChanged(); +// } +// +// internal void Interrupt (TrackEntry entry) { +// eventQueueEntries.Add(new EventQueueEntry(EventType.Interrupt, entry)); +// } +// +// internal void End (TrackEntry entry) { +// eventQueueEntries.Add(new EventQueueEntry(EventType.End, entry)); +// if (AnimationsChanged != null) AnimationsChanged(); +// } +// +// internal void Dispose (TrackEntry entry) { +// eventQueueEntries.Add(new EventQueueEntry(EventType.Dispose, entry)); +// } +// +// internal void Complete (TrackEntry entry) { +// eventQueueEntries.Add(new EventQueueEntry(EventType.Complete, entry)); +// } +// +// internal void Event (TrackEntry entry, Event e) { +// eventQueueEntries.Add(new EventQueueEntry(EventType.Event, entry, e)); +// } +// +// /// Raises all events in the queue and drains the queue. +// internal void Drain () { +// if (drainDisabled) return; +// drainDisabled = true; +// +// var entries = this.eventQueueEntries; +// AnimationState state = this.state; +// +// // Don't cache entries.Count so callbacks can queue their own events (eg, call SetAnimation in AnimationState_Complete). +// for (int i = 0; i < entries.Count; i++) { +// var queueEntry = entries[i]; +// TrackEntry trackEntry = queueEntry.entry; +// +// switch (queueEntry.type) { +// case EventType.Start: +// trackEntry.OnStart(); +// state.OnStart(trackEntry); +// break; +// case EventType.Interrupt: +// trackEntry.OnInterrupt(); +// state.OnInterrupt(trackEntry); +// break; +// case EventType.End: +// trackEntry.OnEnd(); +// state.OnEnd(trackEntry); +// goto case EventType.Dispose; // Fall through. (C#) +// case EventType.Dispose: +// trackEntry.OnDispose(); +// state.OnDispose(trackEntry); +// trackEntryPool.Free(trackEntry); // Pooling +// break; +// case EventType.Complete: +// trackEntry.OnComplete(); +// state.OnComplete(trackEntry); +// break; +// case EventType.Event: +// trackEntry.OnEvent(queueEntry.e); +// state.OnEvent(trackEntry, queueEntry.e); +// break; +// } +// } +// eventQueueEntries.Clear(); +// +// drainDisabled = false; +// } +// +// internal void Clear () { +// eventQueueEntries.Clear(); +// } + }; + + class AnimationState + { +// static readonly Animation EmptyAnimation = new Animation("", new ExposedList(), 0); +// internal const int Subsequent = 0, First = 1, Dip = 2, DipMix = 3; +// +// private AnimationStateData data; +// +// Pool trackEntryPool = new Pool(); +// private readonly ExposedList tracks = new ExposedList(); +// private readonly ExposedList events = new ExposedList(); +// private readonly EventQueue queue; // Initialized by constructor. +// +// private readonly HashSet propertyIDs = new HashSet(); +// private readonly ExposedList mixingTo = new ExposedList(); +// private bool animationsChanged; +// +// private float timeScale = 1; +// +// public AnimationStateData Data { get { return data; } } +// /// A list of tracks that have animations, which may contain nulls. +// public ExposedList Tracks { get { return tracks; } } +// public float TimeScale { get { return timeScale; } set { timeScale = value; } } +// +// public delegate void TrackEntryDelegate (TrackEntry trackEntry); +// public event TrackEntryDelegate Start, Interrupt, End, Dispose, Complete; +// +// public delegate void TrackEntryEventDelegate (TrackEntry trackEntry, Event e); +// public event TrackEntryEventDelegate Event; +// +// public AnimationState (AnimationStateData data) { +// if (data == null) throw new ArgumentNullException("data", "data cannot be null."); +// this.data = data; +// this.queue = new EventQueue( +// this, +// delegate { this.animationsChanged = true; }, +// trackEntryPool +// ); +// } +// +// /// +// /// Increments the track entry times, setting queued animations as current if needed +// /// delta time +// public void Update (float delta) { +// delta *= timeScale; +// var tracksItems = tracks.Items; +// for (int i = 0, n = tracks.Count; i < n; i++) { +// TrackEntry current = tracksItems[i]; +// if (current == null) continue; +// +// current.animationLast = current.nextAnimationLast; +// current.trackLast = current.nextTrackLast; +// +// float currentDelta = delta * current.timeScale; +// +// if (current.delay > 0) { +// current.delay -= currentDelta; +// if (current.delay > 0) continue; +// currentDelta = -current.delay; +// current.delay = 0; +// } +// +// TrackEntry next = current.next; +// if (next != null) { +// // When the next entry's delay is passed, change to the next entry, preserving leftover time. +// float nextTime = current.trackLast - next.delay; +// if (nextTime >= 0) { +// next.delay = 0; +// next.trackTime = nextTime + (delta * next.timeScale); +// current.trackTime += currentDelta; +// SetCurrent(i, next, true); +// while (next.mixingFrom != null) { +// next.mixTime += currentDelta; +// next = next.mixingFrom; +// } +// continue; +// } +// } else if (current.trackLast >= current.trackEnd && current.mixingFrom == null) { +// // Clear the track when there is no next entry, the track end time is reached, and there is no mixingFrom. +// tracksItems[i] = null; +// +// queue.End(current); +// DisposeNext(current); +// continue; +// } +// if (current.mixingFrom != null && UpdateMixingFrom(current, delta)) { +// // End mixing from entries once all have completed. +// var from = current.mixingFrom; +// current.mixingFrom = null; +// while (from != null) { +// queue.End(from); +// from = from.mixingFrom; +// } +// } +// +// current.trackTime += currentDelta; +// } +// +// queue.Drain(); +// } +// +// /// Returns true when all mixing from entries are complete. +// private bool UpdateMixingFrom (TrackEntry to, float delta) { +// TrackEntry from = to.mixingFrom; +// if (from == null) return true; +// +// bool finished = UpdateMixingFrom(from, delta); +// +// // Require mixTime > 0 to ensure the mixing from entry was applied at least once. +// if (to.mixTime > 0 && (to.mixTime >= to.mixDuration || to.timeScale == 0)) { +// // Require totalAlpha == 0 to ensure mixing is complete, unless mixDuration == 0 (the transition is a single frame). +// if (from.totalAlpha == 0 || to.mixDuration == 0) { +// to.mixingFrom = from.mixingFrom; +// to.interruptAlpha = from.interruptAlpha; +// queue.End(from); +// } +// return finished; +// } +// +// from.animationLast = from.nextAnimationLast; +// from.trackLast = from.nextTrackLast; +// from.trackTime += delta * from.timeScale; +// to.mixTime += delta * to.timeScale; +// return false; +// } +// +// /// +// /// Poses the skeleton using the track entry animations. There are no side effects other than invoking listeners, so the +// /// animation state can be applied to multiple skeletons to pose them identically. +// public bool Apply (Skeleton skeleton) { +// if (skeleton == null) throw new ArgumentNullException("skeleton", "skeleton cannot be null."); +// if (animationsChanged) AnimationsChanged(); +// +// var events = this.events; +// +// bool applied = false; +// var tracksItems = tracks.Items; +// for (int i = 0, m = tracks.Count; i < m; i++) { +// TrackEntry current = tracksItems[i]; +// if (current == null || current.delay > 0) continue; +// applied = true; +// MixPose currentPose = i == 0 ? MixPose.Current : MixPose.CurrentLayered; +// +// // Apply mixing from entries first. +// float mix = current.alpha; +// if (current.mixingFrom != null) +// mix *= ApplyMixingFrom(current, skeleton, currentPose); +// else if (current.trackTime >= current.trackEnd && current.next == null) // +// mix = 0; // Set to setup pose the last time the entry will be applied. +// +// // Apply current entry. +// float animationLast = current.animationLast, animationTime = current.AnimationTime; +// int timelineCount = current.animation.timelines.Count; +// var timelines = current.animation.timelines; +// var timelinesItems = timelines.Items; +// if (mix == 1) { +// for (int ii = 0; ii < timelineCount; ii++) +// timelinesItems[ii].Apply(skeleton, animationLast, animationTime, events, 1, MixPose.Setup, MixDirection.In); +// } else { +// var timelineData = current.timelineData.Items; +// +// bool firstFrame = current.timelinesRotation.Count == 0; +// if (firstFrame) current.timelinesRotation.EnsureCapacity(timelines.Count << 1); +// var timelinesRotation = current.timelinesRotation.Items; +// +// for (int ii = 0; ii < timelineCount; ii++) { +// Timeline timeline = timelinesItems[ii]; +// MixPose pose = timelineData[ii] >= AnimationState.First ? MixPose.Setup : currentPose; +// var rotateTimeline = timeline as RotateTimeline; +// if (rotateTimeline != null) +// ApplyRotateTimeline(rotateTimeline, skeleton, animationTime, mix, pose, timelinesRotation, ii << 1, firstFrame); +// else +// timeline.Apply(skeleton, animationLast, animationTime, events, mix, pose, MixDirection.In); +// } +// } +// QueueEvents(current, animationTime); +// events.Clear(false); +// current.nextAnimationLast = animationTime; +// current.nextTrackLast = current.trackTime; +// } +// +// queue.Drain(); +// return applied; +// } +// +// private float ApplyMixingFrom (TrackEntry to, Skeleton skeleton, MixPose currentPose) { +// TrackEntry from = to.mixingFrom; +// if (from.mixingFrom != null) ApplyMixingFrom(from, skeleton, currentPose); +// +// float mix; +// if (to.mixDuration == 0) { // Single frame mix to undo mixingFrom changes. +// mix = 1; +// currentPose = MixPose.Setup; +// } else { +// mix = to.mixTime / to.mixDuration; +// if (mix > 1) mix = 1; +// } +// +// var eventBuffer = mix < from.eventThreshold ? this.events : null; +// bool attachments = mix < from.attachmentThreshold, drawOrder = mix < from.drawOrderThreshold; +// float animationLast = from.animationLast, animationTime = from.AnimationTime; +// var timelines = from.animation.timelines; +// int timelineCount = timelines.Count; +// var timelinesItems = timelines.Items; +// var timelineData = from.timelineData.Items; +// var timelineDipMix = from.timelineDipMix.Items; +// +// bool firstFrame = from.timelinesRotation.Count == 0; +// if (firstFrame) from.timelinesRotation.Resize(timelines.Count << 1); // from.timelinesRotation.setSize +// var timelinesRotation = from.timelinesRotation.Items; +// +// MixPose pose; +// float alphaDip = from.alpha * to.interruptAlpha, alphaMix = alphaDip * (1 - mix), alpha; +// from.totalAlpha = 0; +// for (int i = 0; i < timelineCount; i++) { +// Timeline timeline = timelinesItems[i]; +// switch (timelineData[i]) { +// case Subsequent: +// if (!attachments && timeline is AttachmentTimeline) continue; +// if (!drawOrder && timeline is DrawOrderTimeline) continue; +// pose = currentPose; +// alpha = alphaMix; +// break; +// case First: +// pose = MixPose.Setup; +// alpha = alphaMix; +// break; +// case Dip: +// pose = MixPose.Setup; +// alpha = alphaDip; +// break; +// default: +// pose = MixPose.Setup; +// TrackEntry dipMix = timelineDipMix[i]; +// alpha = alphaDip * Math.Max(0, 1 - dipMix.mixTime / dipMix.mixDuration); +// break; +// } +// from.totalAlpha += alpha; +// var rotateTimeline = timeline as RotateTimeline; +// if (rotateTimeline != null) { +// ApplyRotateTimeline(rotateTimeline, skeleton, animationTime, alpha, pose, timelinesRotation, i << 1, firstFrame); +// } else { +// timeline.Apply(skeleton, animationLast, animationTime, eventBuffer, alpha, pose, MixDirection.Out); +// } +// } +// +// if (to.mixDuration > 0) QueueEvents(from, animationTime); +// this.events.Clear(false); +// from.nextAnimationLast = animationTime; +// from.nextTrackLast = from.trackTime; +// +// return mix; +// } +// +// static private void ApplyRotateTimeline (RotateTimeline rotateTimeline, Skeleton skeleton, float time, float alpha, MixPose pose, +// float[] timelinesRotation, int i, bool firstFrame) { +// +// if (firstFrame) timelinesRotation[i] = 0; +// +// if (alpha == 1) { +// rotateTimeline.Apply(skeleton, 0, time, null, 1, pose, MixDirection.In); +// return; +// } +// +// Bone bone = skeleton.bones.Items[rotateTimeline.boneIndex]; +// float[] frames = rotateTimeline.frames; +// if (time < frames[0]) { +// if (pose == MixPose.Setup) bone.rotation = bone.data.rotation; +// return; +// } +// +// float r2; +// if (time >= frames[frames.Length - RotateTimeline.ENTRIES]) // Time is after last frame. +// r2 = bone.data.rotation + frames[frames.Length + RotateTimeline.PREV_ROTATION]; +// else { +// // Interpolate between the previous frame and the current frame. +// int frame = Animation.BinarySearch(frames, time, RotateTimeline.ENTRIES); +// float prevRotation = frames[frame + RotateTimeline.PREV_ROTATION]; +// float frameTime = frames[frame]; +// float percent = rotateTimeline.GetCurvePercent((frame >> 1) - 1, +// 1 - (time - frameTime) / (frames[frame + RotateTimeline.PREV_TIME] - frameTime)); +// +// r2 = frames[frame + RotateTimeline.ROTATION] - prevRotation; +// r2 -= (16384 - (int)(16384.499999999996 - r2 / 360)) * 360; +// r2 = prevRotation + r2 * percent + bone.data.rotation; +// r2 -= (16384 - (int)(16384.499999999996 - r2 / 360)) * 360; +// } +// +// // Mix between rotations using the direction of the shortest route on the first frame while detecting crosses. +// float r1 = pose == MixPose.Setup ? bone.data.rotation : bone.rotation; +// float total, diff = r2 - r1; +// if (diff == 0) { +// total = timelinesRotation[i]; +// } else { +// diff -= (16384 - (int)(16384.499999999996 - diff / 360)) * 360; +// float lastTotal, lastDiff; +// if (firstFrame) { +// lastTotal = 0; +// lastDiff = diff; +// } else { +// lastTotal = timelinesRotation[i]; // Angle and direction of mix, including loops. +// lastDiff = timelinesRotation[i + 1]; // Difference between bones. +// } +// bool current = diff > 0, dir = lastTotal >= 0; +// // Detect cross at 0 (not 180). +// if (Math.Sign(lastDiff) != Math.Sign(diff) && Math.Abs(lastDiff) <= 90) { +// // A cross after a 360 rotation is a loop. +// if (Math.Abs(lastTotal) > 180) lastTotal += 360 * Math.Sign(lastTotal); +// dir = current; +// } +// total = diff + lastTotal - lastTotal % 360; // Store loops as part of lastTotal. +// if (dir != current) total += 360 * Math.Sign(lastTotal); +// timelinesRotation[i] = total; +// } +// timelinesRotation[i + 1] = diff; +// r1 += total * alpha; +// bone.rotation = r1 - (16384 - (int)(16384.499999999996 - r1 / 360)) * 360; +// } +// +// private void QueueEvents (TrackEntry entry, float animationTime) { +// float animationStart = entry.animationStart, animationEnd = entry.animationEnd; +// float duration = animationEnd - animationStart; +// float trackLastWrapped = entry.trackLast % duration; +// +// // Queue events before complete. +// var events = this.events; +// var eventsItems = events.Items; +// int i = 0, n = events.Count; +// for (; i < n; i++) { +// var e = eventsItems[i]; +// if (e.time < trackLastWrapped) break; +// if (e.time > animationEnd) continue; // Discard events outside animation start/end. +// queue.Event(entry, e); +// } +// +// // Queue complete if completed a loop iteration or the animation. +// if (entry.loop ? (trackLastWrapped > entry.trackTime % duration) +// : (animationTime >= animationEnd && entry.animationLast < animationEnd)) { +// queue.Complete(entry); +// } +// +// // Queue events after complete. +// for (; i < n; i++) { +// Event e = eventsItems[i]; +// if (e.time < animationStart) continue; // Discard events outside animation start/end. +// queue.Event(entry, eventsItems[i]); +// } +// } +// +// /// +// /// Removes all animations from all tracks, leaving skeletons in their previous pose. +// /// It may be desired to use to mix the skeletons back to the setup pose, +// /// rather than leaving them in their previous pose. +// public void ClearTracks () { +// bool oldDrainDisabled = queue.drainDisabled; +// queue.drainDisabled = true; +// for (int i = 0, n = tracks.Count; i < n; i++) { +// ClearTrack(i); +// } +// tracks.Clear(); +// queue.drainDisabled = oldDrainDisabled; +// queue.Drain(); +// } +// +// /// +// /// Removes all animations from the tracks, leaving skeletons in their previous pose. +// /// It may be desired to use to mix the skeletons back to the setup pose, +// /// rather than leaving them in their previous pose. +// public void ClearTrack (int trackIndex) { +// if (trackIndex >= tracks.Count) return; +// TrackEntry current = tracks.Items[trackIndex]; +// if (current == null) return; +// +// queue.End(current); +// +// DisposeNext(current); +// +// TrackEntry entry = current; +// while (true) { +// TrackEntry from = entry.mixingFrom; +// if (from == null) break; +// queue.End(from); +// entry.mixingFrom = null; +// entry = from; +// } +// +// tracks.Items[current.trackIndex] = null; +// +// queue.Drain(); +// } +// +// /// Sets the active TrackEntry for a given track number. +// private void SetCurrent (int index, TrackEntry current, bool interrupt) { +// TrackEntry from = ExpandToIndex(index); +// tracks.Items[index] = current; +// +// if (from != null) { +// if (interrupt) queue.Interrupt(from); +// current.mixingFrom = from; +// current.mixTime = 0; +// +// // Store interrupted mix percentage. +// if (from.mixingFrom != null && from.mixDuration > 0) +// current.interruptAlpha *= Math.Min(1, from.mixTime / from.mixDuration); +// +// from.timelinesRotation.Clear(); // Reset rotation for mixing out, in case entry was mixed in. +// } +// +// queue.Start(current); // triggers AnimationsChanged +// } +// +// +// /// Sets an animation by name. +// public TrackEntry SetAnimation (int trackIndex, string animationName, bool loop) { +// Animation animation = data.skeletonData.FindAnimation(animationName); +// if (animation == null) throw new ArgumentException("Animation not found: " + animationName, "animationName"); +// return SetAnimation(trackIndex, animation, loop); +// } +// +// /// Sets the current animation for a track, discarding any queued animations. +// /// If true, the animation will repeat. +// /// If false, it will not, instead its last frame is applied if played beyond its duration. +// /// In either case determines when the track is cleared. +// /// +// /// A track entry to allow further customization of animation playback. References to the track entry must not be kept +// /// after . +// public TrackEntry SetAnimation (int trackIndex, Animation animation, bool loop) { +// if (animation == null) throw new ArgumentNullException("animation", "animation cannot be null."); +// bool interrupt = true; +// TrackEntry current = ExpandToIndex(trackIndex); +// if (current != null) { +// if (current.nextTrackLast == -1) { +// // Don't mix from an entry that was never applied. +// tracks.Items[trackIndex] = current.mixingFrom; +// queue.Interrupt(current); +// queue.End(current); +// DisposeNext(current); +// current = current.mixingFrom; +// interrupt = false; +// } else { +// DisposeNext(current); +// } +// } +// TrackEntry entry = NewTrackEntry(trackIndex, animation, loop, current); +// SetCurrent(trackIndex, entry, interrupt); +// queue.Drain(); +// return entry; +// } +// +// /// Queues an animation by name. +// /// +// public TrackEntry AddAnimation (int trackIndex, string animationName, bool loop, float delay) { +// Animation animation = data.skeletonData.FindAnimation(animationName); +// if (animation == null) throw new ArgumentException("Animation not found: " + animationName, "animationName"); +// return AddAnimation(trackIndex, animation, loop, delay); +// } +// +// /// Adds an animation to be played delay seconds after the current or last queued animation +// /// for a track. If the track is empty, it is equivalent to calling . +// /// +// /// Seconds to begin this animation after the start of the previous animation. May be <= 0 to use the animation +// /// duration of the previous track minus any mix duration plus the negative delay. +// /// +// /// A track entry to allow further customization of animation playback. References to the track entry must not be kept +// /// after +// public TrackEntry AddAnimation (int trackIndex, Animation animation, bool loop, float delay) { +// if (animation == null) throw new ArgumentNullException("animation", "animation cannot be null."); +// +// TrackEntry last = ExpandToIndex(trackIndex); +// if (last != null) { +// while (last.next != null) +// last = last.next; +// } +// +// TrackEntry entry = NewTrackEntry(trackIndex, animation, loop, last); +// +// if (last == null) { +// SetCurrent(trackIndex, entry, true); +// queue.Drain(); +// } else { +// last.next = entry; +// if (delay <= 0) { +// float duration = last.animationEnd - last.animationStart; +// if (duration != 0) +// delay += duration * (1 + (int)(last.trackTime / duration)) - data.GetMix(last.animation, animation); +// else +// delay = 0; +// } +// } +// +// entry.delay = delay; +// return entry; +// } +// +// /// +// /// Sets an empty animation for a track, discarding any queued animations, and mixes to it over the specified mix duration. +// public TrackEntry SetEmptyAnimation (int trackIndex, float mixDuration) { +// TrackEntry entry = SetAnimation(trackIndex, AnimationState.EmptyAnimation, false); +// entry.mixDuration = mixDuration; +// entry.trackEnd = mixDuration; +// return entry; +// } +// +// /// +// /// Adds an empty animation to be played after the current or last queued animation for a track, and mixes to it over the +// /// specified mix duration. +// /// +// /// A track entry to allow further customization of animation playback. References to the track entry must not be kept after . +// /// +// /// Track number. +// /// Mix duration. +// /// Seconds to begin this animation after the start of the previous animation. May be <= 0 to use the animation +// /// duration of the previous track minus any mix duration plus the negative delay. +// public TrackEntry AddEmptyAnimation (int trackIndex, float mixDuration, float delay) { +// if (delay <= 0) delay -= mixDuration; +// TrackEntry entry = AddAnimation(trackIndex, AnimationState.EmptyAnimation, false, delay); +// entry.mixDuration = mixDuration; +// entry.trackEnd = mixDuration; +// return entry; +// } +// +// /// +// /// Sets an empty animation for every track, discarding any queued animations, and mixes to it over the specified mix duration. +// public void SetEmptyAnimations (float mixDuration) { +// bool oldDrainDisabled = queue.drainDisabled; +// queue.drainDisabled = true; +// for (int i = 0, n = tracks.Count; i < n; i++) { +// TrackEntry current = tracks.Items[i]; +// if (current != null) SetEmptyAnimation(i, mixDuration); +// } +// queue.drainDisabled = oldDrainDisabled; +// queue.Drain(); +// } +// +// private TrackEntry ExpandToIndex (int index) { +// if (index < tracks.Count) return tracks.Items[index]; +// while (index >= tracks.Count) +// tracks.Add(null); +// return null; +// } +// +// /// Object-pooling version of new TrackEntry. Obtain an unused TrackEntry from the pool and clear/initialize its values. +// /// May be null. +// private TrackEntry NewTrackEntry (int trackIndex, Animation animation, bool loop, TrackEntry last) { +// TrackEntry entry = trackEntryPool.Obtain(); // Pooling +// entry.trackIndex = trackIndex; +// entry.animation = animation; +// entry.loop = loop; +// +// entry.eventThreshold = 0; +// entry.attachmentThreshold = 0; +// entry.drawOrderThreshold = 0; +// +// entry.animationStart = 0; +// entry.animationEnd = animation.Duration; +// entry.animationLast = -1; +// entry.nextAnimationLast = -1; +// +// entry.delay = 0; +// entry.trackTime = 0; +// entry.trackLast = -1; +// entry.nextTrackLast = -1; // nextTrackLast == -1 signifies a TrackEntry that wasn't applied yet. +// entry.trackEnd = float.MaxValue; // loop ? float.MaxValue : animation.Duration; +// entry.timeScale = 1; +// +// entry.alpha = 1; +// entry.interruptAlpha = 1; +// entry.mixTime = 0; +// entry.mixDuration = (last == null) ? 0 : data.GetMix(last.animation, animation); +// return entry; +// } +// +// /// Dispose all track entries queued after the given TrackEntry. +// private void DisposeNext (TrackEntry entry) { +// TrackEntry next = entry.next; +// while (next != null) { +// queue.Dispose(next); +// next = next.next; +// } +// entry.next = null; +// } +// +// private void AnimationsChanged () { +// animationsChanged = false; +// +// var propertyIDs = this.propertyIDs; +// propertyIDs.Clear(); +// var mixingTo = this.mixingTo; +// +// var tracksItems = tracks.Items; +// for (int i = 0, n = tracks.Count; i < n; i++) { +// var entry = tracksItems[i]; +// if (entry != null) entry.SetTimelineData(null, mixingTo, propertyIDs); +// } +// } +// +// /// The track entry for the animation currently playing on the track, or null if no animation is currently playing. +// public TrackEntry GetCurrent (int trackIndex) { +// return (trackIndex >= tracks.Count) ? null : tracks.Items[trackIndex]; +// } +// +// override public string ToString () { +// var buffer = new System.Text.StringBuilder(); +// for (int i = 0, n = tracks.Count; i < n; i++) { +// TrackEntry entry = tracks.Items[i]; +// if (entry == null) continue; +// if (buffer.Length > 0) buffer.Append(", "); +// buffer.Append(entry.ToString()); +// } +// return buffer.Length == 0 ? "" : buffer.ToString(); +// } +// +// internal void OnStart (TrackEntry entry) { if (Start != null) Start(entry); } +// internal void OnInterrupt (TrackEntry entry) { if (Interrupt != null) Interrupt(entry); } +// internal void OnEnd (TrackEntry entry) { if (End != null) End(entry); } +// internal void OnDispose (TrackEntry entry) { if (Dispose != null) Dispose(entry); } +// internal void OnComplete (TrackEntry entry) { if (Complete != null) Complete(entry); } +// internal void OnEvent (TrackEntry entry, Event e) { if (Event != null) Event(entry, e); } + }; +} + +#endif /* Spine_AnimationState_h */ diff --git a/spine-cpp/spine-cpp/include/spine/Json.h b/spine-cpp/spine-cpp/include/spine/Json.h new file mode 100644 index 000000000..0e8b64a41 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/Json.h @@ -0,0 +1,39 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Json_h +#define Spine_Json_h + +namespace Spine +{ + // TODO +} + +#endif /* Spine_Json_h */ diff --git a/spine-cpp/spine-cpp/include/spine/SkeletonBinary.h b/spine-cpp/spine-cpp/include/spine/SkeletonBinary.h new file mode 100644 index 000000000..cbb6b01c1 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/SkeletonBinary.h @@ -0,0 +1,39 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_SkeletonBinary_h +#define Spine_SkeletonBinary_h + +namespace Spine +{ + // TODO +} + +#endif /* Spine_SkeletonBinary_h */ diff --git a/spine-cpp/spine-cpp/include/spine/SkeletonJson.h b/spine-cpp/spine-cpp/include/spine/SkeletonJson.h new file mode 100644 index 000000000..1ee1568b5 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/SkeletonJson.h @@ -0,0 +1,39 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_SkeletonJson_h +#define Spine_SkeletonJson_h + +namespace Spine +{ + // TODO +} + +#endif /* Spine_SkeletonJson_h */ diff --git a/spine-cpp/spine-cpp/src/spine/AnimationState.cpp b/spine-cpp/spine-cpp/src/spine/AnimationState.cpp new file mode 100644 index 000000000..bb4d2ccfe --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/AnimationState.cpp @@ -0,0 +1,34 @@ +/****************************************************************************** +* Spine Runtimes Software License v2.5 +* +* Copyright (c) 2013-2016, Esoteric Software +* All rights reserved. +* +* You are granted a perpetual, non-exclusive, non-sublicensable, and +* non-transferable license to use, install, execute, and perform the Spine +* Runtimes software and derivative works solely for personal or internal +* use. Without the written permission of Esoteric Software (see Section 2 of +* the Spine Software License Agreement), you may not (a) modify, translate, +* adapt, or develop new applications using the Spine Runtimes or otherwise +* create derivative works or improvements of the Spine Runtimes or (b) remove, +* delete, alter, or obscure any trademarks or any copyright, trademark, patent, +* or other intellectual property or proprietary rights notices on or in the +* Software, including any copy thereof. Redistributions in binary or source +* form must include this license and terms. +* +* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +namespace Spine +{ + // TODO +} diff --git a/spine-cpp/spine-cpp/src/spine/Json.cpp b/spine-cpp/spine-cpp/src/spine/Json.cpp new file mode 100644 index 000000000..bb4d2ccfe --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/Json.cpp @@ -0,0 +1,34 @@ +/****************************************************************************** +* Spine Runtimes Software License v2.5 +* +* Copyright (c) 2013-2016, Esoteric Software +* All rights reserved. +* +* You are granted a perpetual, non-exclusive, non-sublicensable, and +* non-transferable license to use, install, execute, and perform the Spine +* Runtimes software and derivative works solely for personal or internal +* use. Without the written permission of Esoteric Software (see Section 2 of +* the Spine Software License Agreement), you may not (a) modify, translate, +* adapt, or develop new applications using the Spine Runtimes or otherwise +* create derivative works or improvements of the Spine Runtimes or (b) remove, +* delete, alter, or obscure any trademarks or any copyright, trademark, patent, +* or other intellectual property or proprietary rights notices on or in the +* Software, including any copy thereof. Redistributions in binary or source +* form must include this license and terms. +* +* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +namespace Spine +{ + // TODO +} diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp b/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp new file mode 100644 index 000000000..bb4d2ccfe --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp @@ -0,0 +1,34 @@ +/****************************************************************************** +* Spine Runtimes Software License v2.5 +* +* Copyright (c) 2013-2016, Esoteric Software +* All rights reserved. +* +* You are granted a perpetual, non-exclusive, non-sublicensable, and +* non-transferable license to use, install, execute, and perform the Spine +* Runtimes software and derivative works solely for personal or internal +* use. Without the written permission of Esoteric Software (see Section 2 of +* the Spine Software License Agreement), you may not (a) modify, translate, +* adapt, or develop new applications using the Spine Runtimes or otherwise +* create derivative works or improvements of the Spine Runtimes or (b) remove, +* delete, alter, or obscure any trademarks or any copyright, trademark, patent, +* or other intellectual property or proprietary rights notices on or in the +* Software, including any copy thereof. Redistributions in binary or source +* form must include this license and terms. +* +* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +namespace Spine +{ + // TODO +} diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp b/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp new file mode 100644 index 000000000..bb4d2ccfe --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp @@ -0,0 +1,34 @@ +/****************************************************************************** +* Spine Runtimes Software License v2.5 +* +* Copyright (c) 2013-2016, Esoteric Software +* All rights reserved. +* +* You are granted a perpetual, non-exclusive, non-sublicensable, and +* non-transferable license to use, install, execute, and perform the Spine +* Runtimes software and derivative works solely for personal or internal +* use. Without the written permission of Esoteric Software (see Section 2 of +* the Spine Software License Agreement), you may not (a) modify, translate, +* adapt, or develop new applications using the Spine Runtimes or otherwise +* create derivative works or improvements of the Spine Runtimes or (b) remove, +* delete, alter, or obscure any trademarks or any copyright, trademark, patent, +* or other intellectual property or proprietary rights notices on or in the +* Software, including any copy thereof. Redistributions in binary or source +* form must include this license and terms. +* +* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +namespace Spine +{ + // TODO +} From 3e94e53a4cd20e6eeb03c70174d248ed8d16570a Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Sun, 26 Nov 2017 12:06:41 -0500 Subject: [PATCH 50/83] Adding spine-cpp-unit-tests dir --- spine-cpp/spine-cpp-unit-tests/main.cpp | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100755 spine-cpp/spine-cpp-unit-tests/main.cpp diff --git a/spine-cpp/spine-cpp-unit-tests/main.cpp b/spine-cpp/spine-cpp-unit-tests/main.cpp new file mode 100755 index 000000000..f4343cab2 --- /dev/null +++ b/spine-cpp/spine-cpp-unit-tests/main.cpp @@ -0,0 +1,7 @@ +#include + +int main(int argc, const char * argv[]) +{ + std::cout << "Awww yeah, gonna test some stuff here eventually!\n"; + return 0; +} From 1361203f1cbb3cd48fb7148957682d3d0c0625b7 Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Sun, 26 Nov 2017 18:25:56 -0500 Subject: [PATCH 51/83] wip --- .../spine-cpp/include/spine/AnimationState.h | 745 +++++++++--------- .../include/spine/RegionAttachment.h | 2 +- .../spine-cpp/src/spine/AnimationState.cpp | 94 ++- .../src/spine/AnimationStateData.cpp | 2 +- .../src/spine/ClippingAttachment.cpp | 2 +- .../spine-cpp/src/spine/PathAttachment.cpp | 2 +- .../spine-cpp/src/spine/PointAttachment.cpp | 2 +- .../spine-cpp/src/spine/RegionAttachment.cpp | 25 +- .../spine-cpp/src/spine/SkeletonClipping.cpp | 2 +- .../spine-cpp/src/spine/TwoColorTimeline.cpp | 2 +- 10 files changed, 494 insertions(+), 384 deletions(-) diff --git a/spine-cpp/spine-cpp/include/spine/AnimationState.h b/spine-cpp/spine-cpp/include/spine/AnimationState.h index 180103086..ad2783094 100644 --- a/spine-cpp/spine-cpp/include/spine/AnimationState.h +++ b/spine-cpp/spine-cpp/include/spine/AnimationState.h @@ -31,47 +31,188 @@ #ifndef Spine_AnimationState_h #define Spine_AnimationState_h +#include + namespace Spine { + class Animation; + /// State for the playback of an animation class TrackEntry { -// internal Animation animation; + public: + TrackEntry(); + + /// The index of the track where this entry is either current or queued. + int getTrackIndex(); + + /// The animation to apply for this track entry. + Animation* getAnimation(); + + /// + /// If true, the animation will repeat. If false, it will not, instead its last frame is applied if played beyond its duration. + bool getLoop(); + void setLoop(bool inValue); + + /// + /// Seconds to postpone playing the animation. When a track entry is the current track entry, delay postpones incrementing + /// the track time. When a track entry is queued, delay is the time from the start of the previous animation to when the + /// track entry will become the current track entry. + float getDelay(); + void setDelay(float inValue); + + /// + /// Current time in seconds this track entry has been the current track entry. The track time determines + /// TrackEntry.AnimationTime. The track time can be set to start the animation at a time other than 0, without affecting looping. + float getTrackTime(); + void setTrackTime(float inValue); + + /// + /// The track time in seconds when this animation will be removed from the track. Defaults to the animation duration for + /// non-looping animations and to int.MaxValue for looping animations. If the track end time is reached and no + /// other animations are queued for playback, and mixing from any previous animations is complete, properties keyed by the animation, + /// are set to the setup pose and the track is cleared. + /// + /// It may be desired to use AnimationState.addEmptyAnimation(int, float, float) to mix the properties back to the + /// setup pose over time, rather than have it happen instantly. + /// + float getTrackEnd(); + void setTrackEnd(float inValue); + + /// + /// Seconds when this animation starts, both initially and after looping. Defaults to 0. + /// + /// When changing the animation start time, it often makes sense to set TrackEntry.AnimationLast to the same value to + /// prevent timeline keys before the start time from triggering. + /// + float getAnimationStart(); + void setAnimationStart(float inValue); + + /// + /// Seconds for the last frame of this animation. Non-looping animations won't play past this time. Looping animations will + /// loop back to TrackEntry.AnimationStart at this time. Defaults to the animation duration. + float getAnimationEnd(); + void setAnimationEnd(float inValue); + + /// + /// The time in seconds this animation was last applied. Some timelines use this for one-time triggers. Eg, when this + /// animation is applied, event timelines will fire all events between the animation last time (exclusive) and animation time + /// (inclusive). Defaults to -1 to ensure triggers on frame 0 happen the first time this animation is applied. + float getAnimationLast(); + void setAnimationLast(float inValue); + + /// + /// Uses TrackEntry.TrackTime to compute the animation time between TrackEntry.AnimationStart. and + /// TrackEntry.AnimationEnd. When the track time is 0, the animation time is equal to the animation start time. + /// + float getAnimationTime(); + + /// + /// Multiplier for the delta time when the animation state is updated, causing time for this animation to play slower or + /// faster. Defaults to 1. + /// + float getTimeScale(); + void setTimeScale(float inValue); + + /// + /// Values less than 1 mix this animation with the last skeleton pose. Defaults to 1, which overwrites the last skeleton pose with + /// this animation. + /// + /// Typically track 0 is used to completely pose the skeleton, then alpha can be used on higher tracks. It doesn't make sense + /// to use alpha on track 0 if the skeleton pose is from the last frame render. + /// + float getAlpha(); + void setAlpha(float inValue); + + /// + /// When the mix percentage (mix time / mix duration) is less than the event threshold, event timelines for the animation + /// being mixed out will be applied. Defaults to 0, so event timelines are not applied for an animation being mixed out. + float getEventThreshold(); + void setEventThreshold(float inValue); + + /// + /// When the mix percentage (mix time / mix duration) is less than the attachment threshold, attachment timelines for the + /// animation being mixed out will be applied. Defaults to 0, so attachment timelines are not applied for an animation being + /// mixed out. + float getAttachmentThreshold(); + void setAttachmentThreshold(float inValue); + + /// + /// When the mix percentage (mix time / mix duration) is less than the draw order threshold, draw order timelines for the + /// animation being mixed out will be applied. Defaults to 0, so draw order timelines are not applied for an animation being + /// mixed out. + /// + float getDrawOrderThreshold(); + void setDrawOrderThreshold(float inValue); + + /// + /// The animation queued to start after this animation, or null. + TrackEntry* getNext(); + + /// + /// Returns true if at least one loop has been completed. + bool isComplete(); + + /// + /// Seconds from 0 to the mix duration when mixing from the previous animation to this animation. May be slightly more than + /// TrackEntry.MixDuration when the mix is complete. + float getMixTime(); + void setMixTime(float inValue); + + /// + /// Seconds for mixing from the previous animation to this animation. Defaults to the value provided by + /// AnimationStateData based on the animation before this animation (if any). + /// + /// The mix duration can be set manually rather than use the value from AnimationStateData.GetMix. + /// In that case, the mixDuration must be set before AnimationState.update(float) is next called. + /// + /// When using AnimationState::addAnimation(int, Animation, bool, float) with a delay + /// less than or equal to 0, note the Delay is set using the mix duration from the AnimationStateData + /// + /// + /// + float getMixDuration(); + void setMixDuration(float inValue); + + /// + /// The track entry for the previous animation when mixing from the previous animation to this animation, or null if no + /// mixing is currently occuring. When mixing from multiple animations, MixingFrom makes up a linked list. + TrackEntry* getMixingFrom(); + + /// + /// Resets the rotation directions for mixing this entry's rotate timelines. This can be useful to avoid bones rotating the + /// long way around when using alpha and starting animations on other tracks. + /// + /// Mixing involves finding a rotation between two others, which has two possible solutions: the short way or the long way around. + /// The two rotations likely change over time, so which direction is the short or long way also changes. + /// If the short way was always chosen, bones would flip to the other side when that direction became the long way. + /// TrackEntry chooses the short way the first time it is applied and remembers that direction. + void resetRotationDirections(); + + private: + Animation* _animation; + + TrackEntry* _next; + TrackEntry* _mixingFrom; + int _trackIndex; // -// internal TrackEntry next, mixingFrom; -// internal int trackIndex; -// -// internal bool loop; -// internal float eventThreshold, attachmentThreshold, drawOrderThreshold; -// internal float animationStart, animationEnd, animationLast, nextAnimationLast; -// internal float delay, trackTime, trackLast, nextTrackLast, trackEnd, timeScale = 1f; -// internal float alpha, mixTime, mixDuration, interruptAlpha, totalAlpha; -// internal readonly ExposedList timelineData = new ExposedList(); -// internal readonly ExposedList timelineDipMix = new ExposedList(); -// internal readonly ExposedList timelinesRotation = new ExposedList(); -// -// void reset () + bool _loop; + float _eventThreshold, _attachmentThreshold, _drawOrderThreshold; + float _animationStart, _animationEnd, _animationLast, _nextAnimationLast; + float _delay, _trackTime, _trackLast, _nextTrackLast, _trackEnd, _timeScale = 1.0f; + float _alpha, _mixTime, _mixDuration, _interruptAlpha, _totalAlpha; + Vector _timelineData; + Vector _timelineDipMix; + Vector _timelinesRotation; +// event AnimationState.TrackEntryDelegate Start, Interrupt, End, Dispose, Complete; +// event AnimationState.TrackEntryEventDelegate Event; + + /// Sets the timeline data. + /// @param to May be null. +// TrackEntry setTimelineData(TrackEntry* to, Vector mixingToArray, HashSet propertyIDs) // { -// next = null; -// mixingFrom = null; -// animation = null; -// timelineData.Clear(); -// timelineDipMix.Clear(); -// timelinesRotation.Clear(); -// -// Start = null; -// Interrupt = null; -// End = null; -// Dispose = null; -// Complete = null; -// Event = null; -// } -// -// /// Sets the timeline data. -// /// May be null. -// internal TrackEntry SetTimelineData (TrackEntry to, ExposedList mixingToArray, HashSet propertyIDs) { // if (to != null) mixingToArray.Add(to); -// var lastEntry = mixingFrom != null ? mixingFrom.SetTimelineData(this, mixingToArray, propertyIDs) : this; +// var lastEntry = mixingFrom != null ? mixingFrom.setTimelineData(this, mixingToArray, propertyIDs) : this; // if (to != null) mixingToArray.Pop(); // // var mixingTo = mixingToArray.Items; @@ -79,7 +220,7 @@ namespace Spine // var timelines = animation.timelines.Items; // int timelinesCount = animation.timelines.Count; // var timelineDataItems = timelineData.Resize(timelinesCount).Items; // timelineData.setSize(timelinesCount); -// timelineDipMix.Clear(); +// timelineDipMix.clear(); // var timelineDipMixItems = timelineDipMix.Resize(timelinesCount).Items; //timelineDipMix.setSize(timelinesCount); // // // outer: @@ -87,12 +228,12 @@ namespace Spine // int id = timelines[i].PropertyId; // if (!propertyIDs.Add(id)) { // timelineDataItems[i] = AnimationState.Subsequent; -// } else if (to == null || !to.HasTimeline(id)) { +// } else if (to == null || !to.hasTimeline(id)) { // timelineDataItems[i] = AnimationState.First; // } else { // for (int ii = mixingToLast; ii >= 0; ii--) { // var entry = mixingTo[ii]; -// if (!entry.HasTimeline(id)) { +// if (!entry.hasTimeline(id)) { // if (entry.mixDuration > 0) { // timelineDataItems[i] = AnimationState.DipMix; // timelineDipMixItems[i] = entry; @@ -107,176 +248,42 @@ namespace Spine // } // return lastEntry; // } -// -// bool HasTimeline (int id) { + + bool hasTimeline(int inId) + { // var timelines = animation.timelines.Items; -// for (int i = 0, n = animation.timelines.Count; i < n; i++) -// if (timelines[i].PropertyId == id) return true; -// return false; -// } -// -// /// The index of the track where this entry is either current or queued. -// public int TrackIndex { get { return trackIndex; } } -// -// /// The animation to apply for this track entry. -// public Animation Animation { get { return animation; } } -// -// /// -// /// If true, the animation will repeat. If false, it will not, instead its last frame is applied if played beyond its duration. -// public bool Loop { get { return loop; } set { loop = value; } } -// -// /// -// /// Seconds to postpone playing the animation. When a track entry is the current track entry, delay postpones incrementing -// /// the track time. When a track entry is queued, delay is the time from the start of the previous animation to when the -// /// track entry will become the current track entry. -// public float Delay { get { return delay; } set { delay = value; } } -// -// /// -// /// Current time in seconds this track entry has been the current track entry. The track time determines -// /// . The track time can be set to start the animation at a time other than 0, without affecting looping. -// public float TrackTime { get { return trackTime; } set { trackTime = value; } } -// -// /// -// /// The track time in seconds when this animation will be removed from the track. Defaults to the animation duration for -// /// non-looping animations and to for looping animations. If the track end time is reached and no -// /// other animations are queued for playback, and mixing from any previous animations is complete, properties keyed by the animation, -// /// are set to the setup pose and the track is cleared. -// /// -// /// It may be desired to use to mix the properties back to the -// /// setup pose over time, rather than have it happen instantly. -// /// -// public float TrackEnd { get { return trackEnd; } set { trackEnd = value; } } -// -// /// -// /// Seconds when this animation starts, both initially and after looping. Defaults to 0. -// /// -// /// When changing the animation start time, it often makes sense to set to the same value to -// /// prevent timeline keys before the start time from triggering. -// /// -// public float AnimationStart { get { return animationStart; } set { animationStart = value; } } -// -// /// -// /// Seconds for the last frame of this animation. Non-looping animations won't play past this time. Looping animations will -// /// loop back to at this time. Defaults to the animation duration. -// public float AnimationEnd { get { return animationEnd; } set { animationEnd = value; } } -// -// /// -// /// The time in seconds this animation was last applied. Some timelines use this for one-time triggers. Eg, when this -// /// animation is applied, event timelines will fire all events between the animation last time (exclusive) and animation time -// /// (inclusive). Defaults to -1 to ensure triggers on frame 0 happen the first time this animation is applied. -// public float AnimationLast { -// get { return animationLast; } -// set { -// animationLast = value; -// nextAnimationLast = value; -// } -// } -// -// /// -// /// Uses to compute the animation time between . and -// /// . When the track time is 0, the animation time is equal to the animation start time. -// /// -// public float AnimationTime { -// get { -// if (loop) { -// float duration = animationEnd - animationStart; -// if (duration == 0) return animationStart; -// return (trackTime % duration) + animationStart; +// for (int i = 0, n = animation.timelines.Count; i < n; ++i) +// { +// if (timelines[i].PropertyId == inId) +// { +// return true; // } -// return Math.Min(trackTime + animationStart, animationEnd); // } -// } + return false; + } + +// void onStart() { if (Start != null) Start(this); } +// void onInterrupt() { if (Interrupt != null) Interrupt(this); } +// void onEnd() { if (End != null) End(this); } +// void onDispose() { if (Dispose != null) Dispose(this); } +// void onComplete() { if (Complete != null) Complete(this); } +// void onEvent(Event& e) { if (Event != null) Event(this, e); } // -// /// -// /// Multiplier for the delta time when the animation state is updated, causing time for this animation to play slower or -// /// faster. Defaults to 1. -// /// -// public float TimeScale { get { return timeScale; } set { timeScale = value; } } +// void reset() +// { +// next = null; +// mixingFrom = null; +// animation = null; +// timelineData.clear(); +// timelineDipMix.clear(); +// timelinesRotation.clear(); // -// /// -// /// Values less than 1 mix this animation with the last skeleton pose. Defaults to 1, which overwrites the last skeleton pose with -// /// this animation. -// /// -// /// Typically track 0 is used to completely pose the skeleton, then alpha can be used on higher tracks. It doesn't make sense -// /// to use alpha on track 0 if the skeleton pose is from the last frame render. -// /// -// public float Alpha { get { return alpha; } set { alpha = value; } } -// -// /// -// /// When the mix percentage (mix time / mix duration) is less than the event threshold, event timelines for the animation -// /// being mixed out will be applied. Defaults to 0, so event timelines are not applied for an animation being mixed out. -// public float EventThreshold { get { return eventThreshold; } set { eventThreshold = value; } } -// -// /// -// /// When the mix percentage (mix time / mix duration) is less than the attachment threshold, attachment timelines for the -// /// animation being mixed out will be applied. Defaults to 0, so attachment timelines are not applied for an animation being -// /// mixed out. -// public float AttachmentThreshold { get { return attachmentThreshold; } set { attachmentThreshold = value; } } -// -// /// -// /// When the mix percentage (mix time / mix duration) is less than the draw order threshold, draw order timelines for the -// /// animation being mixed out will be applied. Defaults to 0, so draw order timelines are not applied for an animation being -// /// mixed out. -// /// -// public float DrawOrderThreshold { get { return drawOrderThreshold; } set { drawOrderThreshold = value; } } -// -// /// -// /// The animation queued to start after this animation, or null. -// public TrackEntry Next { get { return next; } } -// -// /// -// /// Returns true if at least one loop has been completed. -// public bool IsComplete { -// get { return trackTime >= animationEnd - animationStart; } -// } -// -// /// -// /// Seconds from 0 to the mix duration when mixing from the previous animation to this animation. May be slightly more than -// /// when the mix is complete. -// public float MixTime { get { return mixTime; } set { mixTime = value; } } -// -// /// -// /// Seconds for mixing from the previous animation to this animation. Defaults to the value provided by -// /// based on the animation before this animation (if any). -// /// -// /// The mix duration can be set manually rather than use the value from AnimationStateData.GetMix. -// /// In that case, the mixDuration must be set before is next called. -// /// -// /// When using with a -// /// delay less than or equal to 0, note the is set using the mix duration from the -// /// -// /// -// /// -// public float MixDuration { get { return mixDuration; } set { mixDuration = value; } } -// -// /// -// /// The track entry for the previous animation when mixing from the previous animation to this animation, or null if no -// /// mixing is currently occuring. When mixing from multiple animations, MixingFrom makes up a linked list. -// public TrackEntry MixingFrom { get { return mixingFrom; } } -// -// public event AnimationState.TrackEntryDelegate Start, Interrupt, End, Dispose, Complete; -// public event AnimationState.TrackEntryEventDelegate Event; -// internal void OnStart () { if (Start != null) Start(this); } -// internal void OnInterrupt () { if (Interrupt != null) Interrupt(this); } -// internal void OnEnd () { if (End != null) End(this); } -// internal void OnDispose () { if (Dispose != null) Dispose(this); } -// internal void OnComplete () { if (Complete != null) Complete(this); } -// internal void OnEvent (Event e) { if (Event != null) Event(this, e); } -// -// /// -// /// Resets the rotation directions for mixing this entry's rotate timelines. This can be useful to avoid bones rotating the -// /// long way around when using and starting animations on other tracks. -// /// -// /// Mixing involves finding a rotation between two others, which has two possible solutions: the short way or the long way around. -// /// The two rotations likely change over time, so which direction is the short or long way also changes. -// /// If the short way was always chosen, bones would flip to the other side when that direction became the long way. -// /// TrackEntry chooses the short way the first time it is applied and remembers that direction. -// public void ResetRotationDirections () { -// timelinesRotation.Clear(); -// } -// -// override public string ToString () { -// return animation == null ? "" : animation.name; +// Start = null; +// Interrupt = null; +// End = null; +// Dispose = null; +// Complete = null; +// Event = null; // } }; @@ -287,11 +294,11 @@ namespace Spine // // private readonly AnimationState state; // private readonly Pool trackEntryPool; -// internal event Action AnimationsChanged; +// internal event Action animationsChanged; // -// internal EventQueue (AnimationState state, Action HandleAnimationsChanged, Pool trackEntryPool) { +// internal EventQueue(AnimationState state, Action HandleanimationsChanged, Pool trackEntryPool) { // this.state = state; -// this.AnimationsChanged += HandleAnimationsChanged; +// this.animationsChanged += HandleanimationsChanged; // this.trackEntryPool = trackEntryPool; // } // @@ -300,7 +307,7 @@ namespace Spine // public TrackEntry entry; // public Event e; // -// public EventQueueEntry (EventType eventType, TrackEntry trackEntry, Event e = null) { +// public EventQueueEntry(EventType eventType, TrackEntry trackEntry, Event e = null) { // this.type = eventType; // this.entry = trackEntry; // this.e = e; @@ -311,113 +318,112 @@ namespace Spine // Start, Interrupt, End, Dispose, Complete, Event // } // -// internal void Start (TrackEntry entry) { +// internal void Start(TrackEntry entry) { // eventQueueEntries.Add(new EventQueueEntry(EventType.Start, entry)); -// if (AnimationsChanged != null) AnimationsChanged(); +// if (animationsChanged != null) animationsChanged(); // } // -// internal void Interrupt (TrackEntry entry) { +// internal void Interrupt(TrackEntry entry) { // eventQueueEntries.Add(new EventQueueEntry(EventType.Interrupt, entry)); // } // -// internal void End (TrackEntry entry) { +// internal void End(TrackEntry entry) { // eventQueueEntries.Add(new EventQueueEntry(EventType.End, entry)); -// if (AnimationsChanged != null) AnimationsChanged(); +// if (animationsChanged != null) animationsChanged(); // } // -// internal void Dispose (TrackEntry entry) { +// internal void Dispose(TrackEntry entry) { // eventQueueEntries.Add(new EventQueueEntry(EventType.Dispose, entry)); // } // -// internal void Complete (TrackEntry entry) { +// internal void Complete(TrackEntry entry) { // eventQueueEntries.Add(new EventQueueEntry(EventType.Complete, entry)); // } // -// internal void Event (TrackEntry entry, Event e) { +// internal void Event(TrackEntry entry, Event e) { // eventQueueEntries.Add(new EventQueueEntry(EventType.Event, entry, e)); // } // -// /// Raises all events in the queue and drains the queue. -// internal void Drain () { +// /// Raises all events in the queue and drains the queue. +// internal void drain() { // if (drainDisabled) return; // drainDisabled = true; // // var entries = this.eventQueueEntries; // AnimationState state = this.state; // -// // Don't cache entries.Count so callbacks can queue their own events (eg, call SetAnimation in AnimationState_Complete). +// // Don't cache entries.Count so callbacks can queue their own events (eg, call setAnimation in AnimationState_Complete). // for (int i = 0; i < entries.Count; i++) { // var queueEntry = entries[i]; // TrackEntry trackEntry = queueEntry.entry; // // switch (queueEntry.type) { // case EventType.Start: -// trackEntry.OnStart(); -// state.OnStart(trackEntry); +// trackEntry.onStart(); +// state.onStart(trackEntry); // break; // case EventType.Interrupt: -// trackEntry.OnInterrupt(); -// state.OnInterrupt(trackEntry); +// trackEntry.onInterrupt(); +// state.onInterrupt(trackEntry); // break; // case EventType.End: -// trackEntry.OnEnd(); -// state.OnEnd(trackEntry); -// goto case EventType.Dispose; // Fall through. (C#) +// trackEntry.onEnd(); +// state.onEnd(trackEntry); // case EventType.Dispose: -// trackEntry.OnDispose(); -// state.OnDispose(trackEntry); +// trackEntry.onDispose(); +// state.onDispose(trackEntry); // trackEntryPool.Free(trackEntry); // Pooling // break; // case EventType.Complete: -// trackEntry.OnComplete(); -// state.OnComplete(trackEntry); +// trackEntry.onComplete(); +// state.onComplete(trackEntry); // break; // case EventType.Event: -// trackEntry.OnEvent(queueEntry.e); -// state.OnEvent(trackEntry, queueEntry.e); +// trackEntry.onEvent(queueEntry.e); +// state.onEvent(trackEntry, queueEntry.e); // break; // } // } -// eventQueueEntries.Clear(); +// eventQueueEntries.clear(); // // drainDisabled = false; // } // -// internal void Clear () { -// eventQueueEntries.Clear(); +// internal void clear() { +// eventQueueEntries.clear(); // } }; class AnimationState { -// static readonly Animation EmptyAnimation = new Animation("", new ExposedList(), 0); +// static readonly Animation EmptyAnimation = new Animation("", new Vector(), 0); // internal const int Subsequent = 0, First = 1, Dip = 2, DipMix = 3; // // private AnimationStateData data; // // Pool trackEntryPool = new Pool(); -// private readonly ExposedList tracks = new ExposedList(); -// private readonly ExposedList events = new ExposedList(); +// private readonly Vector tracks = new Vector(); +// private readonly Vector events = new Vector(); // private readonly EventQueue queue; // Initialized by constructor. // // private readonly HashSet propertyIDs = new HashSet(); -// private readonly ExposedList mixingTo = new ExposedList(); +// private readonly Vector mixingTo = new Vector(); // private bool animationsChanged; // // private float timeScale = 1; // // public AnimationStateData Data { get { return data; } } -// /// A list of tracks that have animations, which may contain nulls. -// public ExposedList Tracks { get { return tracks; } } +// /// A list of tracks that have animations, which may contain nulls. +// public Vector Tracks { get { return tracks; } } // public float TimeScale { get { return timeScale; } set { timeScale = value; } } // -// public delegate void TrackEntryDelegate (TrackEntry trackEntry); +// public delegate void TrackEntryDelegate(TrackEntry trackEntry); // public event TrackEntryDelegate Start, Interrupt, End, Dispose, Complete; // -// public delegate void TrackEntryEventDelegate (TrackEntry trackEntry, Event e); +// public delegate void TrackEntryEventDelegate(TrackEntry trackEntry, Event e); // public event TrackEntryEventDelegate Event; // -// public AnimationState (AnimationStateData data) { +// public AnimationState(AnimationStateData data) { // if (data == null) throw new ArgumentNullException("data", "data cannot be null."); // this.data = data; // this.queue = new EventQueue( @@ -427,10 +433,10 @@ namespace Spine // ); // } // -// /// -// /// Increments the track entry times, setting queued animations as current if needed -// /// delta time -// public void Update (float delta) { +// /// +// /// Increments the track entry times, setting queued animations as current if needed +// /// @param delta delta time +// public void update(float delta) { // delta *= timeScale; // var tracksItems = tracks.Items; // for (int i = 0, n = tracks.Count; i < n; i++) { @@ -457,7 +463,7 @@ namespace Spine // next.delay = 0; // next.trackTime = nextTime + (delta * next.timeScale); // current.trackTime += currentDelta; -// SetCurrent(i, next, true); +// setCurrent(i, next, true); // while (next.mixingFrom != null) { // next.mixTime += currentDelta; // next = next.mixingFrom; @@ -465,14 +471,14 @@ namespace Spine // continue; // } // } else if (current.trackLast >= current.trackEnd && current.mixingFrom == null) { -// // Clear the track when there is no next entry, the track end time is reached, and there is no mixingFrom. +// // clear the track when there is no next entry, the track end time is reached, and there is no mixingFrom. // tracksItems[i] = null; // // queue.End(current); -// DisposeNext(current); +// disposeNext(current); // continue; // } -// if (current.mixingFrom != null && UpdateMixingFrom(current, delta)) { +// if (current.mixingFrom != null && updateMixingFrom(current, delta)) { // // End mixing from entries once all have completed. // var from = current.mixingFrom; // current.mixingFrom = null; @@ -485,15 +491,15 @@ namespace Spine // current.trackTime += currentDelta; // } // -// queue.Drain(); +// queue.drain(); // } // -// /// Returns true when all mixing from entries are complete. -// private bool UpdateMixingFrom (TrackEntry to, float delta) { +// /// Returns true when all mixing from entries are complete. +// private bool updateMixingFrom(TrackEntry to, float delta) { // TrackEntry from = to.mixingFrom; // if (from == null) return true; // -// bool finished = UpdateMixingFrom(from, delta); +// bool finished = updateMixingFrom(from, delta); // // // Require mixTime > 0 to ensure the mixing from entry was applied at least once. // if (to.mixTime > 0 && (to.mixTime >= to.mixDuration || to.timeScale == 0)) { @@ -513,12 +519,12 @@ namespace Spine // return false; // } // -// /// +// /// // /// Poses the skeleton using the track entry animations. There are no side effects other than invoking listeners, so the -// /// animation state can be applied to multiple skeletons to pose them identically. -// public bool Apply (Skeleton skeleton) { +// /// animation state can be applied to multiple skeletons to pose them identically. +// public bool apply(Skeleton skeleton) { // if (skeleton == null) throw new ArgumentNullException("skeleton", "skeleton cannot be null."); -// if (animationsChanged) AnimationsChanged(); +// if (animationsChanged) animationsChanged(); // // var events = this.events; // @@ -530,21 +536,21 @@ namespace Spine // applied = true; // MixPose currentPose = i == 0 ? MixPose.Current : MixPose.CurrentLayered; // -// // Apply mixing from entries first. +// // apply mixing from entries first. // float mix = current.alpha; // if (current.mixingFrom != null) -// mix *= ApplyMixingFrom(current, skeleton, currentPose); +// mix *= applyMixingFrom(current, skeleton, currentPose); // else if (current.trackTime >= current.trackEnd && current.next == null) // // mix = 0; // Set to setup pose the last time the entry will be applied. // -// // Apply current entry. +// // apply current entry. // float animationLast = current.animationLast, animationTime = current.AnimationTime; // int timelineCount = current.animation.timelines.Count; // var timelines = current.animation.timelines; // var timelinesItems = timelines.Items; // if (mix == 1) { // for (int ii = 0; ii < timelineCount; ii++) -// timelinesItems[ii].Apply(skeleton, animationLast, animationTime, events, 1, MixPose.Setup, MixDirection.In); +// timelinesItems[ii].apply(skeleton, animationLast, animationTime, events, 1, MixPose.Setup, MixDirection.In); // } else { // var timelineData = current.timelineData.Items; // @@ -557,24 +563,24 @@ namespace Spine // MixPose pose = timelineData[ii] >= AnimationState.First ? MixPose.Setup : currentPose; // var rotateTimeline = timeline as RotateTimeline; // if (rotateTimeline != null) -// ApplyRotateTimeline(rotateTimeline, skeleton, animationTime, mix, pose, timelinesRotation, ii << 1, firstFrame); +// applyRotateTimeline(rotateTimeline, skeleton, animationTime, mix, pose, timelinesRotation, ii << 1, firstFrame); // else -// timeline.Apply(skeleton, animationLast, animationTime, events, mix, pose, MixDirection.In); +// timeline.apply(skeleton, animationLast, animationTime, events, mix, pose, MixDirection.In); // } // } -// QueueEvents(current, animationTime); -// events.Clear(false); +// queueEvents(current, animationTime); +// events.clear(false); // current.nextAnimationLast = animationTime; // current.nextTrackLast = current.trackTime; // } // -// queue.Drain(); +// queue.drain(); // return applied; // } // -// private float ApplyMixingFrom (TrackEntry to, Skeleton skeleton, MixPose currentPose) { +// private float applyMixingFrom(TrackEntry to, Skeleton skeleton, MixPose currentPose) { // TrackEntry from = to.mixingFrom; -// if (from.mixingFrom != null) ApplyMixingFrom(from, skeleton, currentPose); +// if (from.mixingFrom != null) applyMixingFrom(from, skeleton, currentPose); // // float mix; // if (to.mixDuration == 0) { // Single frame mix to undo mixingFrom changes. @@ -627,27 +633,27 @@ namespace Spine // from.totalAlpha += alpha; // var rotateTimeline = timeline as RotateTimeline; // if (rotateTimeline != null) { -// ApplyRotateTimeline(rotateTimeline, skeleton, animationTime, alpha, pose, timelinesRotation, i << 1, firstFrame); +// applyRotateTimeline(rotateTimeline, skeleton, animationTime, alpha, pose, timelinesRotation, i << 1, firstFrame); // } else { -// timeline.Apply(skeleton, animationLast, animationTime, eventBuffer, alpha, pose, MixDirection.Out); +// timeline.apply(skeleton, animationLast, animationTime, eventBuffer, alpha, pose, MixDirection.Out); // } // } // -// if (to.mixDuration > 0) QueueEvents(from, animationTime); -// this.events.Clear(false); +// if (to.mixDuration > 0) queueEvents(from, animationTime); +// this.events.clear(false); // from.nextAnimationLast = animationTime; // from.nextTrackLast = from.trackTime; // // return mix; // } // -// static private void ApplyRotateTimeline (RotateTimeline rotateTimeline, Skeleton skeleton, float time, float alpha, MixPose pose, +// static private void applyRotateTimeline(RotateTimeline rotateTimeline, Skeleton skeleton, float time, float alpha, MixPose pose, // float[] timelinesRotation, int i, bool firstFrame) { // // if (firstFrame) timelinesRotation[i] = 0; // // if (alpha == 1) { -// rotateTimeline.Apply(skeleton, 0, time, null, 1, pose, MixDirection.In); +// rotateTimeline.apply(skeleton, 0, time, null, 1, pose, MixDirection.In); // return; // } // @@ -706,7 +712,7 @@ namespace Spine // bone.rotation = r1 - (16384 - (int)(16384.499999999996 - r1 / 360)) * 360; // } // -// private void QueueEvents (TrackEntry entry, float animationTime) { +// private void queueEvents(TrackEntry entry, float animationTime) { // float animationStart = entry.animationStart, animationEnd = entry.animationEnd; // float duration = animationEnd - animationStart; // float trackLastWrapped = entry.trackLast % duration; @@ -736,33 +742,33 @@ namespace Spine // } // } // -// /// +// /// // /// Removes all animations from all tracks, leaving skeletons in their previous pose. -// /// It may be desired to use to mix the skeletons back to the setup pose, -// /// rather than leaving them in their previous pose. -// public void ClearTracks () { -// bool oldDrainDisabled = queue.drainDisabled; +// /// It may be desired to use AnimationState.setEmptyAnimations(float) to mix the skeletons back to the setup pose, +// /// rather than leaving them in their previous pose. +// public void clearTracks() { +// bool olddrainDisabled = queue.drainDisabled; // queue.drainDisabled = true; // for (int i = 0, n = tracks.Count; i < n; i++) { -// ClearTrack(i); +// clearTrack(i); // } -// tracks.Clear(); -// queue.drainDisabled = oldDrainDisabled; -// queue.Drain(); +// tracks.clear(); +// queue.drainDisabled = olddrainDisabled; +// queue.drain(); // } // -// /// +// /// // /// Removes all animations from the tracks, leaving skeletons in their previous pose. -// /// It may be desired to use to mix the skeletons back to the setup pose, -// /// rather than leaving them in their previous pose. -// public void ClearTrack (int trackIndex) { +// /// It may be desired to use AnimationState.setEmptyAnimations(float) to mix the skeletons back to the setup pose, +// /// rather than leaving them in their previous pose. +// public void clearTrack(int trackIndex) { // if (trackIndex >= tracks.Count) return; // TrackEntry current = tracks.Items[trackIndex]; // if (current == null) return; // // queue.End(current); // -// DisposeNext(current); +// disposeNext(current); // // TrackEntry entry = current; // while (true) { @@ -775,12 +781,12 @@ namespace Spine // // tracks.Items[current.trackIndex] = null; // -// queue.Drain(); +// queue.drain(); // } // -// /// Sets the active TrackEntry for a given track number. -// private void SetCurrent (int index, TrackEntry current, bool interrupt) { -// TrackEntry from = ExpandToIndex(index); +// /// Sets the active TrackEntry for a given track number. +// private void setCurrent(int index, TrackEntry current, bool interrupt) { +// TrackEntry from = expandToIndex(index); // tracks.Items[index] = current; // // if (from != null) { @@ -792,80 +798,80 @@ namespace Spine // if (from.mixingFrom != null && from.mixDuration > 0) // current.interruptAlpha *= Math.Min(1, from.mixTime / from.mixDuration); // -// from.timelinesRotation.Clear(); // Reset rotation for mixing out, in case entry was mixed in. +// from.timelinesRotation.clear(); // Reset rotation for mixing out, in case entry was mixed in. // } // -// queue.Start(current); // triggers AnimationsChanged +// queue.Start(current); // triggers animationsChanged // } // // -// /// Sets an animation by name. -// public TrackEntry SetAnimation (int trackIndex, string animationName, bool loop) { +// /// Sets an animation by name. setAnimation(int, Animation, bool) +// public TrackEntry setAnimation(int trackIndex, string animationName, bool loop) { // Animation animation = data.skeletonData.FindAnimation(animationName); // if (animation == null) throw new ArgumentException("Animation not found: " + animationName, "animationName"); -// return SetAnimation(trackIndex, animation, loop); +// return setAnimation(trackIndex, animation, loop); // } // -// /// Sets the current animation for a track, discarding any queued animations. -// /// If true, the animation will repeat. +// /// Sets the current animation for a track, discarding any queued animations. +// /// @param loop If true, the animation will repeat. // /// If false, it will not, instead its last frame is applied if played beyond its duration. -// /// In either case determines when the track is cleared. -// /// +// /// In either case TrackEntry.TrackEnd determines when the track is cleared. +// /// @return // /// A track entry to allow further customization of animation playback. References to the track entry must not be kept -// /// after . -// public TrackEntry SetAnimation (int trackIndex, Animation animation, bool loop) { +// /// after AnimationState.Dispose. +// public TrackEntry setAnimation(int trackIndex, Animation animation, bool loop) { // if (animation == null) throw new ArgumentNullException("animation", "animation cannot be null."); // bool interrupt = true; -// TrackEntry current = ExpandToIndex(trackIndex); +// TrackEntry current = expandToIndex(trackIndex); // if (current != null) { // if (current.nextTrackLast == -1) { // // Don't mix from an entry that was never applied. // tracks.Items[trackIndex] = current.mixingFrom; // queue.Interrupt(current); // queue.End(current); -// DisposeNext(current); +// disposeNext(current); // current = current.mixingFrom; // interrupt = false; // } else { -// DisposeNext(current); +// disposeNext(current); // } // } -// TrackEntry entry = NewTrackEntry(trackIndex, animation, loop, current); -// SetCurrent(trackIndex, entry, interrupt); -// queue.Drain(); +// TrackEntry entry = newTrackEntry(trackIndex, animation, loop, current); +// setCurrent(trackIndex, entry, interrupt); +// queue.drain(); // return entry; // } // -// /// Queues an animation by name. -// /// -// public TrackEntry AddAnimation (int trackIndex, string animationName, bool loop, float delay) { +// /// Queues an animation by name. +// /// addAnimation(int, Animation, bool, float) +// public TrackEntry addAnimation(int trackIndex, string animationName, bool loop, float delay) { // Animation animation = data.skeletonData.FindAnimation(animationName); // if (animation == null) throw new ArgumentException("Animation not found: " + animationName, "animationName"); -// return AddAnimation(trackIndex, animation, loop, delay); +// return addAnimation(trackIndex, animation, loop, delay); // } // -// /// Adds an animation to be played delay seconds after the current or last queued animation -// /// for a track. If the track is empty, it is equivalent to calling . -// /// +// /// Adds an animation to be played delay seconds after the current or last queued animation +// /// for a track. If the track is empty, it is equivalent to calling setAnimation. +// /// @param delay // /// Seconds to begin this animation after the start of the previous animation. May be <= 0 to use the animation // /// duration of the previous track minus any mix duration plus the negative delay. -// /// -// /// A track entry to allow further customization of animation playback. References to the track entry must not be kept -// /// after -// public TrackEntry AddAnimation (int trackIndex, Animation animation, bool loop, float delay) { +// /// +// /// @return A track entry to allow further customization of animation playback. References to the track entry must not be kept +// /// after AnimationState.Dispose +// public TrackEntry addAnimation(int trackIndex, Animation animation, bool loop, float delay) { // if (animation == null) throw new ArgumentNullException("animation", "animation cannot be null."); // -// TrackEntry last = ExpandToIndex(trackIndex); +// TrackEntry last = expandToIndex(trackIndex); // if (last != null) { // while (last.next != null) // last = last.next; // } // -// TrackEntry entry = NewTrackEntry(trackIndex, animation, loop, last); +// TrackEntry entry = newTrackEntry(trackIndex, animation, loop, last); // // if (last == null) { -// SetCurrent(trackIndex, entry, true); -// queue.Drain(); +// setCurrent(trackIndex, entry, true); +// queue.drain(); // } else { // last.next = entry; // if (delay <= 0) { @@ -881,56 +887,56 @@ namespace Spine // return entry; // } // -// /// -// /// Sets an empty animation for a track, discarding any queued animations, and mixes to it over the specified mix duration. -// public TrackEntry SetEmptyAnimation (int trackIndex, float mixDuration) { -// TrackEntry entry = SetAnimation(trackIndex, AnimationState.EmptyAnimation, false); +// /// +// /// Sets an empty animation for a track, discarding any queued animations, and mixes to it over the specified mix duration. +// public TrackEntry setEmptyAnimation(int trackIndex, float mixDuration) { +// TrackEntry entry = setAnimation(trackIndex, AnimationState.EmptyAnimation, false); // entry.mixDuration = mixDuration; // entry.trackEnd = mixDuration; // return entry; // } // -// /// +// /// // /// Adds an empty animation to be played after the current or last queued animation for a track, and mixes to it over the -// /// specified mix duration. -// /// -// /// A track entry to allow further customization of animation playback. References to the track entry must not be kept after . -// /// -// /// Track number. -// /// Mix duration. -// /// Seconds to begin this animation after the start of the previous animation. May be <= 0 to use the animation -// /// duration of the previous track minus any mix duration plus the negative delay. -// public TrackEntry AddEmptyAnimation (int trackIndex, float mixDuration, float delay) { +// /// specified mix duration. +// /// @return +// /// A track entry to allow further customization of animation playback. References to the track entry must not be kept after AnimationState.Dispose. +// /// +// /// @param trackIndex Track number. +// /// @param mixDuration Mix duration. +// /// @param delay Seconds to begin this animation after the start of the previous animation. May be <= 0 to use the animation +// /// duration of the previous track minus any mix duration plus the negative delay. +// public TrackEntry addEmptyAnimation(int trackIndex, float mixDuration, float delay) { // if (delay <= 0) delay -= mixDuration; -// TrackEntry entry = AddAnimation(trackIndex, AnimationState.EmptyAnimation, false, delay); +// TrackEntry entry = addAnimation(trackIndex, AnimationState.EmptyAnimation, false, delay); // entry.mixDuration = mixDuration; // entry.trackEnd = mixDuration; // return entry; // } // -// /// -// /// Sets an empty animation for every track, discarding any queued animations, and mixes to it over the specified mix duration. -// public void SetEmptyAnimations (float mixDuration) { -// bool oldDrainDisabled = queue.drainDisabled; +// /// +// /// Sets an empty animation for every track, discarding any queued animations, and mixes to it over the specified mix duration. +// public void setEmptyAnimations(float mixDuration) { +// bool olddrainDisabled = queue.drainDisabled; // queue.drainDisabled = true; // for (int i = 0, n = tracks.Count; i < n; i++) { // TrackEntry current = tracks.Items[i]; -// if (current != null) SetEmptyAnimation(i, mixDuration); +// if (current != null) setEmptyAnimation(i, mixDuration); // } -// queue.drainDisabled = oldDrainDisabled; -// queue.Drain(); +// queue.drainDisabled = olddrainDisabled; +// queue.drain(); // } // -// private TrackEntry ExpandToIndex (int index) { +// private TrackEntry expandToIndex(int index) { // if (index < tracks.Count) return tracks.Items[index]; // while (index >= tracks.Count) // tracks.Add(null); // return null; // } // -// /// Object-pooling version of new TrackEntry. Obtain an unused TrackEntry from the pool and clear/initialize its values. -// /// May be null. -// private TrackEntry NewTrackEntry (int trackIndex, Animation animation, bool loop, TrackEntry last) { +// /// Object-pooling version of new TrackEntry. Obtain an unused TrackEntry from the pool and clear/initialize its values. +// /// @param last May be null. +// private TrackEntry newTrackEntry(int trackIndex, Animation animation, bool loop, TrackEntry last) { // TrackEntry entry = trackEntryPool.Obtain(); // Pooling // entry.trackIndex = trackIndex; // entry.animation = animation; @@ -959,8 +965,8 @@ namespace Spine // return entry; // } // -// /// Dispose all track entries queued after the given TrackEntry. -// private void DisposeNext (TrackEntry entry) { +// /// Dispose all track entries queued after the given TrackEntry. +// private void disposeNext(TrackEntry entry) { // TrackEntry next = entry.next; // while (next != null) { // queue.Dispose(next); @@ -969,42 +975,31 @@ namespace Spine // entry.next = null; // } // -// private void AnimationsChanged () { +// private void animationsChanged() { // animationsChanged = false; // // var propertyIDs = this.propertyIDs; -// propertyIDs.Clear(); +// propertyIDs.clear(); // var mixingTo = this.mixingTo; // // var tracksItems = tracks.Items; // for (int i = 0, n = tracks.Count; i < n; i++) { // var entry = tracksItems[i]; -// if (entry != null) entry.SetTimelineData(null, mixingTo, propertyIDs); +// if (entry != null) entry.setTimelineData(null, mixingTo, propertyIDs); // } // } // -// /// The track entry for the animation currently playing on the track, or null if no animation is currently playing. -// public TrackEntry GetCurrent (int trackIndex) { +// /// @return The track entry for the animation currently playing on the track, or null if no animation is currently playing. +// public TrackEntry getCurrent(int trackIndex) { // return (trackIndex >= tracks.Count) ? null : tracks.Items[trackIndex]; // } // -// override public string ToString () { -// var buffer = new System.Text.StringBuilder(); -// for (int i = 0, n = tracks.Count; i < n; i++) { -// TrackEntry entry = tracks.Items[i]; -// if (entry == null) continue; -// if (buffer.Length > 0) buffer.Append(", "); -// buffer.Append(entry.ToString()); -// } -// return buffer.Length == 0 ? "" : buffer.ToString(); -// } -// -// internal void OnStart (TrackEntry entry) { if (Start != null) Start(entry); } -// internal void OnInterrupt (TrackEntry entry) { if (Interrupt != null) Interrupt(entry); } -// internal void OnEnd (TrackEntry entry) { if (End != null) End(entry); } -// internal void OnDispose (TrackEntry entry) { if (Dispose != null) Dispose(entry); } -// internal void OnComplete (TrackEntry entry) { if (Complete != null) Complete(entry); } -// internal void OnEvent (TrackEntry entry, Event e) { if (Event != null) Event(entry, e); } +// internal void onStart(TrackEntry entry) { if (Start != null) Start(entry); } +// internal void onInterrupt(TrackEntry entry) { if (Interrupt != null) Interrupt(entry); } +// internal void onEnd(TrackEntry entry) { if (End != null) End(entry); } +// internal void onDispose(TrackEntry entry) { if (Dispose != null) Dispose(entry); } +// internal void onComplete(TrackEntry entry) { if (Complete != null) Complete(entry); } +// internal void onEvent(TrackEntry entry, Event e) { if (Event != null) Event(entry, e); } }; } diff --git a/spine-cpp/spine-cpp/include/spine/RegionAttachment.h b/spine-cpp/spine-cpp/include/spine/RegionAttachment.h index 5fd982652..3128fb8f6 100644 --- a/spine-cpp/spine-cpp/include/spine/RegionAttachment.h +++ b/spine-cpp/spine-cpp/include/spine/RegionAttachment.h @@ -124,7 +124,7 @@ namespace Spine static const int BRX; static const int BRY; - float _x, _y, _rotation, _scaleX = 1, _scaleY = 1, _width, _height; + float _x, _y, _rotation, _scaleX, _scaleY, _width, _height; float _regionOffsetX, _regionOffsetY, _regionWidth, _regionHeight, _regionOriginalWidth, _regionOriginalHeight; Vector _offset; Vector _uvs; diff --git a/spine-cpp/spine-cpp/src/spine/AnimationState.cpp b/spine-cpp/spine-cpp/src/spine/AnimationState.cpp index bb4d2ccfe..011f0b660 100644 --- a/spine-cpp/spine-cpp/src/spine/AnimationState.cpp +++ b/spine-cpp/spine-cpp/src/spine/AnimationState.cpp @@ -28,7 +28,99 @@ * POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ +#include + +#include + +#include + namespace Spine { - // TODO + TrackEntry::TrackEntry() + { + + } + + int TrackEntry::getTrackIndex() { return _trackIndex; } + + Animation* TrackEntry::getAnimation() { return _animation; } + + bool TrackEntry::getLoop() { return _loop; } + void TrackEntry::setLoop(bool inValue) { _loop = inValue; } + + float TrackEntry::getDelay() { return _delay; } + void TrackEntry::setDelay(float inValue) { _delay = inValue; } + + float TrackEntry::getTrackTime() { return _trackTime; } + void TrackEntry::setTrackTime(float inValue) { _trackTime = inValue; } + + float TrackEntry::getTrackEnd() { return _trackEnd; } + void TrackEntry::setTrackEnd(float inValue) { _trackEnd = inValue; } + + float TrackEntry::getAnimationStart() { return _animationStart; } + void TrackEntry::setAnimationStart(float inValue) { _animationStart = inValue; } + + float TrackEntry::getAnimationEnd() { return _animationEnd; } + void TrackEntry::setAnimationEnd(float inValue) { _animationEnd = inValue; } + + float TrackEntry::getAnimationLast() { return _animationLast; } + void TrackEntry::setAnimationLast(float inValue) + { + _animationLast = inValue; + _nextAnimationLast = inValue; + } + + float TrackEntry::getAnimationTime() + { + if (_loop) + { + float duration = _animationEnd - _animationStart; + if (duration == 0) + { + return _animationStart; + } + + return fmodf(_trackTime, duration) + _animationStart; + } + + return MIN(_trackTime + _animationStart, _animationEnd); + } + + float TrackEntry::getTimeScale() { return _timeScale; } + void TrackEntry::setTimeScale(float inValue) { _timeScale = inValue; } + + float TrackEntry::getAlpha() { return _alpha; } + void TrackEntry::setAlpha(float inValue) { _alpha = inValue; } + + float TrackEntry::getEventThreshold() { return _eventThreshold; } + void TrackEntry::setEventThreshold(float inValue) { _eventThreshold = inValue; } + + float TrackEntry::getAttachmentThreshold() { return _attachmentThreshold; } + void TrackEntry::setAttachmentThreshold(float inValue) { _attachmentThreshold = inValue; } + + float TrackEntry::getDrawOrderThreshold() { return _drawOrderThreshold; } + void TrackEntry::setDrawOrderThreshold(float inValue) { _drawOrderThreshold = inValue; } + + TrackEntry* TrackEntry::getNext() { return _next; } + + bool TrackEntry::isComplete() + { + return _trackTime >= _animationEnd - _animationStart; + } + + float TrackEntry::getMixTime() { return _mixTime; } + void TrackEntry::setMixTime(float inValue) { _mixTime = inValue; } + + float TrackEntry::getMixDuration() { return _mixDuration; } + void TrackEntry::setMixDuration(float inValue) { _mixDuration = inValue; } + + TrackEntry* TrackEntry::getMixingFrom() { return _mixingFrom; } + +// event AnimationState.TrackEntryDelegate Start, Interrupt, End, Dispose, Complete; +// event AnimationState.TrackEntryEventDelegate Event; + + void TrackEntry::resetRotationDirections() + { + _timelinesRotation.clear(); + } } diff --git a/spine-cpp/spine-cpp/src/spine/AnimationStateData.cpp b/spine-cpp/spine-cpp/src/spine/AnimationStateData.cpp index e1902824e..00dc79ced 100644 --- a/spine-cpp/spine-cpp/src/spine/AnimationStateData.cpp +++ b/spine-cpp/spine-cpp/src/spine/AnimationStateData.cpp @@ -35,7 +35,7 @@ namespace Spine { - AnimationStateData::AnimationStateData(SkeletonData& skeletonData) : _skeletonData(skeletonData) + AnimationStateData::AnimationStateData(SkeletonData& skeletonData) : _skeletonData(skeletonData), _defaultMix(0) { // Empty } diff --git a/spine-cpp/spine-cpp/src/spine/ClippingAttachment.cpp b/spine-cpp/spine-cpp/src/spine/ClippingAttachment.cpp index c87de561c..1f2f9dd2b 100644 --- a/spine-cpp/spine-cpp/src/spine/ClippingAttachment.cpp +++ b/spine-cpp/spine-cpp/src/spine/ClippingAttachment.cpp @@ -36,7 +36,7 @@ namespace Spine { RTTI_IMPL(ClippingAttachment, VertexAttachment); - ClippingAttachment::ClippingAttachment(std::string name) : VertexAttachment(name) + ClippingAttachment::ClippingAttachment(std::string name) : VertexAttachment(name), _endSlot(NULL) { // Empty } diff --git a/spine-cpp/spine-cpp/src/spine/PathAttachment.cpp b/spine-cpp/spine-cpp/src/spine/PathAttachment.cpp index 54bd9337b..28a06940b 100644 --- a/spine-cpp/spine-cpp/src/spine/PathAttachment.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathAttachment.cpp @@ -34,7 +34,7 @@ namespace Spine { RTTI_IMPL(PathAttachment, VertexAttachment); - PathAttachment::PathAttachment(std::string name) : VertexAttachment(name) + PathAttachment::PathAttachment(std::string name) : VertexAttachment(name), _closed(false), _constantSpeed(false) { // Empty } diff --git a/spine-cpp/spine-cpp/src/spine/PointAttachment.cpp b/spine-cpp/spine-cpp/src/spine/PointAttachment.cpp index d309c8d48..693eb837c 100644 --- a/spine-cpp/spine-cpp/src/spine/PointAttachment.cpp +++ b/spine-cpp/spine-cpp/src/spine/PointAttachment.cpp @@ -38,7 +38,7 @@ namespace Spine { RTTI_IMPL(PointAttachment, Attachment); - PointAttachment::PointAttachment(std::string name) : Attachment(name) + PointAttachment::PointAttachment(std::string name) : Attachment(name), _x(0), _y(0), _rotation(0) { // Empty } diff --git a/spine-cpp/spine-cpp/src/spine/RegionAttachment.cpp b/spine-cpp/spine-cpp/src/spine/RegionAttachment.cpp index 310a4619b..de50ce6c4 100644 --- a/spine-cpp/spine-cpp/src/spine/RegionAttachment.cpp +++ b/spine-cpp/spine-cpp/src/spine/RegionAttachment.cpp @@ -49,7 +49,30 @@ namespace Spine const int RegionAttachment::BRX = 6; const int RegionAttachment::BRY = 7; - RegionAttachment::RegionAttachment(std::string name) : Attachment(name) + RegionAttachment::RegionAttachment(std::string name) : Attachment(name), + _x(0), + _y(0), + _rotation(0), + _scaleX(1), + _scaleY(1), + _width(0), + _height(0), + _regionOffsetX(0), + _regionOffsetY(0), + _regionWidth(0), + _regionHeight(0), + _regionOriginalWidth(0), + _regionOriginalHeight(0), + _rendererObject(NULL), + _path(), + _regionU(0), + _regionV(0), + _regionU2(0), + _regionV2(0), + _r(0), + _g(0), + _b(0), + _a(0) { _offset.reserve(NUM_UVS); _uvs.reserve(NUM_UVS); diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonClipping.cpp b/spine-cpp/spine-cpp/src/spine/SkeletonClipping.cpp index 3ca3d9dbd..6a9f516a3 100644 --- a/spine-cpp/spine-cpp/src/spine/SkeletonClipping.cpp +++ b/spine-cpp/spine-cpp/src/spine/SkeletonClipping.cpp @@ -35,7 +35,7 @@ namespace Spine { - SkeletonClipping::SkeletonClipping() + SkeletonClipping::SkeletonClipping() : _clipAttachment(NULL) { _clipOutput.reserve(128); _clippedVertices.reserve(128); diff --git a/spine-cpp/spine-cpp/src/spine/TwoColorTimeline.cpp b/spine-cpp/spine-cpp/src/spine/TwoColorTimeline.cpp index 9003487b4..0232711c3 100644 --- a/spine-cpp/spine-cpp/src/spine/TwoColorTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/TwoColorTimeline.cpp @@ -59,7 +59,7 @@ namespace Spine const int TwoColorTimeline::G2 = 6; const int TwoColorTimeline::B2 = 7; - TwoColorTimeline::TwoColorTimeline(int frameCount) : CurveTimeline(frameCount) + TwoColorTimeline::TwoColorTimeline(int frameCount) : CurveTimeline(frameCount), _slotIndex(0) { _frames.reserve(frameCount * ENTRIES); } From 1449af5864d93b7336ca420a99bb7c3bfc2e808a Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Tue, 28 Nov 2017 10:54:19 -0500 Subject: [PATCH 52/83] Removing unused Vector constructor --- spine-cpp/spine-cpp/include/spine/Vector.h | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/spine-cpp/spine-cpp/include/spine/Vector.h b/spine-cpp/spine-cpp/include/spine/Vector.h index 9ae06e982..3690824e0 100644 --- a/spine-cpp/spine-cpp/include/spine/Vector.h +++ b/spine-cpp/spine-cpp/include/spine/Vector.h @@ -60,18 +60,6 @@ namespace Spine } } - Vector(Vector& inVector) : _size(inVector._size), _capacity(inVector._capacity), _buffer(NULL) - { - if (_capacity > 0) - { - _buffer = allocate(_capacity); - for (size_t i = 0; i < _size; ++i) - { - construct(_buffer + i, inVector._buffer[i]); - } - } - } - Vector& operator=(Vector& inVector) { if (this != &inVector) From d5c47a709ad72d3cf46722b1f4ef225e832f08c4 Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Tue, 28 Nov 2017 19:30:27 -0500 Subject: [PATCH 53/83] wip --- spine-cpp/spine-cpp/include/spine/Animation.h | 5 +- .../spine-cpp/include/spine/AnimationState.h | 414 +++++++----------- .../spine-cpp/src/spine/AnimationState.cpp | 199 ++++++++- 3 files changed, 351 insertions(+), 267 deletions(-) diff --git a/spine-cpp/spine-cpp/include/spine/Animation.h b/spine-cpp/spine-cpp/include/spine/Animation.h index 06a8ec4bf..061f4d27a 100644 --- a/spine-cpp/spine-cpp/include/spine/Animation.h +++ b/spine-cpp/spine-cpp/include/spine/Animation.h @@ -45,8 +45,8 @@ namespace Spine class Animation { - friend class RotateTimeline; - friend class TranslateTimeline; + friend class AnimationState; + friend class TrackEntry; friend class AnimationStateData; friend class AttachmentTimeline; @@ -58,6 +58,7 @@ namespace Spine friend class PathConstraintMixTimeline; friend class PathConstraintPositionTimeline; friend class PathConstraintSpacingTimeline; + friend class RotateTimeline; friend class ScaleTimeline; friend class ShearTimeline; friend class TransformConstraintTimeline; diff --git a/spine-cpp/spine-cpp/include/spine/AnimationState.h b/spine-cpp/spine-cpp/include/spine/AnimationState.h index ad2783094..4408dd4c6 100644 --- a/spine-cpp/spine-cpp/include/spine/AnimationState.h +++ b/spine-cpp/spine-cpp/include/spine/AnimationState.h @@ -32,10 +32,27 @@ #define Spine_AnimationState_h #include +#include namespace Spine { + enum EventType + { + EventType_Start, + EventType_Interrupt, + EventType_End, + EventType_Complete, + EventType_Dispose, + EventType_Event + }; + + class AnimationState; + class TrackEntry; + class Animation; + class Event; + + typedef void (*OnAnimationEventFunc) (AnimationState* state, EventType type, TrackEntry* entry, Event* event); /// State for the playback of an animation class TrackEntry @@ -146,7 +163,7 @@ namespace Spine void setDrawOrderThreshold(float inValue); /// - /// The animation queued to start after this animation, or null. + /// The animation queued to start after this animation, or NULL. TrackEntry* getNext(); /// @@ -175,7 +192,7 @@ namespace Spine void setMixDuration(float inValue); /// - /// The track entry for the previous animation when mixing from the previous animation to this animation, or null if no + /// The track entry for the previous animation when mixing from the previous animation to this animation, or NULL if no /// mixing is currently occuring. When mixing from multiple animations, MixingFrom makes up a linked list. TrackEntry* getMixingFrom(); @@ -189,215 +206,94 @@ namespace Spine /// TrackEntry chooses the short way the first time it is applied and remembers that direction. void resetRotationDirections(); + void setOnAnimationEventFunc(OnAnimationEventFunc inValue); + private: Animation* _animation; TrackEntry* _next; TrackEntry* _mixingFrom; int _trackIndex; -// + bool _loop; float _eventThreshold, _attachmentThreshold, _drawOrderThreshold; float _animationStart, _animationEnd, _animationLast, _nextAnimationLast; float _delay, _trackTime, _trackLast, _nextTrackLast, _trackEnd, _timeScale = 1.0f; float _alpha, _mixTime, _mixDuration, _interruptAlpha, _totalAlpha; Vector _timelineData; - Vector _timelineDipMix; + Vector _timelineDipMix; Vector _timelinesRotation; -// event AnimationState.TrackEntryDelegate Start, Interrupt, End, Dispose, Complete; -// event AnimationState.TrackEntryEventDelegate Event; + OnAnimationEventFunc _onAnimationEventFunc; /// Sets the timeline data. - /// @param to May be null. -// TrackEntry setTimelineData(TrackEntry* to, Vector mixingToArray, HashSet propertyIDs) -// { -// if (to != null) mixingToArray.Add(to); -// var lastEntry = mixingFrom != null ? mixingFrom.setTimelineData(this, mixingToArray, propertyIDs) : this; -// if (to != null) mixingToArray.Pop(); -// -// var mixingTo = mixingToArray.Items; -// int mixingToLast = mixingToArray.Count - 1; -// var timelines = animation.timelines.Items; -// int timelinesCount = animation.timelines.Count; -// var timelineDataItems = timelineData.Resize(timelinesCount).Items; // timelineData.setSize(timelinesCount); -// timelineDipMix.clear(); -// var timelineDipMixItems = timelineDipMix.Resize(timelinesCount).Items; //timelineDipMix.setSize(timelinesCount); -// -// // outer: -// for (int i = 0; i < timelinesCount; i++) { -// int id = timelines[i].PropertyId; -// if (!propertyIDs.Add(id)) { -// timelineDataItems[i] = AnimationState.Subsequent; -// } else if (to == null || !to.hasTimeline(id)) { -// timelineDataItems[i] = AnimationState.First; -// } else { -// for (int ii = mixingToLast; ii >= 0; ii--) { -// var entry = mixingTo[ii]; -// if (!entry.hasTimeline(id)) { -// if (entry.mixDuration > 0) { -// timelineDataItems[i] = AnimationState.DipMix; -// timelineDipMixItems[i] = entry; -// goto continue_outer; // continue outer; -// } -// break; -// } -// } -// timelineDataItems[i] = AnimationState.Dip; -// } -// continue_outer: {} -// } -// return lastEntry; -// } + /// @param to May be NULL. + TrackEntry* setTimelineData(TrackEntry* to, Vector& mixingToArray, Vector& propertyIDs); - bool hasTimeline(int inId) + bool hasTimeline(int inId); + + void reset(); + }; + + class EventQueueEntry + { + friend class EventQueue; + + public: + EventType _type; + TrackEntry* _entry; + Event* _event; + + EventQueueEntry(EventType eventType, TrackEntry* trackEntry, Event* event = NULL) { -// var timelines = animation.timelines.Items; -// for (int i = 0, n = animation.timelines.Count; i < n; ++i) -// { -// if (timelines[i].PropertyId == inId) -// { -// return true; -// } -// } - return false; + _type = eventType; + _entry = trackEntry; + _event = event; } - -// void onStart() { if (Start != null) Start(this); } -// void onInterrupt() { if (Interrupt != null) Interrupt(this); } -// void onEnd() { if (End != null) End(this); } -// void onDispose() { if (Dispose != null) Dispose(this); } -// void onComplete() { if (Complete != null) Complete(this); } -// void onEvent(Event& e) { if (Event != null) Event(this, e); } -// -// void reset() -// { -// next = null; -// mixingFrom = null; -// animation = null; -// timelineData.clear(); -// timelineDipMix.clear(); -// timelinesRotation.clear(); -// -// Start = null; -// Interrupt = null; -// End = null; -// Dispose = null; -// Complete = null; -// Event = null; -// } }; class EventQueue { -// private readonly List eventQueueEntries = new List(); -// internal bool drainDisabled; -// -// private readonly AnimationState state; -// private readonly Pool trackEntryPool; -// internal event Action animationsChanged; -// -// internal EventQueue(AnimationState state, Action HandleanimationsChanged, Pool trackEntryPool) { -// this.state = state; -// this.animationsChanged += HandleanimationsChanged; -// this.trackEntryPool = trackEntryPool; -// } -// -// struct EventQueueEntry { -// public EventType type; -// public TrackEntry entry; -// public Event e; -// -// public EventQueueEntry(EventType eventType, TrackEntry trackEntry, Event e = null) { -// this.type = eventType; -// this.entry = trackEntry; -// this.e = e; -// } -// } -// -// enum EventType { -// Start, Interrupt, End, Dispose, Complete, Event -// } -// -// internal void Start(TrackEntry entry) { -// eventQueueEntries.Add(new EventQueueEntry(EventType.Start, entry)); -// if (animationsChanged != null) animationsChanged(); -// } -// -// internal void Interrupt(TrackEntry entry) { -// eventQueueEntries.Add(new EventQueueEntry(EventType.Interrupt, entry)); -// } -// -// internal void End(TrackEntry entry) { -// eventQueueEntries.Add(new EventQueueEntry(EventType.End, entry)); -// if (animationsChanged != null) animationsChanged(); -// } -// -// internal void Dispose(TrackEntry entry) { -// eventQueueEntries.Add(new EventQueueEntry(EventType.Dispose, entry)); -// } -// -// internal void Complete(TrackEntry entry) { -// eventQueueEntries.Add(new EventQueueEntry(EventType.Complete, entry)); -// } -// -// internal void Event(TrackEntry entry, Event e) { -// eventQueueEntries.Add(new EventQueueEntry(EventType.Event, entry, e)); -// } -// -// /// Raises all events in the queue and drains the queue. -// internal void drain() { -// if (drainDisabled) return; -// drainDisabled = true; -// -// var entries = this.eventQueueEntries; -// AnimationState state = this.state; -// -// // Don't cache entries.Count so callbacks can queue their own events (eg, call setAnimation in AnimationState_Complete). -// for (int i = 0; i < entries.Count; i++) { -// var queueEntry = entries[i]; -// TrackEntry trackEntry = queueEntry.entry; -// -// switch (queueEntry.type) { -// case EventType.Start: -// trackEntry.onStart(); -// state.onStart(trackEntry); -// break; -// case EventType.Interrupt: -// trackEntry.onInterrupt(); -// state.onInterrupt(trackEntry); -// break; -// case EventType.End: -// trackEntry.onEnd(); -// state.onEnd(trackEntry); -// case EventType.Dispose: -// trackEntry.onDispose(); -// state.onDispose(trackEntry); -// trackEntryPool.Free(trackEntry); // Pooling -// break; -// case EventType.Complete: -// trackEntry.onComplete(); -// state.onComplete(trackEntry); -// break; -// case EventType.Event: -// trackEntry.onEvent(queueEntry.e); -// state.onEvent(trackEntry, queueEntry.e); -// break; -// } -// } -// eventQueueEntries.clear(); -// -// drainDisabled = false; -// } -// -// internal void clear() { -// eventQueueEntries.clear(); -// } + friend class AnimationState; + + private: + Vector _eventQueueEntries; + bool _drainDisabled; + + AnimationState& _state; + Pool& _trackEntryPool; + + EventQueue(AnimationState& state, Pool& trackEntryPool); + + void start(TrackEntry* entry); + + void interrupt(TrackEntry* entry); + + void end(TrackEntry* entry); + + void dispose(TrackEntry* entry); + + void complete(TrackEntry* entry); + + void event(TrackEntry* entry, Event* e); + + /// Raises all events in the queue and drains the queue. + void drain(); + + void clear(); }; class AnimationState { + friend class TrackEntry; + friend class EventQueue; + + public: + void setOnAnimationEventFunc(OnAnimationEventFunc inValue); + + private: + static const int Subsequent, First, Dip, DipMix; // static readonly Animation EmptyAnimation = new Animation("", new Vector(), 0); -// internal const int Subsequent = 0, First = 1, Dip = 2, DipMix = 3; + // // private AnimationStateData data; // @@ -408,27 +304,23 @@ namespace Spine // // private readonly HashSet propertyIDs = new HashSet(); // private readonly Vector mixingTo = new Vector(); -// private bool animationsChanged; + bool _animationsChanged; // // private float timeScale = 1; // // public AnimationStateData Data { get { return data; } } -// /// A list of tracks that have animations, which may contain nulls. +// /// A list of tracks that have animations, which may contain NULLs. // public Vector Tracks { get { return tracks; } } // public float TimeScale { get { return timeScale; } set { timeScale = value; } } // -// public delegate void TrackEntryDelegate(TrackEntry trackEntry); -// public event TrackEntryDelegate Start, Interrupt, End, Dispose, Complete; -// -// public delegate void TrackEntryEventDelegate(TrackEntry trackEntry, Event e); -// public event TrackEntryEventDelegate Event; + OnAnimationEventFunc _onAnimationEventFunc; // // public AnimationState(AnimationStateData data) { -// if (data == null) throw new ArgumentNullException("data", "data cannot be null."); -// this.data = data; -// this.queue = new EventQueue( +// if (data == NULL) throw new ArgumentNULLException("data", "data cannot be NULL."); +// _data = data; +// _queue = new EventQueue( // this, -// delegate { this.animationsChanged = true; }, +// delegate { _animationsChanged = true; }, // trackEntryPool // ); // } @@ -441,7 +333,7 @@ namespace Spine // var tracksItems = tracks.Items; // for (int i = 0, n = tracks.Count; i < n; i++) { // TrackEntry current = tracksItems[i]; -// if (current == null) continue; +// if (current == NULL) continue; // // current.animationLast = current.nextAnimationLast; // current.trackLast = current.nextTrackLast; @@ -456,7 +348,7 @@ namespace Spine // } // // TrackEntry next = current.next; -// if (next != null) { +// if (next != NULL) { // // When the next entry's delay is passed, change to the next entry, preserving leftover time. // float nextTime = current.trackLast - next.delay; // if (nextTime >= 0) { @@ -464,26 +356,26 @@ namespace Spine // next.trackTime = nextTime + (delta * next.timeScale); // current.trackTime += currentDelta; // setCurrent(i, next, true); -// while (next.mixingFrom != null) { +// while (next.mixingFrom != NULL) { // next.mixTime += currentDelta; // next = next.mixingFrom; // } // continue; // } -// } else if (current.trackLast >= current.trackEnd && current.mixingFrom == null) { +// } else if (current.trackLast >= current.trackEnd && current.mixingFrom == NULL) { // // clear the track when there is no next entry, the track end time is reached, and there is no mixingFrom. -// tracksItems[i] = null; +// tracksItems[i] = NULL; // -// queue.End(current); +// queue.end(current); // disposeNext(current); // continue; // } -// if (current.mixingFrom != null && updateMixingFrom(current, delta)) { +// if (current.mixingFrom != NULL && updateMixingFrom(current, delta)) { // // End mixing from entries once all have completed. // var from = current.mixingFrom; -// current.mixingFrom = null; -// while (from != null) { -// queue.End(from); +// current.mixingFrom = NULL; +// while (from != NULL) { +// queue.end(from); // from = from.mixingFrom; // } // } @@ -497,7 +389,7 @@ namespace Spine // /// Returns true when all mixing from entries are complete. // private bool updateMixingFrom(TrackEntry to, float delta) { // TrackEntry from = to.mixingFrom; -// if (from == null) return true; +// if (from == NULL) return true; // // bool finished = updateMixingFrom(from, delta); // @@ -507,7 +399,7 @@ namespace Spine // if (from.totalAlpha == 0 || to.mixDuration == 0) { // to.mixingFrom = from.mixingFrom; // to.interruptAlpha = from.interruptAlpha; -// queue.End(from); +// queue.end(from); // } // return finished; // } @@ -523,24 +415,24 @@ namespace Spine // /// Poses the skeleton using the track entry animations. There are no side effects other than invoking listeners, so the // /// animation state can be applied to multiple skeletons to pose them identically. // public bool apply(Skeleton skeleton) { -// if (skeleton == null) throw new ArgumentNullException("skeleton", "skeleton cannot be null."); +// if (skeleton == NULL) throw new ArgumentNULLException("skeleton", "skeleton cannot be NULL."); // if (animationsChanged) animationsChanged(); // -// var events = this.events; +// var events = _events; // // bool applied = false; // var tracksItems = tracks.Items; // for (int i = 0, m = tracks.Count; i < m; i++) { // TrackEntry current = tracksItems[i]; -// if (current == null || current.delay > 0) continue; +// if (current == NULL || current.delay > 0) continue; // applied = true; // MixPose currentPose = i == 0 ? MixPose.Current : MixPose.CurrentLayered; // // // apply mixing from entries first. // float mix = current.alpha; -// if (current.mixingFrom != null) +// if (current.mixingFrom != NULL) // mix *= applyMixingFrom(current, skeleton, currentPose); -// else if (current.trackTime >= current.trackEnd && current.next == null) // +// else if (current.trackTime >= current.trackEnd && current.next == NULL) // // mix = 0; // Set to setup pose the last time the entry will be applied. // // // apply current entry. @@ -562,7 +454,7 @@ namespace Spine // Timeline timeline = timelinesItems[ii]; // MixPose pose = timelineData[ii] >= AnimationState.First ? MixPose.Setup : currentPose; // var rotateTimeline = timeline as RotateTimeline; -// if (rotateTimeline != null) +// if (rotateTimeline != NULL) // applyRotateTimeline(rotateTimeline, skeleton, animationTime, mix, pose, timelinesRotation, ii << 1, firstFrame); // else // timeline.apply(skeleton, animationLast, animationTime, events, mix, pose, MixDirection.In); @@ -580,7 +472,7 @@ namespace Spine // // private float applyMixingFrom(TrackEntry to, Skeleton skeleton, MixPose currentPose) { // TrackEntry from = to.mixingFrom; -// if (from.mixingFrom != null) applyMixingFrom(from, skeleton, currentPose); +// if (from.mixingFrom != NULL) applyMixingFrom(from, skeleton, currentPose); // // float mix; // if (to.mixDuration == 0) { // Single frame mix to undo mixingFrom changes. @@ -591,7 +483,7 @@ namespace Spine // if (mix > 1) mix = 1; // } // -// var eventBuffer = mix < from.eventThreshold ? this.events : null; +// var eventBuffer = mix < from.eventThreshold ? _events : NULL; // bool attachments = mix < from.attachmentThreshold, drawOrder = mix < from.drawOrderThreshold; // float animationLast = from.animationLast, animationTime = from.AnimationTime; // var timelines = from.animation.timelines; @@ -632,7 +524,7 @@ namespace Spine // } // from.totalAlpha += alpha; // var rotateTimeline = timeline as RotateTimeline; -// if (rotateTimeline != null) { +// if (rotateTimeline != NULL) { // applyRotateTimeline(rotateTimeline, skeleton, animationTime, alpha, pose, timelinesRotation, i << 1, firstFrame); // } else { // timeline.apply(skeleton, animationLast, animationTime, eventBuffer, alpha, pose, MixDirection.Out); @@ -640,7 +532,7 @@ namespace Spine // } // // if (to.mixDuration > 0) queueEvents(from, animationTime); -// this.events.clear(false); +// _events.clear(false); // from.nextAnimationLast = animationTime; // from.nextTrackLast = from.trackTime; // @@ -653,7 +545,7 @@ namespace Spine // if (firstFrame) timelinesRotation[i] = 0; // // if (alpha == 1) { -// rotateTimeline.apply(skeleton, 0, time, null, 1, pose, MixDirection.In); +// rotateTimeline.apply(skeleton, 0, time, NULL, 1, pose, MixDirection.In); // return; // } // @@ -718,27 +610,27 @@ namespace Spine // float trackLastWrapped = entry.trackLast % duration; // // // Queue events before complete. -// var events = this.events; +// var events = _events; // var eventsItems = events.Items; // int i = 0, n = events.Count; // for (; i < n; i++) { // var e = eventsItems[i]; // if (e.time < trackLastWrapped) break; // if (e.time > animationEnd) continue; // Discard events outside animation start/end. -// queue.Event(entry, e); +// queue.event(entry, e); // } // // // Queue complete if completed a loop iteration or the animation. // if (entry.loop ? (trackLastWrapped > entry.trackTime % duration) // : (animationTime >= animationEnd && entry.animationLast < animationEnd)) { -// queue.Complete(entry); +// queue.complete(entry); // } // // // Queue events after complete. // for (; i < n; i++) { // Event e = eventsItems[i]; // if (e.time < animationStart) continue; // Discard events outside animation start/end. -// queue.Event(entry, eventsItems[i]); +// queue.event(entry, eventsItems[i]); // } // } // @@ -764,22 +656,22 @@ namespace Spine // public void clearTrack(int trackIndex) { // if (trackIndex >= tracks.Count) return; // TrackEntry current = tracks.Items[trackIndex]; -// if (current == null) return; +// if (current == NULL) return; // -// queue.End(current); +// queue.end(current); // // disposeNext(current); // // TrackEntry entry = current; // while (true) { // TrackEntry from = entry.mixingFrom; -// if (from == null) break; -// queue.End(from); -// entry.mixingFrom = null; +// if (from == NULL) break; +// queue.end(from); +// entry.mixingFrom = NULL; // entry = from; // } // -// tracks.Items[current.trackIndex] = null; +// tracks.Items[current.trackIndex] = NULL; // // queue.drain(); // } @@ -789,26 +681,26 @@ namespace Spine // TrackEntry from = expandToIndex(index); // tracks.Items[index] = current; // -// if (from != null) { -// if (interrupt) queue.Interrupt(from); +// if (from != NULL) { +// if (interrupt) queue.interrupt(from); // current.mixingFrom = from; // current.mixTime = 0; // // // Store interrupted mix percentage. -// if (from.mixingFrom != null && from.mixDuration > 0) +// if (from.mixingFrom != NULL && from.mixDuration > 0) // current.interruptAlpha *= Math.Min(1, from.mixTime / from.mixDuration); // // from.timelinesRotation.clear(); // Reset rotation for mixing out, in case entry was mixed in. // } // -// queue.Start(current); // triggers animationsChanged +// queue.start(current); // triggers animationsChanged // } // // // /// Sets an animation by name. setAnimation(int, Animation, bool) // public TrackEntry setAnimation(int trackIndex, string animationName, bool loop) { // Animation animation = data.skeletonData.FindAnimation(animationName); -// if (animation == null) throw new ArgumentException("Animation not found: " + animationName, "animationName"); +// if (animation == NULL) throw new ArgumentException("Animation not found: " + animationName, "animationName"); // return setAnimation(trackIndex, animation, loop); // } // @@ -820,15 +712,15 @@ namespace Spine // /// A track entry to allow further customization of animation playback. References to the track entry must not be kept // /// after AnimationState.Dispose. // public TrackEntry setAnimation(int trackIndex, Animation animation, bool loop) { -// if (animation == null) throw new ArgumentNullException("animation", "animation cannot be null."); +// if (animation == NULL) throw new ArgumentNULLException("animation", "animation cannot be NULL."); // bool interrupt = true; // TrackEntry current = expandToIndex(trackIndex); -// if (current != null) { +// if (current != NULL) { // if (current.nextTrackLast == -1) { // // Don't mix from an entry that was never applied. // tracks.Items[trackIndex] = current.mixingFrom; -// queue.Interrupt(current); -// queue.End(current); +// queue.interrupt(current); +// queue.end(current); // disposeNext(current); // current = current.mixingFrom; // interrupt = false; @@ -846,7 +738,7 @@ namespace Spine // /// addAnimation(int, Animation, bool, float) // public TrackEntry addAnimation(int trackIndex, string animationName, bool loop, float delay) { // Animation animation = data.skeletonData.FindAnimation(animationName); -// if (animation == null) throw new ArgumentException("Animation not found: " + animationName, "animationName"); +// if (animation == NULL) throw new ArgumentException("Animation not found: " + animationName, "animationName"); // return addAnimation(trackIndex, animation, loop, delay); // } // @@ -859,17 +751,17 @@ namespace Spine // /// @return A track entry to allow further customization of animation playback. References to the track entry must not be kept // /// after AnimationState.Dispose // public TrackEntry addAnimation(int trackIndex, Animation animation, bool loop, float delay) { -// if (animation == null) throw new ArgumentNullException("animation", "animation cannot be null."); +// if (animation == NULL) throw new ArgumentNULLException("animation", "animation cannot be NULL."); // // TrackEntry last = expandToIndex(trackIndex); -// if (last != null) { -// while (last.next != null) +// if (last != NULL) { +// while (last.next != NULL) // last = last.next; // } // // TrackEntry entry = newTrackEntry(trackIndex, animation, loop, last); // -// if (last == null) { +// if (last == NULL) { // setCurrent(trackIndex, entry, true); // queue.drain(); // } else { @@ -921,7 +813,7 @@ namespace Spine // queue.drainDisabled = true; // for (int i = 0, n = tracks.Count; i < n; i++) { // TrackEntry current = tracks.Items[i]; -// if (current != null) setEmptyAnimation(i, mixDuration); +// if (current != NULL) setEmptyAnimation(i, mixDuration); // } // queue.drainDisabled = olddrainDisabled; // queue.drain(); @@ -930,12 +822,12 @@ namespace Spine // private TrackEntry expandToIndex(int index) { // if (index < tracks.Count) return tracks.Items[index]; // while (index >= tracks.Count) -// tracks.Add(null); -// return null; +// tracks.Add(NULL); +// return NULL; // } // // /// Object-pooling version of new TrackEntry. Obtain an unused TrackEntry from the pool and clear/initialize its values. -// /// @param last May be null. +// /// @param last May be NULL. // private TrackEntry newTrackEntry(int trackIndex, Animation animation, bool loop, TrackEntry last) { // TrackEntry entry = trackEntryPool.Obtain(); // Pooling // entry.trackIndex = trackIndex; @@ -961,45 +853,45 @@ namespace Spine // entry.alpha = 1; // entry.interruptAlpha = 1; // entry.mixTime = 0; -// entry.mixDuration = (last == null) ? 0 : data.GetMix(last.animation, animation); +// entry.mixDuration = (last == NULL) ? 0 : data.GetMix(last.animation, animation); // return entry; // } // // /// Dispose all track entries queued after the given TrackEntry. // private void disposeNext(TrackEntry entry) { // TrackEntry next = entry.next; -// while (next != null) { -// queue.Dispose(next); +// while (next != NULL) { +// queue.dispose(next); // next = next.next; // } -// entry.next = null; +// entry.next = NULL; // } // // private void animationsChanged() { // animationsChanged = false; // -// var propertyIDs = this.propertyIDs; +// var propertyIDs = _propertyIDs; // propertyIDs.clear(); -// var mixingTo = this.mixingTo; +// var mixingTo = _mixingTo; // // var tracksItems = tracks.Items; // for (int i = 0, n = tracks.Count; i < n; i++) { // var entry = tracksItems[i]; -// if (entry != null) entry.setTimelineData(null, mixingTo, propertyIDs); +// if (entry != NULL) entry.setTimelineData(NULL, mixingTo, propertyIDs); // } // } // -// /// @return The track entry for the animation currently playing on the track, or null if no animation is currently playing. +// /// @return The track entry for the animation currently playing on the track, or NULL if no animation is currently playing. // public TrackEntry getCurrent(int trackIndex) { -// return (trackIndex >= tracks.Count) ? null : tracks.Items[trackIndex]; +// return (trackIndex >= tracks.Count) ? NULL : tracks.Items[trackIndex]; // } // -// internal void onStart(TrackEntry entry) { if (Start != null) Start(entry); } -// internal void onInterrupt(TrackEntry entry) { if (Interrupt != null) Interrupt(entry); } -// internal void onEnd(TrackEntry entry) { if (End != null) End(entry); } -// internal void onDispose(TrackEntry entry) { if (Dispose != null) Dispose(entry); } -// internal void onComplete(TrackEntry entry) { if (Complete != null) Complete(entry); } -// internal void onEvent(TrackEntry entry, Event e) { if (Event != null) Event(entry, e); } +// internal void onStart(TrackEntry entry) { if (Start != NULL) Start(entry); } +// internal void onInterrupt(TrackEntry entry) { if (Interrupt != NULL) Interrupt(entry); } +// internal void onEnd(TrackEntry entry) { if (End != NULL) End(entry); } +// internal void onDispose(TrackEntry entry) { if (Dispose != NULL) Dispose(entry); } +// internal void onComplete(TrackEntry entry) { if (Complete != NULL) Complete(entry); } +// internal void onEvent(TrackEntry entry, Event e) { if (Event != NULL) Event(entry, e); } }; } diff --git a/spine-cpp/spine-cpp/src/spine/AnimationState.cpp b/spine-cpp/spine-cpp/src/spine/AnimationState.cpp index 011f0b660..fedf61748 100644 --- a/spine-cpp/spine-cpp/src/spine/AnimationState.cpp +++ b/spine-cpp/spine-cpp/src/spine/AnimationState.cpp @@ -31,6 +31,9 @@ #include #include +#include + +#include #include @@ -38,7 +41,7 @@ namespace Spine { TrackEntry::TrackEntry() { - + // Empty } int TrackEntry::getTrackIndex() { return _trackIndex; } @@ -116,11 +119,199 @@ namespace Spine TrackEntry* TrackEntry::getMixingFrom() { return _mixingFrom; } -// event AnimationState.TrackEntryDelegate Start, Interrupt, End, Dispose, Complete; -// event AnimationState.TrackEntryEventDelegate Event; - void TrackEntry::resetRotationDirections() { _timelinesRotation.clear(); } + + void TrackEntry::setOnAnimationEventFunc(OnAnimationEventFunc inValue) + { + _onAnimationEventFunc = inValue; + } + + TrackEntry* TrackEntry::setTimelineData(TrackEntry* to, Vector& mixingToArray, Vector& propertyIDs) + { + if (to != NULL) + { + mixingToArray.push_back(to); + } + + TrackEntry* lastEntry = _mixingFrom != NULL ? _mixingFrom->setTimelineData(this, mixingToArray, propertyIDs) : this; + + if (to != NULL) + { + mixingToArray.erase(mixingToArray.size() - 1); + } + + int mixingToLast = static_cast(mixingToArray.size()) - 1; + Vector& timelines = _animation->_timelines; + int timelinesCount = static_cast(timelines.size()); + _timelineData.reserve(timelinesCount); + _timelineDipMix.clear(); + _timelineDipMix.reserve(timelinesCount); + + // outer: + for (int i = 0; i < timelinesCount; ++i) + { + int id = timelines[i]->getPropertyId(); + if (propertyIDs.contains(id)) + { + _timelineData[i] = AnimationState::Subsequent; + } + else if (to == NULL || !to->hasTimeline(id)) + { + _timelineData[i] = AnimationState::First; + } + else + { + for (int ii = mixingToLast; ii >= 0; --ii) + { + TrackEntry* entry = mixingToArray[ii]; + if (!entry->hasTimeline(id)) + { + if (entry->_mixDuration > 0) + { + _timelineData[i] = AnimationState::DipMix; + _timelineDipMix[i] = entry; + goto continue_outer; // continue outer; + } + break; + } + } + _timelineData[i] = AnimationState::Dip; + } + continue_outer: {} + } + + return lastEntry; + } + + bool TrackEntry::hasTimeline(int inId) + { + Vector& timelines = _animation->_timelines; + for (int i = 0, n = static_cast(timelines.size()); i < n; ++i) + { + if (timelines[i]->getPropertyId() == inId) + { + return true; + } + } + return false; + } + + void TrackEntry::reset() + { + _animation = NULL; + _next = NULL; + _mixingFrom = NULL; + + _timelineData.clear(); + _timelineDipMix.clear(); + _timelinesRotation.clear(); + + _onAnimationEventFunc = NULL; + } + + EventQueue::EventQueue(AnimationState& state, Pool& trackEntryPool) : _state(state), _trackEntryPool(trackEntryPool) + { + // Empty + } + + void EventQueue::start(TrackEntry* entry) + { + _eventQueueEntries.push_back(new EventQueueEntry(EventType_Start, entry)); + _state._animationsChanged = true; + } + + void EventQueue::interrupt(TrackEntry* entry) + { + _eventQueueEntries.push_back(new EventQueueEntry(EventType_Interrupt, entry)); + } + + void EventQueue::end(TrackEntry* entry) + { + _eventQueueEntries.push_back(new EventQueueEntry(EventType_End, entry)); + _state._animationsChanged = true; + } + + void EventQueue::dispose(TrackEntry* entry) + { + _eventQueueEntries.push_back(new EventQueueEntry(EventType_Dispose, entry)); + } + + void EventQueue::complete(TrackEntry* entry) + { + _eventQueueEntries.push_back(new EventQueueEntry(EventType_Complete, entry)); + } + + void EventQueue::event(TrackEntry* entry, Event* e) + { + _eventQueueEntries.push_back(new EventQueueEntry(EventType_Event, entry, e)); + } + + /// Raises all events in the queue and drains the queue. + void EventQueue::drain() + { + if (_drainDisabled) + { + return; + } + + _drainDisabled = true; + + AnimationState& state = _state; + + // Don't cache entries.size() so callbacks can queue their own events (eg, call setAnimation in AnimationState_Complete). + for (int i = 0; i < _eventQueueEntries.size(); ++i) + { + EventQueueEntry* queueEntry = _eventQueueEntries[i]; + TrackEntry* trackEntry = queueEntry->_entry; + + switch (queueEntry->_type) + { +// case EventType_Start: +// trackEntry.onStart(); +// state.onStart(trackEntry); +// break; +// case EventType_Interrupt: +// trackEntry.onInterrupt(); +// state.onInterrupt(trackEntry); +// break; +// case EventType_End: +// trackEntry.onEnd(); +// state.onEnd(trackEntry); +// case EventType_Dispose: +// trackEntry.onDispose(); +// state.onDispose(trackEntry); +// trackEntryPool.Free(trackEntry); // Pooling +// break; +// case EventType_Complete: +// trackEntry.onComplete(); +// state.onComplete(trackEntry); +// break; +// case EventType_Event: +// trackEntry.onEvent(queueEntry.e); +// state.onEvent(trackEntry, queueEntry.e); +// break; + } + } + _eventQueueEntries.clear(); + + _drainDisabled = false; + } + + void EventQueue::clear() + { + _eventQueueEntries.clear(); + } + + const int AnimationState::Subsequent = 0; + const int AnimationState::First = 1; + const int AnimationState::Dip = 2; + const int AnimationState::DipMix = 3; + + void AnimationState::setOnAnimationEventFunc(OnAnimationEventFunc inValue) + { + _onAnimationEventFunc = inValue; + } } From 9bed800466d18f533a23b0b723c8e24ea6cf8d96 Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Wed, 29 Nov 2017 18:30:22 -0500 Subject: [PATCH 54/83] wip, just gotta implement the AnimationState class itself now. --- .../spine-cpp/include/spine/AnimationState.h | 8 ++- .../spine-cpp/src/spine/AnimationState.cpp | 55 ++++++++++--------- 2 files changed, 36 insertions(+), 27 deletions(-) diff --git a/spine-cpp/spine-cpp/include/spine/AnimationState.h b/spine-cpp/spine-cpp/include/spine/AnimationState.h index 4408dd4c6..1b893a94b 100644 --- a/spine-cpp/spine-cpp/include/spine/AnimationState.h +++ b/spine-cpp/spine-cpp/include/spine/AnimationState.h @@ -52,11 +52,13 @@ namespace Spine class Animation; class Event; - typedef void (*OnAnimationEventFunc) (AnimationState* state, EventType type, TrackEntry* entry, Event* event); + typedef void (*OnAnimationEventFunc) (AnimationState& state, EventType type, TrackEntry* entry, Event* event); /// State for the playback of an animation class TrackEntry { + friend class EventQueue; + public: TrackEntry(); @@ -218,7 +220,7 @@ namespace Spine bool _loop; float _eventThreshold, _attachmentThreshold, _drawOrderThreshold; float _animationStart, _animationEnd, _animationLast, _nextAnimationLast; - float _delay, _trackTime, _trackLast, _nextTrackLast, _trackEnd, _timeScale = 1.0f; + float _delay, _trackTime, _trackLast, _nextTrackLast, _trackEnd, _timeScale; float _alpha, _mixTime, _mixDuration, _interruptAlpha, _totalAlpha; Vector _timelineData; Vector _timelineDipMix; @@ -288,6 +290,8 @@ namespace Spine friend class EventQueue; public: + AnimationState(); + void setOnAnimationEventFunc(OnAnimationEventFunc inValue); private: diff --git a/spine-cpp/spine-cpp/src/spine/AnimationState.cpp b/spine-cpp/spine-cpp/src/spine/AnimationState.cpp index fedf61748..16954ade4 100644 --- a/spine-cpp/spine-cpp/src/spine/AnimationState.cpp +++ b/spine-cpp/spine-cpp/src/spine/AnimationState.cpp @@ -39,7 +39,12 @@ namespace Spine { - TrackEntry::TrackEntry() + void dummyOnAnimationEventFunc(AnimationState& state, EventType type, TrackEntry* entry, Event* event = NULL) + { + // Empty + } + + TrackEntry::TrackEntry() : _animation(NULL), _next(NULL), _mixingFrom(NULL), _trackIndex(0), _loop(false), _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(1.0f), _alpha(0), _mixTime(0), _mixDuration(0), _interruptAlpha(0), _totalAlpha(0), _onAnimationEventFunc(dummyOnAnimationEventFunc) { // Empty } @@ -269,30 +274,25 @@ namespace Spine switch (queueEntry->_type) { -// case EventType_Start: -// trackEntry.onStart(); -// state.onStart(trackEntry); -// break; -// case EventType_Interrupt: -// trackEntry.onInterrupt(); -// state.onInterrupt(trackEntry); -// break; -// case EventType_End: -// trackEntry.onEnd(); -// state.onEnd(trackEntry); -// case EventType_Dispose: -// trackEntry.onDispose(); -// state.onDispose(trackEntry); -// trackEntryPool.Free(trackEntry); // Pooling -// break; -// case EventType_Complete: -// trackEntry.onComplete(); -// state.onComplete(trackEntry); -// break; -// case EventType_Event: -// trackEntry.onEvent(queueEntry.e); -// state.onEvent(trackEntry, queueEntry.e); -// break; + case EventType_Start: + case EventType_Interrupt: + case EventType_Complete: + trackEntry->_onAnimationEventFunc(state, queueEntry->_type, trackEntry, NULL); + state._onAnimationEventFunc(state, queueEntry->_type, trackEntry, NULL); + break; + case EventType_End: + trackEntry->_onAnimationEventFunc(state, queueEntry->_type, trackEntry, NULL); + state._onAnimationEventFunc(state, queueEntry->_type, trackEntry, NULL); + /* Yes, we want to fall through here */ + case EventType_Dispose: + trackEntry->_onAnimationEventFunc(state, EventType_Dispose, trackEntry, NULL); + state._onAnimationEventFunc(state, EventType_Dispose, trackEntry, NULL); + _trackEntryPool.free(trackEntry); + break; + case EventType_Event: + trackEntry->_onAnimationEventFunc(state, queueEntry->_type, trackEntry, queueEntry->_event); + state._onAnimationEventFunc(state, queueEntry->_type, trackEntry, queueEntry->_event); + break; } } _eventQueueEntries.clear(); @@ -310,6 +310,11 @@ namespace Spine const int AnimationState::Dip = 2; const int AnimationState::DipMix = 3; + AnimationState::AnimationState() : _onAnimationEventFunc(dummyOnAnimationEventFunc) + { + // Empty + } + void AnimationState::setOnAnimationEventFunc(OnAnimationEventFunc inValue) { _onAnimationEventFunc = inValue; From 0ca68030301a21ef77b88e407a060be1913ef708 Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Thu, 30 Nov 2017 11:11:15 -0500 Subject: [PATCH 55/83] wip --- .../spine-cpp/include/spine/AnimationState.h | 735 +++++++++--------- spine-cpp/spine-cpp/include/spine/Extension.h | 1 + spine-cpp/spine-cpp/include/spine/HashMap.h | 2 +- spine-cpp/spine-cpp/include/spine/Pool.h | 2 +- .../spine-cpp/src/spine/AnimationState.cpp | 113 ++- spine-cpp/spine-cpp/src/spine/Atlas.cpp | 4 +- .../src/spine/AtlasAttachmentLoader.cpp | 12 +- spine-cpp/spine-cpp/src/spine/Skeleton.cpp | 12 +- .../spine-cpp/src/spine/SkeletonBounds.cpp | 2 +- 9 files changed, 477 insertions(+), 406 deletions(-) diff --git a/spine-cpp/spine-cpp/include/spine/AnimationState.h b/spine-cpp/spine-cpp/include/spine/AnimationState.h index 1b893a94b..16ed3c9ce 100644 --- a/spine-cpp/spine-cpp/include/spine/AnimationState.h +++ b/spine-cpp/spine-cpp/include/spine/AnimationState.h @@ -33,6 +33,7 @@ #include #include +#include namespace Spine { @@ -51,6 +52,9 @@ namespace Spine class Animation; class Event; + class AnimationStateData; + class Skeleton; + class RotateTimeline; typedef void (*OnAnimationEventFunc) (AnimationState& state, EventType type, TrackEntry* entry, Event* event); @@ -58,6 +62,7 @@ namespace Spine class TrackEntry { friend class EventQueue; + friend class AnimationState; public: TrackEntry(); @@ -245,12 +250,7 @@ namespace Spine TrackEntry* _entry; Event* _event; - EventQueueEntry(EventType eventType, TrackEntry* trackEntry, Event* event = NULL) - { - _type = eventType; - _entry = trackEntry; - _event = event; - } + EventQueueEntry(EventType eventType, TrackEntry* trackEntry, Event* event = NULL); }; class EventQueue @@ -259,13 +259,18 @@ namespace Spine private: Vector _eventQueueEntries; - bool _drainDisabled; - AnimationState& _state; Pool& _trackEntryPool; + bool _drainDisabled; + + static EventQueue* newEventQueue(AnimationState& state, Pool& trackEntryPool); + static EventQueueEntry* newEventQueueEntry(EventType eventType, TrackEntry* entry, Event* event = NULL); + EventQueue(AnimationState& state, Pool& trackEntryPool); - + + ~EventQueue(); + void start(TrackEntry* entry); void interrupt(TrackEntry* entry); @@ -276,12 +281,10 @@ namespace Spine void complete(TrackEntry* entry); - void event(TrackEntry* entry, Event* e); + void event(TrackEntry* entry, Event* event); /// Raises all events in the queue and drains the queue. void drain(); - - void clear(); }; class AnimationState @@ -290,49 +293,17 @@ namespace Spine friend class EventQueue; public: - AnimationState(); + AnimationState(AnimationStateData& data); + + ~AnimationState(); void setOnAnimationEventFunc(OnAnimationEventFunc inValue); - private: - static const int Subsequent, First, Dip, DipMix; -// static readonly Animation EmptyAnimation = new Animation("", new Vector(), 0); - -// -// private AnimationStateData data; -// -// Pool trackEntryPool = new Pool(); -// private readonly Vector tracks = new Vector(); -// private readonly Vector events = new Vector(); -// private readonly EventQueue queue; // Initialized by constructor. -// -// private readonly HashSet propertyIDs = new HashSet(); -// private readonly Vector mixingTo = new Vector(); - bool _animationsChanged; -// -// private float timeScale = 1; -// -// public AnimationStateData Data { get { return data; } } -// /// A list of tracks that have animations, which may contain NULLs. -// public Vector Tracks { get { return tracks; } } -// public float TimeScale { get { return timeScale; } set { timeScale = value; } } -// - OnAnimationEventFunc _onAnimationEventFunc; -// -// public AnimationState(AnimationStateData data) { -// if (data == NULL) throw new ArgumentNULLException("data", "data cannot be NULL."); -// _data = data; -// _queue = new EventQueue( -// this, -// delegate { _animationsChanged = true; }, -// trackEntryPool -// ); -// } -// -// /// -// /// Increments the track entry times, setting queued animations as current if needed -// /// @param delta delta time -// public void update(float delta) { + /// + /// Increments the track entry times, setting queued animations as current if needed + /// @param delta delta time + void update(float delta) + { // delta *= timeScale; // var tracksItems = tracks.Items; // for (int i = 0, n = tracks.Count; i < n; i++) { @@ -388,43 +359,18 @@ namespace Spine // } // // queue.drain(); -// } -// -// /// Returns true when all mixing from entries are complete. -// private bool updateMixingFrom(TrackEntry to, float delta) { -// TrackEntry from = to.mixingFrom; -// if (from == NULL) return true; -// -// bool finished = updateMixingFrom(from, delta); -// -// // Require mixTime > 0 to ensure the mixing from entry was applied at least once. -// if (to.mixTime > 0 && (to.mixTime >= to.mixDuration || to.timeScale == 0)) { -// // Require totalAlpha == 0 to ensure mixing is complete, unless mixDuration == 0 (the transition is a single frame). -// if (from.totalAlpha == 0 || to.mixDuration == 0) { -// to.mixingFrom = from.mixingFrom; -// to.interruptAlpha = from.interruptAlpha; -// queue.end(from); -// } -// return finished; -// } -// -// from.animationLast = from.nextAnimationLast; -// from.trackLast = from.nextTrackLast; -// from.trackTime += delta * from.timeScale; -// to.mixTime += delta * to.timeScale; -// return false; -// } -// -// /// -// /// Poses the skeleton using the track entry animations. There are no side effects other than invoking listeners, so the -// /// animation state can be applied to multiple skeletons to pose them identically. -// public bool apply(Skeleton skeleton) { -// if (skeleton == NULL) throw new ArgumentNULLException("skeleton", "skeleton cannot be NULL."); + } + + /// + /// Poses the skeleton using the track entry animations. There are no side effects other than invoking listeners, so the + /// animation state can be applied to multiple skeletons to pose them identically. + bool apply(Skeleton& skeleton) + { // if (animationsChanged) animationsChanged(); // // var events = _events; // -// bool applied = false; + bool applied = false; // var tracksItems = tracks.Items; // for (int i = 0, m = tracks.Count; i < m; i++) { // TrackEntry current = tracksItems[i]; @@ -471,10 +417,312 @@ namespace Spine // } // // queue.drain(); -// return applied; -// } + return applied; + } + + /// + /// Removes all animations from all tracks, leaving skeletons in their previous pose. + /// It may be desired to use AnimationState.setEmptyAnimations(float) to mix the skeletons back to the setup pose, + /// rather than leaving them in their previous pose. + void clearTracks() + { +// bool olddrainDisabled = queue.drainDisabled; +// queue.drainDisabled = true; +// for (int i = 0, n = tracks.Count; i < n; i++) { +// clearTrack(i); +// } +// tracks.clear(); +// queue.drainDisabled = olddrainDisabled; +// queue.drain(); + } + + /// + /// Removes all animations from the tracks, leaving skeletons in their previous pose. + /// It may be desired to use AnimationState.setEmptyAnimations(float) to mix the skeletons back to the setup pose, + /// rather than leaving them in their previous pose. + void clearTrack(int trackIndex) + { +// if (trackIndex >= tracks.Count) return; +// TrackEntry current = tracks.Items[trackIndex]; +// if (current == NULL) return; // -// private float applyMixingFrom(TrackEntry to, Skeleton skeleton, MixPose currentPose) { +// queue.end(current); +// +// disposeNext(current); +// +// TrackEntry entry = current; +// while (true) { +// TrackEntry from = entry.mixingFrom; +// if (from == NULL) break; +// queue.end(from); +// entry.mixingFrom = NULL; +// entry = from; +// } +// +// tracks.Items[current.trackIndex] = NULL; +// +// queue.drain(); + } + + /// Sets an animation by name. setAnimation(int, Animation, bool) + TrackEntry* setAnimation(int trackIndex, std::string animationName, bool loop) + { +// Animation animation = data.skeletonData.FindAnimation(animationName); +// if (animation == NULL) throw new ArgumentException("Animation not found: " + animationName, "animationName"); +// return setAnimation(trackIndex, animation, loop); + return NULL; + } + + /// Sets the current animation for a track, discarding any queued animations. + /// @param loop If true, the animation will repeat. + /// If false, it will not, instead its last frame is applied if played beyond its duration. + /// In either case TrackEntry.TrackEnd determines when the track is cleared. + /// @return + /// A track entry to allow further customization of animation playback. References to the track entry must not be kept + /// after AnimationState.Dispose. + TrackEntry* setAnimation(int trackIndex, Animation& animation, bool loop) + { +// bool interrupt = true; +// TrackEntry current = expandToIndex(trackIndex); +// if (current != NULL) { +// if (current.nextTrackLast == -1) { +// // Don't mix from an entry that was never applied. +// tracks.Items[trackIndex] = current.mixingFrom; +// queue.interrupt(current); +// queue.end(current); +// disposeNext(current); +// current = current.mixingFrom; +// interrupt = false; +// } else { +// disposeNext(current); +// } +// } +// TrackEntry entry = newTrackEntry(trackIndex, animation, loop, current); +// setCurrent(trackIndex, entry, interrupt); +// queue.drain(); +// return entry; + return NULL; + } + + /// Queues an animation by name. + /// addAnimation(int, Animation, bool, float) + TrackEntry* addAnimation(int trackIndex, std::string animationName, bool loop, float delay) + { +// Animation animation = data.skeletonData.FindAnimation(animationName); +// if (animation == NULL) throw new ArgumentException("Animation not found: " + animationName, "animationName"); +// return addAnimation(trackIndex, animation, loop, delay); + return NULL; + } + + /// Adds an animation to be played delay seconds after the current or last queued animation + /// for a track. If the track is empty, it is equivalent to calling setAnimation. + /// @param delay + /// Seconds to begin this animation after the start of the previous animation. May be <= 0 to use the animation + /// duration of the previous track minus any mix duration plus the negative delay. + /// + /// @return A track entry to allow further customization of animation playback. References to the track entry must not be kept + /// after AnimationState.Dispose + TrackEntry* addAnimation(int trackIndex, Animation& animation, bool loop, float delay) + { +// TrackEntry last = expandToIndex(trackIndex); +// if (last != NULL) { +// while (last.next != NULL) +// last = last.next; +// } +// +// TrackEntry entry = newTrackEntry(trackIndex, animation, loop, last); +// +// if (last == NULL) { +// setCurrent(trackIndex, entry, true); +// queue.drain(); +// } else { +// last.next = entry; +// if (delay <= 0) { +// float duration = last.animationEnd - last.animationStart; +// if (duration != 0) +// delay += duration * (1 + (int)(last.trackTime / duration)) - data.GetMix(last.animation, animation); +// else +// delay = 0; +// } +// } +// +// entry.delay = delay; +// return entry; + return NULL; + } + + /// + /// Sets an empty animation for a track, discarding any queued animations, and mixes to it over the specified mix duration. + TrackEntry* setEmptyAnimation(int trackIndex, float mixDuration) + { + TrackEntry* entry = setAnimation(trackIndex, AnimationState::getEmptyAnimation(), false); + entry->_mixDuration = mixDuration; + entry->_trackEnd = mixDuration; + return entry; + } + + /// + /// Adds an empty animation to be played after the current or last queued animation for a track, and mixes to it over the + /// specified mix duration. + /// @return + /// A track entry to allow further customization of animation playback. References to the track entry must not be kept after AnimationState.Dispose. + /// + /// @param trackIndex Track number. + /// @param mixDuration Mix duration. + /// @param delay Seconds to begin this animation after the start of the previous animation. May be <= 0 to use the animation + /// duration of the previous track minus any mix duration plus the negative delay. + TrackEntry* addEmptyAnimation(int trackIndex, float mixDuration, float delay) + { + if (delay <= 0) + { + delay -= mixDuration; + } + + TrackEntry* entry = addAnimation(trackIndex, AnimationState::getEmptyAnimation(), false, delay); + entry->_mixDuration = mixDuration; + entry->_trackEnd = mixDuration; + return entry; + } + + /// + /// Sets an empty animation for every track, discarding any queued animations, and mixes to it over the specified mix duration. + void setEmptyAnimations(float mixDuration) + { +// bool olddrainDisabled = queue.drainDisabled; +// queue.drainDisabled = true; +// for (int i = 0, n = tracks.Count; i < n; i++) +// { +// TrackEntry current = tracks.Items[i]; +// if (current != NULL) setEmptyAnimation(i, mixDuration); +// } +// queue.drainDisabled = olddrainDisabled; +// queue.drain(); + } + + /// @return The track entry for the animation currently playing on the track, or NULL if no animation is currently playing. + TrackEntry* getCurrent(int trackIndex) + { + return trackIndex >= _tracks.size() ? NULL : _tracks[trackIndex]; + } + +// AnimationStateData Data { get { return data; } } +// /// A list of tracks that have animations, which may contain NULLs. +// Vector Tracks { get { return tracks; } } +// float TimeScale { get { return timeScale; } set { timeScale = value; } } + + private: + static const int Subsequent, First, Dip, DipMix; + + AnimationStateData& _data; + + Pool _trackEntryPool; + Vector _tracks; + Vector _events; + EventQueue* _queue; + + Vector _propertyIDs; + Vector _mixingTo; + bool _animationsChanged; + + OnAnimationEventFunc _onAnimationEventFunc; + + float _timeScale; + + static Animation& getEmptyAnimation(); + + static void applyRotateTimeline(RotateTimeline* rotateTimeline, Skeleton& skeleton, float time, float alpha, MixPose pose, + Vector& timelinesRotation, int i, bool firstFrame) + { +// if (firstFrame) timelinesRotation[i] = 0; +// +// if (alpha == 1) { +// rotateTimeline.apply(skeleton, 0, time, NULL, 1, pose, MixDirection.In); +// return; +// } +// +// Bone bone = skeleton.bones.Items[rotateTimeline.boneIndex]; +// float[] frames = rotateTimeline.frames; +// if (time < frames[0]) { +// if (pose == MixPose.Setup) bone.rotation = bone.data.rotation; +// return; +// } +// +// float r2; +// if (time >= frames[frames.Length - RotateTimeline.ENTRIES]) // Time is after last frame. +// r2 = bone.data.rotation + frames[frames.Length + RotateTimeline.PREV_ROTATION]; +// else { +// // Interpolate between the previous frame and the current frame. +// int frame = Animation.BinarySearch(frames, time, RotateTimeline.ENTRIES); +// float prevRotation = frames[frame + RotateTimeline.PREV_ROTATION]; +// float frameTime = frames[frame]; +// float percent = rotateTimeline.GetCurvePercent((frame >> 1) - 1, +// 1 - (time - frameTime) / (frames[frame + RotateTimeline.PREV_TIME] - frameTime)); +// +// r2 = frames[frame + RotateTimeline.ROTATION] - prevRotation; +// r2 -= (16384 - (int)(16384.499999999996 - r2 / 360)) * 360; +// r2 = prevRotation + r2 * percent + bone.data.rotation; +// r2 -= (16384 - (int)(16384.499999999996 - r2 / 360)) * 360; +// } +// +// // Mix between rotations using the direction of the shortest route on the first frame while detecting crosses. +// float r1 = pose == MixPose.Setup ? bone.data.rotation : bone.rotation; +// float total, diff = r2 - r1; +// if (diff == 0) { +// total = timelinesRotation[i]; +// } else { +// diff -= (16384 - (int)(16384.499999999996 - diff / 360)) * 360; +// float lastTotal, lastDiff; +// if (firstFrame) { +// lastTotal = 0; +// lastDiff = diff; +// } else { +// lastTotal = timelinesRotation[i]; // Angle and direction of mix, including loops. +// lastDiff = timelinesRotation[i + 1]; // Difference between bones. +// } +// bool current = diff > 0, dir = lastTotal >= 0; +// // Detect cross at 0 (not 180). +// if (Math.Sign(lastDiff) != Math.Sign(diff) && Math.Abs(lastDiff) <= 90) { +// // A cross after a 360 rotation is a loop. +// if (Math.Abs(lastTotal) > 180) lastTotal += 360 * Math.Sign(lastTotal); +// dir = current; +// } +// total = diff + lastTotal - lastTotal % 360; // Store loops as part of lastTotal. +// if (dir != current) total += 360 * Math.Sign(lastTotal); +// timelinesRotation[i] = total; +// } +// timelinesRotation[i + 1] = diff; +// r1 += total * alpha; +// bone.rotation = r1 - (16384 - (int)(16384.499999999996 - r1 / 360)) * 360; + } + + /// Returns true when all mixing from entries are complete. + bool updateMixingFrom(TrackEntry to, float delta) + { +// TrackEntry from = to.mixingFrom; +// if (from == NULL) return true; +// +// bool finished = updateMixingFrom(from, delta); +// +// // Require mixTime > 0 to ensure the mixing from entry was applied at least once. +// if (to.mixTime > 0 && (to.mixTime >= to.mixDuration || to.timeScale == 0)) { +// // Require totalAlpha == 0 to ensure mixing is complete, unless mixDuration == 0 (the transition is a single frame). +// if (from.totalAlpha == 0 || to.mixDuration == 0) { +// to.mixingFrom = from.mixingFrom; +// to.interruptAlpha = from.interruptAlpha; +// queue.end(from); +// } +// return finished; +// } +// +// from.animationLast = from.nextAnimationLast; +// from.trackLast = from.nextTrackLast; +// from.trackTime += delta * from.timeScale; +// to.mixTime += delta * to.timeScale; + return false; + } + + float applyMixingFrom(TrackEntry* to, Skeleton& skeleton, MixPose currentPose) + { // TrackEntry from = to.mixingFrom; // if (from.mixingFrom != NULL) applyMixingFrom(from, skeleton, currentPose); // @@ -541,74 +789,11 @@ namespace Spine // from.nextTrackLast = from.trackTime; // // return mix; -// } -// -// static private void applyRotateTimeline(RotateTimeline rotateTimeline, Skeleton skeleton, float time, float alpha, MixPose pose, -// float[] timelinesRotation, int i, bool firstFrame) { -// -// if (firstFrame) timelinesRotation[i] = 0; -// -// if (alpha == 1) { -// rotateTimeline.apply(skeleton, 0, time, NULL, 1, pose, MixDirection.In); -// return; -// } -// -// Bone bone = skeleton.bones.Items[rotateTimeline.boneIndex]; -// float[] frames = rotateTimeline.frames; -// if (time < frames[0]) { -// if (pose == MixPose.Setup) bone.rotation = bone.data.rotation; -// return; -// } -// -// float r2; -// if (time >= frames[frames.Length - RotateTimeline.ENTRIES]) // Time is after last frame. -// r2 = bone.data.rotation + frames[frames.Length + RotateTimeline.PREV_ROTATION]; -// else { -// // Interpolate between the previous frame and the current frame. -// int frame = Animation.BinarySearch(frames, time, RotateTimeline.ENTRIES); -// float prevRotation = frames[frame + RotateTimeline.PREV_ROTATION]; -// float frameTime = frames[frame]; -// float percent = rotateTimeline.GetCurvePercent((frame >> 1) - 1, -// 1 - (time - frameTime) / (frames[frame + RotateTimeline.PREV_TIME] - frameTime)); -// -// r2 = frames[frame + RotateTimeline.ROTATION] - prevRotation; -// r2 -= (16384 - (int)(16384.499999999996 - r2 / 360)) * 360; -// r2 = prevRotation + r2 * percent + bone.data.rotation; -// r2 -= (16384 - (int)(16384.499999999996 - r2 / 360)) * 360; -// } -// -// // Mix between rotations using the direction of the shortest route on the first frame while detecting crosses. -// float r1 = pose == MixPose.Setup ? bone.data.rotation : bone.rotation; -// float total, diff = r2 - r1; -// if (diff == 0) { -// total = timelinesRotation[i]; -// } else { -// diff -= (16384 - (int)(16384.499999999996 - diff / 360)) * 360; -// float lastTotal, lastDiff; -// if (firstFrame) { -// lastTotal = 0; -// lastDiff = diff; -// } else { -// lastTotal = timelinesRotation[i]; // Angle and direction of mix, including loops. -// lastDiff = timelinesRotation[i + 1]; // Difference between bones. -// } -// bool current = diff > 0, dir = lastTotal >= 0; -// // Detect cross at 0 (not 180). -// if (Math.Sign(lastDiff) != Math.Sign(diff) && Math.Abs(lastDiff) <= 90) { -// // A cross after a 360 rotation is a loop. -// if (Math.Abs(lastTotal) > 180) lastTotal += 360 * Math.Sign(lastTotal); -// dir = current; -// } -// total = diff + lastTotal - lastTotal % 360; // Store loops as part of lastTotal. -// if (dir != current) total += 360 * Math.Sign(lastTotal); -// timelinesRotation[i] = total; -// } -// timelinesRotation[i + 1] = diff; -// r1 += total * alpha; -// bone.rotation = r1 - (16384 - (int)(16384.499999999996 - r1 / 360)) * 360; -// } -// -// private void queueEvents(TrackEntry entry, float animationTime) { + return 0; + } + + void queueEvents(TrackEntry* entry, float animationTime) + { // float animationStart = entry.animationStart, animationEnd = entry.animationEnd; // float duration = animationEnd - animationStart; // float trackLastWrapped = entry.trackLast % duration; @@ -636,52 +821,11 @@ namespace Spine // if (e.time < animationStart) continue; // Discard events outside animation start/end. // queue.event(entry, eventsItems[i]); // } -// } -// -// /// -// /// Removes all animations from all tracks, leaving skeletons in their previous pose. -// /// It may be desired to use AnimationState.setEmptyAnimations(float) to mix the skeletons back to the setup pose, -// /// rather than leaving them in their previous pose. -// public void clearTracks() { -// bool olddrainDisabled = queue.drainDisabled; -// queue.drainDisabled = true; -// for (int i = 0, n = tracks.Count; i < n; i++) { -// clearTrack(i); -// } -// tracks.clear(); -// queue.drainDisabled = olddrainDisabled; -// queue.drain(); -// } -// -// /// -// /// Removes all animations from the tracks, leaving skeletons in their previous pose. -// /// It may be desired to use AnimationState.setEmptyAnimations(float) to mix the skeletons back to the setup pose, -// /// rather than leaving them in their previous pose. -// public void clearTrack(int trackIndex) { -// if (trackIndex >= tracks.Count) return; -// TrackEntry current = tracks.Items[trackIndex]; -// if (current == NULL) return; -// -// queue.end(current); -// -// disposeNext(current); -// -// TrackEntry entry = current; -// while (true) { -// TrackEntry from = entry.mixingFrom; -// if (from == NULL) break; -// queue.end(from); -// entry.mixingFrom = NULL; -// entry = from; -// } -// -// tracks.Items[current.trackIndex] = NULL; -// -// queue.drain(); -// } -// -// /// Sets the active TrackEntry for a given track number. -// private void setCurrent(int index, TrackEntry current, bool interrupt) { + } + + /// Sets the active TrackEntry for a given track number. + void setCurrent(int index, TrackEntry* current, bool interrupt) + { // TrackEntry from = expandToIndex(index); // tracks.Items[index] = current; // @@ -698,141 +842,22 @@ namespace Spine // } // // queue.start(current); // triggers animationsChanged -// } -// -// -// /// Sets an animation by name. setAnimation(int, Animation, bool) -// public TrackEntry setAnimation(int trackIndex, string animationName, bool loop) { -// Animation animation = data.skeletonData.FindAnimation(animationName); -// if (animation == NULL) throw new ArgumentException("Animation not found: " + animationName, "animationName"); -// return setAnimation(trackIndex, animation, loop); -// } -// -// /// Sets the current animation for a track, discarding any queued animations. -// /// @param loop If true, the animation will repeat. -// /// If false, it will not, instead its last frame is applied if played beyond its duration. -// /// In either case TrackEntry.TrackEnd determines when the track is cleared. -// /// @return -// /// A track entry to allow further customization of animation playback. References to the track entry must not be kept -// /// after AnimationState.Dispose. -// public TrackEntry setAnimation(int trackIndex, Animation animation, bool loop) { -// if (animation == NULL) throw new ArgumentNULLException("animation", "animation cannot be NULL."); -// bool interrupt = true; -// TrackEntry current = expandToIndex(trackIndex); -// if (current != NULL) { -// if (current.nextTrackLast == -1) { -// // Don't mix from an entry that was never applied. -// tracks.Items[trackIndex] = current.mixingFrom; -// queue.interrupt(current); -// queue.end(current); -// disposeNext(current); -// current = current.mixingFrom; -// interrupt = false; -// } else { -// disposeNext(current); -// } -// } -// TrackEntry entry = newTrackEntry(trackIndex, animation, loop, current); -// setCurrent(trackIndex, entry, interrupt); -// queue.drain(); -// return entry; -// } -// -// /// Queues an animation by name. -// /// addAnimation(int, Animation, bool, float) -// public TrackEntry addAnimation(int trackIndex, string animationName, bool loop, float delay) { -// Animation animation = data.skeletonData.FindAnimation(animationName); -// if (animation == NULL) throw new ArgumentException("Animation not found: " + animationName, "animationName"); -// return addAnimation(trackIndex, animation, loop, delay); -// } -// -// /// Adds an animation to be played delay seconds after the current or last queued animation -// /// for a track. If the track is empty, it is equivalent to calling setAnimation. -// /// @param delay -// /// Seconds to begin this animation after the start of the previous animation. May be <= 0 to use the animation -// /// duration of the previous track minus any mix duration plus the negative delay. -// /// -// /// @return A track entry to allow further customization of animation playback. References to the track entry must not be kept -// /// after AnimationState.Dispose -// public TrackEntry addAnimation(int trackIndex, Animation animation, bool loop, float delay) { -// if (animation == NULL) throw new ArgumentNULLException("animation", "animation cannot be NULL."); -// -// TrackEntry last = expandToIndex(trackIndex); -// if (last != NULL) { -// while (last.next != NULL) -// last = last.next; -// } -// -// TrackEntry entry = newTrackEntry(trackIndex, animation, loop, last); -// -// if (last == NULL) { -// setCurrent(trackIndex, entry, true); -// queue.drain(); -// } else { -// last.next = entry; -// if (delay <= 0) { -// float duration = last.animationEnd - last.animationStart; -// if (duration != 0) -// delay += duration * (1 + (int)(last.trackTime / duration)) - data.GetMix(last.animation, animation); -// else -// delay = 0; -// } -// } -// -// entry.delay = delay; -// return entry; -// } -// -// /// -// /// Sets an empty animation for a track, discarding any queued animations, and mixes to it over the specified mix duration. -// public TrackEntry setEmptyAnimation(int trackIndex, float mixDuration) { -// TrackEntry entry = setAnimation(trackIndex, AnimationState.EmptyAnimation, false); -// entry.mixDuration = mixDuration; -// entry.trackEnd = mixDuration; -// return entry; -// } -// -// /// -// /// Adds an empty animation to be played after the current or last queued animation for a track, and mixes to it over the -// /// specified mix duration. -// /// @return -// /// A track entry to allow further customization of animation playback. References to the track entry must not be kept after AnimationState.Dispose. -// /// -// /// @param trackIndex Track number. -// /// @param mixDuration Mix duration. -// /// @param delay Seconds to begin this animation after the start of the previous animation. May be <= 0 to use the animation -// /// duration of the previous track minus any mix duration plus the negative delay. -// public TrackEntry addEmptyAnimation(int trackIndex, float mixDuration, float delay) { -// if (delay <= 0) delay -= mixDuration; -// TrackEntry entry = addAnimation(trackIndex, AnimationState.EmptyAnimation, false, delay); -// entry.mixDuration = mixDuration; -// entry.trackEnd = mixDuration; -// return entry; -// } -// -// /// -// /// Sets an empty animation for every track, discarding any queued animations, and mixes to it over the specified mix duration. -// public void setEmptyAnimations(float mixDuration) { -// bool olddrainDisabled = queue.drainDisabled; -// queue.drainDisabled = true; -// for (int i = 0, n = tracks.Count; i < n; i++) { -// TrackEntry current = tracks.Items[i]; -// if (current != NULL) setEmptyAnimation(i, mixDuration); -// } -// queue.drainDisabled = olddrainDisabled; -// queue.drain(); -// } -// -// private TrackEntry expandToIndex(int index) { + } + + TrackEntry* expandToIndex(int index) + { // if (index < tracks.Count) return tracks.Items[index]; // while (index >= tracks.Count) +// { // tracks.Add(NULL); -// return NULL; -// } -// -// /// Object-pooling version of new TrackEntry. Obtain an unused TrackEntry from the pool and clear/initialize its values. -// /// @param last May be NULL. -// private TrackEntry newTrackEntry(int trackIndex, Animation animation, bool loop, TrackEntry last) { +// } + return NULL; + } + + /// Object-pooling version of new TrackEntry. Obtain an unused TrackEntry from the pool and clear/initialize its values. + /// @param last May be NULL. + TrackEntry* newTrackEntry(int trackIndex, Animation* animation, bool loop, TrackEntry* last) + { // TrackEntry entry = trackEntryPool.Obtain(); // Pooling // entry.trackIndex = trackIndex; // entry.animation = animation; @@ -859,19 +884,23 @@ namespace Spine // entry.mixTime = 0; // entry.mixDuration = (last == NULL) ? 0 : data.GetMix(last.animation, animation); // return entry; -// } -// -// /// Dispose all track entries queued after the given TrackEntry. -// private void disposeNext(TrackEntry entry) { + return NULL; + } + + /// Dispose all track entries queued after the given TrackEntry. + void disposeNext(TrackEntry* entry) + { // TrackEntry next = entry.next; -// while (next != NULL) { +// while (next != NULL) +// { // queue.dispose(next); // next = next.next; // } // entry.next = NULL; -// } -// -// private void animationsChanged() { + } + + void animationsChanged() + { // animationsChanged = false; // // var propertyIDs = _propertyIDs; @@ -879,23 +908,15 @@ namespace Spine // var mixingTo = _mixingTo; // // var tracksItems = tracks.Items; -// for (int i = 0, n = tracks.Count; i < n; i++) { +// for (int i = 0, n = tracks.Count; i < n; i++) +// { // var entry = tracksItems[i]; -// if (entry != NULL) entry.setTimelineData(NULL, mixingTo, propertyIDs); +// if (entry != NULL) +// { +// entry.setTimelineData(NULL, mixingTo, propertyIDs); +// } // } -// } -// -// /// @return The track entry for the animation currently playing on the track, or NULL if no animation is currently playing. -// public TrackEntry getCurrent(int trackIndex) { -// return (trackIndex >= tracks.Count) ? NULL : tracks.Items[trackIndex]; -// } -// -// internal void onStart(TrackEntry entry) { if (Start != NULL) Start(entry); } -// internal void onInterrupt(TrackEntry entry) { if (Interrupt != NULL) Interrupt(entry); } -// internal void onEnd(TrackEntry entry) { if (End != NULL) End(entry); } -// internal void onDispose(TrackEntry entry) { if (Dispose != NULL) Dispose(entry); } -// internal void onComplete(TrackEntry entry) { if (Complete != NULL) Complete(entry); } -// internal void onEvent(TrackEntry entry, Event e) { if (Event != NULL) Event(entry, e); } + } }; } diff --git a/spine-cpp/spine-cpp/include/spine/Extension.h b/spine-cpp/spine-cpp/include/spine/Extension.h index d5633d8bc..9c024c968 100644 --- a/spine-cpp/spine-cpp/include/spine/Extension.h +++ b/spine-cpp/spine-cpp/include/spine/Extension.h @@ -33,6 +33,7 @@ /* All allocation uses these. */ #define MALLOC(TYPE,COUNT) ((TYPE*)spineAlloc(sizeof(TYPE) * (COUNT), __FILE__, __LINE__)) +#define NEW(TYPE) ((TYPE*)spineAlloc(sizeof(TYPE), __FILE__, __LINE__)) #define REALLOC(PTR,TYPE,COUNT) ((TYPE*)spineRealloc(PTR, sizeof(TYPE) * (COUNT), __FILE__, __LINE__)) /* Frees memory. Can be used on const types. */ diff --git a/spine-cpp/spine-cpp/include/spine/HashMap.h b/spine-cpp/spine-cpp/include/spine/HashMap.h index b6882b04c..aab044374 100755 --- a/spine-cpp/spine-cpp/include/spine/HashMap.h +++ b/spine-cpp/spine-cpp/include/spine/HashMap.h @@ -149,7 +149,7 @@ namespace Spine size_t index = hash(key); - Entry* entry = MALLOC(Entry, 1); + Entry* entry = NEW(Entry); new (entry) Entry(); entry->_key = key; entry->_value = value; diff --git a/spine-cpp/spine-cpp/include/spine/Pool.h b/spine-cpp/spine-cpp/include/spine/Pool.h index 3ea37cff3..6114dd748 100644 --- a/spine-cpp/spine-cpp/include/spine/Pool.h +++ b/spine-cpp/spine-cpp/include/spine/Pool.h @@ -62,7 +62,7 @@ namespace Spine } else { - T* ret = MALLOC(T, 1); + T* ret = NEW(T); new (ret) T(); return ret; diff --git a/spine-cpp/spine-cpp/src/spine/AnimationState.cpp b/spine-cpp/spine-cpp/src/spine/AnimationState.cpp index 16954ade4..0caa37c60 100644 --- a/spine-cpp/spine-cpp/src/spine/AnimationState.cpp +++ b/spine-cpp/spine-cpp/src/spine/AnimationState.cpp @@ -32,10 +32,14 @@ #include #include +#include +#include +#include #include #include +#include namespace Spine { @@ -163,27 +167,32 @@ namespace Spine { _timelineData[i] = AnimationState::Subsequent; } - else if (to == NULL || !to->hasTimeline(id)) - { - _timelineData[i] = AnimationState::First; - } else { - for (int ii = mixingToLast; ii >= 0; --ii) + propertyIDs.push_back(id); + + if (to == NULL || !to->hasTimeline(id)) { - TrackEntry* entry = mixingToArray[ii]; - if (!entry->hasTimeline(id)) - { - if (entry->_mixDuration > 0) - { - _timelineData[i] = AnimationState::DipMix; - _timelineDipMix[i] = entry; - goto continue_outer; // continue outer; - } - break; - } + _timelineData[i] = AnimationState::First; + } + else + { + for (int ii = mixingToLast; ii >= 0; --ii) + { + TrackEntry* entry = mixingToArray[ii]; + if (!entry->hasTimeline(id)) + { + if (entry->_mixDuration > 0) + { + _timelineData[i] = AnimationState::DipMix; + _timelineDipMix[i] = entry; + goto continue_outer; // continue outer; + } + break; + } + } + _timelineData[i] = AnimationState::Dip; } - _timelineData[i] = AnimationState::Dip; } continue_outer: {} } @@ -217,41 +226,70 @@ namespace Spine _onAnimationEventFunc = NULL; } - EventQueue::EventQueue(AnimationState& state, Pool& trackEntryPool) : _state(state), _trackEntryPool(trackEntryPool) + EventQueueEntry::EventQueueEntry(EventType eventType, TrackEntry* trackEntry, Event* event) : + _type(eventType), + _entry(trackEntry), + _event(event) { // Empty } + EventQueue* EventQueue::newEventQueue(AnimationState& state, Pool& trackEntryPool) + { + EventQueue* ret = NEW(EventQueue); + new (ret) EventQueue(state, trackEntryPool); + + return ret; + } + + EventQueueEntry* EventQueue::newEventQueueEntry(EventType eventType, TrackEntry* entry, Event* event) + { + EventQueueEntry* ret = NEW(EventQueueEntry); + new (ret) EventQueueEntry(eventType, entry, event); + + return ret; + } + + EventQueue::EventQueue(AnimationState& state, Pool& trackEntryPool) : _state(state), _trackEntryPool(trackEntryPool), _drainDisabled(false) + { + // Empty + } + + EventQueue::~EventQueue() + { + ContainerUtil::cleanUpVectorOfPointers(_eventQueueEntries); + } + void EventQueue::start(TrackEntry* entry) { - _eventQueueEntries.push_back(new EventQueueEntry(EventType_Start, entry)); + _eventQueueEntries.push_back(newEventQueueEntry(EventType_Start, entry)); _state._animationsChanged = true; } void EventQueue::interrupt(TrackEntry* entry) { - _eventQueueEntries.push_back(new EventQueueEntry(EventType_Interrupt, entry)); + _eventQueueEntries.push_back(newEventQueueEntry(EventType_Interrupt, entry)); } void EventQueue::end(TrackEntry* entry) { - _eventQueueEntries.push_back(new EventQueueEntry(EventType_End, entry)); + _eventQueueEntries.push_back(newEventQueueEntry(EventType_End, entry)); _state._animationsChanged = true; } void EventQueue::dispose(TrackEntry* entry) { - _eventQueueEntries.push_back(new EventQueueEntry(EventType_Dispose, entry)); + _eventQueueEntries.push_back(newEventQueueEntry(EventType_Dispose, entry)); } void EventQueue::complete(TrackEntry* entry) { - _eventQueueEntries.push_back(new EventQueueEntry(EventType_Complete, entry)); + _eventQueueEntries.push_back(newEventQueueEntry(EventType_Complete, entry)); } - void EventQueue::event(TrackEntry* entry, Event* e) + void EventQueue::event(TrackEntry* entry, Event* event) { - _eventQueueEntries.push_back(new EventQueueEntry(EventType_Event, entry, e)); + _eventQueueEntries.push_back(newEventQueueEntry(EventType_Event, entry, event)); } /// Raises all events in the queue and drains the queue. @@ -266,7 +304,7 @@ namespace Spine AnimationState& state = _state; - // Don't cache entries.size() so callbacks can queue their own events (eg, call setAnimation in AnimationState_Complete). + // Don't cache _eventQueueEntries.size() so callbacks can queue their own events (eg, call setAnimation in AnimationState_Complete). for (int i = 0; i < _eventQueueEntries.size(); ++i) { EventQueueEntry* queueEntry = _eventQueueEntries[i]; @@ -300,23 +338,34 @@ namespace Spine _drainDisabled = false; } - void EventQueue::clear() - { - _eventQueueEntries.clear(); - } - const int AnimationState::Subsequent = 0; const int AnimationState::First = 1; const int AnimationState::Dip = 2; const int AnimationState::DipMix = 3; - AnimationState::AnimationState() : _onAnimationEventFunc(dummyOnAnimationEventFunc) + AnimationState::AnimationState(AnimationStateData& data) : + _data(data), + _queue(EventQueue::newEventQueue(*this, _trackEntryPool)), + _onAnimationEventFunc(dummyOnAnimationEventFunc), + _timeScale(1) { // Empty } + AnimationState::~AnimationState() + { + DESTROY(EventQueue, _queue); + } + void AnimationState::setOnAnimationEventFunc(OnAnimationEventFunc inValue) { _onAnimationEventFunc = inValue; } + + Animation& AnimationState::getEmptyAnimation() + { + static Vector timelines; + static Animation ret(std::string(""), timelines, 0); + return ret; + } } diff --git a/spine-cpp/spine-cpp/src/spine/Atlas.cpp b/spine-cpp/spine-cpp/src/spine/Atlas.cpp index 7b317c2d6..bd720f118 100644 --- a/spine-cpp/spine-cpp/src/spine/Atlas.cpp +++ b/spine-cpp/spine-cpp/src/spine/Atlas.cpp @@ -138,7 +138,7 @@ namespace Spine } strcpy(path + dirLength + needsSlash, name); - AtlasPage* page = MALLOC(AtlasPage, 1); + AtlasPage* page = NEW(AtlasPage); new (page) AtlasPage(std::string(name)); FREE(name); @@ -188,7 +188,7 @@ namespace Spine } else { - AtlasRegion* region = MALLOC(AtlasRegion, 1); + AtlasRegion* region = NEW(AtlasRegion); new (region) AtlasRegion(); region->page = page; diff --git a/spine-cpp/spine-cpp/src/spine/AtlasAttachmentLoader.cpp b/spine-cpp/spine-cpp/src/spine/AtlasAttachmentLoader.cpp index 0d03bc337..3cbc3c5c8 100644 --- a/spine-cpp/spine-cpp/src/spine/AtlasAttachmentLoader.cpp +++ b/spine-cpp/spine-cpp/src/spine/AtlasAttachmentLoader.cpp @@ -56,7 +56,7 @@ namespace Spine AtlasRegion& region = *regionP; - RegionAttachment* attachmentP = MALLOC(RegionAttachment, 1); + RegionAttachment* attachmentP = NEW(RegionAttachment); new (attachmentP) RegionAttachment(name); RegionAttachment& attachment = *attachmentP; @@ -79,7 +79,7 @@ namespace Spine AtlasRegion& region = *regionP; - MeshAttachment* attachmentP = MALLOC(MeshAttachment, 1); + MeshAttachment* attachmentP = NEW(MeshAttachment); new (attachmentP) MeshAttachment(name); MeshAttachment& attachment = *attachmentP; @@ -101,7 +101,7 @@ namespace Spine BoundingBoxAttachment* AtlasAttachmentLoader::newBoundingBoxAttachment(Skin& skin, std::string name) { - BoundingBoxAttachment* attachmentP = MALLOC(BoundingBoxAttachment, 1); + BoundingBoxAttachment* attachmentP = NEW(BoundingBoxAttachment); new (attachmentP) BoundingBoxAttachment(name); return attachmentP; @@ -109,7 +109,7 @@ namespace Spine PathAttachment* AtlasAttachmentLoader::newPathAttachment(Skin& skin, std::string name) { - PathAttachment* attachmentP = MALLOC(PathAttachment, 1); + PathAttachment* attachmentP = NEW(PathAttachment); new (attachmentP) PathAttachment(name); return attachmentP; @@ -117,7 +117,7 @@ namespace Spine PointAttachment* AtlasAttachmentLoader::newPointAttachment(Skin& skin, std::string name) { - PointAttachment* attachmentP = MALLOC(PointAttachment, 1); + PointAttachment* attachmentP = NEW(PointAttachment); new (attachmentP) PointAttachment(name); return attachmentP; @@ -125,7 +125,7 @@ namespace Spine ClippingAttachment* AtlasAttachmentLoader::newClippingAttachment(Skin& skin, std::string name) { - ClippingAttachment* attachmentP = MALLOC(ClippingAttachment, 1); + ClippingAttachment* attachmentP = NEW(ClippingAttachment); new (attachmentP) ClippingAttachment(name); return attachmentP; diff --git a/spine-cpp/spine-cpp/src/spine/Skeleton.cpp b/spine-cpp/spine-cpp/src/spine/Skeleton.cpp index 0221175f8..955d8242c 100644 --- a/spine-cpp/spine-cpp/src/spine/Skeleton.cpp +++ b/spine-cpp/spine-cpp/src/spine/Skeleton.cpp @@ -75,13 +75,13 @@ namespace Spine Bone* bone; if (data->getParent() == NULL) { - bone = MALLOC(Bone, 1); + bone = NEW(Bone); new (bone) Bone(*data, *this, NULL); } else { Bone* parent = _bones[data->getParent()->getIndex()]; - bone = MALLOC(Bone, 1); + bone = NEW(Bone); new (bone) Bone(*data, *this, parent); parent->getChildren().push_back(bone); } @@ -96,7 +96,7 @@ namespace Spine SlotData* data = (*i); Bone* bone = _bones[data->getBoneData().getIndex()]; - Slot* slot = MALLOC(Slot, 1); + Slot* slot = NEW(Slot); new (slot) Slot(*data, *bone); _slots.push_back(slot); @@ -108,7 +108,7 @@ namespace Spine { IkConstraintData* data = (*i); - IkConstraint* constraint = MALLOC(IkConstraint, 1); + IkConstraint* constraint = NEW(IkConstraint); new (constraint) IkConstraint(*data, *this); _ikConstraints.push_back(constraint); @@ -119,7 +119,7 @@ namespace Spine { TransformConstraintData* data = (*i); - TransformConstraint* constraint = MALLOC(TransformConstraint, 1); + TransformConstraint* constraint = NEW(TransformConstraint); new (constraint) TransformConstraint(*data, *this); _transformConstraints.push_back(constraint); @@ -130,7 +130,7 @@ namespace Spine { PathConstraintData* data = (*i); - PathConstraint* constraint = MALLOC(PathConstraint, 1); + PathConstraint* constraint = NEW(PathConstraint); new (constraint) PathConstraint(*data, *this); _pathConstraints.push_back(constraint); diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonBounds.cpp b/spine-cpp/spine-cpp/src/spine/SkeletonBounds.cpp index 217c75deb..a5a6e3c8a 100644 --- a/spine-cpp/spine-cpp/src/spine/SkeletonBounds.cpp +++ b/spine-cpp/spine-cpp/src/spine/SkeletonBounds.cpp @@ -76,7 +76,7 @@ namespace Spine } else { - Polygon* polygonP = MALLOC(Polygon, 1); + Polygon* polygonP = NEW(Polygon); new (polygonP) Polygon(); } From af43d7cff18b5ddc74f032cea10aee4151dc00d4 Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Thu, 30 Nov 2017 20:32:58 -0500 Subject: [PATCH 56/83] Defining SpineExtension class that can be overridden to provide memory allocation and file reading --- spine-cpp/spine-cpp/include/spine/Extension.h | 65 ++++++++++++++----- spine-cpp/spine-cpp/src/spine/Atlas.cpp | 2 +- spine-cpp/spine-cpp/src/spine/Extension.cpp | 58 ++++++++++++++--- 3 files changed, 99 insertions(+), 26 deletions(-) diff --git a/spine-cpp/spine-cpp/include/spine/Extension.h b/spine-cpp/spine-cpp/include/spine/Extension.h index 9c024c968..e58f44991 100644 --- a/spine-cpp/spine-cpp/include/spine/Extension.h +++ b/spine-cpp/spine-cpp/include/spine/Extension.h @@ -31,30 +31,65 @@ #ifndef Spine_Extension_h #define Spine_Extension_h +#include + +#define SPINE_EXTENSION (SpineExtension::getInstance()) + /* All allocation uses these. */ -#define MALLOC(TYPE,COUNT) ((TYPE*)spineAlloc(sizeof(TYPE) * (COUNT), __FILE__, __LINE__)) -#define NEW(TYPE) ((TYPE*)spineAlloc(sizeof(TYPE), __FILE__, __LINE__)) -#define REALLOC(PTR,TYPE,COUNT) ((TYPE*)spineRealloc(PTR, sizeof(TYPE) * (COUNT), __FILE__, __LINE__)) +#define MALLOC(TYPE,COUNT) ((TYPE*)SPINE_EXTENSION->spineAlloc(sizeof(TYPE) * (COUNT), __FILE__, __LINE__)) +#define NEW(TYPE) ((TYPE*)SPINE_EXTENSION->spineAlloc(sizeof(TYPE), __FILE__, __LINE__)) +#define REALLOC(PTR,TYPE,COUNT) ((TYPE*)SPINE_EXTENSION->spineRealloc(PTR, sizeof(TYPE) * (COUNT), __FILE__, __LINE__)) /* Frees memory. Can be used on const types. */ -#define FREE(VALUE) spineFree((void*)VALUE) +#define FREE(VALUE) SPINE_EXTENSION->spineFree((void*)VALUE) /* Call destructor and then frees memory. Can be used on const types. */ -#define DESTROY(TYPE,VALUE) VALUE->~TYPE(); spineFree((void*)VALUE) - -#include +#define DESTROY(TYPE,VALUE) VALUE->~TYPE(); SPINE_EXTENSION->spineFree((void*)VALUE) namespace Spine { - /// Implement this function to use your own memory allocator. - void* spineAlloc(size_t size, const char* file, int line); + class SpineExtension + { + public: + static void setInstance(SpineExtension* inSpineExtension); + + static SpineExtension* getInstance(); + + virtual ~SpineExtension(); + + /// Implement this function to use your own memory allocator + virtual void* spineAlloc(size_t size, const char* file, int line) = 0; + + virtual void* spineRealloc(void* ptr, size_t size, const char* file, int line) = 0; + + /// If you provide a spineAllocFunc, you should also provide a spineFreeFunc + virtual void spineFree(void* mem) = 0; + + virtual char* spineReadFile(const char* path, int* length); + + protected: + SpineExtension(); + + private: + static SpineExtension* _spineExtension; + }; - void* spineRealloc(void* ptr, size_t size, const char* file, int line); - - /// If you implement spineAlloc, you should also implement this function. - void spineFree(void* mem); - - char* spineReadFile(const char* path, int* length); + class DefaultSpineExtension : public SpineExtension + { + public: + static DefaultSpineExtension* getInstance(); + + virtual ~DefaultSpineExtension(); + + virtual void* spineAlloc(size_t size, const char* file, int line); + + virtual void* spineRealloc(void* ptr, size_t size, const char* file, int line); + + virtual void spineFree(void* mem); + + protected: + DefaultSpineExtension(); + }; } #endif /* Spine_Extension_h */ diff --git a/spine-cpp/spine-cpp/src/spine/Atlas.cpp b/spine-cpp/spine-cpp/src/spine/Atlas.cpp index bd720f118..369f57a64 100644 --- a/spine-cpp/spine-cpp/src/spine/Atlas.cpp +++ b/spine-cpp/spine-cpp/src/spine/Atlas.cpp @@ -53,7 +53,7 @@ namespace Spine memcpy(dir, path, dirLength); dir[dirLength] = '\0'; - data = spineReadFile(path, &length); + data = SPINE_EXTENSION->spineReadFile(path, &length); if (data) { load(data, length, dir); diff --git a/spine-cpp/spine-cpp/src/spine/Extension.cpp b/spine-cpp/spine-cpp/src/spine/Extension.cpp index dd52dc6fe..757d44cbe 100644 --- a/spine-cpp/spine-cpp/src/spine/Extension.cpp +++ b/spine-cpp/spine-cpp/src/spine/Extension.cpp @@ -30,31 +30,33 @@ #include -//#include #include +#include namespace Spine { - void* spineAlloc(size_t size, const char* file, int line) + SpineExtension* SpineExtension::_spineExtension = NULL; + + void SpineExtension::setInstance(SpineExtension* inValue) { - //printf("spineAlloc size: %lu, file: %s, line: %d \n", size, file, line); + assert(!_spineExtension); - return malloc(size); + _spineExtension = inValue; } - void* spineRealloc(void* ptr, size_t size, const char* file, int line) + SpineExtension* SpineExtension::getInstance() { - //printf("spineRealloc size: %lu, file: %s, line: %d \n", size, file, line); + assert(_spineExtension); - return realloc(ptr, size); + return _spineExtension; } - void spineFree(void* mem) + SpineExtension::~SpineExtension() { - free(mem); + // Empty } - char* spineReadFile(const char* path, int* length) + char* SpineExtension::spineReadFile(const char* path, int* length) { char *data; FILE *file = fopen(path, "rb"); @@ -70,4 +72,40 @@ namespace Spine return data; } + + SpineExtension::SpineExtension() + { + // Empty + } + + DefaultSpineExtension* DefaultSpineExtension::getInstance() + { + static DefaultSpineExtension ret; + return &ret; + } + + DefaultSpineExtension::~DefaultSpineExtension() + { + // Empty + } + + void* DefaultSpineExtension::spineAlloc(size_t size, const char* file, int line) + { + return malloc(size); + } + + void* DefaultSpineExtension::spineRealloc(void* ptr, size_t size, const char* file, int line) + { + return realloc(ptr, size); + } + + void DefaultSpineExtension::spineFree(void* mem) + { + free(mem); + } + + DefaultSpineExtension::DefaultSpineExtension() : SpineExtension() + { + // Empty + } } From 3fc2f08ff64fc21a80bfe2beb24a75f624dc1b20 Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Sat, 2 Dec 2017 14:46:48 -0500 Subject: [PATCH 57/83] Okay, AnimationState is done, on to SkeletonJson and SkeletonBinary --- spine-cpp/spine-cpp/include/spine/Animation.h | 2 +- .../spine-cpp/include/spine/AnimationState.h | 561 +------------ .../include/spine/AnimationStateData.h | 2 + .../include/spine/AttachmentTimeline.h | 2 +- spine-cpp/spine-cpp/include/spine/Bone.h | 2 + spine-cpp/spine-cpp/include/spine/BoneData.h | 2 + .../spine-cpp/include/spine/ColorTimeline.h | 2 +- .../spine-cpp/include/spine/CurveTimeline.h | 2 +- .../spine-cpp/include/spine/DeformTimeline.h | 2 +- .../include/spine/DrawOrderTimeline.h | 2 +- spine-cpp/spine-cpp/include/spine/Event.h | 2 + .../spine-cpp/include/spine/EventTimeline.h | 2 +- .../include/spine/IkConstraintTimeline.h | 2 +- spine-cpp/spine-cpp/include/spine/MathUtil.h | 6 + .../include/spine/PathConstraintMixTimeline.h | 2 +- .../spine/PathConstraintPositionTimeline.h | 2 +- .../spine/PathConstraintSpacingTimeline.h | 2 +- .../spine-cpp/include/spine/RotateTimeline.h | 4 +- .../spine-cpp/include/spine/ScaleTimeline.h | 2 +- .../spine-cpp/include/spine/ShearTimeline.h | 2 +- spine-cpp/spine-cpp/include/spine/Skeleton.h | 1 + spine-cpp/spine-cpp/include/spine/Timeline.h | 2 +- .../spine/TransformConstraintTimeline.h | 2 +- .../include/spine/TranslateTimeline.h | 2 +- .../include/spine/TwoColorTimeline.h | 2 +- spine-cpp/spine-cpp/src/spine/Animation.cpp | 4 +- .../spine-cpp/src/spine/AnimationState.cpp | 743 +++++++++++++++++- .../src/spine/AttachmentTimeline.cpp | 2 +- .../spine-cpp/src/spine/ColorTimeline.cpp | 2 +- .../spine-cpp/src/spine/DeformTimeline.cpp | 2 +- .../spine-cpp/src/spine/DrawOrderTimeline.cpp | 2 +- .../spine-cpp/src/spine/EventTimeline.cpp | 11 +- .../src/spine/IkConstraintTimeline.cpp | 2 +- .../src/spine/PathConstraintMixTimeline.cpp | 2 +- .../spine/PathConstraintPositionTimeline.cpp | 2 +- .../spine/PathConstraintSpacingTimeline.cpp | 2 +- .../spine-cpp/src/spine/RotateTimeline.cpp | 2 +- .../spine-cpp/src/spine/ScaleTimeline.cpp | 2 +- .../spine-cpp/src/spine/ShearTimeline.cpp | 2 +- .../src/spine/TransformConstraintTimeline.cpp | 2 +- .../spine-cpp/src/spine/TranslateTimeline.cpp | 2 +- .../spine-cpp/src/spine/TwoColorTimeline.cpp | 2 +- 42 files changed, 832 insertions(+), 568 deletions(-) diff --git a/spine-cpp/spine-cpp/include/spine/Animation.h b/spine-cpp/spine-cpp/include/spine/Animation.h index 061f4d27a..8015c57ea 100644 --- a/spine-cpp/spine-cpp/include/spine/Animation.h +++ b/spine-cpp/spine-cpp/include/spine/Animation.h @@ -70,7 +70,7 @@ namespace Spine /// Applies all the animation's timelines to the specified skeleton. /// See also Timeline::apply(Skeleton&, float, float, Vector, float, MixPose, MixDirection) - void apply(Skeleton& skeleton, float lastTime, float time, bool loop, Vector& events, float alpha, MixPose pose, MixDirection direction); + void apply(Skeleton& skeleton, float lastTime, float time, bool loop, Vector* pEvents, float alpha, MixPose pose, MixDirection direction); std::string getName(); diff --git a/spine-cpp/spine-cpp/include/spine/AnimationState.h b/spine-cpp/spine-cpp/include/spine/AnimationState.h index 16ed3c9ce..2b58862bb 100644 --- a/spine-cpp/spine-cpp/include/spine/AnimationState.h +++ b/spine-cpp/spine-cpp/include/spine/AnimationState.h @@ -297,181 +297,30 @@ namespace Spine ~AnimationState(); - void setOnAnimationEventFunc(OnAnimationEventFunc inValue); - /// /// Increments the track entry times, setting queued animations as current if needed /// @param delta delta time - void update(float delta) - { -// delta *= timeScale; -// var tracksItems = tracks.Items; -// for (int i = 0, n = tracks.Count; i < n; i++) { -// TrackEntry current = tracksItems[i]; -// if (current == NULL) continue; -// -// current.animationLast = current.nextAnimationLast; -// current.trackLast = current.nextTrackLast; -// -// float currentDelta = delta * current.timeScale; -// -// if (current.delay > 0) { -// current.delay -= currentDelta; -// if (current.delay > 0) continue; -// currentDelta = -current.delay; -// current.delay = 0; -// } -// -// TrackEntry next = current.next; -// if (next != NULL) { -// // When the next entry's delay is passed, change to the next entry, preserving leftover time. -// float nextTime = current.trackLast - next.delay; -// if (nextTime >= 0) { -// next.delay = 0; -// next.trackTime = nextTime + (delta * next.timeScale); -// current.trackTime += currentDelta; -// setCurrent(i, next, true); -// while (next.mixingFrom != NULL) { -// next.mixTime += currentDelta; -// next = next.mixingFrom; -// } -// continue; -// } -// } else if (current.trackLast >= current.trackEnd && current.mixingFrom == NULL) { -// // clear the track when there is no next entry, the track end time is reached, and there is no mixingFrom. -// tracksItems[i] = NULL; -// -// queue.end(current); -// disposeNext(current); -// continue; -// } -// if (current.mixingFrom != NULL && updateMixingFrom(current, delta)) { -// // End mixing from entries once all have completed. -// var from = current.mixingFrom; -// current.mixingFrom = NULL; -// while (from != NULL) { -// queue.end(from); -// from = from.mixingFrom; -// } -// } -// -// current.trackTime += currentDelta; -// } -// -// queue.drain(); - } + void update(float delta); /// /// Poses the skeleton using the track entry animations. There are no side effects other than invoking listeners, so the /// animation state can be applied to multiple skeletons to pose them identically. - bool apply(Skeleton& skeleton) - { -// if (animationsChanged) animationsChanged(); -// -// var events = _events; -// - bool applied = false; -// var tracksItems = tracks.Items; -// for (int i = 0, m = tracks.Count; i < m; i++) { -// TrackEntry current = tracksItems[i]; -// if (current == NULL || current.delay > 0) continue; -// applied = true; -// MixPose currentPose = i == 0 ? MixPose.Current : MixPose.CurrentLayered; -// -// // apply mixing from entries first. -// float mix = current.alpha; -// if (current.mixingFrom != NULL) -// mix *= applyMixingFrom(current, skeleton, currentPose); -// else if (current.trackTime >= current.trackEnd && current.next == NULL) // -// mix = 0; // Set to setup pose the last time the entry will be applied. -// -// // apply current entry. -// float animationLast = current.animationLast, animationTime = current.AnimationTime; -// int timelineCount = current.animation.timelines.Count; -// var timelines = current.animation.timelines; -// var timelinesItems = timelines.Items; -// if (mix == 1) { -// for (int ii = 0; ii < timelineCount; ii++) -// timelinesItems[ii].apply(skeleton, animationLast, animationTime, events, 1, MixPose.Setup, MixDirection.In); -// } else { -// var timelineData = current.timelineData.Items; -// -// bool firstFrame = current.timelinesRotation.Count == 0; -// if (firstFrame) current.timelinesRotation.EnsureCapacity(timelines.Count << 1); -// var timelinesRotation = current.timelinesRotation.Items; -// -// for (int ii = 0; ii < timelineCount; ii++) { -// Timeline timeline = timelinesItems[ii]; -// MixPose pose = timelineData[ii] >= AnimationState.First ? MixPose.Setup : currentPose; -// var rotateTimeline = timeline as RotateTimeline; -// if (rotateTimeline != NULL) -// applyRotateTimeline(rotateTimeline, skeleton, animationTime, mix, pose, timelinesRotation, ii << 1, firstFrame); -// else -// timeline.apply(skeleton, animationLast, animationTime, events, mix, pose, MixDirection.In); -// } -// } -// queueEvents(current, animationTime); -// events.clear(false); -// current.nextAnimationLast = animationTime; -// current.nextTrackLast = current.trackTime; -// } -// -// queue.drain(); - return applied; - } + bool apply(Skeleton& skeleton); /// /// Removes all animations from all tracks, leaving skeletons in their previous pose. /// It may be desired to use AnimationState.setEmptyAnimations(float) to mix the skeletons back to the setup pose, /// rather than leaving them in their previous pose. - void clearTracks() - { -// bool olddrainDisabled = queue.drainDisabled; -// queue.drainDisabled = true; -// for (int i = 0, n = tracks.Count; i < n; i++) { -// clearTrack(i); -// } -// tracks.clear(); -// queue.drainDisabled = olddrainDisabled; -// queue.drain(); - } + void clearTracks(); /// /// Removes all animations from the tracks, leaving skeletons in their previous pose. /// It may be desired to use AnimationState.setEmptyAnimations(float) to mix the skeletons back to the setup pose, /// rather than leaving them in their previous pose. - void clearTrack(int trackIndex) - { -// if (trackIndex >= tracks.Count) return; -// TrackEntry current = tracks.Items[trackIndex]; -// if (current == NULL) return; -// -// queue.end(current); -// -// disposeNext(current); -// -// TrackEntry entry = current; -// while (true) { -// TrackEntry from = entry.mixingFrom; -// if (from == NULL) break; -// queue.end(from); -// entry.mixingFrom = NULL; -// entry = from; -// } -// -// tracks.Items[current.trackIndex] = NULL; -// -// queue.drain(); - } + void clearTrack(int trackIndex); /// Sets an animation by name. setAnimation(int, Animation, bool) - TrackEntry* setAnimation(int trackIndex, std::string animationName, bool loop) - { -// Animation animation = data.skeletonData.FindAnimation(animationName); -// if (animation == NULL) throw new ArgumentException("Animation not found: " + animationName, "animationName"); -// return setAnimation(trackIndex, animation, loop); - return NULL; - } + TrackEntry* setAnimation(int trackIndex, std::string animationName, bool loop); /// Sets the current animation for a track, discarding any queued animations. /// @param loop If true, the animation will repeat. @@ -480,39 +329,11 @@ namespace Spine /// @return /// A track entry to allow further customization of animation playback. References to the track entry must not be kept /// after AnimationState.Dispose. - TrackEntry* setAnimation(int trackIndex, Animation& animation, bool loop) - { -// bool interrupt = true; -// TrackEntry current = expandToIndex(trackIndex); -// if (current != NULL) { -// if (current.nextTrackLast == -1) { -// // Don't mix from an entry that was never applied. -// tracks.Items[trackIndex] = current.mixingFrom; -// queue.interrupt(current); -// queue.end(current); -// disposeNext(current); -// current = current.mixingFrom; -// interrupt = false; -// } else { -// disposeNext(current); -// } -// } -// TrackEntry entry = newTrackEntry(trackIndex, animation, loop, current); -// setCurrent(trackIndex, entry, interrupt); -// queue.drain(); -// return entry; - return NULL; - } + TrackEntry* setAnimation(int trackIndex, Animation* animation, bool loop); /// Queues an animation by name. /// addAnimation(int, Animation, bool, float) - TrackEntry* addAnimation(int trackIndex, std::string animationName, bool loop, float delay) - { -// Animation animation = data.skeletonData.FindAnimation(animationName); -// if (animation == NULL) throw new ArgumentException("Animation not found: " + animationName, "animationName"); -// return addAnimation(trackIndex, animation, loop, delay); - return NULL; - } + TrackEntry* addAnimation(int trackIndex, std::string animationName, bool loop, float delay); /// Adds an animation to be played delay seconds after the current or last queued animation /// for a track. If the track is empty, it is equivalent to calling setAnimation. @@ -522,44 +343,11 @@ namespace Spine /// /// @return A track entry to allow further customization of animation playback. References to the track entry must not be kept /// after AnimationState.Dispose - TrackEntry* addAnimation(int trackIndex, Animation& animation, bool loop, float delay) - { -// TrackEntry last = expandToIndex(trackIndex); -// if (last != NULL) { -// while (last.next != NULL) -// last = last.next; -// } -// -// TrackEntry entry = newTrackEntry(trackIndex, animation, loop, last); -// -// if (last == NULL) { -// setCurrent(trackIndex, entry, true); -// queue.drain(); -// } else { -// last.next = entry; -// if (delay <= 0) { -// float duration = last.animationEnd - last.animationStart; -// if (duration != 0) -// delay += duration * (1 + (int)(last.trackTime / duration)) - data.GetMix(last.animation, animation); -// else -// delay = 0; -// } -// } -// -// entry.delay = delay; -// return entry; - return NULL; - } + TrackEntry* addAnimation(int trackIndex, Animation* animation, bool loop, float delay); /// /// Sets an empty animation for a track, discarding any queued animations, and mixes to it over the specified mix duration. - TrackEntry* setEmptyAnimation(int trackIndex, float mixDuration) - { - TrackEntry* entry = setAnimation(trackIndex, AnimationState::getEmptyAnimation(), false); - entry->_mixDuration = mixDuration; - entry->_trackEnd = mixDuration; - return entry; - } + TrackEntry* setEmptyAnimation(int trackIndex, float mixDuration); /// /// Adds an empty animation to be played after the current or last queued animation for a track, and mixes to it over the @@ -571,44 +359,22 @@ namespace Spine /// @param mixDuration Mix duration. /// @param delay Seconds to begin this animation after the start of the previous animation. May be <= 0 to use the animation /// duration of the previous track minus any mix duration plus the negative delay. - TrackEntry* addEmptyAnimation(int trackIndex, float mixDuration, float delay) - { - if (delay <= 0) - { - delay -= mixDuration; - } - - TrackEntry* entry = addAnimation(trackIndex, AnimationState::getEmptyAnimation(), false, delay); - entry->_mixDuration = mixDuration; - entry->_trackEnd = mixDuration; - return entry; - } + TrackEntry* addEmptyAnimation(int trackIndex, float mixDuration, float delay); /// /// Sets an empty animation for every track, discarding any queued animations, and mixes to it over the specified mix duration. - void setEmptyAnimations(float mixDuration) - { -// bool olddrainDisabled = queue.drainDisabled; -// queue.drainDisabled = true; -// for (int i = 0, n = tracks.Count; i < n; i++) -// { -// TrackEntry current = tracks.Items[i]; -// if (current != NULL) setEmptyAnimation(i, mixDuration); -// } -// queue.drainDisabled = olddrainDisabled; -// queue.drain(); - } + void setEmptyAnimations(float mixDuration); /// @return The track entry for the animation currently playing on the track, or NULL if no animation is currently playing. - TrackEntry* getCurrent(int trackIndex) - { - return trackIndex >= _tracks.size() ? NULL : _tracks[trackIndex]; - } + TrackEntry* getCurrent(int trackIndex); -// AnimationStateData Data { get { return data; } } -// /// A list of tracks that have animations, which may contain NULLs. -// Vector Tracks { get { return tracks; } } -// float TimeScale { get { return timeScale; } set { timeScale = value; } } + AnimationStateData& getData(); + + /// A list of tracks that have animations, which may contain NULLs. + Vector getTracks(); + float getTimeScale(); + void setTimeScale(float inValue); + void setOnAnimationEventFunc(OnAnimationEventFunc inValue); private: static const int Subsequent, First, Dip, DipMix; @@ -617,306 +383,41 @@ namespace Spine Pool _trackEntryPool; Vector _tracks; - Vector _events; + Vector _events; EventQueue* _queue; Vector _propertyIDs; - Vector _mixingTo; + Vector _mixingTo; bool _animationsChanged; OnAnimationEventFunc _onAnimationEventFunc; float _timeScale; - static Animation& getEmptyAnimation(); + static Animation* getEmptyAnimation(); - static void applyRotateTimeline(RotateTimeline* rotateTimeline, Skeleton& skeleton, float time, float alpha, MixPose pose, - Vector& timelinesRotation, int i, bool firstFrame) - { -// if (firstFrame) timelinesRotation[i] = 0; -// -// if (alpha == 1) { -// rotateTimeline.apply(skeleton, 0, time, NULL, 1, pose, MixDirection.In); -// return; -// } -// -// Bone bone = skeleton.bones.Items[rotateTimeline.boneIndex]; -// float[] frames = rotateTimeline.frames; -// if (time < frames[0]) { -// if (pose == MixPose.Setup) bone.rotation = bone.data.rotation; -// return; -// } -// -// float r2; -// if (time >= frames[frames.Length - RotateTimeline.ENTRIES]) // Time is after last frame. -// r2 = bone.data.rotation + frames[frames.Length + RotateTimeline.PREV_ROTATION]; -// else { -// // Interpolate between the previous frame and the current frame. -// int frame = Animation.BinarySearch(frames, time, RotateTimeline.ENTRIES); -// float prevRotation = frames[frame + RotateTimeline.PREV_ROTATION]; -// float frameTime = frames[frame]; -// float percent = rotateTimeline.GetCurvePercent((frame >> 1) - 1, -// 1 - (time - frameTime) / (frames[frame + RotateTimeline.PREV_TIME] - frameTime)); -// -// r2 = frames[frame + RotateTimeline.ROTATION] - prevRotation; -// r2 -= (16384 - (int)(16384.499999999996 - r2 / 360)) * 360; -// r2 = prevRotation + r2 * percent + bone.data.rotation; -// r2 -= (16384 - (int)(16384.499999999996 - r2 / 360)) * 360; -// } -// -// // Mix between rotations using the direction of the shortest route on the first frame while detecting crosses. -// float r1 = pose == MixPose.Setup ? bone.data.rotation : bone.rotation; -// float total, diff = r2 - r1; -// if (diff == 0) { -// total = timelinesRotation[i]; -// } else { -// diff -= (16384 - (int)(16384.499999999996 - diff / 360)) * 360; -// float lastTotal, lastDiff; -// if (firstFrame) { -// lastTotal = 0; -// lastDiff = diff; -// } else { -// lastTotal = timelinesRotation[i]; // Angle and direction of mix, including loops. -// lastDiff = timelinesRotation[i + 1]; // Difference between bones. -// } -// bool current = diff > 0, dir = lastTotal >= 0; -// // Detect cross at 0 (not 180). -// if (Math.Sign(lastDiff) != Math.Sign(diff) && Math.Abs(lastDiff) <= 90) { -// // A cross after a 360 rotation is a loop. -// if (Math.Abs(lastTotal) > 180) lastTotal += 360 * Math.Sign(lastTotal); -// dir = current; -// } -// total = diff + lastTotal - lastTotal % 360; // Store loops as part of lastTotal. -// if (dir != current) total += 360 * Math.Sign(lastTotal); -// timelinesRotation[i] = total; -// } -// timelinesRotation[i + 1] = diff; -// r1 += total * alpha; -// bone.rotation = r1 - (16384 - (int)(16384.499999999996 - r1 / 360)) * 360; - } + static void applyRotateTimeline(RotateTimeline* rotateTimeline, Skeleton& skeleton, float time, float alpha, MixPose pose, Vector& timelinesRotation, int i, bool firstFrame); /// Returns true when all mixing from entries are complete. - bool updateMixingFrom(TrackEntry to, float delta) - { -// TrackEntry from = to.mixingFrom; -// if (from == NULL) return true; -// -// bool finished = updateMixingFrom(from, delta); -// -// // Require mixTime > 0 to ensure the mixing from entry was applied at least once. -// if (to.mixTime > 0 && (to.mixTime >= to.mixDuration || to.timeScale == 0)) { -// // Require totalAlpha == 0 to ensure mixing is complete, unless mixDuration == 0 (the transition is a single frame). -// if (from.totalAlpha == 0 || to.mixDuration == 0) { -// to.mixingFrom = from.mixingFrom; -// to.interruptAlpha = from.interruptAlpha; -// queue.end(from); -// } -// return finished; -// } -// -// from.animationLast = from.nextAnimationLast; -// from.trackLast = from.nextTrackLast; -// from.trackTime += delta * from.timeScale; -// to.mixTime += delta * to.timeScale; - return false; - } + bool updateMixingFrom(TrackEntry* to, float delta); - float applyMixingFrom(TrackEntry* to, Skeleton& skeleton, MixPose currentPose) - { -// TrackEntry from = to.mixingFrom; -// if (from.mixingFrom != NULL) applyMixingFrom(from, skeleton, currentPose); -// -// float mix; -// if (to.mixDuration == 0) { // Single frame mix to undo mixingFrom changes. -// mix = 1; -// currentPose = MixPose.Setup; -// } else { -// mix = to.mixTime / to.mixDuration; -// if (mix > 1) mix = 1; -// } -// -// var eventBuffer = mix < from.eventThreshold ? _events : NULL; -// bool attachments = mix < from.attachmentThreshold, drawOrder = mix < from.drawOrderThreshold; -// float animationLast = from.animationLast, animationTime = from.AnimationTime; -// var timelines = from.animation.timelines; -// int timelineCount = timelines.Count; -// var timelinesItems = timelines.Items; -// var timelineData = from.timelineData.Items; -// var timelineDipMix = from.timelineDipMix.Items; -// -// bool firstFrame = from.timelinesRotation.Count == 0; -// if (firstFrame) from.timelinesRotation.Resize(timelines.Count << 1); // from.timelinesRotation.setSize -// var timelinesRotation = from.timelinesRotation.Items; -// -// MixPose pose; -// float alphaDip = from.alpha * to.interruptAlpha, alphaMix = alphaDip * (1 - mix), alpha; -// from.totalAlpha = 0; -// for (int i = 0; i < timelineCount; i++) { -// Timeline timeline = timelinesItems[i]; -// switch (timelineData[i]) { -// case Subsequent: -// if (!attachments && timeline is AttachmentTimeline) continue; -// if (!drawOrder && timeline is DrawOrderTimeline) continue; -// pose = currentPose; -// alpha = alphaMix; -// break; -// case First: -// pose = MixPose.Setup; -// alpha = alphaMix; -// break; -// case Dip: -// pose = MixPose.Setup; -// alpha = alphaDip; -// break; -// default: -// pose = MixPose.Setup; -// TrackEntry dipMix = timelineDipMix[i]; -// alpha = alphaDip * Math.Max(0, 1 - dipMix.mixTime / dipMix.mixDuration); -// break; -// } -// from.totalAlpha += alpha; -// var rotateTimeline = timeline as RotateTimeline; -// if (rotateTimeline != NULL) { -// applyRotateTimeline(rotateTimeline, skeleton, animationTime, alpha, pose, timelinesRotation, i << 1, firstFrame); -// } else { -// timeline.apply(skeleton, animationLast, animationTime, eventBuffer, alpha, pose, MixDirection.Out); -// } -// } -// -// if (to.mixDuration > 0) queueEvents(from, animationTime); -// _events.clear(false); -// from.nextAnimationLast = animationTime; -// from.nextTrackLast = from.trackTime; -// -// return mix; - return 0; - } + float applyMixingFrom(TrackEntry* to, Skeleton& skeleton, MixPose currentPose); - void queueEvents(TrackEntry* entry, float animationTime) - { -// float animationStart = entry.animationStart, animationEnd = entry.animationEnd; -// float duration = animationEnd - animationStart; -// float trackLastWrapped = entry.trackLast % duration; -// -// // Queue events before complete. -// var events = _events; -// var eventsItems = events.Items; -// int i = 0, n = events.Count; -// for (; i < n; i++) { -// var e = eventsItems[i]; -// if (e.time < trackLastWrapped) break; -// if (e.time > animationEnd) continue; // Discard events outside animation start/end. -// queue.event(entry, e); -// } -// -// // Queue complete if completed a loop iteration or the animation. -// if (entry.loop ? (trackLastWrapped > entry.trackTime % duration) -// : (animationTime >= animationEnd && entry.animationLast < animationEnd)) { -// queue.complete(entry); -// } -// -// // Queue events after complete. -// for (; i < n; i++) { -// Event e = eventsItems[i]; -// if (e.time < animationStart) continue; // Discard events outside animation start/end. -// queue.event(entry, eventsItems[i]); -// } - } + void queueEvents(TrackEntry* entry, float animationTime); /// Sets the active TrackEntry for a given track number. - void setCurrent(int index, TrackEntry* current, bool interrupt) - { -// TrackEntry from = expandToIndex(index); -// tracks.Items[index] = current; -// -// if (from != NULL) { -// if (interrupt) queue.interrupt(from); -// current.mixingFrom = from; -// current.mixTime = 0; -// -// // Store interrupted mix percentage. -// if (from.mixingFrom != NULL && from.mixDuration > 0) -// current.interruptAlpha *= Math.Min(1, from.mixTime / from.mixDuration); -// -// from.timelinesRotation.clear(); // Reset rotation for mixing out, in case entry was mixed in. -// } -// -// queue.start(current); // triggers animationsChanged - } + void setCurrent(int index, TrackEntry* current, bool interrupt); - TrackEntry* expandToIndex(int index) - { -// if (index < tracks.Count) return tracks.Items[index]; -// while (index >= tracks.Count) -// { -// tracks.Add(NULL); -// } - return NULL; - } + TrackEntry* expandToIndex(int index); /// Object-pooling version of new TrackEntry. Obtain an unused TrackEntry from the pool and clear/initialize its values. /// @param last May be NULL. - TrackEntry* newTrackEntry(int trackIndex, Animation* animation, bool loop, TrackEntry* last) - { -// TrackEntry entry = trackEntryPool.Obtain(); // Pooling -// entry.trackIndex = trackIndex; -// entry.animation = animation; -// entry.loop = loop; -// -// entry.eventThreshold = 0; -// entry.attachmentThreshold = 0; -// entry.drawOrderThreshold = 0; -// -// entry.animationStart = 0; -// entry.animationEnd = animation.Duration; -// entry.animationLast = -1; -// entry.nextAnimationLast = -1; -// -// entry.delay = 0; -// entry.trackTime = 0; -// entry.trackLast = -1; -// entry.nextTrackLast = -1; // nextTrackLast == -1 signifies a TrackEntry that wasn't applied yet. -// entry.trackEnd = float.MaxValue; // loop ? float.MaxValue : animation.Duration; -// entry.timeScale = 1; -// -// entry.alpha = 1; -// entry.interruptAlpha = 1; -// entry.mixTime = 0; -// entry.mixDuration = (last == NULL) ? 0 : data.GetMix(last.animation, animation); -// return entry; - return NULL; - } + TrackEntry* newTrackEntry(int trackIndex, Animation* animation, bool loop, TrackEntry* last); /// Dispose all track entries queued after the given TrackEntry. - void disposeNext(TrackEntry* entry) - { -// TrackEntry next = entry.next; -// while (next != NULL) -// { -// queue.dispose(next); -// next = next.next; -// } -// entry.next = NULL; - } + void disposeNext(TrackEntry* entry); - void animationsChanged() - { -// animationsChanged = false; -// -// var propertyIDs = _propertyIDs; -// propertyIDs.clear(); -// var mixingTo = _mixingTo; -// -// var tracksItems = tracks.Items; -// for (int i = 0, n = tracks.Count; i < n; i++) -// { -// var entry = tracksItems[i]; -// if (entry != NULL) -// { -// entry.setTimelineData(NULL, mixingTo, propertyIDs); -// } -// } - } + void animationsChanged(); }; } diff --git a/spine-cpp/spine-cpp/include/spine/AnimationStateData.h b/spine-cpp/spine-cpp/include/spine/AnimationStateData.h index d0b785094..952b33256 100644 --- a/spine-cpp/spine-cpp/include/spine/AnimationStateData.h +++ b/spine-cpp/spine-cpp/include/spine/AnimationStateData.h @@ -44,6 +44,8 @@ namespace Spine /// Stores mix (crossfade) durations to be applied when AnimationState animations are changed. class AnimationStateData { + friend class AnimationState; + public: /// The SkeletonData to look up animations when they are specified by name. SkeletonData& getSkeletonData(); diff --git a/spine-cpp/spine-cpp/include/spine/AttachmentTimeline.h b/spine-cpp/spine-cpp/include/spine/AttachmentTimeline.h index 07460f6d3..91484b2b6 100644 --- a/spine-cpp/spine-cpp/include/spine/AttachmentTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/AttachmentTimeline.h @@ -51,7 +51,7 @@ namespace Spine public: AttachmentTimeline(int frameCount); - virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction); virtual int getPropertyId(); diff --git a/spine-cpp/spine-cpp/include/spine/Bone.h b/spine-cpp/spine-cpp/include/spine/Bone.h index a2bdae9e3..fafbc8f8a 100644 --- a/spine-cpp/spine-cpp/include/spine/Bone.h +++ b/spine-cpp/spine-cpp/include/spine/Bone.h @@ -49,6 +49,8 @@ namespace Spine { RTTI_DECL; + friend class AnimationState; + friend class RotateTimeline; friend class IkConstraint; friend class TransformConstraint; diff --git a/spine-cpp/spine-cpp/include/spine/BoneData.h b/spine-cpp/spine-cpp/include/spine/BoneData.h index 2d2ce3da6..1a7fcc2e9 100644 --- a/spine-cpp/spine-cpp/include/spine/BoneData.h +++ b/spine-cpp/spine-cpp/include/spine/BoneData.h @@ -39,6 +39,8 @@ namespace Spine { class BoneData { + friend class AnimationState; + friend class RotateTimeline; friend class ScaleTimeline; friend class ShearTimeline; diff --git a/spine-cpp/spine-cpp/include/spine/ColorTimeline.h b/spine-cpp/spine-cpp/include/spine/ColorTimeline.h index 178e4f13e..53a33ddd4 100644 --- a/spine-cpp/spine-cpp/include/spine/ColorTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/ColorTimeline.h @@ -44,7 +44,7 @@ namespace Spine ColorTimeline (int frameCount); - virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction); virtual int getPropertyId(); diff --git a/spine-cpp/spine-cpp/include/spine/CurveTimeline.h b/spine-cpp/spine-cpp/include/spine/CurveTimeline.h index a5222e31e..45854a7a0 100644 --- a/spine-cpp/spine-cpp/include/spine/CurveTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/CurveTimeline.h @@ -46,7 +46,7 @@ namespace Spine public: CurveTimeline(int frameCount); - virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) = 0; + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) = 0; virtual int getPropertyId() = 0; diff --git a/spine-cpp/spine-cpp/include/spine/DeformTimeline.h b/spine-cpp/spine-cpp/include/spine/DeformTimeline.h index 1500b77e5..a23eaca83 100644 --- a/spine-cpp/spine-cpp/include/spine/DeformTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/DeformTimeline.h @@ -44,7 +44,7 @@ namespace Spine public: DeformTimeline(int frameCount); - virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction); virtual int getPropertyId(); diff --git a/spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h b/spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h index 60ab70a08..29226dd88 100644 --- a/spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h @@ -42,7 +42,7 @@ namespace Spine public: DrawOrderTimeline(int frameCount); - virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction); virtual int getPropertyId(); diff --git a/spine-cpp/spine-cpp/include/spine/Event.h b/spine-cpp/spine-cpp/include/spine/Event.h index 07d36999c..1f4688d4c 100644 --- a/spine-cpp/spine-cpp/include/spine/Event.h +++ b/spine-cpp/spine-cpp/include/spine/Event.h @@ -40,6 +40,8 @@ namespace Spine /// Stores the current pose values for an Event. class Event { + friend class AnimationState; + public: Event(float time, const EventData& data); diff --git a/spine-cpp/spine-cpp/include/spine/EventTimeline.h b/spine-cpp/spine-cpp/include/spine/EventTimeline.h index b1512327e..c2f880080 100644 --- a/spine-cpp/spine-cpp/include/spine/EventTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/EventTimeline.h @@ -42,7 +42,7 @@ namespace Spine public: EventTimeline(int frameCount); - virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction); virtual int getPropertyId(); diff --git a/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h b/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h index fe570146b..3cd4235d9 100644 --- a/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h @@ -44,7 +44,7 @@ namespace Spine IkConstraintTimeline(int frameCount); - virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction); virtual int getPropertyId(); diff --git a/spine-cpp/spine-cpp/include/spine/MathUtil.h b/spine-cpp/spine-cpp/include/spine/MathUtil.h index 24dd4641c..325b95d2a 100644 --- a/spine-cpp/spine-cpp/include/spine/MathUtil.h +++ b/spine-cpp/spine-cpp/include/spine/MathUtil.h @@ -50,6 +50,12 @@ namespace Spine { + template + int sign(T val) + { + return (T(0) < val) - (val < T(0)); + } + inline bool areFloatsPracticallyEqual(float A, float B, float maxDiff = 0.0000000000000001f, float maxRelDiff = FLT_EPSILON) { // Check if the numbers are really close -- needed diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h b/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h index 96f0bd1a8..72598ab69 100644 --- a/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h @@ -44,7 +44,7 @@ namespace Spine PathConstraintMixTimeline(int frameCount); - virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction); virtual int getPropertyId(); diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h b/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h index ab6839e1f..2fc8af6a2 100644 --- a/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h @@ -44,7 +44,7 @@ namespace Spine PathConstraintPositionTimeline(int frameCount); - virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction); virtual int getPropertyId(); diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h b/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h index fb959a55a..65392639c 100644 --- a/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h @@ -42,7 +42,7 @@ namespace Spine public: PathConstraintSpacingTimeline(int frameCount); - virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction); virtual int getPropertyId(); }; diff --git a/spine-cpp/spine-cpp/include/spine/RotateTimeline.h b/spine-cpp/spine-cpp/include/spine/RotateTimeline.h index dcc013b71..c14031d98 100644 --- a/spine-cpp/spine-cpp/include/spine/RotateTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/RotateTimeline.h @@ -37,6 +37,8 @@ namespace Spine { class RotateTimeline : public CurveTimeline { + friend class AnimationState; + RTTI_DECL; public: @@ -44,7 +46,7 @@ namespace Spine RotateTimeline(int frameCount); - virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction); virtual int getPropertyId(); diff --git a/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h b/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h index 12f941f42..81409a50a 100644 --- a/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h @@ -42,7 +42,7 @@ namespace Spine public: ScaleTimeline(int frameCount); - virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction); virtual int getPropertyId(); }; diff --git a/spine-cpp/spine-cpp/include/spine/ShearTimeline.h b/spine-cpp/spine-cpp/include/spine/ShearTimeline.h index 5618a6529..ae83d7cef 100644 --- a/spine-cpp/spine-cpp/include/spine/ShearTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/ShearTimeline.h @@ -42,7 +42,7 @@ namespace Spine public: ShearTimeline(int frameCount); - virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction); virtual int getPropertyId(); }; diff --git a/spine-cpp/spine-cpp/include/spine/Skeleton.h b/spine-cpp/spine-cpp/include/spine/Skeleton.h index a7bd84ce9..1b39bd793 100644 --- a/spine-cpp/spine-cpp/include/spine/Skeleton.h +++ b/spine-cpp/spine-cpp/include/spine/Skeleton.h @@ -51,6 +51,7 @@ namespace Spine class Skeleton { + friend class AnimationState; friend class SkeletonBounds; friend class SkeletonClipping; diff --git a/spine-cpp/spine-cpp/include/spine/Timeline.h b/spine-cpp/spine-cpp/include/spine/Timeline.h index b00db7b28..a33bc4031 100644 --- a/spine-cpp/spine-cpp/include/spine/Timeline.h +++ b/spine-cpp/spine-cpp/include/spine/Timeline.h @@ -61,7 +61,7 @@ namespace Spine /// apply animations on top of each other (layered). /// @param pose Controls how mixing is applied when alpha is than 1. /// @param direction Indicates whether the timeline is mixing in or out. Used by timelines which perform instant transitions such as DrawOrderTimeline and AttachmentTimeline. - virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) = 0; + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) = 0; virtual int getPropertyId() = 0; }; diff --git a/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h b/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h index 6065d4727..c001e82b1 100644 --- a/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h @@ -44,7 +44,7 @@ namespace Spine TransformConstraintTimeline(int frameCount); - virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction); virtual int getPropertyId(); diff --git a/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h b/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h index d661f9d3f..37fd21a9e 100644 --- a/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h @@ -47,7 +47,7 @@ namespace Spine TranslateTimeline(int frameCount); - virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction); virtual int getPropertyId(); diff --git a/spine-cpp/spine-cpp/include/spine/TwoColorTimeline.h b/spine-cpp/spine-cpp/include/spine/TwoColorTimeline.h index ceb23848f..fd3f55fd4 100644 --- a/spine-cpp/spine-cpp/include/spine/TwoColorTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/TwoColorTimeline.h @@ -44,7 +44,7 @@ namespace Spine TwoColorTimeline(int frameCount); - virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction); + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction); virtual int getPropertyId(); diff --git a/spine-cpp/spine-cpp/src/spine/Animation.cpp b/spine-cpp/spine-cpp/src/spine/Animation.cpp index 96b625dcb..ac140cbf9 100644 --- a/spine-cpp/spine-cpp/src/spine/Animation.cpp +++ b/spine-cpp/spine-cpp/src/spine/Animation.cpp @@ -47,7 +47,7 @@ namespace Spine assert(_name.length() > 0); } - void Animation::apply(Skeleton& skeleton, float lastTime, float time, bool loop, Vector& events, float alpha, MixPose pose, MixDirection direction) + void Animation::apply(Skeleton& skeleton, float lastTime, float time, bool loop, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) { if (loop && _duration != 0) { @@ -60,7 +60,7 @@ namespace Spine for (int i = 0, n = static_cast(_timelines.size()); i < n; ++i) { - _timelines[i]->apply(skeleton, lastTime, time, events, alpha, pose, direction); + _timelines[i]->apply(skeleton, lastTime, time, pEvents, alpha, pose, direction); } } diff --git a/spine-cpp/spine-cpp/src/spine/AnimationState.cpp b/spine-cpp/spine-cpp/src/spine/AnimationState.cpp index 0caa37c60..5c586c11b 100644 --- a/spine-cpp/spine-cpp/src/spine/AnimationState.cpp +++ b/spine-cpp/spine-cpp/src/spine/AnimationState.cpp @@ -37,6 +37,11 @@ #include #include +#include +#include +#include +#include +#include #include #include @@ -325,6 +330,7 @@ namespace Spine case EventType_Dispose: trackEntry->_onAnimationEventFunc(state, EventType_Dispose, trackEntry, NULL); state._onAnimationEventFunc(state, EventType_Dispose, trackEntry, NULL); + trackEntry->reset(); _trackEntryPool.free(trackEntry); break; case EventType_Event: @@ -357,15 +363,748 @@ namespace Spine DESTROY(EventQueue, _queue); } + void AnimationState::update(float delta) + { + delta *= _timeScale; + for (int i = 0, n = static_cast(_tracks.size()); i < n; ++i) + { + TrackEntry* currentP = _tracks[i]; + if (currentP == NULL) + { + continue; + } + + TrackEntry& current = *currentP; + + current._animationLast = current._nextAnimationLast; + current._trackLast = current._nextTrackLast; + + float currentDelta = delta * current._timeScale; + + if (current._delay > 0) + { + current._delay -= currentDelta; + if (current._delay > 0) + { + continue; + } + currentDelta = -current._delay; + current._delay = 0; + } + + TrackEntry* next = current._next; + if (next != NULL) + { + // When the next entry's delay is passed, change to the next entry, preserving leftover time. + float nextTime = current._trackLast - next->_delay; + if (nextTime >= 0) + { + next->_delay = 0; + next->_trackTime = nextTime + (delta * next->_timeScale); + current._trackTime += currentDelta; + setCurrent(i, next, true); + while (next->_mixingFrom != NULL) + { + next->_mixTime += currentDelta; + next = next->_mixingFrom; + } + continue; + } + } + else if (current._trackLast >= current._trackEnd && current._mixingFrom == NULL) + { + // clear the track when there is no next entry, the track end time is reached, and there is no mixingFrom. + _tracks[i] = NULL; + + _queue->end(currentP); + disposeNext(currentP); + continue; + } + + if (current._mixingFrom != NULL && updateMixingFrom(currentP, delta)) + { + // End mixing from entries once all have completed. + TrackEntry* from = current._mixingFrom; + current._mixingFrom = NULL; + while (from != NULL) + { + _queue->end(from); + from = from->_mixingFrom; + } + } + + current._trackTime += currentDelta; + } + + _queue->drain(); + } + + bool AnimationState::apply(Skeleton& skeleton) + { + if (_animationsChanged) + { + animationsChanged(); + } + + bool applied = false; + for (int i = 0, n = static_cast(_tracks.size()); i < n; ++i) + { + TrackEntry* currentP = _tracks[i]; + if (currentP == NULL || currentP->_delay > 0) + { + continue; + } + + TrackEntry& current = *currentP; + + applied = true; + MixPose currentPose = i == 0 ? MixPose_Current : MixPose_CurrentLayered; + + // apply mixing from entries first. + float mix = current._alpha; + if (current._mixingFrom != NULL) + { + mix *= applyMixingFrom(currentP, skeleton, currentPose); + } + else if (current._trackTime >= current._trackEnd && current._next == NULL) // + { + mix = 0; // Set to setup pose the last time the entry will be applied. + } + + // apply current entry. + float animationLast = current._animationLast, animationTime = current.getAnimationTime(); + int timelineCount = static_cast(current._animation->_timelines.size()); + Vector& timelines = current._animation->_timelines; + if (mix == 1) + { + for (int ii = 0; ii < timelineCount; ++ii) + { + timelines[ii]->apply(skeleton, animationLast, animationTime, &_events, 1, MixPose_Setup, MixDirection_In); + } + } + else + { + Vector& timelineData = current._timelineData; + + bool firstFrame = current._timelinesRotation.size() == 0; + if (firstFrame) + { + current._timelinesRotation.reserve(timelines.size() << 1); + } + Vector& timelinesRotation = current._timelinesRotation; + + for (int ii = 0; ii < timelineCount; ++ii) + { + Timeline* timeline = timelines[ii]; + assert(timeline); + + MixPose pose = timelineData[ii] >= AnimationState::First ? MixPose_Setup : currentPose; + + RotateTimeline* rotateTimeline = NULL; + if (timeline->getRTTI().derivesFrom(RotateTimeline::rtti)) + { + rotateTimeline = static_cast(timeline); + } + + if (rotateTimeline != NULL) + { + applyRotateTimeline(rotateTimeline, skeleton, animationTime, mix, pose, timelinesRotation, ii << 1, firstFrame); + } + else + { + timeline->apply(skeleton, animationLast, animationTime, &_events, mix, pose, MixDirection_In); + } + } + } + + queueEvents(currentP, animationTime); + _events.clear(); + current._nextAnimationLast = animationTime; + current._nextTrackLast = current._trackTime; + } + + _queue->drain(); + return applied; + } + + void AnimationState::clearTracks() + { + bool oldDrainDisabled = _queue->_drainDisabled; + _queue->_drainDisabled = true; + for (int i = 0, n = static_cast(_tracks.size()); i < n; ++i) + { + clearTrack(i); + } + _tracks.clear(); + _queue->_drainDisabled = oldDrainDisabled; + _queue->drain(); + } + + void AnimationState::clearTrack(int trackIndex) + { + if (trackIndex >= _tracks.size()) + { + return; + } + + TrackEntry* current = _tracks[trackIndex]; + if (current == NULL) + { + return; + } + + _queue->end(current); + + disposeNext(current); + + TrackEntry* entry = current; + while (true) + { + TrackEntry* from = entry->_mixingFrom; + if (from == NULL) + { + break; + } + + _queue->end(from); + entry->_mixingFrom = NULL; + entry = from; + } + + _tracks[current->_trackIndex] = NULL; + + _queue->drain(); + } + + TrackEntry* AnimationState::setAnimation(int trackIndex, std::string animationName, bool loop) + { + Animation* animation = _data._skeletonData.findAnimation(animationName); + assert(animation != NULL); + + return setAnimation(trackIndex, animation, loop); + } + + TrackEntry* AnimationState::setAnimation(int trackIndex, Animation* animation, bool loop) + { + assert(animation != NULL); + + bool interrupt = true; + TrackEntry* current = expandToIndex(trackIndex); + if (current != NULL) + { + if (current->_nextTrackLast == -1) + { + // Don't mix from an entry that was never applied. + _tracks[trackIndex] = current->_mixingFrom; + _queue->interrupt(current); + _queue->end(current); + disposeNext(current); + current = current->_mixingFrom; + interrupt = false; + } + else + { + disposeNext(current); + } + } + + TrackEntry* entry = newTrackEntry(trackIndex, animation, loop, current); + setCurrent(trackIndex, entry, interrupt); + _queue->drain(); + + return entry; + } + + TrackEntry* AnimationState::addAnimation(int trackIndex, std::string animationName, bool loop, float delay) + { + Animation* animation = _data._skeletonData.findAnimation(animationName); + assert(animation != NULL); + + return addAnimation(trackIndex, animation, loop, delay); + } + + TrackEntry* AnimationState::addAnimation(int trackIndex, Animation* animation, bool loop, float delay) + { + assert(animation != NULL); + + TrackEntry* last = expandToIndex(trackIndex); + if (last != NULL) + { + while (last->_next != NULL) + { + last = last->_next; + } + } + + TrackEntry* entry = newTrackEntry(trackIndex, animation, loop, last); + + if (last == NULL) + { + setCurrent(trackIndex, entry, true); + _queue->drain(); + } + else + { + last->_next = entry; + if (delay <= 0) + { + float duration = last->_animationEnd - last->_animationStart; + if (duration != 0) + { + delay += duration * (1 + (int)(last->_trackTime / duration)) - _data.getMix(last->_animation, animation); + } + else + { + delay = 0; + } + } + } + + entry->_delay = delay; + return entry; + } + + TrackEntry* AnimationState::setEmptyAnimation(int trackIndex, float mixDuration) + { + TrackEntry* entry = setAnimation(trackIndex, AnimationState::getEmptyAnimation(), false); + entry->_mixDuration = mixDuration; + entry->_trackEnd = mixDuration; + return entry; + } + + TrackEntry* AnimationState::addEmptyAnimation(int trackIndex, float mixDuration, float delay) + { + if (delay <= 0) + { + delay -= mixDuration; + } + + TrackEntry* entry = addAnimation(trackIndex, AnimationState::getEmptyAnimation(), false, delay); + entry->_mixDuration = mixDuration; + entry->_trackEnd = mixDuration; + return entry; + } + + void AnimationState::setEmptyAnimations(float mixDuration) + { + bool oldDrainDisabled = _queue->_drainDisabled; + _queue->_drainDisabled = true; + for (int i = 0, n = static_cast(_tracks.size()); i < n; ++i) + { + TrackEntry* current = _tracks[i]; + if (current != NULL) + { + setEmptyAnimation(i, mixDuration); + } + } + _queue->_drainDisabled = oldDrainDisabled; + _queue->drain(); + } + + TrackEntry* AnimationState::getCurrent(int trackIndex) + { + return trackIndex >= _tracks.size() ? NULL : _tracks[trackIndex]; + } + + AnimationStateData& AnimationState::getData() + { + return _data; + } + + Vector AnimationState::getTracks() + { + return _tracks; + } + + float AnimationState::getTimeScale() + { + return _timeScale; + } + + void AnimationState::setTimeScale(float inValue) + { + _timeScale = inValue; + } + void AnimationState::setOnAnimationEventFunc(OnAnimationEventFunc inValue) { _onAnimationEventFunc = inValue; } - Animation& AnimationState::getEmptyAnimation() + Animation* AnimationState::getEmptyAnimation() { static Vector timelines; static Animation ret(std::string(""), timelines, 0); - return ret; + return &ret; + } + + void AnimationState::applyRotateTimeline(RotateTimeline* rotateTimeline, Skeleton& skeleton, float time, float alpha, MixPose pose, Vector& timelinesRotation, int i, bool firstFrame) + { + if (firstFrame) + { + timelinesRotation[i] = 0; + } + + if (alpha == 1) + { + rotateTimeline->apply(skeleton, 0, time, NULL, 1, pose, MixDirection_In); + return; + } + + Bone* bone = skeleton._bones[rotateTimeline->_boneIndex]; + Vector frames = rotateTimeline->_frames; + if (time < frames[0]) + { + if (pose == MixPose_Setup) + { + bone->_rotation = bone->_data._rotation; + } + return; + } + + float r2; + if (time >= frames[frames.size() - RotateTimeline::ENTRIES]) // Time is after last frame. + { + r2 = bone->_data._rotation + frames[frames.size() + RotateTimeline::PREV_ROTATION]; + } + else + { + // Interpolate between the previous frame and the current frame. + int frame = Animation::binarySearch(frames, time, RotateTimeline::ENTRIES); + float prevRotation = frames[frame + RotateTimeline::PREV_ROTATION]; + float frameTime = frames[frame]; + float percent = rotateTimeline->getCurvePercent((frame >> 1) - 1, 1 - (time - frameTime) / (frames[frame + RotateTimeline::PREV_TIME] - frameTime)); + + r2 = frames[frame + RotateTimeline::ROTATION] - prevRotation; + r2 -= (16384 - (int)(16384.499999999996 - r2 / 360)) * 360; + r2 = prevRotation + r2 * percent + bone->_data._rotation; + r2 -= (16384 - (int)(16384.499999999996 - r2 / 360)) * 360; + } + + // Mix between rotations using the direction of the shortest route on the first frame while detecting crosses. + float r1 = pose == MixPose_Setup ? bone->_data._rotation : bone->_rotation; + float total, diff = r2 - r1; + if (diff == 0) + { + total = timelinesRotation[i]; + } + else + { + diff -= (16384 - (int)(16384.499999999996 - diff / 360)) * 360; + float lastTotal, lastDiff; + if (firstFrame) + { + lastTotal = 0; + lastDiff = diff; + } + else + { + lastTotal = timelinesRotation[i]; // Angle and direction of mix, including loops. + lastDiff = timelinesRotation[i + 1]; // Difference between bones. + } + + bool current = diff > 0, dir = lastTotal >= 0; + // Detect cross at 0 (not 180). + if (sign(lastDiff) != sign(diff) && abs(lastDiff) <= 90) + { + // A cross after a 360 rotation is a loop. + if (abs(lastTotal) > 180) + { + lastTotal += 360 * sign(lastTotal); + } + dir = current; + } + + total = diff + lastTotal - fmod(lastTotal, 360); // Store loops as part of lastTotal. + if (dir != current) + { + total += 360 * sign(lastTotal); + } + timelinesRotation[i] = total; + } + timelinesRotation[i + 1] = diff; + r1 += total * alpha; + bone->_rotation = r1 - (16384 - (int)(16384.499999999996 - r1 / 360)) * 360; + } + + bool AnimationState::updateMixingFrom(TrackEntry* to, float delta) + { + TrackEntry* from = to->_mixingFrom; + if (from == NULL) + { + return true; + } + + bool finished = updateMixingFrom(from, delta); + + // Require mixTime > 0 to ensure the mixing from entry was applied at least once. + if (to->_mixTime > 0 && (to->_mixTime >= to->_mixDuration || to->_timeScale == 0)) + { + // Require totalAlpha == 0 to ensure mixing is complete, unless mixDuration == 0 (the transition is a single frame). + if (from->_totalAlpha == 0 || to->_mixDuration == 0) + { + to->_mixingFrom = from->_mixingFrom; + to->_interruptAlpha = from->_interruptAlpha; + _queue->end(from); + } + return finished; + } + + from->_animationLast = from->_nextAnimationLast; + from->_trackLast = from->_nextTrackLast; + from->_trackTime += delta * from->_timeScale; + to->_mixTime += delta * to->_timeScale; + + return false; + } + + float AnimationState::applyMixingFrom(TrackEntry* to, Skeleton& skeleton, MixPose currentPose) + { + TrackEntry* from = to->_mixingFrom; + if (from->_mixingFrom != NULL) + { + applyMixingFrom(from, skeleton, currentPose); + } + + float mix; + if (to->_mixDuration == 0) + { + // Single frame mix to undo mixingFrom changes. + mix = 1; + currentPose = MixPose_Setup; + } + else + { + mix = to->_mixTime / to->_mixDuration; + if (mix > 1) + { + mix = 1; + } + } + + Vector* eventBuffer = mix < from->_eventThreshold ? &_events : NULL; + bool attachments = mix < from->_attachmentThreshold, drawOrder = mix < from->_drawOrderThreshold; + float animationLast = from->_animationLast, animationTime = from->getAnimationTime(); + Vector& timelines = from->_animation->_timelines; + int timelineCount = static_cast(timelines.size()); + Vector& timelineData = from->_timelineData; + Vector& timelineDipMix = from->_timelineDipMix; + + bool firstFrame = from->_timelinesRotation.size() == 0; + if (firstFrame) + { + // from.timelinesRotation.setSize + from->_timelinesRotation.reserve(timelines.size() << 1); + } + + Vector& timelinesRotation = from->_timelinesRotation; + + MixPose pose; + float alphaDip = from->_alpha * to->_interruptAlpha, alphaMix = alphaDip * (1 - mix), alpha; + from->_totalAlpha = 0; + for (int i = 0; i < timelineCount; ++i) + { + Timeline* timeline = timelines[i]; + switch (timelineData[i]) + { + case Subsequent: + if (!attachments && timeline->getRTTI().derivesFrom(AttachmentTimeline::rtti)) + { + continue; + } + if (!drawOrder && timeline->getRTTI().derivesFrom(DrawOrderTimeline::rtti)) + { + continue; + } + + pose = currentPose; + alpha = alphaMix; + break; + case First: + pose = MixPose_Setup; + alpha = alphaMix; + break; + case Dip: + pose = MixPose_Setup; + alpha = alphaDip; + break; + default: + pose = MixPose_Setup; + TrackEntry* dipMix = timelineDipMix[i]; + alpha = alphaDip * MAX(0, 1 - dipMix->_mixTime / dipMix->_mixDuration); + break; + } + from->_totalAlpha += alpha; + + RotateTimeline* rotateTimeline = NULL; + if (timeline->getRTTI().derivesFrom(RotateTimeline::rtti)) + { + rotateTimeline = static_cast(timeline); + } + + if (rotateTimeline != NULL) + { + applyRotateTimeline(rotateTimeline, skeleton, animationTime, alpha, pose, timelinesRotation, i << 1, firstFrame); + } + else + { + timeline->apply(skeleton, animationLast, animationTime, eventBuffer, alpha, pose, MixDirection_Out); + } + } + + if (to->_mixDuration > 0) + { + queueEvents(from, animationTime); + } + + _events.clear(); + from->_nextAnimationLast = animationTime; + from->_nextTrackLast = from->_trackTime; + + return mix; + } + + void AnimationState::queueEvents(TrackEntry* entry, float animationTime) + { + float animationStart = entry->_animationStart, animationEnd = entry->_animationEnd; + float duration = animationEnd - animationStart; + float trackLastWrapped = fmodf(entry->_trackLast, duration); + + // Queue events before complete. + int i = 0, n = static_cast(_events.size()); + for (; i < n; ++i) + { + Event* e = _events[i]; + if (e->_time < trackLastWrapped) + { + break; + } + if (e->_time > animationEnd) + { + // Discard events outside animation start/end. + continue; + } + _queue->event(entry, e); + } + + // Queue complete if completed a loop iteration or the animation. + if (entry->_loop ? (trackLastWrapped > fmod(entry->_trackTime, duration)) : (animationTime >= animationEnd && entry->_animationLast < animationEnd)) + { + _queue->complete(entry); + } + + // Queue events after complete. + for (; i < n; ++i) + { + Event* e = _events[i]; + if (e->_time < animationStart) + { + // Discard events outside animation start/end. + continue; + } + _queue->event(entry, _events[i]); + } + } + + void AnimationState::setCurrent(int index, TrackEntry* current, bool interrupt) + { + TrackEntry* from = expandToIndex(index); + _tracks[index] = current; + + if (from != NULL) + { + if (interrupt) + { + _queue->interrupt(from); + } + + current->_mixingFrom = from; + current->_mixTime = 0; + + // Store interrupted mix percentage. + if (from->_mixingFrom != NULL && from->_mixDuration > 0) + { + current->_interruptAlpha *= MIN(1, from->_mixTime / from->_mixDuration); + } + + from->_timelinesRotation.clear(); // Reset rotation for mixing out, in case entry was mixed in. + } + + _queue->start(current); // triggers animationsChanged + } + + TrackEntry* AnimationState::expandToIndex(int index) + { + if (index < _tracks.size()) + { + return _tracks[index]; + } + + while (index >= _tracks.size()) + { + _tracks.push_back(NULL); + } + + return NULL; + } + + TrackEntry* AnimationState::newTrackEntry(int trackIndex, Animation* animation, bool loop, TrackEntry* last) + { + TrackEntry* entryP = _trackEntryPool.obtain(); // Pooling + TrackEntry& entry = *entryP; + + entry._trackIndex = trackIndex; + entry._animation = animation; + entry._loop = loop; + + entry._eventThreshold = 0; + entry._attachmentThreshold = 0; + entry._drawOrderThreshold = 0; + + entry._animationStart = 0; + entry._animationEnd = animation->getDuration(); + entry._animationLast = -1; + entry._nextAnimationLast = -1; + + entry._delay = 0; + entry._trackTime = 0; + entry._trackLast = -1; + entry._nextTrackLast = -1; // nextTrackLast == -1 signifies a TrackEntry that wasn't applied yet. + entry._trackEnd = std::numeric_limits::max(); // loop ? float.MaxValue : animation.Duration; + entry._timeScale = 1; + + entry._alpha = 1; + entry._interruptAlpha = 1; + entry._mixTime = 0; + entry._mixDuration = (last == NULL) ? 0 : _data.getMix(last->_animation, animation); + + return entryP; + } + + void AnimationState::disposeNext(TrackEntry* entry) + { + TrackEntry* next = entry->_next; + while (next != NULL) + { + _queue->dispose(next); + next = next->_next; + } + entry->_next = NULL; + } + + void AnimationState::animationsChanged() + { + _animationsChanged = false; + + _propertyIDs.clear(); + + for (int i = 0, n = static_cast(_tracks.size()); i < n; ++i) + { + TrackEntry* entry = _tracks[i]; + if (entry != NULL) + { + entry->setTimelineData(NULL, _mixingTo, _propertyIDs); + } + } } } diff --git a/spine-cpp/spine-cpp/src/spine/AttachmentTimeline.cpp b/spine-cpp/spine-cpp/src/spine/AttachmentTimeline.cpp index c923a4508..53bcaaf72 100644 --- a/spine-cpp/spine-cpp/src/spine/AttachmentTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/AttachmentTimeline.cpp @@ -48,7 +48,7 @@ namespace Spine _attachmentNames.reserve(frameCount); } - void AttachmentTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) + void AttachmentTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) { assert(_slotIndex < skeleton._slots.size()); diff --git a/spine-cpp/spine-cpp/src/spine/ColorTimeline.cpp b/spine-cpp/spine-cpp/src/spine/ColorTimeline.cpp index e7d49f9aa..4d99feb7a 100644 --- a/spine-cpp/spine-cpp/src/spine/ColorTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/ColorTimeline.cpp @@ -58,7 +58,7 @@ namespace Spine _frames.reserve(frameCount * ENTRIES); } - void ColorTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) + void ColorTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) { Slot* slotP = skeleton._slots[_slotIndex]; Slot& slot = *slotP; diff --git a/spine-cpp/spine-cpp/src/spine/DeformTimeline.cpp b/spine-cpp/spine-cpp/src/spine/DeformTimeline.cpp index ac2a981fe..bfa1389aa 100644 --- a/spine-cpp/spine-cpp/src/spine/DeformTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/DeformTimeline.cpp @@ -50,7 +50,7 @@ namespace Spine _frameVertices.reserve(frameCount); } - void DeformTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) + void DeformTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) { Slot* slotP = skeleton._slots[_slotIndex]; Slot& slot = *slotP; diff --git a/spine-cpp/spine-cpp/src/spine/DrawOrderTimeline.cpp b/spine-cpp/spine-cpp/src/spine/DrawOrderTimeline.cpp index 6561db060..207715f8e 100644 --- a/spine-cpp/spine-cpp/src/spine/DrawOrderTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/DrawOrderTimeline.cpp @@ -48,7 +48,7 @@ namespace Spine _drawOrders.reserve(frameCount); } - void DrawOrderTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) + void DrawOrderTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) { Vector& drawOrder = skeleton._drawOrder; Vector& slots = skeleton._slots; diff --git a/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp b/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp index 87ab7a814..23a0fccab 100644 --- a/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp @@ -49,8 +49,15 @@ namespace Spine _events.reserve(frameCount); } - void EventTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) + void EventTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) { + if (pEvents == NULL) + { + return; + } + + Vector& events = *pEvents; + if (events.size() == 0) { return; @@ -61,7 +68,7 @@ namespace Spine if (lastTime > time) { // Fire events after last time for looped animations. - apply(skeleton, lastTime, std::numeric_limits::max(), events, alpha, pose, direction); + apply(skeleton, lastTime, std::numeric_limits::max(), pEvents, alpha, pose, direction); lastTime = -1.0f; } else if (lastTime >= _frames[frameCount - 1]) // Last time is after last frame. diff --git a/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp b/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp index 2b05750e3..483b8c619 100644 --- a/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp @@ -56,7 +56,7 @@ namespace Spine _frames.reserve(frameCount * ENTRIES); } - void IkConstraintTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) + void IkConstraintTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) { IkConstraint* constraintP = skeleton._ikConstraints[_ikConstraintIndex]; IkConstraint& constraint = *constraintP; diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp b/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp index 394ecf48e..18c84ece7 100644 --- a/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp @@ -56,7 +56,7 @@ namespace Spine _frames.reserve(frameCount * ENTRIES); } - void PathConstraintMixTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) + void PathConstraintMixTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) { PathConstraint* constraintP = skeleton._pathConstraints[_pathConstraintIndex]; PathConstraint& constraint = *constraintP; diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp b/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp index 75b423ee9..13363ad45 100644 --- a/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp @@ -54,7 +54,7 @@ namespace Spine _frames.reserve(frameCount * ENTRIES); } - void PathConstraintPositionTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) + void PathConstraintPositionTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) { PathConstraint* constraintP = skeleton._pathConstraints[_pathConstraintIndex]; PathConstraint& constraint = *constraintP; diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp b/spine-cpp/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp index 7d4713585..44d132596 100644 --- a/spine-cpp/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp @@ -49,7 +49,7 @@ namespace Spine // Empty } - void PathConstraintSpacingTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) + void PathConstraintSpacingTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) { PathConstraint* constraintP = skeleton._pathConstraints[_pathConstraintIndex]; PathConstraint& constraint = *constraintP; diff --git a/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp b/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp index acfeb7db1..c57a37b37 100644 --- a/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp @@ -47,7 +47,7 @@ namespace Spine _frames.reserve(frameCount << 1); } - void RotateTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) + void RotateTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) { Bone* bone = skeleton.getBones()[_boneIndex]; diff --git a/spine-cpp/spine-cpp/src/spine/ScaleTimeline.cpp b/spine-cpp/spine-cpp/src/spine/ScaleTimeline.cpp index 0be6f9347..9c110a064 100644 --- a/spine-cpp/spine-cpp/src/spine/ScaleTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/ScaleTimeline.cpp @@ -49,7 +49,7 @@ namespace Spine // Empty } - void ScaleTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) + void ScaleTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) { Bone* boneP = skeleton._bones[_boneIndex]; Bone& bone = *boneP; diff --git a/spine-cpp/spine-cpp/src/spine/ShearTimeline.cpp b/spine-cpp/spine-cpp/src/spine/ShearTimeline.cpp index 4b142eccc..2089e7de4 100644 --- a/spine-cpp/spine-cpp/src/spine/ShearTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/ShearTimeline.cpp @@ -49,7 +49,7 @@ namespace Spine // Empty } - void ShearTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) + void ShearTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) { Bone* boneP = skeleton._bones[_boneIndex]; Bone& bone = *boneP; diff --git a/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp b/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp index bb4769cce..3d7cf2dfd 100644 --- a/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp @@ -60,7 +60,7 @@ namespace Spine _frames.reserve(frameCount * ENTRIES); } - void TransformConstraintTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) + void TransformConstraintTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) { TransformConstraint* constraintP = skeleton._transformConstraints[_transformConstraintIndex]; TransformConstraint& constraint = *constraintP; diff --git a/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp b/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp index 1a886f7d1..f241f31a8 100644 --- a/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp @@ -56,7 +56,7 @@ namespace Spine _frames.reserve(frameCount * ENTRIES); } - void TranslateTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) + void TranslateTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) { Bone* boneP = skeleton._bones[_boneIndex]; Bone& bone = *boneP; diff --git a/spine-cpp/spine-cpp/src/spine/TwoColorTimeline.cpp b/spine-cpp/spine-cpp/src/spine/TwoColorTimeline.cpp index 0232711c3..bce0d0bf7 100644 --- a/spine-cpp/spine-cpp/src/spine/TwoColorTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/TwoColorTimeline.cpp @@ -64,7 +64,7 @@ namespace Spine _frames.reserve(frameCount * ENTRIES); } - void TwoColorTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector& events, float alpha, MixPose pose, MixDirection direction) + void TwoColorTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) { Slot* slotP = skeleton._slots[_slotIndex]; Slot& slot = *slotP; From 9e0ac4d407688d035ceb90ec765b6ac6b23215cd Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Sat, 2 Dec 2017 14:48:35 -0500 Subject: [PATCH 58/83] Addressing some warnings. --- spine-cpp/spine-cpp/include/spine/Timeline.h | 2 +- spine-cpp/spine-cpp/src/spine/AnimationState.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/spine-cpp/spine-cpp/include/spine/Timeline.h b/spine-cpp/spine-cpp/include/spine/Timeline.h index a33bc4031..606854138 100644 --- a/spine-cpp/spine-cpp/include/spine/Timeline.h +++ b/spine-cpp/spine-cpp/include/spine/Timeline.h @@ -54,7 +54,7 @@ namespace Spine /// @param skeleton The skeleton the timeline is being applied to. This provides access to the bones, slots, and other skeleton components the timeline may change. /// @param lastTime lastTime The time this timeline was last applied. Timelines such as EventTimeline trigger only at specific times rather than every frame. In that case, the timeline triggers everything between lastTime (exclusive) and time (inclusive). /// @param time The time within the animation. Most timelines find the key before and the key after this time so they can interpolate between the keys. - /// @param events If any events are fired, they are added to this array. Can be NULL to ignore firing events or if the timeline does not fire events. May be NULL. + /// @param pEvents If any events are fired, they are added to this array. Can be NULL to ignore firing events or if the timeline does not fire events. May be NULL. /// @param alpha alpha 0 applies the current or setup pose value (depending on pose parameter). 1 applies the timeline /// value. Between 0 and 1 applies a value between the current or setup pose and the timeline value. By adjusting /// alpha over time, an animation can be mixed in or out. alpha can also be useful to diff --git a/spine-cpp/spine-cpp/src/spine/AnimationState.cpp b/spine-cpp/spine-cpp/src/spine/AnimationState.cpp index 5c586c11b..bcac04dcb 100644 --- a/spine-cpp/spine-cpp/src/spine/AnimationState.cpp +++ b/spine-cpp/spine-cpp/src/spine/AnimationState.cpp @@ -805,10 +805,10 @@ namespace Spine bool current = diff > 0, dir = lastTotal >= 0; // Detect cross at 0 (not 180). - if (sign(lastDiff) != sign(diff) && abs(lastDiff) <= 90) + if (sign(lastDiff) != sign(diff) && fabs(lastDiff) <= 90) { // A cross after a 360 rotation is a loop. - if (abs(lastTotal) > 180) + if (fabs(lastTotal) > 180) { lastTotal += 360 * sign(lastTotal); } From f7486ef9f841611ab874e83d88d9df873a030bf4 Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Sat, 2 Dec 2017 18:16:58 -0500 Subject: [PATCH 59/83] Chugging through porting SkeletonBinary After that, will port over SkeletonJson and Json --- spine-cpp/spine-cpp/include/spine/BoneData.h | 1 + spine-cpp/spine-cpp/include/spine/Extension.h | 7 +- .../spine-cpp/include/spine/LinkedMesh.h | 53 ++ .../spine-cpp/include/spine/SkeletonBinary.h | 79 ++- .../spine-cpp/include/spine/SkeletonData.h | 4 + .../spine-cpp/include/spine/SkeletonJson.h | 27 +- .../spine-cpp/src/spine/AnimationState.cpp | 1 + spine-cpp/spine-cpp/src/spine/Extension.cpp | 21 +- spine-cpp/spine-cpp/src/spine/LinkedMesh.cpp | 45 ++ .../spine-cpp/src/spine/SkeletonBinary.cpp | 451 +++++++++++++++++- .../spine-cpp/src/spine/SkeletonData.cpp | 15 + .../spine-cpp/src/spine/SkeletonJson.cpp | 39 +- 12 files changed, 733 insertions(+), 10 deletions(-) create mode 100644 spine-cpp/spine-cpp/include/spine/LinkedMesh.h create mode 100644 spine-cpp/spine-cpp/src/spine/LinkedMesh.cpp diff --git a/spine-cpp/spine-cpp/include/spine/BoneData.h b/spine-cpp/spine-cpp/include/spine/BoneData.h index 1a7fcc2e9..25530985e 100644 --- a/spine-cpp/spine-cpp/include/spine/BoneData.h +++ b/spine-cpp/spine-cpp/include/spine/BoneData.h @@ -39,6 +39,7 @@ namespace Spine { class BoneData { + friend class SkeletonBinary; friend class AnimationState; friend class RotateTimeline; diff --git a/spine-cpp/spine-cpp/include/spine/Extension.h b/spine-cpp/spine-cpp/include/spine/Extension.h index e58f44991..3595d365f 100644 --- a/spine-cpp/spine-cpp/include/spine/Extension.h +++ b/spine-cpp/spine-cpp/include/spine/Extension.h @@ -37,6 +37,7 @@ /* All allocation uses these. */ #define MALLOC(TYPE,COUNT) ((TYPE*)SPINE_EXTENSION->spineAlloc(sizeof(TYPE) * (COUNT), __FILE__, __LINE__)) +#define CALLOC(TYPE,COUNT) ((TYPE*)SPINE_EXTENSION->spineCalloc(COUNT, sizeof(TYPE), __FILE__, __LINE__)) #define NEW(TYPE) ((TYPE*)SPINE_EXTENSION->spineAlloc(sizeof(TYPE), __FILE__, __LINE__)) #define REALLOC(PTR,TYPE,COUNT) ((TYPE*)SPINE_EXTENSION->spineRealloc(PTR, sizeof(TYPE) * (COUNT), __FILE__, __LINE__)) @@ -60,6 +61,8 @@ namespace Spine /// Implement this function to use your own memory allocator virtual void* spineAlloc(size_t size, const char* file, int line) = 0; + virtual void* spineCalloc(size_t num, size_t size, const char* file, int line) = 0; + virtual void* spineRealloc(void* ptr, size_t size, const char* file, int line) = 0; /// If you provide a spineAllocFunc, you should also provide a spineFreeFunc @@ -71,7 +74,7 @@ namespace Spine SpineExtension(); private: - static SpineExtension* _spineExtension; + static SpineExtension* _instance; }; class DefaultSpineExtension : public SpineExtension @@ -83,6 +86,8 @@ namespace Spine virtual void* spineAlloc(size_t size, const char* file, int line); + virtual void* spineCalloc(size_t num, size_t size, const char* file, int line); + virtual void* spineRealloc(void* ptr, size_t size, const char* file, int line); virtual void spineFree(void* mem); diff --git a/spine-cpp/spine-cpp/include/spine/LinkedMesh.h b/spine-cpp/spine-cpp/include/spine/LinkedMesh.h new file mode 100644 index 000000000..38482821e --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/LinkedMesh.h @@ -0,0 +1,53 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_LinkedMesh_h +#define Spine_LinkedMesh_h + +#include + +namespace Spine +{ + class MeshAttachment; + + class LinkedMesh + { + public: + LinkedMesh(MeshAttachment* mesh, std::string skin, int slotIndex, std::string parent); + + private: + MeshAttachment* _mesh; + std::string _skin; + int _slotIndex; + std::string _parent; + }; +} + +#endif /* Spine_LinkedMesh_h */ diff --git a/spine-cpp/spine-cpp/include/spine/SkeletonBinary.h b/spine-cpp/spine-cpp/include/spine/SkeletonBinary.h index cbb6b01c1..29d727ac8 100644 --- a/spine-cpp/spine-cpp/include/spine/SkeletonBinary.h +++ b/spine-cpp/spine-cpp/include/spine/SkeletonBinary.h @@ -31,9 +31,86 @@ #ifndef Spine_SkeletonBinary_h #define Spine_SkeletonBinary_h +#include +#include + +#include + namespace Spine { - // TODO + class SkeletonData; + class Atlas; + class AttachmentLoader; + class LinkedMesh; + + class SkeletonBinary + { + public: + static const int BONE_ROTATE; + static const int BONE_TRANSLATE; + static const int BONE_SCALE; + static const int BONE_SHEAR; + + static const int SLOT_ATTACHMENT; + static const int SLOT_COLOR; + static const int SLOT_TWO_COLOR; + + static const int PATH_POSITION; + static const int PATH_SPACING; + static const int PATH_MIX; + + static const int CURVE_LINEAR; + static const int CURVE_STEPPED; + static const int CURVE_BEZIER; + + static const TransformMode TRANSFORM_MODE_VALUES[5]; + + SkeletonBinary(Vector& atlasArray); + + SkeletonBinary(AttachmentLoader* attachmentLoader); + + ~SkeletonBinary(); + + SkeletonData* readSkeletonData(const unsigned char* binary, const int length); + + SkeletonData* readSkeletonDataFile(const char* path); + + private: + class Vertices + { + public: + Vector _bones; + Vector _vertices; + }; + + struct DataInput + { + const unsigned char* cursor; + const unsigned char* end; + }; + + AttachmentLoader* _attachmentLoader; + Vector _linkedMeshes; + std::string _error; + float _scale; + const bool _ownsLoader; + + void setError(const char* value1, const char* value2); + + char* readString(DataInput* input); + + float readFloat(DataInput* input); + + static unsigned char readByte(DataInput* input); + + static signed char readSByte(DataInput* input); + + static int readBoolean(DataInput* input); + + static int readInt(DataInput* input); + + static int readVarint(DataInput* input, bool optimizePositive); + }; } #endif /* Spine_SkeletonBinary_h */ diff --git a/spine-cpp/spine-cpp/include/spine/SkeletonData.h b/spine-cpp/spine-cpp/include/spine/SkeletonData.h index 44e467edc..96b4584cc 100644 --- a/spine-cpp/spine-cpp/include/spine/SkeletonData.h +++ b/spine-cpp/spine-cpp/include/spine/SkeletonData.h @@ -49,11 +49,15 @@ namespace Spine /// Stores the setup pose and all of the stateless data for a skeleton. class SkeletonData { + friend class SkeletonBinary; + friend class SkeletonJson; friend class Skeleton; public: SkeletonData(); + ~SkeletonData(); + /// Finds a bone by comparing each bone's name. /// It is more efficient to cache the results of this method than to call it multiple times. /// @return May be NULL. diff --git a/spine-cpp/spine-cpp/include/spine/SkeletonJson.h b/spine-cpp/spine-cpp/include/spine/SkeletonJson.h index 1ee1568b5..87139437d 100644 --- a/spine-cpp/spine-cpp/include/spine/SkeletonJson.h +++ b/spine-cpp/spine-cpp/include/spine/SkeletonJson.h @@ -31,9 +31,34 @@ #ifndef Spine_SkeletonJson_h #define Spine_SkeletonJson_h +#include + namespace Spine { - // TODO + class SkeletonData; + class Atlas; + class AttachmentLoader; + class LinkedMesh; + + class SkeletonJson + { + public: + SkeletonJson(Vector& atlasArray); + + SkeletonJson(AttachmentLoader* attachmentLoader); + + ~SkeletonJson(); + + SkeletonData* readSkeletonData(const char* json); + + SkeletonData* readSkeletonDataFile(const char* path); + + private: + AttachmentLoader* _attachmentLoader; + Vector _linkedMeshes; + float _scale; + const bool _ownsLoader; + }; } #endif /* Spine_SkeletonJson_h */ diff --git a/spine-cpp/spine-cpp/src/spine/AnimationState.cpp b/spine-cpp/spine-cpp/src/spine/AnimationState.cpp index bcac04dcb..760e99efb 100644 --- a/spine-cpp/spine-cpp/src/spine/AnimationState.cpp +++ b/spine-cpp/spine-cpp/src/spine/AnimationState.cpp @@ -352,6 +352,7 @@ namespace Spine AnimationState::AnimationState(AnimationStateData& data) : _data(data), _queue(EventQueue::newEventQueue(*this, _trackEntryPool)), + _animationsChanged(false), _onAnimationEventFunc(dummyOnAnimationEventFunc), _timeScale(1) { diff --git a/spine-cpp/spine-cpp/src/spine/Extension.cpp b/spine-cpp/spine-cpp/src/spine/Extension.cpp index 757d44cbe..81c667104 100644 --- a/spine-cpp/spine-cpp/src/spine/Extension.cpp +++ b/spine-cpp/spine-cpp/src/spine/Extension.cpp @@ -35,20 +35,20 @@ namespace Spine { - SpineExtension* SpineExtension::_spineExtension = NULL; + SpineExtension* SpineExtension::_instance = NULL; void SpineExtension::setInstance(SpineExtension* inValue) { - assert(!_spineExtension); + assert(!_instance); - _spineExtension = inValue; + _instance = inValue; } SpineExtension* SpineExtension::getInstance() { - assert(_spineExtension); + assert(_instance); - return _spineExtension; + return _instance; } SpineExtension::~SpineExtension() @@ -94,6 +94,17 @@ namespace Spine return malloc(size); } + void* DefaultSpineExtension::spineCalloc(size_t num, size_t size, const char* file, int line) + { + void* ptr = spineAlloc(num * size, file, line); + if (ptr) + { + memset(ptr, 0, num * size); + } + + return ptr; + } + void* DefaultSpineExtension::spineRealloc(void* ptr, size_t size, const char* file, int line) { return realloc(ptr, size); diff --git a/spine-cpp/spine-cpp/src/spine/LinkedMesh.cpp b/spine-cpp/spine-cpp/src/spine/LinkedMesh.cpp new file mode 100644 index 000000000..a1c25db11 --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/LinkedMesh.cpp @@ -0,0 +1,45 @@ +/****************************************************************************** +* Spine Runtimes Software License v2.5 +* +* Copyright (c) 2013-2016, Esoteric Software +* All rights reserved. +* +* You are granted a perpetual, non-exclusive, non-sublicensable, and +* non-transferable license to use, install, execute, and perform the Spine +* Runtimes software and derivative works solely for personal or internal +* use. Without the written permission of Esoteric Software (see Section 2 of +* the Spine Software License Agreement), you may not (a) modify, translate, +* adapt, or develop new applications using the Spine Runtimes or otherwise +* create derivative works or improvements of the Spine Runtimes or (b) remove, +* delete, alter, or obscure any trademarks or any copyright, trademark, patent, +* or other intellectual property or proprietary rights notices on or in the +* Software, including any copy thereof. Redistributions in binary or source +* form must include this license and terms. +* +* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +#include + +#include + +namespace Spine +{ + LinkedMesh::LinkedMesh(MeshAttachment* mesh, std::string skin, int slotIndex, std::string parent) : + _mesh(mesh), + _skin(skin), + _slotIndex(slotIndex), + _parent(parent) + { + // Empty + } +} diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp b/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp index bb4d2ccfe..ed84c76bc 100644 --- a/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp +++ b/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp @@ -28,7 +28,456 @@ * POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ +#include + +#include +#include +#include +#include + +#include +#include +#include + namespace Spine { - // TODO + const int SkeletonBinary::BONE_ROTATE = 0; + const int SkeletonBinary::BONE_TRANSLATE = 1; + const int SkeletonBinary::BONE_SCALE = 2; + const int SkeletonBinary::BONE_SHEAR = 3; + + const int SkeletonBinary::SLOT_ATTACHMENT = 0; + const int SkeletonBinary::SLOT_COLOR = 1; + const int SkeletonBinary::SLOT_TWO_COLOR = 2; + + const int SkeletonBinary::PATH_POSITION = 0; + const int SkeletonBinary::PATH_SPACING = 1; + const int SkeletonBinary::PATH_MIX = 2; + + const int SkeletonBinary::CURVE_LINEAR = 0; + const int SkeletonBinary::CURVE_STEPPED = 1; + const int SkeletonBinary::CURVE_BEZIER = 2; + + const TransformMode SkeletonBinary::TRANSFORM_MODE_VALUES[5] = { + TransformMode_Normal, + TransformMode_OnlyTranslation, + TransformMode_NoRotationOrReflection, + TransformMode_NoScale, + TransformMode_NoScaleOrReflection + }; + + SkeletonBinary::SkeletonBinary(Vector& atlasArray) : _attachmentLoader(NEW(AtlasAttachmentLoader)), _error(), _scale(1), _ownsLoader(true) + { + new (_attachmentLoader) AtlasAttachmentLoader(atlasArray); + } + + SkeletonBinary::SkeletonBinary(AttachmentLoader* attachmentLoader) : _attachmentLoader(attachmentLoader), _error(), _scale(1), _ownsLoader(false) + { + assert(_attachmentLoader != NULL); + } + + SkeletonBinary::~SkeletonBinary() + { + ContainerUtil::cleanUpVectorOfPointers(_linkedMeshes); + + if (_ownsLoader) + { + DESTROY(AttachmentLoader, _attachmentLoader); + } + } + + SkeletonData* SkeletonBinary::readSkeletonData(const unsigned char* binary, const int length) + { + int i, ii, nonessential; + SkeletonData* skeletonData; + + DataInput* input = CALLOC(DataInput, 1); + input->cursor = binary; + input->end = binary + length; + + _linkedMeshes.clear(); + + skeletonData = NEW(SkeletonData); + new (skeletonData) SkeletonData(); + + char* skeletonData_hash = readString(input); + skeletonData->_hash = std::string(skeletonData_hash); + FREE(skeletonData_hash); + + char* skeletonData_version = readString(input); + skeletonData->_version = std::string(skeletonData_version); + FREE(skeletonData_version); + + skeletonData->_width = readFloat(input); + skeletonData->_height = readFloat(input); + + nonessential = readBoolean(input); + + if (nonessential) + { + /* Skip images path & fps */ + readFloat(input); + FREE(readString(input)); + } + + /* Bones. */ + int bonesCount = readVarint(input, 1); + skeletonData->_bones.reserve(bonesCount); + for (i = 0; i < bonesCount; ++i) + { + BoneData* data; + int mode; + const char* name = readString(input); + BoneData* parent = i == 0 ? 0 : skeletonData->_bones[readVarint(input, 1)]; + + data = NEW(BoneData); + new (data) BoneData(i, std::string(name), parent); + + FREE(name); + + data->_rotation = readFloat(input); + data->_x = readFloat(input) * _scale; + data->_y = readFloat(input) * _scale; + data->_scaleX = readFloat(input); + data->_scaleY = readFloat(input); + data->_shearX = readFloat(input); + data->_shearY = readFloat(input); + data->_length = readFloat(input) * _scale; + + mode = readVarint(input, 1); + switch (mode) + { + case 0: + data->_transformMode = TransformMode_Normal; + break; + case 1: + data->_transformMode = TransformMode_OnlyTranslation; + break; + case 2: + data->_transformMode = TransformMode_NoRotationOrReflection; + break; + case 3: + data->_transformMode = TransformMode_NoScale; + break; + case 4: + data->_transformMode = TransformMode_NoScaleOrReflection; + break; + } + + if (nonessential) + { + /* Skip bone color. */ + readInt(input); + } + + skeletonData->_bones.push_back(data); + } + + /* Slots. */ +// skeletonData->slotsCount = readVarint(input, 1); +// skeletonData->slots = MALLOC(spSlotData*, skeletonData->slotsCount); +// for (i = 0; i < skeletonData->slotsCount; ++i) +// { +// int r, g, b, a; +// const char* slotName = readString(input); +// spBoneData* boneData = skeletonData->bones[readVarint(input, 1)]; +// /* TODO Avoid copying of slotName */ +// spSlotData* slotData = spSlotData_create(i, slotName, boneData); +// FREE(slotName); +// readColor(input, &slotData->color.r, &slotData->color.g, &slotData->color.b, &slotData->color.a); +// r = readByte(input); +// g = readByte(input); +// b = readByte(input); +// a = readByte(input); +// if (!(r == 0xff && g == 0xff && b == 0xff && a == 0xff)) +// { +// slotData->darkColor = spColor_create(); +// spColor_setFromFloats(slotData->darkColor, r / 255.0f, g / 255.0f, b / 255.0f, 1); +// } +// slotData->attachmentName = readString(input); +// slotData->blendMode = (spBlendMode)readVarint(input, 1); +// skeletonData->slots[i] = slotData; +// } +// +// /* IK constraints. */ +// skeletonData->ikConstraintsCount = readVarint(input, 1); +// skeletonData->ikConstraints = MALLOC(spIkConstraintData*, skeletonData->ikConstraintsCount); +// for (i = 0; i < skeletonData->ikConstraintsCount; ++i) +// { +// const char* name = readString(input); +// /* TODO Avoid copying of name */ +// spIkConstraintData* data = spIkConstraintData_create(name); +// data->order = readVarint(input, 1); +// FREE(name); +// data->bonesCount = readVarint(input, 1); +// data->bones = MALLOC(spBoneData*, data->bonesCount); +// for (ii = 0; ii < data->bonesCount; ++ii) +// data->bones[ii] = skeletonData->bones[readVarint(input, 1)]; +// data->target = skeletonData->bones[readVarint(input, 1)]; +// data->mix = readFloat(input); +// data->bendDirection = readSByte(input); +// skeletonData->ikConstraints[i] = data; +// } +// +// /* Transform constraints. */ +// skeletonData->transformConstraintsCount = readVarint(input, 1); +// skeletonData->transformConstraints = MALLOC(spTransformConstraintData*, skeletonData->transformConstraintsCount); +// for (i = 0; i < skeletonData->transformConstraintsCount; ++i) +// { +// const char* name = readString(input); +// /* TODO Avoid copying of name */ +// spTransformConstraintData* data = spTransformConstraintData_create(name); +// data->order = readVarint(input, 1); +// FREE(name); +// data->bonesCount = readVarint(input, 1); +// CONST_CAST(spBoneData**, data->bones) = MALLOC(spBoneData*, data->bonesCount); +// for (ii = 0; ii < data->bonesCount; ++ii) +// { +// data->bones[ii] = skeletonData->bones[readVarint(input, 1)]; +// } +// data->target = skeletonData->bones[readVarint(input, 1)]; +// data->local = readBoolean(input); +// data->relative = readBoolean(input); +// data->offsetRotation = readFloat(input); +// data->offsetX = readFloat(input) * _scale; +// data->offsetY = readFloat(input) * _scale; +// data->offsetScaleX = readFloat(input); +// data->offsetScaleY = readFloat(input); +// data->offsetShearY = readFloat(input); +// data->rotateMix = readFloat(input); +// data->translateMix = readFloat(input); +// data->scaleMix = readFloat(input); +// data->shearMix = readFloat(input); +// skeletonData->transformConstraints[i] = data; +// } +// +// /* Path constraints */ +// skeletonData->pathConstraintsCount = readVarint(input, 1); +// skeletonData->pathConstraints = MALLOC(spPathConstraintData*, skeletonData->pathConstraintsCount); +// for (i = 0; i < skeletonData->pathConstraintsCount; ++i) +// { +// const char* name = readString(input); +// /* TODO Avoid copying of name */ +// spPathConstraintData* data = spPathConstraintData_create(name); +// data->order = readVarint(input, 1); +// FREE(name); +// data->bonesCount = readVarint(input, 1); +// CONST_CAST(spBoneData**, data->bones) = MALLOC(spBoneData*, data->bonesCount); +// for (ii = 0; ii < data->bonesCount; ++ii) +// { +// data->bones[ii] = skeletonData->bones[readVarint(input, 1)]; +// } +// data->target = skeletonData->slots[readVarint(input, 1)]; +// data->positionMode = (spPositionMode)readVarint(input, 1); +// data->spacingMode = (spSpacingMode)readVarint(input, 1); +// data->rotateMode = (spRotateMode)readVarint(input, 1); +// data->offsetRotation = readFloat(input); +// data->position = readFloat(input); +// if (data->positionMode == SP_POSITION_MODE_FIXED) data->position *= _scale; +// data->spacing = readFloat(input); +// if (data->spacingMode == SP_SPACING_MODE_LENGTH || data->spacingMode == SP_SPACING_MODE_FIXED) data->spacing *= _scale; +// data->rotateMix = readFloat(input); +// data->translateMix = readFloat(input); +// skeletonData->pathConstraints[i] = data; +// } +// +// /* Default skin. */ +// skeletonData->defaultSkin = spSkeletonBinary_readSkin(self, input, "default", skeletonData, nonessential); +// skeletonData->skinsCount = readVarint(input, 1); +// +// if (skeletonData->defaultSkin) +// { +// ++skeletonData->skinsCount; +// } +// +// skeletonData->skins = MALLOC(spSkin*, skeletonData->skinsCount); +// +// if (skeletonData->defaultSkin) +// { +// skeletonData->skins[0] = skeletonData->defaultSkin; +// } +// +// /* Skins. */ +// for (i = skeletonData->defaultSkin ? 1 : 0; i < skeletonData->skinsCount; ++i) +// { +// const char* skinName = readString(input); +// /* TODO Avoid copying of skinName */ +// skeletonData->skins[i] = spSkeletonBinary_readSkin(self, input, skinName, skeletonData, nonessential); +// FREE(skinName); +// } +// +// /* Linked meshes. */ +// for (i = 0; i < internal->linkedMeshCount; ++i) +// { +// _spLinkedMesh* linkedMesh = internal->linkedMeshes + i; +// spSkin* skin = !linkedMesh->skin ? skeletonData->defaultSkin : spSkeletonData_findSkin(skeletonData, linkedMesh->skin); +// spAttachment* parent; +// if (!skin) +// { +// FREE(input); +// spSkeletonData_dispose(skeletonData); +// _spSkeletonBinary_setError(self, "Skin not found: ", linkedMesh->skin); +// return 0; +// } +// parent = spSkin_getAttachment(skin, linkedMesh->slotIndex, linkedMesh->parent); +// if (!parent) +// { +// FREE(input); +// spSkeletonData_dispose(skeletonData); +// _spSkeletonBinary_setError(self, "Parent mesh not found: ", linkedMesh->parent); +// return 0; +// } +// spMeshAttachment_setParentMesh(linkedMesh->mesh, SUB_CAST(spMeshAttachment, parent)); +// spMeshAttachment_updateUVs(linkedMesh->mesh); +// spAttachmentLoader_configureAttachment(self->attachmentLoader, SUPER(SUPER(linkedMesh->mesh))); +// } +// +// /* Events. */ +// skeletonData->eventsCount = readVarint(input, 1); +// skeletonData->events = MALLOC(spEventData*, skeletonData->eventsCount); +// for (i = 0; i < skeletonData->eventsCount; ++i) +// { +// const char* name = readString(input); +// /* TODO Avoid copying of skinName */ +// spEventData* eventData = spEventData_create(name); +// FREE(name); +// eventData->intValue = readVarint(input, 0); +// eventData->floatValue = readFloat(input); +// eventData->stringValue = readString(input); +// skeletonData->events[i] = eventData; +// } +// +// /* Animations. */ +// skeletonData->animationsCount = readVarint(input, 1); +// skeletonData->animations = MALLOC(spAnimation*, skeletonData->animationsCount); +// for (i = 0; i < skeletonData->animationsCount; ++i) +// { +// const char* name = readString(input); +// spAnimation* animation = _spSkeletonBinary_readAnimation(self, name, input, skeletonData); +// FREE(name); +// if (!animation) +// { +// FREE(input); +// spSkeletonData_dispose(skeletonData); +// return 0; +// } +// skeletonData->animations[i] = animation; +// } + + FREE(input); + + return skeletonData; + } + + SkeletonData* SkeletonBinary::readSkeletonDataFile(const char* path) + { + int length; + SkeletonData* skeletonData; + const char* binary = SPINE_EXTENSION->spineReadFile(path, &length); + if (length == 0 || !binary) + { + setError("Unable to read skeleton file: ", path); + return 0; + } + skeletonData = readSkeletonData((unsigned char*)binary, length); + FREE(binary); + return skeletonData; + } + + void SkeletonBinary::setError(const char* value1, const char* value2) + { + char message[256]; + int length; + strcpy(message, value1); + length = (int)strlen(value1); + if (value2) + { + strncat(message + length, value2, 255 - length); + } + + _error = std::string(message); + } + + char* SkeletonBinary::readString(DataInput* input) + { + int length = readVarint(input, 1); + char* string; + if (length == 0) { + return 0; + } + string = MALLOC(char, length); + memcpy(string, input->cursor, length - 1); + input->cursor += length - 1; + string[length - 1] = '\0'; + return string; + } + + float SkeletonBinary::readFloat(DataInput* input) + { + union + { + int intValue; + float floatValue; + } intToFloat; + + intToFloat.intValue = readInt(input); + + return intToFloat.floatValue; + } + + unsigned char SkeletonBinary::readByte(DataInput* input) + { + return *input->cursor++; + } + + signed char SkeletonBinary::readSByte(DataInput* input) + { + return (signed char)readByte(input); + } + + int SkeletonBinary::readBoolean(DataInput* input) + { + return readByte(input) != 0; + } + + int SkeletonBinary::readInt(DataInput* input) + { + int result = readByte(input); + result <<= 8; + result |= readByte(input); + result <<= 8; + result |= readByte(input); + result <<= 8; + result |= readByte(input); + return result; + } + + int SkeletonBinary::readVarint(DataInput* input, bool optimizePositive) + { + unsigned char b = readByte(input); + int value = b & 0x7F; + if (b & 0x80) + { + b = readByte(input); + value |= (b & 0x7F) << 7; + if (b & 0x80) + { + b = readByte(input); + value |= (b & 0x7F) << 14; + if (b & 0x80) + { + b = readByte(input); + value |= (b & 0x7F) << 21; + if (b & 0x80) value |= (readByte(input) & 0x7F) << 28; + } + } + } + + if (!optimizePositive) + { + value = (((unsigned int)value >> 1) ^ -(value & 1)); + } + + return value; + } } diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonData.cpp b/spine-cpp/spine-cpp/src/spine/SkeletonData.cpp index 3a3367743..4678f658b 100644 --- a/spine-cpp/spine-cpp/src/spine/SkeletonData.cpp +++ b/spine-cpp/spine-cpp/src/spine/SkeletonData.cpp @@ -58,6 +58,21 @@ namespace Spine // Empty } + SkeletonData::~SkeletonData() + { + ContainerUtil::cleanUpVectorOfPointers(_bones); + ContainerUtil::cleanUpVectorOfPointers(_slots); + ContainerUtil::cleanUpVectorOfPointers(_skins); + + delete _defaultSkin; + + ContainerUtil::cleanUpVectorOfPointers(_events); + ContainerUtil::cleanUpVectorOfPointers(_animations); + ContainerUtil::cleanUpVectorOfPointers(_ikConstraints); + ContainerUtil::cleanUpVectorOfPointers(_transformConstraints); + ContainerUtil::cleanUpVectorOfPointers(_pathConstraints); + } + BoneData* SkeletonData::findBone(std::string boneName) { return ContainerUtil::findWithName(_bones, boneName); diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp b/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp index bb4d2ccfe..482b7cbb5 100644 --- a/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp +++ b/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp @@ -28,7 +28,44 @@ * POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ +#include + +#include +#include +#include + +#include +#include + namespace Spine { - // TODO + SkeletonJson::SkeletonJson(Vector& atlasArray) : _attachmentLoader(NEW(AtlasAttachmentLoader)), _scale(1), _ownsLoader(true) + { + new (_attachmentLoader) AtlasAttachmentLoader(atlasArray); + } + + SkeletonJson::SkeletonJson(AttachmentLoader* attachmentLoader) : _attachmentLoader(attachmentLoader), _scale(1), _ownsLoader(false) + { + assert(_attachmentLoader != NULL); + } + + SkeletonJson::~SkeletonJson() + { + ContainerUtil::cleanUpVectorOfPointers(_linkedMeshes); + + if (_ownsLoader) + { + DESTROY(AttachmentLoader, _attachmentLoader); + } + } + + SkeletonData* SkeletonJson::readSkeletonData(const char* json) + { + return NULL; + } + + SkeletonData* SkeletonJson::readSkeletonDataFile(const char* path) + { + return NULL; + } } From b78b0171ec05e7f36176f2847f25bffc45ca9097 Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Sat, 2 Dec 2017 19:06:28 -0500 Subject: [PATCH 60/83] Placing TextureLoader class into its own file. --- spine-cpp/spine-cpp/include/spine/Atlas.h | 7 +-- .../spine-cpp/include/spine/TextureLoader.h | 53 +++++++++++++++++++ spine-cpp/spine-cpp/src/spine/Atlas.cpp | 2 + .../spine-cpp/src/spine/TextureLoader.cpp | 44 +++++++++++++++ 4 files changed, 100 insertions(+), 6 deletions(-) create mode 100644 spine-cpp/spine-cpp/include/spine/TextureLoader.h create mode 100644 spine-cpp/spine-cpp/src/spine/TextureLoader.cpp diff --git a/spine-cpp/spine-cpp/include/spine/Atlas.h b/spine-cpp/spine-cpp/include/spine/Atlas.h index a809c4b25..eb9150cff 100644 --- a/spine-cpp/spine-cpp/include/spine/Atlas.h +++ b/spine-cpp/spine-cpp/include/spine/Atlas.h @@ -97,12 +97,7 @@ namespace Spine Vector pads; }; - class TextureLoader - { - public: - virtual void load(AtlasPage page, std::string path) = 0; - virtual void unload(void* texture) = 0; - }; + class TextureLoader; class Atlas { diff --git a/spine-cpp/spine-cpp/include/spine/TextureLoader.h b/spine-cpp/spine-cpp/include/spine/TextureLoader.h new file mode 100644 index 000000000..82f469945 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/TextureLoader.h @@ -0,0 +1,53 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_TextureLoader_h +#define Spine_TextureLoader_h + +#include + +namespace Spine +{ + class AtlasPage; + + class TextureLoader + { + public: + TextureLoader(); + + virtual ~TextureLoader(); + + virtual void load(AtlasPage& page, std::string path) = 0; + + virtual void unload(void* texture) = 0; + }; +} + +#endif /* Spine_TextureLoader_h */ diff --git a/spine-cpp/spine-cpp/src/spine/Atlas.cpp b/spine-cpp/spine-cpp/src/spine/Atlas.cpp index 369f57a64..506f5042c 100644 --- a/spine-cpp/spine-cpp/src/spine/Atlas.cpp +++ b/spine-cpp/spine-cpp/src/spine/Atlas.cpp @@ -30,6 +30,8 @@ #include +#include + #include #include diff --git a/spine-cpp/spine-cpp/src/spine/TextureLoader.cpp b/spine-cpp/spine-cpp/src/spine/TextureLoader.cpp new file mode 100644 index 000000000..57073cdfe --- /dev/null +++ b/spine-cpp/spine-cpp/src/spine/TextureLoader.cpp @@ -0,0 +1,44 @@ +/****************************************************************************** +* Spine Runtimes Software License v2.5 +* +* Copyright (c) 2013-2016, Esoteric Software +* All rights reserved. +* +* You are granted a perpetual, non-exclusive, non-sublicensable, and +* non-transferable license to use, install, execute, and perform the Spine +* Runtimes software and derivative works solely for personal or internal +* use. Without the written permission of Esoteric Software (see Section 2 of +* the Spine Software License Agreement), you may not (a) modify, translate, +* adapt, or develop new applications using the Spine Runtimes or otherwise +* create derivative works or improvements of the Spine Runtimes or (b) remove, +* delete, alter, or obscure any trademarks or any copyright, trademark, patent, +* or other intellectual property or proprietary rights notices on or in the +* Software, including any copy thereof. Redistributions in binary or source +* form must include this license and terms. +* +* THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*****************************************************************************/ + +#include + +namespace Spine +{ + TextureLoader::TextureLoader() + { + // Empty + } + + TextureLoader::~TextureLoader() + { + // Empty + } +} From 8f28ae1c2d9191fca7665df9e36d2a6027dcbf43 Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Sun, 3 Dec 2017 13:15:57 -0500 Subject: [PATCH 61/83] Almost done with SkeletonBinary --- spine-cpp/spine-cpp/include/spine/Bone.h | 4 +- spine-cpp/spine-cpp/include/spine/BoneData.h | 2 + .../include/spine/ClippingAttachment.h | 5 +- spine-cpp/spine-cpp/include/spine/EventData.h | 2 + .../include/spine/IkConstraintData.h | 2 + .../spine-cpp/include/spine/LinkedMesh.h | 3 + .../spine-cpp/include/spine/MeshAttachment.h | 18 +- .../spine-cpp/include/spine/PathAttachment.h | 3 + .../include/spine/PathConstraintData.h | 3 + .../spine-cpp/include/spine/PointAttachment.h | 3 + .../include/spine/RegionAttachment.h | 6 +- .../spine-cpp/include/spine/SkeletonBinary.h | 28 +- spine-cpp/spine-cpp/include/spine/SlotData.h | 5 +- .../include/spine/TransformConstraintData.h | 3 + .../include/spine/VertexAttachment.h | 4 +- .../spine-cpp/src/spine/MeshAttachment.cpp | 8 +- .../spine-cpp/src/spine/SkeletonBinary.cpp | 1140 ++++++++++++++--- spine-cpp/spine-cpp/src/spine/SlotData.cpp | 1 + 18 files changed, 1024 insertions(+), 216 deletions(-) diff --git a/spine-cpp/spine-cpp/include/spine/Bone.h b/spine-cpp/spine-cpp/include/spine/Bone.h index fafbc8f8a..6b36dd824 100644 --- a/spine-cpp/spine-cpp/include/spine/Bone.h +++ b/spine-cpp/spine-cpp/include/spine/Bone.h @@ -47,8 +47,6 @@ namespace Spine /// constraint or application code modifies the world transform after it was computed from the local transform. class Bone : public Updatable { - RTTI_DECL; - friend class AnimationState; friend class RotateTimeline; @@ -63,6 +61,8 @@ namespace Spine friend class ShearTimeline; friend class TranslateTimeline; + RTTI_DECL; + public: static void setYDown(bool inValue); diff --git a/spine-cpp/spine-cpp/include/spine/BoneData.h b/spine-cpp/spine-cpp/include/spine/BoneData.h index 25530985e..040696871 100644 --- a/spine-cpp/spine-cpp/include/spine/BoneData.h +++ b/spine-cpp/spine-cpp/include/spine/BoneData.h @@ -40,6 +40,8 @@ namespace Spine class BoneData { friend class SkeletonBinary; + friend class SkeletonJson; + friend class AnimationState; friend class RotateTimeline; diff --git a/spine-cpp/spine-cpp/include/spine/ClippingAttachment.h b/spine-cpp/spine-cpp/include/spine/ClippingAttachment.h index f0f913ecc..bbf784429 100644 --- a/spine-cpp/spine-cpp/include/spine/ClippingAttachment.h +++ b/spine-cpp/spine-cpp/include/spine/ClippingAttachment.h @@ -39,10 +39,13 @@ namespace Spine class ClippingAttachment : public VertexAttachment { - RTTI_DECL; + friend class SkeletonBinary; + friend class SkeletonJson; friend class SkeletonClipping; + RTTI_DECL; + public: ClippingAttachment(std::string name); diff --git a/spine-cpp/spine-cpp/include/spine/EventData.h b/spine-cpp/spine-cpp/include/spine/EventData.h index 4f9982d1b..acc4c9fec 100644 --- a/spine-cpp/spine-cpp/include/spine/EventData.h +++ b/spine-cpp/spine-cpp/include/spine/EventData.h @@ -38,6 +38,8 @@ namespace Spine /// Stores the setup pose values for an Event. class EventData { + friend class SkeletonBinary; + friend class SkeletonJson; friend class Event; public: diff --git a/spine-cpp/spine-cpp/include/spine/IkConstraintData.h b/spine-cpp/spine-cpp/include/spine/IkConstraintData.h index 9edc33bf0..5c4732dee 100644 --- a/spine-cpp/spine-cpp/include/spine/IkConstraintData.h +++ b/spine-cpp/spine-cpp/include/spine/IkConstraintData.h @@ -41,6 +41,8 @@ namespace Spine class IkConstraintData { + friend class SkeletonBinary; + friend class SkeletonJson; friend class IkConstraint; friend class Skeleton; friend class IkConstraintTimeline; diff --git a/spine-cpp/spine-cpp/include/spine/LinkedMesh.h b/spine-cpp/spine-cpp/include/spine/LinkedMesh.h index 38482821e..56c7c46bf 100644 --- a/spine-cpp/spine-cpp/include/spine/LinkedMesh.h +++ b/spine-cpp/spine-cpp/include/spine/LinkedMesh.h @@ -39,6 +39,9 @@ namespace Spine class LinkedMesh { + friend class SkeletonBinary; + friend class SkeletonJson; + public: LinkedMesh(MeshAttachment* mesh, std::string skin, int slotIndex, std::string parent); diff --git a/spine-cpp/spine-cpp/include/spine/MeshAttachment.h b/spine-cpp/spine-cpp/include/spine/MeshAttachment.h index c4c25a7c5..edf6c24a6 100644 --- a/spine-cpp/spine-cpp/include/spine/MeshAttachment.h +++ b/spine-cpp/spine-cpp/include/spine/MeshAttachment.h @@ -42,10 +42,12 @@ namespace Spine /// Attachment that displays a texture region using a mesh. class MeshAttachment : public VertexAttachment { - RTTI_DECL; - + friend class SkeletonBinary; + friend class SkeletonJson; friend class AtlasAttachmentLoader; + RTTI_DECL; + public: MeshAttachment(std::string name); @@ -63,8 +65,8 @@ namespace Spine Vector& getUVs(); void setUVs(Vector& inValue); - Vector& getTriangles(); - void setTriangles(Vector& inValue); + Vector& getTriangles(); + void setTriangles(Vector& inValue); float getR(); void setR(float inValue); @@ -123,8 +125,8 @@ namespace Spine void setParentMesh(MeshAttachment* inValue); // Nonessential. - Vector& getEdges(); - void setEdges(Vector& inValue); + Vector& getEdges(); + void setEdges(Vector& inValue); float getWidth(); void setWidth(float inValue); float getHeight(); @@ -135,8 +137,8 @@ namespace Spine MeshAttachment* _parentMesh; Vector _uvs; Vector _regionUVs; - Vector _triangles; - Vector _edges; + Vector _triangles; + Vector _edges; void* _rendererObject; std::string _path; float _regionU; diff --git a/spine-cpp/spine-cpp/include/spine/PathAttachment.h b/spine-cpp/spine-cpp/include/spine/PathAttachment.h index 6f0e53993..aaaa2c68e 100644 --- a/spine-cpp/spine-cpp/include/spine/PathAttachment.h +++ b/spine-cpp/spine-cpp/include/spine/PathAttachment.h @@ -37,6 +37,9 @@ namespace Spine { class PathAttachment : public VertexAttachment { + friend class SkeletonBinary; + friend class SkeletonJson; + RTTI_DECL; public: diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraintData.h b/spine-cpp/spine-cpp/include/spine/PathConstraintData.h index 8a41880f2..8736a1d32 100644 --- a/spine-cpp/spine-cpp/include/spine/PathConstraintData.h +++ b/spine-cpp/spine-cpp/include/spine/PathConstraintData.h @@ -45,6 +45,9 @@ namespace Spine class PathConstraintData { + friend class SkeletonBinary; + friend class SkeletonJson; + friend class PathConstraint; friend class Skeleton; friend class PathConstraintMixTimeline; diff --git a/spine-cpp/spine-cpp/include/spine/PointAttachment.h b/spine-cpp/spine-cpp/include/spine/PointAttachment.h index 6738021a7..cdb13fdd0 100644 --- a/spine-cpp/spine-cpp/include/spine/PointAttachment.h +++ b/spine-cpp/spine-cpp/include/spine/PointAttachment.h @@ -46,6 +46,9 @@ namespace Spine /// class PointAttachment : public Attachment { + friend class SkeletonBinary; + friend class SkeletonJson; + RTTI_DECL; public: diff --git a/spine-cpp/spine-cpp/include/spine/RegionAttachment.h b/spine-cpp/spine-cpp/include/spine/RegionAttachment.h index 3128fb8f6..d48f0c976 100644 --- a/spine-cpp/spine-cpp/include/spine/RegionAttachment.h +++ b/spine-cpp/spine-cpp/include/spine/RegionAttachment.h @@ -46,10 +46,12 @@ namespace Spine /// Attachment that displays a texture region. class RegionAttachment : public Attachment { - RTTI_DECL; - + friend class SkeletonBinary; + friend class SkeletonJson; friend class AtlasAttachmentLoader; + RTTI_DECL; + public: RegionAttachment(std::string name); diff --git a/spine-cpp/spine-cpp/include/spine/SkeletonBinary.h b/spine-cpp/spine-cpp/include/spine/SkeletonBinary.h index 29d727ac8..1d29d3af6 100644 --- a/spine-cpp/spine-cpp/include/spine/SkeletonBinary.h +++ b/spine-cpp/spine-cpp/include/spine/SkeletonBinary.h @@ -42,6 +42,10 @@ namespace Spine class Atlas; class AttachmentLoader; class LinkedMesh; + class Skin; + class Attachment; + class VertexAttachment; + class Animation; class SkeletonBinary { @@ -101,15 +105,29 @@ namespace Spine float readFloat(DataInput* input); - static unsigned char readByte(DataInput* input); + unsigned char readByte(DataInput* input); - static signed char readSByte(DataInput* input); + signed char readSByte(DataInput* input); - static int readBoolean(DataInput* input); + int readBoolean(DataInput* input); - static int readInt(DataInput* input); + int readInt(DataInput* input); - static int readVarint(DataInput* input, bool optimizePositive); + void readColor(DataInput* input, float *r, float *g, float *b, float *a); + + int readVarint(DataInput* input, bool optimizePositive); + + Skin* readSkin(DataInput* input, const char* skinName, SkeletonData* skeletonData, bool nonessential); + + Attachment* readAttachment(DataInput* input, Skin* skin, int slotIndex, const char* attachmentName, SkeletonData* skeletonData, bool nonessential); + + void readVertices(DataInput* input, VertexAttachment* attachment, int vertexCount); + + Vector readFloatArray(DataInput *input, int n, float scale); + + Vector readShortArray(DataInput *input); + + Animation* readAnimation(const char* name, DataInput* input, SkeletonData *skeletonData); }; } diff --git a/spine-cpp/spine-cpp/include/spine/SlotData.h b/spine-cpp/spine-cpp/include/spine/SlotData.h index 02dbaac4a..45eeb834d 100644 --- a/spine-cpp/spine-cpp/include/spine/SlotData.h +++ b/spine-cpp/spine-cpp/include/spine/SlotData.h @@ -41,6 +41,9 @@ namespace Spine class SlotData { + friend class SkeletonBinary; + friend class SkeletonJson; + friend class AttachmentTimeline; friend class ColorTimeline; friend class DeformTimeline; @@ -95,7 +98,7 @@ namespace Spine const std::string _name; BoneData& _boneData; float _r, _g, _b, _a; - float _r2, _g2, _b2; + float _r2, _g2, _b2, _a2; bool _hasSecondColor; std::string _attachmentName; BlendMode _blendMode; diff --git a/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h b/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h index 603175d4f..aa8e737d6 100644 --- a/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h +++ b/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h @@ -41,6 +41,9 @@ namespace Spine class TransformConstraintData { + friend class SkeletonBinary; + friend class SkeletonJson; + friend class TransformConstraint; friend class Skeleton; friend class TransformConstraintTimeline; diff --git a/spine-cpp/spine-cpp/include/spine/VertexAttachment.h b/spine-cpp/spine-cpp/include/spine/VertexAttachment.h index 33a6fed53..3529c5cf3 100644 --- a/spine-cpp/spine-cpp/include/spine/VertexAttachment.h +++ b/spine-cpp/spine-cpp/include/spine/VertexAttachment.h @@ -42,10 +42,10 @@ namespace Spine /// An attachment with vertices that are transformed by one or more bones and can be deformed by a slot's vertices. class VertexAttachment : public Attachment { - RTTI_DECL; - friend class DeformTimeline; + RTTI_DECL; + public: VertexAttachment(std::string name); diff --git a/spine-cpp/spine-cpp/src/spine/MeshAttachment.cpp b/spine-cpp/spine-cpp/src/spine/MeshAttachment.cpp index 6d928a6c3..5a6de205c 100644 --- a/spine-cpp/spine-cpp/src/spine/MeshAttachment.cpp +++ b/spine-cpp/spine-cpp/src/spine/MeshAttachment.cpp @@ -123,12 +123,12 @@ namespace Spine _uvs = inValue; } - Vector& MeshAttachment::getTriangles() + Vector& MeshAttachment::getTriangles() { return _triangles; } - void MeshAttachment::setTriangles(Vector& inValue) + void MeshAttachment::setTriangles(Vector& inValue) { _triangles = inValue; } @@ -335,12 +335,12 @@ namespace Spine } } - Vector& MeshAttachment::getEdges() + Vector& MeshAttachment::getEdges() { return _edges; } - void MeshAttachment::setEdges(Vector& inValue) + void MeshAttachment::setEdges(Vector& inValue) { _edges = inValue; } diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp b/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp index ed84c76bc..918904e45 100644 --- a/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp +++ b/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp @@ -34,10 +34,29 @@ #include #include #include +#include +#include +#include +#include #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include namespace Spine { @@ -170,199 +189,223 @@ namespace Spine readInt(input); } - skeletonData->_bones.push_back(data); + skeletonData->_bones[i] = data; } /* Slots. */ -// skeletonData->slotsCount = readVarint(input, 1); -// skeletonData->slots = MALLOC(spSlotData*, skeletonData->slotsCount); -// for (i = 0; i < skeletonData->slotsCount; ++i) -// { -// int r, g, b, a; -// const char* slotName = readString(input); -// spBoneData* boneData = skeletonData->bones[readVarint(input, 1)]; -// /* TODO Avoid copying of slotName */ -// spSlotData* slotData = spSlotData_create(i, slotName, boneData); -// FREE(slotName); -// readColor(input, &slotData->color.r, &slotData->color.g, &slotData->color.b, &slotData->color.a); -// r = readByte(input); -// g = readByte(input); -// b = readByte(input); -// a = readByte(input); -// if (!(r == 0xff && g == 0xff && b == 0xff && a == 0xff)) -// { -// slotData->darkColor = spColor_create(); -// spColor_setFromFloats(slotData->darkColor, r / 255.0f, g / 255.0f, b / 255.0f, 1); -// } -// slotData->attachmentName = readString(input); -// slotData->blendMode = (spBlendMode)readVarint(input, 1); -// skeletonData->slots[i] = slotData; -// } -// -// /* IK constraints. */ -// skeletonData->ikConstraintsCount = readVarint(input, 1); -// skeletonData->ikConstraints = MALLOC(spIkConstraintData*, skeletonData->ikConstraintsCount); -// for (i = 0; i < skeletonData->ikConstraintsCount; ++i) -// { -// const char* name = readString(input); -// /* TODO Avoid copying of name */ -// spIkConstraintData* data = spIkConstraintData_create(name); -// data->order = readVarint(input, 1); -// FREE(name); -// data->bonesCount = readVarint(input, 1); -// data->bones = MALLOC(spBoneData*, data->bonesCount); -// for (ii = 0; ii < data->bonesCount; ++ii) -// data->bones[ii] = skeletonData->bones[readVarint(input, 1)]; -// data->target = skeletonData->bones[readVarint(input, 1)]; -// data->mix = readFloat(input); -// data->bendDirection = readSByte(input); -// skeletonData->ikConstraints[i] = data; -// } -// -// /* Transform constraints. */ -// skeletonData->transformConstraintsCount = readVarint(input, 1); -// skeletonData->transformConstraints = MALLOC(spTransformConstraintData*, skeletonData->transformConstraintsCount); -// for (i = 0; i < skeletonData->transformConstraintsCount; ++i) -// { -// const char* name = readString(input); -// /* TODO Avoid copying of name */ -// spTransformConstraintData* data = spTransformConstraintData_create(name); -// data->order = readVarint(input, 1); -// FREE(name); -// data->bonesCount = readVarint(input, 1); -// CONST_CAST(spBoneData**, data->bones) = MALLOC(spBoneData*, data->bonesCount); -// for (ii = 0; ii < data->bonesCount; ++ii) -// { -// data->bones[ii] = skeletonData->bones[readVarint(input, 1)]; -// } -// data->target = skeletonData->bones[readVarint(input, 1)]; -// data->local = readBoolean(input); -// data->relative = readBoolean(input); -// data->offsetRotation = readFloat(input); -// data->offsetX = readFloat(input) * _scale; -// data->offsetY = readFloat(input) * _scale; -// data->offsetScaleX = readFloat(input); -// data->offsetScaleY = readFloat(input); -// data->offsetShearY = readFloat(input); -// data->rotateMix = readFloat(input); -// data->translateMix = readFloat(input); -// data->scaleMix = readFloat(input); -// data->shearMix = readFloat(input); -// skeletonData->transformConstraints[i] = data; -// } -// -// /* Path constraints */ -// skeletonData->pathConstraintsCount = readVarint(input, 1); -// skeletonData->pathConstraints = MALLOC(spPathConstraintData*, skeletonData->pathConstraintsCount); -// for (i = 0; i < skeletonData->pathConstraintsCount; ++i) -// { -// const char* name = readString(input); -// /* TODO Avoid copying of name */ -// spPathConstraintData* data = spPathConstraintData_create(name); -// data->order = readVarint(input, 1); -// FREE(name); -// data->bonesCount = readVarint(input, 1); -// CONST_CAST(spBoneData**, data->bones) = MALLOC(spBoneData*, data->bonesCount); -// for (ii = 0; ii < data->bonesCount; ++ii) -// { -// data->bones[ii] = skeletonData->bones[readVarint(input, 1)]; -// } -// data->target = skeletonData->slots[readVarint(input, 1)]; -// data->positionMode = (spPositionMode)readVarint(input, 1); -// data->spacingMode = (spSpacingMode)readVarint(input, 1); -// data->rotateMode = (spRotateMode)readVarint(input, 1); -// data->offsetRotation = readFloat(input); -// data->position = readFloat(input); -// if (data->positionMode == SP_POSITION_MODE_FIXED) data->position *= _scale; -// data->spacing = readFloat(input); -// if (data->spacingMode == SP_SPACING_MODE_LENGTH || data->spacingMode == SP_SPACING_MODE_FIXED) data->spacing *= _scale; -// data->rotateMix = readFloat(input); -// data->translateMix = readFloat(input); -// skeletonData->pathConstraints[i] = data; -// } -// -// /* Default skin. */ -// skeletonData->defaultSkin = spSkeletonBinary_readSkin(self, input, "default", skeletonData, nonessential); -// skeletonData->skinsCount = readVarint(input, 1); -// -// if (skeletonData->defaultSkin) -// { -// ++skeletonData->skinsCount; -// } -// -// skeletonData->skins = MALLOC(spSkin*, skeletonData->skinsCount); -// -// if (skeletonData->defaultSkin) -// { -// skeletonData->skins[0] = skeletonData->defaultSkin; -// } -// -// /* Skins. */ -// for (i = skeletonData->defaultSkin ? 1 : 0; i < skeletonData->skinsCount; ++i) -// { -// const char* skinName = readString(input); -// /* TODO Avoid copying of skinName */ -// skeletonData->skins[i] = spSkeletonBinary_readSkin(self, input, skinName, skeletonData, nonessential); -// FREE(skinName); -// } -// -// /* Linked meshes. */ -// for (i = 0; i < internal->linkedMeshCount; ++i) -// { -// _spLinkedMesh* linkedMesh = internal->linkedMeshes + i; -// spSkin* skin = !linkedMesh->skin ? skeletonData->defaultSkin : spSkeletonData_findSkin(skeletonData, linkedMesh->skin); -// spAttachment* parent; -// if (!skin) -// { -// FREE(input); -// spSkeletonData_dispose(skeletonData); -// _spSkeletonBinary_setError(self, "Skin not found: ", linkedMesh->skin); -// return 0; -// } -// parent = spSkin_getAttachment(skin, linkedMesh->slotIndex, linkedMesh->parent); -// if (!parent) -// { -// FREE(input); -// spSkeletonData_dispose(skeletonData); -// _spSkeletonBinary_setError(self, "Parent mesh not found: ", linkedMesh->parent); -// return 0; -// } -// spMeshAttachment_setParentMesh(linkedMesh->mesh, SUB_CAST(spMeshAttachment, parent)); -// spMeshAttachment_updateUVs(linkedMesh->mesh); -// spAttachmentLoader_configureAttachment(self->attachmentLoader, SUPER(SUPER(linkedMesh->mesh))); -// } -// -// /* Events. */ -// skeletonData->eventsCount = readVarint(input, 1); -// skeletonData->events = MALLOC(spEventData*, skeletonData->eventsCount); -// for (i = 0; i < skeletonData->eventsCount; ++i) -// { -// const char* name = readString(input); -// /* TODO Avoid copying of skinName */ -// spEventData* eventData = spEventData_create(name); -// FREE(name); -// eventData->intValue = readVarint(input, 0); -// eventData->floatValue = readFloat(input); -// eventData->stringValue = readString(input); -// skeletonData->events[i] = eventData; -// } -// -// /* Animations. */ -// skeletonData->animationsCount = readVarint(input, 1); -// skeletonData->animations = MALLOC(spAnimation*, skeletonData->animationsCount); -// for (i = 0; i < skeletonData->animationsCount; ++i) -// { -// const char* name = readString(input); -// spAnimation* animation = _spSkeletonBinary_readAnimation(self, name, input, skeletonData); -// FREE(name); -// if (!animation) -// { -// FREE(input); -// spSkeletonData_dispose(skeletonData); -// return 0; -// } -// skeletonData->animations[i] = animation; -// } + int slotsCount = readVarint(input, 1); + skeletonData->_slots.reserve(slotsCount); + for (i = 0; i < slotsCount; ++i) + { + int r, g, b, a; + const char* slotName = readString(input); + BoneData* boneData = skeletonData->_bones[readVarint(input, 1)]; + + SlotData* slotData = NEW(SlotData); + new (slotData) SlotData(i, std::string(slotName), *boneData); + + FREE(slotName); + readColor(input, &slotData->_r, &slotData->_g, &slotData->_b, &slotData->_a); + r = readByte(input); + g = readByte(input); + b = readByte(input); + a = readByte(input); + if (!(r == 0xff && g == 0xff && b == 0xff && a == 0xff)) + { + slotData->_r2 = r / 255.0f; + slotData->_g2 = g / 255.0f; + slotData->_b2 = b / 255.0f; + } + char* slotData_attachmentName = readString(input); + slotData->_attachmentName = std::string(slotData_attachmentName); + FREE(slotData_attachmentName); + slotData->_blendMode = static_cast(readVarint(input, 1)); + + skeletonData->_slots[i] = slotData; + } + + /* IK constraints. */ + int ikConstraintsCount = readVarint(input, 1); + skeletonData->_ikConstraints.reserve(ikConstraintsCount); + for (i = 0; i < ikConstraintsCount; ++i) + { + const char* name = readString(input); + + IkConstraintData* data = NEW(IkConstraintData); + new (data) IkConstraintData(std::string(name)); + + data->_order = readVarint(input, 1); + + FREE(name); + int bonesCount = readVarint(input, 1); + data->_bones.reserve(bonesCount); + for (ii = 0; ii < bonesCount; ++ii) + { + data->_bones[ii] = skeletonData->_bones[readVarint(input, 1)]; + } + data->_target = skeletonData->_bones[readVarint(input, 1)]; + data->_mix = readFloat(input); + data->_bendDirection = readSByte(input); + + skeletonData->_ikConstraints[i] = data; + } + + /* Transform constraints. */ + int transformConstraintsCount = readVarint(input, 1); + skeletonData->_transformConstraints.reserve(transformConstraintsCount); + for (i = 0; i < transformConstraintsCount; ++i) + { + const char* name = readString(input); + + TransformConstraintData* data = NEW(TransformConstraintData); + new (data) TransformConstraintData(std::string(name)); + + data->_order = readVarint(input, 1); + FREE(name); + int bonesCount = readVarint(input, 1); + data->_bones.reserve(bonesCount); + for (ii = 0; ii < bonesCount; ++ii) + { + data->_bones[ii] = skeletonData->_bones[readVarint(input, 1)]; + } + data->_target = skeletonData->_bones[readVarint(input, 1)]; + data->_local = readBoolean(input); + data->_relative = readBoolean(input); + data->_offsetRotation = readFloat(input); + data->_offsetX = readFloat(input) * _scale; + data->_offsetY = readFloat(input) * _scale; + data->_offsetScaleX = readFloat(input); + data->_offsetScaleY = readFloat(input); + data->_offsetShearY = readFloat(input); + data->_rotateMix = readFloat(input); + data->_translateMix = readFloat(input); + data->_scaleMix = readFloat(input); + data->_shearMix = readFloat(input); + + skeletonData->_transformConstraints[i] = data; + } + + /* Path constraints */ + int pathConstraintsCount = readVarint(input, 1); + skeletonData->_pathConstraints.reserve(pathConstraintsCount); + for (i = 0; i < pathConstraintsCount; ++i) + { + const char* name = readString(input); + + PathConstraintData* data = NEW(PathConstraintData); + new (data) PathConstraintData(std::string(name)); + + data->_order = readVarint(input, 1); + FREE(name); + + int bonesCount = readVarint(input, 1); + data->_bones.reserve(bonesCount); + for (ii = 0; ii < bonesCount; ++ii) + { + data->_bones[ii] = skeletonData->_bones[readVarint(input, 1)]; + } + data->_target = skeletonData->_slots[readVarint(input, 1)]; + data->_positionMode = static_cast(readVarint(input, 1)); + data->_spacingMode = static_cast(readVarint(input, 1)); + data->_rotateMode = static_cast(readVarint(input, 1)); + data->_offsetRotation = readFloat(input); + data->_position = readFloat(input); + if (data->_positionMode == PositionMode_Fixed) + { + data->_position *= _scale; + } + + data->_spacing = readFloat(input); + if (data->_spacingMode == SpacingMode_Length || data->_spacingMode == SpacingMode_Fixed) + { + data->_spacing *= _scale; + } + data->_rotateMix = readFloat(input); + data->_translateMix = readFloat(input); + + skeletonData->_pathConstraints[i] = data; + } + + /* Default skin. */ + skeletonData->_defaultSkin = readSkin(input, "default", skeletonData, nonessential); + int skinsCount = readVarint(input, 1); + + if (skeletonData->_defaultSkin) + { + ++skinsCount; + } + + skeletonData->_skins.reserve(skinsCount); + + if (skeletonData->_defaultSkin) + { + skeletonData->_skins[0] = skeletonData->_defaultSkin; + } + + /* Skins. */ + for (i = skeletonData->_defaultSkin ? 1 : 0; i < skeletonData->_skins.size(); ++i) + { + const char* skinName = readString(input); + skeletonData->_skins[i] = readSkin(input, skinName, skeletonData, nonessential); + FREE(skinName); + } + + /* Linked meshes. */ + for (int i = 0, n = static_cast(_linkedMeshes.size()); i < n; i++) + { + LinkedMesh* linkedMesh = _linkedMeshes[i]; + Skin* skin = linkedMesh->_skin.length() == 0 ? skeletonData->getDefaultSkin() : skeletonData->findSkin(linkedMesh->_skin); + if (skin == NULL) + { + FREE(input); + DESTROY(SkeletonData, skeletonData); + setError("Skin not found: ", linkedMesh->_skin.c_str()); + return NULL; + } + Attachment* parent = skin->getAttachment(linkedMesh->_slotIndex, linkedMesh->_parent); + if (parent == NULL) + { + FREE(input); + DESTROY(SkeletonData, skeletonData); + setError("Parent mesh not found: ", linkedMesh->_parent.c_str()); + return NULL; + } + linkedMesh->_mesh->_parentMesh = static_cast(parent); + linkedMesh->_mesh->updateUVs(); + } + _linkedMeshes.clear(); + + /* Events. */ + int eventsCount = readVarint(input, 1); + skeletonData->_events.reserve(eventsCount); + for (i = 0; i < eventsCount; ++i) + { + const char* name = readString(input); + EventData* eventData = NEW(EventData); + new (eventData) EventData(std::string(name)); + FREE(name); + eventData->_intValue = readVarint(input, 0); + eventData->_floatValue = readFloat(input); + eventData->_stringValue = readString(input); + skeletonData->_events[i] = eventData; + } + + /* Animations. */ + int animationsCount = readVarint(input, 1); + skeletonData->_animations.reserve(animationsCount); + for (i = 0; i < animationsCount; ++i) + { + const char* name = readString(input); + Animation* animation = readAnimation(name, input, skeletonData); + FREE(name); + if (!animation) + { + FREE(input); + DESTROY(SkeletonData, skeletonData); + return NULL; + } + skeletonData->_animations[i] = animation; + } FREE(input); @@ -403,7 +446,7 @@ namespace Spine int length = readVarint(input, 1); char* string; if (length == 0) { - return 0; + return NULL; } string = MALLOC(char, length); memcpy(string, input->cursor, length - 1); @@ -452,6 +495,14 @@ namespace Spine return result; } + void SkeletonBinary::readColor(DataInput* input, float *r, float *g, float *b, float *a) + { + *r = readByte(input) / 255.0f; + *g = readByte(input) / 255.0f; + *b = readByte(input) / 255.0f; + *a = readByte(input) / 255.0f; + } + int SkeletonBinary::readVarint(DataInput* input, bool optimizePositive) { unsigned char b = readByte(input); @@ -480,4 +531,711 @@ namespace Spine return value; } + + Skin* SkeletonBinary::readSkin(DataInput* input, const char* skinName, SkeletonData* skeletonData, bool nonessential) + { + Skin* skin = NULL; + int slotCount = readVarint(input, 1); + int i, ii, nn; + if (slotCount == 0) + { + return 0; + } + + skin = NEW(Skin); + new (skin) Skin(std::string(skinName)); + + for (i = 0; i < slotCount; ++i) + { + int slotIndex = readVarint(input, 1); + for (ii = 0, nn = readVarint(input, 1); ii < nn; ++ii) + { + const char* name = readString(input); + Attachment* attachment = readAttachment(input, skin, slotIndex, name, skeletonData, nonessential); + if (attachment) + { + skin->addAttachment(slotIndex, std::string(name), attachment); + } + FREE(name); + } + } + + return skin; + } + + Attachment* SkeletonBinary::readAttachment(DataInput* input, Skin* skin, int slotIndex, const char* attachmentName, SkeletonData* skeletonData, bool nonessential) + { + int i; + AttachmentType type; + const char* name = readString(input); + int freeName = name != 0; + if (!name) + { + freeName = 0; + name = attachmentName; + } + + type = static_cast(readByte(input)); + + switch (type) + { + case AttachmentType_Region: + { + const char* path = readString(input); + RegionAttachment* region; + if (!path) + { + path = name; + } + region = _attachmentLoader->newRegionAttachment(*skin, std::string(name), std::string(path)); + region->_path = std::string(path); + region->_rotation = readFloat(input); + region->_x = readFloat(input) * _scale; + region->_y = readFloat(input) * _scale; + region->_scaleX = readFloat(input); + region->_scaleY = readFloat(input); + region->_width = readFloat(input) * _scale; + region->_height = readFloat(input) * _scale; + readColor(input, ®ion->_r, ®ion->_g, ®ion->_b, ®ion->_a); + region->updateOffset(); + + if (freeName) + { + FREE(name); + } + + return region; + } + case AttachmentType_Boundingbox: + { + int vertexCount = readVarint(input, 1); + BoundingBoxAttachment* box = _attachmentLoader->newBoundingBoxAttachment(*skin, std::string(name)); + readVertices(input, static_cast(box), vertexCount); + if (nonessential) + { + /* Skip color. */ + readInt(input); + } + if (freeName) + { + FREE(name); + } + + return box; + } + case AttachmentType_Mesh: + { + int vertexCount; + MeshAttachment* mesh; + const char* path = readString(input); + if (!path) + { + path = name; + } + mesh = _attachmentLoader->newMeshAttachment(*skin, std::string(name), std::string(path)); + mesh->_path = std::string(path); + readColor(input, &mesh->_r, &mesh->_g, &mesh->_b, &mesh->_a); + vertexCount = readVarint(input, 1); + Vector float_array = readFloatArray(input, vertexCount << 1, 1); + mesh->setRegionUVs(float_array); + Vector triangles = readShortArray(input); + mesh->setTriangles(triangles); + readVertices(input, static_cast(mesh), vertexCount); + mesh->updateUVs(); + mesh->_hullLength = readVarint(input, 1) << 1; + if (nonessential) + { + Vector edges = readShortArray(input); + mesh->setEdges(edges); + mesh->_width = readFloat(input) * _scale; + mesh->_height = readFloat(input) * _scale; + } + else + { + mesh->_width = 0; + mesh->_height = 0; + } + + if (freeName) + { + FREE(name); + } + + return mesh; + } + case AttachmentType_Linkedmesh: + { + const char* skinName; + const char* parent; + MeshAttachment* mesh; + const char* path = readString(input); + if (!path) + { + path = name; + } + + mesh = _attachmentLoader->newMeshAttachment(*skin, std::string(name), std::string(path)); + mesh->_path = path; + readColor(input, &mesh->_r, &mesh->_g, &mesh->_b, &mesh->_a); + skinName = readString(input); + parent = readString(input); + mesh->_inheritDeform = readBoolean(input); + if (nonessential) + { + mesh->_width = readFloat(input) * _scale; + mesh->_height = readFloat(input) * _scale; + } + + LinkedMesh* linkedMesh = NEW(LinkedMesh); + new (linkedMesh) LinkedMesh(mesh, std::string(skinName), slotIndex, std::string(parent)); + _linkedMeshes.push_back(linkedMesh); + + if (freeName) + { + FREE(name); + } + + return mesh; + } + case AttachmentType_Path: + { + PathAttachment* path = _attachmentLoader->newPathAttachment(*skin, std::string(name)); + int vertexCount = 0; + path->_closed = readBoolean(input); + path->_constantSpeed = readBoolean(input); + vertexCount = readVarint(input, 1); + readVertices(input, static_cast(path), vertexCount); + int lengthsLength = vertexCount / 3; + path->_lengths.reserve(lengthsLength); + for (i = 0; i < lengthsLength; ++i) + { + path->_lengths[i] = readFloat(input) * _scale; + } + + if (nonessential) + { + /* Skip color. */ + readInt(input); + } + + if (freeName) + { + FREE(name); + } + + return path; + } + case AttachmentType_Point: + { + PointAttachment* point = _attachmentLoader->newPointAttachment(*skin, std::string(name)); + point->_rotation = readFloat(input); + point->_x = readFloat(input) * _scale; + point->_y = readFloat(input) * _scale; + + if (nonessential) + { + /* Skip color. */ + readInt(input); + } + + return point; + } + case AttachmentType_Clipping: + { + int endSlotIndex = readVarint(input, 1); + int vertexCount = readVarint(input, 1); + ClippingAttachment* clip = _attachmentLoader->newClippingAttachment(*skin, name); + readVertices(input, static_cast(clip), vertexCount); + + if (nonessential) + { + /* Skip color. */ + readInt(input); + } + + clip->_endSlot = skeletonData->_slots[endSlotIndex]; + + if (freeName) + { + FREE(name); + } + + return clip; + } + } + + if (freeName) + { + FREE(name); + } + + return NULL; + } + + void SkeletonBinary::readVertices(DataInput* input, VertexAttachment* attachment, int vertexCount) + { + float scale = _scale; + int verticesLength = vertexCount << 1; + + if (!readBoolean(input)) + { + attachment->setVertices(readFloatArray(input, verticesLength, scale)); + return; + } + + Vertices vertices; + vertices._bones.reserve(verticesLength * 3); + vertices._vertices.reserve(verticesLength * 3 * 3); + + for (int i = 0; i < vertexCount; ++i) + { + int boneCount = readVarint(input, true); + vertices._bones.push_back(boneCount); + for (int ii = 0; ii < boneCount; ++ii) + { + vertices._bones.push_back(readVarint(input, true)); + vertices._vertices.push_back(readFloat(input) * scale); + vertices._vertices.push_back(readFloat(input) * scale); + vertices._vertices.push_back(readFloat(input)); + } + } + + attachment->setVertices(vertices._vertices); + attachment->setBones(vertices._bones); + } + + Vector SkeletonBinary::readFloatArray(DataInput *input, int n, float scale) + { + Vector array; + array.reserve(n); + + int i; + if (scale == 1) + { + for (i = 0; i < n; ++i) + { + array[i] = readFloat(input); + } + } + else + { + for (i = 0; i < n; ++i) + { + array[i] = readFloat(input) * scale; + } + } + + return array; + } + + Vector SkeletonBinary::readShortArray(DataInput *input) + { + int n = readVarint(input, 1); + + Vector array; + array.reserve(n); + + int i; + for (i = 0; i < n; ++i) + { + array[i] = readByte(input) << 8; + array[i] |= readByte(input); + } + + return array; + } + + Animation* SkeletonBinary::readAnimation(const char* name, DataInput* input, SkeletonData *skeletonData) + { +// var timelines = new ExposedList(); +// float scale = Scale; +// float duration = 0; +// +// // Slot timelines. +// for (int i = 0, n = ReadVarint(input, true); i < n; i++) +// { +// int slotIndex = ReadVarint(input, true); +// for (int ii = 0, nn = ReadVarint(input, true); ii < nn; ii++) +// { +// int timelineType = input.ReadByte(); +// int frameCount = ReadVarint(input, true); +// switch (timelineType) +// { +// case SLOT_ATTACHMENT: +// { +// AttachmentTimeline timeline = new AttachmentTimeline(frameCount); +// timeline.slotIndex = slotIndex; +// for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) +// { +// timeline.SetFrame(frameIndex, ReadFloat(input), ReadString(input)); +// } +// timelines.Add(timeline); +// duration = Math.Max(duration, timeline.frames[frameCount - 1]); +// break; +// } +// case SLOT_COLOR: +// { +// ColorTimeline timeline = new ColorTimeline(frameCount); +// timeline.slotIndex = slotIndex; +// for (int frameIndex = 0; frameIndex < frameCount; frameIndex++)\ +// { +// float time = ReadFloat(input); +// int color = ReadInt(input); +// float r = ((color & 0xff000000) >> 24) / 255f; +// float g = ((color & 0x00ff0000) >> 16) / 255f; +// float b = ((color & 0x0000ff00) >> 8) / 255f; +// float a = ((color & 0x000000ff)) / 255f; +// timeline.SetFrame(frameIndex, time, r, g, b, a); +// if (frameIndex < frameCount - 1) +// { +// ReadCurve(input, frameIndex, timeline); +// } +// } +// timelines.Add(timeline); +// duration = Math.Max(duration, timeline.frames[(timeline.FrameCount - 1) * ColorTimeline.ENTRIES]); +// break; +// } +// case SLOT_TWO_COLOR: +// { +// TwoColorTimeline timeline = new TwoColorTimeline(frameCount); +// timeline.slotIndex = slotIndex; +// for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) +// { +// float time = ReadFloat(input); +// int color = ReadInt(input); +// float r = ((color & 0xff000000) >> 24) / 255f; +// float g = ((color & 0x00ff0000) >> 16) / 255f; +// float b = ((color & 0x0000ff00) >> 8) / 255f; +// float a = ((color & 0x000000ff)) / 255f; +// int color2 = ReadInt(input); // 0x00rrggbb +// float r2 = ((color2 & 0x00ff0000) >> 16) / 255f; +// float g2 = ((color2 & 0x0000ff00) >> 8) / 255f; +// float b2 = ((color2 & 0x000000ff)) / 255f; +// +// timeline.SetFrame(frameIndex, time, r, g, b, a, r2, g2, b2); +// if (frameIndex < frameCount - 1) +// { +// ReadCurve(input, frameIndex, timeline); +// } +// } +// timelines.Add(timeline); +// duration = Math.Max(duration, timeline.frames[(timeline.FrameCount - 1) * TwoColorTimeline.ENTRIES]); +// break; +// } +// } +// } +// } +// +// // Bone timelines. +// for (int i = 0, n = ReadVarint(input, true); i < n; i++) +// { +// int boneIndex = ReadVarint(input, true); +// for (int ii = 0, nn = ReadVarint(input, true); ii < nn; ii++) +// { +// int timelineType = input.ReadByte(); +// int frameCount = ReadVarint(input, true); +// switch (timelineType) +// { +// case BONE_ROTATE: +// { +// RotateTimeline timeline = new RotateTimeline(frameCount); +// timeline.boneIndex = boneIndex; +// for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) +// { +// timeline.SetFrame(frameIndex, ReadFloat(input), ReadFloat(input)); +// if (frameIndex < frameCount - 1) +// { +// ReadCurve(input, frameIndex, timeline); +// } +// } +// timelines.Add(timeline); +// duration = Math.Max(duration, timeline.frames[(frameCount - 1) * RotateTimeline.ENTRIES]); +// break; +// } +// case BONE_TRANSLATE: +// case BONE_SCALE: +// case BONE_SHEAR: +// { +// TranslateTimeline timeline; +// float timelineScale = 1; +// if (timelineType == BONE_SCALE) +// { +// timeline = new ScaleTimeline(frameCount); +// } +// else if (timelineType == BONE_SHEAR) +// { +// timeline = new ShearTimeline(frameCount); +// } +// else +// { +// timeline = new TranslateTimeline(frameCount); +// timelineScale = scale; +// } +// timeline.boneIndex = boneIndex; +// for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) +// { +// timeline.SetFrame(frameIndex, ReadFloat(input), ReadFloat(input) * timelineScale, ReadFloat(input) +// * timelineScale); +// if (frameIndex < frameCount - 1) +// { +// ReadCurve(input, frameIndex, timeline); +// } +// } +// timelines.Add(timeline); +// duration = Math.Max(duration, timeline.frames[(frameCount - 1) * TranslateTimeline.ENTRIES]); +// break; +// } +// } +// } +// } +// +// // IK timelines. +// for (int i = 0, n = ReadVarint(input, true); i < n; i++) +// { +// int index = ReadVarint(input, true); +// int frameCount = ReadVarint(input, true); +// IkConstraintTimeline timeline = new IkConstraintTimeline(frameCount); +// timeline.ikConstraintIndex = index; +// for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) +// { +// timeline.SetFrame(frameIndex, ReadFloat(input), ReadFloat(input), ReadSByte(input)); +// if (frameIndex < frameCount - 1) +// { +// ReadCurve(input, frameIndex, timeline); +// } +// } +// timelines.Add(timeline); +// duration = Math.Max(duration, timeline.frames[(frameCount - 1) * IkConstraintTimeline.ENTRIES]); +// } +// +// // Transform constraint timelines. +// for (int i = 0, n = ReadVarint(input, true); i < n; i++) +// { +// int index = ReadVarint(input, true); +// int frameCount = ReadVarint(input, true); +// TransformConstraintTimeline timeline = new TransformConstraintTimeline(frameCount); +// timeline.transformConstraintIndex = index; +// for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) +// { +// timeline.SetFrame(frameIndex, ReadFloat(input), ReadFloat(input), ReadFloat(input), ReadFloat(input), ReadFloat(input)); +// if (frameIndex < frameCount - 1) +// { +// ReadCurve(input, frameIndex, timeline); +// } +// } +// timelines.Add(timeline); +// duration = Math.Max(duration, timeline.frames[(frameCount - 1) * TransformConstraintTimeline.ENTRIES]); +// } +// +// // Path constraint timelines. +// for (int i = 0, n = ReadVarint(input, true); i < n; i++) +// { +// int index = ReadVarint(input, true); +// PathConstraintData data = skeletonData.pathConstraints.Items[index]; +// for (int ii = 0, nn = ReadVarint(input, true); ii < nn; ii++) +// { +// int timelineType = ReadSByte(input); +// int frameCount = ReadVarint(input, true); +// switch(timelineType) +// { +// case PATH_POSITION: +// case PATH_SPACING: +// { +// PathConstraintPositionTimeline timeline; +// float timelineScale = 1; +// if (timelineType == PATH_SPACING) +// { +// timeline = new PathConstraintSpacingTimeline(frameCount); +// if (data.spacingMode == SpacingMode.Length || data.spacingMode == SpacingMode.Fixed) +// { +// timelineScale = scale; +// } +// } +// else +// { +// timeline = new PathConstraintPositionTimeline(frameCount); +// if (data.positionMode == PositionMode.Fixed) +// { +// timelineScale = scale; +// } +// } +// timeline.pathConstraintIndex = index; +// for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) +// { +// timeline.SetFrame(frameIndex, ReadFloat(input), ReadFloat(input) * timelineScale); +// if (frameIndex < frameCount - 1) +// { +// ReadCurve(input, frameIndex, timeline); +// } +// } +// timelines.Add(timeline); +// duration = Math.Max(duration, timeline.frames[(frameCount - 1) * PathConstraintPositionTimeline.ENTRIES]); +// break; +// } +// case PATH_MIX: +// { +// PathConstraintMixTimeline timeline = new PathConstraintMixTimeline(frameCount); +// timeline.pathConstraintIndex = index; +// for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) +// { +// timeline.SetFrame(frameIndex, ReadFloat(input), ReadFloat(input), ReadFloat(input)); +// if (frameIndex < frameCount - 1) +// { +// ReadCurve(input, frameIndex, timeline); +// } +// } +// timelines.Add(timeline); +// duration = Math.Max(duration, timeline.frames[(frameCount - 1) * PathConstraintMixTimeline.ENTRIES]); +// break; +// } +// } +// } +// } +// +// // Deform timelines. +// for (int i = 0, n = ReadVarint(input, true); i < n; i++) +// { +// Skin skin = skeletonData.skins.Items[ReadVarint(input, true)]; +// for (int ii = 0, nn = ReadVarint(input, true); ii < nn; ii++) +// { +// int slotIndex = ReadVarint(input, true); +// for (int iii = 0, nnn = ReadVarint(input, true); iii < nnn; iii++) +// { +// VertexAttachment attachment = (VertexAttachment)skin.GetAttachment(slotIndex, ReadString(input)); +// bool weighted = attachment.bones != null; +// float[] vertices = attachment.vertices; +// int deformLength = weighted ? vertices.Length / 3 * 2 : vertices.Length; +// +// int frameCount = ReadVarint(input, true); +// DeformTimeline timeline = new DeformTimeline(frameCount); +// timeline.slotIndex = slotIndex; +// timeline.attachment = attachment; +// +// for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) +// { +// float time = ReadFloat(input); +// float[] deform; +// int end = ReadVarint(input, true); +// if (end == 0) +// { +// deform = weighted ? new float[deformLength] : vertices; +// } +// else +// { +// deform = new float[deformLength]; +// int start = ReadVarint(input, true); +// end += start; +// if (scale == 1) +// { +// for (int v = start; v < end; v++) +// { +// deform[v] = ReadFloat(input); +// } +// } +// else +// { +// for (int v = start; v < end; v++) +// { +// deform[v] = ReadFloat(input) * scale; +// } +// } +// +// if (!weighted) +// { +// for (int v = 0, vn = deform.Length; v < vn; v++) +// { +// deform[v] += vertices[v]; +// } +// } +// } +// +// timeline.SetFrame(frameIndex, time, deform); +// if (frameIndex < frameCount - 1) +// { +// ReadCurve(input, frameIndex, timeline); +// } +// } +// +// timelines.Add(timeline); +// duration = Math.Max(duration, timeline.frames[frameCount - 1]); +// } +// } +// } +// +// // Draw order timeline. +// int drawOrderCount = ReadVarint(input, true); +// if (drawOrderCount > 0) +// { +// DrawOrderTimeline timeline = new DrawOrderTimeline(drawOrderCount); +// int slotCount = skeletonData.slots.Count; +// for (int i = 0; i < drawOrderCount; i++) +// { +// float time = ReadFloat(input); +// int offsetCount = ReadVarint(input, true); +// int[] drawOrder = new int[slotCount]; +// for (int ii = slotCount - 1; ii >= 0; ii--) +// { +// drawOrder[ii] = -1; +// } +// int[] unchanged = new int[slotCount - offsetCount]; +// int originalIndex = 0, unchangedIndex = 0; +// for (int ii = 0; ii < offsetCount; ii++) +// { +// int slotIndex = ReadVarint(input, true); +// // Collect unchanged items. +// while (originalIndex != slotIndex) +// { +// unchanged[unchangedIndex++] = originalIndex++; +// } +// // Set changed items. +// drawOrder[originalIndex + ReadVarint(input, true)] = originalIndex++; +// } +// +// // Collect remaining unchanged items. +// while (originalIndex < slotCount) +// { +// unchanged[unchangedIndex++] = originalIndex++; +// } +// +// // Fill in unchanged items. +// for (int ii = slotCount - 1; ii >= 0; ii--) +// { +// if (drawOrder[ii] == -1) +// { +// drawOrder[ii] = unchanged[--unchangedIndex]; +// } +// } +// timeline.SetFrame(i, time, drawOrder); +// } +// timelines.Add(timeline); +// duration = Math.Max(duration, timeline.frames[drawOrderCount - 1]); +// } +// +// // Event timeline. +// int eventCount = ReadVarint(input, true); +// if (eventCount > 0) +// { +// EventTimeline timeline = new EventTimeline(eventCount); +// for (int i = 0; i < eventCount; i++) +// { +// float time = ReadFloat(input); +// EventData eventData = skeletonData.events.Items[ReadVarint(input, true)]; +// Event e = new Event(time, eventData); +// e.Int = ReadVarint(input, false); +// e.Float = ReadFloat(input); +// e.String = ReadBoolean(input) ? ReadString(input) : eventData.String; +// timeline.SetFrame(i, e); +// } +// +// timelines.Add(timeline); +// duration = Math.Max(duration, timeline.frames[eventCount - 1]); +// } +// +// timelines.TrimExcess(); +// + Animation* ret = NEW(Animation); +// new (ret) Animation(std::string(name), timelines, duration); + + return ret; + } } diff --git a/spine-cpp/spine-cpp/src/spine/SlotData.cpp b/spine-cpp/spine-cpp/src/spine/SlotData.cpp index 327327cbb..775b69aca 100644 --- a/spine-cpp/spine-cpp/src/spine/SlotData.cpp +++ b/spine-cpp/spine-cpp/src/spine/SlotData.cpp @@ -45,6 +45,7 @@ namespace Spine _r2(0), _g2(0), _b2(0), + _a2(1), _hasSecondColor(false), _attachmentName(), _blendMode(BlendMode_Normal) From 2b2b34db00d6ebc1c82489f7cfb84502cdb66e9a Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Sun, 3 Dec 2017 16:16:02 -0500 Subject: [PATCH 62/83] Okay, SkeletonBinary is done. --- spine-c/spine-c/src/spine/SkeletonBinary.c | 6 +- spine-cpp/spine-cpp/include/spine/Animation.h | 2 + .../include/spine/AttachmentTimeline.h | 3 + .../spine-cpp/include/spine/ColorTimeline.h | 3 + .../spine-cpp/include/spine/DeformTimeline.h | 3 + .../include/spine/DrawOrderTimeline.h | 3 + spine-cpp/spine-cpp/include/spine/Event.h | 2 + .../spine-cpp/include/spine/EventTimeline.h | 3 + .../include/spine/IkConstraintTimeline.h | 3 + .../include/spine/PathConstraintMixTimeline.h | 3 + .../spine/PathConstraintPositionTimeline.h | 3 + .../spine/PathConstraintSpacingTimeline.h | 3 + .../spine-cpp/include/spine/RotateTimeline.h | 2 + .../spine-cpp/include/spine/ScaleTimeline.h | 3 + .../spine-cpp/include/spine/ShearTimeline.h | 3 + .../spine-cpp/include/spine/SkeletonBinary.h | 3 + .../spine/TransformConstraintTimeline.h | 3 + .../include/spine/TranslateTimeline.h | 3 + .../include/spine/TwoColorTimeline.h | 3 + .../include/spine/VertexAttachment.h | 2 + spine-cpp/spine-cpp/src/spine/Animation.cpp | 7 + .../spine-cpp/src/spine/SkeletonBinary.cpp | 865 ++++++++++-------- 22 files changed, 540 insertions(+), 391 deletions(-) diff --git a/spine-c/spine-c/src/spine/SkeletonBinary.c b/spine-c/spine-c/src/spine/SkeletonBinary.c index eea293778..6b8feba80 100644 --- a/spine-c/spine-c/src/spine/SkeletonBinary.c +++ b/spine-c/spine-c/src/spine/SkeletonBinary.c @@ -262,10 +262,12 @@ static spAnimation* _spSkeletonBinary_readAnimation (spSkeletonBinary* self, con unsigned char timelineType = readByte(input); int frameCount = readVarint(input, 1); switch (timelineType) { - case SLOT_ATTACHMENT: { + case SLOT_ATTACHMENT: + { spAttachmentTimeline* timeline = spAttachmentTimeline_create(frameCount); timeline->slotIndex = slotIndex; - for (frameIndex = 0; frameIndex < frameCount; ++frameIndex) { + for (frameIndex = 0; frameIndex < frameCount; ++frameIndex) + { float time = readFloat(input); const char* attachmentName = readString(input); /* TODO Avoid copying of attachmentName inside */ diff --git a/spine-cpp/spine-cpp/include/spine/Animation.h b/spine-cpp/spine-cpp/include/spine/Animation.h index 8015c57ea..9f0ca70ef 100644 --- a/spine-cpp/spine-cpp/include/spine/Animation.h +++ b/spine-cpp/spine-cpp/include/spine/Animation.h @@ -68,6 +68,8 @@ namespace Spine public: Animation(std::string name, Vector& timelines, float duration); + ~Animation(); + /// Applies all the animation's timelines to the specified skeleton. /// See also Timeline::apply(Skeleton&, float, float, Vector, float, MixPose, MixDirection) void apply(Skeleton& skeleton, float lastTime, float time, bool loop, Vector* pEvents, float alpha, MixPose pose, MixDirection direction); diff --git a/spine-cpp/spine-cpp/include/spine/AttachmentTimeline.h b/spine-cpp/spine-cpp/include/spine/AttachmentTimeline.h index 91484b2b6..6fca8296c 100644 --- a/spine-cpp/spine-cpp/include/spine/AttachmentTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/AttachmentTimeline.h @@ -46,6 +46,9 @@ namespace Spine class AttachmentTimeline : public Timeline { + friend class SkeletonBinary; + friend class SkeletonJson; + RTTI_DECL; public: diff --git a/spine-cpp/spine-cpp/include/spine/ColorTimeline.h b/spine-cpp/spine-cpp/include/spine/ColorTimeline.h index 53a33ddd4..740743134 100644 --- a/spine-cpp/spine-cpp/include/spine/ColorTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/ColorTimeline.h @@ -37,6 +37,9 @@ namespace Spine { class ColorTimeline : public CurveTimeline { + friend class SkeletonBinary; + friend class SkeletonJson; + RTTI_DECL; public: diff --git a/spine-cpp/spine-cpp/include/spine/DeformTimeline.h b/spine-cpp/spine-cpp/include/spine/DeformTimeline.h index a23eaca83..b601ca9f9 100644 --- a/spine-cpp/spine-cpp/include/spine/DeformTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/DeformTimeline.h @@ -39,6 +39,9 @@ namespace Spine class DeformTimeline : public CurveTimeline { + friend class SkeletonBinary; + friend class SkeletonJson; + RTTI_DECL; public: diff --git a/spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h b/spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h index 29226dd88..4d1adc00c 100644 --- a/spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h @@ -37,6 +37,9 @@ namespace Spine { class DrawOrderTimeline : public Timeline { + friend class SkeletonBinary; + friend class SkeletonJson; + RTTI_DECL; public: diff --git a/spine-cpp/spine-cpp/include/spine/Event.h b/spine-cpp/spine-cpp/include/spine/Event.h index 1f4688d4c..7c7330744 100644 --- a/spine-cpp/spine-cpp/include/spine/Event.h +++ b/spine-cpp/spine-cpp/include/spine/Event.h @@ -40,6 +40,8 @@ namespace Spine /// Stores the current pose values for an Event. class Event { + friend class SkeletonBinary; + friend class SkeletonJson; friend class AnimationState; public: diff --git a/spine-cpp/spine-cpp/include/spine/EventTimeline.h b/spine-cpp/spine-cpp/include/spine/EventTimeline.h index c2f880080..30e761b66 100644 --- a/spine-cpp/spine-cpp/include/spine/EventTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/EventTimeline.h @@ -37,6 +37,9 @@ namespace Spine { class EventTimeline : public Timeline { + friend class SkeletonBinary; + friend class SkeletonJson; + RTTI_DECL; public: diff --git a/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h b/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h index 3cd4235d9..295bd1d9c 100644 --- a/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h @@ -37,6 +37,9 @@ namespace Spine { class IkConstraintTimeline : public CurveTimeline { + friend class SkeletonBinary; + friend class SkeletonJson; + RTTI_DECL; public: diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h b/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h index 72598ab69..c2cce00e9 100644 --- a/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h @@ -37,6 +37,9 @@ namespace Spine { class PathConstraintMixTimeline : public CurveTimeline { + friend class SkeletonBinary; + friend class SkeletonJson; + RTTI_DECL; public: diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h b/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h index 2fc8af6a2..b5fe6916b 100644 --- a/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h @@ -37,6 +37,9 @@ namespace Spine { class PathConstraintPositionTimeline : public CurveTimeline { + friend class SkeletonBinary; + friend class SkeletonJson; + RTTI_DECL; public: diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h b/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h index 65392639c..68aad43c9 100644 --- a/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h @@ -37,6 +37,9 @@ namespace Spine { class PathConstraintSpacingTimeline : public PathConstraintPositionTimeline { + friend class SkeletonBinary; + friend class SkeletonJson; + RTTI_DECL; public: diff --git a/spine-cpp/spine-cpp/include/spine/RotateTimeline.h b/spine-cpp/spine-cpp/include/spine/RotateTimeline.h index c14031d98..aed7eb822 100644 --- a/spine-cpp/spine-cpp/include/spine/RotateTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/RotateTimeline.h @@ -37,6 +37,8 @@ namespace Spine { class RotateTimeline : public CurveTimeline { + friend class SkeletonBinary; + friend class SkeletonJson; friend class AnimationState; RTTI_DECL; diff --git a/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h b/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h index 81409a50a..a0788fe1c 100644 --- a/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h @@ -37,6 +37,9 @@ namespace Spine { class ScaleTimeline : public TranslateTimeline { + friend class SkeletonBinary; + friend class SkeletonJson; + RTTI_DECL; public: diff --git a/spine-cpp/spine-cpp/include/spine/ShearTimeline.h b/spine-cpp/spine-cpp/include/spine/ShearTimeline.h index ae83d7cef..d3b46ac70 100644 --- a/spine-cpp/spine-cpp/include/spine/ShearTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/ShearTimeline.h @@ -37,6 +37,9 @@ namespace Spine { class ShearTimeline : public TranslateTimeline { + friend class SkeletonBinary; + friend class SkeletonJson; + RTTI_DECL; public: diff --git a/spine-cpp/spine-cpp/include/spine/SkeletonBinary.h b/spine-cpp/spine-cpp/include/spine/SkeletonBinary.h index 1d29d3af6..725ba5edb 100644 --- a/spine-cpp/spine-cpp/include/spine/SkeletonBinary.h +++ b/spine-cpp/spine-cpp/include/spine/SkeletonBinary.h @@ -46,6 +46,7 @@ namespace Spine class Attachment; class VertexAttachment; class Animation; + class CurveTimeline; class SkeletonBinary { @@ -128,6 +129,8 @@ namespace Spine Vector readShortArray(DataInput *input); Animation* readAnimation(const char* name, DataInput* input, SkeletonData *skeletonData); + + void readCurve(DataInput* input, int frameIndex, CurveTimeline* timeline); }; } diff --git a/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h b/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h index c001e82b1..2324234cb 100644 --- a/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h @@ -37,6 +37,9 @@ namespace Spine { class TransformConstraintTimeline : public CurveTimeline { + friend class SkeletonBinary; + friend class SkeletonJson; + RTTI_DECL; public: diff --git a/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h b/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h index 37fd21a9e..424125ebb 100644 --- a/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h @@ -40,6 +40,9 @@ namespace Spine { class TranslateTimeline : public CurveTimeline { + friend class SkeletonBinary; + friend class SkeletonJson; + RTTI_DECL; public: diff --git a/spine-cpp/spine-cpp/include/spine/TwoColorTimeline.h b/spine-cpp/spine-cpp/include/spine/TwoColorTimeline.h index fd3f55fd4..266eba418 100644 --- a/spine-cpp/spine-cpp/include/spine/TwoColorTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/TwoColorTimeline.h @@ -37,6 +37,9 @@ namespace Spine { class TwoColorTimeline : public CurveTimeline { + friend class SkeletonBinary; + friend class SkeletonJson; + RTTI_DECL; public: diff --git a/spine-cpp/spine-cpp/include/spine/VertexAttachment.h b/spine-cpp/spine-cpp/include/spine/VertexAttachment.h index 3529c5cf3..56c057674 100644 --- a/spine-cpp/spine-cpp/include/spine/VertexAttachment.h +++ b/spine-cpp/spine-cpp/include/spine/VertexAttachment.h @@ -42,6 +42,8 @@ namespace Spine /// An attachment with vertices that are transformed by one or more bones and can be deformed by a slot's vertices. class VertexAttachment : public Attachment { + friend class SkeletonBinary; + friend class SkeletonJson; friend class DeformTimeline; RTTI_DECL; diff --git a/spine-cpp/spine-cpp/src/spine/Animation.cpp b/spine-cpp/spine-cpp/src/spine/Animation.cpp index ac140cbf9..d494c4154 100644 --- a/spine-cpp/spine-cpp/src/spine/Animation.cpp +++ b/spine-cpp/spine-cpp/src/spine/Animation.cpp @@ -34,6 +34,8 @@ #include #include +#include + #include #include /* fmod */ @@ -47,6 +49,11 @@ namespace Spine assert(_name.length() > 0); } + Animation::~Animation() + { + ContainerUtil::cleanUpVectorOfPointers(_timelines); + } + void Animation::apply(Skeleton& skeleton, float lastTime, float time, bool loop, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) { if (loop && _duration != 0) diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp b/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp index 918904e45..34c92bacc 100644 --- a/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp +++ b/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp @@ -57,6 +57,24 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include namespace Spine { @@ -351,7 +369,7 @@ namespace Spine } /* Linked meshes. */ - for (int i = 0, n = static_cast(_linkedMeshes.size()); i < n; i++) + for (int i = 0, n = static_cast(_linkedMeshes.size()); i < n; ++i) { LinkedMesh* linkedMesh = _linkedMeshes[i]; Skin* skin = linkedMesh->_skin.length() == 0 ? skeletonData->getDefaultSkin() : skeletonData->findSkin(linkedMesh->_skin); @@ -386,7 +404,9 @@ namespace Spine FREE(name); eventData->_intValue = readVarint(input, 0); eventData->_floatValue = readFloat(input); - eventData->_stringValue = readString(input); + const char* eventData_stringValue = readString(input); + eventData->_stringValue = std::string(eventData_stringValue); + FREE(eventData_stringValue); skeletonData->_events[i] = eventData; } @@ -695,6 +715,9 @@ namespace Spine FREE(name); } + FREE(skinName); + FREE(parent); + return mesh; } case AttachmentType_Path: @@ -847,395 +870,459 @@ namespace Spine Animation* SkeletonBinary::readAnimation(const char* name, DataInput* input, SkeletonData *skeletonData) { -// var timelines = new ExposedList(); -// float scale = Scale; -// float duration = 0; -// -// // Slot timelines. -// for (int i = 0, n = ReadVarint(input, true); i < n; i++) -// { -// int slotIndex = ReadVarint(input, true); -// for (int ii = 0, nn = ReadVarint(input, true); ii < nn; ii++) -// { -// int timelineType = input.ReadByte(); -// int frameCount = ReadVarint(input, true); -// switch (timelineType) -// { -// case SLOT_ATTACHMENT: -// { -// AttachmentTimeline timeline = new AttachmentTimeline(frameCount); -// timeline.slotIndex = slotIndex; -// for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) -// { -// timeline.SetFrame(frameIndex, ReadFloat(input), ReadString(input)); -// } -// timelines.Add(timeline); -// duration = Math.Max(duration, timeline.frames[frameCount - 1]); -// break; -// } -// case SLOT_COLOR: -// { -// ColorTimeline timeline = new ColorTimeline(frameCount); -// timeline.slotIndex = slotIndex; -// for (int frameIndex = 0; frameIndex < frameCount; frameIndex++)\ -// { -// float time = ReadFloat(input); -// int color = ReadInt(input); -// float r = ((color & 0xff000000) >> 24) / 255f; -// float g = ((color & 0x00ff0000) >> 16) / 255f; -// float b = ((color & 0x0000ff00) >> 8) / 255f; -// float a = ((color & 0x000000ff)) / 255f; -// timeline.SetFrame(frameIndex, time, r, g, b, a); -// if (frameIndex < frameCount - 1) -// { -// ReadCurve(input, frameIndex, timeline); -// } -// } -// timelines.Add(timeline); -// duration = Math.Max(duration, timeline.frames[(timeline.FrameCount - 1) * ColorTimeline.ENTRIES]); -// break; -// } -// case SLOT_TWO_COLOR: -// { -// TwoColorTimeline timeline = new TwoColorTimeline(frameCount); -// timeline.slotIndex = slotIndex; -// for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) -// { -// float time = ReadFloat(input); -// int color = ReadInt(input); -// float r = ((color & 0xff000000) >> 24) / 255f; -// float g = ((color & 0x00ff0000) >> 16) / 255f; -// float b = ((color & 0x0000ff00) >> 8) / 255f; -// float a = ((color & 0x000000ff)) / 255f; -// int color2 = ReadInt(input); // 0x00rrggbb -// float r2 = ((color2 & 0x00ff0000) >> 16) / 255f; -// float g2 = ((color2 & 0x0000ff00) >> 8) / 255f; -// float b2 = ((color2 & 0x000000ff)) / 255f; -// -// timeline.SetFrame(frameIndex, time, r, g, b, a, r2, g2, b2); -// if (frameIndex < frameCount - 1) -// { -// ReadCurve(input, frameIndex, timeline); -// } -// } -// timelines.Add(timeline); -// duration = Math.Max(duration, timeline.frames[(timeline.FrameCount - 1) * TwoColorTimeline.ENTRIES]); -// break; -// } -// } -// } -// } -// -// // Bone timelines. -// for (int i = 0, n = ReadVarint(input, true); i < n; i++) -// { -// int boneIndex = ReadVarint(input, true); -// for (int ii = 0, nn = ReadVarint(input, true); ii < nn; ii++) -// { -// int timelineType = input.ReadByte(); -// int frameCount = ReadVarint(input, true); -// switch (timelineType) -// { -// case BONE_ROTATE: -// { -// RotateTimeline timeline = new RotateTimeline(frameCount); -// timeline.boneIndex = boneIndex; -// for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) -// { -// timeline.SetFrame(frameIndex, ReadFloat(input), ReadFloat(input)); -// if (frameIndex < frameCount - 1) -// { -// ReadCurve(input, frameIndex, timeline); -// } -// } -// timelines.Add(timeline); -// duration = Math.Max(duration, timeline.frames[(frameCount - 1) * RotateTimeline.ENTRIES]); -// break; -// } -// case BONE_TRANSLATE: -// case BONE_SCALE: -// case BONE_SHEAR: -// { -// TranslateTimeline timeline; -// float timelineScale = 1; -// if (timelineType == BONE_SCALE) -// { -// timeline = new ScaleTimeline(frameCount); -// } -// else if (timelineType == BONE_SHEAR) -// { -// timeline = new ShearTimeline(frameCount); -// } -// else -// { -// timeline = new TranslateTimeline(frameCount); -// timelineScale = scale; -// } -// timeline.boneIndex = boneIndex; -// for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) -// { -// timeline.SetFrame(frameIndex, ReadFloat(input), ReadFloat(input) * timelineScale, ReadFloat(input) -// * timelineScale); -// if (frameIndex < frameCount - 1) -// { -// ReadCurve(input, frameIndex, timeline); -// } -// } -// timelines.Add(timeline); -// duration = Math.Max(duration, timeline.frames[(frameCount - 1) * TranslateTimeline.ENTRIES]); -// break; -// } -// } -// } -// } -// -// // IK timelines. -// for (int i = 0, n = ReadVarint(input, true); i < n; i++) -// { -// int index = ReadVarint(input, true); -// int frameCount = ReadVarint(input, true); -// IkConstraintTimeline timeline = new IkConstraintTimeline(frameCount); -// timeline.ikConstraintIndex = index; -// for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) -// { -// timeline.SetFrame(frameIndex, ReadFloat(input), ReadFloat(input), ReadSByte(input)); -// if (frameIndex < frameCount - 1) -// { -// ReadCurve(input, frameIndex, timeline); -// } -// } -// timelines.Add(timeline); -// duration = Math.Max(duration, timeline.frames[(frameCount - 1) * IkConstraintTimeline.ENTRIES]); -// } -// -// // Transform constraint timelines. -// for (int i = 0, n = ReadVarint(input, true); i < n; i++) -// { -// int index = ReadVarint(input, true); -// int frameCount = ReadVarint(input, true); -// TransformConstraintTimeline timeline = new TransformConstraintTimeline(frameCount); -// timeline.transformConstraintIndex = index; -// for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) -// { -// timeline.SetFrame(frameIndex, ReadFloat(input), ReadFloat(input), ReadFloat(input), ReadFloat(input), ReadFloat(input)); -// if (frameIndex < frameCount - 1) -// { -// ReadCurve(input, frameIndex, timeline); -// } -// } -// timelines.Add(timeline); -// duration = Math.Max(duration, timeline.frames[(frameCount - 1) * TransformConstraintTimeline.ENTRIES]); -// } -// -// // Path constraint timelines. -// for (int i = 0, n = ReadVarint(input, true); i < n; i++) -// { -// int index = ReadVarint(input, true); -// PathConstraintData data = skeletonData.pathConstraints.Items[index]; -// for (int ii = 0, nn = ReadVarint(input, true); ii < nn; ii++) -// { -// int timelineType = ReadSByte(input); -// int frameCount = ReadVarint(input, true); -// switch(timelineType) -// { -// case PATH_POSITION: -// case PATH_SPACING: -// { -// PathConstraintPositionTimeline timeline; -// float timelineScale = 1; -// if (timelineType == PATH_SPACING) -// { -// timeline = new PathConstraintSpacingTimeline(frameCount); -// if (data.spacingMode == SpacingMode.Length || data.spacingMode == SpacingMode.Fixed) -// { -// timelineScale = scale; -// } -// } -// else -// { -// timeline = new PathConstraintPositionTimeline(frameCount); -// if (data.positionMode == PositionMode.Fixed) -// { -// timelineScale = scale; -// } -// } -// timeline.pathConstraintIndex = index; -// for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) -// { -// timeline.SetFrame(frameIndex, ReadFloat(input), ReadFloat(input) * timelineScale); -// if (frameIndex < frameCount - 1) -// { -// ReadCurve(input, frameIndex, timeline); -// } -// } -// timelines.Add(timeline); -// duration = Math.Max(duration, timeline.frames[(frameCount - 1) * PathConstraintPositionTimeline.ENTRIES]); -// break; -// } -// case PATH_MIX: -// { -// PathConstraintMixTimeline timeline = new PathConstraintMixTimeline(frameCount); -// timeline.pathConstraintIndex = index; -// for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) -// { -// timeline.SetFrame(frameIndex, ReadFloat(input), ReadFloat(input), ReadFloat(input)); -// if (frameIndex < frameCount - 1) -// { -// ReadCurve(input, frameIndex, timeline); -// } -// } -// timelines.Add(timeline); -// duration = Math.Max(duration, timeline.frames[(frameCount - 1) * PathConstraintMixTimeline.ENTRIES]); -// break; -// } -// } -// } -// } -// -// // Deform timelines. -// for (int i = 0, n = ReadVarint(input, true); i < n; i++) -// { -// Skin skin = skeletonData.skins.Items[ReadVarint(input, true)]; -// for (int ii = 0, nn = ReadVarint(input, true); ii < nn; ii++) -// { -// int slotIndex = ReadVarint(input, true); -// for (int iii = 0, nnn = ReadVarint(input, true); iii < nnn; iii++) -// { -// VertexAttachment attachment = (VertexAttachment)skin.GetAttachment(slotIndex, ReadString(input)); -// bool weighted = attachment.bones != null; -// float[] vertices = attachment.vertices; -// int deformLength = weighted ? vertices.Length / 3 * 2 : vertices.Length; -// -// int frameCount = ReadVarint(input, true); -// DeformTimeline timeline = new DeformTimeline(frameCount); -// timeline.slotIndex = slotIndex; -// timeline.attachment = attachment; -// -// for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) -// { -// float time = ReadFloat(input); -// float[] deform; -// int end = ReadVarint(input, true); -// if (end == 0) -// { -// deform = weighted ? new float[deformLength] : vertices; -// } -// else -// { -// deform = new float[deformLength]; -// int start = ReadVarint(input, true); -// end += start; -// if (scale == 1) -// { -// for (int v = start; v < end; v++) -// { -// deform[v] = ReadFloat(input); -// } -// } -// else -// { -// for (int v = start; v < end; v++) -// { -// deform[v] = ReadFloat(input) * scale; -// } -// } -// -// if (!weighted) -// { -// for (int v = 0, vn = deform.Length; v < vn; v++) -// { -// deform[v] += vertices[v]; -// } -// } -// } -// -// timeline.SetFrame(frameIndex, time, deform); -// if (frameIndex < frameCount - 1) -// { -// ReadCurve(input, frameIndex, timeline); -// } -// } -// -// timelines.Add(timeline); -// duration = Math.Max(duration, timeline.frames[frameCount - 1]); -// } -// } -// } -// -// // Draw order timeline. -// int drawOrderCount = ReadVarint(input, true); -// if (drawOrderCount > 0) -// { -// DrawOrderTimeline timeline = new DrawOrderTimeline(drawOrderCount); -// int slotCount = skeletonData.slots.Count; -// for (int i = 0; i < drawOrderCount; i++) -// { -// float time = ReadFloat(input); -// int offsetCount = ReadVarint(input, true); -// int[] drawOrder = new int[slotCount]; -// for (int ii = slotCount - 1; ii >= 0; ii--) -// { -// drawOrder[ii] = -1; -// } -// int[] unchanged = new int[slotCount - offsetCount]; -// int originalIndex = 0, unchangedIndex = 0; -// for (int ii = 0; ii < offsetCount; ii++) -// { -// int slotIndex = ReadVarint(input, true); -// // Collect unchanged items. -// while (originalIndex != slotIndex) -// { -// unchanged[unchangedIndex++] = originalIndex++; -// } -// // Set changed items. -// drawOrder[originalIndex + ReadVarint(input, true)] = originalIndex++; -// } -// -// // Collect remaining unchanged items. -// while (originalIndex < slotCount) -// { -// unchanged[unchangedIndex++] = originalIndex++; -// } -// -// // Fill in unchanged items. -// for (int ii = slotCount - 1; ii >= 0; ii--) -// { -// if (drawOrder[ii] == -1) -// { -// drawOrder[ii] = unchanged[--unchangedIndex]; -// } -// } -// timeline.SetFrame(i, time, drawOrder); -// } -// timelines.Add(timeline); -// duration = Math.Max(duration, timeline.frames[drawOrderCount - 1]); -// } -// -// // Event timeline. -// int eventCount = ReadVarint(input, true); -// if (eventCount > 0) -// { -// EventTimeline timeline = new EventTimeline(eventCount); -// for (int i = 0; i < eventCount; i++) -// { -// float time = ReadFloat(input); -// EventData eventData = skeletonData.events.Items[ReadVarint(input, true)]; -// Event e = new Event(time, eventData); -// e.Int = ReadVarint(input, false); -// e.Float = ReadFloat(input); -// e.String = ReadBoolean(input) ? ReadString(input) : eventData.String; -// timeline.SetFrame(i, e); -// } -// -// timelines.Add(timeline); -// duration = Math.Max(duration, timeline.frames[eventCount - 1]); -// } -// -// timelines.TrimExcess(); -// + Vector timelines; + float scale = _scale; + float duration = 0; + + // Slot timelines. + for (int i = 0, n = readVarint(input, true); i < n; ++i) + { + int slotIndex = readVarint(input, true); + for (int ii = 0, nn = readVarint(input, true); ii < nn; ++ii) + { + unsigned char timelineType = readByte(input); + int frameCount = readVarint(input, true); + switch (timelineType) + { + case SLOT_ATTACHMENT: + { + AttachmentTimeline* timeline = NEW(AttachmentTimeline); + new(timeline) AttachmentTimeline(frameCount); + timeline->_slotIndex = slotIndex; + for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) + { + const char* attachmentName = readString(input); + timeline->setFrame(frameIndex, readFloat(input), std::string(attachmentName)); + FREE(attachmentName); + } + timelines.push_back(timeline); + duration = MAX(duration, timeline->_frames[frameCount - 1]); + break; + } + case SLOT_COLOR: + { + ColorTimeline* timeline = NEW(ColorTimeline); + new(timeline) ColorTimeline(frameCount); + timeline->_slotIndex = slotIndex; + for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) + { + float time = readFloat(input); + int color = readInt(input); + float r = ((color & 0xff000000) >> 24) / 255.0f; + float g = ((color & 0x00ff0000) >> 16) / 255.0f; + float b = ((color & 0x0000ff00) >> 8) / 255.0f; + float a = ((color & 0x000000ff)) / 255.0f; + timeline->setFrame(frameIndex, time, r, g, b, a); + if (frameIndex < frameCount - 1) + { + readCurve(input, frameIndex, timeline); + } + } + timelines.push_back(timeline); + duration = MAX(duration, timeline->_frames[(frameCount - 1) * ColorTimeline::ENTRIES]); + break; + } + case SLOT_TWO_COLOR: + { + TwoColorTimeline* timeline = NEW(TwoColorTimeline); + new(timeline) TwoColorTimeline(frameCount); + timeline->_slotIndex = slotIndex; + for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) + { + float time = readFloat(input); + int color = readInt(input); + float r = ((color & 0xff000000) >> 24) / 255.0f; + float g = ((color & 0x00ff0000) >> 16) / 255.0f; + float b = ((color & 0x0000ff00) >> 8) / 255.0f; + float a = ((color & 0x000000ff)) / 255.0f; + int color2 = readInt(input); // 0x00rrggbb + float r2 = ((color2 & 0x00ff0000) >> 16) / 255.0f; + float g2 = ((color2 & 0x0000ff00) >> 8) / 255.0f; + float b2 = ((color2 & 0x000000ff)) / 255.0f; + + timeline->setFrame(frameIndex, time, r, g, b, a, r2, g2, b2); + if (frameIndex < frameCount - 1) + { + readCurve(input, frameIndex, timeline); + } + } + timelines.push_back(timeline); + duration = MAX(duration, timeline->_frames[(frameCount - 1) * TwoColorTimeline::ENTRIES]); + break; + } + } + } + } + + // Bone timelines. + for (int i = 0, n = readVarint(input, true); i < n; ++i) + { + int boneIndex = readVarint(input, true); + for (int ii = 0, nn = readVarint(input, true); ii < nn; ++ii) + { + unsigned char timelineType = readByte(input); + int frameCount = readVarint(input, true); + switch (timelineType) + { + case BONE_ROTATE: + { + RotateTimeline* timeline = NEW(RotateTimeline); + new(timeline) RotateTimeline(frameCount); + timeline->_boneIndex = boneIndex; + for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) + { + timeline->setFrame(frameIndex, readFloat(input), readFloat(input)); + if (frameIndex < frameCount - 1) + { + readCurve(input, frameIndex, timeline); + } + } + timelines.push_back(timeline); + duration = MAX(duration, timeline->_frames[(frameCount - 1) * RotateTimeline::ENTRIES]); + break; + } + case BONE_TRANSLATE: + case BONE_SCALE: + case BONE_SHEAR: + { + TranslateTimeline* timeline; + float timelineScale = 1; + if (timelineType == BONE_SCALE) + { + timeline = NEW(ScaleTimeline); + new(timeline) ScaleTimeline(frameCount); + } + else if (timelineType == BONE_SHEAR) + { + timeline = NEW(ShearTimeline); + new(timeline) ShearTimeline(frameCount); + } + else + { + timeline = NEW(TranslateTimeline); + new(timeline) TranslateTimeline(frameCount); + timelineScale = scale; + } + timeline->_boneIndex = boneIndex; + for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) + { + timeline->setFrame(frameIndex, readFloat(input), readFloat(input) * timelineScale, readFloat(input) * timelineScale); + if (frameIndex < frameCount - 1) + { + readCurve(input, frameIndex, timeline); + } + } + timelines.push_back(timeline); + duration = MAX(duration, timeline->_frames[(frameCount - 1) * TranslateTimeline::ENTRIES]); + break; + } + } + } + } + + // IK timelines. + for (int i = 0, n = readVarint(input, true); i < n; ++i) + { + int index = readVarint(input, true); + int frameCount = readVarint(input, true); + IkConstraintTimeline* timeline = NEW(IkConstraintTimeline); + new(timeline) IkConstraintTimeline(frameCount); + timeline->_ikConstraintIndex = index; + for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) + { + timeline->setFrame(frameIndex, readFloat(input), readFloat(input), readSByte(input)); + if (frameIndex < frameCount - 1) + { + readCurve(input, frameIndex, timeline); + } + } + timelines.push_back(timeline); + duration = MAX(duration, timeline->_frames[(frameCount - 1) * IkConstraintTimeline::ENTRIES]); + } + + // Transform constraint timelines. + for (int i = 0, n = readVarint(input, true); i < n; ++i) + { + int index = readVarint(input, true); + int frameCount = readVarint(input, true); + TransformConstraintTimeline* timeline = NEW(TransformConstraintTimeline); + new(timeline) TransformConstraintTimeline(frameCount); + timeline->_transformConstraintIndex = index; + for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) + { + timeline->setFrame(frameIndex, readFloat(input), readFloat(input), readFloat(input), readFloat(input), readFloat(input)); + if (frameIndex < frameCount - 1) + { + readCurve(input, frameIndex, timeline); + } + } + timelines.push_back(timeline); + duration = MAX(duration, timeline->_frames[(frameCount - 1) * TransformConstraintTimeline::ENTRIES]); + } + + // Path constraint timelines. + for (int i = 0, n = readVarint(input, true); i < n; ++i) + { + int index = readVarint(input, true); + PathConstraintData* data = skeletonData->_pathConstraints[index]; + for (int ii = 0, nn = readVarint(input, true); ii < nn; ++ii) + { + int timelineType = readSByte(input); + int frameCount = readVarint(input, true); + switch(timelineType) + { + case PATH_POSITION: + case PATH_SPACING: + { + PathConstraintPositionTimeline* timeline; + float timelineScale = 1; + if (timelineType == PATH_SPACING) + { + timeline = NEW(PathConstraintSpacingTimeline); + new(timeline) PathConstraintSpacingTimeline(frameCount); + + if (data->_spacingMode == SpacingMode_Length || data->_spacingMode == SpacingMode_Fixed) + { + timelineScale = scale; + } + } + else + { + timeline = NEW(PathConstraintPositionTimeline); + new(timeline) PathConstraintPositionTimeline(frameCount); + + if (data->_positionMode == PositionMode_Fixed) + { + timelineScale = scale; + } + } + timeline->_pathConstraintIndex = index; + for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) + { + timeline->setFrame(frameIndex, readFloat(input), readFloat(input) * timelineScale); + if (frameIndex < frameCount - 1) + { + readCurve(input, frameIndex, timeline); + } + } + timelines.push_back(timeline); + duration = MAX(duration, timeline->_frames[(frameCount - 1) * PathConstraintPositionTimeline::ENTRIES]); + break; + } + case PATH_MIX: + { + PathConstraintMixTimeline* timeline = NEW(PathConstraintMixTimeline); + new(timeline) PathConstraintMixTimeline(frameCount); + + timeline->_pathConstraintIndex = index; + for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) + { + timeline->setFrame(frameIndex, readFloat(input), readFloat(input), readFloat(input)); + if (frameIndex < frameCount - 1) + { + readCurve(input, frameIndex, timeline); + } + } + timelines.push_back(timeline); + duration = MAX(duration, timeline->_frames[(frameCount - 1) * PathConstraintMixTimeline::ENTRIES]); + break; + } + } + } + } + + // Deform timelines. + for (int i = 0, n = readVarint(input, true); i < n; ++i) + { + Skin* skin = skeletonData->_skins[readVarint(input, true)]; + for (int ii = 0, nn = readVarint(input, true); ii < nn; ++ii) + { + int slotIndex = readVarint(input, true); + for (int iii = 0, nnn = readVarint(input, true); iii < nnn; iii++) + { + const char* vertexAttachmentName = readString(input); + VertexAttachment* attachment = static_cast(skin->getAttachment(slotIndex, std::string(vertexAttachmentName))); + FREE(vertexAttachmentName); + bool weighted = attachment->_bones.size() > 0; + Vector& vertices = attachment->_vertices; + int deformLength = weighted ? static_cast(vertices.size()) / 3 * 2 : static_cast(vertices.size()); + + int frameCount = readVarint(input, true); + + DeformTimeline* timeline = NEW(DeformTimeline); + new(timeline) DeformTimeline(frameCount); + + timeline->_slotIndex = slotIndex; + timeline->_attachment = attachment; + + for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) + { + float time = readFloat(input); + Vector deform; + int end = readVarint(input, true); + if (end == 0) + { + if (weighted) + { + deform.reserve(deformLength); + } + else + { + deform = vertices; + } + } + else + { + deform.reserve(deformLength); + int start = readVarint(input, true); + end += start; + if (scale == 1) + { + for (int v = start; v < end; ++v) + { + deform[v] = readFloat(input); + } + } + else + { + for (int v = start; v < end; ++v) + { + deform[v] = readFloat(input) * scale; + } + } + + if (!weighted) + { + for (int v = 0, vn = static_cast(deform.size()); v < vn; ++v) + { + deform[v] += vertices[v]; + } + } + } + + timeline->setFrame(frameIndex, time, deform); + if (frameIndex < frameCount - 1) + { + readCurve(input, frameIndex, timeline); + } + } + + timelines.push_back(timeline); + duration = MAX(duration, timeline->_frames[frameCount - 1]); + } + } + } + + // Draw order timeline. + int drawOrderCount = readVarint(input, true); + if (drawOrderCount > 0) + { + DrawOrderTimeline* timeline = NEW(DrawOrderTimeline); + new(timeline) DrawOrderTimeline(drawOrderCount); + + int slotCount = static_cast(skeletonData->_slots.size()); + for (int i = 0; i < drawOrderCount; ++i) + { + float time = readFloat(input); + int offsetCount = readVarint(input, true); + + Vector drawOrder; + drawOrder.reserve(slotCount); + for (int ii = slotCount - 1; ii >= 0; --ii) + { + drawOrder[ii] = -1; + } + + Vector unchanged; + unchanged.reserve(slotCount - offsetCount); + int originalIndex = 0, unchangedIndex = 0; + for (int ii = 0; ii < offsetCount; ++ii) + { + int slotIndex = readVarint(input, true); + // Collect unchanged items. + while (originalIndex != slotIndex) + { + unchanged[unchangedIndex++] = originalIndex++; + } + // Set changed items. + int index = originalIndex; + drawOrder[index + readVarint(input, true)] = originalIndex++; + } + + // Collect remaining unchanged items. + while (originalIndex < slotCount) + { + unchanged[unchangedIndex++] = originalIndex++; + } + + // Fill in unchanged items. + for (int ii = slotCount - 1; ii >= 0; --ii) + { + if (drawOrder[ii] == -1) + { + drawOrder[ii] = unchanged[--unchangedIndex]; + } + } + timeline->setFrame(i, time, drawOrder); + } + timelines.push_back(timeline); + duration = MAX(duration, timeline->_frames[drawOrderCount - 1]); + } + + // Event timeline. + int eventCount = readVarint(input, true); + if (eventCount > 0) + { + EventTimeline* timeline = NEW(EventTimeline); + new(timeline) EventTimeline(eventCount); + + for (int i = 0; i < eventCount; ++i) + { + float time = readFloat(input); + EventData* eventData = skeletonData->_events[readVarint(input, true)]; + Event* event = NEW(Event); + new(event) Event(time, *eventData); + + event->_intValue = readVarint(input, false); + event->_floatValue = readFloat(input); + bool freeString = readBoolean(input); + const char* event_stringValue = freeString ? readString(input) : eventData->_stringValue.c_str(); + event->_stringValue = std::string(event_stringValue); + if (freeString) + { + FREE(event_stringValue); + } + timeline->setFrame(i, event); + } + + timelines.push_back(timeline); + duration = MAX(duration, timeline->_frames[eventCount - 1]); + } + Animation* ret = NEW(Animation); -// new (ret) Animation(std::string(name), timelines, duration); + new (ret) Animation(std::string(name), timelines, duration); return ret; } + + void SkeletonBinary::readCurve(DataInput* input, int frameIndex, CurveTimeline* timeline) + { + switch (readByte(input)) + { + case CURVE_STEPPED: + { + timeline->setStepped(frameIndex); + break; + } + case CURVE_BEZIER: + { + float cx1 = readFloat(input); + float cy1 = readFloat(input); + float cx2 = readFloat(input); + float cy2 = readFloat(input); + timeline->setCurve(frameIndex, cx1, cy1, cx2, cy2); + break; + } + } + } } From 1f415cec9f94e1963ac62b7741030a86fb44429f Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Sun, 3 Dec 2017 16:40:04 -0500 Subject: [PATCH 63/83] Forgot some setError calls and cleanup --- .../spine-cpp/src/spine/SkeletonBinary.cpp | 34 ++++++++++++++++--- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp b/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp index 34c92bacc..57dfb340b 100644 --- a/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp +++ b/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp @@ -440,7 +440,7 @@ namespace Spine if (length == 0 || !binary) { setError("Unable to read skeleton file: ", path); - return 0; + return NULL; } skeletonData = readSkeletonData((unsigned char*)binary, length); FREE(binary); @@ -559,7 +559,7 @@ namespace Spine int i, ii, nn; if (slotCount == 0) { - return 0; + return NULL; } skin = NEW(Skin); @@ -950,6 +950,12 @@ namespace Spine duration = MAX(duration, timeline->_frames[(frameCount - 1) * TwoColorTimeline::ENTRIES]); break; } + default: + { + ContainerUtil::cleanUpVectorOfPointers(timelines); + setError("Invalid timeline type for a slot: ", skeletonData->_slots[slotIndex]->_name.c_str()); + return NULL; + } } } } @@ -1016,6 +1022,12 @@ namespace Spine duration = MAX(duration, timeline->_frames[(frameCount - 1) * TranslateTimeline::ENTRIES]); break; } + default: + { + ContainerUtil::cleanUpVectorOfPointers(timelines); + setError("Invalid timeline type for a bone: ", skeletonData->_bones[boneIndex]->_name.c_str()); + return NULL; + } } } } @@ -1140,9 +1152,21 @@ namespace Spine int slotIndex = readVarint(input, true); for (int iii = 0, nnn = readVarint(input, true); iii < nnn; iii++) { - const char* vertexAttachmentName = readString(input); - VertexAttachment* attachment = static_cast(skin->getAttachment(slotIndex, std::string(vertexAttachmentName))); - FREE(vertexAttachmentName); + const char* attachmentName = readString(input); + Attachment* baseAttachment = skin->getAttachment(slotIndex, std::string(attachmentName)); + + if (!baseAttachment) + { + ContainerUtil::cleanUpVectorOfPointers(timelines); + setError("Attachment not found: ", attachmentName); + FREE(attachmentName); + return NULL; + } + + FREE(attachmentName); + + VertexAttachment* attachment = static_cast(baseAttachment); + bool weighted = attachment->_bones.size() > 0; Vector& vertices = attachment->_vertices; int deformLength = weighted ? static_cast(vertices.size()) / 3 * 2 : static_cast(vertices.size()); From 0b28d385dbada3bcb6c7ea4870e781c57b494f97 Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Sun, 3 Dec 2017 19:49:05 -0500 Subject: [PATCH 64/83] NEW macro calls CALLOC macro --- spine-cpp/spine-cpp/include/spine/Extension.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spine-cpp/spine-cpp/include/spine/Extension.h b/spine-cpp/spine-cpp/include/spine/Extension.h index 3595d365f..6c3a3f9c4 100644 --- a/spine-cpp/spine-cpp/include/spine/Extension.h +++ b/spine-cpp/spine-cpp/include/spine/Extension.h @@ -38,7 +38,7 @@ /* All allocation uses these. */ #define MALLOC(TYPE,COUNT) ((TYPE*)SPINE_EXTENSION->spineAlloc(sizeof(TYPE) * (COUNT), __FILE__, __LINE__)) #define CALLOC(TYPE,COUNT) ((TYPE*)SPINE_EXTENSION->spineCalloc(COUNT, sizeof(TYPE), __FILE__, __LINE__)) -#define NEW(TYPE) ((TYPE*)SPINE_EXTENSION->spineAlloc(sizeof(TYPE), __FILE__, __LINE__)) +#define NEW(TYPE) CALLOC(TYPE,1) #define REALLOC(PTR,TYPE,COUNT) ((TYPE*)SPINE_EXTENSION->spineRealloc(PTR, sizeof(TYPE) * (COUNT), __FILE__, __LINE__)) /* Frees memory. Can be used on const types. */ From be2dfc7ff4709e35975081e57d46aafdd49661e6 Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Sun, 3 Dec 2017 21:32:44 -0500 Subject: [PATCH 65/83] wip --- spine-cpp/spine-cpp/include/spine/Json.h | 73 +- .../spine-cpp/include/spine/SkeletonJson.h | 24 +- spine-cpp/spine-cpp/src/spine/Json.cpp | 616 ++++++++- .../spine-cpp/src/spine/SkeletonJson.cpp | 1185 ++++++++++++++++- 4 files changed, 1893 insertions(+), 5 deletions(-) diff --git a/spine-cpp/spine-cpp/include/spine/Json.h b/spine-cpp/spine-cpp/include/spine/Json.h index 0e8b64a41..e64a7e72a 100644 --- a/spine-cpp/spine-cpp/include/spine/Json.h +++ b/spine-cpp/spine-cpp/include/spine/Json.h @@ -31,9 +31,80 @@ #ifndef Spine_Json_h #define Spine_Json_h +#ifndef SPINE_JSON_HAVE_PREV +/* Spine doesn't use the "prev" link in the Json sibling lists. */ +#define SPINE_JSON_HAVE_PREV 0 +#endif + namespace Spine { - // TODO + class Json + { + public: + /* Json Types: */ + static const int JSON_FALSE; + static const int JSON_TRUE; + static const int JSON_NULL; + static const int JSON_NUMBER; + static const int JSON_STRING; + static const int JSON_ARRAY; + static const int JSON_OBJECT; + + /* Get item "string" from object. Case insensitive. */ + static Json* getItem(Json *object, const char* string); + + static const char* getString(Json *object, const char* name, const char* defaultValue); + + static float getFloat(Json *object, const char* name, float defaultValue); + + static int getInt(Json *object, const char* name, int defaultValue); + + /* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when Json_create() returns 0. 0 when Json_create() succeeds. */ + static const char* getError(); + + /* Supply a block of JSON, and this returns a Json object you can interrogate. Call Json_dispose when finished. */ + Json(const char* value); + + ~Json(); + + private: + static const char* JSON_ERROR; + + Json* _next; +#if SPINE_JSON_HAVE_PREV + Json* _prev; /* next/prev allow you to walk array/object chains. Alternatively, use getSize/getItem */ +#endif + Json* _child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */ + + int _type; /* The type of the item, as above. */ + int _size; /* The number of children. */ + + const char* _valueString; /* The item's string, if type==JSON_STRING */ + int _valueInt; /* The item's number, if type==JSON_NUMBER */ + float _valueFloat; /* The item's number, if type==JSON_NUMBER */ + + const char* _name; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */ + + /* Utility to jump whitespace and cr/lf */ + static const char* skip(const char* inValue); + + /* Parser core - when encountering text, process appropriately. */ + static const char* parseValue(Json *item, const char* value); + + /* Parse the input text into an unescaped cstring, and populate item. */ + static const char* parseString(Json *item, const char* str); + + /* Parse the input text to generate a number, and populate the result into item. */ + static const char* parseNumber(Json *item, const char* num); + + /* Build an array from input text. */ + static const char* parseArray(Json *item, const char* value); + + /* Build an object from the text. */ + static const char* parseObject(Json *item, const char* value); + + static int strcasecmp(const char* s1, const char* s2); + }; } #endif /* Spine_Json_h */ diff --git a/spine-cpp/spine-cpp/include/spine/SkeletonJson.h b/spine-cpp/spine-cpp/include/spine/SkeletonJson.h index 87139437d..cc0c6d7a7 100644 --- a/spine-cpp/spine-cpp/include/spine/SkeletonJson.h +++ b/spine-cpp/spine-cpp/include/spine/SkeletonJson.h @@ -33,8 +33,15 @@ #include +#include + namespace Spine { + class MeshAttachment; + class CurveTimeline; + class VertexAttachment; + class Animation; + class Json; class SkeletonData; class Atlas; class AttachmentLoader; @@ -49,15 +56,28 @@ namespace Spine ~SkeletonJson(); - SkeletonData* readSkeletonData(const char* json); - SkeletonData* readSkeletonDataFile(const char* path); + SkeletonData* readSkeletonData(const char* json); + private: AttachmentLoader* _attachmentLoader; Vector _linkedMeshes; float _scale; const bool _ownsLoader; + std::string _error; + + static float toColor(const char* value, int index); + + static void readCurve(Json* frame, CurveTimeline* timeline, int frameIndex); + + void addLinkedMesh(MeshAttachment* mesh, const char* skin, int slotIndex, const char* parent); + + Animation* readAnimation(Json* root, SkeletonData *skeletonData); + + void readVertices(Json* attachmentMap, VertexAttachment* attachment, int verticesLength); + + void setError(Json* root, const char* value1, const char* value2); }; } diff --git a/spine-cpp/spine-cpp/src/spine/Json.cpp b/spine-cpp/spine-cpp/src/spine/Json.cpp index bb4d2ccfe..80dd36047 100644 --- a/spine-cpp/spine-cpp/src/spine/Json.cpp +++ b/spine-cpp/spine-cpp/src/spine/Json.cpp @@ -28,7 +28,621 @@ * POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ +/* Json */ +/* JSON parser in CPP, shamelessly ripped from json.c in the spine-c runtime */ + +#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 + +#include +#include +#include +#include +#include /* strtod (C89), strtof (C99) */ +#include /* strcasecmp (4.4BSD - compatibility), _stricmp (_WIN32) */ +#include +#include + namespace Spine { - // TODO + const int Json::JSON_FALSE = 0; + const int Json::JSON_TRUE = 1; + const int Json::JSON_NULL = 2; + const int Json::JSON_NUMBER = 3; + const int Json::JSON_STRING = 4; + const int Json::JSON_ARRAY = 5; + const int Json::JSON_OBJECT = 6; + + const char* Json::JSON_ERROR = NULL; + + Json* Json::getItem(Json *object, const char* string) + { + Json *c = object->_child; + while (c && strcasecmp(c->_name, string)) + { + c = c->_next; + } + return c; + } + + const char* Json::getString(Json *object, const char* name, const char* defaultValue) + { + object = getItem(object, name); + if (object) + { + return object->_valueString; + } + + return defaultValue; + } + + float Json::getFloat(Json *value, const char* name, float defaultValue) + { + value = getItem(value, name); + return value ? value->_valueFloat : defaultValue; + } + + int Json::getInt(Json *value, const char* name, int defaultValue) + { + value = getItem(value, name); + return value ? value->_valueInt : defaultValue; + } + + const char* Json::getError() + { + return JSON_ERROR; + } + + Json::Json(const char* value) : + _next(NULL), +#if SPINE_JSON_HAVE_PREV + _prev(NULL), +#endif + _child(NULL), + _type(0), + _size(0), + _valueString(NULL), + _valueInt(0), + _valueFloat(0), + _name(NULL) + { + if (value) + { + value = parseValue(this, skip(value)); + + assert(value); + } + } + + Json::~Json() + { + if (_child) + { + DESTROY(Json, _child); + } + + if (_valueString) + { + FREE(_valueString); + } + + if (_name) + { + FREE(_name); + } + + if (_next) + { + DESTROY(Json, _next); + } + } + + const char* Json::skip(const char* inValue) + { + if (!inValue) + { + /* must propagate NULL since it's often called in skip(f(...)) form */ + return NULL; + } + + while (*inValue && (unsigned char)*inValue <= 32) + { + inValue++; + } + + return inValue; + } + + const char* Json::parseValue(Json *item, const char* value) + { + /* Referenced by constructor, parseArray(), and parseObject(). */ + /* Always called with the result of skip(). */ +#if SPINE_JSON_DEBUG /* Checked at entry to graph, constructor, and after every parse call. */ + if (!value) + { + /* Fail on null. */ + return 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 parseString(item, value); + case '[': + return parseArray(item, value); + case '{': + return parseObject(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 parseNumber(item, value); + default: + break; + } + + JSON_ERROR = value; + return NULL; /* failure. */ + } + + static const unsigned char firstByteMark[7] = {0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC}; + const char* Json::parseString(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 parseValue, but do need from parseObject */ + JSON_ERROR = 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 = NULL; + + if (*ptr == '\"') + { + ptr++; /* TODO error handling if not \" or \0 ? */ + } + + item->_valueString = out; + item->_type = JSON_STRING; + + return ptr; + } + + const char* Json::parseNumber(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 = result; + item->_valueInt = static_cast(result); + item->_type = JSON_NUMBER; + return ptr; + } + else + { + /* Parse failure, JSON_ERROR is set. */ + JSON_ERROR = num; + return NULL; + } + } + + const char* Json::parseArray(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 = NEW(Json); + new (item->_child) Json(NULL); + if (!item->_child) + { + return NULL; /* memory fail */ + } + + value = skip(parseValue(child, skip(value))); /* skip any spacing, get the value. */ + + if (!value) + { + return NULL; + } + + item->_size = 1; + + while (*value == ',') + { + Json *new_item = NEW(Json); + new (new_item) Json(NULL); + if (!new_item) + { + return NULL; /* memory fail */ + } + child->_next = new_item; +#if SPINE_JSON_HAVE_PREV + new_item->prev = child; +#endif + child = new_item; + value = skip(parseValue(child, skip(value + 1))); + if (!value) + { + return NULL; /* parse fail */ + } + item->_size++; + } + + if (*value == ']') + { + return value + 1; /* end of array */ + } + + JSON_ERROR = value; + + return NULL; /* malformed. */ + } + + /* Build an object from the text. */ + const char* Json::parseObject(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 = NEW(Json); + new (item->_child) Json(NULL); + if (!item->_child) + { + return NULL; + } + value = skip(parseString(child, skip(value))); + if (!value) + { + return NULL; + } + child->_name = child->_valueString; + child->_valueString = 0; + if (*value != ':') + { + JSON_ERROR = value; + return NULL; + } /* fail! */ + + value = skip(parseValue(child, skip(value + 1))); /* skip any spacing, get the value. */ + if (!value) + { + return NULL; + } + + item->_size = 1; + + while (*value == ',') + { + Json *new_item = NEW(Json); + new (new_item) Json(NULL); + if (!new_item) + { + return NULL; /* memory fail */ + } + child->_next = new_item; +#if SPINE_JSON_HAVE_PREV + new_item->prev = child; +#endif + child = new_item; + value = skip(parseString(child, skip(value + 1))); + if (!value) + { + return NULL; + } + child->_name = child->_valueString; + child->_valueString = 0; + if (*value != ':') + { + JSON_ERROR = value; + return NULL; + } /* fail! */ + + value = skip(parseValue(child, skip(value + 1))); /* skip any spacing, get the value. */ + if (!value) + { + return NULL; + } + item->_size++; + } + + if (*value == '}') + { + return value + 1; /* end of array */ + } + + JSON_ERROR = value; + + return NULL; /* malformed. */ + } + + 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 */ + } + } + } } diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp b/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp index 482b7cbb5..dd3b04abd 100644 --- a/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp +++ b/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp @@ -30,6 +30,10 @@ #include +#include + +#include +#include #include #include #include @@ -37,6 +41,10 @@ #include #include +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__) +#define strdup _strdup +#endif + namespace Spine { SkeletonJson::SkeletonJson(Vector& atlasArray) : _attachmentLoader(NEW(AtlasAttachmentLoader)), _scale(1), _ownsLoader(true) @@ -59,13 +67,1188 @@ namespace Spine } } + SkeletonData* SkeletonJson::readSkeletonDataFile(const char* path) + { + int length; + SkeletonData* skeletonData; + const char* json = SPINE_EXTENSION->spineReadFile(path, &length); + if (length == 0 || !json) + { + setError(NULL, "Unable to read skeleton file: ", path); + return NULL; + } + + skeletonData = readSkeletonData(json); + + FREE(json); + + return skeletonData; + } + SkeletonData* SkeletonJson::readSkeletonData(const char* json) { +// int i, ii; +// SkeletonData* skeletonData; +// Json *root, *skeleton, *bones, *boneMap, *ik, *transform, *path, *slots, *skins, *animations, *events; +// _spSkeletonJson* internal = SUB_CAST(_spSkeletonJson, self); +// +// FREE(self->error); +// CONST_CAST(char*, self->error) = 0; +// internal->linkedMeshCount = 0; +// +// root = Json_create(json); +// +// if (!root) { +// _spSkeletonJson_setError(self, 0, "Invalid skeleton JSON: ", Json_getError()); +// return 0; +// } +// +// skeletonData = spSkeletonData_create(); +// +// skeleton = Json_getItem(root, "skeleton"); +// if (skeleton) { +// MALLOC_STR(skeletonData->hash, Json_getString(skeleton, "hash", 0)); +// MALLOC_STR(skeletonData->version, Json_getString(skeleton, "spine", 0)); +// skeletonData->width = Json_getFloat(skeleton, "width", 0); +// skeletonData->height = Json_getFloat(skeleton, "height", 0); +// } +// +// /* Bones. */ +// bones = Json_getItem(root, "bones"); +// skeletonData->bones = MALLOC(spBoneData*, bones->size); +// for (boneMap = bones->child, i = 0; boneMap; boneMap = boneMap->next, ++i) { +// spBoneData* data; +// const char* transformMode; +// +// spBoneData* parent = 0; +// const char* parentName = Json_getString(boneMap, "parent", 0); +// if (parentName) { +// parent = spSkeletonData_findBone(skeletonData, parentName); +// if (!parent) { +// spSkeletonData_dispose(skeletonData); +// _spSkeletonJson_setError(self, root, "Parent bone not found: ", parentName); +// return 0; +// } +// } +// +// data = spBoneData_create(skeletonData->bonesCount, Json_getString(boneMap, "name", 0), parent); +// data->length = Json_getFloat(boneMap, "length", 0) * self->scale; +// data->x = Json_getFloat(boneMap, "x", 0) * self->scale; +// data->y = Json_getFloat(boneMap, "y", 0) * self->scale; +// data->rotation = Json_getFloat(boneMap, "rotation", 0); +// data->scaleX = Json_getFloat(boneMap, "scaleX", 1); +// data->scaleY = Json_getFloat(boneMap, "scaleY", 1); +// data->shearX = Json_getFloat(boneMap, "shearX", 0); +// data->shearY = Json_getFloat(boneMap, "shearY", 0); +// transformMode = Json_getString(boneMap, "transform", "normal"); +// data->transformMode = SP_TRANSFORMMODE_NORMAL; +// if (strcmp(transformMode, "normal") == 0) +// data->transformMode = SP_TRANSFORMMODE_NORMAL; +// if (strcmp(transformMode, "onlyTranslation") == 0) +// data->transformMode = SP_TRANSFORMMODE_ONLYTRANSLATION; +// if (strcmp(transformMode, "noRotationOrReflection") == 0) +// data->transformMode = SP_TRANSFORMMODE_NOROTATIONORREFLECTION; +// if (strcmp(transformMode, "noScale") == 0) +// data->transformMode = SP_TRANSFORMMODE_NOSCALE; +// if (strcmp(transformMode, "noScaleOrReflection") == 0) +// data->transformMode = SP_TRANSFORMMODE_NOSCALEORREFLECTION; +// +// skeletonData->bones[i] = data; +// skeletonData->bonesCount++; +// } +// +// /* Slots. */ +// slots = Json_getItem(root, "slots"); +// if (slots) { +// Json *slotMap; +// skeletonData->slotsCount = slots->size; +// skeletonData->slots = MALLOC(spSlotData*, slots->size); +// for (slotMap = slots->child, i = 0; slotMap; slotMap = slotMap->next, ++i) { +// spSlotData* data; +// const char* color; +// const char* dark; +// Json *item; +// +// const char* boneName = Json_getString(slotMap, "bone", 0); +// spBoneData* boneData = spSkeletonData_findBone(skeletonData, boneName); +// if (!boneData) { +// spSkeletonData_dispose(skeletonData); +// _spSkeletonJson_setError(self, root, "Slot bone not found: ", boneName); +// return 0; +// } +// +// data = spSlotData_create(i, Json_getString(slotMap, "name", 0), boneData); +// +// color = Json_getString(slotMap, "color", 0); +// if (color) { +// spColor_setFromFloats(&data->color, +// toColor(color, 0), +// toColor(color, 1), +// toColor(color, 2), +// toColor(color, 3)); +// } +// +// dark = Json_getString(slotMap, "dark", 0); +// if (dark) { +// data->darkColor = spColor_create(); +// spColor_setFromFloats(data->darkColor, +// toColor(dark, 0), +// toColor(dark, 1), +// toColor(dark, 2), +// toColor(dark, 3)); +// } +// +// item = Json_getItem(slotMap, "attachment"); +// if (item) spSlotData_setAttachmentName(data, item->valueString); +// +// item = Json_getItem(slotMap, "blend"); +// if (item) { +// if (strcmp(item->valueString, "additive") == 0) +// data->blendMode = SP_BLEND_MODE_ADDITIVE; +// else if (strcmp(item->valueString, "multiply") == 0) +// data->blendMode = SP_BLEND_MODE_MULTIPLY; +// else if (strcmp(item->valueString, "screen") == 0) +// data->blendMode = SP_BLEND_MODE_SCREEN; +// } +// +// skeletonData->slots[i] = data; +// } +// } +// +// /* IK constraints. */ +// ik = Json_getItem(root, "ik"); +// if (ik) { +// Json *constraintMap; +// skeletonData->ikConstraintsCount = ik->size; +// skeletonData->ikConstraints = MALLOC(spIkConstraintData*, ik->size); +// for (constraintMap = ik->child, i = 0; constraintMap; constraintMap = constraintMap->next, ++i) { +// const char* targetName; +// +// spIkConstraintData* data = spIkConstraintData_create(Json_getString(constraintMap, "name", 0)); +// data->order = Json_getInt(constraintMap, "order", 0); +// +// boneMap = Json_getItem(constraintMap, "bones"); +// data->bonesCount = boneMap->size; +// data->bones = MALLOC(spBoneData*, boneMap->size); +// for (boneMap = boneMap->child, ii = 0; boneMap; boneMap = boneMap->next, ++ii) { +// data->bones[ii] = spSkeletonData_findBone(skeletonData, boneMap->valueString); +// if (!data->bones[ii]) { +// spSkeletonData_dispose(skeletonData); +// _spSkeletonJson_setError(self, root, "IK bone not found: ", boneMap->valueString); +// return 0; +// } +// } +// +// targetName = Json_getString(constraintMap, "target", 0); +// data->target = spSkeletonData_findBone(skeletonData, targetName); +// if (!data->target) { +// spSkeletonData_dispose(skeletonData); +// _spSkeletonJson_setError(self, root, "Target bone not found: ", boneMap->name); +// return 0; +// } +// +// data->bendDirection = Json_getInt(constraintMap, "bendPositive", 1) ? 1 : -1; +// data->mix = Json_getFloat(constraintMap, "mix", 1); +// +// skeletonData->ikConstraints[i] = data; +// } +// } +// +// /* Transform constraints. */ +// transform = Json_getItem(root, "transform"); +// if (transform) { +// Json *constraintMap; +// skeletonData->transformConstraintsCount = transform->size; +// skeletonData->transformConstraints = MALLOC(spTransformConstraintData*, transform->size); +// for (constraintMap = transform->child, i = 0; constraintMap; constraintMap = constraintMap->next, ++i) { +// const char* name; +// +// spTransformConstraintData* data = spTransformConstraintData_create(Json_getString(constraintMap, "name", 0)); +// data->order = Json_getInt(constraintMap, "order", 0); +// +// boneMap = Json_getItem(constraintMap, "bones"); +// data->bonesCount = boneMap->size; +// CONST_CAST(spBoneData**, data->bones) = MALLOC(spBoneData*, boneMap->size); +// for (boneMap = boneMap->child, ii = 0; boneMap; boneMap = boneMap->next, ++ii) { +// data->bones[ii] = spSkeletonData_findBone(skeletonData, boneMap->valueString); +// if (!data->bones[ii]) { +// spSkeletonData_dispose(skeletonData); +// _spSkeletonJson_setError(self, root, "Transform bone not found: ", boneMap->valueString); +// return 0; +// } +// } +// +// name = Json_getString(constraintMap, "target", 0); +// data->target = spSkeletonData_findBone(skeletonData, name); +// if (!data->target) { +// spSkeletonData_dispose(skeletonData); +// _spSkeletonJson_setError(self, root, "Target bone not found: ", boneMap->name); +// return 0; +// } +// +// data->local = Json_getInt(constraintMap, "local", 0); +// data->relative = Json_getInt(constraintMap, "relative", 0); +// data->offsetRotation = Json_getFloat(constraintMap, "rotation", 0); +// data->offsetX = Json_getFloat(constraintMap, "x", 0) * self->scale; +// data->offsetY = Json_getFloat(constraintMap, "y", 0) * self->scale; +// data->offsetScaleX = Json_getFloat(constraintMap, "scaleX", 0); +// data->offsetScaleY = Json_getFloat(constraintMap, "scaleY", 0); +// data->offsetShearY = Json_getFloat(constraintMap, "shearY", 0); +// +// data->rotateMix = Json_getFloat(constraintMap, "rotateMix", 1); +// data->translateMix = Json_getFloat(constraintMap, "translateMix", 1); +// data->scaleMix = Json_getFloat(constraintMap, "scaleMix", 1); +// data->shearMix = Json_getFloat(constraintMap, "shearMix", 1); +// +// skeletonData->transformConstraints[i] = data; +// } +// } +// +// /* Path constraints */ +// path = Json_getItem(root, "path"); +// if (path) { +// Json *constraintMap; +// skeletonData->pathConstraintsCount = path->size; +// skeletonData->pathConstraints = MALLOC(spPathConstraintData*, path->size); +// for (constraintMap = path->child, i = 0; constraintMap; constraintMap = constraintMap->next, ++i) { +// const char* name; +// const char* item; +// +// spPathConstraintData* data = spPathConstraintData_create(Json_getString(constraintMap, "name", 0)); +// data->order = Json_getInt(constraintMap, "order", 0); +// +// boneMap = Json_getItem(constraintMap, "bones"); +// data->bonesCount = boneMap->size; +// CONST_CAST(spBoneData**, data->bones) = MALLOC(spBoneData*, boneMap->size); +// for (boneMap = boneMap->child, ii = 0; boneMap; boneMap = boneMap->next, ++ii) { +// data->bones[ii] = spSkeletonData_findBone(skeletonData, boneMap->valueString); +// if (!data->bones[ii]) { +// spSkeletonData_dispose(skeletonData); +// _spSkeletonJson_setError(self, root, "Path bone not found: ", boneMap->valueString); +// return 0; +// } +// } +// +// name = Json_getString(constraintMap, "target", 0); +// data->target = spSkeletonData_findSlot(skeletonData, name); +// if (!data->target) { +// spSkeletonData_dispose(skeletonData); +// _spSkeletonJson_setError(self, root, "Target slot not found: ", boneMap->name); +// return 0; +// } +// +// item = Json_getString(constraintMap, "positionMode", "percent"); +// if (strcmp(item, "fixed") == 0) data->positionMode = SP_POSITION_MODE_FIXED; +// else if (strcmp(item, "percent") == 0) data->positionMode = SP_POSITION_MODE_PERCENT; +// +// item = Json_getString(constraintMap, "spacingMode", "length"); +// if (strcmp(item, "length") == 0) data->spacingMode = SP_SPACING_MODE_LENGTH; +// else if (strcmp(item, "fixed") == 0) data->spacingMode = SP_SPACING_MODE_FIXED; +// else if (strcmp(item, "percent") == 0) data->spacingMode = SP_SPACING_MODE_PERCENT; +// +// item = Json_getString(constraintMap, "rotateMode", "tangent"); +// if (strcmp(item, "tangent") == 0) data->rotateMode = SP_ROTATE_MODE_TANGENT; +// else if (strcmp(item, "chain") == 0) data->rotateMode = SP_ROTATE_MODE_CHAIN; +// else if (strcmp(item, "chainScale") == 0) data->rotateMode = SP_ROTATE_MODE_CHAIN_SCALE; +// +// data->offsetRotation = Json_getFloat(constraintMap, "rotation", 0); +// data->position = Json_getFloat(constraintMap, "position", 0); +// if (data->positionMode == SP_POSITION_MODE_FIXED) data->position *= self->scale; +// data->spacing = Json_getFloat(constraintMap, "spacing", 0); +// if (data->spacingMode == SP_SPACING_MODE_LENGTH || data->spacingMode == SP_SPACING_MODE_FIXED) data->spacing *= self->scale; +// data->rotateMix = Json_getFloat(constraintMap, "rotateMix", 1); +// data->translateMix = Json_getFloat(constraintMap, "translateMix", 1); +// +// skeletonData->pathConstraints[i] = data; +// } +// } +// +// /* Skins. */ +// skins = Json_getItem(root, "skins"); +// if (skins) { +// Json *skinMap; +// skeletonData->skins = MALLOC(spSkin*, skins->size); +// for (skinMap = skins->child, i = 0; skinMap; skinMap = skinMap->next, ++i) { +// Json *attachmentsMap; +// Json *curves; +// spSkin *skin = spSkin_create(skinMap->name); +// +// skeletonData->skins[skeletonData->skinsCount++] = skin; +// if (strcmp(skinMap->name, "default") == 0) skeletonData->defaultSkin = skin; +// +// for (attachmentsMap = skinMap->child; attachmentsMap; attachmentsMap = attachmentsMap->next) { +// int slotIndex = spSkeletonData_findSlotIndex(skeletonData, attachmentsMap->name); +// Json *attachmentMap; +// +// for (attachmentMap = attachmentsMap->child; attachmentMap; attachmentMap = attachmentMap->next) { +// spAttachment* attachment; +// const char* skinAttachmentName = attachmentMap->name; +// const char* attachmentName = Json_getString(attachmentMap, "name", skinAttachmentName); +// const char* attachmentPath = Json_getString(attachmentMap, "path", attachmentName); +// const char* color; +// Json* entry; +// +// const char* typeString = Json_getString(attachmentMap, "type", "region"); +// spAttachmentType type; +// if (strcmp(typeString, "region") == 0) +// type = SP_ATTACHMENT_REGION; +// else if (strcmp(typeString, "mesh") == 0) +// type = SP_ATTACHMENT_MESH; +// else if (strcmp(typeString, "linkedmesh") == 0) +// type = SP_ATTACHMENT_LINKED_MESH; +// else if (strcmp(typeString, "boundingbox") == 0) +// type = SP_ATTACHMENT_BOUNDING_BOX; +// else if (strcmp(typeString, "path") == 0) +// type = SP_ATTACHMENT_PATH; +// else if (strcmp(typeString, "clipping") == 0) +// type = SP_ATTACHMENT_CLIPPING; +// else { +// spSkeletonData_dispose(skeletonData); +// _spSkeletonJson_setError(self, root, "Unknown attachment type: ", typeString); +// return 0; +// } +// +// attachment = spAttachmentLoader_createAttachment(self->attachmentLoader, skin, type, attachmentName, attachmentPath); +// if (!attachment) { +// if (self->attachmentLoader->error1) { +// spSkeletonData_dispose(skeletonData); +// _spSkeletonJson_setError(self, root, self->attachmentLoader->error1, self->attachmentLoader->error2); +// return 0; +// } +// continue; +// } +// +// switch (attachment->type) { +// case SP_ATTACHMENT_REGION: { +// spRegionAttachment* region = SUB_CAST(spRegionAttachment, attachment); +// if (path) MALLOC_STR(region->path, attachmentPath); +// region->x = Json_getFloat(attachmentMap, "x", 0) * self->scale; +// region->y = Json_getFloat(attachmentMap, "y", 0) * self->scale; +// region->scaleX = Json_getFloat(attachmentMap, "scaleX", 1); +// region->scaleY = Json_getFloat(attachmentMap, "scaleY", 1); +// region->rotation = Json_getFloat(attachmentMap, "rotation", 0); +// region->width = Json_getFloat(attachmentMap, "width", 32) * self->scale; +// region->height = Json_getFloat(attachmentMap, "height", 32) * self->scale; +// +// color = Json_getString(attachmentMap, "color", 0); +// if (color) { +// spColor_setFromFloats(®ion->color, +// toColor(color, 0), +// toColor(color, 1), +// toColor(color, 2), +// toColor(color, 3)); +// } +// +// spRegionAttachment_updateOffset(region); +// +// spAttachmentLoader_configureAttachment(self->attachmentLoader, attachment); +// break; +// } +// case SP_ATTACHMENT_MESH: +// case SP_ATTACHMENT_LINKED_MESH: { +// spMeshAttachment* mesh = SUB_CAST(spMeshAttachment, attachment); +// +// MALLOC_STR(mesh->path, attachmentPath); +// +// color = Json_getString(attachmentMap, "color", 0); +// if (color) { +// spColor_setFromFloats(&mesh->color, +// toColor(color, 0), +// toColor(color, 1), +// toColor(color, 2), +// toColor(color, 3)); +// } +// +// mesh->width = Json_getFloat(attachmentMap, "width", 32) * self->scale; +// mesh->height = Json_getFloat(attachmentMap, "height", 32) * self->scale; +// +// entry = Json_getItem(attachmentMap, "parent"); +// if (!entry) { +// int verticesLength; +// entry = Json_getItem(attachmentMap, "triangles"); +// mesh->trianglesCount = entry->size; +// mesh->triangles = MALLOC(unsigned short, entry->size); +// for (entry = entry->child, ii = 0; entry; entry = entry->next, ++ii) +// mesh->triangles[ii] = (unsigned short)entry->valueInt; +// +// entry = Json_getItem(attachmentMap, "uvs"); +// verticesLength = entry->size; +// mesh->regionUVs = MALLOC(float, verticesLength); +// for (entry = entry->child, ii = 0; entry; entry = entry->next, ++ii) +// mesh->regionUVs[ii] = entry->valueFloat; +// +// _readVertices(self, attachmentMap, SUPER(mesh), verticesLength); +// +// spMeshAttachment_updateUVs(mesh); +// +// mesh->hullLength = Json_getInt(attachmentMap, "hull", 0); +// +// entry = Json_getItem(attachmentMap, "edges"); +// if (entry) { +// mesh->edgesCount = entry->size; +// mesh->edges = MALLOC(int, entry->size); +// for (entry = entry->child, ii = 0; entry; entry = entry->next, ++ii) +// mesh->edges[ii] = entry->valueInt; +// } +// +// spAttachmentLoader_configureAttachment(self->attachmentLoader, attachment); +// } else { +// mesh->inheritDeform = Json_getInt(attachmentMap, "deform", 1); +// _spSkeletonJson_addLinkedMesh(self, SUB_CAST(spMeshAttachment, attachment), Json_getString(attachmentMap, "skin", 0), slotIndex, +// entry->valueString); +// } +// break; +// } +// case SP_ATTACHMENT_BOUNDING_BOX: { +// spBoundingBoxAttachment* box = SUB_CAST(spBoundingBoxAttachment, attachment); +// int vertexCount = Json_getInt(attachmentMap, "vertexCount", 0) << 1; +// _readVertices(self, attachmentMap, SUPER(box), vertexCount); +// box->super.verticesCount = vertexCount; +// spAttachmentLoader_configureAttachment(self->attachmentLoader, attachment); +// break; +// } +// case SP_ATTACHMENT_PATH: { +// spPathAttachment* pathAttatchment = SUB_CAST(spPathAttachment, attachment); +// int vertexCount = 0; +// pathAttatchment->closed = Json_getInt(attachmentMap, "closed", 0); +// pathAttatchment->constantSpeed = Json_getInt(attachmentMap, "constantSpeed", 1); +// vertexCount = Json_getInt(attachmentMap, "vertexCount", 0); +// _readVertices(self, attachmentMap, SUPER(pathAttatchment), vertexCount << 1); +// +// pathAttatchment->lengthsLength = vertexCount / 3; +// pathAttatchment->lengths = MALLOC(float, pathAttatchment->lengthsLength); +// +// curves = Json_getItem(attachmentMap, "lengths"); +// for (curves = curves->child, ii = 0; curves; curves = curves->next, ++ii) { +// pathAttatchment->lengths[ii] = curves->valueFloat * self->scale; +// } +// break; +// } +// case SP_ATTACHMENT_POINT: { +// spPointAttachment* point = SUB_CAST(spPointAttachment, attachment); +// point->x = Json_getFloat(attachmentMap, "x", 0) * self->scale; +// point->y = Json_getFloat(attachmentMap, "y", 0) * self->scale; +// point->rotation = Json_getFloat(attachmentMap, "rotation", 0); +// +// color = Json_getString(attachmentMap, "color", 0); +// if (color) { +// spColor_setFromFloats(&point->color, +// toColor(color, 0), +// toColor(color, 1), +// toColor(color, 2), +// toColor(color, 3)); +// } +// break; +// } +// case SP_ATTACHMENT_CLIPPING: { +// spClippingAttachment* clip = SUB_CAST(spClippingAttachment, attachment); +// int vertexCount = 0; +// const char* end = Json_getString(attachmentMap, "end", 0); +// if (end) { +// spSlotData* slot = spSkeletonData_findSlot(skeletonData, end); +// clip->endSlot = slot; +// } +// vertexCount = Json_getInt(attachmentMap, "vertexCount", 0) << 1; +// _readVertices(self, attachmentMap, SUPER(clip), vertexCount); +// spAttachmentLoader_configureAttachment(self->attachmentLoader, attachment); +// break; +// } +// } +// +// spSkin_addAttachment(skin, slotIndex, skinAttachmentName, attachment); +// } +// } +// } +// } +// +// /* Linked meshes. */ +// for (i = 0; i < internal->linkedMeshCount; i++) { +// spAttachment* parent; +// _spLinkedMesh* linkedMesh = internal->linkedMeshes + i; +// spSkin* skin = !linkedMesh->skin ? skeletonData->defaultSkin : spSkeletonData_findSkin(skeletonData, linkedMesh->skin); +// if (!skin) { +// spSkeletonData_dispose(skeletonData); +// _spSkeletonJson_setError(self, 0, "Skin not found: ", linkedMesh->skin); +// return 0; +// } +// parent = spSkin_getAttachment(skin, linkedMesh->slotIndex, linkedMesh->parent); +// if (!parent) { +// spSkeletonData_dispose(skeletonData); +// _spSkeletonJson_setError(self, 0, "Parent mesh not found: ", linkedMesh->parent); +// return 0; +// } +// spMeshAttachment_setParentMesh(linkedMesh->mesh, SUB_CAST(spMeshAttachment, parent)); +// spMeshAttachment_updateUVs(linkedMesh->mesh); +// spAttachmentLoader_configureAttachment(self->attachmentLoader, SUPER(SUPER(linkedMesh->mesh))); +// } +// +// /* Events. */ +// events = Json_getItem(root, "events"); +// if (events) { +// Json *eventMap; +// const char* stringValue; +// skeletonData->eventsCount = events->size; +// skeletonData->events = MALLOC(spEventData*, events->size); +// for (eventMap = events->child, i = 0; eventMap; eventMap = eventMap->next, ++i) { +// spEventData* eventData = spEventData_create(eventMap->name); +// eventData->intValue = Json_getInt(eventMap, "int", 0); +// eventData->floatValue = Json_getFloat(eventMap, "float", 0); +// stringValue = Json_getString(eventMap, "string", 0); +// if (stringValue) MALLOC_STR(eventData->stringValue, stringValue); +// skeletonData->events[i] = eventData; +// } +// } +// +// /* Animations. */ +// animations = Json_getItem(root, "animations"); +// if (animations) { +// Json *animationMap; +// skeletonData->animations = MALLOC(spAnimation*, animations->size); +// for (animationMap = animations->child; animationMap; animationMap = animationMap->next) { +// spAnimation* animation = _spSkeletonJson_readAnimation(self, animationMap, skeletonData); +// if (!animation) { +// spSkeletonData_dispose(skeletonData); +// return 0; +// } +// skeletonData->animations[skeletonData->animationsCount++] = animation; +// } +// } +// +// Json_dispose(root); +// return skeletonData; return NULL; } - SkeletonData* SkeletonJson::readSkeletonDataFile(const char* path) + float SkeletonJson::toColor(const char* value, int index) { +// char digits[3]; +// char *error; +// int color; +// +// if (index >= strlen(value) / 2) +// { +// return -1; +// } +// +// value += index * 2; +// +// digits[0] = *value; +// digits[1] = *(value + 1); +// digits[2] = '\0'; +// color = (int)strtoul(digits, &error, 16); +// if (*error != 0) +// { +// return -1; +// } +// return color / (float)255; + return 0; + } + + void SkeletonJson::readCurve(Json* frame, CurveTimeline* timeline, int frameIndex) + { +// Json* curve = Json_getItem(frame, "curve"); +// if (!curve) +// { +// return; +// } +// if (curve->type == JSON_STRING && strcmp(curve->valueString, "stepped") == 0) +// { +// spCurveTimeline_setStepped(timeline, frameIndex); +// } +// else if (curve->type == JSON_ARRAY) +// { +// Json* child0 = curve->child; +// Json* child1 = child0->next; +// Json* child2 = child1->next; +// Json* child3 = child2->next; +// spCurveTimeline_setCurve(timeline, frameIndex, child0->valueFloat, child1->valueFloat, child2->valueFloat, child3->valueFloat); +// } + } + + void SkeletonJson::addLinkedMesh(MeshAttachment* mesh, const char* skin, int slotIndex, const char* parent) + { +// _spLinkedMesh* linkedMesh; +// _spSkeletonJson* internal = SUB_CAST(_spSkeletonJson, self); +// +// if (internal->linkedMeshCount == internal->linkedMeshCapacity) +// { +// _spLinkedMesh* linkedMeshes; +// internal->linkedMeshCapacity *= 2; +// if (internal->linkedMeshCapacity < 8) internal->linkedMeshCapacity = 8; +// linkedMeshes = MALLOC(_spLinkedMesh, internal->linkedMeshCapacity); +// memcpy(linkedMeshes, internal->linkedMeshes, sizeof(_spLinkedMesh) * internal->linkedMeshCount); +// FREE(internal->linkedMeshes); +// internal->linkedMeshes = linkedMeshes; +// } +// +// linkedMesh = internal->linkedMeshes + internal->linkedMeshCount++; +// linkedMesh->mesh = mesh; +// linkedMesh->skin = skin; +// linkedMesh->slotIndex = slotIndex; +// linkedMesh->parent = parent; + } + + Animation* SkeletonJson::readAnimation(Json* root, SkeletonData *skeletonData) + { +// int frameIndex; +// spAnimation* animation; +// Json* valueMap; +// int timelinesCount = 0; +// +// Json* bones = Json_getItem(root, "bones"); +// Json* slots = Json_getItem(root, "slots"); +// Json* ik = Json_getItem(root, "ik"); +// Json* transform = Json_getItem(root, "transform"); +// Json* paths = Json_getItem(root, "paths"); +// Json* deform = Json_getItem(root, "deform"); +// Json* drawOrder = Json_getItem(root, "drawOrder"); +// Json* events = Json_getItem(root, "events"); +// Json *boneMap, *slotMap, *constraintMap; +// if (!drawOrder) drawOrder = Json_getItem(root, "draworder"); +// +// for (boneMap = bones ? bones->child : 0; boneMap; boneMap = boneMap->next) +// { +// timelinesCount += boneMap->size; +// } +// for (slotMap = slots ? slots->child : 0; slotMap; slotMap = slotMap->next) +// { +// timelinesCount += slotMap->size; +// } +// timelinesCount += ik ? ik->size : 0; +// timelinesCount += transform ? transform->size : 0; +// for (constraintMap = paths ? paths->child : 0; constraintMap; constraintMap = constraintMap->next) +// { +// timelinesCount += constraintMap->size; +// } +// for (constraintMap = deform ? deform->child : 0; constraintMap; constraintMap = constraintMap->next) +// { +// for (slotMap = constraintMap->child; slotMap; slotMap = slotMap->next) +// { +// timelinesCount += slotMap->size; +// } +// } +// if (drawOrder) +// { +// ++timelinesCount; +// } +// if (events) +// { +// ++timelinesCount; +// } +// +// animation = spAnimation_create(root->name, timelinesCount); +// animation->timelinesCount = 0; +// +// /* Slot timelines. */ +// for (slotMap = slots ? slots->child : 0; slotMap; slotMap = slotMap->next) +// { +// Json *timelineMap; +// +// int slotIndex = spSkeletonData_findSlotIndex(skeletonData, slotMap->name); +// if (slotIndex == -1) +// { +// spAnimation_dispose(animation); +// _spSkeletonJson_setError(self, root, "Slot not found: ", slotMap->name); +// return 0; +// } +// +// for (timelineMap = slotMap->child; timelineMap; timelineMap = timelineMap->next) +// { +// if (strcmp(timelineMap->name, "attachment") == 0) +// { +// spAttachmentTimeline *timeline = spAttachmentTimeline_create(timelineMap->size); +// timeline->slotIndex = slotIndex; +// +// for (valueMap = timelineMap->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) +// { +// Json* name = Json_getItem(valueMap, "name"); +// spAttachmentTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), name->type == Json_NULL ? 0 : name->valueString); +// } +// animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); +// animation->duration = MAX(animation->duration, timeline->frames[timelineMap->size - 1]); +// +// } +// else if (strcmp(timelineMap->name, "color") == 0) +// { +// spColorTimeline *timeline = spColorTimeline_create(timelineMap->size); +// timeline->slotIndex = slotIndex; +// +// for (valueMap = timelineMap->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) +// { +// const char* s = Json_getString(valueMap, "color", 0); +// spColorTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), toColor(s, 0), toColor(s, 1), toColor(s, 2), toColor(s, 3)); +// readCurve(valueMap, SUPER(timeline), frameIndex); +// } +// animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); +// animation->duration = MAX(animation->duration, timeline->frames[(timelineMap->size - 1) * COLOR_ENTRIES]); +// +// } +// else if (strcmp(timelineMap->name, "twoColor") == 0) +// { +// spTwoColorTimeline *timeline = spTwoColorTimeline_create(timelineMap->size); +// timeline->slotIndex = slotIndex; +// +// for (valueMap = timelineMap->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) +// { +// const char* s = Json_getString(valueMap, "light", 0); +// const char* ds = Json_getString(valueMap, "dark", 0); +// spTwoColorTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), toColor(s, 0), toColor(s, 1), toColor(s, 2), +// toColor(s, 3), toColor(ds, 0), toColor(ds, 1), toColor(ds, 2)); +// readCurve(valueMap, SUPER(timeline), frameIndex); +// } +// animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); +// animation->duration = MAX(animation->duration, timeline->frames[(timelineMap->size - 1) * TWOCOLOR_ENTRIES]); +// } +// else +// { +// spAnimation_dispose(animation); +// _spSkeletonJson_setError(self, 0, "Invalid timeline type for a slot: ", timelineMap->name); +// return 0; +// } +// } +// } +// +// /* Bone timelines. */ +// for (boneMap = bones ? bones->child : 0; boneMap; boneMap = boneMap->next) +// { +// Json *timelineMap; +// +// int boneIndex = spSkeletonData_findBoneIndex(skeletonData, boneMap->name); +// if (boneIndex == -1) +// { +// spAnimation_dispose(animation); +// _spSkeletonJson_setError(self, root, "Bone not found: ", boneMap->name); +// return 0; +// } +// +// for (timelineMap = boneMap->child; timelineMap; timelineMap = timelineMap->next) +// { +// if (strcmp(timelineMap->name, "rotate") == 0) +// { +// spRotateTimeline *timeline = spRotateTimeline_create(timelineMap->size); +// timeline->boneIndex = boneIndex; +// +// for (valueMap = timelineMap->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) +// { +// spRotateTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), Json_getFloat(valueMap, "angle", 0)); +// readCurve(valueMap, SUPER(timeline), frameIndex); +// } +// animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); +// animation->duration = MAX(animation->duration, timeline->frames[(timelineMap->size - 1) * ROTATE_ENTRIES]); +// } +// else +// { +// int isScale = strcmp(timelineMap->name, "scale") == 0; +// int isTranslate = strcmp(timelineMap->name, "translate") == 0; +// int isShear = strcmp(timelineMap->name, "shear") == 0; +// if (isScale || isTranslate || isShear) +// { +// float timelineScale = isTranslate ? self->scale: 1; +// spTranslateTimeline *timeline = 0; +// if (isScale) +// { +// timeline = spScaleTimeline_create(timelineMap->size); +// } +// else if (isTranslate) +// { +// timeline = spTranslateTimeline_create(timelineMap->size); +// } +// else if (isShear) +// { +// timeline = spShearTimeline_create(timelineMap->size); +// } +// timeline->boneIndex = boneIndex; +// +// for (valueMap = timelineMap->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) +// { +// spTranslateTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), Json_getFloat(valueMap, "x", 0) * timelineScale, Json_getFloat(valueMap, "y", 0) * timelineScale); +// readCurve(valueMap, SUPER(timeline), frameIndex); +// } +// +// animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); +// animation->duration = MAX(animation->duration, timeline->frames[(timelineMap->size - 1) * TRANSLATE_ENTRIES]); +// } +// else +// { +// spAnimation_dispose(animation); +// _spSkeletonJson_setError(self, 0, "Invalid timeline type for a bone: ", timelineMap->name); +// return 0; +// } +// } +// } +// } +// +// /* IK constraint timelines. */ +// for (constraintMap = ik ? ik->child : 0; constraintMap; constraintMap = constraintMap->next) +// { +// spIkConstraintData* constraint = spSkeletonData_findIkConstraint(skeletonData, constraintMap->name); +// spIkConstraintTimeline* timeline = spIkConstraintTimeline_create(constraintMap->size); +// for (frameIndex = 0; frameIndex < skeletonData->ikConstraintsCount; ++frameIndex) +// { +// if (constraint == skeletonData->ikConstraints[frameIndex]) +// { +// timeline->ikConstraintIndex = frameIndex; +// break; +// } +// } +// for (valueMap = constraintMap->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) +// { +// spIkConstraintTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), Json_getFloat(valueMap, "mix", 1), Json_getInt(valueMap, "bendPositive", 1) ? 1 : -1); +// readCurve(valueMap, SUPER(timeline), frameIndex); +// } +// animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); +// animation->duration = MAX(animation->duration, timeline->frames[(constraintMap->size - 1) * IKCONSTRAINT_ENTRIES]); +// } +// +// /* Transform constraint timelines. */ +// for (constraintMap = transform ? transform->child : 0; constraintMap; constraintMap = constraintMap->next) +// { +// spTransformConstraintData* constraint = spSkeletonData_findTransformConstraint(skeletonData, constraintMap->name); +// spTransformConstraintTimeline* timeline = spTransformConstraintTimeline_create(constraintMap->size); +// for (frameIndex = 0; frameIndex < skeletonData->transformConstraintsCount; ++frameIndex) +// { +// if (constraint == skeletonData->transformConstraints[frameIndex]) +// { +// timeline->transformConstraintIndex = frameIndex; +// break; +// } +// } +// for (valueMap = constraintMap->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) +// { +// spTransformConstraintTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), Json_getFloat(valueMap, "rotateMix", 1), Json_getFloat(valueMap, "translateMix", 1), Json_getFloat(valueMap, "scaleMix", 1), Json_getFloat(valueMap, "shearMix", 1)); +// readCurve(valueMap, SUPER(timeline), frameIndex); +// } +// animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); +// animation->duration = MAX(animation->duration, timeline->frames[(constraintMap->size - 1) * TRANSFORMCONSTRAINT_ENTRIES]); +// } +// +// /** Path constraint timelines. */ +// for (constraintMap = paths ? paths->child : 0; constraintMap; constraintMap = constraintMap->next) +// { +// int constraintIndex, i; +// Json* timelineMap; +// +// spPathConstraintData* data = spSkeletonData_findPathConstraint(skeletonData, constraintMap->name); +// if (!data) +// { +// spAnimation_dispose(animation); +// _spSkeletonJson_setError(self, root, "Path constraint not found: ", constraintMap->name); +// return 0; +// } +// +// for (i = 0; i < skeletonData->pathConstraintsCount; i++) +// { +// if (skeletonData->pathConstraints[i] == data) +// { +// constraintIndex = i; +// break; +// } +// } +// +// for (timelineMap = constraintMap->child; timelineMap; timelineMap = timelineMap->next) +// { +// const char* timelineName = timelineMap->name; +// if (strcmp(timelineName, "position") == 0 || strcmp(timelineName, "spacing") == 0) +// { +// spPathConstraintPositionTimeline* timeline; +// float timelineScale = 1; +// if (strcmp(timelineName, "spacing") == 0) +// { +// timeline = (spPathConstraintPositionTimeline*)spPathConstraintSpacingTimeline_create(timelineMap->size); +// if (data->spacingMode == SP_SPACING_MODE_LENGTH || data->spacingMode == SP_SPACING_MODE_FIXED) +// { +// timelineScale = self->scale; +// } +// } +// else +// { +// timeline = spPathConstraintPositionTimeline_create(timelineMap->size); +// if (data->positionMode == SP_POSITION_MODE_FIXED) +// { +// timelineScale = self->scale; +// } +// } +// +// timeline->pathConstraintIndex = constraintIndex; +// for (valueMap = timelineMap->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) +// { +// spPathConstraintPositionTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), Json_getFloat(valueMap, timelineName, 0) * timelineScale); +// readCurve(valueMap, SUPER(timeline), frameIndex); +// } +// animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); +// animation->duration = MAX(animation->duration, timeline->frames[(timelineMap->size - 1) * PATHCONSTRAINTPOSITION_ENTRIES]); +// } +// else if (strcmp(timelineName, "mix") == 0) +// { +// spPathConstraintMixTimeline* timeline = spPathConstraintMixTimeline_create(timelineMap->size); +// timeline->pathConstraintIndex = constraintIndex; +// for (valueMap = timelineMap->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) +// { +// spPathConstraintMixTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), Json_getFloat(valueMap, "rotateMix", 1), Json_getFloat(valueMap, "translateMix", 1)); +// readCurve(valueMap, SUPER(timeline), frameIndex); +// } +// animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); +// animation->duration = MAX(animation->duration, timeline->frames[(timelineMap->size - 1) * PATHCONSTRAINTMIX_ENTRIES]); +// } +// } +// } +// +// /* Deform timelines. */ +// for (constraintMap = deform ? deform->child : 0; constraintMap; constraintMap = constraintMap->next) +// { +// spSkin* skin = spSkeletonData_findSkin(skeletonData, constraintMap->name); +// for (slotMap = constraintMap->child; slotMap; slotMap = slotMap->next) +// { +// int slotIndex = spSkeletonData_findSlotIndex(skeletonData, slotMap->name); +// Json* timelineMap; +// for (timelineMap = slotMap->child; timelineMap; timelineMap = timelineMap->next) +// { +// float* tempDeform; +// spDeformTimeline *timeline; +// int weighted, deformLength; +// +// spVertexAttachment* attachment = SUB_CAST(spVertexAttachment, spSkin_getAttachment(skin, slotIndex, timelineMap->name)); +// if (!attachment) +// { +// spAnimation_dispose(animation); +// _spSkeletonJson_setError(self, 0, "Attachment not found: ", timelineMap->name); +// return 0; +// } +// weighted = attachment->bones != 0; +// deformLength = weighted ? attachment->verticesCount / 3 * 2 : attachment->verticesCount; +// tempDeform = MALLOC(float, deformLength); +// +// timeline = spDeformTimeline_create(timelineMap->size, deformLength); +// timeline->slotIndex = slotIndex; +// timeline->attachment = SUPER(attachment); +// +// for (valueMap = timelineMap->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) +// { +// Json* vertices = Json_getItem(valueMap, "vertices"); +// float* deform2; +// if (!vertices) +// { +// if (weighted) +// { +// deform2 = tempDeform; +// memset(deform, 0, sizeof(float) * deformLength); +// } +// else +// { +// deform2 = attachment->vertices; +// } +// } +// else +// { +// int v, start = Json_getInt(valueMap, "offset", 0); +// Json* vertex; +// deform2 = tempDeform; +// memset(deform, 0, sizeof(float) * start); +// if (self->scale == 1) +// { +// for (vertex = vertices->child, v = start; vertex; vertex = vertex->next, ++v) +// { +// deform2[v] = vertex->valueFloat; +// } +// } +// else +// { +// for (vertex = vertices->child, v = start; vertex; vertex = vertex->next, ++v) +// { +// deform2[v] = vertex->valueFloat * self->scale; +// } +// } +// memset(deform + v, 0, sizeof(float) * (deformLength - v)); +// if (!weighted) +// { +// float* verticesAttachment = attachment->vertices; +// for (v = 0; v < deformLength; ++v) +// { +// deform2[v] += verticesAttachment[v]; +// } +// } +// } +// spDeformTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), deform2); +// readCurve(valueMap, SUPER(timeline), frameIndex); +// } +// FREE(tempDeform); +// +// animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); +// animation->duration = MAX(animation->duration, timeline->frames[timelineMap->size - 1]); +// } +// } +// } +// +// /* Draw order timeline. */ +// if (drawOrder) +// { +// spDrawOrderTimeline* timeline = spDrawOrderTimeline_create(drawOrder->size, skeletonData->slotsCount); +// for (valueMap = drawOrder->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) +// { +// int ii; +// int* drawOrder2 = 0; +// Json* offsets = Json_getItem(valueMap, "offsets"); +// if (offsets) +// { +// Json* offsetMap; +// int* unchanged = MALLOC(int, skeletonData->slotsCount - offsets->size); +// int originalIndex = 0, unchangedIndex = 0; +// +// drawOrder2 = MALLOC(int, skeletonData->slotsCount); +// for (ii = skeletonData->slotsCount - 1; ii >= 0; --ii) +// { +// drawOrder2[ii] = -1; +// } +// +// for (offsetMap = offsets->child; offsetMap; offsetMap = offsetMap->next) +// { +// int slotIndex = spSkeletonData_findSlotIndex(skeletonData, Json_getString(offsetMap, "slot", 0)); +// if (slotIndex == -1) +// { +// spAnimation_dispose(animation); +// _spSkeletonJson_setError(self, 0, "Slot not found: ", Json_getString(offsetMap, "slot", 0)); +// return 0; +// } +// /* Collect unchanged items. */ +// while (originalIndex != slotIndex) +// { +// unchanged[unchangedIndex++] = originalIndex++; +// } +// /* Set changed items. */ +// drawOrder2[originalIndex + Json_getInt(offsetMap, "offset", 0)] = originalIndex; +// originalIndex++; +// } +// /* Collect remaining unchanged items. */ +// while (originalIndex < skeletonData->slotsCount) +// { +// unchanged[unchangedIndex++] = originalIndex++; +// } +// /* Fill in unchanged items. */ +// for (ii = skeletonData->slotsCount - 1; ii >= 0; ii--) +// { +// if (drawOrder2[ii] == -1) +// { +// drawOrder2[ii] = unchanged[--unchangedIndex]; +// } +// } +// FREE(unchanged); +// } +// spDrawOrderTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), drawOrder2); +// FREE(drawOrder2); +// } +// animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); +// animation->duration = MAX(animation->duration, timeline->frames[drawOrder->size - 1]); +// } +// +// /* Event timeline. */ +// if (events) +// { +// spEventTimeline* timeline = spEventTimeline_create(events->size); +// for (valueMap = events->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) +// { +// spEvent* event; +// const char* stringValue; +// spEventData* eventData = spSkeletonData_findEvent(skeletonData, Json_getString(valueMap, "name", 0)); +// if (!eventData) +// { +// spAnimation_dispose(animation); +// _spSkeletonJson_setError(self, 0, "Event not found: ", Json_getString(valueMap, "name", 0)); +// return 0; +// } +// event = spEvent_create(Json_getFloat(valueMap, "time", 0), eventData); +// event->intValue = Json_getInt(valueMap, "int", eventData->intValue); +// event->floatValue = Json_getFloat(valueMap, "float", eventData->floatValue); +// stringValue = Json_getString(valueMap, "string", eventData->stringValue); +// if (stringValue) +// { +// MALLOC_STR(event->stringValue, stringValue); +// } +// spEventTimeline_setFrame(timeline, frameIndex, event); +// } +// animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); +// animation->duration = MAX(animation->duration, timeline->frames[events->size - 1]); +// } +// +// return animation; return NULL; } + + void SkeletonJson::readVertices(Json* attachmentMap, VertexAttachment* attachment, int verticesLength) + { +// Json* entry; +// float* vertices; +// int i, n, nn, entrySize; +// spFloatArray* weights; +// spIntArray* bones; +// +// attachment->worldVerticesLength = verticesLength; +// +// entry = Json_getItem(attachmentMap, "vertices"); +// entrySize = entry->size; +// vertices = MALLOC(float, entrySize); +// for (entry = entry->child, i = 0; entry; entry = entry->next, ++i) +// { +// vertices[i] = entry->valueFloat; +// } +// +// if (verticesLength == entrySize) +// { +// if (self->scale != 1) +// { +// for (i = 0; i < entrySize; ++i) +// { +// vertices[i] *= self->scale; +// } +// } +// attachment->verticesCount = verticesLength; +// attachment->vertices = vertices; +// +// attachment->bonesCount = 0; +// attachment->bones = 0; +// return; +// } +// +// weights = spFloatArray_create(verticesLength * 3 * 3); +// bones = spIntArray_create(verticesLength * 3); +// +// for (i = 0, n = entrySize; i < n;) +// { +// int boneCount = (int)vertices[i++]; +// spIntArray_add(bones, boneCount); +// for (nn = i + boneCount * 4; i < nn; i += 4) +// { +// spIntArray_add(bones, (int)vertices[i]); +// spFloatArray_add(weights, vertices[i + 1] * self->scale); +// spFloatArray_add(weights, vertices[i + 2] * self->scale); +// spFloatArray_add(weights, vertices[i + 3]); +// } +// } +// +// attachment->verticesCount = weights->size; +// attachment->vertices = weights->items; +// FREE(weights); +// attachment->bonesCount = bones->size; +// attachment->bones = bones->items; +// FREE(bones); +// +// FREE(vertices); + } + + void SkeletonJson::setError(Json* root, const char* value1, const char* value2) + { +// char message[256]; +// int length; +// strcpy(message, value1); +// length = (int)strlen(value1); +// if (value2) +// { +// strncat(message + length, value2, 255 - length); +// } +// +// _error = std::string(message); +// if (root) +// { +// DESTROY(Json, root); +// } + } } From 517c48a2d595252ca8caff7b486bd11faf1af68b Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Mon, 4 Dec 2017 17:37:31 -0500 Subject: [PATCH 66/83] So close! --- spine-cpp/spine-cpp/include/spine/Json.h | 4 +- .../spine-cpp/include/spine/SkeletonBinary.h | 7 - .../spine-cpp/include/spine/SkeletonJson.h | 3 - spine-cpp/spine-cpp/include/spine/Vertices.h | 46 + spine-cpp/spine-cpp/src/spine/Json.cpp | 20 +- .../spine-cpp/src/spine/SkeletonBinary.cpp | 2 + .../spine-cpp/src/spine/SkeletonJson.cpp | 958 +++++++++--------- 7 files changed, 541 insertions(+), 499 deletions(-) create mode 100644 spine-cpp/spine-cpp/include/spine/Vertices.h diff --git a/spine-cpp/spine-cpp/include/spine/Json.h b/spine-cpp/spine-cpp/include/spine/Json.h index e64a7e72a..2124b970e 100644 --- a/spine-cpp/spine-cpp/include/spine/Json.h +++ b/spine-cpp/spine-cpp/include/spine/Json.h @@ -40,6 +40,8 @@ namespace Spine { class Json { + friend class SkeletonJson; + public: /* Json Types: */ static const int JSON_FALSE; @@ -68,7 +70,7 @@ namespace Spine ~Json(); private: - static const char* JSON_ERROR; + static const char* _error; Json* _next; #if SPINE_JSON_HAVE_PREV diff --git a/spine-cpp/spine-cpp/include/spine/SkeletonBinary.h b/spine-cpp/spine-cpp/include/spine/SkeletonBinary.h index 725ba5edb..c26ad8ea8 100644 --- a/spine-cpp/spine-cpp/include/spine/SkeletonBinary.h +++ b/spine-cpp/spine-cpp/include/spine/SkeletonBinary.h @@ -81,13 +81,6 @@ namespace Spine SkeletonData* readSkeletonDataFile(const char* path); private: - class Vertices - { - public: - Vector _bones; - Vector _vertices; - }; - struct DataInput { const unsigned char* cursor; diff --git a/spine-cpp/spine-cpp/include/spine/SkeletonJson.h b/spine-cpp/spine-cpp/include/spine/SkeletonJson.h index cc0c6d7a7..9fbbf11fb 100644 --- a/spine-cpp/spine-cpp/include/spine/SkeletonJson.h +++ b/spine-cpp/spine-cpp/include/spine/SkeletonJson.h @@ -37,7 +37,6 @@ namespace Spine { - class MeshAttachment; class CurveTimeline; class VertexAttachment; class Animation; @@ -71,8 +70,6 @@ namespace Spine static void readCurve(Json* frame, CurveTimeline* timeline, int frameIndex); - void addLinkedMesh(MeshAttachment* mesh, const char* skin, int slotIndex, const char* parent); - Animation* readAnimation(Json* root, SkeletonData *skeletonData); void readVertices(Json* attachmentMap, VertexAttachment* attachment, int verticesLength); diff --git a/spine-cpp/spine-cpp/include/spine/Vertices.h b/spine-cpp/spine-cpp/include/spine/Vertices.h new file mode 100644 index 000000000..bd14260f1 --- /dev/null +++ b/spine-cpp/spine-cpp/include/spine/Vertices.h @@ -0,0 +1,46 @@ +/****************************************************************************** + * Spine Runtimes Software License v2.5 + * + * Copyright (c) 2013-2016, Esoteric Software + * All rights reserved. + * + * You are granted a perpetual, non-exclusive, non-sublicensable, and + * non-transferable license to use, install, execute, and perform the Spine + * Runtimes software and derivative works solely for personal or internal + * use. Without the written permission of Esoteric Software (see Section 2 of + * the Spine Software License Agreement), you may not (a) modify, translate, + * adapt, or develop new applications using the Spine Runtimes or otherwise + * create derivative works or improvements of the Spine Runtimes or (b) remove, + * delete, alter, or obscure any trademarks or any copyright, trademark, patent, + * or other intellectual property or proprietary rights notices on or in the + * Software, including any copy thereof. Redistributions in binary or source + * form must include this license and terms. + * + * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef Spine_Vertices_h +#define Spine_Vertices_h + +#include + +namespace Spine +{ + class Vertices + { + public: + Vector _bones; + Vector _vertices; + }; +} + +#endif /* Spine_Vertices_h */ diff --git a/spine-cpp/spine-cpp/src/spine/Json.cpp b/spine-cpp/spine-cpp/src/spine/Json.cpp index 80dd36047..17a5d7aba 100644 --- a/spine-cpp/spine-cpp/src/spine/Json.cpp +++ b/spine-cpp/spine-cpp/src/spine/Json.cpp @@ -62,7 +62,7 @@ namespace Spine const int Json::JSON_ARRAY = 5; const int Json::JSON_OBJECT = 6; - const char* Json::JSON_ERROR = NULL; + const char* Json::_error = NULL; Json* Json::getItem(Json *object, const char* string) { @@ -99,7 +99,7 @@ namespace Spine const char* Json::getError() { - return JSON_ERROR; + return _error; } Json::Json(const char* value) : @@ -227,7 +227,7 @@ namespace Spine break; } - JSON_ERROR = value; + _error = value; return NULL; /* failure. */ } @@ -242,7 +242,7 @@ namespace Spine if (*str != '\"') { /* TODO: don't need this check when called from parseValue, but do need from parseObject */ - JSON_ERROR = str; + _error = str; return 0; } /* not a string! */ @@ -453,8 +453,8 @@ namespace Spine } else { - /* Parse failure, JSON_ERROR is set. */ - JSON_ERROR = num; + /* Parse failure, _error is set. */ + _error = num; return NULL; } } @@ -520,7 +520,7 @@ namespace Spine return value + 1; /* end of array */ } - JSON_ERROR = value; + _error = value; return NULL; /* malformed. */ } @@ -560,7 +560,7 @@ namespace Spine child->_valueString = 0; if (*value != ':') { - JSON_ERROR = value; + _error = value; return NULL; } /* fail! */ @@ -594,7 +594,7 @@ namespace Spine child->_valueString = 0; if (*value != ':') { - JSON_ERROR = value; + _error = value; return NULL; } /* fail! */ @@ -611,7 +611,7 @@ namespace Spine return value + 1; /* end of array */ } - JSON_ERROR = value; + _error = value; return NULL; /* malformed. */ } diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp b/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp index 57dfb340b..ef3b24c59 100644 --- a/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp +++ b/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -75,6 +76,7 @@ #include #include #include +#include namespace Spine { diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp b/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp index dd3b04abd..110021e60 100644 --- a/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp +++ b/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp @@ -32,6 +32,8 @@ #include +#include +#include #include #include #include @@ -40,6 +42,41 @@ #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__) #define strdup _strdup @@ -87,25 +124,26 @@ namespace Spine SkeletonData* SkeletonJson::readSkeletonData(const char* json) { -// int i, ii; -// SkeletonData* skeletonData; -// Json *root, *skeleton, *bones, *boneMap, *ik, *transform, *path, *slots, *skins, *animations, *events; -// _spSkeletonJson* internal = SUB_CAST(_spSkeletonJson, self); -// -// FREE(self->error); -// CONST_CAST(char*, self->error) = 0; -// internal->linkedMeshCount = 0; -// -// root = Json_create(json); -// -// if (!root) { -// _spSkeletonJson_setError(self, 0, "Invalid skeleton JSON: ", Json_getError()); -// return 0; -// } -// -// skeletonData = spSkeletonData_create(); -// -// skeleton = Json_getItem(root, "skeleton"); + int i, ii; + SkeletonData* skeletonData; + Json *root, *skeleton, *bones, *boneMap, *ik, *transform, *path, *slots, *skins, *animations, *events; + + _error.clear(); + _linkedMeshes.clear(); + + root = NEW(Json); + new (root) Json(json); + + if (!root) + { + setError(root, "Invalid skeleton JSON: ", Json::getError()); + return NULL; + } + + skeletonData = NEW(SkeletonData); + new (skeletonData) SkeletonData(); + +// skeleton = Json::getItem(root, "skeleton"); // if (skeleton) { // MALLOC_STR(skeletonData->hash, Json_getString(skeleton, "hash", 0)); // MALLOC_STR(skeletonData->version, Json_getString(skeleton, "spine", 0)); @@ -114,9 +152,9 @@ namespace Spine // } // // /* Bones. */ -// bones = Json_getItem(root, "bones"); -// skeletonData->bones = MALLOC(spBoneData*, bones->size); -// for (boneMap = bones->child, i = 0; boneMap; boneMap = boneMap->next, ++i) { +// bones = Json::getItem(root, "bones"); +// skeletonData->bones = MALLOC(spBoneData*, bones->_size); +// for (boneMap = bones->_child, i = 0; boneMap; boneMap = boneMap->_next, ++i) { // spBoneData* data; // const char* transformMode; // @@ -126,15 +164,15 @@ namespace Spine // parent = spSkeletonData_findBone(skeletonData, parentName); // if (!parent) { // spSkeletonData_dispose(skeletonData); -// _spSkeletonJson_setError(self, root, "Parent bone not found: ", parentName); -// return 0; +// setError(root, "Parent bone not found: ", parentName); +// return NULL; // } // } // // data = spBoneData_create(skeletonData->bonesCount, Json_getString(boneMap, "name", 0), parent); -// data->length = Json_getFloat(boneMap, "length", 0) * self->scale; -// data->x = Json_getFloat(boneMap, "x", 0) * self->scale; -// data->y = Json_getFloat(boneMap, "y", 0) * self->scale; +// data->length = Json_getFloat(boneMap, "length", 0) * _scale; +// data->x = Json_getFloat(boneMap, "x", 0) * _scale; +// data->y = Json_getFloat(boneMap, "y", 0) * _scale; // data->rotation = Json_getFloat(boneMap, "rotation", 0); // data->scaleX = Json_getFloat(boneMap, "scaleX", 1); // data->scaleY = Json_getFloat(boneMap, "scaleY", 1); @@ -158,12 +196,12 @@ namespace Spine // } // // /* Slots. */ -// slots = Json_getItem(root, "slots"); +// slots = Json::getItem(root, "slots"); // if (slots) { // Json *slotMap; -// skeletonData->slotsCount = slots->size; -// skeletonData->slots = MALLOC(spSlotData*, slots->size); -// for (slotMap = slots->child, i = 0; slotMap; slotMap = slotMap->next, ++i) { +// skeletonData->slotsCount = slots->_size; +// skeletonData->slots = MALLOC(spSlotData*, slots->_size); +// for (slotMap = slots->_child, i = 0; slotMap; slotMap = slotMap->_next, ++i) { // spSlotData* data; // const char* color; // const char* dark; @@ -173,8 +211,8 @@ namespace Spine // spBoneData* boneData = spSkeletonData_findBone(skeletonData, boneName); // if (!boneData) { // spSkeletonData_dispose(skeletonData); -// _spSkeletonJson_setError(self, root, "Slot bone not found: ", boneName); -// return 0; +// setError(root, "Slot bone not found: ", boneName); +// return NULL; // } // // data = spSlotData_create(i, Json_getString(slotMap, "name", 0), boneData); @@ -198,16 +236,16 @@ namespace Spine // toColor(dark, 3)); // } // -// item = Json_getItem(slotMap, "attachment"); -// if (item) spSlotData_setAttachmentName(data, item->valueString); +// item = Json::getItem(slotMap, "attachment"); +// if (item) spSlotData_setAttachmentName(data, item->_valueString); // -// item = Json_getItem(slotMap, "blend"); +// item = Json::getItem(slotMap, "blend"); // if (item) { -// if (strcmp(item->valueString, "additive") == 0) +// if (strcmp(item->_valueString, "additive") == 0) // data->blendMode = SP_BLEND_MODE_ADDITIVE; -// else if (strcmp(item->valueString, "multiply") == 0) +// else if (strcmp(item->_valueString, "multiply") == 0) // data->blendMode = SP_BLEND_MODE_MULTIPLY; -// else if (strcmp(item->valueString, "screen") == 0) +// else if (strcmp(item->_valueString, "screen") == 0) // data->blendMode = SP_BLEND_MODE_SCREEN; // } // @@ -216,26 +254,26 @@ namespace Spine // } // // /* IK constraints. */ -// ik = Json_getItem(root, "ik"); +// ik = Json::getItem(root, "ik"); // if (ik) { // Json *constraintMap; -// skeletonData->ikConstraintsCount = ik->size; -// skeletonData->ikConstraints = MALLOC(spIkConstraintData*, ik->size); -// for (constraintMap = ik->child, i = 0; constraintMap; constraintMap = constraintMap->next, ++i) { +// skeletonData->ikConstraintsCount = ik->_size; +// skeletonData->ikConstraints = MALLOC(spIkConstraintData*, ik->_size); +// for (constraintMap = ik->_child, i = 0; constraintMap; constraintMap = constraintMap->_next, ++i) { // const char* targetName; // // spIkConstraintData* data = spIkConstraintData_create(Json_getString(constraintMap, "name", 0)); // data->order = Json_getInt(constraintMap, "order", 0); // -// boneMap = Json_getItem(constraintMap, "bones"); -// data->bonesCount = boneMap->size; -// data->bones = MALLOC(spBoneData*, boneMap->size); -// for (boneMap = boneMap->child, ii = 0; boneMap; boneMap = boneMap->next, ++ii) { -// data->bones[ii] = spSkeletonData_findBone(skeletonData, boneMap->valueString); +// boneMap = Json::getItem(constraintMap, "bones"); +// data->bonesCount = boneMap->_size; +// data->bones = MALLOC(spBoneData*, boneMap->_size); +// for (boneMap = boneMap->_child, ii = 0; boneMap; boneMap = boneMap->_next, ++ii) { +// data->bones[ii] = spSkeletonData_findBone(skeletonData, boneMap->_valueString); // if (!data->bones[ii]) { // spSkeletonData_dispose(skeletonData); -// _spSkeletonJson_setError(self, root, "IK bone not found: ", boneMap->valueString); -// return 0; +// setError(root, "IK bone not found: ", boneMap->_valueString); +// return NULL; // } // } // @@ -243,8 +281,8 @@ namespace Spine // data->target = spSkeletonData_findBone(skeletonData, targetName); // if (!data->target) { // spSkeletonData_dispose(skeletonData); -// _spSkeletonJson_setError(self, root, "Target bone not found: ", boneMap->name); -// return 0; +// setError(root, "Target bone not found: ", boneMap->_name); +// return NULL; // } // // data->bendDirection = Json_getInt(constraintMap, "bendPositive", 1) ? 1 : -1; @@ -255,26 +293,26 @@ namespace Spine // } // // /* Transform constraints. */ -// transform = Json_getItem(root, "transform"); +// transform = Json::getItem(root, "transform"); // if (transform) { // Json *constraintMap; -// skeletonData->transformConstraintsCount = transform->size; -// skeletonData->transformConstraints = MALLOC(spTransformConstraintData*, transform->size); -// for (constraintMap = transform->child, i = 0; constraintMap; constraintMap = constraintMap->next, ++i) { +// skeletonData->transformConstraintsCount = transform->_size; +// skeletonData->transformConstraints = MALLOC(spTransformConstraintData*, transform->_size); +// for (constraintMap = transform->_child, i = 0; constraintMap; constraintMap = constraintMap->_next, ++i) { // const char* name; // // spTransformConstraintData* data = spTransformConstraintData_create(Json_getString(constraintMap, "name", 0)); // data->order = Json_getInt(constraintMap, "order", 0); // -// boneMap = Json_getItem(constraintMap, "bones"); -// data->bonesCount = boneMap->size; -// CONST_CAST(spBoneData**, data->bones) = MALLOC(spBoneData*, boneMap->size); -// for (boneMap = boneMap->child, ii = 0; boneMap; boneMap = boneMap->next, ++ii) { -// data->bones[ii] = spSkeletonData_findBone(skeletonData, boneMap->valueString); +// boneMap = Json::getItem(constraintMap, "bones"); +// data->bonesCount = boneMap->_size; +// CONST_CAST(spBoneData**, data->bones) = MALLOC(spBoneData*, boneMap->_size); +// for (boneMap = boneMap->_child, ii = 0; boneMap; boneMap = boneMap->_next, ++ii) { +// data->bones[ii] = spSkeletonData_findBone(skeletonData, boneMap->_valueString); // if (!data->bones[ii]) { // spSkeletonData_dispose(skeletonData); -// _spSkeletonJson_setError(self, root, "Transform bone not found: ", boneMap->valueString); -// return 0; +// setError(root, "Transform bone not found: ", boneMap->_valueString); +// return NULL; // } // } // @@ -282,15 +320,15 @@ namespace Spine // data->target = spSkeletonData_findBone(skeletonData, name); // if (!data->target) { // spSkeletonData_dispose(skeletonData); -// _spSkeletonJson_setError(self, root, "Target bone not found: ", boneMap->name); -// return 0; +// setError(root, "Target bone not found: ", boneMap->_name); +// return NULL; // } // // data->local = Json_getInt(constraintMap, "local", 0); // data->relative = Json_getInt(constraintMap, "relative", 0); // data->offsetRotation = Json_getFloat(constraintMap, "rotation", 0); -// data->offsetX = Json_getFloat(constraintMap, "x", 0) * self->scale; -// data->offsetY = Json_getFloat(constraintMap, "y", 0) * self->scale; +// data->offsetX = Json_getFloat(constraintMap, "x", 0) * _scale; +// data->offsetY = Json_getFloat(constraintMap, "y", 0) * _scale; // data->offsetScaleX = Json_getFloat(constraintMap, "scaleX", 0); // data->offsetScaleY = Json_getFloat(constraintMap, "scaleY", 0); // data->offsetShearY = Json_getFloat(constraintMap, "shearY", 0); @@ -305,27 +343,27 @@ namespace Spine // } // // /* Path constraints */ -// path = Json_getItem(root, "path"); +// path = Json::getItem(root, "path"); // if (path) { // Json *constraintMap; -// skeletonData->pathConstraintsCount = path->size; -// skeletonData->pathConstraints = MALLOC(spPathConstraintData*, path->size); -// for (constraintMap = path->child, i = 0; constraintMap; constraintMap = constraintMap->next, ++i) { +// skeletonData->pathConstraintsCount = path->_size; +// skeletonData->pathConstraints = MALLOC(spPathConstraintData*, path->_size); +// for (constraintMap = path->_child, i = 0; constraintMap; constraintMap = constraintMap->_next, ++i) { // const char* name; // const char* item; // // spPathConstraintData* data = spPathConstraintData_create(Json_getString(constraintMap, "name", 0)); // data->order = Json_getInt(constraintMap, "order", 0); // -// boneMap = Json_getItem(constraintMap, "bones"); -// data->bonesCount = boneMap->size; -// CONST_CAST(spBoneData**, data->bones) = MALLOC(spBoneData*, boneMap->size); -// for (boneMap = boneMap->child, ii = 0; boneMap; boneMap = boneMap->next, ++ii) { -// data->bones[ii] = spSkeletonData_findBone(skeletonData, boneMap->valueString); +// boneMap = Json::getItem(constraintMap, "bones"); +// data->bonesCount = boneMap->_size; +// CONST_CAST(spBoneData**, data->bones) = MALLOC(spBoneData*, boneMap->_size); +// for (boneMap = boneMap->_child, ii = 0; boneMap; boneMap = boneMap->_next, ++ii) { +// data->bones[ii] = spSkeletonData_findBone(skeletonData, boneMap->_valueString); // if (!data->bones[ii]) { // spSkeletonData_dispose(skeletonData); -// _spSkeletonJson_setError(self, root, "Path bone not found: ", boneMap->valueString); -// return 0; +// setError(root, "Path bone not found: ", boneMap->_valueString); +// return NULL; // } // } // @@ -333,8 +371,8 @@ namespace Spine // data->target = spSkeletonData_findSlot(skeletonData, name); // if (!data->target) { // spSkeletonData_dispose(skeletonData); -// _spSkeletonJson_setError(self, root, "Target slot not found: ", boneMap->name); -// return 0; +// setError(root, "Target slot not found: ", boneMap->_name); +// return NULL; // } // // item = Json_getString(constraintMap, "positionMode", "percent"); @@ -353,9 +391,9 @@ namespace Spine // // data->offsetRotation = Json_getFloat(constraintMap, "rotation", 0); // data->position = Json_getFloat(constraintMap, "position", 0); -// if (data->positionMode == SP_POSITION_MODE_FIXED) data->position *= self->scale; +// if (data->positionMode == SP_POSITION_MODE_FIXED) data->position *= _scale; // data->spacing = Json_getFloat(constraintMap, "spacing", 0); -// if (data->spacingMode == SP_SPACING_MODE_LENGTH || data->spacingMode == SP_SPACING_MODE_FIXED) data->spacing *= self->scale; +// if (data->spacingMode == SP_SPACING_MODE_LENGTH || data->spacingMode == SP_SPACING_MODE_FIXED) data->spacing *= _scale; // data->rotateMix = Json_getFloat(constraintMap, "rotateMix", 1); // data->translateMix = Json_getFloat(constraintMap, "translateMix", 1); // @@ -364,25 +402,25 @@ namespace Spine // } // // /* Skins. */ -// skins = Json_getItem(root, "skins"); +// skins = Json::getItem(root, "skins"); // if (skins) { // Json *skinMap; -// skeletonData->skins = MALLOC(spSkin*, skins->size); -// for (skinMap = skins->child, i = 0; skinMap; skinMap = skinMap->next, ++i) { +// skeletonData->skins = MALLOC(spSkin*, skins->_size); +// for (skinMap = skins->_child, i = 0; skinMap; skinMap = skinMap->_next, ++i) { // Json *attachmentsMap; // Json *curves; -// spSkin *skin = spSkin_create(skinMap->name); +// spSkin *skin = spSkin_create(skinMap->_name); // // skeletonData->skins[skeletonData->skinsCount++] = skin; -// if (strcmp(skinMap->name, "default") == 0) skeletonData->defaultSkin = skin; +// if (strcmp(skinMap->_name, "default") == 0) skeletonData->defaultSkin = skin; // -// for (attachmentsMap = skinMap->child; attachmentsMap; attachmentsMap = attachmentsMap->next) { -// int slotIndex = spSkeletonData_findSlotIndex(skeletonData, attachmentsMap->name); +// for (attachmentsMap = skinMap->_child; attachmentsMap; attachmentsMap = attachmentsMap->_next) { +// int slotIndex = spSkeletonData_findSlotIndex(skeletonData, attachmentsMap->_name); // Json *attachmentMap; // -// for (attachmentMap = attachmentsMap->child; attachmentMap; attachmentMap = attachmentMap->next) { +// for (attachmentMap = attachmentsMap->_child; attachmentMap; attachmentMap = attachmentMap->_next) { // spAttachment* attachment; -// const char* skinAttachmentName = attachmentMap->name; +// const char* skinAttachmentName = attachmentMap->_name; // const char* attachmentName = Json_getString(attachmentMap, "name", skinAttachmentName); // const char* attachmentPath = Json_getString(attachmentMap, "path", attachmentName); // const char* color; @@ -404,31 +442,31 @@ namespace Spine // type = SP_ATTACHMENT_CLIPPING; // else { // spSkeletonData_dispose(skeletonData); -// _spSkeletonJson_setError(self, root, "Unknown attachment type: ", typeString); -// return 0; +// setError(root, "Unknown attachment type: ", typeString); +// return NULL; // } // -// attachment = spAttachmentLoader_createAttachment(self->attachmentLoader, skin, type, attachmentName, attachmentPath); +// attachment = spAttachmentLoader_createAttachment(_attachmentLoader, skin, type, attachmentName, attachmentPath); // if (!attachment) { -// if (self->attachmentLoader->error1) { +// if (_attachmentLoader->error1) { // spSkeletonData_dispose(skeletonData); -// _spSkeletonJson_setError(self, root, self->attachmentLoader->error1, self->attachmentLoader->error2); -// return 0; +// setError(root, _attachmentLoader->error1, _attachmentLoader->error2); +// return NULL; // } // continue; // } // -// switch (attachment->type) { +// switch (attachment->_type) { // case SP_ATTACHMENT_REGION: { // spRegionAttachment* region = SUB_CAST(spRegionAttachment, attachment); // if (path) MALLOC_STR(region->path, attachmentPath); -// region->x = Json_getFloat(attachmentMap, "x", 0) * self->scale; -// region->y = Json_getFloat(attachmentMap, "y", 0) * self->scale; +// region->x = Json_getFloat(attachmentMap, "x", 0) * _scale; +// region->y = Json_getFloat(attachmentMap, "y", 0) * _scale; // region->scaleX = Json_getFloat(attachmentMap, "scaleX", 1); // region->scaleY = Json_getFloat(attachmentMap, "scaleY", 1); // region->rotation = Json_getFloat(attachmentMap, "rotation", 0); -// region->width = Json_getFloat(attachmentMap, "width", 32) * self->scale; -// region->height = Json_getFloat(attachmentMap, "height", 32) * self->scale; +// region->width = Json_getFloat(attachmentMap, "width", 32) * _scale; +// region->height = Json_getFloat(attachmentMap, "height", 32) * _scale; // // color = Json_getString(attachmentMap, "color", 0); // if (color) { @@ -441,7 +479,7 @@ namespace Spine // // spRegionAttachment_updateOffset(region); // -// spAttachmentLoader_configureAttachment(self->attachmentLoader, attachment); +// spAttachmentLoader_configureAttachment(_attachmentLoader, attachment); // break; // } // case SP_ATTACHMENT_MESH: @@ -459,23 +497,23 @@ namespace Spine // toColor(color, 3)); // } // -// mesh->width = Json_getFloat(attachmentMap, "width", 32) * self->scale; -// mesh->height = Json_getFloat(attachmentMap, "height", 32) * self->scale; +// mesh->width = Json_getFloat(attachmentMap, "width", 32) * _scale; +// mesh->height = Json_getFloat(attachmentMap, "height", 32) * _scale; // -// entry = Json_getItem(attachmentMap, "parent"); +// entry = Json::getItem(attachmentMap, "parent"); // if (!entry) { // int verticesLength; -// entry = Json_getItem(attachmentMap, "triangles"); -// mesh->trianglesCount = entry->size; -// mesh->triangles = MALLOC(unsigned short, entry->size); -// for (entry = entry->child, ii = 0; entry; entry = entry->next, ++ii) -// mesh->triangles[ii] = (unsigned short)entry->valueInt; +// entry = Json::getItem(attachmentMap, "triangles"); +// mesh->trianglesCount = entry->_size; +// mesh->triangles = MALLOC(unsigned short, entry->_size); +// for (entry = entry->_child, ii = 0; entry; entry = entry->_next, ++ii) +// mesh->triangles[ii] = (unsigned short)entry->_valueInt; // -// entry = Json_getItem(attachmentMap, "uvs"); -// verticesLength = entry->size; +// entry = Json::getItem(attachmentMap, "uvs"); +// verticesLength = entry->_size; // mesh->regionUVs = MALLOC(float, verticesLength); -// for (entry = entry->child, ii = 0; entry; entry = entry->next, ++ii) -// mesh->regionUVs[ii] = entry->valueFloat; +// for (entry = entry->_child, ii = 0; entry; entry = entry->_next, ++ii) +// mesh->regionUVs[ii] = entry->_valueFloat; // // _readVertices(self, attachmentMap, SUPER(mesh), verticesLength); // @@ -483,19 +521,19 @@ namespace Spine // // mesh->hullLength = Json_getInt(attachmentMap, "hull", 0); // -// entry = Json_getItem(attachmentMap, "edges"); +// entry = Json::getItem(attachmentMap, "edges"); // if (entry) { -// mesh->edgesCount = entry->size; -// mesh->edges = MALLOC(int, entry->size); -// for (entry = entry->child, ii = 0; entry; entry = entry->next, ++ii) -// mesh->edges[ii] = entry->valueInt; +// mesh->edgesCount = entry->_size; +// mesh->edges = MALLOC(int, entry->_size); +// for (entry = entry->_child, ii = 0; entry; entry = entry->_next, ++ii) +// mesh->edges[ii] = entry->_valueInt; // } // -// spAttachmentLoader_configureAttachment(self->attachmentLoader, attachment); +// spAttachmentLoader_configureAttachment(_attachmentLoader, attachment); // } else { // mesh->inheritDeform = Json_getInt(attachmentMap, "deform", 1); // _spSkeletonJson_addLinkedMesh(self, SUB_CAST(spMeshAttachment, attachment), Json_getString(attachmentMap, "skin", 0), slotIndex, -// entry->valueString); +// entry->_valueString); // } // break; // } @@ -504,7 +542,7 @@ namespace Spine // int vertexCount = Json_getInt(attachmentMap, "vertexCount", 0) << 1; // _readVertices(self, attachmentMap, SUPER(box), vertexCount); // box->super.verticesCount = vertexCount; -// spAttachmentLoader_configureAttachment(self->attachmentLoader, attachment); +// spAttachmentLoader_configureAttachment(_attachmentLoader, attachment); // break; // } // case SP_ATTACHMENT_PATH: { @@ -518,16 +556,16 @@ namespace Spine // pathAttatchment->lengthsLength = vertexCount / 3; // pathAttatchment->lengths = MALLOC(float, pathAttatchment->lengthsLength); // -// curves = Json_getItem(attachmentMap, "lengths"); -// for (curves = curves->child, ii = 0; curves; curves = curves->next, ++ii) { -// pathAttatchment->lengths[ii] = curves->valueFloat * self->scale; +// curves = Json::getItem(attachmentMap, "lengths"); +// for (curves = curves->_child, ii = 0; curves; curves = curves->_next, ++ii) { +// pathAttatchment->lengths[ii] = curves->_valueFloat * _scale; // } // break; // } // case SP_ATTACHMENT_POINT: { // spPointAttachment* point = SUB_CAST(spPointAttachment, attachment); -// point->x = Json_getFloat(attachmentMap, "x", 0) * self->scale; -// point->y = Json_getFloat(attachmentMap, "y", 0) * self->scale; +// point->x = Json_getFloat(attachmentMap, "x", 0) * _scale; +// point->y = Json_getFloat(attachmentMap, "y", 0) * _scale; // point->rotation = Json_getFloat(attachmentMap, "rotation", 0); // // color = Json_getString(attachmentMap, "color", 0); @@ -550,7 +588,7 @@ namespace Spine // } // vertexCount = Json_getInt(attachmentMap, "vertexCount", 0) << 1; // _readVertices(self, attachmentMap, SUPER(clip), vertexCount); -// spAttachmentLoader_configureAttachment(self->attachmentLoader, attachment); +// spAttachmentLoader_configureAttachment(_attachmentLoader, attachment); // break; // } // } @@ -568,29 +606,29 @@ namespace Spine // spSkin* skin = !linkedMesh->skin ? skeletonData->defaultSkin : spSkeletonData_findSkin(skeletonData, linkedMesh->skin); // if (!skin) { // spSkeletonData_dispose(skeletonData); -// _spSkeletonJson_setError(self, 0, "Skin not found: ", linkedMesh->skin); -// return 0; +// setError(root, "Skin not found: ", linkedMesh->skin); +// return NULL; // } // parent = spSkin_getAttachment(skin, linkedMesh->slotIndex, linkedMesh->parent); // if (!parent) { // spSkeletonData_dispose(skeletonData); -// _spSkeletonJson_setError(self, 0, "Parent mesh not found: ", linkedMesh->parent); -// return 0; +// setError(root, "Parent mesh not found: ", linkedMesh->parent); +// return NULL; // } // spMeshAttachment_setParentMesh(linkedMesh->mesh, SUB_CAST(spMeshAttachment, parent)); // spMeshAttachment_updateUVs(linkedMesh->mesh); -// spAttachmentLoader_configureAttachment(self->attachmentLoader, SUPER(SUPER(linkedMesh->mesh))); +// spAttachmentLoader_configureAttachment(_attachmentLoader, SUPER(SUPER(linkedMesh->mesh))); // } // // /* Events. */ -// events = Json_getItem(root, "events"); +// events = Json::getItem(root, "events"); // if (events) { // Json *eventMap; // const char* stringValue; -// skeletonData->eventsCount = events->size; -// skeletonData->events = MALLOC(spEventData*, events->size); -// for (eventMap = events->child, i = 0; eventMap; eventMap = eventMap->next, ++i) { -// spEventData* eventData = spEventData_create(eventMap->name); +// skeletonData->eventsCount = events->_size; +// skeletonData->events = MALLOC(spEventData*, events->_size); +// for (eventMap = events->_child, i = 0; eventMap; eventMap = eventMap->_next, ++i) { +// spEventData* eventData = spEventData_create(eventMap->_name); // eventData->intValue = Json_getInt(eventMap, "int", 0); // eventData->floatValue = Json_getFloat(eventMap, "float", 0); // stringValue = Json_getString(eventMap, "string", 0); @@ -600,195 +638,173 @@ namespace Spine // } // // /* Animations. */ -// animations = Json_getItem(root, "animations"); +// animations = Json::getItem(root, "animations"); // if (animations) { // Json *animationMap; -// skeletonData->animations = MALLOC(spAnimation*, animations->size); -// for (animationMap = animations->child; animationMap; animationMap = animationMap->next) { +// skeletonData->animations = MALLOC(spAnimation*, animations->_size); +// for (animationMap = animations->_child; animationMap; animationMap = animationMap->_next) { // spAnimation* animation = _spSkeletonJson_readAnimation(self, animationMap, skeletonData); // if (!animation) { // spSkeletonData_dispose(skeletonData); -// return 0; +// return NULL; // } // skeletonData->animations[skeletonData->animationsCount++] = animation; // } // } // // Json_dispose(root); -// return skeletonData; - return NULL; + return skeletonData; } float SkeletonJson::toColor(const char* value, int index) { -// char digits[3]; -// char *error; -// int color; -// -// if (index >= strlen(value) / 2) -// { -// return -1; -// } -// -// value += index * 2; -// -// digits[0] = *value; -// digits[1] = *(value + 1); -// digits[2] = '\0'; -// color = (int)strtoul(digits, &error, 16); -// if (*error != 0) -// { -// return -1; -// } -// return color / (float)255; - return 0; + char digits[3]; + char *error; + int color; + + if (index >= strlen(value) / 2) + { + return -1; + } + + value += index * 2; + + digits[0] = *value; + digits[1] = *(value + 1); + digits[2] = '\0'; + color = (int)strtoul(digits, &error, 16); + if (*error != 0) + { + return -1; + } + + return color / (float)255; } void SkeletonJson::readCurve(Json* frame, CurveTimeline* timeline, int frameIndex) { -// Json* curve = Json_getItem(frame, "curve"); -// if (!curve) -// { -// return; -// } -// if (curve->type == JSON_STRING && strcmp(curve->valueString, "stepped") == 0) -// { -// spCurveTimeline_setStepped(timeline, frameIndex); -// } -// else if (curve->type == JSON_ARRAY) -// { -// Json* child0 = curve->child; -// Json* child1 = child0->next; -// Json* child2 = child1->next; -// Json* child3 = child2->next; -// spCurveTimeline_setCurve(timeline, frameIndex, child0->valueFloat, child1->valueFloat, child2->valueFloat, child3->valueFloat); -// } - } - - void SkeletonJson::addLinkedMesh(MeshAttachment* mesh, const char* skin, int slotIndex, const char* parent) - { -// _spLinkedMesh* linkedMesh; -// _spSkeletonJson* internal = SUB_CAST(_spSkeletonJson, self); -// -// if (internal->linkedMeshCount == internal->linkedMeshCapacity) -// { -// _spLinkedMesh* linkedMeshes; -// internal->linkedMeshCapacity *= 2; -// if (internal->linkedMeshCapacity < 8) internal->linkedMeshCapacity = 8; -// linkedMeshes = MALLOC(_spLinkedMesh, internal->linkedMeshCapacity); -// memcpy(linkedMeshes, internal->linkedMeshes, sizeof(_spLinkedMesh) * internal->linkedMeshCount); -// FREE(internal->linkedMeshes); -// internal->linkedMeshes = linkedMeshes; -// } -// -// linkedMesh = internal->linkedMeshes + internal->linkedMeshCount++; -// linkedMesh->mesh = mesh; -// linkedMesh->skin = skin; -// linkedMesh->slotIndex = slotIndex; -// linkedMesh->parent = parent; + Json* curve = Json::getItem(frame, "curve"); + if (!curve) + { + return; + } + if (curve->_type == Json::JSON_STRING && strcmp(curve->_valueString, "stepped") == 0) + { + timeline->setStepped(frameIndex); + } + else if (curve->_type == Json::JSON_ARRAY) + { + Json* child0 = curve->_child; + Json* child1 = child0->_next; + Json* child2 = child1->_next; + Json* child3 = child2->_next; + timeline->setCurve(frameIndex, child0->_valueFloat, child1->_valueFloat, child2->_valueFloat, child3->_valueFloat); + } } Animation* SkeletonJson::readAnimation(Json* root, SkeletonData *skeletonData) { -// int frameIndex; -// spAnimation* animation; -// Json* valueMap; -// int timelinesCount = 0; -// -// Json* bones = Json_getItem(root, "bones"); -// Json* slots = Json_getItem(root, "slots"); -// Json* ik = Json_getItem(root, "ik"); -// Json* transform = Json_getItem(root, "transform"); -// Json* paths = Json_getItem(root, "paths"); -// Json* deform = Json_getItem(root, "deform"); -// Json* drawOrder = Json_getItem(root, "drawOrder"); -// Json* events = Json_getItem(root, "events"); -// Json *boneMap, *slotMap, *constraintMap; -// if (!drawOrder) drawOrder = Json_getItem(root, "draworder"); -// -// for (boneMap = bones ? bones->child : 0; boneMap; boneMap = boneMap->next) -// { -// timelinesCount += boneMap->size; -// } -// for (slotMap = slots ? slots->child : 0; slotMap; slotMap = slotMap->next) -// { -// timelinesCount += slotMap->size; -// } -// timelinesCount += ik ? ik->size : 0; -// timelinesCount += transform ? transform->size : 0; -// for (constraintMap = paths ? paths->child : 0; constraintMap; constraintMap = constraintMap->next) -// { -// timelinesCount += constraintMap->size; -// } -// for (constraintMap = deform ? deform->child : 0; constraintMap; constraintMap = constraintMap->next) -// { -// for (slotMap = constraintMap->child; slotMap; slotMap = slotMap->next) -// { -// timelinesCount += slotMap->size; -// } -// } -// if (drawOrder) -// { -// ++timelinesCount; -// } -// if (events) -// { -// ++timelinesCount; -// } -// -// animation = spAnimation_create(root->name, timelinesCount); -// animation->timelinesCount = 0; -// -// /* Slot timelines. */ -// for (slotMap = slots ? slots->child : 0; slotMap; slotMap = slotMap->next) -// { + Vector timelines; + float scale = _scale; + float duration = 0; + + int frameIndex; + Json* valueMap; + int timelinesCount = 0; + + Json* bones = Json::getItem(root, "bones"); + Json* slots = Json::getItem(root, "slots"); + Json* ik = Json::getItem(root, "ik"); + Json* transform = Json::getItem(root, "transform"); + Json* paths = Json::getItem(root, "paths"); + Json* deform = Json::getItem(root, "deform"); + Json* drawOrder = Json::getItem(root, "drawOrder"); + Json* events = Json::getItem(root, "events"); + Json *boneMap, *slotMap, *constraintMap; + if (!drawOrder) + { + drawOrder = Json::getItem(root, "draworder"); + } + + for (boneMap = bones ? bones->_child : 0; boneMap; boneMap = boneMap->_next) + { + timelinesCount += boneMap->_size; + } + for (slotMap = slots ? slots->_child : 0; slotMap; slotMap = slotMap->_next) + { + timelinesCount += slotMap->_size; + } + timelinesCount += ik ? ik->_size : 0; + timelinesCount += transform ? transform->_size : 0; + for (constraintMap = paths ? paths->_child : 0; constraintMap; constraintMap = constraintMap->_next) + { + timelinesCount += constraintMap->_size; + } + for (constraintMap = deform ? deform->_child : 0; constraintMap; constraintMap = constraintMap->_next) + { + for (slotMap = constraintMap->_child; slotMap; slotMap = slotMap->_next) + { + timelinesCount += slotMap->_size; + } + } + if (drawOrder) + { + ++timelinesCount; + } + if (events) + { + ++timelinesCount; + } + + /* Slot timelines. */ + for (slotMap = slots ? slots->_child : 0; slotMap; slotMap = slotMap->_next) + { // Json *timelineMap; // -// int slotIndex = spSkeletonData_findSlotIndex(skeletonData, slotMap->name); +// int slotIndex = skeletonData->findSlotIndex(slotMap->_name); // if (slotIndex == -1) // { -// spAnimation_dispose(animation); -// _spSkeletonJson_setError(self, root, "Slot not found: ", slotMap->name); -// return 0; +// setError(root, "Slot not found: ", slotMap->_name); +// return NULL; // } // -// for (timelineMap = slotMap->child; timelineMap; timelineMap = timelineMap->next) +// for (timelineMap = slotMap->_child; timelineMap; timelineMap = timelineMap->_next) // { -// if (strcmp(timelineMap->name, "attachment") == 0) +// if (strcmp(timelineMap->_name, "attachment") == 0) // { -// spAttachmentTimeline *timeline = spAttachmentTimeline_create(timelineMap->size); +// spAttachmentTimeline *timeline = spAttachmentTimeline_create(timelineMap->_size); // timeline->slotIndex = slotIndex; // -// for (valueMap = timelineMap->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) +// for (valueMap = timelineMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) // { -// Json* name = Json_getItem(valueMap, "name"); -// spAttachmentTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), name->type == Json_NULL ? 0 : name->valueString); +// Json* name = Json::getItem(valueMap, "name"); +// spAttachmentTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), name->_type == Json_NULL ? 0 : name->_valueString); // } -// animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); -// animation->duration = MAX(animation->duration, timeline->frames[timelineMap->size - 1]); +// timelines[timelinesCount++] = SUPER_CAST(spTimeline, timeline); +// duration = MAX(duration, timeline->frames[timelineMap->_size - 1]); // // } -// else if (strcmp(timelineMap->name, "color") == 0) +// else if (strcmp(timelineMap->_name, "color") == 0) // { -// spColorTimeline *timeline = spColorTimeline_create(timelineMap->size); +// spColorTimeline *timeline = spColorTimeline_create(timelineMap->_size); // timeline->slotIndex = slotIndex; // -// for (valueMap = timelineMap->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) +// for (valueMap = timelineMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) // { // const char* s = Json_getString(valueMap, "color", 0); // spColorTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), toColor(s, 0), toColor(s, 1), toColor(s, 2), toColor(s, 3)); // readCurve(valueMap, SUPER(timeline), frameIndex); // } -// animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); -// animation->duration = MAX(animation->duration, timeline->frames[(timelineMap->size - 1) * COLOR_ENTRIES]); +// timelines[timelinesCount++] = SUPER_CAST(spTimeline, timeline); +// duration = MAX(duration, timeline->frames[(timelineMap->_size - 1) * COLOR_ENTRIES]); // // } -// else if (strcmp(timelineMap->name, "twoColor") == 0) +// else if (strcmp(timelineMap->_name, "twoColor") == 0) // { -// spTwoColorTimeline *timeline = spTwoColorTimeline_create(timelineMap->size); +// spTwoColorTimeline *timeline = spTwoColorTimeline_create(timelineMap->_size); // timeline->slotIndex = slotIndex; // -// for (valueMap = timelineMap->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) +// for (valueMap = timelineMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) // { // const char* s = Json_getString(valueMap, "light", 0); // const char* ds = Json_getString(valueMap, "dark", 0); @@ -796,93 +812,90 @@ namespace Spine // toColor(s, 3), toColor(ds, 0), toColor(ds, 1), toColor(ds, 2)); // readCurve(valueMap, SUPER(timeline), frameIndex); // } -// animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); -// animation->duration = MAX(animation->duration, timeline->frames[(timelineMap->size - 1) * TWOCOLOR_ENTRIES]); +// timelines[timelinesCount++] = SUPER_CAST(spTimeline, timeline); +// duration = MAX(duration, timeline->frames[(timelineMap->_size - 1) * TWOCOLOR_ENTRIES]); // } // else // { -// spAnimation_dispose(animation); -// _spSkeletonJson_setError(self, 0, "Invalid timeline type for a slot: ", timelineMap->name); -// return 0; +// setError(root, "Invalid timeline type for a slot: ", timelineMap->_name); +// return NULL; // } // } -// } -// -// /* Bone timelines. */ -// for (boneMap = bones ? bones->child : 0; boneMap; boneMap = boneMap->next) -// { + } + + /* Bone timelines. */ + for (boneMap = bones ? bones->_child : 0; boneMap; boneMap = boneMap->_next) + { // Json *timelineMap; // -// int boneIndex = spSkeletonData_findBoneIndex(skeletonData, boneMap->name); +// int boneIndex = spSkeletonData_findBoneIndex(skeletonData, boneMap->_name); // if (boneIndex == -1) // { -// spAnimation_dispose(animation); -// _spSkeletonJson_setError(self, root, "Bone not found: ", boneMap->name); -// return 0; +// setError(root, "Bone not found: ", boneMap->_name); +// return NULL; // } // -// for (timelineMap = boneMap->child; timelineMap; timelineMap = timelineMap->next) +// for (timelineMap = boneMap->_child; timelineMap; timelineMap = timelineMap->_next) // { -// if (strcmp(timelineMap->name, "rotate") == 0) +// if (strcmp(timelineMap->_name, "rotate") == 0) // { -// spRotateTimeline *timeline = spRotateTimeline_create(timelineMap->size); +// spRotateTimeline *timeline = spRotateTimeline_create(timelineMap->_size); // timeline->boneIndex = boneIndex; // -// for (valueMap = timelineMap->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) +// for (valueMap = timelineMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) // { // spRotateTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), Json_getFloat(valueMap, "angle", 0)); // readCurve(valueMap, SUPER(timeline), frameIndex); // } -// animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); -// animation->duration = MAX(animation->duration, timeline->frames[(timelineMap->size - 1) * ROTATE_ENTRIES]); +// timelines[timelinesCount++] = SUPER_CAST(spTimeline, timeline); +// duration = MAX(duration, timeline->frames[(timelineMap->_size - 1) * ROTATE_ENTRIES]); // } // else // { -// int isScale = strcmp(timelineMap->name, "scale") == 0; -// int isTranslate = strcmp(timelineMap->name, "translate") == 0; -// int isShear = strcmp(timelineMap->name, "shear") == 0; +// int isScale = strcmp(timelineMap->_name, "scale") == 0; +// int isTranslate = strcmp(timelineMap->_name, "translate") == 0; +// int isShear = strcmp(timelineMap->_name, "shear") == 0; // if (isScale || isTranslate || isShear) // { -// float timelineScale = isTranslate ? self->scale: 1; +// float timelineScale = isTranslate ? _scale: 1; // spTranslateTimeline *timeline = 0; // if (isScale) // { -// timeline = spScaleTimeline_create(timelineMap->size); +// timeline = spScaleTimeline_create(timelineMap->_size); // } // else if (isTranslate) // { -// timeline = spTranslateTimeline_create(timelineMap->size); +// timeline = spTranslateTimeline_create(timelineMap->_size); // } // else if (isShear) // { -// timeline = spShearTimeline_create(timelineMap->size); +// timeline = spShearTimeline_create(timelineMap->_size); // } // timeline->boneIndex = boneIndex; // -// for (valueMap = timelineMap->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) +// for (valueMap = timelineMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) // { // spTranslateTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), Json_getFloat(valueMap, "x", 0) * timelineScale, Json_getFloat(valueMap, "y", 0) * timelineScale); // readCurve(valueMap, SUPER(timeline), frameIndex); // } // -// animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); -// animation->duration = MAX(animation->duration, timeline->frames[(timelineMap->size - 1) * TRANSLATE_ENTRIES]); +// timelines[timelinesCount++] = SUPER_CAST(spTimeline, timeline); +// duration = MAX(duration, timeline->frames[(timelineMap->_size - 1) * TRANSLATE_ENTRIES]); // } // else // { -// spAnimation_dispose(animation); -// _spSkeletonJson_setError(self, 0, "Invalid timeline type for a bone: ", timelineMap->name); -// return 0; +// setError(root, "Invalid timeline type for a bone: ", timelineMap->_name); +// return NULL; // } // } // } -// } -// -// /* IK constraint timelines. */ -// for (constraintMap = ik ? ik->child : 0; constraintMap; constraintMap = constraintMap->next) -// { -// spIkConstraintData* constraint = spSkeletonData_findIkConstraint(skeletonData, constraintMap->name); -// spIkConstraintTimeline* timeline = spIkConstraintTimeline_create(constraintMap->size); + } + + /* IK constraint timelines. */ + for (constraintMap = ik ? ik->_child : 0; constraintMap; constraintMap = constraintMap->_next) + { +// spIkConstraintData* constraint = spSkeletonData_findIkConstraint(skeletonData, constraintMap->_name); +// spIkConstraintTimeline* timeline = spIkConstraintTimeline_create(constraintMap->_size); // for (frameIndex = 0; frameIndex < skeletonData->ikConstraintsCount; ++frameIndex) // { // if (constraint == skeletonData->ikConstraints[frameIndex]) @@ -891,20 +904,20 @@ namespace Spine // break; // } // } -// for (valueMap = constraintMap->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) +// for (valueMap = constraintMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) // { // spIkConstraintTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), Json_getFloat(valueMap, "mix", 1), Json_getInt(valueMap, "bendPositive", 1) ? 1 : -1); // readCurve(valueMap, SUPER(timeline), frameIndex); // } -// animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); -// animation->duration = MAX(animation->duration, timeline->frames[(constraintMap->size - 1) * IKCONSTRAINT_ENTRIES]); -// } -// -// /* Transform constraint timelines. */ -// for (constraintMap = transform ? transform->child : 0; constraintMap; constraintMap = constraintMap->next) -// { -// spTransformConstraintData* constraint = spSkeletonData_findTransformConstraint(skeletonData, constraintMap->name); -// spTransformConstraintTimeline* timeline = spTransformConstraintTimeline_create(constraintMap->size); +// timelines[timelinesCount++] = SUPER_CAST(spTimeline, timeline); +// duration = MAX(duration, timeline->frames[(constraintMap->_size - 1) * IKCONSTRAINT_ENTRIES]); + } + + /* Transform constraint timelines. */ + for (constraintMap = transform ? transform->_child : 0; constraintMap; constraintMap = constraintMap->_next) + { +// spTransformConstraintData* constraint = spSkeletonData_findTransformConstraint(skeletonData, constraintMap->_name); +// spTransformConstraintTimeline* timeline = spTransformConstraintTimeline_create(constraintMap->_size); // for (frameIndex = 0; frameIndex < skeletonData->transformConstraintsCount; ++frameIndex) // { // if (constraint == skeletonData->transformConstraints[frameIndex]) @@ -913,27 +926,26 @@ namespace Spine // break; // } // } -// for (valueMap = constraintMap->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) +// for (valueMap = constraintMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) // { // spTransformConstraintTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), Json_getFloat(valueMap, "rotateMix", 1), Json_getFloat(valueMap, "translateMix", 1), Json_getFloat(valueMap, "scaleMix", 1), Json_getFloat(valueMap, "shearMix", 1)); // readCurve(valueMap, SUPER(timeline), frameIndex); // } -// animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); -// animation->duration = MAX(animation->duration, timeline->frames[(constraintMap->size - 1) * TRANSFORMCONSTRAINT_ENTRIES]); -// } -// -// /** Path constraint timelines. */ -// for (constraintMap = paths ? paths->child : 0; constraintMap; constraintMap = constraintMap->next) -// { +// timelines[timelinesCount++] = SUPER_CAST(spTimeline, timeline); +// duration = MAX(duration, timeline->frames[(constraintMap->_size - 1) * TRANSFORMCONSTRAINT_ENTRIES]); + } + + /** Path constraint timelines. */ + for (constraintMap = paths ? paths->_child : 0; constraintMap; constraintMap = constraintMap->_next) + { // int constraintIndex, i; // Json* timelineMap; // -// spPathConstraintData* data = spSkeletonData_findPathConstraint(skeletonData, constraintMap->name); +// spPathConstraintData* data = spSkeletonData_findPathConstraint(skeletonData, constraintMap->_name); // if (!data) // { -// spAnimation_dispose(animation); -// _spSkeletonJson_setError(self, root, "Path constraint not found: ", constraintMap->name); -// return 0; +// setError(root, "Path constraint not found: ", constraintMap->_name); +// return NULL; // } // // for (i = 0; i < skeletonData->pathConstraintsCount; i++) @@ -945,86 +957,85 @@ namespace Spine // } // } // -// for (timelineMap = constraintMap->child; timelineMap; timelineMap = timelineMap->next) +// for (timelineMap = constraintMap->_child; timelineMap; timelineMap = timelineMap->_next) // { -// const char* timelineName = timelineMap->name; +// const char* timelineName = timelineMap->_name; // if (strcmp(timelineName, "position") == 0 || strcmp(timelineName, "spacing") == 0) // { // spPathConstraintPositionTimeline* timeline; // float timelineScale = 1; // if (strcmp(timelineName, "spacing") == 0) // { -// timeline = (spPathConstraintPositionTimeline*)spPathConstraintSpacingTimeline_create(timelineMap->size); +// timeline = (spPathConstraintPositionTimeline*)spPathConstraintSpacingTimeline_create(timelineMap->_size); // if (data->spacingMode == SP_SPACING_MODE_LENGTH || data->spacingMode == SP_SPACING_MODE_FIXED) // { -// timelineScale = self->scale; +// timelineScale = _scale; // } // } // else // { -// timeline = spPathConstraintPositionTimeline_create(timelineMap->size); +// timeline = spPathConstraintPositionTimeline_create(timelineMap->_size); // if (data->positionMode == SP_POSITION_MODE_FIXED) // { -// timelineScale = self->scale; +// timelineScale = _scale; // } // } // // timeline->pathConstraintIndex = constraintIndex; -// for (valueMap = timelineMap->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) +// for (valueMap = timelineMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) // { // spPathConstraintPositionTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), Json_getFloat(valueMap, timelineName, 0) * timelineScale); // readCurve(valueMap, SUPER(timeline), frameIndex); // } -// animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); -// animation->duration = MAX(animation->duration, timeline->frames[(timelineMap->size - 1) * PATHCONSTRAINTPOSITION_ENTRIES]); +// timelines[timelinesCount++] = SUPER_CAST(spTimeline, timeline); +// duration = MAX(duration, timeline->frames[(timelineMap->_size - 1) * PATHCONSTRAINTPOSITION_ENTRIES]); // } // else if (strcmp(timelineName, "mix") == 0) // { -// spPathConstraintMixTimeline* timeline = spPathConstraintMixTimeline_create(timelineMap->size); +// spPathConstraintMixTimeline* timeline = spPathConstraintMixTimeline_create(timelineMap->_size); // timeline->pathConstraintIndex = constraintIndex; -// for (valueMap = timelineMap->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) +// for (valueMap = timelineMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) // { // spPathConstraintMixTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), Json_getFloat(valueMap, "rotateMix", 1), Json_getFloat(valueMap, "translateMix", 1)); // readCurve(valueMap, SUPER(timeline), frameIndex); // } -// animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); -// animation->duration = MAX(animation->duration, timeline->frames[(timelineMap->size - 1) * PATHCONSTRAINTMIX_ENTRIES]); +// timelines[timelinesCount++] = SUPER_CAST(spTimeline, timeline); +// duration = MAX(duration, timeline->frames[(timelineMap->_size - 1) * PATHCONSTRAINTMIX_ENTRIES]); // } // } -// } -// -// /* Deform timelines. */ -// for (constraintMap = deform ? deform->child : 0; constraintMap; constraintMap = constraintMap->next) -// { -// spSkin* skin = spSkeletonData_findSkin(skeletonData, constraintMap->name); -// for (slotMap = constraintMap->child; slotMap; slotMap = slotMap->next) + } + + /* Deform timelines. */ + for (constraintMap = deform ? deform->_child : 0; constraintMap; constraintMap = constraintMap->_next) + { +// spSkin* skin = spSkeletonData_findSkin(skeletonData, constraintMap->_name); +// for (slotMap = constraintMap->_child; slotMap; slotMap = slotMap->_next) // { -// int slotIndex = spSkeletonData_findSlotIndex(skeletonData, slotMap->name); +// int slotIndex = spSkeletonData_findSlotIndex(skeletonData, slotMap->_name); // Json* timelineMap; -// for (timelineMap = slotMap->child; timelineMap; timelineMap = timelineMap->next) +// for (timelineMap = slotMap->_child; timelineMap; timelineMap = timelineMap->_next) // { // float* tempDeform; // spDeformTimeline *timeline; // int weighted, deformLength; // -// spVertexAttachment* attachment = SUB_CAST(spVertexAttachment, spSkin_getAttachment(skin, slotIndex, timelineMap->name)); +// spVertexAttachment* attachment = SUB_CAST(spVertexAttachment, spSkin_getAttachment(skin, slotIndex, timelineMap->_name)); // if (!attachment) // { -// spAnimation_dispose(animation); -// _spSkeletonJson_setError(self, 0, "Attachment not found: ", timelineMap->name); -// return 0; +// setError(root, "Attachment not found: ", timelineMap->_name); +// return NULL; // } // weighted = attachment->bones != 0; // deformLength = weighted ? attachment->verticesCount / 3 * 2 : attachment->verticesCount; // tempDeform = MALLOC(float, deformLength); // -// timeline = spDeformTimeline_create(timelineMap->size, deformLength); +// timeline = spDeformTimeline_create(timelineMap->_size, deformLength); // timeline->slotIndex = slotIndex; // timeline->attachment = SUPER(attachment); // -// for (valueMap = timelineMap->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) +// for (valueMap = timelineMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) // { -// Json* vertices = Json_getItem(valueMap, "vertices"); +// Json* vertices = Json::getItem(valueMap, "vertices"); // float* deform2; // if (!vertices) // { @@ -1044,18 +1055,18 @@ namespace Spine // Json* vertex; // deform2 = tempDeform; // memset(deform, 0, sizeof(float) * start); -// if (self->scale == 1) +// if (_scale == 1) // { -// for (vertex = vertices->child, v = start; vertex; vertex = vertex->next, ++v) +// for (vertex = vertices->_child, v = start; vertex; vertex = vertex->_next, ++v) // { -// deform2[v] = vertex->valueFloat; +// deform2[v] = vertex->_valueFloat; // } // } // else // { -// for (vertex = vertices->child, v = start; vertex; vertex = vertex->next, ++v) +// for (vertex = vertices->_child, v = start; vertex; vertex = vertex->_next, ++v) // { -// deform2[v] = vertex->valueFloat * self->scale; +// deform2[v] = vertex->_valueFloat * _scale; // } // } // memset(deform + v, 0, sizeof(float) * (deformLength - v)); @@ -1073,25 +1084,25 @@ namespace Spine // } // FREE(tempDeform); // -// animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); -// animation->duration = MAX(animation->duration, timeline->frames[timelineMap->size - 1]); +// timelines[timelinesCount++] = SUPER_CAST(spTimeline, timeline); +// duration = MAX(duration, timeline->frames[timelineMap->_size - 1]); // } // } -// } -// -// /* Draw order timeline. */ -// if (drawOrder) -// { -// spDrawOrderTimeline* timeline = spDrawOrderTimeline_create(drawOrder->size, skeletonData->slotsCount); -// for (valueMap = drawOrder->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) + } + + /* Draw order timeline. */ + if (drawOrder) + { +// spDrawOrderTimeline* timeline = spDrawOrderTimeline_create(drawOrder->_size, skeletonData->slotsCount); +// for (valueMap = drawOrder->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) // { // int ii; // int* drawOrder2 = 0; -// Json* offsets = Json_getItem(valueMap, "offsets"); +// Json* offsets = Json::getItem(valueMap, "offsets"); // if (offsets) // { // Json* offsetMap; -// int* unchanged = MALLOC(int, skeletonData->slotsCount - offsets->size); +// int* unchanged = MALLOC(int, skeletonData->slotsCount - offsets->_size); // int originalIndex = 0, unchangedIndex = 0; // // drawOrder2 = MALLOC(int, skeletonData->slotsCount); @@ -1100,14 +1111,13 @@ namespace Spine // drawOrder2[ii] = -1; // } // -// for (offsetMap = offsets->child; offsetMap; offsetMap = offsetMap->next) +// for (offsetMap = offsets->_child; offsetMap; offsetMap = offsetMap->_next) // { // int slotIndex = spSkeletonData_findSlotIndex(skeletonData, Json_getString(offsetMap, "slot", 0)); // if (slotIndex == -1) // { -// spAnimation_dispose(animation); -// _spSkeletonJson_setError(self, 0, "Slot not found: ", Json_getString(offsetMap, "slot", 0)); -// return 0; +// setError(root, "Slot not found: ", Json_getString(offsetMap, "slot", 0)); +// return NULL; // } // /* Collect unchanged items. */ // while (originalIndex != slotIndex) @@ -1136,24 +1146,23 @@ namespace Spine // spDrawOrderTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), drawOrder2); // FREE(drawOrder2); // } -// animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); -// animation->duration = MAX(animation->duration, timeline->frames[drawOrder->size - 1]); -// } -// -// /* Event timeline. */ -// if (events) -// { -// spEventTimeline* timeline = spEventTimeline_create(events->size); -// for (valueMap = events->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) +// timelines[timelinesCount++] = SUPER_CAST(spTimeline, timeline); +// duration = MAX(duration, timeline->frames[drawOrder->_size - 1]); + } + + /* Event timeline. */ + if (events) + { +// spEventTimeline* timeline = spEventTimeline_create(events->_size); +// for (valueMap = events->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) // { // spEvent* event; // const char* stringValue; // spEventData* eventData = spSkeletonData_findEvent(skeletonData, Json_getString(valueMap, "name", 0)); // if (!eventData) // { -// spAnimation_dispose(animation); -// _spSkeletonJson_setError(self, 0, "Event not found: ", Json_getString(valueMap, "name", 0)); -// return 0; +// setError(root, "Event not found: ", Json_getString(valueMap, "name", 0)); +// return NULL; // } // event = spEvent_create(Json_getFloat(valueMap, "time", 0), eventData); // event->intValue = Json_getInt(valueMap, "int", eventData->intValue); @@ -1165,90 +1174,83 @@ namespace Spine // } // spEventTimeline_setFrame(timeline, frameIndex, event); // } -// animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); -// animation->duration = MAX(animation->duration, timeline->frames[events->size - 1]); -// } -// -// return animation; - return NULL; +// timelines[timelinesCount++] = SUPER_CAST(spTimeline, timeline); +// duration = MAX(duration, timeline->frames[events->_size - 1]); + } + + Animation* ret = NEW(Animation); + new (ret) Animation(std::string(root->_name), timelines, duration); + + return ret; } void SkeletonJson::readVertices(Json* attachmentMap, VertexAttachment* attachment, int verticesLength) { -// Json* entry; -// float* vertices; -// int i, n, nn, entrySize; -// spFloatArray* weights; -// spIntArray* bones; -// -// attachment->worldVerticesLength = verticesLength; -// -// entry = Json_getItem(attachmentMap, "vertices"); -// entrySize = entry->size; -// vertices = MALLOC(float, entrySize); -// for (entry = entry->child, i = 0; entry; entry = entry->next, ++i) -// { -// vertices[i] = entry->valueFloat; -// } -// -// if (verticesLength == entrySize) -// { -// if (self->scale != 1) -// { -// for (i = 0; i < entrySize; ++i) -// { -// vertices[i] *= self->scale; -// } -// } -// attachment->verticesCount = verticesLength; -// attachment->vertices = vertices; -// -// attachment->bonesCount = 0; -// attachment->bones = 0; -// return; -// } -// -// weights = spFloatArray_create(verticesLength * 3 * 3); -// bones = spIntArray_create(verticesLength * 3); -// -// for (i = 0, n = entrySize; i < n;) -// { -// int boneCount = (int)vertices[i++]; -// spIntArray_add(bones, boneCount); -// for (nn = i + boneCount * 4; i < nn; i += 4) -// { -// spIntArray_add(bones, (int)vertices[i]); -// spFloatArray_add(weights, vertices[i + 1] * self->scale); -// spFloatArray_add(weights, vertices[i + 2] * self->scale); -// spFloatArray_add(weights, vertices[i + 3]); -// } -// } -// -// attachment->verticesCount = weights->size; -// attachment->vertices = weights->items; -// FREE(weights); -// attachment->bonesCount = bones->size; -// attachment->bones = bones->items; -// FREE(bones); -// -// FREE(vertices); + Json* entry; + int i, n, nn, entrySize; + Vector vertices; + + attachment->setWorldVerticesLength(verticesLength); + + entry = Json::getItem(attachmentMap, "vertices"); + entrySize = entry->_size; + vertices.reserve(entrySize); + for (entry = entry->_child, i = 0; entry; entry = entry->_next, ++i) + { + vertices[i] = entry->_valueFloat; + } + + if (verticesLength == entrySize) + { + if (_scale != 1) + { + for (i = 0; i < entrySize; ++i) + { + vertices[i] *= _scale; + } + } + + attachment->setVertices(vertices); + return; + } + + Vertices bonesAndWeights; + bonesAndWeights._bones.reserve(verticesLength * 3); + bonesAndWeights._vertices.reserve(verticesLength * 3 * 3); + + for (i = 0, n = entrySize; i < n;) + { + int boneCount = (int)vertices[i++]; + bonesAndWeights._bones.push_back(boneCount); + for (nn = i + boneCount * 4; i < nn; i += 4) + { + bonesAndWeights._bones.push_back((int)vertices[i]); + bonesAndWeights._vertices.push_back(vertices[i + 1] * _scale); + bonesAndWeights._vertices.push_back(vertices[i + 2] * _scale); + bonesAndWeights._vertices.push_back(vertices[i + 3]); + } + } + + attachment->setVertices(bonesAndWeights._vertices); + attachment->setBones(bonesAndWeights._bones); } void SkeletonJson::setError(Json* root, const char* value1, const char* value2) { -// char message[256]; -// int length; -// strcpy(message, value1); -// length = (int)strlen(value1); -// if (value2) -// { -// strncat(message + length, value2, 255 - length); -// } -// -// _error = std::string(message); -// if (root) -// { -// DESTROY(Json, root); -// } + char message[256]; + int length; + strcpy(message, value1); + length = (int)strlen(value1); + if (value2) + { + strncat(message + length, value2, 255 - length); + } + + _error = std::string(message); + + if (root) + { + DESTROY(Json, root); + } } } From 52e04508f6153f1e863539e41ee7d0a8a2610566 Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Tue, 5 Dec 2017 17:44:30 -0500 Subject: [PATCH 67/83] Almost Done! --- .../spine-cpp/include/spine/EventTimeline.h | 4 +- .../spine-cpp/src/spine/EventTimeline.cpp | 12 +- .../spine-cpp/src/spine/SkeletonJson.cpp | 1787 +++++++++-------- 3 files changed, 987 insertions(+), 816 deletions(-) diff --git a/spine-cpp/spine-cpp/include/spine/EventTimeline.h b/spine-cpp/spine-cpp/include/spine/EventTimeline.h index 30e761b66..5fb6fd5e9 100644 --- a/spine-cpp/spine-cpp/include/spine/EventTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/EventTimeline.h @@ -45,12 +45,14 @@ namespace Spine public: EventTimeline(int frameCount); + ~EventTimeline(); + virtual void apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction); virtual int getPropertyId(); /// Sets the time and value of the specified keyframe. - void setFrame(int frameIndex, Event* e); + void setFrame(int frameIndex, Event* event); Vector getFrames(); void setFrames(Vector& inValue); diff --git a/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp b/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp index 23a0fccab..5b26a44d0 100644 --- a/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp @@ -38,6 +38,7 @@ #include #include #include +#include namespace Spine { @@ -49,6 +50,11 @@ namespace Spine _events.reserve(frameCount); } + EventTimeline::~EventTimeline() + { + ContainerUtil::cleanUpVectorOfPointers(_events); + } + void EventTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) { if (pEvents == NULL) @@ -112,10 +118,10 @@ namespace Spine return ((int)TimelineType_Event << 24); } - void EventTimeline::setFrame(int frameIndex, Event* e) + void EventTimeline::setFrame(int frameIndex, Event* event) { - _frames[frameIndex] = e->getTime(); - _events[frameIndex] = e; + _frames[frameIndex] = event->getTime(); + _events[frameIndex] = event; } Vector EventTimeline::getFrames() { return _frames; } diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp b/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp index 110021e60..493b62e4f 100644 --- a/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp +++ b/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp @@ -40,6 +40,7 @@ #include #include +#include #include #include #include @@ -136,340 +137,438 @@ namespace Spine if (!root) { - setError(root, "Invalid skeleton JSON: ", Json::getError()); + setError(NULL, "Invalid skeleton JSON: ", Json::getError()); return NULL; } skeletonData = NEW(SkeletonData); new (skeletonData) SkeletonData(); -// skeleton = Json::getItem(root, "skeleton"); -// if (skeleton) { -// MALLOC_STR(skeletonData->hash, Json_getString(skeleton, "hash", 0)); -// MALLOC_STR(skeletonData->version, Json_getString(skeleton, "spine", 0)); -// skeletonData->width = Json_getFloat(skeleton, "width", 0); -// skeletonData->height = Json_getFloat(skeleton, "height", 0); -// } + skeleton = Json::getItem(root, "skeleton"); + if (skeleton) + { + skeletonData->_hash = Json::getString(skeleton, "hash", 0); + skeletonData->_version = Json::getString(skeleton, "spine", 0); + skeletonData->_width = Json::getFloat(skeleton, "width", 0); + skeletonData->_height = Json::getFloat(skeleton, "height", 0); + } + + /* Bones. */ + bones = Json::getItem(root, "bones"); + skeletonData->_bones.reserve(bones->_size); + for (boneMap = bones->_child, i = 0; boneMap; boneMap = boneMap->_next, ++i) + { + BoneData* data; + const char* transformMode; + + BoneData* parent = 0; + const char* parentName = Json::getString(boneMap, "parent", 0); + if (parentName) + { + parent = skeletonData->findBone(parentName); + if (!parent) + { + DESTROY(SkeletonData, skeletonData); + setError(root, "Parent bone not found: ", parentName); + return NULL; + } + } + + data = NEW(BoneData); + new (data) BoneData(static_cast(skeletonData->_bones.size()), Json::getString(boneMap, "name", 0), parent); + + data->_length = Json::getFloat(boneMap, "length", 0) * _scale; + data->_x = Json::getFloat(boneMap, "x", 0) * _scale; + data->_y = Json::getFloat(boneMap, "y", 0) * _scale; + data->_rotation = Json::getFloat(boneMap, "rotation", 0); + data->_scaleX = Json::getFloat(boneMap, "scaleX", 1); + data->_scaleY = Json::getFloat(boneMap, "scaleY", 1); + data->_shearX = Json::getFloat(boneMap, "shearX", 0); + data->_shearY = Json::getFloat(boneMap, "shearY", 0); + transformMode = Json::getString(boneMap, "transform", "normal"); + data->_transformMode = TransformMode_Normal; + if (strcmp(transformMode, "normal") == 0) + { + data->_transformMode = TransformMode_Normal; + } + if (strcmp(transformMode, "onlyTranslation") == 0) + { + data->_transformMode = TransformMode_OnlyTranslation; + } + if (strcmp(transformMode, "noRotationOrReflection") == 0) + { + data->_transformMode = TransformMode_NoRotationOrReflection; + } + if (strcmp(transformMode, "noScale") == 0) + { + data->_transformMode = TransformMode_NoScale; + } + if (strcmp(transformMode, "noScaleOrReflection") == 0) + { + data->_transformMode = TransformMode_NoScaleOrReflection; + } + + skeletonData->_bones[i] = data; + } + + /* Slots. */ + slots = Json::getItem(root, "slots"); + if (slots) + { + Json *slotMap; + skeletonData->_slots.reserve(slots->_size); + for (slotMap = slots->_child, i = 0; slotMap; slotMap = slotMap->_next, ++i) + { + SlotData* data; + const char* color; + const char* dark; + Json *item; + + const char* boneName = Json::getString(slotMap, "bone", 0); + BoneData* boneData = skeletonData->findBone(boneName); + if (!boneData) + { + DESTROY(SkeletonData, skeletonData); + setError(root, "Slot bone not found: ", boneName); + return NULL; + } + + data = NEW(SlotData); + new (data) SlotData(i, Json::getString(slotMap, "name", 0), *boneData); + + color = Json::getString(slotMap, "color", 0); + if (color) + { + data->_r = toColor(color, 0); + data->_g = toColor(color, 1); + data->_b = toColor(color, 2); + data->_a = toColor(color, 3); + } + + dark = Json::getString(slotMap, "dark", 0); + if (dark) + { + data->_r2 = toColor(dark, 0); + data->_g2 = toColor(dark, 1); + data->_b2 = toColor(dark, 2); + data->_a2 = toColor(dark, 3); + data->_hasSecondColor = true; + } + + item = Json::getItem(slotMap, "attachment"); + if (item) + { + data->setAttachmentName(item->_valueString); + } + + item = Json::getItem(slotMap, "blend"); + if (item) + { + if (strcmp(item->_valueString, "additive") == 0) + { + data->_blendMode = BlendMode_Additive; + } + else if (strcmp(item->_valueString, "multiply") == 0) + { + data->_blendMode = BlendMode_Multiply; + } + else if (strcmp(item->_valueString, "screen") == 0) + { + data->_blendMode = BlendMode_Screen; + } + } + + skeletonData->_slots[i] = data; + } + } + + /* IK constraints. */ + ik = Json::getItem(root, "ik"); + if (ik) + { + Json *constraintMap; + skeletonData->_ikConstraints.reserve(ik->_size); + for (constraintMap = ik->_child, i = 0; constraintMap; constraintMap = constraintMap->_next, ++i) + { + const char* targetName; + + IkConstraintData* data = NEW(IkConstraintData); + new (data) IkConstraintData(Json::getString(constraintMap, "name", 0)); + + data->_order = Json::getInt(constraintMap, "order", 0); + + boneMap = Json::getItem(constraintMap, "bones"); + data->_bones.reserve(boneMap->_size); + for (boneMap = boneMap->_child, ii = 0; boneMap; boneMap = boneMap->_next, ++ii) + { + data->_bones[ii] = skeletonData->findBone(boneMap->_valueString); + if (!data->_bones[ii]) + { + DESTROY(SkeletonData, skeletonData); + setError(root, "IK bone not found: ", boneMap->_valueString); + return NULL; + } + } + + targetName = Json::getString(constraintMap, "target", 0); + data->_target = skeletonData->findBone(targetName); + if (!data->_target) + { + DESTROY(SkeletonData, skeletonData); + setError(root, "Target bone not found: ", boneMap->_name); + return NULL; + } + + data->_bendDirection = Json::getInt(constraintMap, "bendPositive", 1) ? 1 : -1; + data->_mix = Json::getFloat(constraintMap, "mix", 1); + + skeletonData->_ikConstraints[i] = data; + } + } + + /* Transform constraints. */ + transform = Json::getItem(root, "transform"); + if (transform) + { + Json *constraintMap; + skeletonData->_transformConstraints.reserve(transform->_size); + for (constraintMap = transform->_child, i = 0; constraintMap; constraintMap = constraintMap->_next, ++i) + { + const char* name; + + TransformConstraintData* data = NEW(TransformConstraintData); + new (data) TransformConstraintData(Json::getString(constraintMap, "name", 0)); + + data->_order = Json::getInt(constraintMap, "order", 0); + + boneMap = Json::getItem(constraintMap, "bones"); + data->_bones.reserve(boneMap->_size); + for (boneMap = boneMap->_child, ii = 0; boneMap; boneMap = boneMap->_next, ++ii) + { + data->_bones[ii] = skeletonData->findBone(boneMap->_valueString); + if (!data->_bones[ii]) + { + DESTROY(SkeletonData, skeletonData); + setError(root, "Transform bone not found: ", boneMap->_valueString); + return NULL; + } + } + + name = Json::getString(constraintMap, "target", 0); + data->_target = skeletonData->findBone(name); + if (!data->_target) + { + DESTROY(SkeletonData, skeletonData); + setError(root, "Target bone not found: ", boneMap->_name); + return NULL; + } + + data->_local = Json::getInt(constraintMap, "local", 0); + data->_relative = Json::getInt(constraintMap, "relative", 0); + data->_offsetRotation = Json::getFloat(constraintMap, "rotation", 0); + data->_offsetX = Json::getFloat(constraintMap, "x", 0) * _scale; + data->_offsetY = Json::getFloat(constraintMap, "y", 0) * _scale; + data->_offsetScaleX = Json::getFloat(constraintMap, "scaleX", 0); + data->_offsetScaleY = Json::getFloat(constraintMap, "scaleY", 0); + data->_offsetShearY = Json::getFloat(constraintMap, "shearY", 0); + + data->_rotateMix = Json::getFloat(constraintMap, "rotateMix", 1); + data->_translateMix = Json::getFloat(constraintMap, "translateMix", 1); + data->_scaleMix = Json::getFloat(constraintMap, "scaleMix", 1); + data->_shearMix = Json::getFloat(constraintMap, "shearMix", 1); + + skeletonData->_transformConstraints[i] = data; + } + } + + /* Path constraints */ + path = Json::getItem(root, "path"); + if (path) + { + Json *constraintMap; + skeletonData->_pathConstraints.reserve(path->_size); + for (constraintMap = path->_child, i = 0; constraintMap; constraintMap = constraintMap->_next, ++i) + { + const char* name; + const char* item; + + PathConstraintData* data = NEW(PathConstraintData); + new (data) PathConstraintData(Json::getString(constraintMap, "name", 0)); + + data->_order = Json::getInt(constraintMap, "order", 0); + + boneMap = Json::getItem(constraintMap, "bones"); + data->_bones.reserve(boneMap->_size); + for (boneMap = boneMap->_child, ii = 0; boneMap; boneMap = boneMap->_next, ++ii) + { + data->_bones[ii] = skeletonData->findBone(boneMap->_valueString); + if (!data->_bones[ii]) + { + DESTROY(SkeletonData, skeletonData); + setError(root, "Path bone not found: ", boneMap->_valueString); + return NULL; + } + } + + name = Json::getString(constraintMap, "target", 0); + data->_target = skeletonData->findSlot(name); + if (!data->_target) + { + DESTROY(SkeletonData, skeletonData); + setError(root, "Target slot not found: ", boneMap->_name); + return NULL; + } + + item = Json::getString(constraintMap, "positionMode", "percent"); + if (strcmp(item, "fixed") == 0) + { + data->_positionMode = PositionMode_Fixed; + } + else if (strcmp(item, "percent") == 0) + { + data->_positionMode = PositionMode_Percent; + } + + item = Json::getString(constraintMap, "spacingMode", "length"); + if (strcmp(item, "length") == 0) + { + data->_spacingMode = SpacingMode_Length; + } + else if (strcmp(item, "fixed") == 0) + { + data->_spacingMode = SpacingMode_Fixed; + } + else if (strcmp(item, "percent") == 0) + { + data->_spacingMode = SpacingMode_Percent; + } + + item = Json::getString(constraintMap, "rotateMode", "tangent"); + if (strcmp(item, "tangent") == 0) + { + data->_rotateMode = RotateMode_Tangent; + } + else if (strcmp(item, "chain") == 0) + { + data->_rotateMode = RotateMode_Chain; + } + else if (strcmp(item, "chainScale") == 0) + { + data->_rotateMode = RotateMode_ChainScale; + } + + data->_offsetRotation = Json::getFloat(constraintMap, "rotation", 0); + data->_position = Json::getFloat(constraintMap, "position", 0); + if (data->_positionMode == PositionMode_Fixed) + { + data->_position *= _scale; + } + data->_spacing = Json::getFloat(constraintMap, "spacing", 0); + if (data->_spacingMode == SpacingMode_Length || data->_spacingMode == SpacingMode_Fixed) + { + data->_spacing *= _scale; + } + data->_rotateMix = Json::getFloat(constraintMap, "rotateMix", 1); + data->_translateMix = Json::getFloat(constraintMap, "translateMix", 1); + + skeletonData->_pathConstraints[i] = data; + } + } + + /* Skins. */ + skins = Json::getItem(root, "skins"); + if (skins) + { + Json *skinMap; + skeletonData->_skins.reserve(skins->_size); + int skinsIndex = 0; + for (skinMap = skins->_child, i = 0; skinMap; skinMap = skinMap->_next, ++i) + { + Json *attachmentsMap; + Json *curves; + + Skin* skin = NEW(Skin); + new (skin) Skin(skinMap->_name); + + skeletonData->_skins[skinsIndex++] = skin; + if (strcmp(skinMap->_name, "default") == 0) + { + skeletonData->_defaultSkin = skin; + } + + for (attachmentsMap = skinMap->_child; attachmentsMap; attachmentsMap = attachmentsMap->_next) + { + int slotIndex = skeletonData->findSlotIndex(attachmentsMap->_name); + Json *attachmentMap; + + for (attachmentMap = attachmentsMap->_child; attachmentMap; attachmentMap = attachmentMap->_next) + { + Attachment* attachment; + const char* skinAttachmentName = attachmentMap->_name; + const char* attachmentName = Json::getString(attachmentMap, "name", skinAttachmentName); + const char* attachmentPath = Json::getString(attachmentMap, "path", attachmentName); + const char* color; + Json* entry; + + const char* typeString = Json::getString(attachmentMap, "type", "region"); + AttachmentType type; + if (strcmp(typeString, "region") == 0) + { + type = AttachmentType_Region; + } + else if (strcmp(typeString, "mesh") == 0) + { + type = AttachmentType_Mesh; + } + else if (strcmp(typeString, "linkedmesh") == 0) + { + type = AttachmentType_Linkedmesh; + } + else if (strcmp(typeString, "boundingbox") == 0) + { + type = AttachmentType_Boundingbox; + } + else if (strcmp(typeString, "path") == 0) + { + type = AttachmentType_Path; + } + else if (strcmp(typeString, "clipping") == 0) + { + type = AttachmentType_Clipping; + } + else + { + DESTROY(SkeletonData, skeletonData); + setError(root, "Unknown attachment type: ", typeString); + return NULL; + } + +// switch (type) +// { +// case AttachmentType_Region: +// { +// attachment = _attachmentLoader->newRegionAttachment(*skin, attachmentName, attachmentPath); +// if (!attachment) +// { +// DESTROY(SkeletonData, skeletonData); +// setError(root, "Error reading attachment: ", skinAttachmentName); +// return NULL; +// } // -// /* Bones. */ -// bones = Json::getItem(root, "bones"); -// skeletonData->bones = MALLOC(spBoneData*, bones->_size); -// for (boneMap = bones->_child, i = 0; boneMap; boneMap = boneMap->_next, ++i) { -// spBoneData* data; -// const char* transformMode; +// RegionAttachment* region = static_cast(attachment); +// region->_path = attachmentPath; // -// spBoneData* parent = 0; -// const char* parentName = Json_getString(boneMap, "parent", 0); -// if (parentName) { -// parent = spSkeletonData_findBone(skeletonData, parentName); -// if (!parent) { -// spSkeletonData_dispose(skeletonData); -// setError(root, "Parent bone not found: ", parentName); -// return NULL; -// } -// } +// region->_x = Json::getFloat(attachmentMap, "x", 0) * _scale; +// region->_y = Json::getFloat(attachmentMap, "y", 0) * _scale; +// region->_scaleX = Json::getFloat(attachmentMap, "scaleX", 1); +// region->_scaleY = Json::getFloat(attachmentMap, "scaleY", 1); +// region->_rotation = Json::getFloat(attachmentMap, "rotation", 0); +// region->_width = Json::getFloat(attachmentMap, "width", 32) * _scale; +// region->_height = Json::getFloat(attachmentMap, "height", 32) * _scale; // -// data = spBoneData_create(skeletonData->bonesCount, Json_getString(boneMap, "name", 0), parent); -// data->length = Json_getFloat(boneMap, "length", 0) * _scale; -// data->x = Json_getFloat(boneMap, "x", 0) * _scale; -// data->y = Json_getFloat(boneMap, "y", 0) * _scale; -// data->rotation = Json_getFloat(boneMap, "rotation", 0); -// data->scaleX = Json_getFloat(boneMap, "scaleX", 1); -// data->scaleY = Json_getFloat(boneMap, "scaleY", 1); -// data->shearX = Json_getFloat(boneMap, "shearX", 0); -// data->shearY = Json_getFloat(boneMap, "shearY", 0); -// transformMode = Json_getString(boneMap, "transform", "normal"); -// data->transformMode = SP_TRANSFORMMODE_NORMAL; -// if (strcmp(transformMode, "normal") == 0) -// data->transformMode = SP_TRANSFORMMODE_NORMAL; -// if (strcmp(transformMode, "onlyTranslation") == 0) -// data->transformMode = SP_TRANSFORMMODE_ONLYTRANSLATION; -// if (strcmp(transformMode, "noRotationOrReflection") == 0) -// data->transformMode = SP_TRANSFORMMODE_NOROTATIONORREFLECTION; -// if (strcmp(transformMode, "noScale") == 0) -// data->transformMode = SP_TRANSFORMMODE_NOSCALE; -// if (strcmp(transformMode, "noScaleOrReflection") == 0) -// data->transformMode = SP_TRANSFORMMODE_NOSCALEORREFLECTION; -// -// skeletonData->bones[i] = data; -// skeletonData->bonesCount++; -// } -// -// /* Slots. */ -// slots = Json::getItem(root, "slots"); -// if (slots) { -// Json *slotMap; -// skeletonData->slotsCount = slots->_size; -// skeletonData->slots = MALLOC(spSlotData*, slots->_size); -// for (slotMap = slots->_child, i = 0; slotMap; slotMap = slotMap->_next, ++i) { -// spSlotData* data; -// const char* color; -// const char* dark; -// Json *item; -// -// const char* boneName = Json_getString(slotMap, "bone", 0); -// spBoneData* boneData = spSkeletonData_findBone(skeletonData, boneName); -// if (!boneData) { -// spSkeletonData_dispose(skeletonData); -// setError(root, "Slot bone not found: ", boneName); -// return NULL; -// } -// -// data = spSlotData_create(i, Json_getString(slotMap, "name", 0), boneData); -// -// color = Json_getString(slotMap, "color", 0); -// if (color) { -// spColor_setFromFloats(&data->color, -// toColor(color, 0), -// toColor(color, 1), -// toColor(color, 2), -// toColor(color, 3)); -// } -// -// dark = Json_getString(slotMap, "dark", 0); -// if (dark) { -// data->darkColor = spColor_create(); -// spColor_setFromFloats(data->darkColor, -// toColor(dark, 0), -// toColor(dark, 1), -// toColor(dark, 2), -// toColor(dark, 3)); -// } -// -// item = Json::getItem(slotMap, "attachment"); -// if (item) spSlotData_setAttachmentName(data, item->_valueString); -// -// item = Json::getItem(slotMap, "blend"); -// if (item) { -// if (strcmp(item->_valueString, "additive") == 0) -// data->blendMode = SP_BLEND_MODE_ADDITIVE; -// else if (strcmp(item->_valueString, "multiply") == 0) -// data->blendMode = SP_BLEND_MODE_MULTIPLY; -// else if (strcmp(item->_valueString, "screen") == 0) -// data->blendMode = SP_BLEND_MODE_SCREEN; -// } -// -// skeletonData->slots[i] = data; -// } -// } -// -// /* IK constraints. */ -// ik = Json::getItem(root, "ik"); -// if (ik) { -// Json *constraintMap; -// skeletonData->ikConstraintsCount = ik->_size; -// skeletonData->ikConstraints = MALLOC(spIkConstraintData*, ik->_size); -// for (constraintMap = ik->_child, i = 0; constraintMap; constraintMap = constraintMap->_next, ++i) { -// const char* targetName; -// -// spIkConstraintData* data = spIkConstraintData_create(Json_getString(constraintMap, "name", 0)); -// data->order = Json_getInt(constraintMap, "order", 0); -// -// boneMap = Json::getItem(constraintMap, "bones"); -// data->bonesCount = boneMap->_size; -// data->bones = MALLOC(spBoneData*, boneMap->_size); -// for (boneMap = boneMap->_child, ii = 0; boneMap; boneMap = boneMap->_next, ++ii) { -// data->bones[ii] = spSkeletonData_findBone(skeletonData, boneMap->_valueString); -// if (!data->bones[ii]) { -// spSkeletonData_dispose(skeletonData); -// setError(root, "IK bone not found: ", boneMap->_valueString); -// return NULL; -// } -// } -// -// targetName = Json_getString(constraintMap, "target", 0); -// data->target = spSkeletonData_findBone(skeletonData, targetName); -// if (!data->target) { -// spSkeletonData_dispose(skeletonData); -// setError(root, "Target bone not found: ", boneMap->_name); -// return NULL; -// } -// -// data->bendDirection = Json_getInt(constraintMap, "bendPositive", 1) ? 1 : -1; -// data->mix = Json_getFloat(constraintMap, "mix", 1); -// -// skeletonData->ikConstraints[i] = data; -// } -// } -// -// /* Transform constraints. */ -// transform = Json::getItem(root, "transform"); -// if (transform) { -// Json *constraintMap; -// skeletonData->transformConstraintsCount = transform->_size; -// skeletonData->transformConstraints = MALLOC(spTransformConstraintData*, transform->_size); -// for (constraintMap = transform->_child, i = 0; constraintMap; constraintMap = constraintMap->_next, ++i) { -// const char* name; -// -// spTransformConstraintData* data = spTransformConstraintData_create(Json_getString(constraintMap, "name", 0)); -// data->order = Json_getInt(constraintMap, "order", 0); -// -// boneMap = Json::getItem(constraintMap, "bones"); -// data->bonesCount = boneMap->_size; -// CONST_CAST(spBoneData**, data->bones) = MALLOC(spBoneData*, boneMap->_size); -// for (boneMap = boneMap->_child, ii = 0; boneMap; boneMap = boneMap->_next, ++ii) { -// data->bones[ii] = spSkeletonData_findBone(skeletonData, boneMap->_valueString); -// if (!data->bones[ii]) { -// spSkeletonData_dispose(skeletonData); -// setError(root, "Transform bone not found: ", boneMap->_valueString); -// return NULL; -// } -// } -// -// name = Json_getString(constraintMap, "target", 0); -// data->target = spSkeletonData_findBone(skeletonData, name); -// if (!data->target) { -// spSkeletonData_dispose(skeletonData); -// setError(root, "Target bone not found: ", boneMap->_name); -// return NULL; -// } -// -// data->local = Json_getInt(constraintMap, "local", 0); -// data->relative = Json_getInt(constraintMap, "relative", 0); -// data->offsetRotation = Json_getFloat(constraintMap, "rotation", 0); -// data->offsetX = Json_getFloat(constraintMap, "x", 0) * _scale; -// data->offsetY = Json_getFloat(constraintMap, "y", 0) * _scale; -// data->offsetScaleX = Json_getFloat(constraintMap, "scaleX", 0); -// data->offsetScaleY = Json_getFloat(constraintMap, "scaleY", 0); -// data->offsetShearY = Json_getFloat(constraintMap, "shearY", 0); -// -// data->rotateMix = Json_getFloat(constraintMap, "rotateMix", 1); -// data->translateMix = Json_getFloat(constraintMap, "translateMix", 1); -// data->scaleMix = Json_getFloat(constraintMap, "scaleMix", 1); -// data->shearMix = Json_getFloat(constraintMap, "shearMix", 1); -// -// skeletonData->transformConstraints[i] = data; -// } -// } -// -// /* Path constraints */ -// path = Json::getItem(root, "path"); -// if (path) { -// Json *constraintMap; -// skeletonData->pathConstraintsCount = path->_size; -// skeletonData->pathConstraints = MALLOC(spPathConstraintData*, path->_size); -// for (constraintMap = path->_child, i = 0; constraintMap; constraintMap = constraintMap->_next, ++i) { -// const char* name; -// const char* item; -// -// spPathConstraintData* data = spPathConstraintData_create(Json_getString(constraintMap, "name", 0)); -// data->order = Json_getInt(constraintMap, "order", 0); -// -// boneMap = Json::getItem(constraintMap, "bones"); -// data->bonesCount = boneMap->_size; -// CONST_CAST(spBoneData**, data->bones) = MALLOC(spBoneData*, boneMap->_size); -// for (boneMap = boneMap->_child, ii = 0; boneMap; boneMap = boneMap->_next, ++ii) { -// data->bones[ii] = spSkeletonData_findBone(skeletonData, boneMap->_valueString); -// if (!data->bones[ii]) { -// spSkeletonData_dispose(skeletonData); -// setError(root, "Path bone not found: ", boneMap->_valueString); -// return NULL; -// } -// } -// -// name = Json_getString(constraintMap, "target", 0); -// data->target = spSkeletonData_findSlot(skeletonData, name); -// if (!data->target) { -// spSkeletonData_dispose(skeletonData); -// setError(root, "Target slot not found: ", boneMap->_name); -// return NULL; -// } -// -// item = Json_getString(constraintMap, "positionMode", "percent"); -// if (strcmp(item, "fixed") == 0) data->positionMode = SP_POSITION_MODE_FIXED; -// else if (strcmp(item, "percent") == 0) data->positionMode = SP_POSITION_MODE_PERCENT; -// -// item = Json_getString(constraintMap, "spacingMode", "length"); -// if (strcmp(item, "length") == 0) data->spacingMode = SP_SPACING_MODE_LENGTH; -// else if (strcmp(item, "fixed") == 0) data->spacingMode = SP_SPACING_MODE_FIXED; -// else if (strcmp(item, "percent") == 0) data->spacingMode = SP_SPACING_MODE_PERCENT; -// -// item = Json_getString(constraintMap, "rotateMode", "tangent"); -// if (strcmp(item, "tangent") == 0) data->rotateMode = SP_ROTATE_MODE_TANGENT; -// else if (strcmp(item, "chain") == 0) data->rotateMode = SP_ROTATE_MODE_CHAIN; -// else if (strcmp(item, "chainScale") == 0) data->rotateMode = SP_ROTATE_MODE_CHAIN_SCALE; -// -// data->offsetRotation = Json_getFloat(constraintMap, "rotation", 0); -// data->position = Json_getFloat(constraintMap, "position", 0); -// if (data->positionMode == SP_POSITION_MODE_FIXED) data->position *= _scale; -// data->spacing = Json_getFloat(constraintMap, "spacing", 0); -// if (data->spacingMode == SP_SPACING_MODE_LENGTH || data->spacingMode == SP_SPACING_MODE_FIXED) data->spacing *= _scale; -// data->rotateMix = Json_getFloat(constraintMap, "rotateMix", 1); -// data->translateMix = Json_getFloat(constraintMap, "translateMix", 1); -// -// skeletonData->pathConstraints[i] = data; -// } -// } -// -// /* Skins. */ -// skins = Json::getItem(root, "skins"); -// if (skins) { -// Json *skinMap; -// skeletonData->skins = MALLOC(spSkin*, skins->_size); -// for (skinMap = skins->_child, i = 0; skinMap; skinMap = skinMap->_next, ++i) { -// Json *attachmentsMap; -// Json *curves; -// spSkin *skin = spSkin_create(skinMap->_name); -// -// skeletonData->skins[skeletonData->skinsCount++] = skin; -// if (strcmp(skinMap->_name, "default") == 0) skeletonData->defaultSkin = skin; -// -// for (attachmentsMap = skinMap->_child; attachmentsMap; attachmentsMap = attachmentsMap->_next) { -// int slotIndex = spSkeletonData_findSlotIndex(skeletonData, attachmentsMap->_name); -// Json *attachmentMap; -// -// for (attachmentMap = attachmentsMap->_child; attachmentMap; attachmentMap = attachmentMap->_next) { -// spAttachment* attachment; -// const char* skinAttachmentName = attachmentMap->_name; -// const char* attachmentName = Json_getString(attachmentMap, "name", skinAttachmentName); -// const char* attachmentPath = Json_getString(attachmentMap, "path", attachmentName); -// const char* color; -// Json* entry; -// -// const char* typeString = Json_getString(attachmentMap, "type", "region"); -// spAttachmentType type; -// if (strcmp(typeString, "region") == 0) -// type = SP_ATTACHMENT_REGION; -// else if (strcmp(typeString, "mesh") == 0) -// type = SP_ATTACHMENT_MESH; -// else if (strcmp(typeString, "linkedmesh") == 0) -// type = SP_ATTACHMENT_LINKED_MESH; -// else if (strcmp(typeString, "boundingbox") == 0) -// type = SP_ATTACHMENT_BOUNDING_BOX; -// else if (strcmp(typeString, "path") == 0) -// type = SP_ATTACHMENT_PATH; -// else if (strcmp(typeString, "clipping") == 0) -// type = SP_ATTACHMENT_CLIPPING; -// else { -// spSkeletonData_dispose(skeletonData); -// setError(root, "Unknown attachment type: ", typeString); -// return NULL; -// } -// -// attachment = spAttachmentLoader_createAttachment(_attachmentLoader, skin, type, attachmentName, attachmentPath); -// if (!attachment) { -// if (_attachmentLoader->error1) { -// spSkeletonData_dispose(skeletonData); -// setError(root, _attachmentLoader->error1, _attachmentLoader->error2); -// return NULL; -// } -// continue; -// } -// -// switch (attachment->_type) { -// case SP_ATTACHMENT_REGION: { -// spRegionAttachment* region = SUB_CAST(spRegionAttachment, attachment); -// if (path) MALLOC_STR(region->path, attachmentPath); -// region->x = Json_getFloat(attachmentMap, "x", 0) * _scale; -// region->y = Json_getFloat(attachmentMap, "y", 0) * _scale; -// region->scaleX = Json_getFloat(attachmentMap, "scaleX", 1); -// region->scaleY = Json_getFloat(attachmentMap, "scaleY", 1); -// region->rotation = Json_getFloat(attachmentMap, "rotation", 0); -// region->width = Json_getFloat(attachmentMap, "width", 32) * _scale; -// region->height = Json_getFloat(attachmentMap, "height", 32) * _scale; -// -// color = Json_getString(attachmentMap, "color", 0); -// if (color) { +// color = Json::getString(attachmentMap, "color", 0); +// if (color) +// { // spColor_setFromFloats(®ion->color, // toColor(color, 0), // toColor(color, 1), @@ -477,19 +576,20 @@ namespace Spine // toColor(color, 3)); // } // -// spRegionAttachment_updateOffset(region); +// region->updateOffset(); // -// spAttachmentLoader_configureAttachment(_attachmentLoader, attachment); // break; // } -// case SP_ATTACHMENT_MESH: -// case SP_ATTACHMENT_LINKED_MESH: { -// spMeshAttachment* mesh = SUB_CAST(spMeshAttachment, attachment); +// case AttachmentType_Mesh: +// case AttachmentType_Linkedmesh: +// { +// MeshAttachment* mesh = SUB_CAST(MeshAttachment, attachment); // // MALLOC_STR(mesh->path, attachmentPath); // -// color = Json_getString(attachmentMap, "color", 0); -// if (color) { +// color = Json::getString(attachmentMap, "color", 0); +// if (color) +// { // spColor_setFromFloats(&mesh->color, // toColor(color, 0), // toColor(color, 1), @@ -497,79 +597,90 @@ namespace Spine // toColor(color, 3)); // } // -// mesh->width = Json_getFloat(attachmentMap, "width", 32) * _scale; -// mesh->height = Json_getFloat(attachmentMap, "height", 32) * _scale; +// mesh->width = Json::getFloat(attachmentMap, "width", 32) * _scale; +// mesh->height = Json::getFloat(attachmentMap, "height", 32) * _scale; // // entry = Json::getItem(attachmentMap, "parent"); -// if (!entry) { +// if (!entry) +// { // int verticesLength; // entry = Json::getItem(attachmentMap, "triangles"); -// mesh->trianglesCount = entry->_size; -// mesh->triangles = MALLOC(unsigned short, entry->_size); +// mesh->_triangles.reserve(entry->_size); // for (entry = entry->_child, ii = 0; entry; entry = entry->_next, ++ii) +// { // mesh->triangles[ii] = (unsigned short)entry->_valueInt; +// } // // entry = Json::getItem(attachmentMap, "uvs"); // verticesLength = entry->_size; -// mesh->regionUVs = MALLOC(float, verticesLength); +// mesh->_regionUVs.reserve(verticesLength); // for (entry = entry->_child, ii = 0; entry; entry = entry->_next, ++ii) +// { // mesh->regionUVs[ii] = entry->_valueFloat; +// } // // _readVertices(self, attachmentMap, SUPER(mesh), verticesLength); // -// spMeshAttachment_updateUVs(mesh); +// MeshAttachment_updateUVs(mesh); // -// mesh->hullLength = Json_getInt(attachmentMap, "hull", 0); +// mesh->hullLength = Json::getInt(attachmentMap, "hull", 0); // // entry = Json::getItem(attachmentMap, "edges"); -// if (entry) { +// if (entry) +// { // mesh->edgesCount = entry->_size; -// mesh->edges = MALLOC(int, entry->_size); +// mesh->_edges.reserve(entry->_size); // for (entry = entry->_child, ii = 0; entry; entry = entry->_next, ++ii) +// { // mesh->edges[ii] = entry->_valueInt; +// } // } -// -// spAttachmentLoader_configureAttachment(_attachmentLoader, attachment); -// } else { -// mesh->inheritDeform = Json_getInt(attachmentMap, "deform", 1); -// _spSkeletonJson_addLinkedMesh(self, SUB_CAST(spMeshAttachment, attachment), Json_getString(attachmentMap, "skin", 0), slotIndex, +// } +// else +// { +// mesh->inheritDeform = Json::getInt(attachmentMap, "deform", 1); +// _spSkeletonJson_addLinkedMesh(self, SUB_CAST(MeshAttachment, attachment), Json::getString(attachmentMap, "skin", 0), slotIndex, // entry->_valueString); // } // break; // } -// case SP_ATTACHMENT_BOUNDING_BOX: { -// spBoundingBoxAttachment* box = SUB_CAST(spBoundingBoxAttachment, attachment); -// int vertexCount = Json_getInt(attachmentMap, "vertexCount", 0) << 1; +// case AttachmentType_Boundingbox: +// { +// BoundingBoxAttachment* box = SUB_CAST(BoundingBoxAttachment, attachment); +// int vertexCount = Json::getInt(attachmentMap, "vertexCount", 0) << 1; // _readVertices(self, attachmentMap, SUPER(box), vertexCount); // box->super.verticesCount = vertexCount; -// spAttachmentLoader_configureAttachment(_attachmentLoader, attachment); // break; // } -// case SP_ATTACHMENT_PATH: { -// spPathAttachment* pathAttatchment = SUB_CAST(spPathAttachment, attachment); +// case AttachmentType_Path: +// { +// PathAttachment* pathAttatchment = SUB_CAST(PathAttachment, attachment); // int vertexCount = 0; -// pathAttatchment->closed = Json_getInt(attachmentMap, "closed", 0); -// pathAttatchment->constantSpeed = Json_getInt(attachmentMap, "constantSpeed", 1); -// vertexCount = Json_getInt(attachmentMap, "vertexCount", 0); +// pathAttatchment->closed = Json::getInt(attachmentMap, "closed", 0); +// pathAttatchment->constantSpeed = Json::getInt(attachmentMap, "constantSpeed", 1); +// vertexCount = Json::getInt(attachmentMap, "vertexCount", 0); // _readVertices(self, attachmentMap, SUPER(pathAttatchment), vertexCount << 1); // // pathAttatchment->lengthsLength = vertexCount / 3; -// pathAttatchment->lengths = MALLOC(float, pathAttatchment->lengthsLength); +// pathAttatchment->_lengths.reserve(vertexCount / 3); // // curves = Json::getItem(attachmentMap, "lengths"); -// for (curves = curves->_child, ii = 0; curves; curves = curves->_next, ++ii) { +// for (curves = curves->_child, ii = 0; curves; curves = curves->_next, ++ii) +// { // pathAttatchment->lengths[ii] = curves->_valueFloat * _scale; // } // break; // } -// case SP_ATTACHMENT_POINT: { -// spPointAttachment* point = SUB_CAST(spPointAttachment, attachment); -// point->x = Json_getFloat(attachmentMap, "x", 0) * _scale; -// point->y = Json_getFloat(attachmentMap, "y", 0) * _scale; -// point->rotation = Json_getFloat(attachmentMap, "rotation", 0); +// case AttachmentType_Point: +// { +// PointAttachment* point = SUB_CAST(PointAttachment, attachment); +// point->x = Json::getFloat(attachmentMap, "x", 0) * _scale; +// point->y = Json::getFloat(attachmentMap, "y", 0) * _scale; +// point->rotation = Json::getFloat(attachmentMap, "rotation", 0); // -// color = Json_getString(attachmentMap, "color", 0); -// if (color) { +// color = Json::getString(attachmentMap, "color", 0); +// if (color) +// { // spColor_setFromFloats(&point->color, // toColor(color, 0), // toColor(color, 1), @@ -578,81 +689,95 @@ namespace Spine // } // break; // } -// case SP_ATTACHMENT_CLIPPING: { -// spClippingAttachment* clip = SUB_CAST(spClippingAttachment, attachment); +// case AttachmentType_Clipping: +// { +// ClippingAttachment* clip = SUB_CAST(ClippingAttachment, attachment); // int vertexCount = 0; -// const char* end = Json_getString(attachmentMap, "end", 0); -// if (end) { -// spSlotData* slot = spSkeletonData_findSlot(skeletonData, end); +// const char* end = Json::getString(attachmentMap, "end", 0); +// if (end) +// { +// spSlotData* slot = skeletonData->findSlot(end); // clip->endSlot = slot; // } -// vertexCount = Json_getInt(attachmentMap, "vertexCount", 0) << 1; +// vertexCount = Json::getInt(attachmentMap, "vertexCount", 0) << 1; // _readVertices(self, attachmentMap, SUPER(clip), vertexCount); -// spAttachmentLoader_configureAttachment(_attachmentLoader, attachment); // break; // } // } // -// spSkin_addAttachment(skin, slotIndex, skinAttachmentName, attachment); -// } -// } -// } -// } -// -// /* Linked meshes. */ -// for (i = 0; i < internal->linkedMeshCount; i++) { -// spAttachment* parent; +// Skin_addAttachment(skin, slotIndex, skinAttachmentName, attachment); + } + } + } + } + + /* Linked meshes. */ +// for (i = 0; i < internal->linkedMeshCount; i++) +// { +// Attachment* parent; // _spLinkedMesh* linkedMesh = internal->linkedMeshes + i; -// spSkin* skin = !linkedMesh->skin ? skeletonData->defaultSkin : spSkeletonData_findSkin(skeletonData, linkedMesh->skin); -// if (!skin) { -// spSkeletonData_dispose(skeletonData); +// Skin* skin = !linkedMesh->skin ? skeletonData->_defaultSkin : SkeletonData_findSkin(skeletonData, linkedMesh->skin); +// if (!skin) +// { +// DESTROY(SkeletonData, skeletonData); // setError(root, "Skin not found: ", linkedMesh->skin); // return NULL; // } -// parent = spSkin_getAttachment(skin, linkedMesh->slotIndex, linkedMesh->parent); -// if (!parent) { -// spSkeletonData_dispose(skeletonData); +// parent = Skin_getAttachment(skin, linkedMesh->slotIndex, linkedMesh->parent); +// if (!parent) +// { +// DESTROY(SkeletonData, skeletonData); // setError(root, "Parent mesh not found: ", linkedMesh->parent); // return NULL; // } -// spMeshAttachment_setParentMesh(linkedMesh->mesh, SUB_CAST(spMeshAttachment, parent)); -// spMeshAttachment_updateUVs(linkedMesh->mesh); -// spAttachmentLoader_configureAttachment(_attachmentLoader, SUPER(SUPER(linkedMesh->mesh))); +// MeshAttachment_setParentMesh(linkedMesh->mesh, SUB_CAST(MeshAttachment, parent)); +// MeshAttachment_updateUVs(linkedMesh->mesh); +// AttachmentLoader_configureAttachment(_attachmentLoader, SUPER(SUPER(linkedMesh->mesh))); // } -// -// /* Events. */ -// events = Json::getItem(root, "events"); -// if (events) { + + /* Events. */ + events = Json::getItem(root, "events"); + if (events) + { // Json *eventMap; // const char* stringValue; -// skeletonData->eventsCount = events->_size; -// skeletonData->events = MALLOC(spEventData*, events->_size); -// for (eventMap = events->_child, i = 0; eventMap; eventMap = eventMap->_next, ++i) { -// spEventData* eventData = spEventData_create(eventMap->_name); -// eventData->intValue = Json_getInt(eventMap, "int", 0); -// eventData->floatValue = Json_getFloat(eventMap, "float", 0); -// stringValue = Json_getString(eventMap, "string", 0); -// if (stringValue) MALLOC_STR(eventData->stringValue, stringValue); -// skeletonData->events[i] = eventData; +// skeletonData->_events.reserve(events->_size); +// for (eventMap = events->_child, i = 0; eventMap; eventMap = eventMap->_next, ++i) +// { +// EventData* eventData = EventData_create(eventMap->_name); +// eventData->intValue = Json::getInt(eventMap, "int", 0); +// eventData->floatValue = Json::getFloat(eventMap, "float", 0); +// stringValue = Json::getString(eventMap, "string", 0); +// if (stringValue) +// { +// MALLOC_STR(eventData->stringValue, stringValue); +// } +// skeletonData->_events[i] = eventData; // } -// } -// -// /* Animations. */ -// animations = Json::getItem(root, "animations"); -// if (animations) { + } + + /* Animations. */ + animations = Json::getItem(root, "animations"); + if (animations) + { // Json *animationMap; -// skeletonData->animations = MALLOC(spAnimation*, animations->_size); -// for (animationMap = animations->_child; animationMap; animationMap = animationMap->_next) { -// spAnimation* animation = _spSkeletonJson_readAnimation(self, animationMap, skeletonData); -// if (!animation) { -// spSkeletonData_dispose(skeletonData); +// skeletonData->_animations.reserve(animations->_size); +// int animationsIndex = 0; +// for (animationMap = animations->_child; animationMap; animationMap = animationMap->_next) +// { +// Animation* animation = readAnimation(animationMap, skeletonData); +// if (!animation) +// { +// DESTROY(SkeletonData, SkeletonData); +// DESTROY(Json, root); // return NULL; // } -// skeletonData->animations[skeletonData->animationsCount++] = animation; +// skeletonData->_animations[animationsIndex++] = animation; // } -// } -// -// Json_dispose(root); + } + + DESTROY(Json, root); + return skeletonData; } @@ -705,7 +830,6 @@ namespace Spine Animation* SkeletonJson::readAnimation(Json* root, SkeletonData *skeletonData) { Vector timelines; - float scale = _scale; float duration = 0; int frameIndex; @@ -726,456 +850,495 @@ namespace Spine drawOrder = Json::getItem(root, "draworder"); } - for (boneMap = bones ? bones->_child : 0; boneMap; boneMap = boneMap->_next) + for (boneMap = bones ? bones->_child : NULL; boneMap; boneMap = boneMap->_next) { timelinesCount += boneMap->_size; } - for (slotMap = slots ? slots->_child : 0; slotMap; slotMap = slotMap->_next) + + for (slotMap = slots ? slots->_child : NULL; slotMap; slotMap = slotMap->_next) { timelinesCount += slotMap->_size; } + timelinesCount += ik ? ik->_size : 0; timelinesCount += transform ? transform->_size : 0; - for (constraintMap = paths ? paths->_child : 0; constraintMap; constraintMap = constraintMap->_next) + + for (constraintMap = paths ? paths->_child : NULL; constraintMap; constraintMap = constraintMap->_next) { timelinesCount += constraintMap->_size; } - for (constraintMap = deform ? deform->_child : 0; constraintMap; constraintMap = constraintMap->_next) + + for (constraintMap = deform ? deform->_child : NULL; constraintMap; constraintMap = constraintMap->_next) { for (slotMap = constraintMap->_child; slotMap; slotMap = slotMap->_next) { timelinesCount += slotMap->_size; } } + if (drawOrder) { ++timelinesCount; } + if (events) { ++timelinesCount; } - /* Slot timelines. */ + /** Slot timelines. */ for (slotMap = slots ? slots->_child : 0; slotMap; slotMap = slotMap->_next) { -// Json *timelineMap; -// -// int slotIndex = skeletonData->findSlotIndex(slotMap->_name); -// if (slotIndex == -1) -// { -// setError(root, "Slot not found: ", slotMap->_name); -// return NULL; -// } -// -// for (timelineMap = slotMap->_child; timelineMap; timelineMap = timelineMap->_next) -// { -// if (strcmp(timelineMap->_name, "attachment") == 0) -// { -// spAttachmentTimeline *timeline = spAttachmentTimeline_create(timelineMap->_size); -// timeline->slotIndex = slotIndex; -// -// for (valueMap = timelineMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) -// { -// Json* name = Json::getItem(valueMap, "name"); -// spAttachmentTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), name->_type == Json_NULL ? 0 : name->_valueString); -// } -// timelines[timelinesCount++] = SUPER_CAST(spTimeline, timeline); -// duration = MAX(duration, timeline->frames[timelineMap->_size - 1]); -// -// } -// else if (strcmp(timelineMap->_name, "color") == 0) -// { -// spColorTimeline *timeline = spColorTimeline_create(timelineMap->_size); -// timeline->slotIndex = slotIndex; -// -// for (valueMap = timelineMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) -// { -// const char* s = Json_getString(valueMap, "color", 0); -// spColorTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), toColor(s, 0), toColor(s, 1), toColor(s, 2), toColor(s, 3)); -// readCurve(valueMap, SUPER(timeline), frameIndex); -// } -// timelines[timelinesCount++] = SUPER_CAST(spTimeline, timeline); -// duration = MAX(duration, timeline->frames[(timelineMap->_size - 1) * COLOR_ENTRIES]); -// -// } -// else if (strcmp(timelineMap->_name, "twoColor") == 0) -// { -// spTwoColorTimeline *timeline = spTwoColorTimeline_create(timelineMap->_size); -// timeline->slotIndex = slotIndex; -// -// for (valueMap = timelineMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) -// { -// const char* s = Json_getString(valueMap, "light", 0); -// const char* ds = Json_getString(valueMap, "dark", 0); -// spTwoColorTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), toColor(s, 0), toColor(s, 1), toColor(s, 2), -// toColor(s, 3), toColor(ds, 0), toColor(ds, 1), toColor(ds, 2)); -// readCurve(valueMap, SUPER(timeline), frameIndex); -// } -// timelines[timelinesCount++] = SUPER_CAST(spTimeline, timeline); -// duration = MAX(duration, timeline->frames[(timelineMap->_size - 1) * TWOCOLOR_ENTRIES]); -// } -// else -// { -// setError(root, "Invalid timeline type for a slot: ", timelineMap->_name); -// return NULL; -// } -// } + Json *timelineMap; + + int slotIndex = skeletonData->findSlotIndex(slotMap->_name); + if (slotIndex == -1) + { + ContainerUtil::cleanUpVectorOfPointers(timelines); + setError(NULL, "Slot not found: ", slotMap->_name); + return NULL; + } + + for (timelineMap = slotMap->_child; timelineMap; timelineMap = timelineMap->_next) + { + if (strcmp(timelineMap->_name, "attachment") == 0) + { + AttachmentTimeline *timeline = NEW(AttachmentTimeline); + new (timeline) AttachmentTimeline(timelineMap->_size); + + timeline->_slotIndex = slotIndex; + + for (valueMap = timelineMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) + { + Json* name = Json::getItem(valueMap, "name"); + std::string attachmentName; + attachmentName = name->_type == Json::JSON_NULL ? "" : std::string(name->_valueString); + timeline->setFrame(frameIndex, Json::getFloat(valueMap, "time", 0), attachmentName); + } + timelines[timelinesCount++] = timeline; + duration = MAX(duration, timeline->_frames[timelineMap->_size - 1]); + + } + else if (strcmp(timelineMap->_name, "color") == 0) + { + ColorTimeline *timeline = NEW(ColorTimeline); + new (timeline) ColorTimeline(timelineMap->_size); + + timeline->_slotIndex = slotIndex; + + for (valueMap = timelineMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) + { + const char* s = Json::getString(valueMap, "color", 0); + timeline->setFrame(frameIndex, Json::getFloat(valueMap, "time", 0), toColor(s, 0), toColor(s, 1), toColor(s, 2), toColor(s, 3)); + readCurve(valueMap, timeline, frameIndex); + } + timelines[timelinesCount++] = timeline; + duration = MAX(duration, timeline->_frames[(timelineMap->_size - 1) * ColorTimeline::ENTRIES]); + + } + else if (strcmp(timelineMap->_name, "twoColor") == 0) + { + TwoColorTimeline *timeline = NEW(TwoColorTimeline); + new (timeline) TwoColorTimeline(timelineMap->_size); + + timeline->_slotIndex = slotIndex; + + for (valueMap = timelineMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) + { + const char* s = Json::getString(valueMap, "light", 0); + const char* ds = Json::getString(valueMap, "dark", 0); + timeline->setFrame(frameIndex, Json::getFloat(valueMap, "time", 0), toColor(s, 0), toColor(s, 1), toColor(s, 2), + toColor(s, 3), toColor(ds, 0), toColor(ds, 1), toColor(ds, 2)); + readCurve(valueMap, timeline, frameIndex); + } + timelines[timelinesCount++] = timeline; + duration = MAX(duration, timeline->_frames[(timelineMap->_size - 1) * TwoColorTimeline::ENTRIES]); + } + else + { + ContainerUtil::cleanUpVectorOfPointers(timelines); + setError(NULL, "Invalid timeline type for a slot: ", timelineMap->_name); + return NULL; + } + } } - /* Bone timelines. */ + /** Bone timelines. */ for (boneMap = bones ? bones->_child : 0; boneMap; boneMap = boneMap->_next) { -// Json *timelineMap; -// -// int boneIndex = spSkeletonData_findBoneIndex(skeletonData, boneMap->_name); -// if (boneIndex == -1) -// { -// setError(root, "Bone not found: ", boneMap->_name); -// return NULL; -// } -// -// for (timelineMap = boneMap->_child; timelineMap; timelineMap = timelineMap->_next) -// { -// if (strcmp(timelineMap->_name, "rotate") == 0) -// { -// spRotateTimeline *timeline = spRotateTimeline_create(timelineMap->_size); -// timeline->boneIndex = boneIndex; -// -// for (valueMap = timelineMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) -// { -// spRotateTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), Json_getFloat(valueMap, "angle", 0)); -// readCurve(valueMap, SUPER(timeline), frameIndex); -// } -// timelines[timelinesCount++] = SUPER_CAST(spTimeline, timeline); -// duration = MAX(duration, timeline->frames[(timelineMap->_size - 1) * ROTATE_ENTRIES]); -// } -// else -// { -// int isScale = strcmp(timelineMap->_name, "scale") == 0; -// int isTranslate = strcmp(timelineMap->_name, "translate") == 0; -// int isShear = strcmp(timelineMap->_name, "shear") == 0; -// if (isScale || isTranslate || isShear) -// { -// float timelineScale = isTranslate ? _scale: 1; -// spTranslateTimeline *timeline = 0; -// if (isScale) -// { -// timeline = spScaleTimeline_create(timelineMap->_size); -// } -// else if (isTranslate) -// { -// timeline = spTranslateTimeline_create(timelineMap->_size); -// } -// else if (isShear) -// { -// timeline = spShearTimeline_create(timelineMap->_size); -// } -// timeline->boneIndex = boneIndex; -// -// for (valueMap = timelineMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) -// { -// spTranslateTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), Json_getFloat(valueMap, "x", 0) * timelineScale, Json_getFloat(valueMap, "y", 0) * timelineScale); -// readCurve(valueMap, SUPER(timeline), frameIndex); -// } -// -// timelines[timelinesCount++] = SUPER_CAST(spTimeline, timeline); -// duration = MAX(duration, timeline->frames[(timelineMap->_size - 1) * TRANSLATE_ENTRIES]); -// } -// else -// { -// setError(root, "Invalid timeline type for a bone: ", timelineMap->_name); -// return NULL; -// } -// } -// } + Json *timelineMap; + + int boneIndex = skeletonData->findBoneIndex(boneMap->_name); + if (boneIndex == -1) + { + ContainerUtil::cleanUpVectorOfPointers(timelines); + setError(NULL, "Bone not found: ", boneMap->_name); + return NULL; + } + + for (timelineMap = boneMap->_child; timelineMap; timelineMap = timelineMap->_next) + { + if (strcmp(timelineMap->_name, "rotate") == 0) + { + RotateTimeline *timeline = NEW(RotateTimeline); + new (timeline) RotateTimeline(timelineMap->_size); + + timeline->_boneIndex = boneIndex; + + for (valueMap = timelineMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) + { + timeline->setFrame(frameIndex, Json::getFloat(valueMap, "time", 0), Json::getFloat(valueMap, "angle", 0)); + readCurve(valueMap, timeline, frameIndex); + } + timelines[timelinesCount++] = timeline; + duration = MAX(duration, timeline->_frames[(timelineMap->_size - 1) * RotateTimeline::ENTRIES]); + } + else + { + int isScale = strcmp(timelineMap->_name, "scale") == 0; + int isTranslate = strcmp(timelineMap->_name, "translate") == 0; + int isShear = strcmp(timelineMap->_name, "shear") == 0; + if (isScale || isTranslate || isShear) + { + float timelineScale = isTranslate ? _scale: 1; + TranslateTimeline *timeline = 0; + if (isScale) + { + timeline = NEW(ScaleTimeline); + new (timeline) ScaleTimeline(timelineMap->_size); + } + else if (isTranslate) + { + timeline = NEW(TranslateTimeline); + new (timeline) TranslateTimeline(timelineMap->_size); + } + else if (isShear) + { + timeline = NEW(ShearTimeline); + new (timeline) ShearTimeline(timelineMap->_size); + } + timeline->_boneIndex = boneIndex; + + for (valueMap = timelineMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) + { + timeline->setFrame(frameIndex, Json::getFloat(valueMap, "time", 0), Json::getFloat(valueMap, "x", 0) * timelineScale, Json::getFloat(valueMap, "y", 0) * timelineScale); + readCurve(valueMap, timeline, frameIndex); + } + + timelines[timelinesCount++] = timeline; + duration = MAX(duration, timeline->_frames[(timelineMap->_size - 1) * TranslateTimeline::ENTRIES]); + } + else + { + ContainerUtil::cleanUpVectorOfPointers(timelines); + setError(NULL, "Invalid timeline type for a bone: ", timelineMap->_name); + return NULL; + } + } + } } - /* IK constraint timelines. */ + /** IK constraint timelines. */ for (constraintMap = ik ? ik->_child : 0; constraintMap; constraintMap = constraintMap->_next) { -// spIkConstraintData* constraint = spSkeletonData_findIkConstraint(skeletonData, constraintMap->_name); -// spIkConstraintTimeline* timeline = spIkConstraintTimeline_create(constraintMap->_size); -// for (frameIndex = 0; frameIndex < skeletonData->ikConstraintsCount; ++frameIndex) -// { -// if (constraint == skeletonData->ikConstraints[frameIndex]) -// { -// timeline->ikConstraintIndex = frameIndex; -// break; -// } -// } -// for (valueMap = constraintMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) -// { -// spIkConstraintTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), Json_getFloat(valueMap, "mix", 1), Json_getInt(valueMap, "bendPositive", 1) ? 1 : -1); -// readCurve(valueMap, SUPER(timeline), frameIndex); -// } -// timelines[timelinesCount++] = SUPER_CAST(spTimeline, timeline); -// duration = MAX(duration, timeline->frames[(constraintMap->_size - 1) * IKCONSTRAINT_ENTRIES]); + IkConstraintData* constraint = skeletonData->findIkConstraint(constraintMap->_name); + IkConstraintTimeline *timeline = NEW(IkConstraintTimeline); + new (timeline) IkConstraintTimeline(constraintMap->_size); + + for (frameIndex = 0; frameIndex < static_cast(skeletonData->_ikConstraints.size()); ++frameIndex) + { + if (constraint == skeletonData->_ikConstraints[frameIndex]) + { + timeline->_ikConstraintIndex = frameIndex; + break; + } + } + for (valueMap = constraintMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) + { + timeline->setFrame(frameIndex, Json::getFloat(valueMap, "time", 0), Json::getFloat(valueMap, "mix", 1), Json::getInt(valueMap, "bendPositive", 1) ? 1 : -1); + readCurve(valueMap, timeline, frameIndex); + } + timelines[timelinesCount++] = timeline; + duration = MAX(duration, timeline->_frames[(constraintMap->_size - 1) * IkConstraintTimeline::ENTRIES]); } - /* Transform constraint timelines. */ + /** Transform constraint timelines. */ for (constraintMap = transform ? transform->_child : 0; constraintMap; constraintMap = constraintMap->_next) { -// spTransformConstraintData* constraint = spSkeletonData_findTransformConstraint(skeletonData, constraintMap->_name); -// spTransformConstraintTimeline* timeline = spTransformConstraintTimeline_create(constraintMap->_size); -// for (frameIndex = 0; frameIndex < skeletonData->transformConstraintsCount; ++frameIndex) -// { -// if (constraint == skeletonData->transformConstraints[frameIndex]) -// { -// timeline->transformConstraintIndex = frameIndex; -// break; -// } -// } -// for (valueMap = constraintMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) -// { -// spTransformConstraintTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), Json_getFloat(valueMap, "rotateMix", 1), Json_getFloat(valueMap, "translateMix", 1), Json_getFloat(valueMap, "scaleMix", 1), Json_getFloat(valueMap, "shearMix", 1)); -// readCurve(valueMap, SUPER(timeline), frameIndex); -// } -// timelines[timelinesCount++] = SUPER_CAST(spTimeline, timeline); -// duration = MAX(duration, timeline->frames[(constraintMap->_size - 1) * TRANSFORMCONSTRAINT_ENTRIES]); + TransformConstraintData* constraint = skeletonData->findTransformConstraint(constraintMap->_name); + TransformConstraintTimeline *timeline = NEW(TransformConstraintTimeline); + new (timeline) TransformConstraintTimeline(constraintMap->_size); + + for (frameIndex = 0; frameIndex < skeletonData->_transformConstraints.size(); ++frameIndex) + { + if (constraint == skeletonData->_transformConstraints[frameIndex]) + { + timeline->_transformConstraintIndex = frameIndex; + break; + } + } + for (valueMap = constraintMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) + { + timeline->setFrame(frameIndex, Json::getFloat(valueMap, "time", 0), Json::getFloat(valueMap, "rotateMix", 1), Json::getFloat(valueMap, "translateMix", 1), Json::getFloat(valueMap, "scaleMix", 1), Json::getFloat(valueMap, "shearMix", 1)); + readCurve(valueMap, timeline, frameIndex); + } + timelines[timelinesCount++] = timeline; + duration = MAX(duration, timeline->_frames[(constraintMap->_size - 1) * TransformConstraintTimeline::ENTRIES]); } /** Path constraint timelines. */ for (constraintMap = paths ? paths->_child : 0; constraintMap; constraintMap = constraintMap->_next) { -// int constraintIndex, i; -// Json* timelineMap; -// -// spPathConstraintData* data = spSkeletonData_findPathConstraint(skeletonData, constraintMap->_name); -// if (!data) -// { -// setError(root, "Path constraint not found: ", constraintMap->_name); -// return NULL; -// } -// -// for (i = 0; i < skeletonData->pathConstraintsCount; i++) -// { -// if (skeletonData->pathConstraints[i] == data) -// { -// constraintIndex = i; -// break; -// } -// } -// -// for (timelineMap = constraintMap->_child; timelineMap; timelineMap = timelineMap->_next) -// { -// const char* timelineName = timelineMap->_name; -// if (strcmp(timelineName, "position") == 0 || strcmp(timelineName, "spacing") == 0) -// { -// spPathConstraintPositionTimeline* timeline; -// float timelineScale = 1; -// if (strcmp(timelineName, "spacing") == 0) -// { -// timeline = (spPathConstraintPositionTimeline*)spPathConstraintSpacingTimeline_create(timelineMap->_size); -// if (data->spacingMode == SP_SPACING_MODE_LENGTH || data->spacingMode == SP_SPACING_MODE_FIXED) -// { -// timelineScale = _scale; -// } -// } -// else -// { -// timeline = spPathConstraintPositionTimeline_create(timelineMap->_size); -// if (data->positionMode == SP_POSITION_MODE_FIXED) -// { -// timelineScale = _scale; -// } -// } -// -// timeline->pathConstraintIndex = constraintIndex; -// for (valueMap = timelineMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) -// { -// spPathConstraintPositionTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), Json_getFloat(valueMap, timelineName, 0) * timelineScale); -// readCurve(valueMap, SUPER(timeline), frameIndex); -// } -// timelines[timelinesCount++] = SUPER_CAST(spTimeline, timeline); -// duration = MAX(duration, timeline->frames[(timelineMap->_size - 1) * PATHCONSTRAINTPOSITION_ENTRIES]); -// } -// else if (strcmp(timelineName, "mix") == 0) -// { -// spPathConstraintMixTimeline* timeline = spPathConstraintMixTimeline_create(timelineMap->_size); -// timeline->pathConstraintIndex = constraintIndex; -// for (valueMap = timelineMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) -// { -// spPathConstraintMixTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), Json_getFloat(valueMap, "rotateMix", 1), Json_getFloat(valueMap, "translateMix", 1)); -// readCurve(valueMap, SUPER(timeline), frameIndex); -// } -// timelines[timelinesCount++] = SUPER_CAST(spTimeline, timeline); -// duration = MAX(duration, timeline->frames[(timelineMap->_size - 1) * PATHCONSTRAINTMIX_ENTRIES]); -// } -// } + int constraintIndex = 0, i; + Json* timelineMap; + + PathConstraintData* data = skeletonData->findPathConstraint(constraintMap->_name); + if (!data) + { + ContainerUtil::cleanUpVectorOfPointers(timelines); + setError(NULL, "Path constraint not found: ", constraintMap->_name); + return NULL; + } + + for (i = 0; i < skeletonData->_pathConstraints.size(); i++) + { + if (skeletonData->_pathConstraints[i] == data) + { + constraintIndex = i; + break; + } + } + + for (timelineMap = constraintMap->_child; timelineMap; timelineMap = timelineMap->_next) + { + const char* timelineName = timelineMap->_name; + if (strcmp(timelineName, "position") == 0 || strcmp(timelineName, "spacing") == 0) + { + PathConstraintPositionTimeline* timeline; + float timelineScale = 1; + if (strcmp(timelineName, "spacing") == 0) + { + timeline = NEW(PathConstraintSpacingTimeline); + new (timeline) PathConstraintSpacingTimeline(timelineMap->_size); + + if (data->_spacingMode == SpacingMode_Length || data->_spacingMode == SpacingMode_Fixed) + { + timelineScale = _scale; + } + } + else + { + timeline = NEW(PathConstraintPositionTimeline); + new (timeline) PathConstraintPositionTimeline(timelineMap->_size); + + if (data->_positionMode == PositionMode_Fixed) + { + timelineScale = _scale; + } + } + + timeline->_pathConstraintIndex = constraintIndex; + for (valueMap = timelineMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) + { + timeline->setFrame(frameIndex, Json::getFloat(valueMap, "time", 0), Json::getFloat(valueMap, timelineName, 0) * timelineScale); + readCurve(valueMap, timeline, frameIndex); + } + timelines[timelinesCount++] = timeline; + duration = MAX(duration, timeline->_frames[(timelineMap->_size - 1) * PathConstraintPositionTimeline::ENTRIES]); + } + else if (strcmp(timelineName, "mix") == 0) + { + PathConstraintMixTimeline* timeline = NEW(PathConstraintMixTimeline); + new (timeline) PathConstraintMixTimeline(timelineMap->_size); + timeline->_pathConstraintIndex = constraintIndex; + for (valueMap = timelineMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) + { + timeline->setFrame(frameIndex, Json::getFloat(valueMap, "time", 0), Json::getFloat(valueMap, "rotateMix", 1), Json::getFloat(valueMap, "translateMix", 1)); + readCurve(valueMap, timeline, frameIndex); + } + timelines[timelinesCount++] = timeline; + duration = MAX(duration, timeline->_frames[(timelineMap->_size - 1) * PathConstraintMixTimeline::ENTRIES]); + } + } } - /* Deform timelines. */ - for (constraintMap = deform ? deform->_child : 0; constraintMap; constraintMap = constraintMap->_next) + /** Deform timelines. */ + for (constraintMap = deform ? deform->_child : NULL; constraintMap; constraintMap = constraintMap->_next) { -// spSkin* skin = spSkeletonData_findSkin(skeletonData, constraintMap->_name); -// for (slotMap = constraintMap->_child; slotMap; slotMap = slotMap->_next) -// { -// int slotIndex = spSkeletonData_findSlotIndex(skeletonData, slotMap->_name); -// Json* timelineMap; -// for (timelineMap = slotMap->_child; timelineMap; timelineMap = timelineMap->_next) -// { -// float* tempDeform; -// spDeformTimeline *timeline; -// int weighted, deformLength; -// -// spVertexAttachment* attachment = SUB_CAST(spVertexAttachment, spSkin_getAttachment(skin, slotIndex, timelineMap->_name)); -// if (!attachment) -// { -// setError(root, "Attachment not found: ", timelineMap->_name); -// return NULL; -// } -// weighted = attachment->bones != 0; -// deformLength = weighted ? attachment->verticesCount / 3 * 2 : attachment->verticesCount; -// tempDeform = MALLOC(float, deformLength); -// -// timeline = spDeformTimeline_create(timelineMap->_size, deformLength); -// timeline->slotIndex = slotIndex; -// timeline->attachment = SUPER(attachment); -// -// for (valueMap = timelineMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) -// { -// Json* vertices = Json::getItem(valueMap, "vertices"); -// float* deform2; -// if (!vertices) -// { -// if (weighted) -// { -// deform2 = tempDeform; -// memset(deform, 0, sizeof(float) * deformLength); -// } -// else -// { -// deform2 = attachment->vertices; -// } -// } -// else -// { -// int v, start = Json_getInt(valueMap, "offset", 0); -// Json* vertex; -// deform2 = tempDeform; -// memset(deform, 0, sizeof(float) * start); -// if (_scale == 1) -// { -// for (vertex = vertices->_child, v = start; vertex; vertex = vertex->_next, ++v) -// { -// deform2[v] = vertex->_valueFloat; -// } -// } -// else -// { -// for (vertex = vertices->_child, v = start; vertex; vertex = vertex->_next, ++v) -// { -// deform2[v] = vertex->_valueFloat * _scale; -// } -// } -// memset(deform + v, 0, sizeof(float) * (deformLength - v)); -// if (!weighted) -// { -// float* verticesAttachment = attachment->vertices; -// for (v = 0; v < deformLength; ++v) -// { -// deform2[v] += verticesAttachment[v]; -// } -// } -// } -// spDeformTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), deform2); -// readCurve(valueMap, SUPER(timeline), frameIndex); -// } -// FREE(tempDeform); -// -// timelines[timelinesCount++] = SUPER_CAST(spTimeline, timeline); -// duration = MAX(duration, timeline->frames[timelineMap->_size - 1]); -// } -// } + Skin* skin = skeletonData->findSkin(constraintMap->_name); + for (slotMap = constraintMap->_child; slotMap; slotMap = slotMap->_next) + { + int slotIndex = skeletonData->findSlotIndex(slotMap->_name); + Json* timelineMap; + for (timelineMap = slotMap->_child; timelineMap; timelineMap = timelineMap->_next) + { + DeformTimeline *timeline; + int weighted, deformLength; + + Attachment* baseAttachment = skin->getAttachment(slotIndex, timelineMap->_name); + + if (!baseAttachment) + { + ContainerUtil::cleanUpVectorOfPointers(timelines); + setError(NULL, "Attachment not found: ", timelineMap->_name); + return NULL; + } + + VertexAttachment* attachment = static_cast(baseAttachment); + + weighted = attachment->_bones.size() != 0; + Vector& vertices = attachment->_vertices; + deformLength = weighted ? static_cast(vertices.size()) / 3 * 2 : static_cast(vertices.size()); + Vector tempDeform; + tempDeform.reserve(deformLength); + + timeline = NEW(DeformTimeline); + new (timeline) DeformTimeline(timelineMap->_size); + + timeline->_slotIndex = slotIndex; + timeline->_attachment = attachment; + + for (valueMap = timelineMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) + { + Json* vertices = Json::getItem(valueMap, "vertices"); + Vector deform2; + if (!vertices) + { + if (weighted) + { + deform2 = tempDeform; + } + else + { + deform2 = attachment->_vertices; + } + } + else + { + int v, start = Json::getInt(valueMap, "offset", 0); + Json* vertex; + deform2 = tempDeform; + if (_scale == 1) + { + for (vertex = vertices->_child, v = start; vertex; vertex = vertex->_next, ++v) + { + deform2[v] = vertex->_valueFloat; + } + } + else + { + for (vertex = vertices->_child, v = start; vertex; vertex = vertex->_next, ++v) + { + deform2[v] = vertex->_valueFloat * _scale; + } + } + if (!weighted) + { + Vector& verticesAttachment = attachment->_vertices; + for (v = 0; v < deformLength; ++v) + { + deform2[v] += verticesAttachment[v]; + } + } + } + timeline->setFrame(frameIndex, Json::getFloat(valueMap, "time", 0), deform2); + readCurve(valueMap, timeline, frameIndex); + } + + timelines[timelinesCount++] = timeline; + duration = MAX(duration, timeline->_frames[timelineMap->_size - 1]); + } + } } - /* Draw order timeline. */ + /** Draw order timeline. */ if (drawOrder) { -// spDrawOrderTimeline* timeline = spDrawOrderTimeline_create(drawOrder->_size, skeletonData->slotsCount); -// for (valueMap = drawOrder->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) -// { -// int ii; -// int* drawOrder2 = 0; -// Json* offsets = Json::getItem(valueMap, "offsets"); -// if (offsets) -// { -// Json* offsetMap; -// int* unchanged = MALLOC(int, skeletonData->slotsCount - offsets->_size); -// int originalIndex = 0, unchangedIndex = 0; -// -// drawOrder2 = MALLOC(int, skeletonData->slotsCount); -// for (ii = skeletonData->slotsCount - 1; ii >= 0; --ii) -// { -// drawOrder2[ii] = -1; -// } -// -// for (offsetMap = offsets->_child; offsetMap; offsetMap = offsetMap->_next) -// { -// int slotIndex = spSkeletonData_findSlotIndex(skeletonData, Json_getString(offsetMap, "slot", 0)); -// if (slotIndex == -1) -// { -// setError(root, "Slot not found: ", Json_getString(offsetMap, "slot", 0)); -// return NULL; -// } -// /* Collect unchanged items. */ -// while (originalIndex != slotIndex) -// { -// unchanged[unchangedIndex++] = originalIndex++; -// } -// /* Set changed items. */ -// drawOrder2[originalIndex + Json_getInt(offsetMap, "offset", 0)] = originalIndex; -// originalIndex++; -// } -// /* Collect remaining unchanged items. */ -// while (originalIndex < skeletonData->slotsCount) -// { -// unchanged[unchangedIndex++] = originalIndex++; -// } -// /* Fill in unchanged items. */ -// for (ii = skeletonData->slotsCount - 1; ii >= 0; ii--) -// { -// if (drawOrder2[ii] == -1) -// { -// drawOrder2[ii] = unchanged[--unchangedIndex]; -// } -// } -// FREE(unchanged); -// } -// spDrawOrderTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), drawOrder2); -// FREE(drawOrder2); -// } -// timelines[timelinesCount++] = SUPER_CAST(spTimeline, timeline); -// duration = MAX(duration, timeline->frames[drawOrder->_size - 1]); + DrawOrderTimeline* timeline = NEW(DrawOrderTimeline); + new (timeline) DrawOrderTimeline(drawOrder->_size); + + for (valueMap = drawOrder->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) + { + int ii; + Vector drawOrder2; + Json* offsets = Json::getItem(valueMap, "offsets"); + if (offsets) + { + Json* offsetMap; + Vector unchanged; + unchanged.reserve(skeletonData->_slots.size() - offsets->_size); + int originalIndex = 0, unchangedIndex = 0; + + drawOrder2.reserve(skeletonData->_slots.size()); + for (ii = static_cast(skeletonData->_slots.size()) - 1; ii >= 0; --ii) + { + drawOrder2[ii] = -1; + } + + for (offsetMap = offsets->_child; offsetMap; offsetMap = offsetMap->_next) + { + int slotIndex = skeletonData->findSlotIndex(Json::getString(offsetMap, "slot", 0)); + if (slotIndex == -1) + { + ContainerUtil::cleanUpVectorOfPointers(timelines); + setError(NULL, "Slot not found: ", Json::getString(offsetMap, "slot", 0)); + return NULL; + } + /* Collect unchanged items. */ + while (originalIndex != slotIndex) + { + unchanged[unchangedIndex++] = originalIndex++; + } + /* Set changed items. */ + drawOrder2[originalIndex + Json::getInt(offsetMap, "offset", 0)] = originalIndex; + originalIndex++; + } + /* Collect remaining unchanged items. */ + while (originalIndex < skeletonData->_slots.size()) + { + unchanged[unchangedIndex++] = originalIndex++; + } + /* Fill in unchanged items. */ + for (ii = static_cast(skeletonData->_slots.size()) - 1; ii >= 0; ii--) + { + if (drawOrder2[ii] == -1) + { + drawOrder2[ii] = unchanged[--unchangedIndex]; + } + } + } + timeline->setFrame(frameIndex, Json::getFloat(valueMap, "time", 0), drawOrder2); + } + timelines[timelinesCount++] = timeline; + duration = MAX(duration, timeline->_frames[drawOrder->_size - 1]); } - /* Event timeline. */ + /** Event timeline. */ if (events) { -// spEventTimeline* timeline = spEventTimeline_create(events->_size); -// for (valueMap = events->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) -// { -// spEvent* event; -// const char* stringValue; -// spEventData* eventData = spSkeletonData_findEvent(skeletonData, Json_getString(valueMap, "name", 0)); -// if (!eventData) -// { -// setError(root, "Event not found: ", Json_getString(valueMap, "name", 0)); -// return NULL; -// } -// event = spEvent_create(Json_getFloat(valueMap, "time", 0), eventData); -// event->intValue = Json_getInt(valueMap, "int", eventData->intValue); -// event->floatValue = Json_getFloat(valueMap, "float", eventData->floatValue); -// stringValue = Json_getString(valueMap, "string", eventData->stringValue); -// if (stringValue) -// { -// MALLOC_STR(event->stringValue, stringValue); -// } -// spEventTimeline_setFrame(timeline, frameIndex, event); -// } -// timelines[timelinesCount++] = SUPER_CAST(spTimeline, timeline); -// duration = MAX(duration, timeline->frames[events->_size - 1]); + EventTimeline* timeline = NEW(EventTimeline); + new (timeline) EventTimeline(events->_size); + + for (valueMap = events->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) + { + Event* event; + EventData* eventData = skeletonData->findEvent(Json::getString(valueMap, "name", 0)); + if (!eventData) + { + ContainerUtil::cleanUpVectorOfPointers(timelines); + setError(NULL, "Event not found: ", Json::getString(valueMap, "name", 0)); + return NULL; + } + + event = NEW(Event); + new (event) Event(Json::getFloat(valueMap, "time", 0), *eventData); + event->_intValue = Json::getInt(valueMap, "int", eventData->_intValue); + event->_floatValue = Json::getFloat(valueMap, "float", eventData->_floatValue); + event->_stringValue = Json::getString(valueMap, "string", eventData->_stringValue.c_str()); + timeline->setFrame(frameIndex, event); + } + timelines[timelinesCount++] = timeline; + duration = MAX(duration, timeline->_frames[events->_size - 1]); } Animation* ret = NEW(Animation); From e20382a30413a41c48c41aa1b5aa2265a1dd1639 Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Wed, 6 Dec 2017 17:30:48 -0500 Subject: [PATCH 68/83] Now I understand the origin of this deform2 and awkward memset function, haha --- spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp b/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp index 493b62e4f..4673c305a 100644 --- a/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp +++ b/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp @@ -1201,35 +1201,35 @@ namespace Spine for (valueMap = timelineMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) { Json* vertices = Json::getItem(valueMap, "vertices"); - Vector deform2; + Vector deform; if (!vertices) { if (weighted) { - deform2 = tempDeform; + deform = tempDeform; } else { - deform2 = attachment->_vertices; + deform = attachment->_vertices; } } else { int v, start = Json::getInt(valueMap, "offset", 0); Json* vertex; - deform2 = tempDeform; + deform = tempDeform; if (_scale == 1) { for (vertex = vertices->_child, v = start; vertex; vertex = vertex->_next, ++v) { - deform2[v] = vertex->_valueFloat; + deform[v] = vertex->_valueFloat; } } else { for (vertex = vertices->_child, v = start; vertex; vertex = vertex->_next, ++v) { - deform2[v] = vertex->_valueFloat * _scale; + deform[v] = vertex->_valueFloat * _scale; } } if (!weighted) @@ -1237,11 +1237,11 @@ namespace Spine Vector& verticesAttachment = attachment->_vertices; for (v = 0; v < deformLength; ++v) { - deform2[v] += verticesAttachment[v]; + deform[v] += verticesAttachment[v]; } } } - timeline->setFrame(frameIndex, Json::getFloat(valueMap, "time", 0), deform2); + timeline->setFrame(frameIndex, Json::getFloat(valueMap, "time", 0), deform); readCurve(valueMap, timeline, frameIndex); } From 7b32f02e2c258cc7a8ffd8de22da70c731b6e990 Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Wed, 6 Dec 2017 19:00:42 -0500 Subject: [PATCH 69/83] Done. --- .../spine-cpp/src/spine/SkeletonJson.cpp | 425 +++++++++--------- 1 file changed, 210 insertions(+), 215 deletions(-) diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp b/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp index 4673c305a..3be349b61 100644 --- a/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp +++ b/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp @@ -543,237 +543,232 @@ namespace Spine return NULL; } -// switch (type) -// { -// case AttachmentType_Region: -// { -// attachment = _attachmentLoader->newRegionAttachment(*skin, attachmentName, attachmentPath); -// if (!attachment) -// { -// DESTROY(SkeletonData, skeletonData); -// setError(root, "Error reading attachment: ", skinAttachmentName); -// return NULL; -// } -// -// RegionAttachment* region = static_cast(attachment); -// region->_path = attachmentPath; -// -// region->_x = Json::getFloat(attachmentMap, "x", 0) * _scale; -// region->_y = Json::getFloat(attachmentMap, "y", 0) * _scale; -// region->_scaleX = Json::getFloat(attachmentMap, "scaleX", 1); -// region->_scaleY = Json::getFloat(attachmentMap, "scaleY", 1); -// region->_rotation = Json::getFloat(attachmentMap, "rotation", 0); -// region->_width = Json::getFloat(attachmentMap, "width", 32) * _scale; -// region->_height = Json::getFloat(attachmentMap, "height", 32) * _scale; -// -// color = Json::getString(attachmentMap, "color", 0); -// if (color) -// { -// spColor_setFromFloats(®ion->color, -// toColor(color, 0), -// toColor(color, 1), -// toColor(color, 2), -// toColor(color, 3)); -// } -// -// region->updateOffset(); -// -// break; -// } -// case AttachmentType_Mesh: -// case AttachmentType_Linkedmesh: -// { -// MeshAttachment* mesh = SUB_CAST(MeshAttachment, attachment); -// -// MALLOC_STR(mesh->path, attachmentPath); -// -// color = Json::getString(attachmentMap, "color", 0); -// if (color) -// { -// spColor_setFromFloats(&mesh->color, -// toColor(color, 0), -// toColor(color, 1), -// toColor(color, 2), -// toColor(color, 3)); -// } -// -// mesh->width = Json::getFloat(attachmentMap, "width", 32) * _scale; -// mesh->height = Json::getFloat(attachmentMap, "height", 32) * _scale; -// -// entry = Json::getItem(attachmentMap, "parent"); -// if (!entry) -// { -// int verticesLength; -// entry = Json::getItem(attachmentMap, "triangles"); -// mesh->_triangles.reserve(entry->_size); -// for (entry = entry->_child, ii = 0; entry; entry = entry->_next, ++ii) -// { -// mesh->triangles[ii] = (unsigned short)entry->_valueInt; -// } -// -// entry = Json::getItem(attachmentMap, "uvs"); -// verticesLength = entry->_size; -// mesh->_regionUVs.reserve(verticesLength); -// for (entry = entry->_child, ii = 0; entry; entry = entry->_next, ++ii) -// { -// mesh->regionUVs[ii] = entry->_valueFloat; -// } -// -// _readVertices(self, attachmentMap, SUPER(mesh), verticesLength); -// -// MeshAttachment_updateUVs(mesh); -// -// mesh->hullLength = Json::getInt(attachmentMap, "hull", 0); -// -// entry = Json::getItem(attachmentMap, "edges"); -// if (entry) -// { -// mesh->edgesCount = entry->_size; -// mesh->_edges.reserve(entry->_size); -// for (entry = entry->_child, ii = 0; entry; entry = entry->_next, ++ii) -// { -// mesh->edges[ii] = entry->_valueInt; -// } -// } -// } -// else -// { -// mesh->inheritDeform = Json::getInt(attachmentMap, "deform", 1); -// _spSkeletonJson_addLinkedMesh(self, SUB_CAST(MeshAttachment, attachment), Json::getString(attachmentMap, "skin", 0), slotIndex, -// entry->_valueString); -// } -// break; -// } -// case AttachmentType_Boundingbox: -// { -// BoundingBoxAttachment* box = SUB_CAST(BoundingBoxAttachment, attachment); -// int vertexCount = Json::getInt(attachmentMap, "vertexCount", 0) << 1; -// _readVertices(self, attachmentMap, SUPER(box), vertexCount); -// box->super.verticesCount = vertexCount; -// break; -// } -// case AttachmentType_Path: -// { -// PathAttachment* pathAttatchment = SUB_CAST(PathAttachment, attachment); -// int vertexCount = 0; -// pathAttatchment->closed = Json::getInt(attachmentMap, "closed", 0); -// pathAttatchment->constantSpeed = Json::getInt(attachmentMap, "constantSpeed", 1); -// vertexCount = Json::getInt(attachmentMap, "vertexCount", 0); -// _readVertices(self, attachmentMap, SUPER(pathAttatchment), vertexCount << 1); -// -// pathAttatchment->lengthsLength = vertexCount / 3; -// pathAttatchment->_lengths.reserve(vertexCount / 3); -// -// curves = Json::getItem(attachmentMap, "lengths"); -// for (curves = curves->_child, ii = 0; curves; curves = curves->_next, ++ii) -// { -// pathAttatchment->lengths[ii] = curves->_valueFloat * _scale; -// } -// break; -// } -// case AttachmentType_Point: -// { -// PointAttachment* point = SUB_CAST(PointAttachment, attachment); -// point->x = Json::getFloat(attachmentMap, "x", 0) * _scale; -// point->y = Json::getFloat(attachmentMap, "y", 0) * _scale; -// point->rotation = Json::getFloat(attachmentMap, "rotation", 0); -// -// color = Json::getString(attachmentMap, "color", 0); -// if (color) -// { -// spColor_setFromFloats(&point->color, -// toColor(color, 0), -// toColor(color, 1), -// toColor(color, 2), -// toColor(color, 3)); -// } -// break; -// } -// case AttachmentType_Clipping: -// { -// ClippingAttachment* clip = SUB_CAST(ClippingAttachment, attachment); -// int vertexCount = 0; -// const char* end = Json::getString(attachmentMap, "end", 0); -// if (end) -// { -// spSlotData* slot = skeletonData->findSlot(end); -// clip->endSlot = slot; -// } -// vertexCount = Json::getInt(attachmentMap, "vertexCount", 0) << 1; -// _readVertices(self, attachmentMap, SUPER(clip), vertexCount); -// break; -// } -// } -// -// Skin_addAttachment(skin, slotIndex, skinAttachmentName, attachment); + switch (type) + { + case AttachmentType_Region: + { + attachment = _attachmentLoader->newRegionAttachment(*skin, attachmentName, attachmentPath); + if (!attachment) + { + DESTROY(SkeletonData, skeletonData); + setError(root, "Error reading attachment: ", skinAttachmentName); + return NULL; + } + + RegionAttachment* region = static_cast(attachment); + region->_path = attachmentPath; + + region->_x = Json::getFloat(attachmentMap, "x", 0) * _scale; + region->_y = Json::getFloat(attachmentMap, "y", 0) * _scale; + region->_scaleX = Json::getFloat(attachmentMap, "scaleX", 1); + region->_scaleY = Json::getFloat(attachmentMap, "scaleY", 1); + region->_rotation = Json::getFloat(attachmentMap, "rotation", 0); + region->_width = Json::getFloat(attachmentMap, "width", 32) * _scale; + region->_height = Json::getFloat(attachmentMap, "height", 32) * _scale; + + color = Json::getString(attachmentMap, "color", 0); + if (color) + { + region->_r = toColor(color, 0); + region->_g = toColor(color, 1); + region->_b = toColor(color, 2); + region->_a = toColor(color, 3); + } + + region->updateOffset(); + + break; + } + case AttachmentType_Mesh: + case AttachmentType_Linkedmesh: + { + attachment = _attachmentLoader->newMeshAttachment(*skin, attachmentName, attachmentPath); + + MeshAttachment* mesh = static_cast(attachment); + mesh->_path = attachmentPath; + + color = Json::getString(attachmentMap, "color", 0); + if (color) + { + mesh->_r = toColor(color, 0); + mesh->_g = toColor(color, 1); + mesh->_b = toColor(color, 2); + mesh->_a = toColor(color, 3); + } + + mesh->_width = Json::getFloat(attachmentMap, "width", 32) * _scale; + mesh->_height = Json::getFloat(attachmentMap, "height", 32) * _scale; + + entry = Json::getItem(attachmentMap, "parent"); + if (!entry) + { + int verticesLength; + entry = Json::getItem(attachmentMap, "triangles"); + mesh->_triangles.reserve(entry->_size); + for (entry = entry->_child, ii = 0; entry; entry = entry->_next, ++ii) + { + mesh->_triangles[ii] = (unsigned short)entry->_valueInt; + } + + entry = Json::getItem(attachmentMap, "uvs"); + verticesLength = entry->_size; + mesh->_regionUVs.reserve(verticesLength); + for (entry = entry->_child, ii = 0; entry; entry = entry->_next, ++ii) + { + mesh->_regionUVs[ii] = entry->_valueFloat; + } + + readVertices(attachmentMap, mesh, verticesLength); + + mesh->updateUVs(); + + mesh->_hullLength = Json::getInt(attachmentMap, "hull", 0); + + entry = Json::getItem(attachmentMap, "edges"); + if (entry) + { + mesh->_edges.reserve(entry->_size); + for (entry = entry->_child, ii = 0; entry; entry = entry->_next, ++ii) + { + mesh->_edges[ii] = entry->_valueInt; + } + } + } + else + { + mesh->_inheritDeform = Json::getInt(attachmentMap, "deform", 1); + LinkedMesh* linkedMesh = NEW(LinkedMesh); + new (linkedMesh) LinkedMesh(mesh, std::string(Json::getString(attachmentMap, "skin", 0)), slotIndex, std::string(entry->_valueString)); + _linkedMeshes.push_back(linkedMesh); + } + break; + } + case AttachmentType_Boundingbox: + { + attachment = _attachmentLoader->newBoundingBoxAttachment(*skin, attachmentName); + + BoundingBoxAttachment* box = static_cast(attachment); + + int vertexCount = Json::getInt(attachmentMap, "vertexCount", 0) << 1; + readVertices(attachmentMap, box, vertexCount); + break; + } + case AttachmentType_Path: + { + attachment = _attachmentLoader->newPathAttachment(*skin, attachmentName); + + PathAttachment* pathAttatchment = static_cast(attachment); + + int vertexCount = 0; + pathAttatchment->_closed = Json::getInt(attachmentMap, "closed", 0); + pathAttatchment->_constantSpeed = Json::getInt(attachmentMap, "constantSpeed", 1); + vertexCount = Json::getInt(attachmentMap, "vertexCount", 0); + readVertices(attachmentMap, pathAttatchment, vertexCount << 1); + + pathAttatchment->_lengths.reserve(vertexCount / 3); + + curves = Json::getItem(attachmentMap, "lengths"); + for (curves = curves->_child, ii = 0; curves; curves = curves->_next, ++ii) + { + pathAttatchment->_lengths[ii] = curves->_valueFloat * _scale; + } + break; + } + case AttachmentType_Point: + { + attachment = _attachmentLoader->newPointAttachment(*skin, attachmentName); + + PointAttachment* point = static_cast(attachment); + + point->_x = Json::getFloat(attachmentMap, "x", 0) * _scale; + point->_y = Json::getFloat(attachmentMap, "y", 0) * _scale; + point->_rotation = Json::getFloat(attachmentMap, "rotation", 0); + break; + } + case AttachmentType_Clipping: + { + attachment = _attachmentLoader->newClippingAttachment(*skin, attachmentName); + + ClippingAttachment* clip = static_cast(attachment); + + int vertexCount = 0; + const char* end = Json::getString(attachmentMap, "end", 0); + if (end) + { + SlotData* slot = skeletonData->findSlot(end); + clip->_endSlot = slot; + } + vertexCount = Json::getInt(attachmentMap, "vertexCount", 0) << 1; + readVertices(attachmentMap, clip, vertexCount); + break; + } + } + + skin->addAttachment(slotIndex, skinAttachmentName, attachment); } } } } - + /* Linked meshes. */ -// for (i = 0; i < internal->linkedMeshCount; i++) -// { -// Attachment* parent; -// _spLinkedMesh* linkedMesh = internal->linkedMeshes + i; -// Skin* skin = !linkedMesh->skin ? skeletonData->_defaultSkin : SkeletonData_findSkin(skeletonData, linkedMesh->skin); -// if (!skin) -// { -// DESTROY(SkeletonData, skeletonData); -// setError(root, "Skin not found: ", linkedMesh->skin); -// return NULL; -// } -// parent = Skin_getAttachment(skin, linkedMesh->slotIndex, linkedMesh->parent); -// if (!parent) -// { -// DESTROY(SkeletonData, skeletonData); -// setError(root, "Parent mesh not found: ", linkedMesh->parent); -// return NULL; -// } -// MeshAttachment_setParentMesh(linkedMesh->mesh, SUB_CAST(MeshAttachment, parent)); -// MeshAttachment_updateUVs(linkedMesh->mesh); -// AttachmentLoader_configureAttachment(_attachmentLoader, SUPER(SUPER(linkedMesh->mesh))); -// } + for (int i = 0, n = static_cast(_linkedMeshes.size()); i < n; ++i) + { + LinkedMesh* linkedMesh = _linkedMeshes[i]; + Skin* skin = linkedMesh->_skin.length() == 0 ? skeletonData->getDefaultSkin() : skeletonData->findSkin(linkedMesh->_skin); + if (skin == NULL) + { + DESTROY(SkeletonData, skeletonData); + setError(root, "Skin not found: ", linkedMesh->_skin.c_str()); + return NULL; + } + Attachment* parent = skin->getAttachment(linkedMesh->_slotIndex, linkedMesh->_parent); + if (parent == NULL) + { + DESTROY(SkeletonData, skeletonData); + setError(root, "Parent mesh not found: ", linkedMesh->_parent.c_str()); + return NULL; + } + linkedMesh->_mesh->_parentMesh = static_cast(parent); + linkedMesh->_mesh->updateUVs(); + } + _linkedMeshes.clear(); /* Events. */ events = Json::getItem(root, "events"); if (events) { -// Json *eventMap; -// const char* stringValue; -// skeletonData->_events.reserve(events->_size); -// for (eventMap = events->_child, i = 0; eventMap; eventMap = eventMap->_next, ++i) -// { -// EventData* eventData = EventData_create(eventMap->_name); -// eventData->intValue = Json::getInt(eventMap, "int", 0); -// eventData->floatValue = Json::getFloat(eventMap, "float", 0); -// stringValue = Json::getString(eventMap, "string", 0); -// if (stringValue) -// { -// MALLOC_STR(eventData->stringValue, stringValue); -// } -// skeletonData->_events[i] = eventData; -// } + Json *eventMap; + skeletonData->_events.reserve(events->_size); + for (eventMap = events->_child, i = 0; eventMap; eventMap = eventMap->_next, ++i) + { + EventData* eventData = NEW(EventData); + new (eventData) EventData(std::string(eventMap->_name)); + + eventData->_intValue = Json::getInt(eventMap, "int", 0); + eventData->_floatValue = Json::getFloat(eventMap, "float", 0); + eventData->_stringValue = Json::getString(eventMap, "string", 0); + skeletonData->_events[i] = eventData; + } } /* Animations. */ animations = Json::getItem(root, "animations"); if (animations) { -// Json *animationMap; -// skeletonData->_animations.reserve(animations->_size); -// int animationsIndex = 0; -// for (animationMap = animations->_child; animationMap; animationMap = animationMap->_next) -// { -// Animation* animation = readAnimation(animationMap, skeletonData); -// if (!animation) -// { -// DESTROY(SkeletonData, SkeletonData); -// DESTROY(Json, root); -// return NULL; -// } -// skeletonData->_animations[animationsIndex++] = animation; -// } + Json *animationMap; + skeletonData->_animations.reserve(animations->_size); + int animationsIndex = 0; + for (animationMap = animations->_child; animationMap; animationMap = animationMap->_next) + { + Animation* animation = readAnimation(animationMap, skeletonData); + if (!animation) + { + DESTROY(SkeletonData, skeletonData); + DESTROY(Json, root); + return NULL; + } + skeletonData->_animations[animationsIndex++] = animation; + } } DESTROY(Json, root); From a6f0c88994766bec8b9945ef0efa333e1410379c Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Wed, 6 Dec 2017 20:11:10 -0500 Subject: [PATCH 70/83] Wip unit tests, trying to simply port the C ones to CPP, can it be that simple? --- spine-cpp/spine-cpp-unit-tests/CMakeLists.txt | 58 ++ spine-cpp/spine-cpp-unit-tests/README.md | 67 +++ spine-cpp/spine-cpp-unit-tests/main.cpp | 111 +++- .../spine-cpp-unit-tests/memory/KMemory.cpp | 303 +++++++++++ .../spine-cpp-unit-tests/memory/KMemory.h | 189 +++++++ .../spine-cpp-unit-tests/memory/KString.cpp | 185 +++++++ .../spine-cpp-unit-tests/memory/KString.h | 19 + .../minicppunit/MiniCppUnit.cxx | 279 ++++++++++ .../minicppunit/MiniCppUnit.hxx | 504 ++++++++++++++++++ .../spine-cpp-unit-tests/teamcity/README.txt | 30 ++ .../teamcity/teamcity_cppunit.cpp | 82 +++ .../teamcity/teamcity_cppunit.h | 83 +++ .../teamcity/teamcity_messages.cpp | 174 ++++++ .../teamcity/teamcity_messages.h | 59 ++ .../tests/CPP_InterfaceTestFixture.cpp | 48 ++ .../tests/CPP_InterfaceTestFixture.h | 47 ++ .../tests/C_InterfaceTestFixture.cpp | 175 ++++++ .../tests/C_InterfaceTestFixture.h | 33 ++ .../tests/EmptyTestFixture.cpp | 25 + .../tests/EmptyTestFixture.h | 26 + .../tests/MemoryTestFixture.cpp | 338 ++++++++++++ .../tests/MemoryTestFixture.h | 50 ++ .../tests/SpineEventMonitor.cpp | 176 ++++++ .../tests/SpineEventMonitor.h | 126 +++++ .../CPP_InterfaceTestFixture.cpp | 26 + .../CPP_InterfaceTestFixture.h | 30 ++ .../TestFixtureGenerator/_TestFixture.cpp | 26 + .../tests/TestFixtureGenerator/_TestFixture.h | 30 ++ .../tests/TestFixtureGenerator/fnr.exe | Bin 0 -> 185200 bytes .../TestFixtureGenerator/makeFixture.bat | 17 + .../spine-cpp-unit-tests/tests/TestOptions.h | 32 ++ 31 files changed, 3344 insertions(+), 4 deletions(-) create mode 100755 spine-cpp/spine-cpp-unit-tests/CMakeLists.txt create mode 100755 spine-cpp/spine-cpp-unit-tests/README.md create mode 100755 spine-cpp/spine-cpp-unit-tests/memory/KMemory.cpp create mode 100755 spine-cpp/spine-cpp-unit-tests/memory/KMemory.h create mode 100755 spine-cpp/spine-cpp-unit-tests/memory/KString.cpp create mode 100755 spine-cpp/spine-cpp-unit-tests/memory/KString.h create mode 100755 spine-cpp/spine-cpp-unit-tests/minicppunit/MiniCppUnit.cxx create mode 100755 spine-cpp/spine-cpp-unit-tests/minicppunit/MiniCppUnit.hxx create mode 100755 spine-cpp/spine-cpp-unit-tests/teamcity/README.txt create mode 100755 spine-cpp/spine-cpp-unit-tests/teamcity/teamcity_cppunit.cpp create mode 100755 spine-cpp/spine-cpp-unit-tests/teamcity/teamcity_cppunit.h create mode 100755 spine-cpp/spine-cpp-unit-tests/teamcity/teamcity_messages.cpp create mode 100755 spine-cpp/spine-cpp-unit-tests/teamcity/teamcity_messages.h create mode 100755 spine-cpp/spine-cpp-unit-tests/tests/CPP_InterfaceTestFixture.cpp create mode 100755 spine-cpp/spine-cpp-unit-tests/tests/CPP_InterfaceTestFixture.h create mode 100755 spine-cpp/spine-cpp-unit-tests/tests/C_InterfaceTestFixture.cpp create mode 100755 spine-cpp/spine-cpp-unit-tests/tests/C_InterfaceTestFixture.h create mode 100755 spine-cpp/spine-cpp-unit-tests/tests/EmptyTestFixture.cpp create mode 100755 spine-cpp/spine-cpp-unit-tests/tests/EmptyTestFixture.h create mode 100755 spine-cpp/spine-cpp-unit-tests/tests/MemoryTestFixture.cpp create mode 100755 spine-cpp/spine-cpp-unit-tests/tests/MemoryTestFixture.h create mode 100755 spine-cpp/spine-cpp-unit-tests/tests/SpineEventMonitor.cpp create mode 100755 spine-cpp/spine-cpp-unit-tests/tests/SpineEventMonitor.h create mode 100755 spine-cpp/spine-cpp-unit-tests/tests/TestFixtureGenerator/CPP_InterfaceTestFixture.cpp create mode 100755 spine-cpp/spine-cpp-unit-tests/tests/TestFixtureGenerator/CPP_InterfaceTestFixture.h create mode 100755 spine-cpp/spine-cpp-unit-tests/tests/TestFixtureGenerator/_TestFixture.cpp create mode 100755 spine-cpp/spine-cpp-unit-tests/tests/TestFixtureGenerator/_TestFixture.h create mode 100755 spine-cpp/spine-cpp-unit-tests/tests/TestFixtureGenerator/fnr.exe create mode 100755 spine-cpp/spine-cpp-unit-tests/tests/TestFixtureGenerator/makeFixture.bat create mode 100755 spine-cpp/spine-cpp-unit-tests/tests/TestOptions.h diff --git a/spine-cpp/spine-cpp-unit-tests/CMakeLists.txt b/spine-cpp/spine-cpp-unit-tests/CMakeLists.txt new file mode 100755 index 000000000..e08a7d3ba --- /dev/null +++ b/spine-cpp/spine-cpp-unit-tests/CMakeLists.txt @@ -0,0 +1,58 @@ +cmake_minimum_required(VERSION 2.8.9) +project(spine_unit_test) + +set(CMAKE_INSTALL_PREFIX "./") +set(CMAKE_VERBOSE_MAKEFILE ON) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_CRT_SECURE_NO_WARNINGS -DKANJI_MEMTRACE -DUSE_CPP11_MUTEX -std=c++11") + +######################################################### +# set includes +######################################################### +include_directories(../spine-cpp/include teamcity minicppunit tests memory) + +######################################################### +# Add Sources +######################################################### +set(MINICPP_SRC + minicppunit/MiniCppUnit.cxx +) + +set(TEAMCITY_SRC + teamcity/teamcity_cppunit.cpp + teamcity/teamcity_messages.cpp +) + +set(TEST_SRC + tests/SpineEventMonitor.cpp + tests/EmptyTestFixture.cpp + tests/C_InterfaceTestFixture.cpp + tests/CPP_InterfaceTestFixture.cpp + tests/MemoryTestFixture.cpp +) + +set(MEMLEAK_SRC + memory/KMemory.cpp + memory/KString.cpp +) + +######################################################### +# setup main project +######################################################### +add_executable(spine_unit_test main.cpp ${MINICPP_SRC} ${TEAMCITY_SRC} ${TEST_SRC} ${MEMLEAK_SRC}) +target_link_libraries(spine_unit_test spine-cpp) + + +######################################################### +# copy resources to build output directory +######################################################### +add_custom_command(TARGET spine_unit_test PRE_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_directory + ${CMAKE_CURRENT_LIST_DIR}/../../examples/spineboy/export $/testdata/spineboy) + +add_custom_command(TARGET spine_unit_test PRE_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_directory + ${CMAKE_CURRENT_LIST_DIR}/../../examples/raptor/export $/testdata/raptor) + +add_custom_command(TARGET spine_unit_test PRE_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_directory + ${CMAKE_CURRENT_LIST_DIR}/../../examples/goblins/export $/testdata/goblins) diff --git a/spine-cpp/spine-cpp-unit-tests/README.md b/spine-cpp/spine-cpp-unit-tests/README.md new file mode 100755 index 000000000..bfe38c489 --- /dev/null +++ b/spine-cpp/spine-cpp-unit-tests/README.md @@ -0,0 +1,67 @@ +# spine-cpp-unit-tests + +The spine-cpp-unit-tests project is to test the [Spine](http://esotericsoftware.com) skeletal animation system. It does not perform rendering. It is primarily used for regression testing and leak detection. It is designed to be run from a Continuous Integration server and to passively verify changes automatically on check-in. + +## Mini CPP Unit Testing +[MiniCppUnit](https://sourceforge.net/p/minicppunit/wiki/Home/) is a minimal unit testing framework similar to JUnit. It is used here to avoid large dependancies. + +Tests are sorted into Suites, Fixtures and Cases. There is one suite, it contains many fixtures and each fixture contains test cases. To turn off a fixture, edit "TestOptions.h". To turn off specific test cases, comment out the TEST_CASE() line in the fixture's header. + +## Memory Leak Detection +This project includes a very minimal memory leak detector. It is based roughly on the leak detector in the [Popcap Framework](https://sourceforge.net/projects/popcapframework/?source=directory), but has been modified over the years. + +## Continuous Integration +The test runner includes the ability to format output messages to signal a CI server. An example interface for [Teamcity](https://www.jetbrains.com/teamcity/) is included. To implement for another server, determine the wireformat for the messages and duplicate/edit the teamcity_messages class. [Teamcity Wire Format](https://confluence.jetbrains.com/display/TCD10/Build+Script+Interaction+with+TeamCity) + +### Trigger +Your CI server should trigger on VCS check-in. + +### CMake Build Step +The first build step for the CI server should be to run CMake on the 'spine-cpp-unit-tests' folder. Follow the usage directions below. + +### Compile Build Step +This build step should not execute if the previous step did not successfully complete. +Depending on the test agent build environment, you should build the output solution or project from the cmake step. Debug is fine. + +### Test Runner Build Step +This build step should not execute if the previous step did not successfully complete. +Again, depending on the test agent build environment, you should have produced an executable. Run this executable. + + +## Usage +Make sure [CMake](https://cmake.org/download/) is installed. + +Create a 'build' directory in the 'spine-cpp-unit-tests' folder. Then switch to that folder and execute cmake: + +mkdir build +cd build +cmake .. + +### Win32 build +msbuild spine_unit_test.sln /t:spine_unit_test /p:Configuration="Debug" /p:Platform="Win32" + + +## Licensing +This Spine Runtime may only be used for personal or internal use, typically to evaluate Spine before purchasing. If you would like to incorporate a Spine Runtime into your applications, distribute software containing a Spine Runtime, or modify a Spine Runtime, then you will need a valid [Spine license](https://esotericsoftware.com/spine-purchase). Please see the [Spine Runtimes Software License](https://github.com/EsotericSoftware/spine-runtimes/blob/master/LICENSE) for detailed information. + +The Spine Runtimes are developed with the intent to be used with data exported from Spine. By purchasing Spine, `Section 2` of the [Spine Software License](https://esotericsoftware.com/files/license.txt) grants the right to create and distribute derivative works of the Spine Runtimes. + +original "walk"": 330 +second "walk": 0d0 + +queue interrupt for original walk +queue start for second walk +drain interrupt and start + +0d0 is interrupted +0d0 is ended + +"run": 0c0 + 0d0 is interrupted + second walk becomes mixingFrom of run + 0c0 is started + + queue is drained + + first walk: 6f0 + second walk: 9c0 diff --git a/spine-cpp/spine-cpp-unit-tests/main.cpp b/spine-cpp/spine-cpp-unit-tests/main.cpp index f4343cab2..3cfa5fcd4 100755 --- a/spine-cpp/spine-cpp-unit-tests/main.cpp +++ b/spine-cpp/spine-cpp-unit-tests/main.cpp @@ -1,7 +1,110 @@ -#include +// SexyKanjiTestSuite.cpp : Defines the entry point for the console application. +// + +#include "MiniCppUnit.hxx" + +#ifdef WIN32 +#include +#else +#include +#endif // WIN32 + +#include +#include "KString.h" +#include + +#include "spine/Extension.h" + +#include "KMemory.h" // last include -int main(int argc, const char * argv[]) +using namespace Spine; + +class KanjiSpineExtension : public DefaultSpineExtension { - std::cout << "Awww yeah, gonna test some stuff here eventually!\n"; - return 0; +public: + static KanjiSpineExtension* getInstance(); + + virtual ~KanjiSpineExtension(); + + virtual void* spineAlloc(size_t size, const char* file, int line); + + virtual void* spineCalloc(size_t num, size_t size, const char* file, int line); + + virtual void* spineRealloc(void* ptr, size_t size, const char* file, int line); + + virtual void spineFree(void* mem); + +protected: + KanjiSpineExtension(); +}; + +KanjiSpineExtension* KanjiSpineExtension::getInstance() +{ + static KanjiSpineExtension ret; + return &ret; } + +KanjiSpineExtension::~KanjiSpineExtension() +{ + // Empty +} + +void* KanjiSpineExtension::spineAlloc(size_t size, const char* file, int line) +{ + return _kanjimalloc(size); +} + +void* KanjiSpineExtension::spineCalloc(size_t num, size_t size, const char* file, int line) +{ + void* ptr = _kanjimalloc(num * size, file, line); + if (ptr) + { + memset(ptr, 0, num * size); + } + + return ptr; +} + +void* KanjiSpineExtension::spineRealloc(void* ptr, size_t size, const char* file, int line) +{ + return _kanjirealloc(ptr, size); +} + +void KanjiSpineExtension::spineFree(void* mem) +{ + _kanjifree(mem); +} + +KanjiSpineExtension::KanjiSpineExtension() : DefaultSpineExtension() +{ + // Empty +} + +int main(int argc, char* argv[]) +{ + SpineExtension::setInstance(KanjiSpineExtension::getInstance()); + + // Start Timing + time_t start_time, end_time; + time(&start_time); + + /* Set working directory to current location for opening test data */ +#ifdef WIN32 + _chdir( GetFileDir(argv[0], false).c_str() ); +#else + chdir(GetFileDir(argv[0], false).c_str()); +#endif + + // Run Test Suite + if(JetBrains::underTeamcity()) gTeamCityListener.startSuite("Spine-CPP Test Suite"); + int ret_val = TestFixtureFactory::theInstance().runTests() ? 0 : -1; + if(JetBrains::underTeamcity()) gTeamCityListener.endSuite("Spine-CPP Test Suite"); + + // End Timing + time(&end_time); + double secs = difftime(end_time,start_time); + printf("\n\n%i minutes and %i seconds of your life taken from you by these tests.\n", ((int)secs) / 60, ((int)secs) % 60); + + return ret_val; +} + diff --git a/spine-cpp/spine-cpp-unit-tests/memory/KMemory.cpp b/spine-cpp/spine-cpp-unit-tests/memory/KMemory.cpp new file mode 100755 index 000000000..a21cbafba --- /dev/null +++ b/spine-cpp/spine-cpp-unit-tests/memory/KMemory.cpp @@ -0,0 +1,303 @@ +#include +#include +#include +#include +#include + +#include "KString.h" + +#include "KMemory.h" // last include + +/////////////////////////////////////////////////////////////////////////////// +// +// KANJI_DUMP_LEAKED_MEM will print out the memory block that was leaked. +// This is helpful when leaked objects have string identifiers. +// +/////////////////////////////////////////////////////////////////////////////// +//#define KANJI_DUMP_LEAKED_MEM + + +/////////////////////////////////////////////////////////////////////////////// +// +// KANJI_TRACK_MEM_USAGE will print out all memory allocations. +// +/////////////////////////////////////////////////////////////////////////////// +//#define KANJI_TRACK_MEM_USAGE + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +// Our memory system is thread-safe, but instead of linking massive libraries, +// we attempt to use C++11 std::mutex. +#ifdef USE_CPP11_MUTEX_DISABLED +#include +typedef std::recursive_mutex KSysLock; // rentrant +struct KAutoLock { + KAutoLock(KSysLock& lock) :mLock(lock) { mLock.lock(); } // acquire + ~KAutoLock() { mLock.unlock(); } // release + + KSysLock& mLock; +}; +#else // Fallback to unsafe. don't spawn threads +typedef int KSysLock; +struct KAutoLock { + KAutoLock(KSysLock) {} // acquire + ~KAutoLock() {} // release +}; +#endif + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +struct KANJI_ALLOC_INFO +{ + size_t size; + std::string file; + int line; +}; +static bool showLeaks = false; +class KAllocMap : public std::map +{ +public: + KSysLock crit; + static bool allocMapValid; + +public: + KAllocMap() { allocMapValid = true; } + ~KAllocMap() + { + if (showLeaks) + KMemoryDumpUnfreed(); + + allocMapValid = false; + } +}; +bool KAllocMap::allocMapValid = false; +static KAllocMap allocMap; // once this static object destructs, it dumps unfreed memory + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +#ifdef KANJI_TRACK_MEM_USAGE +void KMemoryDumpUsage(); // forward declaration +class KAllocStat +{ +public: + typedef std::map allocCount; // [size] = count + typedef std::map, allocCount> allocInfo; // [file, line] = allocCount + + allocInfo memInfo; + static bool allocMapValid; + +public: + + KAllocStat() + { + allocMapValid = true; + } + ~KAllocStat() + { + if (showLeaks) + KMemoryDumpUsage(); + + allocMapValid = false; + } + void addTrack(const char* fname, int lnum, int asize) + { + allocCount& info = memInfo[std::pair(fname, lnum)]; + info[asize]++; + } +}; +bool KAllocStat::allocMapValid = false; +static KAllocStat allocStat; +#endif // KANJI_TRACK_MEM_USAGE + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +extern void KMemoryAddTrack( void* addr, size_t asize, const char* fname, int lnum ) +{ + if (!KAllocMap::allocMapValid || asize == 0) + return; + + KAutoLock aCrit(allocMap.crit); + showLeaks = true; + + KANJI_ALLOC_INFO& info = allocMap[addr]; + info.file = fname; + info.line = lnum; + info.size = asize; + +#ifdef KANJI_TRACK_MEM_USAGE + if (KAllocStat::allocMapValid) + allocStat.addTrack(fname, lnum, asize); +#endif +}; + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +void KMemoryRemoveTrack(void* addr) +{ + if (!KAllocMap::allocMapValid) + return; + + KAutoLock aCrit(allocMap.crit); + KAllocMap::iterator anItr = allocMap.find(addr); + if (anItr != allocMap.end()) + allocMap.erase(anItr); +}; + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +void KMemoryDumpUnfreed() +{ + if (!KAllocMap::allocMapValid) + return; + + KAutoLock aCrit(allocMap.crit); // prevent modification of the map while iterating + + size_t totalSize = 0; + char buf[8192]; + + FILE* f = fopen("mem_leaks.txt", "wt"); + if (!f) + return; + + time_t aTime = time(NULL); + sprintf(buf, "Memory Leak Report for %s\n", asctime(localtime(&aTime))); + fprintf(f, "%s", buf); + KOutputDebug(DEBUGLVL, "\n"); + KOutputDebug(INFOLVL, buf); + for(KAllocMap::iterator i = allocMap.begin(); i != allocMap.end(); ++i) + { + sprintf(buf, "%s(%d) : Leak %u byte%s @0x%08X\n", i->second.file.c_str(), i->second.line, i->second.size, i->second.size > 1 ? "s" : "", (size_t)i->first); + KOutputDebug(ERRORLVL, buf); + fprintf(f, "%s", buf); + +#ifdef KANJI_DUMP_LEAKED_MEM + unsigned char* data = (unsigned char*)i->first; + int count = 0; + char hex_dump[1024]; + char ascii_dump[1024]; + + for (int index = 0; index < i->second.size; index++) + { + unsigned char _c = *data; + + if (count == 0) + sprintf(hex_dump, "\t%02X ", _c); + else + sprintf(hex_dump, "%s%02X ", hex_dump, _c); // technically, this is undefined behavior + + if ((_c < 32) || (_c > 126)) + _c = '.'; + + if (count == 7) + sprintf(ascii_dump, "%s%c ", ascii_dump, _c); + else + sprintf(ascii_dump, "%s%c", count == 0 ? "\t" : ascii_dump, _c); // technically, this is undefined behavior + + + if (++count == 16) + { + count = 0; + sprintf(buf, "%s\t%s\n", hex_dump, ascii_dump); + fprintf(f, buf); + + memset((void*)hex_dump, 0, 1024); + memset((void*)ascii_dump, 0, 1024); + } + + data++; + } + + if (count != 0) + { + fprintf(f, hex_dump); + for (int index = 0; index < 16 - count; index++) + fprintf(f, "\t"); + + fprintf(f, ascii_dump); + + for (int index = 0; index < 16 - count; index++) + fprintf(f, "."); + } + + count = 0; + fprintf(f, "\n\n"); + memset((void*)hex_dump, 0, 1024); + memset((void*)ascii_dump, 0, 1024); + +#endif // KANJI_DUMP_LEAKED_MEM + + totalSize += i->second.size; + } + + ErrorLevel lvl = (totalSize > 0) ? ERRORLVL : INFOLVL; + + sprintf(buf, "-----------------------------------------------------------\n"); + fprintf(f, "%s", buf); + KOutputDebug(lvl, buf); + sprintf(buf, "Total Unfreed: %u bytes (%luKB)\n\n", totalSize, totalSize / 1024); + KOutputDebug(lvl, buf); + fprintf(f, "%s", buf); + fclose(f); +} + +#ifdef KANJI_TRACK_MEM_USAGE +void KMemoryDumpUsage() +{ + if (!KAllocStat::allocMapValid) + return; + + char buf[8192]; + FILE* f = fopen("mem_usage.txt", "wt"); + + time_t aTime = time(NULL); + sprintf(buf, "Memory Usage Report for %s\n", asctime(localtime(&aTime))); + if (f) fprintf(f, "%s", buf); + KOutputDebug("\n"); + KOutputDebug(buf); + + for(KAllocStat::allocInfo::iterator i = allocStat.memInfo.begin(); i != allocStat.memInfo.end(); ++i) + { + int aBytesTotal = 0; + int aCallsTotal = 0; + for (KAllocStat::allocCount::iterator index = i->second.begin(); index != i->second.end(); ++index) + { + aBytesTotal += index->first; + aCallsTotal += index->second; + sprintf(buf, "%s(%d) : %d bytes (%d %s)\n", i->first.first.c_str(), i->first.second, index->first, index->second, index->second == 1 ? "call" : "calls"); + if (f) fprintf(f, "%s", buf); + KOutputDebug(buf); + } + + if (i->second.size() > 1) + { + sprintf(buf, " %s(%d) : %d KB total (%d calls)\n", i->first.first.c_str(), i->first.second, aBytesTotal / 1024, aCallsTotal); + if (f) fprintf(f, "%s", buf); + KOutputDebug(buf); + } + } + if (f) fclose(f); +} +#endif // KANJI_TRACK_MEM_USAGE + +size_t KMemoryAllocated() +{ + if (!KAllocMap::allocMapValid) + return 0; + + KAutoLock aCrit(allocMap.crit); + + size_t size = 0; + for(auto i = allocMap.begin(); i != allocMap.end(); ++i) + { + KANJI_ALLOC_INFO& info = i->second; + size += info.size; + } + return size; +} diff --git a/spine-cpp/spine-cpp-unit-tests/memory/KMemory.h b/spine-cpp/spine-cpp-unit-tests/memory/KMemory.h new file mode 100755 index 000000000..470a5db7d --- /dev/null +++ b/spine-cpp/spine-cpp-unit-tests/memory/KMemory.h @@ -0,0 +1,189 @@ +#ifndef __KANJIMEMORY_H__ +#define __KANJIMEMORY_H__ + +#include +#include + +#if defined(_DEBUG) && !defined(KANJI_MEMTRACE) +#define KANJI_MEMTRACE +#endif + +#ifdef WIN32 +#pragma warning(disable : 4595) +#endif + +////////////////////////////////////////////////////////////////////////// +// HOW TO USE THIS FILE +// +// In the desired .CPP file (NOT header file), AFTER ALL of your +// #include declarations, do a #include "KMemory.h" or whatever you renamed +// this file to. It's very important that you do it only in the .cpp and +// after every other include file, otherwise it won't compile. The memory leaks +// will appear in a file called mem_leaks.txt and they will also be printed out +// in the output window when the program exits. +// +////////////////////////////////////////////////////////////////////////// + +#ifndef SAFE_DELETE +#define SAFE_DELETE(pPtr) { if(pPtr) delete pPtr; pPtr = 0; } +#endif + +#ifndef SCOPED_AUTO_SAFE_DELETE +template +class ScopedAutoDeletePointerHelper +{ +public: + ScopedAutoDeletePointerHelper(T pPtr) : _pPtr(pPtr) {} + ~ScopedAutoDeletePointerHelper() { SAFE_DELETE(_pPtr); } + + T _pPtr; +}; +#define SCOPED_AUTO_SAFE_DELETE(p) ScopedAutoDeletePointerHelper anAutoDelete##p(p); +#endif + +#ifndef SAFE_DELETE_ARRAY +#define SAFE_DELETE_ARRAY(pPtr) { if(pPtr) delete [] pPtr; pPtr = 0; } +#endif + +extern void KMemoryDumpUnfreed(); +extern size_t KMemoryAllocated(); + +#ifdef WIN32 +#define KMEM_CALLTYPE __cdecl +#else +#define KMEM_CALLTYPE +#endif + +#ifdef __APPLE__ +#define KMEM_THROWSPEC throw(std::bad_alloc) +#define KMEM_THROWS_BADALLOC +#include +#else +#define KMEM_THROWSPEC +#endif + +#if defined(KANJI_MEMTRACE) + +///////////////////////////////////////////// +// DO NOT CALL THESE TWO METHODS DIRECTLY // +///////////////////////////////////////////// + +extern void KMemoryAddTrack(void* addr, size_t asize, const char* fname, int lnum); +extern void KMemoryRemoveTrack(void* addr); + +//Replacement for the standard malloc/free, records size of allocation and the file/line number it was on +inline void* _kanjimalloc (size_t size, const char* file, int line) +{ + void* ptr = (void*)malloc(size); + KMemoryAddTrack(ptr, size, file, line); + return(ptr); +} + +inline void* _kanjimalloc (size_t size) +{ + return _kanjimalloc(size, "", 0); +} + +inline void _kanjifree (void* ptr) +{ + KMemoryRemoveTrack(ptr); + free(ptr); +} + +inline void* _kanjirealloc (void* ptr, size_t size, const char* file, int line) +{ + void* ptr2 = (void*)realloc(ptr, size); + if (ptr2) + { + KMemoryRemoveTrack(ptr); + KMemoryAddTrack(ptr2, size, file, line); + } + return ptr2; +} + +inline void* _kanjirealloc (void* ptr, size_t size) +{ + return _kanjirealloc(ptr, size, "", 0); +} + +#define kanjimalloc(size) _kanjimalloc((size), __FILE__, __LINE__) +#define kanjifree _kanjifree +#define kanjirealloc(ptr, size) _kanjirealloc(ptr, size, __FILE__, __LINE__) + +//Replacement for the standard "new" operator, records size of allocation and the file/line number it was on +inline void* KMEM_CALLTYPE operator new(size_t size, const char* file, int line) +{ + void* ptr = (void*)malloc(size); + KMemoryAddTrack(ptr, size, file, line); + return(ptr); +} + +//Same as above, but for arrays +inline void* KMEM_CALLTYPE operator new[](size_t size, const char* file, int line) +{ + void* ptr = (void*)malloc(size); + KMemoryAddTrack(ptr, size, file, line); + return(ptr); +} + + +// These single argument new operators allow vc6 apps to compile without errors +inline void* KMEM_CALLTYPE operator new(size_t size) KMEM_THROWSPEC +{ + void* ptr = (void*)malloc(size); +#ifdef KMEM_THROWS_BADALLOC + if(!ptr) throw std::bad_alloc(); +#endif + return(ptr); +} + +inline void* KMEM_CALLTYPE operator new[](size_t size) KMEM_THROWSPEC +{ + void* ptr = (void*)malloc(size); +#ifdef KMEM_THROWS_BADALLOC + if(!ptr) throw std::bad_alloc(); +#endif // KMEM_THROWS_BADALLOC + return(ptr); +} + + +//custom delete operators +inline void KMEM_CALLTYPE operator delete(void* p) throw() +{ + KMemoryRemoveTrack(p); + free(p); +} + +inline void KMEM_CALLTYPE operator delete[](void* p) throw() +{ + KMemoryRemoveTrack(p); + free(p); +} + +//needed in case in the constructor of the class we're newing, it throws an exception +inline void KMEM_CALLTYPE operator delete(void* pMem, const char* file, int line) +{ + free(pMem); +} + +inline void KMEM_CALLTYPE operator delete[](void* pMem, const char* file, int line) +{ + free(pMem); +} + +#define KDEBUG_NEW new(__FILE__, __LINE__) +#define new KDEBUG_NEW + +#else // KANJI_MEMTRACE NOT DEFINED + +#define kanjimalloc malloc +#define kanjifree free +#define kanjirealloc realloc + +inline void* _kanjimalloc(size_t size) { return malloc(size); } +inline void _kanjifree(void* ptr) { free(ptr); } +inline void* _kanjirealloc(void* ptr, size_t size) { return realloc(ptr, size); } + +#endif // KANJI_MEMTRACE + +#endif // __KANJIMEMORY_H__ \ No newline at end of file diff --git a/spine-cpp/spine-cpp-unit-tests/memory/KString.cpp b/spine-cpp/spine-cpp-unit-tests/memory/KString.cpp new file mode 100755 index 000000000..bd7aef664 --- /dev/null +++ b/spine-cpp/spine-cpp-unit-tests/memory/KString.cpp @@ -0,0 +1,185 @@ +#include "KString.h" +#include + +#include "MiniCppUnit.hxx" + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +// String Helper + +static std::string vasprintf(const char* fmt, va_list argv) +{ + std::string result; + va_list argv_copy; // vsnprintf modifies argv, need copy +#ifndef va_copy + argv_copy = argv; +#else + va_copy(argv_copy, argv); +#endif + + int len = vsnprintf(NULL, 0, fmt, argv_copy); + if (len > 0 && len < 255) + { + // cover 90% of all calls + char str[256] = { 0 }; + int len2 = vsnprintf(str, 255, fmt, argv); + result = str; + } + else if (len > 0) + { + char* str = static_cast(alloca(len + 1)); // alloca on stack, space for null-termination + int len2 = vsnprintf(str, len + 1, fmt, argv); + result = str; + } + return result; +} + + +static void reportWarning(const std::string& warnStr) +{ + if (JetBrains::underTeamcity()) + gTeamCityListener.messages.messageWarning(warnStr); + else + fprintf(stderr, "%s", warnStr.c_str()); +} + +static void reportError(const std::string& errorStr) +{ + if (JetBrains::underTeamcity()) + gTeamCityListener.messages.messageError(errorStr); + else + fprintf(stderr, "%s", errorStr.c_str()); +} + +static void reportInfo(const std::string& infoStr) +{ + if (JetBrains::underTeamcity()) + gTeamCityListener.messages.messageNormal(infoStr); + else + fprintf(stderr, "%s", infoStr.c_str()); +} + +static void reportDebug(const std::string& debugStr) +{ + fprintf(stderr, "%s", debugStr.c_str()); +} + +static void report(ErrorLevel level, const std::string& Str) +{ + switch (level) { + case WARNLVL: reportWarning(Str); break; + case ERRORLVL: reportError(Str); break; + case INFOLVL: reportInfo(Str); break; + case DEBUGLVL: reportDebug(Str); break; + } +} + +void KOutputDebug(ErrorLevel lvl, const char* fmt ...) +{ + va_list argList; + va_start(argList, fmt); + std::string str = vasprintf(fmt, argList); + va_end(argList); + + report(lvl, str); +} + +#define K_MAX(a,b) ((a>b) ? a : b) + +std::string GetFileName(const std::string& thePath, bool noExtension) +{ + int aLastSlash = K_MAX((int)thePath.rfind('\\'), (int)thePath.rfind('/')); + + if (noExtension) + { + int aLastDot = (int)thePath.rfind('.'); + if (aLastDot > aLastSlash) + return thePath.substr(aLastSlash + 1, aLastDot - aLastSlash - 1); + } + + if (aLastSlash == -1) + return thePath; + else + return thePath.substr(aLastSlash + 1); +} + +std::string GetFileDir(const std::string& thePath, bool withSlash) +{ + int aLastSlash = K_MAX((int)thePath.rfind(('\\')), (int)thePath.rfind(('/'))); + + if (aLastSlash == -1) + return (""); + else + { + if (withSlash) + return thePath.substr(0, aLastSlash + 1); + else + return thePath.substr(0, aLastSlash); + } +} + +std::string GetFileExt(const std::string& thePath) +{ + std::string::size_type idx = thePath.find_last_of('.'); + + if (idx != std::string::npos) + return thePath.substr(idx + 1); + + return (""); +} + +/** + * g_ascii_strcasecmp: + * @s1: string to compare with @s2. + * @s2: string to compare with @s1. + * + * Compare two strings, ignoring the case of ASCII characters. + * + * Unlike the BSD strcasecmp() function, this only recognizes standard + * ASCII letters and ignores the locale, treating all non-ASCII + * bytes as if they are not letters. + * + * This function should be used only on strings that are known to be + * in encodings where the bytes corresponding to ASCII letters always + * represent themselves. This includes UTF-8 and the ISO-8859-* + * charsets, but not for instance double-byte encodings like the + * Windows Codepage 932, where the trailing bytes of double-byte + * characters include all ASCII letters. If you compare two CP932 + * strings using this function, you will get false matches. + * + * Return value: an integer less than, equal to, or greater than + * zero if @s1 is found, respectively, to be less than, + * to match, or to be greater than @s2. + **/ +static int g_ascii_compare_caseless(const char* s1, const char* s2) +{ +#define TOUPPER(c) (((c) >= 'a' && (c) <= 'z') ? (c) - 'a' + 'A' : (c)) +#define TOLOWER(c) (((c) >= 'A' && (c) <= 'Z') ? (c) - 'A' + 'a' : (c)) +#define g_return_val_if_fail(expr,val) { if (!(expr)) return (val); } + + int c1, c2; + + g_return_val_if_fail(s1 != NULL, 0); + g_return_val_if_fail(s2 != NULL, 0); + + while (*s1 && *s2) + { + c1 = (int)(unsigned char)TOLOWER(*s1); + c2 = (int)(unsigned char)TOLOWER(*s2); + if (c1 != c2) + return (c1 - c2); + s1++; s2++; + } + + return (((int)(unsigned char)* s1) - ((int)(unsigned char)* s2)); + +#undef g_return_val_if_fail +#undef TOUPPER +#undef TOLOWER +} + + +int CompareNoCase(const std::string & str1, const std::string & str2) +{ + return g_ascii_compare_caseless(str1.c_str(), str2.c_str()); +} diff --git a/spine-cpp/spine-cpp-unit-tests/memory/KString.h b/spine-cpp/spine-cpp-unit-tests/memory/KString.h new file mode 100755 index 000000000..32a27cb44 --- /dev/null +++ b/spine-cpp/spine-cpp-unit-tests/memory/KString.h @@ -0,0 +1,19 @@ +#pragma once + +#include + +// Error reporting with levels similar to Android and are automatically forwarded to Continuous integration server +enum ErrorLevel { + WARNLVL, + ERRORLVL, + INFOLVL, + DEBUGLVL +}; + +extern void KOutputDebug(ErrorLevel lvl, const char* fmt ...); + +extern std::string GetFileName(const std::string& thePath, bool noExtension); +extern std::string GetFileDir(const std::string& thePath, bool withSlash); +extern std::string GetFileExt(const std::string& thePath); + +extern int CompareNoCase(const std::string& str1, const std::string& str2); diff --git a/spine-cpp/spine-cpp-unit-tests/minicppunit/MiniCppUnit.cxx b/spine-cpp/spine-cpp-unit-tests/minicppunit/MiniCppUnit.cxx new file mode 100755 index 000000000..f14e790fb --- /dev/null +++ b/spine-cpp/spine-cpp-unit-tests/minicppunit/MiniCppUnit.cxx @@ -0,0 +1,279 @@ +/* + * Copyright (c) 2003-2004 Pau Arumí & David García + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "MiniCppUnit.hxx" + +JetBrains::TeamcityProgressListener gTeamCityListener; +bool gUseTeamCity = false; + +#include +#include +#include + +#define MIN(a,b) ((a < b) ? a : b) +#define MAX(a,b) ((a > b) ? a : b) + +TestsListener::TestsListener() : _currentTestName(0) +{ + _executed=_failed=_exceptions=0; + gUseTeamCity = JetBrains::underTeamcity(); +} + +TestsListener& TestsListener::theInstance() +{ + static TestsListener instancia; + return instancia; +} + +std::stringstream& TestsListener::errorsLog() +{ + if (_currentTestName) + { + _log << "\n" << errmsgTag_nameOfTest() << (*_currentTestName) << "\n"; + } + return _log; +} + +std::string TestsListener::logString() +{ + std::string aRetornar = _log.str(); + _log.str(""); + return aRetornar; +} +void TestsListener::currentTestName( std::string& name) +{ + _currentTestName = &name; + + if(gUseTeamCity)gTeamCityListener.startTest(name); +} +void TestsListener::testHasRun() // started +{ + std::cout << "."; + theInstance()._executed++; +} + +void TestsListener::testHasPassed() // finished without errors +{ + if(gUseTeamCity) + gTeamCityListener.endTest(*(theInstance()._currentTestName)); +} + +void TestsListener::testHasFailed(const char* reason, const char* file, int line) +{ + if(gUseTeamCity) + { + gTeamCityListener.addFailure(JetBrains::TestFailure(*(theInstance()._currentTestName), "", JetBrains::SourceLine(file, line), reason)); + gTeamCityListener.endTest(*(theInstance()._currentTestName)); + } + + std::cout << "F"; + theInstance()._failed++; + throw TestFailedException(); +} +void TestsListener::testHasThrown() +{ + if(gUseTeamCity) + { + gTeamCityListener.addFailure(JetBrains::TestFailure(*(theInstance()._currentTestName), "", JetBrains::SourceLine(), "Exception")); + gTeamCityListener.endTest(*(theInstance()._currentTestName)); + } + std::cout << "E"; + theInstance()._exceptions++; +} +std::string TestsListener::summary() +{ + std::ostringstream os; + os << "\nSummary:\n" + << Assert::bold() << "\tExecuted Tests: " + << _executed << Assert::normal() << std::endl + << Assert::green() << "\tPassed Tests: " + << (_executed-_failed-_exceptions) + << Assert::normal() << std::endl; + if (_failed > 0) + { + os << Assert::red() << "\tFailed Tests: " + << _failed << Assert::normal() << std::endl; + } + if (_exceptions > 0) + { + os << Assert::yellow() << "\tUnexpected exceptions: " + << _exceptions << Assert::normal() << std::endl; + } + os << std::endl; + return os.str(); +} +bool TestsListener::allTestsPassed() +{ + return !theInstance()._exceptions && !theInstance()._failed; +} + + + +void Assert::assertTrue(char* strExpression, bool expression, + const char* file, int linia) +{ + if (!expression) + { + TestsListener::theInstance().errorsLog() << "\n" + << errmsgTag_testFailedIn() << file + << errmsgTag_inLine() << linia << "\n" + << errmsgTag_failedExpression() + << bold() << strExpression << normal() << "\n"; + TestsListener::theInstance().testHasFailed(strExpression, file, linia); + } +} + +void Assert::assertTrueMissatge(char* strExpression, bool expression, + const char* missatge, const char* file, int linia) +{ + if (!expression) + { + TestsListener::theInstance().errorsLog() << "\n" + << errmsgTag_testFailedIn() << file + << errmsgTag_inLine() << linia << "\n" + << errmsgTag_failedExpression() + << bold() << strExpression << "\n" + << missatge<< normal() << "\n"; + TestsListener::theInstance().testHasFailed(strExpression, file, linia); + } +} + + + +void Assert::assertEquals( const char * expected, const char * result, + const char* file, int linia ) +{ + assertEquals(std::string(expected), std::string(result), + file, linia); + +} +void Assert::assertEquals( const bool& expected, const bool& result, + const char* file, int linia ) +{ + assertEquals( + (expected?"true":"false"), + (result?"true":"false"), + file, linia); +} + +// floating point numbers comparisons taken +// from c/c++ users journal. dec 04 pag 10 +bool isNaN(double x) +{ + bool b1 = (x < 0.0); + bool b2 = (x >= 0.0); + return !(b1 || b2); +} + +double scaledEpsilon(const double& expected, const double& fuzzyEpsilon ) +{ + const double aa = fabs(expected)+1; + return (std::isinf(aa))? fuzzyEpsilon: fuzzyEpsilon * aa; +} +bool fuzzyEquals(double expected, double result, double fuzzyEpsilon) +{ + return (expected==result) || ( fabs(expected-result) <= scaledEpsilon(expected, fuzzyEpsilon) ); +} +void Assert::assertEquals( const double& expected, const double& result, + const char* file, int linia ) +{ + const double fuzzyEpsilon = 0.000001; + assertEqualsEpsilon( expected, result, fuzzyEpsilon, file, linia ); +} + +void Assert::assertEquals( const float& expected, const float& result, + const char* file, int linia ) +{ + assertEquals((double)expected, (double)result, file, linia); +} +void Assert::assertEquals( const long double& expected, const long double& result, + const char* file, int linia ) +{ + assertEquals((double)expected, (double)result, file, linia); +} +void Assert::assertEqualsEpsilon( const double& expected, const double& result, const double& epsilon, + const char* file, int linia ) +{ + if (isNaN(expected) && isNaN(result) ) return; + if (!isNaN(expected) && !isNaN(result) && fuzzyEquals(expected, result, epsilon) ) return; + + std::stringstream anError; + anError + << errmsgTag_testFailedIn() << file + << errmsgTag_inLine() << linia << "\n" + << errmsgTag_expected() + << bold() << expected << normal() << " " + << errmsgTag_butWas() + << bold() << result << normal() << "\n"; + + TestsListener::theInstance().errorsLog() << anError.str(); + + TestsListener::theInstance().testHasFailed(anError.str().c_str(), file, linia); +} + +int Assert::notEqualIndex( const std::string & one, const std::string & other ) +{ + int end = MIN(one.length(), other.length()); + for ( int index = 0; index < end; index++ ) + if (one[index] != other[index] ) + return index; + return end; +} + + +/** + * we overload the assert with string doing colored diffs + * + * MS Visual6 doesn't allow string by reference :-( + */ +void Assert::assertEquals( const std::string expected, const std::string result, + const char* file, int linia ) +{ + if(expected == result) + return; + + int indexDiferent = notEqualIndex(expected, result); + + std::stringstream anError; + anError + << file << ", linia: " << linia << "\n" + << errmsgTag_expected() << "\n" << blue() + << expected.substr(0,indexDiferent) + << green() << expected.substr(indexDiferent) + << normal() << "\n" + << errmsgTag_butWas() << blue() << "\n" + << result.substr(0,indexDiferent) + << red() << result.substr(indexDiferent) + << normal() << std::endl; + + TestsListener::theInstance().errorsLog() << anError.str(); + + TestsListener::theInstance().testHasFailed(anError.str().c_str(), file, linia); +} +void Assert::fail(const char* motiu, const char* file, int linia) +{ + TestsListener::theInstance().errorsLog() << + file << errmsgTag_inLine() << linia << "\n" << + "Reason: " << motiu << "\n"; + + TestsListener::theInstance().testHasFailed(motiu, file, linia); +} + + diff --git a/spine-cpp/spine-cpp-unit-tests/minicppunit/MiniCppUnit.hxx b/spine-cpp/spine-cpp-unit-tests/minicppunit/MiniCppUnit.hxx new file mode 100755 index 000000000..7ce3d8fd6 --- /dev/null +++ b/spine-cpp/spine-cpp-unit-tests/minicppunit/MiniCppUnit.hxx @@ -0,0 +1,504 @@ +/* + * Copyright (c) 2003-2004 Pau Arum� & David Garc�a + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef MiniCppUnit_hxx +#define MiniCppUnit_hxx + +/** + * @mainpage + * miniCppUnit + * (C) 2003-2006 Pau Arumi & David Garcia + * + * @version 2.5 2006-03-14 + * - MS Visual compatibility: SConstruct ccflags, usage example, #ifdefs + * @version 2.4 2006-03-14 + * - exit test case after first failure + * - double and float comparison with fuzzy equals (using scalable epsilon) + * - have into account not a numbers + * - new ASSERT_EQUALS_EPSILON macro + * - more colors, and disabled when comiled in MS Visual + * - removed catalan location. + * - UsageExample.cxx now uses all macros and features + * @version 2.3 2006-02-13 added usage example and SConstruct + * @version 2.2 2004-11-28 code in english and tests suites + * @version 2.1 2004-11-04 char* especialization + * @version 2.0 2004-10-26 TestsFactory + * @version 1.0 2003-10-28 initial + * + * Example of use: + * + * @code + * #include "MiniCppUnit.hxx" + * class MyTests : public TestFixture + * { + * public: + * TEST_FIXTURE( MyTests ) + * { + * CAS_DE_TEST( testAddition ); + * // etc + * } + * void testAddition() + * { + * ASSERT_EQUALS( 4, 1+1+2 ); + * } + * // etc + * }; + * + * REGISTER_FIXTURE( MyTests ); + * @endcode + * @code + * int main() + * { + * return TestFixtureFactory::theInstance().runTests() ? 0 : -1; + * } + * @endcode + * Good things: + * + * - it's a tiny framework made up of two or three src files. + * => no need to install as a library + * - object oriented and makes use of several GoF patterns + * - very simple usage. Just needs to learn very few C macros + * - string asserts are simpler to use than cppunit + * - string asserts are enhanced with coloured diffs + * - concrete test classes are totally decoupled via static factory + * => no src file have to include them all. + * - it have test suite hierarchies + * - compatible with non-standard compliant VisualC6 + * (though not necessary good ;) + */ + +#include +#include +#include +#include + +#if _MSC_VER < 1300 +/** necesary for Visual 6 which don't define std::min */ +namespace std +{ + template T min(const T& a, const T& b) { return a < b ? a: b; } +} +#endif + +#include "../teamcity/teamcity_cppunit.h" + +extern JetBrains::TeamcityProgressListener gTeamCityListener; + +/** + * A singleton class. + * Receives tests results and stores messages to the test log + * for later listing. + * It's a singleton for an easy global access from the 'Asserts' + * methods but it is probably asking for a refactoring in order to limit + * access only to TestFixtures + */ +class TestsListener +{ +public: + /** accessor to the global (static) singleton instance */ + static TestsListener& theInstance(); + std::stringstream& errorsLog(); + std::string logString(); + void currentTestName( std::string& name); + static void testHasRun(); + static void testHasPassed(); + static void testHasFailed(const char* reason, const char* file, int line); + static void testHasThrown(); + /** the human readable summary of run tests*/ + std::string summary(); + /** returns wheather all run tests have passed */ + static bool allTestsPassed(); + +private: + static const char* errmsgTag_nameOfTest() { return "Test failed: "; } + + /** constructor private: force the singleton to be wellbehaved ! */ + TestsListener(); + + std::string* _currentTestName; + std::stringstream _log; + unsigned _executed; + unsigned _failed; + unsigned _exceptions; +}; + +class TestFailedException +{ +}; + +/** + * Abstract class with interface that allows run a test. That is runTest + * and name. It is implemented by TestFixture and TestCase + * + * It does the 'Component' role in the 'Composite' patten + **/ +class Test +{ +public: + virtual ~Test(){} + /** run the test: exercice the code and check results*/ + virtual void runTest() = 0; + /** the test human-readable name */ + virtual std::string name() const = 0; +}; + + +/** + * This class is just a placeholder for all assert functions --as static methods. + * It is meant for being used just by the assert macros + */ +class Assert +{ + static const char * errmsgTag_testFailedIn() { return "Test failed in "; } + static const char * errmsgTag_inLine() { return ", line: "; }; + static const char * errmsgTag_failedExpression() { return "Failed expression: "; } + static const char * errmsgTag_expected() { return "Expected: "; } + static const char * errmsgTag_butWas() { return "But was: "; } + +public: +#ifdef _MSC_VER + static const char * blue() { return ""; } + static const char * green() { return ""; } + static const char * red() { return ""; } + static const char * normal() { return ""; } + static const char * bold() { return ""; } + static const char * yellow() { return ""; } +#else + static const char * blue() { return "\033[36;1m"; } + static const char * green() { return "\033[32;1m"; } + static const char * red() { return "\033[31;1m"; } + static const char * normal() { return "\033[0m"; } + static const char * bold() { return "\033[" "1m"; } + static const char * yellow() { return "\033[93;1m"; } +#endif + template + static void assertEquals( const AType& expected, const AType& result, + const char* file="", int linia=0 ) + { + if(expected != result) + { + std::stringstream anError; + + anError + << file << ", linia: " << linia << "\n" + << errmsgTag_expected() << " " << expected << " " + << errmsgTag_butWas() << " " << result << "\n"; + + // TestsListener::theInstance().errorsLog() << anError; + + TestsListener::theInstance().testHasFailed(anError.str().c_str(), file, linia); + } + } + + static void assertTrue(char* strExpression, bool expression, + const char* file="", int linia=0); + + static void assertTrueMissatge(char* strExpression, bool expression, + const char* missatge, const char* file="", int linia=0); + + static void assertEquals( const char * expected, const char * result, + const char* file="", int linia=0 ); + + static void assertEquals( const bool& expected, const bool& result, + const char* file="", int linia=0 ); + + static void assertEquals( const double& expected, const double& result, + const char* file="", int linia=0 ); + + static void assertEquals( const float& expected, const float& result, + const char* file="", int linia=0 ); + + static void assertEquals( const long double& expected, const long double& result, + const char* file="", int linia=0 ); + + static void assertEqualsEpsilon( const double& expected, const double& result, const double& epsilon, + const char* file="", int linia=0 ); + + static int notEqualIndex( const std::string & one, const std::string & other ); + + /** + * we overload the assert with string doing colored diffs + * + * MS Visual6 doesn't allow string by reference :-( + */ + static void assertEquals( const std::string expected, const std::string result, + const char* file="", int linia=0 ); + + static void fail(const char* motiu, const char* file="", int linia=0); + + +}; + +/** + * A TestFixture is a class that contain TestCases --which corresponds to + * ConcreteTestFixture methods-- common objects uder tests, and setUp and + * tearDown methods which are automatically executed before and after each + * test case. + * + * Is the base class of ConcreteFixtures implemented by the framework user + * + * It does the 'Composite' role in the 'Composite' GoF pattern. + * Its composite children are TestCases, which wrapps the test methods. + * + * It is a template class parametrized by ConcreteTestFixture so that it can + * instantiate TestCase objects templatized with this same parameter: it needs the + * concrete class type for calling its non-static methods. + */ +template +class TestFixture : public Test +{ +protected: + + typedef ConcreteTestFixture ConcreteFixture; + typedef void(ConcreteTestFixture::*TestCaseMethod)(); + + /** + * Wrapper for the test methods of concrete TestFixtures. + * + * Makes the 'Leave' role in the 'Composite' GoF pattern because can't be + * be a composition of other tests. + * + * It's also a case of 'Command' pattern because it encapsules in an object + * certain functionality whose execution depends on some deferred entity. + */ + class TestCase : public Test + { + public: + TestCase(ConcreteFixture* parent, TestCaseMethod method, const std::string & name) : + _parent(parent), + _testCaseMethod(method), + _name(name) + { + } + /** calls TestFixture method. setUp and tearDown methods are called by + * its parent TestFixture (in its runTest method). + * it is robust to unexpected exceptions (throw) */ + void runTest() + { + TestsListener::theInstance().testHasRun(); + TestsListener::theInstance().currentTestName(_name); + try + { + (_parent->*_testCaseMethod)(); + TestsListener::theInstance().testHasPassed(); + } + catch( std::exception& error ) + { + TestsListener::theInstance().testHasThrown(); + TestsListener::theInstance().errorsLog() + << "std::exception catched by MiniCppUnit: \n" + << "what() : " + << Assert::yellow() << error.what() + << Assert::normal() << "\n"; + } + catch ( TestFailedException& ) //just for skiping current test case + { + // the assert() calls testHasFailed() + } + catch(...) + { + TestsListener::theInstance().testHasThrown(); + TestsListener::theInstance().errorsLog() + << "non standard exception catched by MiniCppUnit.\n"; + } + } + + /** the TestFixture method hame */ + std::string name() const + { + return _name; + } + + private: + ConcreteFixture* _parent; + TestCaseMethod _testCaseMethod; + std::string _name; + }; + //------------- end of class TestCase ---------------------------- + +private: + + typedef std::list TestCases; + TestCases _testCases; + std::string _name; + + void testsList() const + { + std::cout << "\n+ " << name() << "\n"; + for( TestCases::const_iterator it=_testCases.begin(); + it!=_testCases.end(); it++ ) + std::cout << " - "<< (*it)->name() << "\n"; + } + + +public: + virtual void setUp() {} + virtual void tearDown() {} + + std::string name() const + { + return _name; + }; + + TestFixture(const std::string& name="A text fixture") : _name(name) + { + } + + void afegeixCasDeTest(ConcreteFixture* parent, TestCaseMethod method, const char* name) + { + TestCase* casDeTest = new TestCase(parent, method, _name + "::" + name); + _testCases.push_back( casDeTest ); + } + /** calls each test after setUp and tearDown TestFixture methods */ + void runTest() + { + testsList(); + TestCases::iterator it; + for( it=_testCases.begin(); it!=_testCases.end(); it++) + { + setUp(); + (*it)->runTest(); + tearDown(); + } + } + /** TestCase that wrapps TestFixture methods are dynamically created and owned by + * the TestFixture. So here we clean it up*/ + virtual ~TestFixture() + { + TestCases::iterator it; + for( it =_testCases.begin(); it!=_testCases.end(); it++) + delete (*it); + } +}; + + +/** + * This class is aimed to hold a creator method for each concrete TestFixture + */ +class TestFixtureFactory +{ +private: + /** Well behaved singleton: + * Don't allow instantiation apart from theInstance(), so private ctr.*/ + TestFixtureFactory() + { + } + typedef Test* (*FixtureCreator)(); + std::list _creators; +public: + /** Accessor to the (static) singleton instance */ + static TestFixtureFactory& theInstance() + { + static TestFixtureFactory theFactory; + return theFactory; + } + bool runTests() + { + std::list::iterator it; + for(it=_creators.begin(); it!=_creators.end(); it++) + { + FixtureCreator creator = *it; + Test* test = creator(); + test->runTest(); + delete test; + } + std::string errors = TestsListener::theInstance().logString(); + if (errors!="") std::cout << "\n\nError Details:\n" << errors; + std::cout << TestsListener::theInstance().summary(); + + return TestsListener::theInstance().allTestsPassed(); + } + void addFixtureCreator(FixtureCreator creator) + { + _creators.push_back( creator ); + } + +}; + +/** + * Macro a usar despr�s de cada classe de test + */ +#define REGISTER_FIXTURE( ConcreteTestFixture ) \ +\ +Test* Creador##ConcreteTestFixture() { return new ConcreteTestFixture; } \ +\ +class Registrador##ConcreteTestFixture \ +{ \ +public: \ + Registrador##ConcreteTestFixture() \ + { \ + TestFixtureFactory::theInstance().addFixtureCreator( \ + Creador##ConcreteTestFixture); \ + } \ +}; \ +static Registrador##ConcreteTestFixture estatic##ConcreteTestFixture; + + +/** + * Assert macros to use in test methods. An assert is a test condition + * we want to check. + */ +#define ASSERT_EQUALS( expected, result) \ + Assert::assertEquals( expected, result, __FILE__, __LINE__ ); + +#define ASSERT_EQUALS_EPSILON( expected, result, epsilon) \ + Assert::assertEqualsEpsilon( expected, result, epsilon, __FILE__, __LINE__ ); + +#define ASSERT( exp ) \ + Assert::assertTrue(#exp, exp, __FILE__, __LINE__); + +#define ASSERT_MESSAGE( exp, message ) \ + Assert::assertTrueMissatge(#exp, exp, message, __FILE__, __LINE__); + +#define FAIL( why ) \ + Assert::fail(#why, __FILE__, __LINE__); + +/** + * Macros that allows to write the constructor of the concrete TestFixture. + * What the constructor does is agregate a wrapper for each test case (method) + * As easy to write as this: + * + * @code + * class MyTests : public TestFixture + * { + * public: + * TEST_FIXTURE( MyTests ) + * { + * TEST_CASE( test ); + * // etc + * } + * void test() + * { + * ASSERT_EQUALS( 4, 1+1+2 ); + * } + * @endcode + */ + +#define TEST_FIXTURE( ConcreteFixture ) \ + ConcreteFixture() : TestFixture( #ConcreteFixture ) + +#define TEST_CASE( methodName ) \ + afegeixCasDeTest( this, &ConcreteFixture::methodName, #methodName ); + + + + + +#endif // MiniCppUnit_hxx diff --git a/spine-cpp/spine-cpp-unit-tests/teamcity/README.txt b/spine-cpp/spine-cpp-unit-tests/teamcity/README.txt new file mode 100755 index 000000000..04f7914b9 --- /dev/null +++ b/spine-cpp/spine-cpp-unit-tests/teamcity/README.txt @@ -0,0 +1,30 @@ +CppUnit listener for TeamCity +----------------------------- + +To report your tests result to TeamCity server +include teamcity_messages.* teamcity_cppunit.* +to your project and modify "main" function +as shown in example.cpp +(around JetBrains::underTeamcity and JetBrains::TeamcityProgressListener) + +Technical details +----------------- + +Reporting implemented by writing TeamCity service messages to stdout. + +See +http://www.jetbrains.net/confluence/display/TCD3/Build+Script+Interaction+with+TeamCity +for more details. + +Contact information +------------------- + +Mail to teamcity-feedback@jetbrains.com or see other options at + +http://www.jetbrains.com/support/teamcity + +License +------- + +Apache, version 2.0 +http://www.apache.org/licenses/LICENSE-2.0 diff --git a/spine-cpp/spine-cpp-unit-tests/teamcity/teamcity_cppunit.cpp b/spine-cpp/spine-cpp-unit-tests/teamcity/teamcity_cppunit.cpp new file mode 100755 index 000000000..86f163b9c --- /dev/null +++ b/spine-cpp/spine-cpp-unit-tests/teamcity/teamcity_cppunit.cpp @@ -0,0 +1,82 @@ +/* Copyright 2011 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * $Revision: 88625 $ +*/ + +#include + +#include "teamcity_cppunit.h" + +using namespace std; + +namespace JetBrains { + +TeamcityProgressListener::TeamcityProgressListener() +{ + flowid = getFlowIdFromEnvironment(); +} + +TeamcityProgressListener::TeamcityProgressListener(const std::string& _flowid) +{ + flowid = _flowid; +} + +void TeamcityProgressListener::startTest(const std::string& test) { + messages.testStarted(test, flowid); +} + +static string sourceLine2string(const SourceLine &sline) { + stringstream ss; + + ss << sline.fileName << ":" << sline.lineNumber; + + return ss.str(); +} + +void TeamcityProgressListener::addFailure(const TestFailure &failure) +{ + + string details = failure.details; + + if (failure.sourceLine.isValid()) { + details.append(" at "); + details.append(sourceLine2string(failure.sourceLine)); + details.append("\n"); + } + + messages.testFailed( + failure.testName, + failure.description, + details, + flowid + ); +} + +void TeamcityProgressListener::endTest(const std::string& test) +{ + messages.testFinished(test, -1, flowid); +} + +void TeamcityProgressListener::startSuite(const std::string& test) +{ + messages.suiteStarted(test, flowid); +} + +void TeamcityProgressListener::endSuite(const std::string& test) +{ + messages.suiteFinished(test, flowid); +} + +} diff --git a/spine-cpp/spine-cpp-unit-tests/teamcity/teamcity_cppunit.h b/spine-cpp/spine-cpp-unit-tests/teamcity/teamcity_cppunit.h new file mode 100755 index 000000000..7541a5186 --- /dev/null +++ b/spine-cpp/spine-cpp-unit-tests/teamcity/teamcity_cppunit.h @@ -0,0 +1,83 @@ +/* Copyright 2011 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * $Revision: 88625 $ +*/ + +#pragma once + +#include + +#include "teamcity_messages.h" + +namespace JetBrains { + + class SourceLine + { + public: + SourceLine():lineNumber(-1){} + SourceLine(const std::string& theFile, int theLineNum):fileName(theFile),lineNumber(theLineNum){} + ~SourceLine(){} + + std::string fileName; + int lineNumber; + bool isValid() const {return (!fileName.empty() && lineNumber > -1);} + }; + + class TestFailure + { + public: + std::string details; + SourceLine sourceLine; + std::string testName; + std::string description; + public: + TestFailure(){} + ~TestFailure(){} + + TestFailure(const std::string& theTestName, const std::string& theDetails, SourceLine theSourcelLine, const std::string& theDescription) + { + testName = theTestName; + details = theDetails; + sourceLine = theSourcelLine; + description = theDescription; + } + }; + + class TeamcityProgressListener + { + public: + TeamcityMessages messages; + public: + TeamcityProgressListener(const std::string& _flowid); + TeamcityProgressListener(); + ~TeamcityProgressListener(){} + + void startTest(const std::string& test); + void addFailure(const TestFailure &failure); + void endTest(const std::string& test); + void startSuite(const std::string& test); + void endSuite(const std::string& test); + + private: + std::string flowid; + + // Prevents the use of the copy constructor. + TeamcityProgressListener(const TeamcityProgressListener ©); + + // Prevents the use of the copy operator. + void operator =(const TeamcityProgressListener ©); + }; + +} \ No newline at end of file diff --git a/spine-cpp/spine-cpp-unit-tests/teamcity/teamcity_messages.cpp b/spine-cpp/spine-cpp-unit-tests/teamcity/teamcity_messages.cpp new file mode 100755 index 000000000..6f88d1ee9 --- /dev/null +++ b/spine-cpp/spine-cpp-unit-tests/teamcity/teamcity_messages.cpp @@ -0,0 +1,174 @@ +/* Copyright 2011 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * $Revision: 88625 $ +*/ + +#include +#include + +#include "teamcity_messages.h" + +using namespace std; + +namespace JetBrains { + +std::string getFlowIdFromEnvironment() { + const char *flowId = getenv("TEAMCITY_PROCESS_FLOW_ID"); + return flowId == NULL ? "" : flowId; +} + +bool underTeamcity() { + return getenv("TEAMCITY_PROJECT_NAME") != NULL; +} + +TeamcityMessages::TeamcityMessages() +: m_out(&cout) +{} + +void TeamcityMessages::setOutput(ostream &out) { + m_out = &out; +} + +string TeamcityMessages::escape(string s) { + string result; + + for (size_t i = 0; i < s.length(); i++) { + char c = s[i]; + + switch (c) { + case '\n': result.append("|n"); break; + case '\r': result.append("|r"); break; + case '\'': result.append("|'"); break; + case '|': result.append("||"); break; + case ']': result.append("|]"); break; + default: result.append(&c, 1); + } + } + + return result; +} + +void TeamcityMessages::openMsg(const string &name) { + // endl for http://jetbrains.net/tracker/issue/TW-4412 + *m_out << endl << "##teamcity[" << name; +} + +void TeamcityMessages::closeMsg() { + *m_out << "]"; + // endl for http://jetbrains.net/tracker/issue/TW-4412 + *m_out << endl; + m_out->flush(); +} + +void TeamcityMessages::writeProperty(string name, string value) { + *m_out << " " << name << "='" << escape(value) << "'"; +} + +void TeamcityMessages::suiteStarted(string name, string flowid) { + openMsg("testSuiteStarted"); + writeProperty("name", name); + if(flowid.length() > 0) { + writeProperty("flowId", flowid); + } + + closeMsg(); +} + +void TeamcityMessages::suiteFinished(string name, string flowid) { + openMsg("testSuiteFinished"); + writeProperty("name", name); + if(flowid.length() > 0) { + writeProperty("flowId", flowid); + } + + closeMsg(); +} + +void TeamcityMessages::testStarted(string name, string flowid) { + openMsg("testStarted"); + writeProperty("name", name); + if(flowid.length() > 0) { + writeProperty("flowId", flowid); + } + + closeMsg(); +} + +void TeamcityMessages::testFinished(string name, int durationMs, string flowid) { + openMsg("testFinished"); + + writeProperty("name", name); + + if(flowid.length() > 0) { + writeProperty("flowId", flowid); + } + + if(durationMs >= 0) { + stringstream out; + out << durationMs; + writeProperty("duration", out.str()); + } + + closeMsg(); +} + +void TeamcityMessages::testFailed(string name, string message, string details, string flowid) { + openMsg("testFailed"); + writeProperty("name", name); + writeProperty("message", message); + writeProperty("details", details); + if(flowid.length() > 0) { + writeProperty("flowId", flowid); + } + + closeMsg(); +} + +void TeamcityMessages::testIgnored(std::string name, std::string message, string flowid) { + openMsg("testIgnored"); + writeProperty("name", name); + writeProperty("message", message); + if(flowid.length() > 0) { + writeProperty("flowId", flowid); + } + + closeMsg(); +} + +void TeamcityMessages::messageError(const std::string& text) +{ + openMsg("message"); + writeProperty("text", text); + writeProperty("status", "ERROR"); + closeMsg(); +} + +void TeamcityMessages::messageWarning(const std::string& text) +{ + openMsg("message"); + writeProperty("text", text); + writeProperty("status", "WARNING"); + closeMsg(); +} + +void TeamcityMessages::messageNormal(const std::string& text) +{ + openMsg("message"); + writeProperty("text", text); + writeProperty("status", "NORMAL"); + closeMsg(); +} + +} diff --git a/spine-cpp/spine-cpp-unit-tests/teamcity/teamcity_messages.h b/spine-cpp/spine-cpp-unit-tests/teamcity/teamcity_messages.h new file mode 100755 index 000000000..36ad80797 --- /dev/null +++ b/spine-cpp/spine-cpp-unit-tests/teamcity/teamcity_messages.h @@ -0,0 +1,59 @@ +/* Copyright 2011 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * $Revision: 88625 $ +*/ + +#ifndef H_TEAMCITY_MESSAGES +#define H_TEAMCITY_MESSAGES + +#include +#include + +namespace JetBrains { + +std::string getFlowIdFromEnvironment(); +bool underTeamcity(); + +class TeamcityMessages { + std::ostream *m_out; + +protected: + std::string escape(std::string s); + + void openMsg(const std::string &name); + void writeProperty(std::string name, std::string value); + void closeMsg(); + +public: + TeamcityMessages(); + + void setOutput(std::ostream &); + + void suiteStarted(std::string name, std::string flowid = ""); + void suiteFinished(std::string name, std::string flowid = ""); + + void testStarted(std::string name, std::string flowid = ""); + void testFailed(std::string name, std::string message, std::string details, std::string flowid = ""); + void testIgnored(std::string name, std::string message, std::string flowid = ""); + void testFinished(std::string name, int durationMs = -1, std::string flowid = ""); + + void messageError(const std::string& text); + void messageWarning(const std::string& text); + void messageNormal(const std::string& text); +}; + +} + +#endif /* H_TEAMCITY_MESSAGES */ diff --git a/spine-cpp/spine-cpp-unit-tests/tests/CPP_InterfaceTestFixture.cpp b/spine-cpp/spine-cpp-unit-tests/tests/CPP_InterfaceTestFixture.cpp new file mode 100755 index 000000000..dde75c363 --- /dev/null +++ b/spine-cpp/spine-cpp-unit-tests/tests/CPP_InterfaceTestFixture.cpp @@ -0,0 +1,48 @@ +////////////////////////////////////////////////////////////////////// +// filename: C_InterfaceTestFixture.cpp +// +// notes: There is no C++ interface! +// +///////////////////////////////////////////////////////////////////// + +#include "CPP_InterfaceTestFixture.h" + +CPP_InterfaceTestFixture::~CPP_InterfaceTestFixture() +{ + finalize(); +} + +void CPP_InterfaceTestFixture::initialize() +{ + // on a Per- Fixture Basis, before Test execution +} + +void CPP_InterfaceTestFixture::finalize() +{ + // on a Per- Fixture Basis, after all tests pass/fail +} + +void CPP_InterfaceTestFixture::setUp() +{ + // Setup on Per-Test Basis +} + +void CPP_InterfaceTestFixture::tearDown() +{ + // Tear Down on Per-Test Basis +} + +void CPP_InterfaceTestFixture::spineboyTestCase() +{ + // There is no C++ interface. +} + +void CPP_InterfaceTestFixture::raptorTestCase() +{ + // There is no C++ interface. +} + +void CPP_InterfaceTestFixture::goblinsTestCase() +{ + // No c++ interface +} diff --git a/spine-cpp/spine-cpp-unit-tests/tests/CPP_InterfaceTestFixture.h b/spine-cpp/spine-cpp-unit-tests/tests/CPP_InterfaceTestFixture.h new file mode 100755 index 000000000..8dc5fed36 --- /dev/null +++ b/spine-cpp/spine-cpp-unit-tests/tests/CPP_InterfaceTestFixture.h @@ -0,0 +1,47 @@ +#pragma once +////////////////////////////////////////////////////////////////////// +// filename: C_InterfaceTestFixture.h +// +// purpose: Run example animations for regression testing +// on "C++" interface to make sure modifications to "C" +// interface doesn't cause memory leaks or regression +// errors. +///////////////////////////////////////////////////////////////////// + +#include "MiniCppUnit.hxx" +#include "TestOptions.h" + +class CPP_InterfaceTestFixture : public TestFixture < CPP_InterfaceTestFixture > +{ +public: + TEST_FIXTURE(CPP_InterfaceTestFixture){ + TEST_CASE(spineboyTestCase); + TEST_CASE(raptorTestCase); + TEST_CASE(goblinsTestCase); + + initialize(); + } + + virtual ~CPP_InterfaceTestFixture(); + + ////////////////////////////////////////////////////////////////////////// + // Test Cases + ////////////////////////////////////////////////////////////////////////// +public: + void spineboyTestCase(); + void raptorTestCase(); + void goblinsTestCase(); + + ////////////////////////////////////////////////////////////////////////// + // test fixture setup + ////////////////////////////////////////////////////////////////////////// + void initialize(); + void finalize(); +public: + virtual void setUp(); + virtual void tearDown(); + +}; +#if defined(gForceAllTests) || defined(gCPPInterfaceTestFixture) +REGISTER_FIXTURE(CPP_InterfaceTestFixture); +#endif diff --git a/spine-cpp/spine-cpp-unit-tests/tests/C_InterfaceTestFixture.cpp b/spine-cpp/spine-cpp-unit-tests/tests/C_InterfaceTestFixture.cpp new file mode 100755 index 000000000..2c1cb61bc --- /dev/null +++ b/spine-cpp/spine-cpp-unit-tests/tests/C_InterfaceTestFixture.cpp @@ -0,0 +1,175 @@ +#include "C_InterfaceTestFixture.h" +#include "SpineEventMonitor.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include + +#include "KMemory.h" // last include + +#define SPINEBOY_JSON "testdata/spineboy/spineboy-ess.json" +#define SPINEBOY_ATLAS "testdata/spineboy/spineboy.atlas" + +#define RAPTOR_JSON "testdata/raptor/raptor-pro.json" +#define RAPTOR_ATLAS "testdata/raptor/raptor.atlas" + +#define GOBLINS_JSON "testdata/goblins/goblins-pro.json" +#define GOBLINS_ATLAS "testdata/goblins/goblins.atlas" + +#define MAX_RUN_TIME 6000 // equal to about 100 seconds of execution + +using namespace Spine; + +void C_InterfaceTestFixture::setUp() +{ +} + +void C_InterfaceTestFixture::tearDown() +{ +} + +static SkeletonData* readSkeletonJsonData(const char* filename, Atlas* atlas) +{ + Vector atlasArray; + atlasArray.push_back(atlas); + + SkeletonJson* skeletonJson = NEW(SkeletonJson); + new (skeletonJson) SkeletonJson(atlasArray); + ASSERT(skeletonJson != 0); + + SkeletonData* skeletonData = skeletonJson->readSkeletonDataFile(filename); + ASSERT(skeletonData != 0); + + DESTROY(SkeletonJson, skeletonJson); + + return skeletonData; +} + +typedef std::vector AnimList; + +static size_t enumerateAnimations(AnimList& outList, SkeletonData* skeletonData) +{ + if (skeletonData) + { + for (int n = 0; n < skeletonData->getAnimations().size(); n++) + { + outList.push_back(skeletonData->getAnimations()[n]->getName()); + } + } + + return outList.size(); +} + +class MyTextureLoader : public TextureLoader +{ + virtual void load(AtlasPage& page, std::string path) + { + page.rendererObject = NULL; + page.width = 2048; + page.height = 2048; + } + + virtual void unload(void* texture) + { + // TODO + } +}; + +static void testRunner(const char* jsonName, const char* atlasName) +{ + /////////////////////////////////////////////////////////////////////////// + // Global Animation Information + MyTextureLoader myTextureLoader; + Atlas* atlas = NEW(Atlas); + new (atlas) Atlas(atlasName, myTextureLoader); + ASSERT(atlas != 0); + + SkeletonData* skeletonData = readSkeletonJsonData(jsonName, atlas); + ASSERT(skeletonData != 0); + + AnimationStateData* stateData = NEW(AnimationStateData); + new (stateData) AnimationStateData(skeletonData); + ASSERT(stateData != 0); + stateData->setDefaultMix(0.2f); // force mixing + + /////////////////////////////////////////////////////////////////////////// + // Animation Instance + Skeleton* skeleton = NEW(Skeleton); + new (skeleton) Skeleton(skeletonData); + ASSERT(skeleton != 0); + + AnimationState* state = NEW(AnimationState); + new (state) AnimationState(stateData); + ASSERT(state != 0); + + /////////////////////////////////////////////////////////////////////////// + // Run animation + skeleton->setToSetupPose(); + SpineEventMonitor eventMonitor(state); + + AnimList anims; // Let's chain all the animations together as a test + size_t count = enumerateAnimations(anims, skeletonData); + if (count > 0) + { + state->setAnimation(0, anims[0].c_str(), false); + } + + for (size_t i = 1; i < count; ++i) + { + state->addAnimation(0, anims[i].c_str(), false, 0.0f); + } + + // Run Loop + for (int i = 0; i < MAX_RUN_TIME && eventMonitor.isAnimationPlaying(); ++i) + { + const float timeSlice = 1.0f / 60.0f; + skeleton->update(timeSlice); + state->update(timeSlice); + state->apply(*skeleton); + } + + /////////////////////////////////////////////////////////////////////////// + // Dispose Instance + DESTROY(Skeleton, skeleton); + DESTROY(AnimationState, state); + + /////////////////////////////////////////////////////////////////////////// + // Dispose Global + DESTROY(AnimationStateData, stateData); + DESTROY(SkeletonData, skeletonData); + DESTROY(Atlas, atlas); +} + +void C_InterfaceTestFixture::spineboyTestCase() +{ + testRunner(SPINEBOY_JSON, SPINEBOY_ATLAS); +} + +void C_InterfaceTestFixture::raptorTestCase() +{ + testRunner(RAPTOR_JSON, RAPTOR_ATLAS); +} + +void C_InterfaceTestFixture::goblinsTestCase() +{ + testRunner(GOBLINS_JSON, GOBLINS_ATLAS); +} diff --git a/spine-cpp/spine-cpp-unit-tests/tests/C_InterfaceTestFixture.h b/spine-cpp/spine-cpp-unit-tests/tests/C_InterfaceTestFixture.h new file mode 100755 index 000000000..2f30d2bea --- /dev/null +++ b/spine-cpp/spine-cpp-unit-tests/tests/C_InterfaceTestFixture.h @@ -0,0 +1,33 @@ +#pragma once +////////////////////////////////////////////////////////////////////// +// filename: C_InterfaceTestFixture.h +// +// purpose: Run example animations for regression testing +// on "C" interface +///////////////////////////////////////////////////////////////////// + +#include "TestOptions.h" +#include "MiniCppUnit.hxx" + +class C_InterfaceTestFixture : public TestFixture +{ +public: + TEST_FIXTURE(C_InterfaceTestFixture) + { + // enable/disable individual tests here + TEST_CASE(spineboyTestCase); + TEST_CASE(raptorTestCase); + TEST_CASE(goblinsTestCase); + } + +public: + virtual void setUp(); + virtual void tearDown(); + + void spineboyTestCase(); + void raptorTestCase(); + void goblinsTestCase(); +}; +#if defined(gForceAllTests) || defined(gCInterfaceTestFixture) +REGISTER_FIXTURE(C_InterfaceTestFixture); +#endif \ No newline at end of file diff --git a/spine-cpp/spine-cpp-unit-tests/tests/EmptyTestFixture.cpp b/spine-cpp/spine-cpp-unit-tests/tests/EmptyTestFixture.cpp new file mode 100755 index 000000000..d2260b7d5 --- /dev/null +++ b/spine-cpp/spine-cpp-unit-tests/tests/EmptyTestFixture.cpp @@ -0,0 +1,25 @@ +#include "EmptyTestFixture.h" + +#include "KMemory.h" // Last include + + +void EmptyTestFixture::setUp() +{ +} + +void EmptyTestFixture::tearDown() +{ +} + +void EmptyTestFixture::emptyTestCase_1() +{ + // char* pLeak = new char[256]; // test leak detector +} + +void EmptyTestFixture::emptyTestCase_2() +{ +} + +void EmptyTestFixture::emptyTestCase_3() +{ +} diff --git a/spine-cpp/spine-cpp-unit-tests/tests/EmptyTestFixture.h b/spine-cpp/spine-cpp-unit-tests/tests/EmptyTestFixture.h new file mode 100755 index 000000000..c11cfd5f2 --- /dev/null +++ b/spine-cpp/spine-cpp-unit-tests/tests/EmptyTestFixture.h @@ -0,0 +1,26 @@ +#pragma once +#include "TestOptions.h" +#include "MiniCppUnit.hxx" + +class EmptyTestFixture : public TestFixture +{ +public: + TEST_FIXTURE(EmptyTestFixture) + { + // enable/disable individual tests here + TEST_CASE(emptyTestCase_1); + TEST_CASE(emptyTestCase_2); + TEST_CASE(emptyTestCase_3); + } + +public: + virtual void setUp(); + virtual void tearDown(); + + void emptyTestCase_1(); + void emptyTestCase_2(); + void emptyTestCase_3(); +}; +#if defined(gForceAllTests) || defined(gEmptyTestFixture) +REGISTER_FIXTURE(EmptyTestFixture); +#endif \ No newline at end of file diff --git a/spine-cpp/spine-cpp-unit-tests/tests/MemoryTestFixture.cpp b/spine-cpp/spine-cpp-unit-tests/tests/MemoryTestFixture.cpp new file mode 100755 index 000000000..a59822a43 --- /dev/null +++ b/spine-cpp/spine-cpp-unit-tests/tests/MemoryTestFixture.cpp @@ -0,0 +1,338 @@ +//#include +//#include "MemoryTestFixture.h" +//#include "SpineEventMonitor.h" +// +//#include "KMemory.h" // last include +// +//#define SPINEBOY_JSON "testdata/spineboy/spineboy-ess.json" +//#define SPINEBOY_ATLAS "testdata/spineboy/spineboy.atlas" +// +//#define MAX_RUN_TIME 6000 // equal to about 100 seconds of execution +// +//MemoryTestFixture::~MemoryTestFixture() +//{ +// finalize(); +//} +// +//void MemoryTestFixture::initialize() +//{ +// // on a Per- Fixture Basis, before Test execution +//} +// +//void MemoryTestFixture::finalize() +//{ +// // on a Per- Fixture Basis, after all tests pass/fail +//} +// +//void MemoryTestFixture::setUp() +//{ +// // Setup on Per-Test Basis +//} +// +//void MemoryTestFixture::tearDown() +//{ +// // Tear Down on Per-Test Basis +//} +// +// +//////////////////////////////////////////////////////////////////////////// +//// Helper methods +//static spSkeletonData* readSkeletonJsonData(const char* filename, spAtlas* atlas) { +// spSkeletonJson* json = spSkeletonJson_create(atlas); +// ASSERT(json != 0); +// +// spSkeletonData* skeletonData = spSkeletonJson_readSkeletonDataFile(json, filename); +// ASSERT(skeletonData != 0); +// +// spSkeletonJson_dispose(json); +// return skeletonData; +//} +// +//static void LoadSpineboyExample(spAtlas* &atlas, spSkeletonData* &skeletonData, spAnimationStateData* &stateData, spSkeleton* &skeleton, spAnimationState* &state) +//{ +// /////////////////////////////////////////////////////////////////////////// +// // Global Animation Information +// atlas = spAtlas_createFromFile(SPINEBOY_ATLAS, 0); +// ASSERT(atlas != 0); +// +// skeletonData = readSkeletonJsonData(SPINEBOY_JSON, atlas); +// ASSERT(skeletonData != 0); +// +// stateData = spAnimationStateData_create(skeletonData); +// ASSERT(stateData != 0); +// stateData->defaultMix = 0.4f; // force mixing +// +// /////////////////////////////////////////////////////////////////////////// +// // Animation Instance +// skeleton = spSkeleton_create(skeletonData); +// ASSERT(skeleton != 0); +// +// state = spAnimationState_create(stateData); +// ASSERT(state != 0); +//} +// +//static void DisposeAll(spSkeleton* skeleton, spAnimationState* state, spAnimationStateData* stateData, spSkeletonData* skeletonData, spAtlas* atlas) +//{ +// /////////////////////////////////////////////////////////////////////////// +// // Dispose Instance +// spSkeleton_dispose(skeleton); +// spAnimationState_dispose(state); +// +// /////////////////////////////////////////////////////////////////////////// +// // Dispose Global +// spAnimationStateData_dispose(stateData); +// spSkeletonData_dispose(skeletonData); +// spAtlas_dispose(atlas); +//} +// +// +//////////////////////////////////////////////////////////////////////////// +//// Reproduce Memory leak as described in Issue #776 +//// https://github.com/EsotericSoftware/spine-runtimes/issues/776 +//void MemoryTestFixture::reproduceIssue_776() +//{ +// spAtlas* atlas = 0; +// spSkeletonData* skeletonData = 0; +// spAnimationStateData* stateData = 0; +// spSkeleton* skeleton = 0; +// spAnimationState* state = 0; +// +// ////////////////////////////////////////////////////////////////////////// +// // Initialize Animations +// LoadSpineboyExample(atlas, skeletonData, stateData, skeleton, state); +// +// /////////////////////////////////////////////////////////////////////////// +// // Run animation +// spSkeleton_setToSetupPose(skeleton); +// InterruptMonitor eventMonitor(state); +// //eventMonitor.SetDebugLogging(true); +// +// // Interrupt the animation on this specific sequence of spEventType(s) +// eventMonitor +// .AddInterruptEvent(SP_ANIMATION_INTERRUPT, "jump") +// .AddInterruptEvent(SP_ANIMATION_START); +// +// spAnimationState_setAnimationByName(state, 0, "walk", true); +// spAnimationState_addAnimationByName(state, 0, "jump", false, 0.0f); +// spAnimationState_addAnimationByName(state, 0, "run", true, 0.0f); +// spAnimationState_addAnimationByName(state, 0, "jump", false, 3.0f); +// spAnimationState_addAnimationByName(state, 0, "walk", true, 0.0f); +// spAnimationState_addAnimationByName(state, 0, "idle", false, 1.0f); +// +// for (int i = 0; i < MAX_RUN_TIME && eventMonitor.isAnimationPlaying(); ++i) { +// const float timeSlice = 1.0f / 60.0f; +// spSkeleton_update(skeleton, timeSlice); +// spAnimationState_update(state, timeSlice); +// spAnimationState_apply(state, skeleton); +// } +// +// ////////////////////////////////////////////////////////////////////////// +// // Cleanup Animations +// DisposeAll(skeleton, state, stateData, skeletonData, atlas); +//} +// +//void MemoryTestFixture::reproduceIssue_777() +//{ +// spAtlas* atlas = 0; +// spSkeletonData* skeletonData = 0; +// spAnimationStateData* stateData = 0; +// spSkeleton* skeleton = 0; +// spAnimationState* state = 0; +// +// ////////////////////////////////////////////////////////////////////////// +// // Initialize Animations +// LoadSpineboyExample(atlas, skeletonData, stateData, skeleton, state); +// +// /////////////////////////////////////////////////////////////////////////// +// // Run animation +// spSkeleton_setToSetupPose(skeleton); +// SpineEventMonitor eventMonitor(state); +// //eventMonitor.SetDebugLogging(true); +// +// // Set Animation and Play for 5 frames +// spAnimationState_setAnimationByName(state, 0, "walk", true); +// for (int i = 0; i < 5; ++i) { +// const float timeSlice = 1.0f / 60.0f; +// spSkeleton_update(skeleton, timeSlice); +// spAnimationState_update(state, timeSlice); +// spAnimationState_apply(state, skeleton); +// } +// +// // Change animation twice in a row +// spAnimationState_setAnimationByName(state, 0, "walk", false); +// spAnimationState_setAnimationByName(state, 0, "run", false); +// +// // run normal update +// for (int i = 0; i < 5; ++i) { +// const float timeSlice = 1.0f / 60.0f; +// spSkeleton_update(skeleton, timeSlice); +// spAnimationState_update(state, timeSlice); +// spAnimationState_apply(state, skeleton); +// } +// +// // Now we'd lose mixingFrom (the first "walk" entry we set above) and should leak +// spAnimationState_setAnimationByName(state, 0, "run", false); +// +// ////////////////////////////////////////////////////////////////////////// +// // Cleanup Animations +// DisposeAll(skeleton, state, stateData, skeletonData, atlas); +//} +// +//spSkeleton* skeleton = 0; +//static void spineAnimStateHandler(spAnimationState* state, int type, spTrackEntry* entry, spEvent* event) +//{ +// if (type == SP_ANIMATION_COMPLETE) +// { +// spAnimationState_setAnimationByName(state, 0, "walk", false); +// spAnimationState_update(state, 0); +// spAnimationState_apply(state, skeleton); +// } +//} +// +//void MemoryTestFixture::reproduceIssue_Loop() +//{ +// spAtlas* atlas = 0; +// spSkeletonData* skeletonData = 0; +// spAnimationStateData* stateData = 0; +// spAnimationState* state = 0; +// +// ////////////////////////////////////////////////////////////////////////// +// // Initialize Animations +// LoadSpineboyExample(atlas, skeletonData, stateData, skeleton, state); +// +// /////////////////////////////////////////////////////////////////////////// +// +// if (state) +// state->listener = (spAnimationStateListener)&spineAnimStateHandler; +// +// spAnimationState_setAnimationByName(state, 0, "walk", false); +// +// // run normal update +// for (int i = 0; i < 50; ++i) { +// const float timeSlice = 1.0f / 60.0f; +// spSkeleton_update(skeleton, timeSlice); +// spAnimationState_update(state, timeSlice); +// spAnimationState_apply(state, skeleton); +// } +// +// DisposeAll(skeleton, state, stateData, skeletonData, atlas); +//} +// +//void MemoryTestFixture::triangulator() { +// spTriangulator* triangulator = spTriangulator_create(); +// spFloatArray* polygon = spFloatArray_create(16); +// spFloatArray_add(polygon, 0); +// spFloatArray_add(polygon, 0); +// spFloatArray_add(polygon, 100); +// spFloatArray_add(polygon, 0); +// spFloatArray_add(polygon, 100); +// spFloatArray_add(polygon, 100); +// spFloatArray_add(polygon, 0); +// spFloatArray_add(polygon, 100); +// +// spShortArray* triangles = spTriangulator_triangulate(triangulator, polygon); +// ASSERT(triangles->size == 6); +// ASSERT(triangles->items[0] == 3); +// ASSERT(triangles->items[1] == 0); +// ASSERT(triangles->items[2] == 1); +// ASSERT(triangles->items[3] == 3); +// ASSERT(triangles->items[4] == 1); +// ASSERT(triangles->items[5] == 2); +// +// spArrayFloatArray* polys = spTriangulator_decompose(triangulator, polygon, triangles); +// ASSERT(polys->size == 1); +// ASSERT(polys->items[0]->size == 8); +// ASSERT(polys->items[0]->items[0] == 0); +// ASSERT(polys->items[0]->items[1] == 100); +// ASSERT(polys->items[0]->items[2] == 0); +// ASSERT(polys->items[0]->items[3] == 0); +// ASSERT(polys->items[0]->items[4] == 100); +// ASSERT(polys->items[0]->items[5] == 0); +// ASSERT(polys->items[0]->items[6] == 100); +// ASSERT(polys->items[0]->items[7] == 100); +// +// spFloatArray_dispose(polygon); +// spTriangulator_dispose(triangulator); +//} +// +//void MemoryTestFixture::skeletonClipper() { +// spSkeletonClipping* clipping = spSkeletonClipping_create(); +// +// spBoneData* boneData = spBoneData_create(0, "bone", 0); +// spBone* bone = spBone_create(boneData, 0, 0); +// CONST_CAST(float, bone->a) = 1; +// CONST_CAST(float, bone->b) = 0; +// CONST_CAST(float, bone->c) = 0; +// CONST_CAST(float, bone->d) = 1; +// CONST_CAST(float, bone->worldX) = 0; +// CONST_CAST(float, bone->worldY) = 0; +// spSlotData* slotData = spSlotData_create(0, "slot", 0); +// spSlot* slot = spSlot_create(slotData, bone); +// spClippingAttachment* clip = spClippingAttachment_create("clipping"); +// clip->endSlot = slotData; +// clip->super.worldVerticesLength = 4 * 2; +// clip->super.verticesCount = 4; +// clip->super.vertices = MALLOC(float, 4 * 8); +// clip->super.vertices[0] = 0; +// clip->super.vertices[1] = 50; +// clip->super.vertices[2] = 100; +// clip->super.vertices[3] = 50; +// clip->super.vertices[4] = 100; +// clip->super.vertices[5] = 70; +// clip->super.vertices[6] = 0; +// clip->super.vertices[7] = 70; +// +// spSkeletonClipping_clipStart(clipping, slot, clip); +// +// spFloatArray* vertices = spFloatArray_create(16); +// spFloatArray_add(vertices, 0); +// spFloatArray_add(vertices, 0); +// spFloatArray_add(vertices, 100); +// spFloatArray_add(vertices, 0); +// spFloatArray_add(vertices, 50); +// spFloatArray_add(vertices, 150); +// spFloatArray* uvs = spFloatArray_create(16); +// spFloatArray_add(uvs, 0); +// spFloatArray_add(uvs, 0); +// spFloatArray_add(uvs, 1); +// spFloatArray_add(uvs, 0); +// spFloatArray_add(uvs, 0.5f); +// spFloatArray_add(uvs, 1); +// spUnsignedShortArray* indices = spUnsignedShortArray_create(16); +// spUnsignedShortArray_add(indices, 0); +// spUnsignedShortArray_add(indices, 1); +// spUnsignedShortArray_add(indices, 2); +// +// spSkeletonClipping_clipTriangles(clipping, vertices->items, vertices->size, indices->items, indices->size, uvs->items, 2); +// +// float expectedVertices[8] = { 83.333328, 50.000000, 76.666664, 70.000000, 23.333334, 70.000000, 16.666672, 50.000000 }; +// ASSERT(clipping->clippedVertices->size == 8); +// for (int i = 0; i < clipping->clippedVertices->size; i++) { +// ASSERT(ABS(clipping->clippedVertices->items[i] - expectedVertices[i]) < 0.001); +// } +// +// float expectedUVs[8] = { 0.833333f, 0.333333, 0.766667, 0.466667, 0.233333, 0.466667, 0.166667, 0.333333 }; +// ASSERT(clipping->clippedUVs->size == 8); +// for (int i = 0; i < clipping->clippedUVs->size; i++) { +// ASSERT(ABS(clipping->clippedUVs->items[i] - expectedUVs[i]) < 0.001); +// } +// +// short expectedIndices[6] = { 0, 1, 2, 0, 2, 3 }; +// ASSERT(clipping->clippedTriangles->size == 6); +// for (int i = 0; i < clipping->clippedTriangles->size; i++) { +// ASSERT(clipping->clippedTriangles->items[i] == expectedIndices[i]); +// } +// +// spFloatArray_dispose(vertices); +// spFloatArray_dispose(uvs); +// spUnsignedShortArray_dispose(indices); +// +// spSlotData_dispose(slotData); +// spSlot_dispose(slot); +// spBoneData_dispose(boneData); +// spBone_dispose(bone); +// _spClippingAttachment_dispose(SUPER(SUPER(clip))); +// spSkeletonClipping_dispose(clipping); +//} +// +// diff --git a/spine-cpp/spine-cpp-unit-tests/tests/MemoryTestFixture.h b/spine-cpp/spine-cpp-unit-tests/tests/MemoryTestFixture.h new file mode 100755 index 000000000..f45c35c86 --- /dev/null +++ b/spine-cpp/spine-cpp-unit-tests/tests/MemoryTestFixture.h @@ -0,0 +1,50 @@ +////////////////////////////////////////////////////////////////////// +// filename: MemoryTestFixture.h +// +// purpose: Reproduce Memory Error/Leak Bugs to help debug +// and for regression testing +///////////////////////////////////////////////////////////////////// + +#pragma once +#include "MiniCppUnit.hxx" +#include "TestOptions.h" + +class MemoryTestFixture : public TestFixture < MemoryTestFixture > +{ +public: + TEST_FIXTURE(MemoryTestFixture){ + + // Comment out here to disable individual test cases + TEST_CASE(reproduceIssue_776); + TEST_CASE(reproduceIssue_777); + TEST_CASE(reproduceIssue_Loop); + TEST_CASE(triangulator); + TEST_CASE(skeletonClipper); + + initialize(); + } + + virtual ~MemoryTestFixture(); + + ////////////////////////////////////////////////////////////////////////// + // Test Cases + ////////////////////////////////////////////////////////////////////////// +public: + void reproduceIssue_776(); + void reproduceIssue_777(); + void reproduceIssue_Loop(); // http://esotericsoftware.com/forum/spine-c-3-5-animation-jerking-7451 + void triangulator(); + void skeletonClipper(); + + ////////////////////////////////////////////////////////////////////////// + // test fixture setup + ////////////////////////////////////////////////////////////////////////// + void initialize(); + void finalize(); +public: + virtual void setUp(); + virtual void tearDown(); +}; +#if defined(gForceAllTests) || defined(gMemoryTestFixture) +REGISTER_FIXTURE(MemoryTestFixture); +#endif \ No newline at end of file diff --git a/spine-cpp/spine-cpp-unit-tests/tests/SpineEventMonitor.cpp b/spine-cpp/spine-cpp-unit-tests/tests/SpineEventMonitor.cpp new file mode 100755 index 000000000..9ea3e4d6e --- /dev/null +++ b/spine-cpp/spine-cpp-unit-tests/tests/SpineEventMonitor.cpp @@ -0,0 +1,176 @@ +#include "SpineEventMonitor.h" + +#include "KString.h" + +#include "KMemory.h" // Last include + +SpineEventMonitor::SpineEventMonitor(AnimationState* _pAnimationState /*= nullptr*/) +{ + bLogging = false; + RegisterListener(_pAnimationState); +} + +SpineEventMonitor::~SpineEventMonitor() +{ + pAnimState = 0; +} + +void SpineEventMonitor::RegisterListener(AnimationState * _pAnimationState) +{ +// if (_pAnimationState) +// { +// _pAnimationState->rendererObject = this; +// _pAnimationState->listener = (spAnimationStateListener)&SpineEventMonitor::spineAnimStateHandler; +// } +// pAnimState = _pAnimationState; +} + +bool SpineEventMonitor::isAnimationPlaying() +{ +// if (pAnimState) +// { +// return spAnimationState_getCurrent(pAnimState, 0) != 0; +// } + return false; +} + +void SpineEventMonitor::spineAnimStateHandler(AnimationState * state, int type, spTrackEntry * entry, spEvent * event) +{ +// if (state && state->rendererObject) +// { +// SpineEventMonitor* pEventMonitor = (SpineEventMonitor*)state->rendererObject; +// pEventMonitor->OnSpineAnimationStateEvent(state, type, entry, event); +// } +} + +void SpineEventMonitor::OnSpineAnimationStateEvent(AnimationState * state, int type, spTrackEntry * trackEntry, spEvent * event) +{ +// const char* eventName = 0; +// if (state == pAnimState) +// { +// // only monitor ours +// switch(type) +// { +// case SP_ANIMATION_START: eventName = "SP_ANIMATION_START"; break; +// case SP_ANIMATION_INTERRUPT: eventName = "SP_ANIMATION_INTERRUPT"; break; +// case SP_ANIMATION_END: eventName = "SP_ANIMATION_END"; break; +// case SP_ANIMATION_COMPLETE: eventName = "SP_ANIMATION_COMPLETE"; break; +// case SP_ANIMATION_DISPOSE: eventName = "SP_ANIMATION_DISPOSE"; break; +// case SP_ANIMATION_EVENT: eventName = "SP_ANIMATION_EVENT"; break; +// default: +// break; +// } +// +// if (bLogging && eventName && trackEntry && trackEntry->animation && trackEntry->animation->name) +// KOutputDebug(DEBUGLVL, "[%s : '%s']\n", eventName, trackEntry->animation->name);//*/ +// } +} + +InterruptMonitor::InterruptMonitor(AnimationState * _pAnimationState): + SpineEventMonitor(_pAnimationState) +{ + bForceInterrupt = false; + mEventStackCursor = 0; // cursor used to track events +} + +bool InterruptMonitor::isAnimationPlaying() +{ + return !bForceInterrupt && SpineEventMonitor::isAnimationPlaying(); +} + +// Stops the animation on any occurance of the spEventType +InterruptMonitor& InterruptMonitor::AddInterruptEvent(int theEventType) +{ + InterruptEvent ev; + ev.mEventType = theEventType; + mEventStack.push_back(ev); + return *this; +} + +// Stops the animation when the [spEventType : 'animationName'] occurs +InterruptMonitor& InterruptMonitor::AddInterruptEvent(int theEventType, const std::string & theAnimationName) +{ + InterruptEvent ev; + ev.mEventType = theEventType; + ev.mAnimName = theAnimationName; + mEventStack.push_back(ev); + return *this; +} + +// stops the first encounter of spEventType on the specified TrackEntry +InterruptMonitor& InterruptMonitor::AddInterruptEvent(int theEventType, spTrackEntry * theTrackEntry) +{ + InterruptEvent ev; + ev.mEventType = theEventType; + ev.mTrackEntry = theTrackEntry; + mEventStack.push_back(ev); + return *this; +} + +// Stops on the first SP_ANIMATION_EVENT with the string payload of 'theEventTriggerName' +InterruptMonitor& InterruptMonitor::AddInterruptEventTrigger(const std::string & theEventTriggerName) +{ + InterruptEvent ev; +// ev.mEventType = SP_ANIMATION_EVENT; + ev.mEventName = theEventTriggerName; + mEventStack.push_back(ev); + return *this; +} + +void InterruptMonitor::OnSpineAnimationStateEvent(AnimationState * state, int type, spTrackEntry * trackEntry, spEvent * event) +{ + SpineEventMonitor::OnSpineAnimationStateEvent(state, type, trackEntry, event); + + if (mEventStackCursor < mEventStack.size()) + { + if (mEventStack[mEventStackCursor].matches(state, type, trackEntry, event)) + { + ++mEventStackCursor; + } + + if (mEventStackCursor >= mEventStack.size()) + { + bForceInterrupt = true; + OnMatchingComplete(); + } + } +} + +inline bool InterruptMonitor::InterruptEvent::matches(AnimationState * state, int type, spTrackEntry * trackEntry, spEvent * event) +{ + // Must match spEventType {SP_ANIMATION_START, SP_ANIMATION_INTERRUPT, SP_ANIMATION_END, SP_ANIMATION_COMPLETE, SP_ANIMATION_DISPOSE, SP_ANIMATION_EVENT } +// if (mEventType == type) +// { +// // Looking for specific TrackEntry by pointer +// if (mTrackEntry != 0) +// { +// return mTrackEntry == trackEntry; +// } +// +// // looking for Animation Track by name +// if (!mAnimName.empty()) +// { +// if (trackEntry && trackEntry->animation && trackEntry->animation->name) +// { +// if (CompareNoCase(trackEntry->animation->name, mAnimName) == 0) +// { +// return true; +// } +// } +// return false; +// } +// +// // looking for Event String Text +// if (!mEventName.empty()) +// { +// if (event && event->stringValue) +// { +// return (CompareNoCase(event->stringValue, mEventName) == 0); +// } +// return false; +// } +// +// return true; // waiting for ANY spEventType that matches +// } + return false; +} diff --git a/spine-cpp/spine-cpp-unit-tests/tests/SpineEventMonitor.h b/spine-cpp/spine-cpp-unit-tests/tests/SpineEventMonitor.h new file mode 100755 index 000000000..df177c03c --- /dev/null +++ b/spine-cpp/spine-cpp-unit-tests/tests/SpineEventMonitor.h @@ -0,0 +1,126 @@ +////////////////////////////////////////////////////////////////////// +// filename: SpineEventMonitor.h +// +// purpose: Monitor spAnimationState Events +///////////////////////////////////////////////////////////////////// + +#pragma once + +#include +#include + +// forward declarations +typedef struct spAnimationState spAnimationState; +typedef struct spTrackEntry spTrackEntry; +typedef struct spEvent spEvent; + +#include + +using namespace Spine; + +////////////////////////////////////////////////////////////////////// +// class: SpineEventMonitor +// +// purpose: Monitor spAnimationState Events and report when there +// are no more spTrackEntry(s) waiting to play on track 0; +// +// Also allows for debug printing of Events to console. +///////////////////////////////////////////////////////////////////// +class SpineEventMonitor +{ +public: + SpineEventMonitor(AnimationState* _pAnimationState = 0); + virtual ~SpineEventMonitor(); + + void RegisterListener(AnimationState* _pAnimationState); + + void SetDebugLogging(bool val) { bLogging = val; } + bool GetDebugLogging() { return bLogging; } + + virtual bool isAnimationPlaying(); + +protected: + static void spineAnimStateHandler(AnimationState* state, int type, spTrackEntry* entry, spEvent* event); + virtual void OnSpineAnimationStateEvent(AnimationState* state, int type, spTrackEntry* trackEntry, spEvent* event); + +protected: + AnimationState *pAnimState; + bool bLogging; +}; + +////////////////////////////////////////////////////////////////////// +// class: InterruptMonitor +// +// purpose: Allows a programmer to interrupt/stop the updating +// of an animation based on a specific sequence of +// events generated by the animation. +///////////////////////////////////////////////////////////////////// +class InterruptMonitor : public SpineEventMonitor +{ +private: + struct InterruptEvent + { + InterruptEvent() { + mEventType = -1; // invalid + mTrackEntry = 0; + } + + bool matches(AnimationState* state, int type, spTrackEntry* trackEntry, spEvent* event); + + std::string mAnimName; + int mEventType; + spTrackEntry* mTrackEntry; + std::string mEventName; + }; + typedef std::vector InterruptEventStack; + + +public: + InterruptMonitor(AnimationState* _pAnimationState = 0); + ~InterruptMonitor() {} + + virtual bool isAnimationPlaying() override; + +public: + InterruptMonitor& AddInterruptEvent(int theEventType); + InterruptMonitor& AddInterruptEvent(int theEventType, const std::string& theAnimationName); + InterruptMonitor& AddInterruptEvent(int theEventType, spTrackEntry* theTrackEntry); + InterruptMonitor& AddInterruptEventTrigger(const std::string& theEventTriggerName); + +protected: + virtual void OnSpineAnimationStateEvent(AnimationState* state, int type, spTrackEntry* trackEntry, spEvent* event) override; + virtual void OnMatchingComplete() {} + +protected: + bool bForceInterrupt; + InterruptEventStack mEventStack; // must match these events in this order + size_t mEventStackCursor; +}; + +/* + +EXAMPLE +======= + +SpineEventMonitor eventMonitor(state); +eventMonitor.SetDebugLogging(true); + +while(eventMonitor.isAnimationPlaying()){ + // update... +} + + + +EXAMPLE +======= + +InterruptMonitor eventMonitor(state); +eventMonitor.SetDebugLogging(true); + +// Interrupt the animation on this specific sequence of spEventType(s) +eventMonitor + .AddInterruptEvent(SP_ANIMATION_INTERRUPT, "jump") // First, wait for INTERRUPT signal on the 'jump' animation spTrackEntry + .AddInterruptEvent(SP_ANIMATION_START); // Then, stop on any following START signal + + +*/ diff --git a/spine-cpp/spine-cpp-unit-tests/tests/TestFixtureGenerator/CPP_InterfaceTestFixture.cpp b/spine-cpp/spine-cpp-unit-tests/tests/TestFixtureGenerator/CPP_InterfaceTestFixture.cpp new file mode 100755 index 000000000..9c2a964a9 --- /dev/null +++ b/spine-cpp/spine-cpp-unit-tests/tests/TestFixtureGenerator/CPP_InterfaceTestFixture.cpp @@ -0,0 +1,26 @@ +#include "CPP_InterfaceTestFixture.h" + +CPP_InterfaceTestFixture::~CPP_InterfaceTestFixture() +{ + finalize(); +} + +void CPP_InterfaceTestFixture::initialize() +{ + // on a Per- Fixture Basis, before Test execution +} + +void CPP_InterfaceTestFixture::finalize() +{ + // on a Per- Fixture Basis, after all tests pass/fail +} + +void CPP_InterfaceTestFixture::setUp() +{ + // Setup on Per-Test Basis +} + +void CPP_InterfaceTestFixture::tearDown() +{ + // Tear Down on Per-Test Basis +} diff --git a/spine-cpp/spine-cpp-unit-tests/tests/TestFixtureGenerator/CPP_InterfaceTestFixture.h b/spine-cpp/spine-cpp-unit-tests/tests/TestFixtureGenerator/CPP_InterfaceTestFixture.h new file mode 100755 index 000000000..5fcb99c79 --- /dev/null +++ b/spine-cpp/spine-cpp-unit-tests/tests/TestFixtureGenerator/CPP_InterfaceTestFixture.h @@ -0,0 +1,30 @@ +#pragma once +#include "MiniCppUnit.hxx" + +class CPP_InterfaceTestFixture : public TestFixture < CPP_InterfaceTestFixture > +{ +public: + TEST_FIXTURE(CPP_InterfaceTestFixture){ + //TEST_CASE(parseJSON); + + initialize(); + } + + virtual ~CPP_InterfaceTestFixture(); + + ////////////////////////////////////////////////////////////////////////// + // Test Cases + ////////////////////////////////////////////////////////////////////////// +public: + // void parseJSON(); + + ////////////////////////////////////////////////////////////////////////// + // test fixture setup + ////////////////////////////////////////////////////////////////////////// + void initialize(); + void finalize(); +public: + virtual void setUp(); + virtual void tearDown(); +}; +REGISTER_FIXTURE(CPP_InterfaceTestFixture); \ No newline at end of file diff --git a/spine-cpp/spine-cpp-unit-tests/tests/TestFixtureGenerator/_TestFixture.cpp b/spine-cpp/spine-cpp-unit-tests/tests/TestFixtureGenerator/_TestFixture.cpp new file mode 100755 index 000000000..67780f31a --- /dev/null +++ b/spine-cpp/spine-cpp-unit-tests/tests/TestFixtureGenerator/_TestFixture.cpp @@ -0,0 +1,26 @@ +#include "[[FIXTURE_TYPE]].h" + +[[FIXTURE_TYPE]]::~[[FIXTURE_TYPE]]() +{ + finalize(); +} + +void [[FIXTURE_TYPE]]::initialize() +{ + // on a Per- Fixture Basis, before Test execution +} + +void [[FIXTURE_TYPE]]::finalize() +{ + // on a Per- Fixture Basis, after all tests pass/fail +} + +void [[FIXTURE_TYPE]]::setUp() +{ + // Setup on Per-Test Basis +} + +void [[FIXTURE_TYPE]]::tearDown() +{ + // Tear Down on Per-Test Basis +} diff --git a/spine-cpp/spine-cpp-unit-tests/tests/TestFixtureGenerator/_TestFixture.h b/spine-cpp/spine-cpp-unit-tests/tests/TestFixtureGenerator/_TestFixture.h new file mode 100755 index 000000000..3103cda85 --- /dev/null +++ b/spine-cpp/spine-cpp-unit-tests/tests/TestFixtureGenerator/_TestFixture.h @@ -0,0 +1,30 @@ +#pragma once +#include "MiniCppUnit.hxx" + +class [[FIXTURE_TYPE]] : public TestFixture < [[FIXTURE_TYPE]] > +{ +public: + TEST_FIXTURE([[FIXTURE_TYPE]]){ + //TEST_CASE(parseJSON); + + initialize(); + } + + virtual ~[[FIXTURE_TYPE]](); + + ////////////////////////////////////////////////////////////////////////// + // Test Cases + ////////////////////////////////////////////////////////////////////////// +public: + // void parseJSON(); + + ////////////////////////////////////////////////////////////////////////// + // test fixture setup + ////////////////////////////////////////////////////////////////////////// + void initialize(); + void finalize(); +public: + virtual void setUp(); + virtual void tearDown(); +}; +REGISTER_FIXTURE([[FIXTURE_TYPE]]); \ No newline at end of file diff --git a/spine-cpp/spine-cpp-unit-tests/tests/TestFixtureGenerator/fnr.exe b/spine-cpp/spine-cpp-unit-tests/tests/TestFixtureGenerator/fnr.exe new file mode 100755 index 0000000000000000000000000000000000000000..548fc5d91fbc747827dbcc53514793a052e1099f GIT binary patch literal 185200 zcmeFa36xz`mH&V1zW45Xb*n1yQsKQy3aH1Bc&QKwL7}REN+FXXAd{GYG7lyo7w-eq z6cvMtBZJ_C1Bwhz-P#VVZ9C7iHV&<}Z5pR;ZSB_X{yA&M-{-scy>F-_NDu4(U+cgA zwUT@H*=L`9_St9JXPFU<;k3XyR)b!HJ4jCDV z56oGgenJqOGEfTs_9IuGRpj>FAPj~EY6ues0WbZn`UY?d;JdsfonS!8t-sU4xu&4d&zVo0b3%>QYVQ`Az?}owol^m(p$HU;7x`0wJ%=2jS-&?_l`S(cZ zbJ0CTD+nIbllG8nFMGzdgx~*OgeA_(3fTMC3W5s{$=cZ^AWb%83?c&W?IOyClS$q;-OWJkmk1Nz7wXd7R@&iW;ZrK2Apzqr5A@I+8+?=S}S5yk}IIme-^N z5JkGg)4Tl61FD<{%>M)rQKWn9%!9JzJjmcr@DN2xw^2EI<)F|x4>I@@JVcSwe+nM! ztZtK~U{=94SeIQV6?ejSl%^Y?!+9#JJdHYYFdZdDSW1>TEA)DOa6An{e_@;U5-(U& za!`#X$D(*Zc*YCXJRC%ow3McJS`%!hV;y*+F;Q+fiUtyl4|CXuWZGFhePytt*0=s~E&eF&+$525<) zL#SapVtJB?RUd!<*v_a2&&x;|y>d z!;j+(a2&&l;|y>dBb4I|a2z9!;|y>dV~pbra2%tG;|y>dLyY4La2x}S;|y>dV~XPp za2z9w;|y>dBa7n$|(KL-Ra4;>GhK;xD(}&?aX{O(KZgD(Xv2AmQTAs#tqf-LII0ts z9t}uh$^E);p3%8HP1j%+5ttrBY(A@4cvjS-YnKJjhK9CMM-)a`M0qSi%rFTBlVL(0 zQ8>@DY?E|8u2cSU#Uu=L;>c)la(?B$ePFb3^@8KCn3rrVfwFz&J`v(68tiN!c7Fb@EA^=(xoSq;ZoY)N`N}N7M z;p|Lm%O0)Ykv5@R7^asBsYmPMDBO|r9r>r1DwphP5xs!N#HD$%R}1qFVb8hB_IOn;t)g=9WWeUe^l`izDT-liMr>-5&RlM!XvW9s(Y1R7 zbL7BSRPW)^J`I96Dy5I-9hKA5^=hBNGd)vaB|S^8W_q?>=@WRavT=Va<2`+Z7HQ8N z5e+43|2vPgF+f)wU0V;XAV0>mBENG;Jj2)(gyrWh^EQ8SJ2%gZIN^)hIH!%WHrU4NkN57FC_dh^WPu( zn;C=#9wz<4U3okG$K@MKFS5d~f@1m&CXARjX6f}V;&3V58;lFtz8LC}K`lSy;q4>P z3{GSJ1cPS0f2UST4^-+#axM&TgBTChlE`{+nVJ%9l z%hg&-u2!SjsdiGU`Z?(^&xtln^{F%Uw5Ieai?PqAjag?4=N|>_-qvzQEA>hvD_4SR z?x|O3yVe>-X_^K%mhJ74%X^p?kt?!Q9ywl0)jXh2Hj%H-B;`gz%ZjG3517Ll$>{P- zc37yJC0jyUh$_vaszg`D=IG@?r8zfg<&uEe>F{1GQFb{9CGageAD1IL|tn zgSS`>5FG|@9Tya4 zA6CRoKSFUUldDZILkpaUH*8F3NHhZBa`pw8an8v$IN8dCOybu0G_(!L(*WIW(fE6E zA+Jeb5=~EcBzg$exdc6|H|DJKxvd_YQ}Fh-ke9qux*5+$;k@KU5sc(d79r24w+tQL zc^MR5REA#Of3gh20qxiR!g-|4Ys_lJ!i(fK5|ew~23NhclhL)iZSBLqT?wNFw$HPd~L-h$MosI(@Z^hnw)>~3}Kj- zk?BaXs;18b(c_ld*P>dI+_J8^jEx1Mrs~~rjF zH$W6dH8vzVpFzxrGO96ppi;%=b)7KUL_=XUIYluEF=k+&#{1zK*s2fNJjlo-WX~PZ z>0)puBT~AB2R2VDz!hqLK7ITz*_bbZ>HomSJOyQD7xI`m`u{MMavy6(L zVypm6<+fh2zB^Q7yLU}Ykk0zUGJEhvi`cC<>WYGRdz2D)&$gqpK0r|@50+NL`3B=hpIzh4(1jHvPk~t+# z7bN4efLPWkN!3i$TMI~Xw32TW3wm66MR64}ed>MzKa>G93HX2u}$IoHXe^sS&% zO`wy#`0l)#+ZxWF$r}D-n)83H_|wI9$zNo<;xGJ8{6~ZDBO3D_{5$@e?ClT5|Ky$c zA0@%0t=!;S#OR&75p-up%)$@F=-m&Sk*piHxOz(L^N!XW7gA<~rp$|T#3IRc{66Vm zcR4-|vR&y|_?{fyR+|cb!!(T>1i!;Jw6s@lw0P%03yXXTPGyb-Tf|1Th)r*V&@Do< z;W2t>rL@(~?Dr7qYy*)N?55AN;gp-w)&UId4LkcR#oizF9NTO^2eRRO0Ddl6&Fl%j zXFxWOLLR=A_>sZvKS=GaU=qY5dE_0762F%4bPqFQJ_Pf@J%Q9pk8%D7&~rYwC0TJwe$s030b2E8gy}Cm?h& zr#%f-v~MSJo3Iw8O=EXq>=`yj%h_+JjL}LteJNC<(bVI~aA}mhOrdJMS}$*G&N5`t zDyR43HR$d3(2rnQ&- zDZ#~`4@89RKOC&(eFiy)$rTg>g=3hP(^tYOO7G;EzKVxq8=CtWqc4Kc#>CD2oybGU zxr&DOvfwOu^Pj%GPD~m6akvp3TVHB+`;y5=F6h8pS=78`gV({tA$L{N*O11x9foVg zjj6zIcp`bUuhD!Jg$wr%1m!l(I;H~CyLe}346^I;I-udGokF#64aH5A$NcKXc_!C;W7a@kTyCAG3_er2h^hWC&U3*+`V8{Uz=|(M=EvLVN%3Dm7 zeG0hL^}U)yE4d%Kg5dAE1RZx+AHgrX1TUnp#vvPu8LF@BVY45IJf9aARDEoY>k{0u zOM)xA1h?&iz`IP8-QFd;eHUa=PxpzkzlOLd=oc*EjSOWe2V%S&JrWlDAMBF7Vi#nk z^f}`2Dx$QZ_eNBJjcvHsfE!s_GTdmnb^tAbzkgeQJRSme?%LWpur3~DzwME$G9=A) zxF)w~usx!q+JaAQ?)XFCQ!j6t##0Bs@oqZhZ0WKiK_+S|o|CW7BkOl=MXAl4=xAFY z6t>ludpFqjCj;NDnjSWATpe~V1e?s4kk1r6x^^aDgCV$FZSPIU#8^V!(KNVVGD>Nu zOqS~GQOfL5obp*?h!+S!B8CH+G8D`M1qBl~2quC8A@e5E@LV7cHiRapoCmfA6nAtH z#~Fg5x1c!Q5R7#N;v_>bnidFIB9SkAN+#GThS1z;xkM?WOTKTqpXo(|Xx~sO0@o1(2voxI{Fnx<HnAtVxv9 zw*gKZJGa~zs5I%@!Qf@YFxKlGy#7l(r1$?Rk3;_?4=94C*qCYgVJO733c)?Qj-~() zdn52Mczo?pa2@G4s|{lIYWzEcPLRF}SjJ?$^&A)#b9hGmwEq(9HeoGF=g3y4?*TV7 zH43L{`d;ASsFwZ}Z{t&SkJ~@mo=DYPZB?IgdwlQ51}iTQMqt30T(XJxYRN=jP``K| zyoxbO4*t7~Q=3iX+O7P+xJxup`tXeYg4#&O=?pDIzHHKJeF+s4?3>1qDWR znY+P-3_Uqt@O5Ll2jgIK*;5-oDQF*I;D>~@ zF~?8f9n{52$9b~V27XwyQefCNP%SejV2T1XX6pC3I2fORA5pTy4E(6TbzOqP4g8p} zkL+R}WuPTH!ax)KXo2CpO56UpQrODVrJgdfy@Z`H(BxCqhHX;;?XeJQ)<6?gjV3R^ zdILWp4s%`Xu>$ivKdHD!TbyxMJINKH7Scy{!eYdUU1Ci?eZ-HkI1|&xK3CYuhBYNT zuA5kGELZMn27XFXooe8x1wP)u&j>ud3$g+rnPJZqX!~es6RO;H|Ez)1c8-;DQ^!h@ z94kq3P#HOxAIDVNE6(}}o@h;M?mg=#T=pdm(c_kx(d^rQ)=#*7^Rs?N|M#LV8NC{G z!C&yiaBGA?wl@o*vmbS{FtT<1Ss1RK=V1wc+08>erICKl@^kp}J@6Mg@Ob*g4%}$; zil9_kb+}VXgUwsKT7WxP;NP{Ux$VzifG_>$XmUQ;YGY zuh@#o_UY!SFb7?my%`#AG|$lz$m^1;R^ev)H=S(Aotn8!4r>|X!Vv` zxa{z*3`W!JSG{n>VOyg=R`gzI>&!O!P3)U~#j@0>G;vmcHo|3(>t>^HOY5MCWxb^p zx=^oR3Pih)+Fyln`ZeROfvzZ!;C&`e?=6o|*~V^03Qru_UmoF#lc`33MYlW}JQ4oX zUY^2b3tgTHw|>mz*Dt)#<9SV4l9%_hr7&kLD$HtevbOO_*!AYAnCz}@o(eB+8;096 z&(RXRr<f=>LdbT_`>q8R_&*g+{`=$*x;XP}N!BZgH&cZR zF*N73en?+zJ$F%uR7}R=s~GBx^6ko~uTKg+u`DmJrFla)Cxv@+Lhp>?eR|hSJ8}BN zP;VK9Yo>o|IuM+Ftt*DYt$QfQ#L2ySH#U3ZVkkgXmno|+!6hGjG?N!97ra-0u0m!1 z-pxs2B_ptFaHsvdPJH&*t_+H6 zrr++wHPXNDz|HhK9oQr2+!#Hp>fF6!n&XE$~ED%?6lmC)Dl zEp^cpWbGBQ3Z6K*_3A}zh0gBkvNf_j`^7a}QL&cbon3LwuTJy<2!87nz= z#!44EV^u*t*onA>1F~-@R(9E6cT1sg>z62}WrKE4%`0Z2m?;$~8mWYDaY#GZN%M-y zzS(82@ZxdaaK(gW34YpDk;27zBbZio;iB_TV1?TTk)H}uz_;fflx1fzR&1_*@s^u$o!aV-sBbQLp*!iAo-DoMVtZutXK zq{7YI{1n_sztF)?oY~@pe_w+VN%s1#IG+56og_Z2yb<|&hZRvx6yFRPi+1;$Cxr_& zYoS!=L~!e5Dz)EA5<2@tR|176PVLvTaC_&rS!lGn9nR{KkJXSIp{`;N4yAJemaIykS2eEJi3Zufm1=f|397Me-kKBx6P{*w!LD^%KQp zzwgRtl((q<`V1|hCx-J1v^0m+I~8~$k)e60vMYpj5k*yqc)Y=~| zuMxwI6{1Q*L!!}l#;g~^T_ z?FgyxE|#xC7waoa(ldl8+|XwQg)etUbg5cVk2QI+CI6|B2+l1(rOc;LVKLvY=xz1F zWhZrIQ@FLB{xR`{-to#4OVhKwnF7_}8 zojtKDgTlLz!BQ8dn*zx2gheu(0=gJp1$$Ro+-ek)J++&m!V}l@w;ID0^SULtT?tB7 z5QU32ahk#2N(D1f|8h}x5juN!H$Nj=wC*)ru|l;3U+Cs{Dh$T-WeC+TxS9TI2X5U= zZms`Vl%=S$2fJA+Jn_tly?QIvaK$Y0cnFf8!8QH4u~yjjY@4^7hc`8j8sYru;O zO8>1x)bFZMvh3I0d=+lJQ|)Q2H*29MifP8uRF`$Mt8CJLCxbD|nmy@o{tR%Ib+sAJ zpV%AAv7-5fg~c&DtD8pQ*8Lj88ZN0PGqRWVC!^tQ z>Wtxc8#jrRy{F4f;azYuvLAH0DGax#^mE()A-=C|_;G5}Y3uHR+zjda%vSa4Jud(5 zR?Vpoq4wK{&>+``&{Wlj(A?XHka5t5kR8&8&{*DwIBGFM=3*a(Or<`=)MA7z_dbe4 z79-XyMreNPOLFjH#OlR}$;F6+79*0y2!^=+Tvjbc9Jm;9z+%K*pJGGWUwZX_k1?MH!2*a?gq#UATOa4Q@Zv^Ur0tbsmKtca4mzc{J#$R4H4(Pg}F zALniCG7awFVAC(=T+OwlX%8ALB^j>GFt`TGCabk{2qa&evC9~L{g!J`-Dr8RUT)OO zw{A+Ab7MqHmhc{}?EF1iy+V`svrcCRlUsf7b$spZ!A+GQc&_b>v2c$To=BY~T;mdz z!g;|d-ycRZ!&1o}%A%R<$x9orY#!$%%#BgDUS;|VAbsi7iP~FHCn@S3i=*~b)W(M! zm1or;k$oXjFcr7iB47|AM?%6k)UHOO(a*40$>I1pIR*LXNdZQSMN+y^I&oqk~rE* z@9ym0KL`4D6ZAG=Eh?$0Z(Jpr)8)jBOwrE+PT}yuC&v{zr1)l{X7&M@y%NDd{5c3- zZ{=mjj1y%6%<_UE_Mdp;K zJ{r^kQR|6x;Ar}ND2#)l&tQ=7gK9ed)tHrIcMN^MO8V4^03G=3)u+w`bTFpRjlCGt zr%nZQXiT3v7SO@$PM=E?Uet?GmrZp{phIJd)j5F<#uTfA0v(K62bQ1}TpV(+ zTZ=kB(4p>DgN_Gu(A{cCd(l=6I&RP*v}(A{F*~9g$glf#6eni&4bUjFVz(NY1A{t8 zbNj2|nC4=%PTe(T=>)2soI$sD$KVq_DP}W=hYivB82!tE6K29CM03`o8C)rVKmVNE zKL%GPEvG+2)ERWu|7m){^X&at& z7lD7k6E6)CJ~NJ!ZIDdSNCUf;pp+gAu_2QQqUk;P8PLJtSYZ8SZ()%0kCcrtuOQ6x zXu3sw$v#J)-bFz#wvK+j~ zcCvjprSfyFCOb-2M4i=g}>g z&b~VC3*95F{U=|0`R?}I>mt5AM^)8K-${Z)il>p{P7vDHLN07FBk*>Oj3_sG5J z^;JitQ_$R_asuRG@&aI0>?7cjN9fz9FnLjz@@YnSa~E;DA#Uv=?llAhot={I;q?iN zU{r~QmxjHWe9a>0?skT{Cq=2L-09OSSC*E0lk8(LcPgf`w9*@Mmc_i9n7jyA8iImH zqY8eT<+DsJwHR+66`+0l3q$_|O+?A_d4P~Y zEmihHvbUvK@@dJ_n+u!)hVwhCbO!{g58h0^ z?YASHF4lPqZ>Hq8=`|FlOn3QG#8%bVfdSu|h^U&~PpNeyU=Ynw_FA=|)!z8^!PI`tye`8|H6Uwim*&MeZ9<4V3)OHov^=mD~bYnJnO*2A+VbC zg4uLr23eT=CG~6fM-_>(6JVWJd$;_^Ijiz(Y@Q*L4+8+3mKuuo;)q_nv=L(%$6zIy7~u0c<@npZoQJ$yev7AWM<1{&nJ%u zVk~953pM2{zPLTjBaXI-)aY}5E4E&xu0TK8Wkb_F2+or4{HqjJ9I5cKijO zfq(lL#M~yVMJ2NYJM&>#_p=3Gusla#kkxq!gQ=kX=wVRcF#*YxB;=6N2%T2y}? z1G;xBctCl?Wz$I|*U2Zm_<25F{;!%WDu4HQJfAd37rQ8bD`3qTd|k3Nk$ht076t;_ z_~?FE_ar{7TTh|yiJGN*qOr1jZ6s6ne$te=&*?)5V&jG1O&}Zco@jZ+?<`Qr@&5w( zJ<*CK<;4;Ejw@n($xbQeEMo5^`Sk}~RvRp0pC#4BtZuc4eV5c0N4(u4CI*)bE{^$$ z$HYtGo*2#D*^<43YnH_69HqD7-4jg=Eg4!;Su$uvCOEugxF?Z@?d*6Z8gAq?dAj6S zc+i!suHvTVtv%!q4ZbPeUrLfV9P-|-NkF}wo~_>A+&EgEIvq;U8{W;%S&B< z1E11HpJw_wlNO!zaRjZkrxEbZeJX6-4koq3Io5l>rB0jV^@`uDP<9pc)nsb_}v&|H@ zkz9lyAWS~5Hf)&WVi1uHW6@-3?1C{Ten$^69Sve(`iWOuu)>MU`*b;f(TIg{Vsjdo z;c;s#u?zKVEUO35;{OE(Y@7yMXdOc)_8#_Mr>Z5XT}?k9?CCi`;l zrr#v3fh%gNPVstudzd}V;rzMSPg&%-1P;{ z0LMMOz!~7UXB0RC9QVuuXMp3j6gUGMH(%fkaNG?A&H%?d|gfhh`S?fpGZqt z$cPBrCkdp-a+l_jG$R!BH)us=zn;syh{U`112AnIC2@MPsGlZ|`qp|PcnRauze=x- z1hqw6Iizee9I>6I!%!FLS_*Dbq6Pxi9H$T%$~N@SFlg*A!mkuS-LZ}gB%1#8jolr*e_?%y(IWCM?Q&7p5tWN_4*3kZ z;h1A^(#F#jD7K%;W5`^_SGr&o#6>4t~(rDdXJd z`wAj|Z#=#Zm0zEb2uyJ+$2J}{xD(1VT+sG8lZr*K-GwmlqqzmR(>jM4N2{Q$i zC*r)(kCUWm^rdQoW7==2Zw_zY*Q3-*)_i9dO{6hd%gY^d+uR|~^{Uc6e}4~uqBQ1U zzj^;Qz;Vwia0WPTTY)pcaW@t?1Hg^a24tVY{+=hLq)f6xM6W zsCcqD*c+is1IY7M zMa(H;Q0wz(dRZ@#+@=t{gctF67#79r0t4b-r1-KdtLH%yY8%)Mm$5h(#4f5WU=`O^ zkIfjaEOMgh8o8>(YzxI<9n%gjBSf_S4TYy;K+)JyvO()rZZgr`AN)kc`giR3;~&xa zjCy`E4%^q696Kd#&x0S0>#Sa%E(!_tOat658(+IRcrR5mG{8DuJmkB;rNu|83AiX_ zk&PcCxftP6b~WYGU^j* zWq>P)Ph%~q#c*#R`^46QO^b^}$=*dCF3F_!c=1a|*?)BME!E3*$E}&*v{UYA*{(UI zUh#`$D*jQorLgR>6%$1t3lqAjUxhPTmBpT@LvrOgS+M@*S+6E{@RAEQvV>lisN4Ee z9JUl^P-C|&>0m=p-xM4?PcRIQ99VL~fTRhY&2OMUXfioCSsKU01($q|Of|l1tltxa zV0~|X5N|ZY9W2jgxQU~oYALydYPoh##_Qqm24QPe-8H{Dj;e=0sB{{mi?n+!N_*ME zNPD?wHZA+X!LX#$Y!Yg8?E&38R{I7f4N1lDB$XB_R70U{ssXz`z38szWyvRF(GqG*MN69wz$oyQ-`FZNNn|eox2dY@hjMJ_TAdVdz)=rnxBDCwq+Lj?fbspJG z2$6Rh`54vKf@(0b%uULfuw{-|Yfm|jWbP}taOK=H#&Sc zQ#N+AI4qkC8@IRUdcm9q_ON+-Yli|83f#JB#d@kS2*+-p(Igixzujs%xtg+CLZcm3 z6bX%sbd;nPf9s~@J$d|`h`Cly`T+$j-PrA|k0@a2uF3gMte(>(0Mm&>{jTe=+b6Df zny2NwSM>0F7umYj^1K*oEUoVyLRs2M z-D4>dLqH#UznHggx+=Fv)nYrdW?mi5ZlZ?`FltHd`yxv_ap zy{g*WykW?kXAuyV0z?TOS|8i-<80o5F&51*)rv!c=hco4HD)zE)QBD)tXDU07{QF# zNKVpNJrc+bX{5!KM2&4;cVqP`sX~8q=YqNFyaQhSD*b(K{jn-=v{Urq_V$7AO#`gvFbNUlY7VR{|U(OULnH9l;FSk@s&d>Dt~=_eph&E?tl+Wku-)x1oQRLw1{6+=9Q6!) z4<2=my<6+8eNP-Zd!dEb=Hcnt(=9xchv#PJEPQMpK6iGlh0n{w7tXdUd{G|WGHd;3 zVt&1is}o!G)xUZ6i~07>60@+{lg@c=E>V%QObJ0)`ugpyj|0p}_)vHdHv%8Ee-Gjo zA!J$>6f8A@IW1(z;;HqpF7Pi|On6rhVWWreZt&|XJqY#AV}60yaQs(Z9Wjq2!o>Up zz?^K3BC~D4>pv#iTyEp>4(IWfULKvIeo8!gi^{y+Uos}`PRaPKoDT217Zbjrhfrfg zA;kMcxId2q@u9^jKdhAcxQe2NN?Fv%DoaHLd|DJXP~;_(m~-D?Od!eM@aiP#Xy*%} z=+(~iK=jqwYej*zC>}2^c#P2ywkn{8@O@D*ICezeCd5)hKnR7jlQVS$_DnEG8G_|3 z&K-59X!hq(Ah1XJ6RA2DC6aJ`iPUiVa(dm)iSAyU=nab#-LrF|H|~sj$Ihs~Ud-wJ zqB)z#@_6c0UPbLbTX?T3FaDnkp{@bpfjxwH9`d;;*He#dh3~@G=-8E%-t9mGNC^%F zIL-jWb?9GT#2Mi9cNaJVdgy0Mc22x(PmUI7zR@Cp)fD&4AIp58!x+~yaQfP>u+5MG z1-lFe7|(gi;Wz^vcW;3+z;X8#I0L}#(!YaKSN@$-^r|GdTg|_7I`6{2Lj`(%1~~6G z6*vPN_vQj;faBg$;0$owTML{4j{CC$XMp3VSkKo0$Gxq<8Q{3L7dQhP_ZJ1u0LRhl zoSy-XduM?&z;W*?a0WQ;-3877$Ngo2Gr)20DR2gW8(n*RaAp_;EZ4EG&q1xd{vTYN zef}SOZaw~=Fu_ueGCPfNFD`&aTsVQmCzOMfC!STFI3f!t(9>y1yKw?p`i|>|8NAo^ zBR3Ce<>uLi6A0XmM0VUgT8MN!J+?sENO5tO_zLB41qwDj4xbJiUA&l6Z%AKBVCtE@ zNqSvD7dqqrnJZ{8T_BTwSCWpo;wrksMOjOUI!>Qwpu}GH5u^0ObRQM2BCI5S*@;Jb z1CL#~inc9s6+KIG$jj89wEbN0?kc)b6mk_k#{i5W*&E|)j|ujojj?fGw+kQRwpa~S z-DAYw3hO%e7~wIvn39>tsOlc0YT+?bquQ0nsALN~a}y13KY+Rz;i!aMQSisaiK>HL z=McBoZnwEExs;fhRZv&m5i|~1b4Spg!gg55{ZpNEsu@ZVR42n)g8tdoVKYbRy2O@W z*8@a49DMshTdG&w?StFKe%vT_uTO4;=L^^{!9m$^@R*Mqb)ylUEIkYN&SO-8>o(J@z47meq$k*cA_lMW$a91^3sq$)lxLX(7AwZdY_``ePkqVs^ z)GrMVm?s#rN*~$7eNkcX#epT?b~p$=Hn8Sr1N(~x9~CR@!bc_0d{itX`h8R^-THh~ zkJVT=e?LQEkB^EeTRtjb@llQJ&PT;`)R)$LRDU8ZJ}R-zeN+PRQL$s@KB|?$<5hJ2 zeEcoOO^ukv=&4pwv;#F29O`~_Xi4`0gn4% zfinP{_Vu+o)L*_4+kPpvnQW5`?K=fN+rYa7J{K@Q8#AsuHG{{YGaK3QB0Pu4r9mlS z%;A1g$d~eAlmeZbY{Nv`0_ObALHWKnj?{WWSDiO_)w%rom$74$bwS)-3t66T$fg!| zO_OgUj>ayG!x>b;SbCwhM=0lot_RPm!PKZb{8 zG+M2APHb&hUUXt*X8UzovTpql)lpm>`Z6?QdwSc1wW#jyo^5}iYdY!FRq$UL+h+DC z-@qAmcxtV%!;T%PkJwN9sSnu(;LM;x)%u9-l0ttbJlA~2w*ZHGcZuuO zp}Y{}WmGSAs<@Y`s);$S+7;iE@;Qf`gg9>X07?=3)!szksvK z&r>L>C40~~X~IXtyI!s&xARVJGwSWIG9y>d}A#>ecnu((ua6M$qIPP$z|=L1va0AYXlutt)ffjBPmV zeuRD@$eHz>LkpE1jfu{og~2x7$0)%sv3l!Adus5NVB44Cdfq0iMd{+()yXIi)dgaP z!J)wye&>7GIz#zO1Y*L=?Ug+OSqAYC@0)oK^S*^QhQ{n25JuStsK=^bY>tWG7s$u8 z#_Wv6eumiE;@H6=?bnDMTpT-fJt-kcch4ZocAfHQl909fbd>EbYmeO}12xawhZO~~ zlj#}tG5x}2!+!{XLdDUB;iG)p7< zDPZ>RJnVR5_G<;T9cV#2nE(C)bJtBH58j9?PD2AsVMO>}>GZZ7$_8hHGyWNBSLlhhZrJMPQTb+s279m}Z zJN_|g;x(Vxu9~U&uS;NG_H7Dw_BW0UPTFcm&se+Jgkr-7PIWumtomE$N5`cvt53fB z)*Pj8!Hc&R_MLqe>;zmv`W@q1a1rVC=cusMekm~vAE)nxH|Uu#4aLbfNIs(`(2M*g zNIRsG{iiDT<^yoPZi0FX?vXabbDaDc6s+f8ugpoTHZr<)X~3YV^IEJyB?dpNX4%c_ zDdz)&aBNQXr2{+mqGracQ^TYnhRz+^*&=<*aVLT4GZxA8Ulg>bI6I3RCT~>Z7DX>q~vE` z_dGDTX2D`D?PrU$26$S0qUFh1_z7Tp_AjJn^7*9j8F&HQ_^X%k=cA{EPbt#Ve@>v} zF~D)3FK`Bc)7d7u$Z59N!vBpbA~V(dY_27hQy*U;Ctgd>-vH0w#3SyDMVtY|&4kIT zC?Caqmx>vz3QNn9R~v|o{_PB{sU9v3cI>r3jfS1W*Lbw$4}H0yKRHZaD_&No?fv*V zfAV4Rr)xYc{^y5Ti|R{0tW2^=fp3v0XBIN|B2C8?`zD31wiEweQt1&MUXI=fcU@$Z?QUC4URroFE2Zzl%gjF*5nfiVQs99X5uZZ?w3gs@wI1CM`w83y(diX0`-7U zcFJE$iv4h4N=J@w-K6T%X9K~xeRUE}%p{*zF?U%vbn2bTCLSu&iJdZaSOkym;3_#+ z>j&6X-ewFSeRnLY*tf2r7|Xtd9JCJ;UF+QJd@7-RH{x%3;6NIOm8_J$0fe2T%$}k6 zpVAT-ycQl%CZv*Vv^yK5_DcT7%0}D7_H!8wfDW7`QD0e4m|;p~O}<8oq3W{a9%Z8; zEXqX+fjQU9Z%W@w)UxzGo>eO2e%{wgKCcVi+i?`6jC72Z%P?U0N=e1x=OM(>*?6F7 zW|cPp4ynAEc-8_myWEc}f9vB&N(-r%mYwn6VOMf~=>rt&jB3i@nDZ`lR9g6|X%2lD zFuFFhv4iHvw+PY1;KmcsXi(#SoWBJ}6RkNFg+l}r&zh|Qg&Iub&bKMzb0}z9t?`ME z+Ru`W9JO5UR?-TBjVFjjCI4@`@Ah$v_Ziz#cIA}HHzuaxAUG#q;FcHu5xE(J|K6%t z_4!Xl9UA~w{hrfS-t-sFrgLN#()7=fGJPA5{LDlLS!yP42OZl_G_!#3M1=FoN<%e2 zIbrB>iCxfchu*A?*Qpthxe zv!M2RVEvx#G0@SuX-ge>+VAL-#KkM6?*yBRr5ftbK0p6j4_b!>H4K@7)54n%LPPeI zNy&Q|W8KY2I&ORVrLxbIAcE6!8%EV!YBQF{TP7dPj#i%d-G(6UkoFJI@U|bR9!@SC z5r0YS!jFXtR&2GX;M*nd!0+gE@NixfrSv@z=Ut>gy%$vaS3D;9-GkkvE4SY#s=qcW ziayZ_&6q)WwZlPVV_32N{r;RrZS08T1B7TpA9Umq$%p#F=W8~ISK9EqDj`9f{Ht2q zimm@_<>5Oi1N7Tj|4JSVwe<(qqCp#~_%Q=g$H@;#5~cshbErDQv>&uT3Vt}8ehYAz zevCl+aUO;H;`yM>eer6lNvqL(Fxn)1lrka2(@%EzlY(VVf&Ub+4iPR(J`FUZF^HQq zJ|kHDupT{dSRq*>`K*X>XqY>@#_`SC{fcdW4t&al(B~joe>KZFFGel>C(2QqtX>OG zMm!`$EwV{f7{==Q1NaFaqWm{NmY4YpWHVgT!q_~)g`3N5|N)lt8H(HiX;4H-Q(zaE#vpKl5euEqtPAN-vP|D zQhxxW=^>Y+ZvLC3Z=zc|Yg}zzAuH>wl`y_we(!m{jiKIR_ zS+%4pg6n=b_%77USM>*ud`S7<3t5|4mbSNZtJ_B8u3Fv2!so5-9EYvdo$TA=6j_~&8n3=z5S3o&Y?Kk0DZKswtMP}ZbEc9YEJmcR*7A0X7t8A2dMfQU z@2PJ9O(V9R`f`U&XD@WvbY}h9dTLwP$ea8XM)3fHexJ_h*7pmiE_<_p=~)O%OKUqC z3Tax8Wb4GXVZu)$I(eH}pJO$7#~AeHH8>jE61Jyfte-;T)oV3!P1bY!;MOqx3aO_X zWE7@f1$+SUd(2B_`eH6FEnqdpVR_-}ywEXou@G7>7)Im6x$wCkeS6f+$UiT#xin8L%1H&k?P<@ow^N!Q{nqY@+w_72VERl{qYrs zNo83_T~O=f{HM&j`9)pO;@x&u+hI+#7e-ymLYg&EIC(^vprX}$@o(2t1cY%Abi>e( ziT>|$`sd~IVrhXHqm0h}MX#ic8Ow=QTh_>DfWIrU>6MeOLh>~s^Hn(ibErFc&4%;; zMmWVXFj@4y;VYoS(8OL)y6Ni)hV%cfJi4?;UuamRWw8BFX4sMnQGB=jGcSjFzTavV&i_nY zNJpM3qD7g3scKVXDg6gxo0IQnajYy8nq;&f+B~DW%9O{^a-#*M(s|OV-BE*aP201S zG`rRM3iv-DC>-|@^0gl%hi$@IRI&oP89GG}ZT&wzq*alAPo%?BMlz66q*)PH^<23qGE0G<2|W5oJi$hhURLOt77 z<{saChJqI8Cg~^Ylc^Rj2Ni8Q?Corx+m6%d{Z$P3~bTRu1<7XZ}-@}AOfVmdk zr|Assi&;;sVmH--S@+e&LF2)r$%2(m{(Edw=#F9Lcw&s3o_~e-DJH?UN%V84TrhH-(Sz8D# z+SeYI0g1E@+ZVq2{19&#u-1cS$p2j|n5$m$|VcCZHSF)^?vkxnL^ZtxR z_G^;R&4z}wQQO-^!@uZVgSN;g3ybiaR-s|D8*A%$)^9a3r-l5|+S=&ay@TtR)0hf4 z6C}Nj*@qjxdBxo?6UW>I3fm|iDpw0fF=X7dxQ8;B7a!Bu*yM`IS~Hy_lB@RgOjq%o zp=SiuTQ@c5_5moRCknTxfvn@a-tzQNjm^nkt+`?k5Lj)Rce;|UgL-7pN4HwiAT*dP zdA%GEyoh>Xah%sn)9R&tGK}J>%ZXypeH?)l#nAMEYLq@6v@3>cS1;#V8C3v3 zrOR`Y4`+CJ1&jQw~<(XJ}sBrTl{glYxWJT zPOqTlZQ(u*%OB zj25Uq(c^K57VriDFZ@QR^1^TRsx16kuW;T%^9tBJyzo09jSrH)YkygeWy_36<_{rc ze<^#tm9^dybMk6uYp#$7-UP3%({S>{p1720LSx!&I4{|*YoVrPJ4)g+fXFsK8GtJgU;SH&23+ila=X7W!7` zABN!OJ%W^&EUGroO2(4y-&2{Yypq{D(aJbE7*c3EXc z6!dE8(<=$)H5JaQALK%*0^;n`R6yhvVC~%U9}30}DD*#KcWU5;D)P4@4te&bB^a{Q zaIdU>!hHjx*lp{ou4`3YDUOaPKd6we<;KWe>-aNO$rTO)nBCE{N?P|lDJOE}n4RHc zNY(DC#0iGYeIzBI3zsQoIIm~=D^zK=Q1UZGvVEfD=Rmlf_z)Cep(5ha*tuMRs$kSj z`y0~QJ{-C}cp zI4=Q8=`Tfs$=gBv3IuB~(N|NWFKn&RwIlXh#qY5?Foxyy*N~UfH4@n?SZvFwETpno zOX~YCgUC1S(%%45!P4RQ+I@nrkTb46bcl6<&)i1sWz1y1g|5^-5;pAN{*J)#lpHa& z^!LErpYjJ@%aZ@(IejJg!E}ef3p=3vqS5q$78Y&#M?F|yaTSCUv%!n!E}ByNbBryh zZT9i7=Tb^{AVs^yBRz_T?+DLiI_#jdHM1IP`KNAS%4E#JL?ZnB!U4gZA1Lmho(SYv zz^jQ(pp|6V3K*AC7H#~*F#U;%n@nog1fE-85J&3us0$0WQo+*fNOHNAUnR1a8d_I`<%)Cl3LZLHr&1isfAo9x+v% zAK5$jAe`_Q)86R#v^QIz&tQ%5qvVZrSXqvEEfwp%_k`B` zVVWaufW!MK3!jTyckOCyXzE1bxNlP$qb;o@>uFVfEj>t}Hl}LnYC!G=p%|voTC>eE zjoYqw?8QtsKA5l&=j=FKOvmqZ9S`hibal+RKGX4Nu<Tq6zV~Q;srz{2;Dvlu`=MFGy zHCDWj6Nt^(gT%~AI+(s!CmhROP{w*IxR;mPzNhm$Evq@1-(9>n z4EYLn>O3!d7;Fhn|9sKbYIfh<2hl^x3PUAH$|%L~j{W0XN0i#{L7J3Re20V;Kie9` zxk=8`YJw?cAEeVJ-=%Ld@DIW(+-qTom&TfJg!2OTvX3Ht_slWjyeMs*z8*hmP{hTa zQ1klfp!N4KSoG{%hDm4Tfj7Z&aR$u|O#c6#nkQZzSer7Qo;S)Og4Z;znOjYrFi zjFU=b!bPPQ29uT9ahAh^3PG#tNou56i#|tJ%-`_eC|hq<8*Jg0&si(l%c+|!!5jPP zgch@!IvJ6edo3){t90w8g<$~F;r9}%ziy0ZUKD-RVl0f@EE0Ssg z(dt!I)8*OR;9PzF#pdry;nfm+ycc)04Gt@fidt~uZjv2kAG-^k=zOH+9Q`?)hJ7Pl zG`VidV_G7~8E@Q~aVXbF$L7c9WCm7i8>!lOs^W#FRNNCDQ#g46rCwMLI2l~d5p6=H z?6c}K6J9?a)s6dcPk$P>WWi?6K%Kjrgl{i+cG8uz-z;K*6}Y!JT^({{^GUmAq_u?B zNBVmxmX&Py5eVOM;U!?sJ*;GV6T@M1GH4_VJk8#~rn;VdIRSV6u5*^1==VW<$j0Xu zJbTXCU%(K@S$knQYrmgOkh{1Kg56QZ_HNqC=;0$n_wT4yUvPN>XD{z!K z_4&kogz~l3dN_x37q8@XJkm>eM9C`@zEk1L6mF(h>Q$z_rkex}mCT3f=EZQ$U8>b| zA7o8ffvg@G^iPFw?feDw2`;kLve;}P$%jLZ=2FmWiOtVyYOFjJxjrhn-p{NMmqKP` zP8meQB}-T(e{&5tN1{RVlGZF3E|8`i&D(QF^a0YgClF<@C~`hdjs_os|Ho9X4{a9} z2VZ3S3{}lDQZ?HoeIzrK+d`#qEPc9UtNBT}%V1ry8!JocRp8U-^YDvhGN78DkH+t0 zH1}yCHrPmSg`X7TpV2Re2m4!*FVm_eHXD_e@7?W+#CnBo-p;)xoTbDrk0-ff!n;Va z60rtMfiO0KhD@QPBm!U-a{$(Er-JuSK3>7KV+x=OR?jQY0f zL7x%1-M-6*!3sC^qn8_t#9qAo|K=#MO5_5&U*TeM92 za`Gc&*9uHOlw*cz`X%JIJFZ_rk2Qzm(yAZZtmo%8qwcxQ(c03QAKX07ls~aXi#nK9 zdfDAfqaK%i)6L~?q$>O`e&uGpGI400Fqfhm&j>@Un%6uRw8L9O1ui?8swe_vK8!7F z4!dw(eK>tKwEkU`ho9R`TTYiiJl*n)dimsOZ|bGpQ?wgI>*?$uSf1fS@OVy_N2O2J zJdfw~#7`XJ%E0+-jWm5ZidvQ54tOL^%AIcqta)n=f@96z3<8GQfQ?qp5_j+C(^*}t zp@7Y2#%2wx$riE==QWBNxFMX^teMP%2Hv*=PsAH+QkDBi30>29N~=fpKEG$z<8rnI zq1bAP!R^JnptM+PAfD;;5pZ)bPb9xVAA7&v)|xI^Nm6fN-hFqUl{&Xm=68d;og*8n zK^~tp-LxR$Y+g;7;)z{_+_`Nx>pT8zJ({`9d0kt!D6G<9i|rMl&frt(({7C8Us&z2 zjal2T=@Grrh_I)%F%rg848r}K*B=TdnmI_sIll(KWJ&k;$}7k2{%CH%v%oE6m$9BNv4T~e z37ccF*}i)YIA-TEI=+0&o}@#WCV0L+-6MD&xqjNlKWcb&T++|?t!CEHstyMNTN|vu zS%l{E21hJ!q-_rO+I6b?N^S2A8%LrP?<51hRlwfhy#%sRk z-#wNsBapc}AomBH8XR=JeMT?8u^K1d+Z#x&HOWcAS=bn#v38=Yv(q{wPucrOMV^;v zT3ygB4V!*v?`FKy_4l*Pvua^tJdx@Rccd%@~pHlQ|)4=sT z0=-=V9ZbSXwhgrVkMOWobSgHwrz)p3`%G`<>GS(rEUb-^=|@%{)zu zQ!J_2&zV%(AEa7F!ol>Jy!mkJL%fW+&dL_~*Z_4Ay^;fE&M5zGPi`%`9pmg)n!8_G z_(6o|Tv}+2d+GA&+59Qy7GoTj(2cPTwV_wh9`S!pGAzo@o|Hfr5kehS)y8)o|m#|px-In1E9^q|?fK9pX> z$CDaxW}dujFQ~1_%s)05yzRa2|6I|234+*}2(4)+S7dLcOK?Uudtd(kX#W0H{%#~5 ze_u&&&QiQk474WL3+X?nv8u^t$I;AnZ1T-4_ z+|A0ZWETpgg~*e!l4@kJ`3Su#3(ObgaAMfKNE=pQY@fRUt6?DlpU<7hW#wTX+}7%) zg##^8{w3LupGQvppr?+-+xXvpxui^(nKUKHZm6a-bib-X-wffdjN7-1DBFr;?ZZ&` z7HdN*veg5w3%879`@9qeU$Ajo`T92y^8!;UfXm6|C2L{kq_2c+K88-T+#tiyP@!$l zCVTur#l7}V1lox*oR>z@SMQRGbe5;c4LA2i4cUD7MP$S^)SQ!-v(&gv)n><$6Rf#- zlBm7Ubuk-5Q>Q=^m8y$~oH-x(@jc(In~r7$2~q83rRvKzHthhUO(M4ClwHsfUmpZk zpfPeN!48`yMk1OpYb4yLra+CrS`0|W*74QlIjzL>Jts4PHNSz zG>)g#743{>$|Mt~RfgZ8WHq#`hc)fgbe_YV`aNXKfB4>caH_9u5=n2xT25zit|0A~ zt&Sy)Eiv$zNdSptiz_SM@Sfkt;u zSz_}&t58fiyG~k$V=|_ zI#HONj<^Wp*SZ6Jma=;bQRuC72UX5yXzwLiIs1!FWO?CWi@aLj=-fwSCHp`pva+y7 zk$gvkv+8~#mz1;5bYhp37Y?zs&sID()*D4p$-dU5s4N`nS<^0};92PD0rX_6+x8Ji z9gp9l<-BdeN=RGW>nE=zln2Jbc?scx<>9=t^uUU6Ufeyv*gvH%6BSmmubVWMhs*#- zw(f^T!}fMFZ(70kV+!DHW#w&!;%%bKAGR63938B;KPcZyR9e6hQvTnQyvDEGen_4d zHZ$X74NZo+l8o;vPh*<$$?A?s&J2%#JJ6(1?S2%5l9g^0a0Iem+PW4Yi(`!M6fOSV zc$=^ml^jAwT>iVkec>GFlcglTD)+;BJ3$P6|K;t10NLj4V3M_Ex6Va}FGX!&NhNuc z1pHs&!CY}ZZJ7pq7*gB$M+1s)@;*XNVfLV!+gq6Rne+VHJJ!BCeV^7#=i@D$k^Ae= zc0MztAc{LATR&M$C^25UAr&U{+f5O+CQ??#z-1{n6 zq{ooYqObnsE%$Q!Z)S12c_$r}GJOtf1ABg^-gWfN|DukHxxRA_DfzN$s+?$t6CKmH z4p)WB2WtTGgL`CwGXR{%jB(!IlB{kvw0{N*U0FSVD<)bv(%OZWs~XHftG{BJ8a$Yd z>~S9YE%4Q)G?4p76HIm+NH-V|K}^DVJ)Lb{_CfnSre1#guYunzk7O#Ep{79+He(U#PHB>3d5?h^r4P`@n)jZ70%)=a|$5GPaHw2^3ojHFh z&qCCh7DCc={)xOQ_L-OeL{V#Ft+ovU`009=Xd6PC#fRw%xhXBuxva&1&2` ze$wsC@`>hjDscp+OzPrLo64`>o%jrbe8>9Be=_2@!`*%MJ*OA&>ttXcWBWys@I(?ER7||e$&BnaZvZHgE=FIGo`7uPePn61!r?qkCak*pu0{P^Fgyx zx6=w0JFW01oHDw1hA%>crC0hnuaIApKj^RAKf@XNU!g|R$2fIcW)6*)eopa!nl}?Pu$q&Q;Ba2zKoP19KSrO%k1qQD9h@Y9CXAo2qD+r3Vwny-7 zDF1=H8gV{;BnC$H&*Q#Waluzs%;8ESlP7>* zHMIh`rimz;wpB1H4~a0nHTj_cQO#^-jf&H478oPoLY9hl;N1Jw5^GlvnqFB|(j4t; zmLb*)HtAJ!ce{omQ?_}%Le3Q?|0sr&e4lP3Y{Jxp2d`A-j+!3=S}W%lN$k>u)pksm zBjBv_sHZ`mJuE7N<#a7c&ZwMjHytU=nlCzoD=OqoT5T8NR8F^AlxF>x6zv=hY&-`O zM>m&wxkiF_kO`YO_{2?iwWqkGbCb77hMGBHN6O}}v!4*{?u=COoso*)Xi@Ij8PU&# z-bu5ub90FKT2vqDl#IKTo1@k3YKmoZEO-M@9YHBiLzHmLs7q;8W@j<+zp9oRll5Xe z9kw$*-|Nb+h8|a@p8~gN`eL3XKhj^(QS#W>=N0iFl=hv7jdnhWGaP8OxP*g!G!8cC z{5w$ByM6v!bDghZ7rAP>)Q8!wOaFby?;}gawvI~WWy}$ugpXakf_az+b5%>!+!NGk zHj(u`pxO(j>fyZHT zf27##%&C6|wQYMQPlK!wL~?NEfw`>gtV;g-j>gc8iJW(caS=8bL@4<+ziQt?e|)m> zYgqF7tzNcXOMh?R2WTbf9|4OpuWPoyPH>yg?6QlJQ>Z!FN;*%YWuV*Sr+L8a^T#`U zNZ4#NmLYuazAsLpQZkjN zo9&BJsGDxCFHWISLbtU1j#ZrOQv=Y0=4=(Bn6v*OoIeVhqD>qqRn05!{5Y+^^ej{o zE?W>x(-3|4`*#|3oK)dx_S>Tsr~C|n*~x{$`vo+d3>n?kMP-!RUo5cPt-FUJ(a~`Q z4+G!-Hw(%k(9P=8hN-AU0W2cwhsPe5O_{qklxzQ^xbj}>AP|H#dKzywRC=F zo6{O`x{-&OGfbO8*j@daP}6e>aT&_23;`YSHgXlL_ni0J`0XxG+fG7PiSin)Hb!ex z+Umj4U-R7b!#+=f$_uAshE*`#?3F_YV>x(i>nC)YV-#B}=q;90`1-oH&gVw!Ugf#Q zjnN^`HLeeNuEX5V*~xXra~<9(*BoPf9q!GwH+G0z?V3>KT3e*&nycY4sG;iMW7T?! zF*^#5rxYAXuZKQ9nwM>cwxnA@xQ=W}YdTB~nmT7s^J_vHBep4LUP#}pSofVKUm9pE zSr=|qW(oJs+c-(s>YxZ~tlbRHUn@_HfpO^AIaG7%iavKT6v@-bGfbaM%#guxbvU`E zi>ua-*1oTy6r~21lNV7!5hXz++Yv6CX9|w6Wa|w}_GYrT3*U*)!{hv}2?+w`E`Gzq z7N;k##R9*ZZ1_nNZ93R$$~x4fJ>&MlOkI2tX4L11`g{tsrDVqutc~2dX{tmyFwe~I zKg`zc$i#ZC5;OyF1^9E53rJ&5;H?(|jaF7bdN3^G6Q~@bL`*Ir%Co8@mx?U1*LSw7&Z@~}pjLf{it)QDUliOrHlXA| z$W1;wju{XY^U|_l6Vg<|-Rm0*H)!5+6cvmWY%0G`foQUQIav&u`Z?IWSpB)ONB9Mo z(K6buboDHa%8pw>+)kQDfB3es)ap^8?ZHO93aM#(A{nja>aI!MwOrjbsk_G5P^g>aH#=FRhrmSymqBTZ*~Dxx|tC9_z|O3U6@rsQJ6O-7$96r&mbB+9%_=xn90{ z-S@pRqQ#ZrwZKKgsuQn_T3#8|lx;P$S&qe^&=Bwf{=bd?kD?A*y!9viY5X4scP{^} zq6q6ZRxtpmDE{sCH&&Za*nBaxU20sF!+=44@1DSe4hn|Ew)rG^EQ4qEBKl5Z z#tUcjV!z7qetMk$Ky9gcw017C_d=DG52KrHhHA^sy_7}JZkr6(;j{wsJ9;Cm47%kS z#27M=$n)g5)>SayiL#4Ge8lX-5aC^6X3qc3*z_WZVcFw@KcmG?>P1VzRWBzJ?CG z+qCw>Wpv*|U6kfonLQ$u;1;muoEG1b)8eS5oBd~|B>$h)l_&!OT? z%Y9-$3I6Qm14>Ps@ox+9G!*0M9a4jjr^}P8P#ALqO)d7zD2J-aK9onFx?Kly#9SJE zzfPsk-SV>`%Y*%9e4n;x20JlN_OpRr`%%v%9X3=U$7{QCq?^ggmMYm>!Dbf4uoQ2x z)*JILAIMoDb65%kLy0OKRHq4d|=vcRw%1u)Ry68;~zaiRLHJJL@xzDhK~}`EW?}8u)EO zCZ9_^+XCmZmhHPjw$oXozaBa8>FCwO*TOIzhlzfrHaaiop)}aNqA+{f00_aUNQN^2 z+={KQ5sJ8N2JmhD0t@gmFD0WA+AIa*g@PU)iq;whZ)&_Ctzg$1PW$cZ;`(zk*Xa@K zIy&`4uT>(~Z+L?R7HQYAUN%#TQibNiSrFM z9hdF2z45i<^4|xCLtD!J25p!cZpH>2usaX@fTQJ-UQa^%W#)JaGYe@Sk8nd4SG8Xx z=2IorcJg!xTR+CcX+Hxfc_xph4l%|fd;2$Q8Y`>!V7=R}>i=c$U4SFKt~0UQjYl`; zfdP6n;*1Ckdq_$eiX3PF%u^at#G^6n)nEVu7|znB1T`8z2JLBdxB4*v^fDThvsRW$ zQEPeEN_IDvET>jkyCSWvtdv+A%WEa^#?n$%Vxm;pDY>joQB`6ksuC+ym9ozFopbO1 z=x%@`nMyV)afrX~`<{F5x#ygF?)mSJ!12E4{tI-8(244g00jbX(#C}CBYJPOZ(Pz( z7pU9gLTJCMWcjA+HPjavZO_q!?GSPpGW#=w$$R8<9f9Lo%Ql}pQN2%^Prhle*MgFC zT_$apxSsg8Fk&&^gt|xa5QoW8OaJ$+>bO7Xj~jO__Z&U&CLKI9_csn6_{`uz2g||Z zgKqc-PgLJ6a2&LK;sXad1u%I~+5CIX$27tNyQ*`j6@Lz9Dh2xVZ4}muZ*zX94}&JK z&*MAL$|MoTn)x)>4EMGYkTf~h!=6?6(%V+zAN(Dz3j6#F!l$3X^kXUG&W`rH_t-pF z{{pU?`7A1xKLmWp`aeAeV-EMkzwi2%fWiat6dnm6?Z1zozJvMw$bW?lcS!RgB-B2P z_I8*mS*M|lKYSXRAkSxA-|+psAARx4ACC3&u5AhESRE{1aCs6?SpJ1elYo{7YnD5b z{=nr)K+FH3OOt@6;dNUbj|4RBzjkR7(6oQ)(j=g1Uvg;@(6leRGzmzW&J)J>-?%&p zX!-xvrAZ)K{*PRq1ho8DT$%(T<+Y#xB>s_KC8_V=A?B2>>N2QLTn4-JTH?3;t9bat zN!;1=*o5Z$uIk5I%Twk}A?tC<5%qrK-m2>{+RSy`&^zigz4uhV!1d94yh~SZ?}_SP zN`kDHZri=^;kCGh?v>WwXfLw2AVPTHT14EH@Wv}VBpbq?O9lhn)hoR@;*YJ z0j!yL`9DIg>_n@B=kUc~i!l0FKPh7Z{=42qfa2YcP2#6VIViB-L+n3_N)hbyj-1c* zzNy3cx>nqlAnvG)D<@pGB<)g2|UkGZ~~Sxeu% zOTA@8?CV#Q-zs9Q5a>GnyTG#CaZEk|0RE-Ku{QrZx2`0BZjtt{nD!X72?p?rp2QvR z!o6XCjN~pVVX8M-er&I>=5{Ln!LPDN`8kY*cn;P5lW^TXMBX?4&HsV+jrj!rii_K| zy0Qx^}Z`AVTYO%2LNct(SS}T-GkDePj%YTogry9k2qv}0c z@*4GOuJ}lLzOhm)V*x@^}gsq z?+N~!pP1(Vg!%ukaNh^z=RbISlNk87Zs%vZn%gXtZjDS9>KnPrBk5@JPeTZ2$JfrU zU0fR-T|Iv`H=fgp{nLN;qd89YJJENlW;RXERPa(v!Q^q}8`eAidtBhcVcOpiKK^%z z1oGtT4p9%=KNfA)j-NT*)46&M1~UY4TbMDh<%78+Cw?_MbLnz!2rs7m(3l7AOOKuz zdDlCyT+9BQrxurrgz{i3@vrTUS{^8fYcjG%Q_-`7U9Wa zc?EfuBQZmZ&;wU*WT)}FgZM}OHR2yZWTIFs=cmf0TDj=qW;f4s;fZ=ZmtS|Wt6qJk zT=i~M%Z<|N%|dClylIf8p{4aInB#o441QV5u9~${b<8YX^VaHSX`ygy9Y1CX?Ntja zjXHWM6g^wmTQz8QBUhiR)WJ%h@QRfsZ>w(d<&8?YztXbP33CdqF1UF>V-QU+RfHn%TMHL3*N2F zR(lWAg=%|Zwv;b6R=vf>3bMU?y<9DLwf15}@@%elyFDkfB@OIdVDWaLGFd3)s@p6x z?bXo>Ca1ln#r5)Lrj#$Q0-f!-6UEKkb`AL5yU4V+mV?Z61+r_`%XRI~TWxR9j+{W% zZWik6q!Bx8}J4#-+Wlcf$*e60*JDR!7Wj;fZ= zRlKQn5LX+hnJviwn}yZ-`ptE(1Zj>z*39x6XvwRZ<*HH+Lit9uik@`=ndO2I#ayYl zZI+9m+_{QZ%@OxpBxJc#1mUN0#lk8Ztk&w;(jCUIQtQ=n(G+tlUU5`^#!P*yZt2vl z)B%Z*tY)5LCTK`w=NWS}!LlSzfh50vyM>w!lRA+h>s{r5rJK;YV&mbcEM0%qnMw&O zIf&l6<4}fjE?B9SZ&krxCUbyzrO4&nsIlhNYGKtC@;K*M{C5gK^eB71UbZyChz-tH zy*mYO(=}6*@#rGt2&QtSyjNuTmZhSY8fTeBuZUGa?5&lH=xefC-UO4GF64^kTcc89 zGgmS7a=Exvs4TMv<3QXVt1E=l4g~Hu6kz@}O6}84c-e*NMu%78w1QxvOI5?ylH{yDOGA%Vm*cwYw`nYL@Tl z9wH0IQ1S36VY%MIhQVA>0l^j6#$J%Ohs1E0?^I>6k*9oa&l0XUi>%zO4y;b(Bt>sq zMXW~IBhBVY#)a(`$gC=7&z5R+t|p`0a&-}0ZT6f3Kr~quD;%$;W%F>^hD+5U6j~kau&T@HNUQ!PCEqT zvE(}o-uoLK_Mn{vpe<7DoXIf=Io(9C8s74*cC$2pp=R5|Jltc=enOt^+wiY@<^lFe*C7<_ z4$IK(QrgCU9%vCTFq^P zP)g;n8qE z;n&O7ZeXg`(Cn(2^~fP6M8pRGOy*V>3%Af8%#whXw12kF>ka8F+^tQ3WK_v_9#1!PNWW!qM=LvmL$8w_W&;~D=v1#+n--5y zRb8oNS@b0 zzrIwS2jk#`(FWAX#;{zZ6=_**JkSTLx5)iPcwK{F4F!Yw)9e-+50%y&k;3N6d|3@d z0G7&5yHH!k`hn%^M(Orusk~WoOBLJsoNv)uu2|XzdTi)s6$@YX`YJ}Sp|_&OEJHAb zMFDkv#JP;yka%Um%X<)dt9u9yNEMI@v~zTJ4RU-6oTaUi<(lQCX1Ro-03Bv*JUU3k zS!7&U$ZcA#-QLuySRt(4!pab{jIE2}Ghj$|yJ4s&f%}-*@*QukbRDXpt2NmuaO*sk z1A8pgx1CJ0@=4Vpm*|+t&2p7ASoJJ`*Gy*UFn92Myn-fDzJ^6N&mjJdJ$<$*X}4EsCuunnZUbdELTvQ^oK%k033;iOnQ` z#`Fi9C&td{&v^$q)C4DV+NRb5pV=zFRI}=F-W>Lo8=2)*psx(}0|hZ;+_V+B%tNUi z=nF%3YpG=^tz#PPin&6QGc=D5Yhf?*9oUmjK--wEJXI)T*Wh8lyq7lTNY|twKO%qe0}bE zCLF&wnOzFUFSW#{C#M#}`A;m(UJJ*s-Fe3q35?2ba(*HE6kvQRv#=C_Z*k(OiOFl3 z4v@Q?4)8rSaSezG8khL;^=pe}b#tbe!wE~H;A5>(n8|Gvs8U!oZq`09?bY(IYzYrQ z^rp8Wc43Gr#Ga6Y<50q6d38G!ohfX2I8uSJcm^h1)}Tm*YA9St(pIicXI+g(Aq(DC zEy2KTP4BGYavdGbEC=JXq!pS@KgEtb8kdm=4b3lPKm$)@mgg3xiEF0RjC9chaMoL+Rm-bF_?pc;br$?Al|d8W-a^=t`jJ8#w(yp1x>zm{wDa^G5J-kECe6BO>Ab?z< z1eK$$F{mK4V_F3_r>4%bH73)hHc`SMha9VnKouXEply7zyfp$6RYw&VM%zl!_)fXD ze<`vXY=v=*ID)ydZZAQ*BRpd?(7TtN{=QVGBbi;6g)-;ye>-35J?v*F?LMO`7JJePGh*@c)^;B7k zwVgF9F7`QIRwV6Lfbi^nj>7LLslpb6GR7>dt0yEYsL18MUBsHx3oLYUZRxuPUa0$Mg+n zosFpIFj&z!Sb!!QbyyQ>CQ}N>Zd9-(_4B67tcQKqZD~Xsn9r4Pp8EvU+i;wngcf*E zs4bBtt!Tjrd2AUJ?v#$bdVxR@b;d=g58!;h#*W)@-8UZ5l`wZXX(o#4So} zu8%gbL$urR?A`W)<81JRWeX0sy-0BjIh<@yd|Q$n$f5fFG5zusG!i8UKtPuTun%#} zu;>yV=u?!?SG4kU8J?1!HUTRnh@uEP7l6!cQP<5CA@eNhSiOp;$Z!)99gATdCF^!h zosnaDAqwhuH6aHL0dX*_L94QuqTryy;K&-vT`qFwA7IpB1t+%CFb*k7ORLMFc!-+( zWb{aP0NV~0rBmf=rt_ho_K5nk;J-IA!o&|!DFlj~Dh(ROe;vFwT{ZtuG)hskhSo{tUpN^?FfsGVO z7JTg=+OA71deDR%x-`)>(o&XsFQ~NvE(cjCZF0WlI1VZ@03e8GRZ0eqHzFE?=q*Zt zh}cyT%yb_N*6|}Fc~O{v3#%1n!40E_``KD%qXLT;R{}Q{j?#pm3d|v<%7!?MNI?b5 z+1M0j7ZcFv2xHImMGy#&cL^-vpX*C@5Q8nUP?c3~vNah071C@?l4R@^WJt^(vWtsL z)FKbCX-CMER>ecE_`^g4&U$vk>Yn)1;LOJb)+t-+D-z|dBx_0;oC1D$8 zeIDp;XhAVoUJE#-$e@@H5;MkNj-xN0{c+eAJ}JAln%l!^xjhPm_H`Y~=~j=Zhw9Mo zQsI<}4mqp?(%}KVlyYGuHdP{Pme^d3c`f>*7HLcDR8m)>EWQ>WjbM$2oi3#FNCI1J zbG(pZ?Wy6iJQ~+Ur;>wl=97=M8Ft=^PEdWP{CEF4hyD@;FJk3FPKT_cqJRg!nPqD zbJXKQs#ExIefnD#Cdd{wE5f~nhONhe6oOe@@aWqBV20Vi;Xz9xHOH_YG1g^h{rR&Y z)(;Mpr6r;;tEY*D)ka)S*we%>5lM6<-4gRl`3Wo$c%4XoD9T)`B1x7DGd=8fBAJl{ z={e+jqCJNbqz&EMWg%e2_f$^5v~epfSM3aNl871~aODY1p4_f`a?0P5H#s-UteR~B zP7mak*%A}g&t-Bu#AL9N;M-X)-B_GhoXTcd%GO+L)GCF10nU502RgZ74}NqQ^hA(_ zCO!#Fv)N1xm4scuI>|`!P?U8*g@R$p^COw}!?C1hu6m?Wc)HUnDEN{hZyIPc zqKvy=V$0ICu1lBC_K4kp@99z#GarW_0o}q#5WooU((?=fPU>e%V5i{yW$dza3&muV zhI$M>5jZMwIKk+70AXp%s^Zq)o}Gy`QKwtVu$sAvGr4@O3dbhE0p!yn#;!!|F4c8@ z*@;x4YO^KF+V;X6M=q1wvfii_wvNHdxz>>|8G2@?icmPN36Oq6r01<2D z+{S7NoN^E$NiF$aIc5=uHf-20PT2g2n79{l7y&1A3DZY})(8VlS)8Ek?_5>&W<-C< ztCmBY$~k06FCwMcg9OA+2tF<~ND8l7$lJ9FZ04$k9PB_eDCFvL8Y0!5L3VG43Y{$M zs^|r?Pq76LuGu(1a3d9g;S%jcMx#D*C|HL*_F1PO!HTJH!wpQcu$EIi1O73kC(i4Y(VJZ4>0Hrcy0tUrOvfE$Dq zmT7?vD~JSEWxutMrCHK+l=Sm-2Ix?-<$QbQjVkrEc%{fRwz{f_!)C6kzF989^=>5u z@QahDhVCAX;0U0qJ>_OKM<;~2HLMK!WCR68=CmeF!Z{yi1o-Q~V(96+RM>^p;Mk#~ z_2)ZVQ^!ExZ!21iPJ^McSRRu+Tv;mHMWqve17A<9k|QmkODU5embz7{_A9 z=xu~V1i`3)>ta*TT-bT z-}&iC-HsWU6d@Tqkv_`+bJBDK03hF;BEyn2U&RZ&cN93^nFlkmR>r=2p+SWtXhOoF ziN$MJp0|qS;mTXz3D$FIZ8DLLL*i}IF^4#r(s!K%homn%58UF4bC9IbOGq>oD1~I< z{)riRmz0q0f$%|{XkR|MT|%cknG@^nQ{(*Du)yUz|1c+d5@khB#BGSBI;FEMu!dSS%Ni9%WC0Q$8M2Pc(AR2qY7&hl2SEN9{94aK`o^E|Mv zh!jaEDSWk1raC@NUL@-8av`JM286-ueNx3hg|bh;dB)(@&;xfK$Z z+Os%P3DU&4ubkUyTv}wdAYSYO4ogNkM_aOzscfsAJC9$+;!9~nQdPqtZow&qaD6%v z&~(u1xFvdlv$RP>+LKzkdI=tppuC=;G0A0U+z*}eL+6RLrLs@y#3oh^i_TVnr}^*D#JOjHBp7WKq8_Zb~8W1JRS*Q2Zn8?Iy4IkRO|E?fzQUS$O$%)p$LyS zuL+NgrVwFmTujQfr?M=8ka^aV*HDzX+0HI+T;O|Tu@*;*mFrBQEZvgCQqX?IRZa)t zBFs?|mUJ6rs_!T#89|JBZoRlwB}Lj2!zGpIBjs#TxKxLQ7OB!HA4)_mUnmGS05i(0 zt$|yC*}0wNo*C#L6i9zN-Phvfms@3WK<6qIP1dq|WV&Q$=WuOBE4f@zplCy=l*um{Q^2f8T6ayC8BrjY{A3cMO24%2?}bQ#2O$GTyJBTHp# zpur*wicp-obTK-D8^8&xUS<0lK*~)f;1@rWjkTN1lO#fAljuYxX*Wtm7eo!&qX@7z zgtUoBYZGiulKj>ta3GSuEos`C1hZn2MqSJ!6P8il3W$zb;wxr4W$C!uasqHWW$jgo zmfCQ6B4H2ETvmHil7s&D%3&uMuD<>?2cI$}0@-9Ey*1wAnV2axHe3kn?Z0Qin(kl3*g9&A_(#kn%RnGgiwksFN zE}cKyIk$H7jfID;&wSy$R>Fk^mZNn}4hF2Nj12?zw;}ZG#D=DGk0L<{SXG3L_^l9W z5lU*$j}TTgd+aWt2+HgY#uz!qesD+u0_~5wWgt>uUr56g-8zak3eV1BPg$V5XCrsZ z;}F7pVc*;k^#aCyno$O^ZxMfqw6}!yRHrqXtjn>5*0wBC!H1O9wLpXH7EalrfmT-4 zp@>^JZf^GKtd$YAHpP`1u;OU$_`XxnlDqd5>|GEmdfy(y>o7d2EiHDM)RrQ9P3m67 zIzjf@vp){wJ5R|uDN)ARI!rAWQPSE_5f!1WEri8ar##0+Tl4m%&vD@imdQmJdW4K4 z#X3-)wrG4A`|tXooX!qxms0(j_hB!M+2&>_S_B%K92rL+8^{~7~J1u@CvI}MV|08@esJS067g}Ik6 zNx(EIzj&4_>e&@4#3t-35>nrV?Xe@|fkMWqA*SJgMcw9 z8)Rx2Xu=VWyL`NG;Kt>OgpydwK`(?H9*!hP2`YZlxx7;$)9pJXu!bLDX?=}C2O)1% z*z)!z3d!&d#5fBe)P<7U8{!lVmlB8%n+@Rr1qM~ThFayB9I{*jf^e0fCX08uJ@E@b z(oz){O2Ew?P6CpS!wQ!rJOCOkp`6R>+pzLRHVz{xZ}55qcLGRe!$UM`0BY!E%2Wd{5N-J9ExNq*?G0Li zOEBzXGXY0Lj)MYo5?dcuq=|xu7sMzgIRh_T+++vNf;``e=Bdz2A7MGg#z1ubOCDkk z#JzlU_kjKQT5cOn%5XSfc~6T|PeXycLC1)6!hoN>lv`161EwM(Yd;5HA#MuXD!FPq67Xovn#2poJn-6v&4zWv@()f7Z(5BP zN`;M3d>$ZitH`o+uFZn429eSdUaMHa;jv_smnjLN3>Wr>XOV-~GS|?#jS;x(aDnA7 zZOnGM_`(p+ii<^e+6>+X97?uOiu3{zBd-%F%fv)U!UWa^+k>gCh$Uh0LJ?#LE8x%! zE{l58qxQrDeDGXm(iht999bKVx!7N0$LwIDkH3&ppxK;eeWPM+}Ono1V8 zLFt;WePV&7W3agV!C6kK@07qoA};*`mS2QhQ$=cS)vHgsY4!6#1@`4J=RdoMqbDdn zbi*zIt8-jlliLOk{^Sj?tpL$-B+Ek&<;gPBG6|l&W?-pW*id?wJg&2i92AmV6<&&l zTtVL@;MhbiE?WJD#l;~7^eiKuTMG@yTNR9O-Rez#GBh2G%@eF+(7bAqVR-tJaatnb zsuGCsR%sP4Fd`S{Yc*v+%9oWid?xA|SM*yiOCX4?wDO*|*=8Z##oVZZq$LV1P!Ql= zL0}?Wc|nWd^}@%vymej{u|WoZay*N8vjpT=nBWSSwkuC|AVp3Ro5g6$n`pa=8N*zW z7qld+e(UEbPtfHJe-5q)a$lbzOY@2mX^Cr4+)LOjTCp|Vx?-wNY0`+yy#F$ai-q4V zVVy~g;C8^$$s}?Z6U>OgyvqJV3j5e%%u*PGVUfqU-n~N}7tUFPT!s$ z7ZRDqiKe8iOtv_QT~Lk(7$8pp|+_BAa=Tu2fjVVFp3q8v$&;hEq!1YC2clryPb&tE#A#GE#;>@P?OHkmJok!4R!l z7z%EGl~FKNa0F+VRdq005QUUOBprhZQNVHIRI9_&k_W1eOW?v?q;Xx4`9SarKV*+J zyiKGL49T4uVGo8&0dPaC^z4pG@>-VoVIqn*G$4RELEL{%sLHaGgP%9+ za|7+Jg2Tz{G}J^E*DRHri$%|q9j?<9+1LshgUmXV=&k&^DAYXYl8ItOl*M?yP$pY5KD%|11iE^I+a}iJ>8dts@I?u2?Qj}Y(ad>42q94wbM5?4>y>j0#@axFj3g${+mrD?b zIErzH=aS|-6S|{i7PPK8E(!2uzzMg*l<5QRzbr1zVL}z3sDpK9Jq6jO?A3AeAu->w z4`Gs)nMLs2jVDBQA5pscmE*Q;G?`K(zb#r`O-#>(Hah^59ZT3F7%qMXA~?F*$d zxCKjmrG2&{6@5|=(0LyPH3r{RL%5+7w6kO{i)Pc#@T>sT^hGOium?h*c;w*qDf>C5 zDSx2M#(nSHhv3RMBO778_T42(&-Ty&__ZvF-RTQks|ozix1&9UMTAMYlM({7Eqv#>R$QRJl=p#M|=BZQguR93LCO z#TI_VG{C!U8g71qLTPX@hg<`|1%F3&8|(1WFstD1ZfOY@U5DU+{sQ@AHboZ)d9gl! zAeF4?#nhkyLAgb&XfR6(d&s0_E#BAqk3=a1s`I%@p{$PYEo=6!5a5f}>5{sR9*MDIg>E ztSf{>aCtlwW*~SyXWwxID#P!P`>g>Z_8tH)`mU9M8sB~)J-~=M)vzJF&1-6%FP9e- z__EVBDZJR4Al&Z5fiE-U5N@#Uu(np@t(0;F2waW6*)PzGZjZI)CbfVCQ{?27RqDby zlm6;39TZof^r3MUH8r`ql`9Cmn*Ou|OHge!6d!Cq7m|khiT@Hz==N8V8g&fgzeVF- znPL0*lhKPBP~L z)MPKD!c>^Xkxqpe)NjU za_K2x0^)817h@QFaDlhqt;y!V6Yp7>0q5^1?I}%LVxjxgH6DN8okNTBT6HWnL9Fr1dI(qZ*RBwGW^blh3d7 zr-I*!JgnB=m}zX*t8i1!W3qr9z(L zN^@s`S2NJE4M_FXP2k5-3h;~>^JAE0v6-v}7wlBH#dZEz;js4Qaw_37+Db(nYcPFS zrM^doofyolrA3Hjs4)cy65P4$rxCS5EL!F{Rc;BPopRlPTu=@TXkEq4qUI1(Ff-5hysDW}hcq$+ z7zOe;W_6=Nd!_cYVr8-7<#ELpDGoi>v7NGz8yvbq>Al5gh2a^G#$y0z*BK|C%ML$t zYip!igt#bazU0cY3)hy>J*F11N9Tyx)APz5T=$1=R>aJJUzUd6gUjydO(h8l0@%cw0a$kGWx>AXmfuQQ8@|A=e{3 z7lY&y>FDC%EdFhjE)ANZoX5F1O)IMP1Sxvi8aJo&WF_`3FWAMbSd@h_;}ku+%Md9K zgHc3R>Tow1USEdx+-avk)m1cBQD;Jzi*Y>$FE%UvQEJmX?=Q0Uo4;DL@+_p2|4}Ii zf~dlfcDQ%L-Lv8Fh@-9O4y`>wL5$pl!71b&NLKoR_FM|@wqV<8Kj2Vp z7^DE&1o&=4r5jE@ah!#5qac(+M=}16fDH)MGa#EX1|s(>Fu}(lHqLJM=R6F=@Mg&= zddUItFWX;xzGJ}V@mUQ+;?*5E-zAmy2x9mf88XV6k@xUHV|JIqR|*B%wwFIZFc`hn z$n6}7p~%3vWj{jUE5fi=LamU7(0|Z8B7P4DN17p^eoH(F^h*XWOM_>IzvcjoSZMQv zRj*o{uekCE!Dk~h9d^El9azJ)>kD#Z+4eH6ePfnNJ-`KCNh>mNRf%09xU6szDA}Y5 z`ck;pG3{HTNb#K$6mUO_zQ_xHFo(Ci#76@;Hw+yw1#f)|Pmv(oCtOt}zm7^YEBvOKd%*_gL2Lnp znYyG7FUCl|Fe#j#$xtN4AC7dUBuIK66{;VT=eRu2$@4tkK9T(oC|I|bQTE+N=|G(S zijx{t+xEc}8JK9tyg-J!T~}yL@UD>?p2LZ835o(g+F|%6?7`N_do3b#J2|7#X+-&$ zc)>w6bf1+1>*J-mM$g#fN%_#qcvKMycplgVr9GU`oXeHD41Q`nOT>N;M*eT=>ua`~&UR?wKO&5L1a5$6_`)31}vvnjm=mOye#9WH}Ahp=B2 z7bCGsfq3|G0cc&v=&mnB!i{l78giuB7CgbBV5=r z3ko7w>0iOwl|{hVR2iW}!vncnRjRl>*#KKzN}_GEly{ zgYuvwvHdBM;4ACy39t!@;H&t&Z6%T-yJ*d%i6`sY37PxmN^Vz2n6V|d{y91b5o@7T z5Fib8+KGzAFlL0GlWbb0N(PpyLT$Y@*=PL%s1*tl_FXmDWH8ZA-M?1Az5g|@Jwxt? z4U&~BD+Zi06Rb?8&~VmDpPkZt5g_1MEbC8TFSB@Yaw!|eQ)`&$78fVC=;>&I-8Qzl zBf1Rrb(a>?gdoPf;bNvbSuZ*zP8DP|16p9pgtwDA6-?l-4 zNYp`ZUw5*7b4w4Nb=yYCzT{OjN?d-!IqJ`jOXMQ&Jux2cWW1$Q3s=Ollx57>ek5WI z6X6kJqdsB#QiLGkrpfB1Uc84JsXP;LZ^XH;1x(G`*TUQ+3U$ReZ+c`cmd9K7)YseE971%wA=YS-#OyV0kt> zeQh}la|n4NNGPDr()q$T6(Q<@O0y(^F9mvOc#@4?Ho zUB9-c_YOR1#*{$u#h9CgM$-Yo#1Re|k#t+ItxcD&W6eNkr*2%F*)22qs z)V9Gm)(-YLQApqhgIl6EM)V`&wGpx+tUwUDx@)<7%5C{rIL(Xr)}o(W;}h31j*CY+$I<*3>`4&@7cW5 zyI5)ls!WUHoJDm=t#+=3){6i-rhYafOP%C>qptU$Ms37;dvKzic8-G9>%l^+F~ZB6 zjVa;ikF6Jk8y6MdMW*X*-PCV+C;3zS^fOT8e@$A}2NL9?(V)Dx?>R%qR}Vf=+De%% z2EKRg-zT1Fl=4tbBK*vO4M0sWPZm&dx+ig~|6V8`q6{DK(oC3!x z#h~v~wsSw_#4GhWHsBW#DH4f=TK3b$v}QNnyb;v;Si?^!z?L`-g=Q6W;IkPh5Bjy9 z&;=Q;vI9wZfGnxd6uI1vv*a>$b_BoN*4xjOyV0wljIL5wlYXP>SPP=@uR4byq>vP~ zN1U=S5UOYZStOy2%J$Y4(;vHI;`*>b5W_mj19Mc}Mtw6|$XClXe6okq5ev)Z!Lh!I zqXT+>IyoFD*FneO4v@i`P-gUf%A;!tOsAybD7We{^T zh!fMfH94>h>OvI>O~OswtO1S8)5|*}S-5|_umKyJGah4+fL0umFl2uDR>p;nu|ULa zQ{rL)2yr5u1X&IO#^?`In2%k`K)DhN1NPcXHbv_!3C4ML22+9!{VIh5Y0g$1Ggqf9 zS5_$HCagu+g#7g+;JH-@zis$ojYJAq#vub$$B3!9*#PF2szPVw3R<{>eLYQn)!I5x zcC~?{L&1XRvK-w71f@b&D%5C~eypbiw{lV@_~Sq(2jw-+;XYmEA-wRiRgG8!@}P##2vG7r6_+Y1fZz=R% zRu}+NUP=3x<|1G)9g&gNVt=lm6lrQ$#F}&X3#u zOXjv=&IZa8L)*q2X^GoXQOMdMy(W0RZOmXWCzEJ-%a~I$lD7&hPM{C|E?~65JeX4% zjC9FjFKrf4FN#0YeD@8YHHYDNnAo&AfPZUftSYF7BMs8d;9njUHRL8fZSI$*w}6H; zLS;N1K=<3SQL^Y%BMLCTNl#_l(;L#GRh*weielsm0k_bG}k+zN0 zd5o!!DRPhy>LO~-BE5#mVZFCujBk??+9C;><7^1&F5(y0WVWjb&X=Qbb1=v;!_it?h#n}6GrS2#r3;hn zjP>0JOv3!MMgx*y#_cq>L7<}${dTf1$R289tldZz8RgvjBx%r7RMep zrA1N+u})};g2z?X*q#uW(|o@Hc;PHIT2eM8rzky=4sW9cH|MRZa})WTZKbs|N|Jrm zWj%3JWP6;KcVX<&b(mTeb2JO6xR&5-j24MYGZ?MCYD~{{z-basO9^xI zek*jidOv7JDSi^V5(7%&>~STVKGF}_pE(k3*E}?foIKzzqawIc zr6FFp%nIm}>}eIE#++i=n@Cf35oM&(+FQdVoF>_!+?!c$MsUDUk}*<0aYYtK_RW04CHT5$0{!c_rjf>U3VVZB?o_AdjQ#Xl_1n=)87)#Y5@(!oCqm3& zYUL|PFM^SpgN|8ZgrS_VHl|Dr)InEpVnp4LPI+tvX{FZGP+RA~l9gGr4{gIT?@+1p zXy4Im+E>d^;~uTy@;IZy<`b%}nR~Q7-Da zVV9?BP*mMCqppp+RSwPDv*i zsF)N%HxT}I$3?0NrHV=r#7PGg;HnIDgBar)oCFrg6Ll}Ph}KBuRFqA^s+ks=t0;%J zep`D!s(9vXJ5|aYj>JwVmZ*%7?m{Z%IQNX?OS-N}6OLoAAw=Fqm4ZsMavG>-gHcF1 zc1KG%szMFjHkh|NwVflqC79w!seqBwyYag{uX#YBj6z7R9#UUJD{b7Ed$~OcQzYwh zRRPa$*4CmW+E(8Qu0Fg(fq#@jj9IC3La|C^%E>9a+J8BmrnqsEEe#dhNslo8lt(f} z_p?g(X&GC}+LWyhw}F&JY&}YW z!B&mxeOOsf3q0Hs5`N<2t(d#mI~^s4Ih7k>&6n*exucY3-q{K_=gX}CH?L0S2kV6^ z#LO;YBxQ^zz>SVisiAW%HwIk^j+1~2?sK!HZMJO}?+tn*Z_T4;@?hCqKFLuqmIppL z|6Fg;GSOL6?Zj=1IScGP7>7BcE6L&698uor$B$`z0sREDY#z`tC=bX0M}&vE&lFnc zOap7D9ETtdU4CFXK#6;l*R){(W`gLL$XWB?Vk=n=NDopRo4zJ%JP&8qB-g##&`F+xLviy^EGkJq4K5oDyy! z?YCjhP|H#Jxr_D=2G%qqS|cH%p2+QM*s|t0M$4@AIipxCL2P34**AhG`J+jwoHv7R zT{v!Q`j|qhGY?QFC#TxRjJmmRoe$D`h*AdC5=&jvZi;2=%av!kFt6E1&Fk~e9CXqZ zlyz(xGa5EZuzzzX}+4T%$-7}z#5m<`dpLsZokp?n{CV;)nY39DykUnBQBHorT zR&sK4-)rb}N0`q!b28R(=)2_TCmiQ!TP5eC3`OO*ssUQD@6{A*j7v5Q%Zm6UNyMolv=4Qo0=(y}uo@`Ql9 zK!ESk4E{2>IQNNg{)V3W9v_PPvAXfsb3csEX6Mt6>8ZV3*&HqDI!*i8+Ld9k zBuVarW?Y`<fP_Njf2ie=E*2-$9IRLhY`1gys`QOAbE z5W5;A&!EPB%qj*&Q}IA_b=pwI?$Htr$q$%N?7XIP`O=(ncdRIOpR3hb$%(yF^P?kh zW8Pnti#-sAGy`~@auF~g2lZ&3raD^x?cOqA(xX<)IOzxy_4#qKXk<*>uMI~h>}-2&RjGLr>O zme46T-FDWrjb%)ns98rvuqSG~3LJA|zuwYf_8`scHr9!!{Y5QCKCyqRF84{mMZEF2 zmryG66JhmM9iJ-+r)lIX!w-xfFxhmCK%M0J$br4lF3% z_D`0d4hcRzBh~q%Qq8e%m{X$A;O+;sg7>{qmnBrO))MC3+~5c8a-3_noZIkeNhd5F z7PJo@)boJcV_$e>CG|s6GlNvEHPMo4UTW*40WW%cGr5v?6D`P}*9dp<$8A z+byVSR!x1+5=to?Jh64B#~c3IVZZ7<5wu4`o@*&kdEHpJndb2hxZ@GZ!Zoy@rWe!4 zzGPcJPOeToP`6eaf?SAP9Ic&D)l<{R1C~&e>Z`fvM!_>@rm!92iz6c@ zSyNqVI7a1XXfeT4ZOD@z>Kw5y{2f)5nlgPwcxt%y_B=NW++2~nyBVVdHiOF1oq~;i z&O10;bM|egoJHG|5$r>$h7y8YoHU~xUFn1~RR!cU@q`WQ8gG?zJltW9a(ZG^DCf;I zn6p*w#m%0RMk={Y-eKRlV$sCyWLZEp6x5C4D2u2Z5 zDOak~ug!hbS!mEB_3PSGV<%Syw6Axz=aW)+1jBjNjl1rl*d}S1bj=>jVNxG?1My;p z+wn}#4{Pk)`L|O7ZrIO`ONYR`1OK9^X|;TiMA#8Q4jf~23Ftzjw;X}u87^7Kwwzu? zr+oso)#mBghhvMK>IPnZ?e)l>PGdpf)EvK4^2<#ZPTWH$TwGK>Glv~k(WY*B=I|zv zrXmN(>rwlg6E!^3b>Xp4csvw77YgItb-9&kZ^*PbCL5k~CrBu6bm@`VQ;DbB47W#V55u|c6O3_L- z-5HCWD4y(D*)o?HnPspBsBCb6WB?8#mLMeBGsTjdU8Q=mL*RIjt0Zvn!$Ph((Z?km zocM-S9~Bd zQL;kSthgT!G|cewZ8wn9xk&9KT=LX!XzS_RuM=CUlRIj6EJ3BeuSY+*R~zj}>x3Z3 z%qfnn4tkI^)v95}J2`MUO3GsAuDc8BXQcI8*gBerNdlZ|vdpaC7Ab{mgsg@w)XXxD zmWgRHB5D$(LS3<3Jvy<$;cr;S)wL8bLzac+c7oD^+ij9WP!lWcCmsjH^1CQg=l~Op zZVY_n?nZ~P^>L)+MCP!rVYT&`Ii_)h;neWx+?)ggRxLQXc1iSXS2-8P_D)hPDUnB$ zYB!`HW*vOK4E=;Pb87mu4RMa4J@5RZB?L*5(UiO~z0Bb?PSq%c<6xVq5q) z1fE=4z{%0}p3E`gTXk(3TU2)WhgUu&n$?gNF-Fs}X zc|($r+mFVPliK-WFY2I0#y`e512G0rU;6n%ygzP1Nylx6>FxuuR5~ForqU?cgPwK| z$NKp*$RGB_7}}DbkHz`{{_d%Gf2#RyWbeK?X2;dv5Aga40Eg6kl}$g6es*VL7>uUw z8m7L_cF189#w8{$F@li*2W+(KAZmOmp4xpnwe!&)VzmDVpEk9S+IilUV7Lb@>^zSW zjc|zp^#1XFbk+5BQiuWndXo z>QIM-{sZB*lgJOD7Ws~NxOOl<{X%Q_P3^ous$*#Pcx0+lTO^*X$fTsU03ud_-?7AF zp*R5x%%B7=fD;DcJFOxpOshY2nQ3yD%N{Lrl z=Vj1x_j_Z;#PDyR^{k$W{MX$B4%m%9gp-h?@*k4<+l|VmJI)8AOhtj1>8Az~Sa!!+ zEdx|9_BZFo-(i;A=HT_*ay;c4eSLQvRo5)_lVG#)v)sR4a9vW}Xf-M+a@#EvBj%i| z_LCTyOVp96CjGx-W8Qf#FxWWr)&F;ACC@mFQ8VkLIR@tJ0Bq_VcXJ4`^XETLmYr3% z=cYmzUI^6jUoR8g&Og|%mrjag`#PYiP1XJNve5a9@h3ZC+WE$m>{)(ZY|=ZwMaKUh zqHX1MV9>M-M2FUi)&lF<&hw6OMAyPzLg8m`Uz~rv4KX|4ni7%V_E0|`2CJBXMia*~ zZsOghdk30L_dFh{1yDfvJPt2Bm>B*`wXfn{J)FT0&t~4+ssIIBXmX*y?a_#;VSv!8 zVX;=_jPdRy9|L@-!iGdm6D1Dm11y&29BpDET! z`#EWpJrpyEwNh2SPHE6S!G+s7G~LYgB`?38Uc`Mdyj}@Lij!1ym*Q{a7oc$wkbj*M zZ>-s@#Uf4h5ONcKJ`^(#uH@^1M+EpmdwVS}N=)V-o=)g|)-4jtUU1m9e<*+2cE-kw#AGw=B}D^0_N4 z(R6t&jgMI4T0k9K2%!0xIfPGF`X3&OG&F8mgl)-NO?&q920)L0d0ZNyw1N>^ zYUJBUksc?rYe9d7TDnxO2ZO_u*UB4S8rK1Cr>nTBFim2wJt8pF*HIkTF^76y0<*Pr z#krR6{^AQ3awDWyi}d?Yl(;tW2@aIR1oQJ@LTpv}-cXpzu)2n7`+U49(!nMD4tF}Z z6gxeZF07?V0XMUFW!CoCOAIq2XMPncf=4QL0B;zTbXKC|zF%LM(&a z#JVkSrZEP5)-luumRh1%me00E8X4g|)8vxKRNCI;_mP=WBV4ZCwg%6^8UhjseU&QG z?lH|!3dt4Id44T01W$_?kmy@tW(OjH3->TT8@(xaVB(AMNa)L!02k1+8vAL=KK?Um z_h$v~UANl_k3m`=grwXf8z>4vrms5$Nu5FzwCninLS%YRI0huEkJ)K_1J3hGBM|5# z{@13`kETE9M?U;W+I>%o=`M`RY636?0O&GQ4bWj|+O1}?Umob^anyS)`ngLo>s2Tq z=pUTEaAEqw%;igGrluz*&Ww&upFJ~qX>9Dw*|Sq;&&^C-o*W;Y!MWL8mwY5<-WvHT z!pPnqfCx8xd4B)^F_l65@V^lJfO7i6`KipA$%|*FE&QXGE&=|DiL+ph*FJAy%-L|L^637RTZcSzeljzb!H_3srtOd?+q;xn>|}as3ZK2WaPG|5 zUTFo|u|C zb75k1`tsC7W-@aY`;HcrgjPjpTF35UT0{7>#4vsrwFLdsQ{$JXN2kwBogF{xc*f{t z3(sf))Dhl9=KRd)In*1!bZJu2dTIR9*$`SM;K&%BJ0C&QW9KHOrh%5piHl>l-#sQU z+__AqR>j=EW>pqHJ9TkCAb%I?kQDcoFXItyAGfh>w%-KT^tB zjth?|7h>$}S$}EC(0=i-^Zg4%`~neNM8BYeU*O;ubnx@K46x-t2jdL3-~I;%u+7ia z)44o9mQYLU&Hq<$g*h&FcUHs4;M?}M<_m9vQ7)>d#*T_r}Z{JIv6{>(IpZ%lny3-cQ@;KK1q+!+v@DG`TN{?Ne``tbLo@ zH*>!+?3ee`0`t?>+jkKAX6`qN{qnkcQ+@b5jK9I|-c<9!cyB!3+aK>uB4rwXtN7c- z-w^(e;qSvJwbSI|*ZBAtA0OxA6MXz8AD`mmpYZW%K7N;v&++m5eeh9JS6Fdwr7!FO zn*`TYw0_8yNXJp3`2#*)LHZ*I?Dp`{m!O{;JXGZuE~@;66JdXM@8Iq+mVXuHi(S2g z>-c>f2|F)aPukRcy!QaxFvxiy14%v(@iAZl>Suf6e;V%{iuZP*uHK_)@o20Uxo}fu$>#?o49MuhNJ?o1cvL_VM>0qiQ1Fi)k2a{xd#)kB=Al_)|P~{~bf$iuWEA$kam^^RU6> zZMODZ^gqDZ|H;P>{lUKKhyad7{dz!Dcl)jCt^dfqp@T0laI$wj>S)=<0pIL zC(m}J@uqd!^!KLYv7yvNcRB{2#IJv0i=PNQpLe_Nzci1Rg!lNleOS8+DP-1{eAO+G#pojD3k0ui9S<1f0eY^ z-({^-F>a&HWZGB)2HexA06%JkR(nh=3D0Oelf5Pe_tP(S!3c|ZJc+>ZUK8&-K9FQ7 zIG&n#>cmj0`DK8}D0?8}0`U_PCB!`@j@D5n4qtCrg7MeigR=eoXf2gS$H+oH@b?3G zzJi|7(kl}AQ8zLk=`~&b{c*y9rDD1nj;GAwe*A|J|HFb~g8;dC`LO9ibhrnzjo*X; zA`t5XR&>mmE38^h3VtwGL>M5z_?xfFRKblL5gkYoL7j`i^@HhdH#wMaO#bmh>F(6- z`JvR6)b8kz)ZIPLhIU?-$j-~s>W>jY+x-d72|y7HJuc5H=(|7OXQv}If51VRn(qU8 zFe>~Vlu)Yqb%YPe;52;TfMg8!Ae~t30Y;N>&&4dml|QwF9x$5(Vb>^dxV#QSP(q43 z;GZGzQmUJP?s9%G1MidPGm=4aLJnvZZ5`6cA&CrVWB`4}1~&#bFb9Lp(Rk8y4|8@v zCEck@43GkbdyblJnS|7m5^HKc8RxWNu?q10pgR=fPggRTj1L$%dV|xZ<~h}98HF)g zp`fmQ5PeJ;C&KIw*;; zo+1gHO5$>GvezN$_W2>s$!=k20NJS4bzmUY6^jp?G$-+LJIEhQ7j#P;6%;K6kO{n= z69ch09GUx*ERSCX;;~_bNaQ=ecQEaMIyH2NW3n#{451gnNPqt@!X|YBSd67kqy|XK zfj|98Gt@6hIxa+e5ycMxl!6HM48#ED5p-;aUtlfHN=ldrUl72UF+q4B6pOR>_z))+ ztNfLIL|jce)q@9wq6ZuWHy^=ZH~+fP!sjB_P}xw zkX7|93@Ck^E9qMxh5(Ov0|FU90Y<#@f^-zuCuw5X^7HSrEr>eM9ALmN(#gpI0u~qJ zLy80Imk)Z_`Mwa)OG8K4=}YL8!f)p##l}lR;A+G&L<|S6NJv*;Gl@A# zl4dcq*`%ScnC(v{&@l=MQ|eFlrF%d%sjZ~2dlmp!vA*?NLU7-wIOvB+2HbJ{a&)Q7 zlJ!G{;D<h*V23e2=6b zE04W4(-v322i_Y%f6e1uL7cdFe7Jw;aJq{>z!={j=+jtgcX%M(9ZE++!gLMw4-Lc* z5ta5$f=94`2Y0`T)-YErJ}?BqgaF>}d4p@fGK1zJki!5l5&;uqCt!B$FY7XYad7v4 zRp?)223}rxkuw&LlOn)-n=g_SD3+Lk!RYf9t@Dbodr^0k-Aj-Jt)$%#yrIq;wDcP& zXTk9>Tew-0p*|4-NQfUWU6O(z=$gUd9&k=j)+=DV{7E&x!s+Vk>*HJu^pXD$^bGXz zPr}^@Cu|tM1Bi1%lgXiEaxk4_pl<+b*1*s}av*sq-HVig1cHpPT&nr&jIc4}NbFEL zfp9VjRbe1`fIVsjLV_334oW@rh1|nZ6x|}s7@O})H9yMO5$V2i{{x!vW4F6L$o6yj<8Q?fq}$v9}yh; zACr1|h^WElA1a=EIQvlf`}>Y#egz(koWKx`Oy~!IG9U%!2+_p3v%uL2+M?<##4v#F zHTd~~KAXGalD@2I|GBw|FQ45BH)EV zv_o7sUjTse$IcMM|3Z>T{v!v-^H}oKfdqHk2MyG7`?}*HLvd;&qD;rTkpwP)ba@k! z3{OMg^_Vtjq|i3GSD<2N6IAD8LLjPN4T)+pdA@|@=k7vRbb@@>B+v)A03;72T@q>o zc&t1%d_cm7M2rpYeoB9v+x-Wr=TO2z)q[>4`JN{}c&;FiV|m>|slNX# z6f$IZn!VADdp<218iHB_3bCsT+#C|(Fb30~!pNYG9P5XwJlH&zdUm_NfAHB44?f#uJyaxJ_8%I2 z_SY~TNNLE7RP#K_K$qs2n-4+g4mKwk!4Cx7aQ`q`_?UuYL6jd0`;!5HKI{}}d~5fp z;jp1{2!K!HIegR*=fi*>gXz*fF%5uU(b&YE0f6d$FvG1P)^KFuyt z@6pKbl1mJy03Z{0J|{oT-v_=@%`a%=i-$qsc0!?E3u#hE!)6SRR1XMnxc?0(IAljoR6=u5il7Dtifk(&tJhBMWq*yhWd2P2~aNrW6&2( z{P1B>-I{+%6mqlF4@rsj2YMKM_6xxGkgPK-_{&P+pa=ozGHb_&uw}w#gUIVood6I+ z*jK+ojbfMoCuP298%xK!$QHp7u+puLNi1LobRvlX?)E`3!+u=o8B?tL?xRX3@qwd; zTie~s`u`y?hLc8iQ+SUVoi)FXRUeCCn+rX6H;eyeRM=c26BahiRX;ZNGzbVi3#C(8 z!n}c*+RfcxDgc0E9bXde@?C)_Rc7-;v{WIx`}!2h^rHZofpj42XZLCC;Aw1M4+6g38>!vj z1;5lHPXkJ@FU%F5(1FQKfdm2^OG?v3=_!$FLxR`cPak9+gv~7A>+T&!F6Z!b2xw2A zL*yWLdU#8j`$dNNGBU$LKC@ikSpEPL0s<=&Fi=#2&}OlTCcDBYfMmrv_6iUKh$dwU z@Fp=ZjS2DRqZN zGCicCB>%7&0FulnfIDzt@Y%14X5ah@s0V{4^)$D|O4cB;au@NbB#0G1`ac@bK=MQz zcy3J+X%L$DUqh@aA!)r&g#62B9v~2fWS!tkf2KcQ*Pm~41@v~EhN<8**v^9p#e0$n z{Xm|t$n!^dNhbA3@-$`!`)-z`W$Uy_N}X4`QL~5#>{tlljcZ#lHP862k*Ad1JtW}) zHl;R{(`E<_b+L(4l2>4lFj<^-`=nDt-AFls5+E8pVh3FFc(4347U~NE`p);I;t%C1 zAZ;;--5#38&X3O*<@t)hCz~RPzX4Co#=#^B?-bsAZ+<)I;#EJW2|v)ycITl%}x2YlL;aNYwB&Cdt6+0iYCO zkbga33(bwbM9=YLDw8_SG8z0GKaxOy-%p(YxL<)m@&vp8J|ABJY&~yD@V*C_gwj}b zspdCj6o{l@mXD{VQ_UZzR#Us(4!LPo{5l^{ylh#6HsaTfNK2@ zIYXQmG@NRlVU05=$ml`fKvKVlT?*2_cPP;fP|pC_Ks9Ng`2!)G;jSZzM8D0#)IcC2 z6KjSj*m)WM69YRh-(#nOMt2AbMJ3H!3a^|HF`Z`#z-#{jhjTFe1lSqTFNt#3Nq_ug z;^5%=;Kr~ui;Dh^7|G;S4E&x1V0jgYZNAI|0`dw~IF99I(%Wbf<9?j~lB8mqiVuJw z@Eq=eJv9M=#s5gs%`+{X$=*OaLvXkIEs4XpUINUOy&*+cV2fj<8ZZc~yCOV+ z-1+PvbAy2+F`+5_Z%BY`(H8fDpcNzn^X*Zr)SbVGrU6J;Y+nX;<8crh=OUYo$ANKT z894(9To!`Lj@aUyz!dZtFi3Fz7y8d6(_q!){CauwK-{gqB`*p5xp$AH>lr{y&!Jj+7Qsi=QIL2%50r-Q&35MGM5=MAo6U zNV$ShnzwOl)=-8ZfS_(UO?BARkjoc?0DQoaJ)r z(ZP)b0uX<)ia{v5U*&vKnIvyRQ{*gU_`7KaCG<4g7tqp&37S7=;MkZA(h&w98XG9q zmg22XP(nb0B${ufcK$fE^Bs`qpW-CqftIQD$$`dfDf|K^DhVB%!kTwU$rHSamsNr1 zV<0b*)Ct<|gKtk9MyI%FEBxfH7G{Mng5kQL`z1nIT!haTg~N5li5;k`$)kxr^5|w| z7|1w&99FYo5poqUPRc5&+E&6p_uqLrojAmD+=D7WQh0qBc0X8wo1c`{*3mZ-4ifVe z@jEZ~3!YF7zajumCJy~S?7afslUxu*NK z?{V_I?o}77_RnbZQ7ZkBiiSUZHh$2|H4u&8L^Sx&A3yPS&nuXhd@th0k1B;ZGy{Nx>id z9SQ#T20b|m|8s%4YIZ8pC7_=XTR-j15U zp7!kN%Jy*9NvyA+y1)nHspPN5e}m~SU`kK8K3<#P2_6%)2`=C>Vg5Kzh-W($?Z(h; z0=1_Y?S?RP0@d{x>zD~;6B@$Htji{>#Jrm^jSK8z-N$-_^(5iImclwI!>a zHJ&vSwITGJNOkp{_|U|L@C4c}FrK5+I68kK)wqm3TUcvZFR>cSsC<9caMo1T0@Q|3 z_z0Cbtc?3oM&mY)bxIla=)X{XU|!i9WiIe8r{7ez6YZmA*HFF7spRIYHq?5MSiS*0 zozV7#LFL+ndN8#7(eipw#rhI!b|HD*MB5YI!88qFO*z$G!}?kILlb@AVEG$mH{i!| zoCRtOaj%Kp*psbF=ozxtUnY|r9nHefqfpyD;+ z=pNL1aD+WSq3sE7lj!O; zR$w`-*B_xa972CXI8{MyJI{XOWU?EvhOs8Ic4F<#djI5=IPwoqrV>W5r;>H%WV-GP z*nXY$ACqZieaQB1whyzOVZFkBsH7S#tj$<$sP!Pdl14iZwISTk{?bY+e;V5_u)Ub= z<*ch&w^UM%pQFB@eOn3e4~=F*L->)S#wk>n7pwmiO4*j}ZmfM+`?5YfW&D(e@Dl4= zQ`VsUHS1B1o?!iP3bjW}4W8N%GN<-M9W|A9gQ@IUGL_2zgtc}mmGC3m^{0^?I4yW; zJxH3CHw{Kew|J;(=>zBo3#~dTh>0TgIS+K^@PbYXq7!XgYv${{uQiiShujA zWi`#@GEo~s$V{3W;WMc{(KBiGwr5W+dg?*(OzPKYj!r=T@7lDPbdBb6bQwlz?_Q42 z{-AxHc5-)k?}?9|z+Wcv|L(8{X&AmYgYOYx>;%V}LM)UCcR0_nKKKwRiv1!9zcB{O zF^{5rg;2pUcc!7R6v{DQFw?{E53VnARPv}{cq+YzO>l=lM<$Q@Lp%Z>a>~L{!!hr<(5cm1 zIW`ZXnT|2dhZLr>Os_&FllCO#TL>MPyph%-brOis3dyFu4m~)Q%_(1p-W=ce8yBOX(!VqrY~WipsQ(ls_|39U@z=vvOkr|bbzTq(m|XS z?$Gb4;TSs!2RSx@W8cHKJb@}DeaEqCF7ph0kA$ZL$Iif6E@chV5AX}8+{k5~!3)CJGkMaBLaUIi%@Kn`F$% z^f^^sE*kXkCi^UU0Tr6-5DNlP{JjwJE(=s9~Ip5mAXQZ}p<|!#31W zhR;wZ7`|xj0#%&yMZ;e7tYmwG;cK+@UVLewUL0htH5^9!tl=o?754mLIDxj&NNMUD z$!=_b}>=O9ww^A&qOuaO;mdB-4j5WrEYU$wOhS44_RQ>=L540b2@j)HOIuF$Y-gWUqJ;W-^_n{qXwqu&^=0vm$ z%&Bc6VWOF?!i#3QBKNwc`W(=&{(GFV?p4;WtUg2NY6|$A%RJ2~4Hhat7}Wz(EFH1l zY)cN+ZpmwtS2mRW1?FDpdCJnOjSI}T^hI4{xgYf%%R|`O^%j~N+bmS_k6fDB^)d7} zXU$@L*mX2|rnyp@<*Ykc&$^C7zqwvHYCyfosB!fu%_x|L_TTAmE~nS~tM{(2R)u-T zv+8}<%hYRsydL#;ChHQ`?e!@Ase054t^RXp>m%b=pIVa0s*e(tmRHuN{>zx=iTad& zI_qn!A92dFuCHM9ZarFr{(rSccV4@?z0-Sifa|3`y0~1!mh>(YZj;;eE^}k`LB(Cd z?G03|{&LiKw^cm5-bd}~Mk>stqul)3^elVXjmGB#w~d(cW4CRnyV-NtjYi`P+c#L7 zG$2oO14`eObr^f5qvn+@MNeMYng*X@2|G}O;Y5R7X#d=xrgboQHKcYnZMYdVhjjw$ z2du|g8#dx7YbEOrRu^~jXR=OWUCCX{gt^7LzyC=0T^Bn0}rg=uKS1lW8&;w!Zh)5oK&dj#aL z-H-KA)=HlbF}*%Ro@38)pN;6L@!5`gls%#`l@N^T1Kk?G8twzbSW8iFuDhv?ci{-n zWnId;hIKpZ0aO?Gq4AffKeJwMj8_LNzWOzy6=C)L3QK6o8qb=|+K=^7)(X~ntSeZz zvevTx&RW08S6EA66RN8fYZR$_yC#QFd$1O>j$|!keU22CH2GHLdWUm;LVmfo>~3-l zTX>xH7gkeK@-$(MV(r2@6!m7VaZOKQnklF*FuN(WWNuSx$s$r%)%4{yF79jD-rQ8x zE?ZltZSJ2o-Hao)mr8&GP0ykpZF&LqB`rbVVNU`wi3N`rSYs%$^cd+#&rmn}Bk^2B_0npZB9#@d`!-Ec5d~|GS)i zr=O3_1@`;-q1O6go8{>BwFcUHm!0+_y@YzxZ}M+}9#7Vmr~<nT>3W)yA5b_=$XS$j33c0R&7l|3~++1So!n{C4psBYF3 z?fGbD2jNRYsPqj9D8ckcbh3m6j6li==9nd!sX$V9rg@ScVycx?%G9E{p3liNl&KtE z4;Y1Ij*+w;$pBNCYG7|bDSrBPrHmcMwzz^BNWPL92Ugk45G1K} zU@20#q}0F>HVec^>Ky1q%8=9tW3G@b=^>1{LcXNYSY|yak~9O$#NU)ldKF{!VT7dj zF;*YON!o>Fxw_5c z0(VKjVayBsCHVzc*{sk)Qc`d!QiP;JjCn(Xq^B|F4Ox<2#+VP}NLqq1A1IKtDtLsg zF%(PM5bQ)Mk+cKz`NAkkM=+l+l<5RNVZJ8dA4;t*hpWNWNTZnancNh{-9~emYQVGk zd|Ol4C-XIFzS!mm*CpASFSj*=Sz&sa>CH=Qfv~)_PTh2Bqf>G7)fl@jX=L+tw&vg; zuE)xnZ?=WN97)y9x7+RmcYGi)wexi>1wZyCX*E-*q>r1IVyr~cZj6P&I7x?@!trTd zRLWVVsgizYx**9tg!1L!x1&+Y`MBgMf|NnR~3+7e)1iXLl;lmu@4{%1L)w76zVfgt=!aVj&ng|MfA ze}+yEw^(k=fFem_F=bmABWZREH+vQwk+i&phrK3*bqSR?5v%-0*PN~*ZeVK0E09rb)pj1|CgNh^{1!g@&u?n|&2!SZZ9<#+d`B5jg% z>Atr1{;<6h#q^!FKU`oc2ij=|z^p+ObHa`LI@$-oTuIiJ9qsqS0!iU5yV{Fkv81jo zd)Nn3CMW}Ekbpw_1B&o{%R1B)`q!aQc)-p@aK03H5NWwAv$*9W_90L-m@`*}~; z9|X$~qDmOsa-4lAEFVr(4z$LGK`6bYjWoXH54MM4F;gWx-|`vzBXC{D-fTI;{utzz zP|8Z!*wSeq0lS%;u)pO?_Q%2ah#ouBGRQs(RzAwar{PnuhRF%nS}w3Z1vPriVrW%m z8x1=pdA2G=Iv|P8fH6=jiOzsAa844P0b}8^Bsv4|YtJ9!`tVPnM%bPPizGS&o(8KV zIs;0E-A6q2wMg0meiq@6X^(()3;}P@5;BlN3DyZ2y8cB;Urov@OTXD>$0=@}`|5aM{ zVLPXRMbb%Z=QOZNx`MIk_%LWar7_fr6si-?vl$S9T9-pmWt4= zNTHHuh3-U(kTfrJul)rmVyd>h8F~>peF*e>Y?=j;txJ*SN$S#igl!!xmei-U6KSQS zL9HG3^{__L$kxpr>!C){M2u|!{AwgFa}LHfzyV3iF!mADO4@?4kKml7Z(4^tHo|2| zKemoS0{opbwd@AAa}!u3dABJ=vPx>xrpmS%{3Ru0Y%_#P>e43B@i9b5D#Vl@LxQA7 zG3CdQr4!GyEl{EpOlnhN+X6G0%5nE5D#Fj_&@Mc)jl;eL+$QQYhbfn-9Ok!4b!-7+ znI2n2#ZXqy$Mnx9RKH3K^3AXmdYO zjwDNXm2Dg3OY#mcMJm<_do;wc9q2y;zdjo2*ePkNXdb@V_PL_4@X?Olieken9Q$BS z896E~bRv9(pVHBZPK2*usU$iP_QOg^bRz7B^^)jB_!?>?(TVUi?3P3)!T~rSiB5zA za6%HD2nXSuBsvie!c|FhA{?Sk5C5yQ(1~ye+$5#rNE`;Mq8rcJFT>MH21a-$1scw}WOlzJ**#_(}t*NYX)!9fiS?@RbJA2uXC3)WR4^bduCU zg(SLS$6%%;x?;y*t|Xe}-@$^LF`S>@!E&8=ejbO_I>E5;xsKy-ZW4_|IXoKv3ewKW zI*ko~-EjggFjd0T@DkfexUQ3BcKF+llaNqJDJw0nBb|a#Of}-e@OK^G!z?`ppN6k> zoQ88U<-za~wli>9(y4GK5=_xcxrDJFz#<83P9&?O2DTBlv*0hOImXUHsHAw?497W$ zkd$q6BBe+wv?V&uLzbkWHaGiu$dxqO_L1X9D3CPCwjF7(Bs$}Mf)Yt|#{C3iBt2`Z zvR!~ONegVHNHZm^!q`QaBk5y|U4#Xa=xqEMmP(?t@n=}gG|56&`Vy>{L|6I}Y?mqb zVwsmAW~x3)=a_PsD)?$%hJ2=K_}#YGaT(?)`o?hu7ArdAxC(2gQ7L%B+OIf%#}7p6 zWVbhU`~d|sbV^0~6WpqZoG{2PB5uG^Nu%v95g>A%6w}WDO%&*4dC8vW&_uDM#dbHl zCQ2l&z?eadlC&0M22rLH_rWNp%2*AiG>Tc0_F_t-m?!BwdzH;37EAicj=w7rD|O;h zT*MltQ{uY4L4=FgF3I5VjKEZEu1fl%O)!%2Iqsi@cGG&oO%m;< z^@Oh^+D+?=AW5{F))(QDXl=TQ7)i7?-9&~?*v`<127=1Jxtn@OqTTcdo0p=n@R$gE zfu#z~^xw5gaXiFQ*zF-sEdrha0cB-%~=#bQacoBE5Dl4v(= zCe}!z-L#pgkwm*`fY>RCcGCcHKoaeyfudFt?WTd^oFv*!gT!S?w436Kq}kM`N(=3# z!NMYmcGF;Cl|<{Ix$u`n>!G;_l|=W@AtFK&-9v|n6iKuTw-8y9XculFawX9&e4i+g zM7!{PVz4CIgM6k{aOZrVzeNuqm(R$`{4Mvf|5sF))u#DTxN5DO&HEC>@z zZ|1|khl$lXLA)a~qP6g?rjaOzbVo;|5p#8-eYcI6!&C`*juKnASfCT`yWJwf#Suxb zBiV%Siyz-NP5CCDk4hklr+xqG|~Z`xQ1xq{t~sN5+*y!BcjDrrfQhwm=+N$mP=aTm=zHx zGUidrYFO=fF(OGs%-87?$2xnO$X4`PM7k)E^rd5IM26V@ik|Xk$NGpYvHMjbCy0nG z5$%O_0nu#mh&XBQD6*KUAvogGh-|Td$qDfhdm=iEO)}O#;y^@KF=`=Z!?xr_oQdcm zW-{TjoqNBaHSk0ur(&!`BGwC~YA5o*|LPQ^t@EX-e zu`3aU!haFbR@XfdBC?-o!L+6R(TI9T5loeq^ARI#MIwP|lI6DuCsLM-nIlKo`imS% zL6J_R5~i)LiIG*d0b-P-4w0ouWs-VES|jflQzZ?K^hKI0=}9cJSS*k<3Ck=No0uvs zPK*r{+a(o2lIL zC$@8t$d@tCs4ClFQ6wpZX|SZ2s8WoLVA9W{A)-uCv&bQ0rXr{9L9tTNg@}j5dZtOx zKB{@-FtJ<3N^HYKt)gZaJEzEL8!p^mr#?`97a|@O{)$R$kBAsW%_1KWIf|UNN5vRL z7a|@LvzWG8=o*a_b0pC<8Y$*6&4%7lp^=Y^157w0qmm+@6vibtYcH`qCHxgNi+oCi zDstLJiyTE4BF2bfMVXOLi%~jR#zbXDju+!3RYo;KnyONk*d~ZsigF?+h|^5vyxu2@ zt1{o5s6@v^fggmYaj`6oa~-&=rM3a&yB1SE0=NYkc{-KaC?)e8ahSeJQqQVmPF1L36k=n zU$R$=97)B||A?F`ikbA^3A`jqnDjAwNtEd+EssX8iF`>+WvaB4Mt_8~Nm51hr;#s< z(|Ss%ivBuszPK!DPV_qaE5iLPy=AXNABlWb1W8(fv`|Da>9sEs*-W!7A4VUKTqJTO z9g9AVR3P(NVt$NVEDDzEWj2cuQLhW@+d75ExJNA!`y^$@G>&>h)U42BhoYKCEfto3 z==5MrC{p-JoyNx`M7=3;nP{z~MZG14>SUQ2(;@0@F+$SwFBk1rycYH|ia+R42=qF;%wJViQxj z<$I>xlKy0>)l)*_*i^@AG4&m)y&PH~y(elUMaGuc-WQi8wPzajE~Rurzt{(&-WL^; zM#qkf`asNK(ocjnVkuLlWp->?)Ecppsob(Ob_UXVrfS#_`$E)OaYWLmv5TVCi|dm1 z$G#c0QRJ+q`l{iZ*md^Jf^0lVOh3fF6ZNquGB(;kB zG-{hTt!Piwc42&vN|^&GaR;M56~2-NA$=wim?~gaTy4}&F_g&(|A;$j-zCN<`abG& zF;mi-xOMg~#5_qGk#>val6E2O5j&aa8kO3<6i1l00`+0982kaXMUU+lqnPyA*TQ}6 z&Dh1LLt-}*oxWEhz7ePOn1#;NqvC=jIz^9)tCHy4JSy;`_EZD!!bgQg(xJF2jJ1$- znkhljWu|ONUh$MNS5k0%DN>On2gYi}V5V|QCdO*T2pQ{%v14MVq`^%4B#p!6rYFH6JH}Zs7sYr`HC9>AvjJZXh7NaD65bqoLgQ#IDhmSGe zS&_eiQqq`tMxPhEnaV9+#9JeO5(o5{Y7j+b^YcnZ}3pU2-_cup16(1VLlZzO}UL`-A3~{-zKhs=9v@oonSiU zN;Ui`{A;N8Q?69QpJJROs^L#DM<+ow{3)(VqB8#!IiGMoLG}G9@|mcH;%NL_zaHZn zZiw}gsD>NDcdK3>)o??E>%=wO5XF+Hh8tq2B&y+t*u+FNlptMJ^kDQ2;l7Q^)cXfo zxS~g*g_f;oh25ZyQuJiBNt>l;LbOFYr)Y9?ea&q3?xmfR)Flz$f7dQc8kmUh zziaqMG1NcHXpDJl7D;n4=B-&JtxbG6+DG$es)k*O3z0$?w1AEVo7*^)*k z{SqCnjoMB5@ORBge?~hr-#t3rNOXyb)*+HyrsTUTwpq~c_! zt(&%!iF)L;b=OWST4B%CjEATc?rlsDElAN5F}<`5MWr!?+F+)wt`B2x2WXd>DlJbk zU6(YG$#|GsW|_w1CTTX4RnmMWf2K+BMsh{W0Bx?K|BAU^+s;%Y-b)^5AE+6RP?=8H zk-X0SfacDm?`MNFe?=?ogSAjaB{2_bF^Zmu8Kz|^DvfzW%U9&IJ+2iiT48@eD^XMu z^Q1OL(GxLaw5f_pW5#K76;;QSYfE*q98aDX^NhAq#Y$|?XxkOx`@Y&`rmcLBGD&m) zhWfXq9=-0Lr1>-HuMI1-AW8JvutE!GqSuBCV zw3#wSzpa?1&DCRkIyto(MXO_+n)N8PlUltl<~gmHiB?>xZMHU*sRn*bF0swg)-ciP z*cLNK+ob2S{F=NAX}eBfOxcTcS<#`GYHesO*MJ{hJ{|L-wq4QBG4r$$$0&A6?8S3) zfmX&e8$weIu?w{AOmvS@KX#F}<~vI1gsv&Rv9D{}naW`x*0)59IZm;1cpPb|7IZ?V zDJj9RZ)#U1%};3^`?j{`q#k=CB|7#WTGlC@)}&;|zN^iZv@^vw@_jAndp$;<3j9FJ zXL7=cl)~6G+Dx7J-T$@PJSG~!65CpBu_7nZN=3!7A8PBFXuS`OU9W9du@c)y+CD|4 zNVSR{kKL%9Q#3YqlXg{6dF;oU@ieuQYM&BYqq!@Z6}wH#XVS0VXIh0Gvs_52vVEq_ zl%%DWA}x?)O|7!+)RszWjj^5DdPy0nFU9WCY9w_}eH`h4qyd=kbFEg=Sj_jic3IM# z)CI9$XxAmZk-7xQ{S38wlI26pw_Ed-v<>s^)><%C;^#3-Y`7rhb4a=hR8LS6iy+b)DB|@H28t9ilsNk4r&%jPhsq!W@XZULvTpT zIY%k0p*n4y{gAdm(kp3aA`WXSC4GQ&MBAidhhx9dQqJr74r1)6mLur`Qms}bsX_XQ z*kf9Wr2CM*)5bA5;b7Xi*yGx{AN5iiq+f|WrOmydQ@ix0jx*XhNqy2q+z;B$pY>Qt z`bqmaE#{I=W7F%$o!9auRi=B!{m9qI;J(%Le7axUPl^_#H;?;S(K|?&6n!7nJnpih z9qFNQzbM+D9us#>(Yf@DxIb=^pp^8L8~A>X`&L0QlOoFJs)*`qpor>gsEAtDND;N# zU6Q`0y>7-##tgg{R`gI(qQk1lH6thP7I|j$iff``lrLBjj6MjID7cipFK^i+fyAMaGG^rxiV$@pIfnMRPN>_^FDhoii0t zJD5sl|NiWX%gI@T!q2+O=h2eHfzDs~Cm z`H7;2nK^OW6@_NH*>@>Q%S?29uBb4xSKKXn0`u)xu`0}WSP_lV5k+)uPb#93Kc|Ss z?2;n7VpkN=Rry^J%_U*HxpHWpxhSGp;HHSKN&`hSmpmlttHb+d%(N)8dE6~pm)RiR zN5wwN^ohp@mFg?i^i5{7_@;`^X10v?SM*z^BR)WprEP3{kRqS9?c-Z1vbD{Rw<+q- zw!{{#sIcvz_*+!cc6fZOicM@gGCp3>jJ9Lr6BNDF_L=x3MgM496`!VPQ`O))@5Fae?k#mqo)*olL-l96wx&*RYcclydt_r z6BW@ls#HYRXr>~%M$ajtYjlg~8qHC$iEZm8R4ba%)+=GIBDzK|E6Q!xEa6o}54E!= zEKyX}E+b)uqLlD4)?#YDBifY$!wa6$NF@OW37|=EQDAG$+1PM04V6MKmW4Dxx`YL=nw`ql#!2)GBgqwZdtjRz!26fg+j{w}|FMBNd}L;h~7;gqI?k6F!P)PBc|Sb0Sy~&51BYG$$ez z(VU1=L~|lV5zUD-MKmYcDxx{jP7%$CEJZXY+AE?tk*(;FtS=L~D5}W%E}`d560~mn zDxwuWP!X;0p^9j}JgSK1(nv*grSXwE`o1gZsywNPuERJ*G%n95q7j^~h^~=S5nat& zM5FtHiqUm=RS}KuB1JU1OBGSyS16*szpseShYfWI5;iKL-TUJ@R4-wRA{y&Y6w!*? zu83yqr;6xm?o>o))$TfUCH_lAv;w|TM62;@MYP5aDWci>jUrlAM-|bWs8vL>{Fov- zfsWT9uY{9|Xx*MxM7zd0MT@f*#9vgjEz2kVvZ5cds^YIGs@Hx_{8dF^?H9!Vp{Q$n zpLl$Hnw%jc+gHWow^B)ZuKm(@qoQ}Q6tkke?Q7!Q6#dj5SFs}Z4zcmK$lf78-l}4K zI+WO&Dtfv@`}kY5u){O)K`OSjL(BLUicWU$iEpXM+;Mn(sG`;#o5$fFQ_5EN=r|}I z|GZGrlN}xLHbt{L#>P7ot?HN`AE)S0$Bcv&MW*a#30aE5vrBAU6m`#TAAgIU%C;xu zso1O8&%_rhs>!~T&|lHHY%TEtMedy-VW=W|r+NtwE9%_oxr9d)J=m#b{0K#pJ55M< zT+#AQSK^;iw6l{>{8&Xlb{ZaEs>q{r^SJSf5|QvBc5;-8IuDAUsAytmuY__%uXL_V zs8CeX*%3ck(RZC^Bur7Hb$K#js-loC^Ae^jq8+nJ5uFzQrHD?hS#{|B_&JK`#G9*# zPP`Wt(Y||&Xup0*#b~FUCrQ6kef4I{)S-)K;w{SQ(ll{_isf}Fu`N>6r%PqRE$Yx^ zWc*?k%jt4o;_Hei-%>@C?-q6F5|Ow}#d5kNB)+ML^1ZEy^4+4MF6|OmsMv#Dx+Jbt z^k|p-#MO$%bSX;wK+(i5gA+egM5U}(M5TPB=+Q326F*i&rF^1@O4+WcvdiO%pDJ>8 zc{*{IB8u%+M6tb!=69KtxL?uIE;ADkDq7iPcH$vL8?f)+DyqS8IjZQhF0UuvqWwtU zso3!@D-%yD>d<9v;`c7K{2K}Vx}SErpp)fvm(7W%T@o(Stgp0O?ULv??J`x8dk)cD zNx?a8_R}u&Bt>EDjLS|*oiTRCWw)dUF!qDX0ZAh;_Jhj_NfUB5C!TdVCuvH~Hl(Xe z)s|T~pC_Jk!H0?Af7O;(a}FU{nDBFl*!S};p^{eQR3Sx3T9ZSuEJ+_Rtz@c(H96lW zo_F!T!ezooIp-69a*2?%CFkeF3ob>9t|wm9$Bch>IMQ)R5`7YOyX_Z6Vd1Vx`1MKn zp8@nw!v1kvzCTs0dH7KqKCVxu3=40XWKcw(ptYEbu2QtpvKPn9)jU|zQ5-W@^9Y^z zcX{>9V{W4|o#1TFa$7y~JV}PG%WZDvHFZ)pG;fkIzpkl{hUVRMVvWoPbh5;DZIjf< zTq`NPYaG%!N%W~>ck^XQ^r>TaGhEYK-3jw~m}7L}c6yjon4B=6Yg>$E%amigR@pqw zxsqmdEk!D-lh4aMSjOge?UdwYE|K(h*LWN&UhA?dSjLz7yV6Mm<@SHq!h zk0rG-=Sw<<6lNYQ>1?+rliHX^NxF_?GgqisX_CV{SH((`BF)QHtUM{&yh+8%lVZ*L zRBTF8y!nEPO-V{LyIt4Ya<<#ENy+9=N!O85%~_I~g}#uKZXPVj+NS)1DlEN@$j(M)6*zW6+x|>%s(JovYm1nNe34hPtJhF#* zCsVoQYHDp%5Ay*TOYffO=xMIi3A%MJvGp`x(21`~PxDn7d!TzY#w>qQ%k+Id-|Vgv zJl@@D%QuJDiS;ta$XF%jqi0hK*fW5hM127DcKZ-}PW&I&AGpRl+f%olKVcgD_4oa> z8`nq0XNV9{34J!XKP2Dp8JN64)i#{Lbv90T?Y%gS8%)0V^4ae|3wzshA_3CzA&z;wIJEqsi zUjW&<-t_F^s6HF@zJJMSzGMAQ%+k6wk}crQT26AS&Ty1QNrOA>pYP$-QY6st{Mb!N=k3MExq2J)>wi8qEU^|4%GyOs4g%J)eIw1Eiet$6{=C| zaS8Qd720m_A!-BIh>Fh?RQqPoj^{L&bFY*aF?wr- zQs1w0decDiyP@8`gWa0*2JphD5h$eqf7W}|^5606?GL%5e0{dlnBQ#{{i`)PuzU?t zxt6YXwGGgpqa*7?pJvY_)@PNi!CbcQ)rLhF)!=nb^TuDM{J;O|)a~Q{-j#ZbN8>#n z2U=4C>aMtU=rO|Q9KDzS5J&a(Lbe8{2GXkk5!Hz6n##PvX)F&=v>_@!r<3(Gue(6D zTX8h@0m`fA(o4%mzX9@4^_{^44{&u!$5&GdCk(?IXA{Zb@f)7yX~=$aQZuIxtD)3rq_V3 zvO)HmX4=g)a%Ww2$Bm*IKGBWGkjv5Sy8b&o)tvHGZl_-UopXR{(Lhh5+e)eJT|uVv$$>vG3eJ<+3o3XmOwjm z3g@LF>2a=&SVtkI$d1^g8I~ z{&34S@DsKK-1N{|@EJlg;iiXLVi`iSQTNm8pi_p<#AcjQUnwDM>-FBsTeqCLwgFn# zsU^OSO{E!tM!*Pd>y&?UOm41C0s3ph98Pm<9%_)s9-6Bf6tk_L2t$>vL0$WaI)1VZ zcSNzZxH^o|U-x?5%dY!-j9b^p0F$|{d*zzRQRhFY1~2@RN5I|F7+{%7spqQe(Q|3= z0jH^{qdSJ+sSLYOHTV|Q0Oy9#S7Q9i>hd7j-Vaim;0FzuCJb$St%tS|lK;p2)T*0p z(_4FIFUZrLTi6{{gMtS|kO2mwZG?wWP4EOq$=1lmXemc0bM(0fHGEU_1snl0EJC%w z+noMCQKo7kj_n8BhL5mD6MTZ|0=v0hl?K~+1pP*inq>55FKBI^;1bT=QG%Z4GWN>= zH@F17M>q4*m34iH#>f33s@)IO1zMn*W#6f78c^E|T)Xj~+lGD{mLPb9HNd*i6N4q- ziN%y%y-=(#fGRVl|dHZPB9g_jv{^8ty8e12ju{Cp^`+*p@?cNz+&A<&{J&kx-zgJY^7m(pYKh8quT`x2g(?63 zO3~M~%6r%LtEgV`U00S$gC*R#kEtk@aIc+EANhOjMR)Vl88L--o>oohb@y|1>;-JU zgKHM=U2!)M@F}iG4ZdXmQB)1iKV-lXerKCJ2K3NANoS&o&qNnK6U}%g-b!g0N+~Ig zk<*wsjmzImL%XPrTh(wVwLb>irh(s34O`d>OXeuHEtc(nI>B+|+p@m^^J*}F?VBS* zt$G;!M)cDjHIbwF+-p5$6?!yy5u*lp^WR#|dtCBbE?KWj_fU-n*vPHg&NZ$bO4owc zoyMn$fzN9r?8T@Fj$%p|IE!kAUpPI@PrSpy^akAX>FQ7#6WrjGmSOscQ5u@_w`SL^ z(kP`FEW_%~7E14d9>ZPdjEn{u{-2mRGy>R{ApD(noe|S}ckfwrYd-tp7~(5dR2*9z zLldonAQxyoOaz%Ba@ehu_n!Iq#CxD}ELhIJnx5L9hVuq;m(t;?m2jKz1-TV{?DEMciSib z9Xs%?zWlviny%x$?k@iOyYYW+MyWeGZ2voaZ=mnq>+qiH<{ebs)9}t6UhU_YzV1EY zy-$t0_m+RPuim-C-@b?6cE5-1pMv*h0`!yU<~<=@7qoGo*UxT!1=T&x?{y0N^?l%9 zuLw0JSo^=LoI6M3uS;Hw=iUFr-S}NsLC`&?5(J9FvlNPi`D`~4x+c-L20f1@tiE%W#^FBnd9yFaP{2Ho`hccNJP z2rhFBmsWY$|#LM z=v_S2>u64s@-SVm?1!m6_j<2E_n*eka%j+vQ|j;h=Ce(z!Gmm@_!A@gC!KEpybYEA z&mJRx>dAE5r=I@%CFrdk#;qE`t*UE}W>4Lo>Yoy<>-l%t`sWIs<{Iy`r=Z^e_lo}C z=Kn8l?Q^I`+2(4r@xA^!y&zkY(Yp4XDVNkqS@+$4{XO($7{yl!gMHvBh=&7^fIl6e z6Lf|aq8r4B?vQ{#F(MB#L=XJwi9h*}g+JN&lY>7QqBrD=0w@yw@TUldivCc5Kl%7m zj6Z|%rv!hB@Mi@63>AZ6rf>y%HjGnS+bj<9tCYwk&VBt+zXmy`zyx!))4;pdYLge;5>gM8GHKu>ZT3&m(p z!@vJHm*nKl8j?M3tqP7H%7xj$oj=HxnU3#Dg%?p5?G z$;IbYz`K}o8Tv;$f?;FspGm9GHYTryFLLXlexK`}>@2U*ADIg-O*I@)3ILS6}eN5t!Samfea?L2(02E32z z)HdaqYM0+T~ z8W{%bIJz4(QXK4gB{@=j*Yi3?>G_M1+S#6ll(9T|iQ0vpZ(Yx zWNYMD;hyhi&(lHz{8F4+yrV@*q1Gb*q`gpUlixaJ7}qscqi-@8%UAXqMCZq*lxywt zQ&O%$&-}J2)3gWkspQA=JEgpc<=}kK#^m=*X(30WJby?^4!qs7ETsq@O6U;vqBbpm zI@;92P9nCe6Fpm)Z)^cH)zVXoL@H zU*#`LIitmPU72!B^Uix8TmE_8h7?+BHEe&Da#1^)zbC~*T)@1mwCnj_r6dYtFQ@IA z=H2TM+CjbWdn^r+y{b@Cd)4A7b?SxRb7|<=s}yx8>R_JRgK-6&N;xPh?mL$f&OI83 zeYun}iu*E5jKXqUfy!K~jqinjfn%T%xW;(}x8If3gS823Fl!iVBUaU8hnHr2D^IIOAW&sN8-%c-^(L4((oPoX?!BZpS^rj z6J@kP@4!?K;orMu>R8dHH+{1}B5N+|@ZPr6U@@KTmssCm-OxKGHIqvS7GLyE#x&oc zMv9BQ+oD3BPN|&?-hEP1!XTheTO32m8wTNh!jcn3d><#;9Z@sIz&_V;w$t71h z)Ix5RD}2&tNUAIB>$5B+*zirC65Bw-$v!2i!#Fz7@N1vPQ(d+C1!Gh3Tek|PpoSFC z9u-}1BxxF?7bH3owGIVK?1@@oK~-v^Hn!z+sUr<^P4n;yI#J1vgwle!sTF+nU9~v{ z^HU>XQNcT@V+||pYf(28Y(US)1)rok4ciKKrcTqoDEKmU4$px(Jbzxq_I#bX5cMdg z*;jB1^>D%Y#F?_plLhB7J*|;>Jg?^Q>Tnv)6o|BChKmIy`1D(P3MS=Rf~(`#0(06b z0~ETY6`IMPsJRq+rmf|cJGFp9-!!Mzy0BSVqKTrL4J+b9(l#5a<8A1VDI8%d#C7CE zO)N}x>@Z{&uEX`7T^N&gP;@Ii6H%!3Ej(#IXc&Ykow#=N(#&bJC#0ke(`cU@rj{-lXz8rojJe9JVM{+UzQCMQz38m3*rtQNrPo*pdx4s>s7K2CMD%)}h z?z<{&IfSEq5fb`-nL3zHx+8pbXq1j5jpUVhg4+|r(Gy%tCrImi(mvAIx$l~^vBn;K zYtlv2hyCz`F+2^k$B|h4`qKA1UF+L0 z{i3Gz^GT=uxmo%SL&JV8(g(x5d^>96esup+zaZ6dP`nv>IxR)^j^^QY9!Z?-`HAT% zT>f<)N!r^xVwwK^5*-({maI{z<;Jvr#p$aI?fN~E9wW=4opTwEK#9$YqjxIBiYHEo zC@0RnC(^B=V?TUqt;p}!A!;9xoyRHt1w9FUE!&%o&BMp0uQEQ^uLs_hMHiH%Z#F*J zZ)!S?D()&Uso%5ddyLTq&!-sb3j;}5a#rXMq|?6)pmm_h<_B3(`E`hAj4R}G)hiyo(K6wiUd zVpqT2>4UM%H`9Vm2m4tggE8tGIapLgr$t4YPW0QKe#UUV-&Q_tkD{#=ZN)oA@1o<8 zC0IgQ)Eq8n540?ze%Xu8V4Hb{7*mRHo)|k7UBF&P7hJ*q_D0V#y?y&igy>8ru{`38JVVYs57y&4jFS; z=SiE!d=9qi&9s>s*)!RmqtTepWL?hfT#t7wmr_>a-BE|A6MU`r7_W7IKK%q={Z1y@ z&z;)Uq7nEEMM_!2DXrWKEB7}OT>JOHHe37m$;dNZ>t0MP=|4PUAEtjQ;|Qkj5_N>{ zuflnhVmQ|cjppzPjb^x&*UJfP`Kc6aKjuBhc`tL`%ba%}_hKH7Ra(?M?#nQoMJ2Xe zLEo%E_fc;4eL$rd4b8((r3@AH%>qW8jU(~-cGPk=gMK$`;yyX^g+$snDEO5=H5 zYaTu;gVy5<8AAnqN5N1*-&@eaK-aN_f%fniE+<@;6Wf12rf=K-g^XN5-`POx(aGn| z>lx*y4*l_t7f&B2o2d_ir&)Ip%fVMDsJPdm7RQnfjlBp<`~Q@25wxNOu?d2{{bHGco?Ds2`_e)2VgE!& z4qu~#Vq5z$`ayA^|K*Gvz9Sumr{N6T8&CB2O-pq*reo%Z~YOxiOe zGRGQH2P9?E>xj0Q7jZu1ptc>b2k&4*0uH3@X1f#j_VbB5p9-!ggzqrno{4Fu4tN!H z4(dhx5QvBEqBeEFGPLKQ?&FG+RyO#Bw}lw zwu@+gk~x;`YiQ%Q$FMz+Rk%{$GqV%hd8l~z zg1R?zAlt*(KN9s&=2+C6$a1!)u{u%d2_>WpS(l;WD@4|{?6JU5IAYYmCXN~LTh_%% zw7(L^Q3q;QP={z&jrCxJR?nnCx%L}+CTrJ?7Whj0)948YHG|0lM>KELTCFMS2`$jn z5R8T>Om8z-(2g-=nhcO&7=?C@VKi#4VJB+7A;hI26d0;eiwwI^iw&B&Aq+N*L>+3l zfm&iHvNVJdhSshPVU*!n)G>yTdJSQmp)YEgp>_R+P+_P+ooa}8YX~z9J5XmCnl>;) zhVkbH8e|&1OlHV3{(_!t<5kogQK`O)DqJf)Dfm1QAe3Bp^hND{JqDpZjC$NU!ebcvKlLa>&sC3d)IU6?p-1yvfOe|qLe#dN z%h1!&a}(O5JvXC{^W1@+a?e_{w|gE#-Q{@(Jzsi)cG#+U2~@L}tM+CCH?JVH)4hUG zv%JF4)5$9X?b%+LsB^tKp=Z8VG1@hMm{=&Kt zb)R(^dJbAQp>6lxj2i8|13d}ewP?TMeGGMx_Zjpo^#;RX>v!G)^?Pqu!C<3(uCZM+HXjg7Y$ zf49~&u0?xCV=x`Ie%?3;b#LPg)B}x+QNL+C$Yk*TuJJHaeeZLP%h2;n<4LC9t-m#% zhMpUZ7of-Dy9u>{Z!M~)?{SPa_63*2R)60h)L`EXm!BK7^qu75<=xA7k&D55ns12N z&wIA7!GbM8-D_Rp8-n&~)Vzt;8(DNc{i1!xMcHW;hEl2+sO()fh_TGou&igQGvUe@&I_vjM7h=@IZxN>VL0xBU z=C>I=9sRaoT{)=htWWqIN1cxv;=RpJ)W`AkGt>|9-ix}PCM2cl<${~+`{i5lYlDr!6LCI02;f6IRo`d6Zccpvg#h@NBqi|R*v zpF&OcK99Q2df9(7`U9G6!89SL>#VJt9Yarkv*TzNqK0@+Y9`zcTci@MHQ z-7FYAo0^57=M&U+-aAp(S@$%{ME~#2+Myo;+M(Z!y3XnrFcAH50fW#^Mh)>E5>Sqw zl7LBQk3?N(9TTt+J+B39MtvjT80zu>(crLkRX{N6`vIA#>jK&}@blgjP>c2_0mo23 z4S<+-v%s1Jsz+b^>n~7)bjz*sEhZ{0iw}i>#qU9sMiBBQAJ=o zRF}YksPzK}p}Gf_qk0D}L~Ra;%Au0rILNx_#My(fAi`ppY7^*c0ybfEN1pR;Qop)Fi*W35coE<@m1qC}g+gMmw z*j4PJ3%hi%0V>vAmqk%vkp)X^3l{9X#Mm%uj4hT#jU8f(F=}ivh-I-G6HDwG<^9eq z7&Q64&+odP_r0FqAJ6V}f95;)oH^&r%$fU~8FmH+Y|3$ji890DrJWD-OI5C*Ug@T!!5wvo7;7G0*9Ltq~ z`5f^o^(^2Ra0bVLb2%}%h|_{gxlpi>Gk|M3Be;RHfm^sd@EfiW+|8{54{*icA+8Mk zo@45vzu?5+SuPa3$Qi-QTpn1)tpaazq4i5W?{h}*5tj!(<5q#Mxni)KD+5_E)1cJT zMQjIaip#*dV$!hGvw@fay~ScsA`S%=Vj~zJ&I2{#BCwU%4z?GUfm$(XRO%Tn=D--S z80;d}f{9`Sm@Kw|{l$f#Nn8XD7TduLF=>omL(G9A#9DBS*Z}52AfExQ(o)aS5(8+H*uY7WLU5X-2%Igkg9{`?R_eJ# z!htJr;{biS!~lLNv4NWk(8l^;u z5t_6J94fVgSyJMUQJ<6pKapy|@lpdgQECIHN(;eR(jsua)DC_sB>|bHsmHAs8qt z0$a%JU>jLc3&ek!9SoDP!3kcGGI22Czf22ulj-5^V3OPb_Lkeg0rDa+MQ#Vv4$hU6-iZHlZSOu_OXZ{=&MY}G;LMV9;5B&> zcvEf%@5!}BoLO=M_(X04U&;%?xAG#8`q)8dA2JYUmJbJd_#B>Q@~Y=^6V&*~rklJv z`=o$rJ`=&oK5M|$K7}*UVttChBR)m5&|-b;;AtN+8!gs{1512t;8mYO@P#(9|5n8Om4xUozKQ(!sQygAm@_MM4xYXq3=DP;;@x2M^eA#6t zFN1FiINEn2_^I!jbtbQ`eP!!SUZ;I;?lF1Y_ht8*yqx^>pww?-k;$v0-x@I4Z(^~@ zYq+26jLB=hUkbRzk3DPhI^mZB-u9aaij;@JrplXOdnJ3$a8H4I9>^wE8euiCzeoa$Ve?k+HN#!I;Q&q>*73MDLqf$8~sanHAV9~GySTfAw z)KfJHwgdVg>_+DkE$>^d#6q*ecjM*f!W>*jp@juHIAC8rHUY zvMLRh0kdF!G;BZY8SDjo3YTP+KP%tOX zJ7A|_Ea5+c@w*`YlU6ZJ$8Y-iPe#RjX2rY(zYyX-Srz_a75?msd27XdPQ`q#ka`Kj zPd;PZbaiy~bdA8O)=a0+)ldcKij`{JF=b2LIb}PYRu`^|N4oC1!^*?TVr7ah4RhJL zF}jP&Jl!PSOx+3Phs);aK0}I?@E0rB>Ne=A+E>V>Sa}#F92fE%qdTR`)1AY-HNYA$ zK7e0(2TLC6EdDRyEr*Hpb@cW1_5AC-_cYOu5AaYa^}O-5+ce|;Lh7X3TzVdW_OSp8vTo_?`(mxWz{dg+$sE+ziapgY^P^p9jutUQH%^H=IV;WPa!%@{rubHl=?BK6$x zCEx+&s&EUo^?-7dFx@FEJD@BMpX6UdWexCCF*ga(|;+JF4gnpHH(0L|8=wr&+y8<78v2kzhjmBSNPx2$43+^R|qAn z5K4F(J`c4kR-Q+hIT1M#VvmXKJ<>grKLY%>ZiTO57$r8F~8~g8dQtrSu3_6(ka|4RvOzrHa^xE zJ1Mp>HbA!_c5AF%_}+~@tc=A`a!eh35X*1z5B>*~&thl#^IQHFQ;)cn0cQh71iaI} z)0PFS45$}3G(0%&WA9<5qcwHJ(xo^a{5LpmKwL^3uTJ7<42k24sv3~2TYFRTjAQc4RLjFWH!Vd^RJ_GuxiZVwFiEs*bwoo9e&42NDk2oG=TYJ z9D_T>@H^w%2r_< zF|iQ|!GF|7ZgMh_;CElhVKPyXDad6iQIqLJLuQd+GMls{pOIE%8GbFf62F%G95q@? z+LMi>1KEaBc9D)`H|d0b;~Ykch>jE!Jvl_e$r1dj@)(K2KZcFQzfz4MKcO~f@SDpE zWE8nf#*-_kfgLp{Lk(__3HWDe6UlF=0sqg)z8ZQhl#qP_e-vmJ_(&j4=a<$=zX3|p z?|~Y@(@tQ7;OQYSP4Hw0dV-*52wWz3z7bd~c+LrYBzW91_&j|D24(PNwH9=Qz<-se zqYjSJy9p_)mg30SQA0;=$wJNpg_P-n9wl%>#_uR`e#R4UX~rvXZALk`Sx9+ENOK~C z4I|`&z}o`<%%}m6OD13Q#sU?Yb>YznIxMq3bbO{an2;#}dkg-5XIo4{O2@W1YF?bK zKn~{wI=0J^o1^rcOn#4z6*yVo;!HmM8lgV^i7IHvRv!uCYr93r-?0ZAx$P4?X9Qjr z*19h6p1`MqKP*Yy5)C%6bO9w6eyjZj zYAyVBMO%8o-$U>i1f~hh5til&oGEa*zzqT&>+Z7j#k$27{s^A27(mB4p3ma9 z=#gbHcrA)ZbAm1rcun9ff%gSI7WiV=R-|<7E61_;yLKGwwHZ5*^4+k# zpmR3A6SE>7cvv5Tj(3a*6VKg& z6g_NP=&2x{FG5esps#HYJp;Wdo~r~YdfraZvq4JckWlEkAl?;%9+n~VLAkAz+f;+?kWaT&4%r0BV0p_hUbJ$O9ya*&c0qzm*)kdiM+H|X^sB^yWr^hS`9 zO(Y3=Gf2r!(i7Z8lHvIl#9yIFA8-%p2cE*q$QktV1E7B*M(8sj-daLT(C0u(&J#2A z1(1@T$sp*9Al|)>t2&01fRtP!L!nDSyk8GjcX&bx#Jj+V1-wRv!D9#Uy8w(~7;+Ef z|IKPH^nH+G1Tg~ocaUNvF$(%2NbxT=MngXbDS1K0Lcatl{;k7!=+_`6Z!j8R$e$o3 zZ!sca$UBgdavVbj4~1v!PuZ5N{1&EvR zB{|GB=vbafASDx+ThJ3hoOjF}=;a{JJLVqrN)XTGGWVfZfs}mC z{0_Yuq+|{A5PB_$_gylNq1S;pPnjps>p`5S%roeXAkI_f1-O}c1%Ac6fqx4~$yVkq zxQ!`?XFEtq5rYpY2Jq_=Mg;u>i1U}J27MaD`O7$i7Z?}t65|GcDTp_OGBv?Qh(5os<4(4q{N>FK?i{NeG}DyfwToYK_De*)w^104l!q@%%2bS$`;jtBSCJg|sPK&^^FO1`6$pbvp~s*@H# ze-EM!(5cWrfRvo1)1gm+l$@qBp??AqtLbd;BAp99r}N=|0aEgkE`)vsQu3NEhJFK5 z@+Vya{T8I;9bF1t4x&AXmP0cjMg^jkpp$47JkB5`uA!53a z7#oPzLwkUDwfbI=a(udsz-4~=J zgWV0C2~skg-3vVeq+}$!A9@ssXAaqe;8+&t4H*YgVq*_M=YcrZ>=Eb*AdWJ740^bOpAbNTB0`x)_C&tb^6qdXO8R|l}#MOpvkJ}N~n96BO8cF+63ms4A(p7XD-A_-` zGWwXhiTp(!MB$=%QBRRklq;GjS|C~@+95hB`bl(2R3^GFdM#?es@PU+CpLnOXOq~G z?09xETgYx__p(RWEpg{z-=ds@LRrVbGjSzg8SEbHG3*s=N1P~rJL=*F)`9JaYa-Am zULD^KDhw6_>n?cvf?6SRGenDcT@z7Mi&)(Vag-oV`(m`KMU3u%DQn}ODRsu3i^@+D zgyWvI!;=!fd5Yo%t%~WLifKO= zK0jP5RZItAdIBTflcXyVGhK-s&)v$I5#$Xshj`IBL_;?tj_yI4*GMx5QLQ?2oHk{| zSYAss2g{I7)Pj*Sd>$>B%c5LZD7`A`2}`4wMblv~XtC%mdZH$xlZalIMOmVKqGvD> zyHDi89;Y?fn<6nxf%!S)I+ok9{&%9TN_wkvu}5Ey4h$o_f5^rZXTGG!k6{Gpa0i; zfWNXPgd@b(0Mo9RVp8RUo*8p({=v^Dvhn!f<48aFZ;SX`@WOBrA#?1w=HnYr#pgT? zhU$SU%K>0G=?)c*>(9=Zj|L;4`Okj#;X6k(b>!tN)QlkhI6iy?bu6iHV4@d%J#fvL zjeOEbI<7LK(YK}Ix{?3L2)|Y$mKx!;V!07_)YGsuQ&>*ORyG)Q#e>%HXJbhw`o_QK zgjZA`jr#pJ7-xnWIp`5V8AK=xu2!>zGDcyGjF`jAt?>!RTq3jyf63%fh6OdqeP08s zkfsgpoG|ap)FZVO>G`^3y-&#}Ohw(YanHewXu#*L{$RZx@MUAozqU<-w5?%k!79`9 zdnZRon~8d+SE=pC`A6YC46fpkc94*g-^wiXC49{WVS92=hrjzc+)v=}ZH{s^7;*4z zi{HL373=YPm@l_-AM(<+Wm~M4)Et$`lF`m+%?KQ>k#HHt%(PUqHK#|_(vTI$z0WK<#hjUw zmNV*u8U?EPT4fqDP<;F-#NqTblQ9SN4K!wDNrD_Xai)d&9tm)Dp$wyO zQ@c1-^RFqw6J$gk=j7_|#IQ_$Ys#>N9n~Gw^{aSlsa-@2DP%vVHlh|+S&#Lcd!N&_ z3$~1T{PoiNIgd~5dHi)VufqJA2i5uPM0LI>y--9MN^6HT`eT91#D>kfyT%@s`K*go z*LYtmrW(q(2-OiKu}*bqLb%3LUB?MCu65l)Q&JN7Sj2^fX?)Z&-s@J^`@J`OWR5vI z)0oaBCU)gIn{!53vWIFUYK~7Qs@w4I>2#r7cZ(%Q-L!rUbxUog2b;O1gz)Z(-IEd$-`7m6Zsyp627_~Qvf2d&jTkW^FxP6%7D7!R!n?*>-Ploi z&!oi8Dn5&dv}|jRs>{G3W>bzjpOIAEcT6=R%4cffI5Vy^pTRAh4SAhbuQra{pdm>M zJys}cHEVLM-O~KQ>Y^B<_v4_NuMdoRu~zypsoSE7CrfYa&g`i9#g!X$>}kot1@|M_ zj`WoB^L_=a%X9Ve2GbUA-_YdG(6g&rop=*6ch8-Ytd_5D-kEb~>FTBDIy|ehWW=^z zF80BQ>u!f%?O){IkPSGOvF`Gt@sq9mc zOwOffsLblTr|P`N!oK#FvJKSrY@VCVFY@5?7V#dpcZBvyU zdIw~jK3`IhG;@?&ohhTWvo9Qb89Otno@w*0o|oJE?>|@ErKzYOR=@Pdb#1uM6Q5}R zArl`besVtS(x2ys>`fi_!-`+;?Y-=L?9jZ<6FTHYubg+Gxy!H7fvY@*eb(yikUNEOgU-AyY%20E(Y`qFV?k=7?TgjlK5IDe!dahfpZYxb?1X+@c<;Q0UX7l0Lmaw; zICQ!q4%N0edxR^EM%|`)uv+;1EnJPR3{Z%lkzty~ z>V{~CZ1uWzBD2j#gh(#ln2FIOMq$~S+Csxd^m0b@O0{ICXd0;-@X1~4dg!{uchPs@ z5GCW%GSV<+(^P~kQQZcW%W$2~C8Q0?#F&;(*!;hYNhe<3S$FsGVqfiGTkEsmcbYYC z+Pu~Uk+xssmYmLfg{}=6dsIl(h zYFAzw{r&QR>GMAiyEtm);x3v#UB#<5ZYgQ9{Z#IOJ^?+5Y^FzXZnH=4&MtiSs7xbm zFsP_c-M76zU9h0MJef8ln{Ge;<8?dh*WO`&Cgz^*rU|-HnpZMHs_c?{O6rJ7`AiJ< zRKy2S=^w++Us0*)k!=BE3og;YW90kXohNqMdHU+(zeOd!r*uRmL?J{aifh!myid-$ zt6eJthe-5K(JG8j*NjE1QX^IswwSE>m(l8K0BNF@G@Ae@uz0wey^Qy~Fyur+m|DN3G`@FSJ!$l|-zG zZju@s(J(o1RJ7>%vU%4sy0+}=J~z-HO8)6_%8N9Y=i}bp5B@r1+riXjtM_O|?k;F) z44J2C{P5}B6+dqZf9>9?gKf~>{SO1bn^P7tEU10))?VYn4|N|Va(@1#ZT$3B;>OIi zl1u&l@7G*xYpQS3b;`4&by~!H8NYUB&;s|-M-P4$aH#po{WBCkkIK}du1@*;p0@vb zLax)%hkG8Jv%Tzobkm7Zf3#UKdh5JiVRNf}zev1!cWk{p&$P#_x4sL0ae3>t#m{uL zmkyu(jrrN#m34PD-DEkOHf_M34#si)qbE!225#|+Qs-BLv1&)C^B`;H?(I?@_r;{O z%byMI{d>XHk7M2cXw2XPTCiH9Y4tv!XpG$s@?ez<>6jU z-KLGEdF8_D?zD4^#zW|uS!eg^`rJ%&db&AN(+~q#q<3+zjd2}U>E=R*n=2Q&y4Mcx zoM<);<`OLF!sVp3a*^ooi~h?X_rufg`W(n?x#W+`hReoPZ?&k~qVm^4ldF^k`xy?JDC%||25nHi@# zT?qBP*K2*_nzerRbM~)k3|?68?PU4&HCFNGH6u5C_1&_z?)T)=J=N`MAJ49z{zve$ zRf+kkCz<7@-F_MCe<;bQHoe!cJ^aIm&z^H_ytjPkq{Z7tJ-kx;r^^$5+B$0f@CmJd zsWl{}cUDlB<#X2l+-2OS{`>k3G>*Hqx5IDU=Ij3GzlEevzL7MeWW(*X9TJYaj+k}u z`%MKQgFA)R*f?Zblj{4sdJH=dcxXn3jvE=KTk^-9l5sblrd0;HZP-(rKL~RF7{&ey za!bh3nd7IOm9wiST3)^hkGkYrvh2ek=WG)Wz9Yy{+<^NR;myS`If|M5G7NzT12(p{ zI)V>x9NS5a;h2-VaDlU3!%#*<)&6R~$~Z-tdft54vtm3h+yOB2193}=B{0*R6Qt{! zpbm9}$#%F_XjK?o*nG0ON|iHk z@~_-5`V&h2zvq^N>!6D9A;yE1mlDEwu!x$JGQvDg zuXn$HrhbF5cT2l?k583-K?Z9RTJ$1cRjTu;4`mp2-W>J+WT>S75Xt|#axctM*RFD< z?ylj_kB09ru3bbL_bQ87T%Z1Rq34br`89O`$Y>s;IT&&&J!hwb*RuQ{Gx_Rx5EboJ8mou_`Z z{F=Wgu`Zl*RSrL+v&l&*9xQKkq1~E46SoYW`KwcY`LYGm zPF?Z(Vr=i96`rvrcQbEId}6xBx=PlZr-Qm&*q7=wApBCw+ZWw l^D-a)ruVsxjjUTb&RuWbb*iD!rb{ZA(?+fPtxGB){|B#n#qR(B literal 0 HcmV?d00001 diff --git a/spine-cpp/spine-cpp-unit-tests/tests/TestFixtureGenerator/makeFixture.bat b/spine-cpp/spine-cpp-unit-tests/tests/TestFixtureGenerator/makeFixture.bat new file mode 100755 index 000000000..634154a29 --- /dev/null +++ b/spine-cpp/spine-cpp-unit-tests/tests/TestFixtureGenerator/makeFixture.bat @@ -0,0 +1,17 @@ +@echo off +if "%1"=="" goto blank + +copy "_TestFixture.cpp" "%1TestFixture.cpp" +copy "_TestFixture.h" "%1TestFixture.h" + + +fnr --cl --find "[[FIXTURE_TYPE]]" --replace "%1TestFixture" --fileMask "%1TestFixture.cpp" --dir %cd% +fnr --cl --find "[[FIXTURE_TYPE]]" --replace "%1TestFixture" --fileMask "%1TestFixture.h" --dir %cd% + +goto done + +:blank +echo Usage: +echo %~n0 FixtureTypeName + +:done \ No newline at end of file diff --git a/spine-cpp/spine-cpp-unit-tests/tests/TestOptions.h b/spine-cpp/spine-cpp-unit-tests/tests/TestOptions.h new file mode 100755 index 000000000..7f00ffbb7 --- /dev/null +++ b/spine-cpp/spine-cpp-unit-tests/tests/TestOptions.h @@ -0,0 +1,32 @@ +#pragma once + +////////////////////////////////////////////////////////////////////////// +// Force all Tests to 'ON.' Use this for final 'Regression' Testing. + +//#define gForceAllTests + +//#define TURN_ON_ALL_TESTS // Comment this line out to switch to fast testing only + +#ifdef TURN_ON_ALL_TESTS +////////////////////////////////////////////////////////////////////////// +// All tests are ON by default, but you can turn off individual tests. + +#define gEmptyTestFixture +#define gCInterfaceTestFixture +#define gCPPInterfaceTestFixture +#define gMemoryTestFixture + + +#else + +////////////////////////////////////////////////////////////////////////// +// Slow Tests are disabled by default. Use this section to turn on +// Individual tests. +#define gEmptyTestFixture // Fast + +#define gCInterfaceTestFixture // slow +#define gCPPInterfaceTestFixture // fast + +#define gMemoryTestFixture // medium + +#endif \ No newline at end of file From 1e6d8b793a3c20e52e9d4b9a567dcd040ab94e88 Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Thu, 7 Dec 2017 03:23:40 -0500 Subject: [PATCH 71/83] Wip unit tests --- .../spine_unit_test.xcodeproj/project.pbxproj | 775 ++++++++++++++++++ .../contents.xcworkspacedata | 7 + .../spine_unit_test/SimpleTest.h | 197 +++++ .../spine_unit_test/spine_unit_test/main.cpp | 111 +++ .../tests/C_InterfaceTestFixture.cpp | 8 +- .../tests/SpineEventMonitor.cpp | 149 ++-- .../tests/SpineEventMonitor.h | 23 +- .../spine-cpp/include/spine/AnimationState.h | 6 +- .../spine-cpp/src/spine/AnimationState.cpp | 28 +- spine-cpp/spine-cpp/src/spine/Atlas.cpp | 3 +- 10 files changed, 1206 insertions(+), 101 deletions(-) create mode 100644 spine-cpp/spine-cpp-unit-tests/spine_unit_test/spine_unit_test.xcodeproj/project.pbxproj create mode 100644 spine-cpp/spine-cpp-unit-tests/spine_unit_test/spine_unit_test.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 spine-cpp/spine-cpp-unit-tests/spine_unit_test/spine_unit_test/SimpleTest.h create mode 100644 spine-cpp/spine-cpp-unit-tests/spine_unit_test/spine_unit_test/main.cpp diff --git a/spine-cpp/spine-cpp-unit-tests/spine_unit_test/spine_unit_test.xcodeproj/project.pbxproj b/spine-cpp/spine-cpp-unit-tests/spine_unit_test/spine_unit_test.xcodeproj/project.pbxproj new file mode 100644 index 000000000..4d3027361 --- /dev/null +++ b/spine-cpp/spine-cpp-unit-tests/spine_unit_test/spine_unit_test.xcodeproj/project.pbxproj @@ -0,0 +1,775 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 48; + objects = { + +/* Begin PBXBuildFile section */ + BB6017131FD9289A009BD546 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB6017121FD9289A009BD546 /* main.cpp */; }; + BB6017A21FD928AC009BD546 /* Attachment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB6017671FD928AC009BD546 /* Attachment.cpp */; }; + BB6017A31FD928AC009BD546 /* Skeleton.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB6017681FD928AC009BD546 /* Skeleton.cpp */; }; + BB6017A41FD928AC009BD546 /* TranslateTimeline.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB6017691FD928AC009BD546 /* TranslateTimeline.cpp */; }; + BB6017A51FD928AC009BD546 /* Extension.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB60176A1FD928AC009BD546 /* Extension.cpp */; }; + BB6017A61FD928AC009BD546 /* Updatable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB60176B1FD928AC009BD546 /* Updatable.cpp */; }; + BB6017A71FD928AC009BD546 /* Bone.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB60176C1FD928AC009BD546 /* Bone.cpp */; }; + BB6017A81FD928AC009BD546 /* AtlasAttachmentLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB60176D1FD928AC009BD546 /* AtlasAttachmentLoader.cpp */; }; + BB6017A91FD928AC009BD546 /* EventTimeline.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB60176E1FD928AC009BD546 /* EventTimeline.cpp */; }; + BB6017AA1FD928AC009BD546 /* PathConstraint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB60176F1FD928AC009BD546 /* PathConstraint.cpp */; }; + BB6017AB1FD928AC009BD546 /* VertexAttachment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB6017701FD928AC009BD546 /* VertexAttachment.cpp */; }; + BB6017AC1FD928AC009BD546 /* TextureLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB6017711FD928AC009BD546 /* TextureLoader.cpp */; }; + BB6017AD1FD928AC009BD546 /* SkeletonData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB6017721FD928AC009BD546 /* SkeletonData.cpp */; }; + BB6017AE1FD928AC009BD546 /* TransformConstraintTimeline.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB6017731FD928AC009BD546 /* TransformConstraintTimeline.cpp */; }; + BB6017AF1FD928AC009BD546 /* IkConstraint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB6017741FD928AC009BD546 /* IkConstraint.cpp */; }; + BB6017B01FD928AC009BD546 /* CurveTimeline.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB6017751FD928AC009BD546 /* CurveTimeline.cpp */; }; + BB6017B11FD928AC009BD546 /* AnimationStateData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB6017761FD928AC009BD546 /* AnimationStateData.cpp */; }; + BB6017B21FD928AC009BD546 /* Constraint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB6017771FD928AC009BD546 /* Constraint.cpp */; }; + BB6017B31FD928AC009BD546 /* BoundingBoxAttachment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB6017781FD928AC009BD546 /* BoundingBoxAttachment.cpp */; }; + BB6017B41FD928AC009BD546 /* PathAttachment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB6017791FD928AC009BD546 /* PathAttachment.cpp */; }; + BB6017B51FD928AC009BD546 /* MeshAttachment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB60177A1FD928AC009BD546 /* MeshAttachment.cpp */; }; + BB6017B61FD928AC009BD546 /* TransformConstraint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB60177B1FD928AC009BD546 /* TransformConstraint.cpp */; }; + BB6017B71FD928AC009BD546 /* Skin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB60177C1FD928AC009BD546 /* Skin.cpp */; }; + BB6017B81FD928AC009BD546 /* RTTI.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB60177D1FD928AC009BD546 /* RTTI.cpp */; }; + BB6017B91FD928AC009BD546 /* MathUtil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB60177E1FD928AC009BD546 /* MathUtil.cpp */; }; + BB6017BA1FD928AC009BD546 /* IkConstraintData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB60177F1FD928AC009BD546 /* IkConstraintData.cpp */; }; + BB6017BB1FD928AC009BD546 /* Atlas.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB6017801FD928AC009BD546 /* Atlas.cpp */; }; + BB6017BC1FD928AC009BD546 /* ClippingAttachment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB6017811FD928AC009BD546 /* ClippingAttachment.cpp */; }; + BB6017BD1FD928AC009BD546 /* PathConstraintData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB6017821FD928AC009BD546 /* PathConstraintData.cpp */; }; + BB6017BE1FD928AC009BD546 /* Timeline.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB6017831FD928AC009BD546 /* Timeline.cpp */; }; + BB6017BF1FD928AC009BD546 /* SkeletonBinary.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB6017841FD928AC009BD546 /* SkeletonBinary.cpp */; }; + BB6017C01FD928AC009BD546 /* ScaleTimeline.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB6017851FD928AC009BD546 /* ScaleTimeline.cpp */; }; + BB6017C11FD928AC009BD546 /* LinkedMesh.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB6017861FD928AC009BD546 /* LinkedMesh.cpp */; }; + BB6017C21FD928AC009BD546 /* PointAttachment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB6017871FD928AC009BD546 /* PointAttachment.cpp */; }; + BB6017C31FD928AC009BD546 /* RegionAttachment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB6017881FD928AC009BD546 /* RegionAttachment.cpp */; }; + BB6017C41FD928AC009BD546 /* DeformTimeline.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB6017891FD928AC009BD546 /* DeformTimeline.cpp */; }; + BB6017C51FD928AC009BD546 /* Animation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB60178A1FD928AC009BD546 /* Animation.cpp */; }; + BB6017C61FD928AC009BD546 /* AttachmentLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB60178B1FD928AC009BD546 /* AttachmentLoader.cpp */; }; + BB6017C71FD928AC009BD546 /* DrawOrderTimeline.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB60178C1FD928AC009BD546 /* DrawOrderTimeline.cpp */; }; + BB6017C81FD928AC009BD546 /* AttachmentTimeline.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB60178D1FD928AC009BD546 /* AttachmentTimeline.cpp */; }; + BB6017C91FD928AC009BD546 /* EventData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB60178E1FD928AC009BD546 /* EventData.cpp */; }; + BB6017CA1FD928AC009BD546 /* PathConstraintSpacingTimeline.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB60178F1FD928AC009BD546 /* PathConstraintSpacingTimeline.cpp */; }; + BB6017CB1FD928AC009BD546 /* PathConstraintPositionTimeline.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB6017901FD928AC009BD546 /* PathConstraintPositionTimeline.cpp */; }; + BB6017CC1FD928AC009BD546 /* TransformConstraintData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB6017911FD928AC009BD546 /* TransformConstraintData.cpp */; }; + BB6017CD1FD928AC009BD546 /* SkeletonClipping.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB6017921FD928AC009BD546 /* SkeletonClipping.cpp */; }; + BB6017CE1FD928AC009BD546 /* TwoColorTimeline.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB6017931FD928AC009BD546 /* TwoColorTimeline.cpp */; }; + BB6017CF1FD928AC009BD546 /* Slot.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB6017941FD928AC009BD546 /* Slot.cpp */; }; + BB6017D01FD928AC009BD546 /* AnimationState.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB6017951FD928AC009BD546 /* AnimationState.cpp */; }; + BB6017D11FD928AC009BD546 /* SkeletonJson.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB6017961FD928AC009BD546 /* SkeletonJson.cpp */; }; + BB6017D21FD928AC009BD546 /* BoneData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB6017971FD928AC009BD546 /* BoneData.cpp */; }; + BB6017D31FD928AC009BD546 /* IkConstraintTimeline.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB6017981FD928AC009BD546 /* IkConstraintTimeline.cpp */; }; + BB6017D41FD928AC009BD546 /* Event.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB6017991FD928AC009BD546 /* Event.cpp */; }; + BB6017D51FD928AC009BD546 /* RotateTimeline.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB60179A1FD928AC009BD546 /* RotateTimeline.cpp */; }; + BB6017D61FD928AC009BD546 /* PathConstraintMixTimeline.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB60179B1FD928AC009BD546 /* PathConstraintMixTimeline.cpp */; }; + BB6017D71FD928AC009BD546 /* Triangulator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB60179C1FD928AC009BD546 /* Triangulator.cpp */; }; + BB6017D81FD928AC009BD546 /* Json.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB60179D1FD928AC009BD546 /* Json.cpp */; }; + BB6017D91FD928AC009BD546 /* SkeletonBounds.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB60179E1FD928AC009BD546 /* SkeletonBounds.cpp */; }; + BB6017DA1FD928AC009BD546 /* SlotData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB60179F1FD928AC009BD546 /* SlotData.cpp */; }; + BB6017DB1FD928AC009BD546 /* ShearTimeline.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB6017A01FD928AC009BD546 /* ShearTimeline.cpp */; }; + BB6017DC1FD928AC009BD546 /* ColorTimeline.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB6017A11FD928AC009BD546 /* ColorTimeline.cpp */; }; + BB6017E21FD928F7009BD546 /* KMemory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB6017E01FD928F6009BD546 /* KMemory.cpp */; }; + BB6017E31FD928F7009BD546 /* KString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB6017E11FD928F6009BD546 /* KString.cpp */; }; + BB6017E71FD929D0009BD546 /* MiniCppUnit.cxx in Sources */ = {isa = PBXBuildFile; fileRef = BB6017E61FD929D0009BD546 /* MiniCppUnit.cxx */; }; + BB6017EE1FD929F4009BD546 /* teamcity_cppunit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB6017EA1FD929F4009BD546 /* teamcity_cppunit.cpp */; }; + BB6017EF1FD929F4009BD546 /* teamcity_messages.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB6017ED1FD929F4009BD546 /* teamcity_messages.cpp */; }; + BB6018081FD92AF4009BD546 /* SpineEventMonitor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB6017FD1FD92AF3009BD546 /* SpineEventMonitor.cpp */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + BB60170D1FD9289A009BD546 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + ); + runOnlyForDeploymentPostprocessing = 1; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + BB60170F1FD9289A009BD546 /* spine_unit_test */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = spine_unit_test; sourceTree = BUILT_PRODUCTS_DIR; }; + BB6017121FD9289A009BD546 /* main.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; + BB60171C1FD928AC009BD546 /* DeformTimeline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DeformTimeline.h; sourceTree = ""; }; + BB60171D1FD928AC009BD546 /* Animation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Animation.h; sourceTree = ""; }; + BB60171E1FD928AC009BD546 /* EventData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EventData.h; sourceTree = ""; }; + BB60171F1FD928AC009BD546 /* SlotData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SlotData.h; sourceTree = ""; }; + BB6017201FD928AC009BD546 /* PathConstraintMixTimeline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PathConstraintMixTimeline.h; sourceTree = ""; }; + BB6017211FD928AC009BD546 /* SkeletonClipping.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SkeletonClipping.h; sourceTree = ""; }; + BB6017221FD928AC009BD546 /* Pool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Pool.h; sourceTree = ""; }; + BB6017231FD928AC009BD546 /* TimelineType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TimelineType.h; sourceTree = ""; }; + BB6017241FD928AC009BD546 /* TextureLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextureLoader.h; sourceTree = ""; }; + BB6017251FD928AC009BD546 /* PositionMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PositionMode.h; sourceTree = ""; }; + BB6017261FD928AC009BD546 /* RTTI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RTTI.h; sourceTree = ""; }; + BB6017271FD928AC009BD546 /* PathAttachment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PathAttachment.h; sourceTree = ""; }; + BB6017281FD928AC009BD546 /* MixDirection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MixDirection.h; sourceTree = ""; }; + BB6017291FD928AC009BD546 /* CurveTimeline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CurveTimeline.h; sourceTree = ""; }; + BB60172A1FD928AC009BD546 /* PointAttachment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PointAttachment.h; sourceTree = ""; }; + BB60172B1FD928AC009BD546 /* Event.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Event.h; sourceTree = ""; }; + BB60172C1FD928AC009BD546 /* Bone.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Bone.h; sourceTree = ""; }; + BB60172D1FD928AC009BD546 /* Atlas.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Atlas.h; sourceTree = ""; }; + BB60172E1FD928AC009BD546 /* DrawOrderTimeline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DrawOrderTimeline.h; sourceTree = ""; }; + BB60172F1FD928AC009BD546 /* TransformConstraintTimeline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TransformConstraintTimeline.h; sourceTree = ""; }; + BB6017301FD928AC009BD546 /* IkConstraintTimeline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IkConstraintTimeline.h; sourceTree = ""; }; + BB6017311FD928AC009BD546 /* VertexAttachment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VertexAttachment.h; sourceTree = ""; }; + BB6017321FD928AC009BD546 /* AttachmentType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AttachmentType.h; sourceTree = ""; }; + BB6017331FD928AC009BD546 /* RotateMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RotateMode.h; sourceTree = ""; }; + BB6017341FD928AC009BD546 /* ClippingAttachment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ClippingAttachment.h; sourceTree = ""; }; + BB6017351FD928AC009BD546 /* PathConstraintPositionTimeline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PathConstraintPositionTimeline.h; sourceTree = ""; }; + BB6017361FD928AC009BD546 /* RotateTimeline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RotateTimeline.h; sourceTree = ""; }; + BB6017371FD928AC009BD546 /* Triangulator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Triangulator.h; sourceTree = ""; }; + BB6017381FD928AC009BD546 /* RegionAttachment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegionAttachment.h; sourceTree = ""; }; + BB6017391FD928AC009BD546 /* Attachment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Attachment.h; sourceTree = ""; }; + BB60173A1FD928AC009BD546 /* HashMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HashMap.h; sourceTree = ""; }; + BB60173B1FD928AC009BD546 /* TransformConstraint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TransformConstraint.h; sourceTree = ""; }; + BB60173C1FD928AC009BD546 /* TransformMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TransformMode.h; sourceTree = ""; }; + BB60173D1FD928AC009BD546 /* SkeletonJson.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SkeletonJson.h; sourceTree = ""; }; + BB60173E1FD928AC009BD546 /* IkConstraintData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IkConstraintData.h; sourceTree = ""; }; + BB60173F1FD928AC009BD546 /* MixPose.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MixPose.h; sourceTree = ""; }; + BB6017401FD928AC009BD546 /* AnimationStateData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AnimationStateData.h; sourceTree = ""; }; + BB6017411FD928AC009BD546 /* TwoColorTimeline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TwoColorTimeline.h; sourceTree = ""; }; + BB6017421FD928AC009BD546 /* Skeleton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Skeleton.h; sourceTree = ""; }; + BB6017431FD928AC009BD546 /* ColorTimeline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ColorTimeline.h; sourceTree = ""; }; + BB6017441FD928AC009BD546 /* SpacingMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpacingMode.h; sourceTree = ""; }; + BB6017451FD928AC009BD546 /* Vertices.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Vertices.h; sourceTree = ""; }; + BB6017461FD928AC009BD546 /* Constraint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Constraint.h; sourceTree = ""; }; + BB6017471FD928AC009BD546 /* LinkedMesh.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LinkedMesh.h; sourceTree = ""; }; + BB6017481FD928AC009BD546 /* ShearTimeline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ShearTimeline.h; sourceTree = ""; }; + BB6017491FD928AC009BD546 /* Json.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Json.h; sourceTree = ""; }; + BB60174A1FD928AC009BD546 /* AttachmentLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AttachmentLoader.h; sourceTree = ""; }; + BB60174B1FD928AC009BD546 /* Skin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Skin.h; sourceTree = ""; }; + BB60174C1FD928AC009BD546 /* AttachmentTimeline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AttachmentTimeline.h; sourceTree = ""; }; + BB60174D1FD928AC009BD546 /* SkeletonBinary.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SkeletonBinary.h; sourceTree = ""; }; + BB60174E1FD928AC009BD546 /* SkeletonData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SkeletonData.h; sourceTree = ""; }; + BB60174F1FD928AC009BD546 /* ContainerUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContainerUtil.h; sourceTree = ""; }; + BB6017501FD928AC009BD546 /* PathConstraintData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PathConstraintData.h; sourceTree = ""; }; + BB6017511FD928AC009BD546 /* Updatable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Updatable.h; sourceTree = ""; }; + BB6017521FD928AC009BD546 /* TransformConstraintData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TransformConstraintData.h; sourceTree = ""; }; + BB6017531FD928AC009BD546 /* Extension.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Extension.h; sourceTree = ""; }; + BB6017541FD928AC009BD546 /* BlendMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BlendMode.h; sourceTree = ""; }; + BB6017551FD928AC009BD546 /* PathConstraint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PathConstraint.h; sourceTree = ""; }; + BB6017561FD928AC009BD546 /* PathConstraintSpacingTimeline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PathConstraintSpacingTimeline.h; sourceTree = ""; }; + BB6017571FD928AC009BD546 /* ScaleTimeline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScaleTimeline.h; sourceTree = ""; }; + BB6017581FD928AC009BD546 /* IkConstraint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IkConstraint.h; sourceTree = ""; }; + BB6017591FD928AC009BD546 /* BoundingBoxAttachment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BoundingBoxAttachment.h; sourceTree = ""; }; + BB60175A1FD928AC009BD546 /* MathUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MathUtil.h; sourceTree = ""; }; + BB60175B1FD928AC009BD546 /* Vector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Vector.h; sourceTree = ""; }; + BB60175C1FD928AC009BD546 /* SkeletonBounds.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SkeletonBounds.h; sourceTree = ""; }; + BB60175D1FD928AC009BD546 /* Timeline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Timeline.h; sourceTree = ""; }; + BB60175E1FD928AC009BD546 /* Slot.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Slot.h; sourceTree = ""; }; + BB60175F1FD928AC009BD546 /* BoneData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BoneData.h; sourceTree = ""; }; + BB6017601FD928AC009BD546 /* TranslateTimeline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TranslateTimeline.h; sourceTree = ""; }; + BB6017611FD928AC009BD546 /* AnimationState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AnimationState.h; sourceTree = ""; }; + BB6017621FD928AC009BD546 /* MeshAttachment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MeshAttachment.h; sourceTree = ""; }; + BB6017631FD928AC009BD546 /* AtlasAttachmentLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AtlasAttachmentLoader.h; sourceTree = ""; }; + BB6017641FD928AC009BD546 /* EventTimeline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EventTimeline.h; sourceTree = ""; }; + BB6017671FD928AC009BD546 /* Attachment.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Attachment.cpp; sourceTree = ""; }; + BB6017681FD928AC009BD546 /* Skeleton.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Skeleton.cpp; sourceTree = ""; }; + BB6017691FD928AC009BD546 /* TranslateTimeline.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TranslateTimeline.cpp; sourceTree = ""; }; + BB60176A1FD928AC009BD546 /* Extension.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Extension.cpp; sourceTree = ""; }; + BB60176B1FD928AC009BD546 /* Updatable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Updatable.cpp; sourceTree = ""; }; + BB60176C1FD928AC009BD546 /* Bone.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Bone.cpp; sourceTree = ""; }; + BB60176D1FD928AC009BD546 /* AtlasAttachmentLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AtlasAttachmentLoader.cpp; sourceTree = ""; }; + BB60176E1FD928AC009BD546 /* EventTimeline.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EventTimeline.cpp; sourceTree = ""; }; + BB60176F1FD928AC009BD546 /* PathConstraint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PathConstraint.cpp; sourceTree = ""; }; + BB6017701FD928AC009BD546 /* VertexAttachment.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VertexAttachment.cpp; sourceTree = ""; }; + BB6017711FD928AC009BD546 /* TextureLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TextureLoader.cpp; sourceTree = ""; }; + BB6017721FD928AC009BD546 /* SkeletonData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SkeletonData.cpp; sourceTree = ""; }; + BB6017731FD928AC009BD546 /* TransformConstraintTimeline.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TransformConstraintTimeline.cpp; sourceTree = ""; }; + BB6017741FD928AC009BD546 /* IkConstraint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IkConstraint.cpp; sourceTree = ""; }; + BB6017751FD928AC009BD546 /* CurveTimeline.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CurveTimeline.cpp; sourceTree = ""; }; + BB6017761FD928AC009BD546 /* AnimationStateData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AnimationStateData.cpp; sourceTree = ""; }; + BB6017771FD928AC009BD546 /* Constraint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Constraint.cpp; sourceTree = ""; }; + BB6017781FD928AC009BD546 /* BoundingBoxAttachment.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BoundingBoxAttachment.cpp; sourceTree = ""; }; + BB6017791FD928AC009BD546 /* PathAttachment.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PathAttachment.cpp; sourceTree = ""; }; + BB60177A1FD928AC009BD546 /* MeshAttachment.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MeshAttachment.cpp; sourceTree = ""; }; + BB60177B1FD928AC009BD546 /* TransformConstraint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TransformConstraint.cpp; sourceTree = ""; }; + BB60177C1FD928AC009BD546 /* Skin.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Skin.cpp; sourceTree = ""; }; + BB60177D1FD928AC009BD546 /* RTTI.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RTTI.cpp; sourceTree = ""; }; + BB60177E1FD928AC009BD546 /* MathUtil.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MathUtil.cpp; sourceTree = ""; }; + BB60177F1FD928AC009BD546 /* IkConstraintData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IkConstraintData.cpp; sourceTree = ""; }; + BB6017801FD928AC009BD546 /* Atlas.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Atlas.cpp; sourceTree = ""; }; + BB6017811FD928AC009BD546 /* ClippingAttachment.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ClippingAttachment.cpp; sourceTree = ""; }; + BB6017821FD928AC009BD546 /* PathConstraintData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PathConstraintData.cpp; sourceTree = ""; }; + BB6017831FD928AC009BD546 /* Timeline.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Timeline.cpp; sourceTree = ""; }; + BB6017841FD928AC009BD546 /* SkeletonBinary.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SkeletonBinary.cpp; sourceTree = ""; }; + BB6017851FD928AC009BD546 /* ScaleTimeline.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScaleTimeline.cpp; sourceTree = ""; }; + BB6017861FD928AC009BD546 /* LinkedMesh.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LinkedMesh.cpp; sourceTree = ""; }; + BB6017871FD928AC009BD546 /* PointAttachment.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PointAttachment.cpp; sourceTree = ""; }; + BB6017881FD928AC009BD546 /* RegionAttachment.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegionAttachment.cpp; sourceTree = ""; }; + BB6017891FD928AC009BD546 /* DeformTimeline.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DeformTimeline.cpp; sourceTree = ""; }; + BB60178A1FD928AC009BD546 /* Animation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Animation.cpp; sourceTree = ""; }; + BB60178B1FD928AC009BD546 /* AttachmentLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AttachmentLoader.cpp; sourceTree = ""; }; + BB60178C1FD928AC009BD546 /* DrawOrderTimeline.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DrawOrderTimeline.cpp; sourceTree = ""; }; + BB60178D1FD928AC009BD546 /* AttachmentTimeline.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AttachmentTimeline.cpp; sourceTree = ""; }; + BB60178E1FD928AC009BD546 /* EventData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EventData.cpp; sourceTree = ""; }; + BB60178F1FD928AC009BD546 /* PathConstraintSpacingTimeline.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PathConstraintSpacingTimeline.cpp; sourceTree = ""; }; + BB6017901FD928AC009BD546 /* PathConstraintPositionTimeline.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PathConstraintPositionTimeline.cpp; sourceTree = ""; }; + BB6017911FD928AC009BD546 /* TransformConstraintData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TransformConstraintData.cpp; sourceTree = ""; }; + BB6017921FD928AC009BD546 /* SkeletonClipping.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SkeletonClipping.cpp; sourceTree = ""; }; + BB6017931FD928AC009BD546 /* TwoColorTimeline.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TwoColorTimeline.cpp; sourceTree = ""; }; + BB6017941FD928AC009BD546 /* Slot.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Slot.cpp; sourceTree = ""; }; + BB6017951FD928AC009BD546 /* AnimationState.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AnimationState.cpp; sourceTree = ""; }; + BB6017961FD928AC009BD546 /* SkeletonJson.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SkeletonJson.cpp; sourceTree = ""; }; + BB6017971FD928AC009BD546 /* BoneData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BoneData.cpp; sourceTree = ""; }; + BB6017981FD928AC009BD546 /* IkConstraintTimeline.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IkConstraintTimeline.cpp; sourceTree = ""; }; + BB6017991FD928AC009BD546 /* Event.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Event.cpp; sourceTree = ""; }; + BB60179A1FD928AC009BD546 /* RotateTimeline.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RotateTimeline.cpp; sourceTree = ""; }; + BB60179B1FD928AC009BD546 /* PathConstraintMixTimeline.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PathConstraintMixTimeline.cpp; sourceTree = ""; }; + BB60179C1FD928AC009BD546 /* Triangulator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Triangulator.cpp; sourceTree = ""; }; + BB60179D1FD928AC009BD546 /* Json.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Json.cpp; sourceTree = ""; }; + BB60179E1FD928AC009BD546 /* SkeletonBounds.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SkeletonBounds.cpp; sourceTree = ""; }; + BB60179F1FD928AC009BD546 /* SlotData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SlotData.cpp; sourceTree = ""; }; + BB6017A01FD928AC009BD546 /* ShearTimeline.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ShearTimeline.cpp; sourceTree = ""; }; + BB6017A11FD928AC009BD546 /* ColorTimeline.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ColorTimeline.cpp; sourceTree = ""; }; + BB6017DE1FD928F6009BD546 /* KMemory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KMemory.h; sourceTree = ""; }; + BB6017DF1FD928F6009BD546 /* KString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KString.h; sourceTree = ""; }; + BB6017E01FD928F6009BD546 /* KMemory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = KMemory.cpp; sourceTree = ""; }; + BB6017E11FD928F6009BD546 /* KString.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = KString.cpp; sourceTree = ""; }; + BB6017E51FD929D0009BD546 /* MiniCppUnit.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = MiniCppUnit.hxx; sourceTree = ""; }; + BB6017E61FD929D0009BD546 /* MiniCppUnit.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MiniCppUnit.cxx; sourceTree = ""; }; + BB6017E91FD929F4009BD546 /* teamcity_cppunit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = teamcity_cppunit.h; sourceTree = ""; }; + BB6017EA1FD929F4009BD546 /* teamcity_cppunit.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = teamcity_cppunit.cpp; sourceTree = ""; }; + BB6017EB1FD929F4009BD546 /* teamcity_messages.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = teamcity_messages.h; sourceTree = ""; }; + BB6017EC1FD929F4009BD546 /* README.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README.txt; sourceTree = ""; }; + BB6017ED1FD929F4009BD546 /* teamcity_messages.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = teamcity_messages.cpp; sourceTree = ""; }; + BB6017F01FD92A5B009BD546 /* SimpleTest.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SimpleTest.h; sourceTree = ""; }; + BB6017FC1FD92AF3009BD546 /* SpineEventMonitor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpineEventMonitor.h; sourceTree = ""; }; + BB6017FD1FD92AF3009BD546 /* SpineEventMonitor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SpineEventMonitor.cpp; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + BB60170C1FD9289A009BD546 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + BB6017061FD9289A009BD546 = { + isa = PBXGroup; + children = ( + BB6017F11FD92AF3009BD546 /* tests */, + BB6017E81FD929F4009BD546 /* teamcity */, + BB6017E41FD929D0009BD546 /* minicppunit */, + BB6017DD1FD928F6009BD546 /* memory */, + BB6017191FD928AC009BD546 /* spine-cpp */, + BB6017111FD9289A009BD546 /* spine_unit_test */, + BB6017101FD9289A009BD546 /* Products */, + ); + sourceTree = ""; + }; + BB6017101FD9289A009BD546 /* Products */ = { + isa = PBXGroup; + children = ( + BB60170F1FD9289A009BD546 /* spine_unit_test */, + ); + name = Products; + sourceTree = ""; + }; + BB6017111FD9289A009BD546 /* spine_unit_test */ = { + isa = PBXGroup; + children = ( + BB6017121FD9289A009BD546 /* main.cpp */, + BB6017F01FD92A5B009BD546 /* SimpleTest.h */, + ); + path = spine_unit_test; + sourceTree = ""; + }; + BB6017191FD928AC009BD546 /* spine-cpp */ = { + isa = PBXGroup; + children = ( + BB60171A1FD928AC009BD546 /* include */, + BB6017651FD928AC009BD546 /* src */, + ); + name = "spine-cpp"; + path = "../../spine-cpp"; + sourceTree = ""; + }; + BB60171A1FD928AC009BD546 /* include */ = { + isa = PBXGroup; + children = ( + BB60171B1FD928AC009BD546 /* spine */, + ); + path = include; + sourceTree = ""; + }; + BB60171B1FD928AC009BD546 /* spine */ = { + isa = PBXGroup; + children = ( + BB60171D1FD928AC009BD546 /* Animation.h */, + BB6017611FD928AC009BD546 /* AnimationState.h */, + BB6017401FD928AC009BD546 /* AnimationStateData.h */, + BB60172D1FD928AC009BD546 /* Atlas.h */, + BB6017631FD928AC009BD546 /* AtlasAttachmentLoader.h */, + BB6017391FD928AC009BD546 /* Attachment.h */, + BB60174A1FD928AC009BD546 /* AttachmentLoader.h */, + BB60174C1FD928AC009BD546 /* AttachmentTimeline.h */, + BB6017321FD928AC009BD546 /* AttachmentType.h */, + BB6017541FD928AC009BD546 /* BlendMode.h */, + BB60172C1FD928AC009BD546 /* Bone.h */, + BB60175F1FD928AC009BD546 /* BoneData.h */, + BB6017591FD928AC009BD546 /* BoundingBoxAttachment.h */, + BB6017341FD928AC009BD546 /* ClippingAttachment.h */, + BB6017431FD928AC009BD546 /* ColorTimeline.h */, + BB6017461FD928AC009BD546 /* Constraint.h */, + BB60174F1FD928AC009BD546 /* ContainerUtil.h */, + BB6017291FD928AC009BD546 /* CurveTimeline.h */, + BB60171C1FD928AC009BD546 /* DeformTimeline.h */, + BB60172E1FD928AC009BD546 /* DrawOrderTimeline.h */, + BB60172B1FD928AC009BD546 /* Event.h */, + BB60171E1FD928AC009BD546 /* EventData.h */, + BB6017641FD928AC009BD546 /* EventTimeline.h */, + BB6017531FD928AC009BD546 /* Extension.h */, + BB60173A1FD928AC009BD546 /* HashMap.h */, + BB6017581FD928AC009BD546 /* IkConstraint.h */, + BB60173E1FD928AC009BD546 /* IkConstraintData.h */, + BB6017301FD928AC009BD546 /* IkConstraintTimeline.h */, + BB6017491FD928AC009BD546 /* Json.h */, + BB6017471FD928AC009BD546 /* LinkedMesh.h */, + BB60175A1FD928AC009BD546 /* MathUtil.h */, + BB6017621FD928AC009BD546 /* MeshAttachment.h */, + BB6017281FD928AC009BD546 /* MixDirection.h */, + BB60173F1FD928AC009BD546 /* MixPose.h */, + BB6017271FD928AC009BD546 /* PathAttachment.h */, + BB6017551FD928AC009BD546 /* PathConstraint.h */, + BB6017501FD928AC009BD546 /* PathConstraintData.h */, + BB6017201FD928AC009BD546 /* PathConstraintMixTimeline.h */, + BB6017351FD928AC009BD546 /* PathConstraintPositionTimeline.h */, + BB6017561FD928AC009BD546 /* PathConstraintSpacingTimeline.h */, + BB60172A1FD928AC009BD546 /* PointAttachment.h */, + BB6017221FD928AC009BD546 /* Pool.h */, + BB6017251FD928AC009BD546 /* PositionMode.h */, + BB6017381FD928AC009BD546 /* RegionAttachment.h */, + BB6017331FD928AC009BD546 /* RotateMode.h */, + BB6017361FD928AC009BD546 /* RotateTimeline.h */, + BB6017261FD928AC009BD546 /* RTTI.h */, + BB6017571FD928AC009BD546 /* ScaleTimeline.h */, + BB6017481FD928AC009BD546 /* ShearTimeline.h */, + BB6017421FD928AC009BD546 /* Skeleton.h */, + BB60174D1FD928AC009BD546 /* SkeletonBinary.h */, + BB60175C1FD928AC009BD546 /* SkeletonBounds.h */, + BB6017211FD928AC009BD546 /* SkeletonClipping.h */, + BB60174E1FD928AC009BD546 /* SkeletonData.h */, + BB60173D1FD928AC009BD546 /* SkeletonJson.h */, + BB60174B1FD928AC009BD546 /* Skin.h */, + BB60175E1FD928AC009BD546 /* Slot.h */, + BB60171F1FD928AC009BD546 /* SlotData.h */, + BB6017441FD928AC009BD546 /* SpacingMode.h */, + BB6017241FD928AC009BD546 /* TextureLoader.h */, + BB60175D1FD928AC009BD546 /* Timeline.h */, + BB6017231FD928AC009BD546 /* TimelineType.h */, + BB60173B1FD928AC009BD546 /* TransformConstraint.h */, + BB6017521FD928AC009BD546 /* TransformConstraintData.h */, + BB60172F1FD928AC009BD546 /* TransformConstraintTimeline.h */, + BB60173C1FD928AC009BD546 /* TransformMode.h */, + BB6017601FD928AC009BD546 /* TranslateTimeline.h */, + BB6017371FD928AC009BD546 /* Triangulator.h */, + BB6017411FD928AC009BD546 /* TwoColorTimeline.h */, + BB6017511FD928AC009BD546 /* Updatable.h */, + BB60175B1FD928AC009BD546 /* Vector.h */, + BB6017311FD928AC009BD546 /* VertexAttachment.h */, + BB6017451FD928AC009BD546 /* Vertices.h */, + ); + path = spine; + sourceTree = ""; + }; + BB6017651FD928AC009BD546 /* src */ = { + isa = PBXGroup; + children = ( + BB6017661FD928AC009BD546 /* spine */, + ); + path = src; + sourceTree = ""; + }; + BB6017661FD928AC009BD546 /* spine */ = { + isa = PBXGroup; + children = ( + BB60178A1FD928AC009BD546 /* Animation.cpp */, + BB6017951FD928AC009BD546 /* AnimationState.cpp */, + BB6017761FD928AC009BD546 /* AnimationStateData.cpp */, + BB6017801FD928AC009BD546 /* Atlas.cpp */, + BB60176D1FD928AC009BD546 /* AtlasAttachmentLoader.cpp */, + BB6017671FD928AC009BD546 /* Attachment.cpp */, + BB60178B1FD928AC009BD546 /* AttachmentLoader.cpp */, + BB60178D1FD928AC009BD546 /* AttachmentTimeline.cpp */, + BB60176C1FD928AC009BD546 /* Bone.cpp */, + BB6017971FD928AC009BD546 /* BoneData.cpp */, + BB6017781FD928AC009BD546 /* BoundingBoxAttachment.cpp */, + BB6017811FD928AC009BD546 /* ClippingAttachment.cpp */, + BB6017A11FD928AC009BD546 /* ColorTimeline.cpp */, + BB6017771FD928AC009BD546 /* Constraint.cpp */, + BB6017751FD928AC009BD546 /* CurveTimeline.cpp */, + BB6017891FD928AC009BD546 /* DeformTimeline.cpp */, + BB60178C1FD928AC009BD546 /* DrawOrderTimeline.cpp */, + BB6017991FD928AC009BD546 /* Event.cpp */, + BB60178E1FD928AC009BD546 /* EventData.cpp */, + BB60176E1FD928AC009BD546 /* EventTimeline.cpp */, + BB60176A1FD928AC009BD546 /* Extension.cpp */, + BB6017741FD928AC009BD546 /* IkConstraint.cpp */, + BB60177F1FD928AC009BD546 /* IkConstraintData.cpp */, + BB6017981FD928AC009BD546 /* IkConstraintTimeline.cpp */, + BB60179D1FD928AC009BD546 /* Json.cpp */, + BB6017861FD928AC009BD546 /* LinkedMesh.cpp */, + BB60177E1FD928AC009BD546 /* MathUtil.cpp */, + BB60177A1FD928AC009BD546 /* MeshAttachment.cpp */, + BB6017791FD928AC009BD546 /* PathAttachment.cpp */, + BB60176F1FD928AC009BD546 /* PathConstraint.cpp */, + BB6017821FD928AC009BD546 /* PathConstraintData.cpp */, + BB60179B1FD928AC009BD546 /* PathConstraintMixTimeline.cpp */, + BB6017901FD928AC009BD546 /* PathConstraintPositionTimeline.cpp */, + BB60178F1FD928AC009BD546 /* PathConstraintSpacingTimeline.cpp */, + BB6017871FD928AC009BD546 /* PointAttachment.cpp */, + BB6017881FD928AC009BD546 /* RegionAttachment.cpp */, + BB60179A1FD928AC009BD546 /* RotateTimeline.cpp */, + BB60177D1FD928AC009BD546 /* RTTI.cpp */, + BB6017851FD928AC009BD546 /* ScaleTimeline.cpp */, + BB6017A01FD928AC009BD546 /* ShearTimeline.cpp */, + BB6017681FD928AC009BD546 /* Skeleton.cpp */, + BB6017841FD928AC009BD546 /* SkeletonBinary.cpp */, + BB60179E1FD928AC009BD546 /* SkeletonBounds.cpp */, + BB6017921FD928AC009BD546 /* SkeletonClipping.cpp */, + BB6017721FD928AC009BD546 /* SkeletonData.cpp */, + BB6017961FD928AC009BD546 /* SkeletonJson.cpp */, + BB60177C1FD928AC009BD546 /* Skin.cpp */, + BB6017941FD928AC009BD546 /* Slot.cpp */, + BB60179F1FD928AC009BD546 /* SlotData.cpp */, + BB6017711FD928AC009BD546 /* TextureLoader.cpp */, + BB6017831FD928AC009BD546 /* Timeline.cpp */, + BB60177B1FD928AC009BD546 /* TransformConstraint.cpp */, + BB6017911FD928AC009BD546 /* TransformConstraintData.cpp */, + BB6017731FD928AC009BD546 /* TransformConstraintTimeline.cpp */, + BB6017691FD928AC009BD546 /* TranslateTimeline.cpp */, + BB60179C1FD928AC009BD546 /* Triangulator.cpp */, + BB6017931FD928AC009BD546 /* TwoColorTimeline.cpp */, + BB60176B1FD928AC009BD546 /* Updatable.cpp */, + BB6017701FD928AC009BD546 /* VertexAttachment.cpp */, + ); + path = spine; + sourceTree = ""; + }; + BB6017DD1FD928F6009BD546 /* memory */ = { + isa = PBXGroup; + children = ( + BB6017DE1FD928F6009BD546 /* KMemory.h */, + BB6017DF1FD928F6009BD546 /* KString.h */, + BB6017E01FD928F6009BD546 /* KMemory.cpp */, + BB6017E11FD928F6009BD546 /* KString.cpp */, + ); + name = memory; + path = ../memory; + sourceTree = ""; + }; + BB6017E41FD929D0009BD546 /* minicppunit */ = { + isa = PBXGroup; + children = ( + BB6017E51FD929D0009BD546 /* MiniCppUnit.hxx */, + BB6017E61FD929D0009BD546 /* MiniCppUnit.cxx */, + ); + name = minicppunit; + path = ../minicppunit; + sourceTree = ""; + }; + BB6017E81FD929F4009BD546 /* teamcity */ = { + isa = PBXGroup; + children = ( + BB6017E91FD929F4009BD546 /* teamcity_cppunit.h */, + BB6017EA1FD929F4009BD546 /* teamcity_cppunit.cpp */, + BB6017EB1FD929F4009BD546 /* teamcity_messages.h */, + BB6017EC1FD929F4009BD546 /* README.txt */, + BB6017ED1FD929F4009BD546 /* teamcity_messages.cpp */, + ); + name = teamcity; + path = ../teamcity; + sourceTree = ""; + }; + BB6017F11FD92AF3009BD546 /* tests */ = { + isa = PBXGroup; + children = ( + BB6017FC1FD92AF3009BD546 /* SpineEventMonitor.h */, + BB6017FD1FD92AF3009BD546 /* SpineEventMonitor.cpp */, + ); + name = tests; + path = ../tests; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + BB60170E1FD9289A009BD546 /* spine_unit_test */ = { + isa = PBXNativeTarget; + buildConfigurationList = BB6017161FD9289A009BD546 /* Build configuration list for PBXNativeTarget "spine_unit_test" */; + buildPhases = ( + BB60170B1FD9289A009BD546 /* Sources */, + BB60170C1FD9289A009BD546 /* Frameworks */, + BB60170D1FD9289A009BD546 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = spine_unit_test; + productName = spine_unit_test; + productReference = BB60170F1FD9289A009BD546 /* spine_unit_test */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + BB6017071FD9289A009BD546 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0920; + ORGANIZATIONNAME = "Noctis Games"; + TargetAttributes = { + BB60170E1FD9289A009BD546 = { + CreatedOnToolsVersion = 9.2; + ProvisioningStyle = Automatic; + }; + }; + }; + buildConfigurationList = BB60170A1FD9289A009BD546 /* Build configuration list for PBXProject "spine_unit_test" */; + compatibilityVersion = "Xcode 8.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = BB6017061FD9289A009BD546; + productRefGroup = BB6017101FD9289A009BD546 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + BB60170E1FD9289A009BD546 /* spine_unit_test */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + BB60170B1FD9289A009BD546 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + BB6017CB1FD928AC009BD546 /* PathConstraintPositionTimeline.cpp in Sources */, + BB6017CD1FD928AC009BD546 /* SkeletonClipping.cpp in Sources */, + BB6017B51FD928AC009BD546 /* MeshAttachment.cpp in Sources */, + BB6017C01FD928AC009BD546 /* ScaleTimeline.cpp in Sources */, + BB6017D01FD928AC009BD546 /* AnimationState.cpp in Sources */, + BB6017A31FD928AC009BD546 /* Skeleton.cpp in Sources */, + BB6017BA1FD928AC009BD546 /* IkConstraintData.cpp in Sources */, + BB6017EE1FD929F4009BD546 /* teamcity_cppunit.cpp in Sources */, + BB6017CA1FD928AC009BD546 /* PathConstraintSpacingTimeline.cpp in Sources */, + BB6017C91FD928AC009BD546 /* EventData.cpp in Sources */, + BB6017B41FD928AC009BD546 /* PathAttachment.cpp in Sources */, + BB6017A91FD928AC009BD546 /* EventTimeline.cpp in Sources */, + BB6017A21FD928AC009BD546 /* Attachment.cpp in Sources */, + BB6017C81FD928AC009BD546 /* AttachmentTimeline.cpp in Sources */, + BB6017E21FD928F7009BD546 /* KMemory.cpp in Sources */, + BB6017E71FD929D0009BD546 /* MiniCppUnit.cxx in Sources */, + BB6017DA1FD928AC009BD546 /* SlotData.cpp in Sources */, + BB6017BE1FD928AC009BD546 /* Timeline.cpp in Sources */, + BB6017BF1FD928AC009BD546 /* SkeletonBinary.cpp in Sources */, + BB6017131FD9289A009BD546 /* main.cpp in Sources */, + BB6017B21FD928AC009BD546 /* Constraint.cpp in Sources */, + BB6017A41FD928AC009BD546 /* TranslateTimeline.cpp in Sources */, + BB6017A71FD928AC009BD546 /* Bone.cpp in Sources */, + BB6017DC1FD928AC009BD546 /* ColorTimeline.cpp in Sources */, + BB6017AE1FD928AC009BD546 /* TransformConstraintTimeline.cpp in Sources */, + BB6017BB1FD928AC009BD546 /* Atlas.cpp in Sources */, + BB6017C21FD928AC009BD546 /* PointAttachment.cpp in Sources */, + BB6017C11FD928AC009BD546 /* LinkedMesh.cpp in Sources */, + BB6017A61FD928AC009BD546 /* Updatable.cpp in Sources */, + BB6017DB1FD928AC009BD546 /* ShearTimeline.cpp in Sources */, + BB6017C31FD928AC009BD546 /* RegionAttachment.cpp in Sources */, + BB6017D71FD928AC009BD546 /* Triangulator.cpp in Sources */, + BB6017EF1FD929F4009BD546 /* teamcity_messages.cpp in Sources */, + BB6017D61FD928AC009BD546 /* PathConstraintMixTimeline.cpp in Sources */, + BB6017CC1FD928AC009BD546 /* TransformConstraintData.cpp in Sources */, + BB6017C71FD928AC009BD546 /* DrawOrderTimeline.cpp in Sources */, + BB6017B61FD928AC009BD546 /* TransformConstraint.cpp in Sources */, + BB6017BC1FD928AC009BD546 /* ClippingAttachment.cpp in Sources */, + BB6017B81FD928AC009BD546 /* RTTI.cpp in Sources */, + BB6017A51FD928AC009BD546 /* Extension.cpp in Sources */, + BB6017C41FD928AC009BD546 /* DeformTimeline.cpp in Sources */, + BB6017A81FD928AC009BD546 /* AtlasAttachmentLoader.cpp in Sources */, + BB6017AA1FD928AC009BD546 /* PathConstraint.cpp in Sources */, + BB6017B71FD928AC009BD546 /* Skin.cpp in Sources */, + BB6017D21FD928AC009BD546 /* BoneData.cpp in Sources */, + BB6017C61FD928AC009BD546 /* AttachmentLoader.cpp in Sources */, + BB6017CF1FD928AC009BD546 /* Slot.cpp in Sources */, + BB6017B91FD928AC009BD546 /* MathUtil.cpp in Sources */, + BB6017B11FD928AC009BD546 /* AnimationStateData.cpp in Sources */, + BB6018081FD92AF4009BD546 /* SpineEventMonitor.cpp in Sources */, + BB6017E31FD928F7009BD546 /* KString.cpp in Sources */, + BB6017D41FD928AC009BD546 /* Event.cpp in Sources */, + BB6017D81FD928AC009BD546 /* Json.cpp in Sources */, + BB6017CE1FD928AC009BD546 /* TwoColorTimeline.cpp in Sources */, + BB6017AD1FD928AC009BD546 /* SkeletonData.cpp in Sources */, + BB6017D11FD928AC009BD546 /* SkeletonJson.cpp in Sources */, + BB6017D31FD928AC009BD546 /* IkConstraintTimeline.cpp in Sources */, + BB6017AF1FD928AC009BD546 /* IkConstraint.cpp in Sources */, + BB6017AC1FD928AC009BD546 /* TextureLoader.cpp in Sources */, + BB6017C51FD928AC009BD546 /* Animation.cpp in Sources */, + BB6017B01FD928AC009BD546 /* CurveTimeline.cpp in Sources */, + BB6017BD1FD928AC009BD546 /* PathConstraintData.cpp in Sources */, + BB6017D91FD928AC009BD546 /* SkeletonBounds.cpp in Sources */, + BB6017B31FD928AC009BD546 /* BoundingBoxAttachment.cpp in Sources */, + BB6017D51FD928AC009BD546 /* RotateTimeline.cpp in Sources */, + BB6017AB1FD928AC009BD546 /* VertexAttachment.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + BB6017141FD9289A009BD546 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.13; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + }; + name = Debug; + }; + BB6017151FD9289A009BD546 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.13; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + }; + name = Release; + }; + BB6017171FD9289A009BD546 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + HEADER_SEARCH_PATHS = "\"$(SRCROOT)/../../spine-cpp/include\""; + OTHER_LDFLAGS = "-DKANJI_MEMTRACE"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + BB6017181FD9289A009BD546 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + HEADER_SEARCH_PATHS = "\"$(SRCROOT)/../../spine-cpp/include\""; + OTHER_LDFLAGS = "-DKANJI_MEMTRACE"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + BB60170A1FD9289A009BD546 /* Build configuration list for PBXProject "spine_unit_test" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + BB6017141FD9289A009BD546 /* Debug */, + BB6017151FD9289A009BD546 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + BB6017161FD9289A009BD546 /* Build configuration list for PBXNativeTarget "spine_unit_test" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + BB6017171FD9289A009BD546 /* Debug */, + BB6017181FD9289A009BD546 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = BB6017071FD9289A009BD546 /* Project object */; +} diff --git a/spine-cpp/spine-cpp-unit-tests/spine_unit_test/spine_unit_test.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/spine-cpp/spine-cpp-unit-tests/spine_unit_test/spine_unit_test.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..af455f762 --- /dev/null +++ b/spine-cpp/spine-cpp-unit-tests/spine_unit_test/spine_unit_test.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/spine-cpp/spine-cpp-unit-tests/spine_unit_test/spine_unit_test/SimpleTest.h b/spine-cpp/spine-cpp-unit-tests/spine_unit_test/spine_unit_test/SimpleTest.h new file mode 100644 index 000000000..b030095f6 --- /dev/null +++ b/spine-cpp/spine-cpp-unit-tests/spine_unit_test/spine_unit_test/SimpleTest.h @@ -0,0 +1,197 @@ +// +// SimpleTest.h +// TestHarness +// +// Created by Stephen Gowen on 11/9/17. +// Copyright © 2017 Noctis Games. All rights reserved. +// + +#ifndef SimpleTest_h +#define SimpleTest_h + +#include "SpineEventMonitor.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include + +#include "KMemory.h" // last include + +#define SPINEBOY_JSON "/Users/sgowen/Dropbox/Documents/freelance/NoctisGames/github/dante/src/3rdparty/spine-runtimes/examples/spineboy/export/spineboy-ess.json" +#define SPINEBOY_ATLAS "/Users/sgowen/Dropbox/Documents/freelance/NoctisGames/github/dante/src/3rdparty/spine-runtimes/examples/spineboy/export/spineboy.atlas" + +#define RAPTOR_JSON "/Users/sgowen/Dropbox/Documents/freelance/NoctisGames/github/dante/src/3rdparty/spine-runtimes/examples/raptor/export/raptor-pro.json" +#define RAPTOR_ATLAS "/Users/sgowen/Dropbox/Documents/freelance/NoctisGames/github/dante/src/3rdparty/spine-runtimes/examples/raptor/export/raptor.atlas" + +#define GOBLINS_JSON "/Users/sgowen/Dropbox/Documents/freelance/NoctisGames/github/dante/src/3rdparty/spine-runtimes/examples/goblins/export/goblins-pro.json" +#define GOBLINS_ATLAS "/Users/sgowen/Dropbox/Documents/freelance/NoctisGames/github/dante/src/3rdparty/spine-runtimes/examples/goblins/export/goblins.atlas" + +#define MAX_RUN_TIME 6000 // equal to about 100 seconds of execution + +namespace Spine +{ + class SimpleTest + { + public: + static SkeletonData* readSkeletonJsonData(const char* filename, Atlas* atlas) + { + Vector atlasArray; + atlasArray.push_back(atlas); + + SkeletonJson* skeletonJson = NEW(SkeletonJson); + new (skeletonJson) SkeletonJson(atlasArray); + assert(skeletonJson != 0); + + SkeletonData* skeletonData = skeletonJson->readSkeletonDataFile(filename); + assert(skeletonData != 0); + + DESTROY(SkeletonJson, skeletonJson); + + return skeletonData; + } + + typedef std::vector AnimList; + + static size_t enumerateAnimations(AnimList& outList, SkeletonData* skeletonData) + { + if (skeletonData) + { + for (int n = 0; n < skeletonData->getAnimations().size(); n++) + { + outList.push_back(skeletonData->getAnimations()[n]->getName()); + } + } + + return outList.size(); + } + + class MyTextureLoader : public TextureLoader + { + virtual void load(AtlasPage& page, std::string path) + { + page.rendererObject = NULL; + page.width = 2048; + page.height = 2048; + } + + virtual void unload(void* texture) + { + // TODO + } + }; + + static void testRunner(const char* jsonName, const char* atlasName) + { + /////////////////////////////////////////////////////////////////////////// + // Global Animation Information + MyTextureLoader myTextureLoader; + Atlas* atlas = NEW(Atlas); + new (atlas) Atlas(atlasName, myTextureLoader); + assert(atlas != 0); + + SkeletonData* skeletonData = readSkeletonJsonData(jsonName, atlas); + assert(skeletonData != 0); + + AnimationStateData* stateData = NEW(AnimationStateData); + new (stateData) AnimationStateData(*skeletonData); + assert(stateData != 0); + stateData->setDefaultMix(0.2f); // force mixing + + /////////////////////////////////////////////////////////////////////////// + // Animation Instance + Skeleton* skeleton = NEW(Skeleton); + new (skeleton) Skeleton(*skeletonData); + assert(skeleton != 0); + + AnimationState* state = NEW(AnimationState); + new (state) AnimationState(*stateData); + assert(state != 0); + + /////////////////////////////////////////////////////////////////////////// + // Run animation + skeleton->setToSetupPose(); + SpineEventMonitor eventMonitor(state); + + AnimList anims; // Let's chain all the animations together as a test + size_t count = enumerateAnimations(anims, skeletonData); + if (count > 0) + { + state->setAnimation(0, anims[0].c_str(), false); + } + + for (size_t i = 1; i < count; ++i) + { + state->addAnimation(0, anims[i].c_str(), false, 0.0f); + } + + // Run Loop + for (int i = 0; i < MAX_RUN_TIME && eventMonitor.isAnimationPlaying(); ++i) + { + const float timeSlice = 1.0f / 60.0f; + skeleton->update(timeSlice); + state->update(timeSlice); + state->apply(*skeleton); + } + + /////////////////////////////////////////////////////////////////////////// + // Dispose Instance + DESTROY(Skeleton, skeleton); + DESTROY(AnimationState, state); + + /////////////////////////////////////////////////////////////////////////// + // Dispose Global + DESTROY(AnimationStateData, stateData); + DESTROY(SkeletonData, skeletonData); + DESTROY(Atlas, atlas); + } + + static void spineboyTestCase() + { + testRunner(SPINEBOY_JSON, SPINEBOY_ATLAS); + } + + static void raptorTestCase() + { + testRunner(RAPTOR_JSON, RAPTOR_ATLAS); + } + + static void goblinsTestCase() + { + testRunner(GOBLINS_JSON, GOBLINS_ATLAS); + } + + static void test() + { + spineboyTestCase(); + raptorTestCase(); + goblinsTestCase(); + } + + private: + // ctor, copy ctor, and assignment should be private in a Singleton + SimpleTest(); + SimpleTest(const SimpleTest&); + SimpleTest& operator=(const SimpleTest&); + }; +} + +#endif /* SimpleTest_h */ diff --git a/spine-cpp/spine-cpp-unit-tests/spine_unit_test/spine_unit_test/main.cpp b/spine-cpp/spine-cpp-unit-tests/spine_unit_test/spine_unit_test/main.cpp new file mode 100644 index 000000000..ea1741f2f --- /dev/null +++ b/spine-cpp/spine-cpp-unit-tests/spine_unit_test/spine_unit_test/main.cpp @@ -0,0 +1,111 @@ +// +// main.cpp +// spine_unit_test +// +// Created by Stephen Gowen on 12/7/17. +// Copyright © 2017 Noctis Games. All rights reserved. +// + +#ifdef WIN32 +#include +#else +#include +#endif // WIN32 + +#include +#include "KString.h" +#include + +#include "spine/Extension.h" + +#include "SimpleTest.h" + +#include "KMemory.h" // last include + +using namespace Spine; + +class KanjiSpineExtension : public DefaultSpineExtension +{ +public: + static KanjiSpineExtension* getInstance(); + + virtual ~KanjiSpineExtension(); + + virtual void* spineAlloc(size_t size, const char* file, int line); + + virtual void* spineCalloc(size_t num, size_t size, const char* file, int line); + + virtual void* spineRealloc(void* ptr, size_t size, const char* file, int line); + + virtual void spineFree(void* mem); + +protected: + KanjiSpineExtension(); +}; + +KanjiSpineExtension* KanjiSpineExtension::getInstance() +{ + static KanjiSpineExtension ret; + return &ret; +} + +KanjiSpineExtension::~KanjiSpineExtension() +{ + // Empty +} + +void* KanjiSpineExtension::spineAlloc(size_t size, const char* file, int line) +{ + return _kanjimalloc(size); +} + +void* KanjiSpineExtension::spineCalloc(size_t num, size_t size, const char* file, int line) +{ + void* ptr = spineAlloc(num * size, file, line); + if (ptr) + { + memset(ptr, 0, num * size); + } + + return ptr; +} + +void* KanjiSpineExtension::spineRealloc(void* ptr, size_t size, const char* file, int line) +{ + return _kanjirealloc(ptr, size); +} + +void KanjiSpineExtension::spineFree(void* mem) +{ + _kanjifree(mem); +} + +KanjiSpineExtension::KanjiSpineExtension() : DefaultSpineExtension() +{ + // Empty +} + +int main(int argc, char* argv[]) +{ + SpineExtension::setInstance(KanjiSpineExtension::getInstance()); + + // Start Timing + time_t start_time, end_time; + time(&start_time); + + /* Set working directory to current location for opening test data */ +#ifdef WIN32 + _chdir( GetFileDir(argv[0], false).c_str() ); +#else + chdir(GetFileDir(argv[0], false).c_str()); +#endif + + SimpleTest::test(); + + // End Timing + time(&end_time); + double secs = difftime(end_time,start_time); + printf("\n\n%i minutes and %i seconds of your life taken from you by these tests.\n", ((int)secs) / 60, ((int)secs) % 60); + + return 0; +} diff --git a/spine-cpp/spine-cpp-unit-tests/tests/C_InterfaceTestFixture.cpp b/spine-cpp/spine-cpp-unit-tests/tests/C_InterfaceTestFixture.cpp index 2c1cb61bc..072c8531d 100755 --- a/spine-cpp/spine-cpp-unit-tests/tests/C_InterfaceTestFixture.cpp +++ b/spine-cpp/spine-cpp-unit-tests/tests/C_InterfaceTestFixture.cpp @@ -35,9 +35,7 @@ #define GOBLINS_JSON "testdata/goblins/goblins-pro.json" #define GOBLINS_ATLAS "testdata/goblins/goblins.atlas" -#define MAX_RUN_TIME 6000 // equal to about 100 seconds of execution - -using namespace Spine; +#define MAX_RUN_TIME 6000 // equal to about 100 seconds of execution void C_InterfaceTestFixture::setUp() { @@ -47,8 +45,10 @@ void C_InterfaceTestFixture::tearDown() { } -static SkeletonData* readSkeletonJsonData(const char* filename, Atlas* atlas) +static Spine::SkeletonData* readSkeletonJsonData(const char* filename, Atlas* atlas) { + using namespace Spine; + Vector atlasArray; atlasArray.push_back(atlas); diff --git a/spine-cpp/spine-cpp-unit-tests/tests/SpineEventMonitor.cpp b/spine-cpp/spine-cpp-unit-tests/tests/SpineEventMonitor.cpp index 9ea3e4d6e..b24f39521 100755 --- a/spine-cpp/spine-cpp-unit-tests/tests/SpineEventMonitor.cpp +++ b/spine-cpp/spine-cpp-unit-tests/tests/SpineEventMonitor.cpp @@ -2,8 +2,13 @@ #include "KString.h" +#include +#include + #include "KMemory.h" // Last include +using namespace Spine; + SpineEventMonitor::SpineEventMonitor(AnimationState* _pAnimationState /*= nullptr*/) { bLogging = false; @@ -17,53 +22,53 @@ SpineEventMonitor::~SpineEventMonitor() void SpineEventMonitor::RegisterListener(AnimationState * _pAnimationState) { -// if (_pAnimationState) -// { -// _pAnimationState->rendererObject = this; -// _pAnimationState->listener = (spAnimationStateListener)&SpineEventMonitor::spineAnimStateHandler; -// } -// pAnimState = _pAnimationState; + if (_pAnimationState) + { + _pAnimationState->setRendererObject(this); + _pAnimationState->setOnAnimationEventFunc(&SpineEventMonitor::spineAnimStateHandler); + } + pAnimState = _pAnimationState; } bool SpineEventMonitor::isAnimationPlaying() { -// if (pAnimState) -// { -// return spAnimationState_getCurrent(pAnimState, 0) != 0; -// } + if (pAnimState) + { + return pAnimState->getCurrent(0) != NULL; + } return false; } -void SpineEventMonitor::spineAnimStateHandler(AnimationState * state, int type, spTrackEntry * entry, spEvent * event) +void SpineEventMonitor::spineAnimStateHandler(AnimationState* state, EventType type, TrackEntry* entry, Event* event) { -// if (state && state->rendererObject) -// { -// SpineEventMonitor* pEventMonitor = (SpineEventMonitor*)state->rendererObject; -// pEventMonitor->OnSpineAnimationStateEvent(state, type, entry, event); -// } + if (state && state->getRendererObject()) + { + SpineEventMonitor* pEventMonitor = (SpineEventMonitor*)state->getRendererObject(); + pEventMonitor->OnSpineAnimationStateEvent(state, type, entry, event); + } } -void SpineEventMonitor::OnSpineAnimationStateEvent(AnimationState * state, int type, spTrackEntry * trackEntry, spEvent * event) +void SpineEventMonitor::OnSpineAnimationStateEvent(AnimationState* state, EventType type, TrackEntry* entry, Event* event) { -// const char* eventName = 0; -// if (state == pAnimState) -// { -// // only monitor ours -// switch(type) -// { -// case SP_ANIMATION_START: eventName = "SP_ANIMATION_START"; break; -// case SP_ANIMATION_INTERRUPT: eventName = "SP_ANIMATION_INTERRUPT"; break; -// case SP_ANIMATION_END: eventName = "SP_ANIMATION_END"; break; -// case SP_ANIMATION_COMPLETE: eventName = "SP_ANIMATION_COMPLETE"; break; -// case SP_ANIMATION_DISPOSE: eventName = "SP_ANIMATION_DISPOSE"; break; -// case SP_ANIMATION_EVENT: eventName = "SP_ANIMATION_EVENT"; break; -// default: -// break; -// } -// -// if (bLogging && eventName && trackEntry && trackEntry->animation && trackEntry->animation->name) -// KOutputDebug(DEBUGLVL, "[%s : '%s']\n", eventName, trackEntry->animation->name);//*/ -// } + const char* eventName = 0; + if (state == pAnimState) + { + // only monitor ours + switch(type) + { + case EventType_Start: eventName = "EventType_Start"; break; + case EventType_Interrupt: eventName = "EventType_Interrupt"; break; + case EventType_End: eventName = "EventType_End"; break; + case EventType_Complete: eventName = "EventType_Complete"; break; + case EventType_Dispose: eventName = "EventType_Dispose"; break; + case EventType_Event: eventName = "EventType_Event"; break; + default: + break; + } + + if (bLogging && eventName && entry && entry->getAnimation()) + KOutputDebug(DEBUGLVL, "[%s : '%s']\n", eventName, entry->getAnimation()->getName().c_str());//*/ + } } InterruptMonitor::InterruptMonitor(AnimationState * _pAnimationState): @@ -98,7 +103,7 @@ InterruptMonitor& InterruptMonitor::AddInterruptEvent(int theEventType, const st } // stops the first encounter of spEventType on the specified TrackEntry -InterruptMonitor& InterruptMonitor::AddInterruptEvent(int theEventType, spTrackEntry * theTrackEntry) +InterruptMonitor& InterruptMonitor::AddInterruptEvent(int theEventType, TrackEntry * theTrackEntry) { InterruptEvent ev; ev.mEventType = theEventType; @@ -117,7 +122,7 @@ InterruptMonitor& InterruptMonitor::AddInterruptEventTrigger(const std::string & return *this; } -void InterruptMonitor::OnSpineAnimationStateEvent(AnimationState * state, int type, spTrackEntry * trackEntry, spEvent * event) +void InterruptMonitor::OnSpineAnimationStateEvent(AnimationState * state, EventType type, TrackEntry * trackEntry, Event * event) { SpineEventMonitor::OnSpineAnimationStateEvent(state, type, trackEntry, event); @@ -136,41 +141,41 @@ void InterruptMonitor::OnSpineAnimationStateEvent(AnimationState * state, int ty } } -inline bool InterruptMonitor::InterruptEvent::matches(AnimationState * state, int type, spTrackEntry * trackEntry, spEvent * event) +inline bool InterruptMonitor::InterruptEvent::matches(AnimationState * state, EventType type, TrackEntry * trackEntry, Event * event) { // Must match spEventType {SP_ANIMATION_START, SP_ANIMATION_INTERRUPT, SP_ANIMATION_END, SP_ANIMATION_COMPLETE, SP_ANIMATION_DISPOSE, SP_ANIMATION_EVENT } -// if (mEventType == type) -// { -// // Looking for specific TrackEntry by pointer -// if (mTrackEntry != 0) -// { -// return mTrackEntry == trackEntry; -// } -// -// // looking for Animation Track by name -// if (!mAnimName.empty()) -// { -// if (trackEntry && trackEntry->animation && trackEntry->animation->name) -// { -// if (CompareNoCase(trackEntry->animation->name, mAnimName) == 0) -// { -// return true; -// } -// } -// return false; -// } -// -// // looking for Event String Text -// if (!mEventName.empty()) -// { -// if (event && event->stringValue) -// { -// return (CompareNoCase(event->stringValue, mEventName) == 0); -// } -// return false; -// } -// -// return true; // waiting for ANY spEventType that matches -// } + if (mEventType == type) + { + // Looking for specific TrackEntry by pointer + if (mTrackEntry != 0) + { + return mTrackEntry == trackEntry; + } + + // looking for Animation Track by name + if (!mAnimName.empty()) + { + if (trackEntry && trackEntry->getAnimation()) + { + if (CompareNoCase(trackEntry->getAnimation()->getName(), mAnimName) == 0) + { + return true; + } + } + return false; + } + + // looking for Event String Text + if (!mEventName.empty()) + { + if (event) + { + return (CompareNoCase(event->getStringValue(), mEventName) == 0); + } + return false; + } + + return true; // waiting for ANY spEventType that matches + } return false; } diff --git a/spine-cpp/spine-cpp-unit-tests/tests/SpineEventMonitor.h b/spine-cpp/spine-cpp-unit-tests/tests/SpineEventMonitor.h index df177c03c..4590a1e6e 100755 --- a/spine-cpp/spine-cpp-unit-tests/tests/SpineEventMonitor.h +++ b/spine-cpp/spine-cpp-unit-tests/tests/SpineEventMonitor.h @@ -7,12 +7,7 @@ #pragma once #include -#include - -// forward declarations -typedef struct spAnimationState spAnimationState; -typedef struct spTrackEntry spTrackEntry; -typedef struct spEvent spEvent; +#include #include @@ -22,7 +17,7 @@ using namespace Spine; // class: SpineEventMonitor // // purpose: Monitor spAnimationState Events and report when there -// are no more spTrackEntry(s) waiting to play on track 0; +// are no more TrackEntry(s) waiting to play on track 0; // // Also allows for debug printing of Events to console. ///////////////////////////////////////////////////////////////////// @@ -40,8 +35,8 @@ public: virtual bool isAnimationPlaying(); protected: - static void spineAnimStateHandler(AnimationState* state, int type, spTrackEntry* entry, spEvent* event); - virtual void OnSpineAnimationStateEvent(AnimationState* state, int type, spTrackEntry* trackEntry, spEvent* event); + static void spineAnimStateHandler(AnimationState* state, EventType type, TrackEntry* entry, Event* event); + virtual void OnSpineAnimationStateEvent(AnimationState* state, EventType type, TrackEntry* entry, Event* event); protected: AnimationState *pAnimState; @@ -65,11 +60,11 @@ private: mTrackEntry = 0; } - bool matches(AnimationState* state, int type, spTrackEntry* trackEntry, spEvent* event); + bool matches(AnimationState* state, EventType type, TrackEntry* trackEntry, Event* event); std::string mAnimName; int mEventType; - spTrackEntry* mTrackEntry; + TrackEntry* mTrackEntry; std::string mEventName; }; typedef std::vector InterruptEventStack; @@ -84,11 +79,11 @@ public: public: InterruptMonitor& AddInterruptEvent(int theEventType); InterruptMonitor& AddInterruptEvent(int theEventType, const std::string& theAnimationName); - InterruptMonitor& AddInterruptEvent(int theEventType, spTrackEntry* theTrackEntry); + InterruptMonitor& AddInterruptEvent(int theEventType, TrackEntry* theTrackEntry); InterruptMonitor& AddInterruptEventTrigger(const std::string& theEventTriggerName); protected: - virtual void OnSpineAnimationStateEvent(AnimationState* state, int type, spTrackEntry* trackEntry, spEvent* event) override; + virtual void OnSpineAnimationStateEvent(AnimationState* state, EventType type, TrackEntry* trackEntry, Event* event) override; virtual void OnMatchingComplete() {} protected: @@ -119,7 +114,7 @@ eventMonitor.SetDebugLogging(true); // Interrupt the animation on this specific sequence of spEventType(s) eventMonitor - .AddInterruptEvent(SP_ANIMATION_INTERRUPT, "jump") // First, wait for INTERRUPT signal on the 'jump' animation spTrackEntry + .AddInterruptEvent(SP_ANIMATION_INTERRUPT, "jump") // First, wait for INTERRUPT signal on the 'jump' animation TrackEntry .AddInterruptEvent(SP_ANIMATION_START); // Then, stop on any following START signal diff --git a/spine-cpp/spine-cpp/include/spine/AnimationState.h b/spine-cpp/spine-cpp/include/spine/AnimationState.h index 2b58862bb..09821da5b 100644 --- a/spine-cpp/spine-cpp/include/spine/AnimationState.h +++ b/spine-cpp/spine-cpp/include/spine/AnimationState.h @@ -56,7 +56,7 @@ namespace Spine class Skeleton; class RotateTimeline; - typedef void (*OnAnimationEventFunc) (AnimationState& state, EventType type, TrackEntry* entry, Event* event); + typedef void (*OnAnimationEventFunc) (AnimationState* state, EventType type, TrackEntry* entry, Event* event); /// State for the playback of an animation class TrackEntry @@ -375,6 +375,8 @@ namespace Spine float getTimeScale(); void setTimeScale(float inValue); void setOnAnimationEventFunc(OnAnimationEventFunc inValue); + void setRendererObject(void* inValue); + void* getRendererObject(); private: static const int Subsequent, First, Dip, DipMix; @@ -389,6 +391,8 @@ namespace Spine Vector _propertyIDs; Vector _mixingTo; bool _animationsChanged; + + void* _rendererObject; OnAnimationEventFunc _onAnimationEventFunc; diff --git a/spine-cpp/spine-cpp/src/spine/AnimationState.cpp b/spine-cpp/spine-cpp/src/spine/AnimationState.cpp index 760e99efb..d45d3fe47 100644 --- a/spine-cpp/spine-cpp/src/spine/AnimationState.cpp +++ b/spine-cpp/spine-cpp/src/spine/AnimationState.cpp @@ -48,7 +48,7 @@ namespace Spine { - void dummyOnAnimationEventFunc(AnimationState& state, EventType type, TrackEntry* entry, Event* event = NULL) + void dummyOnAnimationEventFunc(AnimationState* state, EventType type, TrackEntry* entry, Event* event = NULL) { // Empty } @@ -320,22 +320,22 @@ namespace Spine case EventType_Start: case EventType_Interrupt: case EventType_Complete: - trackEntry->_onAnimationEventFunc(state, queueEntry->_type, trackEntry, NULL); - state._onAnimationEventFunc(state, queueEntry->_type, trackEntry, NULL); + trackEntry->_onAnimationEventFunc(&state, queueEntry->_type, trackEntry, NULL); + state._onAnimationEventFunc(&state, queueEntry->_type, trackEntry, NULL); break; case EventType_End: - trackEntry->_onAnimationEventFunc(state, queueEntry->_type, trackEntry, NULL); - state._onAnimationEventFunc(state, queueEntry->_type, trackEntry, NULL); + trackEntry->_onAnimationEventFunc(&state, queueEntry->_type, trackEntry, NULL); + state._onAnimationEventFunc(&state, queueEntry->_type, trackEntry, NULL); /* Yes, we want to fall through here */ case EventType_Dispose: - trackEntry->_onAnimationEventFunc(state, EventType_Dispose, trackEntry, NULL); - state._onAnimationEventFunc(state, EventType_Dispose, trackEntry, NULL); + trackEntry->_onAnimationEventFunc(&state, EventType_Dispose, trackEntry, NULL); + state._onAnimationEventFunc(&state, EventType_Dispose, trackEntry, NULL); trackEntry->reset(); _trackEntryPool.free(trackEntry); break; case EventType_Event: - trackEntry->_onAnimationEventFunc(state, queueEntry->_type, trackEntry, queueEntry->_event); - state._onAnimationEventFunc(state, queueEntry->_type, trackEntry, queueEntry->_event); + trackEntry->_onAnimationEventFunc(&state, queueEntry->_type, trackEntry, queueEntry->_event); + state._onAnimationEventFunc(&state, queueEntry->_type, trackEntry, queueEntry->_event); break; } } @@ -732,6 +732,16 @@ namespace Spine _onAnimationEventFunc = inValue; } + void AnimationState::setRendererObject(void* inValue) + { + _rendererObject = inValue; + } + + void* AnimationState::getRendererObject() + { + return _rendererObject; + } + Animation* AnimationState::getEmptyAnimation() { static Vector timelines; diff --git a/spine-cpp/spine-cpp/src/spine/Atlas.cpp b/spine-cpp/spine-cpp/src/spine/Atlas.cpp index 506f5042c..04fbbd39f 100644 --- a/spine-cpp/spine-cpp/src/spine/Atlas.cpp +++ b/spine-cpp/spine-cpp/src/spine/Atlas.cpp @@ -145,7 +145,8 @@ namespace Spine FREE(name); - assert(readTuple(&begin, end, tuple) == 2); + int tupleVal = readTuple(&begin, end, tuple); + assert(tupleVal == 2); /* size is only optional for an atlas packed with an old TexturePacker. */ page->width = toInt(tuple); From ec7ed94525f3bacd8b168909289e059d6808af07 Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Thu, 7 Dec 2017 13:54:41 -0500 Subject: [PATCH 72/83] Got Unit Tests working, but I don't have the fixtures quite configured correctly. --- spine-cpp/spine-cpp/include/spine/Json.h | 2 +- spine-cpp/spine-cpp/include/spine/Skeleton.h | 2 +- .../spine-cpp/include/spine/Triangulator.h | 10 +-- spine-cpp/spine-cpp/include/spine/Vector.h | 10 ++- .../spine-cpp/src/spine/AnimationState.cpp | 4 ++ spine-cpp/spine-cpp/src/spine/Atlas.cpp | 6 +- .../src/spine/AttachmentTimeline.cpp | 7 ++ spine-cpp/spine-cpp/src/spine/BoneData.cpp | 2 +- .../spine-cpp/src/spine/ColorTimeline.cpp | 1 + .../spine-cpp/src/spine/CurveTimeline.cpp | 1 + .../spine-cpp/src/spine/DeformTimeline.cpp | 10 +++ .../spine-cpp/src/spine/DrawOrderTimeline.cpp | 8 +++ .../spine-cpp/src/spine/EventTimeline.cpp | 3 + .../src/spine/IkConstraintTimeline.cpp | 1 + spine-cpp/spine-cpp/src/spine/Json.cpp | 4 +- .../spine-cpp/src/spine/MeshAttachment.cpp | 2 +- .../spine-cpp/src/spine/PathConstraint.cpp | 8 +++ .../src/spine/PathConstraintMixTimeline.cpp | 1 + .../spine/PathConstraintPositionTimeline.cpp | 1 + .../spine-cpp/src/spine/RegionAttachment.cpp | 3 + .../spine-cpp/src/spine/RotateTimeline.cpp | 1 + spine-cpp/spine-cpp/src/spine/Skeleton.cpp | 6 +- .../spine-cpp/src/spine/SkeletonBinary.cpp | 18 +++++ .../spine-cpp/src/spine/SkeletonData.cpp | 2 +- .../spine-cpp/src/spine/SkeletonJson.cpp | 68 ++++++++++++++----- .../src/spine/TransformConstraintTimeline.cpp | 1 + .../spine-cpp/src/spine/TranslateTimeline.cpp | 1 + .../spine-cpp/src/spine/Triangulator.cpp | 8 ++- .../spine-cpp/src/spine/TwoColorTimeline.cpp | 1 + 29 files changed, 156 insertions(+), 36 deletions(-) diff --git a/spine-cpp/spine-cpp/include/spine/Json.h b/spine-cpp/spine-cpp/include/spine/Json.h index 2124b970e..3cf273a1c 100644 --- a/spine-cpp/spine-cpp/include/spine/Json.h +++ b/spine-cpp/spine-cpp/include/spine/Json.h @@ -105,7 +105,7 @@ namespace Spine /* Build an object from the text. */ static const char* parseObject(Json *item, const char* value); - static int strcasecmp(const char* s1, const char* s2); + static int json_strcasecmp(const char* s1, const char* s2); }; } diff --git a/spine-cpp/spine-cpp/include/spine/Skeleton.h b/spine-cpp/spine-cpp/include/spine/Skeleton.h index 1b39bd793..72a305daa 100644 --- a/spine-cpp/spine-cpp/include/spine/Skeleton.h +++ b/spine-cpp/spine-cpp/include/spine/Skeleton.h @@ -71,7 +71,7 @@ namespace Spine friend class TwoColorTimeline; public: - Skeleton(SkeletonData& data); + Skeleton(SkeletonData& skeletonData); ~Skeleton(); diff --git a/spine-cpp/spine-cpp/include/spine/Triangulator.h b/spine-cpp/spine-cpp/include/spine/Triangulator.h index 1b41a6c3d..b8da189fc 100644 --- a/spine-cpp/spine-cpp/include/spine/Triangulator.h +++ b/spine-cpp/spine-cpp/include/spine/Triangulator.h @@ -41,18 +41,18 @@ namespace Spine public: Vector& triangulate(Vector& vertices); - Vector* > decompose(Vector& vertices, Vector& triangles); + Vector< Vector* > decompose(Vector& vertices, Vector& triangles); private: - Vector* > _convexPolygons; - Vector* > _convexPolygonsIndices; + Vector< Vector* > _convexPolygons; + Vector< Vector* > _convexPolygonsIndices; Vector _indices; Vector _isConcaveArray; Vector _triangles; - Pool > _polygonPool; - Pool > _polygonIndicesPool; + Pool< Vector > _polygonPool; + Pool< Vector > _polygonIndicesPool; static bool isConcave(int index, int vertexCount, Vector& vertices, Vector& indices); diff --git a/spine-cpp/spine-cpp/include/spine/Vector.h b/spine-cpp/spine-cpp/include/spine/Vector.h index 3690824e0..538fab273 100644 --- a/spine-cpp/spine-cpp/include/spine/Vector.h +++ b/spine-cpp/spine-cpp/include/spine/Vector.h @@ -192,6 +192,11 @@ namespace Spine } } + void setSize(size_t inValue) + { + _size = inValue; + } + T* begin() { return &_buffer[0]; @@ -243,7 +248,10 @@ namespace Spine void deallocate(T* buffer) { - FREE(buffer); + if (_buffer) + { + FREE(buffer); + } } void construct(T* buffer, const T& val) diff --git a/spine-cpp/spine-cpp/src/spine/AnimationState.cpp b/spine-cpp/spine-cpp/src/spine/AnimationState.cpp index d45d3fe47..bf9f7107f 100644 --- a/spine-cpp/spine-cpp/src/spine/AnimationState.cpp +++ b/spine-cpp/spine-cpp/src/spine/AnimationState.cpp @@ -161,8 +161,10 @@ namespace Spine Vector& timelines = _animation->_timelines; int timelinesCount = static_cast(timelines.size()); _timelineData.reserve(timelinesCount); + _timelineData.setSize(timelinesCount); _timelineDipMix.clear(); _timelineDipMix.reserve(timelinesCount); + _timelineDipMix.setSize(timelinesCount); // outer: for (int i = 0; i < timelinesCount; ++i) @@ -491,6 +493,7 @@ namespace Spine if (firstFrame) { current._timelinesRotation.reserve(timelines.size() << 1); + current._timelinesRotation.setSize(timelines.size() << 1); } Vector& timelinesRotation = current._timelinesRotation; @@ -906,6 +909,7 @@ namespace Spine { // from.timelinesRotation.setSize from->_timelinesRotation.reserve(timelines.size() << 1); + from->_timelinesRotation.setSize(timelines.size() << 1); } Vector& timelinesRotation = from->_timelinesRotation; diff --git a/spine-cpp/spine-cpp/src/spine/Atlas.cpp b/spine-cpp/spine-cpp/src/spine/Atlas.cpp index 04fbbd39f..478bb0aec 100644 --- a/spine-cpp/spine-cpp/src/spine/Atlas.cpp +++ b/spine-cpp/spine-cpp/src/spine/Atlas.cpp @@ -119,7 +119,7 @@ namespace Spine int dirLength = (int)strlen(dir); int needsSlash = dirLength > 0 && dir[dirLength - 1] != '/' && dir[dirLength - 1] != '\\'; - AtlasPage *page = 0; + AtlasPage *page = NULL; Str str; Str tuple[4]; @@ -140,7 +140,7 @@ namespace Spine } strcpy(path + dirLength + needsSlash, name); - AtlasPage* page = NEW(AtlasPage); + page = NEW(AtlasPage); new (page) AtlasPage(std::string(name)); FREE(name); @@ -228,6 +228,7 @@ namespace Spine { /* split is optional */ region->splits.reserve(4); + region->splits.setSize(4); region->splits[0] = toInt(tuple); region->splits[1] = toInt(tuple + 1); region->splits[2] = toInt(tuple + 2); @@ -240,6 +241,7 @@ namespace Spine { /* pad is optional, but only present with splits */ region->pads.reserve(4); + region->pads.setSize(4); region->pads[0] = toInt(tuple); region->pads[1] = toInt(tuple + 1); region->pads[2] = toInt(tuple + 2); diff --git a/spine-cpp/spine-cpp/src/spine/AttachmentTimeline.cpp b/spine-cpp/spine-cpp/src/spine/AttachmentTimeline.cpp index 53bcaaf72..1fb01c0dc 100644 --- a/spine-cpp/spine-cpp/src/spine/AttachmentTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/AttachmentTimeline.cpp @@ -46,6 +46,13 @@ namespace Spine { _frames.reserve(frameCount); _attachmentNames.reserve(frameCount); + + _frames.setSize(frameCount); + + for (int i = 0; i < frameCount; ++i) + { + _attachmentNames.push_back(std::string("")); + } } void AttachmentTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) diff --git a/spine-cpp/spine-cpp/src/spine/BoneData.cpp b/spine-cpp/spine-cpp/src/spine/BoneData.cpp index 47278ea6e..ce90ef754 100644 --- a/spine-cpp/spine-cpp/src/spine/BoneData.cpp +++ b/spine-cpp/spine-cpp/src/spine/BoneData.cpp @@ -48,7 +48,7 @@ namespace Spine _shearY(0), _transformMode(TransformMode_Normal) { - assert(index < 0); + assert(index >= 0); assert(_name.length() > 0); } diff --git a/spine-cpp/spine-cpp/src/spine/ColorTimeline.cpp b/spine-cpp/spine-cpp/src/spine/ColorTimeline.cpp index 4d99feb7a..80d41a1c7 100644 --- a/spine-cpp/spine-cpp/src/spine/ColorTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/ColorTimeline.cpp @@ -56,6 +56,7 @@ namespace Spine ColorTimeline::ColorTimeline(int frameCount) : CurveTimeline(frameCount), _slotIndex(0) { _frames.reserve(frameCount * ENTRIES); + _frames.setSize(frameCount * ENTRIES); } void ColorTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) diff --git a/spine-cpp/spine-cpp/src/spine/CurveTimeline.cpp b/spine-cpp/spine-cpp/src/spine/CurveTimeline.cpp index ea4047eb2..6f66e760f 100644 --- a/spine-cpp/spine-cpp/src/spine/CurveTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/CurveTimeline.cpp @@ -46,6 +46,7 @@ namespace Spine assert(frameCount > 0); _curves.reserve((frameCount - 1) * BEZIER_SIZE); + _curves.setSize((frameCount - 1) * BEZIER_SIZE); } int CurveTimeline::getFrameCount() diff --git a/spine-cpp/spine-cpp/src/spine/DeformTimeline.cpp b/spine-cpp/spine-cpp/src/spine/DeformTimeline.cpp index bfa1389aa..8f9333220 100644 --- a/spine-cpp/spine-cpp/src/spine/DeformTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/DeformTimeline.cpp @@ -48,6 +48,14 @@ namespace Spine { _frames.reserve(frameCount); _frameVertices.reserve(frameCount); + + _frames.setSize(frameCount); + + for (int i = 0; i < frameCount; ++i) + { + Vector vec; + _frameVertices.push_back(vec); + } } void DeformTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) @@ -90,6 +98,7 @@ namespace Spine // Ensure size and preemptively set count. vertices.reserve(vertexCount); + vertices.setSize(vertexCount); if (vertexAttachment->_bones.size() == 0) { @@ -117,6 +126,7 @@ namespace Spine // Ensure size and preemptively set count. vertices.reserve(vertexCount); + vertices.setSize(vertexCount); if (time >= _frames[_frames.size() - 1]) { diff --git a/spine-cpp/spine-cpp/src/spine/DrawOrderTimeline.cpp b/spine-cpp/spine-cpp/src/spine/DrawOrderTimeline.cpp index 207715f8e..2d9577cf3 100644 --- a/spine-cpp/spine-cpp/src/spine/DrawOrderTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/DrawOrderTimeline.cpp @@ -46,6 +46,14 @@ namespace Spine { _frames.reserve(frameCount); _drawOrders.reserve(frameCount); + + _frames.setSize(frameCount); + + for (int i = 0; i < frameCount; ++i) + { + Vector vec; + _drawOrders.push_back(vec); + } } void DrawOrderTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) diff --git a/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp b/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp index 5b26a44d0..56722d579 100644 --- a/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp @@ -48,6 +48,9 @@ namespace Spine { _frames.reserve(frameCount); _events.reserve(frameCount); + + _frames.setSize(frameCount); + _events.setSize(frameCount); } EventTimeline::~EventTimeline() diff --git a/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp b/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp index 483b8c619..ed747c7a4 100644 --- a/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp @@ -54,6 +54,7 @@ namespace Spine IkConstraintTimeline::IkConstraintTimeline(int frameCount) : CurveTimeline(frameCount), _ikConstraintIndex(0) { _frames.reserve(frameCount * ENTRIES); + _frames.setSize(frameCount * ENTRIES); } void IkConstraintTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) diff --git a/spine-cpp/spine-cpp/src/spine/Json.cpp b/spine-cpp/spine-cpp/src/spine/Json.cpp index 17a5d7aba..bc6dfdd97 100644 --- a/spine-cpp/spine-cpp/src/spine/Json.cpp +++ b/spine-cpp/spine-cpp/src/spine/Json.cpp @@ -67,7 +67,7 @@ namespace Spine Json* Json::getItem(Json *object, const char* string) { Json *c = object->_child; - while (c && strcasecmp(c->_name, string)) + while (c && json_strcasecmp(c->_name, string)) { c = c->_next; } @@ -616,7 +616,7 @@ namespace Spine return NULL; /* malformed. */ } - int Json::strcasecmp(const char* s1, const char* s2) + int Json::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 diff --git a/spine-cpp/spine-cpp/src/spine/MeshAttachment.cpp b/spine-cpp/spine-cpp/src/spine/MeshAttachment.cpp index 5a6de205c..7d507b8f5 100644 --- a/spine-cpp/spine-cpp/src/spine/MeshAttachment.cpp +++ b/spine-cpp/spine-cpp/src/spine/MeshAttachment.cpp @@ -67,9 +67,9 @@ namespace Spine if (_uvs.size() != _regionUVs.size()) { _uvs.reserve(_regionUVs.size()); + _uvs.setSize(_regionUVs.size()); } - if (_regionRotate) { for (size_t i = 0, n = _uvs.size(); i < n; i += 2) diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp b/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp index 6075736c3..ad06cd4fd 100644 --- a/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp @@ -69,6 +69,7 @@ namespace Spine } _segments.reserve(10); + _segments.setSize(10); } void PathConstraint::apply() @@ -103,12 +104,14 @@ namespace Spine size_t boneCount = _bones.size(); int spacesCount = static_cast(tangents ? boneCount : boneCount + 1); _spaces.reserve(spacesCount); + _spaces.setSize(spacesCount); float spacing = _spacing; if (scale || lengthSpacing) { if (scale) { _lengths.reserve(boneCount); + _lengths.setSize(boneCount); } for (int i = 0, n = spacesCount - 1; i < n;) @@ -309,6 +312,7 @@ namespace Spine Slot& target = *_target; float position = _position; _positions.reserve(spacesCount * 3 + 2); + _positions.setSize(spacesCount * 3 + 2); bool closed = path.isClosed(); int verticesLength = path.getWorldVerticesLength(); int curveCount = verticesLength / 6; @@ -334,6 +338,7 @@ namespace Spine } _world.reserve(8); + _world.setSize(8); for (int i = 0, o = 0, curve = 0; i < spacesCount; i++, o += 3) { float space = _spaces[i]; @@ -420,6 +425,7 @@ namespace Spine { verticesLength += 2; _world.reserve(verticesLength); + _world.setSize(verticesLength); path.computeWorldVertices(target, 2, verticesLength - 4, _world, 0); path.computeWorldVertices(target, 0, 2, _world, verticesLength - 4); _world[verticesLength - 2] = _world[0]; @@ -430,11 +436,13 @@ namespace Spine curveCount--; verticesLength -= 4; _world.reserve(verticesLength); + _world.setSize(verticesLength); path.computeWorldVertices(target, 2, verticesLength, _world, 0); } // Curve lengths. _curves.reserve(curveCount); + _curves.setSize(curveCount); pathLength = 0; float x1 = _world[0], y1 = _world[1], cx1 = 0, cy1 = 0, cx2 = 0, cy2 = 0, x2 = 0, y2 = 0; float tmpx, tmpy, dddfx, dddfy, ddfx, ddfy, dfx, dfy; diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp b/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp index 18c84ece7..e3ad99d41 100644 --- a/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp @@ -54,6 +54,7 @@ namespace Spine PathConstraintMixTimeline::PathConstraintMixTimeline(int frameCount) : CurveTimeline(frameCount), _pathConstraintIndex(0) { _frames.reserve(frameCount * ENTRIES); + _frames.setSize(frameCount * ENTRIES); } void PathConstraintMixTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp b/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp index 13363ad45..c60c2941f 100644 --- a/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp @@ -52,6 +52,7 @@ namespace Spine PathConstraintPositionTimeline::PathConstraintPositionTimeline(int frameCount) : CurveTimeline(frameCount), _pathConstraintIndex(0) { _frames.reserve(frameCount * ENTRIES); + _frames.setSize(frameCount * ENTRIES); } void PathConstraintPositionTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) diff --git a/spine-cpp/spine-cpp/src/spine/RegionAttachment.cpp b/spine-cpp/spine-cpp/src/spine/RegionAttachment.cpp index de50ce6c4..98d9a9f7d 100644 --- a/spine-cpp/spine-cpp/src/spine/RegionAttachment.cpp +++ b/spine-cpp/spine-cpp/src/spine/RegionAttachment.cpp @@ -76,6 +76,9 @@ namespace Spine { _offset.reserve(NUM_UVS); _uvs.reserve(NUM_UVS); + + _offset.setSize(NUM_UVS); + _uvs.setSize(NUM_UVS); } void RegionAttachment::updateOffset() diff --git a/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp b/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp index c57a37b37..16ceee334 100644 --- a/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp @@ -45,6 +45,7 @@ namespace Spine RotateTimeline::RotateTimeline(int frameCount) : CurveTimeline(frameCount), _boneIndex(0) { _frames.reserve(frameCount << 1); + _frames.setSize(frameCount << 1); } void RotateTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) diff --git a/spine-cpp/spine-cpp/src/spine/Skeleton.cpp b/spine-cpp/spine-cpp/src/spine/Skeleton.cpp index 955d8242c..c7a3e63d9 100644 --- a/spine-cpp/spine-cpp/src/spine/Skeleton.cpp +++ b/spine-cpp/spine-cpp/src/spine/Skeleton.cpp @@ -54,8 +54,8 @@ namespace Spine { - Skeleton::Skeleton(SkeletonData& data) : - _data(data), + Skeleton::Skeleton(SkeletonData& skeletonData) : + _data(skeletonData), _skin(NULL), _r(1), _g(1), @@ -492,6 +492,7 @@ namespace Spine if (outVertexBuffer.size() < 8) { outVertexBuffer.reserve(8); + outVertexBuffer.setSize(8); } regionAttachment->computeWorldVertices(slot->getBone(), outVertexBuffer, 0); } @@ -503,6 +504,7 @@ namespace Spine if (outVertexBuffer.size() < verticesLength) { outVertexBuffer.reserve(verticesLength); + outVertexBuffer.setSize(verticesLength); } mesh->computeWorldVertices(*slot, 0, verticesLength, outVertexBuffer, 0); diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp b/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp index ef3b24c59..5cbd1b5ef 100644 --- a/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp +++ b/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp @@ -162,6 +162,7 @@ namespace Spine /* Bones. */ int bonesCount = readVarint(input, 1); skeletonData->_bones.reserve(bonesCount); + skeletonData->_bones.setSize(bonesCount); for (i = 0; i < bonesCount; ++i) { BoneData* data; @@ -215,6 +216,7 @@ namespace Spine /* Slots. */ int slotsCount = readVarint(input, 1); skeletonData->_slots.reserve(slotsCount); + skeletonData->_slots.setSize(slotsCount); for (i = 0; i < slotsCount; ++i) { int r, g, b, a; @@ -247,6 +249,7 @@ namespace Spine /* IK constraints. */ int ikConstraintsCount = readVarint(input, 1); skeletonData->_ikConstraints.reserve(ikConstraintsCount); + skeletonData->_ikConstraints.setSize(ikConstraintsCount); for (i = 0; i < ikConstraintsCount; ++i) { const char* name = readString(input); @@ -259,6 +262,7 @@ namespace Spine FREE(name); int bonesCount = readVarint(input, 1); data->_bones.reserve(bonesCount); + data->_bones.setSize(bonesCount); for (ii = 0; ii < bonesCount; ++ii) { data->_bones[ii] = skeletonData->_bones[readVarint(input, 1)]; @@ -273,6 +277,7 @@ namespace Spine /* Transform constraints. */ int transformConstraintsCount = readVarint(input, 1); skeletonData->_transformConstraints.reserve(transformConstraintsCount); + skeletonData->_transformConstraints.setSize(transformConstraintsCount); for (i = 0; i < transformConstraintsCount; ++i) { const char* name = readString(input); @@ -284,6 +289,7 @@ namespace Spine FREE(name); int bonesCount = readVarint(input, 1); data->_bones.reserve(bonesCount); + data->_bones.setSize(bonesCount); for (ii = 0; ii < bonesCount; ++ii) { data->_bones[ii] = skeletonData->_bones[readVarint(input, 1)]; @@ -308,6 +314,7 @@ namespace Spine /* Path constraints */ int pathConstraintsCount = readVarint(input, 1); skeletonData->_pathConstraints.reserve(pathConstraintsCount); + skeletonData->_pathConstraints.setSize(pathConstraintsCount); for (i = 0; i < pathConstraintsCount; ++i) { const char* name = readString(input); @@ -320,6 +327,7 @@ namespace Spine int bonesCount = readVarint(input, 1); data->_bones.reserve(bonesCount); + data->_bones.setSize(bonesCount); for (ii = 0; ii < bonesCount; ++ii) { data->_bones[ii] = skeletonData->_bones[readVarint(input, 1)]; @@ -356,6 +364,7 @@ namespace Spine } skeletonData->_skins.reserve(skinsCount); + skeletonData->_skins.setSize(skinsCount); if (skeletonData->_defaultSkin) { @@ -398,6 +407,7 @@ namespace Spine /* Events. */ int eventsCount = readVarint(input, 1); skeletonData->_events.reserve(eventsCount); + skeletonData->_events.setSize(eventsCount); for (i = 0; i < eventsCount; ++i) { const char* name = readString(input); @@ -415,6 +425,7 @@ namespace Spine /* Animations. */ int animationsCount = readVarint(input, 1); skeletonData->_animations.reserve(animationsCount); + skeletonData->_animations.setSize(animationsCount); for (i = 0; i < animationsCount; ++i) { const char* name = readString(input); @@ -732,6 +743,7 @@ namespace Spine readVertices(input, static_cast(path), vertexCount); int lengthsLength = vertexCount / 3; path->_lengths.reserve(lengthsLength); + path->_lengths.setSize(lengthsLength); for (i = 0; i < lengthsLength; ++i) { path->_lengths[i] = readFloat(input) * _scale; @@ -833,6 +845,7 @@ namespace Spine { Vector array; array.reserve(n); + array.setSize(n); int i; if (scale == 1) @@ -859,6 +872,7 @@ namespace Spine Vector array; array.reserve(n); + array.setSize(n); int i; for (i = 0; i < n; ++i) @@ -1191,6 +1205,10 @@ namespace Spine if (weighted) { deform.reserve(deformLength); + for (int i = 0; i < deformLength; ++i) + { + deform.push_back(0); + } } else { diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonData.cpp b/spine-cpp/spine-cpp/src/spine/SkeletonData.cpp index 4678f658b..8f5a337cc 100644 --- a/spine-cpp/spine-cpp/src/spine/SkeletonData.cpp +++ b/spine-cpp/spine-cpp/src/spine/SkeletonData.cpp @@ -64,7 +64,7 @@ namespace Spine ContainerUtil::cleanUpVectorOfPointers(_slots); ContainerUtil::cleanUpVectorOfPointers(_skins); - delete _defaultSkin; + _defaultSkin = NULL; ContainerUtil::cleanUpVectorOfPointers(_events); ContainerUtil::cleanUpVectorOfPointers(_animations); diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp b/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp index 3be349b61..b24d48513 100644 --- a/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp +++ b/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp @@ -156,6 +156,8 @@ namespace Spine /* Bones. */ bones = Json::getItem(root, "bones"); skeletonData->_bones.reserve(bones->_size); + skeletonData->_bones.setSize(bones->_size); + int bonesCount = 0; for (boneMap = bones->_child, i = 0; boneMap; boneMap = boneMap->_next, ++i) { BoneData* data; @@ -175,7 +177,7 @@ namespace Spine } data = NEW(BoneData); - new (data) BoneData(static_cast(skeletonData->_bones.size()), Json::getString(boneMap, "name", 0), parent); + new (data) BoneData(bonesCount, Json::getString(boneMap, "name", 0), parent); data->_length = Json::getFloat(boneMap, "length", 0) * _scale; data->_x = Json::getFloat(boneMap, "x", 0) * _scale; @@ -209,6 +211,7 @@ namespace Spine } skeletonData->_bones[i] = data; + bonesCount++; } /* Slots. */ @@ -217,6 +220,7 @@ namespace Spine { Json *slotMap; skeletonData->_slots.reserve(slots->_size); + skeletonData->_slots.setSize(slots->_size); for (slotMap = slots->_child, i = 0; slotMap; slotMap = slotMap->_next, ++i) { SlotData* data; @@ -288,6 +292,7 @@ namespace Spine { Json *constraintMap; skeletonData->_ikConstraints.reserve(ik->_size); + skeletonData->_ikConstraints.setSize(ik->_size); for (constraintMap = ik->_child, i = 0; constraintMap; constraintMap = constraintMap->_next, ++i) { const char* targetName; @@ -299,6 +304,7 @@ namespace Spine boneMap = Json::getItem(constraintMap, "bones"); data->_bones.reserve(boneMap->_size); + data->_bones.setSize(boneMap->_size); for (boneMap = boneMap->_child, ii = 0; boneMap; boneMap = boneMap->_next, ++ii) { data->_bones[ii] = skeletonData->findBone(boneMap->_valueString); @@ -332,6 +338,7 @@ namespace Spine { Json *constraintMap; skeletonData->_transformConstraints.reserve(transform->_size); + skeletonData->_transformConstraints.setSize(transform->_size); for (constraintMap = transform->_child, i = 0; constraintMap; constraintMap = constraintMap->_next, ++i) { const char* name; @@ -343,6 +350,7 @@ namespace Spine boneMap = Json::getItem(constraintMap, "bones"); data->_bones.reserve(boneMap->_size); + data->_bones.setSize(boneMap->_size); for (boneMap = boneMap->_child, ii = 0; boneMap; boneMap = boneMap->_next, ++ii) { data->_bones[ii] = skeletonData->findBone(boneMap->_valueString); @@ -387,6 +395,7 @@ namespace Spine { Json *constraintMap; skeletonData->_pathConstraints.reserve(path->_size); + skeletonData->_pathConstraints.setSize(path->_size); for (constraintMap = path->_child, i = 0; constraintMap; constraintMap = constraintMap->_next, ++i) { const char* name; @@ -399,6 +408,7 @@ namespace Spine boneMap = Json::getItem(constraintMap, "bones"); data->_bones.reserve(boneMap->_size); + data->_bones.setSize(boneMap->_size); for (boneMap = boneMap->_child, ii = 0; boneMap; boneMap = boneMap->_next, ++ii) { data->_bones[ii] = skeletonData->findBone(boneMap->_valueString); @@ -481,6 +491,7 @@ namespace Spine { Json *skinMap; skeletonData->_skins.reserve(skins->_size); + skeletonData->_skins.setSize(skins->_size); int skinsIndex = 0; for (skinMap = skins->_child, i = 0; skinMap; skinMap = skinMap->_next, ++i) { @@ -605,6 +616,7 @@ namespace Spine int verticesLength; entry = Json::getItem(attachmentMap, "triangles"); mesh->_triangles.reserve(entry->_size); + mesh->_triangles.setSize(entry->_size); for (entry = entry->_child, ii = 0; entry; entry = entry->_next, ++ii) { mesh->_triangles[ii] = (unsigned short)entry->_valueInt; @@ -613,6 +625,7 @@ namespace Spine entry = Json::getItem(attachmentMap, "uvs"); verticesLength = entry->_size; mesh->_regionUVs.reserve(verticesLength); + mesh->_regionUVs.setSize(verticesLength); for (entry = entry->_child, ii = 0; entry; entry = entry->_next, ++ii) { mesh->_regionUVs[ii] = entry->_valueFloat; @@ -628,6 +641,7 @@ namespace Spine if (entry) { mesh->_edges.reserve(entry->_size); + mesh->_edges.setSize(entry->_size); for (entry = entry->_child, ii = 0; entry; entry = entry->_next, ++ii) { mesh->_edges[ii] = entry->_valueInt; @@ -666,6 +680,7 @@ namespace Spine readVertices(attachmentMap, pathAttatchment, vertexCount << 1); pathAttatchment->_lengths.reserve(vertexCount / 3); + pathAttatchment->_lengths.setSize(vertexCount / 3); curves = Json::getItem(attachmentMap, "lengths"); for (curves = curves->_child, ii = 0; curves; curves = curves->_next, ++ii) @@ -739,6 +754,7 @@ namespace Spine { Json *eventMap; skeletonData->_events.reserve(events->_size); + skeletonData->_events.setSize(events->_size); for (eventMap = events->_child, i = 0; eventMap; eventMap = eventMap->_next, ++i) { EventData* eventData = NEW(EventData); @@ -746,7 +762,8 @@ namespace Spine eventData->_intValue = Json::getInt(eventMap, "int", 0); eventData->_floatValue = Json::getFloat(eventMap, "float", 0); - eventData->_stringValue = Json::getString(eventMap, "string", 0); + const char* stringValue = Json::getString(eventMap, "string", 0); + eventData->_stringValue = std::string(stringValue ? stringValue : ""); skeletonData->_events[i] = eventData; } } @@ -757,6 +774,7 @@ namespace Spine { Json *animationMap; skeletonData->_animations.reserve(animations->_size); + skeletonData->_animations.setSize(animations->_size); int animationsIndex = 0; for (animationMap = animations->_child; animationMap; animationMap = animationMap->_next) { @@ -906,11 +924,11 @@ namespace Spine for (valueMap = timelineMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) { Json* name = Json::getItem(valueMap, "name"); - std::string attachmentName; - attachmentName = name->_type == Json::JSON_NULL ? "" : std::string(name->_valueString); + std::string attachmentName = name->_type == Json::JSON_NULL ? std::string("") : std::string(name->_valueString); timeline->setFrame(frameIndex, Json::getFloat(valueMap, "time", 0), attachmentName); } - timelines[timelinesCount++] = timeline; + timelines.push_back(timeline); + timelinesCount++; duration = MAX(duration, timeline->_frames[timelineMap->_size - 1]); } @@ -927,7 +945,8 @@ namespace Spine timeline->setFrame(frameIndex, Json::getFloat(valueMap, "time", 0), toColor(s, 0), toColor(s, 1), toColor(s, 2), toColor(s, 3)); readCurve(valueMap, timeline, frameIndex); } - timelines[timelinesCount++] = timeline; + timelines.push_back(timeline); + timelinesCount++; duration = MAX(duration, timeline->_frames[(timelineMap->_size - 1) * ColorTimeline::ENTRIES]); } @@ -946,7 +965,8 @@ namespace Spine toColor(s, 3), toColor(ds, 0), toColor(ds, 1), toColor(ds, 2)); readCurve(valueMap, timeline, frameIndex); } - timelines[timelinesCount++] = timeline; + timelines.push_back(timeline); + timelinesCount++; duration = MAX(duration, timeline->_frames[(timelineMap->_size - 1) * TwoColorTimeline::ENTRIES]); } else @@ -985,7 +1005,8 @@ namespace Spine timeline->setFrame(frameIndex, Json::getFloat(valueMap, "time", 0), Json::getFloat(valueMap, "angle", 0)); readCurve(valueMap, timeline, frameIndex); } - timelines[timelinesCount++] = timeline; + timelines.push_back(timeline); + timelinesCount++; duration = MAX(duration, timeline->_frames[(timelineMap->_size - 1) * RotateTimeline::ENTRIES]); } else @@ -1020,7 +1041,8 @@ namespace Spine readCurve(valueMap, timeline, frameIndex); } - timelines[timelinesCount++] = timeline; + timelines.push_back(timeline); + timelinesCount++; duration = MAX(duration, timeline->_frames[(timelineMap->_size - 1) * TranslateTimeline::ENTRIES]); } else @@ -1053,7 +1075,8 @@ namespace Spine timeline->setFrame(frameIndex, Json::getFloat(valueMap, "time", 0), Json::getFloat(valueMap, "mix", 1), Json::getInt(valueMap, "bendPositive", 1) ? 1 : -1); readCurve(valueMap, timeline, frameIndex); } - timelines[timelinesCount++] = timeline; + timelines.push_back(timeline); + timelinesCount++; duration = MAX(duration, timeline->_frames[(constraintMap->_size - 1) * IkConstraintTimeline::ENTRIES]); } @@ -1077,7 +1100,8 @@ namespace Spine timeline->setFrame(frameIndex, Json::getFloat(valueMap, "time", 0), Json::getFloat(valueMap, "rotateMix", 1), Json::getFloat(valueMap, "translateMix", 1), Json::getFloat(valueMap, "scaleMix", 1), Json::getFloat(valueMap, "shearMix", 1)); readCurve(valueMap, timeline, frameIndex); } - timelines[timelinesCount++] = timeline; + timelines.push_back(timeline); + timelinesCount++; duration = MAX(duration, timeline->_frames[(constraintMap->_size - 1) * TransformConstraintTimeline::ENTRIES]); } @@ -1138,7 +1162,8 @@ namespace Spine timeline->setFrame(frameIndex, Json::getFloat(valueMap, "time", 0), Json::getFloat(valueMap, timelineName, 0) * timelineScale); readCurve(valueMap, timeline, frameIndex); } - timelines[timelinesCount++] = timeline; + timelines.push_back(timeline); + timelinesCount++; duration = MAX(duration, timeline->_frames[(timelineMap->_size - 1) * PathConstraintPositionTimeline::ENTRIES]); } else if (strcmp(timelineName, "mix") == 0) @@ -1151,7 +1176,8 @@ namespace Spine timeline->setFrame(frameIndex, Json::getFloat(valueMap, "time", 0), Json::getFloat(valueMap, "rotateMix", 1), Json::getFloat(valueMap, "translateMix", 1)); readCurve(valueMap, timeline, frameIndex); } - timelines[timelinesCount++] = timeline; + timelines.push_back(timeline); + timelinesCount++; duration = MAX(duration, timeline->_frames[(timelineMap->_size - 1) * PathConstraintMixTimeline::ENTRIES]); } } @@ -1186,6 +1212,10 @@ namespace Spine deformLength = weighted ? static_cast(vertices.size()) / 3 * 2 : static_cast(vertices.size()); Vector tempDeform; tempDeform.reserve(deformLength); + for (int i = 0; i < deformLength; ++i) + { + tempDeform.push_back(0); + } timeline = NEW(DeformTimeline); new (timeline) DeformTimeline(timelineMap->_size); @@ -1240,7 +1270,8 @@ namespace Spine readCurve(valueMap, timeline, frameIndex); } - timelines[timelinesCount++] = timeline; + timelines.push_back(timeline); + timelinesCount++; duration = MAX(duration, timeline->_frames[timelineMap->_size - 1]); } } @@ -1262,9 +1293,11 @@ namespace Spine Json* offsetMap; Vector unchanged; unchanged.reserve(skeletonData->_slots.size() - offsets->_size); + unchanged.setSize(skeletonData->_slots.size() - offsets->_size); int originalIndex = 0, unchangedIndex = 0; drawOrder2.reserve(skeletonData->_slots.size()); + drawOrder2.setSize(skeletonData->_slots.size()); for (ii = static_cast(skeletonData->_slots.size()) - 1; ii >= 0; --ii) { drawOrder2[ii] = -1; @@ -1304,7 +1337,8 @@ namespace Spine } timeline->setFrame(frameIndex, Json::getFloat(valueMap, "time", 0), drawOrder2); } - timelines[timelinesCount++] = timeline; + timelines.push_back(timeline); + timelinesCount++; duration = MAX(duration, timeline->_frames[drawOrder->_size - 1]); } @@ -1332,7 +1366,8 @@ namespace Spine event->_stringValue = Json::getString(valueMap, "string", eventData->_stringValue.c_str()); timeline->setFrame(frameIndex, event); } - timelines[timelinesCount++] = timeline; + timelines.push_back(timeline); + timelinesCount++; duration = MAX(duration, timeline->_frames[events->_size - 1]); } @@ -1353,6 +1388,7 @@ namespace Spine entry = Json::getItem(attachmentMap, "vertices"); entrySize = entry->_size; vertices.reserve(entrySize); + vertices.setSize(entrySize); for (entry = entry->_child, i = 0; entry; entry = entry->_next, ++i) { vertices[i] = entry->_valueFloat; diff --git a/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp b/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp index 3d7cf2dfd..534be4439 100644 --- a/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp @@ -58,6 +58,7 @@ namespace Spine TransformConstraintTimeline::TransformConstraintTimeline(int frameCount) : CurveTimeline(frameCount), _transformConstraintIndex(0) { _frames.reserve(frameCount * ENTRIES); + _frames.setSize(frameCount * ENTRIES); } void TransformConstraintTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) diff --git a/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp b/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp index f241f31a8..8c23b0e58 100644 --- a/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp @@ -54,6 +54,7 @@ namespace Spine TranslateTimeline::TranslateTimeline(int frameCount) : CurveTimeline(frameCount), _boneIndex(0) { _frames.reserve(frameCount * ENTRIES); + _frames.setSize(frameCount * ENTRIES); } void TranslateTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) diff --git a/spine-cpp/spine-cpp/src/spine/Triangulator.cpp b/spine-cpp/spine-cpp/src/spine/Triangulator.cpp index 4b5983dc9..edf536367 100644 --- a/spine-cpp/spine-cpp/src/spine/Triangulator.cpp +++ b/spine-cpp/spine-cpp/src/spine/Triangulator.cpp @@ -41,6 +41,7 @@ namespace Spine Vector& indices = _indices; indices.clear(); indices.reserve(vertexCount); + indices.setSize(vertexCount); for (int i = 0; i < vertexCount; ++i) { indices[i] = i; @@ -48,6 +49,7 @@ namespace Spine Vector& isConcaveArray = _isConcaveArray; isConcaveArray.reserve(vertexCount); + isConcaveArray.setSize(vertexCount); for (int i = 0, n = vertexCount; i < n; ++i) { isConcaveArray[i] = isConcave(i, vertexCount, vertices, indices); @@ -137,16 +139,16 @@ namespace Spine return triangles; } - Vector* > Triangulator::decompose(Vector& vertices, Vector& triangles) + Vector< Vector* > Triangulator::decompose(Vector& vertices, Vector& triangles) { - Vector* >&convexPolygons = _convexPolygons; + Vector< Vector* >&convexPolygons = _convexPolygons; for (size_t i = 0, n = convexPolygons.size(); i < n; ++i) { _polygonPool.free(convexPolygons[i]); } convexPolygons.clear(); - Vector* > convexPolygonsIndices = _convexPolygonsIndices; + Vector< Vector* > convexPolygonsIndices = _convexPolygonsIndices; for (size_t i = 0, n = convexPolygonsIndices.size(); i < n; ++i) { _polygonIndicesPool.free(convexPolygonsIndices[i]); diff --git a/spine-cpp/spine-cpp/src/spine/TwoColorTimeline.cpp b/spine-cpp/spine-cpp/src/spine/TwoColorTimeline.cpp index bce0d0bf7..16c28b180 100644 --- a/spine-cpp/spine-cpp/src/spine/TwoColorTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/TwoColorTimeline.cpp @@ -62,6 +62,7 @@ namespace Spine TwoColorTimeline::TwoColorTimeline(int frameCount) : CurveTimeline(frameCount), _slotIndex(0) { _frames.reserve(frameCount * ENTRIES); + _frames.setSize(frameCount * ENTRIES); } void TwoColorTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) From a0ad9d8c577e5b145b660acff7c2f4d136e51dae Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Thu, 7 Dec 2017 14:06:13 -0500 Subject: [PATCH 73/83] Okay, got copying and relative paths set up --- .../spine_unit_test.xcodeproj/project.pbxproj | 54 +++++++++++++++++++ .../spine_unit_test/SimpleTest.h | 12 ++--- 2 files changed, 60 insertions(+), 6 deletions(-) diff --git a/spine-cpp/spine-cpp-unit-tests/spine_unit_test/spine_unit_test.xcodeproj/project.pbxproj b/spine-cpp/spine-cpp-unit-tests/spine_unit_test/spine_unit_test.xcodeproj/project.pbxproj index 4d3027361..7c82f0d7e 100644 --- a/spine-cpp/spine-cpp-unit-tests/spine_unit_test/spine_unit_test.xcodeproj/project.pbxproj +++ b/spine-cpp/spine-cpp-unit-tests/spine_unit_test/spine_unit_test.xcodeproj/project.pbxproj @@ -7,6 +7,12 @@ objects = { /* Begin PBXBuildFile section */ + BB4E38561FD9C85600709FF2 /* spineboy-ess.json in CopyFiles */ = {isa = PBXBuildFile; fileRef = BB4E38541FD9C85600709FF2 /* spineboy-ess.json */; }; + BB4E38571FD9C85600709FF2 /* spineboy.atlas in CopyFiles */ = {isa = PBXBuildFile; fileRef = BB4E38551FD9C85600709FF2 /* spineboy.atlas */; }; + BB4E385A1FD9C86400709FF2 /* raptor.atlas in CopyFiles */ = {isa = PBXBuildFile; fileRef = BB4E38581FD9C86400709FF2 /* raptor.atlas */; }; + BB4E385B1FD9C86400709FF2 /* raptor-pro.json in CopyFiles */ = {isa = PBXBuildFile; fileRef = BB4E38591FD9C86400709FF2 /* raptor-pro.json */; }; + BB4E385E1FD9C87700709FF2 /* goblins-pro.json in CopyFiles */ = {isa = PBXBuildFile; fileRef = BB4E385C1FD9C87600709FF2 /* goblins-pro.json */; }; + BB4E385F1FD9C87700709FF2 /* goblins.atlas in CopyFiles */ = {isa = PBXBuildFile; fileRef = BB4E385D1FD9C87700709FF2 /* goblins.atlas */; }; BB6017131FD9289A009BD546 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB6017121FD9289A009BD546 /* main.cpp */; }; BB6017A21FD928AC009BD546 /* Attachment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB6017671FD928AC009BD546 /* Attachment.cpp */; }; BB6017A31FD928AC009BD546 /* Skeleton.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB6017681FD928AC009BD546 /* Skeleton.cpp */; }; @@ -76,6 +82,39 @@ /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ + BB4E38471FD9C72600709FF2 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = testdata/spineboy; + dstSubfolderSpec = 16; + files = ( + BB4E38561FD9C85600709FF2 /* spineboy-ess.json in CopyFiles */, + BB4E38571FD9C85600709FF2 /* spineboy.atlas in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + BB4E384A1FD9C79D00709FF2 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = testdata/raptor; + dstSubfolderSpec = 16; + files = ( + BB4E385A1FD9C86400709FF2 /* raptor.atlas in CopyFiles */, + BB4E385B1FD9C86400709FF2 /* raptor-pro.json in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + BB4E384B1FD9C79E00709FF2 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = testdata/goblins; + dstSubfolderSpec = 16; + files = ( + BB4E385E1FD9C87700709FF2 /* goblins-pro.json in CopyFiles */, + BB4E385F1FD9C87700709FF2 /* goblins.atlas in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; BB60170D1FD9289A009BD546 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; @@ -88,6 +127,12 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + BB4E38541FD9C85600709FF2 /* spineboy-ess.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; name = "spineboy-ess.json"; path = "../../../examples/spineboy/export/spineboy-ess.json"; sourceTree = ""; }; + BB4E38551FD9C85600709FF2 /* spineboy.atlas */ = {isa = PBXFileReference; lastKnownFileType = text; name = spineboy.atlas; path = ../../../examples/spineboy/export/spineboy.atlas; sourceTree = ""; }; + BB4E38581FD9C86400709FF2 /* raptor.atlas */ = {isa = PBXFileReference; lastKnownFileType = text; name = raptor.atlas; path = ../../../examples/raptor/export/raptor.atlas; sourceTree = ""; }; + BB4E38591FD9C86400709FF2 /* raptor-pro.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; name = "raptor-pro.json"; path = "../../../examples/raptor/export/raptor-pro.json"; sourceTree = ""; }; + BB4E385C1FD9C87600709FF2 /* goblins-pro.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; name = "goblins-pro.json"; path = "../../../examples/goblins/export/goblins-pro.json"; sourceTree = ""; }; + BB4E385D1FD9C87700709FF2 /* goblins.atlas */ = {isa = PBXFileReference; lastKnownFileType = text; name = goblins.atlas; path = ../../../examples/goblins/export/goblins.atlas; sourceTree = ""; }; BB60170F1FD9289A009BD546 /* spine_unit_test */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = spine_unit_test; sourceTree = BUILT_PRODUCTS_DIR; }; BB6017121FD9289A009BD546 /* main.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; BB60171C1FD928AC009BD546 /* DeformTimeline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DeformTimeline.h; sourceTree = ""; }; @@ -252,6 +297,12 @@ BB6017061FD9289A009BD546 = { isa = PBXGroup; children = ( + BB4E385C1FD9C87600709FF2 /* goblins-pro.json */, + BB4E385D1FD9C87700709FF2 /* goblins.atlas */, + BB4E38591FD9C86400709FF2 /* raptor-pro.json */, + BB4E38581FD9C86400709FF2 /* raptor.atlas */, + BB4E38541FD9C85600709FF2 /* spineboy-ess.json */, + BB4E38551FD9C85600709FF2 /* spineboy.atlas */, BB6017F11FD92AF3009BD546 /* tests */, BB6017E81FD929F4009BD546 /* teamcity */, BB6017E41FD929D0009BD546 /* minicppunit */, @@ -506,6 +557,9 @@ BB60170B1FD9289A009BD546 /* Sources */, BB60170C1FD9289A009BD546 /* Frameworks */, BB60170D1FD9289A009BD546 /* CopyFiles */, + BB4E38471FD9C72600709FF2 /* CopyFiles */, + BB4E384A1FD9C79D00709FF2 /* CopyFiles */, + BB4E384B1FD9C79E00709FF2 /* CopyFiles */, ); buildRules = ( ); diff --git a/spine-cpp/spine-cpp-unit-tests/spine_unit_test/spine_unit_test/SimpleTest.h b/spine-cpp/spine-cpp-unit-tests/spine_unit_test/spine_unit_test/SimpleTest.h index b030095f6..5cdf2e3d6 100644 --- a/spine-cpp/spine-cpp-unit-tests/spine_unit_test/spine_unit_test/SimpleTest.h +++ b/spine-cpp/spine-cpp-unit-tests/spine_unit_test/spine_unit_test/SimpleTest.h @@ -36,14 +36,14 @@ #include "KMemory.h" // last include -#define SPINEBOY_JSON "/Users/sgowen/Dropbox/Documents/freelance/NoctisGames/github/dante/src/3rdparty/spine-runtimes/examples/spineboy/export/spineboy-ess.json" -#define SPINEBOY_ATLAS "/Users/sgowen/Dropbox/Documents/freelance/NoctisGames/github/dante/src/3rdparty/spine-runtimes/examples/spineboy/export/spineboy.atlas" +#define SPINEBOY_JSON "testdata/spineboy/spineboy-ess.json" +#define SPINEBOY_ATLAS "testdata/spineboy/spineboy.atlas" -#define RAPTOR_JSON "/Users/sgowen/Dropbox/Documents/freelance/NoctisGames/github/dante/src/3rdparty/spine-runtimes/examples/raptor/export/raptor-pro.json" -#define RAPTOR_ATLAS "/Users/sgowen/Dropbox/Documents/freelance/NoctisGames/github/dante/src/3rdparty/spine-runtimes/examples/raptor/export/raptor.atlas" +#define RAPTOR_JSON "testdata/raptor/raptor-pro.json" +#define RAPTOR_ATLAS "testdata/raptor/raptor.atlas" -#define GOBLINS_JSON "/Users/sgowen/Dropbox/Documents/freelance/NoctisGames/github/dante/src/3rdparty/spine-runtimes/examples/goblins/export/goblins-pro.json" -#define GOBLINS_ATLAS "/Users/sgowen/Dropbox/Documents/freelance/NoctisGames/github/dante/src/3rdparty/spine-runtimes/examples/goblins/export/goblins.atlas" +#define GOBLINS_JSON "testdata/goblins/goblins-pro.json" +#define GOBLINS_ATLAS "testdata/goblins/goblins.atlas" #define MAX_RUN_TIME 6000 // equal to about 100 seconds of execution From 37abe9609dbfa361dff39b361ce15d74b62dd45a Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Thu, 7 Dec 2017 14:14:13 -0500 Subject: [PATCH 74/83] Whoops, didn't mean to make changes in spine-c --- spine-c/spine-c/src/spine/SkeletonBinary.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/spine-c/spine-c/src/spine/SkeletonBinary.c b/spine-c/spine-c/src/spine/SkeletonBinary.c index 6da478732..d4e06bc25 100644 --- a/spine-c/spine-c/src/spine/SkeletonBinary.c +++ b/spine-c/spine-c/src/spine/SkeletonBinary.c @@ -262,12 +262,10 @@ static spAnimation* _spSkeletonBinary_readAnimation (spSkeletonBinary* self, con unsigned char timelineType = readByte(input); int frameCount = readVarint(input, 1); switch (timelineType) { - case SLOT_ATTACHMENT: - { + case SLOT_ATTACHMENT: { spAttachmentTimeline* timeline = spAttachmentTimeline_create(frameCount); timeline->slotIndex = slotIndex; - for (frameIndex = 0; frameIndex < frameCount; ++frameIndex) - { + for (frameIndex = 0; frameIndex < frameCount; ++frameIndex) { float time = readFloat(input); const char* attachmentName = readString(input); /* TODO Avoid copying of attachmentName inside */ From c1995586aa3b6db85677c228124ee1ba54a165a4 Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Thu, 7 Dec 2017 14:22:33 -0500 Subject: [PATCH 75/83] README tweaks --- spine-cpp/README.md | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/spine-cpp/README.md b/spine-cpp/README.md index ae59ae773..51d1ed5a0 100644 --- a/spine-cpp/README.md +++ b/spine-cpp/README.md @@ -17,27 +17,22 @@ spine-cpp supports all Spine features. ## Setup 1. Download the Spine Runtimes source using [git](https://help.github.com/articles/set-up-git) or by downloading it as a zip via the download button above. -1. Open the `spine-c.sln` Visual C++ 2010 Express project file. For other IDEs, you will need to create a new project and import the source. +2. Create a new project and import the source. -Alternatively, the contents of the `spine-c/spine-c/src` and `spine-c/spine-c/include` directories can be copied into your project. Be sure your header search is configured to find the contents of the `spine-c/spine-c/include` directory. Note that the includes use `spine/Xxx.h`, so the `spine` directory cannot be omitted when copying the files. - -If `SPINE_SHORT_NAMES` is defined, the `sp` prefix for all structs and functions is optional. Only use this if the spine-cpp names won't cause a conflict. +Alternatively, the contents of the `spine-cpp/spine-cpp/src` and `spine-cpp/spine-cpp/include` directories can be copied into your project. Be sure your header search is configured to find the contents of the `spine-cpp/spine-cpp/include` directory. Note that the includes use `spine/Xxx.h`, so the `spine` directory cannot be omitted when copying the files. ## Extension -Extending spine-cpp requires implementing three methods: +Extending spine-cpp requires implementing both the SpineExtension class (which has a handy default instance) and the TextureLoader class: -- `_spAtlasPage_createTexture` Loads a texture and stores it and its size in the `void* rendererObject`, `width` and `height` fields of an `spAtlasPage` struct. -- `_spAtlasPage_disposeTexture` Disposes of a texture loaded with `_spAtlasPage_createTexture`. -- `_spUtil_readFile` Reads a file. If this doesn't need to be customized, `_readFile` is provided which reads a file using `fopen`. +Spine::SpineExtension::setInstance(Spine::DefaultSpineExtension::getInstance()); -With these implemented, the spine-cpp API can then be used to load Spine animation data. Rendering is done by enumerating the slots for a skeleton and rendering the attachment for each slot. Each attachment has a `rendererObject` field that is set when the attachment is loaded. +class MyTextureLoader : public TextureLoader +{ + virtual void load(AtlasPage& page, std::string path) { // TODO } -For example, `AtlasAttachmentLoader` is typically used to load attachments when using a Spine texture atlas. When `AtlasAttachmentLoader` loads a `RegionAttachment`, the attachment's `void* rendererObject` is set to an `AtlasRegion`. Rendering code can then obtain the `AtlasRegion` from the attachment, get the `AtlasPage` it belongs to, and get the page's `void* rendererObject`. This is the renderer specific texture object set by `_spAtlasPage_createTexture`. Attachment loading can be [customized](http://esotericsoftware.com/spine-using-runtimes/#attachmentloader) if not using `AtlasAttachmentLoader` or to provider different renderer specific data. - -[spine-sfml](../spine-sfml/src/spine/spine-sfml.cpp#L39) serves as a simple example of extending spine-c. - -spine-cpp uses an OOP style of programming where each "class" is made up of a struct and a number of functions prefixed with the struct name. More detals about how this works are available in [extension.h](spine-c/include/spine/extension.h#L2). This mechanism allows you to provide your own implementations for `spAttachmentLoader`, `spAttachment` and `spTimeline`, if necessary. + virtual void unload(void* texture) { // TODO } +}; ## Runtimes extending spine-cpp From e24b061c61bbaf539af35d488d8e811788ea15ac Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Fri, 8 Dec 2017 14:15:30 -0500 Subject: [PATCH 76/83] Yay, now the C++ Runtime passes all the same tests as the C Runtime! --- .../spine_unit_test.xcodeproj/project.pbxproj | 2 + .../spine_unit_test/MemoryTest.h | 444 ++++++++++++ .../spine_unit_test/SimpleTest.h | 2 +- .../spine_unit_test/spine_unit_test/main.cpp | 2 + .../tests/MemoryTestFixture.cpp | 677 +++++++++--------- .../tests/SpineEventMonitor.cpp | 4 +- spine-cpp/spine-cpp/include/spine/Bone.h | 6 + .../include/spine/SkeletonClipping.h | 4 + spine-cpp/spine-cpp/include/spine/Vector.h | 3 + .../spine-cpp/src/spine/AnimationState.cpp | 2 +- spine-cpp/spine-cpp/src/spine/Bone.cpp | 30 + .../spine-cpp/src/spine/SkeletonClipping.cpp | 32 +- 12 files changed, 862 insertions(+), 346 deletions(-) create mode 100644 spine-cpp/spine-cpp-unit-tests/spine_unit_test/spine_unit_test/MemoryTest.h diff --git a/spine-cpp/spine-cpp-unit-tests/spine_unit_test/spine_unit_test.xcodeproj/project.pbxproj b/spine-cpp/spine-cpp-unit-tests/spine_unit_test/spine_unit_test.xcodeproj/project.pbxproj index 7c82f0d7e..b3171bc62 100644 --- a/spine-cpp/spine-cpp-unit-tests/spine_unit_test/spine_unit_test.xcodeproj/project.pbxproj +++ b/spine-cpp/spine-cpp-unit-tests/spine_unit_test/spine_unit_test.xcodeproj/project.pbxproj @@ -281,6 +281,7 @@ BB6017F01FD92A5B009BD546 /* SimpleTest.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SimpleTest.h; sourceTree = ""; }; BB6017FC1FD92AF3009BD546 /* SpineEventMonitor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpineEventMonitor.h; sourceTree = ""; }; BB6017FD1FD92AF3009BD546 /* SpineEventMonitor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SpineEventMonitor.cpp; sourceTree = ""; }; + BBFB507F1FDAF6CD005B22B6 /* MemoryTest.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MemoryTest.h; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -326,6 +327,7 @@ children = ( BB6017121FD9289A009BD546 /* main.cpp */, BB6017F01FD92A5B009BD546 /* SimpleTest.h */, + BBFB507F1FDAF6CD005B22B6 /* MemoryTest.h */, ); path = spine_unit_test; sourceTree = ""; diff --git a/spine-cpp/spine-cpp-unit-tests/spine_unit_test/spine_unit_test/MemoryTest.h b/spine-cpp/spine-cpp-unit-tests/spine_unit_test/spine_unit_test/MemoryTest.h new file mode 100644 index 000000000..ed8705012 --- /dev/null +++ b/spine-cpp/spine-cpp-unit-tests/spine_unit_test/spine_unit_test/MemoryTest.h @@ -0,0 +1,444 @@ +// +// MemoryTest.h +// spine_unit_test +// +// Created by Stephen Gowen on 12/8/17. +// Copyright © 2017 Noctis Games. All rights reserved. +// + +#ifndef MemoryTest_h +#define MemoryTest_h + +#include "SpineEventMonitor.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "KMemory.h" // last include + +#define SPINEBOY_JSON "testdata/spineboy/spineboy-ess.json" +#define SPINEBOY_ATLAS "testdata/spineboy/spineboy.atlas" + +#define MAX_RUN_TIME 6000 // equal to about 100 seconds of execution + +namespace Spine +{ + class MemoryTest + { + public: + class MyTextureLoader : public TextureLoader + { + virtual void load(AtlasPage& page, std::string path) + { + page.rendererObject = NULL; + page.width = 2048; + page.height = 2048; + } + + virtual void unload(void* texture) + { + // TODO + } + }; + + ////////////////////////////////////////////////////////////////////////// + // Helper methods + static SkeletonData* readSkeletonJsonData(const char* filename, Atlas* atlas) + { + Vector atlasArray; + atlasArray.push_back(atlas); + + SkeletonJson* skeletonJson = NEW(SkeletonJson); + new (skeletonJson) SkeletonJson(atlasArray); + assert(skeletonJson != 0); + + SkeletonData* skeletonData = skeletonJson->readSkeletonDataFile(filename); + assert(skeletonData != 0); + + DESTROY(SkeletonJson, skeletonJson); + + return skeletonData; + } + + static void loadSpineboyExample(Atlas* &atlas, SkeletonData* &skeletonData, AnimationStateData* &stateData, Skeleton* &skeleton, AnimationState* &state) + { + /////////////////////////////////////////////////////////////////////////// + // Global Animation Information + static MyTextureLoader myTextureLoader; + atlas = NEW(Atlas); + new (atlas) Atlas(SPINEBOY_ATLAS, myTextureLoader); + assert(atlas != 0); + + skeletonData = readSkeletonJsonData(SPINEBOY_JSON, atlas); + assert(skeletonData != 0); + + stateData = NEW(AnimationStateData); + new (stateData) AnimationStateData(*skeletonData); + assert(stateData != 0); + stateData->setDefaultMix(0.2f); // force mixing + + /////////////////////////////////////////////////////////////////////////// + // Animation Instance + skeleton = NEW(Skeleton); + new (skeleton) Skeleton(*skeletonData); + assert(skeleton != 0); + + state = NEW(AnimationState); + new (state) AnimationState(*stateData); + assert(state != 0); + } + + static void disposeAll(Skeleton* skeleton, AnimationState* state, AnimationStateData* stateData, SkeletonData* skeletonData, Atlas* atlas) + { + /////////////////////////////////////////////////////////////////////////// + // Dispose Instance + DESTROY(Skeleton, skeleton); + DESTROY(AnimationState, state); + + /////////////////////////////////////////////////////////////////////////// + // Dispose Global + DESTROY(AnimationStateData, stateData); + DESTROY(SkeletonData, skeletonData); + DESTROY(Atlas, atlas); + } + + ////////////////////////////////////////////////////////////////////////// + // Reproduce Memory leak as described in Issue #776 + // https://github.com/EsotericSoftware/spine-runtimes/issues/776 + static void reproduceIssue_776() + { + Atlas* atlas = NULL; + SkeletonData* skeletonData = NULL; + AnimationStateData* stateData = NULL; + Skeleton* skeleton = NULL; + AnimationState* state = NULL; + + ////////////////////////////////////////////////////////////////////////// + // Initialize Animations + loadSpineboyExample(atlas, skeletonData, stateData, skeleton, state); + + /////////////////////////////////////////////////////////////////////////// + // Run animation + skeleton->setToSetupPose(); + InterruptMonitor eventMonitor(state); + + // Interrupt the animation on this specific sequence of spEventType(s) + eventMonitor + .AddInterruptEvent(EventType_Interrupt, "jump") + .AddInterruptEvent(EventType_Start); + + state->setAnimation(0, "walk", true); + state->addAnimation(0, "jump", false, 0.0f); + state->addAnimation(0, "run", true, 0.0f); + state->addAnimation(0, "jump", false, 3.0f); + state->addAnimation(0, "walk", true, 0.0f); + state->addAnimation(0, "idle", false, 1.0f); + + for (int i = 0; i < MAX_RUN_TIME && eventMonitor.isAnimationPlaying(); ++i) + { + const float timeSlice = 1.0f / 60.0f; + skeleton->update(timeSlice); + state->update(timeSlice); + state->apply(*skeleton); + } + + ////////////////////////////////////////////////////////////////////////// + // Cleanup Animations + disposeAll(skeleton, state, stateData, skeletonData, atlas); + } + + static void reproduceIssue_777() + { + Atlas* atlas = NULL; + SkeletonData* skeletonData = NULL; + AnimationStateData* stateData = NULL; + Skeleton* skeleton = NULL; + AnimationState* state = NULL; + + ////////////////////////////////////////////////////////////////////////// + // Initialize Animations + loadSpineboyExample(atlas, skeletonData, stateData, skeleton, state); + + /////////////////////////////////////////////////////////////////////////// + // Run animation + skeleton->setToSetupPose(); + SpineEventMonitor eventMonitor(state); + + // Set Animation and Play for 5 frames + state->setAnimation(0, "walk", true); + for (int i = 0; i < 5; ++i) + { + const float timeSlice = 1.0f / 60.0f; + skeleton->update(timeSlice); + state->update(timeSlice); + state->apply(*skeleton); + } + + // Change animation twice in a row + state->setAnimation(0, "walk", false); + state->setAnimation(0, "run", false); + + // run normal update + for (int i = 0; i < 5; ++i) + { + const float timeSlice = 1.0f / 60.0f; + skeleton->update(timeSlice); + state->update(timeSlice); + state->apply(*skeleton); + } + + // Now we'd lose mixingFrom (the first "walk" entry we set above) and should leak + state->setAnimation(0, "run", false); + + ////////////////////////////////////////////////////////////////////////// + // Cleanup Animations + disposeAll(skeleton, state, stateData, skeletonData, atlas); + } + + static void spineAnimStateHandler(AnimationState* state, EventType type, TrackEntry* entry, Event* event) + { + if (type == EventType_Complete) + { + state->setAnimation(0, "walk", false); + state->update(0); + state->apply(*skeleton); + } + } + + static void reproduceIssue_Loop() + { + Atlas* atlas = NULL; + SkeletonData* skeletonData = NULL; + AnimationStateData* stateData = NULL; + AnimationState* state = NULL; + + ////////////////////////////////////////////////////////////////////////// + // Initialize Animations + loadSpineboyExample(atlas, skeletonData, stateData, skeleton, state); + + /////////////////////////////////////////////////////////////////////////// + + if (state) + { + state->setOnAnimationEventFunc(spineAnimStateHandler); + } + + state->setAnimation(0, "walk", false); + + // run normal update + for (int i = 0; i < 50; ++i) + { + const float timeSlice = 1.0f / 60.0f; + skeleton->update(timeSlice); + state->update(timeSlice); + state->apply(*skeleton); + } + + disposeAll(skeleton, state, stateData, skeletonData, atlas); + } + + static void triangulator() + { + Triangulator* triangulator = NEW(Triangulator); + new (triangulator) Triangulator(); + + Vector polygon; + polygon.reserve(16); + polygon.push_back(0); + polygon.push_back(0); + polygon.push_back(100); + polygon.push_back(0); + polygon.push_back(100); + polygon.push_back(100); + polygon.push_back(0); + polygon.push_back(100); + + Vector triangles = triangulator->triangulate(polygon); + assert(triangles.size() == 6); + assert(triangles[0] == 3); + assert(triangles[1] == 0); + assert(triangles[2] == 1); + assert(triangles[3] == 3); + assert(triangles[4] == 1); + assert(triangles[5] == 2); + + Vector< Vector *> polys = triangulator->decompose(polygon, triangles); + assert(polys.size() == 1); + assert(polys[0]->size() == 8); + + assert(polys[0]->operator[](0) == 0); + assert(polys[0]->operator[](1) == 100); + assert(polys[0]->operator[](2) == 0); + assert(polys[0]->operator[](3) == 0); + assert(polys[0]->operator[](4) == 100); + assert(polys[0]->operator[](5) == 0); + assert(polys[0]->operator[](6) == 100); + assert(polys[0]->operator[](7) == 100); + + DESTROY(Triangulator, triangulator); + } + + static void skeletonClipper() + { + Atlas* atlas = NULL; + SkeletonData* skeletonData = NULL; + AnimationStateData* stateData = NULL; + Skeleton* skeleton = NULL; + AnimationState* state = NULL; + + ////////////////////////////////////////////////////////////////////////// + // Initialize Animations + loadSpineboyExample(atlas, skeletonData, stateData, skeleton, state); + + SkeletonClipping* clipping = NEW(SkeletonClipping); + new (clipping) SkeletonClipping(); + + BoneData* boneData = NEW(BoneData); + new (boneData) BoneData(0, "bone", 0); + + Bone* bone = NEW(Bone); + new(bone) Bone(*boneData, *skeleton, NULL); + + bone->setA(1); + bone->setB(0); + bone->setC(0); + bone->setD(1); + bone->setWorldX(0); + bone->setWorldY(0); + + SlotData* slotData = NEW(SlotData); + new (slotData) SlotData(0, "slot", *boneData); + + Slot* slot = NEW(Slot); + new(slot) Slot(*slotData, *bone); + + ClippingAttachment* clip = NEW(ClippingAttachment); + new(clip) ClippingAttachment("clipping"); + + clip->setEndSlot(slotData); + clip->setWorldVerticesLength(4 * 2); + + Vector clipVertices; + clipVertices.reserve(8); + clipVertices.setSize(8); + + clip->setVertices(clipVertices); + clip->getVertices()[0] = 0; + clip->getVertices()[1] = 50; + clip->getVertices()[2] = 100; + clip->getVertices()[3] = 50; + clip->getVertices()[4] = 100; + clip->getVertices()[5] = 70; + clip->getVertices()[6] = 0; + clip->getVertices()[7] = 70; + + clipping->clipStart(*slot, clip); + + Vector vertices; + vertices.reserve(16); + vertices.push_back(0); + vertices.push_back(0); + vertices.push_back(100); + vertices.push_back(0); + vertices.push_back(50); + vertices.push_back(150); + + Vector uvs; + uvs.reserve(16); + uvs.push_back(0); + uvs.push_back(0); + uvs.push_back(1); + uvs.push_back(0); + uvs.push_back(0.5f); + uvs.push_back(1); + + Vector indices; + indices.reserve(16); + indices.push_back(0); + indices.push_back(1); + indices.push_back(2); + + clipping->clipTriangles(vertices, static_cast(vertices.size()), indices, static_cast(indices.size()), uvs); + + float expectedVertices[8] = { 83.333328, 50.000000, 76.666664, 70.000000, 23.333334, 70.000000, 16.666672, 50.000000 }; + assert(clipping->getClippedVertices().size() == 8); + for (int i = 0; i < clipping->getClippedVertices().size(); i++) + { + assert(abs(clipping->getClippedVertices()[i] - expectedVertices[i]) < 0.001); + } + + float expectedUVs[8] = { 0.833333f, 0.333333, 0.766667, 0.466667, 0.233333, 0.466667, 0.166667, 0.333333 }; + assert(clipping->getClippedUVs().size() == 8); + for (int i = 0; i < clipping->getClippedUVs().size(); i++) + { + assert(abs(clipping->getClippedUVs()[i] - expectedUVs[i]) < 0.001); + } + + short expectedIndices[6] = { 0, 1, 2, 0, 2, 3 }; + assert(clipping->getClippedTriangles().size() == 6); + for (int i = 0; i < clipping->getClippedTriangles().size(); i++) + { + assert(clipping->getClippedTriangles()[i] == expectedIndices[i]); + } + + DESTROY(SlotData, slotData); + DESTROY(Slot, slot); + DESTROY(BoneData, boneData); + DESTROY(Bone, bone); + DESTROY(ClippingAttachment, clip); + DESTROY(SkeletonClipping, clipping); + + ////////////////////////////////////////////////////////////////////////// + // Cleanup Animations + disposeAll(skeleton, state, stateData, skeletonData, atlas); + } + + static void test() + { + reproduceIssue_776(); + reproduceIssue_777(); + reproduceIssue_Loop(); + triangulator(); + skeletonClipper(); + } + + private: + static Skeleton* skeleton; + + // ctor, copy ctor, and assignment should be private in a Singleton + MemoryTest(); + MemoryTest(const MemoryTest&); + MemoryTest& operator=(const MemoryTest&); + }; +} + +Skeleton* MemoryTest::skeleton = NULL; + +#endif /* MemoryTest_h */ diff --git a/spine-cpp/spine-cpp-unit-tests/spine_unit_test/spine_unit_test/SimpleTest.h b/spine-cpp/spine-cpp-unit-tests/spine_unit_test/spine_unit_test/SimpleTest.h index 5cdf2e3d6..5f09bba0d 100644 --- a/spine-cpp/spine-cpp-unit-tests/spine_unit_test/spine_unit_test/SimpleTest.h +++ b/spine-cpp/spine-cpp-unit-tests/spine_unit_test/spine_unit_test/SimpleTest.h @@ -1,6 +1,6 @@ // // SimpleTest.h -// TestHarness +// spine_unit_test // // Created by Stephen Gowen on 11/9/17. // Copyright © 2017 Noctis Games. All rights reserved. diff --git a/spine-cpp/spine-cpp-unit-tests/spine_unit_test/spine_unit_test/main.cpp b/spine-cpp/spine-cpp-unit-tests/spine_unit_test/spine_unit_test/main.cpp index ea1741f2f..05b091cae 100644 --- a/spine-cpp/spine-cpp-unit-tests/spine_unit_test/spine_unit_test/main.cpp +++ b/spine-cpp/spine-cpp-unit-tests/spine_unit_test/spine_unit_test/main.cpp @@ -19,6 +19,7 @@ #include "spine/Extension.h" #include "SimpleTest.h" +#include "MemoryTest.h" #include "KMemory.h" // last include @@ -101,6 +102,7 @@ int main(int argc, char* argv[]) #endif SimpleTest::test(); + MemoryTest::test(); // End Timing time(&end_time); diff --git a/spine-cpp/spine-cpp-unit-tests/tests/MemoryTestFixture.cpp b/spine-cpp/spine-cpp-unit-tests/tests/MemoryTestFixture.cpp index a59822a43..d06c196e6 100755 --- a/spine-cpp/spine-cpp-unit-tests/tests/MemoryTestFixture.cpp +++ b/spine-cpp/spine-cpp-unit-tests/tests/MemoryTestFixture.cpp @@ -1,338 +1,339 @@ -//#include -//#include "MemoryTestFixture.h" -//#include "SpineEventMonitor.h" -// -//#include "KMemory.h" // last include -// -//#define SPINEBOY_JSON "testdata/spineboy/spineboy-ess.json" -//#define SPINEBOY_ATLAS "testdata/spineboy/spineboy.atlas" -// -//#define MAX_RUN_TIME 6000 // equal to about 100 seconds of execution -// -//MemoryTestFixture::~MemoryTestFixture() -//{ -// finalize(); -//} -// -//void MemoryTestFixture::initialize() -//{ -// // on a Per- Fixture Basis, before Test execution -//} -// -//void MemoryTestFixture::finalize() -//{ -// // on a Per- Fixture Basis, after all tests pass/fail -//} -// -//void MemoryTestFixture::setUp() -//{ -// // Setup on Per-Test Basis -//} -// -//void MemoryTestFixture::tearDown() -//{ -// // Tear Down on Per-Test Basis -//} -// -// -//////////////////////////////////////////////////////////////////////////// -//// Helper methods -//static spSkeletonData* readSkeletonJsonData(const char* filename, spAtlas* atlas) { -// spSkeletonJson* json = spSkeletonJson_create(atlas); -// ASSERT(json != 0); -// -// spSkeletonData* skeletonData = spSkeletonJson_readSkeletonDataFile(json, filename); -// ASSERT(skeletonData != 0); -// -// spSkeletonJson_dispose(json); -// return skeletonData; -//} -// -//static void LoadSpineboyExample(spAtlas* &atlas, spSkeletonData* &skeletonData, spAnimationStateData* &stateData, spSkeleton* &skeleton, spAnimationState* &state) -//{ -// /////////////////////////////////////////////////////////////////////////// -// // Global Animation Information -// atlas = spAtlas_createFromFile(SPINEBOY_ATLAS, 0); -// ASSERT(atlas != 0); -// -// skeletonData = readSkeletonJsonData(SPINEBOY_JSON, atlas); -// ASSERT(skeletonData != 0); -// -// stateData = spAnimationStateData_create(skeletonData); -// ASSERT(stateData != 0); -// stateData->defaultMix = 0.4f; // force mixing -// -// /////////////////////////////////////////////////////////////////////////// -// // Animation Instance -// skeleton = spSkeleton_create(skeletonData); -// ASSERT(skeleton != 0); -// -// state = spAnimationState_create(stateData); -// ASSERT(state != 0); -//} -// -//static void DisposeAll(spSkeleton* skeleton, spAnimationState* state, spAnimationStateData* stateData, spSkeletonData* skeletonData, spAtlas* atlas) -//{ -// /////////////////////////////////////////////////////////////////////////// -// // Dispose Instance -// spSkeleton_dispose(skeleton); -// spAnimationState_dispose(state); -// -// /////////////////////////////////////////////////////////////////////////// -// // Dispose Global -// spAnimationStateData_dispose(stateData); -// spSkeletonData_dispose(skeletonData); -// spAtlas_dispose(atlas); -//} -// -// -//////////////////////////////////////////////////////////////////////////// -//// Reproduce Memory leak as described in Issue #776 -//// https://github.com/EsotericSoftware/spine-runtimes/issues/776 -//void MemoryTestFixture::reproduceIssue_776() -//{ -// spAtlas* atlas = 0; -// spSkeletonData* skeletonData = 0; -// spAnimationStateData* stateData = 0; -// spSkeleton* skeleton = 0; -// spAnimationState* state = 0; -// -// ////////////////////////////////////////////////////////////////////////// -// // Initialize Animations -// LoadSpineboyExample(atlas, skeletonData, stateData, skeleton, state); -// -// /////////////////////////////////////////////////////////////////////////// -// // Run animation -// spSkeleton_setToSetupPose(skeleton); -// InterruptMonitor eventMonitor(state); -// //eventMonitor.SetDebugLogging(true); -// -// // Interrupt the animation on this specific sequence of spEventType(s) -// eventMonitor -// .AddInterruptEvent(SP_ANIMATION_INTERRUPT, "jump") -// .AddInterruptEvent(SP_ANIMATION_START); -// -// spAnimationState_setAnimationByName(state, 0, "walk", true); -// spAnimationState_addAnimationByName(state, 0, "jump", false, 0.0f); -// spAnimationState_addAnimationByName(state, 0, "run", true, 0.0f); -// spAnimationState_addAnimationByName(state, 0, "jump", false, 3.0f); -// spAnimationState_addAnimationByName(state, 0, "walk", true, 0.0f); -// spAnimationState_addAnimationByName(state, 0, "idle", false, 1.0f); -// -// for (int i = 0; i < MAX_RUN_TIME && eventMonitor.isAnimationPlaying(); ++i) { -// const float timeSlice = 1.0f / 60.0f; -// spSkeleton_update(skeleton, timeSlice); -// spAnimationState_update(state, timeSlice); -// spAnimationState_apply(state, skeleton); -// } -// -// ////////////////////////////////////////////////////////////////////////// -// // Cleanup Animations -// DisposeAll(skeleton, state, stateData, skeletonData, atlas); -//} -// -//void MemoryTestFixture::reproduceIssue_777() -//{ -// spAtlas* atlas = 0; -// spSkeletonData* skeletonData = 0; -// spAnimationStateData* stateData = 0; -// spSkeleton* skeleton = 0; -// spAnimationState* state = 0; -// -// ////////////////////////////////////////////////////////////////////////// -// // Initialize Animations -// LoadSpineboyExample(atlas, skeletonData, stateData, skeleton, state); -// -// /////////////////////////////////////////////////////////////////////////// -// // Run animation -// spSkeleton_setToSetupPose(skeleton); -// SpineEventMonitor eventMonitor(state); -// //eventMonitor.SetDebugLogging(true); -// -// // Set Animation and Play for 5 frames -// spAnimationState_setAnimationByName(state, 0, "walk", true); -// for (int i = 0; i < 5; ++i) { -// const float timeSlice = 1.0f / 60.0f; -// spSkeleton_update(skeleton, timeSlice); -// spAnimationState_update(state, timeSlice); -// spAnimationState_apply(state, skeleton); -// } -// -// // Change animation twice in a row -// spAnimationState_setAnimationByName(state, 0, "walk", false); -// spAnimationState_setAnimationByName(state, 0, "run", false); -// -// // run normal update -// for (int i = 0; i < 5; ++i) { -// const float timeSlice = 1.0f / 60.0f; -// spSkeleton_update(skeleton, timeSlice); -// spAnimationState_update(state, timeSlice); -// spAnimationState_apply(state, skeleton); -// } -// -// // Now we'd lose mixingFrom (the first "walk" entry we set above) and should leak -// spAnimationState_setAnimationByName(state, 0, "run", false); -// -// ////////////////////////////////////////////////////////////////////////// -// // Cleanup Animations -// DisposeAll(skeleton, state, stateData, skeletonData, atlas); -//} -// -//spSkeleton* skeleton = 0; -//static void spineAnimStateHandler(spAnimationState* state, int type, spTrackEntry* entry, spEvent* event) -//{ -// if (type == SP_ANIMATION_COMPLETE) -// { -// spAnimationState_setAnimationByName(state, 0, "walk", false); -// spAnimationState_update(state, 0); -// spAnimationState_apply(state, skeleton); -// } -//} -// -//void MemoryTestFixture::reproduceIssue_Loop() -//{ -// spAtlas* atlas = 0; -// spSkeletonData* skeletonData = 0; -// spAnimationStateData* stateData = 0; -// spAnimationState* state = 0; -// -// ////////////////////////////////////////////////////////////////////////// -// // Initialize Animations -// LoadSpineboyExample(atlas, skeletonData, stateData, skeleton, state); -// -// /////////////////////////////////////////////////////////////////////////// -// -// if (state) -// state->listener = (spAnimationStateListener)&spineAnimStateHandler; -// -// spAnimationState_setAnimationByName(state, 0, "walk", false); -// -// // run normal update -// for (int i = 0; i < 50; ++i) { -// const float timeSlice = 1.0f / 60.0f; -// spSkeleton_update(skeleton, timeSlice); -// spAnimationState_update(state, timeSlice); -// spAnimationState_apply(state, skeleton); -// } -// -// DisposeAll(skeleton, state, stateData, skeletonData, atlas); -//} -// -//void MemoryTestFixture::triangulator() { -// spTriangulator* triangulator = spTriangulator_create(); -// spFloatArray* polygon = spFloatArray_create(16); -// spFloatArray_add(polygon, 0); -// spFloatArray_add(polygon, 0); -// spFloatArray_add(polygon, 100); -// spFloatArray_add(polygon, 0); -// spFloatArray_add(polygon, 100); -// spFloatArray_add(polygon, 100); -// spFloatArray_add(polygon, 0); -// spFloatArray_add(polygon, 100); -// -// spShortArray* triangles = spTriangulator_triangulate(triangulator, polygon); -// ASSERT(triangles->size == 6); -// ASSERT(triangles->items[0] == 3); -// ASSERT(triangles->items[1] == 0); -// ASSERT(triangles->items[2] == 1); -// ASSERT(triangles->items[3] == 3); -// ASSERT(triangles->items[4] == 1); -// ASSERT(triangles->items[5] == 2); -// -// spArrayFloatArray* polys = spTriangulator_decompose(triangulator, polygon, triangles); -// ASSERT(polys->size == 1); -// ASSERT(polys->items[0]->size == 8); -// ASSERT(polys->items[0]->items[0] == 0); -// ASSERT(polys->items[0]->items[1] == 100); -// ASSERT(polys->items[0]->items[2] == 0); -// ASSERT(polys->items[0]->items[3] == 0); -// ASSERT(polys->items[0]->items[4] == 100); -// ASSERT(polys->items[0]->items[5] == 0); -// ASSERT(polys->items[0]->items[6] == 100); -// ASSERT(polys->items[0]->items[7] == 100); -// -// spFloatArray_dispose(polygon); -// spTriangulator_dispose(triangulator); -//} -// -//void MemoryTestFixture::skeletonClipper() { -// spSkeletonClipping* clipping = spSkeletonClipping_create(); -// -// spBoneData* boneData = spBoneData_create(0, "bone", 0); -// spBone* bone = spBone_create(boneData, 0, 0); -// CONST_CAST(float, bone->a) = 1; -// CONST_CAST(float, bone->b) = 0; -// CONST_CAST(float, bone->c) = 0; -// CONST_CAST(float, bone->d) = 1; -// CONST_CAST(float, bone->worldX) = 0; -// CONST_CAST(float, bone->worldY) = 0; -// spSlotData* slotData = spSlotData_create(0, "slot", 0); -// spSlot* slot = spSlot_create(slotData, bone); -// spClippingAttachment* clip = spClippingAttachment_create("clipping"); -// clip->endSlot = slotData; -// clip->super.worldVerticesLength = 4 * 2; -// clip->super.verticesCount = 4; -// clip->super.vertices = MALLOC(float, 4 * 8); -// clip->super.vertices[0] = 0; -// clip->super.vertices[1] = 50; -// clip->super.vertices[2] = 100; -// clip->super.vertices[3] = 50; -// clip->super.vertices[4] = 100; -// clip->super.vertices[5] = 70; -// clip->super.vertices[6] = 0; -// clip->super.vertices[7] = 70; -// -// spSkeletonClipping_clipStart(clipping, slot, clip); -// -// spFloatArray* vertices = spFloatArray_create(16); -// spFloatArray_add(vertices, 0); -// spFloatArray_add(vertices, 0); -// spFloatArray_add(vertices, 100); -// spFloatArray_add(vertices, 0); -// spFloatArray_add(vertices, 50); -// spFloatArray_add(vertices, 150); -// spFloatArray* uvs = spFloatArray_create(16); -// spFloatArray_add(uvs, 0); -// spFloatArray_add(uvs, 0); -// spFloatArray_add(uvs, 1); -// spFloatArray_add(uvs, 0); -// spFloatArray_add(uvs, 0.5f); -// spFloatArray_add(uvs, 1); -// spUnsignedShortArray* indices = spUnsignedShortArray_create(16); -// spUnsignedShortArray_add(indices, 0); -// spUnsignedShortArray_add(indices, 1); -// spUnsignedShortArray_add(indices, 2); -// -// spSkeletonClipping_clipTriangles(clipping, vertices->items, vertices->size, indices->items, indices->size, uvs->items, 2); -// -// float expectedVertices[8] = { 83.333328, 50.000000, 76.666664, 70.000000, 23.333334, 70.000000, 16.666672, 50.000000 }; -// ASSERT(clipping->clippedVertices->size == 8); -// for (int i = 0; i < clipping->clippedVertices->size; i++) { -// ASSERT(ABS(clipping->clippedVertices->items[i] - expectedVertices[i]) < 0.001); -// } -// -// float expectedUVs[8] = { 0.833333f, 0.333333, 0.766667, 0.466667, 0.233333, 0.466667, 0.166667, 0.333333 }; -// ASSERT(clipping->clippedUVs->size == 8); -// for (int i = 0; i < clipping->clippedUVs->size; i++) { -// ASSERT(ABS(clipping->clippedUVs->items[i] - expectedUVs[i]) < 0.001); -// } -// -// short expectedIndices[6] = { 0, 1, 2, 0, 2, 3 }; -// ASSERT(clipping->clippedTriangles->size == 6); -// for (int i = 0; i < clipping->clippedTriangles->size; i++) { -// ASSERT(clipping->clippedTriangles->items[i] == expectedIndices[i]); -// } -// -// spFloatArray_dispose(vertices); -// spFloatArray_dispose(uvs); -// spUnsignedShortArray_dispose(indices); -// -// spSlotData_dispose(slotData); -// spSlot_dispose(slot); -// spBoneData_dispose(boneData); -// spBone_dispose(bone); -// _spClippingAttachment_dispose(SUPER(SUPER(clip))); -// spSkeletonClipping_dispose(clipping); -//} -// -// +#include +#include "MemoryTestFixture.h" +#include "SpineEventMonitor.h" + +#include "KMemory.h" // last include + +#define SPINEBOY_JSON "testdata/spineboy/spineboy-ess.json" +#define SPINEBOY_ATLAS "testdata/spineboy/spineboy.atlas" + +#define MAX_RUN_TIME 6000 // equal to about 100 seconds of execution + +MemoryTestFixture::~MemoryTestFixture() +{ + finalize(); +} + +void MemoryTestFixture::initialize() +{ + // on a Per- Fixture Basis, before Test execution +} + +void MemoryTestFixture::finalize() +{ + // on a Per- Fixture Basis, after all tests pass/fail +} + +void MemoryTestFixture::setUp() +{ + // Setup on Per-Test Basis +} + +void MemoryTestFixture::tearDown() +{ + // Tear Down on Per-Test Basis +} + + +////////////////////////////////////////////////////////////////////////// +// Helper methods +static spSkeletonData* readSkeletonJsonData(const char* filename, spAtlas* atlas) { + spSkeletonJson* json = spSkeletonJson_create(atlas); + ASSERT(json != 0); + + spSkeletonData* skeletonData = spSkeletonJson_readSkeletonDataFile(json, filename); + ASSERT(skeletonData != 0); + + spSkeletonJson_dispose(json); + return skeletonData; +} + +static void LoadSpineboyExample(spAtlas* &atlas, spSkeletonData* &skeletonData, spAnimationStateData* &stateData, spSkeleton* &skeleton, spAnimationState* &state) +{ + /////////////////////////////////////////////////////////////////////////// + // Global Animation Information + atlas = spAtlas_createFromFile(SPINEBOY_ATLAS, 0); + ASSERT(atlas != 0); + + skeletonData = readSkeletonJsonData(SPINEBOY_JSON, atlas); + ASSERT(skeletonData != 0); + + stateData = spAnimationStateData_create(skeletonData); + ASSERT(stateData != 0); + stateData->defaultMix = 0.4f; // force mixing + + /////////////////////////////////////////////////////////////////////////// + // Animation Instance + skeleton = spSkeleton_create(skeletonData); + ASSERT(skeleton != 0); + + state = spAnimationState_create(stateData); + ASSERT(state != 0); +} + +static void DisposeAll(spSkeleton* skeleton, spAnimationState* state, spAnimationStateData* stateData, spSkeletonData* skeletonData, spAtlas* atlas) +{ + /////////////////////////////////////////////////////////////////////////// + // Dispose Instance + spSkeleton_dispose(skeleton); + spAnimationState_dispose(state); + + /////////////////////////////////////////////////////////////////////////// + // Dispose Global + spAnimationStateData_dispose(stateData); + spSkeletonData_dispose(skeletonData); + spAtlas_dispose(atlas); +} + + +////////////////////////////////////////////////////////////////////////// +// Reproduce Memory leak as described in Issue #776 +// https://github.com/EsotericSoftware/spine-runtimes/issues/776 +void MemoryTestFixture::reproduceIssue_776() +{ + spAtlas* atlas = 0; + spSkeletonData* skeletonData = 0; + spAnimationStateData* stateData = 0; + spSkeleton* skeleton = 0; + spAnimationState* state = 0; + + ////////////////////////////////////////////////////////////////////////// + // Initialize Animations + LoadSpineboyExample(atlas, skeletonData, stateData, skeleton, state); + + /////////////////////////////////////////////////////////////////////////// + // Run animation + spSkeleton_setToSetupPose(skeleton); + InterruptMonitor eventMonitor(state); + //eventMonitor.SetDebugLogging(true); + + // Interrupt the animation on this specific sequence of spEventType(s) + eventMonitor + .AddInterruptEvent(SP_ANIMATION_INTERRUPT, "jump") + .AddInterruptEvent(SP_ANIMATION_START); + + spAnimationState_setAnimationByName(state, 0, "walk", true); + spAnimationState_addAnimationByName(state, 0, "jump", false, 0.0f); + spAnimationState_addAnimationByName(state, 0, "run", true, 0.0f); + spAnimationState_addAnimationByName(state, 0, "jump", false, 3.0f); + spAnimationState_addAnimationByName(state, 0, "walk", true, 0.0f); + spAnimationState_addAnimationByName(state, 0, "idle", false, 1.0f); + + for (int i = 0; i < MAX_RUN_TIME && eventMonitor.isAnimationPlaying(); ++i) { + const float timeSlice = 1.0f / 60.0f; + spSkeleton_update(skeleton, timeSlice); + spAnimationState_update(state, timeSlice); + spAnimationState_apply(state, skeleton); + } + + ////////////////////////////////////////////////////////////////////////// + // Cleanup Animations + DisposeAll(skeleton, state, stateData, skeletonData, atlas); +} + +void MemoryTestFixture::reproduceIssue_777() +{ + spAtlas* atlas = 0; + spSkeletonData* skeletonData = 0; + spAnimationStateData* stateData = 0; + spSkeleton* skeleton = 0; + spAnimationState* state = 0; + + ////////////////////////////////////////////////////////////////////////// + // Initialize Animations + LoadSpineboyExample(atlas, skeletonData, stateData, skeleton, state); + + /////////////////////////////////////////////////////////////////////////// + // Run animation + spSkeleton_setToSetupPose(skeleton); + SpineEventMonitor eventMonitor(state); + //eventMonitor.SetDebugLogging(true); + + // Set Animation and Play for 5 frames + spAnimationState_setAnimationByName(state, 0, "walk", true); + for (int i = 0; i < 5; ++i) { + const float timeSlice = 1.0f / 60.0f; + spSkeleton_update(skeleton, timeSlice); + spAnimationState_update(state, timeSlice); + spAnimationState_apply(state, skeleton); + } + + // Change animation twice in a row + spAnimationState_setAnimationByName(state, 0, "walk", false); + spAnimationState_setAnimationByName(state, 0, "run", false); + + // run normal update + for (int i = 0; i < 5; ++i) { + const float timeSlice = 1.0f / 60.0f; + spSkeleton_update(skeleton, timeSlice); + spAnimationState_update(state, timeSlice); + spAnimationState_apply(state, skeleton); + } + + // Now we'd lose mixingFrom (the first "walk" entry we set above) and should leak + spAnimationState_setAnimationByName(state, 0, "run", false); + + ////////////////////////////////////////////////////////////////////////// + // Cleanup Animations + DisposeAll(skeleton, state, stateData, skeletonData, atlas); +} + +spSkeleton* skeleton = 0; +static void spineAnimStateHandler(spAnimationState* state, int type, spTrackEntry* entry, spEvent* event) +{ + if (type == SP_ANIMATION_COMPLETE) + { + spAnimationState_setAnimationByName(state, 0, "walk", false); + spAnimationState_update(state, 0); + spAnimationState_apply(state, skeleton); + } +} + +void MemoryTestFixture::reproduceIssue_Loop() +{ + spAtlas* atlas = 0; + spSkeletonData* skeletonData = 0; + spAnimationStateData* stateData = 0; + spAnimationState* state = 0; + + ////////////////////////////////////////////////////////////////////////// + // Initialize Animations + LoadSpineboyExample(atlas, skeletonData, stateData, skeleton, state); + + /////////////////////////////////////////////////////////////////////////// + + if (state) + state->listener = (spAnimationStateListener)&spineAnimStateHandler; + + spAnimationState_setAnimationByName(state, 0, "walk", false); + + // run normal update + for (int i = 0; i < 50; ++i) { + const float timeSlice = 1.0f / 60.0f; + spSkeleton_update(skeleton, timeSlice); + spAnimationState_update(state, timeSlice); + spAnimationState_apply(state, skeleton); + } + + DisposeAll(skeleton, state, stateData, skeletonData, atlas); +} + +void MemoryTestFixture::triangulator() { + spTriangulator* triangulator = spTriangulator_create(); + spFloatArray* polygon = spFloatArray_create(16); + spFloatArray_add(polygon, 0); + spFloatArray_add(polygon, 0); + spFloatArray_add(polygon, 100); + spFloatArray_add(polygon, 0); + spFloatArray_add(polygon, 100); + spFloatArray_add(polygon, 100); + spFloatArray_add(polygon, 0); + spFloatArray_add(polygon, 100); + + spShortArray* triangles = spTriangulator_triangulate(triangulator, polygon); + ASSERT(triangles->size == 6); + ASSERT(triangles->items[0] == 3); + ASSERT(triangles->items[1] == 0); + ASSERT(triangles->items[2] == 1); + ASSERT(triangles->items[3] == 3); + ASSERT(triangles->items[4] == 1); + ASSERT(triangles->items[5] == 2); + + spArrayFloatArray* polys = spTriangulator_decompose(triangulator, polygon, triangles); + ASSERT(polys->size == 1); + ASSERT(polys->items[0]->size == 8); + ASSERT(polys->items[0]->items[0] == 0); + ASSERT(polys->items[0]->items[1] == 100); + ASSERT(polys->items[0]->items[2] == 0); + ASSERT(polys->items[0]->items[3] == 0); + ASSERT(polys->items[0]->items[4] == 100); + ASSERT(polys->items[0]->items[5] == 0); + ASSERT(polys->items[0]->items[6] == 100); + ASSERT(polys->items[0]->items[7] == 100); + + spFloatArray_dispose(polygon); + spTriangulator_dispose(triangulator); +} + +void MemoryTestFixture::skeletonClipper() { + spSkeletonClipping* clipping = spSkeletonClipping_create(); + + spBoneData* boneData = spBoneData_create(0, "bone", 0); + spBone* bone = spBone_create(boneData, 0, 0); + CONST_CAST(float, bone->a) = 1; + CONST_CAST(float, bone->b) = 0; + CONST_CAST(float, bone->c) = 0; + CONST_CAST(float, bone->d) = 1; + CONST_CAST(float, bone->worldX) = 0; + CONST_CAST(float, bone->worldY) = 0; + spSlotData* slotData = spSlotData_create(0, "slot", 0); + spSlot* slot = spSlot_create(slotData, bone); + spClippingAttachment* clip = spClippingAttachment_create("clipping"); + clip->endSlot = slotData; + clip->super.worldVerticesLength = 4 * 2; + clip->super.verticesCount = 4; + clip->super.vertices = MALLOC(float, 4 * 8); + clip->super.vertices[0] = 0; + clip->super.vertices[1] = 50; + clip->super.vertices[2] = 100; + clip->super.vertices[3] = 50; + clip->super.vertices[4] = 100; + clip->super.vertices[5] = 70; + clip->super.vertices[6] = 0; + clip->super.vertices[7] = 70; + + spSkeletonClipping_clipStart(clipping, slot, clip); + + spFloatArray* vertices = spFloatArray_create(16); + spFloatArray_add(vertices, 0); + spFloatArray_add(vertices, 0); + spFloatArray_add(vertices, 100); + spFloatArray_add(vertices, 0); + spFloatArray_add(vertices, 50); + spFloatArray_add(vertices, 150); + spFloatArray* uvs = spFloatArray_create(16); + spFloatArray_add(uvs, 0); + spFloatArray_add(uvs, 0); + spFloatArray_add(uvs, 1); + spFloatArray_add(uvs, 0); + spFloatArray_add(uvs, 0.5f); + spFloatArray_add(uvs, 1); + spUnsignedShortArray* indices = spUnsignedShortArray_create(16); + spUnsignedShortArray_add(indices, 0); + spUnsignedShortArray_add(indices, 1); + spUnsignedShortArray_add(indices, 2); + + spSkeletonClipping_clipTriangles(clipping, vertices->items, vertices->size, indices->items, indices->size, uvs->items, 2); + + float expectedVertices[8] = { 83.333328, 50.000000, 76.666664, 70.000000, 23.333334, 70.000000, 16.666672, 50.000000 }; + ASSERT(clipping->clippedVertices->size == 8); + for (int i = 0; i < clipping->clippedVertices->size; i++) { + ASSERT(ABS(clipping->clippedVertices->items[i] - expectedVertices[i]) < 0.001); + } + + float expectedUVs[8] = { 0.833333f, 0.333333, 0.766667, 0.466667, 0.233333, 0.466667, 0.166667, 0.333333 }; + ASSERT(clipping->clippedUVs->size == 8); + for (int i = 0; i < clipping->clippedUVs->size; i++) { + ASSERT(ABS(clipping->clippedUVs->items[i] - expectedUVs[i]) < 0.001); + } + + short expectedIndices[6] = { 0, 1, 2, 0, 2, 3 }; + ASSERT(clipping->clippedTriangles->size == 6); + for (int i = 0; i < clipping->clippedTriangles->size; i++) { + ASSERT(clipping->clippedTriangles->items[i] == expectedIndices[i]); + } + + spFloatArray_dispose(vertices); + spFloatArray_dispose(uvs); + spUnsignedShortArray_dispose(indices); + + spSlotData_dispose(slotData); + spSlot_dispose(slot); + spBoneData_dispose(boneData); + spBone_dispose(bone); + _spClippingAttachment_dispose(SUPER(SUPER(clip))); + spSkeletonClipping_dispose(clipping); +} + + + diff --git a/spine-cpp/spine-cpp-unit-tests/tests/SpineEventMonitor.cpp b/spine-cpp/spine-cpp-unit-tests/tests/SpineEventMonitor.cpp index b24f39521..9506e354c 100755 --- a/spine-cpp/spine-cpp-unit-tests/tests/SpineEventMonitor.cpp +++ b/spine-cpp/spine-cpp-unit-tests/tests/SpineEventMonitor.cpp @@ -116,7 +116,7 @@ InterruptMonitor& InterruptMonitor::AddInterruptEvent(int theEventType, TrackEnt InterruptMonitor& InterruptMonitor::AddInterruptEventTrigger(const std::string & theEventTriggerName) { InterruptEvent ev; -// ev.mEventType = SP_ANIMATION_EVENT; + ev.mEventType = EventType_Event; ev.mEventName = theEventTriggerName; mEventStack.push_back(ev); return *this; @@ -143,7 +143,7 @@ void InterruptMonitor::OnSpineAnimationStateEvent(AnimationState * state, EventT inline bool InterruptMonitor::InterruptEvent::matches(AnimationState * state, EventType type, TrackEntry * trackEntry, Event * event) { - // Must match spEventType {SP_ANIMATION_START, SP_ANIMATION_INTERRUPT, SP_ANIMATION_END, SP_ANIMATION_COMPLETE, SP_ANIMATION_DISPOSE, SP_ANIMATION_EVENT } + // Must match EventType {EventType_Start, EventType_Interrupt, EventType_End, EventType_Complete, EventType_Dispose, EventType_Event } if (mEventType == type) { // Looking for specific TrackEntry by pointer diff --git a/spine-cpp/spine-cpp/include/spine/Bone.h b/spine-cpp/spine-cpp/include/spine/Bone.h index 6b36dd824..c7f1c7bf6 100644 --- a/spine-cpp/spine-cpp/include/spine/Bone.h +++ b/spine-cpp/spine-cpp/include/spine/Bone.h @@ -162,12 +162,18 @@ namespace Spine void setAShearY(float inValue); float getA(); + void setA(float inValue); float getB(); + void setB(float inValue); float getC(); + void setC(float inValue); float getD(); + void setD(float inValue); float getWorldX(); + void setWorldX(float inValue); float getWorldY(); + void setWorldY(float inValue); float getWorldRotationX(); float getWorldRotationY(); diff --git a/spine-cpp/spine-cpp/include/spine/SkeletonClipping.h b/spine-cpp/spine-cpp/include/spine/SkeletonClipping.h index 7a5cde4cd..f61e4aa7d 100644 --- a/spine-cpp/spine-cpp/include/spine/SkeletonClipping.h +++ b/spine-cpp/spine-cpp/include/spine/SkeletonClipping.h @@ -54,6 +54,10 @@ namespace Spine bool isClipping(); + Vector& getClippedVertices(); + Vector& getClippedTriangles(); + Vector& getClippedUVs(); + private: Triangulator _triangulator; Vector _clippingPolygon; diff --git a/spine-cpp/spine-cpp/include/spine/Vector.h b/spine-cpp/spine-cpp/include/spine/Vector.h index 538fab273..7c7dc3394 100644 --- a/spine-cpp/spine-cpp/include/spine/Vector.h +++ b/spine-cpp/spine-cpp/include/spine/Vector.h @@ -66,6 +66,7 @@ namespace Spine { clear(); deallocate(_buffer); + _buffer = NULL; _size = inVector._size; _capacity = inVector._capacity; @@ -194,6 +195,8 @@ namespace Spine void setSize(size_t inValue) { + assert(inValue <= _capacity); + _size = inValue; } diff --git a/spine-cpp/spine-cpp/src/spine/AnimationState.cpp b/spine-cpp/spine-cpp/src/spine/AnimationState.cpp index bf9f7107f..48e2485c9 100644 --- a/spine-cpp/spine-cpp/src/spine/AnimationState.cpp +++ b/spine-cpp/spine-cpp/src/spine/AnimationState.cpp @@ -230,7 +230,7 @@ namespace Spine _timelineDipMix.clear(); _timelinesRotation.clear(); - _onAnimationEventFunc = NULL; + _onAnimationEventFunc = dummyOnAnimationEventFunc; } EventQueueEntry::EventQueueEntry(EventType eventType, TrackEntry* trackEntry, Event* event) : diff --git a/spine-cpp/spine-cpp/src/spine/Bone.cpp b/spine-cpp/spine-cpp/src/spine/Bone.cpp index 71e119c95..14ffbf850 100644 --- a/spine-cpp/spine-cpp/src/spine/Bone.cpp +++ b/spine-cpp/spine-cpp/src/spine/Bone.cpp @@ -521,31 +521,61 @@ namespace Spine return _a; } + void Bone::setA(float inValue) + { + _a = inValue; + } + float Bone::getB() { return _b; } + void Bone::setB(float inValue) + { + _b = inValue; + } + float Bone::getC() { return _c; } + void Bone::setC(float inValue) + { + _c = inValue; + } + float Bone::getD() { return _d; } + void Bone::setD(float inValue) + { + _d = inValue; + } + float Bone::getWorldX() { return _worldX; } + void Bone::setWorldX(float inValue) + { + _worldX = inValue; + } + float Bone::getWorldY() { return _worldY; } + void Bone::setWorldY(float inValue) + { + _worldY = inValue; + } + float Bone::getWorldRotationX() { return MathUtil::atan2(_c, _a) * RadDeg; diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonClipping.cpp b/spine-cpp/spine-cpp/src/spine/SkeletonClipping.cpp index 6a9f516a3..69e7a958f 100644 --- a/spine-cpp/spine-cpp/src/spine/SkeletonClipping.cpp +++ b/spine-cpp/spine-cpp/src/spine/SkeletonClipping.cpp @@ -54,6 +54,7 @@ namespace Spine int n = clip->getWorldVerticesLength(); _clippingPolygon.reserve(n); + _clippingPolygon.setSize(n); clip->computeWorldVertices(slot, 0, n, _clippingPolygon, 0, 2); makeClockwise(_clippingPolygon); Vector< Vector* > clippingPolygons = _triangulator.decompose(_clippingPolygon, _triangulator.triangulate(_clippingPolygon)); @@ -96,7 +97,8 @@ namespace Spine void SkeletonClipping::clipTriangles(Vector& vertices, int verticesLength, Vector& triangles, int trianglesLength, Vector& uvs) { - Vector& clipOutput = _clipOutput, clippedVertices = _clippedVertices; + Vector& clipOutput = _clipOutput; + Vector& clippedVertices = _clippedVertices; Vector& clippedTriangles = _clippedTriangles; Vector< Vector* >& polygons = _clippingPolygons; int polygonsCount = static_cast(_clippingPolygons.size()); @@ -135,7 +137,9 @@ namespace Spine int clipOutputCount = clipOutputLength >> 1; clippedVertices.reserve(s + clipOutputCount * 2); + clippedVertices.setSize(s + clipOutputCount * 2); _clippedUVs.reserve(s + clipOutputCount * 2); + _clippedUVs.setSize(s + clipOutputCount * 2); for (int ii = 0; ii < clipOutputLength; ii += 2) { float x = clipOutput[ii], y = clipOutput[ii + 1]; @@ -152,6 +156,7 @@ namespace Spine s = static_cast(clippedTriangles.size()); clippedTriangles.reserve(s + 3 * (clipOutputCount - 2)); + clippedTriangles.setSize(s + 3 * (clipOutputCount - 2)); clipOutputCount--; for (int ii = 1; ii < clipOutputCount; ii++) { @@ -165,7 +170,9 @@ namespace Spine else { clippedVertices.reserve(s + 3 * 2); + clippedVertices.setSize(s + 3 * 2); _clippedUVs.reserve(s + 3 * 2); + _clippedUVs.setSize(s + 3 * 2); clippedVertices[s] = x1; clippedVertices[s + 1] = y1; clippedVertices[s + 2] = x2; @@ -182,6 +189,7 @@ namespace Spine s = static_cast(clippedTriangles.size()); clippedTriangles.reserve(s + 3); + clippedTriangles.setSize(s + 3); clippedTriangles[s] = index; clippedTriangles[s + 1] = index + 1; clippedTriangles[s + 2] = index + 2; @@ -197,9 +205,24 @@ namespace Spine return _clipAttachment != NULL; } + Vector& SkeletonClipping::getClippedVertices() + { + return _clippedVertices; + } + + Vector& SkeletonClipping::getClippedTriangles() + { + return _clippedTriangles; + } + + Vector& SkeletonClipping::getClippedUVs() + { + return _clippedUVs; + } + bool SkeletonClipping::clip(float x1, float y1, float x2, float y2, float x3, float y3, Vector& clippingArea, Vector& output) { - Vector originalOutput = output; + Vector& originalOutput = output; bool clipped = false; // Avoid copy at the end. @@ -225,7 +248,7 @@ namespace Spine input.push_back(y1); output.clear(); - Vector clippingVertices = clippingArea; + Vector& clippingVertices = clippingArea; int clippingVerticesLast = static_cast(clippingArea.size()) - 4; for (int i = 0; ; i += 2) { @@ -233,7 +256,7 @@ namespace Spine float edgeX2 = clippingVertices[i + 2], edgeY2 = clippingVertices[i + 3]; float deltaX = edgeX - edgeX2, deltaY = edgeY - edgeY2; - Vector inputVertices = input; + Vector& inputVertices = input; int inputVerticesLength = static_cast(input.size()) - 2, outputStart = static_cast(output.size()); for (int ii = 0; ii < inputVerticesLength; ii += 2) { @@ -299,6 +322,7 @@ namespace Spine else { originalOutput.reserve(originalOutput.size() - 2); + originalOutput.setSize(originalOutput.size() - 2); } return clipped; From dfd540992205688800a854331a79ade00ffa9228 Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Fri, 8 Dec 2017 14:51:24 -0500 Subject: [PATCH 77/83] Improving Time Elapsed logic --- .../spine_unit_test/spine_unit_test/main.cpp | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/spine-cpp/spine-cpp-unit-tests/spine_unit_test/spine_unit_test/main.cpp b/spine-cpp/spine-cpp-unit-tests/spine_unit_test/spine_unit_test/main.cpp index 05b091cae..5ed9971da 100644 --- a/spine-cpp/spine-cpp-unit-tests/spine_unit_test/spine_unit_test/main.cpp +++ b/spine-cpp/spine-cpp-unit-tests/spine_unit_test/spine_unit_test/main.cpp @@ -86,13 +86,18 @@ KanjiSpineExtension::KanjiSpineExtension() : DefaultSpineExtension() // Empty } +double timeNow() +{ + timespec lTimeVal; + clock_gettime(CLOCK_MONOTONIC, &lTimeVal); + return lTimeVal.tv_sec + (lTimeVal.tv_nsec * 1.0e-9); +} + int main(int argc, char* argv[]) { SpineExtension::setInstance(KanjiSpineExtension::getInstance()); - // Start Timing - time_t start_time, end_time; - time(&start_time); + double startTime = timeNow(); /* Set working directory to current location for opening test data */ #ifdef WIN32 @@ -105,9 +110,10 @@ int main(int argc, char* argv[]) MemoryTest::test(); // End Timing - time(&end_time); - double secs = difftime(end_time,start_time); - printf("\n\n%i minutes and %i seconds of your life taken from you by these tests.\n", ((int)secs) / 60, ((int)secs) % 60); + double endTime = timeNow(); + double timeElapsed = (endTime - startTime); + printf("\n\n%i minutes and %i seconds of your life taken from you by these tests.\n", ((int)timeElapsed) / 60, ((int)timeElapsed) % 60); + printf("timeElapsed: %f \n", timeElapsed); return 0; } From 89ad68c27a141d40d1053174ad695c90aecf165e Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Fri, 8 Dec 2017 16:20:21 -0500 Subject: [PATCH 78/83] Failed to build on Ubuntu until I added these cstring includes. Xcode and Visual Studio are building fine though! --- spine-cpp/spine-cpp/src/spine/Extension.cpp | 1 + spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp | 2 ++ spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp | 2 ++ 3 files changed, 5 insertions(+) diff --git a/spine-cpp/spine-cpp/src/spine/Extension.cpp b/spine-cpp/spine-cpp/src/spine/Extension.cpp index 81c667104..5cfe0b3ab 100644 --- a/spine-cpp/spine-cpp/src/spine/Extension.cpp +++ b/spine-cpp/spine-cpp/src/spine/Extension.cpp @@ -32,6 +32,7 @@ #include #include +#include namespace Spine { diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp b/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp index 5cbd1b5ef..16c44cee2 100644 --- a/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp +++ b/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp @@ -78,6 +78,8 @@ #include #include +#include + namespace Spine { const int SkeletonBinary::BONE_ROTATE = 0; diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp b/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp index b24d48513..2642e069d 100644 --- a/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp +++ b/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp @@ -79,6 +79,8 @@ #include #include +#include + #if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__) #define strdup _strdup #endif From c7ae6d23b1c9cd9d6475e7fd5c7fa4f53f37f846 Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Sat, 9 Dec 2017 15:09:36 -0500 Subject: [PATCH 79/83] Fixing a bug in Pool class. --- spine-cpp/spine-cpp/include/spine/Pool.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spine-cpp/spine-cpp/include/spine/Pool.h b/spine-cpp/spine-cpp/include/spine/Pool.h index 6114dd748..963fd6b55 100644 --- a/spine-cpp/spine-cpp/include/spine/Pool.h +++ b/spine-cpp/spine-cpp/include/spine/Pool.h @@ -56,9 +56,10 @@ namespace Spine if (_objects.size() > 0) { T** object = _objects.begin(); + T* ret = *object; _objects.erase(0); - return *object; + return ret; } else { From 64fd7c28866abc880b454a6b1bd6268aba20fdf1 Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Tue, 12 Dec 2017 10:51:11 -0500 Subject: [PATCH 80/83] Moving Braces to Same Line --- spine-cpp/spine-cpp/include/spine/Animation.h | 3 +- .../spine-cpp/include/spine/AnimationState.h | 15 +- .../include/spine/AnimationStateData.h | 9 +- spine-cpp/spine-cpp/include/spine/Atlas.h | 21 +- .../include/spine/AtlasAttachmentLoader.h | 3 +- .../spine-cpp/include/spine/Attachment.h | 3 +- .../include/spine/AttachmentLoader.h | 3 +- .../include/spine/AttachmentTimeline.h | 3 +- .../spine-cpp/include/spine/AttachmentType.h | 3 +- spine-cpp/spine-cpp/include/spine/BlendMode.h | 3 +- spine-cpp/spine-cpp/include/spine/Bone.h | 3 +- spine-cpp/spine-cpp/include/spine/BoneData.h | 3 +- .../include/spine/BoundingBoxAttachment.h | 3 +- .../include/spine/ClippingAttachment.h | 3 +- .../spine-cpp/include/spine/ColorTimeline.h | 3 +- .../spine-cpp/include/spine/Constraint.h | 3 +- .../spine-cpp/include/spine/ContainerUtil.h | 45 +- .../spine-cpp/include/spine/CurveTimeline.h | 3 +- .../spine-cpp/include/spine/DeformTimeline.h | 3 +- .../include/spine/DrawOrderTimeline.h | 3 +- spine-cpp/spine-cpp/include/spine/Event.h | 3 +- spine-cpp/spine-cpp/include/spine/EventData.h | 3 +- .../spine-cpp/include/spine/EventTimeline.h | 3 +- spine-cpp/spine-cpp/include/spine/Extension.h | 6 +- spine-cpp/spine-cpp/include/spine/HashMap.h | 138 ++--- .../spine-cpp/include/spine/IkConstraint.h | 3 +- .../include/spine/IkConstraintData.h | 3 +- .../include/spine/IkConstraintTimeline.h | 3 +- spine-cpp/spine-cpp/include/spine/Json.h | 3 +- .../spine-cpp/include/spine/LinkedMesh.h | 3 +- spine-cpp/spine-cpp/include/spine/MathUtil.h | 18 +- .../spine-cpp/include/spine/MeshAttachment.h | 3 +- .../spine-cpp/include/spine/MixDirection.h | 3 +- spine-cpp/spine-cpp/include/spine/MixPose.h | 3 +- .../spine-cpp/include/spine/PathAttachment.h | 3 +- .../spine-cpp/include/spine/PathConstraint.h | 3 +- .../include/spine/PathConstraintData.h | 3 +- .../include/spine/PathConstraintMixTimeline.h | 3 +- .../spine/PathConstraintPositionTimeline.h | 3 +- .../spine/PathConstraintSpacingTimeline.h | 3 +- .../spine-cpp/include/spine/PointAttachment.h | 3 +- spine-cpp/spine-cpp/include/spine/Pool.h | 24 +- .../spine-cpp/include/spine/PositionMode.h | 3 +- spine-cpp/spine-cpp/include/spine/RTTI.h | 3 +- .../include/spine/RegionAttachment.h | 3 +- .../spine-cpp/include/spine/RotateMode.h | 3 +- .../spine-cpp/include/spine/RotateTimeline.h | 3 +- .../spine-cpp/include/spine/ScaleTimeline.h | 3 +- .../spine-cpp/include/spine/ShearTimeline.h | 3 +- spine-cpp/spine-cpp/include/spine/Skeleton.h | 3 +- .../spine-cpp/include/spine/SkeletonBinary.h | 6 +- .../spine-cpp/include/spine/SkeletonBounds.h | 9 +- .../include/spine/SkeletonClipping.h | 3 +- .../spine-cpp/include/spine/SkeletonData.h | 3 +- .../spine-cpp/include/spine/SkeletonJson.h | 3 +- spine-cpp/spine-cpp/include/spine/Skin.h | 9 +- spine-cpp/spine-cpp/include/spine/Slot.h | 3 +- spine-cpp/spine-cpp/include/spine/SlotData.h | 3 +- .../spine-cpp/include/spine/SpacingMode.h | 3 +- .../spine-cpp/include/spine/TextureLoader.h | 3 +- spine-cpp/spine-cpp/include/spine/Timeline.h | 3 +- .../spine-cpp/include/spine/TimelineType.h | 3 +- .../include/spine/TransformConstraint.h | 3 +- .../include/spine/TransformConstraintData.h | 3 +- .../spine/TransformConstraintTimeline.h | 3 +- .../spine-cpp/include/spine/TransformMode.h | 3 +- .../include/spine/TranslateTimeline.h | 3 +- .../spine-cpp/include/spine/Triangulator.h | 3 +- .../include/spine/TwoColorTimeline.h | 3 +- spine-cpp/spine-cpp/include/spine/Updatable.h | 3 +- spine-cpp/spine-cpp/include/spine/Vector.h | 129 ++-- .../include/spine/VertexAttachment.h | 3 +- spine-cpp/spine-cpp/include/spine/Vertices.h | 3 +- spine-cpp/spine-cpp/src/spine/Animation.cpp | 78 +-- .../spine-cpp/src/spine/AnimationState.cpp | 463 +++++--------- .../src/spine/AnimationStateData.cpp | 39 +- spine-cpp/spine-cpp/src/spine/Atlas.cpp | 150 ++--- .../src/spine/AtlasAttachmentLoader.cpp | 30 +- spine-cpp/spine-cpp/src/spine/Attachment.cpp | 6 +- .../spine-cpp/src/spine/AttachmentLoader.cpp | 6 +- .../src/spine/AttachmentTimeline.cpp | 52 +- spine-cpp/spine-cpp/src/spine/Bone.cpp | 246 +++----- spine-cpp/spine-cpp/src/spine/BoneData.cpp | 66 +- .../src/spine/BoundingBoxAttachment.cpp | 3 +- .../src/spine/ClippingAttachment.cpp | 9 +- .../spine-cpp/src/spine/ColorTimeline.cpp | 48 +- spine-cpp/spine-cpp/src/spine/Constraint.cpp | 6 +- .../spine-cpp/src/spine/CurveTimeline.cpp | 42 +- .../spine-cpp/src/spine/DeformTimeline.cpp | 126 ++-- .../spine-cpp/src/spine/DrawOrderTimeline.cpp | 63 +- spine-cpp/spine-cpp/src/spine/Event.cpp | 27 +- spine-cpp/spine-cpp/src/spine/EventData.cpp | 24 +- .../spine-cpp/src/spine/EventTimeline.cpp | 46 +- spine-cpp/spine-cpp/src/spine/Extension.cpp | 39 +- .../spine-cpp/src/spine/IkConstraint.cpp | 141 ++--- .../spine-cpp/src/spine/IkConstraintData.cpp | 33 +- .../src/spine/IkConstraintTimeline.cpp | 39 +- spine-cpp/spine-cpp/src/spine/Json.cpp | 261 +++----- spine-cpp/spine-cpp/src/spine/LinkedMesh.cpp | 3 +- spine-cpp/spine-cpp/src/spine/MathUtil.cpp | 39 +- .../spine-cpp/src/spine/MeshAttachment.cpp | 183 ++---- .../spine-cpp/src/spine/PathAttachment.cpp | 21 +- .../spine-cpp/src/spine/PathConstraint.cpp | 258 +++----- .../src/spine/PathConstraintData.cpp | 69 +-- .../src/spine/PathConstraintMixTimeline.cpp | 30 +- .../spine/PathConstraintPositionTimeline.cpp | 31 +- .../spine/PathConstraintSpacingTimeline.cpp | 28 +- .../spine-cpp/src/spine/PointAttachment.cpp | 27 +- spine-cpp/spine-cpp/src/spine/RTTI.cpp | 21 +- .../spine-cpp/src/spine/RegionAttachment.cpp | 138 ++--- .../spine-cpp/src/spine/RotateTimeline.cpp | 54 +- .../spine-cpp/src/spine/ScaleTimeline.cpp | 39 +- .../spine-cpp/src/spine/ShearTimeline.cpp | 27 +- spine-cpp/spine-cpp/src/spine/Skeleton.cpp | 399 +++++-------- .../spine-cpp/src/spine/SkeletonBinary.cpp | 498 ++++++---------- .../spine-cpp/src/spine/SkeletonBounds.cpp | 114 ++-- .../spine-cpp/src/spine/SkeletonClipping.cpp | 111 ++-- .../spine-cpp/src/spine/SkeletonData.cpp | 129 ++-- .../spine-cpp/src/spine/SkeletonJson.cpp | 564 ++++++------------ spine-cpp/spine-cpp/src/spine/Skin.cpp | 57 +- spine-cpp/spine-cpp/src/spine/Slot.cpp | 90 +-- spine-cpp/spine-cpp/src/spine/SlotData.cpp | 72 +-- .../spine-cpp/src/spine/TextureLoader.cpp | 6 +- spine-cpp/spine-cpp/src/spine/Timeline.cpp | 6 +- .../src/spine/TransformConstraint.cpp | 201 +++---- .../src/spine/TransformConstraintData.cpp | 51 +- .../src/spine/TransformConstraintTimeline.cpp | 30 +- .../spine-cpp/src/spine/TranslateTimeline.cpp | 30 +- .../spine-cpp/src/spine/Triangulator.cpp | 108 ++-- .../spine-cpp/src/spine/TwoColorTimeline.cpp | 42 +- spine-cpp/spine-cpp/src/spine/Updatable.cpp | 6 +- .../spine-cpp/src/spine/VertexAttachment.cpp | 66 +- 132 files changed, 2071 insertions(+), 4132 deletions(-) diff --git a/spine-cpp/spine-cpp/include/spine/Animation.h b/spine-cpp/spine-cpp/include/spine/Animation.h index 9f0ca70ef..fa674382e 100644 --- a/spine-cpp/spine-cpp/include/spine/Animation.h +++ b/spine-cpp/spine-cpp/include/spine/Animation.h @@ -43,8 +43,7 @@ namespace Spine class Skeleton; class Event; - class Animation - { + class Animation { friend class AnimationState; friend class TrackEntry; friend class AnimationStateData; diff --git a/spine-cpp/spine-cpp/include/spine/AnimationState.h b/spine-cpp/spine-cpp/include/spine/AnimationState.h index 09821da5b..4e81c40d3 100644 --- a/spine-cpp/spine-cpp/include/spine/AnimationState.h +++ b/spine-cpp/spine-cpp/include/spine/AnimationState.h @@ -37,8 +37,7 @@ namespace Spine { - enum EventType - { + enum EventType { EventType_Start, EventType_Interrupt, EventType_End, @@ -59,8 +58,7 @@ namespace Spine typedef void (*OnAnimationEventFunc) (AnimationState* state, EventType type, TrackEntry* entry, Event* event); /// State for the playback of an animation - class TrackEntry - { + class TrackEntry { friend class EventQueue; friend class AnimationState; @@ -241,8 +239,7 @@ namespace Spine void reset(); }; - class EventQueueEntry - { + class EventQueueEntry { friend class EventQueue; public: @@ -253,8 +250,7 @@ namespace Spine EventQueueEntry(EventType eventType, TrackEntry* trackEntry, Event* event = NULL); }; - class EventQueue - { + class EventQueue { friend class AnimationState; private: @@ -287,8 +283,7 @@ namespace Spine void drain(); }; - class AnimationState - { + class AnimationState { friend class TrackEntry; friend class EventQueue; diff --git a/spine-cpp/spine-cpp/include/spine/AnimationStateData.h b/spine-cpp/spine-cpp/include/spine/AnimationStateData.h index 952b33256..c2befdd01 100644 --- a/spine-cpp/spine-cpp/include/spine/AnimationStateData.h +++ b/spine-cpp/spine-cpp/include/spine/AnimationStateData.h @@ -42,8 +42,7 @@ namespace Spine class Animation; /// Stores mix (crossfade) durations to be applied when AnimationState animations are changed. - class AnimationStateData - { + class AnimationStateData { friend class AnimationState; public: @@ -70,8 +69,7 @@ namespace Spine float getMix(Animation* from, Animation* to); private: - class AnimationPair - { + class AnimationPair { public: Animation* _a1; Animation* _a2; @@ -81,8 +79,7 @@ namespace Spine bool operator==(const AnimationPair &other) const; }; - struct HashAnimationPair - { + struct HashAnimationPair { std::size_t operator()(const Spine::AnimationStateData::AnimationPair& val) const; }; diff --git a/spine-cpp/spine-cpp/include/spine/Atlas.h b/spine-cpp/spine-cpp/include/spine/Atlas.h index eb9150cff..606a35faa 100644 --- a/spine-cpp/spine-cpp/include/spine/Atlas.h +++ b/spine-cpp/spine-cpp/include/spine/Atlas.h @@ -38,8 +38,7 @@ namespace Spine { - enum Format - { + enum Format { Format_Alpha, Format_Intensity, Format_LuminanceAlpha, @@ -49,8 +48,7 @@ namespace Spine Format_RGBA8888 }; - enum TextureFilter - { + enum TextureFilter { TextureFilter_Nearest, TextureFilter_Linear, TextureFilter_MipMap, @@ -60,15 +58,13 @@ namespace Spine TextureFilter_MipMapLinearLinear }; - enum TextureWrap - { + enum TextureWrap { TextureWrap_MirroredRepeat, TextureWrap_ClampToEdge, TextureWrap_Repeat }; - class AtlasPage - { + class AtlasPage { public: std::string name; Format format; @@ -82,8 +78,7 @@ namespace Spine AtlasPage(std::string inName) : name(inName) {} }; - class AtlasRegion - { + class AtlasRegion { public: AtlasPage* page; std::string name; @@ -99,8 +94,7 @@ namespace Spine class TextureLoader; - class Atlas - { + class Atlas { public: Atlas(const char* path, TextureLoader& textureLoader); @@ -124,8 +118,7 @@ namespace Spine void load(const char* begin, int length, const char* dir); - class Str - { + class Str { public: const char* begin; const char* end; diff --git a/spine-cpp/spine-cpp/include/spine/AtlasAttachmentLoader.h b/spine-cpp/spine-cpp/include/spine/AtlasAttachmentLoader.h index 440b5ac5b..2052bb69b 100644 --- a/spine-cpp/spine-cpp/include/spine/AtlasAttachmentLoader.h +++ b/spine-cpp/spine-cpp/include/spine/AtlasAttachmentLoader.h @@ -44,8 +44,7 @@ namespace Spine /// An AttachmentLoader that configures attachments using texture regions from an Atlas. /// See http://esotericsoftware.com/spine-loading-skeleton-data#JSON-and-binary-data about Loading Skeleton Data in the Spine Runtimes Guide. /// - class AtlasAttachmentLoader : public AttachmentLoader - { + class AtlasAttachmentLoader : public AttachmentLoader { RTTI_DECL; public: diff --git a/spine-cpp/spine-cpp/include/spine/Attachment.h b/spine-cpp/spine-cpp/include/spine/Attachment.h index fdf5a1a58..35ae099b7 100644 --- a/spine-cpp/spine-cpp/include/spine/Attachment.h +++ b/spine-cpp/spine-cpp/include/spine/Attachment.h @@ -37,8 +37,7 @@ namespace Spine { - class Attachment - { + class Attachment { RTTI_DECL; public: diff --git a/spine-cpp/spine-cpp/include/spine/AttachmentLoader.h b/spine-cpp/spine-cpp/include/spine/AttachmentLoader.h index 91f59705e..1da82e4f7 100644 --- a/spine-cpp/spine-cpp/include/spine/AttachmentLoader.h +++ b/spine-cpp/spine-cpp/include/spine/AttachmentLoader.h @@ -45,8 +45,7 @@ namespace Spine class PointAttachment; class ClippingAttachment; - class AttachmentLoader - { + class AttachmentLoader { RTTI_DECL; AttachmentLoader(); diff --git a/spine-cpp/spine-cpp/include/spine/AttachmentTimeline.h b/spine-cpp/spine-cpp/include/spine/AttachmentTimeline.h index 6fca8296c..c0a1fad41 100644 --- a/spine-cpp/spine-cpp/include/spine/AttachmentTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/AttachmentTimeline.h @@ -44,8 +44,7 @@ namespace Spine class Skeleton; class Event; - class AttachmentTimeline : public Timeline - { + class AttachmentTimeline : public Timeline { friend class SkeletonBinary; friend class SkeletonJson; diff --git a/spine-cpp/spine-cpp/include/spine/AttachmentType.h b/spine-cpp/spine-cpp/include/spine/AttachmentType.h index 3799207cd..1ad7a4d62 100644 --- a/spine-cpp/spine-cpp/include/spine/AttachmentType.h +++ b/spine-cpp/spine-cpp/include/spine/AttachmentType.h @@ -33,8 +33,7 @@ namespace Spine { - enum AttachmentType - { + enum AttachmentType { AttachmentType_Region, AttachmentType_Boundingbox, AttachmentType_Mesh, diff --git a/spine-cpp/spine-cpp/include/spine/BlendMode.h b/spine-cpp/spine-cpp/include/spine/BlendMode.h index 0f0afa645..d61fcdd77 100644 --- a/spine-cpp/spine-cpp/include/spine/BlendMode.h +++ b/spine-cpp/spine-cpp/include/spine/BlendMode.h @@ -33,8 +33,7 @@ namespace Spine { - enum BlendMode - { + enum BlendMode { BlendMode_Normal = 0, BlendMode_Additive, BlendMode_Multiply, diff --git a/spine-cpp/spine-cpp/include/spine/Bone.h b/spine-cpp/spine-cpp/include/spine/Bone.h index c7f1c7bf6..4413be97d 100644 --- a/spine-cpp/spine-cpp/include/spine/Bone.h +++ b/spine-cpp/spine-cpp/include/spine/Bone.h @@ -45,8 +45,7 @@ namespace Spine /// A bone has a local transform which is used to compute its world transform. A bone also has an applied transform, which is a /// local transform that can be applied to compute the world transform. The local transform and applied transform may differ if a /// constraint or application code modifies the world transform after it was computed from the local transform. - class Bone : public Updatable - { + class Bone : public Updatable { friend class AnimationState; friend class RotateTimeline; diff --git a/spine-cpp/spine-cpp/include/spine/BoneData.h b/spine-cpp/spine-cpp/include/spine/BoneData.h index 040696871..4825ed4fe 100644 --- a/spine-cpp/spine-cpp/include/spine/BoneData.h +++ b/spine-cpp/spine-cpp/include/spine/BoneData.h @@ -37,8 +37,7 @@ namespace Spine { - class BoneData - { + class BoneData { friend class SkeletonBinary; friend class SkeletonJson; diff --git a/spine-cpp/spine-cpp/include/spine/BoundingBoxAttachment.h b/spine-cpp/spine-cpp/include/spine/BoundingBoxAttachment.h index 996af9f94..aef2b7c47 100644 --- a/spine-cpp/spine-cpp/include/spine/BoundingBoxAttachment.h +++ b/spine-cpp/spine-cpp/include/spine/BoundingBoxAttachment.h @@ -36,8 +36,7 @@ namespace Spine { /// Attachment that has a polygon for bounds checking. - class BoundingBoxAttachment : public VertexAttachment - { + class BoundingBoxAttachment : public VertexAttachment { RTTI_DECL; BoundingBoxAttachment(std::string name); diff --git a/spine-cpp/spine-cpp/include/spine/ClippingAttachment.h b/spine-cpp/spine-cpp/include/spine/ClippingAttachment.h index bbf784429..8740407b3 100644 --- a/spine-cpp/spine-cpp/include/spine/ClippingAttachment.h +++ b/spine-cpp/spine-cpp/include/spine/ClippingAttachment.h @@ -37,8 +37,7 @@ namespace Spine { class SlotData; - class ClippingAttachment : public VertexAttachment - { + class ClippingAttachment : public VertexAttachment { friend class SkeletonBinary; friend class SkeletonJson; diff --git a/spine-cpp/spine-cpp/include/spine/ColorTimeline.h b/spine-cpp/spine-cpp/include/spine/ColorTimeline.h index 740743134..03295baff 100644 --- a/spine-cpp/spine-cpp/include/spine/ColorTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/ColorTimeline.h @@ -35,8 +35,7 @@ namespace Spine { - class ColorTimeline : public CurveTimeline - { + class ColorTimeline : public CurveTimeline { friend class SkeletonBinary; friend class SkeletonJson; diff --git a/spine-cpp/spine-cpp/include/spine/Constraint.h b/spine-cpp/spine-cpp/include/spine/Constraint.h index aa0122c34..ced362987 100644 --- a/spine-cpp/spine-cpp/include/spine/Constraint.h +++ b/spine-cpp/spine-cpp/include/spine/Constraint.h @@ -36,8 +36,7 @@ namespace Spine { /// The interface for all constraints. - class Constraint : public Updatable - { + class Constraint : public Updatable { RTTI_DECL; public: diff --git a/spine-cpp/spine-cpp/include/spine/ContainerUtil.h b/spine-cpp/spine-cpp/include/spine/ContainerUtil.h index 053a56634..c44c18817 100644 --- a/spine-cpp/spine-cpp/include/spine/ContainerUtil.h +++ b/spine-cpp/spine-cpp/include/spine/ContainerUtil.h @@ -40,22 +40,18 @@ namespace Spine { - class ContainerUtil - { + class ContainerUtil { public: /// Finds an item by comparing each item's name. /// It is more efficient to cache the results of this method than to call it multiple times. /// @return May be NULL. template - static T* findWithName(Vector& items, std::string name) - { + static T* findWithName(Vector& items, std::string name) { assert(name.length() > 0); - for (T** i = items.begin(); i != items.end(); ++i) - { + for (T** i = items.begin(); i != items.end(); ++i) { T* item = (*i); - if (item->getName() == name) - { + if (item->getName() == name) { return item; } } @@ -65,15 +61,12 @@ namespace Spine /// @return -1 if the item was not found. template - static int findIndexWithName(Vector& items, std::string name) - { + static int findIndexWithName(Vector& items, std::string name) { assert(name.length() > 0); - for (size_t i = 0, len = items.size(); i < len; ++i) - { + for (size_t i = 0, len = items.size(); i < len; ++i) { T* item = items[i]; - if (item->getName() == name) - { + if (item->getName() == name) { return static_cast(i); } } @@ -85,15 +78,12 @@ namespace Spine /// It is more efficient to cache the results of this method than to call it multiple times. /// @return May be NULL. template - static T* findWithDataName(Vector& items, std::string name) - { + static T* findWithDataName(Vector& items, std::string name) { assert(name.length() > 0); - for (T** i = items.begin(); i != items.end(); ++i) - { + for (T** i = items.begin(); i != items.end(); ++i) { T* item = (*i); - if (item->getData().getName() == name) - { + if (item->getData().getName() == name) { return item; } } @@ -103,15 +93,12 @@ namespace Spine /// @return -1 if the item was not found. template - static int findIndexWithDataName(Vector& items, std::string name) - { + static int findIndexWithDataName(Vector& items, std::string name) { assert(name.length() > 0); - for (size_t i = 0, len = items.size(); i < len; ++i) - { + for (size_t i = 0, len = items.size(); i < len; ++i) { T* item = items[i]; - if (item->getData().getName() == name) - { + if (item->getData().getName() == name) { return static_cast(i); } } @@ -120,10 +107,8 @@ namespace Spine } template - static void cleanUpVectorOfPointers(Vector& items) - { - for (size_t i = 0; i < items.size(); ) - { + static void cleanUpVectorOfPointers(Vector& items) { + for (size_t i = 0; i < items.size(); ) { T* item = items[i]; DESTROY(T, item); diff --git a/spine-cpp/spine-cpp/include/spine/CurveTimeline.h b/spine-cpp/spine-cpp/include/spine/CurveTimeline.h index 45854a7a0..286d53c4a 100644 --- a/spine-cpp/spine-cpp/include/spine/CurveTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/CurveTimeline.h @@ -39,8 +39,7 @@ namespace Spine { /// Base class for frames that use an interpolation bezier curve. - class CurveTimeline : public Timeline - { + class CurveTimeline : public Timeline { RTTI_DECL; public: diff --git a/spine-cpp/spine-cpp/include/spine/DeformTimeline.h b/spine-cpp/spine-cpp/include/spine/DeformTimeline.h index b601ca9f9..7510ce509 100644 --- a/spine-cpp/spine-cpp/include/spine/DeformTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/DeformTimeline.h @@ -37,8 +37,7 @@ namespace Spine { class VertexAttachment; - class DeformTimeline : public CurveTimeline - { + class DeformTimeline : public CurveTimeline { friend class SkeletonBinary; friend class SkeletonJson; diff --git a/spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h b/spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h index 4d1adc00c..e11d74c0f 100644 --- a/spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h @@ -35,8 +35,7 @@ namespace Spine { - class DrawOrderTimeline : public Timeline - { + class DrawOrderTimeline : public Timeline { friend class SkeletonBinary; friend class SkeletonJson; diff --git a/spine-cpp/spine-cpp/include/spine/Event.h b/spine-cpp/spine-cpp/include/spine/Event.h index 7c7330744..9956d9030 100644 --- a/spine-cpp/spine-cpp/include/spine/Event.h +++ b/spine-cpp/spine-cpp/include/spine/Event.h @@ -38,8 +38,7 @@ namespace Spine class EventData; /// Stores the current pose values for an Event. - class Event - { + class Event { friend class SkeletonBinary; friend class SkeletonJson; friend class AnimationState; diff --git a/spine-cpp/spine-cpp/include/spine/EventData.h b/spine-cpp/spine-cpp/include/spine/EventData.h index acc4c9fec..dcb0c774c 100644 --- a/spine-cpp/spine-cpp/include/spine/EventData.h +++ b/spine-cpp/spine-cpp/include/spine/EventData.h @@ -36,8 +36,7 @@ namespace Spine { /// Stores the setup pose values for an Event. - class EventData - { + class EventData { friend class SkeletonBinary; friend class SkeletonJson; friend class Event; diff --git a/spine-cpp/spine-cpp/include/spine/EventTimeline.h b/spine-cpp/spine-cpp/include/spine/EventTimeline.h index 5fb6fd5e9..f474e637b 100644 --- a/spine-cpp/spine-cpp/include/spine/EventTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/EventTimeline.h @@ -35,8 +35,7 @@ namespace Spine { - class EventTimeline : public Timeline - { + class EventTimeline : public Timeline { friend class SkeletonBinary; friend class SkeletonJson; diff --git a/spine-cpp/spine-cpp/include/spine/Extension.h b/spine-cpp/spine-cpp/include/spine/Extension.h index 6c3a3f9c4..0a9379308 100644 --- a/spine-cpp/spine-cpp/include/spine/Extension.h +++ b/spine-cpp/spine-cpp/include/spine/Extension.h @@ -49,8 +49,7 @@ namespace Spine { - class SpineExtension - { + class SpineExtension { public: static void setInstance(SpineExtension* inSpineExtension); @@ -77,8 +76,7 @@ namespace Spine static SpineExtension* _instance; }; - class DefaultSpineExtension : public SpineExtension - { + class DefaultSpineExtension : public SpineExtension { public: static DefaultSpineExtension* getInstance(); diff --git a/spine-cpp/spine-cpp/include/spine/HashMap.h b/spine-cpp/spine-cpp/include/spine/HashMap.h index aab044374..e32cf4e30 100755 --- a/spine-cpp/spine-cpp/include/spine/HashMap.h +++ b/spine-cpp/spine-cpp/include/spine/HashMap.h @@ -37,51 +37,42 @@ namespace Spine { template - class HashMap - { + class HashMap { private: class Entry; public: - class Iterator - { + class Iterator { friend class HashMap; public: - Iterator(Entry* entry = NULL) : _entry(entry) - { + Iterator(Entry* entry = NULL) : _entry(entry) { // Empty } - Iterator& operator++() - { + Iterator& operator++() { _entry = _entry->next; return *this; } - Iterator& operator--() - { + Iterator& operator--() { _entry = _entry->prev; return *this; } - bool operator==(const Iterator& p) const - { + bool operator==(const Iterator& p) const { return _entry == p._entry; } - bool operator!=(const Iterator& p) const - { + bool operator!=(const Iterator& p) const { return _entry != p._entry; } - K& first() - { + K& first() { return _entry->_key; } - V& second() - { + V& second() { return _entry->_value; } @@ -94,11 +85,9 @@ namespace Spine _capacity(capacity), _header(), _trailer(), - _hashSize(0) - { + _hashSize(0) { _hashTable.reserve(capacity); - for (int i = 0; i < _capacity; ++i) - { + for (int i = 0; i < _capacity; ++i) { _hashTable.push_back(Entry()); } @@ -108,42 +97,34 @@ namespace Spine _trailer.next = &_trailer; } - ~HashMap() - { + ~HashMap() { _hashSize = 0; } - size_t size() - { + size_t size() { return _hashSize; } - Iterator begin() - { + Iterator begin() { return Iterator(_header.next); } - Iterator end() - { + Iterator end() { return Iterator(&_trailer); } - Iterator rbegin() - { + Iterator rbegin() { return Iterator(_trailer.prev); } - Iterator rend() - { + Iterator rend() { return Iterator(_header); } - std::pair insert(const K& key, const V& value) - { + std::pair insert(const K& key, const V& value) { Iterator iter = find(key); - if (iter._entry != &_trailer) - { + if (iter._entry != &_trailer) { return std::make_pair(iter, false); } @@ -156,8 +137,7 @@ namespace Spine _hashSize++; - if (_header.next == (&_trailer)) - { + if (_header.next == (&_trailer)) { _hashTable[index].next = entry; _hashTable[index].prev = entry; _header.next = entry; @@ -168,19 +148,16 @@ namespace Spine return std::make_pair(Iterator(entry), true); } - if (_hashTable[index].next == NULL) - { + if (_hashTable[index].next == NULL) { _hashTable[index].next = entry; _hashTable[index].prev = entry; - if (index < hash(_header.next->_key)) - { + if (index < hash(_header.next->_key)) { entry->next = _header.next; entry->prev = &_header; _header.next->prev = entry; _header.next = entry; } - else - { + else { entry->next = &_trailer; entry->prev = _trailer.prev; _trailer.prev = entry; @@ -190,16 +167,14 @@ namespace Spine return std::make_pair(Iterator(entry), true); } - if (index == hash(_header.next->_key)) - { + if (index == hash(_header.next->_key)) { _header.next = entry; entry->next = _hashTable[index].next; entry->prev = &_header; _hashTable[index].next->prev = entry; _hashTable[index].next = entry; } - else - { + else { entry->next = _hashTable[index].next; entry->prev = _hashTable[index].next->prev; entry->next->prev = entry; @@ -210,17 +185,13 @@ namespace Spine return std::make_pair(Iterator(entry), true); } - Iterator find(const K& key) - { + Iterator find(const K& key) { const size_t index = hash(key); Iterator iter(_hashTable[index].next); - if (iter._entry != NULL) - { - for ( ; hash(iter._entry->_key) == index ; ++iter) - { - if (iter._entry->_key == key) - { + if (iter._entry != NULL) { + for ( ; hash(iter._entry->_key) == index ; ++iter) { + if (iter._entry->_key == key) { return iter; } } @@ -229,71 +200,58 @@ namespace Spine return Iterator(&_trailer); } - Iterator erase(Iterator pos) - { - if (pos._entry != &_header && pos._entry != &_trailer) - { + Iterator erase(Iterator pos) { + if (pos._entry != &_header && pos._entry != &_trailer) { Entry* next = pos._entry->next; size_t index = hash(pos._entry->_key); - if (_hashTable[index].next == pos._entry && _hashTable[index].prev == pos._entry) - { + if (_hashTable[index].next == pos._entry && _hashTable[index].prev == pos._entry) { _hashTable[index].next = NULL; _hashTable[index].prev = NULL; - if (_header.next == pos._entry) - { + if (_header.next == pos._entry) { _header.next = pos._entry->next; pos._entry->next->prev = &_header; } - else if (_trailer.prev == pos._entry) - { + else if (_trailer.prev == pos._entry) { _trailer.prev = pos._entry->prev; pos._entry->prev->next = &_trailer; } - else - { + else { pos._entry->prev->next = pos._entry->next; pos._entry->next->prev = pos._entry->prev; } DESTROY(Entry, pos._entry); } - else if (_hashTable[index].next == pos._entry) - { + else if (_hashTable[index].next == pos._entry) { _hashTable[index].next = pos._entry->next; - if (_header.next == pos._entry) - { + if (_header.next == pos._entry) { _header.next = pos._entry->next; pos._entry->next->prev = &_header; } - else - { + else { pos._entry->prev->next = pos._entry->next; pos._entry->next->prev = pos._entry->prev; } DESTROY(Entry, pos._entry); } - else if (_hashTable[index].prev == pos._entry) - { + else if (_hashTable[index].prev == pos._entry) { _hashTable[index].prev = pos._entry->prev; - if (_trailer.prev == pos._entry) - { + if (_trailer.prev == pos._entry) { _trailer.prev = pos._entry->prev; pos._entry->prev->next = &_trailer; } - else - { + else { pos._entry->prev->next = pos._entry->next; pos._entry->next->prev = pos._entry->prev; } DESTROY(Entry, pos._entry); } - else - { + else { pos._entry->prev->next = pos._entry->next; pos._entry->next->prev = pos._entry->prev; @@ -308,12 +266,10 @@ namespace Spine return Iterator(&_trailer); } - V operator[](const K& key) - { + V operator[](const K& key) { Iterator iter = find(key); - if (iter._entry != _trailer) - { + if (iter._entry != _trailer) { return iter._entry->_value; } @@ -321,8 +277,7 @@ namespace Spine } private: - class Entry - { + class Entry { public: K _key; V _value; @@ -337,8 +292,7 @@ namespace Spine Entry _trailer; size_t _hashSize; - size_t hash(const K& key) - { + size_t hash(const K& key) { return _hashFunction(key) % _capacity; } }; diff --git a/spine-cpp/spine-cpp/include/spine/IkConstraint.h b/spine-cpp/spine-cpp/include/spine/IkConstraint.h index 387efb900..dbaf59786 100644 --- a/spine-cpp/spine-cpp/include/spine/IkConstraint.h +++ b/spine-cpp/spine-cpp/include/spine/IkConstraint.h @@ -41,8 +41,7 @@ namespace Spine class Skeleton; class Bone; - class IkConstraint : public Constraint - { + class IkConstraint : public Constraint { friend class Skeleton; friend class IkConstraintTimeline; diff --git a/spine-cpp/spine-cpp/include/spine/IkConstraintData.h b/spine-cpp/spine-cpp/include/spine/IkConstraintData.h index 5c4732dee..286bcddb2 100644 --- a/spine-cpp/spine-cpp/include/spine/IkConstraintData.h +++ b/spine-cpp/spine-cpp/include/spine/IkConstraintData.h @@ -39,8 +39,7 @@ namespace Spine { class BoneData; - class IkConstraintData - { + class IkConstraintData { friend class SkeletonBinary; friend class SkeletonJson; friend class IkConstraint; diff --git a/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h b/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h index 295bd1d9c..957fd9178 100644 --- a/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h @@ -35,8 +35,7 @@ namespace Spine { - class IkConstraintTimeline : public CurveTimeline - { + class IkConstraintTimeline : public CurveTimeline { friend class SkeletonBinary; friend class SkeletonJson; diff --git a/spine-cpp/spine-cpp/include/spine/Json.h b/spine-cpp/spine-cpp/include/spine/Json.h index 3cf273a1c..df73ddd4d 100644 --- a/spine-cpp/spine-cpp/include/spine/Json.h +++ b/spine-cpp/spine-cpp/include/spine/Json.h @@ -38,8 +38,7 @@ namespace Spine { - class Json - { + class Json { friend class SkeletonJson; public: diff --git a/spine-cpp/spine-cpp/include/spine/LinkedMesh.h b/spine-cpp/spine-cpp/include/spine/LinkedMesh.h index 56c7c46bf..136c53bb8 100644 --- a/spine-cpp/spine-cpp/include/spine/LinkedMesh.h +++ b/spine-cpp/spine-cpp/include/spine/LinkedMesh.h @@ -37,8 +37,7 @@ namespace Spine { class MeshAttachment; - class LinkedMesh - { + class LinkedMesh { friend class SkeletonBinary; friend class SkeletonJson; diff --git a/spine-cpp/spine-cpp/include/spine/MathUtil.h b/spine-cpp/spine-cpp/include/spine/MathUtil.h index 325b95d2a..cbd31b755 100644 --- a/spine-cpp/spine-cpp/include/spine/MathUtil.h +++ b/spine-cpp/spine-cpp/include/spine/MathUtil.h @@ -51,18 +51,15 @@ namespace Spine { template - int sign(T val) - { + int sign(T val) { return (T(0) < val) - (val < T(0)); } - inline bool areFloatsPracticallyEqual(float A, float B, float maxDiff = 0.0000000000000001f, float maxRelDiff = FLT_EPSILON) - { + inline bool areFloatsPracticallyEqual(float A, float B, float maxDiff = 0.0000000000000001f, float maxRelDiff = FLT_EPSILON) { // Check if the numbers are really close -- needed // when comparing numbers near zero. float diff = fabs(A - B); - if (diff <= maxDiff) - { + if (diff <= maxDiff) { return true; } @@ -71,21 +68,18 @@ namespace Spine float largest = (B > A) ? B : A; - if (diff <= largest * maxRelDiff) - { + if (diff <= largest * maxRelDiff) { return true; } return false; } - inline float clamp(float x, float lower, float upper) - { + inline float clamp(float x, float lower, float upper) { return fminf(upper, fmaxf(x, lower)); } - class MathUtil - { + class MathUtil { public: MathUtil(); diff --git a/spine-cpp/spine-cpp/include/spine/MeshAttachment.h b/spine-cpp/spine-cpp/include/spine/MeshAttachment.h index edf6c24a6..7c73488f8 100644 --- a/spine-cpp/spine-cpp/include/spine/MeshAttachment.h +++ b/spine-cpp/spine-cpp/include/spine/MeshAttachment.h @@ -40,8 +40,7 @@ namespace Spine { /// Attachment that displays a texture region using a mesh. - class MeshAttachment : public VertexAttachment - { + class MeshAttachment : public VertexAttachment { friend class SkeletonBinary; friend class SkeletonJson; friend class AtlasAttachmentLoader; diff --git a/spine-cpp/spine-cpp/include/spine/MixDirection.h b/spine-cpp/spine-cpp/include/spine/MixDirection.h index ab14a3823..3dd096ea7 100644 --- a/spine-cpp/spine-cpp/include/spine/MixDirection.h +++ b/spine-cpp/spine-cpp/include/spine/MixDirection.h @@ -36,8 +36,7 @@ namespace Spine /// /// Indicates whether a timeline's alpha is mixing out over time toward 0 (the setup or current pose) or mixing in toward 1 (the timeline's pose). /// See also Timeline::apply(Skeleton&, float, float, Vector&, float, MixPose, MixDirection) - enum MixDirection - { + enum MixDirection { MixDirection_In = 0, MixDirection_Out }; diff --git a/spine-cpp/spine-cpp/include/spine/MixPose.h b/spine-cpp/spine-cpp/include/spine/MixPose.h index f95fce969..b9aeec4ae 100644 --- a/spine-cpp/spine-cpp/include/spine/MixPose.h +++ b/spine-cpp/spine-cpp/include/spine/MixPose.h @@ -36,8 +36,7 @@ namespace Spine /// /// Controls how a timeline is mixed with the setup or current pose. /// See also Timeline::apply(Skeleton&, float, float, Vector&, float, MixPose, MixDirection) - enum MixPose - { + enum MixPose { /// The timeline value is mixed with the setup pose (the current pose is not used). MixPose_Setup = 0, /// The timeline value is mixed with the current pose. The setup pose is used as the timeline value before the first key, diff --git a/spine-cpp/spine-cpp/include/spine/PathAttachment.h b/spine-cpp/spine-cpp/include/spine/PathAttachment.h index aaaa2c68e..f5abcc32c 100644 --- a/spine-cpp/spine-cpp/include/spine/PathAttachment.h +++ b/spine-cpp/spine-cpp/include/spine/PathAttachment.h @@ -35,8 +35,7 @@ namespace Spine { - class PathAttachment : public VertexAttachment - { + class PathAttachment : public VertexAttachment { friend class SkeletonBinary; friend class SkeletonJson; diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraint.h b/spine-cpp/spine-cpp/include/spine/PathConstraint.h index a88e5a4cc..2daa91ebb 100644 --- a/spine-cpp/spine-cpp/include/spine/PathConstraint.h +++ b/spine-cpp/spine-cpp/include/spine/PathConstraint.h @@ -43,8 +43,7 @@ namespace Spine class Bone; class Slot; - class PathConstraint : public Constraint - { + class PathConstraint : public Constraint { friend class Skeleton; friend class PathConstraintMixTimeline; friend class PathConstraintPositionTimeline; diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraintData.h b/spine-cpp/spine-cpp/include/spine/PathConstraintData.h index 8736a1d32..68991f8c8 100644 --- a/spine-cpp/spine-cpp/include/spine/PathConstraintData.h +++ b/spine-cpp/spine-cpp/include/spine/PathConstraintData.h @@ -43,8 +43,7 @@ namespace Spine class BoneData; class SlotData; - class PathConstraintData - { + class PathConstraintData { friend class SkeletonBinary; friend class SkeletonJson; diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h b/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h index c2cce00e9..7e64ac85d 100644 --- a/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h @@ -35,8 +35,7 @@ namespace Spine { - class PathConstraintMixTimeline : public CurveTimeline - { + class PathConstraintMixTimeline : public CurveTimeline { friend class SkeletonBinary; friend class SkeletonJson; diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h b/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h index b5fe6916b..172a897a7 100644 --- a/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h @@ -35,8 +35,7 @@ namespace Spine { - class PathConstraintPositionTimeline : public CurveTimeline - { + class PathConstraintPositionTimeline : public CurveTimeline { friend class SkeletonBinary; friend class SkeletonJson; diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h b/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h index 68aad43c9..c30394f79 100644 --- a/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h @@ -35,8 +35,7 @@ namespace Spine { - class PathConstraintSpacingTimeline : public PathConstraintPositionTimeline - { + class PathConstraintSpacingTimeline : public PathConstraintPositionTimeline { friend class SkeletonBinary; friend class SkeletonJson; diff --git a/spine-cpp/spine-cpp/include/spine/PointAttachment.h b/spine-cpp/spine-cpp/include/spine/PointAttachment.h index cdb13fdd0..f1f5f0b1d 100644 --- a/spine-cpp/spine-cpp/include/spine/PointAttachment.h +++ b/spine-cpp/spine-cpp/include/spine/PointAttachment.h @@ -44,8 +44,7 @@ namespace Spine /// /// See http://esotericsoftware.com/spine-point-attachments for Point Attachments in the Spine User Guide. /// - class PointAttachment : public Attachment - { + class PointAttachment : public Attachment { friend class SkeletonBinary; friend class SkeletonJson; diff --git a/spine-cpp/spine-cpp/include/spine/Pool.h b/spine-cpp/spine-cpp/include/spine/Pool.h index 963fd6b55..29a447a13 100644 --- a/spine-cpp/spine-cpp/include/spine/Pool.h +++ b/spine-cpp/spine-cpp/include/spine/Pool.h @@ -38,31 +38,25 @@ namespace Spine { template - class Pool - { + class Pool { public: - Pool() - { + Pool() { // Empty } - ~Pool() - { + ~Pool() { ContainerUtil::cleanUpVectorOfPointers(_objects); } - T* obtain() - { - if (_objects.size() > 0) - { + T* obtain() { + if (_objects.size() > 0) { T** object = _objects.begin(); T* ret = *object; _objects.erase(0); return ret; } - else - { + else { T* ret = NEW(T); new (ret) T(); @@ -70,10 +64,8 @@ namespace Spine } } - void free(T* object) - { - if (!_objects.contains(object)) - { + void free(T* object) { + if (!_objects.contains(object)) { _objects.push_back(object); } } diff --git a/spine-cpp/spine-cpp/include/spine/PositionMode.h b/spine-cpp/spine-cpp/include/spine/PositionMode.h index 66a601cac..c5ad9bdfc 100644 --- a/spine-cpp/spine-cpp/include/spine/PositionMode.h +++ b/spine-cpp/spine-cpp/include/spine/PositionMode.h @@ -33,8 +33,7 @@ namespace Spine { - enum PositionMode - { + enum PositionMode { PositionMode_Fixed = 0, PositionMode_Percent }; diff --git a/spine-cpp/spine-cpp/include/spine/RTTI.h b/spine-cpp/spine-cpp/include/spine/RTTI.h index 79f413efa..362c3548a 100644 --- a/spine-cpp/spine-cpp/include/spine/RTTI.h +++ b/spine-cpp/spine-cpp/include/spine/RTTI.h @@ -35,8 +35,7 @@ namespace Spine { - class RTTI - { + class RTTI { public: RTTI(const std::string& className); diff --git a/spine-cpp/spine-cpp/include/spine/RegionAttachment.h b/spine-cpp/spine-cpp/include/spine/RegionAttachment.h index d48f0c976..acdb6a870 100644 --- a/spine-cpp/spine-cpp/include/spine/RegionAttachment.h +++ b/spine-cpp/spine-cpp/include/spine/RegionAttachment.h @@ -44,8 +44,7 @@ namespace Spine class Bone; /// Attachment that displays a texture region. - class RegionAttachment : public Attachment - { + class RegionAttachment : public Attachment { friend class SkeletonBinary; friend class SkeletonJson; friend class AtlasAttachmentLoader; diff --git a/spine-cpp/spine-cpp/include/spine/RotateMode.h b/spine-cpp/spine-cpp/include/spine/RotateMode.h index a8ccd6f97..3c5cbe789 100644 --- a/spine-cpp/spine-cpp/include/spine/RotateMode.h +++ b/spine-cpp/spine-cpp/include/spine/RotateMode.h @@ -33,8 +33,7 @@ namespace Spine { - enum RotateMode - { + enum RotateMode { RotateMode_Tangent = 0, RotateMode_Chain, RotateMode_ChainScale diff --git a/spine-cpp/spine-cpp/include/spine/RotateTimeline.h b/spine-cpp/spine-cpp/include/spine/RotateTimeline.h index aed7eb822..778fd9a15 100644 --- a/spine-cpp/spine-cpp/include/spine/RotateTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/RotateTimeline.h @@ -35,8 +35,7 @@ namespace Spine { - class RotateTimeline : public CurveTimeline - { + class RotateTimeline : public CurveTimeline { friend class SkeletonBinary; friend class SkeletonJson; friend class AnimationState; diff --git a/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h b/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h index a0788fe1c..f02c40afa 100644 --- a/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h @@ -35,8 +35,7 @@ namespace Spine { - class ScaleTimeline : public TranslateTimeline - { + class ScaleTimeline : public TranslateTimeline { friend class SkeletonBinary; friend class SkeletonJson; diff --git a/spine-cpp/spine-cpp/include/spine/ShearTimeline.h b/spine-cpp/spine-cpp/include/spine/ShearTimeline.h index d3b46ac70..a42e2ec45 100644 --- a/spine-cpp/spine-cpp/include/spine/ShearTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/ShearTimeline.h @@ -35,8 +35,7 @@ namespace Spine { - class ShearTimeline : public TranslateTimeline - { + class ShearTimeline : public TranslateTimeline { friend class SkeletonBinary; friend class SkeletonJson; diff --git a/spine-cpp/spine-cpp/include/spine/Skeleton.h b/spine-cpp/spine-cpp/include/spine/Skeleton.h index 72a305daa..c6f9564f3 100644 --- a/spine-cpp/spine-cpp/include/spine/Skeleton.h +++ b/spine-cpp/spine-cpp/include/spine/Skeleton.h @@ -49,8 +49,7 @@ namespace Spine class Skin; class Attachment; - class Skeleton - { + class Skeleton { friend class AnimationState; friend class SkeletonBounds; friend class SkeletonClipping; diff --git a/spine-cpp/spine-cpp/include/spine/SkeletonBinary.h b/spine-cpp/spine-cpp/include/spine/SkeletonBinary.h index c26ad8ea8..96c970019 100644 --- a/spine-cpp/spine-cpp/include/spine/SkeletonBinary.h +++ b/spine-cpp/spine-cpp/include/spine/SkeletonBinary.h @@ -48,8 +48,7 @@ namespace Spine class Animation; class CurveTimeline; - class SkeletonBinary - { + class SkeletonBinary { public: static const int BONE_ROTATE; static const int BONE_TRANSLATE; @@ -81,8 +80,7 @@ namespace Spine SkeletonData* readSkeletonDataFile(const char* path); private: - struct DataInput - { + struct DataInput { const unsigned char* cursor; const unsigned char* end; }; diff --git a/spine-cpp/spine-cpp/include/spine/SkeletonBounds.h b/spine-cpp/spine-cpp/include/spine/SkeletonBounds.h index 424bc2a7f..c000cbe44 100644 --- a/spine-cpp/spine-cpp/include/spine/SkeletonBounds.h +++ b/spine-cpp/spine-cpp/include/spine/SkeletonBounds.h @@ -44,8 +44,7 @@ namespace Spine /// Collects each BoundingBoxAttachment that is visible and computes the world vertices for its polygon. /// The polygon vertices are provided along with convenience methods for doing hit detection. /// - class SkeletonBounds - { + class SkeletonBounds { public: SkeletonBounds(); @@ -96,14 +95,12 @@ namespace Spine void aabbCompute(); }; - class Polygon - { + class Polygon { public: Vector _vertices; int _count; - Polygon() : _count(0) - { + Polygon() : _count(0) { _vertices.reserve(16); } }; diff --git a/spine-cpp/spine-cpp/include/spine/SkeletonClipping.h b/spine-cpp/spine-cpp/include/spine/SkeletonClipping.h index f61e4aa7d..19baa4746 100644 --- a/spine-cpp/spine-cpp/include/spine/SkeletonClipping.h +++ b/spine-cpp/spine-cpp/include/spine/SkeletonClipping.h @@ -39,8 +39,7 @@ namespace Spine class Slot; class ClippingAttachment; - class SkeletonClipping - { + class SkeletonClipping { public: SkeletonClipping(); diff --git a/spine-cpp/spine-cpp/include/spine/SkeletonData.h b/spine-cpp/spine-cpp/include/spine/SkeletonData.h index 96b4584cc..04e195a8c 100644 --- a/spine-cpp/spine-cpp/include/spine/SkeletonData.h +++ b/spine-cpp/spine-cpp/include/spine/SkeletonData.h @@ -47,8 +47,7 @@ namespace Spine class PathConstraintData; /// Stores the setup pose and all of the stateless data for a skeleton. - class SkeletonData - { + class SkeletonData { friend class SkeletonBinary; friend class SkeletonJson; friend class Skeleton; diff --git a/spine-cpp/spine-cpp/include/spine/SkeletonJson.h b/spine-cpp/spine-cpp/include/spine/SkeletonJson.h index 9fbbf11fb..6c0ea928b 100644 --- a/spine-cpp/spine-cpp/include/spine/SkeletonJson.h +++ b/spine-cpp/spine-cpp/include/spine/SkeletonJson.h @@ -46,8 +46,7 @@ namespace Spine class AttachmentLoader; class LinkedMesh; - class SkeletonJson - { + class SkeletonJson { public: SkeletonJson(Vector& atlasArray); diff --git a/spine-cpp/spine-cpp/include/spine/Skin.h b/spine-cpp/spine-cpp/include/spine/Skin.h index 4ec62317d..8836b692e 100644 --- a/spine-cpp/spine-cpp/include/spine/Skin.h +++ b/spine-cpp/spine-cpp/include/spine/Skin.h @@ -43,13 +43,11 @@ namespace Spine /// Stores attachments by slot index and attachment name. /// See SkeletonData::getDefaultSkin, Skeleton::getSkin, and /// http://esotericsoftware.com/spine-runtime-skins in the Spine Runtimes Guide. - class Skin - { + class Skin { friend class Skeleton; public: - class AttachmentKey - { + class AttachmentKey { public: int _slotIndex; std::string _name; @@ -59,8 +57,7 @@ namespace Spine bool operator==(const AttachmentKey &other) const; }; - struct HashAttachmentKey - { + struct HashAttachmentKey { std::size_t operator()(const Spine::Skin::AttachmentKey& val) const; }; diff --git a/spine-cpp/spine-cpp/include/spine/Slot.h b/spine-cpp/spine-cpp/include/spine/Slot.h index 780db4425..c85713a5c 100644 --- a/spine-cpp/spine-cpp/include/spine/Slot.h +++ b/spine-cpp/spine-cpp/include/spine/Slot.h @@ -42,8 +42,7 @@ namespace Spine class Skeleton; class Attachment; - class Slot - { + class Slot { friend class VertexAttachment; friend class Skeleton; friend class SkeletonBounds; diff --git a/spine-cpp/spine-cpp/include/spine/SlotData.h b/spine-cpp/spine-cpp/include/spine/SlotData.h index 45eeb834d..444195aa6 100644 --- a/spine-cpp/spine-cpp/include/spine/SlotData.h +++ b/spine-cpp/spine-cpp/include/spine/SlotData.h @@ -39,8 +39,7 @@ namespace Spine { class BoneData; - class SlotData - { + class SlotData { friend class SkeletonBinary; friend class SkeletonJson; diff --git a/spine-cpp/spine-cpp/include/spine/SpacingMode.h b/spine-cpp/spine-cpp/include/spine/SpacingMode.h index 76b2986b4..e3b52dd07 100644 --- a/spine-cpp/spine-cpp/include/spine/SpacingMode.h +++ b/spine-cpp/spine-cpp/include/spine/SpacingMode.h @@ -33,8 +33,7 @@ namespace Spine { - enum SpacingMode - { + enum SpacingMode { SpacingMode_Length = 0, SpacingMode_Fixed, SpacingMode_Percent diff --git a/spine-cpp/spine-cpp/include/spine/TextureLoader.h b/spine-cpp/spine-cpp/include/spine/TextureLoader.h index 82f469945..5502922f7 100644 --- a/spine-cpp/spine-cpp/include/spine/TextureLoader.h +++ b/spine-cpp/spine-cpp/include/spine/TextureLoader.h @@ -37,8 +37,7 @@ namespace Spine { class AtlasPage; - class TextureLoader - { + class TextureLoader { public: TextureLoader(); diff --git a/spine-cpp/spine-cpp/include/spine/Timeline.h b/spine-cpp/spine-cpp/include/spine/Timeline.h index 606854138..0e1e0e3fe 100644 --- a/spine-cpp/spine-cpp/include/spine/Timeline.h +++ b/spine-cpp/spine-cpp/include/spine/Timeline.h @@ -41,8 +41,7 @@ namespace Spine class Skeleton; class Event; - class Timeline - { + class Timeline { RTTI_DECL; public: diff --git a/spine-cpp/spine-cpp/include/spine/TimelineType.h b/spine-cpp/spine-cpp/include/spine/TimelineType.h index 06f085b6e..f055fb599 100644 --- a/spine-cpp/spine-cpp/include/spine/TimelineType.h +++ b/spine-cpp/spine-cpp/include/spine/TimelineType.h @@ -33,8 +33,7 @@ namespace Spine { - enum TimelineType - { + enum TimelineType { TimelineType_Rotate = 0, TimelineType_Translate, TimelineType_Scale, diff --git a/spine-cpp/spine-cpp/include/spine/TransformConstraint.h b/spine-cpp/spine-cpp/include/spine/TransformConstraint.h index 7c5061f60..ad837b54d 100644 --- a/spine-cpp/spine-cpp/include/spine/TransformConstraint.h +++ b/spine-cpp/spine-cpp/include/spine/TransformConstraint.h @@ -41,8 +41,7 @@ namespace Spine class Skeleton; class Bone; - class TransformConstraint : public Constraint - { + class TransformConstraint : public Constraint { friend class Skeleton; friend class TransformConstraintTimeline; diff --git a/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h b/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h index aa8e737d6..c12cb40c6 100644 --- a/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h +++ b/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h @@ -39,8 +39,7 @@ namespace Spine { class BoneData; - class TransformConstraintData - { + class TransformConstraintData { friend class SkeletonBinary; friend class SkeletonJson; diff --git a/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h b/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h index 2324234cb..ddefa6f20 100644 --- a/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h @@ -35,8 +35,7 @@ namespace Spine { - class TransformConstraintTimeline : public CurveTimeline - { + class TransformConstraintTimeline : public CurveTimeline { friend class SkeletonBinary; friend class SkeletonJson; diff --git a/spine-cpp/spine-cpp/include/spine/TransformMode.h b/spine-cpp/spine-cpp/include/spine/TransformMode.h index 35c1ae55b..8b9c6df53 100644 --- a/spine-cpp/spine-cpp/include/spine/TransformMode.h +++ b/spine-cpp/spine-cpp/include/spine/TransformMode.h @@ -33,8 +33,7 @@ namespace Spine { - enum TransformMode - { + enum TransformMode { //0000 0 Flip Scale Rotation TransformMode_Normal = 0, // 0000 TransformMode_OnlyTranslation = 7, // 0111 diff --git a/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h b/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h index 424125ebb..d5014894d 100644 --- a/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h @@ -38,8 +38,7 @@ namespace Spine { - class TranslateTimeline : public CurveTimeline - { + class TranslateTimeline : public CurveTimeline { friend class SkeletonBinary; friend class SkeletonJson; diff --git a/spine-cpp/spine-cpp/include/spine/Triangulator.h b/spine-cpp/spine-cpp/include/spine/Triangulator.h index b8da189fc..8e43659ea 100644 --- a/spine-cpp/spine-cpp/include/spine/Triangulator.h +++ b/spine-cpp/spine-cpp/include/spine/Triangulator.h @@ -36,8 +36,7 @@ namespace Spine { - class Triangulator - { + class Triangulator { public: Vector& triangulate(Vector& vertices); diff --git a/spine-cpp/spine-cpp/include/spine/TwoColorTimeline.h b/spine-cpp/spine-cpp/include/spine/TwoColorTimeline.h index 266eba418..0f8aee052 100644 --- a/spine-cpp/spine-cpp/include/spine/TwoColorTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/TwoColorTimeline.h @@ -35,8 +35,7 @@ namespace Spine { - class TwoColorTimeline : public CurveTimeline - { + class TwoColorTimeline : public CurveTimeline { friend class SkeletonBinary; friend class SkeletonJson; diff --git a/spine-cpp/spine-cpp/include/spine/Updatable.h b/spine-cpp/spine-cpp/include/spine/Updatable.h index fac634191..8bf9df75c 100644 --- a/spine-cpp/spine-cpp/include/spine/Updatable.h +++ b/spine-cpp/spine-cpp/include/spine/Updatable.h @@ -35,8 +35,7 @@ namespace Spine { - class Updatable - { + class Updatable { RTTI_DECL; public: diff --git a/spine-cpp/spine-cpp/include/spine/Vector.h b/spine-cpp/spine-cpp/include/spine/Vector.h index 7c7dc3394..5272122b5 100644 --- a/spine-cpp/spine-cpp/include/spine/Vector.h +++ b/spine-cpp/spine-cpp/include/spine/Vector.h @@ -40,30 +40,23 @@ namespace Spine { template - class Vector - { + class Vector { public: - Vector() : _size(0), _capacity(0), _buffer(NULL) - { + Vector() : _size(0), _capacity(0), _buffer(NULL) { // Empty } - Vector(const Vector& inVector) : _size(inVector._size), _capacity(inVector._capacity), _buffer(NULL) - { - if (_capacity > 0) - { + Vector(const Vector& inVector) : _size(inVector._size), _capacity(inVector._capacity), _buffer(NULL) { + if (_capacity > 0) { _buffer = allocate(_capacity); - for (size_t i = 0; i < _size; ++i) - { + for (size_t i = 0; i < _size; ++i) { construct(_buffer + i, inVector._buffer[i]); } } } - Vector& operator=(Vector& inVector) - { - if (this != &inVector) - { + Vector& operator=(Vector& inVector) { + if (this != &inVector) { clear(); deallocate(_buffer); _buffer = NULL; @@ -71,11 +64,9 @@ namespace Spine _size = inVector._size; _capacity = inVector._capacity; - if (_capacity > 0) - { + if (_capacity > 0) { _buffer = allocate(_capacity); - for (size_t i = 0; i < _size; ++i) - { + for (size_t i = 0; i < _size; ++i) { construct(_buffer + i, inVector._buffer[i]); } } @@ -84,18 +75,14 @@ namespace Spine return *this; } - ~Vector() - { + ~Vector() { clear(); deallocate(_buffer); } - bool contains(const T& inValue) - { - for (size_t i = 0; i < _size; ++i) - { - if (_buffer[i] == inValue) - { + bool contains(const T& inValue) { + for (size_t i = 0; i < _size; ++i) { + if (_buffer[i] == inValue) { return true; } } @@ -103,12 +90,9 @@ namespace Spine return false; } - int indexOf(const T& inValue) - { - for (size_t i = 0; i < _size; ++i) - { - if (_buffer[i] == inValue) - { + int indexOf(const T& inValue) { + for (size_t i = 0; i < _size; ++i) { + if (_buffer[i] == inValue) { return static_cast(i); } } @@ -116,27 +100,22 @@ namespace Spine return -1; } - void push_back(const T& inValue) - { - if (_size == _capacity) - { + void push_back(const T& inValue) { + if (_size == _capacity) { reserve(); } construct(_buffer + _size++, inValue); } - void insert(size_t inIndex, const T& inValue) - { + void insert(size_t inIndex, const T& inValue) { assert(inIndex < _size); - if (_size == _capacity) - { + if (_size == _capacity) { reserve(); } - for (size_t i = ++_size - 1; i > inIndex; --i) - { + for (size_t i = ++_size - 1; i > inIndex; --i) { construct(_buffer + i, _buffer[i - 1]); destroy(_buffer + (i - 1)); } @@ -144,16 +123,13 @@ namespace Spine construct(_buffer + inIndex, inValue); } - void erase(size_t inIndex) - { + void erase(size_t inIndex) { assert(inIndex < _size); --_size; - if (inIndex != _size) - { - for (size_t i = inIndex; i < _size; ++i) - { + if (inIndex != _size) { + for (size_t i = inIndex; i < _size; ++i) { std::swap(_buffer[i], _buffer[i + 1]); } } @@ -161,66 +137,53 @@ namespace Spine destroy(_buffer + _size); } - void clear() - { - for (size_t i = 0; i < _size; ++i) - { + void clear() { + for (size_t i = 0; i < _size; ++i) { destroy(_buffer + (_size - 1 - i)); } _size = 0; } - size_t size() const - { + size_t size() const { return _size; } - T& operator[](size_t inIndex) - { + T& operator[](size_t inIndex) { assert(inIndex < _size); return _buffer[inIndex]; } - void reserve(size_t inCapacity = 0) - { + void reserve(size_t inCapacity = 0) { size_t newCapacity = inCapacity > 0 ? inCapacity : _capacity > 0 ? _capacity * 2 : 1; - if (newCapacity > _capacity) - { + if (newCapacity > _capacity) { _buffer = REALLOC(_buffer, T, newCapacity); _capacity = newCapacity; } } - void setSize(size_t inValue) - { + void setSize(size_t inValue) { assert(inValue <= _capacity); _size = inValue; } - T* begin() - { + T* begin() { return &_buffer[0]; } - T* end() - { + T* end() { return &_buffer[_size]; } - friend bool operator==(Vector& lhs, Vector& rhs) - { - if (lhs.size() != rhs.size()) - { + friend bool operator==(Vector& lhs, Vector& rhs) { + if (lhs.size() != rhs.size()) { return false; } - for (int i = 0, n = static_cast(lhs.size()); i < n; ++i) - { - if (lhs[i] != rhs[i]) - { + for (int i = 0, n = static_cast(lhs.size()); i < n; ++i) { + if (lhs[i] != rhs[i]) { return false; } } @@ -228,8 +191,7 @@ namespace Spine return true; } - friend bool operator!=(Vector& lhs, Vector& rhs) - { + friend bool operator!=(Vector& lhs, Vector& rhs) { return !(lhs == rhs); } @@ -238,8 +200,7 @@ namespace Spine size_t _capacity; T* _buffer; - T* allocate(size_t n) - { + T* allocate(size_t n) { assert(n > 0); T* ptr = MALLOC(T, n); @@ -249,24 +210,20 @@ namespace Spine return ptr; } - void deallocate(T* buffer) - { - if (_buffer) - { + void deallocate(T* buffer) { + if (_buffer) { FREE(buffer); } } - void construct(T* buffer, const T& val) - { + void construct(T* buffer, const T& val) { /// This is a placement new operator /// which basically means we are contructing a new object /// using pre-allocated memory new (buffer) T(val); } - void destroy(T* buffer) - { + void destroy(T* buffer) { buffer->~T(); } }; diff --git a/spine-cpp/spine-cpp/include/spine/VertexAttachment.h b/spine-cpp/spine-cpp/include/spine/VertexAttachment.h index 56c057674..a60031dd8 100644 --- a/spine-cpp/spine-cpp/include/spine/VertexAttachment.h +++ b/spine-cpp/spine-cpp/include/spine/VertexAttachment.h @@ -40,8 +40,7 @@ namespace Spine class Slot; /// An attachment with vertices that are transformed by one or more bones and can be deformed by a slot's vertices. - class VertexAttachment : public Attachment - { + class VertexAttachment : public Attachment { friend class SkeletonBinary; friend class SkeletonJson; friend class DeformTimeline; diff --git a/spine-cpp/spine-cpp/include/spine/Vertices.h b/spine-cpp/spine-cpp/include/spine/Vertices.h index bd14260f1..f8ba613b7 100644 --- a/spine-cpp/spine-cpp/include/spine/Vertices.h +++ b/spine-cpp/spine-cpp/include/spine/Vertices.h @@ -35,8 +35,7 @@ namespace Spine { - class Vertices - { + class Vertices { public: Vector _bones; Vector _vertices; diff --git a/spine-cpp/spine-cpp/src/spine/Animation.cpp b/spine-cpp/spine-cpp/src/spine/Animation.cpp index d494c4154..b18b502f2 100644 --- a/spine-cpp/spine-cpp/src/spine/Animation.cpp +++ b/spine-cpp/spine-cpp/src/spine/Animation.cpp @@ -44,82 +44,65 @@ namespace Spine Animation::Animation(std::string name, Vector& timelines, float duration) : _timelines(timelines), _duration(duration), - _name(name) - { + _name(name) { assert(_name.length() > 0); } - Animation::~Animation() - { + Animation::~Animation() { ContainerUtil::cleanUpVectorOfPointers(_timelines); } - void Animation::apply(Skeleton& skeleton, float lastTime, float time, bool loop, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) - { - if (loop && _duration != 0) - { + void Animation::apply(Skeleton& skeleton, float lastTime, float time, bool loop, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) { + if (loop && _duration != 0) { time = fmod(time, _duration); - if (lastTime > 0) - { + if (lastTime > 0) { lastTime = fmod(lastTime, _duration); } } - for (int i = 0, n = static_cast(_timelines.size()); i < n; ++i) - { + for (int i = 0, n = static_cast(_timelines.size()); i < n; ++i) { _timelines[i]->apply(skeleton, lastTime, time, pEvents, alpha, pose, direction); } } - std::string Animation::getName() - { + std::string Animation::getName() { return _name; } - Vector Animation::getTimelines() - { + Vector Animation::getTimelines() { return _timelines; } - void Animation::setTimelines(Vector inValue) - { + void Animation::setTimelines(Vector inValue) { _timelines = inValue; } - float Animation::getDuration() - { + float Animation::getDuration() { return _duration; } - void Animation::setDuration(float inValue) - { + void Animation::setDuration(float inValue) { _duration = inValue; } - int Animation::binarySearch(Vector& values, float target, int step) - { + int Animation::binarySearch(Vector& values, float target, int step) { int low = 0; int size = static_cast(values.size()); int high = size / step - 2; - if (high == 0) - { + if (high == 0) { return step; } int current = (int)(static_cast(high) >> 1); - while (true) - { - if (values[(current + 1) * step] <= target) - { + while (true) { + if (values[(current + 1) * step] <= target) { low = current + 1; } - else - { + else { high = current; } - if (low == high) - { + if (low == high) { return (low + 1) * step; } @@ -127,30 +110,24 @@ namespace Spine } } - int Animation::binarySearch(Vector& values, float target) - { + int Animation::binarySearch(Vector& values, float target) { int low = 0; int size = static_cast(values.size()); int high = size - 2; - if (high == 0) - { + if (high == 0) { return 1; } int current = (int)(static_cast(high) >> 1); - while (true) - { - if (values[(current + 1)] <= target) - { + while (true) { + if (values[(current + 1)] <= target) { low = current + 1; } - else - { + else { high = current; } - if (low == high) - { + if (low == high) { return (low + 1); } @@ -158,12 +135,9 @@ namespace Spine } } - int Animation::linearSearch(Vector& values, float target, int step) - { - for (int i = 0, last = static_cast(values.size()) - step; i <= last; i += step) - { - if (values[i] > target) - { + int Animation::linearSearch(Vector& values, float target, int step) { + for (int i = 0, last = static_cast(values.size()) - step; i <= last; i += step) { + if (values[i] > target) { return i; } } diff --git a/spine-cpp/spine-cpp/src/spine/AnimationState.cpp b/spine-cpp/spine-cpp/src/spine/AnimationState.cpp index 48e2485c9..9650053b6 100644 --- a/spine-cpp/spine-cpp/src/spine/AnimationState.cpp +++ b/spine-cpp/spine-cpp/src/spine/AnimationState.cpp @@ -48,13 +48,11 @@ namespace Spine { - void dummyOnAnimationEventFunc(AnimationState* state, EventType type, TrackEntry* entry, Event* event = NULL) - { + void dummyOnAnimationEventFunc(AnimationState* state, EventType type, TrackEntry* entry, Event* event = NULL) { // Empty } - TrackEntry::TrackEntry() : _animation(NULL), _next(NULL), _mixingFrom(NULL), _trackIndex(0), _loop(false), _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(1.0f), _alpha(0), _mixTime(0), _mixDuration(0), _interruptAlpha(0), _totalAlpha(0), _onAnimationEventFunc(dummyOnAnimationEventFunc) - { + TrackEntry::TrackEntry() : _animation(NULL), _next(NULL), _mixingFrom(NULL), _trackIndex(0), _loop(false), _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(1.0f), _alpha(0), _mixTime(0), _mixDuration(0), _interruptAlpha(0), _totalAlpha(0), _onAnimationEventFunc(dummyOnAnimationEventFunc) { // Empty } @@ -81,19 +79,15 @@ namespace Spine void TrackEntry::setAnimationEnd(float inValue) { _animationEnd = inValue; } float TrackEntry::getAnimationLast() { return _animationLast; } - void TrackEntry::setAnimationLast(float inValue) - { + void TrackEntry::setAnimationLast(float inValue) { _animationLast = inValue; _nextAnimationLast = inValue; } - float TrackEntry::getAnimationTime() - { - if (_loop) - { + float TrackEntry::getAnimationTime() { + if (_loop) { float duration = _animationEnd - _animationStart; - if (duration == 0) - { + if (duration == 0) { return _animationStart; } @@ -120,8 +114,7 @@ namespace Spine TrackEntry* TrackEntry::getNext() { return _next; } - bool TrackEntry::isComplete() - { + bool TrackEntry::isComplete() { return _trackTime >= _animationEnd - _animationStart; } @@ -133,27 +126,22 @@ namespace Spine TrackEntry* TrackEntry::getMixingFrom() { return _mixingFrom; } - void TrackEntry::resetRotationDirections() - { + void TrackEntry::resetRotationDirections() { _timelinesRotation.clear(); } - void TrackEntry::setOnAnimationEventFunc(OnAnimationEventFunc inValue) - { + void TrackEntry::setOnAnimationEventFunc(OnAnimationEventFunc inValue) { _onAnimationEventFunc = inValue; } - TrackEntry* TrackEntry::setTimelineData(TrackEntry* to, Vector& mixingToArray, Vector& propertyIDs) - { - if (to != NULL) - { + TrackEntry* TrackEntry::setTimelineData(TrackEntry* to, Vector& mixingToArray, Vector& propertyIDs) { + if (to != NULL) { mixingToArray.push_back(to); } TrackEntry* lastEntry = _mixingFrom != NULL ? _mixingFrom->setTimelineData(this, mixingToArray, propertyIDs) : this; - if (to != NULL) - { + if (to != NULL) { mixingToArray.erase(mixingToArray.size() - 1); } @@ -167,30 +155,22 @@ namespace Spine _timelineDipMix.setSize(timelinesCount); // outer: - for (int i = 0; i < timelinesCount; ++i) - { + for (int i = 0; i < timelinesCount; ++i) { int id = timelines[i]->getPropertyId(); - if (propertyIDs.contains(id)) - { + if (propertyIDs.contains(id)) { _timelineData[i] = AnimationState::Subsequent; } - else - { + else { propertyIDs.push_back(id); - if (to == NULL || !to->hasTimeline(id)) - { + if (to == NULL || !to->hasTimeline(id)) { _timelineData[i] = AnimationState::First; } - else - { - for (int ii = mixingToLast; ii >= 0; --ii) - { + else { + for (int ii = mixingToLast; ii >= 0; --ii) { TrackEntry* entry = mixingToArray[ii]; - if (!entry->hasTimeline(id)) - { - if (entry->_mixDuration > 0) - { + if (!entry->hasTimeline(id)) { + if (entry->_mixDuration > 0) { _timelineData[i] = AnimationState::DipMix; _timelineDipMix[i] = entry; goto continue_outer; // continue outer; @@ -207,21 +187,17 @@ namespace Spine return lastEntry; } - bool TrackEntry::hasTimeline(int inId) - { + bool TrackEntry::hasTimeline(int inId) { Vector& timelines = _animation->_timelines; - for (int i = 0, n = static_cast(timelines.size()); i < n; ++i) - { - if (timelines[i]->getPropertyId() == inId) - { + for (int i = 0, n = static_cast(timelines.size()); i < n; ++i) { + if (timelines[i]->getPropertyId() == inId) { return true; } } return false; } - void TrackEntry::reset() - { + void TrackEntry::reset() { _animation = NULL; _next = NULL; _mixingFrom = NULL; @@ -236,74 +212,61 @@ namespace Spine EventQueueEntry::EventQueueEntry(EventType eventType, TrackEntry* trackEntry, Event* event) : _type(eventType), _entry(trackEntry), - _event(event) - { + _event(event) { // Empty } - EventQueue* EventQueue::newEventQueue(AnimationState& state, Pool& trackEntryPool) - { + EventQueue* EventQueue::newEventQueue(AnimationState& state, Pool& trackEntryPool) { EventQueue* ret = NEW(EventQueue); new (ret) EventQueue(state, trackEntryPool); return ret; } - EventQueueEntry* EventQueue::newEventQueueEntry(EventType eventType, TrackEntry* entry, Event* event) - { + EventQueueEntry* EventQueue::newEventQueueEntry(EventType eventType, TrackEntry* entry, Event* event) { EventQueueEntry* ret = NEW(EventQueueEntry); new (ret) EventQueueEntry(eventType, entry, event); return ret; } - EventQueue::EventQueue(AnimationState& state, Pool& trackEntryPool) : _state(state), _trackEntryPool(trackEntryPool), _drainDisabled(false) - { + EventQueue::EventQueue(AnimationState& state, Pool& trackEntryPool) : _state(state), _trackEntryPool(trackEntryPool), _drainDisabled(false) { // Empty } - EventQueue::~EventQueue() - { + EventQueue::~EventQueue() { ContainerUtil::cleanUpVectorOfPointers(_eventQueueEntries); } - void EventQueue::start(TrackEntry* entry) - { + void EventQueue::start(TrackEntry* entry) { _eventQueueEntries.push_back(newEventQueueEntry(EventType_Start, entry)); _state._animationsChanged = true; } - void EventQueue::interrupt(TrackEntry* entry) - { + void EventQueue::interrupt(TrackEntry* entry) { _eventQueueEntries.push_back(newEventQueueEntry(EventType_Interrupt, entry)); } - void EventQueue::end(TrackEntry* entry) - { + void EventQueue::end(TrackEntry* entry) { _eventQueueEntries.push_back(newEventQueueEntry(EventType_End, entry)); _state._animationsChanged = true; } - void EventQueue::dispose(TrackEntry* entry) - { + void EventQueue::dispose(TrackEntry* entry) { _eventQueueEntries.push_back(newEventQueueEntry(EventType_Dispose, entry)); } - void EventQueue::complete(TrackEntry* entry) - { + void EventQueue::complete(TrackEntry* entry) { _eventQueueEntries.push_back(newEventQueueEntry(EventType_Complete, entry)); } - void EventQueue::event(TrackEntry* entry, Event* event) - { + void EventQueue::event(TrackEntry* entry, Event* event) { _eventQueueEntries.push_back(newEventQueueEntry(EventType_Event, entry, event)); } /// Raises all events in the queue and drains the queue. - void EventQueue::drain() - { - if (_drainDisabled) - { + void EventQueue::drain() { + if (_drainDisabled) { return; } @@ -312,13 +275,11 @@ namespace Spine AnimationState& state = _state; // Don't cache _eventQueueEntries.size() so callbacks can queue their own events (eg, call setAnimation in AnimationState_Complete). - for (int i = 0; i < _eventQueueEntries.size(); ++i) - { + for (int i = 0; i < _eventQueueEntries.size(); ++i) { EventQueueEntry* queueEntry = _eventQueueEntries[i]; TrackEntry* trackEntry = queueEntry->_entry; - switch (queueEntry->_type) - { + switch (queueEntry->_type) { case EventType_Start: case EventType_Interrupt: case EventType_Complete: @@ -356,24 +317,19 @@ namespace Spine _queue(EventQueue::newEventQueue(*this, _trackEntryPool)), _animationsChanged(false), _onAnimationEventFunc(dummyOnAnimationEventFunc), - _timeScale(1) - { + _timeScale(1) { // Empty } - AnimationState::~AnimationState() - { + AnimationState::~AnimationState() { DESTROY(EventQueue, _queue); } - void AnimationState::update(float delta) - { + void AnimationState::update(float delta) { delta *= _timeScale; - for (int i = 0, n = static_cast(_tracks.size()); i < n; ++i) - { + for (int i = 0, n = static_cast(_tracks.size()); i < n; ++i) { TrackEntry* currentP = _tracks[i]; - if (currentP == NULL) - { + if (currentP == NULL) { continue; } @@ -384,11 +340,9 @@ namespace Spine float currentDelta = delta * current._timeScale; - if (current._delay > 0) - { + if (current._delay > 0) { current._delay -= currentDelta; - if (current._delay > 0) - { + if (current._delay > 0) { continue; } currentDelta = -current._delay; @@ -396,26 +350,22 @@ namespace Spine } TrackEntry* next = current._next; - if (next != NULL) - { + if (next != NULL) { // When the next entry's delay is passed, change to the next entry, preserving leftover time. float nextTime = current._trackLast - next->_delay; - if (nextTime >= 0) - { + if (nextTime >= 0) { next->_delay = 0; next->_trackTime = nextTime + (delta * next->_timeScale); current._trackTime += currentDelta; setCurrent(i, next, true); - while (next->_mixingFrom != NULL) - { + while (next->_mixingFrom != NULL) { next->_mixTime += currentDelta; next = next->_mixingFrom; } continue; } } - else if (current._trackLast >= current._trackEnd && current._mixingFrom == NULL) - { + else if (current._trackLast >= current._trackEnd && current._mixingFrom == NULL) { // clear the track when there is no next entry, the track end time is reached, and there is no mixingFrom. _tracks[i] = NULL; @@ -424,13 +374,11 @@ namespace Spine continue; } - if (current._mixingFrom != NULL && updateMixingFrom(currentP, delta)) - { + if (current._mixingFrom != NULL && updateMixingFrom(currentP, delta)) { // End mixing from entries once all have completed. TrackEntry* from = current._mixingFrom; current._mixingFrom = NULL; - while (from != NULL) - { + while (from != NULL) { _queue->end(from); from = from->_mixingFrom; } @@ -442,19 +390,15 @@ namespace Spine _queue->drain(); } - bool AnimationState::apply(Skeleton& skeleton) - { - if (_animationsChanged) - { + bool AnimationState::apply(Skeleton& skeleton) { + if (_animationsChanged) { animationsChanged(); } bool applied = false; - for (int i = 0, n = static_cast(_tracks.size()); i < n; ++i) - { + for (int i = 0, n = static_cast(_tracks.size()); i < n; ++i) { TrackEntry* currentP = _tracks[i]; - if (currentP == NULL || currentP->_delay > 0) - { + if (currentP == NULL || currentP->_delay > 0) { continue; } @@ -465,12 +409,10 @@ namespace Spine // apply mixing from entries first. float mix = current._alpha; - if (current._mixingFrom != NULL) - { + if (current._mixingFrom != NULL) { mix *= applyMixingFrom(currentP, skeleton, currentPose); } - else if (current._trackTime >= current._trackEnd && current._next == NULL) // - { + else if (current._trackTime >= current._trackEnd && current._next == NULL) { mix = 0; // Set to setup pose the last time the entry will be applied. } @@ -478,44 +420,36 @@ namespace Spine float animationLast = current._animationLast, animationTime = current.getAnimationTime(); int timelineCount = static_cast(current._animation->_timelines.size()); Vector& timelines = current._animation->_timelines; - if (mix == 1) - { - for (int ii = 0; ii < timelineCount; ++ii) - { + if (mix == 1) { + for (int ii = 0; ii < timelineCount; ++ii) { timelines[ii]->apply(skeleton, animationLast, animationTime, &_events, 1, MixPose_Setup, MixDirection_In); } } - else - { + else { Vector& timelineData = current._timelineData; bool firstFrame = current._timelinesRotation.size() == 0; - if (firstFrame) - { + if (firstFrame) { current._timelinesRotation.reserve(timelines.size() << 1); current._timelinesRotation.setSize(timelines.size() << 1); } Vector& timelinesRotation = current._timelinesRotation; - for (int ii = 0; ii < timelineCount; ++ii) - { + for (int ii = 0; ii < timelineCount; ++ii) { Timeline* timeline = timelines[ii]; assert(timeline); MixPose pose = timelineData[ii] >= AnimationState::First ? MixPose_Setup : currentPose; RotateTimeline* rotateTimeline = NULL; - if (timeline->getRTTI().derivesFrom(RotateTimeline::rtti)) - { + if (timeline->getRTTI().derivesFrom(RotateTimeline::rtti)) { rotateTimeline = static_cast(timeline); } - if (rotateTimeline != NULL) - { + if (rotateTimeline != NULL) { applyRotateTimeline(rotateTimeline, skeleton, animationTime, mix, pose, timelinesRotation, ii << 1, firstFrame); } - else - { + else { timeline->apply(skeleton, animationLast, animationTime, &_events, mix, pose, MixDirection_In); } } @@ -531,12 +465,10 @@ namespace Spine return applied; } - void AnimationState::clearTracks() - { + void AnimationState::clearTracks() { bool oldDrainDisabled = _queue->_drainDisabled; _queue->_drainDisabled = true; - for (int i = 0, n = static_cast(_tracks.size()); i < n; ++i) - { + for (int i = 0, n = static_cast(_tracks.size()); i < n; ++i) { clearTrack(i); } _tracks.clear(); @@ -544,16 +476,13 @@ namespace Spine _queue->drain(); } - void AnimationState::clearTrack(int trackIndex) - { - if (trackIndex >= _tracks.size()) - { + void AnimationState::clearTrack(int trackIndex) { + if (trackIndex >= _tracks.size()) { return; } TrackEntry* current = _tracks[trackIndex]; - if (current == NULL) - { + if (current == NULL) { return; } @@ -562,11 +491,9 @@ namespace Spine disposeNext(current); TrackEntry* entry = current; - while (true) - { + while (true) { TrackEntry* from = entry->_mixingFrom; - if (from == NULL) - { + if (from == NULL) { break; } @@ -580,24 +507,20 @@ namespace Spine _queue->drain(); } - TrackEntry* AnimationState::setAnimation(int trackIndex, std::string animationName, bool loop) - { + TrackEntry* AnimationState::setAnimation(int trackIndex, std::string animationName, bool loop) { Animation* animation = _data._skeletonData.findAnimation(animationName); assert(animation != NULL); return setAnimation(trackIndex, animation, loop); } - TrackEntry* AnimationState::setAnimation(int trackIndex, Animation* animation, bool loop) - { + TrackEntry* AnimationState::setAnimation(int trackIndex, Animation* animation, bool loop) { assert(animation != NULL); bool interrupt = true; TrackEntry* current = expandToIndex(trackIndex); - if (current != NULL) - { - if (current->_nextTrackLast == -1) - { + if (current != NULL) { + if (current->_nextTrackLast == -1) { // Don't mix from an entry that was never applied. _tracks[trackIndex] = current->_mixingFrom; _queue->interrupt(current); @@ -606,8 +529,7 @@ namespace Spine current = current->_mixingFrom; interrupt = false; } - else - { + else { disposeNext(current); } } @@ -619,46 +541,37 @@ namespace Spine return entry; } - TrackEntry* AnimationState::addAnimation(int trackIndex, std::string animationName, bool loop, float delay) - { + TrackEntry* AnimationState::addAnimation(int trackIndex, std::string animationName, bool loop, float delay) { Animation* animation = _data._skeletonData.findAnimation(animationName); assert(animation != NULL); return addAnimation(trackIndex, animation, loop, delay); } - TrackEntry* AnimationState::addAnimation(int trackIndex, Animation* animation, bool loop, float delay) - { + TrackEntry* AnimationState::addAnimation(int trackIndex, Animation* animation, bool loop, float delay) { assert(animation != NULL); TrackEntry* last = expandToIndex(trackIndex); - if (last != NULL) - { - while (last->_next != NULL) - { + if (last != NULL) { + while (last->_next != NULL) { last = last->_next; } } TrackEntry* entry = newTrackEntry(trackIndex, animation, loop, last); - if (last == NULL) - { + if (last == NULL) { setCurrent(trackIndex, entry, true); _queue->drain(); } - else - { + else { last->_next = entry; - if (delay <= 0) - { + if (delay <= 0) { float duration = last->_animationEnd - last->_animationStart; - if (duration != 0) - { + if (duration != 0) { delay += duration * (1 + (int)(last->_trackTime / duration)) - _data.getMix(last->_animation, animation); } - else - { + else { delay = 0; } } @@ -668,18 +581,15 @@ namespace Spine return entry; } - TrackEntry* AnimationState::setEmptyAnimation(int trackIndex, float mixDuration) - { + TrackEntry* AnimationState::setEmptyAnimation(int trackIndex, float mixDuration) { TrackEntry* entry = setAnimation(trackIndex, AnimationState::getEmptyAnimation(), false); entry->_mixDuration = mixDuration; entry->_trackEnd = mixDuration; return entry; } - TrackEntry* AnimationState::addEmptyAnimation(int trackIndex, float mixDuration, float delay) - { - if (delay <= 0) - { + TrackEntry* AnimationState::addEmptyAnimation(int trackIndex, float mixDuration, float delay) { + if (delay <= 0) { delay -= mixDuration; } @@ -689,15 +599,12 @@ namespace Spine return entry; } - void AnimationState::setEmptyAnimations(float mixDuration) - { + void AnimationState::setEmptyAnimations(float mixDuration) { bool oldDrainDisabled = _queue->_drainDisabled; _queue->_drainDisabled = true; - for (int i = 0, n = static_cast(_tracks.size()); i < n; ++i) - { + for (int i = 0, n = static_cast(_tracks.size()); i < n; ++i) { TrackEntry* current = _tracks[i]; - if (current != NULL) - { + if (current != NULL) { setEmptyAnimation(i, mixDuration); } } @@ -705,84 +612,69 @@ namespace Spine _queue->drain(); } - TrackEntry* AnimationState::getCurrent(int trackIndex) - { + TrackEntry* AnimationState::getCurrent(int trackIndex) { return trackIndex >= _tracks.size() ? NULL : _tracks[trackIndex]; } - AnimationStateData& AnimationState::getData() - { + AnimationStateData& AnimationState::getData() { return _data; } - Vector AnimationState::getTracks() - { + Vector AnimationState::getTracks() { return _tracks; } - float AnimationState::getTimeScale() - { + float AnimationState::getTimeScale() { return _timeScale; } - void AnimationState::setTimeScale(float inValue) - { + void AnimationState::setTimeScale(float inValue) { _timeScale = inValue; } - void AnimationState::setOnAnimationEventFunc(OnAnimationEventFunc inValue) - { + void AnimationState::setOnAnimationEventFunc(OnAnimationEventFunc inValue) { _onAnimationEventFunc = inValue; } - void AnimationState::setRendererObject(void* inValue) - { + void AnimationState::setRendererObject(void* inValue) { _rendererObject = inValue; } - void* AnimationState::getRendererObject() - { + void* AnimationState::getRendererObject() { return _rendererObject; } - Animation* AnimationState::getEmptyAnimation() - { + Animation* AnimationState::getEmptyAnimation() { static Vector timelines; static Animation ret(std::string(""), timelines, 0); return &ret; } - void AnimationState::applyRotateTimeline(RotateTimeline* rotateTimeline, Skeleton& skeleton, float time, float alpha, MixPose pose, Vector& timelinesRotation, int i, bool firstFrame) - { - if (firstFrame) - { + void AnimationState::applyRotateTimeline(RotateTimeline* rotateTimeline, Skeleton& skeleton, float time, float alpha, MixPose pose, Vector& timelinesRotation, int i, bool firstFrame) { + if (firstFrame) { timelinesRotation[i] = 0; } - if (alpha == 1) - { + if (alpha == 1) { rotateTimeline->apply(skeleton, 0, time, NULL, 1, pose, MixDirection_In); return; } Bone* bone = skeleton._bones[rotateTimeline->_boneIndex]; Vector frames = rotateTimeline->_frames; - if (time < frames[0]) - { - if (pose == MixPose_Setup) - { + if (time < frames[0]) { + if (pose == MixPose_Setup) { bone->_rotation = bone->_data._rotation; } return; } float r2; - if (time >= frames[frames.size() - RotateTimeline::ENTRIES]) // Time is after last frame. - { + if (time >= frames[frames.size() - RotateTimeline::ENTRIES]) { + // Time is after last frame. r2 = bone->_data._rotation + frames[frames.size() + RotateTimeline::PREV_ROTATION]; } - else - { + else { // Interpolate between the previous frame and the current frame. int frame = Animation::binarySearch(frames, time, RotateTimeline::ENTRIES); float prevRotation = frames[frame + RotateTimeline::PREV_ROTATION]; @@ -798,40 +690,33 @@ namespace Spine // Mix between rotations using the direction of the shortest route on the first frame while detecting crosses. float r1 = pose == MixPose_Setup ? bone->_data._rotation : bone->_rotation; float total, diff = r2 - r1; - if (diff == 0) - { + if (diff == 0) { total = timelinesRotation[i]; } - else - { + else { diff -= (16384 - (int)(16384.499999999996 - diff / 360)) * 360; float lastTotal, lastDiff; - if (firstFrame) - { + if (firstFrame) { lastTotal = 0; lastDiff = diff; } - else - { + else { lastTotal = timelinesRotation[i]; // Angle and direction of mix, including loops. lastDiff = timelinesRotation[i + 1]; // Difference between bones. } bool current = diff > 0, dir = lastTotal >= 0; // Detect cross at 0 (not 180). - if (sign(lastDiff) != sign(diff) && fabs(lastDiff) <= 90) - { + if (sign(lastDiff) != sign(diff) && fabs(lastDiff) <= 90) { // A cross after a 360 rotation is a loop. - if (fabs(lastTotal) > 180) - { + if (fabs(lastTotal) > 180) { lastTotal += 360 * sign(lastTotal); } dir = current; } total = diff + lastTotal - fmod(lastTotal, 360); // Store loops as part of lastTotal. - if (dir != current) - { + if (dir != current) { total += 360 * sign(lastTotal); } timelinesRotation[i] = total; @@ -841,22 +726,18 @@ namespace Spine bone->_rotation = r1 - (16384 - (int)(16384.499999999996 - r1 / 360)) * 360; } - bool AnimationState::updateMixingFrom(TrackEntry* to, float delta) - { + bool AnimationState::updateMixingFrom(TrackEntry* to, float delta) { TrackEntry* from = to->_mixingFrom; - if (from == NULL) - { + if (from == NULL) { return true; } bool finished = updateMixingFrom(from, delta); // Require mixTime > 0 to ensure the mixing from entry was applied at least once. - if (to->_mixTime > 0 && (to->_mixTime >= to->_mixDuration || to->_timeScale == 0)) - { + if (to->_mixTime > 0 && (to->_mixTime >= to->_mixDuration || to->_timeScale == 0)) { // Require totalAlpha == 0 to ensure mixing is complete, unless mixDuration == 0 (the transition is a single frame). - if (from->_totalAlpha == 0 || to->_mixDuration == 0) - { + if (from->_totalAlpha == 0 || to->_mixDuration == 0) { to->_mixingFrom = from->_mixingFrom; to->_interruptAlpha = from->_interruptAlpha; _queue->end(from); @@ -872,26 +753,21 @@ namespace Spine return false; } - float AnimationState::applyMixingFrom(TrackEntry* to, Skeleton& skeleton, MixPose currentPose) - { + float AnimationState::applyMixingFrom(TrackEntry* to, Skeleton& skeleton, MixPose currentPose) { TrackEntry* from = to->_mixingFrom; - if (from->_mixingFrom != NULL) - { + if (from->_mixingFrom != NULL) { applyMixingFrom(from, skeleton, currentPose); } float mix; - if (to->_mixDuration == 0) - { + if (to->_mixDuration == 0) { // Single frame mix to undo mixingFrom changes. mix = 1; currentPose = MixPose_Setup; } - else - { + else { mix = to->_mixTime / to->_mixDuration; - if (mix > 1) - { + if (mix > 1) { mix = 1; } } @@ -905,8 +781,7 @@ namespace Spine Vector& timelineDipMix = from->_timelineDipMix; bool firstFrame = from->_timelinesRotation.size() == 0; - if (firstFrame) - { + if (firstFrame) { // from.timelinesRotation.setSize from->_timelinesRotation.reserve(timelines.size() << 1); from->_timelinesRotation.setSize(timelines.size() << 1); @@ -917,18 +792,14 @@ namespace Spine MixPose pose; float alphaDip = from->_alpha * to->_interruptAlpha, alphaMix = alphaDip * (1 - mix), alpha; from->_totalAlpha = 0; - for (int i = 0; i < timelineCount; ++i) - { + for (int i = 0; i < timelineCount; ++i) { Timeline* timeline = timelines[i]; - switch (timelineData[i]) - { + switch (timelineData[i]) { case Subsequent: - if (!attachments && timeline->getRTTI().derivesFrom(AttachmentTimeline::rtti)) - { + if (!attachments && timeline->getRTTI().derivesFrom(AttachmentTimeline::rtti)) { continue; } - if (!drawOrder && timeline->getRTTI().derivesFrom(DrawOrderTimeline::rtti)) - { + if (!drawOrder && timeline->getRTTI().derivesFrom(DrawOrderTimeline::rtti)) { continue; } @@ -952,23 +823,19 @@ namespace Spine from->_totalAlpha += alpha; RotateTimeline* rotateTimeline = NULL; - if (timeline->getRTTI().derivesFrom(RotateTimeline::rtti)) - { + if (timeline->getRTTI().derivesFrom(RotateTimeline::rtti)) { rotateTimeline = static_cast(timeline); } - if (rotateTimeline != NULL) - { + if (rotateTimeline != NULL) { applyRotateTimeline(rotateTimeline, skeleton, animationTime, alpha, pose, timelinesRotation, i << 1, firstFrame); } - else - { + else { timeline->apply(skeleton, animationLast, animationTime, eventBuffer, alpha, pose, MixDirection_Out); } } - if (to->_mixDuration > 0) - { + if (to->_mixDuration > 0) { queueEvents(from, animationTime); } @@ -979,23 +846,19 @@ namespace Spine return mix; } - void AnimationState::queueEvents(TrackEntry* entry, float animationTime) - { + void AnimationState::queueEvents(TrackEntry* entry, float animationTime) { float animationStart = entry->_animationStart, animationEnd = entry->_animationEnd; float duration = animationEnd - animationStart; float trackLastWrapped = fmodf(entry->_trackLast, duration); // Queue events before complete. int i = 0, n = static_cast(_events.size()); - for (; i < n; ++i) - { + for (; i < n; ++i) { Event* e = _events[i]; - if (e->_time < trackLastWrapped) - { + if (e->_time < trackLastWrapped) { break; } - if (e->_time > animationEnd) - { + if (e->_time > animationEnd) { // Discard events outside animation start/end. continue; } @@ -1003,17 +866,14 @@ namespace Spine } // Queue complete if completed a loop iteration or the animation. - if (entry->_loop ? (trackLastWrapped > fmod(entry->_trackTime, duration)) : (animationTime >= animationEnd && entry->_animationLast < animationEnd)) - { + if (entry->_loop ? (trackLastWrapped > fmod(entry->_trackTime, duration)) : (animationTime >= animationEnd && entry->_animationLast < animationEnd)) { _queue->complete(entry); } // Queue events after complete. - for (; i < n; ++i) - { + for (; i < n; ++i) { Event* e = _events[i]; - if (e->_time < animationStart) - { + if (e->_time < animationStart) { // Discard events outside animation start/end. continue; } @@ -1021,15 +881,12 @@ namespace Spine } } - void AnimationState::setCurrent(int index, TrackEntry* current, bool interrupt) - { + void AnimationState::setCurrent(int index, TrackEntry* current, bool interrupt) { TrackEntry* from = expandToIndex(index); _tracks[index] = current; - if (from != NULL) - { - if (interrupt) - { + if (from != NULL) { + if (interrupt) { _queue->interrupt(from); } @@ -1037,8 +894,7 @@ namespace Spine current->_mixTime = 0; // Store interrupted mix percentage. - if (from->_mixingFrom != NULL && from->_mixDuration > 0) - { + if (from->_mixingFrom != NULL && from->_mixDuration > 0) { current->_interruptAlpha *= MIN(1, from->_mixTime / from->_mixDuration); } @@ -1048,23 +904,19 @@ namespace Spine _queue->start(current); // triggers animationsChanged } - TrackEntry* AnimationState::expandToIndex(int index) - { - if (index < _tracks.size()) - { + TrackEntry* AnimationState::expandToIndex(int index) { + if (index < _tracks.size()) { return _tracks[index]; } - while (index >= _tracks.size()) - { + while (index >= _tracks.size()) { _tracks.push_back(NULL); } return NULL; } - TrackEntry* AnimationState::newTrackEntry(int trackIndex, Animation* animation, bool loop, TrackEntry* last) - { + TrackEntry* AnimationState::newTrackEntry(int trackIndex, Animation* animation, bool loop, TrackEntry* last) { TrackEntry* entryP = _trackEntryPool.obtain(); // Pooling TrackEntry& entry = *entryP; @@ -1096,28 +948,23 @@ namespace Spine return entryP; } - void AnimationState::disposeNext(TrackEntry* entry) - { + void AnimationState::disposeNext(TrackEntry* entry) { TrackEntry* next = entry->_next; - while (next != NULL) - { + while (next != NULL) { _queue->dispose(next); next = next->_next; } entry->_next = NULL; } - void AnimationState::animationsChanged() - { + void AnimationState::animationsChanged() { _animationsChanged = false; _propertyIDs.clear(); - for (int i = 0, n = static_cast(_tracks.size()); i < n; ++i) - { + for (int i = 0, n = static_cast(_tracks.size()); i < n; ++i) { TrackEntry* entry = _tracks[i]; - if (entry != NULL) - { + if (entry != NULL) { entry->setTimelineData(NULL, _mixingTo, _propertyIDs); } } diff --git a/spine-cpp/spine-cpp/src/spine/AnimationStateData.cpp b/spine-cpp/spine-cpp/src/spine/AnimationStateData.cpp index 00dc79ced..3f1e9e173 100644 --- a/spine-cpp/spine-cpp/src/spine/AnimationStateData.cpp +++ b/spine-cpp/spine-cpp/src/spine/AnimationStateData.cpp @@ -35,21 +35,18 @@ namespace Spine { - AnimationStateData::AnimationStateData(SkeletonData& skeletonData) : _skeletonData(skeletonData), _defaultMix(0) - { + AnimationStateData::AnimationStateData(SkeletonData& skeletonData) : _skeletonData(skeletonData), _defaultMix(0) { // Empty } - void AnimationStateData::setMix(std::string fromName, std::string toName, float duration) - { + void AnimationStateData::setMix(std::string fromName, std::string toName, float duration) { Animation* from = _skeletonData.findAnimation(fromName); Animation* to = _skeletonData.findAnimation(toName); setMix(from, to, duration); } - void AnimationStateData::setMix(Animation* from, Animation* to, float duration) - { + void AnimationStateData::setMix(Animation* from, Animation* to, float duration) { assert(from != NULL); assert(to != NULL); @@ -59,8 +56,7 @@ namespace Spine _animationToMixTime.insert(key, duration); } - float AnimationStateData::getMix(Animation* from, Animation* to) - { + float AnimationStateData::getMix(Animation* from, Animation* to) { assert(from != NULL); assert(to != NULL); @@ -68,52 +64,43 @@ namespace Spine HashMap::Iterator i = _animationToMixTime.find(key); - if (i != _animationToMixTime.end()) - { + if (i != _animationToMixTime.end()) { return i.second(); } return _defaultMix; } - SkeletonData& AnimationStateData::getSkeletonData() - { + SkeletonData& AnimationStateData::getSkeletonData() { return _skeletonData; } - float AnimationStateData::getDefaultMix() - { + float AnimationStateData::getDefaultMix() { return _defaultMix; } - void AnimationStateData::setDefaultMix(float inValue) - { + void AnimationStateData::setDefaultMix(float inValue) { _defaultMix = inValue; } - AnimationStateData::AnimationPair::AnimationPair(Animation* a1, Animation* a2) : _a1(a1), _a2(a2) - { + AnimationStateData::AnimationPair::AnimationPair(Animation* a1, Animation* a2) : _a1(a1), _a2(a2) { // Empty } - bool AnimationStateData::AnimationPair::operator==(const AnimationPair &other) const - { + bool AnimationStateData::AnimationPair::operator==(const AnimationPair &other) const { return _a1->_name == other._a1->_name && _a2->_name == other._a2->_name; } - std::size_t AnimationStateData::HashAnimationPair::operator()(const Spine::AnimationStateData::AnimationPair& val) const - { + std::size_t AnimationStateData::HashAnimationPair::operator()(const Spine::AnimationStateData::AnimationPair& val) const { std::size_t h1 = 7; size_t strlen = val._a1->_name.length(); - for (int i = 0; i < strlen; ++i) - { + for (int i = 0; i < strlen; ++i) { h1 = h1 * 31 + val._a1->_name.at(i); } std::size_t h2 = 7; strlen = val._a2->_name.length(); - for (int i = 0; i < strlen; ++i) - { + for (int i = 0; i < strlen; ++i) { h2 = h2 * 31 + val._a2->_name.at(i); } diff --git a/spine-cpp/spine-cpp/src/spine/Atlas.cpp b/spine-cpp/spine-cpp/src/spine/Atlas.cpp index 478bb0aec..5c41d1918 100644 --- a/spine-cpp/spine-cpp/src/spine/Atlas.cpp +++ b/spine-cpp/spine-cpp/src/spine/Atlas.cpp @@ -38,8 +38,7 @@ namespace Spine { - Atlas::Atlas(const char* path, TextureLoader& textureLoader) : _textureLoader(textureLoader) - { + Atlas::Atlas(const char* path, TextureLoader& textureLoader) : _textureLoader(textureLoader) { int dirLength; char *dir; int length; @@ -56,8 +55,7 @@ namespace Spine dir[dirLength] = '\0'; data = SPINE_EXTENSION->spineReadFile(path, &length); - if (data) - { + if (data) { load(data, length, dir); } @@ -65,21 +63,17 @@ namespace Spine FREE(dir); } - Atlas::Atlas(const char* data, int length, const char* dir, TextureLoader& textureLoader) : _textureLoader(textureLoader) - { + Atlas::Atlas(const char* data, int length, const char* dir, TextureLoader& textureLoader) : _textureLoader(textureLoader) { load(data, length, dir); } - Atlas::~Atlas() - { + Atlas::~Atlas() { ContainerUtil::cleanUpVectorOfPointers(_pages); ContainerUtil::cleanUpVectorOfPointers(_regions); } - void Atlas::flipV() - { - for (size_t i = 0, n = _regions.size(); i < n; ++i) - { + void Atlas::flipV() { + for (size_t i = 0, n = _regions.size(); i < n; ++i) { AtlasRegion* regionP = _regions[i]; AtlasRegion& region = *regionP; region.v = 1 - region.v; @@ -87,12 +81,9 @@ namespace Spine } } - AtlasRegion* Atlas::findRegion(std::string name) - { - for (size_t i = 0, n = _regions.size(); i < n; ++i) - { - if (_regions[i]->name == name) - { + AtlasRegion* Atlas::findRegion(std::string name) { + for (size_t i = 0, n = _regions.size(); i < n; ++i) { + if (_regions[i]->name == name) { return _regions[i]; } } @@ -100,16 +91,13 @@ namespace Spine return NULL; } - void Atlas::dispose() - { - for (size_t i = 0, n = _pages.size(); i < n; ++i) - { + void Atlas::dispose() { + for (size_t i = 0, n = _pages.size(); i < n; ++i) { _textureLoader.unload(_pages[i]->rendererObject); } } - void Atlas::load(const char* begin, int length, const char* dir) - { + void Atlas::load(const char* begin, int length, const char* dir) { static const char* formatNames[] = { "", "Alpha", "Intensity", "LuminanceAlpha", "RGB565", "RGBA4444", "RGB888", "RGBA8888" }; static const char* textureFilterNames[] = { "", "Nearest", "Linear", "MipMap", "MipMapNearestNearest", "MipMapLinearNearest", "MipMapNearestLinear", "MipMapLinearLinear" }; @@ -123,19 +111,15 @@ namespace Spine Str str; Str tuple[4]; - while (readLine(&begin, end, &str)) - { - if (str.end - str.begin == 0) - { + while (readLine(&begin, end, &str)) { + if (str.end - str.begin == 0) { page = 0; } - else if (!page) - { + else if (!page) { char* name = mallocString(&str); char* path = MALLOC(char, dirLength + needsSlash + strlen(name) + 1); memcpy(path, dir, dirLength); - if (needsSlash) - { + if (needsSlash) { path[dirLength] = '/'; } strcpy(path + dirLength + needsSlash, name); @@ -163,21 +147,16 @@ namespace Spine page->uWrap = TextureWrap_ClampToEdge; page->vWrap = TextureWrap_ClampToEdge; - if (!equals(&str, "none")) - { - if (str.end - str.begin == 1) - { - if (*str.begin == 'x') - { + if (!equals(&str, "none")) { + if (str.end - str.begin == 1) { + if (*str.begin == 'x') { page->uWrap = TextureWrap_Repeat; } - else if (*str.begin == 'y') - { + else if (*str.begin == 'y') { page->vWrap = TextureWrap_Repeat; } } - else if (equals(&str, "xy")) - { + else if (equals(&str, "xy")) { page->uWrap = TextureWrap_Repeat; page->vWrap = TextureWrap_Repeat; } @@ -189,8 +168,7 @@ namespace Spine _pages.push_back(page); } - else - { + else { AtlasRegion* region = NEW(AtlasRegion); new (region) AtlasRegion(); @@ -210,13 +188,11 @@ namespace Spine region->u = region->x / (float)page->width; region->v = region->y / (float)page->height; - if (region->rotate) - { + if (region->rotate) { region->u2 = (region->x + region->height) / (float)page->width; region->v2 = (region->y + region->width) / (float)page->height; } - else - { + else { region->u2 = (region->x + region->width) / (float)page->width; region->v2 = (region->y + region->height) / (float)page->height; } @@ -224,8 +200,7 @@ namespace Spine count = readTuple(&begin, end, tuple); assert(count); - if (count == 4) - { + if (count == 4) { /* split is optional */ region->splits.reserve(4); region->splits.setSize(4); @@ -237,8 +212,7 @@ namespace Spine count = readTuple(&begin, end, tuple); assert(count); - if (count == 4) - { + if (count == 4) { /* pad is optional, but only present with splits */ region->pads.reserve(4); region->pads.setSize(4); @@ -267,67 +241,55 @@ namespace Spine } } - void Atlas::trim(Str* str) - { - while (isspace((unsigned char)*str->begin) && str->begin < str->end) - { + void Atlas::trim(Str* str) { + while (isspace((unsigned char)*str->begin) && str->begin < str->end) { (str->begin)++; } - if (str->begin == str->end) - { + if (str->begin == str->end) { return; } str->end--; - while (isspace((unsigned char)*str->end) && str->end >= str->begin) - { + while (isspace((unsigned char)*str->end) && str->end >= str->begin) { str->end--; } str->end++; } - int Atlas::readLine(const char** begin, const char* end, Str* str) - { - if (*begin == end) - { + int Atlas::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') - { + while (*begin != end && **begin != '\n') { (*begin)++; } str->end = *begin; trim(str); - if (*begin != end) - { + if (*begin != end) { (*begin)++; } return 1; } - int Atlas::beginPast(Str* str, char c) - { + int Atlas::beginPast(Str* str, char c) { const char* begin = str->begin; - while (1) - { + while (1) { char lastSkippedChar = *begin; - if (begin == str->end) - { + if (begin == str->end) { return 0; } begin++; - if (lastSkippedChar == c) - { + if (lastSkippedChar == c) { break; } } @@ -335,11 +297,9 @@ namespace Spine return 1; } - int Atlas::readValue(const char** begin, const char* end, Str* str) - { + int Atlas::readValue(const char** begin, const char* end, Str* str) { readLine(begin, end, str); - if (!beginPast(str, ':')) - { + if (!beginPast(str, ':')) { return 0; } @@ -347,21 +307,17 @@ namespace Spine return 1; } - int Atlas::readTuple(const char** begin, const char* end, Str tuple[]) - { + int Atlas::readTuple(const char** begin, const char* end, Str tuple[]) { int i; Str str = { NULL, NULL }; readLine(begin, end, &str); - if (!beginPast(&str, ':')) - { + if (!beginPast(&str, ':')) { return 0; } - for (i = 0; i < 3; ++i) - { + for (i = 0; i < 3; ++i) { tuple[i].begin = str.begin; - if (!beginPast(&str, ',')) - { + if (!beginPast(&str, ',')) { break; } @@ -376,8 +332,7 @@ namespace Spine return i + 1; } - char* Atlas::mallocString(Str* str) - { + char* Atlas::mallocString(Str* str) { int length = (int)(str->end - str->begin); char* string = MALLOC(char, length + 1); memcpy(string, str->begin, length); @@ -385,27 +340,22 @@ namespace Spine return string; } - int Atlas::indexOf(const char** array, int count, Str* str) - { + int Atlas::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) - { + for (i = count - 1; i >= 0; i--) { + if (strncmp(array[i], str->begin, length) == 0) { return i; } } return 0; } - int Atlas::equals(Str* str, const char* other) - { + int Atlas::equals(Str* str, const char* other) { return strncmp(other, str->begin, str->end - str->begin) == 0; } - int Atlas::toInt(Str* str) - { + int Atlas::toInt(Str* str) { return (int)strtol(str->begin, (char**)&str->end, 10); } } diff --git a/spine-cpp/spine-cpp/src/spine/AtlasAttachmentLoader.cpp b/spine-cpp/spine-cpp/src/spine/AtlasAttachmentLoader.cpp index 3cbc3c5c8..4509a071c 100644 --- a/spine-cpp/spine-cpp/src/spine/AtlasAttachmentLoader.cpp +++ b/spine-cpp/spine-cpp/src/spine/AtlasAttachmentLoader.cpp @@ -44,13 +44,11 @@ namespace Spine { RTTI_IMPL(AtlasAttachmentLoader, AttachmentLoader); - AtlasAttachmentLoader::AtlasAttachmentLoader(Vector& inAtlasArray) : AttachmentLoader(), _atlasArray(inAtlasArray) - { + AtlasAttachmentLoader::AtlasAttachmentLoader(Vector& inAtlasArray) : AttachmentLoader(), _atlasArray(inAtlasArray) { // Empty } - RegionAttachment* AtlasAttachmentLoader::newRegionAttachment(Skin& skin, std::string name, std::string path) - { + RegionAttachment* AtlasAttachmentLoader::newRegionAttachment(Skin& skin, std::string name, std::string path) { AtlasRegion* regionP = findRegion(path); assert(regionP != NULL); @@ -72,8 +70,7 @@ namespace Spine return attachmentP; } - MeshAttachment* AtlasAttachmentLoader::newMeshAttachment(Skin& skin, std::string name, std::string path) - { + MeshAttachment* AtlasAttachmentLoader::newMeshAttachment(Skin& skin, std::string name, std::string path) { AtlasRegion* regionP = findRegion(path); assert(regionP != NULL); @@ -99,47 +96,40 @@ namespace Spine return attachmentP; } - BoundingBoxAttachment* AtlasAttachmentLoader::newBoundingBoxAttachment(Skin& skin, std::string name) - { + BoundingBoxAttachment* AtlasAttachmentLoader::newBoundingBoxAttachment(Skin& skin, std::string name) { BoundingBoxAttachment* attachmentP = NEW(BoundingBoxAttachment); new (attachmentP) BoundingBoxAttachment(name); return attachmentP; } - PathAttachment* AtlasAttachmentLoader::newPathAttachment(Skin& skin, std::string name) - { + PathAttachment* AtlasAttachmentLoader::newPathAttachment(Skin& skin, std::string name) { PathAttachment* attachmentP = NEW(PathAttachment); new (attachmentP) PathAttachment(name); return attachmentP; } - PointAttachment* AtlasAttachmentLoader::newPointAttachment(Skin& skin, std::string name) - { + PointAttachment* AtlasAttachmentLoader::newPointAttachment(Skin& skin, std::string name) { PointAttachment* attachmentP = NEW(PointAttachment); new (attachmentP) PointAttachment(name); return attachmentP; } - ClippingAttachment* AtlasAttachmentLoader::newClippingAttachment(Skin& skin, std::string name) - { + ClippingAttachment* AtlasAttachmentLoader::newClippingAttachment(Skin& skin, std::string name) { ClippingAttachment* attachmentP = NEW(ClippingAttachment); new (attachmentP) ClippingAttachment(name); return attachmentP; } - AtlasRegion* AtlasAttachmentLoader::findRegion(std::string name) - { + AtlasRegion* AtlasAttachmentLoader::findRegion(std::string name) { AtlasRegion* ret; - for (int i = 0; i < _atlasArray.size(); i++) - { + for (int i = 0; i < _atlasArray.size(); i++) { ret = _atlasArray[i]->findRegion(name); - if (ret != NULL) - { + if (ret != NULL) { return ret; } } diff --git a/spine-cpp/spine-cpp/src/spine/Attachment.cpp b/spine-cpp/spine-cpp/src/spine/Attachment.cpp index 74a734f27..b977277a0 100644 --- a/spine-cpp/spine-cpp/src/spine/Attachment.cpp +++ b/spine-cpp/spine-cpp/src/spine/Attachment.cpp @@ -36,13 +36,11 @@ namespace Spine { RTTI_IMPL_NOPARENT(Attachment); - Attachment::Attachment(std::string name) : _name(name) - { + Attachment::Attachment(std::string name) : _name(name) { assert(_name.length() > 0); } - const std::string& Attachment::getName() - { + const std::string& Attachment::getName() { return _name; } } diff --git a/spine-cpp/spine-cpp/src/spine/AttachmentLoader.cpp b/spine-cpp/spine-cpp/src/spine/AttachmentLoader.cpp index 93e848ab7..b6ab71714 100644 --- a/spine-cpp/spine-cpp/src/spine/AttachmentLoader.cpp +++ b/spine-cpp/spine-cpp/src/spine/AttachmentLoader.cpp @@ -42,13 +42,11 @@ namespace Spine { RTTI_IMPL_NOPARENT(AttachmentLoader); - AttachmentLoader::AttachmentLoader() - { + AttachmentLoader::AttachmentLoader() { // Empty } - AttachmentLoader::~AttachmentLoader() - { + AttachmentLoader::~AttachmentLoader() { // Empty } } diff --git a/spine-cpp/spine-cpp/src/spine/AttachmentTimeline.cpp b/spine-cpp/spine-cpp/src/spine/AttachmentTimeline.cpp index 1fb01c0dc..f6a68c62c 100644 --- a/spine-cpp/spine-cpp/src/spine/AttachmentTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/AttachmentTimeline.cpp @@ -42,38 +42,32 @@ namespace Spine { RTTI_IMPL(AttachmentTimeline, Timeline); - AttachmentTimeline::AttachmentTimeline(int frameCount) : Timeline(), _slotIndex(0) - { + AttachmentTimeline::AttachmentTimeline(int frameCount) : Timeline(), _slotIndex(0) { _frames.reserve(frameCount); _attachmentNames.reserve(frameCount); _frames.setSize(frameCount); - for (int i = 0; i < frameCount; ++i) - { + for (int i = 0; i < frameCount; ++i) { _attachmentNames.push_back(std::string("")); } } - void AttachmentTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) - { + void AttachmentTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) { assert(_slotIndex < skeleton._slots.size()); std::string attachmentName; Slot* slotP = skeleton._slots[_slotIndex]; Slot& slot = *slotP; - if (direction == MixDirection_Out && pose == MixPose_Setup) - { + if (direction == MixDirection_Out && pose == MixPose_Setup) { attachmentName = slot._data._attachmentName; slot._attachment = attachmentName.length() == 0 ? NULL : skeleton.getAttachment(_slotIndex, attachmentName); return; } - if (time < _frames[0]) - { + if (time < _frames[0]) { // Time is before first frame. - if (pose == MixPose_Setup) - { + if (pose == MixPose_Setup) { attachmentName = slot._data._attachmentName; slot._attachment = attachmentName.length() == 0 ? NULL : skeleton.getAttachment(_slotIndex, attachmentName); } @@ -81,12 +75,11 @@ namespace Spine } int frameIndex; - if (time >= _frames[_frames.size() - 1]) // Time is after last frame. - { + if (time >= _frames[_frames.size() - 1]) { + // Time is after last frame. frameIndex = static_cast(_frames.size()) - 1; } - else - { + else { frameIndex = Animation::binarySearch(_frames, time, 1) - 1; } @@ -94,49 +87,40 @@ namespace Spine slot._attachment = attachmentName.length() == 0 ? NULL : skeleton.getAttachment(_slotIndex, attachmentName); } - int AttachmentTimeline::getPropertyId() - { + int AttachmentTimeline::getPropertyId() { return ((int)TimelineType_Attachment << 24) + _slotIndex; } - void AttachmentTimeline::setFrame(int frameIndex, float time, std::string attachmentName) - { + void AttachmentTimeline::setFrame(int frameIndex, float time, std::string attachmentName) { _frames[frameIndex] = time; _attachmentNames[frameIndex] = attachmentName; } - int AttachmentTimeline::getSlotIndex() - { + int AttachmentTimeline::getSlotIndex() { return _slotIndex; } - void AttachmentTimeline::setSlotIndex(int inValue) - { + void AttachmentTimeline::setSlotIndex(int inValue) { _slotIndex = inValue; } - Vector& AttachmentTimeline::getFrames() - { + Vector& AttachmentTimeline::getFrames() { return _frames; } - void AttachmentTimeline::setFrames(Vector& inValue) - { + void AttachmentTimeline::setFrames(Vector& inValue) { _frames = inValue; } - Vector AttachmentTimeline::getAttachmentNames() - { + Vector AttachmentTimeline::getAttachmentNames() { return _attachmentNames; } - void AttachmentTimeline::setAttachmentNames(Vector& inValue) - { + void AttachmentTimeline::setAttachmentNames(Vector& inValue) { _attachmentNames = inValue; } - int AttachmentTimeline::getFrameCount() - { + int AttachmentTimeline::getFrameCount() { return static_cast(_frames.size()); } } diff --git a/spine-cpp/spine-cpp/src/spine/Bone.cpp b/spine-cpp/spine-cpp/src/spine/Bone.cpp index 14ffbf850..1b4db4928 100644 --- a/spine-cpp/spine-cpp/src/spine/Bone.cpp +++ b/spine-cpp/spine-cpp/src/spine/Bone.cpp @@ -42,13 +42,11 @@ namespace Spine bool Bone::yDown = false; - void Bone::setYDown(bool inValue) - { + void Bone::setYDown(bool inValue) { yDown = inValue; } - bool Bone::isYDown() - { + bool Bone::isYDown() { return yDown; } @@ -77,23 +75,19 @@ namespace Spine _c(0), _d(0), _worldY(0), - _sorted(false) - { + _sorted(false) { setToSetupPose(); } - void Bone::update() - { + void Bone::update() { updateWorldTransform(_x, _y, _rotation, _scaleX, _scaleY, _shearX, _shearY); } - void Bone::updateWorldTransform() - { + void Bone::updateWorldTransform() { updateWorldTransform(_x, _y, _rotation, _scaleX, _scaleY, _shearX, _shearY); } - void Bone::updateWorldTransform(float x, float y, float rotation, float scaleX, float scaleY, float shearX, float shearY) - { + void Bone::updateWorldTransform(float x, float y, float rotation, float scaleX, float scaleY, float shearX, float shearY) { _ax = x; _ay = y; _arotation = rotation; @@ -105,23 +99,20 @@ namespace Spine Skeleton& skeleton = _skeleton; Bone* parent = _parent; - if (!parent) - { + if (!parent) { // Root bone. float rotationY = rotation + 90 + shearY; float la = MathUtil::cosDeg(rotation + shearX) * scaleX; float lb = MathUtil::cosDeg(rotationY) * scaleY; float lc = MathUtil::sinDeg(rotation + shearX) * scaleX; float ld = MathUtil::sinDeg(rotationY) * scaleY; - if (_skeleton.getFlipX()) - { + if (_skeleton.getFlipX()) { x = -x; la = -la; lb = -lb; } - if (_skeleton.getFlipY() != Bone::isYDown()) - { + if (_skeleton.getFlipY() != Bone::isYDown()) { y = -y; lc = -lc; ld = -ld; @@ -145,10 +136,8 @@ namespace Spine _worldX = pa * x + pb * y + parent->_worldX; _worldY = pc * x + pd * y + parent->_worldY; - switch (_data.getTransformMode()) - { - case TransformMode_Normal: - { + switch (_data.getTransformMode()) { + case TransformMode_Normal: { float rotationY = rotation + 90 + shearY; float la = MathUtil::cosDeg(rotation + shearX) * scaleX; float lb = MathUtil::cosDeg(rotationY) * scaleY; @@ -161,8 +150,7 @@ namespace Spine return; } - case TransformMode_OnlyTranslation: - { + case TransformMode_OnlyTranslation: { float rotationY = rotation + 90 + shearY; _a = MathUtil::cosDeg(rotation + shearX) * scaleX; _b = MathUtil::cosDeg(rotationY) * scaleY; @@ -171,18 +159,15 @@ namespace Spine break; } - case TransformMode_NoRotationOrReflection: - { + case TransformMode_NoRotationOrReflection: { float s = pa * pa + pc * pc, prx; - if (s > 0.0001f) - { + if (s > 0.0001f) { s = fabs(pa * pd - pb * pc) / s; pb = pc * s; pd = pa * s; prx = MathUtil::atan2(pc, pa) * RadDeg; } - else - { + else { pa = 0; pc = 0; prx = 90 - MathUtil::atan2(pd, pb) * RadDeg; @@ -202,15 +187,13 @@ namespace Spine break; } case TransformMode_NoScale: - case TransformMode_NoScaleOrReflection: - { + case TransformMode_NoScaleOrReflection: { float cos = MathUtil::cosDeg(rotation); float sin = MathUtil::sinDeg(rotation); float za = pa * cos + pb * sin; float zc = pc * cos + pd * sin; float s = sqrt(za * za + zc * zc); - if (s > 0.00001f) - { + if (s > 0.00001f) { s = 1 / s; } @@ -225,8 +208,7 @@ namespace Spine float lc = MathUtil::sinDeg(shearX) * scaleX; float ld = MathUtil::sinDeg(90 + shearY) * scaleY; - if (_data.getTransformMode() != TransformMode_NoScaleOrReflection ? pa * pd - pb * pc < 0 : _skeleton.getFlipX() != _skeleton.getFlipY()) - { + if (_data.getTransformMode() != TransformMode_NoScaleOrReflection ? pa * pd - pb * pc < 0 : _skeleton.getFlipX() != _skeleton.getFlipY()) { zb = -zb; zd = -zd; } @@ -240,21 +222,18 @@ namespace Spine } } - if (_skeleton.getFlipX()) - { + if (_skeleton.getFlipX()) { _a = -_a; _b = -_b; } - if (skeleton.getFlipY() != Bone::isYDown()) - { + if (skeleton.getFlipY() != Bone::isYDown()) { _c = -_c; _d = -_d; } } - void Bone::setToSetupPose() - { + void Bone::setToSetupPose() { BoneData& data = _data; _x = data.getX(); _y = data.getY(); @@ -265,8 +244,7 @@ namespace Spine _shearY = data.getShearY(); } - void Bone::worldToLocal(float worldX, float worldY, float& outLocalX, float& outLocalY) - { + void Bone::worldToLocal(float worldX, float worldY, float& outLocalX, float& outLocalY) { float a = _a; float b = _b; float c = _c; @@ -280,30 +258,26 @@ namespace Spine outLocalY = (y * a * invDet - x * c * invDet); } - void Bone::localToWorld(float localX, float localY, float& outWorldX, float& outWorldY) - { + void Bone::localToWorld(float localX, float localY, float& outWorldX, float& outWorldY) { outWorldX = localX * _a + localY * _b + _worldX; outWorldY = localX * _c + localY * _d + _worldY; } - float Bone::worldToLocalRotation(float worldRotation) - { + float Bone::worldToLocalRotation(float worldRotation) { float sin = MathUtil::sinDeg(worldRotation); float cos = MathUtil::cosDeg(worldRotation); return MathUtil::atan2(_a * sin - _c * cos, _d * cos - _b * sin) * RadDeg; } - float Bone::localToWorldRotation(float localRotation) - { + float Bone::localToWorldRotation(float localRotation) { float sin = MathUtil::sinDeg(localRotation); float cos = MathUtil::cosDeg(localRotation); return MathUtil::atan2(cos * _c + sin * _d, cos * _a + sin * _b) * RadDeg; } - void Bone::rotateWorld(float degrees) - { + void Bone::rotateWorld(float degrees) { float a = _a; float b = _b; float c = _c; @@ -320,11 +294,9 @@ namespace Spine _appliedValid = false; } - float Bone::getWorldToLocalRotationX() - { + float Bone::getWorldToLocalRotationX() { Bone* parent = _parent; - if (!parent) - { + if (!parent) { return _arotation; } @@ -338,11 +310,9 @@ namespace Spine return MathUtil::atan2(pa * c - pc * a, pd * a - pb * c) * RadDeg; } - float Bone::getWorldToLocalRotationY() - { + float Bone::getWorldToLocalRotationY() { Bone* parent = _parent; - if (!parent) - { + if (!parent) { return _arotation; } @@ -356,252 +326,202 @@ namespace Spine return MathUtil::atan2(pa * d - pc * b, pd * b - pb * d) * RadDeg; } - BoneData& Bone::getData() - { + BoneData& Bone::getData() { return _data; } - Skeleton& Bone::getSkeleton() - { + Skeleton& Bone::getSkeleton() { return _skeleton; } - Bone* Bone::getParent() - { + Bone* Bone::getParent() { return _parent; } - Vector& Bone::getChildren() - { + Vector& Bone::getChildren() { return _children; } - float Bone::getX() - { + float Bone::getX() { return _x; } - void Bone::setX(float inValue) - { + void Bone::setX(float inValue) { _x = inValue; } - float Bone::getY() - { + float Bone::getY() { return _y; } - void Bone::setY(float inValue) - { + void Bone::setY(float inValue) { _y = inValue; } - float Bone::getRotation() - { + float Bone::getRotation() { return _rotation; } - void Bone::setRotation(float inValue) - { + void Bone::setRotation(float inValue) { _rotation = inValue; } - float Bone::getScaleX() - { + float Bone::getScaleX() { return _scaleX; } - void Bone::setScaleX(float inValue) - { + void Bone::setScaleX(float inValue) { _scaleX = inValue; } - float Bone::getScaleY() - { + float Bone::getScaleY() { return _scaleY; } - void Bone::setScaleY(float inValue) - { + void Bone::setScaleY(float inValue) { _scaleY = inValue; } - float Bone::getShearX() - { + float Bone::getShearX() { return _shearX; } - void Bone::setShearX(float inValue) - { + void Bone::setShearX(float inValue) { _shearX = inValue; } - float Bone::getShearY() - { + float Bone::getShearY() { return _shearY; } - void Bone::setShearY(float inValue) - { + void Bone::setShearY(float inValue) { _shearY = inValue; } - float Bone::getAppliedRotation() - { + float Bone::getAppliedRotation() { return _arotation; } - void Bone::setAppliedRotation(float inValue) - { + void Bone::setAppliedRotation(float inValue) { _arotation = inValue; } - float Bone::getAX() - { + float Bone::getAX() { return _ax; } - void Bone::setAX(float inValue) - { + void Bone::setAX(float inValue) { _ax = inValue; } - float Bone::getAY() - { + float Bone::getAY() { return _ay; } - void Bone::setAY(float inValue) - { + void Bone::setAY(float inValue) { _ay = inValue; } - float Bone::getAScaleX() - { + float Bone::getAScaleX() { return _ascaleX; } - void Bone::setAScaleX(float inValue) - { + void Bone::setAScaleX(float inValue) { _ascaleX = inValue; } - float Bone::getAScaleY() - { + float Bone::getAScaleY() { return _ascaleY; } - void Bone::setAScaleY(float inValue) - { + void Bone::setAScaleY(float inValue) { _ascaleY = inValue; } - float Bone::getAShearX() - { + float Bone::getAShearX() { return _ashearX; } - void Bone::setAShearX(float inValue) - { + void Bone::setAShearX(float inValue) { _ashearX = inValue; } - float Bone::getAShearY() - { + float Bone::getAShearY() { return _ashearY; } - void Bone::setAShearY(float inValue) - { + void Bone::setAShearY(float inValue) { _ashearY = inValue; } - float Bone::getA() - { + float Bone::getA() { return _a; } - void Bone::setA(float inValue) - { + void Bone::setA(float inValue) { _a = inValue; } - float Bone::getB() - { + float Bone::getB() { return _b; } - void Bone::setB(float inValue) - { + void Bone::setB(float inValue) { _b = inValue; } - float Bone::getC() - { + float Bone::getC() { return _c; } - void Bone::setC(float inValue) - { + void Bone::setC(float inValue) { _c = inValue; } - float Bone::getD() - { + float Bone::getD() { return _d; } - void Bone::setD(float inValue) - { + void Bone::setD(float inValue) { _d = inValue; } - float Bone::getWorldX() - { + float Bone::getWorldX() { return _worldX; } - void Bone::setWorldX(float inValue) - { + void Bone::setWorldX(float inValue) { _worldX = inValue; } - float Bone::getWorldY() - { + float Bone::getWorldY() { return _worldY; } - void Bone::setWorldY(float inValue) - { + void Bone::setWorldY(float inValue) { _worldY = inValue; } - float Bone::getWorldRotationX() - { + float Bone::getWorldRotationX() { return MathUtil::atan2(_c, _a) * RadDeg; } - float Bone::getWorldRotationY() - { + float Bone::getWorldRotationY() { return MathUtil::atan2(_d, _b) * RadDeg; } - float Bone::getWorldScaleX() - { + float Bone::getWorldScaleX() { return sqrt(_a * _a + _c * _c); } - float Bone::getWorldScaleY() - { + float Bone::getWorldScaleY() { return sqrt(_b * _b + _d * _d); } - void Bone::updateAppliedTransform() - { + void Bone::updateAppliedTransform() { _appliedValid = true; Bone* parent = _parent; - if (!parent) - { + if (!parent) { _ax = _worldX; _ay = _worldY; _arotation = MathUtil::atan2(_c, _a) * RadDeg; @@ -638,15 +558,13 @@ namespace Spine _ashearX = 0; _ascaleX = sqrt(ra * ra + rc * rc); - if (_ascaleX > 0.0001f) - { + if (_ascaleX > 0.0001f) { float det = ra * rd - rb * rc; _ascaleY = det / _ascaleX; _ashearY = MathUtil::atan2(ra * rb + rc * rd, det) * RadDeg; _arotation = MathUtil::atan2(rc, ra) * RadDeg; } - else - { + else { _ascaleX = 0; _ascaleY = sqrt(rb * rb + rd * rd); _ashearY = 0; diff --git a/spine-cpp/spine-cpp/src/spine/BoneData.cpp b/spine-cpp/spine-cpp/src/spine/BoneData.cpp index ce90ef754..2e5ac3fbd 100644 --- a/spine-cpp/spine-cpp/src/spine/BoneData.cpp +++ b/spine-cpp/spine-cpp/src/spine/BoneData.cpp @@ -46,114 +46,92 @@ namespace Spine _scaleY(1), _shearX(0), _shearY(0), - _transformMode(TransformMode_Normal) - { + _transformMode(TransformMode_Normal) { assert(index >= 0); assert(_name.length() > 0); } - const int BoneData::getIndex() - { + const int BoneData::getIndex() { return _index; } - const std::string& BoneData::getName() - { + const std::string& BoneData::getName() { return _name; } - BoneData* BoneData::getParent() - { + BoneData* BoneData::getParent() { return _parent; } - float BoneData::getLength() - { + float BoneData::getLength() { return _length; } - void BoneData::setLength(float inValue) - { + void BoneData::setLength(float inValue) { _length = inValue; } - float BoneData::getX() - { + float BoneData::getX() { return _x; } - void BoneData::setX(float inValue) - { + void BoneData::setX(float inValue) { _x = inValue; } - float BoneData::getY() - { + float BoneData::getY() { return _y; } - void BoneData::setY(float inValue) - { + void BoneData::setY(float inValue) { _y = inValue; } - float BoneData::getRotation() - { + float BoneData::getRotation() { return _rotation; } - void BoneData::setRotation(float inValue) - { + void BoneData::setRotation(float inValue) { _rotation = inValue; } - float BoneData::getScaleX() - { + float BoneData::getScaleX() { return _scaleX; } - void BoneData::setScaleX(float inValue) - { + void BoneData::setScaleX(float inValue) { _scaleX = inValue; } - float BoneData::getScaleY() - { + float BoneData::getScaleY() { return _scaleY; } - void BoneData::setScaleY(float inValue) - { + void BoneData::setScaleY(float inValue) { _scaleY = inValue; } - float BoneData::getShearX() - { + float BoneData::getShearX() { return _shearX; } - void BoneData::setShearX(float inValue) - { + void BoneData::setShearX(float inValue) { _shearX = inValue; } - float BoneData::getShearY() - { + float BoneData::getShearY() { return _shearY; } - void BoneData::setShearY(float inValue) - { + void BoneData::setShearY(float inValue) { _shearY = inValue; } - TransformMode BoneData::getTransformMode() - { + TransformMode BoneData::getTransformMode() { return _transformMode; } - void BoneData::setTransformMode(TransformMode inValue) - { + void BoneData::setTransformMode(TransformMode inValue) { _transformMode = inValue; } } diff --git a/spine-cpp/spine-cpp/src/spine/BoundingBoxAttachment.cpp b/spine-cpp/spine-cpp/src/spine/BoundingBoxAttachment.cpp index ffa7f7355..02d662233 100644 --- a/spine-cpp/spine-cpp/src/spine/BoundingBoxAttachment.cpp +++ b/spine-cpp/spine-cpp/src/spine/BoundingBoxAttachment.cpp @@ -34,8 +34,7 @@ namespace Spine { RTTI_IMPL(BoundingBoxAttachment, VertexAttachment); - BoundingBoxAttachment::BoundingBoxAttachment(std::string name) : VertexAttachment(name) - { + BoundingBoxAttachment::BoundingBoxAttachment(std::string name) : VertexAttachment(name) { // Empty } } diff --git a/spine-cpp/spine-cpp/src/spine/ClippingAttachment.cpp b/spine-cpp/spine-cpp/src/spine/ClippingAttachment.cpp index 1f2f9dd2b..3c8efc3b5 100644 --- a/spine-cpp/spine-cpp/src/spine/ClippingAttachment.cpp +++ b/spine-cpp/spine-cpp/src/spine/ClippingAttachment.cpp @@ -36,18 +36,15 @@ namespace Spine { RTTI_IMPL(ClippingAttachment, VertexAttachment); - ClippingAttachment::ClippingAttachment(std::string name) : VertexAttachment(name), _endSlot(NULL) - { + ClippingAttachment::ClippingAttachment(std::string name) : VertexAttachment(name), _endSlot(NULL) { // Empty } - SlotData* ClippingAttachment::getEndSlot() - { + SlotData* ClippingAttachment::getEndSlot() { return _endSlot; } - void ClippingAttachment::setEndSlot(SlotData* inValue) - { + void ClippingAttachment::setEndSlot(SlotData* inValue) { _endSlot = inValue; } } diff --git a/spine-cpp/spine-cpp/src/spine/ColorTimeline.cpp b/spine-cpp/spine-cpp/src/spine/ColorTimeline.cpp index 80d41a1c7..4c6bea7a4 100644 --- a/spine-cpp/spine-cpp/src/spine/ColorTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/ColorTimeline.cpp @@ -53,21 +53,17 @@ namespace Spine const int ColorTimeline::B = 3; const int ColorTimeline::A = 4; - ColorTimeline::ColorTimeline(int frameCount) : CurveTimeline(frameCount), _slotIndex(0) - { + ColorTimeline::ColorTimeline(int frameCount) : CurveTimeline(frameCount), _slotIndex(0) { _frames.reserve(frameCount * ENTRIES); _frames.setSize(frameCount * ENTRIES); } - void ColorTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) - { + void ColorTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) { Slot* slotP = skeleton._slots[_slotIndex]; Slot& slot = *slotP; - if (time < _frames[0]) - { + if (time < _frames[0]) { SlotData& slotData = slot._data; - switch (pose) - { + switch (pose) { case MixPose_Setup: slot._r = slotData._r; slot._g = slotData._g; @@ -87,8 +83,7 @@ namespace Spine } float r, g, b, a; - if (time >= _frames[_frames.size() - ENTRIES]) - { + if (time >= _frames[_frames.size() - ENTRIES]) { // Time is after last frame. int i = static_cast(_frames.size()); r = _frames[i + PREV_R]; @@ -96,8 +91,7 @@ namespace Spine b = _frames[i + PREV_B]; a = _frames[i + PREV_A]; } - else - { + else { // Interpolate between the previous frame and the current frame. int frame = Animation::binarySearch(_frames, time, ENTRIES); r = _frames[frame + PREV_R]; @@ -113,25 +107,21 @@ namespace Spine a += (_frames[frame + A] - a) * percent; } - if (alpha == 1) - { + if (alpha == 1) { slot._r = r; slot._g = g; slot._b = b; slot._a = a; } - else - { + else { float br, bg, bb, ba; - if (pose == MixPose_Setup) - { + if (pose == MixPose_Setup) { br = slot._data._r; bg = slot._data._g; bb = slot._data._b; ba = slot._data._a; } - else - { + else { br = slot._r; bg = slot._g; bb = slot._b; @@ -144,13 +134,11 @@ namespace Spine } } - int ColorTimeline::getPropertyId() - { + int ColorTimeline::getPropertyId() { return ((int)TimelineType_Color << 24) + _slotIndex; } - void ColorTimeline::setFrame(int frameIndex, float time, float r, float g, float b, float a) - { + void ColorTimeline::setFrame(int frameIndex, float time, float r, float g, float b, float a) { frameIndex *= ENTRIES; _frames[frameIndex] = time; _frames[frameIndex + R] = r; @@ -159,23 +147,19 @@ namespace Spine _frames[frameIndex + A] = a; } - int ColorTimeline::getSlotIndex() - { + int ColorTimeline::getSlotIndex() { return _slotIndex; } - void ColorTimeline::setSlotIndex(int inValue) - { + void ColorTimeline::setSlotIndex(int inValue) { _slotIndex = inValue; } - Vector& ColorTimeline::getFrames() - { + Vector& ColorTimeline::getFrames() { return _frames; } - void ColorTimeline::setFrames(Vector& inValue) - { + void ColorTimeline::setFrames(Vector& inValue) { _frames = inValue; } } diff --git a/spine-cpp/spine-cpp/src/spine/Constraint.cpp b/spine-cpp/spine-cpp/src/spine/Constraint.cpp index bad9d1a0b..85618372b 100644 --- a/spine-cpp/spine-cpp/src/spine/Constraint.cpp +++ b/spine-cpp/spine-cpp/src/spine/Constraint.cpp @@ -34,13 +34,11 @@ namespace Spine { RTTI_IMPL(Constraint, Updatable); - Constraint::Constraint() - { + Constraint::Constraint() { // Empty } - Constraint::~Constraint() - { + Constraint::~Constraint() { // Empty } } diff --git a/spine-cpp/spine-cpp/src/spine/CurveTimeline.cpp b/spine-cpp/spine-cpp/src/spine/CurveTimeline.cpp index 6f66e760f..88b25e375 100644 --- a/spine-cpp/spine-cpp/src/spine/CurveTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/CurveTimeline.cpp @@ -41,31 +41,26 @@ namespace Spine const float CurveTimeline::BEZIER = 2; const int CurveTimeline::BEZIER_SIZE = 10 * 2 - 1; - CurveTimeline::CurveTimeline(int frameCount) - { + CurveTimeline::CurveTimeline(int frameCount) { assert(frameCount > 0); _curves.reserve((frameCount - 1) * BEZIER_SIZE); _curves.setSize((frameCount - 1) * BEZIER_SIZE); } - int CurveTimeline::getFrameCount() - { + int CurveTimeline::getFrameCount() { return static_cast(_curves.size() / BEZIER_SIZE + 1); } - void CurveTimeline::setLinear(int frameIndex) - { + void CurveTimeline::setLinear(int frameIndex) { _curves[frameIndex * BEZIER_SIZE] = LINEAR; } - void CurveTimeline::setStepped(int frameIndex) - { + void CurveTimeline::setStepped(int frameIndex) { _curves[frameIndex * BEZIER_SIZE] = STEPPED; } - void CurveTimeline::setCurve(int frameIndex, float cx1, float cy1, float cx2, float cy2) - { + void CurveTimeline::setCurve(int frameIndex, float cx1, float cy1, float cx2, float cy2) { float tmpx = (-cx1 * 2 + cx2) * 0.03f, tmpy = (-cy1 * 2 + cy2) * 0.03f; float dddfx = ((cx1 - cx2) * 3 + 1) * 0.006f, dddfy = ((cy1 - cy2) * 3 + 1) * 0.006f; float ddfx = tmpx * 2 + dddfx, ddfy = tmpy * 2 + dddfy; @@ -75,8 +70,7 @@ namespace Spine _curves[i++] = BEZIER; float x = dfx, y = dfy; - for (int n = i + BEZIER_SIZE - 1; i < n; i += 2) - { + for (int n = i + BEZIER_SIZE - 1; i < n; i += 2) { _curves[i] = x; _curves[i + 1] = y; dfx += ddfx; @@ -88,37 +82,30 @@ namespace Spine } } - float CurveTimeline::getCurvePercent(int frameIndex, float percent) - { + float CurveTimeline::getCurvePercent(int frameIndex, float percent) { percent = clamp(percent, 0, 1); int i = frameIndex * BEZIER_SIZE; float type = _curves[i]; - if (type == LINEAR) - { + if (type == LINEAR) { return percent; } - if (type == STEPPED) - { + if (type == STEPPED) { return 0; } i++; float x = 0; - for (int start = i, n = i + BEZIER_SIZE - 1; i < n; i += 2) - { + for (int start = i, n = i + BEZIER_SIZE - 1; i < n; i += 2) { x = _curves[i]; - if (x >= percent) - { + if (x >= percent) { float prevX, prevY; - if (i == start) - { + if (i == start) { prevX = 0; prevY = 0; } - else - { + else { prevX = _curves[i - 2]; prevY = _curves[i - 1]; } @@ -132,8 +119,7 @@ namespace Spine return y + (1 - y) * (percent - x) / (1 - x); // Last point is 1,1. } - float CurveTimeline::getCurveType(int frameIndex) - { + float CurveTimeline::getCurveType(int frameIndex) { return _curves[frameIndex * BEZIER_SIZE]; } } diff --git a/spine-cpp/spine-cpp/src/spine/DeformTimeline.cpp b/spine-cpp/spine-cpp/src/spine/DeformTimeline.cpp index 8f9333220..bede7342e 100644 --- a/spine-cpp/spine-cpp/src/spine/DeformTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/DeformTimeline.cpp @@ -44,54 +44,45 @@ namespace Spine { RTTI_IMPL(DeformTimeline, CurveTimeline); - DeformTimeline::DeformTimeline(int frameCount) : CurveTimeline(frameCount), _slotIndex(0), _attachment(NULL) - { + DeformTimeline::DeformTimeline(int frameCount) : CurveTimeline(frameCount), _slotIndex(0), _attachment(NULL) { _frames.reserve(frameCount); _frameVertices.reserve(frameCount); _frames.setSize(frameCount); - for (int i = 0; i < frameCount; ++i) - { + for (int i = 0; i < frameCount; ++i) { Vector vec; _frameVertices.push_back(vec); } } - void DeformTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) - { + void DeformTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) { Slot* slotP = skeleton._slots[_slotIndex]; Slot& slot = *slotP; - if (slot._attachment == NULL || !slot._attachment->getRTTI().derivesFrom(VertexAttachment::rtti)) - { + if (slot._attachment == NULL || !slot._attachment->getRTTI().derivesFrom(VertexAttachment::rtti)) { return; } VertexAttachment* vertexAttachment = static_cast(slot._attachment); - if (!vertexAttachment->applyDeform(_attachment)) - { + if (!vertexAttachment->applyDeform(_attachment)) { return; } Vector& vertices = slot._attachmentVertices; - if (vertices.size() == 0) - { + if (vertices.size() == 0) { alpha = 1; } int vertexCount = static_cast(_frameVertices[0].size()); - if (time < _frames[0]) - { - switch (pose) - { + if (time < _frames[0]) { + switch (pose) { case MixPose_Setup: vertices.clear(); return; case MixPose_Current: - if (alpha == 1) - { + if (alpha == 1) { vertices.clear(); return; } @@ -100,21 +91,17 @@ namespace Spine vertices.reserve(vertexCount); vertices.setSize(vertexCount); - if (vertexAttachment->_bones.size() == 0) - { + if (vertexAttachment->_bones.size() == 0) { // Unweighted vertex positions. Vector& setupVertices = vertexAttachment->_vertices; - for (int i = 0; i < vertexCount; ++i) - { + for (int i = 0; i < vertexCount; ++i) { vertices[i] += (setupVertices[i] - vertices[i]) * alpha; } } - else - { + else { // Weighted deform offsets. alpha = 1 - alpha; - for (int i = 0; i < vertexCount; ++i) - { + for (int i = 0; i < vertexCount; ++i) { vertices[i] *= alpha; } } @@ -128,46 +115,36 @@ namespace Spine vertices.reserve(vertexCount); vertices.setSize(vertexCount); - if (time >= _frames[_frames.size() - 1]) - { + if (time >= _frames[_frames.size() - 1]) { // Time is after last frame. Vector& lastVertices = _frameVertices[_frames.size() - 1]; - if (alpha == 1) - { + if (alpha == 1) { // Vertex positions or deform offsets, no alpha. vertices.clear(); - for (int i = 0; i < vertexCount; ++i) - { + for (int i = 0; i < vertexCount; ++i) { float vertex = lastVertices[i]; vertices.push_back(vertex); } } - else if (pose == MixPose_Setup) - { - if (vertexAttachment->_bones.size() == 0) - { + else if (pose == MixPose_Setup) { + if (vertexAttachment->_bones.size() == 0) { // Unweighted vertex positions, with alpha. Vector& setupVertices = vertexAttachment->_vertices; - for (int i = 0; i < vertexCount; i++) - { + for (int i = 0; i < vertexCount; i++) { float setup = setupVertices[i]; vertices[i] = setup + (lastVertices[i] - setup) * alpha; } } - else - { + else { // Weighted deform offsets, with alpha. - for (int i = 0; i < vertexCount; ++i) - { + for (int i = 0; i < vertexCount; ++i) { vertices[i] = lastVertices[i] * alpha; } } } - else - { + else { // Vertex positions or deform offsets, with alpha. - for (int i = 0; i < vertexCount; ++i) - { + for (int i = 0; i < vertexCount; ++i) { vertices[i] += (lastVertices[i] - vertices[i]) * alpha; } } @@ -181,98 +158,79 @@ namespace Spine float frameTime = _frames[frame]; float percent = getCurvePercent(frame - 1, 1 - (time - frameTime) / (_frames[frame - 1] - frameTime)); - if (alpha == 1) - { + if (alpha == 1) { // Vertex positions or deform offsets, no alpha. - for (int i = 0; i < vertexCount; ++i) - { + for (int i = 0; i < vertexCount; ++i) { float prev = prevVertices[i]; vertices[i] = prev + (nextVertices[i] - prev) * percent; } } - else if (pose == MixPose_Setup) - { - if (vertexAttachment->_bones.size() == 0) - { + else if (pose == MixPose_Setup) { + if (vertexAttachment->_bones.size() == 0) { // Unweighted vertex positions, with alpha. Vector& setupVertices = vertexAttachment->_vertices; - for (int i = 0; i < vertexCount; ++i) - { + for (int i = 0; i < vertexCount; ++i) { float prev = prevVertices[i], setup = setupVertices[i]; vertices[i] = setup + (prev + (nextVertices[i] - prev) * percent - setup) * alpha; } } - else - { + else { // Weighted deform offsets, with alpha. - for (int i = 0; i < vertexCount; ++i) - { + for (int i = 0; i < vertexCount; ++i) { float prev = prevVertices[i]; vertices[i] = (prev + (nextVertices[i] - prev) * percent) * alpha; } } } - else - { + else { // Vertex positions or deform offsets, with alpha. - for (int i = 0; i < vertexCount; ++i) - { + for (int i = 0; i < vertexCount; ++i) { float prev = prevVertices[i]; vertices[i] += (prev + (nextVertices[i] - prev) * percent - vertices[i]) * alpha; } } } - int DeformTimeline::getPropertyId() - { + int DeformTimeline::getPropertyId() { assert(_attachment != NULL); return ((int)TimelineType_Deform << 24) + _attachment->_id + _slotIndex; } - void DeformTimeline::setFrame(int frameIndex, float time, Vector& vertices) - { + void DeformTimeline::setFrame(int frameIndex, float time, Vector& vertices) { _frames[frameIndex] = time; _frameVertices[frameIndex] = vertices; } - int DeformTimeline::getSlotIndex() - { + int DeformTimeline::getSlotIndex() { return _slotIndex; } - void DeformTimeline::setSlotIndex(int inValue) - { + void DeformTimeline::setSlotIndex(int inValue) { _slotIndex = inValue; } - Vector& DeformTimeline::getFrames() - { + Vector& DeformTimeline::getFrames() { return _frames; } - void DeformTimeline::setFrames(Vector& inValue) - { + void DeformTimeline::setFrames(Vector& inValue) { _frames = inValue; } - Vector< Vector >& DeformTimeline::getVertices() - { + Vector< Vector >& DeformTimeline::getVertices() { return _frameVertices; } - void DeformTimeline::setVertices(Vector< Vector >& inValue) - { + void DeformTimeline::setVertices(Vector< Vector >& inValue) { _frameVertices = inValue; } - VertexAttachment* DeformTimeline::getAttachment() - { + VertexAttachment* DeformTimeline::getAttachment() { return _attachment; } - void DeformTimeline::setAttachment(VertexAttachment* inValue) - { + void DeformTimeline::setAttachment(VertexAttachment* inValue) { _attachment = inValue; } } diff --git a/spine-cpp/spine-cpp/src/spine/DrawOrderTimeline.cpp b/spine-cpp/spine-cpp/src/spine/DrawOrderTimeline.cpp index 2d9577cf3..83ad3259a 100644 --- a/spine-cpp/spine-cpp/src/spine/DrawOrderTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/DrawOrderTimeline.cpp @@ -42,43 +42,35 @@ namespace Spine { RTTI_IMPL(DrawOrderTimeline, Timeline); - DrawOrderTimeline::DrawOrderTimeline(int frameCount) : Timeline() - { + DrawOrderTimeline::DrawOrderTimeline(int frameCount) : Timeline() { _frames.reserve(frameCount); _drawOrders.reserve(frameCount); _frames.setSize(frameCount); - for (int i = 0; i < frameCount; ++i) - { + for (int i = 0; i < frameCount; ++i) { Vector vec; _drawOrders.push_back(vec); } } - void DrawOrderTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) - { + void DrawOrderTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) { Vector& drawOrder = skeleton._drawOrder; Vector& slots = skeleton._slots; - if (direction == MixDirection_Out && pose == MixPose_Setup) - { + if (direction == MixDirection_Out && pose == MixPose_Setup) { drawOrder.clear(); drawOrder.reserve(slots.size()); - for (int i = 0, n = static_cast(slots.size()); i < n; ++i) - { + for (int i = 0, n = static_cast(slots.size()); i < n; ++i) { drawOrder.push_back(slots[i]); } return; } - if (time < _frames[0]) - { - if (pose == MixPose_Setup) - { + if (time < _frames[0]) { + if (pose == MixPose_Setup) { drawOrder.clear(); drawOrder.reserve(slots.size()); - for (int i = 0, n = static_cast(slots.size()); i < n; ++i) - { + for (int i = 0, n = static_cast(slots.size()); i < n; ++i) { drawOrder.push_back(slots[i]); } } @@ -86,67 +78,54 @@ namespace Spine } int frame; - if (time >= _frames[_frames.size() - 1]) - { + if (time >= _frames[_frames.size() - 1]) { // Time is after last frame. frame = static_cast(_frames.size()) - 1; } - else - { + else { frame = Animation::binarySearch(_frames, time) - 1; } Vector& drawOrderToSetupIndex = _drawOrders[frame]; - if (drawOrderToSetupIndex.size() == 0) - { + if (drawOrderToSetupIndex.size() == 0) { drawOrder.clear(); - for (int i = 0, n = static_cast(slots.size()); i < n; ++i) - { + for (int i = 0, n = static_cast(slots.size()); i < n; ++i) { drawOrder.push_back(slots[i]); } } - else - { - for (int i = 0, n = static_cast(drawOrderToSetupIndex.size()); i < n; ++i) - { + else { + for (int i = 0, n = static_cast(drawOrderToSetupIndex.size()); i < n; ++i) { drawOrder[i] = slots[drawOrderToSetupIndex[i]]; } } } - int DrawOrderTimeline::getPropertyId() - { + int DrawOrderTimeline::getPropertyId() { return ((int)TimelineType_DrawOrder << 24); } - void DrawOrderTimeline::setFrame(int frameIndex, float time, Vector& drawOrder) - { + void DrawOrderTimeline::setFrame(int frameIndex, float time, Vector& drawOrder) { _frames[frameIndex] = time; _drawOrders[frameIndex] = drawOrder; } - Vector& DrawOrderTimeline::getFrames() - { + Vector& DrawOrderTimeline::getFrames() { return _frames; } - void DrawOrderTimeline::setFrames(Vector& inValue) - { + void DrawOrderTimeline::setFrames(Vector& inValue) { _frames = inValue; } - Vector< Vector >& DrawOrderTimeline::getDrawOrders() - { + Vector< Vector >& DrawOrderTimeline::getDrawOrders() { return _drawOrders; } - void DrawOrderTimeline::setDrawOrders(Vector< Vector >& inValue) - { + void DrawOrderTimeline::setDrawOrders(Vector< Vector >& inValue) { _drawOrders = inValue; } - int DrawOrderTimeline::getFrameCount() - { + int DrawOrderTimeline::getFrameCount() { return static_cast(_frames.size()); } } diff --git a/spine-cpp/spine-cpp/src/spine/Event.cpp b/spine-cpp/spine-cpp/src/spine/Event.cpp index 09ba067b2..1bce25bdb 100644 --- a/spine-cpp/spine-cpp/src/spine/Event.cpp +++ b/spine-cpp/spine-cpp/src/spine/Event.cpp @@ -39,48 +39,39 @@ namespace Spine _time(time), _intValue(0), _floatValue(0), - _stringValue() - { + _stringValue() { // Empty } - const EventData& Event::getData() - { + const EventData& Event::getData() { return _data; } - float Event::getTime() - { + float Event::getTime() { return _time; } - int Event::getIntValue() - { + int Event::getIntValue() { return _intValue; } - void Event::setIntValue(int inValue) - { + void Event::setIntValue(int inValue) { _intValue = inValue; } - float Event::getFloatValue() - { + float Event::getFloatValue() { return _floatValue; } - void Event::setFloatValue(int inValue) - { + void Event::setFloatValue(int inValue) { _floatValue = inValue; } - std::string Event::getStringValue() - { + std::string Event::getStringValue() { return _stringValue; } - void Event::setStringValue(std::string inValue) - { + void Event::setStringValue(std::string inValue) { _stringValue = inValue; } } diff --git a/spine-cpp/spine-cpp/src/spine/EventData.cpp b/spine-cpp/spine-cpp/src/spine/EventData.cpp index e0eccf90b..e6c95dc0b 100644 --- a/spine-cpp/spine-cpp/src/spine/EventData.cpp +++ b/spine-cpp/spine-cpp/src/spine/EventData.cpp @@ -38,44 +38,36 @@ namespace Spine _name(name), _intValue(0), _floatValue(0), - _stringValue() - { + _stringValue() { assert(_name.length() > 0); } /// The name of the event, which is unique within the skeleton. - const std::string& EventData::getName() - { + const std::string& EventData::getName() { return _name; } - int EventData::getIntValue() - { + int EventData::getIntValue() { return _intValue; } - void EventData::setIntValue(int inValue) - { + void EventData::setIntValue(int inValue) { _intValue = inValue; } - float EventData::getFloatValue() - { + float EventData::getFloatValue() { return _floatValue; } - void EventData::setFloatValue(float inValue) - { + void EventData::setFloatValue(float inValue) { _floatValue = inValue; } - std::string EventData::getStringValue() - { + std::string EventData::getStringValue() { return _stringValue; } - void EventData::setStringValue(std::string inValue) - { + void EventData::setStringValue(std::string inValue) { _stringValue = inValue; } } diff --git a/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp b/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp index 56722d579..66505930b 100644 --- a/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp @@ -44,8 +44,7 @@ namespace Spine { RTTI_IMPL(EventTimeline, Timeline); - EventTimeline::EventTimeline(int frameCount) : Timeline() - { + EventTimeline::EventTimeline(int frameCount) : Timeline() { _frames.reserve(frameCount); _events.reserve(frameCount); @@ -53,76 +52,63 @@ namespace Spine _events.setSize(frameCount); } - EventTimeline::~EventTimeline() - { + EventTimeline::~EventTimeline() { ContainerUtil::cleanUpVectorOfPointers(_events); } - void EventTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) - { - if (pEvents == NULL) - { + void EventTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) { + if (pEvents == NULL) { return; } Vector& events = *pEvents; - if (events.size() == 0) - { + if (events.size() == 0) { return; } int frameCount = static_cast(_frames.size()); - if (lastTime > time) - { + if (lastTime > time) { // Fire events after last time for looped animations. apply(skeleton, lastTime, std::numeric_limits::max(), pEvents, alpha, pose, direction); lastTime = -1.0f; } - else if (lastTime >= _frames[frameCount - 1]) // Last time is after last frame. - { + else if (lastTime >= _frames[frameCount - 1]) { + // Last time is after last frame. return; } - if (time < _frames[0]) - { + if (time < _frames[0]) { return; // Time is before first frame. } int frame; - if (lastTime < _frames[0]) - { + if (lastTime < _frames[0]) { frame = 0; } - else - { + else { frame = Animation::binarySearch(_frames, lastTime); float frameTime = _frames[frame]; - while (frame > 0) - { + while (frame > 0) { // Fire multiple events with the same frame. - if (_frames[frame - 1] != frameTime) - { + if (_frames[frame - 1] != frameTime) { break; } frame--; } } - for (; frame < frameCount && time >= _frames[frame]; ++frame) - { + for (; frame < frameCount && time >= _frames[frame]; ++frame) { events.push_back(_events[frame]); } } - int EventTimeline::getPropertyId() - { + int EventTimeline::getPropertyId() { return ((int)TimelineType_Event << 24); } - void EventTimeline::setFrame(int frameIndex, Event* event) - { + void EventTimeline::setFrame(int frameIndex, Event* event) { _frames[frameIndex] = event->getTime(); _events[frameIndex] = event; } diff --git a/spine-cpp/spine-cpp/src/spine/Extension.cpp b/spine-cpp/spine-cpp/src/spine/Extension.cpp index 5cfe0b3ab..09ce5543d 100644 --- a/spine-cpp/spine-cpp/src/spine/Extension.cpp +++ b/spine-cpp/spine-cpp/src/spine/Extension.cpp @@ -38,27 +38,23 @@ namespace Spine { SpineExtension* SpineExtension::_instance = NULL; - void SpineExtension::setInstance(SpineExtension* inValue) - { + void SpineExtension::setInstance(SpineExtension* inValue) { assert(!_instance); _instance = inValue; } - SpineExtension* SpineExtension::getInstance() - { + SpineExtension* SpineExtension::getInstance() { assert(_instance); return _instance; } - SpineExtension::~SpineExtension() - { + SpineExtension::~SpineExtension() { // Empty } - char* SpineExtension::spineReadFile(const char* path, int* length) - { + char* SpineExtension::spineReadFile(const char* path, int* length) { char *data; FILE *file = fopen(path, "rb"); if (!file) return 0; @@ -74,50 +70,41 @@ namespace Spine return data; } - SpineExtension::SpineExtension() - { + SpineExtension::SpineExtension() { // Empty } - DefaultSpineExtension* DefaultSpineExtension::getInstance() - { + DefaultSpineExtension* DefaultSpineExtension::getInstance() { static DefaultSpineExtension ret; return &ret; } - DefaultSpineExtension::~DefaultSpineExtension() - { + DefaultSpineExtension::~DefaultSpineExtension() { // Empty } - void* DefaultSpineExtension::spineAlloc(size_t size, const char* file, int line) - { + void* DefaultSpineExtension::spineAlloc(size_t size, const char* file, int line) { return malloc(size); } - void* DefaultSpineExtension::spineCalloc(size_t num, size_t size, const char* file, int line) - { + void* DefaultSpineExtension::spineCalloc(size_t num, size_t size, const char* file, int line) { void* ptr = spineAlloc(num * size, file, line); - if (ptr) - { + if (ptr) { memset(ptr, 0, num * size); } return ptr; } - void* DefaultSpineExtension::spineRealloc(void* ptr, size_t size, const char* file, int line) - { + void* DefaultSpineExtension::spineRealloc(void* ptr, size_t size, const char* file, int line) { return realloc(ptr, size); } - void DefaultSpineExtension::spineFree(void* mem) - { + void DefaultSpineExtension::spineFree(void* mem) { free(mem); } - DefaultSpineExtension::DefaultSpineExtension() : SpineExtension() - { + DefaultSpineExtension::DefaultSpineExtension() : SpineExtension() { // Empty } } diff --git a/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp b/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp index 0359854d8..933eb9c62 100644 --- a/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp +++ b/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp @@ -41,10 +41,8 @@ namespace Spine { RTTI_IMPL(IkConstraint, Constraint); - void IkConstraint::apply(Bone& bone, float targetX, float targetY, float alpha) - { - if (!bone._appliedValid) - { + void IkConstraint::apply(Bone& bone, float targetX, float targetY, float alpha) { + if (!bone._appliedValid) { bone.updateAppliedTransform(); } @@ -56,39 +54,32 @@ namespace Spine float tx = (x * p._d - y * p._b) * id - bone._ax, ty = (y * p._a - x * p._c) * id - bone._ay; float rotationIK = (float)atan2(ty, tx) * RadDeg - bone._ashearX - bone._arotation; - if (bone._ascaleX < 0) - { + if (bone._ascaleX < 0) { rotationIK += 180; } - if (rotationIK > 180) - { + if (rotationIK > 180) { rotationIK -= 360; } - else if (rotationIK < -180) - { + else if (rotationIK < -180) { rotationIK += 360; } bone.updateWorldTransform(bone._ax, bone._ay, bone._arotation + rotationIK * alpha, bone._ascaleX, bone._ascaleY, bone._ashearX, bone._ashearY); } - void IkConstraint::apply(Bone& parent, Bone& child, float targetX, float targetY, int bendDir, float alpha) - { - if (areFloatsPracticallyEqual(alpha, 0)) - { + void IkConstraint::apply(Bone& parent, Bone& child, float targetX, float targetY, int bendDir, float alpha) { + if (areFloatsPracticallyEqual(alpha, 0)) { child.updateWorldTransform(); return; } - if (!parent._appliedValid) - { + if (!parent._appliedValid) { parent.updateAppliedTransform(); } - if (!child._appliedValid) - { + if (!child._appliedValid) { child.updateAppliedTransform(); } @@ -99,31 +90,26 @@ namespace Spine float csx = child._ascaleX; int os1, os2, s2; - if (psx < 0) - { + if (psx < 0) { psx = -psx; os1 = 180; s2 = -1; } - else - { + else { os1 = 0; s2 = 1; } - if (psy < 0) - { + if (psy < 0) { psy = -psy; s2 = -s2; } - if (csx < 0) - { + if (csx < 0) { csx = -csx; os2 = 180; } - else - { + else { os2 = 0; } @@ -137,14 +123,12 @@ namespace Spine float d = parent._d; bool u = fabs(psx - psy) <= 0.0001f; - if (!u) - { + if (!u) { cy = 0; cwx = a * cx + parent._worldX; cwy = c * cx + parent._worldY; } - else - { + else { cy = child._ay; cwx = a * cx + b * cy + parent._worldX; cwy = c * cx + d * cy + parent._worldY; @@ -164,16 +148,13 @@ namespace Spine y = cwy - pp._worldY; float dx = (x * d - y * b) * id - px, dy = (y * a - x * c) * id - py; float l1 = (float)sqrt(dx * dx + dy * dy), l2 = child._data.getLength() * csx, a1, a2; - if (u) - { + if (u) { l2 *= psx; float cos = (tx * tx + ty * ty - l1 * l1 - l2 * l2) / (2 * l1 * l2); - if (cos < -1) - { + if (cos < -1) { cos = -1; } - else if (cos > 1) - { + else if (cos > 1) { cos = 1; } @@ -182,23 +163,20 @@ namespace Spine b = l2 * (float)sin(a2); a1 = (float)atan2(ty * a - tx * b, tx * a + ty * b); } - else - { + else { a = psx * l2; b = psy * l2; float aa = a * a, bb = b * b, dd = tx * tx + ty * ty, ta = (float)atan2(ty, tx); c = bb * l1 * l1 + aa * dd - aa * bb; float c1 = -2 * bb * l1, c2 = bb - aa; d = c1 * c1 - 4 * c2 * c; - if (d >= 0) - { + if (d >= 0) { float q = (float)sqrt(d); if (c1 < 0) q = -q; q = -(c1 + q) / 2; float r0 = q / c2, r1 = c / q; float r = fabs(r0) < fabs(r1) ? r0 : r1; - if (r * r <= dd) - { + if (r * r <= dd) { y = (float)sqrt(dd - r * r) * bendDir; a1 = ta - (float)atan2(y, r); a2 = (float)atan2(y / psy, (r - l1) / psx); @@ -206,12 +184,10 @@ namespace Spine float os = (float)atan2(cy, cx) * s2; float rotation = parent._arotation; a1 = (a1 - os) * RadDeg + os1 - rotation; - if (a1 > 180) - { + if (a1 > 180) { a1 -= 360; } - else if (a1 < -180) - { + else if (a1 < -180) { a1 += 360; } @@ -219,12 +195,10 @@ namespace Spine rotation = child._arotation; a2 = ((a2 + os) * RadDeg - child._ashearX) * s2 + os2 - rotation; - if (a2 > 180) - { + if (a2 > 180) { a2 -= 360; } - else if (a2 < -180) - { + else if (a2 < -180) { a2 += 360; } @@ -237,23 +211,20 @@ namespace Spine float minAngle = SPINE_PI, minX = l1 - a, minDist = minX * minX, minY = 0; float maxAngle = 0, maxX = l1 + a, maxDist = maxX * maxX, maxY = 0; c = -a * l1 / (aa - bb); - if (c >= -1 && c <= 1) - { + if (c >= -1 && c <= 1) { c = (float)acos(c); x = a * (float)cos(c) + l1; y = b * (float)sin(c); d = x * x + y * y; - if (d < minDist) - { + if (d < minDist) { minAngle = c; minDist = d; minX = x; minY = y; } - if (d > maxDist) - { + if (d > maxDist) { maxAngle = c; maxDist = d; maxX = x; @@ -261,13 +232,11 @@ namespace Spine } } - if (dd <= (minDist + maxDist) / 2) - { + if (dd <= (minDist + maxDist) / 2) { a1 = ta - (float)atan2(minY * bendDir, minX); a2 = minAngle * bendDir; } - else - { + else { a1 = ta - (float)atan2(maxY * bendDir, maxX); a2 = maxAngle * bendDir; } @@ -278,11 +247,9 @@ namespace Spine _data(data), _mix(data.getMix()), _bendDirection(data.getBendDirection()), - _target(skeleton.findBone(data.getTarget()->getName())) - { + _target(skeleton.findBone(data.getTarget()->getName())) { _bones.reserve(_data.getBones().size()); - for (BoneData** i = _data.getBones().begin(); i != _data.getBones().end(); ++i) - { + for (BoneData** i = _data.getBones().begin(); i != _data.getBones().end(); ++i) { BoneData* boneData = (*i); _bones.push_back(skeleton.findBone(boneData->getName())); @@ -290,23 +257,18 @@ namespace Spine } /// Applies the constraint to the constrained bones. - void IkConstraint::apply() - { + void IkConstraint::apply() { update(); } - void IkConstraint::update() - { - switch (_bones.size()) - { - case 1: - { + void IkConstraint::update() { + switch (_bones.size()) { + case 1: { Bone* bone0 = _bones[0]; apply(*bone0, _target->getWorldX(), _target->getWorldY(), _mix); } break; - case 2: - { + case 2: { Bone* bone0 = _bones[0]; Bone* bone1 = _bones[1]; apply(*bone0, *bone1, _target->getWorldX(), _target->getWorldY(), _bendDirection, _mix); @@ -315,48 +277,39 @@ namespace Spine } } - int IkConstraint::getOrder() - { + int IkConstraint::getOrder() { return _data.getOrder(); } - IkConstraintData& IkConstraint::getData() - { + IkConstraintData& IkConstraint::getData() { return _data; } - Vector& IkConstraint::getBones() - { + Vector& IkConstraint::getBones() { return _bones; } - Bone* IkConstraint::getTarget() - { + Bone* IkConstraint::getTarget() { return _target; } - void IkConstraint::setTarget(Bone* inValue) - { + void IkConstraint::setTarget(Bone* inValue) { _target = inValue; } - int IkConstraint::getBendDirection() - { + int IkConstraint::getBendDirection() { return _bendDirection; } - void IkConstraint::setBendDirection(int inValue) - { + void IkConstraint::setBendDirection(int inValue) { _bendDirection = inValue; } - float IkConstraint::getMix() - { + float IkConstraint::getMix() { return _mix; } - void IkConstraint::setMix(float inValue) - { + void IkConstraint::setMix(float inValue) { _mix = inValue; } } diff --git a/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp b/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp index 13378993f..c06fcdccc 100644 --- a/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp +++ b/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp @@ -39,58 +39,47 @@ namespace Spine _order(0), _target(NULL), _bendDirection(1), - _mix(1) - { + _mix(1) { // Empty } - const std::string& IkConstraintData::getName() - { + const std::string& IkConstraintData::getName() { return _name; } - int IkConstraintData::getOrder() - { + int IkConstraintData::getOrder() { return _order; } - void IkConstraintData::setOrder(int inValue) - { + void IkConstraintData::setOrder(int inValue) { _order = inValue; } - Vector& IkConstraintData::getBones() - { + Vector& IkConstraintData::getBones() { return _bones; } - BoneData* IkConstraintData::getTarget() - { + BoneData* IkConstraintData::getTarget() { return _target; } - void IkConstraintData::setTarget(BoneData* inValue) - { + void IkConstraintData::setTarget(BoneData* inValue) { _target = inValue; } - int IkConstraintData::getBendDirection() - { + int IkConstraintData::getBendDirection() { return _bendDirection; } - void IkConstraintData::setBendDirection(int inValue) - { + void IkConstraintData::setBendDirection(int inValue) { _bendDirection = inValue; } - float IkConstraintData::getMix() - { + float IkConstraintData::getMix() { return _mix; } - void IkConstraintData::setMix(float inValue) - { + void IkConstraintData::setMix(float inValue) { _mix = inValue; } } diff --git a/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp b/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp index ed747c7a4..e0bb67c07 100644 --- a/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp @@ -51,20 +51,16 @@ namespace Spine const int IkConstraintTimeline::MIX = 1; const int IkConstraintTimeline::BEND_DIRECTION = 2; - IkConstraintTimeline::IkConstraintTimeline(int frameCount) : CurveTimeline(frameCount), _ikConstraintIndex(0) - { + IkConstraintTimeline::IkConstraintTimeline(int frameCount) : CurveTimeline(frameCount), _ikConstraintIndex(0) { _frames.reserve(frameCount * ENTRIES); _frames.setSize(frameCount * ENTRIES); } - void IkConstraintTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) - { + void IkConstraintTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) { IkConstraint* constraintP = skeleton._ikConstraints[_ikConstraintIndex]; IkConstraint& constraint = *constraintP; - if (time < _frames[0]) - { - switch (pose) - { + if (time < _frames[0]) { + switch (pose) { case MixPose_Setup: constraint._mix = constraint._data._mix; constraint._bendDirection = constraint._data._bendDirection; @@ -79,20 +75,16 @@ namespace Spine } } - if (time >= _frames[_frames.size() - ENTRIES]) - { + if (time >= _frames[_frames.size() - ENTRIES]) { // Time is after last frame. - if (pose == MixPose_Setup) - { + if (pose == MixPose_Setup) { constraint._mix = constraint._data._mix + (_frames[_frames.size() + PREV_MIX] - constraint._data._mix) * alpha; constraint._bendDirection = direction == MixDirection_Out ? constraint._data._bendDirection : (int)_frames[_frames.size() + PREV_BEND_DIRECTION]; } - else - { + else { constraint._mix += (_frames[_frames.size() + PREV_MIX] - constraint._mix) * alpha; - if (direction == MixDirection_In) - { + if (direction == MixDirection_In) { constraint._bendDirection = (int)_frames[_frames.size() + PREV_BEND_DIRECTION]; } } @@ -105,28 +97,23 @@ namespace Spine float frameTime = _frames[frame]; float percent = getCurvePercent(frame / ENTRIES - 1, 1 - (time - frameTime) / (_frames[frame + PREV_TIME] - frameTime)); - if (pose == MixPose_Setup) - { + if (pose == MixPose_Setup) { constraint._mix = constraint._data._mix + (mix + (_frames[frame + MIX] - mix) * percent - constraint._data._mix) * alpha; constraint._bendDirection = direction == MixDirection_Out ? constraint._data._bendDirection : (int)_frames[frame + PREV_BEND_DIRECTION]; } - else - { + else { constraint._mix += (mix + (_frames[frame + MIX] - mix) * percent - constraint._mix) * alpha; - if (direction == MixDirection_In) - { + if (direction == MixDirection_In) { constraint._bendDirection = (int)_frames[frame + PREV_BEND_DIRECTION]; } } } - int IkConstraintTimeline::getPropertyId() - { + int IkConstraintTimeline::getPropertyId() { return ((int)TimelineType_IkConstraint << 24) + _ikConstraintIndex; } - void IkConstraintTimeline::setFrame(int frameIndex, float time, float mix, int bendDirection) - { + void IkConstraintTimeline::setFrame(int frameIndex, float time, float mix, int bendDirection) { frameIndex *= ENTRIES; _frames[frameIndex] = time; _frames[frameIndex + MIX] = mix; diff --git a/spine-cpp/spine-cpp/src/spine/Json.cpp b/spine-cpp/spine-cpp/src/spine/Json.cpp index bc6dfdd97..6e967e552 100644 --- a/spine-cpp/spine-cpp/src/spine/Json.cpp +++ b/spine-cpp/spine-cpp/src/spine/Json.cpp @@ -64,41 +64,34 @@ namespace Spine const char* Json::_error = NULL; - Json* Json::getItem(Json *object, const char* string) - { + Json* Json::getItem(Json *object, const char* string) { Json *c = object->_child; - while (c && json_strcasecmp(c->_name, string)) - { + while (c && json_strcasecmp(c->_name, string)) { c = c->_next; } return c; } - const char* Json::getString(Json *object, const char* name, const char* defaultValue) - { + const char* Json::getString(Json *object, const char* name, const char* defaultValue) { object = getItem(object, name); - if (object) - { + if (object) { return object->_valueString; } return defaultValue; } - float Json::getFloat(Json *value, const char* name, float defaultValue) - { + float Json::getFloat(Json *value, const char* name, float defaultValue) { value = getItem(value, name); return value ? value->_valueFloat : defaultValue; } - int Json::getInt(Json *value, const char* name, int defaultValue) - { + int Json::getInt(Json *value, const char* name, int defaultValue) { value = getItem(value, name); return value ? value->_valueInt : defaultValue; } - const char* Json::getError() - { + const char* Json::getError() { return _error; } @@ -113,92 +106,73 @@ namespace Spine _valueString(NULL), _valueInt(0), _valueFloat(0), - _name(NULL) - { - if (value) - { + _name(NULL) { + if (value) { value = parseValue(this, skip(value)); assert(value); } } - Json::~Json() - { - if (_child) - { + Json::~Json() { + if (_child) { DESTROY(Json, _child); } - if (_valueString) - { + if (_valueString) { FREE(_valueString); } - if (_name) - { + if (_name) { FREE(_name); } - if (_next) - { + if (_next) { DESTROY(Json, _next); } } - const char* Json::skip(const char* inValue) - { - if (!inValue) - { + const char* Json::skip(const char* inValue) { + if (!inValue) { /* must propagate NULL since it's often called in skip(f(...)) form */ return NULL; } - while (*inValue && (unsigned char)*inValue <= 32) - { + while (*inValue && (unsigned char)*inValue <= 32) { inValue++; } return inValue; } - const char* Json::parseValue(Json *item, const char* value) - { + const char* Json::parseValue(Json *item, const char* value) { /* Referenced by constructor, parseArray(), and parseObject(). */ /* Always called with the result of skip(). */ #if SPINE_JSON_DEBUG /* Checked at entry to graph, constructor, and after every parse call. */ - if (!value) - { + if (!value) { /* Fail on null. */ return NULL; } #endif - switch (*value) - { - case 'n': - { - if (!strncmp(value + 1, "ull", 3)) - { + 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)) - { + 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)) - { + case 't': { + if (!strncmp(value + 1, "rue", 3)) { item->_type = JSON_TRUE; item->_valueInt = 1; return value + 4; @@ -232,47 +206,38 @@ namespace Spine } static const unsigned char firstByteMark[7] = {0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC}; - const char* Json::parseString(Json *item, const char* str) - { + const char* Json::parseString(Json *item, const char* str) { const char* ptr = str + 1; char* ptr2; char* out; int len = 0; unsigned uc, uc2; - if (*str != '\"') - { + if (*str != '\"') { /* TODO: don't need this check when called from parseValue, but do need from parseObject */ _error = str; return 0; } /* not a string! */ - while (*ptr != '\"' && *ptr && ++len) - { - if (*ptr++ == '\\') - { + while (*ptr != '\"' && *ptr && ++len) { + if (*ptr++ == '\\') { ptr++; /* Skip escaped quotes. */ } } out = MALLOC(char, len + 1); /* The length needed for the string, roughly. */ - if (!out) - { + if (!out) { return 0; } ptr = str + 1; ptr2 = out; - while (*ptr != '\"' && *ptr) - { - if (*ptr != '\\') - { + while (*ptr != '\"' && *ptr) { + if (*ptr != '\\') { *ptr2++ = *ptr++; } - else - { + else { ptr++; - switch (*ptr) - { + switch (*ptr) { case 'b': *ptr2++ = '\b'; break; @@ -288,50 +253,41 @@ namespace Spine case 't': *ptr2++ = '\t'; break; - case 'u': - { + case 'u': { /* transcode utf16 to utf8. */ sscanf(ptr + 1, "%4x", &uc); ptr += 4; /* get the unicode char. */ - if ((uc >= 0xDC00 && uc <= 0xDFFF) || uc == 0) - { + 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') - { + 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) - { + if (uc2 < 0xDC00 || uc2 > 0xDFFF) { break; /* invalid second-half of surrogate. */ } uc = 0x10000 + (((uc & 0x3FF) << 10) | (uc2 & 0x3FF)); } len = 4; - if (uc < 0x80) - { + if (uc < 0x80) { len = 1; } - else if (uc < 0x800) - { + else if (uc < 0x800) { len = 2; } - else if (uc < 0x10000) - { + else if (uc < 0x10000) { len = 3; } ptr2 += len; - switch (len) - { + switch (len) { case 4: *--ptr2 = ((uc | 0x80) & 0xBF); uc >>= 6; @@ -360,8 +316,7 @@ namespace Spine *ptr2 = NULL; - if (*ptr == '\"') - { + if (*ptr == '\"') { ptr++; /* TODO error handling if not \" or \0 ? */ } @@ -371,32 +326,27 @@ namespace Spine return ptr; } - const char* Json::parseNumber(Json *item, const char* num) - { + const char* Json::parseNumber(Json *item, const char* num) { double result = 0.0; int negative = 0; char* ptr = (char*)num; - if (*ptr == '-') - { + if (*ptr == '-') { negative = -1; ++ptr; } - while (*ptr >= '0' && *ptr <= '9') - { + while (*ptr >= '0' && *ptr <= '9') { result = result * 10.0 + (*ptr - '0'); ++ptr; } - if (*ptr == '.') - { + if (*ptr == '.') { double fraction = 0.0; int n = 0; ++ptr; - while (*ptr >= '0' && *ptr <= '9') - { + while (*ptr >= '0' && *ptr <= '9') { fraction = (fraction * 10.0) + (*ptr - '0'); ++ptr; ++n; @@ -404,68 +354,57 @@ namespace Spine result += fraction / pow(10.0, n); } - if (negative) - { + if (negative) { result = -result; } - if (*ptr == 'e' || *ptr == 'E') - { + if (*ptr == 'e' || *ptr == 'E') { double exponent = 0; int expNegative = 0; int n = 0; ++ptr; - if (*ptr == '-') - { + if (*ptr == '-') { expNegative = -1; ++ptr; } - else if (*ptr == '+') - { + else if (*ptr == '+') { ++ptr; } - while (*ptr >= '0' && *ptr <= '9') - { + while (*ptr >= '0' && *ptr <= '9') { exponent = (exponent * 10.0) + (*ptr - '0'); ++ptr; ++n; } - if (expNegative) - { + if (expNegative) { result = result / pow(10, exponent); } - else - { + else { result = result * pow(10, exponent); } } - if (ptr != num) - { + if (ptr != num) { /* Parse success, number found. */ item->_valueFloat = result; item->_valueInt = static_cast(result); item->_type = JSON_NUMBER; return ptr; } - else - { + else { /* Parse failure, _error is set. */ _error = num; return NULL; } } - const char* Json::parseArray(Json *item, const char* value) - { + const char* Json::parseArray(Json *item, const char* value) { Json *child; #if SPINE_JSON_DEBUG /* unnecessary, only callsite (parse_value) verifies this */ - if (*value != '[') - { + if (*value != '[') { ep = value; return 0; } /* not an array! */ @@ -473,33 +412,28 @@ namespace Spine item->_type = JSON_ARRAY; value = skip(value + 1); - if (*value == ']') - { + if (*value == ']') { return value + 1; /* empty array. */ } item->_child = child = NEW(Json); new (item->_child) Json(NULL); - if (!item->_child) - { + if (!item->_child) { return NULL; /* memory fail */ } value = skip(parseValue(child, skip(value))); /* skip any spacing, get the value. */ - if (!value) - { + if (!value) { return NULL; } item->_size = 1; - while (*value == ',') - { + while (*value == ',') { Json *new_item = NEW(Json); new (new_item) Json(NULL); - if (!new_item) - { + if (!new_item) { return NULL; /* memory fail */ } child->_next = new_item; @@ -508,15 +442,13 @@ namespace Spine #endif child = new_item; value = skip(parseValue(child, skip(value + 1))); - if (!value) - { + if (!value) { return NULL; /* parse fail */ } item->_size++; } - if (*value == ']') - { + if (*value == ']') { return value + 1; /* end of array */ } @@ -526,13 +458,11 @@ namespace Spine } /* Build an object from the text. */ - const char* Json::parseObject(Json *item, const char* value) - { + const char* Json::parseObject(Json *item, const char* value) { Json *child; #if SPINE_JSON_DEBUG /* unnecessary, only callsite (parse_value) verifies this */ - if (*value != '{') - { + if (*value != '{') { ep = value; return 0; } /* not an object! */ @@ -540,44 +470,37 @@ namespace Spine item->_type = JSON_OBJECT; value = skip(value + 1); - if (*value == '}') - { + if (*value == '}') { return value + 1; /* empty array. */ } item->_child = child = NEW(Json); new (item->_child) Json(NULL); - if (!item->_child) - { + if (!item->_child) { return NULL; } value = skip(parseString(child, skip(value))); - if (!value) - { + if (!value) { return NULL; } child->_name = child->_valueString; child->_valueString = 0; - if (*value != ':') - { + if (*value != ':') { _error = value; return NULL; } /* fail! */ value = skip(parseValue(child, skip(value + 1))); /* skip any spacing, get the value. */ - if (!value) - { + if (!value) { return NULL; } item->_size = 1; - while (*value == ',') - { + while (*value == ',') { Json *new_item = NEW(Json); new (new_item) Json(NULL); - if (!new_item) - { + if (!new_item) { return NULL; /* memory fail */ } child->_next = new_item; @@ -586,28 +509,24 @@ namespace Spine #endif child = new_item; value = skip(parseString(child, skip(value + 1))); - if (!value) - { + if (!value) { return NULL; } child->_name = child->_valueString; child->_valueString = 0; - if (*value != ':') - { + if (*value != ':') { _error = value; return NULL; } /* fail! */ value = skip(parseValue(child, skip(value + 1))); /* skip any spacing, get the value. */ - if (!value) - { + if (!value) { return NULL; } item->_size++; } - if (*value == '}') - { + if (*value == '}') { return value + 1; /* end of array */ } @@ -616,31 +535,25 @@ namespace Spine return NULL; /* malformed. */ } - int Json::json_strcasecmp(const char* s1, const char* s2) - { + int Json::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 (s1 && s2) { #if defined(_WIN32) return _stricmp(s1, s2); #else return strcasecmp( s1, s2 ); #endif } - else - { - if (s1 < s2) - { + else { + if (s1 < s2) { return -1; /* s1 is null, s2 is not */ } - else if (s1 == s2) - { + else if (s1 == s2) { return 0; /* both are null */ } - else - { + else { return 1; /* s2 is nul s1 is not */ } } diff --git a/spine-cpp/spine-cpp/src/spine/LinkedMesh.cpp b/spine-cpp/spine-cpp/src/spine/LinkedMesh.cpp index a1c25db11..c4e5cdb6e 100644 --- a/spine-cpp/spine-cpp/src/spine/LinkedMesh.cpp +++ b/spine-cpp/spine-cpp/src/spine/LinkedMesh.cpp @@ -38,8 +38,7 @@ namespace Spine _mesh(mesh), _skin(skin), _slotIndex(slotIndex), - _parent(parent) - { + _parent(parent) { // Empty } } diff --git a/spine-cpp/spine-cpp/src/spine/MathUtil.cpp b/spine-cpp/spine-cpp/src/spine/MathUtil.cpp index ddcde2f1e..ac1b25b69 100644 --- a/spine-cpp/spine-cpp/src/spine/MathUtil.cpp +++ b/spine-cpp/spine-cpp/src/spine/MathUtil.cpp @@ -34,56 +34,45 @@ namespace Spine { float MathUtil::SIN_TABLE[SIN_COUNT] = {0.0f}; - MathUtil::MathUtil() - { - for (int i = 0; i < SIN_COUNT; ++i) - { + MathUtil::MathUtil() { + for (int i = 0; i < SIN_COUNT; ++i) { SIN_TABLE[i] = (float)sin((i + 0.5f) / SIN_COUNT * RadFull); } - for (int i = 0; i < 360; i += 90) - { + for (int i = 0; i < 360; i += 90) { SIN_TABLE[(int)(i * DegToIndex) & SIN_MASK] = (float)sin(i * DegRad); } } /// Returns the sine in radians from a lookup table. - float MathUtil::sin(float radians) - { + float MathUtil::sin(float radians) { return SIN_TABLE[(int)(radians * RadToIndex) & SIN_MASK]; } /// Returns the cosine in radians from a lookup table. - float MathUtil::cos(float radians) - { + float MathUtil::cos(float radians) { return SIN_TABLE[(int)((radians + SPINE_PI / 2) * RadToIndex) & SIN_MASK]; } /// Returns the sine in radians from a lookup table. - float MathUtil::sinDeg(float degrees) - { + float MathUtil::sinDeg(float degrees) { return SIN_TABLE[(int)(degrees * DegToIndex) & SIN_MASK]; } /// Returns the cosine in radians from a lookup table. - float MathUtil::cosDeg(float degrees) - { + float MathUtil::cosDeg(float degrees) { return SIN_TABLE[(int)((degrees + 90) * DegToIndex) & SIN_MASK]; } /// Returns atan2 in radians, faster but less accurate than Math.Atan2. Average error of 0.00231 radians (0.1323 /// degrees), largest error of 0.00488 radians (0.2796 degrees). - float MathUtil::atan2(float y, float x) - { - if (areFloatsPracticallyEqual(x, 0.0f)) - { - if (y > 0.0f) - { + float MathUtil::atan2(float y, float x) { + if (areFloatsPracticallyEqual(x, 0.0f)) { + if (y > 0.0f) { return SPINE_PI / 2; } - if (areFloatsPracticallyEqual(y, 0.0f)) - { + if (areFloatsPracticallyEqual(y, 0.0f)) { return 0.0f; } @@ -92,11 +81,9 @@ namespace Spine float atan, z = y / x; - if (fabs(z) < 1.0f) - { + if (fabs(z) < 1.0f) { atan = z / (1.0f + 0.28f * z * z); - if (x < 0.0f) - { + if (x < 0.0f) { return atan + (y < 0.0f ? -SPINE_PI : SPINE_PI); } diff --git a/spine-cpp/spine-cpp/src/spine/MeshAttachment.cpp b/spine-cpp/spine-cpp/src/spine/MeshAttachment.cpp index 7d507b8f5..2c6c459a4 100644 --- a/spine-cpp/spine-cpp/src/spine/MeshAttachment.cpp +++ b/spine-cpp/spine-cpp/src/spine/MeshAttachment.cpp @@ -56,273 +56,218 @@ namespace Spine _a(1), _hullLength(0), _inheritDeform(false), - _regionRotate(false) - { + _regionRotate(false) { // Empty } - void MeshAttachment::updateUVs() - { + void MeshAttachment::updateUVs() { float u = _regionU, v = _regionV, width = _regionU2 - _regionU, height = _regionV2 - _regionV; - if (_uvs.size() != _regionUVs.size()) - { + if (_uvs.size() != _regionUVs.size()) { _uvs.reserve(_regionUVs.size()); _uvs.setSize(_regionUVs.size()); } - if (_regionRotate) - { - for (size_t i = 0, n = _uvs.size(); i < n; i += 2) - { + if (_regionRotate) { + for (size_t i = 0, n = _uvs.size(); i < n; i += 2) { _uvs[i] = u + _regionUVs[i + 1] * width; _uvs[i + 1] = v + height - _regionUVs[i] * height; } } - else - { - for (size_t i = 0, n = _uvs.size(); i < n; i += 2) - { + else { + for (size_t i = 0, n = _uvs.size(); i < n; i += 2) { _uvs[i] = u + _regionUVs[i] * width; _uvs[i + 1] = v + _regionUVs[i + 1] * height; } } } - bool MeshAttachment::applyDeform(VertexAttachment* sourceAttachment) - { + bool MeshAttachment::applyDeform(VertexAttachment* sourceAttachment) { return this == sourceAttachment || (_inheritDeform && _parentMesh == sourceAttachment); } - int MeshAttachment::getHullLength() - { + int MeshAttachment::getHullLength() { return _hullLength; } - void MeshAttachment::setHullLength(float inValue) - { + void MeshAttachment::setHullLength(float inValue) { _hullLength = inValue; } - Vector& MeshAttachment::getRegionUVs() - { + Vector& MeshAttachment::getRegionUVs() { return _regionUVs; } - void MeshAttachment::setRegionUVs(Vector& inValue) - { + void MeshAttachment::setRegionUVs(Vector& inValue) { _regionUVs = inValue; } - Vector& MeshAttachment::getUVs() - { + Vector& MeshAttachment::getUVs() { return _uvs; } - void MeshAttachment::setUVs(Vector& inValue) - { + void MeshAttachment::setUVs(Vector& inValue) { _uvs = inValue; } - Vector& MeshAttachment::getTriangles() - { + Vector& MeshAttachment::getTriangles() { return _triangles; } - void MeshAttachment::setTriangles(Vector& inValue) - { + void MeshAttachment::setTriangles(Vector& inValue) { _triangles = inValue; } - float MeshAttachment::getR() - { + float MeshAttachment::getR() { return _r; } - void MeshAttachment::setR(float inValue) - { + void MeshAttachment::setR(float inValue) { _r = inValue; } - float MeshAttachment::getG() - { + float MeshAttachment::getG() { return _g; } - void MeshAttachment::setG(float inValue) - { + void MeshAttachment::setG(float inValue) { _g = inValue; } - float MeshAttachment::getB() - { + float MeshAttachment::getB() { return _b; } - void MeshAttachment::setB(float inValue) - { + void MeshAttachment::setB(float inValue) { _b = inValue; } - float MeshAttachment::getA() - { + float MeshAttachment::getA() { return _a; } - void MeshAttachment::setA(float inValue) - { + void MeshAttachment::setA(float inValue) { _a = inValue; } - std::string MeshAttachment::getPath() - { + std::string MeshAttachment::getPath() { return _path; } - void MeshAttachment::setPath(std::string inValue) - { + void MeshAttachment::setPath(std::string inValue) { _path = inValue; } - void* MeshAttachment::getRendererObject() - { + void* MeshAttachment::getRendererObject() { return _rendererObject; } - void MeshAttachment::setRendererObject(void* inValue) - { + void MeshAttachment::setRendererObject(void* inValue) { _rendererObject = inValue; } - float MeshAttachment::getRegionU() - { + float MeshAttachment::getRegionU() { return _regionU; } - void MeshAttachment::setRegionU(float inValue) - { + void MeshAttachment::setRegionU(float inValue) { _regionU = inValue; } - float MeshAttachment::getRegionV() - { + float MeshAttachment::getRegionV() { return _regionV; } - void MeshAttachment::setRegionV(float inValue) - { + void MeshAttachment::setRegionV(float inValue) { _regionV = inValue; } - float MeshAttachment::getRegionU2() - { + float MeshAttachment::getRegionU2() { return _regionU2; } - void MeshAttachment::setRegionU2(float inValue) - { + void MeshAttachment::setRegionU2(float inValue) { _regionU2 = inValue; } - float MeshAttachment::getRegionV2() - { + float MeshAttachment::getRegionV2() { return _regionV2; } - void MeshAttachment::setRegionV2(float inValue) - { + void MeshAttachment::setRegionV2(float inValue) { _regionV2 = inValue; } - bool MeshAttachment::getRegionRotate() - { + bool MeshAttachment::getRegionRotate() { return _regionRotate; } - void MeshAttachment::setRegionRotate(float inValue) - { + void MeshAttachment::setRegionRotate(float inValue) { _regionRotate = inValue; } - float MeshAttachment::getRegionOffsetX() - { + float MeshAttachment::getRegionOffsetX() { return _regionOffsetX; } - void MeshAttachment::setRegionOffsetX(float inValue) - { + void MeshAttachment::setRegionOffsetX(float inValue) { _regionOffsetX = inValue; } - float MeshAttachment::getRegionOffsetY() - { + float MeshAttachment::getRegionOffsetY() { return _regionOffsetY; } - void MeshAttachment::setRegionOffsetY(float inValue) - { + void MeshAttachment::setRegionOffsetY(float inValue) { _regionOffsetY = inValue; } - float MeshAttachment::getRegionWidth() - { + float MeshAttachment::getRegionWidth() { return _regionWidth; } - void MeshAttachment::setRegionWidth(float inValue) - { + void MeshAttachment::setRegionWidth(float inValue) { _regionWidth = inValue; } - float MeshAttachment::getRegionHeight() - { + float MeshAttachment::getRegionHeight() { return _regionHeight; } - void MeshAttachment::setRegionHeight(float inValue) - { + void MeshAttachment::setRegionHeight(float inValue) { _regionHeight = inValue; } - float MeshAttachment::getRegionOriginalWidth() - { + float MeshAttachment::getRegionOriginalWidth() { return _regionOriginalWidth; } - void MeshAttachment::setRegionOriginalWidth(float inValue) - { + void MeshAttachment::setRegionOriginalWidth(float inValue) { _regionOriginalWidth = inValue; } - float MeshAttachment::getRegionOriginalHeight() - { + float MeshAttachment::getRegionOriginalHeight() { return _regionOriginalHeight; } - void MeshAttachment::setRegionOriginalHeight(float inValue) - { + void MeshAttachment::setRegionOriginalHeight(float inValue) { _regionOriginalHeight = inValue; } - bool MeshAttachment::getInheritDeform() - { + bool MeshAttachment::getInheritDeform() { return _inheritDeform; } - void MeshAttachment::setInheritDeform(bool inValue) - { + void MeshAttachment::setInheritDeform(bool inValue) { _inheritDeform = inValue; } - MeshAttachment* MeshAttachment::getParentMesh() - { + MeshAttachment* MeshAttachment::getParentMesh() { return _parentMesh; } - void MeshAttachment::setParentMesh(MeshAttachment* inValue) - { + void MeshAttachment::setParentMesh(MeshAttachment* inValue) { _parentMesh = inValue; - if (inValue != NULL) - { + if (inValue != NULL) { _bones = inValue->_bones; _vertices = inValue->_vertices; _worldVerticesLength = inValue->_worldVerticesLength; @@ -335,33 +280,27 @@ namespace Spine } } - Vector& MeshAttachment::getEdges() - { + Vector& MeshAttachment::getEdges() { return _edges; } - void MeshAttachment::setEdges(Vector& inValue) - { + void MeshAttachment::setEdges(Vector& inValue) { _edges = inValue; } - float MeshAttachment::getWidth() - { + float MeshAttachment::getWidth() { return _width; } - void MeshAttachment::setWidth(float inValue) - { + void MeshAttachment::setWidth(float inValue) { _width = inValue; } - float MeshAttachment::getHeight() - { + float MeshAttachment::getHeight() { return _height; } - void MeshAttachment::setHeight(float inValue) - { + void MeshAttachment::setHeight(float inValue) { _height = inValue; } } diff --git a/spine-cpp/spine-cpp/src/spine/PathAttachment.cpp b/spine-cpp/spine-cpp/src/spine/PathAttachment.cpp index 28a06940b..866405ee2 100644 --- a/spine-cpp/spine-cpp/src/spine/PathAttachment.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathAttachment.cpp @@ -34,38 +34,31 @@ namespace Spine { RTTI_IMPL(PathAttachment, VertexAttachment); - PathAttachment::PathAttachment(std::string name) : VertexAttachment(name), _closed(false), _constantSpeed(false) - { + PathAttachment::PathAttachment(std::string name) : VertexAttachment(name), _closed(false), _constantSpeed(false) { // Empty } - Vector& PathAttachment::getLengths() - { + Vector& PathAttachment::getLengths() { return _lengths; } - void PathAttachment::setLengths(Vector inValue) - { + void PathAttachment::setLengths(Vector inValue) { _lengths = inValue; } - bool PathAttachment::isClosed() - { + bool PathAttachment::isClosed() { return _closed; } - void PathAttachment::setClosed(bool inValue) - { + void PathAttachment::setClosed(bool inValue) { _closed = inValue; } - bool PathAttachment::isConstantSpeed() - { + bool PathAttachment::isConstantSpeed() { return _constantSpeed; } - void PathAttachment::setConstantSpeed(bool inValue) - { + void PathAttachment::setConstantSpeed(bool inValue) { _constantSpeed = inValue; } } diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp b/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp index ad06cd4fd..686886290 100644 --- a/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp @@ -58,11 +58,9 @@ namespace Spine _position(data.getPosition()), _spacing(data.getSpacing()), _rotateMix(data.getRotateMix()), - _translateMix(data.getTranslateMix()) - { + _translateMix(data.getTranslateMix()) { _bones.reserve(_data.getBones().size()); - for (BoneData** i = _data.getBones().begin(); i != _data.getBones().end(); ++i) - { + for (BoneData** i = _data.getBones().begin(); i != _data.getBones().end(); ++i) { BoneData* boneData = (*i); _bones.push_back(skeleton.findBone(boneData->getName())); @@ -72,16 +70,13 @@ namespace Spine _segments.setSize(10); } - void PathConstraint::apply() - { + void PathConstraint::apply() { update(); } - void PathConstraint::update() - { + void PathConstraint::update() { Attachment* baseAttachment = _target->getAttachment(); - if (baseAttachment == NULL || !baseAttachment->getRTTI().derivesFrom(PathAttachment::rtti)) - { + if (baseAttachment == NULL || !baseAttachment->getRTTI().derivesFrom(PathAttachment::rtti)) { return; } @@ -91,8 +86,7 @@ namespace Spine float translateMix = _translateMix; bool translate = translateMix > 0; bool rotate = rotateMix > 0; - if (!translate && !rotate) - { + if (!translate && !rotate) { return; } @@ -106,34 +100,27 @@ namespace Spine _spaces.reserve(spacesCount); _spaces.setSize(spacesCount); float spacing = _spacing; - if (scale || lengthSpacing) - { - if (scale) - { + if (scale || lengthSpacing) { + if (scale) { _lengths.reserve(boneCount); _lengths.setSize(boneCount); } - for (int i = 0, n = spacesCount - 1; i < n;) - { + for (int i = 0, n = spacesCount - 1; i < n;) { Bone* boneP = _bones[i]; Bone& bone = *boneP; float setupLength = bone._data.getLength(); - if (setupLength < PathConstraint::EPSILON) - { - if (scale) - { + if (setupLength < PathConstraint::EPSILON) { + if (scale) { _lengths[i] = 0; } _spaces[++i] = 0; } - else - { + else { float x = setupLength * bone._a; float y = setupLength * bone._c; float length = (float)sqrt(x * x + y * y); - if (scale) - { + if (scale) { _lengths[i] = length; } @@ -141,10 +128,8 @@ namespace Spine } } } - else - { - for (int i = 1; i < spacesCount; ++i) - { + else { + for (int i = 1; i < spacesCount; ++i) { _spaces[i] = spacing; } } @@ -154,19 +139,16 @@ namespace Spine float boneY = positions[1]; float offsetRotation = data.getOffsetRotation(); bool tip; - if (offsetRotation == 0) - { + if (offsetRotation == 0) { tip = rotateMode == RotateMode_Chain; } - else - { + else { tip = false; Bone p = _target->getBone(); offsetRotation *= p.getA() * p.getD() - p.getB() * p.getC() > 0 ? DegRad : -DegRad; } - for (int i = 0, p = 3; i < boneCount; i++, p += 3) - { + for (int i = 0, p = 3; i < boneCount; i++, p += 3) { Bone* boneP = _bones[i]; Bone& bone = *boneP; bone._worldX += (boneX - bone._worldX) * translateMix; @@ -175,11 +157,9 @@ namespace Spine float y = positions[p + 1]; float dx = x - boneX; float dy = y - boneY; - if (scale) - { + if (scale) { float length = _lengths[i]; - if (length >= PathConstraint::EPSILON) - { + if (length >= PathConstraint::EPSILON) { float s = ((float)sqrt(dx * dx + dy * dy) / length - 1) * rotateMix + 1; bone._a *= s; bone._c *= s; @@ -189,43 +169,35 @@ namespace Spine boneX = x; boneY = y; - if (rotate) - { + if (rotate) { float a = bone._a, b = bone._b, c = bone._c, d = bone._d, r, cos, sin; - if (tangents) - { + if (tangents) { r = positions[p - 1]; } - else if (_spaces[i + 1] < PathConstraint::EPSILON) - { + else if (_spaces[i + 1] < PathConstraint::EPSILON) { r = positions[p + 2]; } - else - { + else { r = MathUtil::atan2(dy, dx); } r -= MathUtil::atan2(c, a); - if (tip) - { + if (tip) { cos = MathUtil::cos(r); sin = MathUtil::sin(r); float length = bone._data.getLength(); boneX += (length * (cos * a - sin * c) - dx) * rotateMix; boneY += (length * (sin * a + cos * c) - dy) * rotateMix; } - else - { + else { r += offsetRotation; } - if (r > SPINE_PI) - { + if (r > SPINE_PI) { r -= SPINE_PI_2; } - else if (r < -SPINE_PI) - { + else if (r < -SPINE_PI) { r += SPINE_PI_2; } @@ -242,73 +214,59 @@ namespace Spine } } - int PathConstraint::getOrder() - { + int PathConstraint::getOrder() { return _data.getOrder(); } - float PathConstraint::getPosition() - { + float PathConstraint::getPosition() { return _position; } - void PathConstraint::setPosition(float inValue) - { + void PathConstraint::setPosition(float inValue) { _position = inValue; } - float PathConstraint::getSpacing() - { + float PathConstraint::getSpacing() { return _spacing; } - void PathConstraint::setSpacing(float inValue) - { + void PathConstraint::setSpacing(float inValue) { _spacing = inValue; } - float PathConstraint::getRotateMix() - { + float PathConstraint::getRotateMix() { return _rotateMix; } - void PathConstraint::setRotateMix(float inValue) - { + void PathConstraint::setRotateMix(float inValue) { _rotateMix = inValue; } - float PathConstraint::getTranslateMix() - { + float PathConstraint::getTranslateMix() { return _translateMix; } - void PathConstraint::setTranslateMix(float inValue) - { + void PathConstraint::setTranslateMix(float inValue) { _translateMix = inValue; } - Vector& PathConstraint::getBones() - { + Vector& PathConstraint::getBones() { return _bones; } - Slot* PathConstraint::getTarget() - { + Slot* PathConstraint::getTarget() { return _target; } - void PathConstraint::setTarget(Slot* inValue) - { + void PathConstraint::setTarget(Slot* inValue) { _target = inValue; } - PathConstraintData& PathConstraint::getData() - { + PathConstraintData& PathConstraint::getData() { return _data; } - Vector PathConstraint::computeWorldPositions(PathAttachment& path, int spacesCount, bool tangents, bool percentPosition, bool percentSpacing) - { + Vector PathConstraint::computeWorldPositions(PathAttachment& path, int spacesCount, bool tangents, bool percentPosition, bool percentSpacing) { Slot& target = *_target; float position = _position; _positions.reserve(spacesCount * 3 + 2); @@ -319,46 +277,37 @@ namespace Spine int prevCurve = NONE; float pathLength; - if (!path.isConstantSpeed()) - { + if (!path.isConstantSpeed()) { Vector& lengths = path.getLengths(); curveCount -= closed ? 1 : 2; pathLength = lengths[curveCount]; - if (percentPosition) - { + if (percentPosition) { position *= pathLength; } - if (percentSpacing) - { - for (int i = 0; i < spacesCount; ++i) - { + if (percentSpacing) { + for (int i = 0; i < spacesCount; ++i) { _spaces[i] *= pathLength; } } _world.reserve(8); _world.setSize(8); - for (int i = 0, o = 0, curve = 0; i < spacesCount; i++, o += 3) - { + for (int i = 0, o = 0, curve = 0; i < spacesCount; i++, o += 3) { float space = _spaces[i]; position += space; float p = position; - if (closed) - { + if (closed) { p = fmod(p, pathLength); - if (p < 0) - { + if (p < 0) { p += pathLength; } curve = 0; } - else if (p < 0) - { - if (prevCurve != BEFORE) - { + else if (p < 0) { + if (prevCurve != BEFORE) { prevCurve = BEFORE; path.computeWorldVertices(target, 2, 4, _world, 0); } @@ -367,10 +316,8 @@ namespace Spine continue; } - else if (p > pathLength) - { - if (prevCurve != AFTER) - { + else if (p > pathLength) { + if (prevCurve != AFTER) { prevCurve = AFTER; path.computeWorldVertices(target, verticesLength - 6, 4, _world, 0); } @@ -381,36 +328,29 @@ namespace Spine } // Determine curve containing position. - for (;; curve++) - { + for (;; curve++) { float length = lengths[curve]; - if (p > length) - { + if (p > length) { continue; } - if (curve == 0) - { + if (curve == 0) { p /= length; } - else - { + else { float prev = lengths[curve - 1]; p = (p - prev) / (length - prev); } break; } - if (curve != prevCurve) - { + if (curve != prevCurve) { prevCurve = curve; - if (closed && curve == curveCount) - { + if (closed && curve == curveCount) { path.computeWorldVertices(target, verticesLength - 4, 4, _world, 0); path.computeWorldVertices(target, 0, 4, _world, 4); } - else - { + else { path.computeWorldVertices(target, curve * 6 + 2, 8, _world, 0); } } @@ -421,8 +361,7 @@ namespace Spine } // World vertices. - if (closed) - { + if (closed) { verticesLength += 2; _world.reserve(verticesLength); _world.setSize(verticesLength); @@ -431,8 +370,7 @@ namespace Spine _world[verticesLength - 2] = _world[0]; _world[verticesLength - 1] = _world[1]; } - else - { + else { curveCount--; verticesLength -= 4; _world.reserve(verticesLength); @@ -446,8 +384,7 @@ namespace Spine pathLength = 0; float x1 = _world[0], y1 = _world[1], cx1 = 0, cy1 = 0, cx2 = 0, cy2 = 0, x2 = 0, y2 = 0; float tmpx, tmpy, dddfx, dddfy, ddfx, ddfy, dfx, dfy; - for (int i = 0, w = 2; i < curveCount; i++, w += 6) - { + for (int i = 0, w = 2; i < curveCount; i++, w += 6) { cx1 = _world[w]; cy1 = _world[w + 1]; cx2 = _world[w + 2]; @@ -479,62 +416,50 @@ namespace Spine y1 = y2; } - if (percentPosition) - { + if (percentPosition) { position *= pathLength; } - if (percentSpacing) - { - for (int i = 0; i < spacesCount; ++i) - { + if (percentSpacing) { + for (int i = 0; i < spacesCount; ++i) { _spaces[i] *= pathLength; } } float curveLength = 0; - for (int i = 0, o = 0, curve = 0, segment = 0; i < spacesCount; i++, o += 3) - { + for (int i = 0, o = 0, curve = 0, segment = 0; i < spacesCount; i++, o += 3) { float space = _spaces[i]; position += space; float p = position; - if (closed) - { + if (closed) { p = fmod(p, pathLength); - if (p < 0) - { + if (p < 0) { p += pathLength; } curve = 0; } - else if (p < 0) - { + else if (p < 0) { addBeforePosition(p, _world, 0, _positions, o); continue; } - else if (p > pathLength) - { + else if (p > pathLength) { addAfterPosition(p - pathLength, _world, verticesLength - 4, _positions, o); continue; } // Determine curve containing position. - for (;; curve++) - { + for (;; curve++) { float length = _curves[curve]; - if (p > length) - { + if (p > length) { continue; } - if (curve == 0) - { + if (curve == 0) { p /= length; } - else - { + else { float prev = _curves[curve - 1]; p = (p - prev) / (length - prev); } @@ -542,8 +467,7 @@ namespace Spine } // Curve segment lengths. - if (curve != prevCurve) - { + if (curve != prevCurve) { prevCurve = curve; int ii = curve * 6; x1 = _world[ii]; @@ -564,8 +488,7 @@ namespace Spine dfy = (cy1 - y1) * 0.3f + tmpy + dddfy * 0.16666667f; curveLength = (float)sqrt(dfx * dfx + dfy * dfy); _segments[0] = curveLength; - for (ii = 1; ii < 8; ii++) - { + for (ii = 1; ii < 8; ii++) { dfx += ddfx; dfy += ddfy; ddfx += dddfx; @@ -586,20 +509,16 @@ namespace Spine // Weight by segment length. p *= curveLength; - for (;; segment++) - { + for (;; segment++) { float length = _segments[segment]; - if (p > length) - { + if (p > length) { continue; } - if (segment == 0) - { + if (segment == 0) { p /= length; } - else - { + else { float prev = _segments[segment - 1]; p = segment + (p - prev) / (length - prev); } @@ -611,8 +530,7 @@ namespace Spine return _positions; } - void PathConstraint::addBeforePosition(float p, Vector& temp, int i, Vector& output, int o) - { + void PathConstraint::addBeforePosition(float p, Vector& temp, int i, Vector& output, int o) { float x1 = temp[i]; float y1 = temp[i + 1]; float dx = temp[i + 2] - x1; @@ -624,8 +542,7 @@ namespace Spine output[o + 2] = r; } - void PathConstraint::addAfterPosition(float p, Vector& temp, int i, Vector& output, int o) - { + void PathConstraint::addAfterPosition(float p, Vector& temp, int i, Vector& output, int o) { float x1 = temp[i + 2]; float y1 = temp[i + 3]; float dx = x1 - temp[i]; @@ -636,10 +553,8 @@ namespace Spine output[o + 2] = r; } - void PathConstraint::addCurvePosition(float p, float x1, float y1, float cx1, float cy1, float cx2, float cy2, float x2, float y2, Vector& output, int o, bool tangents) - { - if (p < EPSILON || isnan(p)) - { + void PathConstraint::addCurvePosition(float p, float x1, float y1, float cx1, float cy1, float cx2, float cy2, float x2, float y2, Vector& output, int o, bool tangents) { + if (p < EPSILON || isnan(p)) { p = EPSILON; } @@ -648,8 +563,7 @@ namespace Spine float x = x1 * uuu + cx1 * uut3 + cx2 * utt3 + x2 * ttt, y = y1 * uuu + cy1 * uut3 + cy2 * utt3 + y2 * ttt; output[o] = x; output[o + 1] = y; - if (tangents) - { + if (tangents) { output[o + 2] = (float)atan2(y - (y1 * uu + cy1 * ut * 2 + cy2 * tt), x - (x1 * uu + cx1 * ut * 2 + cx2 * tt)); } } diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraintData.cpp b/spine-cpp/spine-cpp/src/spine/PathConstraintData.cpp index f3ef57df7..380719527 100644 --- a/spine-cpp/spine-cpp/src/spine/PathConstraintData.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathConstraintData.cpp @@ -48,118 +48,95 @@ namespace Spine _position(0), _spacing(0), _rotateMix(0), - _translateMix(0) - { + _translateMix(0) { assert(_name.length() > 0); } - const std::string& PathConstraintData::getName() - { + const std::string& PathConstraintData::getName() { return _name; } - int PathConstraintData::getOrder() - { + int PathConstraintData::getOrder() { return _order; } - void PathConstraintData::setOrder(int inValue) - { + void PathConstraintData::setOrder(int inValue) { _order = inValue; } - Vector& PathConstraintData::getBones() - { + Vector& PathConstraintData::getBones() { return _bones; } - SlotData* PathConstraintData::getTarget() - { + SlotData* PathConstraintData::getTarget() { return _target; } - void PathConstraintData::setTarget(SlotData* inValue) - { + void PathConstraintData::setTarget(SlotData* inValue) { _target = inValue; } - PositionMode PathConstraintData::getPositionMode() - { + PositionMode PathConstraintData::getPositionMode() { return _positionMode; } - void PathConstraintData::setPositionMode(PositionMode inValue) - { + void PathConstraintData::setPositionMode(PositionMode inValue) { _positionMode = inValue; } - SpacingMode PathConstraintData::getSpacingMode() - { + SpacingMode PathConstraintData::getSpacingMode() { return _spacingMode; } - void PathConstraintData::setSpacingMode(SpacingMode inValue) - { + void PathConstraintData::setSpacingMode(SpacingMode inValue) { _spacingMode = inValue; } - RotateMode PathConstraintData::getRotateMode() - { + RotateMode PathConstraintData::getRotateMode() { return _rotateMode; } - void PathConstraintData::setRotateMode(RotateMode inValue) - { + void PathConstraintData::setRotateMode(RotateMode inValue) { _rotateMode = inValue; } - float PathConstraintData::getOffsetRotation() - { + float PathConstraintData::getOffsetRotation() { return _offsetRotation; } - void PathConstraintData::setOffsetRotation(float inValue) - { + void PathConstraintData::setOffsetRotation(float inValue) { _offsetRotation = inValue; } - float PathConstraintData::getPosition() - { + float PathConstraintData::getPosition() { return _position; } - void PathConstraintData::setPosition(float inValue) - { + void PathConstraintData::setPosition(float inValue) { _position = inValue; } - float PathConstraintData::getSpacing() - { + float PathConstraintData::getSpacing() { return _spacing; } - void PathConstraintData::setSpacing(float inValue) - { + void PathConstraintData::setSpacing(float inValue) { _spacing = inValue; } - float PathConstraintData::getRotateMix() - { + float PathConstraintData::getRotateMix() { return _rotateMix; } - void PathConstraintData::setRotateMix(float inValue) - { + void PathConstraintData::setRotateMix(float inValue) { _rotateMix = inValue; } - float PathConstraintData::getTranslateMix() - { + float PathConstraintData::getTranslateMix() { return _translateMix; } - void PathConstraintData::setTranslateMix(float inValue) - { + void PathConstraintData::setTranslateMix(float inValue) { _translateMix = inValue; } } diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp b/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp index e3ad99d41..606d71b9e 100644 --- a/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp @@ -51,20 +51,16 @@ namespace Spine const int PathConstraintMixTimeline::ROTATE = 1; const int PathConstraintMixTimeline::TRANSLATE = 2; - PathConstraintMixTimeline::PathConstraintMixTimeline(int frameCount) : CurveTimeline(frameCount), _pathConstraintIndex(0) - { + PathConstraintMixTimeline::PathConstraintMixTimeline(int frameCount) : CurveTimeline(frameCount), _pathConstraintIndex(0) { _frames.reserve(frameCount * ENTRIES); _frames.setSize(frameCount * ENTRIES); } - void PathConstraintMixTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) - { + void PathConstraintMixTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) { PathConstraint* constraintP = skeleton._pathConstraints[_pathConstraintIndex]; PathConstraint& constraint = *constraintP; - if (time < _frames[0]) - { - switch (pose) - { + if (time < _frames[0]) { + switch (pose) { case MixPose_Setup: constraint._rotateMix = constraint._data._rotateMix; constraint._translateMix = constraint._data._translateMix; @@ -80,14 +76,12 @@ namespace Spine } float rotate, translate; - if (time >= _frames[_frames.size() - ENTRIES]) - { + if (time >= _frames[_frames.size() - ENTRIES]) { // Time is after last frame. rotate = _frames[_frames.size() + PREV_ROTATE]; translate = _frames[_frames.size() + PREV_TRANSLATE]; } - else - { + else { // Interpolate between the previous frame and the current frame. int frame = Animation::binarySearch(_frames, time, ENTRIES); rotate = _frames[frame + PREV_ROTATE]; @@ -100,25 +94,21 @@ namespace Spine translate += (_frames[frame + TRANSLATE] - translate) * percent; } - if (pose == MixPose_Setup) - { + if (pose == MixPose_Setup) { constraint._rotateMix = constraint._data._rotateMix + (rotate - constraint._data._rotateMix) * alpha; constraint._translateMix = constraint._data._translateMix + (translate - constraint._data._translateMix) * alpha; } - else - { + else { constraint._rotateMix += (rotate - constraint._rotateMix) * alpha; constraint._translateMix += (translate - constraint._translateMix) * alpha; } } - int PathConstraintMixTimeline::getPropertyId() - { + int PathConstraintMixTimeline::getPropertyId() { return ((int)TimelineType_PathConstraintMix << 24) + _pathConstraintIndex; } - void PathConstraintMixTimeline::setFrame(int frameIndex, float time, float rotateMix, float translateMix) - { + void PathConstraintMixTimeline::setFrame(int frameIndex, float time, float rotateMix, float translateMix) { frameIndex *= ENTRIES; _frames[frameIndex] = time; _frames[frameIndex + ROTATE] = rotateMix; diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp b/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp index c60c2941f..ba0a63555 100644 --- a/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp @@ -49,20 +49,16 @@ namespace Spine const int PathConstraintPositionTimeline::PREV_VALUE = -1; const int PathConstraintPositionTimeline::VALUE = 1; - PathConstraintPositionTimeline::PathConstraintPositionTimeline(int frameCount) : CurveTimeline(frameCount), _pathConstraintIndex(0) - { + PathConstraintPositionTimeline::PathConstraintPositionTimeline(int frameCount) : CurveTimeline(frameCount), _pathConstraintIndex(0) { _frames.reserve(frameCount * ENTRIES); _frames.setSize(frameCount * ENTRIES); } - void PathConstraintPositionTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) - { + void PathConstraintPositionTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) { PathConstraint* constraintP = skeleton._pathConstraints[_pathConstraintIndex]; PathConstraint& constraint = *constraintP; - if (time < _frames[0]) - { - switch (pose) - { + if (time < _frames[0]) { + switch (pose) { case MixPose_Setup: constraint._position = constraint._data._position; return; @@ -76,12 +72,11 @@ namespace Spine } float position; - if (time >= _frames[_frames.size() - ENTRIES]) // Time is after last frame. - { + if (time >= _frames[_frames.size() - ENTRIES]) { + // Time is after last frame. position = _frames[_frames.size() + PREV_VALUE]; } - else - { + else { // Interpolate between the previous frame and the current frame. int frame = Animation::binarySearch(_frames, time, ENTRIES); position = _frames[frame + PREV_VALUE]; @@ -91,23 +86,19 @@ namespace Spine position += (_frames[frame + VALUE] - position) * percent; } - if (pose == MixPose_Setup) - { + if (pose == MixPose_Setup) { constraint._position = constraint._data._position + (position - constraint._data._position) * alpha; } - else - { + else { constraint._position += (position - constraint._position) * alpha; } } - int PathConstraintPositionTimeline::getPropertyId() - { + int PathConstraintPositionTimeline::getPropertyId() { return ((int)TimelineType_PathConstraintPosition << 24) + _pathConstraintIndex; } - void PathConstraintPositionTimeline::setFrame(int frameIndex, float time, float value) - { + void PathConstraintPositionTimeline::setFrame(int frameIndex, float time, float value) { frameIndex *= ENTRIES; _frames[frameIndex] = time; _frames[frameIndex + VALUE] = value; diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp b/spine-cpp/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp index 44d132596..f029a9e4a 100644 --- a/spine-cpp/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp @@ -44,19 +44,15 @@ namespace Spine { RTTI_IMPL(PathConstraintSpacingTimeline, PathConstraintPositionTimeline); - PathConstraintSpacingTimeline::PathConstraintSpacingTimeline(int frameCount) : PathConstraintPositionTimeline(frameCount) - { + PathConstraintSpacingTimeline::PathConstraintSpacingTimeline(int frameCount) : PathConstraintPositionTimeline(frameCount) { // Empty } - void PathConstraintSpacingTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) - { + void PathConstraintSpacingTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) { PathConstraint* constraintP = skeleton._pathConstraints[_pathConstraintIndex]; PathConstraint& constraint = *constraintP; - if (time < _frames[0]) - { - switch (pose) - { + if (time < _frames[0]) { + switch (pose) { case MixPose_Setup: constraint._spacing = constraint._data._spacing; return; @@ -70,12 +66,11 @@ namespace Spine } float spacing; - if (time >= _frames[_frames.size() - ENTRIES]) // Time is after last frame. - { + if (time >= _frames[_frames.size() - ENTRIES]) { + // Time is after last frame. spacing = _frames[_frames.size() + PREV_VALUE]; } - else - { + else { // Interpolate between the previous frame and the current frame. int frame = Animation::binarySearch(_frames, time, ENTRIES); spacing = _frames[frame + PREV_VALUE]; @@ -86,18 +81,15 @@ namespace Spine spacing += (_frames[frame + VALUE] - spacing) * percent; } - if (pose == MixPose_Setup) - { + if (pose == MixPose_Setup) { constraint._spacing = constraint._data._spacing + (spacing - constraint._data._spacing) * alpha; } - else - { + else { constraint._spacing += (spacing - constraint._spacing) * alpha; } } - int PathConstraintSpacingTimeline::getPropertyId() - { + int PathConstraintSpacingTimeline::getPropertyId() { return ((int)TimelineType_PathConstraintSpacing << 24) + _pathConstraintIndex; } } diff --git a/spine-cpp/spine-cpp/src/spine/PointAttachment.cpp b/spine-cpp/spine-cpp/src/spine/PointAttachment.cpp index 693eb837c..09c32d43c 100644 --- a/spine-cpp/spine-cpp/src/spine/PointAttachment.cpp +++ b/spine-cpp/spine-cpp/src/spine/PointAttachment.cpp @@ -38,18 +38,15 @@ namespace Spine { RTTI_IMPL(PointAttachment, Attachment); - PointAttachment::PointAttachment(std::string name) : Attachment(name), _x(0), _y(0), _rotation(0) - { + PointAttachment::PointAttachment(std::string name) : Attachment(name), _x(0), _y(0), _rotation(0) { // Empty } - void PointAttachment::computeWorldPosition(Bone& bone, float& ox, float& oy) - { + void PointAttachment::computeWorldPosition(Bone& bone, float& ox, float& oy) { bone.localToWorld(_x, _y, ox, oy); } - float PointAttachment::computeWorldRotation(Bone& bone) - { + float PointAttachment::computeWorldRotation(Bone& bone) { float cos = MathUtil::cosDeg(_rotation); float sin = MathUtil::sinDeg(_rotation); float ix = cos * bone._a + sin * bone._b; @@ -58,33 +55,27 @@ namespace Spine return MathUtil::atan2(iy, ix) * RadDeg; } - float PointAttachment::getX() - { + float PointAttachment::getX() { return _x; } - void PointAttachment::setX(float inValue) - { + void PointAttachment::setX(float inValue) { _x = inValue; } - float PointAttachment::getY() - { + float PointAttachment::getY() { return _y; } - void PointAttachment::setY(float inValue) - { + void PointAttachment::setY(float inValue) { _y = inValue; } - float PointAttachment::getRotation() - { + float PointAttachment::getRotation() { return _rotation; } - void PointAttachment::setRotation(float inValue) - { + void PointAttachment::setRotation(float inValue) { _rotation = inValue; } } diff --git a/spine-cpp/spine-cpp/src/spine/RTTI.cpp b/spine-cpp/spine-cpp/src/spine/RTTI.cpp index 9d271f894..8a734a898 100644 --- a/spine-cpp/spine-cpp/src/spine/RTTI.cpp +++ b/spine-cpp/spine-cpp/src/spine/RTTI.cpp @@ -32,34 +32,27 @@ namespace Spine { - RTTI::RTTI(const std::string& className) : m_className(className), m_pBaseRTTI(NULL) - { + RTTI::RTTI(const std::string& className) : m_className(className), m_pBaseRTTI(NULL) { // Empty } - RTTI::RTTI(const std::string& className, const RTTI& baseRTTI) : m_className(className), m_pBaseRTTI(&baseRTTI) - { + RTTI::RTTI(const std::string& className, const RTTI& baseRTTI) : m_className(className), m_pBaseRTTI(&baseRTTI) { // Empty } - const std::string& RTTI::getClassName() const - { + const std::string& RTTI::getClassName() const { return m_className; } - bool RTTI::isExactly(const RTTI& rtti) const - { + bool RTTI::isExactly(const RTTI& rtti) const { return (this == &rtti); } - bool RTTI::derivesFrom(const RTTI& rtti) const - { + bool RTTI::derivesFrom(const RTTI& rtti) const { const RTTI * pCompare = this; - while (pCompare) - { - if (pCompare == &rtti) - { + while (pCompare) { + if (pCompare == &rtti) { return true; } diff --git a/spine-cpp/spine-cpp/src/spine/RegionAttachment.cpp b/spine-cpp/spine-cpp/src/spine/RegionAttachment.cpp index 98d9a9f7d..b2e38ba79 100644 --- a/spine-cpp/spine-cpp/src/spine/RegionAttachment.cpp +++ b/spine-cpp/spine-cpp/src/spine/RegionAttachment.cpp @@ -72,8 +72,7 @@ namespace Spine _r(0), _g(0), _b(0), - _a(0) - { + _a(0) { _offset.reserve(NUM_UVS); _uvs.reserve(NUM_UVS); @@ -81,8 +80,7 @@ namespace Spine _uvs.setSize(NUM_UVS); } - void RegionAttachment::updateOffset() - { + void RegionAttachment::updateOffset() { float regionScaleX = _width / _regionOriginalWidth * _scaleX; float regionScaleY = _height / _regionOriginalHeight * _scaleY; float localX = -_width / 2 * _scaleX + _regionOffsetX * regionScaleX; @@ -110,10 +108,8 @@ namespace Spine _offset[BRY] = localYCos + localX2Sin; } - void RegionAttachment::setUVs(float u, float v, float u2, float v2, bool rotate) - { - if (rotate) - { + void RegionAttachment::setUVs(float u, float v, float u2, float v2, bool rotate) { + if (rotate) { _uvs[URX] = u; _uvs[URY] = v2; _uvs[BRX] = u; @@ -123,8 +119,7 @@ namespace Spine _uvs[ULX] = u2; _uvs[ULY] = v2; } - else - { + else { _uvs[ULX] = u; _uvs[ULY] = v2; _uvs[URX] = u; @@ -136,8 +131,7 @@ namespace Spine } } - void RegionAttachment::computeWorldVertices(Bone& bone, Vector& worldVertices, int offset, int stride) - { + void RegionAttachment::computeWorldVertices(Bone& bone, Vector& worldVertices, int offset, int stride) { assert(worldVertices.size() >= (offset + 8)); float bwx = bone._worldX, bwy = bone._worldY; @@ -168,203 +162,163 @@ namespace Spine worldVertices[offset + 1] = offsetX * c + offsetY * d + bwy; } - float RegionAttachment::getX() - { + float RegionAttachment::getX() { return _x; } - void RegionAttachment::setX(float inValue) - { + void RegionAttachment::setX(float inValue) { _x = inValue; } - float RegionAttachment::getY() - { + float RegionAttachment::getY() { return _y; } - void RegionAttachment::setY(float inValue) - { + void RegionAttachment::setY(float inValue) { _y = inValue; } - float RegionAttachment::getRotation() - { + float RegionAttachment::getRotation() { return _rotation; } - void RegionAttachment::setRotation(float inValue) - { + void RegionAttachment::setRotation(float inValue) { _rotation = inValue; } - float RegionAttachment::getScaleX() - { + float RegionAttachment::getScaleX() { return _scaleX; } - void RegionAttachment::setScaleX(float inValue) - { + void RegionAttachment::setScaleX(float inValue) { _scaleX = inValue; } - float RegionAttachment::getScaleY() - { + float RegionAttachment::getScaleY() { return _scaleY; } - void RegionAttachment::setScaleY(float inValue) - { + void RegionAttachment::setScaleY(float inValue) { _scaleY = inValue; } - float RegionAttachment::getWidth() - { + float RegionAttachment::getWidth() { return _width; } - void RegionAttachment::setWidth(float inValue) - { + void RegionAttachment::setWidth(float inValue) { _width = inValue; } - float RegionAttachment::getHeight() - { + float RegionAttachment::getHeight() { return _height; } - void RegionAttachment::setHeight(float inValue) - { + void RegionAttachment::setHeight(float inValue) { _height = inValue; } - float RegionAttachment::getR() - { + float RegionAttachment::getR() { return _r; } - void RegionAttachment::setR(float inValue) - { + void RegionAttachment::setR(float inValue) { _r = inValue; } - float RegionAttachment::getG() - { + float RegionAttachment::getG() { return _g; } - void RegionAttachment::setG(float inValue) - { + void RegionAttachment::setG(float inValue) { _g = inValue; } - float RegionAttachment::getB() - { + float RegionAttachment::getB() { return _b; } - void RegionAttachment::setB(float inValue) - { + void RegionAttachment::setB(float inValue) { _b = inValue; } - float RegionAttachment::getA() - { + float RegionAttachment::getA() { return _a; } - void RegionAttachment::setA(float inValue) - { + void RegionAttachment::setA(float inValue) { _a = inValue; } - std::string RegionAttachment::getPath() - { + std::string RegionAttachment::getPath() { return _path; } - void RegionAttachment::setPath(std::string inValue) - { + void RegionAttachment::setPath(std::string inValue) { _path = inValue; } - void* RegionAttachment::getRendererObject() - { + void* RegionAttachment::getRendererObject() { return _rendererObject; } - void RegionAttachment::setRendererObject(void* inValue) - { + void RegionAttachment::setRendererObject(void* inValue) { _rendererObject = inValue; } - float RegionAttachment::getRegionOffsetX() - { + float RegionAttachment::getRegionOffsetX() { return _regionOffsetX; } - void RegionAttachment::setRegionOffsetX(float inValue) - { + void RegionAttachment::setRegionOffsetX(float inValue) { _regionOffsetX = inValue; } - float RegionAttachment::getRegionOffsetY() - { + float RegionAttachment::getRegionOffsetY() { return _regionOffsetY; } - void RegionAttachment::setRegionOffsetY(float inValue) - { + void RegionAttachment::setRegionOffsetY(float inValue) { _regionOffsetY = inValue; } - float RegionAttachment::getRegionWidth() - { + float RegionAttachment::getRegionWidth() { return _regionWidth; } - void RegionAttachment::setRegionWidth(float inValue) - { + void RegionAttachment::setRegionWidth(float inValue) { _regionWidth = inValue; } - float RegionAttachment::getRegionHeight() - { + float RegionAttachment::getRegionHeight() { return _regionHeight; } - void RegionAttachment::setRegionHeight(float inValue) - { + void RegionAttachment::setRegionHeight(float inValue) { _regionHeight = inValue; } - float RegionAttachment::getRegionOriginalWidth() - { + float RegionAttachment::getRegionOriginalWidth() { return _regionOriginalWidth; } - void RegionAttachment::setRegionOriginalWidth(float inValue) - { + void RegionAttachment::setRegionOriginalWidth(float inValue) { _regionOriginalWidth = inValue; } - float RegionAttachment::getRegionOriginalHeight() - { + float RegionAttachment::getRegionOriginalHeight() { return _regionOriginalHeight; } - void RegionAttachment::setRegionOriginalHeight(float inValue) - { + void RegionAttachment::setRegionOriginalHeight(float inValue) { _regionOriginalHeight = inValue; } - Vector& RegionAttachment::getOffset() - { + Vector& RegionAttachment::getOffset() { return _offset; } - Vector& RegionAttachment::getUVs() - { + Vector& RegionAttachment::getUVs() { return _uvs; } } diff --git a/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp b/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp index 16ceee334..b17a406f7 100644 --- a/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp @@ -42,34 +42,27 @@ namespace Spine { RTTI_IMPL(RotateTimeline, CurveTimeline); - RotateTimeline::RotateTimeline(int frameCount) : CurveTimeline(frameCount), _boneIndex(0) - { + RotateTimeline::RotateTimeline(int frameCount) : CurveTimeline(frameCount), _boneIndex(0) { _frames.reserve(frameCount << 1); _frames.setSize(frameCount << 1); } - void RotateTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) - { + void RotateTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) { Bone* bone = skeleton.getBones()[_boneIndex]; - if (time < _frames[0]) - { - switch (pose) - { - case MixPose_Setup: - { + if (time < _frames[0]) { + switch (pose) { + case MixPose_Setup: { bone->_rotation = bone->_data._rotation; break; } - case MixPose_Current: - { + case MixPose_Current: { float rr = bone->_data._rotation - bone->_rotation; rr -= (16384 - (int)(16384.499999999996 - rr / 360)) * 360; bone->_rotation += rr * alpha; break; } - case MixPose_CurrentLayered: - { + case MixPose_CurrentLayered: { // TODO? break; } @@ -78,15 +71,12 @@ namespace Spine return; } - if (time >= _frames[_frames.size() - ENTRIES]) - { + if (time >= _frames[_frames.size() - ENTRIES]) { // Time is after last frame. - if (pose == MixPose_Setup) - { + if (pose == MixPose_Setup) { bone->_rotation = bone->_data._rotation + _frames[_frames.size() + PREV_ROTATION] * alpha; } - else - { + else { float rr = bone->_data._rotation + _frames[_frames.size() + PREV_ROTATION] - bone->_rotation; rr -= (16384 - (int)(16384.499999999996 - rr / 360)) * 360; // Wrap within -180 and 180. bone->_rotation += rr * alpha; @@ -105,48 +95,40 @@ namespace Spine r -= (16384 - (int)(16384.499999999996 - r / 360)) * 360; r = prevRotation + r * percent; - if (pose == MixPose_Setup) - { + if (pose == MixPose_Setup) { r -= (16384 - (int)(16384.499999999996 - r / 360)) * 360; bone->_rotation = bone->_data._rotation + r * alpha; } - else - { + else { r = bone->_data._rotation + r - bone->_rotation; r -= (16384 - (int)(16384.499999999996 - r / 360)) * 360; bone->_rotation += r * alpha; } } - int RotateTimeline::getPropertyId() - { + int RotateTimeline::getPropertyId() { return ((int)TimelineType_Rotate << 24) + _boneIndex; } - void RotateTimeline::setFrame(int frameIndex, float time, float degrees) - { + void RotateTimeline::setFrame(int frameIndex, float time, float degrees) { frameIndex <<= 1; _frames[frameIndex] = time; _frames[frameIndex + ROTATION] = degrees; } - int RotateTimeline::getBoneIndex() - { + int RotateTimeline::getBoneIndex() { return _boneIndex; } - void RotateTimeline::setBoneIndex(int inValue) - { + void RotateTimeline::setBoneIndex(int inValue) { _boneIndex = inValue; } - Vector& RotateTimeline::getFrames() - { + Vector& RotateTimeline::getFrames() { return _frames; } - void RotateTimeline::setFrames(Vector inValue) - { + void RotateTimeline::setFrames(Vector inValue) { _frames = inValue; } } diff --git a/spine-cpp/spine-cpp/src/spine/ScaleTimeline.cpp b/spine-cpp/spine-cpp/src/spine/ScaleTimeline.cpp index 9c110a064..fe5ccc6fc 100644 --- a/spine-cpp/spine-cpp/src/spine/ScaleTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/ScaleTimeline.cpp @@ -44,20 +44,16 @@ namespace Spine { RTTI_IMPL(ScaleTimeline, TranslateTimeline); - ScaleTimeline::ScaleTimeline(int frameCount) : TranslateTimeline(frameCount) - { + ScaleTimeline::ScaleTimeline(int frameCount) : TranslateTimeline(frameCount) { // Empty } - void ScaleTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) - { + void ScaleTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) { Bone* boneP = skeleton._bones[_boneIndex]; Bone& bone = *boneP; - if (time < _frames[0]) - { - switch (pose) - { + if (time < _frames[0]) { + switch (pose) { case MixPose_Setup: bone._scaleX = bone._data._scaleX; bone._scaleY = bone._data._scaleY; @@ -73,14 +69,12 @@ namespace Spine } float x, y; - if (time >= _frames[_frames.size() - ENTRIES]) - { + if (time >= _frames[_frames.size() - ENTRIES]) { // Time is after last frame. x = _frames[_frames.size() + PREV_X] * bone._data._scaleX; y = _frames[_frames.size() + PREV_Y] * bone._data._scaleY; } - else - { + else { // Interpolate between the previous frame and the current frame. int frame = Animation::binarySearch(_frames, time, ENTRIES); x = _frames[frame + PREV_X]; @@ -93,32 +87,26 @@ namespace Spine y = (y + (_frames[frame + Y] - y) * percent) * bone._data._scaleY; } - if (alpha == 1) - { + if (alpha == 1) { bone._scaleX = x; bone._scaleY = y; } - else - { + else { float bx, by; - if (pose == MixPose_Setup) - { + if (pose == MixPose_Setup) { bx = bone._data._scaleX; by = bone._data._scaleY; } - else - { + else { bx = bone._scaleX; by = bone._scaleY; } // Mixing out uses sign of setup or current pose, else use sign of key. - if (direction == MixDirection_Out) - { + if (direction == MixDirection_Out) { x = (x >= 0 ? x : -x) * (bx >= 0 ? 1 : -1); y = (y >= 0 ? y : -y) * (by >= 0 ? 1 : -1); } - else - { + else { bx = (bx >= 0 ? bx : -bx) * (x >= 0 ? 1 : -1); by = (by >= 0 ? by : -by) * (y >= 0 ? 1 : -1); } @@ -127,8 +115,7 @@ namespace Spine } } - int ScaleTimeline::getPropertyId() - { + int ScaleTimeline::getPropertyId() { return ((int)TimelineType_Scale << 24) + _boneIndex; } } diff --git a/spine-cpp/spine-cpp/src/spine/ShearTimeline.cpp b/spine-cpp/spine-cpp/src/spine/ShearTimeline.cpp index 2089e7de4..3cf98aefc 100644 --- a/spine-cpp/spine-cpp/src/spine/ShearTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/ShearTimeline.cpp @@ -44,20 +44,16 @@ namespace Spine { RTTI_IMPL(ShearTimeline, TranslateTimeline); - ShearTimeline::ShearTimeline(int frameCount) : TranslateTimeline(frameCount) - { + ShearTimeline::ShearTimeline(int frameCount) : TranslateTimeline(frameCount) { // Empty } - void ShearTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) - { + void ShearTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) { Bone* boneP = skeleton._bones[_boneIndex]; Bone& bone = *boneP; - if (time < _frames[0]) - { - switch (pose) - { + if (time < _frames[0]) { + switch (pose) { case MixPose_Setup: bone._shearX = bone._data._shearX; bone._shearY = bone._data._shearY; @@ -73,14 +69,12 @@ namespace Spine } float x, y; - if (time >= _frames[_frames.size() - ENTRIES]) - { + if (time >= _frames[_frames.size() - ENTRIES]) { // Time is after last frame. x = _frames[_frames.size() + PREV_X]; y = _frames[_frames.size() + PREV_Y]; } - else - { + else { // Interpolate between the previous frame and the current frame. int frame = Animation::binarySearch(_frames, time, ENTRIES); x = _frames[frame + PREV_X]; @@ -93,20 +87,17 @@ namespace Spine y = y + (_frames[frame + Y] - y) * percent; } - if (pose == MixPose_Setup) - { + if (pose == MixPose_Setup) { bone._shearX = bone._data._shearX + x * alpha; bone._shearY = bone._data._shearY + y * alpha; } - else - { + else { bone._shearX += (bone._data._shearX + x - bone._shearX) * alpha; bone._shearY += (bone._data._shearY + y - bone._shearY) * alpha; } } - int ShearTimeline::getPropertyId() - { + int ShearTimeline::getPropertyId() { return ((int)TimelineType_Shear << 24) + _boneIndex; } } diff --git a/spine-cpp/spine-cpp/src/spine/Skeleton.cpp b/spine-cpp/spine-cpp/src/spine/Skeleton.cpp index c7a3e63d9..1913be075 100644 --- a/spine-cpp/spine-cpp/src/spine/Skeleton.cpp +++ b/spine-cpp/spine-cpp/src/spine/Skeleton.cpp @@ -65,21 +65,17 @@ namespace Spine _flipX(false), _flipY(false), _x(0), - _y(0) - { + _y(0) { _bones.reserve(_data.getBones().size()); - for (BoneData** i = _data.getBones().begin(); i != _data.getBones().end(); ++i) - { + for (BoneData** i = _data.getBones().begin(); i != _data.getBones().end(); ++i) { BoneData* data = (*i); Bone* bone; - if (data->getParent() == NULL) - { + if (data->getParent() == NULL) { bone = NEW(Bone); new (bone) Bone(*data, *this, NULL); } - else - { + else { Bone* parent = _bones[data->getParent()->getIndex()]; bone = NEW(Bone); new (bone) Bone(*data, *this, parent); @@ -91,8 +87,7 @@ namespace Spine _slots.reserve(_data.getSlots().size()); _drawOrder.reserve(_data.getSlots().size()); - for (SlotData** i = _data.getSlots().begin(); i != _data.getSlots().end(); ++i) - { + for (SlotData** i = _data.getSlots().begin(); i != _data.getSlots().end(); ++i) { SlotData* data = (*i); Bone* bone = _bones[data->getBoneData().getIndex()]; @@ -104,8 +99,7 @@ namespace Spine } _ikConstraints.reserve(_data.getIkConstraints().size()); - for (IkConstraintData** i = _data.getIkConstraints().begin(); i != _data.getIkConstraints().end(); ++i) - { + for (IkConstraintData** i = _data.getIkConstraints().begin(); i != _data.getIkConstraints().end(); ++i) { IkConstraintData* data = (*i); IkConstraint* constraint = NEW(IkConstraint); @@ -115,8 +109,7 @@ namespace Spine } _transformConstraints.reserve(_data.getTransformConstraints().size()); - for (TransformConstraintData** i = _data.getTransformConstraints().begin(); i != _data.getTransformConstraints().end(); ++i) - { + for (TransformConstraintData** i = _data.getTransformConstraints().begin(); i != _data.getTransformConstraints().end(); ++i) { TransformConstraintData* data = (*i); TransformConstraint* constraint = NEW(TransformConstraint); @@ -126,8 +119,7 @@ namespace Spine } _pathConstraints.reserve(_data.getPathConstraints().size()); - for (PathConstraintData** i = _data.getPathConstraints().begin(); i != _data.getPathConstraints().end(); ++i) - { + for (PathConstraintData** i = _data.getPathConstraints().begin(); i != _data.getPathConstraints().end(); ++i) { PathConstraintData* data = (*i); PathConstraint* constraint = NEW(PathConstraint); @@ -140,8 +132,7 @@ namespace Spine updateWorldTransform(); } - Skeleton::~Skeleton() - { + Skeleton::~Skeleton() { ContainerUtil::cleanUpVectorOfPointers(_bones); ContainerUtil::cleanUpVectorOfPointers(_slots); ContainerUtil::cleanUpVectorOfPointers(_ikConstraints); @@ -149,13 +140,11 @@ namespace Spine ContainerUtil::cleanUpVectorOfPointers(_pathConstraints); } - void Skeleton::updateCache() - { + void Skeleton::updateCache() { _updateCache.clear(); _updateCacheReset.clear(); - for (int i = 0, n = static_cast(_bones.size()); i < n; ++i) - { + for (int i = 0, n = static_cast(_bones.size()); i < n; ++i) { _bones[i]->_sorted = false; } @@ -165,15 +154,12 @@ namespace Spine int constraintCount = ikCount + transformCount + pathCount; - for (int i = 0; i < constraintCount; ++i) - { + for (int i = 0; i < constraintCount; ++i) { bool gotoNextConstraintCount = false; - for (int ii = 0; ii < ikCount; ++ii) - { + for (int ii = 0; ii < ikCount; ++ii) { IkConstraint* constraint = _ikConstraints[ii]; - if (constraint->getData().getOrder() == i) - { + if (constraint->getData().getOrder() == i) { sortIkConstraint(constraint); gotoNextConstraintCount = true; @@ -181,16 +167,13 @@ namespace Spine } } - if (gotoNextConstraintCount) - { + if (gotoNextConstraintCount) { break; } - for (int ii = 0; ii < transformCount; ++ii) - { + for (int ii = 0; ii < transformCount; ++ii) { TransformConstraint* constraint = _transformConstraints[ii]; - if (constraint->getData().getOrder() == i) - { + if (constraint->getData().getOrder() == i) { sortTransformConstraint(constraint); gotoNextConstraintCount = true; @@ -198,16 +181,13 @@ namespace Spine } } - if (gotoNextConstraintCount) - { + if (gotoNextConstraintCount) { break; } - for (int ii = 0; ii < pathCount; ++ii) - { + for (int ii = 0; ii < pathCount; ++ii) { PathConstraint* constraint = _pathConstraints[ii]; - if (constraint->getData().getOrder() == i) - { + if (constraint->getData().getOrder() == i) { sortPathConstraint(constraint); gotoNextConstraintCount = true; @@ -215,22 +195,18 @@ namespace Spine } } - if (gotoNextConstraintCount) - { + if (gotoNextConstraintCount) { break; } } - for (int i = 0, n = static_cast(_bones.size()); i < n; ++i) - { + for (int i = 0, n = static_cast(_bones.size()); i < n; ++i) { sortBone(_bones[i]); } } - void Skeleton::updateWorldTransform() - { - for (int i = 0, n = static_cast(_updateCacheReset.size()); i < n; ++i) - { + void Skeleton::updateWorldTransform() { + for (int i = 0, n = static_cast(_updateCacheReset.size()); i < n; ++i) { Bone* boneP = _updateCacheReset[i]; Bone& bone = *boneP; bone._ax = bone._x; @@ -243,27 +219,22 @@ namespace Spine bone._appliedValid = true; } - for (int i = 0, n = static_cast(_updateCache.size()); i < n; ++i) - { + for (int i = 0, n = static_cast(_updateCache.size()); i < n; ++i) { _updateCache[i]->update(); } } - void Skeleton::setToSetupPose() - { + void Skeleton::setToSetupPose() { setBonesToSetupPose(); setSlotsToSetupPose(); } - void Skeleton::setBonesToSetupPose() - { - for (int i = 0, n = static_cast(_bones.size()); i < n; ++i) - { + void Skeleton::setBonesToSetupPose() { + for (int i = 0, n = static_cast(_bones.size()); i < n; ++i) { _bones[i]->setToSetupPose(); } - for (int i = 0, n = static_cast(_ikConstraints.size()); i < n; ++i) - { + for (int i = 0, n = static_cast(_ikConstraints.size()); i < n; ++i) { IkConstraint* constraintP = _ikConstraints[i]; IkConstraint& constraint = *constraintP; @@ -271,8 +242,7 @@ namespace Spine constraint._mix = constraint._data._mix; } - for (int i = 0, n = static_cast(_transformConstraints.size()); i < n; ++i) - { + for (int i = 0, n = static_cast(_transformConstraints.size()); i < n; ++i) { TransformConstraint* constraintP = _transformConstraints[i]; TransformConstraint& constraint = *constraintP; TransformConstraintData& constraintData = constraint._data; @@ -283,8 +253,7 @@ namespace Spine constraint._shearMix = constraintData._shearMix; } - for (int i = 0, n = static_cast(_pathConstraints.size()); i < n; ++i) - { + for (int i = 0, n = static_cast(_pathConstraints.size()); i < n; ++i) { PathConstraint* constraintP = _pathConstraints[i]; PathConstraint& constraint = *constraintP; PathConstraintData& constraintData = constraint._data; @@ -296,42 +265,34 @@ namespace Spine } } - void Skeleton::setSlotsToSetupPose() - { + void Skeleton::setSlotsToSetupPose() { _drawOrder.clear(); - for (int i = 0, n = static_cast(_slots.size()); i < n; ++i) - { + for (int i = 0, n = static_cast(_slots.size()); i < n; ++i) { _drawOrder.push_back(_slots[i]); } - for (int i = 0, n = static_cast(_slots.size()); i < n; ++i) - { + for (int i = 0, n = static_cast(_slots.size()); i < n; ++i) { _slots[i]->setToSetupPose(); } } - Bone* Skeleton::findBone(std::string boneName) - { + Bone* Skeleton::findBone(std::string boneName) { return ContainerUtil::findWithDataName(_bones, boneName); } - int Skeleton::findBoneIndex(std::string boneName) - { + int Skeleton::findBoneIndex(std::string boneName) { return ContainerUtil::findIndexWithDataName(_bones, boneName); } - Slot* Skeleton::findSlot(std::string slotName) - { + Slot* Skeleton::findSlot(std::string slotName) { return ContainerUtil::findWithDataName(_slots, slotName); } - int Skeleton::findSlotIndex(std::string slotName) - { + int Skeleton::findSlotIndex(std::string slotName) { return ContainerUtil::findIndexWithDataName(_slots, slotName); } - void Skeleton::setSkin(std::string skinName) - { + void Skeleton::setSkin(std::string skinName) { Skin* foundSkin = _data.findSkin(skinName); assert(foundSkin != NULL); @@ -339,27 +300,20 @@ namespace Spine setSkin(foundSkin); } - void Skeleton::setSkin(Skin* newSkin) - { - if (newSkin != NULL) - { - if (_skin != NULL) - { + void Skeleton::setSkin(Skin* newSkin) { + if (newSkin != NULL) { + if (_skin != NULL) { Skeleton& thisRef = *this; newSkin->attachAll(thisRef, *_skin); } - else - { - for (int i = 0, n = static_cast(_slots.size()); i < n; ++i) - { + else { + for (int i = 0, n = static_cast(_slots.size()); i < n; ++i) { Slot* slotP = _slots[i]; Slot& slot = *slotP; std::string name = slot._data.getAttachmentName(); - if (name.length() > 0) - { + if (name.length() > 0) { Attachment* attachment = newSkin->getAttachment(i, name); - if (attachment != NULL) - { + if (attachment != NULL) { slot.setAttachment(attachment); } } @@ -370,20 +324,16 @@ namespace Spine _skin = newSkin; } - Attachment* Skeleton::getAttachment(std::string slotName, std::string attachmentName) - { + Attachment* Skeleton::getAttachment(std::string slotName, std::string attachmentName) { return getAttachment(_data.findSlotIndex(slotName), attachmentName); } - Attachment* Skeleton::getAttachment(int slotIndex, std::string attachmentName) - { + Attachment* Skeleton::getAttachment(int slotIndex, std::string attachmentName) { assert(attachmentName.length() > 0); - if (_skin != NULL) - { + if (_skin != NULL) { Attachment* attachment = _skin->getAttachment(slotIndex, attachmentName); - if (attachment != NULL) - { + if (attachment != NULL) { return attachment; } } @@ -391,18 +341,14 @@ namespace Spine return _data.getDefaultSkin() != NULL ? _data.getDefaultSkin()->getAttachment(slotIndex, attachmentName) : NULL; } - void Skeleton::setAttachment(std::string slotName, std::string attachmentName) - { + void Skeleton::setAttachment(std::string slotName, std::string attachmentName) { assert(slotName.length() > 0); - for (int i = 0, n = static_cast(_slots.size()); i < n; ++i) - { + for (int i = 0, n = static_cast(_slots.size()); i < n; ++i) { Slot* slot = _slots[i]; - if (slot->_data.getName() == slotName) - { + if (slot->_data.getName() == slotName) { Attachment* attachment = NULL; - if (attachmentName.length() > 0) - { + if (attachmentName.length() > 0) { attachment = getAttachment(i, attachmentName); assert(attachment != NULL); @@ -419,30 +365,24 @@ namespace Spine assert(false); } - IkConstraint* Skeleton::findIkConstraint(std::string constraintName) - { + IkConstraint* Skeleton::findIkConstraint(std::string constraintName) { assert(constraintName.length() > 0); - for (int i = 0, n = static_cast(_ikConstraints.size()); i < n; ++i) - { + for (int i = 0, n = static_cast(_ikConstraints.size()); i < n; ++i) { IkConstraint* ikConstraint = _ikConstraints[i]; - if (ikConstraint->_data.getName() == constraintName) - { + if (ikConstraint->_data.getName() == constraintName) { return ikConstraint; } } return NULL; } - TransformConstraint* Skeleton::findTransformConstraint(std::string constraintName) - { + TransformConstraint* Skeleton::findTransformConstraint(std::string constraintName) { assert(constraintName.length() > 0); - for (int i = 0, n = static_cast(_transformConstraints.size()); i < n; ++i) - { + for (int i = 0, n = static_cast(_transformConstraints.size()); i < n; ++i) { TransformConstraint* transformConstraint = _transformConstraints[i]; - if (transformConstraint->_data.getName() == constraintName) - { + if (transformConstraint->_data.getName() == constraintName) { return transformConstraint; } } @@ -450,15 +390,12 @@ namespace Spine return NULL; } - PathConstraint* Skeleton::findPathConstraint(std::string constraintName) - { + PathConstraint* Skeleton::findPathConstraint(std::string constraintName) { assert(constraintName.length() > 0); - for (int i = 0, n = static_cast(_pathConstraints.size()); i < n; ++i) - { + for (int i = 0, n = static_cast(_pathConstraints.size()); i < n; ++i) { PathConstraint* constraint = _pathConstraints[i]; - if (constraint->_data.getName() == constraintName) - { + if (constraint->_data.getName() == constraintName) { return constraint; } } @@ -466,43 +403,36 @@ namespace Spine return NULL; } - void Skeleton::update(float delta) - { + void Skeleton::update(float delta) { _time += delta; } - void Skeleton::getBounds(float& outX, float& outY, float& outWidth, float& outHeight, Vector& outVertexBuffer) - { + void Skeleton::getBounds(float& outX, float& outY, float& outWidth, float& outHeight, Vector& outVertexBuffer) { float minX = std::numeric_limits::max(); float minY = std::numeric_limits::max(); float maxX = std::numeric_limits::min(); float maxY = std::numeric_limits::min(); - for (Slot** i = _drawOrder.begin(); i != _drawOrder.end(); ++i) - { + for (Slot** i = _drawOrder.begin(); i != _drawOrder.end(); ++i) { Slot* slot = (*i); int verticesLength = 0; Attachment* attachment = slot->getAttachment(); - if (attachment != NULL && attachment->getRTTI().derivesFrom(RegionAttachment::rtti)) - { + if (attachment != NULL && attachment->getRTTI().derivesFrom(RegionAttachment::rtti)) { RegionAttachment* regionAttachment = static_cast(attachment); verticesLength = 8; - if (outVertexBuffer.size() < 8) - { + if (outVertexBuffer.size() < 8) { outVertexBuffer.reserve(8); outVertexBuffer.setSize(8); } regionAttachment->computeWorldVertices(slot->getBone(), outVertexBuffer, 0); } - else if (attachment != NULL && attachment->getRTTI().derivesFrom(MeshAttachment::rtti)) - { + else if (attachment != NULL && attachment->getRTTI().derivesFrom(MeshAttachment::rtti)) { MeshAttachment* mesh = static_cast(attachment); verticesLength = mesh->getWorldVerticesLength(); - if (outVertexBuffer.size() < verticesLength) - { + if (outVertexBuffer.size() < verticesLength) { outVertexBuffer.reserve(verticesLength); outVertexBuffer.setSize(verticesLength); } @@ -510,8 +440,7 @@ namespace Spine mesh->computeWorldVertices(*slot, 0, verticesLength, outVertexBuffer, 0); } - for (int ii = 0; ii < verticesLength; ii += 2) - { + for (int ii = 0; ii < verticesLength; ii += 2) { float vx = outVertexBuffer[ii]; float vy = outVertexBuffer[ii + 1]; @@ -528,148 +457,119 @@ namespace Spine outHeight = maxY - minY; } - Bone* Skeleton::getRootBone() - { + Bone* Skeleton::getRootBone() { return _bones.size() == 0 ? NULL : _bones[0]; } - const SkeletonData& Skeleton::getData() - { + const SkeletonData& Skeleton::getData() { return _data; } - Vector& Skeleton::getBones() - { + Vector& Skeleton::getBones() { return _bones; } - Vector& Skeleton::getUpdateCacheList() - { + Vector& Skeleton::getUpdateCacheList() { return _updateCache; } - Vector& Skeleton::getSlots() - { + Vector& Skeleton::getSlots() { return _slots; } - Vector& Skeleton::getDrawOrder() - { + Vector& Skeleton::getDrawOrder() { return _drawOrder; } - Vector& Skeleton::getIkConstraints() - { + Vector& Skeleton::getIkConstraints() { return _ikConstraints; } - Vector& Skeleton::getPathConstraints() - { + Vector& Skeleton::getPathConstraints() { return _pathConstraints; } - Vector& Skeleton::getTransformConstraints() - { + Vector& Skeleton::getTransformConstraints() { return _transformConstraints; } - Skin* Skeleton::getSkin() - { + Skin* Skeleton::getSkin() { return _skin; } - float Skeleton::getR() - { + float Skeleton::getR() { return _r; } - void Skeleton::setR(float inValue) - { + void Skeleton::setR(float inValue) { _r = inValue; } - float Skeleton::getG() - { + float Skeleton::getG() { return _g; } - void Skeleton::setG(float inValue) - { + void Skeleton::setG(float inValue) { _g = inValue; } - float Skeleton::getB() - { + float Skeleton::getB() { return _b; } - void Skeleton::setB(float inValue) - { + void Skeleton::setB(float inValue) { _b = inValue; } - float Skeleton::getA() - { + float Skeleton::getA() { return _a; } - void Skeleton::setA(float inValue) - { + void Skeleton::setA(float inValue) { _a = inValue; } - float Skeleton::getTime() - { + float Skeleton::getTime() { return _time; } - void Skeleton::setTime(float inValue) - { + void Skeleton::setTime(float inValue) { _time = inValue; } - float Skeleton::getX() - { + float Skeleton::getX() { return _x; } - void Skeleton::setX(float inValue) - { + void Skeleton::setX(float inValue) { _x = inValue; } - float Skeleton::getY() - { + float Skeleton::getY() { return _y; } - void Skeleton::setY(float inValue) - { + void Skeleton::setY(float inValue) { _y = inValue; } - bool Skeleton::getFlipX() - { + bool Skeleton::getFlipX() { return _flipX; } - void Skeleton::setFlipX(float inValue) - { + void Skeleton::setFlipX(float inValue) { _flipX = inValue; } - bool Skeleton::getFlipY() - { + bool Skeleton::getFlipY() { return _flipY; } - void Skeleton::setFlipY(float inValue) - { + void Skeleton::setFlipY(float inValue) { _flipY = inValue; } - void Skeleton::sortIkConstraint(IkConstraint* constraint) - { + void Skeleton::sortIkConstraint(IkConstraint* constraint) { Bone* target = constraint->getTarget(); sortBone(target); @@ -677,11 +577,9 @@ namespace Spine Bone* parent = constrained[0]; sortBone(parent); - if (constrained.size() > 1) - { + if (constrained.size() > 1) { Bone* child = constrained[constrained.size() - 1]; - if (!_updateCache.contains(child)) - { + if (!_updateCache.contains(child)) { _updateCacheReset.push_back(child); } } @@ -692,147 +590,119 @@ namespace Spine constrained[constrained.size() - 1]->_sorted = true; } - void Skeleton::sortPathConstraint(PathConstraint* constraint) - { + void Skeleton::sortPathConstraint(PathConstraint* constraint) { Slot* slot = constraint->getTarget(); int slotIndex = slot->_data.getIndex(); Bone& slotBone = slot->_bone; - if (_skin != NULL) - { + if (_skin != NULL) { sortPathConstraintAttachment(_skin, slotIndex, slotBone); } - if (_data._defaultSkin != NULL && _data._defaultSkin != _skin) - { + if (_data._defaultSkin != NULL && _data._defaultSkin != _skin) { sortPathConstraintAttachment(_data._defaultSkin, slotIndex, slotBone); } - for (int ii = 0, nn = static_cast(_data._skins.size()); ii < nn; ++ii) - { + for (int ii = 0, nn = static_cast(_data._skins.size()); ii < nn; ++ii) { sortPathConstraintAttachment(_data._skins[ii], slotIndex, slotBone); } Attachment* attachment = slot->_attachment; - if (attachment != NULL && attachment->getRTTI().derivesFrom(PathAttachment::rtti)) - { + if (attachment != NULL && attachment->getRTTI().derivesFrom(PathAttachment::rtti)) { sortPathConstraintAttachment(attachment, slotBone); } Vector& constrained = constraint->getBones(); int boneCount = static_cast(constrained.size()); - for (int i = 0; i < boneCount; ++i) - { + for (int i = 0; i < boneCount; ++i) { sortBone(constrained[i]); } _updateCache.push_back(constraint); - for (int i = 0; i < boneCount; ++i) - { + for (int i = 0; i < boneCount; ++i) { sortReset(constrained[i]->getChildren()); } - for (int i = 0; i < boneCount; ++i) - { + for (int i = 0; i < boneCount; ++i) { constrained[i]->_sorted = true; } } - void Skeleton::sortTransformConstraint(TransformConstraint* constraint) - { + void Skeleton::sortTransformConstraint(TransformConstraint* constraint) { sortBone(constraint->getTarget()); Vector& constrained = constraint->getBones(); int boneCount = static_cast(constrained.size()); - if (constraint->_data.isLocal()) - { - for (int i = 0; i < boneCount; ++i) - { + if (constraint->_data.isLocal()) { + for (int i = 0; i < boneCount; ++i) { Bone* child = constrained[i]; sortBone(child->getParent()); - if (!_updateCache.contains(child)) - { + if (!_updateCache.contains(child)) { _updateCacheReset.push_back(child); } } } - else - { - for (int i = 0; i < boneCount; ++i) - { + else { + for (int i = 0; i < boneCount; ++i) { sortBone(constrained[i]); } } _updateCache.push_back(constraint); - for (int i = 0; i < boneCount; ++i) - { + for (int i = 0; i < boneCount; ++i) { sortReset(constrained[i]->getChildren()); } - for (int i = 0; i < boneCount; ++i) - { + for (int i = 0; i < boneCount; ++i) { constrained[i]->_sorted = true; } } - void Skeleton::sortPathConstraintAttachment(Skin* skin, int slotIndex, Bone& slotBone) - { + void Skeleton::sortPathConstraintAttachment(Skin* skin, int slotIndex, Bone& slotBone) { HashMap& attachments = skin->getAttachments(); - for (typename HashMap::Iterator i = attachments.begin(); i != attachments.end(); ++i) - { + for (typename HashMap::Iterator i = attachments.begin(); i != attachments.end(); ++i) { Skin::AttachmentKey key = i.first(); - if (key._slotIndex == slotIndex) - { + if (key._slotIndex == slotIndex) { Attachment* value = i.second(); sortPathConstraintAttachment(value, slotBone); } } } - void Skeleton::sortPathConstraintAttachment(Attachment* attachment, Bone& slotBone) - { - if (attachment == NULL || attachment->getRTTI().derivesFrom(PathAttachment::rtti)) - { + void Skeleton::sortPathConstraintAttachment(Attachment* attachment, Bone& slotBone) { + if (attachment == NULL || attachment->getRTTI().derivesFrom(PathAttachment::rtti)) { return; } PathAttachment* pathAttachment = static_cast(attachment); Vector& pathBonesRef = pathAttachment->getBones(); Vector pathBones = pathBonesRef; - if (pathBones.size() == 0) - { + if (pathBones.size() == 0) { sortBone(&slotBone); } - else - { - for (int i = 0, n = static_cast(pathBones.size()); i < n;) - { + else { + for (int i = 0, n = static_cast(pathBones.size()); i < n;) { int nn = pathBones[i++]; nn += i; - while (i < nn) - { + while (i < nn) { sortBone(_bones[pathBones[i++]]); } } } } - void Skeleton::sortBone(Bone* bone) - { + void Skeleton::sortBone(Bone* bone) { assert(bone != NULL); - if (bone->_sorted) - { + if (bone->_sorted) { return; } Bone* parent = bone->_parent; - if (parent != NULL) - { + if (parent != NULL) { sortBone(parent); } @@ -841,13 +711,10 @@ namespace Spine _updateCache.push_back(bone); } - void Skeleton::sortReset(Vector& bones) - { - for (Bone** i = bones.begin(); i != bones.end(); ++i) - { + void Skeleton::sortReset(Vector& bones) { + for (Bone** i = bones.begin(); i != bones.end(); ++i) { Bone* bone = (*i); - if (bone->_sorted) - { + if (bone->_sorted) { sortReset(bone->getChildren()); } diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp b/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp index 16c44cee2..68709ac59 100644 --- a/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp +++ b/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp @@ -107,28 +107,23 @@ namespace Spine TransformMode_NoScaleOrReflection }; - SkeletonBinary::SkeletonBinary(Vector& atlasArray) : _attachmentLoader(NEW(AtlasAttachmentLoader)), _error(), _scale(1), _ownsLoader(true) - { + SkeletonBinary::SkeletonBinary(Vector& atlasArray) : _attachmentLoader(NEW(AtlasAttachmentLoader)), _error(), _scale(1), _ownsLoader(true) { new (_attachmentLoader) AtlasAttachmentLoader(atlasArray); } - SkeletonBinary::SkeletonBinary(AttachmentLoader* attachmentLoader) : _attachmentLoader(attachmentLoader), _error(), _scale(1), _ownsLoader(false) - { + SkeletonBinary::SkeletonBinary(AttachmentLoader* attachmentLoader) : _attachmentLoader(attachmentLoader), _error(), _scale(1), _ownsLoader(false) { assert(_attachmentLoader != NULL); } - SkeletonBinary::~SkeletonBinary() - { + SkeletonBinary::~SkeletonBinary() { ContainerUtil::cleanUpVectorOfPointers(_linkedMeshes); - if (_ownsLoader) - { + if (_ownsLoader) { DESTROY(AttachmentLoader, _attachmentLoader); } } - SkeletonData* SkeletonBinary::readSkeletonData(const unsigned char* binary, const int length) - { + SkeletonData* SkeletonBinary::readSkeletonData(const unsigned char* binary, const int length) { int i, ii, nonessential; SkeletonData* skeletonData; @@ -154,8 +149,7 @@ namespace Spine nonessential = readBoolean(input); - if (nonessential) - { + if (nonessential) { /* Skip images path & fps */ readFloat(input); FREE(readString(input)); @@ -165,8 +159,7 @@ namespace Spine int bonesCount = readVarint(input, 1); skeletonData->_bones.reserve(bonesCount); skeletonData->_bones.setSize(bonesCount); - for (i = 0; i < bonesCount; ++i) - { + for (i = 0; i < bonesCount; ++i) { BoneData* data; int mode; const char* name = readString(input); @@ -187,8 +180,7 @@ namespace Spine data->_length = readFloat(input) * _scale; mode = readVarint(input, 1); - switch (mode) - { + switch (mode) { case 0: data->_transformMode = TransformMode_Normal; break; @@ -206,8 +198,7 @@ namespace Spine break; } - if (nonessential) - { + if (nonessential) { /* Skip bone color. */ readInt(input); } @@ -219,8 +210,7 @@ namespace Spine int slotsCount = readVarint(input, 1); skeletonData->_slots.reserve(slotsCount); skeletonData->_slots.setSize(slotsCount); - for (i = 0; i < slotsCount; ++i) - { + for (i = 0; i < slotsCount; ++i) { int r, g, b, a; const char* slotName = readString(input); BoneData* boneData = skeletonData->_bones[readVarint(input, 1)]; @@ -234,8 +224,7 @@ namespace Spine g = readByte(input); b = readByte(input); a = readByte(input); - if (!(r == 0xff && g == 0xff && b == 0xff && a == 0xff)) - { + if (!(r == 0xff && g == 0xff && b == 0xff && a == 0xff)) { slotData->_r2 = r / 255.0f; slotData->_g2 = g / 255.0f; slotData->_b2 = b / 255.0f; @@ -252,8 +241,7 @@ namespace Spine int ikConstraintsCount = readVarint(input, 1); skeletonData->_ikConstraints.reserve(ikConstraintsCount); skeletonData->_ikConstraints.setSize(ikConstraintsCount); - for (i = 0; i < ikConstraintsCount; ++i) - { + for (i = 0; i < ikConstraintsCount; ++i) { const char* name = readString(input); IkConstraintData* data = NEW(IkConstraintData); @@ -265,8 +253,7 @@ namespace Spine int bonesCount = readVarint(input, 1); data->_bones.reserve(bonesCount); data->_bones.setSize(bonesCount); - for (ii = 0; ii < bonesCount; ++ii) - { + for (ii = 0; ii < bonesCount; ++ii) { data->_bones[ii] = skeletonData->_bones[readVarint(input, 1)]; } data->_target = skeletonData->_bones[readVarint(input, 1)]; @@ -280,8 +267,7 @@ namespace Spine int transformConstraintsCount = readVarint(input, 1); skeletonData->_transformConstraints.reserve(transformConstraintsCount); skeletonData->_transformConstraints.setSize(transformConstraintsCount); - for (i = 0; i < transformConstraintsCount; ++i) - { + for (i = 0; i < transformConstraintsCount; ++i) { const char* name = readString(input); TransformConstraintData* data = NEW(TransformConstraintData); @@ -292,8 +278,7 @@ namespace Spine int bonesCount = readVarint(input, 1); data->_bones.reserve(bonesCount); data->_bones.setSize(bonesCount); - for (ii = 0; ii < bonesCount; ++ii) - { + for (ii = 0; ii < bonesCount; ++ii) { data->_bones[ii] = skeletonData->_bones[readVarint(input, 1)]; } data->_target = skeletonData->_bones[readVarint(input, 1)]; @@ -317,8 +302,7 @@ namespace Spine int pathConstraintsCount = readVarint(input, 1); skeletonData->_pathConstraints.reserve(pathConstraintsCount); skeletonData->_pathConstraints.setSize(pathConstraintsCount); - for (i = 0; i < pathConstraintsCount; ++i) - { + for (i = 0; i < pathConstraintsCount; ++i) { const char* name = readString(input); PathConstraintData* data = NEW(PathConstraintData); @@ -330,8 +314,7 @@ namespace Spine int bonesCount = readVarint(input, 1); data->_bones.reserve(bonesCount); data->_bones.setSize(bonesCount); - for (ii = 0; ii < bonesCount; ++ii) - { + for (ii = 0; ii < bonesCount; ++ii) { data->_bones[ii] = skeletonData->_bones[readVarint(input, 1)]; } data->_target = skeletonData->_slots[readVarint(input, 1)]; @@ -340,14 +323,12 @@ namespace Spine data->_rotateMode = static_cast(readVarint(input, 1)); data->_offsetRotation = readFloat(input); data->_position = readFloat(input); - if (data->_positionMode == PositionMode_Fixed) - { + if (data->_positionMode == PositionMode_Fixed) { data->_position *= _scale; } data->_spacing = readFloat(input); - if (data->_spacingMode == SpacingMode_Length || data->_spacingMode == SpacingMode_Fixed) - { + if (data->_spacingMode == SpacingMode_Length || data->_spacingMode == SpacingMode_Fixed) { data->_spacing *= _scale; } data->_rotateMix = readFloat(input); @@ -360,42 +341,36 @@ namespace Spine skeletonData->_defaultSkin = readSkin(input, "default", skeletonData, nonessential); int skinsCount = readVarint(input, 1); - if (skeletonData->_defaultSkin) - { + if (skeletonData->_defaultSkin) { ++skinsCount; } skeletonData->_skins.reserve(skinsCount); skeletonData->_skins.setSize(skinsCount); - if (skeletonData->_defaultSkin) - { + if (skeletonData->_defaultSkin) { skeletonData->_skins[0] = skeletonData->_defaultSkin; } /* Skins. */ - for (i = skeletonData->_defaultSkin ? 1 : 0; i < skeletonData->_skins.size(); ++i) - { + for (i = skeletonData->_defaultSkin ? 1 : 0; i < skeletonData->_skins.size(); ++i) { const char* skinName = readString(input); skeletonData->_skins[i] = readSkin(input, skinName, skeletonData, nonessential); FREE(skinName); } /* Linked meshes. */ - for (int i = 0, n = static_cast(_linkedMeshes.size()); i < n; ++i) - { + for (int i = 0, n = static_cast(_linkedMeshes.size()); i < n; ++i) { LinkedMesh* linkedMesh = _linkedMeshes[i]; Skin* skin = linkedMesh->_skin.length() == 0 ? skeletonData->getDefaultSkin() : skeletonData->findSkin(linkedMesh->_skin); - if (skin == NULL) - { + if (skin == NULL) { FREE(input); DESTROY(SkeletonData, skeletonData); setError("Skin not found: ", linkedMesh->_skin.c_str()); return NULL; } Attachment* parent = skin->getAttachment(linkedMesh->_slotIndex, linkedMesh->_parent); - if (parent == NULL) - { + if (parent == NULL) { FREE(input); DESTROY(SkeletonData, skeletonData); setError("Parent mesh not found: ", linkedMesh->_parent.c_str()); @@ -410,8 +385,7 @@ namespace Spine int eventsCount = readVarint(input, 1); skeletonData->_events.reserve(eventsCount); skeletonData->_events.setSize(eventsCount); - for (i = 0; i < eventsCount; ++i) - { + for (i = 0; i < eventsCount; ++i) { const char* name = readString(input); EventData* eventData = NEW(EventData); new (eventData) EventData(std::string(name)); @@ -428,13 +402,11 @@ namespace Spine int animationsCount = readVarint(input, 1); skeletonData->_animations.reserve(animationsCount); skeletonData->_animations.setSize(animationsCount); - for (i = 0; i < animationsCount; ++i) - { + for (i = 0; i < animationsCount; ++i) { const char* name = readString(input); Animation* animation = readAnimation(name, input, skeletonData); FREE(name); - if (!animation) - { + if (!animation) { FREE(input); DESTROY(SkeletonData, skeletonData); return NULL; @@ -447,13 +419,11 @@ namespace Spine return skeletonData; } - SkeletonData* SkeletonBinary::readSkeletonDataFile(const char* path) - { + SkeletonData* SkeletonBinary::readSkeletonDataFile(const char* path) { int length; SkeletonData* skeletonData; const char* binary = SPINE_EXTENSION->spineReadFile(path, &length); - if (length == 0 || !binary) - { + if (length == 0 || !binary) { setError("Unable to read skeleton file: ", path); return NULL; } @@ -462,22 +432,19 @@ namespace Spine return skeletonData; } - void SkeletonBinary::setError(const char* value1, const char* value2) - { + void SkeletonBinary::setError(const char* value1, const char* value2) { char message[256]; int length; strcpy(message, value1); length = (int)strlen(value1); - if (value2) - { + if (value2) { strncat(message + length, value2, 255 - length); } _error = std::string(message); } - char* SkeletonBinary::readString(DataInput* input) - { + char* SkeletonBinary::readString(DataInput* input) { int length = readVarint(input, 1); char* string; if (length == 0) { @@ -490,10 +457,8 @@ namespace Spine return string; } - float SkeletonBinary::readFloat(DataInput* input) - { - union - { + float SkeletonBinary::readFloat(DataInput* input) { + union { int intValue; float floatValue; } intToFloat; @@ -503,23 +468,19 @@ namespace Spine return intToFloat.floatValue; } - unsigned char SkeletonBinary::readByte(DataInput* input) - { + unsigned char SkeletonBinary::readByte(DataInput* input) { return *input->cursor++; } - signed char SkeletonBinary::readSByte(DataInput* input) - { + signed char SkeletonBinary::readSByte(DataInput* input) { return (signed char)readByte(input); } - int SkeletonBinary::readBoolean(DataInput* input) - { + int SkeletonBinary::readBoolean(DataInput* input) { return readByte(input) != 0; } - int SkeletonBinary::readInt(DataInput* input) - { + int SkeletonBinary::readInt(DataInput* input) { int result = readByte(input); result <<= 8; result |= readByte(input); @@ -530,28 +491,23 @@ namespace Spine return result; } - void SkeletonBinary::readColor(DataInput* input, float *r, float *g, float *b, float *a) - { + void SkeletonBinary::readColor(DataInput* input, float *r, float *g, float *b, float *a) { *r = readByte(input) / 255.0f; *g = readByte(input) / 255.0f; *b = readByte(input) / 255.0f; *a = readByte(input) / 255.0f; } - int SkeletonBinary::readVarint(DataInput* input, bool optimizePositive) - { + int SkeletonBinary::readVarint(DataInput* input, bool optimizePositive) { unsigned char b = readByte(input); int value = b & 0x7F; - if (b & 0x80) - { + if (b & 0x80) { b = readByte(input); value |= (b & 0x7F) << 7; - if (b & 0x80) - { + if (b & 0x80) { b = readByte(input); value |= (b & 0x7F) << 14; - if (b & 0x80) - { + if (b & 0x80) { b = readByte(input); value |= (b & 0x7F) << 21; if (b & 0x80) value |= (readByte(input) & 0x7F) << 28; @@ -559,36 +515,30 @@ namespace Spine } } - if (!optimizePositive) - { + if (!optimizePositive) { value = (((unsigned int)value >> 1) ^ -(value & 1)); } return value; } - Skin* SkeletonBinary::readSkin(DataInput* input, const char* skinName, SkeletonData* skeletonData, bool nonessential) - { + Skin* SkeletonBinary::readSkin(DataInput* input, const char* skinName, SkeletonData* skeletonData, bool nonessential) { Skin* skin = NULL; int slotCount = readVarint(input, 1); int i, ii, nn; - if (slotCount == 0) - { + if (slotCount == 0) { return NULL; } skin = NEW(Skin); new (skin) Skin(std::string(skinName)); - for (i = 0; i < slotCount; ++i) - { + for (i = 0; i < slotCount; ++i) { int slotIndex = readVarint(input, 1); - for (ii = 0, nn = readVarint(input, 1); ii < nn; ++ii) - { + for (ii = 0, nn = readVarint(input, 1); ii < nn; ++ii) { const char* name = readString(input); Attachment* attachment = readAttachment(input, skin, slotIndex, name, skeletonData, nonessential); - if (attachment) - { + if (attachment) { skin->addAttachment(slotIndex, std::string(name), attachment); } FREE(name); @@ -598,28 +548,23 @@ namespace Spine return skin; } - Attachment* SkeletonBinary::readAttachment(DataInput* input, Skin* skin, int slotIndex, const char* attachmentName, SkeletonData* skeletonData, bool nonessential) - { + Attachment* SkeletonBinary::readAttachment(DataInput* input, Skin* skin, int slotIndex, const char* attachmentName, SkeletonData* skeletonData, bool nonessential) { int i; AttachmentType type; const char* name = readString(input); int freeName = name != 0; - if (!name) - { + if (!name) { freeName = 0; name = attachmentName; } type = static_cast(readByte(input)); - switch (type) - { - case AttachmentType_Region: - { + switch (type) { + case AttachmentType_Region: { const char* path = readString(input); RegionAttachment* region; - if (!path) - { + if (!path) { path = name; } region = _attachmentLoader->newRegionAttachment(*skin, std::string(name), std::string(path)); @@ -634,37 +579,31 @@ namespace Spine readColor(input, ®ion->_r, ®ion->_g, ®ion->_b, ®ion->_a); region->updateOffset(); - if (freeName) - { + if (freeName) { FREE(name); } return region; } - case AttachmentType_Boundingbox: - { + case AttachmentType_Boundingbox: { int vertexCount = readVarint(input, 1); BoundingBoxAttachment* box = _attachmentLoader->newBoundingBoxAttachment(*skin, std::string(name)); readVertices(input, static_cast(box), vertexCount); - if (nonessential) - { + if (nonessential) { /* Skip color. */ readInt(input); } - if (freeName) - { + if (freeName) { FREE(name); } return box; } - case AttachmentType_Mesh: - { + case AttachmentType_Mesh: { int vertexCount; MeshAttachment* mesh; const char* path = readString(input); - if (!path) - { + if (!path) { path = name; } mesh = _attachmentLoader->newMeshAttachment(*skin, std::string(name), std::string(path)); @@ -678,34 +617,29 @@ namespace Spine readVertices(input, static_cast(mesh), vertexCount); mesh->updateUVs(); mesh->_hullLength = readVarint(input, 1) << 1; - if (nonessential) - { + if (nonessential) { Vector edges = readShortArray(input); mesh->setEdges(edges); mesh->_width = readFloat(input) * _scale; mesh->_height = readFloat(input) * _scale; } - else - { + else { mesh->_width = 0; mesh->_height = 0; } - if (freeName) - { + if (freeName) { FREE(name); } return mesh; } - case AttachmentType_Linkedmesh: - { + case AttachmentType_Linkedmesh: { const char* skinName; const char* parent; MeshAttachment* mesh; const char* path = readString(input); - if (!path) - { + if (!path) { path = name; } @@ -715,8 +649,7 @@ namespace Spine skinName = readString(input); parent = readString(input); mesh->_inheritDeform = readBoolean(input); - if (nonessential) - { + if (nonessential) { mesh->_width = readFloat(input) * _scale; mesh->_height = readFloat(input) * _scale; } @@ -725,8 +658,7 @@ namespace Spine new (linkedMesh) LinkedMesh(mesh, std::string(skinName), slotIndex, std::string(parent)); _linkedMeshes.push_back(linkedMesh); - if (freeName) - { + if (freeName) { FREE(name); } @@ -735,8 +667,7 @@ namespace Spine return mesh; } - case AttachmentType_Path: - { + case AttachmentType_Path: { PathAttachment* path = _attachmentLoader->newPathAttachment(*skin, std::string(name)); int vertexCount = 0; path->_closed = readBoolean(input); @@ -746,56 +677,48 @@ namespace Spine int lengthsLength = vertexCount / 3; path->_lengths.reserve(lengthsLength); path->_lengths.setSize(lengthsLength); - for (i = 0; i < lengthsLength; ++i) - { + for (i = 0; i < lengthsLength; ++i) { path->_lengths[i] = readFloat(input) * _scale; } - if (nonessential) - { + if (nonessential) { /* Skip color. */ readInt(input); } - if (freeName) - { + if (freeName) { FREE(name); } return path; } - case AttachmentType_Point: - { + case AttachmentType_Point: { PointAttachment* point = _attachmentLoader->newPointAttachment(*skin, std::string(name)); point->_rotation = readFloat(input); point->_x = readFloat(input) * _scale; point->_y = readFloat(input) * _scale; - if (nonessential) - { + if (nonessential) { /* Skip color. */ readInt(input); } return point; } - case AttachmentType_Clipping: - { + case AttachmentType_Clipping: { int endSlotIndex = readVarint(input, 1); int vertexCount = readVarint(input, 1); ClippingAttachment* clip = _attachmentLoader->newClippingAttachment(*skin, name); readVertices(input, static_cast(clip), vertexCount); - if (nonessential) - { + if (nonessential) { /* Skip color. */ readInt(input); } clip->_endSlot = skeletonData->_slots[endSlotIndex]; - if (freeName) - { + if (freeName) { FREE(name); } @@ -803,21 +726,18 @@ namespace Spine } } - if (freeName) - { + if (freeName) { FREE(name); } return NULL; } - void SkeletonBinary::readVertices(DataInput* input, VertexAttachment* attachment, int vertexCount) - { + void SkeletonBinary::readVertices(DataInput* input, VertexAttachment* attachment, int vertexCount) { float scale = _scale; int verticesLength = vertexCount << 1; - if (!readBoolean(input)) - { + if (!readBoolean(input)) { attachment->setVertices(readFloatArray(input, verticesLength, scale)); return; } @@ -826,12 +746,10 @@ namespace Spine vertices._bones.reserve(verticesLength * 3); vertices._vertices.reserve(verticesLength * 3 * 3); - for (int i = 0; i < vertexCount; ++i) - { + for (int i = 0; i < vertexCount; ++i) { int boneCount = readVarint(input, true); vertices._bones.push_back(boneCount); - for (int ii = 0; ii < boneCount; ++ii) - { + for (int ii = 0; ii < boneCount; ++ii) { vertices._bones.push_back(readVarint(input, true)); vertices._vertices.push_back(readFloat(input) * scale); vertices._vertices.push_back(readFloat(input) * scale); @@ -843,24 +761,19 @@ namespace Spine attachment->setBones(vertices._bones); } - Vector SkeletonBinary::readFloatArray(DataInput *input, int n, float scale) - { + Vector SkeletonBinary::readFloatArray(DataInput *input, int n, float scale) { Vector array; array.reserve(n); array.setSize(n); int i; - if (scale == 1) - { - for (i = 0; i < n; ++i) - { + if (scale == 1) { + for (i = 0; i < n; ++i) { array[i] = readFloat(input); } } - else - { - for (i = 0; i < n; ++i) - { + else { + for (i = 0; i < n; ++i) { array[i] = readFloat(input) * scale; } } @@ -868,8 +781,7 @@ namespace Spine return array; } - Vector SkeletonBinary::readShortArray(DataInput *input) - { + Vector SkeletonBinary::readShortArray(DataInput *input) { int n = readVarint(input, 1); Vector array; @@ -877,8 +789,7 @@ namespace Spine array.setSize(n); int i; - for (i = 0; i < n; ++i) - { + for (i = 0; i < n; ++i) { array[i] = readByte(input) << 8; array[i] |= readByte(input); } @@ -886,29 +797,23 @@ namespace Spine return array; } - Animation* SkeletonBinary::readAnimation(const char* name, DataInput* input, SkeletonData *skeletonData) - { + Animation* SkeletonBinary::readAnimation(const char* name, DataInput* input, SkeletonData *skeletonData) { Vector timelines; float scale = _scale; float duration = 0; // Slot timelines. - for (int i = 0, n = readVarint(input, true); i < n; ++i) - { + for (int i = 0, n = readVarint(input, true); i < n; ++i) { int slotIndex = readVarint(input, true); - for (int ii = 0, nn = readVarint(input, true); ii < nn; ++ii) - { + for (int ii = 0, nn = readVarint(input, true); ii < nn; ++ii) { unsigned char timelineType = readByte(input); int frameCount = readVarint(input, true); - switch (timelineType) - { - case SLOT_ATTACHMENT: - { + switch (timelineType) { + case SLOT_ATTACHMENT: { AttachmentTimeline* timeline = NEW(AttachmentTimeline); new(timeline) AttachmentTimeline(frameCount); timeline->_slotIndex = slotIndex; - for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) - { + for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) { const char* attachmentName = readString(input); timeline->setFrame(frameIndex, readFloat(input), std::string(attachmentName)); FREE(attachmentName); @@ -917,13 +822,11 @@ namespace Spine duration = MAX(duration, timeline->_frames[frameCount - 1]); break; } - case SLOT_COLOR: - { + case SLOT_COLOR: { ColorTimeline* timeline = NEW(ColorTimeline); new(timeline) ColorTimeline(frameCount); timeline->_slotIndex = slotIndex; - for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) - { + for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) { float time = readFloat(input); int color = readInt(input); float r = ((color & 0xff000000) >> 24) / 255.0f; @@ -931,8 +834,7 @@ namespace Spine float b = ((color & 0x0000ff00) >> 8) / 255.0f; float a = ((color & 0x000000ff)) / 255.0f; timeline->setFrame(frameIndex, time, r, g, b, a); - if (frameIndex < frameCount - 1) - { + if (frameIndex < frameCount - 1) { readCurve(input, frameIndex, timeline); } } @@ -940,13 +842,11 @@ namespace Spine duration = MAX(duration, timeline->_frames[(frameCount - 1) * ColorTimeline::ENTRIES]); break; } - case SLOT_TWO_COLOR: - { + case SLOT_TWO_COLOR: { TwoColorTimeline* timeline = NEW(TwoColorTimeline); new(timeline) TwoColorTimeline(frameCount); timeline->_slotIndex = slotIndex; - for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) - { + for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) { float time = readFloat(input); int color = readInt(input); float r = ((color & 0xff000000) >> 24) / 255.0f; @@ -959,8 +859,7 @@ namespace Spine float b2 = ((color2 & 0x000000ff)) / 255.0f; timeline->setFrame(frameIndex, time, r, g, b, a, r2, g2, b2); - if (frameIndex < frameCount - 1) - { + if (frameIndex < frameCount - 1) { readCurve(input, frameIndex, timeline); } } @@ -968,8 +867,7 @@ namespace Spine duration = MAX(duration, timeline->_frames[(frameCount - 1) * TwoColorTimeline::ENTRIES]); break; } - default: - { + default: { ContainerUtil::cleanUpVectorOfPointers(timelines); setError("Invalid timeline type for a slot: ", skeletonData->_slots[slotIndex]->_name.c_str()); return NULL; @@ -979,25 +877,19 @@ namespace Spine } // Bone timelines. - for (int i = 0, n = readVarint(input, true); i < n; ++i) - { + for (int i = 0, n = readVarint(input, true); i < n; ++i) { int boneIndex = readVarint(input, true); - for (int ii = 0, nn = readVarint(input, true); ii < nn; ++ii) - { + for (int ii = 0, nn = readVarint(input, true); ii < nn; ++ii) { unsigned char timelineType = readByte(input); int frameCount = readVarint(input, true); - switch (timelineType) - { - case BONE_ROTATE: - { + switch (timelineType) { + case BONE_ROTATE: { RotateTimeline* timeline = NEW(RotateTimeline); new(timeline) RotateTimeline(frameCount); timeline->_boneIndex = boneIndex; - for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) - { + for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) { timeline->setFrame(frameIndex, readFloat(input), readFloat(input)); - if (frameIndex < frameCount - 1) - { + if (frameIndex < frameCount - 1) { readCurve(input, frameIndex, timeline); } } @@ -1007,32 +899,26 @@ namespace Spine } case BONE_TRANSLATE: case BONE_SCALE: - case BONE_SHEAR: - { + case BONE_SHEAR: { TranslateTimeline* timeline; float timelineScale = 1; - if (timelineType == BONE_SCALE) - { + if (timelineType == BONE_SCALE) { timeline = NEW(ScaleTimeline); new(timeline) ScaleTimeline(frameCount); } - else if (timelineType == BONE_SHEAR) - { + else if (timelineType == BONE_SHEAR) { timeline = NEW(ShearTimeline); new(timeline) ShearTimeline(frameCount); } - else - { + else { timeline = NEW(TranslateTimeline); new(timeline) TranslateTimeline(frameCount); timelineScale = scale; } timeline->_boneIndex = boneIndex; - for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) - { + for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) { timeline->setFrame(frameIndex, readFloat(input), readFloat(input) * timelineScale, readFloat(input) * timelineScale); - if (frameIndex < frameCount - 1) - { + if (frameIndex < frameCount - 1) { readCurve(input, frameIndex, timeline); } } @@ -1040,8 +926,7 @@ namespace Spine duration = MAX(duration, timeline->_frames[(frameCount - 1) * TranslateTimeline::ENTRIES]); break; } - default: - { + default: { ContainerUtil::cleanUpVectorOfPointers(timelines); setError("Invalid timeline type for a bone: ", skeletonData->_bones[boneIndex]->_name.c_str()); return NULL; @@ -1051,18 +936,15 @@ namespace Spine } // IK timelines. - for (int i = 0, n = readVarint(input, true); i < n; ++i) - { + for (int i = 0, n = readVarint(input, true); i < n; ++i) { int index = readVarint(input, true); int frameCount = readVarint(input, true); IkConstraintTimeline* timeline = NEW(IkConstraintTimeline); new(timeline) IkConstraintTimeline(frameCount); timeline->_ikConstraintIndex = index; - for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) - { + for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) { timeline->setFrame(frameIndex, readFloat(input), readFloat(input), readSByte(input)); - if (frameIndex < frameCount - 1) - { + if (frameIndex < frameCount - 1) { readCurve(input, frameIndex, timeline); } } @@ -1071,18 +953,15 @@ namespace Spine } // Transform constraint timelines. - for (int i = 0, n = readVarint(input, true); i < n; ++i) - { + for (int i = 0, n = readVarint(input, true); i < n; ++i) { int index = readVarint(input, true); int frameCount = readVarint(input, true); TransformConstraintTimeline* timeline = NEW(TransformConstraintTimeline); new(timeline) TransformConstraintTimeline(frameCount); timeline->_transformConstraintIndex = index; - for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) - { + for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) { timeline->setFrame(frameIndex, readFloat(input), readFloat(input), readFloat(input), readFloat(input), readFloat(input)); - if (frameIndex < frameCount - 1) - { + if (frameIndex < frameCount - 1) { readCurve(input, frameIndex, timeline); } } @@ -1091,47 +970,37 @@ namespace Spine } // Path constraint timelines. - for (int i = 0, n = readVarint(input, true); i < n; ++i) - { + for (int i = 0, n = readVarint(input, true); i < n; ++i) { int index = readVarint(input, true); PathConstraintData* data = skeletonData->_pathConstraints[index]; - for (int ii = 0, nn = readVarint(input, true); ii < nn; ++ii) - { + for (int ii = 0, nn = readVarint(input, true); ii < nn; ++ii) { int timelineType = readSByte(input); int frameCount = readVarint(input, true); - switch(timelineType) - { + switch(timelineType) { case PATH_POSITION: - case PATH_SPACING: - { + case PATH_SPACING: { PathConstraintPositionTimeline* timeline; float timelineScale = 1; - if (timelineType == PATH_SPACING) - { + if (timelineType == PATH_SPACING) { timeline = NEW(PathConstraintSpacingTimeline); new(timeline) PathConstraintSpacingTimeline(frameCount); - if (data->_spacingMode == SpacingMode_Length || data->_spacingMode == SpacingMode_Fixed) - { + if (data->_spacingMode == SpacingMode_Length || data->_spacingMode == SpacingMode_Fixed) { timelineScale = scale; } } - else - { + else { timeline = NEW(PathConstraintPositionTimeline); new(timeline) PathConstraintPositionTimeline(frameCount); - if (data->_positionMode == PositionMode_Fixed) - { + if (data->_positionMode == PositionMode_Fixed) { timelineScale = scale; } } timeline->_pathConstraintIndex = index; - for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) - { + for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) { timeline->setFrame(frameIndex, readFloat(input), readFloat(input) * timelineScale); - if (frameIndex < frameCount - 1) - { + if (frameIndex < frameCount - 1) { readCurve(input, frameIndex, timeline); } } @@ -1139,17 +1008,14 @@ namespace Spine duration = MAX(duration, timeline->_frames[(frameCount - 1) * PathConstraintPositionTimeline::ENTRIES]); break; } - case PATH_MIX: - { + case PATH_MIX: { PathConstraintMixTimeline* timeline = NEW(PathConstraintMixTimeline); new(timeline) PathConstraintMixTimeline(frameCount); timeline->_pathConstraintIndex = index; - for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) - { + for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) { timeline->setFrame(frameIndex, readFloat(input), readFloat(input), readFloat(input)); - if (frameIndex < frameCount - 1) - { + if (frameIndex < frameCount - 1) { readCurve(input, frameIndex, timeline); } } @@ -1162,19 +1028,15 @@ namespace Spine } // Deform timelines. - for (int i = 0, n = readVarint(input, true); i < n; ++i) - { + for (int i = 0, n = readVarint(input, true); i < n; ++i) { Skin* skin = skeletonData->_skins[readVarint(input, true)]; - for (int ii = 0, nn = readVarint(input, true); ii < nn; ++ii) - { + for (int ii = 0, nn = readVarint(input, true); ii < nn; ++ii) { int slotIndex = readVarint(input, true); - for (int iii = 0, nnn = readVarint(input, true); iii < nnn; iii++) - { + for (int iii = 0, nnn = readVarint(input, true); iii < nnn; iii++) { const char* attachmentName = readString(input); Attachment* baseAttachment = skin->getAttachment(slotIndex, std::string(attachmentName)); - if (!baseAttachment) - { + if (!baseAttachment) { ContainerUtil::cleanUpVectorOfPointers(timelines); setError("Attachment not found: ", attachmentName); FREE(attachmentName); @@ -1197,58 +1059,45 @@ namespace Spine timeline->_slotIndex = slotIndex; timeline->_attachment = attachment; - for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) - { + for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) { float time = readFloat(input); Vector deform; int end = readVarint(input, true); - if (end == 0) - { - if (weighted) - { + if (end == 0) { + if (weighted) { deform.reserve(deformLength); - for (int i = 0; i < deformLength; ++i) - { + for (int i = 0; i < deformLength; ++i) { deform.push_back(0); } } - else - { + else { deform = vertices; } } - else - { + else { deform.reserve(deformLength); int start = readVarint(input, true); end += start; - if (scale == 1) - { - for (int v = start; v < end; ++v) - { + if (scale == 1) { + for (int v = start; v < end; ++v) { deform[v] = readFloat(input); } } - else - { - for (int v = start; v < end; ++v) - { + else { + for (int v = start; v < end; ++v) { deform[v] = readFloat(input) * scale; } } - if (!weighted) - { - for (int v = 0, vn = static_cast(deform.size()); v < vn; ++v) - { + if (!weighted) { + for (int v = 0, vn = static_cast(deform.size()); v < vn; ++v) { deform[v] += vertices[v]; } } } timeline->setFrame(frameIndex, time, deform); - if (frameIndex < frameCount - 1) - { + if (frameIndex < frameCount - 1) { readCurve(input, frameIndex, timeline); } } @@ -1261,33 +1110,28 @@ namespace Spine // Draw order timeline. int drawOrderCount = readVarint(input, true); - if (drawOrderCount > 0) - { + if (drawOrderCount > 0) { DrawOrderTimeline* timeline = NEW(DrawOrderTimeline); new(timeline) DrawOrderTimeline(drawOrderCount); int slotCount = static_cast(skeletonData->_slots.size()); - for (int i = 0; i < drawOrderCount; ++i) - { + for (int i = 0; i < drawOrderCount; ++i) { float time = readFloat(input); int offsetCount = readVarint(input, true); Vector drawOrder; drawOrder.reserve(slotCount); - for (int ii = slotCount - 1; ii >= 0; --ii) - { + for (int ii = slotCount - 1; ii >= 0; --ii) { drawOrder[ii] = -1; } Vector unchanged; unchanged.reserve(slotCount - offsetCount); int originalIndex = 0, unchangedIndex = 0; - for (int ii = 0; ii < offsetCount; ++ii) - { + for (int ii = 0; ii < offsetCount; ++ii) { int slotIndex = readVarint(input, true); // Collect unchanged items. - while (originalIndex != slotIndex) - { + while (originalIndex != slotIndex) { unchanged[unchangedIndex++] = originalIndex++; } // Set changed items. @@ -1296,16 +1140,13 @@ namespace Spine } // Collect remaining unchanged items. - while (originalIndex < slotCount) - { + while (originalIndex < slotCount) { unchanged[unchangedIndex++] = originalIndex++; } // Fill in unchanged items. - for (int ii = slotCount - 1; ii >= 0; --ii) - { - if (drawOrder[ii] == -1) - { + for (int ii = slotCount - 1; ii >= 0; --ii) { + if (drawOrder[ii] == -1) { drawOrder[ii] = unchanged[--unchangedIndex]; } } @@ -1317,13 +1158,11 @@ namespace Spine // Event timeline. int eventCount = readVarint(input, true); - if (eventCount > 0) - { + if (eventCount > 0) { EventTimeline* timeline = NEW(EventTimeline); new(timeline) EventTimeline(eventCount); - for (int i = 0; i < eventCount; ++i) - { + for (int i = 0; i < eventCount; ++i) { float time = readFloat(input); EventData* eventData = skeletonData->_events[readVarint(input, true)]; Event* event = NEW(Event); @@ -1334,8 +1173,7 @@ namespace Spine bool freeString = readBoolean(input); const char* event_stringValue = freeString ? readString(input) : eventData->_stringValue.c_str(); event->_stringValue = std::string(event_stringValue); - if (freeString) - { + if (freeString) { FREE(event_stringValue); } timeline->setFrame(i, event); @@ -1351,17 +1189,13 @@ namespace Spine return ret; } - void SkeletonBinary::readCurve(DataInput* input, int frameIndex, CurveTimeline* timeline) - { - switch (readByte(input)) - { - case CURVE_STEPPED: - { + void SkeletonBinary::readCurve(DataInput* input, int frameIndex, CurveTimeline* timeline) { + switch (readByte(input)) { + case CURVE_STEPPED: { timeline->setStepped(frameIndex); break; } - case CURVE_BEZIER: - { + case CURVE_BEZIER: { float cx1 = readFloat(input); float cy1 = readFloat(input); float cx2 = readFloat(input); diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonBounds.cpp b/spine-cpp/spine-cpp/src/spine/SkeletonBounds.cpp index a5a6e3c8a..a1e171e03 100644 --- a/spine-cpp/spine-cpp/src/spine/SkeletonBounds.cpp +++ b/spine-cpp/spine-cpp/src/spine/SkeletonBounds.cpp @@ -38,30 +38,25 @@ namespace Spine { - SkeletonBounds::SkeletonBounds() : _minX(0), _minY(0), _maxX(0), _maxY(0) - { + SkeletonBounds::SkeletonBounds() : _minX(0), _minY(0), _maxX(0), _maxY(0) { // Empty } - void SkeletonBounds::update(Skeleton& skeleton, bool updateAabb) - { + void SkeletonBounds::update(Skeleton& skeleton, bool updateAabb) { Vector& slots = skeleton._slots; int slotCount = static_cast(slots.size()); _boundingBoxes.clear(); - for (int i = 0, n = static_cast(_polygons.size()); i < n; ++i) - { + for (int i = 0, n = static_cast(_polygons.size()); i < n; ++i) { _polygonPool.push_back(_polygons[i]); } _polygons.clear(); - for (int i = 0; i < slotCount; i++) - { + for (int i = 0; i < slotCount; i++) { Slot* slot = slots[i]; Attachment* attachment = slot->_attachment; - if (attachment == NULL || !attachment->getRTTI().derivesFrom(BoundingBoxAttachment::rtti)) - { + if (attachment == NULL || !attachment->getRTTI().derivesFrom(BoundingBoxAttachment::rtti)) { continue; } BoundingBoxAttachment* boundingBox = static_cast(attachment); @@ -69,13 +64,11 @@ namespace Spine Polygon* polygonP = NULL; int poolCount = static_cast(_polygonPool.size()); - if (poolCount > 0) - { + if (poolCount > 0) { polygonP = _polygonPool[poolCount - 1]; _polygonPool.erase(poolCount - 1); } - else - { + else { Polygon* polygonP = NEW(Polygon); new (polygonP) Polygon(); } @@ -86,19 +79,16 @@ namespace Spine int count = boundingBox->getWorldVerticesLength(); polygon._count = count; - if (polygon._vertices.size() < count) - { + if (polygon._vertices.size() < count) { polygon._vertices.reserve(count); } boundingBox->computeWorldVertices(*slot, polygon._vertices); } - if (updateAabb) - { + if (updateAabb) { aabbCompute(); } - else - { + else { _minX = std::numeric_limits::min(); _minY = std::numeric_limits::min(); _maxX = std::numeric_limits::max(); @@ -106,68 +96,56 @@ namespace Spine } } - bool SkeletonBounds::aabbcontainsPoint(float x, float y) - { + bool SkeletonBounds::aabbcontainsPoint(float x, float y) { return x >= _minX && x <= _maxX && y >= _minY && y <= _maxY; } - bool SkeletonBounds::aabbintersectsSegment(float x1, float y1, float x2, float y2) - { + bool SkeletonBounds::aabbintersectsSegment(float x1, float y1, float x2, float y2) { float minX = _minX; float minY = _minY; float maxX = _maxX; float maxY = _maxY; - if ((x1 <= minX && x2 <= minX) || (y1 <= minY && y2 <= minY) || (x1 >= maxX && x2 >= maxX) || (y1 >= maxY && y2 >= maxY)) - { + if ((x1 <= minX && x2 <= minX) || (y1 <= minY && y2 <= minY) || (x1 >= maxX && x2 >= maxX) || (y1 >= maxY && y2 >= maxY)) { return false; } float m = (y2 - y1) / (x2 - x1); float y = m * (minX - x1) + y1; - if (y > minY && y < maxY) - { + if (y > minY && y < maxY) { return true; } y = m * (maxX - x1) + y1; - if (y > minY && y < maxY) - { + if (y > minY && y < maxY) { return true; } float x = (minY - y1) / m + x1; - if (x > minX && x < maxX) - { + if (x > minX && x < maxX) { return true; } x = (maxY - y1) / m + x1; - if (x > minX && x < maxX) - { + if (x > minX && x < maxX) { return true; } return false; } - bool SkeletonBounds::aabbIntersectsSkeleton(SkeletonBounds bounds) - { + bool SkeletonBounds::aabbIntersectsSkeleton(SkeletonBounds bounds) { return _minX < bounds._maxX && _maxX > bounds._minX && _minY < bounds._maxY && _maxY > bounds._minY; } - bool SkeletonBounds::containsPoint(Polygon* polygon, float x, float y) - { + bool SkeletonBounds::containsPoint(Polygon* polygon, float x, float y) { Vector& vertices = polygon->_vertices; int nn = polygon->_count; int prevIndex = nn - 2; bool inside = false; - for (int ii = 0; ii < nn; ii += 2) - { + for (int ii = 0; ii < nn; ii += 2) { float vertexY = vertices[ii + 1]; float prevY = vertices[prevIndex + 1]; - if ((vertexY < y && prevY >= y) || (prevY < y && vertexY >= y)) - { + if ((vertexY < y && prevY >= y) || (prevY < y && vertexY >= y)) { float vertexX = vertices[ii]; - if (vertexX + (y - vertexY) / (prevY - vertexY) * (vertices[prevIndex] - vertexX) < x) - { + if (vertexX + (y - vertexY) / (prevY - vertexY) * (vertices[prevIndex] - vertexX) < x) { inside = !inside; } } @@ -176,12 +154,9 @@ namespace Spine return inside; } - BoundingBoxAttachment* SkeletonBounds::containsPoint(float x, float y) - { - for (int i = 0, n = static_cast(_polygons.size()); i < n; ++i) - { - if (containsPoint(_polygons[i], x, y)) - { + BoundingBoxAttachment* SkeletonBounds::containsPoint(float x, float y) { + for (int i = 0, n = static_cast(_polygons.size()); i < n; ++i) { + if (containsPoint(_polygons[i], x, y)) { return _boundingBoxes[i]; } } @@ -189,38 +164,31 @@ namespace Spine return NULL; } - BoundingBoxAttachment* SkeletonBounds::intersectsSegment(float x1, float y1, float x2, float y2) - { - for (int i = 0, n = static_cast(_polygons.size()); i < n; ++i) - { - if (intersectsSegment(_polygons[i], x1, y1, x2, y2)) - { + BoundingBoxAttachment* SkeletonBounds::intersectsSegment(float x1, float y1, float x2, float y2) { + for (int i = 0, n = static_cast(_polygons.size()); i < n; ++i) { + if (intersectsSegment(_polygons[i], x1, y1, x2, y2)) { return _boundingBoxes[i]; } } return NULL; } - bool SkeletonBounds::intersectsSegment(Polygon* polygon, float x1, float y1, float x2, float y2) - { + bool SkeletonBounds::intersectsSegment(Polygon* polygon, float x1, float y1, float x2, float y2) { Vector& vertices = polygon->_vertices; int nn = polygon->_count; float width12 = x1 - x2, height12 = y1 - y2; float det1 = x1 * y2 - y1 * x2; float x3 = vertices[nn - 2], y3 = vertices[nn - 1]; - for (int ii = 0; ii < nn; ii += 2) - { + for (int ii = 0; ii < nn; ii += 2) { float x4 = vertices[ii], y4 = vertices[ii + 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))) - { + 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))) - { + if (((y >= y3 && y <= y4) || (y >= y4 && y <= y3)) && ((y >= y1 && y <= y2) || (y >= y2 && y <= y1))) { return true; } } @@ -231,36 +199,30 @@ namespace Spine return false; } - Polygon* SkeletonBounds::getPolygon(BoundingBoxAttachment* attachment) - { + Polygon* SkeletonBounds::getPolygon(BoundingBoxAttachment* attachment) { int index = _boundingBoxes.indexOf(attachment); return index == -1 ? NULL : _polygons[index]; } - float SkeletonBounds::getWidth() - { + float SkeletonBounds::getWidth() { return _maxX - _minX; } - float SkeletonBounds::getHeight() - { + float SkeletonBounds::getHeight() { return _maxY - _minY; } - void SkeletonBounds::aabbCompute() - { + void SkeletonBounds::aabbCompute() { float minX = std::numeric_limits::min(); float minY = std::numeric_limits::min(); float maxX = std::numeric_limits::max(); float maxY = std::numeric_limits::max(); - for (int i = 0, n = static_cast(_polygons.size()); i < n; ++i) - { + for (int i = 0, n = static_cast(_polygons.size()); i < n; ++i) { Polygon* polygon = _polygons[i]; Vector& vertices = polygon->_vertices; - for (int ii = 0, nn = polygon->_count; ii < nn; ii += 2) - { + for (int ii = 0, nn = polygon->_count; ii < nn; ii += 2) { float x = vertices[ii]; float y = vertices[ii + 1]; minX = MIN(minX, x); diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonClipping.cpp b/spine-cpp/spine-cpp/src/spine/SkeletonClipping.cpp index 69e7a958f..252856bf3 100644 --- a/spine-cpp/spine-cpp/src/spine/SkeletonClipping.cpp +++ b/spine-cpp/spine-cpp/src/spine/SkeletonClipping.cpp @@ -35,18 +35,15 @@ namespace Spine { - SkeletonClipping::SkeletonClipping() : _clipAttachment(NULL) - { + SkeletonClipping::SkeletonClipping() : _clipAttachment(NULL) { _clipOutput.reserve(128); _clippedVertices.reserve(128); _clippedTriangles.reserve(128); _clippedUVs.reserve(128); } - int SkeletonClipping::clipStart(Slot& slot, ClippingAttachment* clip) - { - if (_clipAttachment != NULL) - { + int SkeletonClipping::clipStart(Slot& slot, ClippingAttachment* clip) { + if (_clipAttachment != NULL) { return 0; } @@ -61,8 +58,7 @@ namespace Spine _clippingPolygons = clippingPolygons; - for (Vector** i = _clippingPolygons.begin(); i != _clippingPolygons.end(); ++i) - { + for (Vector** i = _clippingPolygons.begin(); i != _clippingPolygons.end(); ++i) { Vector* polygonP = (*i); Vector& polygon = *polygonP; makeClockwise(polygon); @@ -73,18 +69,14 @@ namespace Spine return static_cast(_clippingPolygons.size()); } - void SkeletonClipping::clipEnd(Slot& slot) - { - if (_clipAttachment != NULL && _clipAttachment->_endSlot == &slot._data) - { + void SkeletonClipping::clipEnd(Slot& slot) { + if (_clipAttachment != NULL && _clipAttachment->_endSlot == &slot._data) { clipEnd(); } } - void SkeletonClipping::clipEnd() - { - if (_clipAttachment == NULL) - { + void SkeletonClipping::clipEnd() { + if (_clipAttachment == NULL) { return; } @@ -95,8 +87,7 @@ namespace Spine _clippingPolygon.clear(); } - void SkeletonClipping::clipTriangles(Vector& vertices, int verticesLength, Vector& triangles, int trianglesLength, Vector& uvs) - { + void SkeletonClipping::clipTriangles(Vector& vertices, int verticesLength, Vector& triangles, int trianglesLength, Vector& uvs) { Vector& clipOutput = _clipOutput; Vector& clippedVertices = _clippedVertices; Vector& clippedTriangles = _clippedTriangles; @@ -108,8 +99,7 @@ namespace Spine _clippedUVs.clear(); clippedTriangles.clear(); - for (int i = 0; i < trianglesLength; i += 3) - { + for (int i = 0; i < trianglesLength; i += 3) { int vertexOffset = triangles[i] << 1; float x1 = vertices[vertexOffset], y1 = vertices[vertexOffset + 1]; float u1 = uvs[vertexOffset], v1 = uvs[vertexOffset + 1]; @@ -122,14 +112,11 @@ namespace Spine float x3 = vertices[vertexOffset], y3 = vertices[vertexOffset + 1]; float u3 = uvs[vertexOffset], v3 = uvs[vertexOffset + 1]; - for (int p = 0; p < polygonsCount; p++) - { + for (int p = 0; p < polygonsCount; p++) { int s = static_cast(clippedVertices.size()); - if (clip(x1, y1, x2, y2, x3, y3, *polygons[p], clipOutput)) - { + if (clip(x1, y1, x2, y2, x3, y3, *polygons[p], clipOutput)) { int clipOutputLength = static_cast(clipOutput.size()); - if (clipOutputLength == 0) - { + if (clipOutputLength == 0) { continue; } float d0 = y2 - y3, d1 = x3 - x2, d2 = x1 - x3, d4 = y3 - y1; @@ -140,8 +127,7 @@ namespace Spine clippedVertices.setSize(s + clipOutputCount * 2); _clippedUVs.reserve(s + clipOutputCount * 2); _clippedUVs.setSize(s + clipOutputCount * 2); - for (int ii = 0; ii < clipOutputLength; ii += 2) - { + for (int ii = 0; ii < clipOutputLength; ii += 2) { float x = clipOutput[ii], y = clipOutput[ii + 1]; clippedVertices[s] = x; clippedVertices[s + 1] = y; @@ -158,8 +144,7 @@ namespace Spine clippedTriangles.reserve(s + 3 * (clipOutputCount - 2)); clippedTriangles.setSize(s + 3 * (clipOutputCount - 2)); clipOutputCount--; - for (int ii = 1; ii < clipOutputCount; ii++) - { + for (int ii = 1; ii < clipOutputCount; ii++) { clippedTriangles[s] = index; clippedTriangles[s + 1] = index + ii; clippedTriangles[s + 2] = index + ii + 1; @@ -167,8 +152,7 @@ namespace Spine } index += clipOutputCount + 1; } - else - { + else { clippedVertices.reserve(s + 3 * 2); clippedVertices.setSize(s + 3 * 2); _clippedUVs.reserve(s + 3 * 2); @@ -200,40 +184,33 @@ namespace Spine } } - bool SkeletonClipping::isClipping() - { + bool SkeletonClipping::isClipping() { return _clipAttachment != NULL; } - Vector& SkeletonClipping::getClippedVertices() - { + Vector& SkeletonClipping::getClippedVertices() { return _clippedVertices; } - Vector& SkeletonClipping::getClippedTriangles() - { + Vector& SkeletonClipping::getClippedTriangles() { return _clippedTriangles; } - Vector& SkeletonClipping::getClippedUVs() - { + Vector& SkeletonClipping::getClippedUVs() { return _clippedUVs; } - bool SkeletonClipping::clip(float x1, float y1, float x2, float y2, float x3, float y3, Vector& clippingArea, Vector& output) - { + bool SkeletonClipping::clip(float x1, float y1, float x2, float y2, float x3, float y3, Vector& clippingArea, Vector& output) { Vector& originalOutput = output; bool clipped = false; // Avoid copy at the end. Vector input; - if (clippingArea.size() % 4 >= 2) - { + if (clippingArea.size() % 4 >= 2) { input = output; output = _scratch; } - else - { + else { input = _scratch; } @@ -250,23 +227,19 @@ namespace Spine Vector& clippingVertices = clippingArea; int clippingVerticesLast = static_cast(clippingArea.size()) - 4; - for (int i = 0; ; i += 2) - { + for (int i = 0; ; i += 2) { float edgeX = clippingVertices[i], edgeY = clippingVertices[i + 1]; float edgeX2 = clippingVertices[i + 2], edgeY2 = clippingVertices[i + 3]; float deltaX = edgeX - edgeX2, deltaY = edgeY - edgeY2; Vector& inputVertices = input; int inputVerticesLength = static_cast(input.size()) - 2, outputStart = static_cast(output.size()); - for (int ii = 0; ii < inputVerticesLength; ii += 2) - { + for (int ii = 0; ii < inputVerticesLength; ii += 2) { float inputX = inputVertices[ii], inputY = inputVertices[ii + 1]; float inputX2 = inputVertices[ii + 2], inputY2 = inputVertices[ii + 3]; bool side2 = deltaX * (inputY2 - edgeY2) - deltaY * (inputX2 - edgeX2) > 0; - if (deltaX * (inputY - edgeY2) - deltaY * (inputX - edgeX2) > 0) - { - if (side2) - { + if (deltaX * (inputY - edgeY2) - deltaY * (inputX - edgeX2) > 0) { + if (side2) { // v1 inside, v2 inside output.push_back(inputX2); output.push_back(inputY2); @@ -278,8 +251,7 @@ namespace Spine output.push_back(edgeX + (edgeX2 - edgeX) * ua); output.push_back(edgeY + (edgeY2 - edgeY) * ua); } - else if (side2) - { + else if (side2) { // v1 outside, v2 inside float c0 = inputY2 - inputY, c2 = inputX2 - inputX; float ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / (c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY)); @@ -291,8 +263,7 @@ namespace Spine clipped = true; } - if (outputStart == output.size()) - { + if (outputStart == output.size()) { // All edges outside. originalOutput.clear(); return true; @@ -301,8 +272,7 @@ namespace Spine output.push_back(output[0]); output.push_back(output[1]); - if (i == clippingVerticesLast) - { + if (i == clippingVerticesLast) { break; } Vector temp = output; @@ -311,16 +281,13 @@ namespace Spine input = temp; } - if (originalOutput != output) - { + if (originalOutput != output) { originalOutput.clear(); - for (int i = 0, n = static_cast(output.size()) - 2; i < n; ++i) - { + for (int i = 0, n = static_cast(output.size()) - 2; i < n; ++i) { originalOutput.push_back(output[i]); } } - else - { + else { originalOutput.reserve(originalOutput.size() - 2); originalOutput.setSize(originalOutput.size() - 2); } @@ -328,14 +295,12 @@ namespace Spine return clipped; } - void SkeletonClipping::makeClockwise(Vector& polygon) - { + void SkeletonClipping::makeClockwise(Vector& polygon) { int verticeslength = static_cast(polygon.size()); float area = polygon[verticeslength - 2] * polygon[1] - polygon[0] * polygon[verticeslength - 1], p1x, p1y, p2x, p2y; - for (int i = 0, n = verticeslength - 3; i < n; i += 2) - { + for (int i = 0, n = verticeslength - 3; i < n; i += 2) { p1x = polygon[i]; p1y = polygon[i + 1]; p2x = polygon[i + 2]; @@ -343,13 +308,11 @@ namespace Spine area += p1x * p2y - p2x * p1y; } - if (area < 0) - { + if (area < 0) { return; } - for (int i = 0, lastX = verticeslength - 2, n = verticeslength >> 1; i < n; i += 2) - { + for (int i = 0, lastX = verticeslength - 2, n = verticeslength >> 1; i < n; i += 2) { float x = polygon[i], y = polygon[i + 1]; int other = lastX - i; polygon[i] = polygon[other]; diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonData.cpp b/spine-cpp/spine-cpp/src/spine/SkeletonData.cpp index 8f5a337cc..6c8e09e1a 100644 --- a/spine-cpp/spine-cpp/src/spine/SkeletonData.cpp +++ b/spine-cpp/spine-cpp/src/spine/SkeletonData.cpp @@ -53,13 +53,11 @@ namespace Spine _version(), _hash(), _fps(0), - _imagesPath() - { + _imagesPath() { // Empty } - SkeletonData::~SkeletonData() - { + SkeletonData::~SkeletonData() { ContainerUtil::cleanUpVectorOfPointers(_bones); ContainerUtil::cleanUpVectorOfPointers(_slots); ContainerUtil::cleanUpVectorOfPointers(_skins); @@ -73,208 +71,167 @@ namespace Spine ContainerUtil::cleanUpVectorOfPointers(_pathConstraints); } - BoneData* SkeletonData::findBone(std::string boneName) - { + BoneData* SkeletonData::findBone(std::string boneName) { return ContainerUtil::findWithName(_bones, boneName); } - int SkeletonData::findBoneIndex(std::string boneName) - { + int SkeletonData::findBoneIndex(std::string boneName) { return ContainerUtil::findIndexWithName(_bones, boneName); } - SlotData* SkeletonData::findSlot(std::string slotName) - { + SlotData* SkeletonData::findSlot(std::string slotName) { return ContainerUtil::findWithName(_slots, slotName); } - int SkeletonData::findSlotIndex(std::string slotName) - { + int SkeletonData::findSlotIndex(std::string slotName) { return ContainerUtil::findIndexWithName(_slots, slotName); } - Skin* SkeletonData::findSkin(std::string skinName) - { + Skin* SkeletonData::findSkin(std::string skinName) { return ContainerUtil::findWithName(_skins, skinName); } - EventData* SkeletonData::findEvent(std::string eventDataName) - { + EventData* SkeletonData::findEvent(std::string eventDataName) { return ContainerUtil::findWithName(_events, eventDataName); } - Animation* SkeletonData::findAnimation(std::string animationName) - { + Animation* SkeletonData::findAnimation(std::string animationName) { return ContainerUtil::findWithName(_animations, animationName); } - IkConstraintData* SkeletonData::findIkConstraint(std::string constraintName) - { + IkConstraintData* SkeletonData::findIkConstraint(std::string constraintName) { return ContainerUtil::findWithName(_ikConstraints, constraintName); } - TransformConstraintData* SkeletonData::findTransformConstraint(std::string constraintName) - { + TransformConstraintData* SkeletonData::findTransformConstraint(std::string constraintName) { return ContainerUtil::findWithName(_transformConstraints, constraintName); } - PathConstraintData* SkeletonData::findPathConstraint(std::string constraintName) - { + PathConstraintData* SkeletonData::findPathConstraint(std::string constraintName) { return ContainerUtil::findWithName(_pathConstraints, constraintName); } - int SkeletonData::findPathConstraintIndex(std::string pathConstraintName) - { + int SkeletonData::findPathConstraintIndex(std::string pathConstraintName) { return ContainerUtil::findIndexWithName(_pathConstraints, pathConstraintName); } - std::string SkeletonData::getName() - { + std::string SkeletonData::getName() { return _name; } - void SkeletonData::setName(std::string inValue) - { + void SkeletonData::setName(std::string inValue) { _name = inValue; } - Vector& SkeletonData::getBones() - { + Vector& SkeletonData::getBones() { return _bones; } - Vector& SkeletonData::getSlots() - { + Vector& SkeletonData::getSlots() { return _slots; } - Vector& SkeletonData::getSkins() - { + Vector& SkeletonData::getSkins() { return _skins; } - void SkeletonData::setSkins(Vector& inValue) - { + void SkeletonData::setSkins(Vector& inValue) { _skins = inValue; } - Skin* SkeletonData::getDefaultSkin() - { + Skin* SkeletonData::getDefaultSkin() { return _defaultSkin; } - void SkeletonData::setDefaultSkin(Skin* inValue) - { + void SkeletonData::setDefaultSkin(Skin* inValue) { _defaultSkin = inValue; } - Vector& SkeletonData::getEvents() - { + Vector& SkeletonData::getEvents() { return _events; } - void SkeletonData::setEvents(Vector& inValue) - { + void SkeletonData::setEvents(Vector& inValue) { _events = inValue; } - Vector& SkeletonData::getAnimations() - { + Vector& SkeletonData::getAnimations() { return _animations; } - void SkeletonData::setAnimations(Vector& inValue) - { + void SkeletonData::setAnimations(Vector& inValue) { _animations = inValue; } - Vector& SkeletonData::getIkConstraints() - { + Vector& SkeletonData::getIkConstraints() { return _ikConstraints; } - void SkeletonData::setIkConstraints(Vector& inValue) - { + void SkeletonData::setIkConstraints(Vector& inValue) { _ikConstraints = inValue; } - Vector& SkeletonData::getTransformConstraints() - { + Vector& SkeletonData::getTransformConstraints() { return _transformConstraints; } - void SkeletonData::setTransformConstraints(Vector& inValue) - { + void SkeletonData::setTransformConstraints(Vector& inValue) { _transformConstraints = inValue; } - Vector& SkeletonData::getPathConstraints() - { + Vector& SkeletonData::getPathConstraints() { return _pathConstraints; } - void SkeletonData::setPathConstraints(Vector& inValue) - { + void SkeletonData::setPathConstraints(Vector& inValue) { _pathConstraints = inValue; } - float SkeletonData::getWidth() - { + float SkeletonData::getWidth() { return _width; } - void SkeletonData::setWidth(float inValue) - { + void SkeletonData::setWidth(float inValue) { _width = inValue; } - float SkeletonData::getHeight() - { + float SkeletonData::getHeight() { return _height; } - void SkeletonData::setHeight(float inValue) - { + void SkeletonData::setHeight(float inValue) { _height = inValue; } - std::string SkeletonData::getVersion() - { + std::string SkeletonData::getVersion() { return _version; } - void SkeletonData::setVersion(std::string inValue) - { + void SkeletonData::setVersion(std::string inValue) { _version = inValue; } - std::string SkeletonData::getHash() - { + std::string SkeletonData::getHash() { return _hash; } - void SkeletonData::setHash(std::string inValue) - { + void SkeletonData::setHash(std::string inValue) { _hash = inValue; } - std::string SkeletonData::getImagesPath() - { + std::string SkeletonData::getImagesPath() { return _imagesPath; } - void SkeletonData::setImagesPath(std::string inValue) - { + void SkeletonData::setImagesPath(std::string inValue) { _imagesPath = inValue; } - float SkeletonData::getFps() - { + float SkeletonData::getFps() { return _fps; } - void SkeletonData::setFps(float inValue) - { + void SkeletonData::setFps(float inValue) { _fps = inValue; } } diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp b/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp index 2642e069d..fe11fe698 100644 --- a/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp +++ b/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp @@ -87,33 +87,27 @@ namespace Spine { - SkeletonJson::SkeletonJson(Vector& atlasArray) : _attachmentLoader(NEW(AtlasAttachmentLoader)), _scale(1), _ownsLoader(true) - { + SkeletonJson::SkeletonJson(Vector& atlasArray) : _attachmentLoader(NEW(AtlasAttachmentLoader)), _scale(1), _ownsLoader(true) { new (_attachmentLoader) AtlasAttachmentLoader(atlasArray); } - SkeletonJson::SkeletonJson(AttachmentLoader* attachmentLoader) : _attachmentLoader(attachmentLoader), _scale(1), _ownsLoader(false) - { + SkeletonJson::SkeletonJson(AttachmentLoader* attachmentLoader) : _attachmentLoader(attachmentLoader), _scale(1), _ownsLoader(false) { assert(_attachmentLoader != NULL); } - SkeletonJson::~SkeletonJson() - { + SkeletonJson::~SkeletonJson() { ContainerUtil::cleanUpVectorOfPointers(_linkedMeshes); - if (_ownsLoader) - { + if (_ownsLoader) { DESTROY(AttachmentLoader, _attachmentLoader); } } - SkeletonData* SkeletonJson::readSkeletonDataFile(const char* path) - { + SkeletonData* SkeletonJson::readSkeletonDataFile(const char* path) { int length; SkeletonData* skeletonData; const char* json = SPINE_EXTENSION->spineReadFile(path, &length); - if (length == 0 || !json) - { + if (length == 0 || !json) { setError(NULL, "Unable to read skeleton file: ", path); return NULL; } @@ -125,8 +119,7 @@ namespace Spine return skeletonData; } - SkeletonData* SkeletonJson::readSkeletonData(const char* json) - { + SkeletonData* SkeletonJson::readSkeletonData(const char* json) { int i, ii; SkeletonData* skeletonData; Json *root, *skeleton, *bones, *boneMap, *ik, *transform, *path, *slots, *skins, *animations, *events; @@ -137,8 +130,7 @@ namespace Spine root = NEW(Json); new (root) Json(json); - if (!root) - { + if (!root) { setError(NULL, "Invalid skeleton JSON: ", Json::getError()); return NULL; } @@ -147,8 +139,7 @@ namespace Spine new (skeletonData) SkeletonData(); skeleton = Json::getItem(root, "skeleton"); - if (skeleton) - { + if (skeleton) { skeletonData->_hash = Json::getString(skeleton, "hash", 0); skeletonData->_version = Json::getString(skeleton, "spine", 0); skeletonData->_width = Json::getFloat(skeleton, "width", 0); @@ -160,18 +151,15 @@ namespace Spine skeletonData->_bones.reserve(bones->_size); skeletonData->_bones.setSize(bones->_size); int bonesCount = 0; - for (boneMap = bones->_child, i = 0; boneMap; boneMap = boneMap->_next, ++i) - { + for (boneMap = bones->_child, i = 0; boneMap; boneMap = boneMap->_next, ++i) { BoneData* data; const char* transformMode; BoneData* parent = 0; const char* parentName = Json::getString(boneMap, "parent", 0); - if (parentName) - { + if (parentName) { parent = skeletonData->findBone(parentName); - if (!parent) - { + if (!parent) { DESTROY(SkeletonData, skeletonData); setError(root, "Parent bone not found: ", parentName); return NULL; @@ -191,24 +179,19 @@ namespace Spine data->_shearY = Json::getFloat(boneMap, "shearY", 0); transformMode = Json::getString(boneMap, "transform", "normal"); data->_transformMode = TransformMode_Normal; - if (strcmp(transformMode, "normal") == 0) - { + if (strcmp(transformMode, "normal") == 0) { data->_transformMode = TransformMode_Normal; } - if (strcmp(transformMode, "onlyTranslation") == 0) - { + if (strcmp(transformMode, "onlyTranslation") == 0) { data->_transformMode = TransformMode_OnlyTranslation; } - if (strcmp(transformMode, "noRotationOrReflection") == 0) - { + if (strcmp(transformMode, "noRotationOrReflection") == 0) { data->_transformMode = TransformMode_NoRotationOrReflection; } - if (strcmp(transformMode, "noScale") == 0) - { + if (strcmp(transformMode, "noScale") == 0) { data->_transformMode = TransformMode_NoScale; } - if (strcmp(transformMode, "noScaleOrReflection") == 0) - { + if (strcmp(transformMode, "noScaleOrReflection") == 0) { data->_transformMode = TransformMode_NoScaleOrReflection; } @@ -218,13 +201,11 @@ namespace Spine /* Slots. */ slots = Json::getItem(root, "slots"); - if (slots) - { + if (slots) { Json *slotMap; skeletonData->_slots.reserve(slots->_size); skeletonData->_slots.setSize(slots->_size); - for (slotMap = slots->_child, i = 0; slotMap; slotMap = slotMap->_next, ++i) - { + for (slotMap = slots->_child, i = 0; slotMap; slotMap = slotMap->_next, ++i) { SlotData* data; const char* color; const char* dark; @@ -232,8 +213,7 @@ namespace Spine const char* boneName = Json::getString(slotMap, "bone", 0); BoneData* boneData = skeletonData->findBone(boneName); - if (!boneData) - { + if (!boneData) { DESTROY(SkeletonData, skeletonData); setError(root, "Slot bone not found: ", boneName); return NULL; @@ -243,8 +223,7 @@ namespace Spine new (data) SlotData(i, Json::getString(slotMap, "name", 0), *boneData); color = Json::getString(slotMap, "color", 0); - if (color) - { + if (color) { data->_r = toColor(color, 0); data->_g = toColor(color, 1); data->_b = toColor(color, 2); @@ -252,8 +231,7 @@ namespace Spine } dark = Json::getString(slotMap, "dark", 0); - if (dark) - { + if (dark) { data->_r2 = toColor(dark, 0); data->_g2 = toColor(dark, 1); data->_b2 = toColor(dark, 2); @@ -262,24 +240,19 @@ namespace Spine } item = Json::getItem(slotMap, "attachment"); - if (item) - { + if (item) { data->setAttachmentName(item->_valueString); } item = Json::getItem(slotMap, "blend"); - if (item) - { - if (strcmp(item->_valueString, "additive") == 0) - { + if (item) { + if (strcmp(item->_valueString, "additive") == 0) { data->_blendMode = BlendMode_Additive; } - else if (strcmp(item->_valueString, "multiply") == 0) - { + else if (strcmp(item->_valueString, "multiply") == 0) { data->_blendMode = BlendMode_Multiply; } - else if (strcmp(item->_valueString, "screen") == 0) - { + else if (strcmp(item->_valueString, "screen") == 0) { data->_blendMode = BlendMode_Screen; } } @@ -290,13 +263,11 @@ namespace Spine /* IK constraints. */ ik = Json::getItem(root, "ik"); - if (ik) - { + if (ik) { Json *constraintMap; skeletonData->_ikConstraints.reserve(ik->_size); skeletonData->_ikConstraints.setSize(ik->_size); - for (constraintMap = ik->_child, i = 0; constraintMap; constraintMap = constraintMap->_next, ++i) - { + for (constraintMap = ik->_child, i = 0; constraintMap; constraintMap = constraintMap->_next, ++i) { const char* targetName; IkConstraintData* data = NEW(IkConstraintData); @@ -307,11 +278,9 @@ namespace Spine boneMap = Json::getItem(constraintMap, "bones"); data->_bones.reserve(boneMap->_size); data->_bones.setSize(boneMap->_size); - for (boneMap = boneMap->_child, ii = 0; boneMap; boneMap = boneMap->_next, ++ii) - { + for (boneMap = boneMap->_child, ii = 0; boneMap; boneMap = boneMap->_next, ++ii) { data->_bones[ii] = skeletonData->findBone(boneMap->_valueString); - if (!data->_bones[ii]) - { + if (!data->_bones[ii]) { DESTROY(SkeletonData, skeletonData); setError(root, "IK bone not found: ", boneMap->_valueString); return NULL; @@ -320,8 +289,7 @@ namespace Spine targetName = Json::getString(constraintMap, "target", 0); data->_target = skeletonData->findBone(targetName); - if (!data->_target) - { + if (!data->_target) { DESTROY(SkeletonData, skeletonData); setError(root, "Target bone not found: ", boneMap->_name); return NULL; @@ -336,13 +304,11 @@ namespace Spine /* Transform constraints. */ transform = Json::getItem(root, "transform"); - if (transform) - { + if (transform) { Json *constraintMap; skeletonData->_transformConstraints.reserve(transform->_size); skeletonData->_transformConstraints.setSize(transform->_size); - for (constraintMap = transform->_child, i = 0; constraintMap; constraintMap = constraintMap->_next, ++i) - { + for (constraintMap = transform->_child, i = 0; constraintMap; constraintMap = constraintMap->_next, ++i) { const char* name; TransformConstraintData* data = NEW(TransformConstraintData); @@ -353,11 +319,9 @@ namespace Spine boneMap = Json::getItem(constraintMap, "bones"); data->_bones.reserve(boneMap->_size); data->_bones.setSize(boneMap->_size); - for (boneMap = boneMap->_child, ii = 0; boneMap; boneMap = boneMap->_next, ++ii) - { + for (boneMap = boneMap->_child, ii = 0; boneMap; boneMap = boneMap->_next, ++ii) { data->_bones[ii] = skeletonData->findBone(boneMap->_valueString); - if (!data->_bones[ii]) - { + if (!data->_bones[ii]) { DESTROY(SkeletonData, skeletonData); setError(root, "Transform bone not found: ", boneMap->_valueString); return NULL; @@ -366,8 +330,7 @@ namespace Spine name = Json::getString(constraintMap, "target", 0); data->_target = skeletonData->findBone(name); - if (!data->_target) - { + if (!data->_target) { DESTROY(SkeletonData, skeletonData); setError(root, "Target bone not found: ", boneMap->_name); return NULL; @@ -393,13 +356,11 @@ namespace Spine /* Path constraints */ path = Json::getItem(root, "path"); - if (path) - { + if (path) { Json *constraintMap; skeletonData->_pathConstraints.reserve(path->_size); skeletonData->_pathConstraints.setSize(path->_size); - for (constraintMap = path->_child, i = 0; constraintMap; constraintMap = constraintMap->_next, ++i) - { + for (constraintMap = path->_child, i = 0; constraintMap; constraintMap = constraintMap->_next, ++i) { const char* name; const char* item; @@ -411,11 +372,9 @@ namespace Spine boneMap = Json::getItem(constraintMap, "bones"); data->_bones.reserve(boneMap->_size); data->_bones.setSize(boneMap->_size); - for (boneMap = boneMap->_child, ii = 0; boneMap; boneMap = boneMap->_next, ++ii) - { + for (boneMap = boneMap->_child, ii = 0; boneMap; boneMap = boneMap->_next, ++ii) { data->_bones[ii] = skeletonData->findBone(boneMap->_valueString); - if (!data->_bones[ii]) - { + if (!data->_bones[ii]) { DESTROY(SkeletonData, skeletonData); setError(root, "Path bone not found: ", boneMap->_valueString); return NULL; @@ -424,60 +383,49 @@ namespace Spine name = Json::getString(constraintMap, "target", 0); data->_target = skeletonData->findSlot(name); - if (!data->_target) - { + if (!data->_target) { DESTROY(SkeletonData, skeletonData); setError(root, "Target slot not found: ", boneMap->_name); return NULL; } item = Json::getString(constraintMap, "positionMode", "percent"); - if (strcmp(item, "fixed") == 0) - { + if (strcmp(item, "fixed") == 0) { data->_positionMode = PositionMode_Fixed; } - else if (strcmp(item, "percent") == 0) - { + else if (strcmp(item, "percent") == 0) { data->_positionMode = PositionMode_Percent; } item = Json::getString(constraintMap, "spacingMode", "length"); - if (strcmp(item, "length") == 0) - { + if (strcmp(item, "length") == 0) { data->_spacingMode = SpacingMode_Length; } - else if (strcmp(item, "fixed") == 0) - { + else if (strcmp(item, "fixed") == 0) { data->_spacingMode = SpacingMode_Fixed; } - else if (strcmp(item, "percent") == 0) - { + else if (strcmp(item, "percent") == 0) { data->_spacingMode = SpacingMode_Percent; } item = Json::getString(constraintMap, "rotateMode", "tangent"); - if (strcmp(item, "tangent") == 0) - { + if (strcmp(item, "tangent") == 0) { data->_rotateMode = RotateMode_Tangent; } - else if (strcmp(item, "chain") == 0) - { + else if (strcmp(item, "chain") == 0) { data->_rotateMode = RotateMode_Chain; } - else if (strcmp(item, "chainScale") == 0) - { + else if (strcmp(item, "chainScale") == 0) { data->_rotateMode = RotateMode_ChainScale; } data->_offsetRotation = Json::getFloat(constraintMap, "rotation", 0); data->_position = Json::getFloat(constraintMap, "position", 0); - if (data->_positionMode == PositionMode_Fixed) - { + if (data->_positionMode == PositionMode_Fixed) { data->_position *= _scale; } data->_spacing = Json::getFloat(constraintMap, "spacing", 0); - if (data->_spacingMode == SpacingMode_Length || data->_spacingMode == SpacingMode_Fixed) - { + if (data->_spacingMode == SpacingMode_Length || data->_spacingMode == SpacingMode_Fixed) { data->_spacing *= _scale; } data->_rotateMix = Json::getFloat(constraintMap, "rotateMix", 1); @@ -489,14 +437,12 @@ namespace Spine /* Skins. */ skins = Json::getItem(root, "skins"); - if (skins) - { + if (skins) { Json *skinMap; skeletonData->_skins.reserve(skins->_size); skeletonData->_skins.setSize(skins->_size); int skinsIndex = 0; - for (skinMap = skins->_child, i = 0; skinMap; skinMap = skinMap->_next, ++i) - { + for (skinMap = skins->_child, i = 0; skinMap; skinMap = skinMap->_next, ++i) { Json *attachmentsMap; Json *curves; @@ -504,18 +450,15 @@ namespace Spine new (skin) Skin(skinMap->_name); skeletonData->_skins[skinsIndex++] = skin; - if (strcmp(skinMap->_name, "default") == 0) - { + if (strcmp(skinMap->_name, "default") == 0) { skeletonData->_defaultSkin = skin; } - for (attachmentsMap = skinMap->_child; attachmentsMap; attachmentsMap = attachmentsMap->_next) - { + for (attachmentsMap = skinMap->_child; attachmentsMap; attachmentsMap = attachmentsMap->_next) { int slotIndex = skeletonData->findSlotIndex(attachmentsMap->_name); Json *attachmentMap; - for (attachmentMap = attachmentsMap->_child; attachmentMap; attachmentMap = attachmentMap->_next) - { + for (attachmentMap = attachmentsMap->_child; attachmentMap; attachmentMap = attachmentMap->_next) { Attachment* attachment; const char* skinAttachmentName = attachmentMap->_name; const char* attachmentName = Json::getString(attachmentMap, "name", skinAttachmentName); @@ -525,44 +468,34 @@ namespace Spine const char* typeString = Json::getString(attachmentMap, "type", "region"); AttachmentType type; - if (strcmp(typeString, "region") == 0) - { + if (strcmp(typeString, "region") == 0) { type = AttachmentType_Region; } - else if (strcmp(typeString, "mesh") == 0) - { + else if (strcmp(typeString, "mesh") == 0) { type = AttachmentType_Mesh; } - else if (strcmp(typeString, "linkedmesh") == 0) - { + else if (strcmp(typeString, "linkedmesh") == 0) { type = AttachmentType_Linkedmesh; } - else if (strcmp(typeString, "boundingbox") == 0) - { + else if (strcmp(typeString, "boundingbox") == 0) { type = AttachmentType_Boundingbox; } - else if (strcmp(typeString, "path") == 0) - { + else if (strcmp(typeString, "path") == 0) { type = AttachmentType_Path; } - else if (strcmp(typeString, "clipping") == 0) - { + else if (strcmp(typeString, "clipping") == 0) { type = AttachmentType_Clipping; } - else - { + else { DESTROY(SkeletonData, skeletonData); setError(root, "Unknown attachment type: ", typeString); return NULL; } - switch (type) - { - case AttachmentType_Region: - { + switch (type) { + case AttachmentType_Region: { attachment = _attachmentLoader->newRegionAttachment(*skin, attachmentName, attachmentPath); - if (!attachment) - { + if (!attachment) { DESTROY(SkeletonData, skeletonData); setError(root, "Error reading attachment: ", skinAttachmentName); return NULL; @@ -580,8 +513,7 @@ namespace Spine region->_height = Json::getFloat(attachmentMap, "height", 32) * _scale; color = Json::getString(attachmentMap, "color", 0); - if (color) - { + if (color) { region->_r = toColor(color, 0); region->_g = toColor(color, 1); region->_b = toColor(color, 2); @@ -593,16 +525,14 @@ namespace Spine break; } case AttachmentType_Mesh: - case AttachmentType_Linkedmesh: - { + case AttachmentType_Linkedmesh: { attachment = _attachmentLoader->newMeshAttachment(*skin, attachmentName, attachmentPath); MeshAttachment* mesh = static_cast(attachment); mesh->_path = attachmentPath; color = Json::getString(attachmentMap, "color", 0); - if (color) - { + if (color) { mesh->_r = toColor(color, 0); mesh->_g = toColor(color, 1); mesh->_b = toColor(color, 2); @@ -613,14 +543,12 @@ namespace Spine mesh->_height = Json::getFloat(attachmentMap, "height", 32) * _scale; entry = Json::getItem(attachmentMap, "parent"); - if (!entry) - { + if (!entry) { int verticesLength; entry = Json::getItem(attachmentMap, "triangles"); mesh->_triangles.reserve(entry->_size); mesh->_triangles.setSize(entry->_size); - for (entry = entry->_child, ii = 0; entry; entry = entry->_next, ++ii) - { + for (entry = entry->_child, ii = 0; entry; entry = entry->_next, ++ii) { mesh->_triangles[ii] = (unsigned short)entry->_valueInt; } @@ -628,8 +556,7 @@ namespace Spine verticesLength = entry->_size; mesh->_regionUVs.reserve(verticesLength); mesh->_regionUVs.setSize(verticesLength); - for (entry = entry->_child, ii = 0; entry; entry = entry->_next, ++ii) - { + for (entry = entry->_child, ii = 0; entry; entry = entry->_next, ++ii) { mesh->_regionUVs[ii] = entry->_valueFloat; } @@ -640,18 +567,15 @@ namespace Spine mesh->_hullLength = Json::getInt(attachmentMap, "hull", 0); entry = Json::getItem(attachmentMap, "edges"); - if (entry) - { + if (entry) { mesh->_edges.reserve(entry->_size); mesh->_edges.setSize(entry->_size); - for (entry = entry->_child, ii = 0; entry; entry = entry->_next, ++ii) - { + for (entry = entry->_child, ii = 0; entry; entry = entry->_next, ++ii) { mesh->_edges[ii] = entry->_valueInt; } } } - else - { + else { mesh->_inheritDeform = Json::getInt(attachmentMap, "deform", 1); LinkedMesh* linkedMesh = NEW(LinkedMesh); new (linkedMesh) LinkedMesh(mesh, std::string(Json::getString(attachmentMap, "skin", 0)), slotIndex, std::string(entry->_valueString)); @@ -659,8 +583,7 @@ namespace Spine } break; } - case AttachmentType_Boundingbox: - { + case AttachmentType_Boundingbox: { attachment = _attachmentLoader->newBoundingBoxAttachment(*skin, attachmentName); BoundingBoxAttachment* box = static_cast(attachment); @@ -669,8 +592,7 @@ namespace Spine readVertices(attachmentMap, box, vertexCount); break; } - case AttachmentType_Path: - { + case AttachmentType_Path: { attachment = _attachmentLoader->newPathAttachment(*skin, attachmentName); PathAttachment* pathAttatchment = static_cast(attachment); @@ -685,14 +607,12 @@ namespace Spine pathAttatchment->_lengths.setSize(vertexCount / 3); curves = Json::getItem(attachmentMap, "lengths"); - for (curves = curves->_child, ii = 0; curves; curves = curves->_next, ++ii) - { + for (curves = curves->_child, ii = 0; curves; curves = curves->_next, ++ii) { pathAttatchment->_lengths[ii] = curves->_valueFloat * _scale; } break; } - case AttachmentType_Point: - { + case AttachmentType_Point: { attachment = _attachmentLoader->newPointAttachment(*skin, attachmentName); PointAttachment* point = static_cast(attachment); @@ -702,16 +622,14 @@ namespace Spine point->_rotation = Json::getFloat(attachmentMap, "rotation", 0); break; } - case AttachmentType_Clipping: - { + case AttachmentType_Clipping: { attachment = _attachmentLoader->newClippingAttachment(*skin, attachmentName); ClippingAttachment* clip = static_cast(attachment); int vertexCount = 0; const char* end = Json::getString(attachmentMap, "end", 0); - if (end) - { + if (end) { SlotData* slot = skeletonData->findSlot(end); clip->_endSlot = slot; } @@ -728,19 +646,16 @@ namespace Spine } /* Linked meshes. */ - for (int i = 0, n = static_cast(_linkedMeshes.size()); i < n; ++i) - { + for (int i = 0, n = static_cast(_linkedMeshes.size()); i < n; ++i) { LinkedMesh* linkedMesh = _linkedMeshes[i]; Skin* skin = linkedMesh->_skin.length() == 0 ? skeletonData->getDefaultSkin() : skeletonData->findSkin(linkedMesh->_skin); - if (skin == NULL) - { + if (skin == NULL) { DESTROY(SkeletonData, skeletonData); setError(root, "Skin not found: ", linkedMesh->_skin.c_str()); return NULL; } Attachment* parent = skin->getAttachment(linkedMesh->_slotIndex, linkedMesh->_parent); - if (parent == NULL) - { + if (parent == NULL) { DESTROY(SkeletonData, skeletonData); setError(root, "Parent mesh not found: ", linkedMesh->_parent.c_str()); return NULL; @@ -752,13 +667,11 @@ namespace Spine /* Events. */ events = Json::getItem(root, "events"); - if (events) - { + if (events) { Json *eventMap; skeletonData->_events.reserve(events->_size); skeletonData->_events.setSize(events->_size); - for (eventMap = events->_child, i = 0; eventMap; eventMap = eventMap->_next, ++i) - { + for (eventMap = events->_child, i = 0; eventMap; eventMap = eventMap->_next, ++i) { EventData* eventData = NEW(EventData); new (eventData) EventData(std::string(eventMap->_name)); @@ -772,17 +685,14 @@ namespace Spine /* Animations. */ animations = Json::getItem(root, "animations"); - if (animations) - { + if (animations) { Json *animationMap; skeletonData->_animations.reserve(animations->_size); skeletonData->_animations.setSize(animations->_size); int animationsIndex = 0; - for (animationMap = animations->_child; animationMap; animationMap = animationMap->_next) - { + for (animationMap = animations->_child; animationMap; animationMap = animationMap->_next) { Animation* animation = readAnimation(animationMap, skeletonData); - if (!animation) - { + if (!animation) { DESTROY(SkeletonData, skeletonData); DESTROY(Json, root); return NULL; @@ -796,14 +706,12 @@ namespace Spine return skeletonData; } - float SkeletonJson::toColor(const char* value, int index) - { + float SkeletonJson::toColor(const char* value, int index) { char digits[3]; char *error; int color; - if (index >= strlen(value) / 2) - { + if (index >= strlen(value) / 2) { return -1; } @@ -813,27 +721,22 @@ namespace Spine digits[1] = *(value + 1); digits[2] = '\0'; color = (int)strtoul(digits, &error, 16); - if (*error != 0) - { + if (*error != 0) { return -1; } return color / (float)255; } - void SkeletonJson::readCurve(Json* frame, CurveTimeline* timeline, int frameIndex) - { + void SkeletonJson::readCurve(Json* frame, CurveTimeline* timeline, int frameIndex) { Json* curve = Json::getItem(frame, "curve"); - if (!curve) - { + if (!curve) { return; } - if (curve->_type == Json::JSON_STRING && strcmp(curve->_valueString, "stepped") == 0) - { + if (curve->_type == Json::JSON_STRING && strcmp(curve->_valueString, "stepped") == 0) { timeline->setStepped(frameIndex); } - else if (curve->_type == Json::JSON_ARRAY) - { + else if (curve->_type == Json::JSON_ARRAY) { Json* child0 = curve->_child; Json* child1 = child0->_next; Json* child2 = child1->_next; @@ -842,8 +745,7 @@ namespace Spine } } - Animation* SkeletonJson::readAnimation(Json* root, SkeletonData *skeletonData) - { + Animation* SkeletonJson::readAnimation(Json* root, SkeletonData *skeletonData) { Vector timelines; float duration = 0; @@ -860,71 +762,58 @@ namespace Spine Json* drawOrder = Json::getItem(root, "drawOrder"); Json* events = Json::getItem(root, "events"); Json *boneMap, *slotMap, *constraintMap; - if (!drawOrder) - { + if (!drawOrder) { drawOrder = Json::getItem(root, "draworder"); } - for (boneMap = bones ? bones->_child : NULL; boneMap; boneMap = boneMap->_next) - { + for (boneMap = bones ? bones->_child : NULL; boneMap; boneMap = boneMap->_next) { timelinesCount += boneMap->_size; } - for (slotMap = slots ? slots->_child : NULL; slotMap; slotMap = slotMap->_next) - { + for (slotMap = slots ? slots->_child : NULL; slotMap; slotMap = slotMap->_next) { timelinesCount += slotMap->_size; } timelinesCount += ik ? ik->_size : 0; timelinesCount += transform ? transform->_size : 0; - for (constraintMap = paths ? paths->_child : NULL; constraintMap; constraintMap = constraintMap->_next) - { + for (constraintMap = paths ? paths->_child : NULL; constraintMap; constraintMap = constraintMap->_next) { timelinesCount += constraintMap->_size; } - for (constraintMap = deform ? deform->_child : NULL; constraintMap; constraintMap = constraintMap->_next) - { - for (slotMap = constraintMap->_child; slotMap; slotMap = slotMap->_next) - { + for (constraintMap = deform ? deform->_child : NULL; constraintMap; constraintMap = constraintMap->_next) { + for (slotMap = constraintMap->_child; slotMap; slotMap = slotMap->_next) { timelinesCount += slotMap->_size; } } - if (drawOrder) - { + if (drawOrder) { ++timelinesCount; } - if (events) - { + if (events) { ++timelinesCount; } /** Slot timelines. */ - for (slotMap = slots ? slots->_child : 0; slotMap; slotMap = slotMap->_next) - { + for (slotMap = slots ? slots->_child : 0; slotMap; slotMap = slotMap->_next) { Json *timelineMap; int slotIndex = skeletonData->findSlotIndex(slotMap->_name); - if (slotIndex == -1) - { + if (slotIndex == -1) { ContainerUtil::cleanUpVectorOfPointers(timelines); setError(NULL, "Slot not found: ", slotMap->_name); return NULL; } - for (timelineMap = slotMap->_child; timelineMap; timelineMap = timelineMap->_next) - { - if (strcmp(timelineMap->_name, "attachment") == 0) - { + for (timelineMap = slotMap->_child; timelineMap; timelineMap = timelineMap->_next) { + if (strcmp(timelineMap->_name, "attachment") == 0) { AttachmentTimeline *timeline = NEW(AttachmentTimeline); new (timeline) AttachmentTimeline(timelineMap->_size); timeline->_slotIndex = slotIndex; - for (valueMap = timelineMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) - { + for (valueMap = timelineMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) { Json* name = Json::getItem(valueMap, "name"); std::string attachmentName = name->_type == Json::JSON_NULL ? std::string("") : std::string(name->_valueString); timeline->setFrame(frameIndex, Json::getFloat(valueMap, "time", 0), attachmentName); @@ -934,15 +823,13 @@ namespace Spine duration = MAX(duration, timeline->_frames[timelineMap->_size - 1]); } - else if (strcmp(timelineMap->_name, "color") == 0) - { + else if (strcmp(timelineMap->_name, "color") == 0) { ColorTimeline *timeline = NEW(ColorTimeline); new (timeline) ColorTimeline(timelineMap->_size); timeline->_slotIndex = slotIndex; - for (valueMap = timelineMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) - { + for (valueMap = timelineMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) { const char* s = Json::getString(valueMap, "color", 0); timeline->setFrame(frameIndex, Json::getFloat(valueMap, "time", 0), toColor(s, 0), toColor(s, 1), toColor(s, 2), toColor(s, 3)); readCurve(valueMap, timeline, frameIndex); @@ -952,15 +839,13 @@ namespace Spine duration = MAX(duration, timeline->_frames[(timelineMap->_size - 1) * ColorTimeline::ENTRIES]); } - else if (strcmp(timelineMap->_name, "twoColor") == 0) - { + else if (strcmp(timelineMap->_name, "twoColor") == 0) { TwoColorTimeline *timeline = NEW(TwoColorTimeline); new (timeline) TwoColorTimeline(timelineMap->_size); timeline->_slotIndex = slotIndex; - for (valueMap = timelineMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) - { + for (valueMap = timelineMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) { const char* s = Json::getString(valueMap, "light", 0); const char* ds = Json::getString(valueMap, "dark", 0); timeline->setFrame(frameIndex, Json::getFloat(valueMap, "time", 0), toColor(s, 0), toColor(s, 1), toColor(s, 2), @@ -971,8 +856,7 @@ namespace Spine timelinesCount++; duration = MAX(duration, timeline->_frames[(timelineMap->_size - 1) * TwoColorTimeline::ENTRIES]); } - else - { + else { ContainerUtil::cleanUpVectorOfPointers(timelines); setError(NULL, "Invalid timeline type for a slot: ", timelineMap->_name); return NULL; @@ -981,29 +865,24 @@ namespace Spine } /** Bone timelines. */ - for (boneMap = bones ? bones->_child : 0; boneMap; boneMap = boneMap->_next) - { + for (boneMap = bones ? bones->_child : 0; boneMap; boneMap = boneMap->_next) { Json *timelineMap; int boneIndex = skeletonData->findBoneIndex(boneMap->_name); - if (boneIndex == -1) - { + if (boneIndex == -1) { ContainerUtil::cleanUpVectorOfPointers(timelines); setError(NULL, "Bone not found: ", boneMap->_name); return NULL; } - for (timelineMap = boneMap->_child; timelineMap; timelineMap = timelineMap->_next) - { - if (strcmp(timelineMap->_name, "rotate") == 0) - { + for (timelineMap = boneMap->_child; timelineMap; timelineMap = timelineMap->_next) { + if (strcmp(timelineMap->_name, "rotate") == 0) { RotateTimeline *timeline = NEW(RotateTimeline); new (timeline) RotateTimeline(timelineMap->_size); timeline->_boneIndex = boneIndex; - for (valueMap = timelineMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) - { + for (valueMap = timelineMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) { timeline->setFrame(frameIndex, Json::getFloat(valueMap, "time", 0), Json::getFloat(valueMap, "angle", 0)); readCurve(valueMap, timeline, frameIndex); } @@ -1011,34 +890,28 @@ namespace Spine timelinesCount++; duration = MAX(duration, timeline->_frames[(timelineMap->_size - 1) * RotateTimeline::ENTRIES]); } - else - { + else { int isScale = strcmp(timelineMap->_name, "scale") == 0; int isTranslate = strcmp(timelineMap->_name, "translate") == 0; int isShear = strcmp(timelineMap->_name, "shear") == 0; - if (isScale || isTranslate || isShear) - { + if (isScale || isTranslate || isShear) { float timelineScale = isTranslate ? _scale: 1; TranslateTimeline *timeline = 0; - if (isScale) - { + if (isScale) { timeline = NEW(ScaleTimeline); new (timeline) ScaleTimeline(timelineMap->_size); } - else if (isTranslate) - { + else if (isTranslate) { timeline = NEW(TranslateTimeline); new (timeline) TranslateTimeline(timelineMap->_size); } - else if (isShear) - { + else if (isShear) { timeline = NEW(ShearTimeline); new (timeline) ShearTimeline(timelineMap->_size); } timeline->_boneIndex = boneIndex; - for (valueMap = timelineMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) - { + for (valueMap = timelineMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) { timeline->setFrame(frameIndex, Json::getFloat(valueMap, "time", 0), Json::getFloat(valueMap, "x", 0) * timelineScale, Json::getFloat(valueMap, "y", 0) * timelineScale); readCurve(valueMap, timeline, frameIndex); } @@ -1047,8 +920,7 @@ namespace Spine timelinesCount++; duration = MAX(duration, timeline->_frames[(timelineMap->_size - 1) * TranslateTimeline::ENTRIES]); } - else - { + else { ContainerUtil::cleanUpVectorOfPointers(timelines); setError(NULL, "Invalid timeline type for a bone: ", timelineMap->_name); return NULL; @@ -1058,22 +930,18 @@ namespace Spine } /** IK constraint timelines. */ - for (constraintMap = ik ? ik->_child : 0; constraintMap; constraintMap = constraintMap->_next) - { + for (constraintMap = ik ? ik->_child : 0; constraintMap; constraintMap = constraintMap->_next) { IkConstraintData* constraint = skeletonData->findIkConstraint(constraintMap->_name); IkConstraintTimeline *timeline = NEW(IkConstraintTimeline); new (timeline) IkConstraintTimeline(constraintMap->_size); - for (frameIndex = 0; frameIndex < static_cast(skeletonData->_ikConstraints.size()); ++frameIndex) - { - if (constraint == skeletonData->_ikConstraints[frameIndex]) - { + for (frameIndex = 0; frameIndex < static_cast(skeletonData->_ikConstraints.size()); ++frameIndex) { + if (constraint == skeletonData->_ikConstraints[frameIndex]) { timeline->_ikConstraintIndex = frameIndex; break; } } - for (valueMap = constraintMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) - { + for (valueMap = constraintMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) { timeline->setFrame(frameIndex, Json::getFloat(valueMap, "time", 0), Json::getFloat(valueMap, "mix", 1), Json::getInt(valueMap, "bendPositive", 1) ? 1 : -1); readCurve(valueMap, timeline, frameIndex); } @@ -1083,22 +951,18 @@ namespace Spine } /** Transform constraint timelines. */ - for (constraintMap = transform ? transform->_child : 0; constraintMap; constraintMap = constraintMap->_next) - { + for (constraintMap = transform ? transform->_child : 0; constraintMap; constraintMap = constraintMap->_next) { TransformConstraintData* constraint = skeletonData->findTransformConstraint(constraintMap->_name); TransformConstraintTimeline *timeline = NEW(TransformConstraintTimeline); new (timeline) TransformConstraintTimeline(constraintMap->_size); - for (frameIndex = 0; frameIndex < skeletonData->_transformConstraints.size(); ++frameIndex) - { - if (constraint == skeletonData->_transformConstraints[frameIndex]) - { + for (frameIndex = 0; frameIndex < skeletonData->_transformConstraints.size(); ++frameIndex) { + if (constraint == skeletonData->_transformConstraints[frameIndex]) { timeline->_transformConstraintIndex = frameIndex; break; } } - for (valueMap = constraintMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) - { + for (valueMap = constraintMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) { timeline->setFrame(frameIndex, Json::getFloat(valueMap, "time", 0), Json::getFloat(valueMap, "rotateMix", 1), Json::getFloat(valueMap, "translateMix", 1), Json::getFloat(valueMap, "scaleMix", 1), Json::getFloat(valueMap, "shearMix", 1)); readCurve(valueMap, timeline, frameIndex); } @@ -1108,59 +972,48 @@ namespace Spine } /** Path constraint timelines. */ - for (constraintMap = paths ? paths->_child : 0; constraintMap; constraintMap = constraintMap->_next) - { + for (constraintMap = paths ? paths->_child : 0; constraintMap; constraintMap = constraintMap->_next) { int constraintIndex = 0, i; Json* timelineMap; PathConstraintData* data = skeletonData->findPathConstraint(constraintMap->_name); - if (!data) - { + if (!data) { ContainerUtil::cleanUpVectorOfPointers(timelines); setError(NULL, "Path constraint not found: ", constraintMap->_name); return NULL; } - for (i = 0; i < skeletonData->_pathConstraints.size(); i++) - { - if (skeletonData->_pathConstraints[i] == data) - { + for (i = 0; i < skeletonData->_pathConstraints.size(); i++) { + if (skeletonData->_pathConstraints[i] == data) { constraintIndex = i; break; } } - for (timelineMap = constraintMap->_child; timelineMap; timelineMap = timelineMap->_next) - { + for (timelineMap = constraintMap->_child; timelineMap; timelineMap = timelineMap->_next) { const char* timelineName = timelineMap->_name; - if (strcmp(timelineName, "position") == 0 || strcmp(timelineName, "spacing") == 0) - { + if (strcmp(timelineName, "position") == 0 || strcmp(timelineName, "spacing") == 0) { PathConstraintPositionTimeline* timeline; float timelineScale = 1; - if (strcmp(timelineName, "spacing") == 0) - { + if (strcmp(timelineName, "spacing") == 0) { timeline = NEW(PathConstraintSpacingTimeline); new (timeline) PathConstraintSpacingTimeline(timelineMap->_size); - if (data->_spacingMode == SpacingMode_Length || data->_spacingMode == SpacingMode_Fixed) - { + if (data->_spacingMode == SpacingMode_Length || data->_spacingMode == SpacingMode_Fixed) { timelineScale = _scale; } } - else - { + else { timeline = NEW(PathConstraintPositionTimeline); new (timeline) PathConstraintPositionTimeline(timelineMap->_size); - if (data->_positionMode == PositionMode_Fixed) - { + if (data->_positionMode == PositionMode_Fixed) { timelineScale = _scale; } } timeline->_pathConstraintIndex = constraintIndex; - for (valueMap = timelineMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) - { + for (valueMap = timelineMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) { timeline->setFrame(frameIndex, Json::getFloat(valueMap, "time", 0), Json::getFloat(valueMap, timelineName, 0) * timelineScale); readCurve(valueMap, timeline, frameIndex); } @@ -1168,13 +1021,11 @@ namespace Spine timelinesCount++; duration = MAX(duration, timeline->_frames[(timelineMap->_size - 1) * PathConstraintPositionTimeline::ENTRIES]); } - else if (strcmp(timelineName, "mix") == 0) - { + else if (strcmp(timelineName, "mix") == 0) { PathConstraintMixTimeline* timeline = NEW(PathConstraintMixTimeline); new (timeline) PathConstraintMixTimeline(timelineMap->_size); timeline->_pathConstraintIndex = constraintIndex; - for (valueMap = timelineMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) - { + for (valueMap = timelineMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) { timeline->setFrame(frameIndex, Json::getFloat(valueMap, "time", 0), Json::getFloat(valueMap, "rotateMix", 1), Json::getFloat(valueMap, "translateMix", 1)); readCurve(valueMap, timeline, frameIndex); } @@ -1186,22 +1037,18 @@ namespace Spine } /** Deform timelines. */ - for (constraintMap = deform ? deform->_child : NULL; constraintMap; constraintMap = constraintMap->_next) - { + for (constraintMap = deform ? deform->_child : NULL; constraintMap; constraintMap = constraintMap->_next) { Skin* skin = skeletonData->findSkin(constraintMap->_name); - for (slotMap = constraintMap->_child; slotMap; slotMap = slotMap->_next) - { + for (slotMap = constraintMap->_child; slotMap; slotMap = slotMap->_next) { int slotIndex = skeletonData->findSlotIndex(slotMap->_name); Json* timelineMap; - for (timelineMap = slotMap->_child; timelineMap; timelineMap = timelineMap->_next) - { + for (timelineMap = slotMap->_child; timelineMap; timelineMap = timelineMap->_next) { DeformTimeline *timeline; int weighted, deformLength; Attachment* baseAttachment = skin->getAttachment(slotIndex, timelineMap->_name); - if (!baseAttachment) - { + if (!baseAttachment) { ContainerUtil::cleanUpVectorOfPointers(timelines); setError(NULL, "Attachment not found: ", timelineMap->_name); return NULL; @@ -1214,8 +1061,7 @@ namespace Spine deformLength = weighted ? static_cast(vertices.size()) / 3 * 2 : static_cast(vertices.size()); Vector tempDeform; tempDeform.reserve(deformLength); - for (int i = 0; i < deformLength; ++i) - { + for (int i = 0; i < deformLength; ++i) { tempDeform.push_back(0); } @@ -1225,45 +1071,34 @@ namespace Spine timeline->_slotIndex = slotIndex; timeline->_attachment = attachment; - for (valueMap = timelineMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) - { + for (valueMap = timelineMap->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) { Json* vertices = Json::getItem(valueMap, "vertices"); Vector deform; - if (!vertices) - { - if (weighted) - { + if (!vertices) { + if (weighted) { deform = tempDeform; } - else - { + else { deform = attachment->_vertices; } } - else - { + else { int v, start = Json::getInt(valueMap, "offset", 0); Json* vertex; deform = tempDeform; - if (_scale == 1) - { - for (vertex = vertices->_child, v = start; vertex; vertex = vertex->_next, ++v) - { + if (_scale == 1) { + for (vertex = vertices->_child, v = start; vertex; vertex = vertex->_next, ++v) { deform[v] = vertex->_valueFloat; } } - else - { - for (vertex = vertices->_child, v = start; vertex; vertex = vertex->_next, ++v) - { + else { + for (vertex = vertices->_child, v = start; vertex; vertex = vertex->_next, ++v) { deform[v] = vertex->_valueFloat * _scale; } } - if (!weighted) - { + if (!weighted) { Vector& verticesAttachment = attachment->_vertices; - for (v = 0; v < deformLength; ++v) - { + for (v = 0; v < deformLength; ++v) { deform[v] += verticesAttachment[v]; } } @@ -1280,18 +1115,15 @@ namespace Spine } /** Draw order timeline. */ - if (drawOrder) - { + if (drawOrder) { DrawOrderTimeline* timeline = NEW(DrawOrderTimeline); new (timeline) DrawOrderTimeline(drawOrder->_size); - for (valueMap = drawOrder->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) - { + for (valueMap = drawOrder->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) { int ii; Vector drawOrder2; Json* offsets = Json::getItem(valueMap, "offsets"); - if (offsets) - { + if (offsets) { Json* offsetMap; Vector unchanged; unchanged.reserve(skeletonData->_slots.size() - offsets->_size); @@ -1300,23 +1132,19 @@ namespace Spine drawOrder2.reserve(skeletonData->_slots.size()); drawOrder2.setSize(skeletonData->_slots.size()); - for (ii = static_cast(skeletonData->_slots.size()) - 1; ii >= 0; --ii) - { + for (ii = static_cast(skeletonData->_slots.size()) - 1; ii >= 0; --ii) { drawOrder2[ii] = -1; } - for (offsetMap = offsets->_child; offsetMap; offsetMap = offsetMap->_next) - { + for (offsetMap = offsets->_child; offsetMap; offsetMap = offsetMap->_next) { int slotIndex = skeletonData->findSlotIndex(Json::getString(offsetMap, "slot", 0)); - if (slotIndex == -1) - { + if (slotIndex == -1) { ContainerUtil::cleanUpVectorOfPointers(timelines); setError(NULL, "Slot not found: ", Json::getString(offsetMap, "slot", 0)); return NULL; } /* Collect unchanged items. */ - while (originalIndex != slotIndex) - { + while (originalIndex != slotIndex) { unchanged[unchangedIndex++] = originalIndex++; } /* Set changed items. */ @@ -1324,15 +1152,12 @@ namespace Spine originalIndex++; } /* Collect remaining unchanged items. */ - while (originalIndex < skeletonData->_slots.size()) - { + while (originalIndex < skeletonData->_slots.size()) { unchanged[unchangedIndex++] = originalIndex++; } /* Fill in unchanged items. */ - for (ii = static_cast(skeletonData->_slots.size()) - 1; ii >= 0; ii--) - { - if (drawOrder2[ii] == -1) - { + for (ii = static_cast(skeletonData->_slots.size()) - 1; ii >= 0; ii--) { + if (drawOrder2[ii] == -1) { drawOrder2[ii] = unchanged[--unchangedIndex]; } } @@ -1345,17 +1170,14 @@ namespace Spine } /** Event timeline. */ - if (events) - { + if (events) { EventTimeline* timeline = NEW(EventTimeline); new (timeline) EventTimeline(events->_size); - for (valueMap = events->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) - { + for (valueMap = events->_child, frameIndex = 0; valueMap; valueMap = valueMap->_next, ++frameIndex) { Event* event; EventData* eventData = skeletonData->findEvent(Json::getString(valueMap, "name", 0)); - if (!eventData) - { + if (!eventData) { ContainerUtil::cleanUpVectorOfPointers(timelines); setError(NULL, "Event not found: ", Json::getString(valueMap, "name", 0)); return NULL; @@ -1379,8 +1201,7 @@ namespace Spine return ret; } - void SkeletonJson::readVertices(Json* attachmentMap, VertexAttachment* attachment, int verticesLength) - { + void SkeletonJson::readVertices(Json* attachmentMap, VertexAttachment* attachment, int verticesLength) { Json* entry; int i, n, nn, entrySize; Vector vertices; @@ -1391,17 +1212,13 @@ namespace Spine entrySize = entry->_size; vertices.reserve(entrySize); vertices.setSize(entrySize); - for (entry = entry->_child, i = 0; entry; entry = entry->_next, ++i) - { + for (entry = entry->_child, i = 0; entry; entry = entry->_next, ++i) { vertices[i] = entry->_valueFloat; } - if (verticesLength == entrySize) - { - if (_scale != 1) - { - for (i = 0; i < entrySize; ++i) - { + if (verticesLength == entrySize) { + if (_scale != 1) { + for (i = 0; i < entrySize; ++i) { vertices[i] *= _scale; } } @@ -1414,12 +1231,10 @@ namespace Spine bonesAndWeights._bones.reserve(verticesLength * 3); bonesAndWeights._vertices.reserve(verticesLength * 3 * 3); - for (i = 0, n = entrySize; i < n;) - { + for (i = 0, n = entrySize; i < n;) { int boneCount = (int)vertices[i++]; bonesAndWeights._bones.push_back(boneCount); - for (nn = i + boneCount * 4; i < nn; i += 4) - { + for (nn = i + boneCount * 4; i < nn; i += 4) { bonesAndWeights._bones.push_back((int)vertices[i]); bonesAndWeights._vertices.push_back(vertices[i + 1] * _scale); bonesAndWeights._vertices.push_back(vertices[i + 2] * _scale); @@ -1431,21 +1246,18 @@ namespace Spine attachment->setBones(bonesAndWeights._bones); } - void SkeletonJson::setError(Json* root, const char* value1, const char* value2) - { + void SkeletonJson::setError(Json* root, const char* value1, const char* value2) { char message[256]; int length; strcpy(message, value1); length = (int)strlen(value1); - if (value2) - { + if (value2) { strncat(message + length, value2, 255 - length); } _error = std::string(message); - if (root) - { + if (root) { DESTROY(Json, root); } } diff --git a/spine-cpp/spine-cpp/src/spine/Skin.cpp b/spine-cpp/spine-cpp/src/spine/Skin.cpp index 522e34e02..c02f20dfa 100644 --- a/spine-cpp/spine-cpp/src/spine/Skin.cpp +++ b/spine-cpp/spine-cpp/src/spine/Skin.cpp @@ -41,95 +41,76 @@ namespace Spine { Skin::AttachmentKey::AttachmentKey(int slotIndex, std::string name) : _slotIndex(slotIndex), - _name(name) - { + _name(name) { // Empty } - bool Skin::AttachmentKey::operator==(const AttachmentKey &other) const - { + bool Skin::AttachmentKey::operator==(const AttachmentKey &other) const { return _slotIndex == other._slotIndex && _name == other._name; } - std::size_t Skin::HashAttachmentKey::operator()(const Spine::Skin::AttachmentKey& val) const - { + std::size_t Skin::HashAttachmentKey::operator()(const Spine::Skin::AttachmentKey& val) const { std::size_t h1 = val._slotIndex; return h1; } - Skin::Skin(std::string name) : _name(name) - { + Skin::Skin(std::string name) : _name(name) { assert(_name.length() > 0); } - void Skin::addAttachment(int slotIndex, std::string name, Attachment* attachment) - { + void Skin::addAttachment(int slotIndex, std::string name, Attachment* attachment) { assert(attachment); _attachments.insert(AttachmentKey(slotIndex, name), attachment); } - Attachment* Skin::getAttachment(int slotIndex, std::string name) - { + Attachment* Skin::getAttachment(int slotIndex, std::string name) { HashMap::Iterator i = _attachments.find(AttachmentKey(slotIndex, name)); Attachment* ret = NULL; - if (i != _attachments.end()) - { + if (i != _attachments.end()) { ret = i.second(); } return ret; } - void Skin::findNamesForSlot(int slotIndex, Vector& names) - { - for (HashMap::Iterator i = _attachments.begin(); i != _attachments.end(); ++i) - { - if (i.first()._slotIndex == slotIndex) - { + void Skin::findNamesForSlot(int slotIndex, Vector& names) { + for (HashMap::Iterator i = _attachments.begin(); i != _attachments.end(); ++i) { + if (i.first()._slotIndex == slotIndex) { names.push_back(i.first()._name); } } } - void Skin::findAttachmentsForSlot(int slotIndex, Vector& attachments) - { - for (HashMap::Iterator i = _attachments.begin(); i != _attachments.end(); ++i) - { - if (i.first()._slotIndex == slotIndex) - { + void Skin::findAttachmentsForSlot(int slotIndex, Vector& attachments) { + for (HashMap::Iterator i = _attachments.begin(); i != _attachments.end(); ++i) { + if (i.first()._slotIndex == slotIndex) { attachments.push_back(i.second()); } } } - const std::string& Skin::getName() - { + const std::string& Skin::getName() { return _name; } - HashMap& Skin::getAttachments() - { + HashMap& Skin::getAttachments() { return _attachments; } - void Skin::attachAll(Skeleton& skeleton, Skin& oldSkin) - { + void Skin::attachAll(Skeleton& skeleton, Skin& oldSkin) { Vector& slots = skeleton.getSlots(); - for (HashMap::Iterator i = oldSkin.getAttachments().begin(); i != oldSkin.getAttachments().end(); ++i) - { + for (HashMap::Iterator i = oldSkin.getAttachments().begin(); i != oldSkin.getAttachments().end(); ++i) { int slotIndex = i.first()._slotIndex; Slot* slot = slots[slotIndex]; - if (slot->getAttachment() == i.second()) - { + if (slot->getAttachment() == i.second()) { Attachment* attachment = NULL; - if ((attachment = getAttachment(slotIndex, i.first()._name))) - { + if ((attachment = getAttachment(slotIndex, i.first()._name))) { slot->setAttachment(attachment); } } diff --git a/spine-cpp/spine-cpp/src/spine/Slot.cpp b/spine-cpp/spine-cpp/src/spine/Slot.cpp index d245533ad..65fb1585c 100644 --- a/spine-cpp/spine-cpp/src/spine/Slot.cpp +++ b/spine-cpp/spine-cpp/src/spine/Slot.cpp @@ -50,134 +50,108 @@ namespace Spine _b2(0), _hasSecondColor(false), _attachment(NULL), - _attachmentTime(0) - { + _attachmentTime(0) { setToSetupPose(); } - void Slot::setToSetupPose() - { + void Slot::setToSetupPose() { _r = _data.getR(); _g = _data.getG(); _b = _data.getB(); _a = _data.getA(); std::string attachmentName = _data.getAttachmentName(); - if (attachmentName.length() > 0) - { + if (attachmentName.length() > 0) { _attachment = NULL; setAttachment(_skeleton.getAttachment(_data.getIndex(), attachmentName)); } - else - { + else { setAttachment(NULL); } } - SlotData& Slot::getData() - { + SlotData& Slot::getData() { return _data; } - Bone& Slot::getBone() - { + Bone& Slot::getBone() { return _bone; } - Skeleton& Slot::getSkeleton() - { + Skeleton& Slot::getSkeleton() { return _skeleton; } - float Slot::getR() - { + float Slot::getR() { return _r; } - void Slot::setR(float inValue) - { + void Slot::setR(float inValue) { _r = inValue; } - float Slot::getG() - { + float Slot::getG() { return _g; } - void Slot::setG(float inValue) - { + void Slot::setG(float inValue) { _g = inValue; } - float Slot::getB() - { + float Slot::getB() { return _b; } - void Slot::setB(float inValue) - { + void Slot::setB(float inValue) { _b = inValue; } - float Slot::getA() - { + float Slot::getA() { return _a; } - void Slot::setA(float inValue) - { + void Slot::setA(float inValue) { _a = inValue; } - float Slot::getR2() - { + float Slot::getR2() { return _r2; } - void Slot::setR2(float inValue) - { + void Slot::setR2(float inValue) { _r2 = inValue; } - float Slot::getG2() - { + float Slot::getG2() { return _g2; } - void Slot::setG2(float inValue) - { + void Slot::setG2(float inValue) { _g2 = inValue; } - float Slot::getB2() - { + float Slot::getB2() { return _b2; } - void Slot::setB2(float inValue) - { + void Slot::setB2(float inValue) { _b2 = inValue; } - bool Slot::hasSecondColor() - { + bool Slot::hasSecondColor() { return _hasSecondColor; } - void Slot::setHasSecondColor(bool inValue) - { + void Slot::setHasSecondColor(bool inValue) { _hasSecondColor = inValue; } - Attachment* Slot::getAttachment() - { + Attachment* Slot::getAttachment() { return _attachment; } - void Slot::setAttachment(Attachment* inValue) - { - if (_attachment == inValue) - { + void Slot::setAttachment(Attachment* inValue) { + if (_attachment == inValue) { return; } @@ -186,23 +160,19 @@ namespace Spine _attachmentVertices.clear(); } - float Slot::getAttachmentTime() - { + float Slot::getAttachmentTime() { return _skeleton.getTime() - _attachmentTime; } - void Slot::setAttachmentTime(float inValue) - { + void Slot::setAttachmentTime(float inValue) { _attachmentTime = _skeleton.getTime() - inValue; } - Vector& Slot::getAttachmentVertices() - { + Vector& Slot::getAttachmentVertices() { return _attachmentVertices; } - void Slot::setAttachmentVertices(Vector inValue) - { + void Slot::setAttachmentVertices(Vector inValue) { _attachmentVertices = inValue; } } diff --git a/spine-cpp/spine-cpp/src/spine/SlotData.cpp b/spine-cpp/spine-cpp/src/spine/SlotData.cpp index 775b69aca..8ef6adaf7 100644 --- a/spine-cpp/spine-cpp/src/spine/SlotData.cpp +++ b/spine-cpp/spine-cpp/src/spine/SlotData.cpp @@ -48,124 +48,100 @@ namespace Spine _a2(1), _hasSecondColor(false), _attachmentName(), - _blendMode(BlendMode_Normal) - { + _blendMode(BlendMode_Normal) { assert(_index >= 0); assert(_name.length() > 0); } - const int SlotData::getIndex() - { + const int SlotData::getIndex() { return _index; } - const std::string& SlotData::getName() - { + const std::string& SlotData::getName() { return _name; } - BoneData& SlotData::getBoneData() - { + BoneData& SlotData::getBoneData() { return _boneData; } - float SlotData::getR() - { + float SlotData::getR() { return _r; } - void SlotData::setR(float inValue) - { + void SlotData::setR(float inValue) { _r = inValue; } - float SlotData::getG() - { + float SlotData::getG() { return _g; } - void SlotData::setG(float inValue) - { + void SlotData::setG(float inValue) { _g = inValue; } - float SlotData::getB() - { + float SlotData::getB() { return _b; } - void SlotData::setB(float inValue) - { + void SlotData::setB(float inValue) { _b = inValue; } - float SlotData::getA() - { + float SlotData::getA() { return _a; } - void SlotData::setA(float inValue) - { + void SlotData::setA(float inValue) { _a = inValue; } - float SlotData::getR2() - { + float SlotData::getR2() { return _r2; } - void SlotData::setR2(float inValue) - { + void SlotData::setR2(float inValue) { _r2 = inValue; } - float SlotData::getG2() - { + float SlotData::getG2() { return _g2; } - void SlotData::setG2(float inValue) - { + void SlotData::setG2(float inValue) { _g2 = inValue; } - float SlotData::getB2() - { + float SlotData::getB2() { return _b2; } - void SlotData::setB2(float inValue) - { + void SlotData::setB2(float inValue) { _b2 = inValue; } - bool SlotData::hasSecondColor() - { + bool SlotData::hasSecondColor() { return _hasSecondColor; } - void SlotData::setHasSecondColor(bool inValue) - { + void SlotData::setHasSecondColor(bool inValue) { _hasSecondColor = inValue; } - std::string SlotData::getAttachmentName() - { + std::string SlotData::getAttachmentName() { return _attachmentName; } - void SlotData::setAttachmentName(std::string inValue) - { + void SlotData::setAttachmentName(std::string inValue) { _attachmentName = inValue; } - BlendMode SlotData::getBlendMode() - { + BlendMode SlotData::getBlendMode() { return _blendMode; } - void SlotData::setBlendMode(BlendMode inValue) - { + void SlotData::setBlendMode(BlendMode inValue) { _blendMode = inValue; } } diff --git a/spine-cpp/spine-cpp/src/spine/TextureLoader.cpp b/spine-cpp/spine-cpp/src/spine/TextureLoader.cpp index 57073cdfe..155f316d0 100644 --- a/spine-cpp/spine-cpp/src/spine/TextureLoader.cpp +++ b/spine-cpp/spine-cpp/src/spine/TextureLoader.cpp @@ -32,13 +32,11 @@ namespace Spine { - TextureLoader::TextureLoader() - { + TextureLoader::TextureLoader() { // Empty } - TextureLoader::~TextureLoader() - { + TextureLoader::~TextureLoader() { // Empty } } diff --git a/spine-cpp/spine-cpp/src/spine/Timeline.cpp b/spine-cpp/spine-cpp/src/spine/Timeline.cpp index 6dac2f210..32d22dffa 100644 --- a/spine-cpp/spine-cpp/src/spine/Timeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/Timeline.cpp @@ -37,13 +37,11 @@ namespace Spine { RTTI_IMPL_NOPARENT(Timeline); - Timeline::Timeline() - { + Timeline::Timeline() { // Empty } - Timeline::~Timeline() - { + Timeline::~Timeline() { // Empty } } diff --git a/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp b/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp index 3f970e502..e9defe296 100644 --- a/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp +++ b/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp @@ -47,138 +47,110 @@ namespace Spine _rotateMix(data.getRotateMix()), _translateMix(data.getTranslateMix()), _scaleMix(data.getScaleMix()), - _shearMix(data.getShearMix()) - { + _shearMix(data.getShearMix()) { _bones.reserve(_data.getBones().size()); - for (BoneData** i = _data.getBones().begin(); i != _data.getBones().end(); ++i) - { + for (BoneData** i = _data.getBones().begin(); i != _data.getBones().end(); ++i) { BoneData* boneData = (*i); _bones.push_back(skeleton.findBone(boneData->getName())); } } - void TransformConstraint::apply() - { + void TransformConstraint::apply() { update(); } - void TransformConstraint::update() - { - if (_data.isLocal()) - { - if (_data.isRelative()) - { + void TransformConstraint::update() { + if (_data.isLocal()) { + if (_data.isRelative()) { applyRelativeLocal(); } - else - { + else { applyAbsoluteLocal(); } } - else - { - if (_data.isRelative()) - { + else { + if (_data.isRelative()) { applyRelativeWorld(); } - else - { + else { applyAbsoluteWorld(); } } } - int TransformConstraint::getOrder() - { + int TransformConstraint::getOrder() { return _data.getOrder(); } - TransformConstraintData& TransformConstraint::getData() - { + TransformConstraintData& TransformConstraint::getData() { return _data; } - Vector& TransformConstraint::getBones() - { + Vector& TransformConstraint::getBones() { return _bones; } - Bone* TransformConstraint::getTarget() - { + Bone* TransformConstraint::getTarget() { return _target; } - void TransformConstraint::setTarget(Bone* inValue) - { + void TransformConstraint::setTarget(Bone* inValue) { _target = inValue; } - float TransformConstraint::getRotateMix() - { + float TransformConstraint::getRotateMix() { return _rotateMix; } - void TransformConstraint::setRotateMix(float inValue) - { + void TransformConstraint::setRotateMix(float inValue) { _rotateMix = inValue; } - float TransformConstraint::getTranslateMix() - { + float TransformConstraint::getTranslateMix() { return _translateMix; } - void TransformConstraint::setTranslateMix(float inValue) - { + void TransformConstraint::setTranslateMix(float inValue) { _translateMix = inValue; } - float TransformConstraint::getScaleMix() - { + float TransformConstraint::getScaleMix() { return _scaleMix; } - void TransformConstraint::setScaleMix(float inValue) - { + void TransformConstraint::setScaleMix(float inValue) { _scaleMix = inValue; } - float TransformConstraint::getShearMix() - { + float TransformConstraint::getShearMix() { return _shearMix; } - void TransformConstraint::setShearMix(float inValue) - { + void TransformConstraint::setShearMix(float inValue) { _shearMix = inValue; } - void TransformConstraint::applyAbsoluteWorld() - { + void TransformConstraint::applyAbsoluteWorld() { float rotateMix = _rotateMix, translateMix = _translateMix, scaleMix = _scaleMix, shearMix = _shearMix; Bone& target = *_target; float ta = target._a, tb = target._b, tc = target._c, td = target._d; float degRadReflect = ta * td - tb * tc > 0 ? DegRad : -DegRad; float offsetRotation = _data._offsetRotation * degRadReflect, offsetShearY = _data._offsetShearY * degRadReflect; - for (Bone** i = _bones.begin(); i != _bones.end(); ++i) - { + for (Bone** i = _bones.begin(); i != _bones.end(); ++i) { Bone* item = (*i); Bone& bone = *item; bool modified = false; - if (rotateMix != 0) - { + if (rotateMix != 0) { float a = bone._a, b = bone._b, c = bone._c, d = bone._d; float r = MathUtil::atan2(tc, ta) - MathUtil::atan2(c, a) + offsetRotation; - if (r > SPINE_PI) - { + if (r > SPINE_PI) { r -= SPINE_PI_2; } - else if (r < -SPINE_PI) - { + else if (r < -SPINE_PI) { r += SPINE_PI_2; } @@ -191,8 +163,7 @@ namespace Spine modified = true; } - if (translateMix != 0) - { + if (translateMix != 0) { float tx, ty; target.localToWorld(_data._offsetX, _data._offsetY, tx, ty); bone._worldX += (tx - bone._worldX) * translateMix; @@ -200,20 +171,17 @@ namespace Spine modified = true; } - if (scaleMix > 0) - { + if (scaleMix > 0) { float s = (float)sqrt(bone._a * bone._a + bone._c * bone._c); - if (s > 0.00001f) - { + if (s > 0.00001f) { s = (s + ((float)sqrt(ta * ta + tc * tc) - s + _data._offsetScaleX) * scaleMix) / s; } bone._a *= s; bone._c *= s; s = (float)sqrt(bone._b * bone._b + bone._d * bone._d); - if (s > 0.00001f) - { + if (s > 0.00001f) { s = (s + ((float)sqrt(tb * tb + td * td) - s + _data._offsetScaleY) * scaleMix) / s; } bone._b *= s; @@ -221,17 +189,14 @@ namespace Spine modified = true; } - if (shearMix > 0) - { + if (shearMix > 0) { float b = bone._b, d = bone._d; float by = MathUtil::atan2(d, b); float r = MathUtil::atan2(td, tb) - MathUtil::atan2(tc, ta) - (by - MathUtil::atan2(bone._c, bone._a)); - if (r > SPINE_PI) - { + if (r > SPINE_PI) { r -= SPINE_PI_2; } - else if (r < -SPINE_PI) - { + else if (r < -SPINE_PI) { r += SPINE_PI_2; } @@ -242,37 +207,31 @@ namespace Spine modified = true; } - if (modified) - { + if (modified) { bone._appliedValid = false; } } } - void TransformConstraint::applyRelativeWorld() - { + void TransformConstraint::applyRelativeWorld() { float rotateMix = _rotateMix, translateMix = _translateMix, scaleMix = _scaleMix, shearMix = _shearMix; Bone& target = *_target; float ta = target._a, tb = target._b, tc = target._c, td = target._d; float degRadReflect = ta * td - tb * tc > 0 ? DegRad : -DegRad; float offsetRotation = _data._offsetRotation * degRadReflect, offsetShearY = _data._offsetShearY * degRadReflect; - for (Bone** i = _bones.begin(); i != _bones.end(); ++i) - { + for (Bone** i = _bones.begin(); i != _bones.end(); ++i) { Bone* item = (*i); Bone& bone = *item; bool modified = false; - if (rotateMix != 0) - { + if (rotateMix != 0) { float a = bone._a, b = bone._b, c = bone._c, d = bone._d; float r = MathUtil::atan2(tc, ta) + offsetRotation; - if (r > SPINE_PI) - { + if (r > SPINE_PI) { r -= SPINE_PI_2; } - else if (r < -SPINE_PI) - { + else if (r < -SPINE_PI) { r += SPINE_PI_2; } @@ -285,8 +244,7 @@ namespace Spine modified = true; } - if (translateMix != 0) - { + if (translateMix != 0) { float tx, ty; target.localToWorld(_data._offsetX, _data._offsetY, tx, ty); bone._worldX += tx * translateMix; @@ -294,8 +252,7 @@ namespace Spine modified = true; } - if (scaleMix > 0) - { + if (scaleMix > 0) { float s = ((float)sqrt(ta * ta + tc * tc) - 1 + _data._offsetScaleX) * scaleMix + 1; bone._a *= s; bone._c *= s; @@ -305,15 +262,12 @@ namespace Spine modified = true; } - if (shearMix > 0) - { + if (shearMix > 0) { float r = MathUtil::atan2(td, tb) - MathUtil::atan2(tc, ta); - if (r > SPINE_PI) - { + if (r > SPINE_PI) { r -= SPINE_PI_2; } - else if (r < -SPINE_PI) - { + else if (r < -SPINE_PI) { r += SPINE_PI_2; } @@ -325,64 +279,53 @@ namespace Spine modified = true; } - if (modified) - { + if (modified) { bone._appliedValid = false; } } } - void TransformConstraint::applyAbsoluteLocal() - { + void TransformConstraint::applyAbsoluteLocal() { float rotateMix = _rotateMix, translateMix = _translateMix, scaleMix = _scaleMix, shearMix = _shearMix; Bone& target = *_target; - if (!target._appliedValid) - { + if (!target._appliedValid) { target.updateAppliedTransform(); } - for (Bone** i = _bones.begin(); i != _bones.end(); ++i) - { + for (Bone** i = _bones.begin(); i != _bones.end(); ++i) { Bone* item = (*i); Bone& bone = *item; - if (!bone._appliedValid) - { + if (!bone._appliedValid) { bone.updateAppliedTransform(); } float rotation = bone._arotation; - if (rotateMix != 0) - { + if (rotateMix != 0) { float r = target._arotation - rotation + _data._offsetRotation; r -= (16384 - (int)(16384.499999999996 - r / 360)) * 360; rotation += r * rotateMix; } float x = bone._ax, y = bone._ay; - if (translateMix != 0) - { + if (translateMix != 0) { x += (target._ax - x + _data._offsetX) * translateMix; y += (target._ay - y + _data._offsetY) * translateMix; } float scaleX = bone._ascaleX, scaleY = bone._ascaleY; - if (scaleMix > 0) - { - if (scaleX > 0.00001f) - { + if (scaleMix > 0) { + if (scaleX > 0.00001f) { scaleX = (scaleX + (target._ascaleX - scaleX + _data._offsetScaleX) * scaleMix) / scaleX; } - if (scaleY > 0.00001f) - { + if (scaleY > 0.00001f) { scaleY = (scaleY + (target._ascaleY - scaleY + _data._offsetScaleY) * scaleMix) / scaleY; } } float shearY = bone._ashearY; - if (shearMix > 0) - { + if (shearMix > 0) { float r = target._ashearY - shearY + _data._offsetShearY; r -= (16384 - (int)(16384.499999999996 - r / 360)) * 360; bone._shearY += r * shearMix; @@ -392,55 +335,45 @@ namespace Spine } } - void TransformConstraint::applyRelativeLocal() - { + void TransformConstraint::applyRelativeLocal() { float rotateMix = _rotateMix, translateMix = _translateMix, scaleMix = _scaleMix, shearMix = _shearMix; Bone& target = *_target; - if (!target._appliedValid) - { + if (!target._appliedValid) { target.updateAppliedTransform(); } - for (Bone** i = _bones.begin(); i != _bones.end(); ++i) - { + for (Bone** i = _bones.begin(); i != _bones.end(); ++i) { Bone* item = (*i); Bone& bone = *item; - if (!bone._appliedValid) - { + if (!bone._appliedValid) { bone.updateAppliedTransform(); } float rotation = bone._arotation; - if (rotateMix != 0) - { + if (rotateMix != 0) { rotation += (target._arotation + _data._offsetRotation) * rotateMix; } float x = bone._ax, y = bone._ay; - if (translateMix != 0) - { + if (translateMix != 0) { x += (target._ax + _data._offsetX) * translateMix; y += (target._ay + _data._offsetY) * translateMix; } float scaleX = bone._ascaleX, scaleY = bone._ascaleY; - if (scaleMix > 0) - { - if (scaleX > 0.00001f) - { + if (scaleMix > 0) { + if (scaleX > 0.00001f) { scaleX *= ((target._ascaleX - 1 + _data._offsetScaleX) * scaleMix) + 1; } - if (scaleY > 0.00001f) - { + if (scaleY > 0.00001f) { scaleY *= ((target._ascaleY - 1 + _data._offsetScaleY) * scaleMix) + 1; } } float shearY = bone._ashearY; - if (shearMix > 0) - { + if (shearMix > 0) { shearY += (target._ashearY + _data._offsetShearY) * shearMix; } diff --git a/spine-cpp/spine-cpp/src/spine/TransformConstraintData.cpp b/spine-cpp/spine-cpp/src/spine/TransformConstraintData.cpp index 6a9942c32..e1daf92a6 100644 --- a/spine-cpp/spine-cpp/src/spine/TransformConstraintData.cpp +++ b/spine-cpp/spine-cpp/src/spine/TransformConstraintData.cpp @@ -51,87 +51,70 @@ namespace Spine _offsetScaleY(0), _offsetShearY(0), _relative(false), - _local(false) - { + _local(false) { assert(_name.length() > 0); } - const std::string& TransformConstraintData::getName() - { + const std::string& TransformConstraintData::getName() { return _name; } - int TransformConstraintData::getOrder() - { + int TransformConstraintData::getOrder() { return _order; } - Vector& TransformConstraintData::getBones() - { + Vector& TransformConstraintData::getBones() { return _bones; } - BoneData* TransformConstraintData::getTarget() - { + BoneData* TransformConstraintData::getTarget() { return _target; } - float TransformConstraintData::getRotateMix() - { + float TransformConstraintData::getRotateMix() { return _rotateMix; } - float TransformConstraintData::getTranslateMix() - { + float TransformConstraintData::getTranslateMix() { return _translateMix; } - float TransformConstraintData::getScaleMix() - { + float TransformConstraintData::getScaleMix() { return _scaleMix; } - float TransformConstraintData::getShearMix() - { + float TransformConstraintData::getShearMix() { return _shearMix; } - float TransformConstraintData::getOffsetRotation() - { + float TransformConstraintData::getOffsetRotation() { return _offsetRotation; } - float TransformConstraintData::getOffsetX() - { + float TransformConstraintData::getOffsetX() { return _offsetX; } - float TransformConstraintData::getOffsetY() - { + float TransformConstraintData::getOffsetY() { return _offsetY; } - float TransformConstraintData::getOffsetScaleX() - { + float TransformConstraintData::getOffsetScaleX() { return _offsetScaleX; } - float TransformConstraintData::getOffsetScaleY() - { + float TransformConstraintData::getOffsetScaleY() { return _offsetScaleY; } - float TransformConstraintData::getOffsetShearY() - { + float TransformConstraintData::getOffsetShearY() { return _offsetShearY; } - bool TransformConstraintData::isRelative() - { + bool TransformConstraintData::isRelative() { return _relative; } - bool TransformConstraintData::isLocal() - { + bool TransformConstraintData::isLocal() { return _local; } } diff --git a/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp b/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp index 534be4439..2b2f9c5d6 100644 --- a/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp @@ -55,21 +55,17 @@ namespace Spine const int TransformConstraintTimeline::SCALE = 3; const int TransformConstraintTimeline::SHEAR = 4; - TransformConstraintTimeline::TransformConstraintTimeline(int frameCount) : CurveTimeline(frameCount), _transformConstraintIndex(0) - { + TransformConstraintTimeline::TransformConstraintTimeline(int frameCount) : CurveTimeline(frameCount), _transformConstraintIndex(0) { _frames.reserve(frameCount * ENTRIES); _frames.setSize(frameCount * ENTRIES); } - void TransformConstraintTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) - { + void TransformConstraintTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) { TransformConstraint* constraintP = skeleton._transformConstraints[_transformConstraintIndex]; TransformConstraint& constraint = *constraintP; - if (time < _frames[0]) - { - switch (pose) - { + if (time < _frames[0]) { + switch (pose) { case MixPose_Setup: constraint._rotateMix = constraint._data._rotateMix; constraint._translateMix = constraint._data._translateMix; @@ -89,8 +85,7 @@ namespace Spine } float rotate, translate, scale, shear; - if (time >= _frames[_frames.size() - ENTRIES]) - { + if (time >= _frames[_frames.size() - ENTRIES]) { // Time is after last frame. int i = static_cast(_frames.size()); rotate = _frames[i + PREV_ROTATE]; @@ -98,8 +93,7 @@ namespace Spine scale = _frames[i + PREV_SCALE]; shear = _frames[i + PREV_SHEAR]; } - else - { + else { // Interpolate between the previous frame and the current frame. int frame = Animation::binarySearch(_frames, time, ENTRIES); rotate = _frames[frame + PREV_ROTATE]; @@ -116,16 +110,14 @@ namespace Spine shear += (_frames[frame + SHEAR] - shear) * percent; } - if (pose == MixPose_Setup) - { + if (pose == MixPose_Setup) { TransformConstraintData& data = constraint._data; constraint._rotateMix = data._rotateMix + (rotate - data._rotateMix) * alpha; constraint._translateMix = data._translateMix + (translate - data._translateMix) * alpha; constraint._scaleMix = data._scaleMix + (scale - data._scaleMix) * alpha; constraint._shearMix = data._shearMix + (shear - data._shearMix) * alpha; } - else - { + else { constraint._rotateMix += (rotate - constraint._rotateMix) * alpha; constraint._translateMix += (translate - constraint._translateMix) * alpha; constraint._scaleMix += (scale - constraint._scaleMix) * alpha; @@ -133,13 +125,11 @@ namespace Spine } } - int TransformConstraintTimeline::getPropertyId() - { + int TransformConstraintTimeline::getPropertyId() { return ((int)TimelineType_TransformConstraint << 24) + _transformConstraintIndex; } - void TransformConstraintTimeline::setFrame(int frameIndex, float time, float rotateMix, float translateMix, float scaleMix, float shearMix) - { + void TransformConstraintTimeline::setFrame(int frameIndex, float time, float rotateMix, float translateMix, float scaleMix, float shearMix) { frameIndex *= ENTRIES; _frames[frameIndex] = time; _frames[frameIndex + ROTATE] = rotateMix; diff --git a/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp b/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp index 8c23b0e58..c8dfb639e 100644 --- a/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp @@ -51,21 +51,17 @@ namespace Spine const int TranslateTimeline::X = 1; const int TranslateTimeline::Y = 2; - TranslateTimeline::TranslateTimeline(int frameCount) : CurveTimeline(frameCount), _boneIndex(0) - { + TranslateTimeline::TranslateTimeline(int frameCount) : CurveTimeline(frameCount), _boneIndex(0) { _frames.reserve(frameCount * ENTRIES); _frames.setSize(frameCount * ENTRIES); } - void TranslateTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) - { + void TranslateTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) { Bone* boneP = skeleton._bones[_boneIndex]; Bone& bone = *boneP; - if (time < _frames[0]) - { - switch (pose) - { + if (time < _frames[0]) { + switch (pose) { case MixPose_Setup: bone._x = bone._data._x; bone._y = bone._data._y; @@ -81,14 +77,12 @@ namespace Spine } float x, y; - if (time >= _frames[_frames.size() - ENTRIES]) - { + if (time >= _frames[_frames.size() - ENTRIES]) { // Time is after last frame. x = _frames[_frames.size() + PREV_X]; y = _frames[_frames.size() + PREV_Y]; } - else - { + else { // Interpolate between the previous frame and the current frame. int frame = Animation::binarySearch(_frames, time, ENTRIES); x = _frames[frame + PREV_X]; @@ -100,25 +94,21 @@ namespace Spine y += (_frames[frame + Y] - y) * percent; } - if (pose == MixPose_Setup) - { + if (pose == MixPose_Setup) { bone._x = bone._data._x + x * alpha; bone._y = bone._data._y + y * alpha; } - else - { + else { bone._x += (bone._data._x + x - bone._x) * alpha; bone._y += (bone._data._y + y - bone._y) * alpha; } } - int TranslateTimeline::getPropertyId() - { + int TranslateTimeline::getPropertyId() { return ((int)TimelineType_Translate << 24) + _boneIndex; } - void TranslateTimeline::setFrame(int frameIndex, float time, float x, float y) - { + void TranslateTimeline::setFrame(int frameIndex, float time, float x, float y) { frameIndex *= ENTRIES; _frames[frameIndex] = time; _frames[frameIndex + X] = x; diff --git a/spine-cpp/spine-cpp/src/spine/Triangulator.cpp b/spine-cpp/spine-cpp/src/spine/Triangulator.cpp index edf536367..1b715609f 100644 --- a/spine-cpp/spine-cpp/src/spine/Triangulator.cpp +++ b/spine-cpp/spine-cpp/src/spine/Triangulator.cpp @@ -34,24 +34,21 @@ namespace Spine { - Vector& Triangulator::triangulate(Vector& vertices) - { + Vector& Triangulator::triangulate(Vector& vertices) { int vertexCount = static_cast(vertices.size() >> 1); Vector& indices = _indices; indices.clear(); indices.reserve(vertexCount); indices.setSize(vertexCount); - for (int i = 0; i < vertexCount; ++i) - { + for (int i = 0; i < vertexCount; ++i) { indices[i] = i; } Vector& isConcaveArray = _isConcaveArray; isConcaveArray.reserve(vertexCount); isConcaveArray.setSize(vertexCount); - for (int i = 0, n = vertexCount; i < n; ++i) - { + for (int i = 0, n = vertexCount; i < n; ++i) { isConcaveArray[i] = isConcave(i, vertexCount, vertices, indices); } @@ -59,35 +56,27 @@ namespace Spine triangles.clear(); triangles.reserve(MAX(0, vertexCount - 2) << 2); - while (vertexCount > 3) - { + while (vertexCount > 3) { // Find ear tip. int previous = vertexCount - 1, i = 0, next = 1; // outer: - while (true) - { - if (!isConcaveArray[i]) - { + while (true) { + if (!isConcaveArray[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 (int ii = (next + 1) % vertexCount; ii != previous; ii = (ii + 1) % vertexCount) - { - if (!isConcaveArray[ii]) - { + for (int ii = (next + 1) % vertexCount; ii != previous; ii = (ii + 1) % vertexCount) { + if (!isConcaveArray[ii]) { continue; } int v = indices[ii] << 1; float& 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)) - { + 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 outer; } } @@ -97,12 +86,9 @@ namespace Spine } break_outer: - if (next == 0) - { - do - { - if (!isConcaveArray[i]) - { + if (next == 0) { + do { + if (!isConcaveArray[i]) { break; } i--; @@ -129,8 +115,7 @@ namespace Spine isConcaveArray[nextIndex] = isConcave(nextIndex, vertexCount, vertices, indices); } - if (vertexCount == 3) - { + if (vertexCount == 3) { triangles.push_back(indices[2]); triangles.push_back(indices[0]); triangles.push_back(indices[1]); @@ -139,18 +124,15 @@ namespace Spine return triangles; } - Vector< Vector* > Triangulator::decompose(Vector& vertices, Vector& triangles) - { + Vector< Vector* > Triangulator::decompose(Vector& vertices, Vector& triangles) { Vector< Vector* >&convexPolygons = _convexPolygons; - for (size_t i = 0, n = convexPolygons.size(); i < n; ++i) - { + for (size_t i = 0, n = convexPolygons.size(); i < n; ++i) { _polygonPool.free(convexPolygons[i]); } convexPolygons.clear(); Vector< Vector* > convexPolygonsIndices = _convexPolygonsIndices; - for (size_t i = 0, n = convexPolygonsIndices.size(); i < n; ++i) - { + for (size_t i = 0, n = convexPolygonsIndices.size(); i < n; ++i) { _polygonIndicesPool.free(convexPolygonsIndices[i]); } convexPolygonsIndices.clear(); @@ -165,8 +147,7 @@ namespace Spine // Merge subsequent triangles if they form a triangle fan. int fanBaseIndex = -1, lastwinding = 0; - for (size_t i = 0, n = triangles.size(); i < n; i += 3) - { + for (size_t i = 0, n = triangles.size(); i < n; i += 3) { int t1 = triangles[i] << 1, t2 = triangles[i + 1] << 1, t3 = triangles[i + 2] << 1; float x1 = vertices[t1], y1 = vertices[t1 + 1]; float x2 = vertices[t2], y2 = vertices[t2 + 1]; @@ -174,14 +155,12 @@ namespace Spine // If the base of the last triangle is the same as this triangle, check if they form a convex polygon (triangle fan). bool merged = false; - if (fanBaseIndex == t1) - { + if (fanBaseIndex == t1) { size_t o = polygon.size() - 4; Vector& p = polygon; 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) - { + if (winding1 == lastwinding && winding2 == lastwinding) { polygon.push_back(x3); polygon.push_back(y3); polygonIndices.push_back(t3); @@ -190,15 +169,12 @@ namespace Spine } // Otherwise make this triangle the new base. - if (!merged) - { - if (polygon.size() > 0) - { + if (!merged) { + if (polygon.size() > 0) { convexPolygons.push_back(&polygon); convexPolygonsIndices.push_back(&polygonIndices); } - else - { + else { _polygonPool.free(&polygon); _polygonIndicesPool.free(&polygonIndices); } @@ -221,15 +197,13 @@ namespace Spine } } - if (polygon.size() > 0) - { + if (polygon.size() > 0) { convexPolygons.push_back(&polygon); convexPolygonsIndices.push_back(&polygonIndices); } // Go through the list of polygons and try to merge the remaining triangles with the found triangle fans. - for (size_t i = 0, n = convexPolygons.size(); i < n; ++i) - { + for (size_t i = 0, n = convexPolygons.size(); i < n; ++i) { polygonIndicesP = convexPolygonsIndices[i]; polygonIndices = *polygonIndicesP; @@ -246,18 +220,15 @@ namespace Spine float secondX = p[2], secondY = p[3]; int winding0 = winding(prevPrevX, prevPrevY, prevX, prevY, firstX, firstY); - for (int ii = 0; ii < n; ++ii) - { - if (ii == i) - { + for (int ii = 0; ii < n; ++ii) { + if (ii == i) { continue; } Vector* otherIndicesP = convexPolygonsIndices[ii]; Vector& otherIndices = *otherIndicesP; - if (otherIndices.size() != 3) - { + if (otherIndices.size() != 3) { continue; } @@ -270,15 +241,13 @@ namespace Spine float x3 = otherPoly[otherPoly.size() - 2], y3 = otherPoly[otherPoly.size() - 1]; - if (otherFirstIndex != firstIndex || otherSecondIndex != lastIndex) - { + if (otherFirstIndex != firstIndex || otherSecondIndex != lastIndex) { continue; } int winding1 = winding(prevPrevX, prevPrevY, prevX, prevY, x3, y3); int winding2 = winding(x3, y3, firstX, firstY, secondX, secondY); - if (winding1 == winding0 && winding2 == winding0) - { + if (winding1 == winding0 && winding2 == winding0) { otherPoly.clear(); otherIndices.clear(); polygon.push_back(x3); @@ -294,11 +263,9 @@ namespace Spine } // Remove empty polygons that resulted from the merge step above. - for (int i = static_cast(convexPolygons.size()) - 1; i >= 0; --i) - { + for (int i = static_cast(convexPolygons.size()) - 1; i >= 0; --i) { polygon = *convexPolygons[i]; - if (polygon.size() == 0) - { + if (polygon.size() == 0) { convexPolygons.erase(i); _polygonPool.free(&polygon); polygonIndices = *convexPolygonsIndices[i]; @@ -310,8 +277,7 @@ namespace Spine return convexPolygons; } - bool Triangulator::isConcave(int index, int vertexCount, Vector& vertices, Vector& indices) - { + bool Triangulator::isConcave(int index, int vertexCount, Vector& vertices, Vector& indices) { int previous = indices[(vertexCount + index - 1) % vertexCount] << 1; int current = indices[index] << 1; int next = indices[(index + 1) % vertexCount] << 1; @@ -319,13 +285,11 @@ namespace Spine return !positiveArea(vertices[previous], vertices[previous + 1], vertices[current], vertices[current + 1], vertices[next], vertices[next + 1]); } - bool Triangulator::positiveArea(float p1x, float p1y, float p2x, float p2y, float p3x, float p3y) - { + bool Triangulator::positiveArea(float p1x, float p1y, float p2x, float p2y, float p3x, float p3y) { return p1x * (p3y - p2y) + p2x * (p1y - p3y) + p3x * (p2y - p1y) >= 0; } - int Triangulator::winding(float p1x, float p1y, float p2x, float p2y, float p3x, float p3y) - { + int Triangulator::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; diff --git a/spine-cpp/spine-cpp/src/spine/TwoColorTimeline.cpp b/spine-cpp/spine-cpp/src/spine/TwoColorTimeline.cpp index 16c28b180..5cb546b26 100644 --- a/spine-cpp/spine-cpp/src/spine/TwoColorTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/TwoColorTimeline.cpp @@ -59,22 +59,18 @@ namespace Spine const int TwoColorTimeline::G2 = 6; const int TwoColorTimeline::B2 = 7; - TwoColorTimeline::TwoColorTimeline(int frameCount) : CurveTimeline(frameCount), _slotIndex(0) - { + TwoColorTimeline::TwoColorTimeline(int frameCount) : CurveTimeline(frameCount), _slotIndex(0) { _frames.reserve(frameCount * ENTRIES); _frames.setSize(frameCount * ENTRIES); } - void TwoColorTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) - { + void TwoColorTimeline::apply(Skeleton& skeleton, float lastTime, float time, Vector* pEvents, float alpha, MixPose pose, MixDirection direction) { Slot* slotP = skeleton._slots[_slotIndex]; Slot& slot = *slotP; - if (time < _frames[0]) - { + if (time < _frames[0]) { // Time is before first frame. - switch (pose) - { + switch (pose) { case MixPose_Setup: slot._r = slot._data._r; slot._g = slot._data._g; @@ -100,8 +96,7 @@ namespace Spine } float r, g, b, a, r2, g2, b2; - if (time >= _frames[_frames.size() - ENTRIES]) - { + if (time >= _frames[_frames.size() - ENTRIES]) { // Time is after last frame. int i = static_cast(_frames.size()); r = _frames[i + PREV_R]; @@ -112,8 +107,7 @@ namespace Spine g2 = _frames[i + PREV_G2]; b2 = _frames[i + PREV_B2]; } - else - { + else { // Interpolate between the previous frame and the current frame. int frame = Animation::binarySearch(_frames, time, ENTRIES); r = _frames[frame + PREV_R]; @@ -136,8 +130,7 @@ namespace Spine b2 += (_frames[frame + B2] - b2) * percent; } - if (alpha == 1) - { + if (alpha == 1) { slot._r = r; slot._g = g; slot._b = b; @@ -146,11 +139,9 @@ namespace Spine slot._g2 = g2; slot._b2 = b2; } - else - { + else { float br, bg, bb, ba, br2, bg2, bb2; - if (pose == MixPose_Setup) - { + if (pose == MixPose_Setup) { br = slot._data._r; bg = slot._data._g; bb = slot._data._b; @@ -159,8 +150,7 @@ namespace Spine bg2 = slot._data._g2; bb2 = slot._data._b2; } - else - { + else { br = slot._r; bg = slot._g; bb = slot._b; @@ -180,13 +170,11 @@ namespace Spine } } - int TwoColorTimeline::getPropertyId() - { + int TwoColorTimeline::getPropertyId() { return ((int)TimelineType_TwoColor << 24) + _slotIndex; } - void TwoColorTimeline::setFrame(int frameIndex, float time, float r, float g, float b, float a, float r2, float g2, float b2) - { + void TwoColorTimeline::setFrame(int frameIndex, float time, float r, float g, float b, float a, float r2, float g2, float b2) { frameIndex *= ENTRIES; _frames[frameIndex] = time; _frames[frameIndex + R] = r; @@ -198,13 +186,11 @@ namespace Spine _frames[frameIndex + B2] = b2; } - int TwoColorTimeline::getSlotIndex() - { + int TwoColorTimeline::getSlotIndex() { return _slotIndex; } - void TwoColorTimeline::setSlotIndex(int inValue) - { + void TwoColorTimeline::setSlotIndex(int inValue) { assert(inValue >= 0); _slotIndex = inValue; } diff --git a/spine-cpp/spine-cpp/src/spine/Updatable.cpp b/spine-cpp/spine-cpp/src/spine/Updatable.cpp index 598955a9a..8993b94ae 100644 --- a/spine-cpp/spine-cpp/src/spine/Updatable.cpp +++ b/spine-cpp/spine-cpp/src/spine/Updatable.cpp @@ -34,13 +34,11 @@ namespace Spine { RTTI_IMPL_NOPARENT(Updatable); - Updatable::Updatable() - { + Updatable::Updatable() { // Empty } - Updatable::~Updatable() - { + Updatable::~Updatable() { // Empty } } diff --git a/spine-cpp/spine-cpp/src/spine/VertexAttachment.cpp b/spine-cpp/spine-cpp/src/spine/VertexAttachment.cpp index 6cfa69a34..318b15263 100644 --- a/spine-cpp/spine-cpp/src/spine/VertexAttachment.cpp +++ b/spine-cpp/spine-cpp/src/spine/VertexAttachment.cpp @@ -39,27 +39,22 @@ namespace Spine { RTTI_IMPL(VertexAttachment, Attachment); - VertexAttachment::VertexAttachment(std::string name) : Attachment(name), _worldVerticesLength(0), _id(getNextID()) - { + VertexAttachment::VertexAttachment(std::string name) : Attachment(name), _worldVerticesLength(0), _id(getNextID()) { // Empty } - void VertexAttachment::computeWorldVertices(Slot& slot, Vector& worldVertices) - { + void VertexAttachment::computeWorldVertices(Slot& slot, Vector& worldVertices) { computeWorldVertices(slot, 0, _worldVerticesLength, worldVertices, 0); } - void VertexAttachment::computeWorldVertices(Slot& slot, int start, int count, Vector& worldVertices, int offset, int stride) - { + void VertexAttachment::computeWorldVertices(Slot& slot, int start, int count, Vector& worldVertices, int offset, int stride) { count = offset + (count >> 1) * stride; Skeleton& skeleton = slot._bone._skeleton; Vector& deformArray = slot.getAttachmentVertices(); Vector& vertices = _vertices; Vector& bones = _bones; - if (bones.size() == 0) - { - if (deformArray.size() > 0) - { + if (bones.size() == 0) { + if (deformArray.size() > 0) { vertices = deformArray; } @@ -67,8 +62,7 @@ namespace Spine float x = bone._worldX; float y = bone._worldY; float a = bone._a, b = bone._b, c = bone._c, d = bone._d; - for (int vv = start, w = offset; w < count; vv += 2, w += stride) - { + for (int vv = start, w = offset; w < count; vv += 2, w += stride) { float vx = vertices[vv]; float vy = vertices[vv + 1]; worldVertices[w] = vx * a + vy * b + x; @@ -78,23 +72,19 @@ namespace Spine } int v = 0, skip = 0; - for (int i = 0; i < start; i += 2) - { + for (int i = 0; i < start; i += 2) { int n = bones[v]; v += n + 1; skip += n; } Vector& skeletonBones = skeleton.getBones(); - if (deformArray.size() == 0) - { - for (int w = offset, b = skip * 3; w < count; w += stride) - { + if (deformArray.size() == 0) { + for (int 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) - { + for (; v < n; v++, b += 3) { Bone* boneP = skeletonBones[bones[v]]; Bone& bone = *boneP; float vx = vertices[b]; @@ -107,15 +97,12 @@ namespace Spine worldVertices[w + 1] = wy; } } - else - { - for (int w = offset, b = skip * 3, f = skip << 1; w < count; w += stride) - { + else { + for (int 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) - { + for (; v < n; v++, b += 3, f += 2) { Bone* boneP = skeletonBones[bones[v]]; Bone& bone = *boneP; float vx = vertices[b] + deformArray[f]; @@ -130,48 +117,39 @@ namespace Spine } } - bool VertexAttachment::applyDeform(VertexAttachment* sourceAttachment) - { + bool VertexAttachment::applyDeform(VertexAttachment* sourceAttachment) { return this == sourceAttachment; } - int VertexAttachment::getId() - { + int VertexAttachment::getId() { return _id; } - Vector& VertexAttachment::getBones() - { + Vector& VertexAttachment::getBones() { return _bones; } - void VertexAttachment::setBones(Vector inValue) - { + void VertexAttachment::setBones(Vector inValue) { _bones = inValue; } - Vector& VertexAttachment::getVertices() - { + Vector& VertexAttachment::getVertices() { return _vertices; } - void VertexAttachment::setVertices(Vector inValue) - { + void VertexAttachment::setVertices(Vector inValue) { _vertices = inValue; } - int VertexAttachment::getWorldVerticesLength() - { + int VertexAttachment::getWorldVerticesLength() { return _worldVerticesLength; } - void VertexAttachment::setWorldVerticesLength(int inValue) - { + void VertexAttachment::setWorldVerticesLength(int inValue) { _worldVerticesLength = inValue; } - int VertexAttachment::getNextID() - { + int VertexAttachment::getNextID() { static int nextID = 0; return (nextID++ & 65535) << 11; From d403db2754f16a85e6f3acad181c4e2cf080810a Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Wed, 13 Dec 2017 12:08:23 -0500 Subject: [PATCH 81/83] Forgot to move the namespace braces. --- spine-cpp/spine-cpp/include/spine/Animation.h | 3 +-- spine-cpp/spine-cpp/include/spine/AnimationState.h | 3 +-- spine-cpp/spine-cpp/include/spine/AnimationStateData.h | 3 +-- spine-cpp/spine-cpp/include/spine/Atlas.h | 3 +-- spine-cpp/spine-cpp/include/spine/AtlasAttachmentLoader.h | 3 +-- spine-cpp/spine-cpp/include/spine/Attachment.h | 3 +-- spine-cpp/spine-cpp/include/spine/AttachmentLoader.h | 3 +-- spine-cpp/spine-cpp/include/spine/AttachmentTimeline.h | 3 +-- spine-cpp/spine-cpp/include/spine/AttachmentType.h | 3 +-- spine-cpp/spine-cpp/include/spine/BlendMode.h | 3 +-- spine-cpp/spine-cpp/include/spine/Bone.h | 3 +-- spine-cpp/spine-cpp/include/spine/BoneData.h | 3 +-- spine-cpp/spine-cpp/include/spine/BoundingBoxAttachment.h | 3 +-- spine-cpp/spine-cpp/include/spine/ClippingAttachment.h | 3 +-- spine-cpp/spine-cpp/include/spine/ColorTimeline.h | 3 +-- spine-cpp/spine-cpp/include/spine/Constraint.h | 3 +-- spine-cpp/spine-cpp/include/spine/ContainerUtil.h | 3 +-- spine-cpp/spine-cpp/include/spine/CurveTimeline.h | 3 +-- spine-cpp/spine-cpp/include/spine/DeformTimeline.h | 3 +-- spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h | 3 +-- spine-cpp/spine-cpp/include/spine/Event.h | 3 +-- spine-cpp/spine-cpp/include/spine/EventData.h | 3 +-- spine-cpp/spine-cpp/include/spine/EventTimeline.h | 3 +-- spine-cpp/spine-cpp/include/spine/Extension.h | 3 +-- spine-cpp/spine-cpp/include/spine/HashMap.h | 3 +-- spine-cpp/spine-cpp/include/spine/IkConstraint.h | 3 +-- spine-cpp/spine-cpp/include/spine/IkConstraintData.h | 3 +-- spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h | 3 +-- spine-cpp/spine-cpp/include/spine/Json.h | 3 +-- spine-cpp/spine-cpp/include/spine/LinkedMesh.h | 3 +-- spine-cpp/spine-cpp/include/spine/MathUtil.h | 3 +-- spine-cpp/spine-cpp/include/spine/MeshAttachment.h | 3 +-- spine-cpp/spine-cpp/include/spine/MixDirection.h | 3 +-- spine-cpp/spine-cpp/include/spine/MixPose.h | 3 +-- spine-cpp/spine-cpp/include/spine/PathAttachment.h | 3 +-- spine-cpp/spine-cpp/include/spine/PathConstraint.h | 3 +-- spine-cpp/spine-cpp/include/spine/PathConstraintData.h | 3 +-- spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h | 3 +-- .../spine-cpp/include/spine/PathConstraintPositionTimeline.h | 3 +-- .../spine-cpp/include/spine/PathConstraintSpacingTimeline.h | 3 +-- spine-cpp/spine-cpp/include/spine/PointAttachment.h | 3 +-- spine-cpp/spine-cpp/include/spine/Pool.h | 3 +-- spine-cpp/spine-cpp/include/spine/PositionMode.h | 3 +-- spine-cpp/spine-cpp/include/spine/RTTI.h | 3 +-- spine-cpp/spine-cpp/include/spine/RegionAttachment.h | 3 +-- spine-cpp/spine-cpp/include/spine/RotateMode.h | 3 +-- spine-cpp/spine-cpp/include/spine/RotateTimeline.h | 3 +-- spine-cpp/spine-cpp/include/spine/ScaleTimeline.h | 3 +-- spine-cpp/spine-cpp/include/spine/ShearTimeline.h | 3 +-- spine-cpp/spine-cpp/include/spine/Skeleton.h | 3 +-- spine-cpp/spine-cpp/include/spine/SkeletonBinary.h | 3 +-- spine-cpp/spine-cpp/include/spine/SkeletonBounds.h | 3 +-- spine-cpp/spine-cpp/include/spine/SkeletonClipping.h | 3 +-- spine-cpp/spine-cpp/include/spine/SkeletonData.h | 3 +-- spine-cpp/spine-cpp/include/spine/SkeletonJson.h | 3 +-- spine-cpp/spine-cpp/include/spine/Skin.h | 3 +-- spine-cpp/spine-cpp/include/spine/Slot.h | 3 +-- spine-cpp/spine-cpp/include/spine/SlotData.h | 3 +-- spine-cpp/spine-cpp/include/spine/SpacingMode.h | 3 +-- spine-cpp/spine-cpp/include/spine/TextureLoader.h | 3 +-- spine-cpp/spine-cpp/include/spine/Timeline.h | 3 +-- spine-cpp/spine-cpp/include/spine/TimelineType.h | 3 +-- spine-cpp/spine-cpp/include/spine/TransformConstraint.h | 3 +-- spine-cpp/spine-cpp/include/spine/TransformConstraintData.h | 3 +-- .../spine-cpp/include/spine/TransformConstraintTimeline.h | 3 +-- spine-cpp/spine-cpp/include/spine/TransformMode.h | 3 +-- spine-cpp/spine-cpp/include/spine/TranslateTimeline.h | 3 +-- spine-cpp/spine-cpp/include/spine/Triangulator.h | 3 +-- spine-cpp/spine-cpp/include/spine/TwoColorTimeline.h | 3 +-- spine-cpp/spine-cpp/include/spine/Updatable.h | 3 +-- spine-cpp/spine-cpp/include/spine/Vector.h | 3 +-- spine-cpp/spine-cpp/include/spine/VertexAttachment.h | 3 +-- spine-cpp/spine-cpp/include/spine/Vertices.h | 3 +-- spine-cpp/spine-cpp/src/spine/Animation.cpp | 3 +-- spine-cpp/spine-cpp/src/spine/AnimationState.cpp | 3 +-- spine-cpp/spine-cpp/src/spine/AnimationStateData.cpp | 3 +-- spine-cpp/spine-cpp/src/spine/Atlas.cpp | 3 +-- spine-cpp/spine-cpp/src/spine/AtlasAttachmentLoader.cpp | 3 +-- spine-cpp/spine-cpp/src/spine/Attachment.cpp | 3 +-- spine-cpp/spine-cpp/src/spine/AttachmentLoader.cpp | 3 +-- spine-cpp/spine-cpp/src/spine/AttachmentTimeline.cpp | 3 +-- spine-cpp/spine-cpp/src/spine/Bone.cpp | 3 +-- spine-cpp/spine-cpp/src/spine/BoneData.cpp | 3 +-- spine-cpp/spine-cpp/src/spine/BoundingBoxAttachment.cpp | 3 +-- spine-cpp/spine-cpp/src/spine/ClippingAttachment.cpp | 3 +-- spine-cpp/spine-cpp/src/spine/ColorTimeline.cpp | 3 +-- spine-cpp/spine-cpp/src/spine/Constraint.cpp | 3 +-- spine-cpp/spine-cpp/src/spine/CurveTimeline.cpp | 3 +-- spine-cpp/spine-cpp/src/spine/DeformTimeline.cpp | 3 +-- spine-cpp/spine-cpp/src/spine/DrawOrderTimeline.cpp | 3 +-- spine-cpp/spine-cpp/src/spine/Event.cpp | 3 +-- spine-cpp/spine-cpp/src/spine/EventData.cpp | 3 +-- spine-cpp/spine-cpp/src/spine/EventTimeline.cpp | 3 +-- spine-cpp/spine-cpp/src/spine/Extension.cpp | 3 +-- spine-cpp/spine-cpp/src/spine/IkConstraint.cpp | 3 +-- spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp | 3 +-- spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp | 3 +-- spine-cpp/spine-cpp/src/spine/Json.cpp | 3 +-- spine-cpp/spine-cpp/src/spine/LinkedMesh.cpp | 3 +-- spine-cpp/spine-cpp/src/spine/MathUtil.cpp | 3 +-- spine-cpp/spine-cpp/src/spine/MeshAttachment.cpp | 3 +-- spine-cpp/spine-cpp/src/spine/PathAttachment.cpp | 3 +-- spine-cpp/spine-cpp/src/spine/PathConstraint.cpp | 3 +-- spine-cpp/spine-cpp/src/spine/PathConstraintData.cpp | 3 +-- spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp | 3 +-- .../spine-cpp/src/spine/PathConstraintPositionTimeline.cpp | 3 +-- .../spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp | 3 +-- spine-cpp/spine-cpp/src/spine/PointAttachment.cpp | 3 +-- spine-cpp/spine-cpp/src/spine/RTTI.cpp | 3 +-- spine-cpp/spine-cpp/src/spine/RegionAttachment.cpp | 3 +-- spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp | 3 +-- spine-cpp/spine-cpp/src/spine/ScaleTimeline.cpp | 3 +-- spine-cpp/spine-cpp/src/spine/ShearTimeline.cpp | 3 +-- spine-cpp/spine-cpp/src/spine/Skeleton.cpp | 3 +-- spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp | 3 +-- spine-cpp/spine-cpp/src/spine/SkeletonBounds.cpp | 3 +-- spine-cpp/spine-cpp/src/spine/SkeletonClipping.cpp | 3 +-- spine-cpp/spine-cpp/src/spine/SkeletonData.cpp | 3 +-- spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp | 3 +-- spine-cpp/spine-cpp/src/spine/Skin.cpp | 3 +-- spine-cpp/spine-cpp/src/spine/Slot.cpp | 3 +-- spine-cpp/spine-cpp/src/spine/SlotData.cpp | 3 +-- spine-cpp/spine-cpp/src/spine/TextureLoader.cpp | 3 +-- spine-cpp/spine-cpp/src/spine/Timeline.cpp | 3 +-- spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp | 3 +-- spine-cpp/spine-cpp/src/spine/TransformConstraintData.cpp | 3 +-- spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp | 3 +-- spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp | 3 +-- spine-cpp/spine-cpp/src/spine/Triangulator.cpp | 3 +-- spine-cpp/spine-cpp/src/spine/TwoColorTimeline.cpp | 3 +-- spine-cpp/spine-cpp/src/spine/Updatable.cpp | 3 +-- spine-cpp/spine-cpp/src/spine/VertexAttachment.cpp | 3 +-- 132 files changed, 132 insertions(+), 264 deletions(-) diff --git a/spine-cpp/spine-cpp/include/spine/Animation.h b/spine-cpp/spine-cpp/include/spine/Animation.h index fa674382e..6713fd6b2 100644 --- a/spine-cpp/spine-cpp/include/spine/Animation.h +++ b/spine-cpp/spine-cpp/include/spine/Animation.h @@ -37,8 +37,7 @@ #include -namespace Spine -{ +namespace Spine { class Timeline; class Skeleton; class Event; diff --git a/spine-cpp/spine-cpp/include/spine/AnimationState.h b/spine-cpp/spine-cpp/include/spine/AnimationState.h index 4e81c40d3..404193400 100644 --- a/spine-cpp/spine-cpp/include/spine/AnimationState.h +++ b/spine-cpp/spine-cpp/include/spine/AnimationState.h @@ -35,8 +35,7 @@ #include #include -namespace Spine -{ +namespace Spine { enum EventType { EventType_Start, EventType_Interrupt, diff --git a/spine-cpp/spine-cpp/include/spine/AnimationStateData.h b/spine-cpp/spine-cpp/include/spine/AnimationStateData.h index c2befdd01..1ce86ca26 100644 --- a/spine-cpp/spine-cpp/include/spine/AnimationStateData.h +++ b/spine-cpp/spine-cpp/include/spine/AnimationStateData.h @@ -36,8 +36,7 @@ #include #include -namespace Spine -{ +namespace Spine { class SkeletonData; class Animation; diff --git a/spine-cpp/spine-cpp/include/spine/Atlas.h b/spine-cpp/spine-cpp/include/spine/Atlas.h index 606a35faa..1fc1afbee 100644 --- a/spine-cpp/spine-cpp/include/spine/Atlas.h +++ b/spine-cpp/spine-cpp/include/spine/Atlas.h @@ -36,8 +36,7 @@ #include -namespace Spine -{ +namespace Spine { enum Format { Format_Alpha, Format_Intensity, diff --git a/spine-cpp/spine-cpp/include/spine/AtlasAttachmentLoader.h b/spine-cpp/spine-cpp/include/spine/AtlasAttachmentLoader.h index 2052bb69b..a43f245db 100644 --- a/spine-cpp/spine-cpp/include/spine/AtlasAttachmentLoader.h +++ b/spine-cpp/spine-cpp/include/spine/AtlasAttachmentLoader.h @@ -35,8 +35,7 @@ #include -namespace Spine -{ +namespace Spine { class Atlas; class AtlasRegion; diff --git a/spine-cpp/spine-cpp/include/spine/Attachment.h b/spine-cpp/spine-cpp/include/spine/Attachment.h index 35ae099b7..8054e4d23 100644 --- a/spine-cpp/spine-cpp/include/spine/Attachment.h +++ b/spine-cpp/spine-cpp/include/spine/Attachment.h @@ -35,8 +35,7 @@ #include -namespace Spine -{ +namespace Spine { class Attachment { RTTI_DECL; diff --git a/spine-cpp/spine-cpp/include/spine/AttachmentLoader.h b/spine-cpp/spine-cpp/include/spine/AttachmentLoader.h index 1da82e4f7..07eb4fdfb 100644 --- a/spine-cpp/spine-cpp/include/spine/AttachmentLoader.h +++ b/spine-cpp/spine-cpp/include/spine/AttachmentLoader.h @@ -35,8 +35,7 @@ #include -namespace Spine -{ +namespace Spine { class Skin; class RegionAttachment; class MeshAttachment; diff --git a/spine-cpp/spine-cpp/include/spine/AttachmentTimeline.h b/spine-cpp/spine-cpp/include/spine/AttachmentTimeline.h index c0a1fad41..f81586ccb 100644 --- a/spine-cpp/spine-cpp/include/spine/AttachmentTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/AttachmentTimeline.h @@ -39,8 +39,7 @@ #include -namespace Spine -{ +namespace Spine { class Skeleton; class Event; diff --git a/spine-cpp/spine-cpp/include/spine/AttachmentType.h b/spine-cpp/spine-cpp/include/spine/AttachmentType.h index 1ad7a4d62..76ecb42d9 100644 --- a/spine-cpp/spine-cpp/include/spine/AttachmentType.h +++ b/spine-cpp/spine-cpp/include/spine/AttachmentType.h @@ -31,8 +31,7 @@ #ifndef Spine_AttachmentType_h #define Spine_AttachmentType_h -namespace Spine -{ +namespace Spine { enum AttachmentType { AttachmentType_Region, AttachmentType_Boundingbox, diff --git a/spine-cpp/spine-cpp/include/spine/BlendMode.h b/spine-cpp/spine-cpp/include/spine/BlendMode.h index d61fcdd77..65d8a674b 100644 --- a/spine-cpp/spine-cpp/include/spine/BlendMode.h +++ b/spine-cpp/spine-cpp/include/spine/BlendMode.h @@ -31,8 +31,7 @@ #ifndef Spine_BlendMode_h #define Spine_BlendMode_h -namespace Spine -{ +namespace Spine { enum BlendMode { BlendMode_Normal = 0, BlendMode_Additive, diff --git a/spine-cpp/spine-cpp/include/spine/Bone.h b/spine-cpp/spine-cpp/include/spine/Bone.h index 4413be97d..d2e876f8c 100644 --- a/spine-cpp/spine-cpp/include/spine/Bone.h +++ b/spine-cpp/spine-cpp/include/spine/Bone.h @@ -35,8 +35,7 @@ #include -namespace Spine -{ +namespace Spine { class BoneData; class Skeleton; diff --git a/spine-cpp/spine-cpp/include/spine/BoneData.h b/spine-cpp/spine-cpp/include/spine/BoneData.h index 4825ed4fe..12b060f3f 100644 --- a/spine-cpp/spine-cpp/include/spine/BoneData.h +++ b/spine-cpp/spine-cpp/include/spine/BoneData.h @@ -35,8 +35,7 @@ #include -namespace Spine -{ +namespace Spine { class BoneData { friend class SkeletonBinary; friend class SkeletonJson; diff --git a/spine-cpp/spine-cpp/include/spine/BoundingBoxAttachment.h b/spine-cpp/spine-cpp/include/spine/BoundingBoxAttachment.h index aef2b7c47..d0a707ed2 100644 --- a/spine-cpp/spine-cpp/include/spine/BoundingBoxAttachment.h +++ b/spine-cpp/spine-cpp/include/spine/BoundingBoxAttachment.h @@ -33,8 +33,7 @@ #include -namespace Spine -{ +namespace Spine { /// Attachment that has a polygon for bounds checking. class BoundingBoxAttachment : public VertexAttachment { RTTI_DECL; diff --git a/spine-cpp/spine-cpp/include/spine/ClippingAttachment.h b/spine-cpp/spine-cpp/include/spine/ClippingAttachment.h index 8740407b3..5f4a56545 100644 --- a/spine-cpp/spine-cpp/include/spine/ClippingAttachment.h +++ b/spine-cpp/spine-cpp/include/spine/ClippingAttachment.h @@ -33,8 +33,7 @@ #include -namespace Spine -{ +namespace Spine { class SlotData; class ClippingAttachment : public VertexAttachment { diff --git a/spine-cpp/spine-cpp/include/spine/ColorTimeline.h b/spine-cpp/spine-cpp/include/spine/ColorTimeline.h index 03295baff..14b74a5b0 100644 --- a/spine-cpp/spine-cpp/include/spine/ColorTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/ColorTimeline.h @@ -33,8 +33,7 @@ #include -namespace Spine -{ +namespace Spine { class ColorTimeline : public CurveTimeline { friend class SkeletonBinary; friend class SkeletonJson; diff --git a/spine-cpp/spine-cpp/include/spine/Constraint.h b/spine-cpp/spine-cpp/include/spine/Constraint.h index ced362987..4979d7602 100644 --- a/spine-cpp/spine-cpp/include/spine/Constraint.h +++ b/spine-cpp/spine-cpp/include/spine/Constraint.h @@ -33,8 +33,7 @@ #include -namespace Spine -{ +namespace Spine { /// The interface for all constraints. class Constraint : public Updatable { RTTI_DECL; diff --git a/spine-cpp/spine-cpp/include/spine/ContainerUtil.h b/spine-cpp/spine-cpp/include/spine/ContainerUtil.h index c44c18817..3e764aeb3 100644 --- a/spine-cpp/spine-cpp/include/spine/ContainerUtil.h +++ b/spine-cpp/spine-cpp/include/spine/ContainerUtil.h @@ -38,8 +38,7 @@ #include #include -namespace Spine -{ +namespace Spine { class ContainerUtil { public: /// Finds an item by comparing each item's name. diff --git a/spine-cpp/spine-cpp/include/spine/CurveTimeline.h b/spine-cpp/spine-cpp/include/spine/CurveTimeline.h index 286d53c4a..7df660410 100644 --- a/spine-cpp/spine-cpp/include/spine/CurveTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/CurveTimeline.h @@ -36,8 +36,7 @@ #include -namespace Spine -{ +namespace Spine { /// Base class for frames that use an interpolation bezier curve. class CurveTimeline : public Timeline { RTTI_DECL; diff --git a/spine-cpp/spine-cpp/include/spine/DeformTimeline.h b/spine-cpp/spine-cpp/include/spine/DeformTimeline.h index 7510ce509..031c420f3 100644 --- a/spine-cpp/spine-cpp/include/spine/DeformTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/DeformTimeline.h @@ -33,8 +33,7 @@ #include -namespace Spine -{ +namespace Spine { class VertexAttachment; class DeformTimeline : public CurveTimeline { diff --git a/spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h b/spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h index e11d74c0f..263336954 100644 --- a/spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/DrawOrderTimeline.h @@ -33,8 +33,7 @@ #include -namespace Spine -{ +namespace Spine { class DrawOrderTimeline : public Timeline { friend class SkeletonBinary; friend class SkeletonJson; diff --git a/spine-cpp/spine-cpp/include/spine/Event.h b/spine-cpp/spine-cpp/include/spine/Event.h index 9956d9030..179c74028 100644 --- a/spine-cpp/spine-cpp/include/spine/Event.h +++ b/spine-cpp/spine-cpp/include/spine/Event.h @@ -33,8 +33,7 @@ #include -namespace Spine -{ +namespace Spine { class EventData; /// Stores the current pose values for an Event. diff --git a/spine-cpp/spine-cpp/include/spine/EventData.h b/spine-cpp/spine-cpp/include/spine/EventData.h index dcb0c774c..691c5acbf 100644 --- a/spine-cpp/spine-cpp/include/spine/EventData.h +++ b/spine-cpp/spine-cpp/include/spine/EventData.h @@ -33,8 +33,7 @@ #include -namespace Spine -{ +namespace Spine { /// Stores the setup pose values for an Event. class EventData { friend class SkeletonBinary; diff --git a/spine-cpp/spine-cpp/include/spine/EventTimeline.h b/spine-cpp/spine-cpp/include/spine/EventTimeline.h index f474e637b..51f290529 100644 --- a/spine-cpp/spine-cpp/include/spine/EventTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/EventTimeline.h @@ -33,8 +33,7 @@ #include -namespace Spine -{ +namespace Spine { class EventTimeline : public Timeline { friend class SkeletonBinary; friend class SkeletonJson; diff --git a/spine-cpp/spine-cpp/include/spine/Extension.h b/spine-cpp/spine-cpp/include/spine/Extension.h index 0a9379308..752d445e0 100644 --- a/spine-cpp/spine-cpp/include/spine/Extension.h +++ b/spine-cpp/spine-cpp/include/spine/Extension.h @@ -47,8 +47,7 @@ /* Call destructor and then frees memory. Can be used on const types. */ #define DESTROY(TYPE,VALUE) VALUE->~TYPE(); SPINE_EXTENSION->spineFree((void*)VALUE) -namespace Spine -{ +namespace Spine { class SpineExtension { public: static void setInstance(SpineExtension* inSpineExtension); diff --git a/spine-cpp/spine-cpp/include/spine/HashMap.h b/spine-cpp/spine-cpp/include/spine/HashMap.h index e32cf4e30..07a9b2ef3 100755 --- a/spine-cpp/spine-cpp/include/spine/HashMap.h +++ b/spine-cpp/spine-cpp/include/spine/HashMap.h @@ -34,8 +34,7 @@ #include #include -namespace Spine -{ +namespace Spine { template class HashMap { private: diff --git a/spine-cpp/spine-cpp/include/spine/IkConstraint.h b/spine-cpp/spine-cpp/include/spine/IkConstraint.h index dbaf59786..528ebf45a 100644 --- a/spine-cpp/spine-cpp/include/spine/IkConstraint.h +++ b/spine-cpp/spine-cpp/include/spine/IkConstraint.h @@ -35,8 +35,7 @@ #include -namespace Spine -{ +namespace Spine { class IkConstraintData; class Skeleton; class Bone; diff --git a/spine-cpp/spine-cpp/include/spine/IkConstraintData.h b/spine-cpp/spine-cpp/include/spine/IkConstraintData.h index 286bcddb2..119563d2a 100644 --- a/spine-cpp/spine-cpp/include/spine/IkConstraintData.h +++ b/spine-cpp/spine-cpp/include/spine/IkConstraintData.h @@ -35,8 +35,7 @@ #include -namespace Spine -{ +namespace Spine { class BoneData; class IkConstraintData { diff --git a/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h b/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h index 957fd9178..bbc75df6b 100644 --- a/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/IkConstraintTimeline.h @@ -33,8 +33,7 @@ #include -namespace Spine -{ +namespace Spine { class IkConstraintTimeline : public CurveTimeline { friend class SkeletonBinary; friend class SkeletonJson; diff --git a/spine-cpp/spine-cpp/include/spine/Json.h b/spine-cpp/spine-cpp/include/spine/Json.h index df73ddd4d..083e22322 100644 --- a/spine-cpp/spine-cpp/include/spine/Json.h +++ b/spine-cpp/spine-cpp/include/spine/Json.h @@ -36,8 +36,7 @@ #define SPINE_JSON_HAVE_PREV 0 #endif -namespace Spine -{ +namespace Spine { class Json { friend class SkeletonJson; diff --git a/spine-cpp/spine-cpp/include/spine/LinkedMesh.h b/spine-cpp/spine-cpp/include/spine/LinkedMesh.h index 136c53bb8..f8fde0944 100644 --- a/spine-cpp/spine-cpp/include/spine/LinkedMesh.h +++ b/spine-cpp/spine-cpp/include/spine/LinkedMesh.h @@ -33,8 +33,7 @@ #include -namespace Spine -{ +namespace Spine { class MeshAttachment; class LinkedMesh { diff --git a/spine-cpp/spine-cpp/include/spine/MathUtil.h b/spine-cpp/spine-cpp/include/spine/MathUtil.h index cbd31b755..cd7d32f42 100644 --- a/spine-cpp/spine-cpp/include/spine/MathUtil.h +++ b/spine-cpp/spine-cpp/include/spine/MathUtil.h @@ -48,8 +48,7 @@ #define MAX(a, b) (((a) > (b)) ? (a) : (b)) #define MIN(a, b) (((a) < (b)) ? (a) : (b)) -namespace Spine -{ +namespace Spine { template int sign(T val) { return (T(0) < val) - (val < T(0)); diff --git a/spine-cpp/spine-cpp/include/spine/MeshAttachment.h b/spine-cpp/spine-cpp/include/spine/MeshAttachment.h index 7c73488f8..101f6dcf9 100644 --- a/spine-cpp/spine-cpp/include/spine/MeshAttachment.h +++ b/spine-cpp/spine-cpp/include/spine/MeshAttachment.h @@ -37,8 +37,7 @@ #include -namespace Spine -{ +namespace Spine { /// Attachment that displays a texture region using a mesh. class MeshAttachment : public VertexAttachment { friend class SkeletonBinary; diff --git a/spine-cpp/spine-cpp/include/spine/MixDirection.h b/spine-cpp/spine-cpp/include/spine/MixDirection.h index 3dd096ea7..68f937a8b 100644 --- a/spine-cpp/spine-cpp/include/spine/MixDirection.h +++ b/spine-cpp/spine-cpp/include/spine/MixDirection.h @@ -31,8 +31,7 @@ #ifndef Spine_MixDirection_h #define Spine_MixDirection_h -namespace Spine -{ +namespace Spine { /// /// Indicates whether a timeline's alpha is mixing out over time toward 0 (the setup or current pose) or mixing in toward 1 (the timeline's pose). /// See also Timeline::apply(Skeleton&, float, float, Vector&, float, MixPose, MixDirection) diff --git a/spine-cpp/spine-cpp/include/spine/MixPose.h b/spine-cpp/spine-cpp/include/spine/MixPose.h index b9aeec4ae..7156a8fdc 100644 --- a/spine-cpp/spine-cpp/include/spine/MixPose.h +++ b/spine-cpp/spine-cpp/include/spine/MixPose.h @@ -31,8 +31,7 @@ #ifndef Spine_MixPose_h #define Spine_MixPose_h -namespace Spine -{ +namespace Spine { /// /// Controls how a timeline is mixed with the setup or current pose. /// See also Timeline::apply(Skeleton&, float, float, Vector&, float, MixPose, MixDirection) diff --git a/spine-cpp/spine-cpp/include/spine/PathAttachment.h b/spine-cpp/spine-cpp/include/spine/PathAttachment.h index f5abcc32c..4463f1d01 100644 --- a/spine-cpp/spine-cpp/include/spine/PathAttachment.h +++ b/spine-cpp/spine-cpp/include/spine/PathAttachment.h @@ -33,8 +33,7 @@ #include -namespace Spine -{ +namespace Spine { class PathAttachment : public VertexAttachment { friend class SkeletonBinary; friend class SkeletonJson; diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraint.h b/spine-cpp/spine-cpp/include/spine/PathConstraint.h index 2daa91ebb..abb073a82 100644 --- a/spine-cpp/spine-cpp/include/spine/PathConstraint.h +++ b/spine-cpp/spine-cpp/include/spine/PathConstraint.h @@ -35,8 +35,7 @@ #include -namespace Spine -{ +namespace Spine { class PathConstraintData; class Skeleton; class PathAttachment; diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraintData.h b/spine-cpp/spine-cpp/include/spine/PathConstraintData.h index 68991f8c8..c4e3812e5 100644 --- a/spine-cpp/spine-cpp/include/spine/PathConstraintData.h +++ b/spine-cpp/spine-cpp/include/spine/PathConstraintData.h @@ -38,8 +38,7 @@ #include -namespace Spine -{ +namespace Spine { class BoneData; class SlotData; diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h b/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h index 7e64ac85d..5e93c1235 100644 --- a/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/PathConstraintMixTimeline.h @@ -33,8 +33,7 @@ #include -namespace Spine -{ +namespace Spine { class PathConstraintMixTimeline : public CurveTimeline { friend class SkeletonBinary; friend class SkeletonJson; diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h b/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h index 172a897a7..fb4d222e1 100644 --- a/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/PathConstraintPositionTimeline.h @@ -33,8 +33,7 @@ #include -namespace Spine -{ +namespace Spine { class PathConstraintPositionTimeline : public CurveTimeline { friend class SkeletonBinary; friend class SkeletonJson; diff --git a/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h b/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h index c30394f79..ca723f907 100644 --- a/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/PathConstraintSpacingTimeline.h @@ -33,8 +33,7 @@ #include -namespace Spine -{ +namespace Spine { class PathConstraintSpacingTimeline : public PathConstraintPositionTimeline { friend class SkeletonBinary; friend class SkeletonJson; diff --git a/spine-cpp/spine-cpp/include/spine/PointAttachment.h b/spine-cpp/spine-cpp/include/spine/PointAttachment.h index f1f5f0b1d..eba6a0f8d 100644 --- a/spine-cpp/spine-cpp/include/spine/PointAttachment.h +++ b/spine-cpp/spine-cpp/include/spine/PointAttachment.h @@ -33,8 +33,7 @@ #include -namespace Spine -{ +namespace Spine { class Bone; /// diff --git a/spine-cpp/spine-cpp/include/spine/Pool.h b/spine-cpp/spine-cpp/include/spine/Pool.h index 29a447a13..18f17a6e9 100644 --- a/spine-cpp/spine-cpp/include/spine/Pool.h +++ b/spine-cpp/spine-cpp/include/spine/Pool.h @@ -35,8 +35,7 @@ #include #include -namespace Spine -{ +namespace Spine { template class Pool { public: diff --git a/spine-cpp/spine-cpp/include/spine/PositionMode.h b/spine-cpp/spine-cpp/include/spine/PositionMode.h index c5ad9bdfc..c46d3002d 100644 --- a/spine-cpp/spine-cpp/include/spine/PositionMode.h +++ b/spine-cpp/spine-cpp/include/spine/PositionMode.h @@ -31,8 +31,7 @@ #ifndef Spine_PositionMode_h #define Spine_PositionMode_h -namespace Spine -{ +namespace Spine { enum PositionMode { PositionMode_Fixed = 0, PositionMode_Percent diff --git a/spine-cpp/spine-cpp/include/spine/RTTI.h b/spine-cpp/spine-cpp/include/spine/RTTI.h index 362c3548a..73db676cc 100644 --- a/spine-cpp/spine-cpp/include/spine/RTTI.h +++ b/spine-cpp/spine-cpp/include/spine/RTTI.h @@ -33,8 +33,7 @@ #include -namespace Spine -{ +namespace Spine { class RTTI { public: RTTI(const std::string& className); diff --git a/spine-cpp/spine-cpp/include/spine/RegionAttachment.h b/spine-cpp/spine-cpp/include/spine/RegionAttachment.h index acdb6a870..e23ea4986 100644 --- a/spine-cpp/spine-cpp/include/spine/RegionAttachment.h +++ b/spine-cpp/spine-cpp/include/spine/RegionAttachment.h @@ -39,8 +39,7 @@ #define NUM_UVS 8 -namespace Spine -{ +namespace Spine { class Bone; /// Attachment that displays a texture region. diff --git a/spine-cpp/spine-cpp/include/spine/RotateMode.h b/spine-cpp/spine-cpp/include/spine/RotateMode.h index 3c5cbe789..f7dfab14d 100644 --- a/spine-cpp/spine-cpp/include/spine/RotateMode.h +++ b/spine-cpp/spine-cpp/include/spine/RotateMode.h @@ -31,8 +31,7 @@ #ifndef Spine_RotateMode_h #define Spine_RotateMode_h -namespace Spine -{ +namespace Spine { enum RotateMode { RotateMode_Tangent = 0, RotateMode_Chain, diff --git a/spine-cpp/spine-cpp/include/spine/RotateTimeline.h b/spine-cpp/spine-cpp/include/spine/RotateTimeline.h index 778fd9a15..558f5a96b 100644 --- a/spine-cpp/spine-cpp/include/spine/RotateTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/RotateTimeline.h @@ -33,8 +33,7 @@ #include -namespace Spine -{ +namespace Spine { class RotateTimeline : public CurveTimeline { friend class SkeletonBinary; friend class SkeletonJson; diff --git a/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h b/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h index f02c40afa..32f434287 100644 --- a/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/ScaleTimeline.h @@ -33,8 +33,7 @@ #include -namespace Spine -{ +namespace Spine { class ScaleTimeline : public TranslateTimeline { friend class SkeletonBinary; friend class SkeletonJson; diff --git a/spine-cpp/spine-cpp/include/spine/ShearTimeline.h b/spine-cpp/spine-cpp/include/spine/ShearTimeline.h index a42e2ec45..fa687e15d 100644 --- a/spine-cpp/spine-cpp/include/spine/ShearTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/ShearTimeline.h @@ -33,8 +33,7 @@ #include -namespace Spine -{ +namespace Spine { class ShearTimeline : public TranslateTimeline { friend class SkeletonBinary; friend class SkeletonJson; diff --git a/spine-cpp/spine-cpp/include/spine/Skeleton.h b/spine-cpp/spine-cpp/include/spine/Skeleton.h index c6f9564f3..8efd439a3 100644 --- a/spine-cpp/spine-cpp/include/spine/Skeleton.h +++ b/spine-cpp/spine-cpp/include/spine/Skeleton.h @@ -37,8 +37,7 @@ #include #include // std::numeric_limits -namespace Spine -{ +namespace Spine { class SkeletonData; class Bone; class Updatable; diff --git a/spine-cpp/spine-cpp/include/spine/SkeletonBinary.h b/spine-cpp/spine-cpp/include/spine/SkeletonBinary.h index 96c970019..17749fca4 100644 --- a/spine-cpp/spine-cpp/include/spine/SkeletonBinary.h +++ b/spine-cpp/spine-cpp/include/spine/SkeletonBinary.h @@ -36,8 +36,7 @@ #include -namespace Spine -{ +namespace Spine { class SkeletonData; class Atlas; class AttachmentLoader; diff --git a/spine-cpp/spine-cpp/include/spine/SkeletonBounds.h b/spine-cpp/spine-cpp/include/spine/SkeletonBounds.h index c000cbe44..983600835 100644 --- a/spine-cpp/spine-cpp/include/spine/SkeletonBounds.h +++ b/spine-cpp/spine-cpp/include/spine/SkeletonBounds.h @@ -33,8 +33,7 @@ #include -namespace Spine -{ +namespace Spine { class Skeleton; class BoundingBoxAttachment; diff --git a/spine-cpp/spine-cpp/include/spine/SkeletonClipping.h b/spine-cpp/spine-cpp/include/spine/SkeletonClipping.h index 19baa4746..6d5667517 100644 --- a/spine-cpp/spine-cpp/include/spine/SkeletonClipping.h +++ b/spine-cpp/spine-cpp/include/spine/SkeletonClipping.h @@ -34,8 +34,7 @@ #include #include -namespace Spine -{ +namespace Spine { class Slot; class ClippingAttachment; diff --git a/spine-cpp/spine-cpp/include/spine/SkeletonData.h b/spine-cpp/spine-cpp/include/spine/SkeletonData.h index 04e195a8c..53065ade0 100644 --- a/spine-cpp/spine-cpp/include/spine/SkeletonData.h +++ b/spine-cpp/spine-cpp/include/spine/SkeletonData.h @@ -35,8 +35,7 @@ #include -namespace Spine -{ +namespace Spine { class BoneData; class SlotData; class Skin; diff --git a/spine-cpp/spine-cpp/include/spine/SkeletonJson.h b/spine-cpp/spine-cpp/include/spine/SkeletonJson.h index 6c0ea928b..ef40a7a83 100644 --- a/spine-cpp/spine-cpp/include/spine/SkeletonJson.h +++ b/spine-cpp/spine-cpp/include/spine/SkeletonJson.h @@ -35,8 +35,7 @@ #include -namespace Spine -{ +namespace Spine { class CurveTimeline; class VertexAttachment; class Animation; diff --git a/spine-cpp/spine-cpp/include/spine/Skin.h b/spine-cpp/spine-cpp/include/spine/Skin.h index 8836b692e..5756b65d3 100644 --- a/spine-cpp/spine-cpp/include/spine/Skin.h +++ b/spine-cpp/spine-cpp/include/spine/Skin.h @@ -35,8 +35,7 @@ #include #include -namespace Spine -{ +namespace Spine { class Attachment; class Skeleton; diff --git a/spine-cpp/spine-cpp/include/spine/Slot.h b/spine-cpp/spine-cpp/include/spine/Slot.h index c85713a5c..69f7f6666 100644 --- a/spine-cpp/spine-cpp/include/spine/Slot.h +++ b/spine-cpp/spine-cpp/include/spine/Slot.h @@ -35,8 +35,7 @@ #include -namespace Spine -{ +namespace Spine { class SlotData; class Bone; class Skeleton; diff --git a/spine-cpp/spine-cpp/include/spine/SlotData.h b/spine-cpp/spine-cpp/include/spine/SlotData.h index 444195aa6..6e422e534 100644 --- a/spine-cpp/spine-cpp/include/spine/SlotData.h +++ b/spine-cpp/spine-cpp/include/spine/SlotData.h @@ -35,8 +35,7 @@ #include -namespace Spine -{ +namespace Spine { class BoneData; class SlotData { diff --git a/spine-cpp/spine-cpp/include/spine/SpacingMode.h b/spine-cpp/spine-cpp/include/spine/SpacingMode.h index e3b52dd07..b8bf965af 100644 --- a/spine-cpp/spine-cpp/include/spine/SpacingMode.h +++ b/spine-cpp/spine-cpp/include/spine/SpacingMode.h @@ -31,8 +31,7 @@ #ifndef Spine_SpacingMode_h #define Spine_SpacingMode_h -namespace Spine -{ +namespace Spine { enum SpacingMode { SpacingMode_Length = 0, SpacingMode_Fixed, diff --git a/spine-cpp/spine-cpp/include/spine/TextureLoader.h b/spine-cpp/spine-cpp/include/spine/TextureLoader.h index 5502922f7..f0b836910 100644 --- a/spine-cpp/spine-cpp/include/spine/TextureLoader.h +++ b/spine-cpp/spine-cpp/include/spine/TextureLoader.h @@ -33,8 +33,7 @@ #include -namespace Spine -{ +namespace Spine { class AtlasPage; class TextureLoader { diff --git a/spine-cpp/spine-cpp/include/spine/Timeline.h b/spine-cpp/spine-cpp/include/spine/Timeline.h index 0e1e0e3fe..d23a36753 100644 --- a/spine-cpp/spine-cpp/include/spine/Timeline.h +++ b/spine-cpp/spine-cpp/include/spine/Timeline.h @@ -36,8 +36,7 @@ #include #include -namespace Spine -{ +namespace Spine { class Skeleton; class Event; diff --git a/spine-cpp/spine-cpp/include/spine/TimelineType.h b/spine-cpp/spine-cpp/include/spine/TimelineType.h index f055fb599..518c2ce63 100644 --- a/spine-cpp/spine-cpp/include/spine/TimelineType.h +++ b/spine-cpp/spine-cpp/include/spine/TimelineType.h @@ -31,8 +31,7 @@ #ifndef Spine_TimelineType_h #define Spine_TimelineType_h -namespace Spine -{ +namespace Spine { enum TimelineType { TimelineType_Rotate = 0, TimelineType_Translate, diff --git a/spine-cpp/spine-cpp/include/spine/TransformConstraint.h b/spine-cpp/spine-cpp/include/spine/TransformConstraint.h index ad837b54d..b878c0f4c 100644 --- a/spine-cpp/spine-cpp/include/spine/TransformConstraint.h +++ b/spine-cpp/spine-cpp/include/spine/TransformConstraint.h @@ -35,8 +35,7 @@ #include -namespace Spine -{ +namespace Spine { class TransformConstraintData; class Skeleton; class Bone; diff --git a/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h b/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h index c12cb40c6..090675a31 100644 --- a/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h +++ b/spine-cpp/spine-cpp/include/spine/TransformConstraintData.h @@ -35,8 +35,7 @@ #include -namespace Spine -{ +namespace Spine { class BoneData; class TransformConstraintData { diff --git a/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h b/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h index ddefa6f20..f117bbf82 100644 --- a/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/TransformConstraintTimeline.h @@ -33,8 +33,7 @@ #include -namespace Spine -{ +namespace Spine { class TransformConstraintTimeline : public CurveTimeline { friend class SkeletonBinary; friend class SkeletonJson; diff --git a/spine-cpp/spine-cpp/include/spine/TransformMode.h b/spine-cpp/spine-cpp/include/spine/TransformMode.h index 8b9c6df53..d3cb2b7f9 100644 --- a/spine-cpp/spine-cpp/include/spine/TransformMode.h +++ b/spine-cpp/spine-cpp/include/spine/TransformMode.h @@ -31,8 +31,7 @@ #ifndef Spine_TransformMode_h #define Spine_TransformMode_h -namespace Spine -{ +namespace Spine { enum TransformMode { //0000 0 Flip Scale Rotation TransformMode_Normal = 0, // 0000 diff --git a/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h b/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h index d5014894d..ae1f209d7 100644 --- a/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/TranslateTimeline.h @@ -36,8 +36,7 @@ #include #include -namespace Spine -{ +namespace Spine { class TranslateTimeline : public CurveTimeline { friend class SkeletonBinary; friend class SkeletonJson; diff --git a/spine-cpp/spine-cpp/include/spine/Triangulator.h b/spine-cpp/spine-cpp/include/spine/Triangulator.h index 8e43659ea..d5fff1994 100644 --- a/spine-cpp/spine-cpp/include/spine/Triangulator.h +++ b/spine-cpp/spine-cpp/include/spine/Triangulator.h @@ -34,8 +34,7 @@ #include #include -namespace Spine -{ +namespace Spine { class Triangulator { public: Vector& triangulate(Vector& vertices); diff --git a/spine-cpp/spine-cpp/include/spine/TwoColorTimeline.h b/spine-cpp/spine-cpp/include/spine/TwoColorTimeline.h index 0f8aee052..34977c3ec 100644 --- a/spine-cpp/spine-cpp/include/spine/TwoColorTimeline.h +++ b/spine-cpp/spine-cpp/include/spine/TwoColorTimeline.h @@ -33,8 +33,7 @@ #include -namespace Spine -{ +namespace Spine { class TwoColorTimeline : public CurveTimeline { friend class SkeletonBinary; friend class SkeletonJson; diff --git a/spine-cpp/spine-cpp/include/spine/Updatable.h b/spine-cpp/spine-cpp/include/spine/Updatable.h index 8bf9df75c..d076e0439 100644 --- a/spine-cpp/spine-cpp/include/spine/Updatable.h +++ b/spine-cpp/spine-cpp/include/spine/Updatable.h @@ -33,8 +33,7 @@ #include -namespace Spine -{ +namespace Spine { class Updatable { RTTI_DECL; diff --git a/spine-cpp/spine-cpp/include/spine/Vector.h b/spine-cpp/spine-cpp/include/spine/Vector.h index 5272122b5..6fad04736 100644 --- a/spine-cpp/spine-cpp/include/spine/Vector.h +++ b/spine-cpp/spine-cpp/include/spine/Vector.h @@ -37,8 +37,7 @@ #include #include -namespace Spine -{ +namespace Spine { template class Vector { public: diff --git a/spine-cpp/spine-cpp/include/spine/VertexAttachment.h b/spine-cpp/spine-cpp/include/spine/VertexAttachment.h index a60031dd8..4385886f5 100644 --- a/spine-cpp/spine-cpp/include/spine/VertexAttachment.h +++ b/spine-cpp/spine-cpp/include/spine/VertexAttachment.h @@ -35,8 +35,7 @@ #include -namespace Spine -{ +namespace Spine { class Slot; /// An attachment with vertices that are transformed by one or more bones and can be deformed by a slot's vertices. diff --git a/spine-cpp/spine-cpp/include/spine/Vertices.h b/spine-cpp/spine-cpp/include/spine/Vertices.h index f8ba613b7..0dff1321d 100644 --- a/spine-cpp/spine-cpp/include/spine/Vertices.h +++ b/spine-cpp/spine-cpp/include/spine/Vertices.h @@ -33,8 +33,7 @@ #include -namespace Spine -{ +namespace Spine { class Vertices { public: Vector _bones; diff --git a/spine-cpp/spine-cpp/src/spine/Animation.cpp b/spine-cpp/spine-cpp/src/spine/Animation.cpp index b18b502f2..3b25f5b95 100644 --- a/spine-cpp/spine-cpp/src/spine/Animation.cpp +++ b/spine-cpp/spine-cpp/src/spine/Animation.cpp @@ -39,8 +39,7 @@ #include #include /* fmod */ -namespace Spine -{ +namespace Spine { Animation::Animation(std::string name, Vector& timelines, float duration) : _timelines(timelines), _duration(duration), diff --git a/spine-cpp/spine-cpp/src/spine/AnimationState.cpp b/spine-cpp/spine-cpp/src/spine/AnimationState.cpp index 9650053b6..f11649d6b 100644 --- a/spine-cpp/spine-cpp/src/spine/AnimationState.cpp +++ b/spine-cpp/spine-cpp/src/spine/AnimationState.cpp @@ -46,8 +46,7 @@ #include #include -namespace Spine -{ +namespace Spine { void dummyOnAnimationEventFunc(AnimationState* state, EventType type, TrackEntry* entry, Event* event = NULL) { // Empty } diff --git a/spine-cpp/spine-cpp/src/spine/AnimationStateData.cpp b/spine-cpp/spine-cpp/src/spine/AnimationStateData.cpp index 3f1e9e173..5edb8b934 100644 --- a/spine-cpp/spine-cpp/src/spine/AnimationStateData.cpp +++ b/spine-cpp/spine-cpp/src/spine/AnimationStateData.cpp @@ -33,8 +33,7 @@ #include #include -namespace Spine -{ +namespace Spine { AnimationStateData::AnimationStateData(SkeletonData& skeletonData) : _skeletonData(skeletonData), _defaultMix(0) { // Empty } diff --git a/spine-cpp/spine-cpp/src/spine/Atlas.cpp b/spine-cpp/spine-cpp/src/spine/Atlas.cpp index 5c41d1918..01ddc728d 100644 --- a/spine-cpp/spine-cpp/src/spine/Atlas.cpp +++ b/spine-cpp/spine-cpp/src/spine/Atlas.cpp @@ -36,8 +36,7 @@ #include -namespace Spine -{ +namespace Spine { Atlas::Atlas(const char* path, TextureLoader& textureLoader) : _textureLoader(textureLoader) { int dirLength; char *dir; diff --git a/spine-cpp/spine-cpp/src/spine/AtlasAttachmentLoader.cpp b/spine-cpp/spine-cpp/src/spine/AtlasAttachmentLoader.cpp index 4509a071c..ada9bde71 100644 --- a/spine-cpp/spine-cpp/src/spine/AtlasAttachmentLoader.cpp +++ b/spine-cpp/spine-cpp/src/spine/AtlasAttachmentLoader.cpp @@ -40,8 +40,7 @@ #include -namespace Spine -{ +namespace Spine { RTTI_IMPL(AtlasAttachmentLoader, AttachmentLoader); AtlasAttachmentLoader::AtlasAttachmentLoader(Vector& inAtlasArray) : AttachmentLoader(), _atlasArray(inAtlasArray) { diff --git a/spine-cpp/spine-cpp/src/spine/Attachment.cpp b/spine-cpp/spine-cpp/src/spine/Attachment.cpp index b977277a0..779be06a6 100644 --- a/spine-cpp/spine-cpp/src/spine/Attachment.cpp +++ b/spine-cpp/spine-cpp/src/spine/Attachment.cpp @@ -32,8 +32,7 @@ #include -namespace Spine -{ +namespace Spine { RTTI_IMPL_NOPARENT(Attachment); Attachment::Attachment(std::string name) : _name(name) { diff --git a/spine-cpp/spine-cpp/src/spine/AttachmentLoader.cpp b/spine-cpp/spine-cpp/src/spine/AttachmentLoader.cpp index b6ab71714..5d166a05c 100644 --- a/spine-cpp/spine-cpp/src/spine/AttachmentLoader.cpp +++ b/spine-cpp/spine-cpp/src/spine/AttachmentLoader.cpp @@ -38,8 +38,7 @@ #include #include -namespace Spine -{ +namespace Spine { RTTI_IMPL_NOPARENT(AttachmentLoader); AttachmentLoader::AttachmentLoader() { diff --git a/spine-cpp/spine-cpp/src/spine/AttachmentTimeline.cpp b/spine-cpp/spine-cpp/src/spine/AttachmentTimeline.cpp index f6a68c62c..7c417a7c8 100644 --- a/spine-cpp/spine-cpp/src/spine/AttachmentTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/AttachmentTimeline.cpp @@ -38,8 +38,7 @@ #include #include -namespace Spine -{ +namespace Spine { RTTI_IMPL(AttachmentTimeline, Timeline); AttachmentTimeline::AttachmentTimeline(int frameCount) : Timeline(), _slotIndex(0) { diff --git a/spine-cpp/spine-cpp/src/spine/Bone.cpp b/spine-cpp/spine-cpp/src/spine/Bone.cpp index 1b4db4928..184b1c0e1 100644 --- a/spine-cpp/spine-cpp/src/spine/Bone.cpp +++ b/spine-cpp/spine-cpp/src/spine/Bone.cpp @@ -36,8 +36,7 @@ #include #include -namespace Spine -{ +namespace Spine { RTTI_IMPL(Bone, Updatable); bool Bone::yDown = false; diff --git a/spine-cpp/spine-cpp/src/spine/BoneData.cpp b/spine-cpp/spine-cpp/src/spine/BoneData.cpp index 2e5ac3fbd..f0cbb9502 100644 --- a/spine-cpp/spine-cpp/src/spine/BoneData.cpp +++ b/spine-cpp/spine-cpp/src/spine/BoneData.cpp @@ -32,8 +32,7 @@ #include -namespace Spine -{ +namespace Spine { BoneData::BoneData(int index, std::string name, BoneData* parent) : _index(index), _name(name), diff --git a/spine-cpp/spine-cpp/src/spine/BoundingBoxAttachment.cpp b/spine-cpp/spine-cpp/src/spine/BoundingBoxAttachment.cpp index 02d662233..41148ae80 100644 --- a/spine-cpp/spine-cpp/src/spine/BoundingBoxAttachment.cpp +++ b/spine-cpp/spine-cpp/src/spine/BoundingBoxAttachment.cpp @@ -30,8 +30,7 @@ #include -namespace Spine -{ +namespace Spine { RTTI_IMPL(BoundingBoxAttachment, VertexAttachment); BoundingBoxAttachment::BoundingBoxAttachment(std::string name) : VertexAttachment(name) { diff --git a/spine-cpp/spine-cpp/src/spine/ClippingAttachment.cpp b/spine-cpp/spine-cpp/src/spine/ClippingAttachment.cpp index 3c8efc3b5..644ba9c39 100644 --- a/spine-cpp/spine-cpp/src/spine/ClippingAttachment.cpp +++ b/spine-cpp/spine-cpp/src/spine/ClippingAttachment.cpp @@ -32,8 +32,7 @@ #include -namespace Spine -{ +namespace Spine { RTTI_IMPL(ClippingAttachment, VertexAttachment); ClippingAttachment::ClippingAttachment(std::string name) : VertexAttachment(name), _endSlot(NULL) { diff --git a/spine-cpp/spine-cpp/src/spine/ColorTimeline.cpp b/spine-cpp/spine-cpp/src/spine/ColorTimeline.cpp index 4c6bea7a4..7f2085829 100644 --- a/spine-cpp/spine-cpp/src/spine/ColorTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/ColorTimeline.cpp @@ -38,8 +38,7 @@ #include #include -namespace Spine -{ +namespace Spine { RTTI_IMPL(ColorTimeline, CurveTimeline); const int ColorTimeline::ENTRIES = 5; diff --git a/spine-cpp/spine-cpp/src/spine/Constraint.cpp b/spine-cpp/spine-cpp/src/spine/Constraint.cpp index 85618372b..4f1a797cd 100644 --- a/spine-cpp/spine-cpp/src/spine/Constraint.cpp +++ b/spine-cpp/spine-cpp/src/spine/Constraint.cpp @@ -30,8 +30,7 @@ #include -namespace Spine -{ +namespace Spine { RTTI_IMPL(Constraint, Updatable); Constraint::Constraint() { diff --git a/spine-cpp/spine-cpp/src/spine/CurveTimeline.cpp b/spine-cpp/spine-cpp/src/spine/CurveTimeline.cpp index 88b25e375..63571800d 100644 --- a/spine-cpp/spine-cpp/src/spine/CurveTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/CurveTimeline.cpp @@ -32,8 +32,7 @@ #include -namespace Spine -{ +namespace Spine { RTTI_IMPL(CurveTimeline, Timeline); const float CurveTimeline::LINEAR = 0; diff --git a/spine-cpp/spine-cpp/src/spine/DeformTimeline.cpp b/spine-cpp/spine-cpp/src/spine/DeformTimeline.cpp index bede7342e..a9941702e 100644 --- a/spine-cpp/spine-cpp/src/spine/DeformTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/DeformTimeline.cpp @@ -40,8 +40,7 @@ #include #include -namespace Spine -{ +namespace Spine { RTTI_IMPL(DeformTimeline, CurveTimeline); DeformTimeline::DeformTimeline(int frameCount) : CurveTimeline(frameCount), _slotIndex(0), _attachment(NULL) { diff --git a/spine-cpp/spine-cpp/src/spine/DrawOrderTimeline.cpp b/spine-cpp/spine-cpp/src/spine/DrawOrderTimeline.cpp index 83ad3259a..079cbcbca 100644 --- a/spine-cpp/spine-cpp/src/spine/DrawOrderTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/DrawOrderTimeline.cpp @@ -38,8 +38,7 @@ #include #include -namespace Spine -{ +namespace Spine { RTTI_IMPL(DrawOrderTimeline, Timeline); DrawOrderTimeline::DrawOrderTimeline(int frameCount) : Timeline() { diff --git a/spine-cpp/spine-cpp/src/spine/Event.cpp b/spine-cpp/spine-cpp/src/spine/Event.cpp index 1bce25bdb..f5ef271d2 100644 --- a/spine-cpp/spine-cpp/src/spine/Event.cpp +++ b/spine-cpp/spine-cpp/src/spine/Event.cpp @@ -32,8 +32,7 @@ #include -namespace Spine -{ +namespace Spine { Event::Event(float time, const EventData& data) : _data(data), _time(time), diff --git a/spine-cpp/spine-cpp/src/spine/EventData.cpp b/spine-cpp/spine-cpp/src/spine/EventData.cpp index e6c95dc0b..1d390e459 100644 --- a/spine-cpp/spine-cpp/src/spine/EventData.cpp +++ b/spine-cpp/spine-cpp/src/spine/EventData.cpp @@ -32,8 +32,7 @@ #include -namespace Spine -{ +namespace Spine { EventData::EventData(std::string name) : _name(name), _intValue(0), diff --git a/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp b/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp index 66505930b..5fb00ccae 100644 --- a/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/EventTimeline.cpp @@ -40,8 +40,7 @@ #include #include -namespace Spine -{ +namespace Spine { RTTI_IMPL(EventTimeline, Timeline); EventTimeline::EventTimeline(int frameCount) : Timeline() { diff --git a/spine-cpp/spine-cpp/src/spine/Extension.cpp b/spine-cpp/spine-cpp/src/spine/Extension.cpp index 09ce5543d..4e1294cdb 100644 --- a/spine-cpp/spine-cpp/src/spine/Extension.cpp +++ b/spine-cpp/spine-cpp/src/spine/Extension.cpp @@ -34,8 +34,7 @@ #include #include -namespace Spine -{ +namespace Spine { SpineExtension* SpineExtension::_instance = NULL; void SpineExtension::setInstance(SpineExtension* inValue) { diff --git a/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp b/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp index 933eb9c62..13153d794 100644 --- a/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp +++ b/spine-cpp/spine-cpp/src/spine/IkConstraint.cpp @@ -37,8 +37,7 @@ #include #include -namespace Spine -{ +namespace Spine { RTTI_IMPL(IkConstraint, Constraint); void IkConstraint::apply(Bone& bone, float targetX, float targetY, float alpha) { diff --git a/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp b/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp index c06fcdccc..416d5cebe 100644 --- a/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp +++ b/spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp @@ -32,8 +32,7 @@ #include -namespace Spine -{ +namespace Spine { IkConstraintData::IkConstraintData(std::string name) : _name(name), _order(0), diff --git a/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp b/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp index e0bb67c07..6bcab4b74 100644 --- a/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/IkConstraintTimeline.cpp @@ -40,8 +40,7 @@ #include #include -namespace Spine -{ +namespace Spine { RTTI_IMPL(IkConstraintTimeline, CurveTimeline); const int IkConstraintTimeline::ENTRIES = 3; diff --git a/spine-cpp/spine-cpp/src/spine/Json.cpp b/spine-cpp/spine-cpp/src/spine/Json.cpp index 6e967e552..2a5494f00 100644 --- a/spine-cpp/spine-cpp/src/spine/Json.cpp +++ b/spine-cpp/spine-cpp/src/spine/Json.cpp @@ -52,8 +52,7 @@ #include #include -namespace Spine -{ +namespace Spine { const int Json::JSON_FALSE = 0; const int Json::JSON_TRUE = 1; const int Json::JSON_NULL = 2; diff --git a/spine-cpp/spine-cpp/src/spine/LinkedMesh.cpp b/spine-cpp/spine-cpp/src/spine/LinkedMesh.cpp index c4e5cdb6e..2cbfef3d5 100644 --- a/spine-cpp/spine-cpp/src/spine/LinkedMesh.cpp +++ b/spine-cpp/spine-cpp/src/spine/LinkedMesh.cpp @@ -32,8 +32,7 @@ #include -namespace Spine -{ +namespace Spine { LinkedMesh::LinkedMesh(MeshAttachment* mesh, std::string skin, int slotIndex, std::string parent) : _mesh(mesh), _skin(skin), diff --git a/spine-cpp/spine-cpp/src/spine/MathUtil.cpp b/spine-cpp/spine-cpp/src/spine/MathUtil.cpp index ac1b25b69..399365063 100644 --- a/spine-cpp/spine-cpp/src/spine/MathUtil.cpp +++ b/spine-cpp/spine-cpp/src/spine/MathUtil.cpp @@ -30,8 +30,7 @@ #include -namespace Spine -{ +namespace Spine { float MathUtil::SIN_TABLE[SIN_COUNT] = {0.0f}; MathUtil::MathUtil() { diff --git a/spine-cpp/spine-cpp/src/spine/MeshAttachment.cpp b/spine-cpp/spine-cpp/src/spine/MeshAttachment.cpp index 2c6c459a4..b6c5ff92a 100644 --- a/spine-cpp/spine-cpp/src/spine/MeshAttachment.cpp +++ b/spine-cpp/spine-cpp/src/spine/MeshAttachment.cpp @@ -30,8 +30,7 @@ #include -namespace Spine -{ +namespace Spine { RTTI_IMPL(MeshAttachment, VertexAttachment); MeshAttachment::MeshAttachment(std::string name) : VertexAttachment(name), diff --git a/spine-cpp/spine-cpp/src/spine/PathAttachment.cpp b/spine-cpp/spine-cpp/src/spine/PathAttachment.cpp index 866405ee2..4e5c93cfd 100644 --- a/spine-cpp/spine-cpp/src/spine/PathAttachment.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathAttachment.cpp @@ -30,8 +30,7 @@ #include -namespace Spine -{ +namespace Spine { RTTI_IMPL(PathAttachment, VertexAttachment); PathAttachment::PathAttachment(std::string name) : VertexAttachment(name), _closed(false), _constantSpeed(false) { diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp b/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp index 686886290..29a8882bf 100644 --- a/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathConstraint.cpp @@ -43,8 +43,7 @@ #include #include -namespace Spine -{ +namespace Spine { RTTI_IMPL(PathConstraint, Constraint); const float PathConstraint::EPSILON = 0.00001f; diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraintData.cpp b/spine-cpp/spine-cpp/src/spine/PathConstraintData.cpp index 380719527..caa545e3d 100644 --- a/spine-cpp/spine-cpp/src/spine/PathConstraintData.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathConstraintData.cpp @@ -35,8 +35,7 @@ #include -namespace Spine -{ +namespace Spine { PathConstraintData::PathConstraintData(std::string name) : _name(name), _order(0), diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp b/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp index 606d71b9e..556ef1f37 100644 --- a/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathConstraintMixTimeline.cpp @@ -40,8 +40,7 @@ #include #include -namespace Spine -{ +namespace Spine { RTTI_IMPL(PathConstraintMixTimeline, CurveTimeline); const int PathConstraintMixTimeline::ENTRIES = 3; diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp b/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp index ba0a63555..e5635d4dd 100644 --- a/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathConstraintPositionTimeline.cpp @@ -40,8 +40,7 @@ #include #include -namespace Spine -{ +namespace Spine { RTTI_IMPL(PathConstraintPositionTimeline, CurveTimeline); const int PathConstraintPositionTimeline::ENTRIES = 2; diff --git a/spine-cpp/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp b/spine-cpp/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp index f029a9e4a..23305353c 100644 --- a/spine-cpp/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/PathConstraintSpacingTimeline.cpp @@ -40,8 +40,7 @@ #include #include -namespace Spine -{ +namespace Spine { RTTI_IMPL(PathConstraintSpacingTimeline, PathConstraintPositionTimeline); PathConstraintSpacingTimeline::PathConstraintSpacingTimeline(int frameCount) : PathConstraintPositionTimeline(frameCount) { diff --git a/spine-cpp/spine-cpp/src/spine/PointAttachment.cpp b/spine-cpp/spine-cpp/src/spine/PointAttachment.cpp index 09c32d43c..d69338695 100644 --- a/spine-cpp/spine-cpp/src/spine/PointAttachment.cpp +++ b/spine-cpp/spine-cpp/src/spine/PointAttachment.cpp @@ -34,8 +34,7 @@ #include -namespace Spine -{ +namespace Spine { RTTI_IMPL(PointAttachment, Attachment); PointAttachment::PointAttachment(std::string name) : Attachment(name), _x(0), _y(0), _rotation(0) { diff --git a/spine-cpp/spine-cpp/src/spine/RTTI.cpp b/spine-cpp/spine-cpp/src/spine/RTTI.cpp index 8a734a898..db6898c25 100644 --- a/spine-cpp/spine-cpp/src/spine/RTTI.cpp +++ b/spine-cpp/spine-cpp/src/spine/RTTI.cpp @@ -30,8 +30,7 @@ #include -namespace Spine -{ +namespace Spine { RTTI::RTTI(const std::string& className) : m_className(className), m_pBaseRTTI(NULL) { // Empty } diff --git a/spine-cpp/spine-cpp/src/spine/RegionAttachment.cpp b/spine-cpp/spine-cpp/src/spine/RegionAttachment.cpp index b2e38ba79..8a83f28ea 100644 --- a/spine-cpp/spine-cpp/src/spine/RegionAttachment.cpp +++ b/spine-cpp/spine-cpp/src/spine/RegionAttachment.cpp @@ -36,8 +36,7 @@ #include -namespace Spine -{ +namespace Spine { RTTI_IMPL(RegionAttachment, Attachment); const int RegionAttachment::BLX = 0; diff --git a/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp b/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp index b17a406f7..cfc2866ef 100644 --- a/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/RotateTimeline.cpp @@ -38,8 +38,7 @@ #include #include -namespace Spine -{ +namespace Spine { RTTI_IMPL(RotateTimeline, CurveTimeline); RotateTimeline::RotateTimeline(int frameCount) : CurveTimeline(frameCount), _boneIndex(0) { diff --git a/spine-cpp/spine-cpp/src/spine/ScaleTimeline.cpp b/spine-cpp/spine-cpp/src/spine/ScaleTimeline.cpp index fe5ccc6fc..211a6fdba 100644 --- a/spine-cpp/spine-cpp/src/spine/ScaleTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/ScaleTimeline.cpp @@ -40,8 +40,7 @@ #include #include -namespace Spine -{ +namespace Spine { RTTI_IMPL(ScaleTimeline, TranslateTimeline); ScaleTimeline::ScaleTimeline(int frameCount) : TranslateTimeline(frameCount) { diff --git a/spine-cpp/spine-cpp/src/spine/ShearTimeline.cpp b/spine-cpp/spine-cpp/src/spine/ShearTimeline.cpp index 3cf98aefc..a4d433921 100644 --- a/spine-cpp/spine-cpp/src/spine/ShearTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/ShearTimeline.cpp @@ -40,8 +40,7 @@ #include #include -namespace Spine -{ +namespace Spine { RTTI_IMPL(ShearTimeline, TranslateTimeline); ShearTimeline::ShearTimeline(int frameCount) : TranslateTimeline(frameCount) { diff --git a/spine-cpp/spine-cpp/src/spine/Skeleton.cpp b/spine-cpp/spine-cpp/src/spine/Skeleton.cpp index 1913be075..221298519 100644 --- a/spine-cpp/spine-cpp/src/spine/Skeleton.cpp +++ b/spine-cpp/spine-cpp/src/spine/Skeleton.cpp @@ -52,8 +52,7 @@ #include #include -namespace Spine -{ +namespace Spine { Skeleton::Skeleton(SkeletonData& skeletonData) : _data(skeletonData), _skin(NULL), diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp b/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp index 68709ac59..364f128b0 100644 --- a/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp +++ b/spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp @@ -80,8 +80,7 @@ #include -namespace Spine -{ +namespace Spine { const int SkeletonBinary::BONE_ROTATE = 0; const int SkeletonBinary::BONE_TRANSLATE = 1; const int SkeletonBinary::BONE_SCALE = 2; diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonBounds.cpp b/spine-cpp/spine-cpp/src/spine/SkeletonBounds.cpp index a1e171e03..15ad8e4f4 100644 --- a/spine-cpp/spine-cpp/src/spine/SkeletonBounds.cpp +++ b/spine-cpp/spine-cpp/src/spine/SkeletonBounds.cpp @@ -36,8 +36,7 @@ #include #include -namespace Spine -{ +namespace Spine { SkeletonBounds::SkeletonBounds() : _minX(0), _minY(0), _maxX(0), _maxY(0) { // Empty } diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonClipping.cpp b/spine-cpp/spine-cpp/src/spine/SkeletonClipping.cpp index 252856bf3..7d5ae1ddd 100644 --- a/spine-cpp/spine-cpp/src/spine/SkeletonClipping.cpp +++ b/spine-cpp/spine-cpp/src/spine/SkeletonClipping.cpp @@ -33,8 +33,7 @@ #include #include -namespace Spine -{ +namespace Spine { SkeletonClipping::SkeletonClipping() : _clipAttachment(NULL) { _clipOutput.reserve(128); _clippedVertices.reserve(128); diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonData.cpp b/spine-cpp/spine-cpp/src/spine/SkeletonData.cpp index 6c8e09e1a..67159eac3 100644 --- a/spine-cpp/spine-cpp/src/spine/SkeletonData.cpp +++ b/spine-cpp/spine-cpp/src/spine/SkeletonData.cpp @@ -43,8 +43,7 @@ #include -namespace Spine -{ +namespace Spine { SkeletonData::SkeletonData() : _name(), _defaultSkin(NULL), diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp b/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp index fe11fe698..5bc8b0b8b 100644 --- a/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp +++ b/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp @@ -85,8 +85,7 @@ #define strdup _strdup #endif -namespace Spine -{ +namespace Spine { SkeletonJson::SkeletonJson(Vector& atlasArray) : _attachmentLoader(NEW(AtlasAttachmentLoader)), _scale(1), _ownsLoader(true) { new (_attachmentLoader) AtlasAttachmentLoader(atlasArray); } diff --git a/spine-cpp/spine-cpp/src/spine/Skin.cpp b/spine-cpp/spine-cpp/src/spine/Skin.cpp index c02f20dfa..12c80620a 100644 --- a/spine-cpp/spine-cpp/src/spine/Skin.cpp +++ b/spine-cpp/spine-cpp/src/spine/Skin.cpp @@ -37,8 +37,7 @@ #include -namespace Spine -{ +namespace Spine { Skin::AttachmentKey::AttachmentKey(int slotIndex, std::string name) : _slotIndex(slotIndex), _name(name) { diff --git a/spine-cpp/spine-cpp/src/spine/Slot.cpp b/spine-cpp/spine-cpp/src/spine/Slot.cpp index 65fb1585c..9ea7c7651 100644 --- a/spine-cpp/spine-cpp/src/spine/Slot.cpp +++ b/spine-cpp/spine-cpp/src/spine/Slot.cpp @@ -35,8 +35,7 @@ #include #include -namespace Spine -{ +namespace Spine { Slot::Slot(SlotData& data, Bone& bone) : _data(data), _bone(bone), diff --git a/spine-cpp/spine-cpp/src/spine/SlotData.cpp b/spine-cpp/spine-cpp/src/spine/SlotData.cpp index 8ef6adaf7..e8d517905 100644 --- a/spine-cpp/spine-cpp/src/spine/SlotData.cpp +++ b/spine-cpp/spine-cpp/src/spine/SlotData.cpp @@ -32,8 +32,7 @@ #include -namespace Spine -{ +namespace Spine { SlotData::SlotData(int index, std::string name, BoneData& boneData) : _index(index), _name(name), diff --git a/spine-cpp/spine-cpp/src/spine/TextureLoader.cpp b/spine-cpp/spine-cpp/src/spine/TextureLoader.cpp index 155f316d0..8658f8af9 100644 --- a/spine-cpp/spine-cpp/src/spine/TextureLoader.cpp +++ b/spine-cpp/spine-cpp/src/spine/TextureLoader.cpp @@ -30,8 +30,7 @@ #include -namespace Spine -{ +namespace Spine { TextureLoader::TextureLoader() { // Empty } diff --git a/spine-cpp/spine-cpp/src/spine/Timeline.cpp b/spine-cpp/spine-cpp/src/spine/Timeline.cpp index 32d22dffa..106a2896b 100644 --- a/spine-cpp/spine-cpp/src/spine/Timeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/Timeline.cpp @@ -33,8 +33,7 @@ #include #include -namespace Spine -{ +namespace Spine { RTTI_IMPL_NOPARENT(Timeline); Timeline::Timeline() { diff --git a/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp b/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp index e9defe296..267e1dd17 100644 --- a/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp +++ b/spine-cpp/spine-cpp/src/spine/TransformConstraint.cpp @@ -37,8 +37,7 @@ #include #include -namespace Spine -{ +namespace Spine { RTTI_IMPL(TransformConstraint, Constraint); TransformConstraint::TransformConstraint(TransformConstraintData& data, Skeleton& skeleton) : Constraint(), diff --git a/spine-cpp/spine-cpp/src/spine/TransformConstraintData.cpp b/spine-cpp/spine-cpp/src/spine/TransformConstraintData.cpp index e1daf92a6..fb3f5be91 100644 --- a/spine-cpp/spine-cpp/src/spine/TransformConstraintData.cpp +++ b/spine-cpp/spine-cpp/src/spine/TransformConstraintData.cpp @@ -34,8 +34,7 @@ #include -namespace Spine -{ +namespace Spine { TransformConstraintData::TransformConstraintData(std::string name) : _name(name), _order(0), diff --git a/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp b/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp index 2b2f9c5d6..60b11f6eb 100644 --- a/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/TransformConstraintTimeline.cpp @@ -40,8 +40,7 @@ #include #include -namespace Spine -{ +namespace Spine { RTTI_IMPL(TransformConstraintTimeline, CurveTimeline); const int TransformConstraintTimeline::ENTRIES = 5; diff --git a/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp b/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp index c8dfb639e..b5ceccc75 100644 --- a/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/TranslateTimeline.cpp @@ -40,8 +40,7 @@ #include #include -namespace Spine -{ +namespace Spine { RTTI_IMPL(TranslateTimeline, CurveTimeline); const int TranslateTimeline::ENTRIES = 3; diff --git a/spine-cpp/spine-cpp/src/spine/Triangulator.cpp b/spine-cpp/spine-cpp/src/spine/Triangulator.cpp index 1b715609f..3006cda54 100644 --- a/spine-cpp/spine-cpp/src/spine/Triangulator.cpp +++ b/spine-cpp/spine-cpp/src/spine/Triangulator.cpp @@ -32,8 +32,7 @@ #include -namespace Spine -{ +namespace Spine { Vector& Triangulator::triangulate(Vector& vertices) { int vertexCount = static_cast(vertices.size() >> 1); diff --git a/spine-cpp/spine-cpp/src/spine/TwoColorTimeline.cpp b/spine-cpp/spine-cpp/src/spine/TwoColorTimeline.cpp index 5cb546b26..9f824e70d 100644 --- a/spine-cpp/spine-cpp/src/spine/TwoColorTimeline.cpp +++ b/spine-cpp/spine-cpp/src/spine/TwoColorTimeline.cpp @@ -38,8 +38,7 @@ #include #include -namespace Spine -{ +namespace Spine { RTTI_IMPL(TwoColorTimeline, CurveTimeline); const int TwoColorTimeline::ENTRIES = 8; diff --git a/spine-cpp/spine-cpp/src/spine/Updatable.cpp b/spine-cpp/spine-cpp/src/spine/Updatable.cpp index 8993b94ae..581df4b43 100644 --- a/spine-cpp/spine-cpp/src/spine/Updatable.cpp +++ b/spine-cpp/spine-cpp/src/spine/Updatable.cpp @@ -30,8 +30,7 @@ #include -namespace Spine -{ +namespace Spine { RTTI_IMPL_NOPARENT(Updatable); Updatable::Updatable() { diff --git a/spine-cpp/spine-cpp/src/spine/VertexAttachment.cpp b/spine-cpp/spine-cpp/src/spine/VertexAttachment.cpp index 318b15263..be8cc1f1e 100644 --- a/spine-cpp/spine-cpp/src/spine/VertexAttachment.cpp +++ b/spine-cpp/spine-cpp/src/spine/VertexAttachment.cpp @@ -35,8 +35,7 @@ #include #include -namespace Spine -{ +namespace Spine { RTTI_IMPL(VertexAttachment, Attachment); VertexAttachment::VertexAttachment(std::string name) : Attachment(name), _worldVerticesLength(0), _id(getNextID()) { From c39f4547f76da74b65a15fbd3ed852b66379193e Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Thu, 14 Dec 2017 11:29:33 -0500 Subject: [PATCH 82/83] Bringing over recent changes to spine-c --- spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp b/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp index 5bc8b0b8b..3dbddb488 100644 --- a/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp +++ b/spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp @@ -290,7 +290,7 @@ namespace Spine { data->_target = skeletonData->findBone(targetName); if (!data->_target) { DESTROY(SkeletonData, skeletonData); - setError(root, "Target bone not found: ", boneMap->_name); + setError(root, "Target bone not found: ", targetName); return NULL; } @@ -331,7 +331,7 @@ namespace Spine { data->_target = skeletonData->findBone(name); if (!data->_target) { DESTROY(SkeletonData, skeletonData); - setError(root, "Target bone not found: ", boneMap->_name); + setError(root, "Target bone not found: ", name); return NULL; } @@ -384,7 +384,7 @@ namespace Spine { data->_target = skeletonData->findSlot(name); if (!data->_target) { DESTROY(SkeletonData, skeletonData); - setError(root, "Target slot not found: ", boneMap->_name); + setError(root, "Target slot not found: ", name); return NULL; } From 162cbeec72208a418ef37e2a9e3bc956e84ce08e Mon Sep 17 00:00:00 2001 From: Stephen Gowen Date: Tue, 16 Jan 2018 09:50:31 -0500 Subject: [PATCH 83/83] Porting over recent change from AnimationState.c to AnimationState.cpp --- spine-cpp/spine-cpp/src/spine/AnimationState.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/spine-cpp/spine-cpp/src/spine/AnimationState.cpp b/spine-cpp/spine-cpp/src/spine/AnimationState.cpp index f11649d6b..9d0140b82 100644 --- a/spine-cpp/spine-cpp/src/spine/AnimationState.cpp +++ b/spine-cpp/spine-cpp/src/spine/AnimationState.cpp @@ -568,9 +568,13 @@ namespace Spine { if (delay <= 0) { float duration = last->_animationEnd - last->_animationStart; if (duration != 0) { - delay += duration * (1 + (int)(last->_trackTime / duration)) - _data.getMix(last->_animation, animation); - } - else { + if (last->_loop) { + delay += duration * (1 + (int)(last->_trackTime / duration)); + } else { + delay += duration; + } + delay -= _data.getMix(last->_animation, animation); + } else { delay = 0; } }