Merge remote-tracking branch 'origin/3.6' into 3.6

This commit is contained in:
NathanSweet 2017-07-31 13:15:03 +02:00
commit e62d8a921c
185 changed files with 10673 additions and 7014 deletions

3
.gitignore vendored
View File

@ -55,6 +55,7 @@ spine-xna/obj
spine-xna/example/bin
spine-xna/example/obj
spine-xna/example-content/obj/
spine-xna/.vs/
spine-unity/Assets/spine-csharp*
!spine-unity/Assets/spine-csharp/Place spine-csharp src here.*
@ -107,3 +108,5 @@ spine-ue4/SpineUE4.VC.opendb
spine-ue4/SpineUE4.VC.db
spine-ue4/SpineUE4.sln
spine-ue4/SpineUE4.VC.db
spine-ue4/.vs/
spine-ue4/SpineUE4.VC.VC.opendb

View File

@ -17,12 +17,14 @@
* Added `ClippingAttachment`, additional method `newClippingAttachment` in `AttachmentLoader` interface.
* `AnimationState#apply` returns boolean indicating if any timeline was applied or not.
* `Animation#apply` and `Timeline#apply`` now take enums `MixPose` and `MixDirection` instead of booleans
* Added `VertexEffect` and implementations `JitterEffect` and `SwirlEffect`. Allows you to modify vertices before they are submitted for drawing. See Starling changes.
### Starling
* Fixed renderer to work with 3.6 changes.
* Added support for two color tinting.
* Added support for clipping.
* Added support for rotated regions in texture atlas loaded via StarlingAtlasAttachmentLoader.
* Added support for vertex effects. See `RaptorExample.as`
## C
* **Breaking changes**
@ -46,6 +48,8 @@
* Added `spSkeletonClipper` and `spTriangulator`, used to implement software clipping of attachments.
* `AnimationState#apply` returns boolean indicating if any timeline was applied or not.
* `Animation#apply` and `Timeline#apply`` now take enums `MixPose` and `MixDirection` instead of booleans
* Added `spVertexEffect` and corresponding implementations `spJitterVertexEffect` and `spSwirlVertexEffect`. Create/dispose through the corresponding `spXXXVertexEffect_create()/dispose()` functions. Set on framework/engine specific renderer. See changes for spine-c based frameworks/engines below.
* Functions in `extension.h` are not prefixed with `_sp` instead of just `_` to avoid interference with other libraries.
### Cocos2d-X
* Fixed renderer to work with 3.6 changes
@ -55,6 +59,7 @@
* Added mesh debug rendering. Enable/Disable via `SkeletonRenderer::setDebugMeshesEnabled()`.
* Added support for clipping.
* SkeletonRenderer now combines the displayed color of the Node (cascaded from all parents) with the skeleton color for tinting.
* Added support for vertex effects. See `RaptorExample.cpp`.
### Cocos2d-Objc
* Fixed renderer to work with 3.6 changes
@ -64,6 +69,7 @@
### SFML
* Fixed renderer to work with 3.6 changes. Sadly, two color tinting does not work, as the vertex format in SFML is fixed.
* Added support for clipping.
* Added support for vertex effects. See raptor example.
### Unreal Engine 4
* Fixed renderer to work with 3.6 changes
@ -134,6 +140,7 @@
* Removed `RegionBatcher` and `SkeletonRegionRenderer`, renamed `SkeletonMeshRenderer` to `SkeletonRenderer`
* Added support for two color tint. For it to work, you need to add the `SpineEffect.fx` file to your content project, then load it via `var effect = Content.Load<Effect>("SpineEffect");`, and set it on the `SkeletonRenderer`. See the example project for code.
* Added support for any `Effect` to be used by `SkeletonRenderer`
* Added `SkeletonDebugRenderer`
## Java
* **Breaking changes**
@ -174,15 +181,18 @@
* Added `SkeletonClipper` and `Triangulator`, used to implement software clipping of attachments.
* `AnimationState#apply` returns boolean indicating if any timeline was applied or not.
* `Animation#apply` and `Timeline#apply`` now take enums `MixPose` and `MixDirection` instead of booleans
* Added `JitterEffect` and `SwirlEffect` and support for vertex effects in Corona and Love
### Love2D
* Fixed renderer to work with 3.6 changes
* Added support for two color tinting. Enable it via `SkeletonRenderer.new(true)`.
* Added clipping support.
* Added support for vertex effects. Set an implementation like "JitterEffect" on `Skeleton.vertexEffect`. See `main.lua` for an example.
### Corona
* Fixed renderer to work with 3.6 changes. Sadly, two color tinting is not supported, as Corona doesn't let us change the vertex format needed and its doesn't allow to modify shaders in the way needed for two color tinting
* Added clipping support.
* Added support for vertex effects. Set an implementation like "JitterEffect" on `SkeletonRenderer.vertexEffect`. See `main.lua` for an example
## Typescript/Javascript
* **Breaking changes**
@ -216,6 +226,7 @@
* Improved performance by using `DYNAMIC_DRAW` for vertex buffer objects and fixing bug that copied to much data to the GPU each frame in `PolygonBatcher`/`Mesh`.
* Added two color tinting support, enabled by default. You can disable it via the constructors of `SceneRenderer`, `SkeletonRenderer`and `PolygonBatcher`. Note that you will need to use a shader created via `Shader.newTwoColoredTexturedShader` shader with `SkeletonRenderer` and `PolygonBatcher` if two color tinting is enabled.
* Added clipping support
* Added `VertexEffect` interface, instances of which can be set on `SkeletonRenderer`. Allows to modify vertices before submitting them to GPU. See `SwirlEffect`, `JitterEffect`, and the example which allows to set effects.
### Canvas backend
* Fixed renderer to work for 3.6 changes. Sadly, we can't support two color tinting via the Canvas API.
@ -225,6 +236,7 @@
### Three.js backend
* Fixed renderer to work with 3.6 changes. Two color tinting is not supported.
* Added clipping support
* Added `VertexEffect` interface, instances of which can be set on `SkeletonMesh`. Allows to modify vertices before submitting them to GPU. See `SwirlEffect`, `JitterEffect`.
### Widget backend
* Fixed WebGL context loss (see WebGL backend changes). Enabled automatically.

View File

@ -10,7 +10,7 @@ The Spine Runtimes are developed with the intent to be used with data exported f
## Spine version
spine-as3 works with data exported from Spine 3.5.xx.
spine-as3 works with data exported from Spine 3.6.xx.
spine-as3 supports all Spine features, including meshes. If using the `spine.flash` classes for rendering, meshes are not supported.
@ -18,7 +18,7 @@ spine-as3 does not yet support loading the binary format.
## Usage
1. Create a new Flex or Adobe AIR project in your preferred IDE.
2. Download the Spine Runtimes source using git (`git clone https://github.com/esotericsoftware/spine-runtimes`) or download it [as a zip](https://github.com/EsotericSoftware/spine-runtimes/archive/master.zip)
2. Download the Spine Runtimes source using git (`git clone https://github.com/esotericsoftware/spine-runtimes`) or download it [as a zip](https://github.com/EsotericSoftware/spine-runtimes/archive/3.6.zip)
3. Add the sources from `spine-as3/spine-as3/src/` to your project
## Example

View File

@ -1,10 +1,18 @@
eclipse.preferences.version=1
encoding//src/spine/Interpolation.as=UTF-8
encoding//src/spine/MathUtils.as=UTF-8
encoding//src/spine/SkeletonClipping.as=UTF-8
encoding//src/spine/SkeletonJson.as=UTF-8
encoding//src/spine/Triangulator.as=UTF-8
encoding//src/spine/Vertex.as=UTF-8
encoding//src/spine/VertexEffect.as=UTF-8
encoding//src/spine/animation/MixDirection.as=UTF-8
encoding//src/spine/animation/MixPose.as=UTF-8
encoding//src/spine/animation/TwoColorTimeline.as=UTF-8
encoding//src/spine/attachments/ClippingAttachment.as=UTF-8
encoding//src/spine/attachments/PointAttachment.as=UTF-8
encoding//src/spine/interpolation/Pow.as=UTF-8
encoding//src/spine/interpolation/PowOut.as=UTF-8
encoding//src/spine/vertexeffects/JitterEffect.as=UTF-8
encoding//src/spine/vertexeffects/SwirlEffect.as=UTF-8
encoding/<project>=UTF-8

View File

@ -188,14 +188,14 @@ package spine {
lb = MathUtils.cosDeg(90 + shearY) * scaleY;
lc = MathUtils.sinDeg(shearX) * scaleX;
ld = MathUtils.sinDeg(90 + shearY) * scaleY;
if (this.data.transformMode != TransformMode.noScaleOrReflection ? pa * pd - pb * pc < 0 : this.skeleton.flipX != this.skeleton.flipY) {
zb = -zb;
zd = -zd;
}
this.a = za * la + zb * lc;
this.b = za * lb + zb * ld;
this.c = zc * la + zd * lc;
this.d = zc * lb + zd * ld;
if (this.data.transformMode != TransformMode.noScaleOrReflection ? pa * pd - pb * pc < 0 : skeleton.flipX != skeleton.flipY) {
this.b = -this.b;
this.d = -this.d;
}
this.d = zc * lb + zd * ld;
return;
}
}

View File

@ -0,0 +1,41 @@
/******************************************************************************
* Spine Runtimes Software License v2.5
*
* Copyright (c) 2013-2016, 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 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 develop new applications using the Spine Runtimes or otherwise
* create derivative works or improvements of the Spine Runtimes 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, BUSINESS INTERRUPTION, OR LOSS OF
* USE, DATA, OR PROFITS) 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.
*****************************************************************************/
package spine {
public class Interpolation {
protected function applyInternal (a : Number) : Number {
return a;
}
public function apply (start : Number, end : Number, a : Number) : Number {
return start + (end - start) * applyInternal(a);
}
}
}

View File

