jack0088

  • 8 квiт 2019 р.
  • Приєднався 5 бер 2017 р.
  • 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 написав

    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 🙂

  • у «scalling»

    I knew something takes priority and overrides it. Now I know what - thank you for giving some insight. A solution would be to nest the "root bone" into another root bone. And never key the top most bone... I guess it should work.

    I ended up modifying the viewMatrix. In Codea, this works same as love.graphics.scale() which scales all fallowing drawings. This is quick and works flawless in any case.

    I knew I could set the scale factor when loading the data, but I needed also a way to do this dynamically when needed (e.g. Point-And-Click game when character walks away and gets smaller).

    Thank you for the quick responses.
    You all do great work.

  • у «scalling»

    I took the unmodified example files from the export folder (raptor.json, raptor.atlas, raptor.png).

    This is my setup.

    local raptor = spine.Actor(lfs.DROPBOX.."/spine-data", "raptor.json", "raptor.atlas")
    raptor:setPosition(-200, 0) 
    
    ---
    
     sets skeleton.x and skeleton.y
    raptor:setScale(.25) 
    
    ---
    
     scales the root bone as shown in post above
    raptor:setAnimation("walk") 
    
    ---
    
     play a sequence of chained animations
    raptor:queueAnimation("walk") 
    
    ---
    
     build animation queue
    raptor:queueAnimation("walk")
    raptor:queueAnimation("Jump")
    raptor:queueAnimation("walk", true)

    This is what the *:setAnimation() and *:queueAnimation() methods do.
    Basically I wrapped some spine methods for convenience. All animations play only on one track entry.

    function spine.Actor:setAnimation(new_animation_name, loop, crossfade_time)
        local track_entry = self.animation:setAnimationByName(0, new_animation_name, loop)
        track_entry.mixDuration = crossfade_time or .25
    end
    
    function spine.Actor:queueAnimation(animation_name, loop, delay)
        self.animation:addAnimationByName(0, animation_name, loop, delay or 0)
    end

    self.animation is an AnimationState.new() instance.

  • у «scalling»

    Worked for me on some example-projects, but not for the "raptor" example.
    Playing the "Jump" animation with the "root" bone scaled down has no effect on the skeleton and attachments size at all.
    Other animations like "walk" do work fine. Please see the screenshot.

    Am I doing it wrong or was something "keyed" that gets priority at runtime?

    local root_bone = self.skeleton:findBone(root_bone_name or "root")
    root_bone.scaleX = new_scale_x
    root_bone.scaleY = new_scale_y or new_scale_x

    (played animation queue: walk, walk, jump, walk)

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

    Thank you guys!

    #edited

    • Змінено

    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