mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-03-26 22:49:01 +08:00
231 lines
8.4 KiB
Lua
231 lines
8.4 KiB
Lua
-------------------------------------------------------------------------------
|
|
-- Spine Runtimes Software License
|
|
-- Version 2.3
|
|
--
|
|
-- Copyright (c) 2013-2015, Esoteric Software
|
|
-- All rights reserved.
|
|
--
|
|
-- You are granted a perpetual, non-exclusive, non-sublicensable and
|
|
-- non-transferable license to use, install, execute and perform the Spine
|
|
-- Runtimes Software (the "Software") and derivative works solely for personal
|
|
-- or internal use. Without the written permission of Esoteric Software (see
|
|
-- Section 2 of the Spine Software License Agreement), you may not (a) modify,
|
|
-- translate, adapt or otherwise create derivative works, improvements of the
|
|
-- Software or develop new applications using the Software or (b) remove,
|
|
-- delete, alter or obscure any trademarks or any copyright, trademark, patent
|
|
-- or other intellectual property or proprietary rights notices on or in the
|
|
-- Software, including any copy thereof. Redistributions in binary or source
|
|
-- form must include this license and terms.
|
|
--
|
|
-- THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 ESOTERIC SOFTWARE 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.IkConstraintData = require "spine-lua.IkConstraintData"
|
|
spine.Skin = require "spine-lua.Skin"
|
|
spine.RegionAttachment = require "spine-lua.RegionAttachment"
|
|
spine.MeshAttachment = require "spine-lua.MeshAttachment"
|
|
spine.SkinnedMeshAttachment = require "spine-lua.SkinnedMeshAttachment"
|
|
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.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.utils.readFile = function (fileName, base)
|
|
local path = fileName
|
|
if base then path = base .. '/' .. path end
|
|
return love.filesystem.read(path)
|
|
end
|
|
|
|
local json = require "spine-love.dkjson"
|
|
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)
|
|
local self = spine.Skeleton.new_super(skeletonData)
|
|
|
|
-- createImage can customize where images are found.
|
|
function self:createImage (attachment)
|
|
return love.graphics.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
|
|
|
|
if not self.attachments then self.attachments = {} end
|
|
local attachments = self.attachments
|
|
|
|
for i,slot in ipairs(self.drawOrder) do
|
|
local attachment = slot.attachment
|
|
if not attachment then
|
|
images[slot] = nil
|
|
elseif attachment.type == spine.AttachmentType.region then
|
|
local image = images[slot]
|
|
if image and attachments[image] ~= attachment then -- Attachment image has changed.
|
|
image = nil
|
|
end
|
|
if not image then -- Create new image.
|
|
image = self:createImage(attachment)
|
|
if image then
|
|
local imageWidth = image:getWidth()
|
|
local imageHeight = image:getHeight()
|
|
attachment.widthRatio = attachment.width / imageWidth
|
|
attachment.heightRatio = attachment.height / imageHeight
|
|
attachment.originX = imageWidth / 2
|
|
attachment.originY = imageHeight / 2
|
|
else
|
|
print("Error creating image: " .. attachment.name)
|
|
image = spine.Skeleton.failed
|
|
end
|
|
images[slot] = image
|
|
attachments[image] = attachment
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function self:draw()
|
|
if not self.images then self.images = {} end
|
|
local images = self.images
|
|
|
|
local r, g, b, a = self.r * 255, self.g * 255, self.b * 255, self.a * 255
|
|
|
|
for i,slot in ipairs(self.drawOrder) do
|
|
local image = images[slot]
|
|
if image and image ~= spine.Skeleton.failed then
|
|
local attachment = slot.attachment
|
|
local x = slot.bone.worldX + attachment.x * slot.bone.m00 + attachment.y * slot.bone.m01
|
|
local y = slot.bone.worldY + attachment.x * slot.bone.m10 + attachment.y * slot.bone.m11
|
|
local rotation = slot.bone.worldRotation + attachment.rotation
|
|
local xScale = slot.bone.worldScaleX + attachment.scaleX - 1
|
|
local yScale = slot.bone.worldScaleY + attachment.scaleY - 1
|
|
if self.flipX then
|
|
xScale = -xScale
|
|
rotation = -rotation
|
|
end
|
|
if self.flipY then
|
|
yScale = -yScale
|
|
rotation = -rotation
|
|
end
|
|
love.graphics.setColor(r * slot.r, g * slot.g, b * slot.b, a * slot.a)
|
|
if slot.data.blendMode == spine.BlendMode.normal then
|
|
love.graphics.setBlendMode("alpha")
|
|
elseif slot.data.blendMode == spine.BlendMode.additive then
|
|
love.graphics.setBlendMode("additive")
|
|
elseif slot.data.blendMode == spine.BlendMode.multiply then
|
|
love.graphics.setBlendMode("multiply")
|
|
elseif slot.data.blendMode == spine.BlendMode.screen then
|
|
love.graphics.setBlendMode("screen")
|
|
end
|
|
love.graphics.draw(image,
|
|
self.x + x,
|
|
self.y - y,
|
|
-rotation * 3.1415927 / 180,
|
|
xScale * attachment.widthRatio,
|
|
yScale * attachment.heightRatio,
|
|
attachment.originX,
|
|
attachment.originY)
|
|
end
|
|
end
|
|
|
|
-- Debug bones.
|
|
if self.debugBones then
|
|
for i,bone in ipairs(self.bones) do
|
|
local xScale
|
|
local yScale
|
|
local rotation = -bone.worldRotation
|
|
|
|
if self.flipX then
|
|
xScale = -1
|
|
rotation = -rotation
|
|
else
|
|
xScale = 1
|
|
end
|
|
|
|
if self.flipY then
|
|
yScale = -1
|
|
rotation = -rotation
|
|
else
|
|
yScale = 1
|
|
end
|
|
|
|
love.graphics.push()
|
|
love.graphics.translate(self.x + bone.worldX, self.y - bone.worldY)
|
|
love.graphics.rotate(rotation * 3.1415927 / 180)
|
|
love.graphics.scale(xScale, yScale)
|
|
love.graphics.setColor(255, 0, 0)
|
|
love.graphics.line(0, 0, bone.data.length, 0)
|
|
love.graphics.setColor(0, 255, 0)
|
|
love.graphics.circle('fill', 0, 0, 3)
|
|
love.graphics.pop()
|
|
end
|
|
end
|
|
|
|
-- Debug slots.
|
|
if self.debugSlots then
|
|
love.graphics.setColor(0, 0, 255, 128)
|
|
for i,slot in ipairs(self.drawOrder) do
|
|
local attachment = slot.attachment
|
|
if attachment and attachment.type == spine.AttachmentType.region then
|
|
local x = slot.bone.worldX + attachment.x * slot.bone.m00 + attachment.y * slot.bone.m01
|
|
local y = slot.bone.worldY + attachment.x * slot.bone.m10 + attachment.y * slot.bone.m11
|
|
local rotation = slot.bone.worldRotation + attachment.rotation
|
|
local xScale = slot.bone.worldScaleX + attachment.scaleX - 1
|
|
local yScale = slot.bone.worldScaleY + attachment.scaleY - 1
|
|
if self.flipX then
|
|
xScale = -xScale
|
|
rotation = -rotation
|
|
end
|
|
if self.flipY then
|
|
yScale = -yScale
|
|
rotation = -rotation
|
|
end
|
|
love.graphics.push()
|
|
love.graphics.translate(self.x + x, self.y - y)
|
|
love.graphics.rotate(-rotation * 3.1415927 / 180)
|
|
love.graphics.scale(xScale, yScale)
|
|
love.graphics.rectangle('line', -attachment.width / 2, -attachment.height / 2, attachment.width, attachment.height)
|
|
love.graphics.pop()
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
return self
|
|
end
|
|
|
|
return spine
|