@ -27,7 +27,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
package spine {
public class MathUtils {
static public var PI : Number = Math.PI;
@ -52,5 +52,16 @@ package spine {
static public function signum(value : Number) : Number {
return value > 0 ? 1 : value < 0 ? -1 : 0;
}
static public function randomTriangular(min : Number, max : Number) : Number {
return randomTriangularWith(min, max, (min + max) * 0.5);
}
static public function randomTriangularWith(min : Number, max : Number, mode : Number) : Number {
var u : Number = Math.random();
var d : Number = max - min;
if (u <= (mode - min) / d) return min + Math.sqrt(u * d * (mode - min));
return max - Math.sqrt((1 - u) * d * (max - mode));
}
}
}

View File

@ -87,7 +87,9 @@ package spine {
}
for (var i : int = 0, n : int = spacesCount - 1; i < n;) {
var bone : Bone = bones[i];
var setupLength : Number = bone.data.length, x : Number = setupLength * bone.a, y : Number = setupLength * bone.c;
var setupLength : Number = bone.data.length;
if (setupLength == 0) setupLength = 0.000000001;
var x : Number = setupLength * bone.a, y : Number = setupLength * bone.c;
var length : Number = Math.sqrt(x * x + y * y);
if (scale) lengths[i] = length;
spaces[++i] = (lengthSpacing ? setupLength + spacing : spacing) * length / setupLength;

View File

@ -0,0 +1,45 @@
/******************************************************************************
* Spine Runtimes Software License v2.5
*
* Copyright (c) 2013-2016, 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 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 develop new applications using the Spine Runtimes or otherwise
* create derivative works or improvements of the Spine Runtimes 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, BUSINESS INTERRUPTION, OR LOSS OF
* USE, DATA, OR PROFITS) 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.
*****************************************************************************/
package spine {
/**
* @author badlogic
*/
public class Vertex {
public var x : Number;
public var y : Number;
public var u : Number;
public var v : Number;
public var light : Color = new spine.Color(0, 0, 0);
public var dark : Color = new spine.Color(0, 0, 0);
function Vertex() { }
}
}

View File

@ -0,0 +1,39 @@
/******************************************************************************
* Spine Runtimes Software License v2.5
*
* Copyright (c) 2013-2016, 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 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 develop new applications using the Spine Runtimes or otherwise
* create derivative works or improvements of the Spine Runtimes 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, BUSINESS INTERRUPTION, OR LOSS OF
* USE, DATA, OR PROFITS) 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.
*****************************************************************************/
package spine {
public interface VertexEffect {
function begin(skeleton : Skeleton) : void;
function transform(vertex : Vertex) : void;
function end() : void;
}
}

View File

@ -551,14 +551,10 @@ package spine.animation {
animationsChanged = false;
var propertyIDs : Dictionary = this.propertyIDs = new Dictionary();
var mixingTo : Vector.<TrackEntry> = this.mixingTo;
var lastEntry : TrackEntry = null;
var mixingTo : Vector.<TrackEntry> = this.mixingTo;
for (var i : int = 0, n : int = tracks.length; i < n; i++) {
var entry : TrackEntry = tracks[i];
if (entry != null) {
entry.setTimelineData(lastEntry, mixingTo, propertyIDs);
lastEntry = entry;
}
if (entry != null) entry.setTimelineData(null, mixingTo, propertyIDs);
}
}

View File

@ -36,6 +36,7 @@ package spine.animation {
import spine.Slot;
public class DeformTimeline extends CurveTimeline {
private static var zeros : Vector.<Number> = new Vector.<Number>(64);
public var slotIndex : int;
public var frames : Vector.<Number>;
public var frameVertices : Vector.<Vector.<Number>>;
@ -58,35 +59,54 @@ package spine.animation {
}
override public function apply(skeleton : Skeleton, lastTime : Number, time : Number, firedEvents : Vector.<Event>, alpha : Number, pose : MixPose, direction : MixDirection) : void {
var vertexAttachment : VertexAttachment;
var setupVertices : Vector.<Number>;
var slot : Slot = skeleton.slots[slotIndex];
var slotAttachment : Attachment = slot.attachment;
if (!(slotAttachment is VertexAttachment) || !(VertexAttachment(slotAttachment)).applyDeform(attachment)) return;
var verticesArray : Vector.<Number> = slot.attachmentVertices;
var frameVertices : Vector.<Vector.<Number>> = this.frameVertices;
var vertexCount : int = frameVertices[0].length;
if (verticesArray.length != vertexCount && pose != MixPose.setup) alpha = 1; // Don't mix from uninitialized slot vertices.
var vertexCount : int = frameVertices[0].length;
verticesArray.length = vertexCount;
var vertices : Vector.<Number> = verticesArray;
var frames : Vector.<Number> = this.frames;
var i : int;
if (time < frames[0]) {
vertexAttachment = VertexAttachment(slotAttachment);
switch (pose) {
case MixPose.setup:
verticesArray.length = 0;
var zeroVertices : Vector.<Number>;
if (vertexAttachment.bones == null) {
// Unweighted vertex positions (setup pose).
zeroVertices = vertexAttachment.vertices;
} else {
// Weighted deform offsets (zeros).
zeroVertices = zeros;
if (zeroVertices.length < vertexCount) zeros = zeroVertices = new Vector.<Number>(vertexCount);
}
for (i = 0; i < vertexCount; i++)
vertices[i] = zeroVertices[i];
return;
case MixPose.current:
alpha = 1 - alpha;
for (i = 0; i < vertexCount; i++)
vertices[i] *= alpha;
if (alpha == 1) break;
if (vertexAttachment.bones == null) {
// Unweighted vertex positions.
setupVertices = vertexAttachment.vertices;
for (i = 0; i < vertexCount; i++)
vertices[i] += (setupVertices[i] - vertices[i]) * alpha;
} else {
// Weighted deform offsets.
alpha = 1 - alpha;
for (i = 0; i < vertexCount; i++)
vertices[i] *= alpha;
}
}
return;
}
var n : int;
var vertexAttachment : VertexAttachment;
var setupVertices : Vector.<Number>;
var n : int;
var setup : Number, prev : Number;
if (time >= frames[frames.length - 1]) { // Time is after last frame.
var lastVertices : Vector.<Number> = frameVertices[frames.length - 1];

View File

@ -69,29 +69,29 @@ package spine.attachments {
public function updateOffset() : void {
var regionScaleX : Number = width / regionOriginalWidth * scaleX;
var regionScaleY : Number = height / regionOriginalHeight * scaleY;
var localX : Number = -width / 2 * scaleX + regionOffsetX * regionScaleX;
var localY : Number = -height / 2 * scaleY + regionOffsetY * regionScaleY;
var localX : Number = -width * 0.5 * scaleX + regionOffsetX * regionScaleX;
var localY : Number = -height * 0.5 * scaleY + regionOffsetY * regionScaleY;
var localX2 : Number = localX + regionWidth * regionScaleX;
var localY2 : Number = localY + regionHeight * regionScaleY;
var radians : Number = rotation * Math.PI / 180;
var cos : Number = Math.cos(radians);
var sin : Number = Math.sin(radians);
var localXCos : Number = localX * cos + x;
var localXSin : Number = localX * sin;
var localYCos : Number = localY * cos + y;
var localYSin : Number = localY * sin;
var localX2Cos : Number = localX2 * cos + x;
var localX2Sin : Number = localX2 * sin;
var localY2Cos : Number = localY2 * cos + y;
var localY2Sin : Number = localY2 * sin;
offset[BLX] = localXCos - localYSin;
offset[BLY] = localYCos + localXSin;
offset[ULX] = localXCos - localY2Sin;
offset[ULY] = localY2Cos + localXSin;
offset[URX] = localX2Cos - localY2Sin;
offset[URY] = localY2Cos + localX2Sin;
offset[BRX] = localX2Cos - localYSin;
offset[BRY] = localYCos + localX2Sin;
var ulDist : Number = Math.sqrt(localX * localX + localY * localY);
var ulAngle : Number = Math.atan2(localY, localX);
var urDist : Number = Math.sqrt(localX2 * localX2 + localY * localY);
var urAngle : Number = Math.atan2(localY, localX2);
var blDist : Number = Math.sqrt(localX * localX + localY2 * localY2);
var blAngle : Number = Math.atan2(localY2, localX);
var brDist : Number = Math.sqrt(localX2 * localX2 + localY2 * localY2);
var brAngle : Number = Math.atan2(localY2, localX2);
offset[BLX] = Math.cos(radians - blAngle) * blDist + x;
offset[BLY] = Math.sin(radians - blAngle) * blDist + y;
offset[ULX] = Math.cos(radians - ulAngle) * ulDist + x;
offset[ULY] = Math.sin(radians - ulAngle) * ulDist + y;
offset[URX] = Math.cos(radians - urAngle) * urDist + x;
offset[URY] = Math.sin(radians - urAngle) * urDist + y;
offset[BRX] = Math.cos(radians - brAngle) * brDist + x;
offset[BRY] = Math.sin(radians - brAngle) * brDist + y;
}
public function setUVs(u : Number, v : Number, u2 : Number, v2 : Number, rotate : Boolean) : void {

View File

@ -0,0 +1,46 @@
/******************************************************************************
* Spine Runtimes Software License v2.5
*
* Copyright (c) 2013-2016, 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 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 develop new applications using the Spine Runtimes or otherwise
* create derivative works or improvements of the Spine Runtimes 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, BUSINESS INTERRUPTION, OR LOSS OF
* USE, DATA, OR PROFITS) 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.
*****************************************************************************/
package spine.interpolation {
import spine.Interpolation;
public class Pow extends Interpolation {
protected var power : Number;
public function Pow(power : Number) {
this.power = power;
}
protected override function applyInternal(a : Number) : Number {
if (a <= 0.5) return Math.pow(a * 2, power) / 2;
return Math.pow((a - 1) * 2, power) / (power % 2 == 0 ? -2 : 2) + 1;
}
}
}

View File

@ -0,0 +1,41 @@
/******************************************************************************
* Spine Runtimes Software License v2.5
*
* Copyright (c) 2013-2016, 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 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 develop new applications using the Spine Runtimes or otherwise
* create derivative works or improvements of the Spine Runtimes 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, BUSINESS INTERRUPTION, OR LOSS OF
* USE, DATA, OR PROFITS) 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.
*****************************************************************************/
package spine.interpolation {
public class PowOut extends Pow {
public function PowOut(power : Number) {
super(power);
}
protected override function applyInternal(a : Number) : Number {
return Math.pow(a - 1, power) * (power % 2 == 0 ? -1 : 1) + 1;
}
}
}

View File

@ -0,0 +1,57 @@
/******************************************************************************
* Spine Runtimes Software License v2.5
*
* Copyright (c) 2013-2016, 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 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 develop new applications using the Spine Runtimes or otherwise
* create derivative works or improvements of the Spine Runtimes 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, BUSINESS INTERRUPTION, OR LOSS OF
* USE, DATA, OR PROFITS) 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.
*****************************************************************************/
package spine.vertexeffects {
import spine.MathUtils;
import spine.Skeleton;
import spine.Vertex;
import spine.VertexEffect;
public class JitterEffect implements VertexEffect {
public var jitterX : Number;
public var jitterY : Number;
public function JitterEffect(jitterX: Number, jitterY: Number) {
this.jitterX = jitterX;
this.jitterY = jitterY;
}
public function begin(skeleton : Skeleton) : void {
}
public function transform(vertex : Vertex) : void {
vertex.x += MathUtils.randomTriangular(-jitterX, jitterY);
vertex.y += MathUtils.randomTriangular(-jitterX, jitterY);
}
public function end() : void {
}
}
}

View File

@ -0,0 +1,84 @@
/******************************************************************************
* Spine Runtimes Software License v2.5
*
* Copyright (c) 2013-2016, 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 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 develop new applications using the Spine Runtimes or otherwise
* create derivative works or improvements of the Spine Runtimes 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, BUSINESS INTERRUPTION, OR LOSS OF
* USE, DATA, OR PROFITS) 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.
*****************************************************************************/
package spine.vertexeffects {
import spine.interpolation.Pow;
import spine.MathUtils;
import spine.Interpolation;
import spine.Skeleton;
import spine.Vertex;
import spine.VertexEffect;
public class SwirlEffect implements VertexEffect {
private var worldX : Number, worldY : Number, _radius : Number = 0, _angle : Number = 0;
private var _interpolation : Interpolation;
private var _centerX : Number = 0, _centerY : Number = 0;
public function SwirlEffect(radius : Number) {
this._interpolation = new Pow(2);;
this._radius = radius;
}
public function begin(skeleton : Skeleton) : void {
worldX = skeleton.x + _centerX;
worldY = skeleton.y + _centerY;
}
public function transform(vertex : Vertex) : void {
var x : Number = vertex.x - worldX;
var y : Number = vertex.y - worldY;
var dist : Number = Math.sqrt(x * x + y * y);
if (dist < radius) {
var theta : Number = interpolation.apply(0, angle, (radius - dist) / radius);
var cos : Number = Math.cos(theta), sin : Number = Math.sin(theta);
vertex.x = cos * x - sin * y + worldX;
vertex.y = sin * x + cos * y + worldY;
}
}
public function end() : void {
}
public function get radius () : Number { return _radius; }
public function set radius (radius : Number) : void { _radius = radius; }
public function get angle () : Number { return _angle; }
public function set angle (angle : Number) : void { _angle = angle * MathUtils.degRad; }
public function get centerX () : Number { return _centerX; }
public function set centerX (centerX : Number) : void { _centerX = centerX; }
public function get centerY () : Number { return _centerY; }
public function set centerY (centerY : Number) : void { _centerY = centerY; }
public function get interpolation () : Interpolation { return _interpolation; }
public function set interpolation (interpolation : Interpolation) : void { _interpolation = interpolation; }
}
}

View File

@ -12,13 +12,13 @@ The Spine Runtimes are developed with the intent to be used with data exported f
## Spine version
spine-c works with data exported from Spine 3.5.xx.
spine-c works with data exported from Spine 3.6.xx.
spine-c supports all Spine features.
## Setup
1. Download the Spine Runtimes source using [git](https://help.github.com/articles/set-up-git) or by downloading it [as a zip](https://github.com/EsotericSoftware/spine-runtimes/archive/master.zip).
1. Download the Spine Runtimes source using [git](https://help.github.com/articles/set-up-git) or by downloading it [as a zip](https://github.com/EsotericSoftware/spine-runtimes/archive/3.6.zip).
1. Open the `spine-c.sln` Visual C++ 2010 Express project file. For other IDEs, you will need to create a new project and import the source.
Alternatively, the contents of the `spine-c/spine-c/src` and `spine-c/spine-c/include` directories can be copied into your project. Be sure your header search is configured to find the contents of the `spine-c/spine-c/include` directory. Note that the includes use `spine/Xxx.h`, so the `spine` directory cannot be omitted when copying the files.

View File

@ -6,13 +6,13 @@
#include "KMemory.h" // last include
#define SPINEBOY_JSON "testdata/spineboy/spineboy.json"
#define SPINEBOY_JSON "testdata/spineboy/spineboy-ess.json"
#define SPINEBOY_ATLAS "testdata/spineboy/spineboy.atlas"
#define RAPTOR_JSON "testdata/raptor/raptor.json"
#define RAPTOR_JSON "testdata/raptor/raptor-pro.json"
#define RAPTOR_ATLAS "testdata/raptor/raptor.atlas"
#define GOBLINS_JSON "testdata/goblins/goblins.json"
#define GOBLINS_JSON "testdata/goblins/goblins-pro.json"
#define GOBLINS_ATLAS "testdata/goblins/goblins.atlas"
#define MAX_RUN_TIME 6000 // equal to about 100 seconds of execution

View File

@ -6,7 +6,7 @@
#include "KMemory.h" // last include
#define SPINEBOY_JSON "testdata/spineboy/spineboy.json"
#define SPINEBOY_JSON "testdata/spineboy/spineboy-ess.json"
#define SPINEBOY_ATLAS "testdata/spineboy/spineboy.atlas"
#define MAX_RUN_TIME 6000 // equal to about 100 seconds of execution

View File

@ -100,7 +100,6 @@ extern "C" {
void name##_removeAt(name* self, int index) { \
self->size--; \
memmove(self->items + index, self->items + index + 1, sizeof(itemType) * (self->size - index)); \
self->items[self->size] = 0; \
} \
int name##_contains(name* self, itemType value) { \
itemType* items = self->items; \
@ -112,7 +111,6 @@ extern "C" {
} \
itemType name##_pop(name* self) { \
itemType item = self->items[--self->size]; \
self->items[self->size] = 0; \
return item; \
} \
itemType name##_peek(name* self) { \

View File

@ -42,6 +42,10 @@ typedef struct spColor {
spColor() :
r(0), g(0), b(0), a(0) {
}
bool operator==(const spColor& rhs) {
return r == rhs.r && g == rhs.g && b == rhs.b && a == rhs.a;
}
#endif
} spColor;

View File

@ -0,0 +1,84 @@
/******************************************************************************
* Spine Runtimes Software License v2.5
*
* Copyright (c) 2013-2016, 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 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 develop new applications using the Spine Runtimes or otherwise
* create derivative works or improvements of the Spine Runtimes 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, BUSINESS INTERRUPTION, OR LOSS OF
* USE, DATA, OR PROFITS) 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.
*****************************************************************************/
#ifndef SPINE_VERTEXEFFECT_H_
#define SPINE_VERTEXEFFECT_H_
#include <spine/Skeleton.h>
#include <spine/Color.h>
#ifdef __cplusplus
extern "C" {
#endif
struct spVertexEffect;
typedef void (*spVertexEffectBegin)(struct spVertexEffect *self, spSkeleton *skeleton);
typedef void (*spVertexEffectTransform)(struct spVertexEffect *self, float *x, float *y, float *u, float *v,
spColor *light, spColor *dark);
typedef void (*spVertexEffectEnd)(struct spVertexEffect *self);
typedef struct spVertexEffect {
spVertexEffectBegin begin;
spVertexEffectTransform transform;
spVertexEffectEnd end;
} spVertexEffect;
typedef struct spJitterVertexEffect {
spVertexEffect super;
float jitterX;
float jitterY;
} spJitterVertexEffect;
typedef struct spSwirlVertexEffect {
spVertexEffect super;
float centerX;
float centerY;
float radius;
float angle;
float worldX;
float worldY;
} spSwirlVertexEffect;
spJitterVertexEffect *spJitterVertexEffect_create(float jitterX, float jitterY);
void spJitterVertexEffect_dispose(spJitterVertexEffect *effect);
spSwirlVertexEffect *spSwirlVertexEffect_create(float radius);
void spSwirlVertexEffect_dispose(spSwirlVertexEffect *effect);
#ifdef __cplusplus
}
#endif
#endif /* SPINE_VERTEX_EFFECT_H_ */

View File

@ -62,9 +62,9 @@
#define SPINE_EXTENSION_H_
/* All allocation uses these. */
#define MALLOC(TYPE,COUNT) ((TYPE*)_malloc(sizeof(TYPE) * (COUNT), __FILE__, __LINE__))
#define CALLOC(TYPE,COUNT) ((TYPE*)_calloc(COUNT, sizeof(TYPE), __FILE__, __LINE__))
#define REALLOC(PTR,TYPE,COUNT) ((TYPE*)_realloc(PTR, sizeof(TYPE) * (COUNT)))
#define MALLOC(TYPE,COUNT) ((TYPE*)_spMalloc(sizeof(TYPE) * (COUNT), __FILE__, __LINE__))
#define CALLOC(TYPE,COUNT) ((TYPE*)_spCalloc(COUNT, sizeof(TYPE), __FILE__, __LINE__))
#define REALLOC(PTR,TYPE,COUNT) ((TYPE*)_spRealloc(PTR, sizeof(TYPE) * (COUNT)))
#define NEW(TYPE) CALLOC(TYPE,1)
/* Gets the direct super class. Type safe. */
@ -83,7 +83,7 @@
#define VTABLE(TYPE,VALUE) ((_##TYPE##Vtable*)((TYPE*)VALUE)->vtable)
/* Frees memory. Can be used on const types. */
#define FREE(VALUE) _free((void*)VALUE)
#define FREE(VALUE) _spFree((void*)VALUE)
/* Allocates a new char[], assigns it to TO, and copies FROM to it. Can be used on const types. */
#define MALLOC_STR(TO,FROM) strcpy(CONST_CAST(char*, TO) = (char*)MALLOC(char, strlen(FROM) + 1), FROM)
@ -103,6 +103,7 @@
#define COS(A) cosf(A)
#define SQRT(A) sqrtf(A)
#define ACOS(A) acosf(A)
#define POW(A,B) pow(A, B)
#else
#define FMOD(A,B) (float)fmod(A, B)
#define ATAN2(A,B) (float)atan2(A, B)
@ -110,6 +111,7 @@
#define SIN(A) (float)sin(A)
#define SQRT(A) (float)sqrt(A)
#define ACOS(A) (float)acos(A)
#define POW(A,B) (float)pow(A, B)
#endif
#define SIN_DEG(A) SIN((A) * DEG_RAD)
@ -162,17 +164,30 @@ char* _spUtil_readFile (const char* path, int* length);
* Internal API available for extension:
*/
void* _malloc (size_t size, const char* file, int line);
void* _calloc (size_t num, size_t size, const char* file, int line);
void* _realloc(void* ptr, size_t size);
void _free (void* ptr);
void* _spMalloc (size_t size, const char* file, int line);
void* _spCalloc (size_t num, size_t size, const char* file, int line);
void* _spRealloc(void* ptr, size_t size);
void _spFree (void* ptr);
float _spRandom ();
void _setMalloc (void* (*_malloc) (size_t size));
void _setDebugMalloc (void* (*_malloc) (size_t size, const char* file, int line));
void _setRealloc(void* (*_realloc) (void* ptr, size_t size));
void _setFree (void (*_free) (void* ptr));
void _spSetMalloc (void* (*_malloc) (size_t size));
void _spSetDebugMalloc (void* (*_malloc) (size_t size, const char* file, int line));
void _spSetRealloc(void* (*_realloc) (void* ptr, size_t size));
void _spSetFree (void (*_free) (void* ptr));
void _spSetRandom(float (*_random) ());
char* _readFile (const char* path, int* length);
char* _spReadFile (const char* path, int* length);
/*
* Math utilities
*/
float _spMath_random(float min, float max);
float _spMath_randomTriangular(float min, float max);
float _spMath_randomTriangularWith(float min, float max, float mode);
float _spMath_interpolate(float (*apply) (float a), float start, float end, float a);
float _spMath_pow2_apply(float a);
float _spMath_pow2out_apply(float a);
/**/

View File

@ -57,5 +57,6 @@
#include <spine/SkeletonClipping.h>
#include <spine/Event.h>
#include <spine/EventData.h>
#include <spine/VertexEffect.h>
#endif /* SPINE_SPINE_H_ */

View File

@ -851,22 +851,35 @@ void _spDeformTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton,
slot->attachmentVerticesCapacity = vertexCount;
}
}
if (slot->attachmentVerticesCount != vertexCount && pose != SP_MIX_POSE_SETUP) alpha = 1; /* Don't mix from uninitialized slot vertices. */
slot->attachmentVerticesCount = vertexCount;
frameVertices = self->frameVertices;
vertices = slot->attachmentVertices;
if (time < frames[0]) { /* Time is before first frame. */
spVertexAttachment* vertexAttachment = SUB_CAST(spVertexAttachment, slot->attachment);
switch (pose) {
case SP_MIX_POSE_SETUP:
slot->attachmentVerticesCount = 0;
if (!vertexAttachment->bones) {
memcpy(vertices, vertexAttachment->vertices, vertexCount * sizeof(float));
} else {
for (i = 0; i < vertexCount; i++) vertices[i] = 0;
}
return;
case SP_MIX_POSE_CURRENT:
case SP_MIX_POSE_CURRENT_LAYERED: /* to appease compiler */
alpha = 1 - alpha;
for (i = 0; i < vertexCount; i++)
vertices[i] *= alpha;
if (alpha == 1) break;
if (!vertexAttachment->bones) {
float* setupVertices = vertexAttachment->vertices;
for (i = 0; i < vertexCount; i++) {
vertices[i] += (setupVertices[i] - vertices[i]) * alpha;
}
} else {
alpha = 1 - alpha;
for (i = 0; i < vertexCount; i++) {
vertices[i] *= alpha;
}
}
}
return;
}

View File

@ -801,7 +801,6 @@ void _spAnimationState_animationsChanged (spAnimationState* self) {
_spAnimationState* internal = SUB_CAST(_spAnimationState, self);
int i, n;
spTrackEntry* entry;
spTrackEntry* lastEntry = 0;
spTrackEntryArray* mixingTo;
internal->animationsChanged = 0;
@ -812,10 +811,7 @@ void _spAnimationState_animationsChanged (spAnimationState* self) {
for (;i < n; i++) {
entry = self->tracks[i];
if (entry != 0) {
_spTrackEntry_setTimelineData(entry, lastEntry, mixingTo, self);
lastEntry = entry;
}
if (entry != 0) _spTrackEntry_setTimelineData(entry, 0, mixingTo, self);
}
}

View File

@ -173,14 +173,14 @@ void spBone_updateWorldTransformWith (spBone* self, float x, float y, float rota
lb = COS_DEG(90 + shearY) * scaleY;
lc = SIN_DEG(shearX) * scaleX;
ld = SIN_DEG(90 + shearY) * scaleY;
if (self->data->transformMode != SP_TRANSFORMMODE_NOSCALEORREFLECTION ? pa * pd - pb * pc < 0 : self->skeleton->flipX != self->skeleton->flipY) {
zb = -zb;
zd = -zd;
}
CONST_CAST(float, self->a) = za * la + zb * lc;
CONST_CAST(float, self->b) = za * lb + zb * ld;
CONST_CAST(float, self->c) = zc * la + zd * lc;
CONST_CAST(float, self->d) = zc * lb + zd * ld;
if (self->data->transformMode != SP_TRANSFORMMODE_NOSCALEORREFLECTION ? pa * pd - pb * pc < 0 : self->skeleton->flipX != self->skeleton->flipY) {
CONST_CAST(float, self->b) = -self->b;
CONST_CAST(float, self->d) = -self->d;
}
return;
}
}

View File

@ -114,7 +114,9 @@ void spPathConstraint_apply (spPathConstraint* self) {
}
for (i = 0, n = spacesCount - 1; i < n;) {
spBone* bone = bones[i];
setupLength = bone->data->length, x = setupLength * bone->a, y = setupLength * bone->c;
setupLength = bone->data->length;
if (setupLength == 0) setupLength = 0.000000001f;
x = setupLength * bone->a, y = setupLength * bone->c;
length = SQRT(x * x + y * y);
if (scale) lengths[i] = length;
spaces[++i] = (lengthSpacing ? setupLength + spacing : spacing) * length / setupLength;

View File

@ -0,0 +1,98 @@
/******************************************************************************
* Spine Runtimes Software License v2.5
*
* Copyright (c) 2013-2016, 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 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 develop new applications using the Spine Runtimes or otherwise
* create derivative works or improvements of the Spine Runtimes 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, BUSINESS INTERRUPTION, OR LOSS OF
* USE, DATA, OR PROFITS) 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.
*****************************************************************************/
#include <spine/VertexEffect.h>
#include <spine/extension.h>
void _spJitterVertexEffect_begin(spVertexEffect* self, spSkeleton* skeleton) {
}
void _spJitterVertexEffect_transform(spVertexEffect* self, float* x, float* y, float* u, float* v, spColor* light, spColor* dark) {
spJitterVertexEffect* internal = (spJitterVertexEffect*)self;
float jitterX = internal->jitterX;
float jitterY = internal->jitterY;
(*x) += _spMath_randomTriangular(-jitterX, jitterY);
(*y) += _spMath_randomTriangular(-jitterX, jitterY);
}
void _spJitterVertexEffect_end(spVertexEffect* self) {
}
spJitterVertexEffect* spJitterVertexEffect_create(float jitterX, float jitterY) {
spJitterVertexEffect* effect = CALLOC(spJitterVertexEffect, 1);
effect->super.begin = _spJitterVertexEffect_begin;
effect->super.transform = _spJitterVertexEffect_transform;
effect->super.end = _spJitterVertexEffect_end;
effect->jitterX = jitterX;
effect->jitterY = jitterY;
return effect;
}
void spJitterVertexEffect_dispose(spJitterVertexEffect* effect) {
FREE(effect);
}
void _spSwirlVertexEffect_begin(spVertexEffect* self, spSkeleton* skeleton) {
spSwirlVertexEffect* internal = (spSwirlVertexEffect*)self;
internal->worldX = skeleton->x + internal->centerX;
internal->worldY = skeleton->y + internal->centerY;
}
void _spSwirlVertexEffect_transform(spVertexEffect* self, float* positionX, float* positionY, float* u, float* v, spColor* light, spColor* dark) {
spSwirlVertexEffect* internal = (spSwirlVertexEffect*)self;
float radAngle = internal->angle * DEG_RAD;
float x = *positionX - internal->worldX;
float y = *positionY - internal->worldY;
float dist = SQRT(x * x + y * y);
if (dist < internal->radius) {
float theta = _spMath_interpolate(_spMath_pow2_apply, 0, radAngle, (internal->radius - dist) / internal->radius);
float cosine = COS(theta);
float sine = SIN(theta);
(*positionX) = cosine * x - sine * y + internal->worldX;
(*positionY) = sine * x + cosine * y + internal->worldY;
}
}
void _spSwirlVertexEffect_end(spVertexEffect* self) {
}
spSwirlVertexEffect* spSwirlVertexEffect_create(float radius) {
spSwirlVertexEffect* effect = CALLOC(spSwirlVertexEffect, 1);
effect->super.begin = _spSwirlVertexEffect_begin;
effect->super.transform = _spSwirlVertexEffect_transform;
effect->super.end = _spSwirlVertexEffect_end;
effect->radius = radius;
return effect;
}
void spSwirlVertexEffect_dispose(spSwirlVertexEffect* effect) {
FREE(effect);
}

View File

@ -31,46 +31,59 @@
#include <spine/extension.h>
#include <stdio.h>
float _spInternalRandom () {
return rand() / (float)RAND_MAX;
}
static void* (*mallocFunc) (size_t size) = malloc;
static void* (*reallocFunc) (void* ptr, size_t size) = realloc;
static void* (*debugMallocFunc) (size_t size, const char* file, int line) = NULL;
static void (*freeFunc) (void* ptr) = free;
static float (*randomFunc) () = _spInternalRandom;
void* _malloc (size_t size, const char* file, int line) {
void* _spMalloc (size_t size, const char* file, int line) {
if(debugMallocFunc)
return debugMallocFunc(size, file, line);
return mallocFunc(size);
}
void* _calloc (size_t num, size_t size, const char* file, int line) {
void* ptr = _malloc(num * size, file, line);
void* _spCalloc (size_t num, size_t size, const char* file, int line) {
void* ptr = _spMalloc(num * size, file, line);
if (ptr) memset(ptr, 0, num * size);
return ptr;
}
void* _realloc(void* ptr, size_t size) {
void* _spRealloc(void* ptr, size_t size) {
return reallocFunc(ptr, size);
}
void _free (void* ptr) {
void _spFree (void* ptr) {
freeFunc(ptr);
}
void _setDebugMalloc(void* (*malloc) (size_t size, const char* file, int line)) {
float _spRandom () {
return randomFunc();
}
void _spSetDebugMalloc(void* (*malloc) (size_t size, const char* file, int line)) {
debugMallocFunc = malloc;
}
void _setMalloc (void* (*malloc) (size_t size)) {
void _spSetMalloc (void* (*malloc) (size_t size)) {
mallocFunc = malloc;
}
void _setRealloc (void* (*realloc) (void* ptr, size_t size)) {
void _spSetRealloc (void* (*realloc) (void* ptr, size_t size)) {
reallocFunc = realloc;
}
void _setFree (void (*free) (void* ptr)) {
void _spSetFree (void (*free) (void* ptr)) {
freeFunc = free;
}
char* _readFile (const char* path, int* length) {
void _spSetRandom (float (*random) ()) {
randomFunc = random;
}
char* _spReadFile (const char* path, int* length) {
char *data;
FILE *file = fopen(path, "rb");
if (!file) return 0;
@ -85,3 +98,31 @@ char* _readFile (const char* path, int* length) {
return data;
}
float _spMath_random(float min, float max) {
return min + (max - min) * _spRandom();
}
float _spMath_randomTriangular(float min, float max) {
return _spMath_randomTriangularWith(min, max, (min + max) * 0.5f);
}
float _spMath_randomTriangularWith(float min, float max, float mode) {
float u = _spRandom();
float d = max - min;
if (u <= (mode - min) / d) return min + SQRT(u * d * (mode - min));
return max - SQRT((1 - u) * d * (max - mode));
}
float _spMath_interpolate(float (*apply) (float a), float start, float end, float a) {
return start + (end - start) * apply(a);
}
float _spMath_pow2_apply(float a) {
if (a <= 0.5) return POW(a * 2, 2) / 2;
return POW((a - 1) * 2, 2) / -2 + 1;
}
float _spMath_pow2out_apply(float a) {
return POW(a - 1, 2) * -1 + 1;
}

View File

@ -19,9 +19,10 @@ spine-cocos2d-objc does not yet support loading the binary format.
## Usage
1. Create a new cocos2d-obj project. See the [cocos2d-objc documentation](http://cocos2d-objc.org/started/) or have a look at the example in this repository.
2. Download the Spine Runtimes source using git (`git clone https://github.com/esotericsoftware/spine-runtimes`) or download it [as a zip](https://github.com/EsotericSoftware/spine-runtimes/archive/master.zip)
2. Download the Spine Runtimes source using git (`git clone https://github.com/esotericsoftware/spine-runtimes`) or download it [as a zip](https://github.com/EsotericSoftware/spine-runtimes/archive/3.6.zip)
3. Add the sources from `spine-c/spine-c/src/spine` and `spine-cocos2d-objc/src/spine` to your project
4. Add the folders `spine-c/spine-c/include` and `spine-cocos2d-objc/src` to your header search path. Note that includes are specified as `#inclue <spine/file.h>`, so the `spine` directory cannot be omitted when copying the source files.
5. If your project uses ARC, you have to exclude the `.m` files in `spine-cocos2d-objc/src` from ARC. See https://stackoverflow.com/questions/6646052/how-can-i-disable-arc-for-a-single-file-in-a-project for more information.
See the [Spine Runtimes documentation](http://esotericsoftware.com/spine-documentation#runtimesTitle) on how to use the APIs or check out the Spine cocos2d-objc example.
@ -36,7 +37,7 @@ The Spine cocos2d-objc example works on iOS simulators and devices.
1. Install [Xcode](https://developer.apple.com/xcode/)
2. Install [Homebrew](http://brew.sh/)
3. Open a terminal and install CMake via `brew install cmake`
3. Download the Spine Runtimes repository using git (`git clone https://github.com/esotericsoftware/spine-runtimes`) or download it [as a zip](https://github.com/EsotericSoftware/spine-runtimes/archive/master.zip)
3. Download the Spine Runtimes repository using git (`git clone https://github.com/esotericsoftware/spine-runtimes`) or download it [as a zip](https://github.com/EsotericSoftware/spine-runtimes/archive/3.6.zip)
4. Open a terminal, and `cd` into the `spine-runtimes/spine-cocos2d-objc` folder
5. Type `mkdir build && cd build && cmake ../..`, this will download the cocos2d-objc dependency
6. Open the Xcode project in `spine-runtimes/spine-cocos2d-objc/spine-cocos2d-objc.xcodeproj/`

View File

@ -31,6 +31,8 @@
#import "RaptorExample.h"
#import "TankExample.h"
spJitterVertexEffect* effect = 0;
@implementation RaptorExample
+ (CCScene*) scene {
@ -42,9 +44,12 @@
-(id) init {
self = [super init];
if (!self) return nil;
if (!effect) effect = spJitterVertexEffect_create(10, 10);
skeletonNode = [SkeletonAnimation skeletonWithFile:@"raptor-pro.json" atlasFile:@"raptor.atlas" scale:0.3f];
[skeletonNode setAnimationForTrack:0 name:@"walk" loop:YES];
[skeletonNode setEffect:&effect->super];
CGSize windowSize = [[CCDirector sharedDirector] viewSize];
[skeletonNode setPosition:ccp(windowSize.width / 2, 20)];

View File

@ -84,6 +84,7 @@
76F5BDAD1D2BDFA2005917E5 /* TankExample.m in Sources */ = {isa = PBXBuildFile; fileRef = 76F5BDAC1D2BDFA2005917E5 /* TankExample.m */; };
76FAC1961E3FA15E001CCC8C /* Color.c in Sources */ = {isa = PBXBuildFile; fileRef = 76FAC1941E3FA15E001CCC8C /* Color.c */; };
76FAC1971E3FA15E001CCC8C /* PointAttachment.c in Sources */ = {isa = PBXBuildFile; fileRef = 76FAC1951E3FA15E001CCC8C /* PointAttachment.c */; };
76FB151A1F01413B00C5377F /* VertexEffect.c in Sources */ = {isa = PBXBuildFile; fileRef = 76FB15191F01413B00C5377F /* VertexEffect.c */; };
83F1A0EF1986955A001F6B44 /* GLKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 83F1A0EE1986955A001F6B44 /* GLKit.framework */; };
9A5D2499170A94DA0030D4DD /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9A5D2498170A94DA0030D4DD /* QuartzCore.framework */; };
9A5D249B170A94DA0030D4DD /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9A5D249A170A94DA0030D4DD /* OpenGLES.framework */; };
@ -137,7 +138,7 @@
/* Begin PBXFileReference section */
43C3282D170B0C19004A9460 /* spine-cocos2d-objc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "spine-cocos2d-objc.m"; path = "src/spine/spine-cocos2d-objc.m"; sourceTree = "<group>"; };
43C3282E170B0C19004A9460 /* spine-cocos2d-objc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "spine-cocos2d-objc.h"; path = "src/spine/spine-cocos2d-objc.h"; sourceTree = "<group>"; };
43C32868170B0DA6004A9460 /* spineboy-ess.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = spineboy-ess.json; path = Resources/spineboy-ess.json; sourceTree = "<group>"; };
43C32868170B0DA6004A9460 /* spineboy-ess.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = "spineboy-ess.json"; path = "Resources/spineboy-ess.json"; sourceTree = "<group>"; };
43C3286A170B0DA6004A9460 /* spineboy.atlas */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = spineboy.atlas; path = Resources/spineboy.atlas; sourceTree = "<group>"; };
43C3286B170B0DA6004A9460 /* spineboy.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = spineboy.png; path = Resources/spineboy.png; sourceTree = "<group>"; };
43C32871170B0DBE004A9460 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Default-568h@2x.png"; path = "Resources-ios/Default-568h@2x.png"; sourceTree = "<group>"; };
@ -175,7 +176,7 @@
76EE4E441EB36DE6000254F4 /* SkeletonClipping.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = SkeletonClipping.c; path = "../spine-c/spine-c/src/spine/SkeletonClipping.c"; sourceTree = "<group>"; };
76EE4E451EB36DE6000254F4 /* Triangulator.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = Triangulator.c; path = "../spine-c/spine-c/src/spine/Triangulator.c"; sourceTree = "<group>"; };
76EE4E4E1EB36E53000254F4 /* coin.atlas */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = coin.atlas; path = Resources/coin.atlas; sourceTree = "<group>"; };
76EE4E4F1EB36E53000254F4 /* coin-pro.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = coin-pro.json; path = Resources/coin-pro.json; sourceTree = "<group>"; };
76EE4E4F1EB36E53000254F4 /* coin-pro.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = "coin-pro.json"; path = "Resources/coin-pro.json"; sourceTree = "<group>"; };
76EE4E501EB36E53000254F4 /* coin.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = coin.png; path = Resources/coin.png; sourceTree = "<group>"; };
76EE4E541EB36E94000254F4 /* CoinExample.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CoinExample.h; path = example/CoinExample.h; sourceTree = "<group>"; };
76EE4E551EB36E94000254F4 /* CoinExample.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CoinExample.m; path = example/CoinExample.m; sourceTree = "<group>"; };
@ -214,10 +215,10 @@
76F28D141DEC810300CDE54D /* TransformConstraintData.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = TransformConstraintData.c; path = "../spine-c/spine-c/src/spine/TransformConstraintData.c"; sourceTree = "<group>"; };
76F28D151DEC810300CDE54D /* VertexAttachment.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = VertexAttachment.c; path = "../spine-c/spine-c/src/spine/VertexAttachment.c"; sourceTree = "<group>"; };
76F5BD9C1D2BDE1C005917E5 /* raptor.atlas */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = raptor.atlas; path = Resources/raptor.atlas; sourceTree = "<group>"; };
76F5BD9D1D2BDE1C005917E5 /* raptor-pro.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = raptor-pro.json; path = Resources/raptor-pro.json; sourceTree = "<group>"; };
76F5BD9D1D2BDE1C005917E5 /* raptor-pro.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = "raptor-pro.json"; path = "Resources/raptor-pro.json"; sourceTree = "<group>"; };
76F5BD9E1D2BDE1C005917E5 /* raptor.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = raptor.png; path = Resources/raptor.png; sourceTree = "<group>"; };
76F5BD9F1D2BDE1C005917E5 /* tank.atlas */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = tank.atlas; path = Resources/tank.atlas; sourceTree = "<group>"; };
76F5BDA01D2BDE1C005917E5 /* tank-pro.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = tank-pro.json; path = Resources/tank-pro.json; sourceTree = "<group>"; };
76F5BDA01D2BDE1C005917E5 /* tank-pro.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = "tank-pro.json"; path = "Resources/tank-pro.json"; sourceTree = "<group>"; };
76F5BDA11D2BDE1C005917E5 /* tank.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = tank.png; path = Resources/tank.png; sourceTree = "<group>"; };
76F5BDA81D2BDE67005917E5 /* RaptorExample.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RaptorExample.h; path = example/RaptorExample.h; sourceTree = "<group>"; };
76F5BDA91D2BDE67005917E5 /* RaptorExample.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RaptorExample.m; path = example/RaptorExample.m; sourceTree = "<group>"; };
@ -225,6 +226,7 @@
76F5BDAC1D2BDFA2005917E5 /* TankExample.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TankExample.m; path = example/TankExample.m; sourceTree = "<group>"; };
76FAC1941E3FA15E001CCC8C /* Color.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = Color.c; path = "../spine-c/spine-c/src/spine/Color.c"; sourceTree = "<group>"; };
76FAC1951E3FA15E001CCC8C /* PointAttachment.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = PointAttachment.c; path = "../spine-c/spine-c/src/spine/PointAttachment.c"; sourceTree = "<group>"; };
76FB15191F01413B00C5377F /* VertexEffect.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = VertexEffect.c; path = "../spine-c/spine-c/src/spine/VertexEffect.c"; sourceTree = "<group>"; };
83F1A0EE1986955A001F6B44 /* GLKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GLKit.framework; path = System/Library/Frameworks/GLKit.framework; sourceTree = SDKROOT; };
9A5D2495170A94DA0030D4DD /* SpineExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SpineExample.app; sourceTree = BUILT_PRODUCTS_DIR; };
9A5D2498170A94DA0030D4DD /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
@ -299,6 +301,7 @@
43C32822170B0BC2004A9460 /* spine-c */ = {
isa = PBXGroup;
children = (
76FB15191F01413B00C5377F /* VertexEffect.c */,
76EE4E421EB36DE6000254F4 /* Array.c */,
76EE4E431EB36DE6000254F4 /* ClippingAttachment.c */,
76EE4E441EB36DE6000254F4 /* SkeletonClipping.c */,
@ -597,6 +600,7 @@
76BF7E071E66ED9C00485998 /* GLUtils.c in Sources */,
76EE4E481EB36DE6000254F4 /* SkeletonClipping.c in Sources */,
43C3282F170B0C19004A9460 /* spine-cocos2d-objc.m in Sources */,
76FB151A1F01413B00C5377F /* VertexEffect.c in Sources */,
76F28D1F1DEC810300CDE54D /* BoundingBoxAttachment.c in Sources */,
76F28D281DEC810300CDE54D /* PathConstraint.c in Sources */,
76F28D2F1DEC810300CDE54D /* SkeletonJson.c in Sources */,

View File

@ -47,6 +47,7 @@
float* _worldVertices;
CCBlendMode* screenMode;
spSkeletonClipping* _clipper;
spVertexEffect* _effect;
}
+ (id) skeletonWithData:(spSkeletonData*)skeletonData ownsSkeletonData:(bool)ownsSkeletonData;
@ -90,5 +91,6 @@
@property (nonatomic) bool debugBones;
@property (nonatomic) bool skipVisibilityCheck;
@property (nonatomic) spBone* rootBone;
@property (nonatomic) spVertexEffect* effect;
@end

View File

@ -50,6 +50,7 @@ static bool handlerQueued = false;
@synthesize twoColorTint = _twoColorTint;
@synthesize debugSlots = _debugSlots;
@synthesize debugBones = _debugBones;
@synthesize effect = _effect;
+ (id) skeletonWithData:(spSkeletonData*)skeletonData ownsSkeletonData:(bool)ownsSkeletonData {
return [[[self alloc] initWithData:skeletonData ownsSkeletonData:ownsSkeletonData] autorelease];
@ -91,6 +92,7 @@ static bool handlerQueued = false;
];
_clipper = spSkeletonClipping_create();
_effect = 0;
}
- (id) initWithData:(spSkeletonData*)skeletonData ownsSkeletonData:(bool)ownsSkeletonData {
@ -173,6 +175,8 @@ static bool handlerQueued = false;
handlerQueued = true;
}
if (_effect) _effect->begin(_effect, _skeleton);
CCColor* nodeColor = self.color;
_skeleton->color.r = nodeColor.red;
_skeleton->color.g = nodeColor.green;
@ -288,6 +292,20 @@ static bool handlerQueued = false;
vertex.position = GLKVector4Make(vertices[i * 2], vertices[i * 2 + 1], 0.0, 1.0);
vertex.color = GLKVector4Make(r, g, b, a);
vertex.texCoord1 = GLKVector2Make(uvs[i * 2], 1 - uvs[i * 2 + 1]);
if (_effect) {
spColor light;
spColor dark;
light.r = r;
light.g = g;
light.b = b;
light.a = a;
dark.r = dark.g = dark.b = dark.a = 0;
_effect->transform(_effect, &vertex.position.x, &vertex.position.y, &vertex.texCoord1.s, &vertex.texCoord1.t, &light, &dark);
vertex.color.r = light.r;
vertex.color.g = light.g;
vertex.color.b = light.b;
vertex.color.a = light.a;
}
CCRenderBufferSetVertex(buffer, i, CCVertexApplyTransform(vertex, transform));
}
for (int j = 0; j * 3 < trianglesCount; ++j) {
@ -308,18 +326,50 @@ static bool handlerQueued = false;
spVertex* verts = &meshPart.mesh->vertices[meshPart.startVertex];
unsigned short* indices = &meshPart.mesh->indices[meshPart.startIndex];
for (int i = 0; i * 2 < verticesCount; i++, verts++) {
CCVertex vertex;
vertex.position = GLKVector4Make(vertices[i * 2], vertices[i * 2 + 1], 0.0, 1.0);
vertex = CCVertexApplyTransform(vertex, transform);
verts->x = vertex.position.x;
verts->y = vertex.position.y;
verts->z = vertex.position.z;
verts->w = vertex.position.w;
verts->color = ((unsigned short)(r * 255))| ((unsigned short)(g * 255)) << 8 | ((unsigned short)(b * 255)) <<16 | ((unsigned short)(a * 255)) << 24;
verts->color2 = ((unsigned short)(dr * 255)) | ((unsigned short)(dg * 255)) << 8 | ((unsigned short)(db * 255)) << 16 | ((unsigned short)(255)) << 24;
verts->u = uvs[i * 2];
verts->v = 1 - uvs[i * 2 + 1];
if (_effect) {
spColor light;
light.r = r;
light.g = g;
light.b = b;
light.a = a;
spColor dark;
dark.r = dr;
dark.g = dg;
dark.b = db;
dark.a = 1;
for (int i = 0; i * 2 < verticesCount; i++, verts++) {
spColor lightCopy = light;
spColor darkCopy = dark;
CCVertex vertex;
vertex.position = GLKVector4Make(vertices[i * 2], vertices[i * 2 + 1], 0.0, 1.0);
verts->u = uvs[i * 2];
verts->v = 1 - uvs[i * 2 + 1];
_effect->transform(_effect, &vertex.position.x, &vertex.position.y, &verts->u, &verts->v, &lightCopy, &darkCopy);
vertex = CCVertexApplyTransform(vertex, transform);
verts->x = vertex.position.x;
verts->y = vertex.position.y;
verts->z = vertex.position.z;
verts->w = vertex.position.w;
verts->color = ((unsigned short)(lightCopy.r * 255))| ((unsigned short)(lightCopy.g * 255)) << 8 | ((unsigned short)(lightCopy.b * 255)) <<16 | ((unsigned short)(lightCopy.a * 255)) << 24;
verts->color2 = ((unsigned short)(darkCopy.r * 255)) | ((unsigned short)(darkCopy.g * 255)) << 8 | ((unsigned short)(darkCopy.b * 255)) << 16 | ((unsigned short)(255)) << 24;
}
} else {
for (int i = 0; i * 2 < verticesCount; i++, verts++) {
CCVertex vertex;
vertex.position = GLKVector4Make(vertices[i * 2], vertices[i * 2 + 1], 0.0, 1.0);
vertex = CCVertexApplyTransform(vertex, transform);
verts->x = vertex.position.x;
verts->y = vertex.position.y;
verts->z = vertex.position.z;
verts->w = vertex.position.w;
verts->color = ((unsigned short)(r * 255))| ((unsigned short)(g * 255)) << 8 | ((unsigned short)(b * 255)) <<16 | ((unsigned short)(a * 255)) << 24;
verts->color2 = ((unsigned short)(dr * 255)) | ((unsigned short)(dg * 255)) << 8 | ((unsigned short)(db * 255)) << 16 | ((unsigned short)(255)) << 24;
verts->u = uvs[i * 2];
verts->v = 1 - uvs[i * 2 + 1];
}
}
for (int j = 0; j < trianglesCount; j++, indices++) {
@ -375,6 +425,8 @@ static bool handlerQueued = false;
if (i == 0) [_drawNode drawDot:ccp(bone->worldX, bone->worldY) radius:4 color:[CCColor blueColor]];
}
}
if (_effect) _effect->end(_effect);
}
- (CCTexture*) getTextureForRegion:(spRegionAttachment*)attachment {

View File

@ -44,5 +44,5 @@ void _spAtlasPage_disposeTexture (spAtlasPage* self) {
}
char* _spUtil_readFile (const char* path, int* length) {
return _readFile([[[CCFileUtils sharedFileUtils] fullPathForFilename:@(path)] UTF8String], length);
return _spReadFile([[[CCFileUtils sharedFileUtils] fullPathForFilename:@(path)] UTF8String], length);
}

View File

@ -21,7 +21,7 @@ The setup for cocos2d-x differs from most other Spine Runtimes because the cocos
1. Create a new cocos2d-x project. See [the cocos2d-x documentation](http://www.cocos2d-x.org/docs/static-pages/installation.html)
2. Delete the folder `cocos2d/cocos/editor-support/spine`. This will remove the outdated Spine cocos2d-x runtime shipped by cocos2d-x.
3. Open your project in your IDE of choice, then open the cocos2d_libs sub project and delete the `editor-support/spine` group. This will remove the outdated Spine cocos2d-x runtime shipped by cocos2d-x from your build.
3. Download the Spine Runtimes source using git (`git clone https://github.com/esotericsoftware/spine-runtimes`) or download it [as a zip](https://github.com/EsotericSoftware/spine-runtimes/archive/master.zip)
3. Download the Spine Runtimes source using git (`git clone https://github.com/esotericsoftware/spine-runtimes`) or download it [as a zip](https://github.com/EsotericSoftware/spine-runtimes/archive/3.6.zip)
4. Add the sources from `spine-c/spine-c/src/spine` and `spine-cocos2dx/src/spine` to your project
4. Add the folders `spine-c/spine-c/include` and `spine-cocos2dx/src` to your header search path. Note that includes are specified as `#inclue <spine/file.h>`, so the `spine` directory cannot be omitted when copying the source files.
@ -31,7 +31,7 @@ The Spine cocos2d-x example works on Windows and Mac OS X.
### Windows
1. Install [Visual Studio 2015 Community](https://www.visualstudio.com/en-us/downloads/download-visual-studio-vs.aspx)
2. Install CMake via the [Windows installer package](https://cmake.org/download/).
3. Download the Spine Runtimes repository using git (`git clone https://github.com/esotericsoftware/spine-runtimes`) or download it [as a zip](https://github.com/EsotericSoftware/spine-runtimes/archive/master.zip)
3. Download the Spine Runtimes repository using git (`git clone https://github.com/esotericsoftware/spine-runtimes`) or download it [as a zip](https://github.com/EsotericSoftware/spine-runtimes/archive/3.6.zip)
4. Run CMake GUI from the start menu
5. Click `Browse Source` and select the directory `spine-runtimes`
6. Click `Browse Build` and select the `spine-runtimes/spine-cocos2dx/build` directory. You can create the `build` folder directly in the file dialog via `New Folder`.
@ -47,7 +47,7 @@ The Spine cocos2d-x example works on Windows and Mac OS X.
1. Install [Xcode](https://developer.apple.com/xcode/)
2. Install [Homebrew](http://brew.sh/)
3. Open a terminal and install CMake via `brew install cmake`
3. Download the Spine Runtimes repository using git (`git clone https://github.com/esotericsoftware/spine-runtimes`) or download it [as a zip](https://github.com/EsotericSoftware/spine-runtimes/archive/master.zip)
3. Download the Spine Runtimes repository using git (`git clone https://github.com/esotericsoftware/spine-runtimes`) or download it [as a zip](https://github.com/EsotericSoftware/spine-runtimes/archive/3.6.zip)
4. Open a terminal, and `cd` into the `spine-runtimes/spine-cocos2dx` folder
5. Type `mkdir build && cd build && cmake ../..`. This will download the cocos2d-x dependency and wire it up with the example source code in `spine-runtimes/spine-cocos2dx/example`. The download is 400mb, so get yourself a cup of tea.
6. Open the Xcode project in `spine-runtimes/spine-cocos2dx/example/proj.ios_mac`
@ -58,7 +58,7 @@ The Spine cocos2d-x example works on Windows and Mac OS X.
1. Install the prerequisits for [cocos2d-x Android development](http://www.cocos2d-x.org/docs/installation/Android-terminal/)
2. Install [Homebrew](http://brew.sh/)
3. Open a terminal and install CMake via `brew install cmake`
3. Download the Spine Runtimes repository using git (`git clone https://github.com/esotericsoftware/spine-runtimes`) or download it [as a zip](https://github.com/EsotericSoftware/spine-runtimes/archive/master.zip)
3. Download the Spine Runtimes repository using git (`git clone https://github.com/esotericsoftware/spine-runtimes`) or download it [as a zip](https://github.com/EsotericSoftware/spine-runtimes/archive/3.6.zip)
4. Open a terminal, and `cd` into the `spine-runtimes/spine-cocos2dx` folder
5. Type `mkdir build && cd build && cmake ../..`. This will download the cocos2d-x dependency and wire it up with the example source code in `spine-runtimes/spine-cocos2dx/example`. The download is 400mb, so get yourself a cup of tea.
6. Delete `spine-runtimes/spine-cocos2dx/example/cocos2d/cocos/editor-support/spine`

View File

@ -30,10 +30,13 @@
#include "RaptorExample.h"
#include "TankExample.h"
#include <spine/extension.h>
USING_NS_CC;
using namespace spine;
spSwirlVertexEffect* effect = spSwirlVertexEffect_create(400);
Scene* RaptorExample::scene () {
Scene *scene = Scene::create();
scene->addChild(RaptorExample::create());
@ -46,7 +49,13 @@ bool RaptorExample::init () {
skeletonNode = SkeletonAnimation::createWithJsonFile("raptor-pro.json", "raptor.atlas", 0.5f);
skeletonNode->setAnimation(0, "walk", true);
skeletonNode->setAnimation(1, "empty", false);
skeletonNode->addAnimation(1, "gungrab", false, 2);
skeletonNode->addAnimation(1, "gungrab", false, 2);
skeletonNode->setTwoColorTint(true);
effect->centerY = 200;
swirlTime = 0;
skeletonNode->setVertexEffect(&effect->super);
skeletonNode->setPosition(Vec2(_contentSize.width / 2, 20));
addChild(skeletonNode);
@ -68,3 +77,10 @@ bool RaptorExample::init () {
return true;
}
void RaptorExample::update(float fDelta) {
swirlTime += fDelta;
float percent = fmod(swirlTime, 2);
if (percent > 1) percent = 1 - (percent - 1);
effect->angle = _spMath_interpolate(_spMath_pow2_apply, -60, 60, percent);
}

View File

@ -41,9 +41,12 @@ public:
CREATE_FUNC(RaptorExample);
virtual bool init ();
virtual void update(float fDelta);
private:
spine::SkeletonAnimation* skeletonNode;
float swirlTime;
};
#endif // _RAPTOREXAMPLE_H_

View File

@ -59,6 +59,7 @@ LOCAL_SRC_FILES := hellocpp/main.cpp \
../../../../spine-c/spine-c/src/spine/TransformConstraint.c \
../../../../spine-c/spine-c/src/spine/TransformConstraintData.c \
../../../../spine-c/spine-c/src/spine/VertexAttachment.c \
../../../../spine-c/spine-c/src/spine/VertexEffect.c \
../../../../spine-c/spine-c/src/spine/extension.c

View File

@ -0,0 +1,98 @@
/******************************************************************************
* Spine Runtimes Software License v2.5
*
* Copyright (c) 2013-2016, 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 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 develop new applications using the Spine Runtimes or otherwise
* create derivative works or improvements of the Spine Runtimes 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, BUSINESS INTERRUPTION, OR LOSS OF
* USE, DATA, OR PROFITS) 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.
*****************************************************************************/
#include <spine/VertexEffect.h>
#include <spine/extension.h>
void _spJitterVertexEffect_begin(spVertexEffect* self, spSkeleton* skeleton) {
}
void _spJitterVertexEffect_transform(spVertexEffect* self, float* x, float* y, float* u, float* v, spColor* light, spColor* dark) {
spJitterVertexEffect* internal = (spJitterVertexEffect*)self;
float jitterX = internal->jitterX;
float jitterY = internal->jitterY;
(*x) += _spMath_randomTriangular(-jitterX, jitterY);
(*y) += _spMath_randomTriangular(-jitterX, jitterY);
}
void _spJitterVertexEffect_end(spVertexEffect* self) {
}
spJitterVertexEffect* spJitterVertexEffect_create(float jitterX, float jitterY) {
spJitterVertexEffect* effect = CALLOC(spJitterVertexEffect, 1);
effect->super.begin = _spJitterVertexEffect_begin;
effect->super.transform = _spJitterVertexEffect_transform;
effect->super.end = _spJitterVertexEffect_end;
effect->jitterX = jitterX;
effect->jitterY = jitterY;
return effect;
}
void spJitterVertexEffect_dispose(spJitterVertexEffect* effect) {
FREE(effect);
}
void _spSwirlVertexEffect_begin(spVertexEffect* self, spSkeleton* skeleton) {
spSwirlVertexEffect* internal = (spSwirlVertexEffect*)self;
internal->worldX = skeleton->x + internal->centerX;
internal->worldY = skeleton->y + internal->centerY;
}
void _spSwirlVertexEffect_transform(spVertexEffect* self, float* positionX, float* positionY, float* u, float* v, spColor* light, spColor* dark) {
spSwirlVertexEffect* internal = (spSwirlVertexEffect*)self;
float radAngle = internal->angle * DEG_RAD;
float x = *positionX - internal->worldX;
float y = *positionY - internal->worldY;
float dist = SQRT(x * x + y * y);
if (dist < internal->radius) {
float theta = _spMath_interpolate(_spMath_pow2_apply, 0, radAngle, (internal->radius - dist) / internal->radius);
float cosine = COS(theta);
float sine = SIN(theta);
(*positionX) = cosine * x - sine * y + internal->worldX;
(*positionY) = sine * x + cosine * y + internal->worldY;
}
}
void _spSwirlVertexEffect_end(spVertexEffect* self) {
}
spSwirlVertexEffect* spSwirlVertexEffect_create(float radius) {
spSwirlVertexEffect* effect = CALLOC(spSwirlVertexEffect, 1);
effect->super.begin = _spSwirlVertexEffect_begin;
effect->super.transform = _spSwirlVertexEffect_transform;
effect->super.end = _spSwirlVertexEffect_end;
effect->radius = radius;
return effect;
}
void spSwirlVertexEffect_dispose(spSwirlVertexEffect* effect) {
FREE(effect);
}

View File

@ -170,6 +170,8 @@
76FAC18D1E3F97D2001CCC8C /* PointAttachment.c in Sources */ = {isa = PBXBuildFile; fileRef = 76FAC18B1E3F97D2001CCC8C /* PointAttachment.c */; };
76FAC18F1E3F98A0001CCC8C /* Color.c in Sources */ = {isa = PBXBuildFile; fileRef = 76FAC18A1E3F97D2001CCC8C /* Color.c */; };
76FAC1901E3F98A0001CCC8C /* PointAttachment.c in Sources */ = {isa = PBXBuildFile; fileRef = 76FAC18B1E3F97D2001CCC8C /* PointAttachment.c */; };
76FB150F1F01377200C5377F /* VertexEffect.c in Sources */ = {isa = PBXBuildFile; fileRef = 76FB150E1F01377200C5377F /* VertexEffect.c */; };
76FB15111F0139B400C5377F /* VertexEffect.c in Sources */ = {isa = PBXBuildFile; fileRef = 76FB150E1F01377200C5377F /* VertexEffect.c */; };
8262943E1AAF051F00CB7CF7 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8262943D1AAF051F00CB7CF7 /* Security.framework */; };
BF171245129291EC00B8313A /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BF170DB012928DE900B8313A /* OpenGLES.framework */; };
BF1712471292920000B8313A /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = BF170DB412928DE900B8313A /* libz.dylib */; };
@ -335,6 +337,7 @@
76F5BD541D2BD7D3005917E5 /* TankExample.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TankExample.h; sourceTree = "<group>"; };
76FAC18A1E3F97D2001CCC8C /* Color.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = Color.c; path = "../../../spine-c/spine-c/src/spine/Color.c"; sourceTree = "<group>"; };
76FAC18B1E3F97D2001CCC8C /* PointAttachment.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = PointAttachment.c; path = "../../../spine-c/spine-c/src/spine/PointAttachment.c"; sourceTree = "<group>"; };
76FB150E1F01377200C5377F /* VertexEffect.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = VertexEffect.c; sourceTree = "<group>"; };
8262943D1AAF051F00CB7CF7 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };
BF170DB012928DE900B8313A /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = System/Library/Frameworks/OpenGLES.framework; sourceTree = SDKROOT; };
BF170DB412928DE900B8313A /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; };
@ -552,6 +555,7 @@
76AAA3B21D180F7300C54FCB /* spine */ = {
isa = PBXGroup;
children = (
76FB150E1F01377200C5377F /* VertexEffect.c */,
76D520E11EB3625700572471 /* Array.c */,
76D520D71EB3611300572471 /* ClippingAttachment.c */,
76D520D81EB3611300572471 /* SkeletonClipping.c */,
@ -803,6 +807,7 @@
76F28CB81DEC7EBB00CDE54D /* Bone.c in Sources */,
76F28CB61DEC7EBB00CDE54D /* Attachment.c in Sources */,
503AE10217EB989F00D1A890 /* RootViewController.mm in Sources */,
76FB150F1F01377200C5377F /* VertexEffect.c in Sources */,
503AE10117EB989F00D1A890 /* main.m in Sources */,
76D520DB1EB3611300572471 /* SkeletonClipping.c in Sources */,
76F28CCB1DEC7EBB00CDE54D /* Skin.c in Sources */,
@ -820,6 +825,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
76FB15111F0139B400C5377F /* VertexEffect.c in Sources */,
76D520E71EB3634600572471 /* CoinExample.cpp in Sources */,
76D520E31EB3625B00572471 /* Array.c in Sources */,
76D520DE1EB3619800572471 /* ClippingAttachment.c in Sources */,

View File

@ -179,6 +179,7 @@ xcopy "$(ProjectDir)..\Resources" "$(OutDir)" /D /E /I /F /Y
<ClCompile Include="..\..\..\spine-c\spine-c\src\spine\TransformConstraint.c" />
<ClCompile Include="..\..\..\spine-c\spine-c\src\spine\TransformConstraintData.c" />
<ClCompile Include="..\..\..\spine-c\spine-c\src\spine\VertexAttachment.c" />
<ClCompile Include="..\..\..\spine-c\spine-c\src\spine\VertexEffect.c" />
<ClCompile Include="..\..\src\spine\AttachmentVertices.cpp" />
<ClCompile Include="..\..\src\spine\Cocos2dAttachmentLoader.cpp" />
<ClCompile Include="..\..\src\spine\SkeletonAnimation.cpp" />

View File

@ -77,21 +77,21 @@ void SkeletonRenderer::setSkeletonData (spSkeletonData *skeletonData, bool ownsS
}
SkeletonRenderer::SkeletonRenderer ()
: _atlas(nullptr), _attachmentLoader(nullptr), _debugSlots(false), _debugBones(false), _debugMeshes(false), _timeScale(1) {
: _atlas(nullptr), _attachmentLoader(nullptr), _debugSlots(false), _debugBones(false), _debugMeshes(false), _timeScale(1), _effect(nullptr) {
}
SkeletonRenderer::SkeletonRenderer (spSkeletonData *skeletonData, bool ownsSkeletonData)
: _atlas(nullptr), _attachmentLoader(nullptr), _debugSlots(false), _debugBones(false), _debugMeshes(false), _timeScale(1) {
: _atlas(nullptr), _attachmentLoader(nullptr), _debugSlots(false), _debugBones(false), _debugMeshes(false), _timeScale(1), _effect(nullptr) {
initWithData(skeletonData, ownsSkeletonData);
}
SkeletonRenderer::SkeletonRenderer (const std::string& skeletonDataFile, spAtlas* atlas, float scale)
: _atlas(nullptr), _attachmentLoader(nullptr), _debugSlots(false), _debugBones(false), _debugMeshes(false), _timeScale(1) {
: _atlas(nullptr), _attachmentLoader(nullptr), _debugSlots(false), _debugBones(false), _debugMeshes(false), _timeScale(1), _effect(nullptr) {
initWithJsonFile(skeletonDataFile, atlas, scale);
}
SkeletonRenderer::SkeletonRenderer (const std::string& skeletonDataFile, const std::string& atlasFile, float scale)
: _atlas(nullptr), _attachmentLoader(nullptr), _debugSlots(false), _debugBones(false), _debugMeshes(false), _timeScale(1) {
: _atlas(nullptr), _attachmentLoader(nullptr), _debugSlots(false), _debugBones(false), _debugMeshes(false), _timeScale(1), _effect(nullptr) {
initWithJsonFile(skeletonDataFile, atlasFile, scale);
}
@ -183,6 +183,8 @@ void SkeletonRenderer::draw (Renderer* renderer, const Mat4& transform, uint32_t
SkeletonBatch* batch = SkeletonBatch::getInstance();
SkeletonTwoColorBatch* twoColorBatch = SkeletonTwoColorBatch::getInstance();
bool isTwoColorTint = this->isTwoColorTint();
if (_effect) _effect->begin(_effect, _skeleton);
Color4F nodeColor;
nodeColor.r = getDisplayedColor().r / (float)255;
@ -279,6 +281,11 @@ void SkeletonRenderer::draw (Renderer* renderer, const Mat4& transform, uint32_t
}
color.a *= nodeColor.a * _skeleton->color.a * slot->color.a * 255;
// skip rendering if the color of this attachment is 0
if (color.a == 0){
spSkeletonClipping_clipEnd(_clipper, slot);
continue;
}
float multiplier = _premultipliedAlpha ? color.a : 255;
color.r *= nodeColor.r * _skeleton->color.r * slot->color.r * multiplier;
color.g *= nodeColor.g * _skeleton->color.g * slot->color.g * multiplier;
@ -308,8 +315,10 @@ void SkeletonRenderer::draw (Renderer* renderer, const Mat4& transform, uint32_t
spSkeletonClipping_clipTriangles(_clipper, (float*)&triangles.verts[0].vertices, triangles.vertCount * sizeof(cocos2d::V3F_C4B_T2F) / 4, triangles.indices, triangles.indexCount, (float*)&triangles.verts[0].texCoords, 6);
batch->deallocateVertices(triangles.vertCount);
if (_clipper->clippedTriangles->size == 0)
if (_clipper->clippedTriangles->size == 0){
spSkeletonClipping_clipEnd(_clipper, slot);
continue;
}
triangles.vertCount = _clipper->clippedVertices->size >> 1;
triangles.verts = batch->allocateVertices(triangles.vertCount);
@ -321,26 +330,70 @@ void SkeletonRenderer::draw (Renderer* renderer, const Mat4& transform, uint32_t
float* verts = _clipper->clippedVertices->items;
float* uvs = _clipper->clippedUVs->items;
for (int v = 0, vn = batchedTriangles->getTriangles().vertCount, vv = 0; v < vn; ++v, vv+=2) {
V3F_C4B_T2F* vertex = batchedTriangles->getTriangles().verts + v;
vertex->vertices.x = verts[vv];
vertex->vertices.y = verts[vv + 1];
vertex->texCoords.u = uvs[vv];
vertex->texCoords.v = uvs[vv + 1];
vertex->colors.r = (GLubyte)color.r;
vertex->colors.g = (GLubyte)color.g;
vertex->colors.b = (GLubyte)color.b;
vertex->colors.a = (GLubyte)color.a;
if (_effect) {
spColor light;
spColor dark;
light.r = color.r / 255.0f;
light.g = color.g / 255.0f;
light.b = color.b / 255.0f;
light.a = color.a / 255.0f;
dark.r = dark.g = dark.b = dark.a = 0;
for (int v = 0, vn = batchedTriangles->getTriangles().vertCount, vv = 0; v < vn; ++v, vv+=2) {
V3F_C4B_T2F* vertex = batchedTriangles->getTriangles().verts + v;
spColor lightCopy = light;
spColor darkCopy = dark;
vertex->vertices.x = verts[vv];
vertex->vertices.y = verts[vv + 1];
vertex->texCoords.u = uvs[vv];
vertex->texCoords.v = uvs[vv + 1];
_effect->transform(_effect, &vertex->vertices.x, &vertex->vertices.y, &vertex->texCoords.u, &vertex->texCoords.v, &lightCopy, &darkCopy);
vertex->colors.r = (GLubyte)(lightCopy.r * 255);
vertex->colors.g = (GLubyte)(lightCopy.g * 255);
vertex->colors.b = (GLubyte)(lightCopy.b * 255);
vertex->colors.a = (GLubyte)(lightCopy.a * 255);
}
} else {
for (int v = 0, vn = batchedTriangles->getTriangles().vertCount, vv = 0; v < vn; ++v, vv+=2) {
V3F_C4B_T2F* vertex = batchedTriangles->getTriangles().verts + v;
vertex->vertices.x = verts[vv];
vertex->vertices.y = verts[vv + 1];
vertex->texCoords.u = uvs[vv];
vertex->texCoords.v = uvs[vv + 1];
vertex->colors.r = (GLubyte)color.r;
vertex->colors.g = (GLubyte)color.g;
vertex->colors.b = (GLubyte)color.b;
vertex->colors.a = (GLubyte)color.a;
}
}
} else {
cocos2d::TrianglesCommand* batchedTriangles = batch->addCommand(renderer, _globalZOrder, attachmentVertices->_texture, _glProgramState, blendFunc, triangles, transform, transformFlags);
for (int v = 0, vn = batchedTriangles->getTriangles().vertCount; v < vn; ++v) {
V3F_C4B_T2F* vertex = batchedTriangles->getTriangles().verts + v;
vertex->colors.r = (GLubyte)color.r;
vertex->colors.g = (GLubyte)color.g;
vertex->colors.b = (GLubyte)color.b;
vertex->colors.a = (GLubyte)color.a;
if (_effect) {
spColor light;
spColor dark;
light.r = color.r / 255.0f;
light.g = color.g / 255.0f;
light.b = color.b / 255.0f;
light.a = color.a / 255.0f;
dark.r = dark.g = dark.b = dark.a = 0;
for (int v = 0, vn = batchedTriangles->getTriangles().vertCount; v < vn; ++v) {
V3F_C4B_T2F* vertex = batchedTriangles->getTriangles().verts + v;
spColor lightCopy = light;
spColor darkCopy = dark;
_effect->transform(_effect, &vertex->vertices.x, &vertex->vertices.y, &vertex->texCoords.u, &vertex->texCoords.v, &lightCopy, &darkCopy);
vertex->colors.r = (GLubyte)(lightCopy.r * 255);
vertex->colors.g = (GLubyte)(lightCopy.g * 255);
vertex->colors.b = (GLubyte)(lightCopy.b * 255);
vertex->colors.a = (GLubyte)(lightCopy.a * 255);
}
} else {
for (int v = 0, vn = batchedTriangles->getTriangles().vertCount; v < vn; ++v) {
V3F_C4B_T2F* vertex = batchedTriangles->getTriangles().verts + v;
vertex->colors.r = (GLubyte)color.r;
vertex->colors.g = (GLubyte)color.g;
vertex->colors.b = (GLubyte)color.b;
vertex->colors.a = (GLubyte)color.a;
}
}
}
} else {
@ -348,8 +401,10 @@ void SkeletonRenderer::draw (Renderer* renderer, const Mat4& transform, uint32_t
spSkeletonClipping_clipTriangles(_clipper, (float*)&trianglesTwoColor.verts[0].position, trianglesTwoColor.vertCount * sizeof(V3F_C4B_C4B_T2F) / 4, trianglesTwoColor.indices, trianglesTwoColor.indexCount, (float*)&trianglesTwoColor.verts[0].texCoords, 7);
twoColorBatch->deallocateVertices(trianglesTwoColor.vertCount);
if (_clipper->clippedTriangles->size == 0)
if (_clipper->clippedTriangles->size == 0){
spSkeletonClipping_clipEnd(_clipper, slot);
continue;
}
trianglesTwoColor.vertCount = _clipper->clippedVertices->size >> 1;
trianglesTwoColor.verts = twoColorBatch->allocateVertices(trianglesTwoColor.vertCount);
@ -361,34 +416,94 @@ void SkeletonRenderer::draw (Renderer* renderer, const Mat4& transform, uint32_t
float* verts = _clipper->clippedVertices->items;
float* uvs = _clipper->clippedUVs->items;
for (int v = 0, vn = batchedTriangles->getTriangles().vertCount, vv = 0; v < vn; ++v, vv += 2) {
V3F_C4B_C4B_T2F* vertex = batchedTriangles->getTriangles().verts + v;
vertex->position.x = verts[vv];
vertex->position.y = verts[vv + 1];
vertex->texCoords.u = uvs[vv];
vertex->texCoords.v = uvs[vv + 1];
vertex->color.r = (GLubyte)color.r;
vertex->color.g = (GLubyte)color.g;
vertex->color.b = (GLubyte)color.b;
vertex->color.a = (GLubyte)color.a;
vertex->color2.r = (GLubyte)darkColor.r;
vertex->color2.g = (GLubyte)darkColor.g;
vertex->color2.b = (GLubyte)darkColor.b;
vertex->color2.a = 1;
if (_effect) {
spColor light;
spColor dark;
light.r = color.r / 255.0f;
light.g = color.g / 255.0f;
light.b = color.b / 255.0f;
light.a = color.a / 255.0f;
dark.r = darkColor.r / 255.0f;
dark.g = darkColor.g / 255.0f;
dark.b = darkColor.b / 255.0f;
dark.a = darkColor.a / 255.0f;
for (int v = 0, vn = batchedTriangles->getTriangles().vertCount, vv = 0; v < vn; ++v, vv += 2) {
V3F_C4B_C4B_T2F* vertex = batchedTriangles->getTriangles().verts + v;
spColor lightCopy = light;
spColor darkCopy = dark;
vertex->position.x = verts[vv];
vertex->position.y = verts[vv + 1];
vertex->texCoords.u = uvs[vv];
vertex->texCoords.v = uvs[vv + 1];
_effect->transform(_effect, &vertex->position.x, &vertex->position.y, &vertex->texCoords.u, &vertex->texCoords.v, &lightCopy, &darkCopy);
vertex->color.r = (GLubyte)(lightCopy.r * 255);
vertex->color.g = (GLubyte)(lightCopy.g * 255);
vertex->color.b = (GLubyte)(lightCopy.b * 255);
vertex->color.a = (GLubyte)(lightCopy.a * 255);
vertex->color2.r = (GLubyte)(darkCopy.r * 255);
vertex->color2.g = (GLubyte)(darkCopy.g * 255);
vertex->color2.b = (GLubyte)(darkCopy.b * 255);
vertex->color2.a = 1;
}
} else {
for (int v = 0, vn = batchedTriangles->getTriangles().vertCount, vv = 0; v < vn; ++v, vv += 2) {
V3F_C4B_C4B_T2F* vertex = batchedTriangles->getTriangles().verts + v;
vertex->position.x = verts[vv];
vertex->position.y = verts[vv + 1];
vertex->texCoords.u = uvs[vv];
vertex->texCoords.v = uvs[vv + 1];
vertex->color.r = (GLubyte)color.r;
vertex->color.g = (GLubyte)color.g;
vertex->color.b = (GLubyte)color.b;
vertex->color.a = (GLubyte)color.a;
vertex->color2.r = (GLubyte)darkColor.r;
vertex->color2.g = (GLubyte)darkColor.g;
vertex->color2.b = (GLubyte)darkColor.b;
vertex->color2.a = 1;
}
}
} else {
TwoColorTrianglesCommand* batchedTriangles = lastTwoColorTrianglesCommand = twoColorBatch->addCommand(renderer, _globalZOrder, attachmentVertices->_texture->getName(), _glProgramState, blendFunc, trianglesTwoColor, transform, transformFlags);
for (int v = 0, vn = batchedTriangles->getTriangles().vertCount; v < vn; ++v) {
V3F_C4B_C4B_T2F* vertex = batchedTriangles->getTriangles().verts + v;
vertex->color.r = (GLubyte)color.r;
vertex->color.g = (GLubyte)color.g;
vertex->color.b = (GLubyte)color.b;
vertex->color.a = (GLubyte)color.a;
vertex->color2.r = (GLubyte)darkColor.r;
vertex->color2.g = (GLubyte)darkColor.g;
vertex->color2.b = (GLubyte)darkColor.b;
vertex->color2.a = 1;
if (_effect) {
spColor light;
spColor dark;
light.r = color.r / 255.0f;
light.g = color.g / 255.0f;
light.b = color.b / 255.0f;
light.a = color.a / 255.0f;
dark.r = darkColor.r / 255.0f;
dark.g = darkColor.g / 255.0f;
dark.b = darkColor.b / 255.0f;
dark.a = darkColor.a / 255.0f;
for (int v = 0, vn = batchedTriangles->getTriangles().vertCount; v < vn; ++v) {
V3F_C4B_C4B_T2F* vertex = batchedTriangles->getTriangles().verts + v;
spColor lightCopy = light;
spColor darkCopy = dark;
_effect->transform(_effect, &vertex->position.x, &vertex->position.y, &vertex->texCoords.u, &vertex->texCoords.v, &lightCopy, &darkCopy);
vertex->color.r = (GLubyte)(lightCopy.r * 255);
vertex->color.g = (GLubyte)(lightCopy.g * 255);
vertex->color.b = (GLubyte)(lightCopy.b * 255);
vertex->color.a = (GLubyte)(lightCopy.a * 255);
vertex->color2.r = (GLubyte)(darkCopy.r * 255);
vertex->color2.g = (GLubyte)(darkCopy.g * 255);
vertex->color2.b = (GLubyte)(darkCopy.b * 255);
vertex->color2.a = 1;
}
} else {
for (int v = 0, vn = batchedTriangles->getTriangles().vertCount; v < vn; ++v) {
V3F_C4B_C4B_T2F* vertex = batchedTriangles->getTriangles().verts + v;
vertex->color.r = (GLubyte)color.r;
vertex->color.g = (GLubyte)color.g;
vertex->color.b = (GLubyte)color.b;
vertex->color.a = (GLubyte)color.a;
vertex->color2.r = (GLubyte)darkColor.r;
vertex->color2.g = (GLubyte)darkColor.g;
vertex->color2.b = (GLubyte)darkColor.b;
vertex->color2.a = 1;
}
}
}
}
@ -432,6 +547,8 @@ void SkeletonRenderer::draw (Renderer* renderer, const Mat4& transform, uint32_t
}
}
}
if (_effect) _effect->end(_effect);
if (_debugSlots || _debugBones || _debugMeshes) {
drawDebug(renderer, transform, transformFlags);
@ -595,6 +712,10 @@ void SkeletonRenderer::setTwoColorTint(bool enabled) {
bool SkeletonRenderer::isTwoColorTint() {
return getGLProgramState() == SkeletonTwoColorBatch::getInstance()->getTwoColorTintProgramState();
}
void SkeletonRenderer::setVertexEffect(spVertexEffect *effect) {
this->_effect = effect;
}
spSkeleton* SkeletonRenderer::getSkeleton () {
return _skeleton;

View File

@ -99,6 +99,9 @@ public:
void setTwoColorTint(bool enabled);
/* Whether two color tinting is enabled */
bool isTwoColorTint();
/* Sets the vertex effect to be used, set to 0 to disable vertex effects */
void setVertexEffect(spVertexEffect* effect);
// --- BlendProtocol
virtual void setBlendFunc (const cocos2d::BlendFunc& blendFunc)override;
@ -125,7 +128,7 @@ CC_CONSTRUCTOR_ACCESS:
protected:
void setSkeletonData (spSkeletonData* skeletonData, bool ownsSkeletonData);
virtual AttachmentVertices* getAttachmentVertices (spRegionAttachment* attachment) const;
virtual AttachmentVertices* getAttachmentVertices (spMeshAttachment* attachment) const;
virtual AttachmentVertices* getAttachmentVertices (spMeshAttachment* attachment) const;
bool _ownsSkeletonData;
spAtlas* _atlas;
@ -140,6 +143,7 @@ protected:
bool _debugBones;
bool _debugMeshes;
spSkeletonClipping* _clipper;
spVertexEffect* _effect;
};
}

View File

@ -10,7 +10,7 @@ The Spine Runtimes are developed with the intent to be used with data exported f
## Spine version
spine-corona works with data exported from Spine 3.5.xx.
spine-corona works with data exported from Spine 3.6.xx.
spine-corona supports all Spine features.
@ -18,7 +18,7 @@ spine-corona does not yet support loading the binary format.
## Setup
1. Download the Spine Runtimes source using [git](https://help.github.com/articles/set-up-git) or by downloading it [as a zip](https://github.com/EsotericSoftware/spine-runtimes/archive/master.zip).
1. Download the Spine Runtimes source using [git](https://help.github.com/articles/set-up-git) or by downloading it [as a zip](https://github.com/EsotericSoftware/spine-runtimes/archive/3.6.zip).
1. Copy the contents of `spine-lua` to `spine-corona/spine-lua`.
1. Run the `main.lua` file using Corona. Tap/click to switch between skeletons

View File

@ -5,6 +5,8 @@ local spine = require "spine-corona.spine"
local skeletons = {}
local activeSkeleton = 1
local lastTime = 0
local swirl = spine.SwirlEffect.new(400)
local swirlTime = 0
function loadSkeleton(atlasFile, jsonFile, x, y, scale, animation, skin)
-- to load an atlas, we need to define a function that returns
@ -67,7 +69,11 @@ function loadSkeleton(atlasFile, jsonFile, x, y, scale, animation, skin)
animationState:setAnimationByName(0, "walk", true)
local jumpEntry = animationState:addAnimationByName(0, "jump", false, 3)
animationState:addAnimationByName(0, "run", true, 0)
else
elseif atlasFile == "raptor.atlas" then
--skeleton.vertexEffect = spine.JitterEffect.new(5, 5)
skeleton.vertexEffect = swirl
animationState:setAnimationByName(0, animation, true)
else
animationState:setAnimationByName(0, animation, true)
end
@ -77,11 +83,11 @@ end
-- table.insert(skeletons, loadSkeleton("coin.atlas", "coin-pro.json", 240, 300, 0.4, "rotate"))
-- table.insert(skeletons, loadSkeleton("spineboy.atlas", "spineboy-ess.json", 240, 300, 0.4, "walk"))
-- table.insert(skeletons, loadSkeleton("raptor.atlas", "raptor-pro.json", 200, 300, 0.25, "walk"))
table.insert(skeletons, loadSkeleton("raptor.atlas", "raptor-pro.json", 200, 300, 0.25, "walk"))
-- table.insert(skeletons, loadSkeleton("goblins.atlas", "goblins-pro.json", 240, 300, 0.8, "walk", "goblin"))
-- table.insert(skeletons, loadSkeleton("stretchyman.atlas", "stretchyman-pro.json", 40, 300, 0.5, "sneak"))
table.insert(skeletons, loadSkeleton("tank.atlas", "tank-pro.json", 400, 300, 0.2, "drive"))
-- table.insert(skeletons, loadSkeleton("vine.atlas", "vine-pro.json", 240, 300, 0.3, "grow"))
table.insert(skeletons, loadSkeleton("stretchyman.atlas", "stretchyman-pro.json", 40, 300, 0.5, "sneak"))
-- table.insert(skeletons, loadSkeleton("tank.atlas", "tank-pro.json", 400, 300, 0.2, "drive"))
table.insert(skeletons, loadSkeleton("vine.atlas", "vine-pro.json", 240, 300, 0.3, "grow"))
local triangulator = spine.Triangulator.new()
local polygon = { 411, 219, 199, 230, 161, 362, 534, 407, 346, 305, 596, 265 }
@ -109,6 +115,11 @@ Runtime:addEventListener("enterFrame", function (event)
local currentTime = event.time / 1000
local delta = currentTime - lastTime
lastTime = currentTime
swirlTime = swirlTime + delta
local percent = swirlTime % 2
if (percent > 1) then percent = 1 - (percent - 1) end
swirl.angle = spine.Interpolation.apply(spine.Interpolation.pow2, -60, 60, percent)
skeleton = skeletons[activeSkeleton].skeleton
skeleton.group.isVisible = true

View File

@ -65,6 +65,9 @@ spine.AtlasAttachmentLoader = require "spine-lua.AtlasAttachmentLoader"
spine.Color = require "spine-lua.Color"
spine.Triangulator = require "spine-lua.Triangulator"
spine.SkeletonClipping = require "spine-lua.SkeletonClipping"
spine.JitterEffect = require "spine-lua.vertexeffects.JitterEffect"
spine.SwirlEffect = require "spine-lua.vertexeffects.SwirlEffect"
spine.Interpolation = require "spine-lua.Interpolation"
spine.utils.readFile = function (fileName, base)
if not base then base = system.ResourceDirectory end
@ -92,6 +95,14 @@ spine.Skeleton.new = function(skeletonData, group)
self.batches = 0
self.tempColor = spine.Color.newWith(1, 1, 1, 1)
self.tempColor2 = spine.Color.newWith(-1, 1, 1, 1)
self.tempVertex = {
x = 0,
y = 0,
u = 0,
v = 0,
light = spine.Color.newWith(1, 1, 1, 1),
dark = spine.Color.newWith(0, 0, 0, 0)
}
self.clipper = spine.SkeletonClipping.new()
return self
end
@ -119,6 +130,8 @@ function spine.Skeleton:updateWorldTransform()
local premultipliedAlpha = self.premultipliedAlpha
self.batches = 0
if (self.vertexEffect) then self.vertexEffect:beginEffect(self) end
-- Remove old drawing group, we will start anew
if self.drawingGroup then self.drawingGroup:removeSelf() end
@ -217,6 +230,7 @@ function spine.Skeleton:updateWorldTransform()
end
self.clipper:clipEnd2()
if (self.vertexEffect) then self.vertexEffect:endEffect() end
end
function spine.Skeleton:flush(groupVertices, groupUvs, groupIndices, texture, color, blendMode, drawingGroup)
@ -250,13 +264,31 @@ function spine.Skeleton:batch(vertices, uvs, numVertices, indices, groupVertices
i = 1
local vertexStart = #groupVertices + 1
local vertexEnd = vertexStart + numVertices * 2
while vertexStart < vertexEnd do
groupVertices[vertexStart] = vertices[i]
groupVertices[vertexStart+1] = vertices[i+1]
groupUvs[vertexStart] = uvs[i]
groupUvs[vertexStart+1] = uvs[i+1]
vertexStart = vertexStart + 2
i = i + 2
if (self.vertexEffect) then
local effect = self.vertexEffect
local vertex = self.tempVertex
while vertexStart < vertexEnd do
vertex.x = vertices[i]
vertex.y = vertices[i+1]
vertex.u = uvs[i]
vertex.v = uvs[i+1]
effect:transform(vertex);
groupVertices[vertexStart] = vertex.x
groupVertices[vertexStart+1] = vertex.y
groupUvs[vertexStart] = vertex.u
groupUvs[vertexStart+1] = vertex.v
vertexStart = vertexStart + 2
i = i + 2
end
else
while vertexStart < vertexEnd do
groupVertices[vertexStart] = vertices[i]
groupVertices[vertexStart+1] = vertices[i+1]
groupUvs[vertexStart] = uvs[i]
groupUvs[vertexStart+1] = uvs[i+1]
vertexStart = vertexStart + 2
i = i + 2
end
end
end

View File

@ -16,7 +16,7 @@ spine-csharp supports all Spine features.
## Setup
1. Download the Spine Runtimes source using [git](https://help.github.com/articles/set-up-git) or by downloading it [as a zip](https://github.com/EsotericSoftware/spine-runtimes/archive/master.zip).
1. Download the Spine Runtimes source using [git](https://help.github.com/articles/set-up-git) or by downloading it [as a zip](https://github.com/EsotericSoftware/spine-runtimes/archive/3.6.zip).
1. Open the `spine-csharp.sln` Visual Studio 2015 Community project file.
Alternatively, the contents of the `spine-csharp/src` directory can be copied into your project.

View File

@ -34,21 +34,21 @@ using System.Collections.Generic;
namespace Spine {
public class AnimationState {
static readonly Animation EmptyAnimation = new Animation("<empty>", new ExposedList<Timeline>(), 0);
internal const int SUBSEQUENT = 0, FIRST = 1, DIP = 2, DIP_MIX = 3;
internal const int Subsequent = 0, First = 1, Dip = 2, DipMix = 3;
private AnimationStateData data;
private readonly ExposedList<TrackEntry> tracks = new ExposedList<TrackEntry>();
private readonly HashSet<int> propertyIDs = new HashSet<int>();
private readonly ExposedList<Event> events = new ExposedList<Event>();
private readonly EventQueue queue;
Pool<TrackEntry> trackEntryPool = new Pool<TrackEntry>();
private readonly ExposedList<TrackEntry> tracks = new ExposedList<TrackEntry>();
private readonly ExposedList<Event> events = new ExposedList<Event>();
private readonly EventQueue queue; // Initialized by constructor.
private readonly HashSet<int> propertyIDs = new HashSet<int>();
private readonly ExposedList<TrackEntry> mixingTo = new ExposedList<TrackEntry>();
private bool animationsChanged;
private float timeScale = 1;
Pool<TrackEntry> trackEntryPool = new Pool<TrackEntry>();
public AnimationStateData Data { get { return data; } }
/// <summary>A list of tracks that have animations, which may contain nulls.</summary>
public ExposedList<TrackEntry> Tracks { get { return tracks; } }
@ -63,13 +63,13 @@ namespace Spine {
public AnimationState (AnimationStateData data) {
if (data == null) throw new ArgumentNullException("data", "data cannot be null.");
this.data = data;
this.queue = new EventQueue(this, HandleAnimationsChanged, trackEntryPool);
this.queue = new EventQueue(
this,
delegate { this.animationsChanged = true; },
trackEntryPool
);
}
void HandleAnimationsChanged () {
this.animationsChanged = true;
}
/// <summary>
/// Increments the track entry times, setting queued animations as current if needed</summary>
/// <param name="delta">delta time</param>
@ -155,7 +155,6 @@ namespace Spine {
return false;
}
/// <summary>
/// Poses the skeleton using the track entry animations. There are no side effects other than invoking listeners, so the
/// animation state can be applied to multiple skeletons to pose them identically.</summary>
@ -197,7 +196,7 @@ namespace Spine {
for (int ii = 0; ii < timelineCount; ii++) {
Timeline timeline = timelinesItems[ii];
MixPose pose = timelineData[ii] >= FIRST ? MixPose.Setup : currentPose;
MixPose pose = timelineData[ii] >= AnimationState.First ? MixPose.Setup : currentPose;
var rotateTimeline = timeline as RotateTimeline;
if (rotateTimeline != null)
ApplyRotateTimeline(rotateTimeline, skeleton, animationTime, mix, pose, timelinesRotation, ii << 1, firstFrame);
@ -246,17 +245,17 @@ namespace Spine {
for (int i = 0; i < timelineCount; i++) {
Timeline timeline = timelinesItems[i];
switch (timelineData[i]) {
case SUBSEQUENT:
case Subsequent:
if (!attachments && timeline is AttachmentTimeline) continue;
if (!drawOrder && timeline is DrawOrderTimeline) continue;
pose = currentPose;
alpha = alphaMix;
break;
case FIRST:
case First:
pose = MixPose.Setup;
alpha = alphaMix;
break;
case DIP:
case Dip:
pose = MixPose.Setup;
alpha = alphaDip;
break;
@ -421,6 +420,7 @@ namespace Spine {
queue.Drain();
}
/// <summary>Sets the active TrackEntry for a given track number.</summary>
private void SetCurrent (int index, TrackEntry current, bool interrupt) {
TrackEntry from = ExpandToIndex(index);
tracks.Items[index] = current;
@ -437,12 +437,12 @@ namespace Spine {
from.timelinesRotation.Clear(); // Reset rotation for mixing out, in case entry was mixed in.
}
queue.Start(current);
queue.Start(current); // triggers AnimationsChanged
}
/// <summary>Sets an animation by name. <seealso cref="SetAnimation(int, Animation, bool)" /></summary>
public TrackEntry SetAnimation (int trackIndex, String animationName, bool loop) {
public TrackEntry SetAnimation (int trackIndex, string animationName, bool loop) {
Animation animation = data.skeletonData.FindAnimation(animationName);
if (animation == null) throw new ArgumentException("Animation not found: " + animationName, "animationName");
return SetAnimation(trackIndex, animation, loop);
@ -480,7 +480,7 @@ namespace Spine {
/// <summary>Queues an animation by name.</summary>
/// <seealso cref="AddAnimation(int, Animation, bool, float)" />
public TrackEntry AddAnimation (int trackIndex, String animationName, bool loop, float delay) {
public TrackEntry AddAnimation (int trackIndex, string animationName, bool loop, float delay) {
Animation animation = data.skeletonData.FindAnimation(animationName);
if (animation == null) throw new ArgumentException("Animation not found: " + animationName, "animationName");
return AddAnimation(trackIndex, animation, loop, delay);
@ -570,6 +570,7 @@ namespace Spine {
return null;
}
/// <summary>Object-pooling version of new TrackEntry. Obtain an unused TrackEntry from the pool and clear/initialize its values.</summary>
/// <param name="last">May be null.</param>
private TrackEntry NewTrackEntry (int trackIndex, Animation animation, bool loop, TrackEntry last) {
TrackEntry entry = trackEntryPool.Obtain(); // Pooling
@ -589,7 +590,7 @@ namespace Spine {
entry.delay = 0;
entry.trackTime = 0;
entry.trackLast = -1;
entry.nextTrackLast = -1;
entry.nextTrackLast = -1; // nextTrackLast == -1 signifies a TrackEntry that wasn't applied yet.
entry.trackEnd = float.MaxValue; // loop ? float.MaxValue : animation.Duration;
entry.timeScale = 1;
@ -600,6 +601,7 @@ namespace Spine {
return entry;
}
/// <summary>Dispose all track entries queued after the given TrackEntry.</summary>
private void DisposeNext (TrackEntry entry) {
TrackEntry next = entry.next;
while (next != null) {
@ -628,7 +630,7 @@ namespace Spine {
return (trackIndex >= tracks.Count) ? null : tracks.Items[trackIndex];
}
override public String ToString () {
override public string ToString () {
var buffer = new System.Text.StringBuilder();
for (int i = 0, n = tracks.Count; i < n; i++) {
TrackEntry entry = tracks.Items[i];
@ -680,11 +682,12 @@ namespace Spine {
Event = null;
}
/// <summary>Sets the timeline data.</summary>
/// <param name="to">May be null.</param>
internal TrackEntry SetTimelineData (TrackEntry to, ExposedList<TrackEntry> mixingToArray, HashSet<int> propertyIDs) {
if (to != null) mixingToArray.Add(to);
var lastEntry = mixingFrom != null ? mixingFrom.SetTimelineData(this, mixingToArray, propertyIDs) : this;
if (to != null) mixingToArray.RemoveAt(mixingToArray.Count - 1); // mixingToArray.pop();
if (to != null) mixingToArray.Pop();
var mixingTo = mixingToArray.Items;
int mixingToLast = mixingToArray.Count - 1;
@ -698,21 +701,19 @@ namespace Spine {
for (int i = 0; i < timelinesCount; i++) {
int id = timelines[i].PropertyId;
if (!propertyIDs.Add(id)) {
timelineDataItems[i] = AnimationState.SUBSEQUENT;
timelineDataItems[i] = AnimationState.Subsequent;
} else if (to == null || !to.HasTimeline(id)) {
timelineDataItems[i] = AnimationState.FIRST;
timelineDataItems[i] = AnimationState.First;
} else {
for (int ii = mixingToLast; ii >= 0; ii--) {
var entry = mixingTo[ii];
if (!entry.HasTimeline(id)) {
if (entry.mixDuration > 0) {
timelineDataItems[i] = AnimationState.DIP_MIX;
timelineDipMixItems[i] = entry;
goto outer; // continue outer;
}
if (entry.mixDuration > 0 && !entry.HasTimeline(id)) {
timelineDataItems[i] = AnimationState.DipMix;
timelineDipMixItems[i] = entry;
goto outer; // continue outer;
}
}
timelineDataItems[i] = AnimationState.DIP;
timelineDataItems[i] = AnimationState.Dip;
}
outer: {}
}
@ -886,20 +887,20 @@ namespace Spine {
timelinesRotation.Clear();
}
override public String ToString () {
override public string ToString () {
return animation == null ? "<none>" : animation.name;
}
}
class EventQueue {
private readonly List<EventQueueEntry> eventQueueEntries = new List<EventQueueEntry>();
public bool drainDisabled;
internal bool drainDisabled;
private readonly AnimationState state;
private readonly Pool<TrackEntry> trackEntryPool;
public event Action AnimationsChanged;
internal event Action AnimationsChanged;
public EventQueue (AnimationState state, Action HandleAnimationsChanged, Pool<TrackEntry> trackEntryPool) {
internal EventQueue (AnimationState state, Action HandleAnimationsChanged, Pool<TrackEntry> trackEntryPool) {
this.state = state;
this.AnimationsChanged += HandleAnimationsChanged;
this.trackEntryPool = trackEntryPool;
@ -921,33 +922,34 @@ namespace Spine {
Start, Interrupt, End, Dispose, Complete, Event
}
public void Start (TrackEntry entry) {
internal void Start (TrackEntry entry) {
eventQueueEntries.Add(new EventQueueEntry(EventType.Start, entry));
if (AnimationsChanged != null) AnimationsChanged();
}
public void Interrupt (TrackEntry entry) {
internal void Interrupt (TrackEntry entry) {
eventQueueEntries.Add(new EventQueueEntry(EventType.Interrupt, entry));
}
public void End (TrackEntry entry) {
internal void End (TrackEntry entry) {
eventQueueEntries.Add(new EventQueueEntry(EventType.End, entry));
if (AnimationsChanged != null) AnimationsChanged();
}
public void Dispose (TrackEntry entry) {
internal void Dispose (TrackEntry entry) {
eventQueueEntries.Add(new EventQueueEntry(EventType.Dispose, entry));
}
public void Complete (TrackEntry entry) {
internal void Complete (TrackEntry entry) {
eventQueueEntries.Add(new EventQueueEntry(EventType.Complete, entry));
}
public void Event (TrackEntry entry, Event e) {
internal void Event (TrackEntry entry, Event e) {
eventQueueEntries.Add(new EventQueueEntry(EventType.Event, entry, e));
}
public void Drain () {
/// <summary>Raises all events in the queue and drains the queue.</summary>
internal void Drain () {
if (drainDisabled) return;
drainDisabled = true;
@ -992,7 +994,7 @@ namespace Spine {
drainDisabled = false;
}
public void Clear () {
internal void Clear () {
eventQueueEntries.Clear();
}
}

View File

@ -28,6 +28,10 @@
* POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#if (UNITY_5 || UNITY_5_3_OR_NEWER || UNITY_WSA || UNITY_WP8 || UNITY_WP8_1)
#define IS_UNITY
#endif
using System;
using System.Collections.Generic;
using System.IO;
@ -39,12 +43,22 @@ using Windows.Storage;
#endif
namespace Spine {
public class Atlas {
public class Atlas : IEnumerable<AtlasRegion> {
readonly List<AtlasPage> pages = new List<AtlasPage>();
List<AtlasRegion> regions = new List<AtlasRegion>();
TextureLoader textureLoader;
#if !(UNITY_5 || UNITY_4 || UNITY_WSA || UNITY_WP8 || UNITY_WP8_1) // !UNITY
#region IEnumerable implementation
public IEnumerator<AtlasRegion> GetEnumerator () {
return regions.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator () {
return regions.GetEnumerator();
}
#endregion
#if !(IS_UNITY)
#if WINDOWS_STOREAPP
private async Task ReadFile(string path, TextureLoader textureLoader) {
var folder = Windows.ApplicationModel.Package.Current.InstalledLocation;
@ -82,7 +96,7 @@ namespace Spine {
}
#endif // WINDOWS_STOREAPP
#endif // !(UNITY)
#endif
public Atlas (TextReader reader, string dir, TextureLoader textureLoader) {
Load(reader, dir, textureLoader);
@ -95,7 +109,7 @@ namespace Spine {
}
private void Load (TextReader reader, string imagesDir, TextureLoader textureLoader) {
if (textureLoader == null) throw new ArgumentNullException("textureLoader cannot be null.");
if (textureLoader == null) throw new ArgumentNullException("textureLoader", "textureLoader cannot be null.");
this.textureLoader = textureLoader;
string[] tuple = new string[4];
@ -164,11 +178,11 @@ namespace Spine {
region.height = Math.Abs(height);
if (ReadTuple(reader, tuple) == 4) { // split is optional
region.splits = new int[] {int.Parse(tuple[0]), int.Parse(tuple[1]),
region.splits = new [] {int.Parse(tuple[0]), int.Parse(tuple[1]),
int.Parse(tuple[2]), int.Parse(tuple[3])};
if (ReadTuple(reader, tuple) == 4) { // pad is optional, but only present with splits
region.pads = new int[] {int.Parse(tuple[0]), int.Parse(tuple[1]),
region.pads = new [] {int.Parse(tuple[0]), int.Parse(tuple[1]),
int.Parse(tuple[2]), int.Parse(tuple[3])};
ReadTuple(reader, tuple);

View File

@ -246,14 +246,14 @@ namespace Spine {
float lb = MathUtils.CosDeg(90 + shearY) * scaleY;
float lc = MathUtils.SinDeg(shearX) * scaleX;
float ld = MathUtils.SinDeg(90 + shearY) * scaleY;
if (data.transformMode != TransformMode.NoScaleOrReflection? pa * pd - pb* pc< 0 : skeleton.flipX != skeleton.flipY) {
zb = -zb;
zd = -zd;
}
a = za * la + zb * lc;
b = za * lb + zb * ld;
c = zc * la + zd * lc;
d = zc * lb + zd * ld;
if (data.transformMode != TransformMode.NoScaleOrReflection ? pa * pd - pb * pc < 0 : skeleton.flipX != skeleton.flipY) {
b = -b;
d = -d;
}
d = zc * lb + zd * ld;
return;
}
}

View File

@ -104,14 +104,14 @@ namespace Spine {
}
}
private void CheckRange (int idx, int count) {
if (idx < 0)
private void CheckRange (int index, int count) {
if (index < 0)
throw new ArgumentOutOfRangeException("index");
if (count < 0)
throw new ArgumentOutOfRangeException("count");
if ((uint)idx + (uint)count > (uint)Count)
if ((uint)index + (uint)count > (uint)Count)
throw new ArgumentException("index and count exceed length of list");
}
@ -450,6 +450,21 @@ namespace Spine {
version++;
}
// Spine Added Method
// Based on Stack<T>.Pop(); https://referencesource.microsoft.com/#mscorlib/system/collections/stack.cs
/// <summary>Pops the last item of the list. If the list is empty, Pop throws an InvalidOperationException.</summary>
public T Pop () {
if (Count == 0)
throw new InvalidOperationException("List is empty. Nothing to pop.");
int i = Count - 1;
T item = Items[i];
Items[i] = default(T);
Count--;
version++;
return item;
}
public void RemoveRange (int index, int count) {
CheckRange(index, count);
if (count > 0) {

View File

@ -91,7 +91,9 @@ namespace Spine {
if (scale) lengths = this.lengths.Resize(boneCount);
for (int i = 0, n = spacesCount - 1; i < n;) {
Bone bone = bonesItems[i];
float setupLength = bone.data.length, x = setupLength * bone.a, y = setupLength * bone.c;
float setupLength = bone.data.length;
if (setupLength == 0) setupLength = 0.000000001f;
float x = setupLength * bone.a, y = setupLength * bone.c;
float length = (float)Math.Sqrt(x * x + y * y);
if (scale) lengths.Items[i] = setupLength;
spaces.Items[++i] = (lengthSpacing ? Math.Max(0, setupLength + spacing) : spacing) * length / setupLength;

View File

@ -502,14 +502,16 @@ namespace Spine {
var regionAttachment = attachment as RegionAttachment;
if (regionAttachment != null) {
verticesLength = 8;
if (temp.Length < 8) temp = new float[8];
vertices = temp;
if (vertices.Length < 8) vertices = temp = new float[8];
regionAttachment.ComputeWorldVertices(slot.bone, temp, 0);
} else {
var meshAttachment = attachment as MeshAttachment;
if (meshAttachment != null) {
MeshAttachment mesh = meshAttachment;
verticesLength = mesh.WorldVerticesLength;
if (temp.Length < verticesLength) temp = new float[verticesLength];
vertices = temp;
if (vertices.Length < verticesLength) vertices = temp = new float[verticesLength];
mesh.ComputeWorldVertices(slot, 0, verticesLength, temp, 0);
}
}

View File

@ -28,7 +28,7 @@
* POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#if (UNITY_5 || UNITY_4_0 || UNITY_4_1 || UNITY_4_2 || UNITY_4_3 || UNITY_4_4 || UNITY_4_5 || UNITY_4_6 || UNITY_4_7 || UNITY_WSA || UNITY_WP8 || UNITY_WP8_1)
#if (UNITY_5 || UNITY_5_3_OR_NEWER || UNITY_WSA || UNITY_WP8 || UNITY_WP8_1)
#define IS_UNITY
#endif

View File

@ -154,7 +154,7 @@ namespace Spine {
clippedUVsItems[s + 2] = u2;
clippedUVsItems[s + 3] = v2;
clippedUVsItems[s + 4] = u3;
clippedUVsItems[s + 5] = v3;
clippedUVsItems[s + 5] = v3;
s = clippedTriangles.Count;
int[] clippedTrianglesItems = clippedTriangles.Resize(s + 3).Items;
@ -180,9 +180,9 @@ namespace Spine {
if (clippingArea.Count % 4 >= 2) {
input = output;
output = scratch;
}
else
} else {
input = scratch;
}
input.Clear();
input.Add(x1);
@ -251,14 +251,14 @@ namespace Spine {
for (int i = 0, n = output.Count - 2; i < n; i++) {
originalOutput.Add(output.Items[i]);
}
}
else
} else {
originalOutput.Resize(originalOutput.Count - 2);
}
return clipped;
}
static void MakeClockwise (ExposedList<float> polygon) {
public static void MakeClockwise (ExposedList<float> polygon) {
float[] vertices = polygon.Items;
int verticeslength = polygon.Count;

View File

@ -420,10 +420,17 @@ namespace Spine {
ClippingAttachment clip = attachmentLoader.NewClippingAttachment(skin, name);
if (clip == null) return null;
SlotData slot = skeletonData.FindSlot(GetString(map, "end", null));
if (slot == null) throw new Exception("Clipping end slot not found: " + GetString(map, "end", null));
clip.endSlot = slot;
string end = GetString(map, "end", null);
if (end != null) {
SlotData slot = skeletonData.FindSlot(end);
if (slot == null) throw new Exception("Clipping end slot not found: " + end);
clip.EndSlot = slot;
}
ReadVertices(map, clip, GetInt(map, "vertexCount", 0) << 1);
//string color = GetString(map, "color", null);
// if (color != null) clip.color = color;
return clip;
}
}

View File

@ -31,7 +31,7 @@
using System;
namespace Spine {
internal class Triangulator {
public class Triangulator {
private readonly ExposedList<ExposedList<float>> convexPolygons = new ExposedList<ExposedList<float>>();
private readonly ExposedList<ExposedList<int>> convexPolygonsIndices = new ExposedList<ExposedList<int>>();
@ -84,6 +84,7 @@ namespace Spine {
}
break;
}
outer:
if (next == 0) {
do {
@ -97,7 +98,6 @@ namespace Spine {
i = next;
next = (next + 1) % vertexCount;
}
outer:
// Cut ear tip.
triangles.Add(indices[(vertexCount + i - 1) % vertexCount]);

View File

@ -10,13 +10,13 @@ The Spine Runtimes are developed with the intent to be used with data exported f
## Spine version
spine-libgdx works with data exported from Spine 3.5.xx.
spine-libgdx works with data exported from Spine 3.6.xx.
spine-libgdx supports all Spine features and is the reference runtime implementation.
## Setup
1. Download the Spine Runtimes source using [git](https://help.github.com/articles/set-up-git) or by downloading it [as a zip](https://github.com/EsotericSoftware/spine-runtimes/archive/master.zip).
1. Download the Spine Runtimes source using [git](https://help.github.com/articles/set-up-git) or by downloading it [as a zip](https://github.com/EsotericSoftware/spine-runtimes/archive/3.6.zip).
1. Using Eclipse, import the project by choosing File -> Import -> Existing projects. For other IDEs you will need to create a new project and import the source.
Alternatively, the contents of the `spine-libgdx/src` directory can be copied into your project.

View File

@ -39,6 +39,7 @@ import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.g2d.PolygonSpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.math.Interpolation;
import com.esotericsoftware.spine.vertexeffects.JitterEffect;
import com.esotericsoftware.spine.vertexeffects.SwirlEffect;
public class VertexEffectTest extends ApplicationAdapter {

View File

@ -201,15 +201,15 @@ public class Bone implements Updatable {
float la = cosDeg(shearX) * scaleX;
float lb = cosDeg(90 + shearY) * scaleY;
float lc = sinDeg(shearX) * scaleX;
float ld = sinDeg(90 + shearY) * scaleY;
float ld = sinDeg(90 + shearY) * scaleY;
if (data.transformMode != TransformMode.noScaleOrReflection ? pa * pd - pb * pc < 0 : skeleton.flipX != skeleton.flipY) {
zb = -zb;
zd = -zd;
}
a = za * la + zb * lc;
b = za * lb + zb * ld;
c = zc * la + zd * lc;
d = zc * lb + zd * ld;
if (data.transformMode != TransformMode.noScaleOrReflection ? pa * pd - pb * pc < 0 : skeleton.flipX != skeleton.flipY) {
b = -b;
d = -d;
}
return;
}
}

View File

@ -112,9 +112,11 @@ public class PathConstraint implements Constraint {
if (scale) lengths = this.lengths.setSize(boneCount);
for (int i = 0, n = spacesCount - 1; i < n;) {
Bone bone = (Bone)bones[i];
float setupLength = bone.data.length, x = setupLength * bone.a, y = setupLength * bone.c;
float setupLength = bone.data.length;
if (setupLength == 0) setupLength = 0.000000001f;
float x = setupLength * bone.a, y = setupLength * bone.c;
float length = (float)Math.sqrt(x * x + y * y);
if (scale) lengths[i] = length;
if (scale) lengths[i] = length;
spaces[++i] = (lengthSpacing ? setupLength + spacing : spacing) * length / setupLength;
}
} else {

View File

@ -56,7 +56,8 @@ public class SkeletonClipping {
float[] vertices = clippingPolygon.setSize(n);
clip.computeWorldVertices(slot, 0, n, vertices, 0, 2);
makeClockwise(clippingPolygon);
clippingPolygons = triangulator.decompose(clippingPolygon, triangulator.triangulate(clippingPolygon));
ShortArray triangles = triangulator.triangulate(clippingPolygon);
clippingPolygons = triangulator.decompose(clippingPolygon, triangles);
for (FloatArray polygon : clippingPolygons) {
makeClockwise(polygon);
polygon.add(polygon.items[0]);

View File

@ -18,7 +18,7 @@ spine-love does not yet support loading the binary format.
## Setup
1. Download the Spine Runtimes source using [git](https://help.github.com/articles/set-up-git) or by downloading it [as a zip](https://github.com/EsotericSoftware/spine-runtimes/archive/master.zip).
1. Download the Spine Runtimes source using [git](https://help.github.com/articles/set-up-git) or by downloading it [as a zip](https://github.com/EsotericSoftware/spine-runtimes/archive/3.6.zip).
1. Copy the contents of `spine-lua` to `spine-love/spine-lua`.
1. Run the `main.lua` file using LÖVE.

View File

@ -32,6 +32,8 @@ local spine = require "spine-love.spine"
local skeletons = {}
local activeSkeleton = 1
local swirl = spine.SwirlEffect.new(400)
local swirlTime = 0
function loadSkeleton (jsonFile, atlasFile, animation, skin, scale, x, y)
local loader = function (path) return love.graphics.newImage("data/" .. path) end
@ -53,13 +55,19 @@ function loadSkeleton (jsonFile, atlasFile, animation, skin, scale, x, y)
local stateData = spine.AnimationStateData.new(skeletonData)
local state = spine.AnimationState.new(stateData)
state:setAnimationByName(0, animation, true)
if (jsonFile == "spineboy") then
if (jsonFile == "spineboy-ess") then
stateData:setMix("walk", "jump", 0.5)
stateData:setMix("jump", "run", 0.5)
state:addAnimationByName(0, "jump", false, 3)
state:addAnimationByName(0, "run", true, 0)
end
if (jsonFile == "raptor-pro") then
swirl.centerY = -200
skeleton.vertexEffect = swirl
-- skeleton.vertexEffect = spine.JitterEffect.new(10, 10)
end
-- set some event callbacks
state.onStart = function (entry)
print(entry.trackIndex.." start: "..entry.animation.name)
@ -88,6 +96,7 @@ end
function love.load(arg)
if arg[#arg] == "-debug" then require("mobdebug").start() end
skeletonRenderer = spine.SkeletonRenderer.new(true)
table.insert(skeletons, loadSkeleton("coin-pro", "coin", "rotate", nil, 0.5, 400, 500))
table.insert(skeletons, loadSkeleton("spineboy-ess", "spineboy", "walk", nil, 0.5, 400, 500))
table.insert(skeletons, loadSkeleton("raptor-pro", "raptor", "walk", nil, 0.3, 400, 500))
@ -95,7 +104,6 @@ function love.load(arg)
table.insert(skeletons, loadSkeleton("tank-pro", "tank", "drive", nil, 0.2, 600, 500))
table.insert(skeletons, loadSkeleton("vine-pro", "vine", "grow", nil, 0.3, 400, 500))
table.insert(skeletons, loadSkeleton("stretchyman-pro", "stretchyman", "sneak", nil, 0.3, 200, 500))
skeletonRenderer = spine.SkeletonRenderer.new(true)
end
function love.update (delta)
@ -105,12 +113,25 @@ function love.update (delta)
state:update(delta)
state:apply(skeleton)
skeleton:updateWorldTransform()
if (skeleton.vertexEffect) then
skeletonRenderer.vertexEffect = skeleton.vertexEffect
if (skeleton.vertexEffect == swirl) then
swirlTime = swirlTime + delta
local percent = swirlTime % 2
if (percent > 1) then percent = 1 - (percent - 1) end
swirl.angle = spine.Interpolation.apply(spine.Interpolation.pow2, -60, 60, percent)
end
else
skeletonRenderer.vertexEffect = nil
end
end
function love.draw ()
love.graphics.setBackgroundColor(128, 128, 128, 255)
love.graphics.setColor(255, 255, 255)
local skeleton = skeletons[activeSkeleton].skeleton
skeletonRenderer:draw(skeleton)
end

View File

@ -67,6 +67,9 @@ spine.AtlasAttachmentLoader = require "spine-lua.AtlasAttachmentLoader"
spine.Color = require "spine-lua.Color"
spine.Triangulator = require "spine-lua.Triangulator"
spine.SkeletonClipping = require "spine-lua.SkeletonClipping"
spine.JitterEffect = require "spine-lua.vertexeffects.JitterEffect"
spine.SwirlEffect = require "spine-lua.vertexeffects.SwirlEffect"
spine.Interpolation = require "spine-lua.Interpolation"
spine.utils.readFile = function (fileName, base)
local path = fileName
@ -139,7 +142,15 @@ function PolygonBatcher.new(vertexCount, useTwoColorTint)
vertex = { 0, 0, 0, 0, 0, 0, 0, 0 },
indices = nil,
useTwoColorTint = useTwoColorTint,
twoColorTintShader = twoColorTintShader
twoColorTintShader = twoColorTintShader,
tempVertex = {
x = 0,
y = 0,
u = 0,
v = 0,
light = spine.Color.newWith(1, 1, 1, 1),
dark = spine.Color.newWith(0, 0, 0, 0)
}
}
local indices = {}
@ -163,7 +174,7 @@ function PolygonBatcher:begin ()
self.drawCalls = 0
end
function PolygonBatcher:draw (texture, vertices, uvs, numVertices, indices, color, darkColor)
function PolygonBatcher:draw (texture, vertices, uvs, numVertices, indices, color, darkColor, vertexEffect)
local numIndices = #indices
local mesh = self.mesh
@ -207,14 +218,44 @@ function PolygonBatcher:draw (texture, vertices, uvs, numVertices, indices, colo
end
local v = 1
while vertexStart < vertexEnd do
vertex[1] = vertices[v]
vertex[2] = vertices[v + 1]
vertex[3] = uvs[v]
vertex[4] = uvs[v + 1]
mesh:setVertex(vertexStart, vertex)
vertexStart = vertexStart + 1
v = v + 2
if (vertexEffect) then
local tempVertex = self.tempVertex
while vertexStart < vertexEnd do
tempVertex.x = vertices[v]
tempVertex.y = vertices[v + 1]
tempVertex.u = uvs[v]
tempVertex.v = uvs[v + 1]
tempVertex.light:setFrom(color)
tempVertex.dark:setFrom(darkColor)
vertexEffect:transform(tempVertex)
vertex[1] = tempVertex.x
vertex[2] = tempVertex.y
vertex[3] = tempVertex.u
vertex[4] = tempVertex.v
vertex[5] = tempVertex.light.r * 255
vertex[6] = tempVertex.light.g * 255
vertex[7] = tempVertex.light.b * 255
vertex[8] = tempVertex.light.a * 255
if (self.useTwoColorTint) then
vertex[9] = tempVertex.dark.r * 255
vertex[10] = tempVertex.dark.g * 255
vertex[11] = tempVertex.dark.b * 255
vertex[12] = tempVertex.dark.a * 255
end
mesh:setVertex(vertexStart, vertex)
vertexStart = vertexStart + 1
v = v + 2
end
else
while vertexStart < vertexEnd do
vertex[1] = vertices[v]
vertex[2] = vertices[v + 1]
vertex[3] = uvs[v]
vertex[4] = uvs[v + 1]
mesh:setVertex(vertexStart, vertex)
vertexStart = vertexStart + 1
v = v + 2
end
end
self.verticesLength = self.verticesLength + numVertices
end
@ -255,7 +296,8 @@ function SkeletonRenderer.new (useTwoColorTint)
batcher = PolygonBatcher.new(3 * 500, useTwoColorTint),
premultipliedAlpha = false,
useTwoColorTint = useTwoColorTint,
clipper = spine.SkeletonClipping.new()
clipper = spine.SkeletonClipping.new(),
vertexEffect = nil
}
setmetatable(self, SkeletonRenderer)
@ -270,6 +312,8 @@ function SkeletonRenderer:draw (skeleton)
local batcher = self.batcher
local premultipliedAlpha = self.premultipliedAlpha
if (self.vertexEffect) then self.vertexEffect:beginEffect(skeleton) end
local lastLoveBlendMode = love.graphics.getBlendMode()
love.graphics.setBlendMode("alpha")
local lastBlendMode = spine.BlendMode.normal
@ -342,7 +386,7 @@ function SkeletonRenderer:draw (skeleton)
indices = self.clipper.clippedTriangles
end
batcher:draw(texture, vertices, uvs, numVertices, indices, color, dark)
batcher:draw(texture, vertices, uvs, numVertices, indices, color, dark, self.vertexEffect)
end
self.clipper:clipEnd(slot)
@ -352,6 +396,7 @@ function SkeletonRenderer:draw (skeleton)
batcher:stop()
love.graphics.setBlendMode(lastLoveBlendMode)
self.clipper:clipEnd2()
if (self.vertexEffect) then self.vertexEffect:endEffect(skeleton) end
end
spine.PolygonBatcher = PolygonBatcher

View File

@ -800,21 +800,43 @@ function Animation.DeformTimeline.new (frameCount)
local frameVertices = self.frameVertices
local vertexCount = #(frameVertices[0])
if (#verticesArray ~= vertexCount and not setupPose) then alpha = 1 end -- Don't mix from uninitialized slot vertices.
local vertices = utils.setArraySize(verticesArray, vertexCount)
if time < frames[0] then
local vertexAttachment = slotAttachment;
if pose == MixPose.setup then
verticesArray = {}
slot.attachmentVertices = verticesArray
elseif pose == MixPose.current then
alpha = 1 - alpha
local i = 1
while i <= vertexCount do
vertices[i] = vertices[i] * alpha
i = i + 1
if (vertexAttachment.bones == nil) then
local i = 1
local setupVertices = vertexAttachment.vertices
while i <= vertexCount do
vertices[i] = setupVertices[i]
i = i + 1
end
else
local i = 1
while i <= vertexCount do
vertices[i] = 0
i = i + 1
end
end
elseif pose == MixPose.current then
if (alpha ~= 1) then
if (vertexAttachment.bones == nil) then
local setupVertices = vertexAttachment.vertices
local i = 1
while i <= vertexCount do
vertices[i] = vertices[i] + (setupVertices[i] - vertices[i]) * alpha
i = i + 1
end
else
alpha = 1 - alpha
local i = 1
while i <= vertexCount do
vertices[i] = vertices[i] * alpha
i = i + 1
end
end
end
end
return
end

View File

@ -804,17 +804,15 @@ function AnimationState:disposeNext (entry)
end
function AnimationState:_animationsChanged ()
self.animationsChanged = false
self.animationsChanged = false
self.propertyIDs = {}
local propertyIDs = self.propertyIDs
self.propertyIDs = {}
local propertyIDs = self.propertyIDs
local mixingTo = self.mixingTo
local lastEntry = nil
for i, entry in pairs(self.tracks) do
if entry then
entry:setTimelineData(lastEntry, mixingTo, propertyIDs)
lastEntry = entry
entry:setTimelineData(nil, mixingTo, propertyIDs)
end
end
end

View File

@ -190,16 +190,16 @@ function Bone:updateWorldTransformWith (x, y, rotation, scaleX, scaleY, shearX,
local lb = math_cos(math_rad(90 + shearY)) * scaleY;
local lc = math_sin(math_rad(shearX)) * scaleX;
local ld = math_sin(90 + shearY) * scaleY;
self.a = za * la + zb * lc
self.b = za * lb + zb * ld
self.c = zc * la + zd * lc
self.d = zc * lb + zd * ld
local flip = self.skeleton.flipX ~= self.skeleton.flipY
if transformMode ~= TransformMode.noScaleOrReflection then flip = pa * pd - pb * pc < 0 end
if flip then
self.b = -self.b
self.d = -self.d
zb = -zb
zd = -zd
end
self.a = za * la + zb * lc
self.b = za * lb + zb * ld
self.c = zc * la + zd * lc
self.d = zc * lb + zd * ld
return
end

View File

@ -0,0 +1,48 @@
-------------------------------------------------------------------------------
-- Spine Runtimes Software License v2.5
--
-- Copyright (c) 2013-2016, 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 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 develop new applications using the Spine Runtimes or otherwise
-- create derivative works or improvements of the Spine Runtimes 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, BUSINESS INTERRUPTION, OR LOSS OF
-- USE, DATA, OR PROFITS) 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 interpolation = {}
local math_pow = math.pow
function interpolation.apply (func, start, _end, a)
return start + (_end - start) * func(a)
end
function interpolation.pow2(a)
if (a <= 0.5) then return math_pow(a * 2, 2) / 2 end
return math_pow((a - 1) * 2, 2) / -2 + 1
end
function interpolation.pow2out(a)
return math_pow(a - 1, 2) * -1 + 1
end
return interpolation

View File

@ -118,6 +118,7 @@ function PathConstraint:update ()
while i < n do
local bone = bones[i + 1];
local setupLength = bone.data.length
if setupLength == 0 then setupLength = 0.0000001 end
local x = setupLength * bone.a
local y = setupLength * bone.c
local length = math_sqrt(x * x + y * y)

View File

@ -10,7 +10,7 @@ The Spine Runtimes are developed with the intent to be used with data exported f
## Spine version
spine-lua works with data exported from Spine 3.5.xx.
spine-lua works with data exported from Spine 3.6.xx.
spine-lua supports all Spine features.
@ -18,7 +18,7 @@ spine-lua does not yet support loading the binary format.
## Setup
1. Download the Spine Runtimes source using [git](https://help.github.com/articles/set-up-git) or by downloading it [as a zip](https://github.com/EsotericSoftware/spine-runtimes/archive/master.zip).
1. Download the Spine Runtimes source using [git](https://help.github.com/articles/set-up-git) or by downloading it [as a zip](https://github.com/EsotericSoftware/spine-runtimes/archive/3.6.zip).
1. Copy the contents of the `spine-lua` directory into your project.
## Runtimes Extending spine-lua

View File

@ -63,21 +63,24 @@ function Skin:getAttachment (slotIndex, name)
end
function Skin:attachAll(skeleton, oldSkin)
local slotIndex = 0
for i, slot in ipairs(skeleton.slots) do
local slotAttachment = slot.attachment
if slotAttachment and slotIndex <= #oldSkin.attachments then
local dictionary = oldSkin.attachments[slotIndex]
for key, value in dictionary do
local skinAttachment = value
if slotAttachment == skinAttachment then
local attachment = getAttachment(slotIndex, key)
if attachment then slot.attachment = attachment end
break
if slotAttachment then
local dictionary = oldSkin.attachments[i]
if (dictionary) then
for key, value in pairs(dictionary) do
local skinAttachment = value
if slotAttachment == skinAttachment then
local attachment = self:getAttachment(i, key)
if attachment then
print("Set attachment " .. attachment.name .. " on slot " .. slot.data.name)
slot:setAttachment(attachment)
end
break
end
end
end
end
slotIndex = slotIndex + 1
end
end

View File

@ -103,6 +103,7 @@ function MeshAttachment:setParentMesh (parentMesh)
if parentMesh then
self.bones = parentMesh.bones
self.vertices = parentMesh.vertices
self.worldVerticesLength = parentMesh.worldVerticesLength
self.regionUVs = parentMesh.regionUVs
self.triangles = parentMesh.triangles
self.hullLength = parentMesh.hullLength

View File

@ -30,6 +30,9 @@
local utils = {}
local math_sqrt = math.sqrt
local math_random = math.random
utils.degRad = math.pi / 180
function tablePrint (tt, indent, done)
@ -153,4 +156,15 @@ function utils.mod(a, b)
end
end
function utils.randomTriangular(min, max)
return utils.randomTriangularWith(min, max, (min + max) * 0.5)
end
function utils.randomTriangularWith(min, max, mode)
local u = math.random()
local d = max - min
if (u <= (mode - min) / d) then return min + math_sqrt(u * d * (mode - min)) end
return max - math_sqrt((1 - u) * d * (max - mode))
end
return utils

View File

@ -0,0 +1,64 @@
-------------------------------------------------------------------------------
-- Spine Runtimes Software License v2.5
--
-- Copyright (c) 2013-2016, 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 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 develop new applications using the Spine Runtimes or otherwise
-- create derivative works or improvements of the Spine Runtimes 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, BUSINESS INTERRUPTION, OR LOSS OF
-- USE, DATA, OR PROFITS) 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 utils = require "spine-lua.utils"
local setmetatable = setmetatable
local math_min = math.min
local math_max = math.max
local ipairs = ipairs
local table_insert = table.insert
local table_remove = table.remove
local JitterEffect = {}
JitterEffect.__index = JitterEffect
function JitterEffect.new (jitterX, jitterY)
local self = {
jitterX = jitterX,
jitterY = jitterY
}
setmetatable(self, JitterEffect)
return self
end
function JitterEffect:beginEffect (skeleton)
end
function JitterEffect:transform (vertex)
vertex.x = vertex.x + utils.randomTriangular(-self.jitterX, self.jitterY)
vertex.y = vertex.y + utils.randomTriangular(-self.jitterX, self.jitterY)
end
function JitterEffect:endEffect ()
end
return JitterEffect

View File

@ -0,0 +1,85 @@
-------------------------------------------------------------------------------
-- Spine Runtimes Software License v2.5
--
-- Copyright (c) 2013-2016, 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 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 develop new applications using the Spine Runtimes or otherwise
-- create derivative works or improvements of the Spine Runtimes 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, BUSINESS INTERRUPTION, OR LOSS OF
-- USE, DATA, OR PROFITS) 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 utils = require "spine-lua.utils"
local interpolation = require "spine-lua.Interpolation"
local setmetatable = setmetatable
local math_min = math.min
local math_max = math.max
local ipairs = ipairs
local table_insert = table.insert
local table_remove = table.remove
local utils_deg_rad = utils.degRad
local math_sqrt = math.sqrt
local math_sin = math.sin
local math_cos = math.cos
local SwirlEffect = {}
SwirlEffect.__index = SwirlEffect
function SwirlEffect.new (radius)
local self = {
worldX = 0,
worldY = 0,
centerX = 0,
centerY = 0,
radius = radius,
angle = 0,
interpolation = interpolation.pow2
}
setmetatable(self, SwirlEffect)
return self
end
function SwirlEffect:beginEffect (skeleton)
self.worldX = skeleton.x + self.centerX
self.worldY = skeleton.y + self.centerY
self.angleRad = self.angle * utils_deg_rad
end
function SwirlEffect:transform (vertex)
local x = vertex.x - self.worldX
local y = vertex.y - self.worldY
local dist = math_sqrt(x * x + y * y)
if (dist < self.radius) then
local theta = interpolation.apply(self.interpolation, 0, self.angleRad, (self.radius - dist) / self.radius)
local cos = math_cos(theta)
local sin = math_sin(theta)
vertex.x = cos * x - sin * y + self.worldX
vertex.y = sin * x + cos * y + self.worldY
end
end
function SwirlEffect:endEffect ()
end
return SwirlEffect

View File

@ -10,18 +10,18 @@ The Spine Runtimes are developed with the intent to be used with data exported f
## Spine version
spine-monogame works with data exported from Spine 3.5.xx.
spine-monogame works with data exported from Spine 3.6.xx.
spine-monogame supports all Spine features.
## Setup
1. Download the Spine Runtimes source using [git](https://help.github.com/articles/set-up-git) or by downloading it [as a zip](https://github.com/EsotericSoftware/spine-runtimes/archive/master.zip).
1. Download the Spine Runtimes source using [git](https://help.github.com/articles/set-up-git) or by downloading it [as a zip](https://github.com/EsotericSoftware/spine-runtimes/archive/3.6.zip).
1. Copy the contents of the `spine-csharp/src` and `spine-xna/src` directories into your project.
## Example
1. Download the Spine Runtimes source using [git](https://help.github.com/articles/set-up-git) or by downloading it [as a zip](https://github.com/EsotericSoftware/spine-runtimes/archive/master.zip).
1. Download the Spine Runtimes source using [git](https://help.github.com/articles/set-up-git) or by downloading it [as a zip](https://github.com/EsotericSoftware/spine-runtimes/archive/3.6.zip).
1. Open the `spine-monogame-example.sln` Solution in either Visual Studio 2015 or Xamarin Studio
1. Right click the `spine-monogame-example` project in the solution explorer and select `Properties`
1. Select `Debug` and set the working directory to point to `spine-runtimes/spine-xna/example`

View File

@ -29,15 +29,9 @@
*****************************************************************************/
using System;
using System.IO;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Spine;
namespace Spine {
public class Example : Microsoft.Xna.Framework.Game {
@ -50,7 +44,7 @@ namespace Spine {
private string assetsFolder = "data/";
public Example () {
public Example() {
IsMouseVisible = true;
graphics = new GraphicsDeviceManager(this);
@ -59,56 +53,51 @@ namespace Spine {
graphics.PreferredBackBufferHeight = 600;
}
protected override void Initialize () {
// TODO: Add your initialization logic here
base.Initialize();
}
protected override void LoadContent() {
// Two color tint effect, comment line 76 to disable
// Two color tint effect, comment line 80 to disable
var spineEffect = Content.Load<Effect>("Content\\SpineEffect");
spineEffect.Parameters["World"].SetValue(Matrix.Identity);
spineEffect.Parameters["View"].SetValue(Matrix.CreateLookAt(new Vector3(0.0f, 0.0f, 1.0f), Vector3.Zero, Vector3.Up));
skeletonRenderer = new SkeletonRenderer(GraphicsDevice);
skeletonRenderer.PremultipliedAlpha = true;
skeletonRenderer.PremultipliedAlpha = false;
skeletonRenderer.Effect = spineEffect;
// String name = "spineboy";
// String name = "goblins-mesh";
// String name = "raptor";
// String name = "tank";
// String name = "coin";
String name = "TwoColorTest";
bool binaryData = true;
// String name = "spineboy-ess";
// String name = "goblins-pro";
// String name = "raptor-pro";
// String name = "tank-pro";
String name = "coin-pro";
String atlasName = name.Replace("-pro", "").Replace("-ess", "");
bool binaryData = false;
Atlas atlas = new Atlas(assetsFolder + name + ".atlas", new XnaTextureLoader(GraphicsDevice));
Atlas atlas = new Atlas(assetsFolder + atlasName + ".atlas", new XnaTextureLoader(GraphicsDevice));
float scale = 1;
if (name == "spineboy") scale = 0.6f;
if (name == "raptor") scale = 0.5f;
if (name == "tank") scale = 0.3f;
if (name == "TwoColorTest") scale = 0.5f;
if (name == "spineboy-ess") scale = 0.6f;
if (name == "raptor-pro") scale = 0.5f;
if (name == "tank-pro") scale = 0.3f;
if (name == "coin-pro") scale = 1;
SkeletonData skeletonData;
if (binaryData) {
SkeletonBinary binary = new SkeletonBinary(atlas);
binary.Scale = scale;
skeletonData = binary.ReadSkeletonData(assetsFolder + name + ".skel");
} else {
}
else {
SkeletonJson json = new SkeletonJson(atlas);
json.Scale = scale;
skeletonData = json.ReadSkeletonData(assetsFolder + name + ".json");
}
skeleton = new Skeleton(skeletonData);
if (name == "goblins-mesh") skeleton.SetSkin("goblin");
if (name == "goblins-pro") skeleton.SetSkin("goblin");
// Define mixing between animations.
AnimationStateData stateData = new AnimationStateData(skeleton.Data);
state = new AnimationState(stateData);
if (name == "spineboy") {
if (name == "spineboy-ess") {
stateData.SetMix("run", "jump", 0.2f);
stateData.SetMix("jump", "run", 0.4f);
@ -123,41 +112,36 @@ namespace Spine {
entry.End += End; // Event handling for queued animations.
state.AddAnimation(0, "run", true, 0);
}
else if (name == "raptor") {
else if (name == "raptor-pro") {
state.SetAnimation(0, "walk", true);
state.AddAnimation(1, "gungrab", false, 2);
}
else if (name == "coin") {
else if (name == "coin-pro") {
state.SetAnimation(0, "rotate", true);
}
else if (name == "tank") {
else if (name == "tank-pro") {
state.SetAnimation(0, "drive", true);
}
else if (name == "TwoColorTest") {
state.SetAnimation(0, "animation", true);
} else {
else {
state.SetAnimation(0, "walk", true);
}
skeleton.X = 400 + (name == "tank" ? 300: 0);
skeleton.Y = 580 + (name == "TwoColorTest" ? -300 : 0);
skeleton.X = 400 + (name == "tank-pro" ? 300 : 0);
skeleton.Y = GraphicsDevice.Viewport.Height;
skeleton.UpdateWorldTransform();
headSlot = skeleton.FindSlot("head");
}
protected override void UnloadContent () {
}
protected override void Update (GameTime gameTime) {
protected override void Update(GameTime gameTime) {
base.Update(gameTime);
}
protected override void Draw (GameTime gameTime) {
protected override void Draw(GameTime gameTime) {
GraphicsDevice.Clear(Color.Black);
state.Update(gameTime.ElapsedGameTime.Milliseconds / 1000f);
state.Apply(skeleton);
state.Apply(skeleton);
skeleton.UpdateWorldTransform();
if (skeletonRenderer.Effect is BasicEffect) {
((BasicEffect)skeletonRenderer.Effect).Projection = Matrix.CreateOrthographicOffCenter(0, GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height, 0, 1, 0);
@ -186,19 +170,19 @@ namespace Spine {
base.Draw(gameTime);
}
public void Start (TrackEntry entry) {
public void Start(TrackEntry entry) {
Console.WriteLine(entry + ": start");
}
public void End (TrackEntry entry) {
public void End(TrackEntry entry) {
Console.WriteLine(entry + ": end");
}
public void Complete (TrackEntry entry) {
public void Complete(TrackEntry entry) {
Console.WriteLine(entry + ": complete ");
}
public void Event (TrackEntry entry, Event e) {
public void Event(TrackEntry entry, Event e) {
Console.WriteLine(entry + ": event " + e);
}
}

View File

@ -1,3 +1,4 @@
cmake_minimum_required(VERSION 2.8.9)
#
# First download and extract SFML 2.3.2 for the respective OS we are on
#

View File

@ -10,7 +10,7 @@ The Spine Runtimes are developed with the intent to be used with data exported f
## Spine version
spine-sfml works with data exported from Spine 3.5.xx.
spine-sfml works with data exported from Spine 3.6.xx.
spine-sfml supports all Spine features.
@ -18,7 +18,7 @@ spine-sfml does not yet support loading the binary format.
## Usage
1. Create a new SFML project. See the [SFML documentation](http://www.sfml-dev.org/tutorials/2.1/) or have a look at the example in this repository.
2. Download the Spine Runtimes source using git (`git clone https://github.com/esotericsoftware/spine-runtimes`) or download it [as a zip](https://github.com/EsotericSoftware/spine-runtimes/archive/master.zip)
2. Download the Spine Runtimes source using git (`git clone https://github.com/esotericsoftware/spine-runtimes`) or download it [as a zip](https://github.com/EsotericSoftware/spine-runtimes/archive/3.6.zip)
3. Add the sources from `spine-c/spine-c/src/spine` and `spine-sfml/src/spine` to your project
4. Add the folder `spine-c/spine-c/include` to your header search path. Note that includes are specified as `#inclue <spine/file.h>`, so the `spine` directory cannot be omitted when copying the source files.
@ -30,7 +30,7 @@ The Spine SFML example works on Windows, Linux and Mac OS X.
### Windows
1. Install [Visual Studio 2015 Community](https://www.visualstudio.com/en-us/downloads/download-visual-studio-vs.aspx). Make sure you install support for C++ as well as th Windows SDK for XP/7/8.
2. Install CMake via the [Windows installer package](https://cmake.org/download/).
3. Download the Spine Runtimes repository using git (`git clone https://github.com/esotericsoftware/spine-runtimes`) or download it [as a zip](https://github.com/EsotericSoftware/spine-runtimes/archive/master.zip)
3. Download the Spine Runtimes repository using git (`git clone https://github.com/esotericsoftware/spine-runtimes`) or download it [as a zip](https://github.com/EsotericSoftware/spine-runtimes/archive/3.6.zip)
4. Run CMake GUI from the start menu
5. Click `Browse Source` and select the directory `spine-runtimes`
6. Click `Browse Build` and select the `spine-runtimes/spine-sfml/build` directory. You can create the `build` folder directly in the file dialog via `New Folder`.
@ -46,7 +46,7 @@ The entire example code is contained in [main.cpp](https://github.com/EsotericSo
### Linux
1. Install the SFML dependencies, e.g. on Ubuntu/Debian via `sudo apt-get install -y libpthread-stubs0-dev libgl1-mesa-dev libx11-dev libxrandr-dev libfreetype6-dev libglew1.5-dev libjpeg8-dev libsndfile1-dev libopenal-dev libudev-dev libxcb-image0-dev libjpeg-dev libflac-dev`
2. Install CMake, e.g. on Ubuntu/Debian via `sudo apt-get install -y cmake`
3. Download the Spine Runtimes repository using git (`git clone https://github.com/esotericsoftware/spine-runtimes`) or download it [as a zip](https://github.com/EsotericSoftware/spine-runtimes/archive/master.zip)
3. Download the Spine Runtimes repository using git (`git clone https://github.com/esotericsoftware/spine-runtimes`) or download it [as a zip](https://github.com/EsotericSoftware/spine-runtimes/archive/3.6.zip)
4. Open a terminal, and `cd` into the `spine-runtimes/spine-sfml` folder
5. Type `mkdir build && cd build && cmake ../..` to generate Make files
6. Type `make` to compile the example
@ -56,7 +56,7 @@ The entire example code is contained in [main.cpp](https://github.com/EsotericSo
1. Install [Xcode](https://developer.apple.com/xcode/)
2. Install [Homebrew](http://brew.sh/)
3. Open a terminal and install CMake via `brew install cmake`
3. Download the Spine Runtimes repository using git (`git clone https://github.com/esotericsoftware/spine-runtimes`) or download it [as a zip](https://github.com/EsotericSoftware/spine-runtimes/archive/master.zip)
3. Download the Spine Runtimes repository using git (`git clone https://github.com/esotericsoftware/spine-runtimes`) or download it [as a zip](https://github.com/EsotericSoftware/spine-runtimes/archive/3.6.zip)
4. Open a terminal, and `cd` into the `spine-runtimes/spine-sfml` folder
5. Type `mkdir build && cd build && cmake -G Xcode ../..` to generate an Xcode project called `spine.xcodeproj`
6. Open the Xcode project in `spine-runtimes/spine-sfml/build/`

View File

@ -204,6 +204,10 @@ void raptor (SkeletonData* skeletonData, Atlas* atlas) {
SkeletonDrawable* drawable = new SkeletonDrawable(skeletonData);
drawable->timeScale = 1;
spSwirlVertexEffect* effect = spSwirlVertexEffect_create(400);
effect->centerY = -200;
drawable->vertexEffect = &effect->super;
Skeleton* skeleton = drawable->skeleton;
skeleton->x = 320;
skeleton->y = 590;
@ -216,6 +220,7 @@ void raptor (SkeletonData* skeletonData, Atlas* atlas) {
window.setFramerateLimit(60);
sf::Event event;
sf::Clock deltaClock;
float swirlTime = 0;
while (window.isOpen()) {
while (window.pollEvent(event))
if (event.type == sf::Event::Closed) window.close();
@ -223,12 +228,18 @@ void raptor (SkeletonData* skeletonData, Atlas* atlas) {
float delta = deltaClock.getElapsedTime().asSeconds();
deltaClock.restart();
swirlTime += delta;
float percent = fmod(swirlTime, 2);
if (percent > 1) percent = 1 - (percent - 1);
effect->angle = _spMath_interpolate(_spMath_pow2_apply, -60, 60, percent);
drawable->update(delta);
window.clear();
window.draw(*drawable);
window.display();
}
spSwirlVertexEffect_dispose(effect);
}
void tank (SkeletonData* skeletonData, Atlas* atlas) {
@ -338,6 +349,7 @@ void coin (SkeletonData* skeletonData, Atlas* atlas) {
window.setFramerateLimit(60);
sf::Event event;
sf::Clock deltaClock;
float swirlTime = 0;
while (window.isOpen()) {
while (window.pollEvent(event))
if (event.type == sf::Event::Closed) window.close();

View File

@ -36,6 +36,8 @@
using namespace sf;
_SP_ARRAY_IMPLEMENT_TYPE(spColorArray, spColor)
void _AtlasPage_createTexture (AtlasPage* self, const char* path){
Texture* texture = new Texture();
if (!texture->loadFromFile(path)) return;
@ -54,7 +56,7 @@ void _AtlasPage_disposeTexture (AtlasPage* self){
}
char* _Util_readFile (const char* path, int* length){
return _readFile(path, length);
return _spReadFile(path, length);
}
/**/
@ -64,10 +66,13 @@ namespace spine {
SkeletonDrawable::SkeletonDrawable (SkeletonData* skeletonData, AnimationStateData* stateData) :
timeScale(1),
vertexArray(new VertexArray(Triangles, skeletonData->bonesCount * 4)),
vertexEffect(0),
worldVertices(0), clipper(0) {
Bone_setYDown(true);
worldVertices = MALLOC(float, SPINE_MESH_VERTEX_COUNT_MAX);
skeleton = Skeleton_create(skeletonData);
tempUvs = spFloatArray_create(16);
tempColors = spColorArray_create(16);
ownsAnimationStateData = stateData == 0;
if (ownsAnimationStateData) stateData = AnimationStateData_create(skeletonData);
@ -84,6 +89,8 @@ SkeletonDrawable::~SkeletonDrawable () {
AnimationState_dispose(state);
Skeleton_dispose(skeleton);
spSkeletonClipping_dispose(clipper);
spFloatArray_dispose(tempUvs);
spColorArray_dispose(tempColors);
}
void SkeletonDrawable::update (float deltaTime) {
@ -98,6 +105,8 @@ void SkeletonDrawable::draw (RenderTarget& target, RenderStates states) const {
states.texture = 0;
unsigned short quadIndices[6] = { 0, 1, 2, 2, 3, 0 };
if (vertexEffect != 0) vertexEffect->begin(vertexEffect, skeleton);
sf::Vertex vertex;
Texture* texture = 0;
for (int i = 0; i < skeleton->slotsCount; ++i) {
@ -147,6 +156,12 @@ void SkeletonDrawable::draw (RenderTarget& target, RenderStates states) const {
vertex.color.b = b;
vertex.color.a = a;
spColor light;
light.r = r / 255.0f;
light.g = g / 255.0f;
light.b = b / 255.0f;
light.a = a / 255.0f;
sf::BlendMode blend;
switch (slot->data->blendMode) {
case BLEND_MODE_ADDITIVE:
@ -179,19 +194,57 @@ void SkeletonDrawable::draw (RenderTarget& target, RenderStates states) const {
}
Vector2u size = texture->getSize();
for (int i = 0; i < indicesCount; ++i) {
int index = indices[i] << 1;
vertex.position.x = vertices[index];
vertex.position.y = vertices[index + 1];
vertex.texCoords.x = uvs[index] * size.x;
vertex.texCoords.y = uvs[index + 1] * size.y;
vertexArray->append(vertex);
if (vertexEffect != 0) {
spFloatArray_clear(tempUvs);
spColorArray_clear(tempColors);
for (int i = 0; i < verticesCount; i++) {
spColor vertexColor = light;
spColor dark;
dark.r = dark.g = dark.b = dark.a = 0;
int index = i << 1;
float x = vertices[index];
float y = vertices[index + 1];
float u = uvs[index];
float v = uvs[index + 1];
vertexEffect->transform(vertexEffect, &x, &y, &u, &v, &vertexColor, &dark);
vertices[index] = x;
vertices[index + 1] = y;
spFloatArray_add(tempUvs, u);
spFloatArray_add(tempUvs, v);
spColorArray_add(tempColors, vertexColor);
}
for (int i = 0; i < indicesCount; ++i) {
int index = indices[i] << 1;
vertex.position.x = vertices[index];
vertex.position.y = vertices[index + 1];
vertex.texCoords.x = uvs[index] * size.x;
vertex.texCoords.y = uvs[index + 1] * size.y;
spColor vertexColor = tempColors->items[index >> 1];
vertex.color.r = static_cast<Uint8>(vertexColor.r * 255);
vertex.color.g = static_cast<Uint8>(vertexColor.g * 255);
vertex.color.b = static_cast<Uint8>(vertexColor.b * 255);
vertex.color.a = static_cast<Uint8>(vertexColor.a * 255);
vertexArray->append(vertex);
}
} else {
for (int i = 0; i < indicesCount; ++i) {
int index = indices[i] << 1;
vertex.position.x = vertices[index];
vertex.position.y = vertices[index + 1];
vertex.texCoords.x = uvs[index] * size.x;
vertex.texCoords.y = uvs[index + 1] * size.y;
vertexArray->append(vertex);
}
}
spSkeletonClipping_clipEnd(clipper, slot);
}
target.draw(*vertexArray, states);
spSkeletonClipping_clipEnd2(clipper);
if (vertexEffect != 0) vertexEffect->end(vertexEffect);
}
} /* namespace spine */

View File

@ -40,6 +40,8 @@
#include <SFML/Graphics/RenderTarget.hpp>
#include <SFML/Graphics/RenderStates.hpp>
_SP_ARRAY_DECLARE_TYPE(spColorArray, spColor)
namespace spine {
class SkeletonDrawable: public sf::Drawable {
@ -48,6 +50,7 @@ public:
AnimationState* state;
float timeScale;
sf::VertexArray* vertexArray;
spVertexEffect* vertexEffect;
SkeletonDrawable (SkeletonData* skeleton, AnimationStateData* stateData = 0);
~SkeletonDrawable ();
@ -58,6 +61,8 @@ public:
private:
bool ownsAnimationStateData;
float* worldVertices;
spFloatArray* tempUvs;
spColorArray* tempColors;
spSkeletonClipping* clipper;
};

View File

@ -10,7 +10,7 @@ The Spine Runtimes are developed with the intent to be used with data exported f
## Spine version
spine-starling works with data exported from Spine 3.5.xx.
spine-starling works with data exported from Spine 3.6.xx.
spine-starling supports all Spine features.
@ -18,7 +18,7 @@ spine-starling does not yet support loading the binary format.
# Usage
1. Create a new Starling 2.0 project as per the [documentation].
2. Download the Spine Runtimes source using [git](https://help.github.com/articles/set-up-git) or by downloading it [as a zip](https://github.com/EsotericSoftware/spine-runtimes/archive/master.zip).
2. Download the Spine Runtimes source using [git](https://help.github.com/articles/set-up-git) or by downloading it [as a zip](https://github.com/EsotericSoftware/spine-runtimes/archive/3.6.zip).
3. Copy the sources in `spine-as3/spine-as3/src/` and `spine-starling/spine-starling/src/` into your project's source directory
## Example

View File

@ -66,7 +66,7 @@ package spine.examples {
private var skinChangeCount: Number = 0;
public function GoblinsExample() {
var useStarlingAtlas : Boolean = false;
var useStarlingAtlas : Boolean = true;
var attachmentLoader : AttachmentLoader;
if (useStarlingAtlas) {

View File

@ -29,6 +29,10 @@
*****************************************************************************/
package spine.examples {
import spine.interpolation.Pow;
import starling.animation.IAnimatable;
import spine.vertexeffects.SwirlEffect;
import spine.vertexeffects.JitterEffect;
import starling.display.DisplayObjectContainer;
import spine.atlas.Atlas;
import spine.*;
@ -43,7 +47,7 @@ package spine.examples {
import starling.events.TouchEvent;
import starling.events.TouchPhase;
public class RaptorExample extends Sprite {
public class RaptorExample extends Sprite implements IAnimatable {
[Embed(source = "/raptor-pro.json", mimeType = "application/octet-stream")]
static public const RaptorJson : Class;
@ -55,6 +59,10 @@ package spine.examples {
private var skeleton : SkeletonAnimation;
private var gunGrabbed : Boolean;
private var gunGrabCount : Number = 0;
private var swirl : SwirlEffect;
private var swirlTime : Number = 0;
private var pow2 : Interpolation = new Pow(2);
public function RaptorExample() {
var attachmentLoader : AttachmentLoader;
@ -74,9 +82,15 @@ package spine.examples {
skeleton.state.apply(skeleton.skeleton);
skeleton.skeleton.updateWorldTransform();
this.setRequiresRedraw();
// skeleton.vertexEffect = new JitterEffect(10, 10);
swirl = new SwirlEffect(400);
swirl.centerY = -200;
skeleton.vertexEffect = swirl;
addChild(skeleton);
Starling.juggler.add(skeleton);
Starling.juggler.add(this);
addEventListener(TouchEvent.TOUCH, onClick);
}
@ -98,5 +112,12 @@ package spine.examples {
}
}
}
public function advanceTime(time : Number) : void {
swirlTime += time;
var percent : Number = swirlTime % 2;
if (percent > 1) percent = 1 - (percent - 1);
swirl.angle = pow2.apply(-60, 60, percent);
}
}
}

View File

@ -39,6 +39,7 @@ package spine.starling {
import spine.attachments.Attachment;
import spine.attachments.MeshAttachment;
import spine.attachments.RegionAttachment;
import spine.VertexEffect;
import starling.display.BlendMode;
import starling.display.DisplayObject;
@ -63,6 +64,11 @@ package spine.starling {
private var _smoothing : String = "bilinear";
private static var clipper: SkeletonClipping = new SkeletonClipping();
private static var QUAD_INDICES : Vector.<uint> = new <uint>[0, 1, 2, 2, 3, 0];
public var vertexEffect : VertexEffect;
private var tempLight : spine.Color = new spine.Color(0, 0, 0);
private var tempDark : spine.Color = new spine.Color(0, 0, 0);
private var tempVertex : spine.Vertex = new spine.Vertex();
public function SkeletonSprite(skeletonData : SkeletonData) {
Bone.yDown = true;
@ -86,6 +92,8 @@ package spine.starling {
var verticesLength : int, verticesCount : int, indicesLength : int;
var indexData : IndexData, indices : Vector.<uint>, vertexData : VertexData;
var uvs : Vector.<Number>;
if (vertexEffect != null) vertexEffect.begin(skeleton);
for (var i : int = 0, n : int = drawOrder.length; i < n; ++i) {
var worldVertices : Vector.<Number> = _tempVertices;
@ -171,13 +179,37 @@ package spine.starling {
}
vertexData = mesh.getVertexData();
vertexData.numVertices = verticesCount;
vertexData.colorize("color", rgb, a);
vertexData.colorize("color2", dark);
for (ii = 0, iii = 0; ii < verticesCount; ii++, iii += 2) {
mesh.setVertexPosition(ii, worldVertices[iii], worldVertices[iii + 1]);
mesh.setTexCoords(ii, uvs[iii], uvs[iii + 1]);
}
vertexData.numVertices = verticesCount;
if (vertexEffect != null) {
tempLight.r = ((rgb >> 16) & 0xff) / 255.0;
tempLight.g = ((rgb >> 8) & 0xff) / 255.0;
tempLight.b = (rgb & 0xff) / 255.0;
tempLight.a = a;
tempDark.r = ((dark >> 16) & 0xff) / 255.0;
tempDark.g = ((dark >> 8) & 0xff) / 255.0;
tempDark.b = (dark & 0xff) / 255.0;
tempDark.a = 0;
for (ii = 0, iii = 0; ii < verticesCount; ii++, iii += 2) {
tempVertex.x = worldVertices[iii];
tempVertex.y = worldVertices[iii + 1];
tempVertex.u = uvs[iii];
tempVertex.v = uvs[iii + 1];
tempVertex.light.setFromColor(tempLight);
tempVertex.dark.setFromColor(tempDark);
vertexEffect.transform(tempVertex);
vertexData.colorize("color", Color.rgb(tempVertex.light.r * 255, tempVertex.light.g * 255, tempVertex.light.b * 255), tempVertex.light.a, ii, 1);
vertexData.colorize("color2", Color.rgb(tempVertex.dark.r * 255, tempVertex.dark.g * 255, tempVertex.dark.b * 255), a, ii, 1);
mesh.setVertexPosition(ii, tempVertex.x, tempVertex.y);
mesh.setTexCoords(ii, tempVertex.u, tempVertex.v);
}
} else {
vertexData.colorize("color", rgb, a);
vertexData.colorize("color2", dark);
for (ii = 0, iii = 0; ii < verticesCount; ii++, iii += 2) {
mesh.setVertexPosition(ii, worldVertices[iii], worldVertices[iii + 1]);
mesh.setTexCoords(ii, uvs[iii], uvs[iii + 1]);
}
}
painter.state.blendMode = blendModes[slot.data.blendMode.ordinal];
painter.batchMesh(mesh);
@ -185,6 +217,8 @@ package spine.starling {
}
painter.state.blendMode = originalBlendMode;
clipper.clipEnd();
if (vertexEffect != null) vertexEffect.end();
}
override public function hitTest(localPoint : Point) : DisplayObject {

View File

@ -27,21 +27,18 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
package spine.starling {
import spine.attachments.ClippingAttachment;
import spine.attachments.PointAttachment;
import spine.attachments.PathAttachment;
import starling.display.Image;
import spine.Bone;
import spine.Skin;
import spine.attachments.AttachmentLoader;
import spine.attachments.BoundingBoxAttachment;
import spine.attachments.ClippingAttachment;
import spine.attachments.MeshAttachment;
import spine.attachments.PathAttachment;
import spine.attachments.PointAttachment;
import spine.attachments.RegionAttachment;
import starling.display.Image;
import starling.textures.SubTexture;
import starling.textures.Texture;
import starling.textures.TextureAtlas;
@ -53,16 +50,19 @@ package spine.starling {
public function StarlingAtlasAttachmentLoader(atlas : TextureAtlas) {
this.atlas = atlas;
Bone.yDown = true;
}
protected function getTexture(path : String) : Texture {
return atlas.getTexture(path);
}
public function newRegionAttachment(skin : Skin, name : String, path : String) : RegionAttachment {
var texture : Texture = atlas.getTexture(path);
var texture : SubTexture = getTexture(path) as SubTexture;
if (texture == null)
throw new Error("Region not found in Starling atlas: " + path + " (region attachment: " + name + ")");
var attachment : RegionAttachment = new RegionAttachment(name);
var rotated : Boolean = atlas.getRotation(path);
var rotated : Boolean = texture.rotated;
attachment.rendererObject = new Image(Texture.fromTexture(texture)); // Discard frame.
var frame : Rectangle = texture.frame;
attachment.regionOffsetX = frame ? -frame.x : 0;
@ -78,76 +78,44 @@ package spine.starling {
tmp = attachment.regionWidth;
attachment.regionWidth = attachment.regionHeight;
attachment.regionHeight = tmp;
attachment["regionU2"] = 0;
attachment["regionV2"] = 1;
attachment["regionU"] = 1;
attachment["regionV"] = 0;
}else{
attachment["regionU"] = 0;
attachment["regionV"] = 0;
attachment["regionU2"] = 1;
attachment["regionV2"] = 1;
}
var subTexture : SubTexture = texture as SubTexture;
if (subTexture) {
var root : Texture = subTexture.root;
var rectRegion : Rectangle = atlas.getRegion(path);
if (!rotated) {
attachment["regionU"] = rectRegion.x / root.width;
attachment["regionV"] = rectRegion.y / root.height;
attachment["regionU2"] = (rectRegion.x + subTexture.width) / root.width;
attachment["regionV2"] = (rectRegion.y + subTexture.height) / root.height;
} else {
attachment["regionU2"] = rectRegion.x / root.width;
attachment["regionV2"] = rectRegion.y / root.height;
attachment["regionU"] = (rectRegion.x + subTexture.width) / root.width;
attachment["regionV"] = (rectRegion.y + subTexture.height) / root.height;
}
attachment.setUVs(attachment["regionU"], attachment["regionV"], attachment["regionU2"], attachment["regionV2"], atlas.getRotation(path));
} else {
if (!rotated) {
attachment["regionU"] = 0;
attachment["regionV"] = 1;
attachment["regionU2"] = 1;
attachment["regionV2"] = 0;
} else {
attachment["regionU2"] = 0;
attachment["regionV2"] = 1;
attachment["regionU"] = 1;
attachment["regionV"] = 0;
}
}
attachment.setUVs(attachment["regionU"], attachment["regionV"], attachment["regionU2"], attachment["regionV2"], rotated);
return attachment;
}
public function newMeshAttachment(skin : Skin, name : String, path : String) : MeshAttachment {
var texture : Texture = atlas.getTexture(path);
var texture : SubTexture = getTexture(path) as SubTexture;
if (texture == null)
throw new Error("Region not found in Starling atlas: " + path + " (mesh attachment: " + name + ")");
var rotated : Boolean = atlas.getRotation(path);
var rotated : Boolean = texture.rotated;
var attachment : MeshAttachment = new MeshAttachment(name);
attachment.regionRotate = rotated;
attachment.rendererObject = new Image(Texture.fromTexture(texture)); // Discard frame.
var subTexture : SubTexture = texture as SubTexture;
if (subTexture) {
var root : Texture = subTexture.root;
var rectRegion : Rectangle = atlas.getRegion(path);
if (!rotated) {
attachment.regionU = rectRegion.x / root.width;
attachment.regionV = rectRegion.y / root.height;
attachment.regionU2 = (rectRegion.x + subTexture.width) / root.width;
attachment.regionV2 = (rectRegion.y + subTexture.height) / root.height;
} else {
attachment.regionU2 = rectRegion.x / root.width;
attachment.regionV2 = rectRegion.y / root.height;
attachment.regionU = (rectRegion.x + subTexture.height) / root.width;
attachment.regionV = (rectRegion.y + subTexture.width) / root.height;
}
attachment.rendererObject = new Image(root);
var root : Texture = texture.root;
var rectRegion : Rectangle = atlas.getRegion(path);
if (!rotated) {
attachment.regionU = rectRegion.x / root.width;
attachment.regionV = rectRegion.y / root.height;
attachment.regionU2 = (rectRegion.x + texture.width) / root.width;
attachment.regionV2 = (rectRegion.y + texture.height) / root.height;
} else {
if (!rotated) {
attachment.regionU = 0;
attachment.regionV = 1;
attachment.regionU2 = 1;
attachment.regionV2 = 0;
} else {
attachment.regionU2 = 0;
attachment.regionV2 = 1;
attachment.regionU = 1;
attachment.regionV = 0;
}
attachment.regionU2 = rectRegion.x / root.width;
attachment.regionV2 = rectRegion.y / root.height;
attachment.regionU = (rectRegion.x + texture.height) / root.width;
attachment.regionV = (rectRegion.y + texture.width) / root.height;
}
attachment.rendererObject = new Image(root);
var frame : Rectangle = texture.frame;
attachment.regionOffsetX = frame ? -frame.x : 0;
attachment.regionOffsetY = frame ? -frame.y : 0;
@ -177,7 +145,7 @@ package spine.starling {
public function newPointAttachment(skin : Skin, name : String) : PointAttachment {
return new PointAttachment(name);
}
public function newClippingAttachment(skin : Skin, name : String) : ClippingAttachment {
return new ClippingAttachment(name);
}

View File

@ -18,7 +18,7 @@ The Spine Runtimes are developed with the intent to be used with data exported f
## Spine version
spine-ts works with data exported from Spine 3.6.xx
spine-ts works with data exported from Spine 3.6.xx.
spine-ts WebGL & Widget backends supports all Spine features.
@ -29,7 +29,7 @@ spine-ts THREE.JS does not support color tinting, blend modes and clipping. The
spine-ts does not yet support loading the binary format.
## Usage
1. Download the Spine Runtimes source using [git](https://help.github.com/articles/set-up-git) or by downloading it [as a zip](https://github.com/EsotericSoftware/spine-runtimes/archive/master.zip).
1. Download the Spine Runtimes source using [git](https://help.github.com/articles/set-up-git) or by downloading it [as a zip](https://github.com/EsotericSoftware/spine-runtimes/archive/3.6.zip).
2. To use only the core library without rendering support, include the `build/spine-core.js` file in your project.
3. To use the WebGL backend, include the `spine-webgl.js` file in your project.
3. To use the Canvas backend, include the `spine-canvas.js` file in your project.

View File

@ -1,97 +1,3 @@
declare module spine {
class AssetManager implements Disposable {
private pathPrefix;
private textureLoader;
private assets;
private errors;
private toLoad;
private loaded;
constructor(textureLoader: (image: HTMLImageElement) => any, pathPrefix?: string);
loadText(path: string, success?: (path: string, text: string) => void, error?: (path: string, error: string) => void): void;
loadTexture(path: string, success?: (path: string, image: HTMLImageElement) => void, error?: (path: string, error: string) => void): void;
loadTextureData(path: string, data: string, success?: (path: string, image: HTMLImageElement) => void, error?: (path: string, error: string) => void): void;
get(path: string): any;
remove(path: string): void;
removeAll(): void;
isLoadingComplete(): boolean;
getToLoad(): number;
getLoaded(): number;
dispose(): void;
hasErrors(): boolean;
getErrors(): Map<string>;
}
}
declare module spine.canvas {
class AssetManager extends spine.AssetManager {
constructor(pathPrefix?: string);
}
}
declare module spine {
abstract class Texture {
protected _image: HTMLImageElement;
constructor(image: HTMLImageElement);
getImage(): HTMLImageElement;
abstract setFilters(minFilter: TextureFilter, magFilter: TextureFilter): void;
abstract setWraps(uWrap: TextureWrap, vWrap: TextureWrap): void;
abstract dispose(): void;
static filterFromString(text: string): TextureFilter;
static wrapFromString(text: string): TextureWrap;
}
enum TextureFilter {
Nearest = 9728,
Linear = 9729,
MipMap = 9987,
MipMapNearestNearest = 9984,
MipMapLinearNearest = 9985,
MipMapNearestLinear = 9986,
MipMapLinearLinear = 9987,
}
enum TextureWrap {
MirroredRepeat = 33648,
ClampToEdge = 33071,
Repeat = 10497,
}
class TextureRegion {
renderObject: any;
u: number;
v: number;
u2: number;
v2: number;
width: number;
height: number;
rotate: boolean;
offsetX: number;
offsetY: number;
originalWidth: number;
originalHeight: number;
}
}
declare module spine.canvas {
class CanvasTexture extends Texture {
constructor(image: HTMLImageElement);
setFilters(minFilter: TextureFilter, magFilter: TextureFilter): void;
setWraps(uWrap: TextureWrap, vWrap: TextureWrap): void;
dispose(): void;
}
}
declare module spine.canvas {
class SkeletonRenderer {
static QUAD_TRIANGLES: number[];
static VERTEX_SIZE: number;
private ctx;
triangleRendering: boolean;
debugRendering: boolean;
private vertices;
private tempColor;
constructor(context: CanvasRenderingContext2D);
draw(skeleton: Skeleton): void;
private drawImages(skeleton);
private drawTriangles(skeleton);
private drawTriangle(img, x0, y0, u0, v0, x1, y1, u1, v1, x2, y2, u2, v2);
private computeRegionVertices(slot, region, pma);
private computeMeshVertices(slot, mesh, pma);
}
}
declare module spine {
class Animation {
name: string;
@ -458,6 +364,29 @@ declare module spine {
getMix(from: Animation, to: Animation): number;
}
}
declare module spine {
class AssetManager implements Disposable {
private pathPrefix;
private textureLoader;
private assets;
private errors;
private toLoad;
private loaded;
constructor(textureLoader: (image: HTMLImageElement) => any, pathPrefix?: string);
loadText(path: string, success?: (path: string, text: string) => void, error?: (path: string, error: string) => void): void;
loadTexture(path: string, success?: (path: string, image: HTMLImageElement) => void, error?: (path: string, error: string) => void): void;
loadTextureData(path: string, data: string, success?: (path: string, image: HTMLImageElement) => void, error?: (path: string, error: string) => void): void;
get(path: string): any;
remove(path: string): void;
removeAll(): void;
isLoadingComplete(): boolean;
getToLoad(): number;
getLoaded(): number;
dispose(): void;
hasErrors(): boolean;
getErrors(): Map<string>;
}
}
declare module spine {
class AtlasAttachmentLoader implements AttachmentLoader {
atlas: TextureAtlas;
@ -470,156 +399,6 @@ declare module spine {
newClippingAttachment(skin: Skin, name: string): ClippingAttachment;
}
}
declare module spine {
abstract class Attachment {
name: string;
constructor(name: string);
}
abstract class VertexAttachment extends Attachment {
private static nextID;
id: number;
bones: Array<number>;
vertices: ArrayLike<number>;
worldVerticesLength: number;
constructor(name: string);
computeWorldVertices(slot: Slot, start: number, count: number, worldVertices: ArrayLike<number>, offset: number, stride: number): void;
applyDeform(sourceAttachment: VertexAttachment): boolean;
}
}
declare module spine {
interface AttachmentLoader {
newRegionAttachment(skin: Skin, name: string, path: string): RegionAttachment;
newMeshAttachment(skin: Skin, name: string, path: string): MeshAttachment;
newBoundingBoxAttachment(skin: Skin, name: string): BoundingBoxAttachment;
newPathAttachment(skin: Skin, name: string): PathAttachment;
newPointAttachment(skin: Skin, name: string): PointAttachment;
newClippingAttachment(skin: Skin, name: string): ClippingAttachment;
}
}
declare module spine {
enum AttachmentType {
Region = 0,
BoundingBox = 1,
Mesh = 2,
LinkedMesh = 3,
Path = 4,
Point = 5,
}
}
declare module spine {
class BoundingBoxAttachment extends VertexAttachment {
color: Color;
constructor(name: string);
}
}
declare module spine {
class ClippingAttachment extends VertexAttachment {
endSlot: SlotData;
color: Color;
constructor(name: string);
}
}
declare module spine {
class MeshAttachment extends VertexAttachment {
region: TextureRegion;
path: string;
regionUVs: ArrayLike<number>;
uvs: ArrayLike<number>;
triangles: Array<number>;
color: Color;
hullLength: number;
private parentMesh;
inheritDeform: boolean;
tempColor: Color;
constructor(name: string);
updateUVs(): void;
applyDeform(sourceAttachment: VertexAttachment): boolean;
getParentMesh(): MeshAttachment;
setParentMesh(parentMesh: MeshAttachment): void;
}
}
declare module spine {
class PathAttachment extends VertexAttachment {
lengths: Array<number>;
closed: boolean;
constantSpeed: boolean;
color: Color;
constructor(name: string);
}
}
declare module spine {
class PointAttachment extends VertexAttachment {
x: number;
y: number;
rotation: number;
color: Color;
constructor(name: string);
computeWorldPosition(bone: Bone, point: Vector2): Vector2;
computeWorldRotation(bone: Bone): number;
}
}
declare module spine {
class RegionAttachment extends Attachment {
static OX1: number;
static OY1: number;
static OX2: number;
static OY2: number;
static OX3: number;
static OY3: number;
static OX4: number;
static OY4: number;
static X1: number;
static Y1: number;
static C1R: number;
static C1G: number;
static C1B: number;
static C1A: number;
static U1: number;
static V1: number;
static X2: number;
static Y2: number;
static C2R: number;
static C2G: number;
static C2B: number;
static C2A: number;
static U2: number;
static V2: number;
static X3: number;
static Y3: number;
static C3R: number;
static C3G: number;
static C3B: number;
static C3A: number;
static U3: number;
static V3: number;
static X4: number;
static Y4: number;
static C4R: number;
static C4G: number;
static C4B: number;
static C4A: number;
static U4: number;
static V4: number;
x: number;
y: number;
scaleX: number;
scaleY: number;
rotation: number;
width: number;
height: number;
color: Color;
path: string;
rendererObject: any;
region: TextureRegion;
offset: ArrayLike<number>;
uvs: ArrayLike<number>;
tempColor: Color;
constructor(name: string);
updateOffset(): void;
setRegion(region: TextureRegion): void;
computeWorldVertices(bone: Bone, worldVertices: ArrayLike<number>, offset: number, stride: number): void;
}
}
declare module spine {
enum BlendMode {
Normal = 0,
@ -1005,6 +784,46 @@ declare module spine {
constructor(index: number, name: string, boneData: BoneData);
}
}
declare module spine {
abstract class Texture {
protected _image: HTMLImageElement;
constructor(image: HTMLImageElement);
getImage(): HTMLImageElement;
abstract setFilters(minFilter: TextureFilter, magFilter: TextureFilter): void;
abstract setWraps(uWrap: TextureWrap, vWrap: TextureWrap): void;
abstract dispose(): void;
static filterFromString(text: string): TextureFilter;
static wrapFromString(text: string): TextureWrap;
}
enum TextureFilter {
Nearest = 9728,
Linear = 9729,
MipMap = 9987,
MipMapNearestNearest = 9984,
MipMapLinearNearest = 9985,
MipMapNearestLinear = 9986,
MipMapLinearLinear = 9987,
}
enum TextureWrap {
MirroredRepeat = 33648,
ClampToEdge = 33071,
Repeat = 10497,
}
class TextureRegion {
renderObject: any;
u: number;
v: number;
u2: number;
v2: number;
width: number;
height: number;
rotate: boolean;
offsetX: number;
offsetY: number;
originalWidth: number;
originalHeight: number;
}
}
declare module spine {
class TextureAtlas implements Disposable {
pages: TextureAtlasPage[];
@ -1222,6 +1041,156 @@ declare module spine {
end(): void;
}
}
declare module spine {
abstract class Attachment {
name: string;
constructor(name: string);
}
abstract class VertexAttachment extends Attachment {
private static nextID;
id: number;
bones: Array<number>;
vertices: ArrayLike<number>;
worldVerticesLength: number;
constructor(name: string);
computeWorldVertices(slot: Slot, start: number, count: number, worldVertices: ArrayLike<number>, offset: number, stride: number): void;
applyDeform(sourceAttachment: VertexAttachment): boolean;
}
}
declare module spine {
interface AttachmentLoader {
newRegionAttachment(skin: Skin, name: string, path: string): RegionAttachment;
newMeshAttachment(skin: Skin, name: string, path: string): MeshAttachment;
newBoundingBoxAttachment(skin: Skin, name: string): BoundingBoxAttachment;
newPathAttachment(skin: Skin, name: string): PathAttachment;
newPointAttachment(skin: Skin, name: string): PointAttachment;
newClippingAttachment(skin: Skin, name: string): ClippingAttachment;
}
}
declare module spine {
enum AttachmentType {
Region = 0,
BoundingBox = 1,
Mesh = 2,
LinkedMesh = 3,
Path = 4,
Point = 5,
}
}
declare module spine {
class BoundingBoxAttachment extends VertexAttachment {
color: Color;
constructor(name: string);
}
}
declare module spine {
class ClippingAttachment extends VertexAttachment {
endSlot: SlotData;
color: Color;
constructor(name: string);
}
}
declare module spine {
class MeshAttachment extends VertexAttachment {
region: TextureRegion;
path: string;
regionUVs: ArrayLike<number>;
uvs: ArrayLike<number>;
triangles: Array<number>;
color: Color;
hullLength: number;
private parentMesh;
inheritDeform: boolean;
tempColor: Color;
constructor(name: string);
updateUVs(): void;
applyDeform(sourceAttachment: VertexAttachment): boolean;
getParentMesh(): MeshAttachment;
setParentMesh(parentMesh: MeshAttachment): void;
}
}
declare module spine {
class PathAttachment extends VertexAttachment {
lengths: Array<number>;
closed: boolean;
constantSpeed: boolean;
color: Color;
constructor(name: string);
}
}
declare module spine {
class PointAttachment extends VertexAttachment {
x: number;
y: number;
rotation: number;
color: Color;
constructor(name: string);
computeWorldPosition(bone: Bone, point: Vector2): Vector2;
computeWorldRotation(bone: Bone): number;
}
}
declare module spine {
class RegionAttachment extends Attachment {
static OX1: number;
static OY1: number;
static OX2: number;
static OY2: number;
static OX3: number;
static OY3: number;
static OX4: number;
static OY4: number;
static X1: number;
static Y1: number;
static C1R: number;
static C1G: number;
static C1B: number;
static C1A: number;
static U1: number;
static V1: number;
static X2: number;
static Y2: number;
static C2R: number;
static C2G: number;
static C2B: number;
static C2A: number;
static U2: number;
static V2: number;
static X3: number;
static Y3: number;
static C3R: number;
static C3G: number;
static C3B: number;
static C3A: number;
static U3: number;
static V3: number;
static X4: number;
static Y4: number;
static C4R: number;
static C4G: number;
static C4B: number;
static C4A: number;
static U4: number;
static V4: number;
x: number;
y: number;
scaleX: number;
scaleY: number;
rotation: number;
width: number;
height: number;
color: Color;
path: string;
rendererObject: any;
region: TextureRegion;
offset: ArrayLike<number>;
uvs: ArrayLike<number>;
tempColor: Color;
constructor(name: string);
updateOffset(): void;
setRegion(region: TextureRegion): void;
computeWorldVertices(bone: Bone, worldVertices: ArrayLike<number>, offset: number, stride: number): void;
}
}
declare module spine {
class JitterEffect implements VertexEffect {
jitterX: number;
@ -1247,52 +1216,35 @@ declare module spine {
end(): void;
}
}
declare module spine.threejs {
declare module spine.canvas {
class AssetManager extends spine.AssetManager {
constructor(pathPrefix?: string);
}
}
declare module spine.threejs {
class MeshBatcher {
mesh: THREE.Mesh;
private static VERTEX_SIZE;
private vertexBuffer;
private vertices;
private verticesLength;
private indices;
private indicesLength;
constructor(mesh: THREE.Mesh, maxVertices?: number);
begin(): void;
batch(vertices: ArrayLike<number>, verticesLength: number, indices: ArrayLike<number>, indicesLength: number, z?: number): void;
end(): void;
}
}
declare module spine.threejs {
class SkeletonMesh extends THREE.Mesh {
skeleton: Skeleton;
state: AnimationState;
zOffset: number;
vertexEffect: VertexEffect;
private batcher;
private clipper;
static QUAD_TRIANGLES: number[];
static VERTEX_SIZE: number;
private vertices;
private tempColor;
constructor(skeletonData: SkeletonData);
update(deltaTime: number): void;
private updateGeometry();
}
}
declare module spine.threejs {
class ThreeJsTexture extends Texture {
texture: THREE.Texture;
declare module spine.canvas {
class CanvasTexture extends Texture {
constructor(image: HTMLImageElement);
setFilters(minFilter: TextureFilter, magFilter: TextureFilter): void;
setWraps(uWrap: TextureWrap, vWrap: TextureWrap): void;
dispose(): void;
static toThreeJsTextureFilter(filter: TextureFilter): THREE.TextureFilter;
static toThreeJsTextureWrap(wrap: TextureWrap): THREE.Wrapping;
}
}
declare module spine.canvas {
class SkeletonRenderer {
static QUAD_TRIANGLES: number[];
static VERTEX_SIZE: number;
private ctx;
triangleRendering: boolean;
debugRendering: boolean;
private vertices;
private tempColor;
constructor(context: CanvasRenderingContext2D);
draw(skeleton: Skeleton): void;
private drawImages(skeleton);
private drawTriangles(skeleton);
private drawTriangle(img, x0, y0, u0, v0, x1, y1, u1, v1, x2, y2, u2, v2);
private computeRegionVertices(slot, region, pma);
private computeMeshVertices(slot, mesh, pma);
}
}
declare module spine.webgl {
@ -1386,22 +1338,22 @@ declare module spine.webgl {
}
}
declare module spine.webgl {
const M00: number;
const M01: number;
const M02: number;
const M03: number;
const M10: number;
const M11: number;
const M12: number;
const M13: number;
const M20: number;
const M21: number;
const M22: number;
const M23: number;
const M30: number;
const M31: number;
const M32: number;
const M33: number;
const M00 = 0;
const M01 = 4;
const M02 = 8;
const M03 = 12;
const M10 = 1;
const M11 = 5;
const M12 = 9;
const M13 = 13;
const M20 = 2;
const M21 = 6;
const M22 = 10;
const M23 = 14;
const M30 = 3;
const M31 = 7;
const M32 = 11;
const M33 = 15;
class Matrix4 {
temp: Float32Array;
values: Float32Array;
@ -1725,6 +1677,58 @@ declare module spine.webgl {
static getSourceGLBlendMode(blendMode: BlendMode, premultipliedAlpha?: boolean): number;
}
}
declare module spine.threejs {
class AssetManager extends spine.AssetManager {
constructor(pathPrefix?: string);
}
}
declare module spine.threejs {
class MeshBatcher {
mesh: THREE.Mesh;
private static VERTEX_SIZE;
private vertexBuffer;
private vertices;
private verticesLength;
private indices;
private indicesLength;
constructor(mesh: THREE.Mesh, maxVertices?: number);
begin(): void;
batch(vertices: ArrayLike<number>, verticesLength: number, indices: ArrayLike<number>, indicesLength: number, z?: number): void;
end(): void;
}
}
declare module spine.threejs {
class SkeletonMesh extends THREE.Mesh {
tempPos: Vector2;
tempUv: Vector2;
tempLight: Color;
tempDark: Color;
skeleton: Skeleton;
state: AnimationState;
zOffset: number;
vertexEffect: VertexEffect;
private batcher;
private clipper;
static QUAD_TRIANGLES: number[];
static VERTEX_SIZE: number;
private vertices;
private tempColor;
constructor(skeletonData: SkeletonData);
update(deltaTime: number): void;
private updateGeometry();
}
}
declare module spine.threejs {
class ThreeJsTexture extends Texture {
texture: THREE.Texture;
constructor(image: HTMLImageElement);
setFilters(minFilter: TextureFilter, magFilter: TextureFilter): void;
setWraps(uWrap: TextureWrap, vWrap: TextureWrap): void;
dispose(): void;
static toThreeJsTextureFilter(filter: TextureFilter): THREE.TextureFilter;
static toThreeJsTextureWrap(wrap: TextureWrap): THREE.Wrapping;
}
}
declare module spine {
class SpineWidget {
skeleton: Skeleton;

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -1,97 +1,3 @@
declare module spine {
class AssetManager implements Disposable {
private pathPrefix;
private textureLoader;
private assets;
private errors;
private toLoad;
private loaded;
constructor(textureLoader: (image: HTMLImageElement) => any, pathPrefix?: string);
loadText(path: string, success?: (path: string, text: string) => void, error?: (path: string, error: string) => void): void;
loadTexture(path: string, success?: (path: string, image: HTMLImageElement) => void, error?: (path: string, error: string) => void): void;
loadTextureData(path: string, data: string, success?: (path: string, image: HTMLImageElement) => void, error?: (path: string, error: string) => void): void;
get(path: string): any;
remove(path: string): void;
removeAll(): void;
isLoadingComplete(): boolean;
getToLoad(): number;
getLoaded(): number;
dispose(): void;
hasErrors(): boolean;
getErrors(): Map<string>;
}
}
declare module spine.canvas {
class AssetManager extends spine.AssetManager {
constructor(pathPrefix?: string);
}
}
declare module spine {
abstract class Texture {
protected _image: HTMLImageElement;
constructor(image: HTMLImageElement);
getImage(): HTMLImageElement;
abstract setFilters(minFilter: TextureFilter, magFilter: TextureFilter): void;
abstract setWraps(uWrap: TextureWrap, vWrap: TextureWrap): void;
abstract dispose(): void;
static filterFromString(text: string): TextureFilter;
static wrapFromString(text: string): TextureWrap;
}
enum TextureFilter {
Nearest = 9728,
Linear = 9729,
MipMap = 9987,
MipMapNearestNearest = 9984,
MipMapLinearNearest = 9985,
MipMapNearestLinear = 9986,
MipMapLinearLinear = 9987,
}
enum TextureWrap {
MirroredRepeat = 33648,
ClampToEdge = 33071,
Repeat = 10497,
}
class TextureRegion {
renderObject: any;
u: number;
v: number;
u2: number;
v2: number;
width: number;
height: number;
rotate: boolean;
offsetX: number;
offsetY: number;
originalWidth: number;
originalHeight: number;
}
}
declare module spine.canvas {
class CanvasTexture extends Texture {
constructor(image: HTMLImageElement);
setFilters(minFilter: TextureFilter, magFilter: TextureFilter): void;
setWraps(uWrap: TextureWrap, vWrap: TextureWrap): void;
dispose(): void;
}
}
declare module spine.canvas {
class SkeletonRenderer {
static QUAD_TRIANGLES: number[];
static VERTEX_SIZE: number;
private ctx;
triangleRendering: boolean;
debugRendering: boolean;
private vertices;
private tempColor;
constructor(context: CanvasRenderingContext2D);
draw(skeleton: Skeleton): void;
private drawImages(skeleton);
private drawTriangles(skeleton);
private drawTriangle(img, x0, y0, u0, v0, x1, y1, u1, v1, x2, y2, u2, v2);
private computeRegionVertices(slot, region, pma);
private computeMeshVertices(slot, mesh, pma);
}
}
declare module spine {
class Animation {
name: string;
@ -458,6 +364,29 @@ declare module spine {
getMix(from: Animation, to: Animation): number;
}
}
declare module spine {
class AssetManager implements Disposable {
private pathPrefix;
private textureLoader;
private assets;
private errors;
private toLoad;
private loaded;
constructor(textureLoader: (image: HTMLImageElement) => any, pathPrefix?: string);
loadText(path: string, success?: (path: string, text: string) => void, error?: (path: string, error: string) => void): void;
loadTexture(path: string, success?: (path: string, image: HTMLImageElement) => void, error?: (path: string, error: string) => void): void;
loadTextureData(path: string, data: string, success?: (path: string, image: HTMLImageElement) => void, error?: (path: string, error: string) => void): void;
get(path: string): any;
remove(path: string): void;
removeAll(): void;
isLoadingComplete(): boolean;
getToLoad(): number;
getLoaded(): number;
dispose(): void;
hasErrors(): boolean;
getErrors(): Map<string>;
}
}
declare module spine {
class AtlasAttachmentLoader implements AttachmentLoader {
atlas: TextureAtlas;
@ -470,156 +399,6 @@ declare module spine {
newClippingAttachment(skin: Skin, name: string): ClippingAttachment;
}
}
declare module spine {
abstract class Attachment {
name: string;
constructor(name: string);
}
abstract class VertexAttachment extends Attachment {
private static nextID;
id: number;
bones: Array<number>;
vertices: ArrayLike<number>;
worldVerticesLength: number;
constructor(name: string);
computeWorldVertices(slot: Slot, start: number, count: number, worldVertices: ArrayLike<number>, offset: number, stride: number): void;
applyDeform(sourceAttachment: VertexAttachment): boolean;
}
}
declare module spine {
interface AttachmentLoader {
newRegionAttachment(skin: Skin, name: string, path: string): RegionAttachment;
newMeshAttachment(skin: Skin, name: string, path: string): MeshAttachment;
newBoundingBoxAttachment(skin: Skin, name: string): BoundingBoxAttachment;
newPathAttachment(skin: Skin, name: string): PathAttachment;
newPointAttachment(skin: Skin, name: string): PointAttachment;
newClippingAttachment(skin: Skin, name: string): ClippingAttachment;
}
}
declare module spine {
enum AttachmentType {
Region = 0,
BoundingBox = 1,
Mesh = 2,
LinkedMesh = 3,
Path = 4,
Point = 5,
}
}
declare module spine {
class BoundingBoxAttachment extends VertexAttachment {
color: Color;
constructor(name: string);
}
}
declare module spine {
class ClippingAttachment extends VertexAttachment {
endSlot: SlotData;
color: Color;
constructor(name: string);
}
}
declare module spine {
class MeshAttachment extends VertexAttachment {
region: TextureRegion;
path: string;
regionUVs: ArrayLike<number>;
uvs: ArrayLike<number>;
triangles: Array<number>;
color: Color;
hullLength: number;
private parentMesh;
inheritDeform: boolean;
tempColor: Color;
constructor(name: string);
updateUVs(): void;
applyDeform(sourceAttachment: VertexAttachment): boolean;
getParentMesh(): MeshAttachment;
setParentMesh(parentMesh: MeshAttachment): void;
}
}
declare module spine {
class PathAttachment extends VertexAttachment {
lengths: Array<number>;
closed: boolean;
constantSpeed: boolean;
color: Color;
constructor(name: string);
}
}
declare module spine {
class PointAttachment extends VertexAttachment {
x: number;
y: number;
rotation: number;
color: Color;
constructor(name: string);
computeWorldPosition(bone: Bone, point: Vector2): Vector2;
computeWorldRotation(bone: Bone): number;
}
}
declare module spine {
class RegionAttachment extends Attachment {
static OX1: number;
static OY1: number;
static OX2: number;
static OY2: number;
static OX3: number;
static OY3: number;
static OX4: number;
static OY4: number;
static X1: number;
static Y1: number;
static C1R: number;
static C1G: number;
static C1B: number;
static C1A: number;
static U1: number;
static V1: number;
static X2: number;
static Y2: number;
static C2R: number;
static C2G: number;
static C2B: number;
static C2A: number;
static U2: number;
static V2: number;
static X3: number;
static Y3: number;
static C3R: number;
static C3G: number;
static C3B: number;
static C3A: number;
static U3: number;
static V3: number;
static X4: number;
static Y4: number;
static C4R: number;
static C4G: number;
static C4B: number;
static C4A: number;
static U4: number;
static V4: number;
x: number;
y: number;
scaleX: number;
scaleY: number;
rotation: number;
width: number;
height: number;
color: Color;
path: string;
rendererObject: any;
region: TextureRegion;
offset: ArrayLike<number>;
uvs: ArrayLike<number>;
tempColor: Color;
constructor(name: string);
updateOffset(): void;
setRegion(region: TextureRegion): void;
computeWorldVertices(bone: Bone, worldVertices: ArrayLike<number>, offset: number, stride: number): void;
}
}
declare module spine {
enum BlendMode {
Normal = 0,
@ -1005,6 +784,46 @@ declare module spine {
constructor(index: number, name: string, boneData: BoneData);
}
}
declare module spine {
abstract class Texture {
protected _image: HTMLImageElement;
constructor(image: HTMLImageElement);
getImage(): HTMLImageElement;
abstract setFilters(minFilter: TextureFilter, magFilter: TextureFilter): void;
abstract setWraps(uWrap: TextureWrap, vWrap: TextureWrap): void;
abstract dispose(): void;
static filterFromString(text: string): TextureFilter;
static wrapFromString(text: string): TextureWrap;
}
enum TextureFilter {
Nearest = 9728,
Linear = 9729,
MipMap = 9987,
MipMapNearestNearest = 9984,
MipMapLinearNearest = 9985,
MipMapNearestLinear = 9986,
MipMapLinearLinear = 9987,
}
enum TextureWrap {
MirroredRepeat = 33648,
ClampToEdge = 33071,
Repeat = 10497,
}
class TextureRegion {
renderObject: any;
u: number;
v: number;
u2: number;
v2: number;
width: number;
height: number;
rotate: boolean;
offsetX: number;
offsetY: number;
originalWidth: number;
originalHeight: number;
}
}
declare module spine {
class TextureAtlas implements Disposable {
pages: TextureAtlasPage[];
@ -1222,6 +1041,156 @@ declare module spine {
end(): void;
}
}
declare module spine {
abstract class Attachment {
name: string;
constructor(name: string);
}
abstract class VertexAttachment extends Attachment {
private static nextID;
id: number;
bones: Array<number>;
vertices: ArrayLike<number>;
worldVerticesLength: number;
constructor(name: string);
computeWorldVertices(slot: Slot, start: number, count: number, worldVertices: ArrayLike<number>, offset: number, stride: number): void;
applyDeform(sourceAttachment: VertexAttachment): boolean;
}
}
declare module spine {
interface AttachmentLoader {
newRegionAttachment(skin: Skin, name: string, path: string): RegionAttachment;
newMeshAttachment(skin: Skin, name: string, path: string): MeshAttachment;
newBoundingBoxAttachment(skin: Skin, name: string): BoundingBoxAttachment;
newPathAttachment(skin: Skin, name: string): PathAttachment;
newPointAttachment(skin: Skin, name: string): PointAttachment;
newClippingAttachment(skin: Skin, name: string): ClippingAttachment;
}
}
declare module spine {
enum AttachmentType {
Region = 0,
BoundingBox = 1,
Mesh = 2,
LinkedMesh = 3,
Path = 4,
Point = 5,
}
}
declare module spine {
class BoundingBoxAttachment extends VertexAttachment {
color: Color;
constructor(name: string);
}
}
declare module spine {
class ClippingAttachment extends VertexAttachment {
endSlot: SlotData;
color: Color;
constructor(name: string);
}
}
declare module spine {
class MeshAttachment extends VertexAttachment {
region: TextureRegion;
path: string;
regionUVs: ArrayLike<number>;
uvs: ArrayLike<number>;
triangles: Array<number>;
color: Color;
hullLength: number;
private parentMesh;
inheritDeform: boolean;
tempColor: Color;
constructor(name: string);
updateUVs(): void;
applyDeform(sourceAttachment: VertexAttachment): boolean;
getParentMesh(): MeshAttachment;
setParentMesh(parentMesh: MeshAttachment): void;
}
}
declare module spine {
class PathAttachment extends VertexAttachment {
lengths: Array<number>;
closed: boolean;
constantSpeed: boolean;
color: Color;
constructor(name: string);
}
}
declare module spine {
class PointAttachment extends VertexAttachment {
x: number;
y: number;
rotation: number;
color: Color;
constructor(name: string);
computeWorldPosition(bone: Bone, point: Vector2): Vector2;
computeWorldRotation(bone: Bone): number;
}
}
declare module spine {
class RegionAttachment extends Attachment {
static OX1: number;
static OY1: number;
static OX2: number;
static OY2: number;
static OX3: number;
static OY3: number;
static OX4: number;
static OY4: number;
static X1: number;
static Y1: number;
static C1R: number;
static C1G: number;
static C1B: number;
static C1A: number;
static U1: number;
static V1: number;
static X2: number;
static Y2: number;
static C2R: number;
static C2G: number;
static C2B: number;
static C2A: number;
static U2: number;
static V2: number;
static X3: number;
static Y3: number;
static C3R: number;
static C3G: number;
static C3B: number;
static C3A: number;
static U3: number;
static V3: number;
static X4: number;
static Y4: number;
static C4R: number;
static C4G: number;
static C4B: number;
static C4A: number;
static U4: number;
static V4: number;
x: number;
y: number;
scaleX: number;
scaleY: number;
rotation: number;
width: number;
height: number;
color: Color;
path: string;
rendererObject: any;
region: TextureRegion;
offset: ArrayLike<number>;
uvs: ArrayLike<number>;
tempColor: Color;
constructor(name: string);
updateOffset(): void;
setRegion(region: TextureRegion): void;
computeWorldVertices(bone: Bone, worldVertices: ArrayLike<number>, offset: number, stride: number): void;
}
}
declare module spine {
class JitterEffect implements VertexEffect {
jitterX: number;
@ -1247,3 +1216,34 @@ declare module spine {
end(): void;
}
}
declare module spine.canvas {
class AssetManager extends spine.AssetManager {
constructor(pathPrefix?: string);
}
}
declare module spine.canvas {
class CanvasTexture extends Texture {
constructor(image: HTMLImageElement);
setFilters(minFilter: TextureFilter, magFilter: TextureFilter): void;
setWraps(uWrap: TextureWrap, vWrap: TextureWrap): void;
dispose(): void;
}
}
declare module spine.canvas {
class SkeletonRenderer {
static QUAD_TRIANGLES: number[];
static VERTEX_SIZE: number;
private ctx;
triangleRendering: boolean;
debugRendering: boolean;
private vertices;
private tempColor;
constructor(context: CanvasRenderingContext2D);
draw(skeleton: Skeleton): void;
private drawImages(skeleton);
private drawTriangles(skeleton);
private drawTriangle(img, x0, y0, u0, v0, x1, y1, u1, v1, x2, y2, u2, v2);
private computeRegionVertices(slot, region, pma);
private computeMeshVertices(slot, mesh, pma);
}
}

Some files were not shown because too many files have changed in this diff Show More