• Runtimes
  • Empty slot attachment?

Hey guys,

I'm trying to port the löve2d runtime to Codea since its the closes one. http://codea.io
The code I have right now should be able to render spine data completely - but interestingly it only work for attachments of type

spine.AttachmentType.region

and for some attachments of type

spine.AttachmentType.mesh

– Let me explain.

When I run fallowing examples all renders 100% correct: "dragon", "alien", "spineboy"
But e.g. "goblins" only renders the shield and spear. Everything else gets skipped. This is confusing, since I think that these attachments are actually mesh types. I tried to debug and quickly noticed that not each loop through

skeleton.drawOrder

actually finds an

slot.attachment

. How can this be? (Inside LÖVE this renders ok.)

What my renderer does:

  1. I define a new "Actor" class for convenience. This will hold all skeleton data, animations states and methods for modifying the skeleton (playing animations, changing skins, etc)
  2. Next, I load all required libraries, functions and json and atlas files.
  3. Then comes the actual renderer. Meshes are working a little differen here than in LÖVE.
    We do not pass a combined table of all vertices, uvs and colors and then supplying a map-table for the triangles (indices) to render the mesh, Instead we have separate buffers for each of them. One buffer for vertices (triangulated) one for their UVs and one for their colors.

Inside the draw() method I first call updateWorldTransform() to have updated bones to work with.
Next, I begin looping through the skeleton.drawOrder.
For each slot.attachment I expect to receive vertices, triangles and a texture, unless the slot is empty.
This information is immediately applied to the mesh, by first clearing and instantly rebuilding it.
This data gets splitted for the different buffers and is send to the GPU which eventually renders the mesh.
This process is repeated for each slot.attachment.

As far as I understand:
Vertices: describe the rectangular region of the attachment
Indices: describe the index of the vertex to choose from Vertices in order to finally get a list of triangulated faces for the mesh
Texture: is the spritesheet (Hopefully that texture is cached and not completely loaded for each attachment?)

I checked everything manually. All vertices and UVs seem to be translated ok. For all cases. It should all work, but i doesn't. What am I missing here? Why is the goblin not rendered as expected?

local QUAD_TRIANGLES = {1, 2, 3, 3, 4, 1}
local table_insert = table.insert

spine = {}

spine.Actor = class()
spine.utils = require "spine-lua.utils"
spine.SkeletonJson = require "spine-lua.SkeletonJson"
spine.SkeletonData = require "spine-lua.SkeletonData"
spine.BoneData = require "spine-lua.BoneData"
spine.SlotData = require "spine-lua.SlotData"
spine.IkConstraintData = require "spine-lua.IkConstraintData"
spine.Skin = require "spine-lua.Skin"
spine.Attachment = require "spine-lua.attachments.Attachment"
spine.BoundingBoxAttachment = require "spine-lua.attachments.BoundingBoxAttachment"
spine.RegionAttachment = require "spine-lua.attachments.RegionAttachment"
spine.MeshAttachment = require "spine-lua.attachments.MeshAttachment"
spine.VertexAttachment = require "spine-lua.attachments.VertexAttachment"
spine.PathAttachment = require "spine-lua.attachments.PathAttachment"
spine.Skeleton = require "spine-lua.Skeleton"
spine.Bone = require "spine-lua.Bone"
spine.Slot = require "spine-lua.Slot"
spine.IkConstraint = require "spine-lua.IkConstraint"
spine.AttachmentType = require "spine-lua.attachments.AttachmentType"
spine.AttachmentLoader = require "spine-lua.AttachmentLoader"
spine.Animation = require "spine-lua.Animation"
spine.AnimationStateData = require "spine-lua.AnimationStateData"
spine.AnimationState = require "spine-lua.AnimationState"
spine.EventData = require "spine-lua.EventData"
spine.Event = require "spine-lua.Event"
spine.SkeletonBounds = require "spine-lua.SkeletonBounds"
spine.BlendMode = require "spine-lua.BlendMode"
spine.TextureAtlas = require "spine-lua.TextureAtlas"
spine.TextureRegion = require "spine-lua.TextureRegion"
spine.TextureAtlasRegion = require "spine-lua.TextureAtlasRegion"
spine.AtlasAttachmentLoader = require "spine-lua.AtlasAttachmentLoader"
spine.Color = require "spine-lua.Color"

spine.utils.readJSON = json.decode

