mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-03-26 22:49:01 +08:00
Merge remote-tracking branch 'origin/3.6' into 3.6
This commit is contained in:
commit
9df8790c5e
@ -92,29 +92,65 @@ void Json_dispose (Json *c) {
|
|||||||
|
|
||||||
/* Parse the input text to generate a number, and populate the result into item. */
|
/* Parse the input text to generate a number, and populate the result into item. */
|
||||||
static const char* parse_number (Json *item, const char* num) {
|
static const char* parse_number (Json *item, const char* num) {
|
||||||
char * endptr;
|
double result = 0.0;
|
||||||
float n;
|
int negative = 0;
|
||||||
|
char* ptr = (char*)num;
|
||||||
|
|
||||||
/* Using strtod and strtof is slightly more permissive than RFC4627,
|
if (*ptr == '-') {
|
||||||
* accepting for example hex-encoded floating point, but either
|
negative = -1;
|
||||||
* is often leagues faster than any manual implementation.
|
++ptr;
|
||||||
*
|
}
|
||||||
* 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) {
|
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. */
|
/* Parse success, number found. */
|
||||||
item->valueFloat = n;
|
item->valueFloat = result;
|
||||||
item->valueInt = (int)n;
|
item->valueInt = (int)result;
|
||||||
item->type = Json_Number;
|
item->type = Json_Number;
|
||||||
return endptr;
|
return ptr;
|
||||||
} else {
|
} else {
|
||||||
/* Parse failure, ep is set. */
|
/* Parse failure, ep is set. */
|
||||||
ep = num;
|
ep = num;
|
||||||
|
|||||||
@ -30,7 +30,6 @@
|
|||||||
|
|
||||||
#include <spine/SkeletonJson.h>
|
#include <spine/SkeletonJson.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <locale.h>
|
|
||||||
#include "Json.h"
|
#include "Json.h"
|
||||||
#include <spine/extension.h>
|
#include <spine/extension.h>
|
||||||
#include <spine/AtlasAttachmentLoader.h>
|
#include <spine/AtlasAttachmentLoader.h>
|
||||||
@ -579,25 +578,14 @@ spSkeletonData* spSkeletonJson_readSkeletonData (spSkeletonJson* self, const cha
|
|||||||
int i, ii;
|
int i, ii;
|
||||||
spSkeletonData* skeletonData;
|
spSkeletonData* skeletonData;
|
||||||
Json *root, *skeleton, *bones, *boneMap, *ik, *transform, *path, *slots, *skins, *animations, *events;
|
Json *root, *skeleton, *bones, *boneMap, *ik, *transform, *path, *slots, *skins, *animations, *events;
|
||||||
char* oldLocale;
|
|
||||||
_spSkeletonJson* internal = SUB_CAST(_spSkeletonJson, self);
|
_spSkeletonJson* internal = SUB_CAST(_spSkeletonJson, self);
|
||||||
|
|
||||||
FREE(self->error);
|
FREE(self->error);
|
||||||
CONST_CAST(char*, self->error) = 0;
|
CONST_CAST(char*, self->error) = 0;
|
||||||
internal->linkedMeshCount = 0;
|
internal->linkedMeshCount = 0;
|
||||||
|
|
||||||
#ifndef __ANDROID__
|
|
||||||
oldLocale = strdup(setlocale(LC_NUMERIC, NULL));
|
|
||||||
setlocale(LC_NUMERIC, "C");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
root = Json_create(json);
|
root = Json_create(json);
|
||||||
|
|
||||||
#ifndef __ANDROID__
|
|
||||||
setlocale(LC_NUMERIC, oldLocale);
|
|
||||||
free(oldLocale);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!root) {
|
if (!root) {
|
||||||
_spSkeletonJson_setError(self, 0, "Invalid skeleton JSON: ", Json_getError());
|
_spSkeletonJson_setError(self, 0, "Invalid skeleton JSON: ", Json_getError());
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@ -36,12 +36,35 @@
|
|||||||
#include <spine/Cocos2dAttachmentLoader.h>
|
#include <spine/Cocos2dAttachmentLoader.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
#define INITIAL_WORLD_VERTICES_LENGTH 1000
|
||||||
|
// Used for transforming attachments for bounding boxes & debug rendering
|
||||||
|
static float* worldVertices = nullptr;
|
||||||
|
static size_t worldVerticesLength = 0;
|
||||||
|
|
||||||
|
void ensureWorldVerticesCapacity(size_t capacity) {
|
||||||
|
if (worldVerticesLength < capacity) {
|
||||||
|
float* newWorldVertices = new float[capacity];
|
||||||
|
memcpy(newWorldVertices, worldVertices, capacity * sizeof(float));
|
||||||
|
delete[] worldVertices;
|
||||||
|
worldVertices = newWorldVertices;
|
||||||
|
worldVerticesLength = capacity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
USING_NS_CC;
|
USING_NS_CC;
|
||||||
using std::min;
|
using std::min;
|
||||||
using std::max;
|
using std::max;
|
||||||
|
|
||||||
namespace spine {
|
namespace spine {
|
||||||
|
|
||||||
|
void SkeletonRenderer::destroyScratchBuffers() {
|
||||||
|
if (worldVertices) {
|
||||||
|
delete[] worldVertices;
|
||||||
|
worldVertices = nullptr;
|
||||||
|
worldVerticesLength = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SkeletonRenderer* SkeletonRenderer::createWithData (spSkeletonData* skeletonData, bool ownsSkeletonData) {
|
SkeletonRenderer* SkeletonRenderer::createWithData (spSkeletonData* skeletonData, bool ownsSkeletonData) {
|
||||||
SkeletonRenderer* node = new SkeletonRenderer(skeletonData, ownsSkeletonData);
|
SkeletonRenderer* node = new SkeletonRenderer(skeletonData, ownsSkeletonData);
|
||||||
node->autorelease();
|
node->autorelease();
|
||||||
@ -61,7 +84,10 @@ SkeletonRenderer* SkeletonRenderer::createWithFile (const std::string& skeletonD
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SkeletonRenderer::initialize () {
|
void SkeletonRenderer::initialize () {
|
||||||
_worldVertices = new float[1000]; // Max number of vertices per mesh.
|
if (!worldVertices) {
|
||||||
|
worldVertices = new float[INITIAL_WORLD_VERTICES_LENGTH];
|
||||||
|
worldVerticesLength = INITIAL_WORLD_VERTICES_LENGTH;
|
||||||
|
}
|
||||||
|
|
||||||
_clipper = spSkeletonClipping_create();
|
_clipper = spSkeletonClipping_create();
|
||||||
|
|
||||||
@ -131,8 +157,7 @@ SkeletonRenderer::~SkeletonRenderer () {
|
|||||||
if (_ownsSkeletonData) spSkeletonData_dispose(_skeleton->data);
|
if (_ownsSkeletonData) spSkeletonData_dispose(_skeleton->data);
|
||||||
spSkeleton_dispose(_skeleton);
|
spSkeleton_dispose(_skeleton);
|
||||||
if (_atlas) spAtlas_dispose(_atlas);
|
if (_atlas) spAtlas_dispose(_atlas);
|
||||||
if (_attachmentLoader) spAttachmentLoader_dispose(_attachmentLoader);
|
if (_attachmentLoader) spAttachmentLoader_dispose(_attachmentLoader);
|
||||||
delete [] _worldVertices;
|
|
||||||
spSkeletonClipping_dispose(_clipper);
|
spSkeletonClipping_dispose(_clipper);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -613,11 +638,11 @@ void SkeletonRenderer::drawDebug (Renderer* renderer, const Mat4 &transform, uin
|
|||||||
spSlot* slot = _skeleton->drawOrder[i];
|
spSlot* slot = _skeleton->drawOrder[i];
|
||||||
if (!slot->attachment || slot->attachment->type != SP_ATTACHMENT_REGION) continue;
|
if (!slot->attachment || slot->attachment->type != SP_ATTACHMENT_REGION) continue;
|
||||||
spRegionAttachment* attachment = (spRegionAttachment*)slot->attachment;
|
spRegionAttachment* attachment = (spRegionAttachment*)slot->attachment;
|
||||||
spRegionAttachment_computeWorldVertices(attachment, slot->bone, _worldVertices, 0, 2);
|
spRegionAttachment_computeWorldVertices(attachment, slot->bone, worldVertices, 0, 2);
|
||||||
points[0] = Vec2(_worldVertices[0], _worldVertices[1]);
|
points[0] = Vec2(worldVertices[0], worldVertices[1]);
|
||||||
points[1] = Vec2(_worldVertices[2], _worldVertices[3]);
|
points[1] = Vec2(worldVertices[2], worldVertices[3]);
|
||||||
points[2] = Vec2(_worldVertices[4], _worldVertices[5]);
|
points[2] = Vec2(worldVertices[4], worldVertices[5]);
|
||||||
points[3] = Vec2(_worldVertices[6], _worldVertices[7]);
|
points[3] = Vec2(worldVertices[6], worldVertices[7]);
|
||||||
drawNode->drawPoly(points, 4, true, Color4F::BLUE);
|
drawNode->drawPoly(points, 4, true, Color4F::BLUE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -645,12 +670,13 @@ void SkeletonRenderer::drawDebug (Renderer* renderer, const Mat4 &transform, uin
|
|||||||
for (int i = 0, n = _skeleton->slotsCount; i < n; ++i) {
|
for (int i = 0, n = _skeleton->slotsCount; i < n; ++i) {
|
||||||
spSlot* slot = _skeleton->drawOrder[i];
|
spSlot* slot = _skeleton->drawOrder[i];
|
||||||
if (!slot->attachment || slot->attachment->type != SP_ATTACHMENT_MESH) continue;
|
if (!slot->attachment || slot->attachment->type != SP_ATTACHMENT_MESH) continue;
|
||||||
spMeshAttachment* attachment = (spMeshAttachment*)slot->attachment;
|
spMeshAttachment* attachment = (spMeshAttachment*)slot->attachment;
|
||||||
spVertexAttachment_computeWorldVertices(SUPER(attachment), slot, 0, attachment->super.worldVerticesLength, _worldVertices, 0, 2);
|
ensureWorldVerticesCapacity(attachment->super.worldVerticesLength);
|
||||||
|
spVertexAttachment_computeWorldVertices(SUPER(attachment), slot, 0, attachment->super.worldVerticesLength, worldVertices, 0, 2);
|
||||||
for (int ii = 0; ii < attachment->trianglesCount;) {
|
for (int ii = 0; ii < attachment->trianglesCount;) {
|
||||||
Vec2 v1(_worldVertices + (attachment->triangles[ii++] * 2));
|
Vec2 v1(worldVertices + (attachment->triangles[ii++] * 2));
|
||||||
Vec2 v2(_worldVertices + (attachment->triangles[ii++] * 2));
|
Vec2 v2(worldVertices + (attachment->triangles[ii++] * 2));
|
||||||
Vec2 v3(_worldVertices + (attachment->triangles[ii++] * 2));
|
Vec2 v3(worldVertices + (attachment->triangles[ii++] * 2));
|
||||||
drawNode->drawLine(v1, v2, Color4F::YELLOW);
|
drawNode->drawLine(v1, v2, Color4F::YELLOW);
|
||||||
drawNode->drawLine(v2, v3, Color4F::YELLOW);
|
drawNode->drawLine(v2, v3, Color4F::YELLOW);
|
||||||
drawNode->drawLine(v3, v1, Color4F::YELLOW);
|
drawNode->drawLine(v3, v1, Color4F::YELLOW);
|
||||||
@ -680,16 +706,17 @@ Rect SkeletonRenderer::getBoundingBox () const {
|
|||||||
int verticesCount;
|
int verticesCount;
|
||||||
if (slot->attachment->type == SP_ATTACHMENT_REGION) {
|
if (slot->attachment->type == SP_ATTACHMENT_REGION) {
|
||||||
spRegionAttachment* attachment = (spRegionAttachment*)slot->attachment;
|
spRegionAttachment* attachment = (spRegionAttachment*)slot->attachment;
|
||||||
spRegionAttachment_computeWorldVertices(attachment, slot->bone, _worldVertices, 0, 2);
|
spRegionAttachment_computeWorldVertices(attachment, slot->bone, worldVertices, 0, 2);
|
||||||
verticesCount = 8;
|
verticesCount = 8;
|
||||||
} else if (slot->attachment->type == SP_ATTACHMENT_MESH) {
|
} else if (slot->attachment->type == SP_ATTACHMENT_MESH) {
|
||||||
spMeshAttachment* mesh = (spMeshAttachment*)slot->attachment;
|
spMeshAttachment* mesh = (spMeshAttachment*)slot->attachment;
|
||||||
spVertexAttachment_computeWorldVertices(SUPER(mesh), slot, 0, mesh->super.worldVerticesLength, _worldVertices, 0, 2);
|
ensureWorldVerticesCapacity(mesh->super.worldVerticesLength);
|
||||||
|
spVertexAttachment_computeWorldVertices(SUPER(mesh), slot, 0, mesh->super.worldVerticesLength, worldVertices, 0, 2);
|
||||||
verticesCount = mesh->super.worldVerticesLength;
|
verticesCount = mesh->super.worldVerticesLength;
|
||||||
} else
|
} else
|
||||||
continue;
|
continue;
|
||||||
for (int ii = 0; ii < verticesCount; ii += 2) {
|
for (int ii = 0; ii < verticesCount; ii += 2) {
|
||||||
float x = _worldVertices[ii] * scaleX, y = _worldVertices[ii + 1] * scaleY;
|
float x = worldVertices[ii] * scaleX, y = worldVertices[ii + 1] * scaleY;
|
||||||
minX = min(minX, x);
|
minX = min(minX, x);
|
||||||
minY = min(minY, y);
|
minY = min(minY, y);
|
||||||
maxX = max(maxX, x);
|
maxX = max(maxX, x);
|
||||||
|
|||||||
@ -108,6 +108,9 @@ public:
|
|||||||
virtual const cocos2d::BlendFunc& getBlendFunc () const override;
|
virtual const cocos2d::BlendFunc& getBlendFunc () const override;
|
||||||
virtual void setOpacityModifyRGB (bool value) override;
|
virtual void setOpacityModifyRGB (bool value) override;
|
||||||
virtual bool isOpacityModifyRGB () const override;
|
virtual bool isOpacityModifyRGB () const override;
|
||||||
|
|
||||||
|
// Frees global memory used for temporay vertex transformations.
|
||||||
|
static void destroyScratchBuffers();
|
||||||
|
|
||||||
CC_CONSTRUCTOR_ACCESS:
|
CC_CONSTRUCTOR_ACCESS:
|
||||||
SkeletonRenderer ();
|
SkeletonRenderer ();
|
||||||
@ -136,7 +139,6 @@ protected:
|
|||||||
spAttachmentLoader* _attachmentLoader;
|
spAttachmentLoader* _attachmentLoader;
|
||||||
cocos2d::CustomCommand _debugCommand;
|
cocos2d::CustomCommand _debugCommand;
|
||||||
cocos2d::BlendFunc _blendFunc;
|
cocos2d::BlendFunc _blendFunc;
|
||||||
float* _worldVertices;
|
|
||||||
bool _premultipliedAlpha;
|
bool _premultipliedAlpha;
|
||||||
spSkeleton* _skeleton;
|
spSkeleton* _skeleton;
|
||||||
float _timeScale;
|
float _timeScale;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user