diff --git a/spine-cpp/spine-cpp-lite/spine-cpp-lite.cpp b/spine-cpp/spine-cpp-lite/spine-cpp-lite.cpp index 236d8166d..d306b8b1c 100644 --- a/spine-cpp/spine-cpp-lite/spine-cpp-lite.cpp +++ b/spine-cpp/spine-cpp-lite/spine-cpp-lite.cpp @@ -34,76 +34,6 @@ using namespace spine; -struct Block { - int size; - int allocated; - uint8_t *memory; - - int free() { - return size - allocated; - } - - bool canFit(int numBytes) { - return free() >= numBytes; - } - - uint8_t *allocate(int numBytes) { - uint8_t *ptr = memory + allocated; - allocated += numBytes; - return ptr; - } -}; - -class BlockAllocator : public SpineObject { - int initialBlockSize; - Vector blocks; - -public: - BlockAllocator(int initialBlockSize) : initialBlockSize(initialBlockSize) { - blocks.add(newBlock(initialBlockSize)); - } - - ~BlockAllocator() { - for (int i = 0, n = (int) blocks.size(); i < n; i++) { - SpineExtension::free(blocks[i].memory, __FILE__, __LINE__); - } - } - - Block newBlock(int numBytes) { - Block block = {MathUtil::max(initialBlockSize, numBytes), 0, nullptr}; - block.memory = SpineExtension::alloc(block.size, __FILE__, __LINE__); - return block; - } - - template - T *allocate(size_t num) { - return (T *) _allocate((int) (sizeof(T) * num)); - } - - void compress() { - if (blocks.size() == 1) return; - int totalSize = 0; - for (int i = 0, n = blocks.size(); i < n; i++) { - totalSize += blocks[i].size; - SpineExtension::free(blocks[i].memory, __FILE__, __LINE__); - } - blocks.clear(); - blocks.add(newBlock(totalSize)); - } - -private: - void *_allocate(int numBytes) { - // 16-byte align allocations - int alignedNumBytes = numBytes + (numBytes % 16 != 0 ? 16 - (numBytes % 16) : 0); - Block *block = &blocks[blocks.size() - 1]; - if (!block->canFit(alignedNumBytes)) { - blocks.add(newBlock(MathUtil::max(initialBlockSize, alignedNumBytes))); - block = &blocks[blocks.size() - 1]; - } - return block->allocate(alignedNumBytes); - } -}; - struct AnimationStateEvent { EventType type; TrackEntry *entry; @@ -132,19 +62,6 @@ typedef struct _spine_skeleton_data_result { utf8 *error; } _spine_skeleton_data_result; -typedef struct _spine_render_command { - float *positions; - float *uvs; - int32_t *colors; - int32_t *darkColors; - int32_t numVertices; - uint16_t *indices; - int32_t numIndices; - int32_t atlasPage; - spine_blend_mode blendMode; - struct _spine_render_command *next; -} _spine_render_command; - typedef struct _spine_bounds { float x, y, width, height; } _spine_bounds; @@ -158,20 +75,7 @@ typedef struct _spine_skeleton_drawable : public SpineObject { spine_animation_state animationState; spine_animation_state_data animationStateData; spine_animation_state_events animationStateEvents; - void *clipping; - BlockAllocator *allocator; - Vector worldVertices; - Vector quadIndices; - Vector<_spine_render_command *> renderCommands; - - _spine_skeleton_drawable() { - quadIndices.add(0); - quadIndices.add(1); - quadIndices.add(2); - quadIndices.add(2); - quadIndices.add(3); - quadIndices.add(0); - } + SkeletonRenderer *renderer; } _spine_skeleton_drawable; typedef struct _spine_skin_entry { @@ -278,10 +182,20 @@ float spine_vector_get_y(spine_vector vector) { // Atlas +class LiteTextureLoad : public TextureLoader { + void load(AtlasPage &page, const String &path) { + page.texture = (void *) (intptr_t) page.index; + } + + void unload(void *texture) { + } +}; +LiteTextureLoad liteLoader; + spine_atlas spine_atlas_load(const utf8 *atlasData) { if (!atlasData) return nullptr; int32_t length = (int32_t) strlen(atlasData); - auto atlas = new (__FILE__, __LINE__) Atlas(atlasData, length, "", (TextureLoader *) nullptr, false); + auto atlas = new (__FILE__, __LINE__) Atlas(atlasData, length, "", &liteLoader, true); _spine_atlas *result = SpineExtension::calloc<_spine_atlas>(1, __FILE__, __LINE__); result->atlas = atlas; result->numImagePaths = (int32_t) atlas->getPages().size(); @@ -649,22 +563,6 @@ void spine_skeleton_data_dispose(spine_skeleton_data data) { delete (SkeletonData *) data; } -// RenderCommand -static _spine_render_command *spine_render_command_create(BlockAllocator &allocator, int numVertices, int32_t numIndices, spine_blend_mode blendMode, int32_t pageIndex) { - _spine_render_command *cmd = allocator.allocate<_spine_render_command>(1); - cmd->positions = allocator.allocate(numVertices << 1); - cmd->uvs = allocator.allocate(numVertices << 1); - cmd->colors = allocator.allocate(numVertices); - cmd->darkColors = allocator.allocate(numVertices); - cmd->numVertices = numVertices; - cmd->indices = allocator.allocate(numIndices); - cmd->numIndices = numIndices; - cmd->blendMode = blendMode; - cmd->atlasPage = pageIndex; - cmd->next = nullptr; - return cmd; -} - // SkeletonDrawable spine_skeleton_drawable spine_skeleton_drawable_create(spine_skeleton_data skeletonData) { @@ -678,8 +576,7 @@ spine_skeleton_drawable spine_skeleton_drawable_create(spine_skeleton_data skele EventListener *listener = new EventListener(); drawable->animationStateEvents = (spine_animation_state_events) listener; state->setListener(listener); - drawable->clipping = new (__FILE__, __LINE__) SkeletonClipping(); - drawable->allocator = new (__FILE__, __LINE__) BlockAllocator(2048); + drawable->renderer = new (__FILE__, __LINE__) SkeletonRenderer(); return (spine_skeleton_drawable) drawable; } @@ -690,194 +587,16 @@ void spine_skeleton_drawable_dispose(spine_skeleton_drawable drawable) { if (_drawable->animationState) delete (AnimationState *) _drawable->animationState; if (_drawable->animationStateData) delete (AnimationStateData *) _drawable->animationStateData; if (_drawable->animationStateEvents) delete (Vector *) (_drawable->animationStateEvents); - if (_drawable->clipping) delete (SkeletonClipping *) _drawable->clipping; - if (_drawable->allocator) delete (BlockAllocator *) _drawable->allocator; + if (_drawable->renderer) delete (SkeletonRenderer *) _drawable->renderer; SpineExtension::free(drawable, __FILE__, __LINE__); } -static _spine_render_command *batch_sub_commands(BlockAllocator &allocator, Vector<_spine_render_command *> &commands, int first, int last, int numVertices, int numIndices) { - _spine_render_command *batched = spine_render_command_create(allocator, numVertices, numIndices, commands[first]->blendMode, commands[first]->atlasPage); - float *positions = batched->positions; - float *uvs = batched->uvs; - int32_t *colors = batched->colors; - int32_t *darkColors = batched->darkColors; - uint16_t *indices = batched->indices; - int indicesOffset = 0; - for (int i = first; i <= last; i++) { - _spine_render_command *cmd = commands[i]; - memcpy(positions, cmd->positions, sizeof(float) * 2 * cmd->numVertices); - memcpy(uvs, cmd->uvs, sizeof(float) * 2 * cmd->numVertices); - memcpy(colors, cmd->colors, sizeof(int32_t) * cmd->numVertices); - memcpy(darkColors, cmd->darkColors, sizeof(int32_t) * cmd->numVertices); - for (int ii = 0; ii < cmd->numIndices; ii++) - indices[ii] = cmd->indices[ii] + indicesOffset; - indicesOffset += cmd->numVertices; - positions += 2 * cmd->numVertices; - uvs += 2 * cmd->numVertices; - colors += cmd->numVertices; - darkColors += cmd->numVertices; - indices += cmd->numIndices; - } - return batched; -} - -static _spine_render_command *batch_commands(BlockAllocator &allocator, Vector<_spine_render_command *> &commands) { - if (commands.size() == 0) return nullptr; - - _spine_render_command *root = nullptr; - _spine_render_command *last = nullptr; - - _spine_render_command *first = commands[0]; - int startIndex = 0; - int i = 1; - int numVertices = first->numVertices; - int numIndices = first->numIndices; - while (i <= (int) commands.size()) { - _spine_render_command *cmd = i < (int) commands.size() ? commands[i] : nullptr; - - if (cmd && cmd->numVertices == 0 && cmd->numIndices == 0) { - i++; - continue; - } - - if (cmd != nullptr && cmd->atlasPage == first->atlasPage && - cmd->blendMode == first->blendMode && - cmd->colors[0] == first->colors[0] && - cmd->darkColors[0] == first->darkColors[0] && - numIndices + cmd->numIndices < 0xffff) { - numVertices += cmd->numVertices; - numIndices += cmd->numIndices; - } else { - _spine_render_command *batched = batch_sub_commands(allocator, commands, startIndex, i - 1, numVertices, numIndices); - if (!last) { - root = last = batched; - } else { - last->next = batched; - last = batched; - } - if (i == (int) commands.size()) break; - first = commands[i]; - startIndex = i; - numVertices = first->numVertices; - numIndices = first->numIndices; - } - i++; - } - return root; -} - spine_render_command spine_skeleton_drawable_render(spine_skeleton_drawable drawable) { _spine_skeleton_drawable *_drawable = (_spine_skeleton_drawable *) drawable; if (!_drawable) return nullptr; if (!_drawable->skeleton) return nullptr; - - _drawable->allocator->compress(); - _drawable->renderCommands.clear(); - - SkeletonClipping &clipper = *(SkeletonClipping *) _drawable->clipping; - Skeleton *skeleton = (Skeleton *) _drawable->skeleton; - - for (unsigned i = 0; i < skeleton->getSlots().size(); ++i) { - Slot &slot = *skeleton->getDrawOrder()[i]; - Attachment *attachment = slot.getAttachment(); - if (!attachment) { - clipper.clipEnd(slot); - continue; - } - - // Early out if the slot color is 0 or the bone is not active - if (slot.getColor().a == 0 || !slot.getBone().isActive()) { - clipper.clipEnd(slot); - continue; - } - - Vector *worldVertices = &_drawable->worldVertices; - Vector *quadIndices = &_drawable->quadIndices; - Vector *vertices = worldVertices; - int32_t verticesCount; - Vector *uvs; - Vector *indices; - int32_t indicesCount; - Color *attachmentColor; - int32_t pageIndex; - - if (attachment->getRTTI().isExactly(RegionAttachment::rtti)) { - RegionAttachment *regionAttachment = (RegionAttachment *) attachment; - attachmentColor = ®ionAttachment->getColor(); - - // Early out if the slot color is 0 - if (attachmentColor->a == 0) { - clipper.clipEnd(slot); - continue; - } - - worldVertices->setSize(8, 0); - regionAttachment->computeWorldVertices(slot, *worldVertices, 0, 2); - verticesCount = 4; - uvs = ®ionAttachment->getUVs(); - indices = quadIndices; - indicesCount = 6; - pageIndex = ((AtlasRegion *) regionAttachment->getRegion())->page->index; - - } else if (attachment->getRTTI().isExactly(MeshAttachment::rtti)) { - MeshAttachment *mesh = (MeshAttachment *) attachment; - attachmentColor = &mesh->getColor(); - - // Early out if the slot color is 0 - if (attachmentColor->a == 0) { - clipper.clipEnd(slot); - continue; - } - - worldVertices->setSize(mesh->getWorldVerticesLength(), 0); - mesh->computeWorldVertices(slot, 0, mesh->getWorldVerticesLength(), worldVertices->buffer(), 0, 2); - verticesCount = (int32_t) (mesh->getWorldVerticesLength() >> 1); - uvs = &mesh->getUVs(); - indices = &mesh->getTriangles(); - indicesCount = (int32_t) indices->size(); - pageIndex = ((AtlasRegion *) mesh->getRegion())->page->index; - - } else if (attachment->getRTTI().isExactly(ClippingAttachment::rtti)) { - ClippingAttachment *clip = (ClippingAttachment *) slot.getAttachment(); - clipper.clipStart(slot, clip); - continue; - } else - continue; - - uint8_t r = static_cast(skeleton->getColor().r * slot.getColor().r * attachmentColor->r * 255); - uint8_t g = static_cast(skeleton->getColor().g * slot.getColor().g * attachmentColor->g * 255); - uint8_t b = static_cast(skeleton->getColor().b * slot.getColor().b * attachmentColor->b * 255); - uint8_t a = static_cast(skeleton->getColor().a * slot.getColor().a * attachmentColor->a * 255); - uint32_t color = (a << 24) | (r << 16) | (g << 8) | b; - uint32_t darkColor = 0xff000000; - if (slot.hasDarkColor()) { - Color &slotDarkColor = slot.getDarkColor(); - darkColor = 0xff000000 | (static_cast(slotDarkColor.r * 255) << 16) | (static_cast(slotDarkColor.g * 255) << 8) | static_cast(slotDarkColor.b * 255); - } - - if (clipper.isClipping()) { - clipper.clipTriangles(*worldVertices, *indices, *uvs, 2); - vertices = &clipper.getClippedVertices(); - verticesCount = (int32_t) (clipper.getClippedVertices().size() >> 1); - uvs = &clipper.getClippedUVs(); - indices = &clipper.getClippedTriangles(); - indicesCount = (int32_t) (clipper.getClippedTriangles().size()); - } - - _spine_render_command *cmd = spine_render_command_create(*_drawable->allocator, verticesCount, indicesCount, (spine_blend_mode) slot.getData().getBlendMode(), pageIndex); - _drawable->renderCommands.add(cmd); - memcpy(cmd->positions, vertices->buffer(), (verticesCount << 1) * sizeof(float)); - memcpy(cmd->uvs, uvs->buffer(), (verticesCount << 1) * sizeof(float)); - for (int ii = 0; ii < verticesCount; ii++) { - cmd->colors[ii] = color; - cmd->darkColors[ii] = darkColor; - } - memcpy(cmd->indices, indices->buffer(), indices->size() * sizeof(uint16_t)); - clipper.clipEnd(slot); - } - clipper.clipEnd(); - - return (spine_render_command) batch_commands(*_drawable->allocator, _drawable->renderCommands); + if (!_drawable->renderer) return nullptr; + return (spine_render_command) _drawable->renderer->render(*(Skeleton *) _drawable->skeleton); } spine_skeleton spine_skeleton_drawable_get_skeleton(spine_skeleton_drawable drawable) { @@ -903,52 +622,52 @@ spine_animation_state_events spine_skeleton_drawable_get_animation_state_events( // Render command float *spine_render_command_get_positions(spine_render_command command) { if (!command) return nullptr; - return ((_spine_render_command *) command)->positions; + return ((RenderCommand *) command)->positions; } float *spine_render_command_get_uvs(spine_render_command command) { if (!command) return nullptr; - return ((_spine_render_command *) command)->uvs; + return ((RenderCommand *) command)->uvs; } int32_t *spine_render_command_get_colors(spine_render_command command) { if (!command) return nullptr; - return ((_spine_render_command *) command)->colors; + return (int32_t *) ((RenderCommand *) command)->colors; } int32_t *spine_render_command_get_dark_colors(spine_render_command command) { if (!command) return nullptr; - return ((_spine_render_command *) command)->darkColors; + return (int32_t *) ((RenderCommand *) command)->darkColors; } int32_t spine_render_command_get_num_vertices(spine_render_command command) { if (!command) return 0; - return ((_spine_render_command *) command)->numVertices; + return ((RenderCommand *) command)->numVertices; } uint16_t *spine_render_command_get_indices(spine_render_command command) { if (!command) return nullptr; - return ((_spine_render_command *) command)->indices; + return ((RenderCommand *) command)->indices; } int32_t spine_render_command_get_num_indices(spine_render_command command) { if (!command) return 0; - return ((_spine_render_command *) command)->numIndices; + return ((RenderCommand *) command)->numIndices; } int32_t spine_render_command_get_atlas_page(spine_render_command command) { if (!command) return 0; - return ((_spine_render_command *) command)->atlasPage; + return (int32_t) (intptr_t) ((RenderCommand *) command)->texture; } spine_blend_mode spine_render_command_get_blend_mode(spine_render_command command) { if (!command) return SPINE_BLEND_MODE_NORMAL; - return ((_spine_render_command *) command)->blendMode; + return (spine_blend_mode) ((RenderCommand *) command)->blendMode; } spine_render_command spine_render_command_get_next(spine_render_command command) { if (!command) return nullptr; - return (spine_render_command) ((_spine_render_command *) command)->next; + return (spine_render_command) ((RenderCommand *) command)->next; } // Animation diff --git a/spine-cpp/spine-cpp/include/spine/BlockAllocator.h b/spine-cpp/spine-cpp/include/spine/BlockAllocator.h index 89eb5fd2a..422d2a487 100644 --- a/spine-cpp/spine-cpp/include/spine/BlockAllocator.h +++ b/spine-cpp/spine-cpp/include/spine/BlockAllocator.h @@ -79,7 +79,7 @@ namespace spine { void compress() { if (blocks.size() == 1) return; int totalSize = 0; - for (int i = 0, n = blocks.size(); i < n; i++) { + for (int i = 0, n = (int)blocks.size(); i < n; i++) { totalSize += blocks[i].size; SpineExtension::free(blocks[i].memory, __FILE__, __LINE__); } diff --git a/spine-cpp/spine-cpp/src/spine/Atlas.cpp b/spine-cpp/spine-cpp/src/spine/Atlas.cpp index d87070b82..11e24a99b 100644 --- a/spine-cpp/spine-cpp/src/spine/Atlas.cpp +++ b/spine-cpp/spine-cpp/src/spine/Atlas.cpp @@ -280,13 +280,9 @@ void Atlas::load(const char *begin, int length, const char *dir, bool createText } } - if (createTexture) { - if (_textureLoader) _textureLoader->load(*page, String(path)); - SpineExtension::free(path, __FILE__, __LINE__); - } else { - page->texturePath = String(path, true); - } page->index = (int) _pages.size(); + if (createTexture && _textureLoader) _textureLoader->load(*page, String(path)); + page->texturePath = String(path, true); _pages.add(page); } else { AtlasRegion *region = new (__FILE__, __LINE__) AtlasRegion(); diff --git a/spine-cpp/spine-cpp/src/spine/SkeletonRenderer.cpp b/spine-cpp/spine-cpp/src/spine/SkeletonRenderer.cpp index 7be7770c4..1934b19c0 100644 --- a/spine-cpp/spine-cpp/src/spine/SkeletonRenderer.cpp +++ b/spine-cpp/spine-cpp/src/spine/SkeletonRenderer.cpp @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include @@ -137,7 +136,6 @@ static RenderCommand *batchCommands(BlockAllocator &allocator, Vectorpositions; float *uvs = command->uvs; - int32_t *colors = command->colors; - int32_t *darkColors = command->darkColors; + uint32_t *colors = command->colors; + uint32_t *darkColors = command->darkColors; for (int i = 0, j = 0; i < num_command_vertices; i++, j += 2) { vertex_t *vertex = &renderer->vertex_buffer[i]; vertex->x = positions[j];