function spine.utils.readFile(file_name, base_path)
    local src = lfs.read(base_path and base_path.."/"..file_name or file_name)
    return src
end

function spine.utils.readImage(file_name, base_path)
    return image(spine.utils.readFile(file_name, base_path))
end

function spine.Actor:init(base_path, json_file, atlas_file)
    base_path = base_path or lfs.DROPBOX
    local image_loader = function(file) return spine.utils.readImage(file, base_path) end
    local atlas_data = spine.TextureAtlas.new(spine.utils.readFile(atlas_file, base_path), image_loader)
    local skeleton_data = spine.SkeletonJson.new(spine.AtlasAttachmentLoader.new(atlas_data))
    
self.skeleton = spine.Skeleton.new(skeleton_data:readSkeletonDataFile(json_file, base_path)) self.skeleton:setToSetupPose() self.mesh = mesh() self.mesh.vertex_buffer = self.mesh:buffer("position") self.mesh.texture_buffer = self.mesh:buffer("texCoord") self.mesh.color_buffer = self.mesh:buffer("color") end function spine.Actor:draw() self.skeleton:updateWorldTransform()
for i, slot in ipairs(self.skeleton.drawOrder) do local attachment = slot.attachment if attachment then local texture = attachment.region.renderObject.texture local vertices = attachment:updateWorldVertices(slot, true) local triangles if attachment.type == spine.AttachmentType.region then triangles = QUAD_TRIANGLES elseif attachment.type == spine.AttachmentType.mesh then triangles = attachment.triangles end if triangles then pushStyle() local faces = {} local uvs = {} local colors = {} local blend_mode = slot.data.blendMode if blend_mode == spine.BlendMode.additive then blendMode(ADDITIVE) elseif blend_mode == spine.BlendMode.multiply then blendMode(MULTIPLY) elseif blend_mode == spine.BlendMode.screen then blendMode(ONE, ONE_MINUS_SRC_COLOR) else blendMode(NORMAL) end --- blend_mode == spine.BlendMode.normal and undefined

--- triangulate and supply to GPU for j, id in ipairs(triangles) do --- listed in cw order local pos = id * 8 - 8 local vert = vec2(vertices[pos + 1], vertices[pos + 2]) local uv = vec2(vertices[pos + 3], 1 - vertices[pos + 4]) --- flip y local r = vertices[pos + 5] * 255 local g = vertices[pos + 6] * 255 local b = vertices[pos + 7] * 255 local a = vertices[pos + 8] * 255 table_insert(faces, vert) table_insert(uvs, uv) table_insert(colors, color(r, g, b, a)) end
self.mesh:clear() self.mesh.texture = texture self.mesh.vertex_buffer:set(faces) self.mesh.texture_buffer:set(uvs) self.mesh.color_buffer:set(colors) self.mesh:draw() popStyle() end end end end
Related Discussions
...

It looks like none of the meshes are being renderer, those that you see are all region attachments. Trying to figure out what is wrong when you see nothing is always a fun part of runtimes! Your code does look OK. I would guess that the problem is with how the Love mesh is rendered. Try dumping the data you pass to the mesh, then write a new Love app which doesn't use any runtimes, it just creates a mesh with the dumped data and renders it. If that doesn't work, something is up either with the data or the mesh, and it should be easier to figure out in the simpler app.

You have to set the skin on the Goblin for the male goblin attachments to be set on the slots. See spine-runtimes/main.lua at master and spine-runtimes/main.lua at master. Your rendering code looks good to me, so setting the skin should resolve the issue. The spear is actually a mesh attachment, which confirms that your rendering code is correct.

Aha, thanks badlogic!

@badlogic yes, yes, yes! That was it! Works perfect!

Thank you guys!

#edited

Awesome! We'd be happy to link to the Codea runtime on our Spine: Runtimes page.

un año más tarde

I contacted you on twitter!
Here is my announcement tweet with the forum discussion and link to the source code.
https://twitter.com/supacowa/status/839132375015649281


badlogic escribió

Awesome! We'd be happy to link to the Codea runtime on our Spine: Runtimes page.

@badlogic hey sorry for waking up an old thread but I noticed that you still didn't link it on your website.
Is there a problem with my repo or something? I'd be happy if more people could see that Codea does also support Spine. Please tell me whats wrong so I can fix this 🙂

Sorry, I totally forgot. Fixed!