diff --git a/spine-sdl/example/main.cpp b/spine-sdl/example/main.cpp index efa4c6598..c1d50b384 100644 --- a/spine-sdl/example/main.cpp +++ b/spine-sdl/example/main.cpp @@ -11,6 +11,9 @@ namespace spine { Skeleton *skeleton; bool ownsAnimationStateData; AnimationState *animationState; + SkeletonClipping clipper; + Vector worldVertices; + Vector quadIndices; SkeletonDrawable(SkeletonData *skeletonData, AnimationStateData *animationStateData = nullptr) { Bone::setYDown(true); @@ -19,6 +22,12 @@ namespace spine { ownsAnimationStateData = animationStateData == 0; if (ownsAnimationStateData) animationStateData = new(__FILE__, __LINE__) AnimationStateData(skeletonData); animationState = new(__FILE__, __LINE__) AnimationState(animationStateData); + quadIndices.add(0); + quadIndices.add(1); + quadIndices.add(2); + quadIndices.add(2); + quadIndices.add(3); + quadIndices.add(0); } ~SkeletonDrawable() { @@ -33,18 +42,124 @@ namespace spine { skeleton->updateWorldTransform(); } - void draw() { + void draw(SDL_Renderer *renderer) { + SDL_Texture *texture; + spine::Vector sdlVertices; + SDL_Vertex sdlVertex; + Vector sdlIndices; + for (unsigned i = 0; i < skeleton->getSlots().size(); ++i) { + Slot &slot = *skeleton->getDrawOrder()[i]; + Attachment *attachment = slot.getAttachment(); + if (!attachment) 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 *vertices = &worldVertices; + int verticesCount = 0; + Vector *uvs = NULL; + Vector *indices; + int indicesCount = 0; + Color *attachmentColor; + + 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; + texture = (SDL_Texture *) ((AtlasRegion *) regionAttachment->getRendererObject())->page->getRendererObject(); + + } 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); + texture = (SDL_Texture *) ((AtlasRegion *) mesh->getRendererObject())->page->getRendererObject(); + mesh->computeWorldVertices(slot, 0, mesh->getWorldVerticesLength(), worldVertices.buffer(), 0, 2); + verticesCount = mesh->getWorldVerticesLength() >> 1; + uvs = &mesh->getUVs(); + indices = &mesh->getTriangles(); + indicesCount = indices->size(); + + } else if (attachment->getRTTI().isExactly(ClippingAttachment::rtti)) { + ClippingAttachment *clip = (ClippingAttachment *) slot.getAttachment(); + clipper.clipStart(slot, clip); + continue; + } else + continue; + + Uint8 r = static_cast(skeleton->getColor().r * slot.getColor().r * attachmentColor->r * 255); + Uint8 g = static_cast(skeleton->getColor().g * slot.getColor().g * attachmentColor->g * 255); + Uint8 b = static_cast(skeleton->getColor().b * slot.getColor().b * attachmentColor->b * 255); + Uint8 a = static_cast(skeleton->getColor().a * slot.getColor().a * attachmentColor->a * 255); + sdlVertex.color.r = r; + sdlVertex.color.g = g; + sdlVertex.color.b = b; + sdlVertex.color.a = a; + + Color light; + light.r = r / 255.0f; + light.g = g / 255.0f; + light.b = b / 255.0f; + light.a = a / 255.0f; + + if (clipper.isClipping()) { + clipper.clipTriangles(worldVertices, *indices, *uvs, 2); + vertices = &clipper.getClippedVertices(); + verticesCount = clipper.getClippedVertices().size() >> 1; + uvs = &clipper.getClippedUVs(); + indices = &clipper.getClippedTriangles(); + indicesCount = clipper.getClippedTriangles().size(); + } + + + sdlVertices.clear(); + for (int ii = 0; ii < verticesCount; ++ii) { + sdlVertex.position.x = (*vertices)[ii]; + sdlVertex.position.y = (*vertices)[ii + 1]; + sdlVertex.tex_coord.x = (*uvs)[ii]; + sdlVertex.tex_coord.y = (*uvs)[ii + 1]; + sdlVertices.add(sdlVertex); + } + sdlIndices.clear(); + for (int ii = 0; ii < indices->size(); ii++) + sdlIndices.add((*indices)[ii]); + + SDL_RenderGeometry(renderer, texture, sdlVertices.buffer(), sdlVertices.size(), sdlIndices.buffer(), indicesCount); + clipper.clipEnd(slot); + } + clipper.clipEnd(); } }; class SDLTextureLoader : public spine::TextureLoader { SDL_Renderer *renderer; + public: SDLTextureLoader(SDL_Renderer *renderer): renderer(renderer) { } - SDL_Texture *loadTexture(SDL_Renderer *renderer, const spine::String &path) { + SDL_Texture *loadTexture(const spine::String &path) { int width, height, components; stbi_uc *imageData = stbi_load(path.buffer(), &width, &height, &components, 4); if (!imageData) return nullptr; @@ -62,7 +177,7 @@ namespace spine { } void load(AtlasPage &page, const String &path) { - SDL_Texture *texture = loadTexture(renderer, path); + SDL_Texture *texture = loadTexture(path); if (!texture) return; page.setRendererObject(texture); SDL_QueryTexture(texture, nullptr, nullptr, &page.width, &page.height); @@ -100,6 +215,16 @@ int main() { printf("Error: %s", SDL_GetError()); return -1; } + + spine::SDLTextureLoader textureLoader(renderer); + spine::Atlas atlas("/Users/badlogic/workspaces/spine-runtimes/examples/spineboy/export/spineboy.atlas", &textureLoader); + spine::AtlasAttachmentLoader attachmentLoader(&atlas); + spine::SkeletonJson json(&attachmentLoader); + spine::SkeletonData *skeletonData = json.readSkeletonDataFile("/Users/badlogic/workspaces/spine-runtimes/examples/spineboy/export/spineboy-pro.json"); + spine::SkeletonDrawable drawable(skeletonData); + drawable.skeleton->setPosition(400, 500); + drawable.update(0); + // spine::SkeletonDrawable skeletonDrawable(nullptr, nullptr); bool quit = false; @@ -114,6 +239,7 @@ int main() { SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); SDL_RenderClear(renderer); + drawable.draw(renderer); SDL_RenderPresent(renderer); }