spine-lua generic Lua runtime, refactored spine-corona.

This commit is contained in:
NathanSweet 2013-04-19 10:54:15 +02:00
parent 5a46f8c6b4
commit 9e49979db1
16 changed files with 195 additions and 167 deletions

3
.gitignore vendored
View File

@ -41,3 +41,6 @@ spine-unity/*.sln
*.pidb *.pidb
Assembly-*.csproj Assembly-*.csproj
Assembly-*.pidb Assembly-*.pidb
spine-corona/spine-lua/
!spine-corona/spine-lua/Place spine-lua here.txt

View File

@ -1,21 +1,16 @@
local spine = require "spine.spine" local spine = require "spine-corona.spine"
-- Using your own attachment loader is optional. It can customizes the path where images are local json = spine.SkeletonJson.new()
-- loaded. To load from a texture atlas, use an image sheet. It also creates instances of
-- all attachments, which can be used for customization.
local attachmentLoader = spine.AttachmentLoader.new()
function attachmentLoader:createImage (attachment)
return display.newImage("data/" .. attachment.name .. ".png")
end
local json = spine.SkeletonJson.new(attachmentLoader)
json.scale = 1 json.scale = 1
local skeletonData = json:readSkeletonDataFile("data/spineboy.json") local skeletonData = json:readSkeletonDataFile("data/spineboy.json")
local walkAnimation = skeletonData:findAnimation("walk") local walkAnimation = skeletonData:findAnimation("walk")
-- Optional second parameter can be the group for the Skeleton to use. Eg, could be an image group.
local skeleton = spine.Skeleton.new(skeletonData) local skeleton = spine.Skeleton.new(skeletonData)
function skeleton:createImage (attachment)
-- Customize where images are loaded.
return display.newImage("data/" .. attachment.name .. ".png")
end
skeleton.x = 150 skeleton.x = 150
skeleton.y = 325 skeleton.y = 325
skeleton.flipX = false skeleton.flipX = false

View File

@ -0,0 +1,154 @@
-------------------------------------------------------------------------------
-- Copyright (c) 2013, Esoteric Software
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- 1. Redistributions of source code must retain the above copyright notice, this
-- list of conditions and the following disclaimer.
-- 2. Redistributions in binary form must reproduce the above copyright notice,
-- this list of conditions and the following disclaimer in the documentation
-- and/or other materials provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-- ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
------------------------------------------------------------------------------
spine = {}
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.Skin = require "spine-lua.Skin"
spine.RegionAttachment = require "spine-lua.RegionAttachment"
spine.Skeleton = require "spine-lua.Skeleton"
spine.Bone = require "spine-lua.Bone"
spine.Slot = require "spine-lua.Slot"
spine.AttachmentLoader = require "spine-lua.AttachmentLoader"
spine.Animation = require "spine-lua.Animation"
spine.utils.readFile = function (fileName, base)
if not base then base = system.ResourceDirectory end
local path = system.pathForFile(fileName, base)
local file = io.open(path, "r")
if not file then return nil end
local contents = file:read("*a")
io.close(file)
return contents
end
local json = require "json"
spine.utils.readJSON = function (text)
return json.decode(text)
end
spine.Skeleton.failed = {} -- Placeholder for an image that failed to load.
spine.Skeleton.new_super = spine.Skeleton.new
function spine.Skeleton.new (skeletonData, group)
-- Skeleton extends a group.
local self = spine.Skeleton.new_super(skeletonData)
self = spine.utils.copy(self, group or display.newGroup())
-- createImage can customize where images are found.
function self:createImage (attachment)
return display.newImage(attachment.name .. ".png")
end
-- updateWorldTransform positions images.
local updateWorldTransform_super = self.updateWorldTransform
function self:updateWorldTransform ()
updateWorldTransform_super(self)
if not self.images then self.images = {} end
local images = self.images
for i,slot in ipairs(self.drawOrder) do
local attachment = slot.attachment
local image = images[attachment]
if not attachment then
-- Attachment is gone, remove the image.
if image then
image:removeSelf()
images[attachment] = nil
end
else
-- Create new image.
if not image then
image = self:createImage(attachment)
if image then
image:setReferencePoint(display.CenterReferencePoint)
image.width = attachment.width
image.height = attachment.height
else
print("Error creating image: " .. attachment.name)
image = spine.Skeleton.failed
end
images[attachment] = image
end
-- Position image based on attachment and bone.
if image ~= spine.Skeleton.failed then
image.x = slot.bone.worldX + attachment.x * slot.bone.m00 + attachment.y * slot.bone.m01
image.y = -(slot.bone.worldY + attachment.x * slot.bone.m10 + attachment.y * slot.bone.m11)
image.rotation = -(slot.bone.worldRotation + attachment.rotation)
image.xScale = slot.bone.worldScaleX + attachment.scaleX - 1
image.yScale = slot.bone.worldScaleY + attachment.scaleY - 1
if self.flipX then
image.xScale = -image.xScale
image.rotation = -image.rotation
end
if self.flipY then
image.yScale = -image.yScale
image.rotation = -image.rotation
end
image:setFillColor(slot.r, slot.g, slot.b, slot.a)
self:insert(image)
end
end
end
if self.debug then
for i,bone in ipairs(self.bones) do
if not bone.line then bone.line = display.newLine(0, 0, bone.data.length, 0) end
bone.line.x = bone.worldX
bone.line.y = -bone.worldY
bone.line.rotation = -bone.worldRotation
if self.flipX then
bone.line.xScale = -1
bone.line.rotation = -bone.line.rotation
else
bone.line.xScale = 1
end
if self.flipY then
bone.line.yScale = -1
bone.line.rotation = -bone.line.rotation
else
bone.line.yScale = 1
end
bone.line:setColor(255, 0, 0)
self:insert(bone.line)
if not bone.circle then bone.circle = display.newCircle(0, 0, 3) end
bone.circle.x = bone.worldX
bone.circle.y = -bone.worldY
bone.circle:setFillColor(0, 255, 0)
self:insert(bone.circle)
end
end
end
return self
end
return spine

View File

@ -1,41 +0,0 @@
-------------------------------------------------------------------------------
-- Copyright (c) 2013, Esoteric Software
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- 1. Redistributions of source code must retain the above copyright notice, this
-- list of conditions and the following disclaimer.
-- 2. Redistributions in binary form must reproduce the above copyright notice,
-- this list of conditions and the following disclaimer in the documentation
-- and/or other materials provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-- ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
------------------------------------------------------------------------------
local spine = {}
spine.utils = require "spine.utils"
spine.SkeletonJson = require "spine.SkeletonJson"
spine.SkeletonData = require "spine.SkeletonData"
spine.BoneData = require "spine.BoneData"
spine.SlotData = require "spine.SlotData"
spine.Skin = require "spine.Skin"
spine.RegionAttachment = require "spine.RegionAttachment"
spine.Skeleton = require "spine.Skeleton"
spine.Bone = require "spine.Bone"
spine.Slot = require "spine.Slot"
spine.AttachmentLoader = require "spine.AttachmentLoader"
spine.Animation = require "spine.Animation"
return spine

View File

@ -23,8 +23,6 @@
-- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
local utils = require "spine.utils"
local Animation = {} local Animation = {}
function Animation.new (name, timelines, duration) function Animation.new (name, timelines, duration)
if not timelines then error("timelines cannot be nil", 2) end if not timelines then error("timelines cannot be nil", 2) end

View File

@ -23,7 +23,7 @@
-- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
local RegionAttachment = require "spine.RegionAttachment" local RegionAttachment = require "spine-lua.RegionAttachment"
local AttachmentLoader = { local AttachmentLoader = {
failed = {}, failed = {},
@ -39,10 +39,6 @@ function AttachmentLoader.new ()
error("Unknown attachment type: " .. type .. " (" + name + ")") error("Unknown attachment type: " .. type .. " (" + name + ")")
end end
function self:createImage (attachment)
return display.newImage(attachment.name .. ".png")
end
return self return self
end end
return AttachmentLoader return AttachmentLoader

View File

@ -24,6 +24,7 @@
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
local Bone = {} local Bone = {}
function Bone.new (data, parent) function Bone.new (data, parent)
if not data then error("data cannot be nil", 2) end if not data then error("data cannot be nil", 2) end

View File

@ -23,91 +23,25 @@
-- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
local utils = require "spine.utils" local Bone = require "spine-lua.Bone"
local Bone = require "spine.Bone" local Slot = require "spine-lua.Slot"
local Slot = require "spine.Slot" local AttachmentLoader = require "spine-lua.AttachmentLoader"
local AttachmentLoader = require "spine.AttachmentLoader"
local Skeleton = {} local Skeleton = {}
function Skeleton.new (skeletonData, group) function Skeleton.new (skeletonData)
if not skeletonData then error("skeletonData cannot be nil", 2) end if not skeletonData then error("skeletonData cannot be nil", 2) end
local self = group or display.newGroup() local self = {
self.data = skeletonData data = skeletonData,
self.bones = {} bones = {},
self.slots = {} slots = {},
self.drawOrder = {} drawOrder = {}
self.images = {} }
function self:updateWorldTransform () function self:updateWorldTransform ()
for i,bone in ipairs(self.bones) do for i,bone in ipairs(self.bones) do
bone:updateWorldTransform(self.flipX, self.flipY) bone:updateWorldTransform(self.flipX, self.flipY)
end end
for i,slot in ipairs(self.drawOrder) do
local attachment = slot.attachment
if attachment then
local image = self.images[attachment]
if not image then
image = self.data.attachmentLoader:createImage(attachment)
if image then
image:setReferencePoint(display.CenterReferencePoint);
image.width = attachment.width
image.height = attachment.height
else
print("Error creating image: " .. attachment.name)
image = AttachmentLoader.failed
end
self.images[attachment] = image
end
if image ~= AttachmentLoader.failed then
image.x = slot.bone.worldX + attachment.x * slot.bone.m00 + attachment.y * slot.bone.m01
image.y = -(slot.bone.worldY + attachment.x * slot.bone.m10 + attachment.y * slot.bone.m11)
image.rotation = -(slot.bone.worldRotation + attachment.rotation)
image.xScale = slot.bone.worldScaleX + attachment.scaleX - 1
image.yScale = slot.bone.worldScaleY + attachment.scaleY - 1
if self.flipX then
image.xScale = -image.xScale
image.rotation = -image.rotation
end
if self.flipY then
image.yScale = -image.yScale
image.rotation = -image.rotation
end
image:setFillColor(slot.r, slot.g, slot.b, slot.a)
self:insert(image)
end
end
end
if self.debug then
for i,bone in ipairs(self.bones) do
if not bone.line then bone.line = display.newLine(0, 0, bone.data.length, 0) end
bone.line.x = bone.worldX
bone.line.y = -bone.worldY
bone.line.rotation = -bone.worldRotation
if self.flipX then
bone.line.xScale = -1
bone.line.rotation = -bone.line.rotation
else
bone.line.xScale = 1
end
if self.flipY then
bone.line.yScale = -1
bone.line.rotation = -bone.line.rotation
else
bone.line.yScale = 1
end
bone.line:setColor(255, 0, 0)
self:insert(bone.line)
if not bone.circle then bone.circle = display.newCircle(0, 0, 3) end
bone.circle.x = bone.worldX
bone.circle.y = -bone.worldY
bone.circle:setFillColor(0, 255, 0)
self:insert(bone.circle)
end
end
end end
function self:setToBindPose () function self:setToBindPose ()
@ -192,12 +126,12 @@ function Skeleton.new (skeletonData, group)
for i,boneData in ipairs(skeletonData.bones) do for i,boneData in ipairs(skeletonData.bones) do
local parent local parent
if boneData.parent then parent = self.bones[utils.indexOf(skeletonData.bones, boneData.parent)] end if boneData.parent then parent = self.bones[spine.utils.indexOf(skeletonData.bones, boneData.parent)] end
table.insert(self.bones, Bone.new(boneData, parent)) table.insert(self.bones, Bone.new(boneData, parent))
end end
for i,slotData in ipairs(skeletonData.slots) do for i,slotData in ipairs(skeletonData.slots) do
local bone = self.bones[utils.indexOf(skeletonData.bones, slotData.boneData)] local bone = self.bones[spine.utils.indexOf(skeletonData.bones, slotData.boneData)]
local slot = Slot.new(slotData, self, bone) local slot = Slot.new(slotData, self, bone)
table.insert(self.slots, slot) table.insert(self.slots, slot)
table.insert(self.drawOrder, slot) table.insert(self.drawOrder, slot)

View File

@ -24,11 +24,8 @@
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
local SkeletonData = {} local SkeletonData = {}
function SkeletonData.new (attachmentLoader) function SkeletonData.new ()
if not attachmentLoader then error("attachmentLoader cannot be nil", 2) end
local self = { local self = {
attachmentLoader = attachmentLoader,
bones = {}, bones = {},
slots = {}, slots = {},
skins = {}, skins = {},

View File

@ -23,14 +23,12 @@
-- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
local utils = require "spine.utils" local SkeletonData = require "spine-lua.SkeletonData"
local SkeletonData = require "spine.SkeletonData" local BoneData = require "spine-lua.BoneData"
local BoneData = require "spine.BoneData" local SlotData = require "spine-lua.SlotData"
local SlotData = require "spine.SlotData" local Skin = require "spine-lua.Skin"
local Skin = require "spine.Skin" local AttachmentLoader = require "spine-lua.AttachmentLoader"
local AttachmentLoader = require "spine.AttachmentLoader" local Animation = require "spine-lua.Animation"
local Animation = require "spine.Animation"
local json = require "json"
local TIMELINE_SCALE = "scale" local TIMELINE_SCALE = "scale"
local TIMELINE_ROTATE = "rotate" local TIMELINE_ROTATE = "rotate"
@ -48,7 +46,7 @@ function SkeletonJson.new (attachmentLoader)
} }
function self:readSkeletonDataFile (fileName, base) function self:readSkeletonDataFile (fileName, base)
return self:readSkeletonData(utils.readFile(fileName, base)) return self:readSkeletonData(spine.utils.readFile(fileName, base))
end end
local readAttachment local readAttachment
@ -58,7 +56,7 @@ function SkeletonJson.new (attachmentLoader)
function self:readSkeletonData (jsonText) function self:readSkeletonData (jsonText)
local skeletonData = SkeletonData.new(self.attachmentLoader) local skeletonData = SkeletonData.new(self.attachmentLoader)
local root = json.decode(jsonText) local root = spine.utils.readJSON(jsonText)
if not root then error("Invalid JSON: " .. jsonText, 2) end if not root then error("Invalid JSON: " .. jsonText, 2) end
-- Bones. -- Bones.
@ -127,6 +125,7 @@ function SkeletonJson.new (attachmentLoader)
end end
end end
-- Animations.
map = root["animations"] map = root["animations"]
if map then if map then
for animationName,animationMap in pairs(map) do for animationName,animationMap in pairs(map) do

View File

@ -23,8 +23,6 @@
-- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
local utils = require "spine.utils"
local Slot = {} local Slot = {}
function Slot.new (slotData, skeleton, bone) function Slot.new (slotData, skeleton, bone)
if not slotData then error("slotData cannot be nil", 2) end if not slotData then error("slotData cannot be nil", 2) end
@ -45,10 +43,6 @@ function Slot.new (slotData, skeleton, bone)
end end
function self:setAttachment (attachment) function self:setAttachment (attachment)
if self.attachment and self.attachment ~= attachment and self.skeleton.images[self.attachment] then
self.skeleton.images[self.attachment]:removeSelf()
self.skeleton.images[self.attachment] = nil
end
self.attachment = attachment self.attachment = attachment
self.attachmentTime = self.skeleton.time self.attachmentTime = self.skeleton.time
end end

View File

@ -25,16 +25,6 @@
local utils = {} local utils = {}
utils.readFile = function (fileName, base)
if not base then base = system.ResourceDirectory; end
local path = system.pathForFile(fileName, base)
local file = io.open(path, "r")
if not file then return nil; end
local contents = file:read("*a")
io.close(file)
return contents
end
function tablePrint (tt, indent, done) function tablePrint (tt, indent, done)
done = done or {} done = done or {}
indent = indent or 0 indent = indent or 0
@ -80,4 +70,12 @@ function utils.indexOf (haystack, needle)
return nil return nil
end end
function utils.copy (from, to)
if not to then to = {} end
for k,v in pairs(from) do
to[k] = v
end
return to
end
return utils return utils