├── README.md
├── spine-csharp
├── Properties
│ └── AssemblyInfo.cs
├── README.md
├── nuget
│ └── Spine.1.6.18.nuspec
└── src
│ ├── Animation.cs
│ ├── AnimationState.cs
│ ├── AnimationStateData.cs
│ ├── Atlas.cs
│ ├── Attachments
│ ├── AtlasAttachmentLoader.cs
│ ├── Attachment.cs
│ ├── AttachmentLoader.cs
│ ├── AttachmentType.cs
│ ├── BoundingBoxAttachment.cs
│ ├── MeshAttachment.cs
│ ├── RegionAttachment.cs
│ └── SkinnedMeshAttachment.cs
│ ├── Bone.cs
│ ├── BoneData.cs
│ ├── Event.cs
│ ├── EventData.cs
│ ├── IkConstraint.cs
│ ├── IkConstraintData.cs
│ ├── Json.cs
│ ├── Skeleton.cs
│ ├── SkeletonBinary.cs
│ ├── SkeletonBounds.cs
│ ├── SkeletonData.cs
│ ├── SkeletonJson.cs
│ ├── Skin.cs
│ ├── Slot.cs
│ └── SlotData.cs
└── spine-unity
├── AtlasAsset.cs
├── AtlasRegionAttacher.cs
├── BoneFollower.cs
├── CustomSkin.cs
├── Editor
├── AtlasAssetInspector.cs
├── BoneFollowerInspector.cs
├── GUI
│ ├── icon-animation.png
│ ├── icon-animationRoot.png
│ ├── icon-bone.png
│ ├── icon-boneNib.png
│ ├── icon-boundingBox.png
│ ├── icon-constraintNib.png
│ ├── icon-event.png
│ ├── icon-hingeChain.png
│ ├── icon-image.png
│ ├── icon-mesh.png
│ ├── icon-null.png
│ ├── icon-poseBones.png
│ ├── icon-skeleton.png
│ ├── icon-skeletonUtility.png
│ ├── icon-skin.png
│ ├── icon-skinPlaceholder.png
│ ├── icon-skinsRoot.png
│ ├── icon-slot.png
│ ├── icon-slotRoot.png
│ ├── icon-spine.png
│ ├── icon-subMeshRenderer.png
│ ├── icon-warning.png
│ └── icon-weights.png
├── Menus.cs
├── SkeletonAnimationInspector.cs
├── SkeletonAnimatorInspector.cs
├── SkeletonBaker.cs
├── SkeletonDataAssetInspector.cs
├── SkeletonRendererInspector.cs
├── SpineAttributeDrawers.cs
└── SpineEditorUtilities.cs
├── Shaders
├── Bones.shader
├── HiddenPass.mat
├── HiddenPass.shader
├── SkeletonLit.shader
├── Spine-Skeleton-BlendMode.shader
├── Spine-Skeleton-HDR.shader
└── Spine-Skeleton.shader
├── SkeletonAnimation.cs
├── SkeletonAnimationInterface.cs
├── SkeletonAnimator.cs
├── SkeletonDataAsset.cs
├── SkeletonExtensions.cs
├── SkeletonRenderer.cs
├── SkeletonUtility
├── Editor
│ ├── SkeletonUtilityBoneInspector.cs
│ ├── SkeletonUtilityInspector.cs
│ └── SkeletonUtilitySubmeshRendererInspector.cs
├── SkeletonUtility.cs
├── SkeletonUtilityBone.cs
├── SkeletonUtilityConstraint.cs
├── SkeletonUtilityEyeConstraint.cs
├── SkeletonUtilityGroundConstraint.cs
├── SkeletonUtilityKinematicShadow.cs
└── SkeletonUtilitySubmeshRenderer.cs
├── SpineAttributes.cs
├── SpriteAttacher.cs
└── SpriteCollectionAttachmentLoader.cs
/README.md:
--------------------------------------------------------------------------------
1 | # spine-optimize
2 | Spine for Unity Version 2.1
3 |
4 | First:
5 | Convert JSON to binary.
6 |
7 | Second:
8 | Use pointer movement instead of Stream read.
9 |
10 | Once again, to optimize:
11 | All strings moved to the header, using index instead.
12 | Delete nonessential data.
13 | Merge Timeline.
14 | So the binary 50%-70% smaller.
15 |
16 | spine版本比较老2.1,但优化原理一样。
17 | 第一步:读取json格式转成二进制。
18 | 第二步:使用指针代替Stream读取。
19 | 第三步:将所有的string移到头部,使用下标代替,合并相同的timeline。
20 | 这样可以使二进制再小50%-70%。
--------------------------------------------------------------------------------
/spine-csharp/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 |
9 | // Setting ComVisible to false makes the types in this assembly not visible
10 | // to COM components. If you need to access a type in this assembly from
11 | // COM, set the ComVisible attribute to true on that type. Only Windows
12 | // assemblies support COM.
13 | [assembly: ComVisible(false)]
14 |
15 | // On Windows, the following GUID is for the ID of the typelib if this
16 | // project is exposed to COM. On other platforms, it unique identifies the
17 | // title storage container when deploying this assembly to the device.
18 | [assembly: Guid("3ac8567e-9ae8-4624-87b9-a84f0101c629")]
19 |
20 | // Version information for an assembly consists of the following four values:
21 | //
22 | // Major Version
23 | // Minor Version
24 | // Build Number
25 | // Revision
26 | //
--------------------------------------------------------------------------------
/spine-csharp/README.md:
--------------------------------------------------------------------------------
1 | # spine-csharp
2 |
3 | The spine-csharp runtime provides functionality to load and manipulate [Spine](http://esotericsoftware.com) skeletal animation data using C# (C Sharp). It does not perform rendering but can be extended to enable Spine animations for other C#-based projects.
4 |
5 | ## Setup
6 |
7 | 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).
8 | 1. Open the `spine-csharp.sln` Visual C# 2010 Express project file.
9 |
10 | Alternatively, the contents of the `spine-csharp/src` directory can be copied into your project.
11 |
12 | ## Runtimes Extending spine-csharp
13 |
14 | - [spine-monogame](https://github.com/EsotericSoftware/spine-runtimes/blob/master/spine-monogame)
15 | - [spine-tk2d](https://github.com/EsotericSoftware/spine-runtimes/blob/master/spine-tk2d)
16 | - [spine-unity](https://github.com/EsotericSoftware/spine-runtimes/blob/master/spine-unity)
17 | - [spine-xna](https://github.com/EsotericSoftware/spine-runtimes/blob/master/spine-xna)
18 |
--------------------------------------------------------------------------------
/spine-csharp/nuget/Spine.1.6.18.nuspec:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Spine
5 | 1.6.18.0
6 | Esoteric Software
7 | Esoteric Software
8 | https://github.com/EsotericSoftware/spine-runtimes/blob/master/LICENSE
9 | http://esotericsoftware.com/
10 | http://esotericsoftware.com/spine/files/logo-420.png
11 | true
12 | Spine is a 2D skeletal animation tool for game development and other animation projects.
13 | Spine features an intuitive workflow to rig and animate skeletons, a multiple-timeline dopesheet for retiming and tweaking animations, powerful exporting capabilities, and runtimes for many programming languages and game toolkits.
14 | Release build for .NET 4.0 of version 1.6.18 (changeset c732a687, 2013-10-24)
15 | Copyright 2013
16 | 2D skeletal animation runtime Spine
17 |
18 |
--------------------------------------------------------------------------------
/spine-csharp/src/AnimationStateData.cs:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Spine Runtimes Software License
3 | * Version 2.1
4 | *
5 | * Copyright (c) 2013, Esoteric Software
6 | * All rights reserved.
7 | *
8 | * You are granted a perpetual, non-exclusive, non-sublicensable and
9 | * non-transferable license to install, execute and perform the Spine Runtimes
10 | * Software (the "Software") solely for internal use. Without the written
11 | * permission of Esoteric Software (typically granted by licensing Spine), you
12 | * may not (a) modify, translate, adapt or otherwise create derivative works,
13 | * improvements of the Software or develop new applications using the Software
14 | * or (b) remove, delete, alter or obscure any trademarks or any copyright,
15 | * trademark, patent or other intellectual property or proprietary rights
16 | * notices on or in the Software, including any copy thereof. Redistributions
17 | * in binary or source form must include this license and terms.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
22 | * EVENT SHALL ESOTERIC SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 | *****************************************************************************/
30 |
31 | using System;
32 | using System.Collections.Generic;
33 |
34 | namespace Spine {
35 | public class AnimationStateData {
36 | internal SkeletonData skeletonData;
37 | private Dictionary, float> animationToMixTime = new Dictionary, float>();
38 | internal float defaultMix;
39 |
40 | public SkeletonData SkeletonData { get { return skeletonData; } }
41 | public float DefaultMix { get { return defaultMix; } set { defaultMix = value; } }
42 |
43 | public AnimationStateData (SkeletonData skeletonData) {
44 | this.skeletonData = skeletonData;
45 | }
46 |
47 | public void SetMix (String fromName, String toName, float duration) {
48 | Animation from = skeletonData.FindAnimation(fromName);
49 | if (from == null) throw new ArgumentException("Animation not found: " + fromName);
50 | Animation to = skeletonData.FindAnimation(toName);
51 | if (to == null) throw new ArgumentException("Animation not found: " + toName);
52 | SetMix(from, to, duration);
53 | }
54 |
55 | public void SetMix (Animation from, Animation to, float duration) {
56 | if (from == null) throw new ArgumentNullException("from cannot be null.");
57 | if (to == null) throw new ArgumentNullException("to cannot be null.");
58 | KeyValuePair key = new KeyValuePair(from, to);
59 | animationToMixTime.Remove(key);
60 | animationToMixTime.Add(key, duration);
61 | }
62 |
63 | public float GetMix (Animation from, Animation to) {
64 | KeyValuePair key = new KeyValuePair(from, to);
65 | float duration;
66 | if (animationToMixTime.TryGetValue(key, out duration)) return duration;
67 | return defaultMix;
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/spine-csharp/src/Attachments/AtlasAttachmentLoader.cs:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Spine Runtimes Software License
3 | * Version 2.1
4 | *
5 | * Copyright (c) 2013, Esoteric Software
6 | * All rights reserved.
7 | *
8 | * You are granted a perpetual, non-exclusive, non-sublicensable and
9 | * non-transferable license to install, execute and perform the Spine Runtimes
10 | * Software (the "Software") solely for internal use. Without the written
11 | * permission of Esoteric Software (typically granted by licensing Spine), you
12 | * may not (a) modify, translate, adapt or otherwise create derivative works,
13 | * improvements of the Software or develop new applications using the Software
14 | * or (b) remove, delete, alter or obscure any trademarks or any copyright,
15 | * trademark, patent or other intellectual property or proprietary rights
16 | * notices on or in the Software, including any copy thereof. Redistributions
17 | * in binary or source form must include this license and terms.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
22 | * EVENT SHALL ESOTERIC SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 | *****************************************************************************/
30 |
31 | using System;
32 | using System.Collections.Generic;
33 |
34 | namespace Spine {
35 | public class AtlasAttachmentLoader : AttachmentLoader {
36 | private Atlas[] atlasArray;
37 |
38 | // HuaHua. cache regions, quickly find
39 | private Dictionary regins = new Dictionary();
40 |
41 | public AtlasAttachmentLoader(params Atlas[] atlasArray)
42 | {
43 | if (atlasArray == null) throw new ArgumentNullException("atlas array cannot be null.");
44 | this.atlasArray = atlasArray;
45 |
46 | // HuaHua.
47 | for (int i = 0; i < atlasArray.Length; i++)
48 | {
49 | var regions = atlasArray[i].regions;
50 |
51 | for (int ir = 0, n = regions.Count; ir < n; ir++)
52 | {
53 | regins.Add(regions[ir].name, regions[ir]);
54 | }
55 | }
56 | }
57 |
58 | public RegionAttachment NewRegionAttachment (Skin skin, String name, String path) {
59 | AtlasRegion region = FindRegion(path);
60 | if (region == null) throw new Exception("Region not found in atlas: " + path + " (region attachment: " + name + ")");
61 | RegionAttachment attachment = new RegionAttachment(name);
62 | attachment.RendererObject = region;
63 | attachment.SetUVs(region.u, region.v, region.u2, region.v2, region.rotate);
64 | attachment.regionOffsetX = region.offsetX;
65 | attachment.regionOffsetY = region.offsetY;
66 | attachment.regionWidth = region.width;
67 | attachment.regionHeight = region.height;
68 | attachment.regionOriginalWidth = region.originalWidth;
69 | attachment.regionOriginalHeight = region.originalHeight;
70 | return attachment;
71 | }
72 |
73 | public MeshAttachment NewMeshAttachment (Skin skin, String name, String path) {
74 | AtlasRegion region = FindRegion(path);
75 | if (region == null) throw new Exception("Region not found in atlas: " + path + " (mesh attachment: " + name + ")");
76 | MeshAttachment attachment = new MeshAttachment(name);
77 | attachment.RendererObject = region;
78 | attachment.RegionU = region.u;
79 | attachment.RegionV = region.v;
80 | attachment.RegionU2 = region.u2;
81 | attachment.RegionV2 = region.v2;
82 | attachment.RegionRotate = region.rotate;
83 | attachment.regionOffsetX = region.offsetX;
84 | attachment.regionOffsetY = region.offsetY;
85 | attachment.regionWidth = region.width;
86 | attachment.regionHeight = region.height;
87 | attachment.regionOriginalWidth = region.originalWidth;
88 | attachment.regionOriginalHeight = region.originalHeight;
89 | return attachment;
90 | }
91 |
92 | public SkinnedMeshAttachment NewSkinnedMeshAttachment (Skin skin, String name, String path) {
93 | AtlasRegion region = FindRegion(path);
94 | if (region == null) throw new Exception("Region not found in atlas: " + path + " (skinned mesh attachment: " + name + ")");
95 | SkinnedMeshAttachment attachment = new SkinnedMeshAttachment(name);
96 | attachment.RendererObject = region;
97 | attachment.RegionU = region.u;
98 | attachment.RegionV = region.v;
99 | attachment.RegionU2 = region.u2;
100 | attachment.RegionV2 = region.v2;
101 | attachment.RegionRotate = region.rotate;
102 | attachment.regionOffsetX = region.offsetX;
103 | attachment.regionOffsetY = region.offsetY;
104 | attachment.regionWidth = region.width;
105 | attachment.regionHeight = region.height;
106 | attachment.regionOriginalWidth = region.originalWidth;
107 | attachment.regionOriginalHeight = region.originalHeight;
108 | return attachment;
109 | }
110 |
111 | public BoundingBoxAttachment NewBoundingBoxAttachment (Skin skin, String name) {
112 | return new BoundingBoxAttachment(name);
113 | }
114 |
115 | public AtlasRegion FindRegion(string name) {
116 | regins.TryGetValue(name, out AtlasRegion region);
117 | return region;
118 | }
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/spine-csharp/src/Attachments/Attachment.cs:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Spine Runtimes Software License
3 | * Version 2.1
4 | *
5 | * Copyright (c) 2013, Esoteric Software
6 | * All rights reserved.
7 | *
8 | * You are granted a perpetual, non-exclusive, non-sublicensable and
9 | * non-transferable license to install, execute and perform the Spine Runtimes
10 | * Software (the "Software") solely for internal use. Without the written
11 | * permission of Esoteric Software (typically granted by licensing Spine), you
12 | * may not (a) modify, translate, adapt or otherwise create derivative works,
13 | * improvements of the Software or develop new applications using the Software
14 | * or (b) remove, delete, alter or obscure any trademarks or any copyright,
15 | * trademark, patent or other intellectual property or proprietary rights
16 | * notices on or in the Software, including any copy thereof. Redistributions
17 | * in binary or source form must include this license and terms.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
22 | * EVENT SHALL ESOTERIC SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 | *****************************************************************************/
30 |
31 | using System;
32 |
33 | namespace Spine {
34 | abstract public class Attachment {
35 | public String Name { get; private set; }
36 |
37 | public Attachment (String name) {
38 | if (name == null) throw new ArgumentNullException("name cannot be null.");
39 | Name = name;
40 | }
41 |
42 | override public String ToString () {
43 | return Name;
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/spine-csharp/src/Attachments/AttachmentLoader.cs:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Spine Runtimes Software License
3 | * Version 2.1
4 | *
5 | * Copyright (c) 2013, Esoteric Software
6 | * All rights reserved.
7 | *
8 | * You are granted a perpetual, non-exclusive, non-sublicensable and
9 | * non-transferable license to install, execute and perform the Spine Runtimes
10 | * Software (the "Software") solely for internal use. Without the written
11 | * permission of Esoteric Software (typically granted by licensing Spine), you
12 | * may not (a) modify, translate, adapt or otherwise create derivative works,
13 | * improvements of the Software or develop new applications using the Software
14 | * or (b) remove, delete, alter or obscure any trademarks or any copyright,
15 | * trademark, patent or other intellectual property or proprietary rights
16 | * notices on or in the Software, including any copy thereof. Redistributions
17 | * in binary or source form must include this license and terms.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
22 | * EVENT SHALL ESOTERIC SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 | *****************************************************************************/
30 |
31 | using System;
32 |
33 | namespace Spine {
34 | public interface AttachmentLoader {
35 | /// May be null to not load any attachment.
36 | RegionAttachment NewRegionAttachment (Skin skin, String name, String path);
37 |
38 | /// May be null to not load any attachment.
39 | MeshAttachment NewMeshAttachment (Skin skin, String name, String path);
40 |
41 | /// May be null to not load any attachment.
42 | SkinnedMeshAttachment NewSkinnedMeshAttachment (Skin skin, String name, String path);
43 |
44 | /// May be null to not load any attachment.
45 | BoundingBoxAttachment NewBoundingBoxAttachment (Skin skin, String name);
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/spine-csharp/src/Attachments/AttachmentType.cs:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Spine Runtimes Software License
3 | * Version 2.1
4 | *
5 | * Copyright (c) 2013, Esoteric Software
6 | * All rights reserved.
7 | *
8 | * You are granted a perpetual, non-exclusive, non-sublicensable and
9 | * non-transferable license to install, execute and perform the Spine Runtimes
10 | * Software (the "Software") solely for internal use. Without the written
11 | * permission of Esoteric Software (typically granted by licensing Spine), you
12 | * may not (a) modify, translate, adapt or otherwise create derivative works,
13 | * improvements of the Software or develop new applications using the Software
14 | * or (b) remove, delete, alter or obscure any trademarks or any copyright,
15 | * trademark, patent or other intellectual property or proprietary rights
16 | * notices on or in the Software, including any copy thereof. Redistributions
17 | * in binary or source form must include this license and terms.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
22 | * EVENT SHALL ESOTERIC SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 | *****************************************************************************/
30 |
31 | namespace Spine {
32 | public enum AttachmentType {
33 | region, boundingbox, mesh, skinnedmesh
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/spine-csharp/src/Attachments/BoundingBoxAttachment.cs:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Spine Runtimes Software License
3 | * Version 2.1
4 | *
5 | * Copyright (c) 2013, Esoteric Software
6 | * All rights reserved.
7 | *
8 | * You are granted a perpetual, non-exclusive, non-sublicensable and
9 | * non-transferable license to install, execute and perform the Spine Runtimes
10 | * Software (the "Software") solely for internal use. Without the written
11 | * permission of Esoteric Software (typically granted by licensing Spine), you
12 | * may not (a) modify, translate, adapt or otherwise create derivative works,
13 | * improvements of the Software or develop new applications using the Software
14 | * or (b) remove, delete, alter or obscure any trademarks or any copyright,
15 | * trademark, patent or other intellectual property or proprietary rights
16 | * notices on or in the Software, including any copy thereof. Redistributions
17 | * in binary or source form must include this license and terms.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
22 | * EVENT SHALL ESOTERIC SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 | *****************************************************************************/
30 |
31 | using System;
32 |
33 | namespace Spine {
34 | /// Attachment that has a polygon for bounds checking.
35 | public class BoundingBoxAttachment : Attachment {
36 | internal float[] vertices;
37 |
38 | public float[] Vertices { get { return vertices; } set { vertices = value; } }
39 |
40 | public BoundingBoxAttachment (string name)
41 | : base(name) {
42 | }
43 |
44 | /// Must have at least the same length as this attachment's vertices.
45 | public void ComputeWorldVertices (Bone bone, float[] worldVertices) {
46 | float x = bone.skeleton.x + bone.worldX, y = bone.skeleton.y + bone.worldY;
47 | float m00 = bone.m00;
48 | float m01 = bone.m01;
49 | float m10 = bone.m10;
50 | float m11 = bone.m11;
51 | float[] vertices = this.vertices;
52 | for (int i = 0, n = vertices.Length; i < n; i += 2) {
53 | float px = vertices[i];
54 | float py = vertices[i + 1];
55 | worldVertices[i] = px * m00 + py * m01 + x;
56 | worldVertices[i + 1] = px * m10 + py * m11 + y;
57 | }
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/spine-csharp/src/Attachments/MeshAttachment.cs:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Spine Runtimes Software License
3 | * Version 2.1
4 | *
5 | * Copyright (c) 2013, Esoteric Software
6 | * All rights reserved.
7 | *
8 | * You are granted a perpetual, non-exclusive, non-sublicensable and
9 | * non-transferable license to install, execute and perform the Spine Runtimes
10 | * Software (the "Software") solely for internal use. Without the written
11 | * permission of Esoteric Software (typically granted by licensing Spine), you
12 | * may not (a) modify, translate, adapt or otherwise create derivative works,
13 | * improvements of the Software or develop new applications using the Software
14 | * or (b) remove, delete, alter or obscure any trademarks or any copyright,
15 | * trademark, patent or other intellectual property or proprietary rights
16 | * notices on or in the Software, including any copy thereof. Redistributions
17 | * in binary or source form must include this license and terms.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
22 | * EVENT SHALL ESOTERIC SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 | *****************************************************************************/
30 |
31 | using System;
32 |
33 | namespace Spine {
34 | /// Attachment that displays a texture region.
35 | public class MeshAttachment : Attachment {
36 | internal float[] vertices, uvs, regionUVs;
37 | internal int[] triangles;
38 | internal float regionOffsetX, regionOffsetY, regionWidth, regionHeight, regionOriginalWidth, regionOriginalHeight;
39 | internal float r = 1, g = 1, b = 1, a = 1;
40 |
41 | public int HullLength { get; set; }
42 | public float[] Vertices { get { return vertices; } set { vertices = value; } }
43 | public float[] RegionUVs { get { return regionUVs; } set { regionUVs = value; } }
44 | public float[] UVs { get { return uvs; } set { uvs = value; } }
45 | public int[] Triangles { get { return triangles; } set { triangles = value; } }
46 |
47 | public float R { get { return r; } set { r = value; } }
48 | public float G { get { return g; } set { g = value; } }
49 | public float B { get { return b; } set { b = value; } }
50 | public float A { get { return a; } set { a = value; } }
51 |
52 | public String Path { get; set; }
53 | public Object RendererObject { get; set; }
54 | public float RegionU { get; set; }
55 | public float RegionV { get; set; }
56 | public float RegionU2 { get; set; }
57 | public float RegionV2 { get; set; }
58 | public bool RegionRotate { get; set; }
59 | public float RegionOffsetX { get { return regionOffsetX; } set { regionOffsetX = value; } }
60 | public float RegionOffsetY { get { return regionOffsetY; } set { regionOffsetY = value; } } // Pixels stripped from the bottom left, unrotated.
61 | public float RegionWidth { get { return regionWidth; } set { regionWidth = value; } }
62 | public float RegionHeight { get { return regionHeight; } set { regionHeight = value; } } // Unrotated, stripped size.
63 | public float RegionOriginalWidth { get { return regionOriginalWidth; } set { regionOriginalWidth = value; } }
64 | public float RegionOriginalHeight { get { return regionOriginalHeight; } set { regionOriginalHeight = value; } } // Unrotated, unstripped size.
65 |
66 | // Nonessential.
67 | //public int[] Edges { get; set; } //HuaHua Delete nonessential data
68 | //public float Width { get; set; } //HuaHua Delete nonessential data
69 | //public float Height { get; set; } //HuaHua Delete nonessential data
70 |
71 | public MeshAttachment (string name)
72 | : base(name) {
73 | }
74 |
75 | public void UpdateUVs () {
76 | float u = RegionU, v = RegionV, width = RegionU2 - RegionU, height = RegionV2 - RegionV;
77 | float[] regionUVs = this.regionUVs;
78 | if (this.uvs == null || this.uvs.Length != regionUVs.Length) this.uvs = new float[regionUVs.Length];
79 | float[] uvs = this.uvs;
80 | if (RegionRotate) {
81 | for (int i = 0, n = uvs.Length; i < n; i += 2) {
82 | uvs[i] = u + regionUVs[i + 1] * width;
83 | uvs[i + 1] = v + height - regionUVs[i] * height;
84 | }
85 | } else {
86 | for (int i = 0, n = uvs.Length; i < n; i += 2) {
87 | uvs[i] = u + regionUVs[i] * width;
88 | uvs[i + 1] = v + regionUVs[i + 1] * height;
89 | }
90 | }
91 | }
92 |
93 | public void ComputeWorldVertices (Slot slot, float[] worldVertices) {
94 | Bone bone = slot.bone;
95 | float x = bone.skeleton.x + bone.worldX, y = bone.skeleton.y + bone.worldY;
96 | float m00 = bone.m00, m01 = bone.m01, m10 = bone.m10, m11 = bone.m11;
97 | float[] vertices = this.vertices;
98 | int verticesCount = vertices.Length;
99 | if (slot.attachmentVerticesCount == verticesCount) vertices = slot.AttachmentVertices;
100 | for (int i = 0; i < verticesCount; i += 2) {
101 | float vx = vertices[i];
102 | float vy = vertices[i + 1];
103 | worldVertices[i] = vx * m00 + vy * m01 + x;
104 | worldVertices[i + 1] = vx * m10 + vy * m11 + y;
105 | }
106 | }
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/spine-csharp/src/Attachments/RegionAttachment.cs:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Spine Runtimes Software License
3 | * Version 2.1
4 | *
5 | * Copyright (c) 2013, Esoteric Software
6 | * All rights reserved.
7 | *
8 | * You are granted a perpetual, non-exclusive, non-sublicensable and
9 | * non-transferable license to install, execute and perform the Spine Runtimes
10 | * Software (the "Software") solely for internal use. Without the written
11 | * permission of Esoteric Software (typically granted by licensing Spine), you
12 | * may not (a) modify, translate, adapt or otherwise create derivative works,
13 | * improvements of the Software or develop new applications using the Software
14 | * or (b) remove, delete, alter or obscure any trademarks or any copyright,
15 | * trademark, patent or other intellectual property or proprietary rights
16 | * notices on or in the Software, including any copy thereof. Redistributions
17 | * in binary or source form must include this license and terms.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
22 | * EVENT SHALL ESOTERIC SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 | *****************************************************************************/
30 |
31 | using System;
32 |
33 | namespace Spine {
34 | /// Attachment that displays a texture region.
35 | public class RegionAttachment : Attachment {
36 | public const int X1 = 0;
37 | public const int Y1 = 1;
38 | public const int X2 = 2;
39 | public const int Y2 = 3;
40 | public const int X3 = 4;
41 | public const int Y3 = 5;
42 | public const int X4 = 6;
43 | public const int Y4 = 7;
44 |
45 | internal float x, y, rotation, scaleX = 1, scaleY = 1, width, height;
46 | internal float regionOffsetX, regionOffsetY, regionWidth, regionHeight, regionOriginalWidth, regionOriginalHeight;
47 | internal float[] offset = new float[8], uvs = new float[8];
48 | internal float r = 1, g = 1, b = 1, a = 1;
49 |
50 | public float X { get { return x; } set { x = value; } }
51 | public float Y { get { return y; } set { y = value; } }
52 | public float Rotation { get { return rotation; } set { rotation = value; } }
53 | public float ScaleX { get { return scaleX; } set { scaleX = value; } }
54 | public float ScaleY { get { return scaleY; } set { scaleY = value; } }
55 | public float Width { get { return width; } set { width = value; } }
56 | public float Height { get { return height; } set { height = value; } }
57 |
58 | public float R { get { return r; } set { r = value; } }
59 | public float G { get { return g; } set { g = value; } }
60 | public float B { get { return b; } set { b = value; } }
61 | public float A { get { return a; } set { a = value; } }
62 |
63 | public String Path { get; set; }
64 | public Object RendererObject { get; set; }
65 | public float RegionOffsetX { get { return regionOffsetX; } set { regionOffsetX = value; } }
66 | public float RegionOffsetY { get { return regionOffsetY; } set { regionOffsetY = value; } } // Pixels stripped from the bottom left, unrotated.
67 | public float RegionWidth { get { return regionWidth; } set { regionWidth = value; } }
68 | public float RegionHeight { get { return regionHeight; } set { regionHeight = value; } } // Unrotated, stripped size.
69 | public float RegionOriginalWidth { get { return regionOriginalWidth; } set { regionOriginalWidth = value; } }
70 | public float RegionOriginalHeight { get { return regionOriginalHeight; } set { regionOriginalHeight = value; } } // Unrotated, unstripped size.
71 |
72 | public float[] Offset { get { return offset; } }
73 | public float[] UVs { get { return uvs; } }
74 |
75 | public RegionAttachment (string name)
76 | : base(name) {
77 | }
78 |
79 | public void SetUVs (float u, float v, float u2, float v2, bool rotate) {
80 | float[] uvs = this.uvs;
81 | if (rotate) {
82 | uvs[X2] = u;
83 | uvs[Y2] = v2;
84 | uvs[X3] = u;
85 | uvs[Y3] = v;
86 | uvs[X4] = u2;
87 | uvs[Y4] = v;
88 | uvs[X1] = u2;
89 | uvs[Y1] = v2;
90 | } else {
91 | uvs[X1] = u;
92 | uvs[Y1] = v2;
93 | uvs[X2] = u;
94 | uvs[Y2] = v;
95 | uvs[X3] = u2;
96 | uvs[Y3] = v;
97 | uvs[X4] = u2;
98 | uvs[Y4] = v2;
99 | }
100 | }
101 |
102 | public void UpdateOffset () {
103 | float width = this.width;
104 | float height = this.height;
105 | float scaleX = this.scaleX;
106 | float scaleY = this.scaleY;
107 | float regionScaleX = width / regionOriginalWidth * scaleX;
108 | float regionScaleY = height / regionOriginalHeight * scaleY;
109 | float localX = -width / 2 * scaleX + regionOffsetX * regionScaleX;
110 | float localY = -height / 2 * scaleY + regionOffsetY * regionScaleY;
111 | float localX2 = localX + regionWidth * regionScaleX;
112 | float localY2 = localY + regionHeight * regionScaleY;
113 | float radians = rotation * (float)Math.PI / 180;
114 | float cos = (float)Math.Cos(radians);
115 | float sin = (float)Math.Sin(radians);
116 | float x = this.x;
117 | float y = this.y;
118 | float localXCos = localX * cos + x;
119 | float localXSin = localX * sin;
120 | float localYCos = localY * cos + y;
121 | float localYSin = localY * sin;
122 | float localX2Cos = localX2 * cos + x;
123 | float localX2Sin = localX2 * sin;
124 | float localY2Cos = localY2 * cos + y;
125 | float localY2Sin = localY2 * sin;
126 | float[] offset = this.offset;
127 | offset[X1] = localXCos - localYSin;
128 | offset[Y1] = localYCos + localXSin;
129 | offset[X2] = localXCos - localY2Sin;
130 | offset[Y2] = localY2Cos + localXSin;
131 | offset[X3] = localX2Cos - localY2Sin;
132 | offset[Y3] = localY2Cos + localX2Sin;
133 | offset[X4] = localX2Cos - localYSin;
134 | offset[Y4] = localYCos + localX2Sin;
135 | }
136 |
137 | public void ComputeWorldVertices (Bone bone, float[] worldVertices) {
138 | float x = bone.skeleton.x + bone.worldX, y = bone.skeleton.y + bone.worldY;
139 | float m00 = bone.m00, m01 = bone.m01, m10 = bone.m10, m11 = bone.m11;
140 | float[] offset = this.offset;
141 | worldVertices[X1] = offset[X1] * m00 + offset[Y1] * m01 + x;
142 | worldVertices[Y1] = offset[X1] * m10 + offset[Y1] * m11 + y;
143 | worldVertices[X2] = offset[X2] * m00 + offset[Y2] * m01 + x;
144 | worldVertices[Y2] = offset[X2] * m10 + offset[Y2] * m11 + y;
145 | worldVertices[X3] = offset[X3] * m00 + offset[Y3] * m01 + x;
146 | worldVertices[Y3] = offset[X3] * m10 + offset[Y3] * m11 + y;
147 | worldVertices[X4] = offset[X4] * m00 + offset[Y4] * m01 + x;
148 | worldVertices[Y4] = offset[X4] * m10 + offset[Y4] * m11 + y;
149 | }
150 | }
151 | }
152 |
--------------------------------------------------------------------------------
/spine-csharp/src/Attachments/SkinnedMeshAttachment.cs:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Spine Runtimes Software License
3 | * Version 2.1
4 | *
5 | * Copyright (c) 2013, Esoteric Software
6 | * All rights reserved.
7 | *
8 | * You are granted a perpetual, non-exclusive, non-sublicensable and
9 | * non-transferable license to install, execute and perform the Spine Runtimes
10 | * Software (the "Software") solely for internal use. Without the written
11 | * permission of Esoteric Software (typically granted by licensing Spine), you
12 | * may not (a) modify, translate, adapt or otherwise create derivative works,
13 | * improvements of the Software or develop new applications using the Software
14 | * or (b) remove, delete, alter or obscure any trademarks or any copyright,
15 | * trademark, patent or other intellectual property or proprietary rights
16 | * notices on or in the Software, including any copy thereof. Redistributions
17 | * in binary or source form must include this license and terms.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
22 | * EVENT SHALL ESOTERIC SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 | *****************************************************************************/
30 |
31 | using System;
32 | using System.Collections.Generic;
33 |
34 | namespace Spine {
35 | /// Attachment that displays a texture region.
36 | public class SkinnedMeshAttachment : Attachment {
37 | internal int[] bones;
38 | internal float[] weights, uvs, regionUVs;
39 | internal int[] triangles;
40 | internal float regionOffsetX, regionOffsetY, regionWidth, regionHeight, regionOriginalWidth, regionOriginalHeight;
41 | internal float r = 1, g = 1, b = 1, a = 1;
42 |
43 | public int HullLength { get; set; }
44 | public int[] Bones { get { return bones; } set { bones = value; } }
45 | public float[] Weights { get { return weights; } set { weights = value; } }
46 | public float[] RegionUVs { get { return regionUVs; } set { regionUVs = value; } }
47 | public float[] UVs { get { return uvs; } set { uvs = value; } }
48 | public int[] Triangles { get { return triangles; } set { triangles = value; } }
49 |
50 | public float R { get { return r; } set { r = value; } }
51 | public float G { get { return g; } set { g = value; } }
52 | public float B { get { return b; } set { b = value; } }
53 | public float A { get { return a; } set { a = value; } }
54 |
55 | public String Path { get; set; }
56 | public Object RendererObject { get; set; }
57 | public float RegionU { get; set; }
58 | public float RegionV { get; set; }
59 | public float RegionU2 { get; set; }
60 | public float RegionV2 { get; set; }
61 | public bool RegionRotate { get; set; }
62 | public float RegionOffsetX { get { return regionOffsetX; } set { regionOffsetX = value; } }
63 | public float RegionOffsetY { get { return regionOffsetY; } set { regionOffsetY = value; } } // Pixels stripped from the bottom left, unrotated.
64 | public float RegionWidth { get { return regionWidth; } set { regionWidth = value; } }
65 | public float RegionHeight { get { return regionHeight; } set { regionHeight = value; } } // Unrotated, stripped size.
66 | public float RegionOriginalWidth { get { return regionOriginalWidth; } set { regionOriginalWidth = value; } }
67 | public float RegionOriginalHeight { get { return regionOriginalHeight; } set { regionOriginalHeight = value; } } // Unrotated, unstripped size.
68 |
69 | // Nonessential.
70 | //public int[] Edges { get; set; } //HuaHua Delete nonessential data
71 | //public float Width { get; set; } //HuaHua Delete nonessential data
72 | //public float Height { get; set; } //HuaHua Delete nonessential data
73 |
74 | public SkinnedMeshAttachment (string name)
75 | : base(name) {
76 | }
77 |
78 | public void UpdateUVs () {
79 | float u = RegionU, v = RegionV, width = RegionU2 - RegionU, height = RegionV2 - RegionV;
80 | float[] regionUVs = this.regionUVs;
81 | if (this.uvs == null || this.uvs.Length != regionUVs.Length) this.uvs = new float[regionUVs.Length];
82 | float[] uvs = this.uvs;
83 | if (RegionRotate) {
84 | for (int i = 0, n = uvs.Length; i < n; i += 2) {
85 | uvs[i] = u + regionUVs[i + 1] * width;
86 | uvs[i + 1] = v + height - regionUVs[i] * height;
87 | }
88 | } else {
89 | for (int i = 0, n = uvs.Length; i < n; i += 2) {
90 | uvs[i] = u + regionUVs[i] * width;
91 | uvs[i + 1] = v + regionUVs[i + 1] * height;
92 | }
93 | }
94 | }
95 |
96 | public void ComputeWorldVertices (Slot slot, float[] worldVertices) {
97 | Skeleton skeleton = slot.bone.skeleton;
98 | List skeletonBones = skeleton.bones;
99 | float x = skeleton.x, y = skeleton.y;
100 | float[] weights = this.weights;
101 | int[] bones = this.bones;
102 | if (slot.attachmentVerticesCount == 0) {
103 | for (int w = 0, v = 0, b = 0, n = bones.Length; v < n; w += 2) {
104 | float wx = 0, wy = 0;
105 | int nn = bones[v++] + v;
106 | for (; v < nn; v++, b += 3) {
107 | Bone bone = skeletonBones[bones[v]];
108 | float vx = weights[b], vy = weights[b + 1], weight = weights[b + 2];
109 | wx += (vx * bone.m00 + vy * bone.m01 + bone.worldX) * weight;
110 | wy += (vx * bone.m10 + vy * bone.m11 + bone.worldY) * weight;
111 | }
112 | worldVertices[w] = wx + x;
113 | worldVertices[w + 1] = wy + y;
114 | }
115 | } else {
116 | float[] ffd = slot.AttachmentVertices;
117 | for (int w = 0, v = 0, b = 0, f = 0, n = bones.Length; v < n; w += 2) {
118 | float wx = 0, wy = 0;
119 | int nn = bones[v++] + v;
120 | for (; v < nn; v++, b += 3, f += 2) {
121 | Bone bone = skeletonBones[bones[v]];
122 | float vx = weights[b] + ffd[f], vy = weights[b + 1] + ffd[f + 1], weight = weights[b + 2];
123 | wx += (vx * bone.m00 + vy * bone.m01 + bone.worldX) * weight;
124 | wy += (vx * bone.m10 + vy * bone.m11 + bone.worldY) * weight;
125 | }
126 | worldVertices[w] = wx + x;
127 | worldVertices[w + 1] = wy + y;
128 | }
129 | }
130 | }
131 | }
132 | }
133 |
--------------------------------------------------------------------------------
/spine-csharp/src/Bone.cs:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Spine Runtimes Software License
3 | * Version 2.1
4 | *
5 | * Copyright (c) 2013, Esoteric Software
6 | * All rights reserved.
7 | *
8 | * You are granted a perpetual, non-exclusive, non-sublicensable and
9 | * non-transferable license to install, execute and perform the Spine Runtimes
10 | * Software (the "Software") solely for internal use. Without the written
11 | * permission of Esoteric Software (typically granted by licensing Spine), you
12 | * may not (a) modify, translate, adapt or otherwise create derivative works,
13 | * improvements of the Software or develop new applications using the Software
14 | * or (b) remove, delete, alter or obscure any trademarks or any copyright,
15 | * trademark, patent or other intellectual property or proprietary rights
16 | * notices on or in the Software, including any copy thereof. Redistributions
17 | * in binary or source form must include this license and terms.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
22 | * EVENT SHALL ESOTERIC SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 | *****************************************************************************/
30 |
31 | using System;
32 | using System.Collections.Generic;
33 |
34 | namespace Spine {
35 | public class Bone{
36 | static public bool yDown;
37 |
38 | internal BoneData data;
39 | internal Skeleton skeleton;
40 | internal Bone parent;
41 | internal List children = new List();
42 | internal float x, y, rotation, rotationIK, scaleX, scaleY;
43 | internal bool flipX, flipY;
44 | internal float m00, m01, m10, m11;
45 | internal float worldX, worldY, worldRotation, worldScaleX, worldScaleY;
46 | internal bool worldFlipX, worldFlipY;
47 |
48 | public BoneData Data { get { return data; } }
49 | public Skeleton Skeleton { get { return skeleton; } }
50 | public Bone Parent { get { return parent; } }
51 | public List Children { get { return children; } }
52 | public float X { get { return x; } set { x = value; } }
53 | public float Y { get { return y; } set { y = value; } }
54 | /// The forward kinetics rotation.
55 | public float Rotation { get { return rotation; } set { rotation = value; } }
56 | /// The inverse kinetics rotation, as calculated by any IK constraints.
57 | public float RotationIK { get { return rotationIK; } set { rotationIK = value; } }
58 | public float ScaleX { get { return scaleX; } set { scaleX = value; } }
59 | public float ScaleY { get { return scaleY; } set { scaleY = value; } }
60 | public bool FlipX { get { return flipX; } set { flipX = value; } }
61 | public bool FlipY { get { return flipY; } set { flipY = value; } }
62 |
63 | public float M00 { get { return m00; } }
64 | public float M01 { get { return m01; } }
65 | public float M10 { get { return m10; } }
66 | public float M11 { get { return m11; } }
67 | public float WorldX { get { return worldX; } }
68 | public float WorldY { get { return worldY; } }
69 | public float WorldRotation { get { return worldRotation; } }
70 | public float WorldScaleX { get { return worldScaleX; } }
71 | public float WorldScaleY { get { return worldScaleY; } }
72 | public bool WorldFlipX { get { return worldFlipX; } set { worldFlipX = value; } }
73 | public bool WorldFlipY { get { return worldFlipY; } set { worldFlipY = value; } }
74 |
75 | /// May be null.
76 | public Bone (BoneData data, Skeleton skeleton, Bone parent) {
77 | if (data == null) throw new ArgumentNullException("data cannot be null.");
78 | if (skeleton == null) throw new ArgumentNullException("skeleton cannot be null.");
79 | this.data = data;
80 | this.skeleton = skeleton;
81 | this.parent = parent;
82 | SetToSetupPose();
83 | }
84 |
85 | /// Computes the world SRT using the parent bone and the local SRT.
86 | public void UpdateWorldTransform () {
87 | Bone parent = this.parent;
88 | float x = this.x, y = this.y;
89 | if (parent != null) {
90 | worldX = x * parent.m00 + y * parent.m01 + parent.worldX;
91 | worldY = x * parent.m10 + y * parent.m11 + parent.worldY;
92 | if (data.inheritScale) {
93 | worldScaleX = parent.worldScaleX * scaleX;
94 | worldScaleY = parent.worldScaleY * scaleY;
95 | } else {
96 | worldScaleX = scaleX;
97 | worldScaleY = scaleY;
98 | }
99 | worldRotation = data.inheritRotation ? parent.worldRotation + rotationIK : rotationIK;
100 | worldFlipX = parent.worldFlipX != flipX;
101 | worldFlipY = parent.worldFlipY != flipY;
102 | } else {
103 | Skeleton skeleton = this.skeleton;
104 | bool skeletonFlipX = skeleton.flipX, skeletonFlipY = skeleton.flipY;
105 | worldX = skeletonFlipX ? -x : x;
106 | worldY = skeletonFlipY != yDown ? -y : y;
107 | worldScaleX = scaleX;
108 | worldScaleY = scaleY;
109 | worldRotation = rotationIK;
110 | worldFlipX = skeletonFlipX != flipX;
111 | worldFlipY = skeletonFlipY != flipY;
112 | }
113 | float radians = worldRotation * (float)Math.PI / 180;
114 | float cos = (float)Math.Cos(radians);
115 | float sin = (float)Math.Sin(radians);
116 | if (worldFlipX) {
117 | m00 = -cos * worldScaleX;
118 | m01 = sin * worldScaleY;
119 | } else {
120 | m00 = cos * worldScaleX;
121 | m01 = -sin * worldScaleY;
122 | }
123 | if (worldFlipY != yDown) {
124 | m10 = -sin * worldScaleX;
125 | m11 = -cos * worldScaleY;
126 | } else {
127 | m10 = sin * worldScaleX;
128 | m11 = cos * worldScaleY;
129 | }
130 | }
131 |
132 | public void SetToSetupPose () {
133 | BoneData data = this.data;
134 | x = data.x;
135 | y = data.y;
136 | rotation = data.rotation;
137 | rotationIK = rotation;
138 | scaleX = data.scaleX;
139 | scaleY = data.scaleY;
140 | flipX = data.flipX;
141 | flipY = data.flipY;
142 | }
143 |
144 | public void worldToLocal (float worldX, float worldY, out float localX, out float localY) {
145 | float dx = worldX - this.worldX, dy = worldY - this.worldY;
146 | float m00 = this.m00, m10 = this.m10, m01 = this.m01, m11 = this.m11;
147 | if (worldFlipX != (worldFlipY != yDown)) {
148 | m00 = -m00;
149 | m11 = -m11;
150 | }
151 | float invDet = 1 / (m00 * m11 - m01 * m10);
152 | localX = (dx * m00 * invDet - dy * m01 * invDet);
153 | localY = (dy * m11 * invDet - dx * m10 * invDet);
154 | }
155 |
156 | public void localToWorld (float localX, float localY, out float worldX, out float worldY) {
157 | worldX = localX * m00 + localY * m01 + this.worldX;
158 | worldY = localX * m10 + localY * m11 + this.worldY;
159 | }
160 |
161 | override public String ToString () {
162 | return data.name;
163 | }
164 | }
165 | }
166 |
--------------------------------------------------------------------------------
/spine-csharp/src/BoneData.cs:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Spine Runtimes Software License
3 | * Version 2.1
4 | *
5 | * Copyright (c) 2013, Esoteric Software
6 | * All rights reserved.
7 | *
8 | * You are granted a perpetual, non-exclusive, non-sublicensable and
9 | * non-transferable license to install, execute and perform the Spine Runtimes
10 | * Software (the "Software") solely for internal use. Without the written
11 | * permission of Esoteric Software (typically granted by licensing Spine), you
12 | * may not (a) modify, translate, adapt or otherwise create derivative works,
13 | * improvements of the Software or develop new applications using the Software
14 | * or (b) remove, delete, alter or obscure any trademarks or any copyright,
15 | * trademark, patent or other intellectual property or proprietary rights
16 | * notices on or in the Software, including any copy thereof. Redistributions
17 | * in binary or source form must include this license and terms.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
22 | * EVENT SHALL ESOTERIC SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 | *****************************************************************************/
30 |
31 | using System;
32 |
33 | namespace Spine {
34 | public class BoneData {
35 | internal BoneData parent;
36 | internal String name;
37 | internal float length, x, y, rotation, scaleX = 1, scaleY = 1;
38 | internal bool flipX, flipY;
39 | internal bool inheritScale = true, inheritRotation = true;
40 |
41 | /// May be null.
42 | public BoneData Parent { get { return parent; } }
43 | public String Name { get { return name; } }
44 | public float Length { get { return length; } set { length = value; } }
45 | public float X { get { return x; } set { x = value; } }
46 | public float Y { get { return y; } set { y = value; } }
47 | public float Rotation { get { return rotation; } set { rotation = value; } }
48 | public float ScaleX { get { return scaleX; } set { scaleX = value; } }
49 | public float ScaleY { get { return scaleY; } set { scaleY = value; } }
50 | public bool FlipX { get { return flipX; } set { flipX = value; } }
51 | public bool FlipY { get { return flipY; } set { flipY = value; } }
52 | public bool InheritScale { get { return inheritScale; } set { inheritScale = value; } }
53 | public bool InheritRotation { get { return inheritRotation; } set { inheritRotation = value; } }
54 |
55 | /// May be null.
56 | public BoneData (String name, BoneData parent) {
57 | if (name == null) throw new ArgumentNullException("name cannot be null.");
58 | this.name = name;
59 | this.parent = parent;
60 | }
61 |
62 | override public String ToString () {
63 | return name;
64 | }
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/spine-csharp/src/Event.cs:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Spine Runtimes Software License
3 | * Version 2.1
4 | *
5 | * Copyright (c) 2013, Esoteric Software
6 | * All rights reserved.
7 | *
8 | * You are granted a perpetual, non-exclusive, non-sublicensable and
9 | * non-transferable license to install, execute and perform the Spine Runtimes
10 | * Software (the "Software") solely for internal use. Without the written
11 | * permission of Esoteric Software (typically granted by licensing Spine), you
12 | * may not (a) modify, translate, adapt or otherwise create derivative works,
13 | * improvements of the Software or develop new applications using the Software
14 | * or (b) remove, delete, alter or obscure any trademarks or any copyright,
15 | * trademark, patent or other intellectual property or proprietary rights
16 | * notices on or in the Software, including any copy thereof. Redistributions
17 | * in binary or source form must include this license and terms.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
22 | * EVENT SHALL ESOTERIC SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 | *****************************************************************************/
30 |
31 | using System;
32 |
33 | namespace Spine {
34 | public class Event {
35 | public EventData Data { get; private set; }
36 | public int Int { get; set; }
37 | public float Float { get; set; }
38 | public String String { get; set; }
39 |
40 | public Event (EventData data) {
41 | Data = data;
42 | }
43 |
44 | override public String ToString () {
45 | return Data.Name;
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/spine-csharp/src/EventData.cs:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Spine Runtimes Software License
3 | * Version 2.1
4 | *
5 | * Copyright (c) 2013, Esoteric Software
6 | * All rights reserved.
7 | *
8 | * You are granted a perpetual, non-exclusive, non-sublicensable and
9 | * non-transferable license to install, execute and perform the Spine Runtimes
10 | * Software (the "Software") solely for internal use. Without the written
11 | * permission of Esoteric Software (typically granted by licensing Spine), you
12 | * may not (a) modify, translate, adapt or otherwise create derivative works,
13 | * improvements of the Software or develop new applications using the Software
14 | * or (b) remove, delete, alter or obscure any trademarks or any copyright,
15 | * trademark, patent or other intellectual property or proprietary rights
16 | * notices on or in the Software, including any copy thereof. Redistributions
17 | * in binary or source form must include this license and terms.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
22 | * EVENT SHALL ESOTERIC SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 | *****************************************************************************/
30 |
31 | using System;
32 |
33 | namespace Spine {
34 | public class EventData {
35 | internal String name;
36 |
37 | public String Name { get { return name; } }
38 | public int Int { get; set; }
39 | public float Float { get; set; }
40 | public String String { get; set; }
41 |
42 | public EventData (String name) {
43 | if (name == null) throw new ArgumentNullException("name cannot be null.");
44 | this.name = name;
45 | }
46 |
47 | override public String ToString () {
48 | return Name;
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/spine-csharp/src/IkConstraint.cs:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Spine Runtimes Software License
3 | * Version 2.1
4 | *
5 | * Copyright (c) 2013, Esoteric Software
6 | * All rights reserved.
7 | *
8 | * You are granted a perpetual, non-exclusive, non-sublicensable and
9 | * non-transferable license to install, execute and perform the Spine Runtimes
10 | * Software (the "Software") solely for internal use. Without the written
11 | * permission of Esoteric Software (typically granted by licensing Spine), you
12 | * may not (a) modify, translate, adapt or otherwise create derivative works,
13 | * improvements of the Software or develop new applications using the Software
14 | * or (b) remove, delete, alter or obscure any trademarks or any copyright,
15 | * trademark, patent or other intellectual property or proprietary rights
16 | * notices on or in the Software, including any copy thereof. Redistributions
17 | * in binary or source form must include this license and terms.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
22 | * EVENT SHALL ESOTERIC SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 | *****************************************************************************/
30 |
31 | using System;
32 | using System.Collections.Generic;
33 |
34 | namespace Spine {
35 | public class IkConstraint {
36 | private const float radDeg = 180 / (float)Math.PI;
37 |
38 | internal IkConstraintData data;
39 | internal List bones = new List();
40 | internal Bone target;
41 | internal int bendDirection;
42 | internal float mix;
43 |
44 | public IkConstraintData Data { get { return data; } }
45 | public List Bones { get { return bones; } }
46 | public Bone Target { get { return target; } set { target = value; } }
47 | public int BendDirection { get { return bendDirection; } set { bendDirection = value; } }
48 | public float Mix { get { return mix; } set { mix = value; } }
49 |
50 | public IkConstraint (IkConstraintData data, Skeleton skeleton) {
51 | if (data == null) throw new ArgumentNullException("data cannot be null.");
52 | if (skeleton == null) throw new ArgumentNullException("skeleton cannot be null.");
53 | this.data = data;
54 | mix = data.mix;
55 | bendDirection = data.bendDirection;
56 |
57 | bones = new List(data.bones.Count);
58 | foreach (BoneData boneData in data.bones)
59 | bones.Add(skeleton.FindBone(boneData.name));
60 | target = skeleton.FindBone(data.target.name);
61 | }
62 |
63 | public void apply () {
64 | Bone target = this.target;
65 | List bones = this.bones;
66 | switch (bones.Count) {
67 | case 1:
68 | apply(bones[0], target.worldX, target.worldY, mix);
69 | break;
70 | case 2:
71 | apply(bones[0], bones[1], target.worldX, target.worldY, bendDirection, mix);
72 | break;
73 | }
74 | }
75 |
76 | override public String ToString () {
77 | return data.name;
78 | }
79 |
80 | /// Adjusts the bone rotation so the tip is as close to the target position as possible. The target is specified
81 | /// in the world coordinate system.
82 | static public void apply (Bone bone, float targetX, float targetY, float alpha) {
83 | float parentRotation = (!bone.data.inheritRotation || bone.parent == null) ? 0 : bone.parent.worldRotation;
84 | float rotation = bone.rotation;
85 | float rotationIK = (float)Math.Atan2(targetY - bone.worldY, targetX - bone.worldX) * radDeg;
86 | if (bone.worldFlipX != (bone.worldFlipY != Bone.yDown)) rotationIK = -rotationIK;
87 | rotationIK -= parentRotation;
88 | bone.rotationIK = rotation + (rotationIK - rotation) * alpha;
89 | }
90 |
91 | /// Adjusts the parent and child bone rotations so the tip of the child is as close to the target position as
92 | /// possible. The target is specified in the world coordinate system.
93 | /// Any descendant bone of the parent.
94 | static public void apply (Bone parent, Bone child, float targetX, float targetY, int bendDirection, float alpha) {
95 | float childRotation = child.rotation, parentRotation = parent.rotation;
96 | if (alpha == 0) {
97 | child.rotationIK = childRotation;
98 | parent.rotationIK = parentRotation;
99 | return;
100 | }
101 | float positionX, positionY;
102 | Bone parentParent = parent.parent;
103 | if (parentParent != null) {
104 | parentParent.worldToLocal(targetX, targetY, out positionX, out positionY);
105 | targetX = (positionX - parent.x) * parentParent.worldScaleX;
106 | targetY = (positionY - parent.y) * parentParent.worldScaleY;
107 | } else {
108 | targetX -= parent.x;
109 | targetY -= parent.y;
110 | }
111 | if (child.parent == parent) {
112 | positionX = child.x;
113 | positionY = child.y;
114 | } else {
115 | child.parent.localToWorld(child.x, child.y, out positionX, out positionY);
116 | parent.worldToLocal(positionX, positionY, out positionX, out positionY);
117 | }
118 | float childX = positionX * parent.worldScaleX, childY = positionY * parent.worldScaleY;
119 | float offset = (float)Math.Atan2(childY, childX);
120 | float len1 = (float)Math.Sqrt(childX * childX + childY * childY), len2 = child.data.length * child.worldScaleX;
121 | // Based on code by Ryan Juckett with permission: Copyright (c) 2008-2009 Ryan Juckett, http://www.ryanjuckett.com/
122 | float cosDenom = 2 * len1 * len2;
123 | if (cosDenom < 0.0001f) {
124 | child.rotationIK = childRotation + ((float)Math.Atan2(targetY, targetX) * radDeg - parentRotation - childRotation)
125 | * alpha;
126 | return;
127 | }
128 | float cos = (targetX * targetX + targetY * targetY - len1 * len1 - len2 * len2) / cosDenom;
129 | if (cos < -1)
130 | cos = -1;
131 | else if (cos > 1)
132 | cos = 1;
133 | float childAngle = (float)Math.Acos(cos) * bendDirection;
134 | float adjacent = len1 + len2 * cos, opposite = len2 * (float)Math.Sin(childAngle);
135 | float parentAngle = (float)Math.Atan2(targetY * adjacent - targetX * opposite, targetX * adjacent + targetY * opposite);
136 | float rotation = (parentAngle - offset) * radDeg - parentRotation;
137 | if (rotation > 180)
138 | rotation -= 360;
139 | else if (rotation < -180) //
140 | rotation += 360;
141 | parent.rotationIK = parentRotation + rotation * alpha;
142 | rotation = (childAngle + offset) * radDeg - childRotation;
143 | if (rotation > 180)
144 | rotation -= 360;
145 | else if (rotation < -180) //
146 | rotation += 360;
147 | child.rotationIK = childRotation + (rotation + parent.worldRotation - child.parent.worldRotation) * alpha;
148 | }
149 | }
150 | }
151 |
--------------------------------------------------------------------------------
/spine-csharp/src/IkConstraintData.cs:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Spine Runtimes Software License
3 | * Version 2.1
4 | *
5 | * Copyright (c) 2013, Esoteric Software
6 | * All rights reserved.
7 | *
8 | * You are granted a perpetual, non-exclusive, non-sublicensable and
9 | * non-transferable license to install, execute and perform the Spine Runtimes
10 | * Software (the "Software") solely for internal use. Without the written
11 | * permission of Esoteric Software (typically granted by licensing Spine), you
12 | * may not (a) modify, translate, adapt or otherwise create derivative works,
13 | * improvements of the Software or develop new applications using the Software
14 | * or (b) remove, delete, alter or obscure any trademarks or any copyright,
15 | * trademark, patent or other intellectual property or proprietary rights
16 | * notices on or in the Software, including any copy thereof. Redistributions
17 | * in binary or source form must include this license and terms.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
22 | * EVENT SHALL ESOTERIC SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 | *****************************************************************************/
30 |
31 | using System;
32 | using System.Collections.Generic;
33 |
34 | namespace Spine {
35 | public class IkConstraintData {
36 | internal String name;
37 | internal List bones = new List();
38 | internal BoneData target;
39 | internal int bendDirection = 1;
40 | internal float mix = 1;
41 |
42 | public String Name { get { return name; } }
43 | public List Bones { get { return bones; } }
44 | public BoneData Target { get { return target; } set { target = value; } }
45 | public int BendDirection { get { return bendDirection; } set { bendDirection = value; } }
46 | public float Mix { get { return mix; } set { mix = value; } }
47 |
48 | public IkConstraintData (String name) {
49 | if (name == null) throw new ArgumentNullException("name cannot be null.");
50 | this.name = name;
51 | }
52 |
53 | override public String ToString () {
54 | return name;
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/spine-csharp/src/SkeletonBounds.cs:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Spine Runtimes Software License
3 | * Version 2.1
4 | *
5 | * Copyright (c) 2013, Esoteric Software
6 | * All rights reserved.
7 | *
8 | * You are granted a perpetual, non-exclusive, non-sublicensable and
9 | * non-transferable license to install, execute and perform the Spine Runtimes
10 | * Software (the "Software") solely for internal use. Without the written
11 | * permission of Esoteric Software (typically granted by licensing Spine), you
12 | * may not (a) modify, translate, adapt or otherwise create derivative works,
13 | * improvements of the Software or develop new applications using the Software
14 | * or (b) remove, delete, alter or obscure any trademarks or any copyright,
15 | * trademark, patent or other intellectual property or proprietary rights
16 | * notices on or in the Software, including any copy thereof. Redistributions
17 | * in binary or source form must include this license and terms.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
22 | * EVENT SHALL ESOTERIC SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 | *****************************************************************************/
30 |
31 | using System;
32 | using System.Collections.Generic;
33 |
34 | namespace Spine {
35 | public class SkeletonBounds {
36 | private List polygonPool = new List();
37 | private float minX, minY, maxX, maxY;
38 |
39 | public List BoundingBoxes { get; private set; }
40 | public List Polygons { get; private set; }
41 | public float MinX { get { return minX; } set { minX = value; } }
42 | public float MinY { get { return minY; } set { minY = value; } }
43 | public float MaxX { get { return maxX; } set { maxX = value; } }
44 | public float MaxY { get { return maxY; } set { maxY = value; } }
45 | public float Width { get { return maxX - minX; } }
46 | public float Height { get { return maxY - minY; } }
47 |
48 | public SkeletonBounds () {
49 | BoundingBoxes = new List();
50 | Polygons = new List();
51 | }
52 |
53 | public void Update (Skeleton skeleton, bool updateAabb) {
54 | List boundingBoxes = BoundingBoxes;
55 | List polygons = Polygons;
56 | List slots = skeleton.slots;
57 | int slotCount = slots.Count;
58 |
59 | boundingBoxes.Clear();
60 | foreach (Polygon polygon in polygons)
61 | polygonPool.Add(polygon);
62 | polygons.Clear();
63 |
64 | for (int i = 0; i < slotCount; i++) {
65 | Slot slot = slots[i];
66 | BoundingBoxAttachment boundingBox = slot.attachment as BoundingBoxAttachment;
67 | if (boundingBox == null) continue;
68 | boundingBoxes.Add(boundingBox);
69 |
70 | Polygon polygon = null;
71 | int poolCount = polygonPool.Count;
72 | if (poolCount > 0) {
73 | polygon = polygonPool[poolCount - 1];
74 | polygonPool.RemoveAt(poolCount - 1);
75 | } else
76 | polygon = new Polygon();
77 | polygons.Add(polygon);
78 |
79 | int count = boundingBox.Vertices.Length;
80 | polygon.Count = count;
81 | if (polygon.Vertices.Length < count) polygon.Vertices = new float[count];
82 | boundingBox.ComputeWorldVertices(slot.bone, polygon.Vertices);
83 | }
84 |
85 | if (updateAabb) aabbCompute();
86 | }
87 |
88 | private void aabbCompute () {
89 | float minX = int.MaxValue, minY = int.MaxValue, maxX = int.MinValue, maxY = int.MinValue;
90 | List polygons = Polygons;
91 | for (int i = 0, n = polygons.Count; i < n; i++) {
92 | Polygon polygon = polygons[i];
93 | float[] vertices = polygon.Vertices;
94 | for (int ii = 0, nn = polygon.Count; ii < nn; ii += 2) {
95 | float x = vertices[ii];
96 | float y = vertices[ii + 1];
97 | minX = Math.Min(minX, x);
98 | minY = Math.Min(minY, y);
99 | maxX = Math.Max(maxX, x);
100 | maxY = Math.Max(maxY, y);
101 | }
102 | }
103 | this.minX = minX;
104 | this.minY = minY;
105 | this.maxX = maxX;
106 | this.maxY = maxY;
107 | }
108 |
109 |
110 | /// Returns true if the axis aligned bounding box contains the point.
111 | public bool AabbContainsPoint (float x, float y) {
112 | return x >= minX && x <= maxX && y >= minY && y <= maxY;
113 | }
114 |
115 | /// Returns true if the axis aligned bounding box intersects the line segment.
116 | public bool AabbIntersectsSegment (float x1, float y1, float x2, float y2) {
117 | float minX = this.minX;
118 | float minY = this.minY;
119 | float maxX = this.maxX;
120 | float maxY = this.maxY;
121 | if ((x1 <= minX && x2 <= minX) || (y1 <= minY && y2 <= minY) || (x1 >= maxX && x2 >= maxX) || (y1 >= maxY && y2 >= maxY))
122 | return false;
123 | float m = (y2 - y1) / (x2 - x1);
124 | float y = m * (minX - x1) + y1;
125 | if (y > minY && y < maxY) return true;
126 | y = m * (maxX - x1) + y1;
127 | if (y > minY && y < maxY) return true;
128 | float x = (minY - y1) / m + x1;
129 | if (x > minX && x < maxX) return true;
130 | x = (maxY - y1) / m + x1;
131 | if (x > minX && x < maxX) return true;
132 | return false;
133 | }
134 |
135 | /// Returns true if the axis aligned bounding box intersects the axis aligned bounding box of the specified bounds.
136 | public bool AabbIntersectsSkeleton (SkeletonBounds bounds) {
137 | return minX < bounds.maxX && maxX > bounds.minX && minY < bounds.maxY && maxY > bounds.minY;
138 | }
139 |
140 | /// Returns true if the polygon contains the point.
141 | public bool ContainsPoint (Polygon polygon, float x, float y) {
142 | float[] vertices = polygon.Vertices;
143 | int nn = polygon.Count;
144 |
145 | int prevIndex = nn - 2;
146 | bool inside = false;
147 | for (int ii = 0; ii < nn; ii += 2) {
148 | float vertexY = vertices[ii + 1];
149 | float prevY = vertices[prevIndex + 1];
150 | if ((vertexY < y && prevY >= y) || (prevY < y && vertexY >= y)) {
151 | float vertexX = vertices[ii];
152 | if (vertexX + (y - vertexY) / (prevY - vertexY) * (vertices[prevIndex] - vertexX) < x) inside = !inside;
153 | }
154 | prevIndex = ii;
155 | }
156 | return inside;
157 | }
158 |
159 | /// Returns the first bounding box attachment that contains the point, or null. When doing many checks, it is usually more
160 | /// efficient to only call this method if {@link #aabbContainsPoint(float, float)} returns true.
161 | public BoundingBoxAttachment ContainsPoint (float x, float y) {
162 | List polygons = Polygons;
163 | for (int i = 0, n = polygons.Count; i < n; i++)
164 | if (ContainsPoint(polygons[i], x, y)) return BoundingBoxes[i];
165 | return null;
166 | }
167 |
168 | /// Returns the first bounding box attachment that contains the line segment, or null. When doing many checks, it is usually
169 | /// more efficient to only call this method if {@link #aabbIntersectsSegment(float, float, float, float)} returns true.
170 | public BoundingBoxAttachment IntersectsSegment (float x1, float y1, float x2, float y2) {
171 | List polygons = Polygons;
172 | for (int i = 0, n = polygons.Count; i < n; i++)
173 | if (IntersectsSegment(polygons[i], x1, y1, x2, y2)) return BoundingBoxes[i];
174 | return null;
175 | }
176 |
177 | /// Returns true if the polygon contains the line segment.
178 | public bool IntersectsSegment (Polygon polygon, float x1, float y1, float x2, float y2) {
179 | float[] vertices = polygon.Vertices;
180 | int nn = polygon.Count;
181 |
182 | float width12 = x1 - x2, height12 = y1 - y2;
183 | float det1 = x1 * y2 - y1 * x2;
184 | float x3 = vertices[nn - 2], y3 = vertices[nn - 1];
185 | for (int ii = 0; ii < nn; ii += 2) {
186 | float x4 = vertices[ii], y4 = vertices[ii + 1];
187 | float det2 = x3 * y4 - y3 * x4;
188 | float width34 = x3 - x4, height34 = y3 - y4;
189 | float det3 = width12 * height34 - height12 * width34;
190 | float x = (det1 * width34 - width12 * det2) / det3;
191 | if (((x >= x3 && x <= x4) || (x >= x4 && x <= x3)) && ((x >= x1 && x <= x2) || (x >= x2 && x <= x1))) {
192 | float y = (det1 * height34 - height12 * det2) / det3;
193 | if (((y >= y3 && y <= y4) || (y >= y4 && y <= y3)) && ((y >= y1 && y <= y2) || (y >= y2 && y <= y1))) return true;
194 | }
195 | x3 = x4;
196 | y3 = y4;
197 | }
198 | return false;
199 | }
200 |
201 | public Polygon getPolygon (BoundingBoxAttachment attachment) {
202 | int index = BoundingBoxes.IndexOf(attachment);
203 | return index == -1 ? null : Polygons[index];
204 | }
205 | }
206 |
207 | public class Polygon {
208 | public float[] Vertices { get; set; }
209 | public int Count { get; set; }
210 |
211 | public Polygon () {
212 | Vertices = new float[16];
213 | }
214 | }
215 | }
216 |
--------------------------------------------------------------------------------
/spine-csharp/src/SkeletonData.cs:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Spine Runtimes Software License
3 | * Version 2.1
4 | *
5 | * Copyright (c) 2013, Esoteric Software
6 | * All rights reserved.
7 | *
8 | * You are granted a perpetual, non-exclusive, non-sublicensable and
9 | * non-transferable license to install, execute and perform the Spine Runtimes
10 | * Software (the "Software") solely for internal use. Without the written
11 | * permission of Esoteric Software (typically granted by licensing Spine), you
12 | * may not (a) modify, translate, adapt or otherwise create derivative works,
13 | * improvements of the Software or develop new applications using the Software
14 | * or (b) remove, delete, alter or obscure any trademarks or any copyright,
15 | * trademark, patent or other intellectual property or proprietary rights
16 | * notices on or in the Software, including any copy thereof. Redistributions
17 | * in binary or source form must include this license and terms.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
22 | * EVENT SHALL ESOTERIC SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 | *****************************************************************************/
30 |
31 | using System;
32 | using System.Collections.Generic;
33 |
34 | namespace Spine {
35 | public class SkeletonData {
36 | internal String name;
37 | internal List bones = new List();
38 | internal List slots = new List();
39 | internal List skins = new List();
40 | internal Skin defaultSkin;
41 | internal List events = new List();
42 | internal List animations = new List();
43 | internal List ikConstraints = new List();
44 | internal float width, height;
45 | internal String version, hash;//, imagesPath; //HuaHua Delete nonessential data
46 |
47 | public String Name { get { return name; } set { name = value; } }
48 | public List Bones { get { return bones; } } // Ordered parents first.
49 | public List Slots { get { return slots; } } // Setup pose draw order.
50 | public List Skins { get { return skins; } set { skins = value; } }
51 | /// May be null.
52 | public Skin DefaultSkin { get { return defaultSkin; } set { defaultSkin = value; } }
53 | public List Events { get { return events; } set { events = value; } }
54 | public List Animations { get { return animations; } set { animations = value; } }
55 | public List IkConstraints { get { return ikConstraints; } set { ikConstraints = value; } }
56 | public float Width { get { return width; } set { width = value; } }
57 | public float Height { get { return height; } set { height = value; } }
58 | /// The Spine version used to export this data.
59 | public String Version { get { return version; } set { version = value; } }
60 | public String Hash { get { return hash; } set { hash = value; } }
61 |
62 | // --- Bones.
63 |
64 | /// May be null.
65 | public BoneData FindBone (String boneName) {
66 | if (boneName == null) throw new ArgumentNullException("boneName cannot be null.");
67 | List bones = this.bones;
68 | for (int i = 0, n = bones.Count; i < n; i++) {
69 | BoneData bone = bones[i];
70 | if (bone.name == boneName) return bone;
71 | }
72 | return null;
73 | }
74 |
75 | /// -1 if the bone was not found.
76 | public int FindBoneIndex (String boneName) {
77 | if (boneName == null) throw new ArgumentNullException("boneName cannot be null.");
78 | List bones = this.bones;
79 | for (int i = 0, n = bones.Count; i < n; i++)
80 | if (bones[i].name == boneName) return i;
81 | return -1;
82 | }
83 |
84 | // --- Slots.
85 |
86 | /// May be null.
87 | public SlotData FindSlot (String slotName) {
88 | if (slotName == null) throw new ArgumentNullException("slotName cannot be null.");
89 | List slots = this.slots;
90 | for (int i = 0, n = slots.Count; i < n; i++) {
91 | SlotData slot = slots[i];
92 | if (slot.name == slotName) return slot;
93 | }
94 | return null;
95 | }
96 |
97 | /// -1 if the bone was not found.
98 | public int FindSlotIndex (String slotName) {
99 | if (slotName == null) throw new ArgumentNullException("slotName cannot be null.");
100 | List slots = this.slots;
101 | for (int i = 0, n = slots.Count; i < n; i++)
102 | if (slots[i].name == slotName) return i;
103 | return -1;
104 | }
105 |
106 | // --- Skins.
107 |
108 | /// May be null.
109 | public Skin FindSkin (String skinName) {
110 | if (skinName == null) throw new ArgumentNullException("skinName cannot be null.");
111 | foreach (Skin skin in skins)
112 | if (skin.name == skinName) return skin;
113 | return null;
114 | }
115 |
116 | // --- Events.
117 |
118 | /// May be null.
119 | public EventData FindEvent (String eventDataName) {
120 | if (eventDataName == null) throw new ArgumentNullException("eventDataName cannot be null.");
121 | foreach (EventData eventData in events)
122 | if (eventData.name == eventDataName) return eventData;
123 | return null;
124 | }
125 |
126 | // --- Animations.
127 |
128 | /// May be null.
129 | public Animation FindAnimation (String animationName) {
130 | if (animationName == null) throw new ArgumentNullException("animationName cannot be null.");
131 | List animations = this.animations;
132 | for (int i = 0, n = animations.Count; i < n; i++) {
133 | Animation animation = animations[i];
134 | if (animation.name == animationName) return animation;
135 | }
136 | return null;
137 | }
138 |
139 | public Animation FindAnimationByIndex (int animationIndex) {
140 | List animations = this.animations;
141 | if (animationIndex >= animations.Count)
142 | return null;
143 | return animations[animationIndex];
144 | }
145 |
146 | // --- IK constraints.
147 |
148 | /// May be null.
149 | public IkConstraintData FindIkConstraint (String ikConstraintName) {
150 | if (ikConstraintName == null) throw new ArgumentNullException("ikConstraintName cannot be null.");
151 | List ikConstraints = this.ikConstraints;
152 | for (int i = 0, n = ikConstraints.Count; i < n; i++) {
153 | IkConstraintData ikConstraint = ikConstraints[i];
154 | if (ikConstraint.name == ikConstraintName) return ikConstraint;
155 | }
156 | return null;
157 | }
158 |
159 | public string GetAttachName(Attachment attachment)
160 | {
161 | for (int si = 0; si < skins.Count; ++si)
162 | {
163 | var skin = skins[si];
164 | foreach (var entry in skin.Attachments)
165 | {
166 | foreach (var each in entry.Value)
167 | {
168 | if (attachment == each.Value)
169 | {
170 | return each.Key;
171 | }
172 | }
173 | }
174 | }
175 | return null;
176 | }
177 |
178 | public int GetSkinIndex(Attachment attachment)
179 | {
180 | for (int si = 0; si < skins.Count; ++si)
181 | {
182 | var skin = skins[si];
183 | foreach (var entry in skin.Attachments)
184 | {
185 | foreach (var each in entry.Value)
186 | {
187 | if (attachment == each.Value)
188 | {
189 | return si;
190 | }
191 | }
192 | }
193 | }
194 |
195 | return -1;
196 | }
197 |
198 | // ---
199 |
200 | override public String ToString () {
201 | return name ?? base.ToString();
202 | }
203 | }
204 | }
205 |
--------------------------------------------------------------------------------
/spine-csharp/src/Skin.cs:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Spine Runtimes Software License
3 | * Version 2.1
4 | *
5 | * Copyright (c) 2013, Esoteric Software
6 | * All rights reserved.
7 | *
8 | * You are granted a perpetual, non-exclusive, non-sublicensable and
9 | * non-transferable license to install, execute and perform the Spine Runtimes
10 | * Software (the "Software") solely for internal use. Without the written
11 | * permission of Esoteric Software (typically granted by licensing Spine), you
12 | * may not (a) modify, translate, adapt or otherwise create derivative works,
13 | * improvements of the Software or develop new applications using the Software
14 | * or (b) remove, delete, alter or obscure any trademarks or any copyright,
15 | * trademark, patent or other intellectual property or proprietary rights
16 | * notices on or in the Software, including any copy thereof. Redistributions
17 | * in binary or source form must include this license and terms.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
22 | * EVENT SHALL ESOTERIC SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 | *****************************************************************************/
30 |
31 | using System;
32 | using System.Collections.Generic;
33 |
34 | namespace Spine {
35 | /// Stores attachments by slot index and attachment name.
36 | public class Skin {
37 | internal String name;
38 |
39 | // HuaHua. quickly find
40 | private Dictionary> attachments =
41 | new Dictionary>();
42 |
43 | #if UNITY_EDITOR
44 | //HuaHua
45 | internal Dictionary> Attachments
46 | {
47 | get
48 | {
49 | return attachments;
50 | }
51 | }
52 | #endif
53 |
54 | public String Name { get { return name; } }
55 |
56 | public Skin (String name) {
57 | if (name == null) throw new ArgumentNullException("name cannot be null.");
58 | this.name = name;
59 | }
60 |
61 | public void AddAttachment (int slotIndex, String name, Attachment attachment) {
62 | if (attachment == null) throw new ArgumentNullException("attachment cannot be null.");
63 |
64 | if (!attachments.TryGetValue(slotIndex, out Dictionary ats))
65 | {
66 | ats = new Dictionary();
67 | attachments.Add(slotIndex, ats);
68 | }
69 | ats[name] = attachment;
70 | }
71 |
72 | /// May be null.
73 | public Attachment GetAttachment (int slotIndex, String name) {
74 | if (!attachments.TryGetValue(slotIndex, out Dictionary ats))
75 | {
76 | return null;
77 | }
78 |
79 | ats.TryGetValue(name, out Attachment attachment);
80 | return attachment;
81 | }
82 |
83 | public void RemoveAttachment(int slotIndex, string name) {
84 | if (attachments.TryGetValue(slotIndex, out Dictionary ats))
85 | {
86 | ats.Remove(name);
87 | if (ats.Count == 0)
88 | {
89 | attachments.Remove(slotIndex);
90 | }
91 | }
92 | }
93 |
94 | public void RemoveAttachmentsForSlot(int slotIndex)
95 | {
96 | var names = new List();
97 | FindNamesForSlot(slotIndex, names);
98 | foreach (var name in names)
99 | {
100 | RemoveAttachment(slotIndex, name);
101 | }
102 | }
103 |
104 | public void FindNamesForSlot (int slotIndex, List names) {
105 | if (names == null) throw new ArgumentNullException("names cannot be null.");
106 | if (attachments.TryGetValue(slotIndex, out Dictionary ats))
107 | {
108 | foreach(var each in ats)
109 | {
110 | names.Add(each.Key);
111 | }
112 | }
113 | }
114 |
115 | public void FindAttachmentsForSlot (int slotIndex, List attachments) {
116 | if (attachments == null) throw new ArgumentNullException("attachments cannot be null.");
117 | if (this.attachments.TryGetValue(slotIndex, out Dictionary ats))
118 | {
119 | foreach (var each in ats)
120 | {
121 | attachments.Add(each.Value);
122 | }
123 | }
124 | }
125 |
126 | override public String ToString () {
127 | return name;
128 | }
129 |
130 | ///Adds all attachments from the specified skin to this skin.
131 | public void CopySkin(Skin skin)
132 | {
133 | foreach (var entry in skin.attachments)
134 | {
135 | int slotIndex = entry.Key;
136 | foreach(var each in entry.Value)
137 | {
138 | AddAttachment(slotIndex, each.Key, each.Value);
139 | }
140 | }
141 | }
142 |
143 | public void DetachSkin(Skin skin)
144 | {
145 | foreach (var entry in skin.attachments)
146 | {
147 | int slotIndex = entry.Key;
148 | foreach (var each in entry.Value)
149 | {
150 | RemoveAttachment(slotIndex, each.Key);
151 | }
152 | }
153 | }
154 |
155 | // Avoids boxing in the dictionary.
156 | private class AttachmentComparer : IEqualityComparer> {
157 | internal static readonly AttachmentComparer Instance = new AttachmentComparer();
158 |
159 | bool IEqualityComparer>.Equals (KeyValuePair o1, KeyValuePair o2) {
160 | return o1.Key == o2.Key && o1.Value == o2.Value;
161 | }
162 |
163 | int IEqualityComparer>.GetHashCode (KeyValuePair o) {
164 | return o.Key;
165 | }
166 | }
167 | }
168 | }
169 |
--------------------------------------------------------------------------------
/spine-csharp/src/Slot.cs:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Spine Runtimes Software License
3 | * Version 2.1
4 | *
5 | * Copyright (c) 2013, Esoteric Software
6 | * All rights reserved.
7 | *
8 | * You are granted a perpetual, non-exclusive, non-sublicensable and
9 | * non-transferable license to install, execute and perform the Spine Runtimes
10 | * Software (the "Software") solely for internal use. Without the written
11 | * permission of Esoteric Software (typically granted by licensing Spine), you
12 | * may not (a) modify, translate, adapt or otherwise create derivative works,
13 | * improvements of the Software or develop new applications using the Software
14 | * or (b) remove, delete, alter or obscure any trademarks or any copyright,
15 | * trademark, patent or other intellectual property or proprietary rights
16 | * notices on or in the Software, including any copy thereof. Redistributions
17 | * in binary or source form must include this license and terms.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
22 | * EVENT SHALL ESOTERIC SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 | *****************************************************************************/
30 |
31 | using System;
32 |
33 | namespace Spine {
34 | public class Slot {
35 | internal SlotData data;
36 | internal Bone bone;
37 | internal float r, g, b, a;
38 | internal Attachment attachment;
39 | internal float attachmentTime;
40 | internal float[] attachmentVertices = new float[0];
41 | internal int attachmentVerticesCount;
42 |
43 | public SlotData Data { get { return data; } }
44 | public Bone Bone { get { return bone; } }
45 | public Skeleton Skeleton { get { return bone.skeleton; } }
46 | public float R { get { return r; } set { r = value; } }
47 | public float G { get { return g; } set { g = value; } }
48 | public float B { get { return b; } set { b = value; } }
49 | public float A { get { return a; } set { a = value; } }
50 |
51 | /// May be null.
52 | public Attachment Attachment {
53 | get {
54 | return attachment;
55 | }
56 | set {
57 | attachment = value;
58 | attachmentTime = bone.skeleton.time;
59 | attachmentVerticesCount = 0;
60 | }
61 | }
62 |
63 | public float AttachmentTime {
64 | get {
65 | return bone.skeleton.time - attachmentTime;
66 | }
67 | set {
68 | attachmentTime = bone.skeleton.time - value;
69 | }
70 | }
71 |
72 | public float[] AttachmentVertices { get { return attachmentVertices; } set { attachmentVertices = value; } }
73 | public int AttachmentVerticesCount { get { return attachmentVerticesCount; } set { attachmentVerticesCount = value; } }
74 |
75 | public Slot (SlotData data, Bone bone) {
76 | if (data == null) throw new ArgumentNullException("data cannot be null.");
77 | if (bone == null) throw new ArgumentNullException("bone cannot be null.");
78 | this.data = data;
79 | this.bone = bone;
80 | SetToSetupPose();
81 | }
82 |
83 | internal void SetToSetupPose (int slotIndex) {
84 | r = data.r;
85 | g = data.g;
86 | b = data.b;
87 | a = data.a;
88 | Attachment = data.attachmentName == null ? null : bone.skeleton.GetAttachment(slotIndex, data.attachmentName);
89 | }
90 |
91 | public void SetToSetupPose () {
92 | SetToSetupPose(bone.skeleton.data.slots.IndexOf(data));
93 | }
94 |
95 | override public String ToString () {
96 | return data.name;
97 | }
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/spine-csharp/src/SlotData.cs:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Spine Runtimes Software License
3 | * Version 2.1
4 | *
5 | * Copyright (c) 2013, Esoteric Software
6 | * All rights reserved.
7 | *
8 | * You are granted a perpetual, non-exclusive, non-sublicensable and
9 | * non-transferable license to install, execute and perform the Spine Runtimes
10 | * Software (the "Software") solely for internal use. Without the written
11 | * permission of Esoteric Software (typically granted by licensing Spine), you
12 | * may not (a) modify, translate, adapt or otherwise create derivative works,
13 | * improvements of the Software or develop new applications using the Software
14 | * or (b) remove, delete, alter or obscure any trademarks or any copyright,
15 | * trademark, patent or other intellectual property or proprietary rights
16 | * notices on or in the Software, including any copy thereof. Redistributions
17 | * in binary or source form must include this license and terms.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
22 | * EVENT SHALL ESOTERIC SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 | *****************************************************************************/
30 |
31 | using System;
32 |
33 | namespace Spine {
34 | public class SlotData {
35 | internal String name;
36 | internal BoneData boneData;
37 | internal float r = 1, g = 1, b = 1, a = 1;
38 | internal String attachmentName;
39 | internal bool additiveBlending;
40 |
41 | public String Name { get { return name; } }
42 | public BoneData BoneData { get { return boneData; } }
43 | public float R { get { return r; } set { r = value; } }
44 | public float G { get { return g; } set { g = value; } }
45 | public float B { get { return b; } set { b = value; } }
46 | public float A { get { return a; } set { a = value; } }
47 | /// May be null.
48 | public String AttachmentName { get { return attachmentName; } set { attachmentName = value; } }
49 | public bool AdditiveBlending { get { return additiveBlending; } set { additiveBlending = value; } }
50 |
51 | public SlotData (String name, BoneData boneData) {
52 | if (name == null) throw new ArgumentNullException("name cannot be null.");
53 | if (boneData == null) throw new ArgumentNullException("boneData cannot be null.");
54 | this.name = name;
55 | this.boneData = boneData;
56 | }
57 |
58 | override public String ToString () {
59 | return name;
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/spine-unity/AtlasAsset.cs:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Spine Runtimes Software License
3 | * Version 2.1
4 | *
5 | * Copyright (c) 2013, Esoteric Software
6 | * All rights reserved.
7 | *
8 | * You are granted a perpetual, non-exclusive, non-sublicensable and
9 | * non-transferable license to install, execute and perform the Spine Runtimes
10 | * Software (the "Software") solely for internal use. Without the written
11 | * permission of Esoteric Software (typically granted by licensing Spine), you
12 | * may not (a) modify, translate, adapt or otherwise create derivative works,
13 | * improvements of the Software or develop new applications using the Software
14 | * or (b) remove, delete, alter or obscure any trademarks or any copyright,
15 | * trademark, patent or other intellectual property or proprietary rights
16 | * notices on or in the Software, including any copy thereof. Redistributions
17 | * in binary or source form must include this license and terms.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
22 | * EVENT SHALL ESOTERIC SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 | *****************************************************************************/
30 |
31 | using System;
32 | using System.IO;
33 | using UnityEngine;
34 | using Spine;
35 |
36 | /// Loads and stores a Spine atlas and list of materials.
37 | public class AtlasAsset : ScriptableObject {
38 | public TextAsset atlasFile;
39 | public Material[] materials;
40 | private Atlas atlas;
41 |
42 | public void Reset () {
43 | atlas = null;
44 | }
45 |
46 | /// The atlas or null if it could not be loaded.
47 | public Atlas GetAtlas () {
48 | if (atlasFile == null) {
49 | Debug.LogError("Atlas file not set for atlas asset: " + name, this);
50 | Reset();
51 | return null;
52 | }
53 |
54 | if (materials == null || materials.Length == 0) {
55 | Debug.LogError("Materials not set for atlas asset: " + name, this);
56 | Reset();
57 | return null;
58 | }
59 |
60 | if (atlas != null)
61 | return atlas;
62 |
63 | try {
64 | atlas = new Atlas(new StringReader(atlasFile.text), "", new MaterialsTextureLoader(this));
65 | atlas.FlipV();
66 | return atlas;
67 | } catch (Exception ex) {
68 | Debug.LogError("Error reading atlas file for atlas asset: " + name + "\n" + ex.Message + "\n" + ex.StackTrace, this);
69 | return null;
70 | }
71 | }
72 | }
73 |
74 | public class MaterialsTextureLoader : TextureLoader {
75 | AtlasAsset atlasAsset;
76 |
77 | public MaterialsTextureLoader (AtlasAsset atlasAsset) {
78 | this.atlasAsset = atlasAsset;
79 | }
80 |
81 | public void Load (AtlasPage page, String path) {
82 | String name = Path.GetFileNameWithoutExtension(path);
83 | Material material = null;
84 | foreach (Material other in atlasAsset.materials) {
85 | if (other.mainTexture == null) {
86 | Debug.LogError("Material is missing texture: " + other.name, other);
87 | return;
88 | }
89 | if (other.mainTexture.name == name) {
90 | material = other;
91 | break;
92 | }
93 | }
94 | if (material == null) {
95 | Debug.LogError("Material with texture name \"" + name + "\" not found for atlas asset: " + atlasAsset.name, atlasAsset);
96 | return;
97 | }
98 | page.rendererObject = material;
99 |
100 | // Very old atlas files expected the texture's actual size to be used at runtime.
101 | if (page.width == 0 || page.height == 0) {
102 | page.width = material.mainTexture.width;
103 | page.height = material.mainTexture.height;
104 | }
105 | }
106 |
107 | public void Unload (object texture) {
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/spine-unity/AtlasRegionAttacher.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 | using System.Collections;
3 | using Spine;
4 |
5 |
6 | public class AtlasRegionAttacher : MonoBehaviour {
7 |
8 | [System.Serializable]
9 | public class SlotRegionPair {
10 | [SpineSlot]
11 | public string slot;
12 |
13 | [SpineAtlasRegion]
14 | public string region;
15 | }
16 |
17 | public AtlasAsset atlasAsset;
18 | public SlotRegionPair[] attachments;
19 |
20 | Atlas atlas;
21 |
22 | void Awake() {
23 | GetComponent().OnReset += Apply;
24 | }
25 |
26 |
27 | void Apply(SkeletonRenderer skeletonRenderer) {
28 | atlas = atlasAsset.GetAtlas();
29 |
30 | AtlasAttachmentLoader loader = new AtlasAttachmentLoader(atlas);
31 |
32 | float scaleMultiplier = skeletonRenderer.skeletonDataAsset.scale;
33 |
34 | var enumerator = attachments.GetEnumerator();
35 | while (enumerator.MoveNext()) {
36 | var entry = (SlotRegionPair)enumerator.Current;
37 | var regionAttachment = loader.NewRegionAttachment(null, entry.region, entry.region);
38 | regionAttachment.Width = regionAttachment.RegionOriginalWidth * scaleMultiplier;
39 | regionAttachment.Height = regionAttachment.RegionOriginalHeight * scaleMultiplier;
40 |
41 | regionAttachment.SetColor(new Color(1, 1, 1, 1));
42 | regionAttachment.UpdateOffset();
43 |
44 | var slot = skeletonRenderer.skeleton.FindSlot(entry.slot);
45 | slot.Attachment = regionAttachment;
46 | }
47 | }
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/spine-unity/BoneFollower.cs:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Spine Runtimes Software License
3 | * Version 2.1
4 | *
5 | * Copyright (c) 2013, Esoteric Software
6 | * All rights reserved.
7 | *
8 | * You are granted a perpetual, non-exclusive, non-sublicensable and
9 | * non-transferable license to install, execute and perform the Spine Runtimes
10 | * Software (the "Software") solely for internal use. Without the written
11 | * permission of Esoteric Software (typically granted by licensing Spine), you
12 | * may not (a) modify, translate, adapt or otherwise create derivative works,
13 | * improvements of the Software or develop new applications using the Software
14 | * or (b) remove, delete, alter or obscure any trademarks or any copyright,
15 | * trademark, patent or other intellectual property or proprietary rights
16 | * notices on or in the Software, including any copy thereof. Redistributions
17 | * in binary or source form must include this license and terms.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
22 | * EVENT SHALL ESOTERIC SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 | *****************************************************************************/
30 |
31 | using System;
32 | using System.IO;
33 | using System.Collections.Generic;
34 | using UnityEngine;
35 | using Spine;
36 |
37 | /// Sets a GameObject's transform to match a bone on a Spine skeleton.
38 | [ExecuteInEditMode]
39 | [AddComponentMenu("Spine/BoneFollower")]
40 | public class BoneFollower : MonoBehaviour {
41 |
42 | [System.NonSerialized]
43 | public bool
44 | valid;
45 | public SkeletonRenderer skeletonRenderer;
46 | public Bone bone;
47 | public bool followZPosition = true;
48 | public bool followBoneRotation = true;
49 |
50 | public SkeletonRenderer SkeletonRenderer {
51 | get { return skeletonRenderer; }
52 | set {
53 | skeletonRenderer = value;
54 | Reset();
55 | }
56 | }
57 |
58 |
59 | /// If a bone isn't set, boneName is used to find the bone.
60 | public String boneName;
61 | public bool resetOnAwake = true;
62 | protected Transform cachedTransform;
63 | protected Transform skeletonTransform;
64 |
65 | public void HandleResetRenderer (SkeletonRenderer skeletonRenderer) {
66 | Reset();
67 | }
68 |
69 | public void Reset () {
70 | bone = null;
71 | cachedTransform = transform;
72 | valid = skeletonRenderer != null && skeletonRenderer.valid;
73 | if (!valid)
74 | return;
75 | skeletonTransform = skeletonRenderer.transform;
76 |
77 | skeletonRenderer.OnReset -= HandleResetRenderer;
78 | skeletonRenderer.OnReset += HandleResetRenderer;
79 |
80 | if (Application.isEditor)
81 | DoUpdate();
82 | }
83 |
84 | void OnDestroy () {
85 | //cleanup
86 | if (skeletonRenderer != null)
87 | skeletonRenderer.OnReset -= HandleResetRenderer;
88 | }
89 |
90 | public void Awake () {
91 | if (resetOnAwake)
92 | Reset();
93 | }
94 |
95 | void LateUpdate () {
96 | DoUpdate();
97 | }
98 |
99 | public void DoUpdate () {
100 | if (!valid) {
101 | Reset();
102 | return;
103 | }
104 |
105 | if (bone == null) {
106 | if (boneName == null || boneName.Length == 0)
107 | return;
108 | bone = skeletonRenderer.skeleton.FindBone(boneName);
109 | if (bone == null) {
110 | Debug.LogError("Bone not found: " + boneName, this);
111 | return;
112 | } else {
113 |
114 | }
115 | }
116 |
117 | Spine.Skeleton skeleton = skeletonRenderer.skeleton;
118 | float flipRotation = (skeleton.flipX ^ skeleton.flipY) ? -1f : 1f;
119 |
120 | if (cachedTransform.parent == skeletonTransform) {
121 | cachedTransform.localPosition = new Vector3(bone.worldX, bone.worldY, followZPosition ? 0f : cachedTransform.localPosition.z);
122 |
123 | if (followBoneRotation) {
124 | Vector3 rotation = cachedTransform.localRotation.eulerAngles;
125 | cachedTransform.localRotation = Quaternion.Euler(rotation.x, rotation.y, bone.worldRotation * flipRotation);
126 | }
127 |
128 | } else {
129 | Vector3 targetWorldPosition = skeletonTransform.TransformPoint(new Vector3(bone.worldX, bone.worldY, 0f));
130 | if (!followZPosition)
131 | targetWorldPosition.z = cachedTransform.position.z;
132 |
133 | cachedTransform.position = targetWorldPosition;
134 |
135 | if (followBoneRotation) {
136 | Vector3 rotation = skeletonTransform.rotation.eulerAngles;
137 |
138 | cachedTransform.rotation = Quaternion.Euler(rotation.x, rotation.y, skeletonTransform.rotation.eulerAngles.z + (bone.worldRotation * flipRotation));
139 | }
140 | }
141 |
142 | }
143 | }
--------------------------------------------------------------------------------
/spine-unity/CustomSkin.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 | using System.Collections;
3 | using Spine;
4 |
5 | public class CustomSkin : MonoBehaviour {
6 |
7 |
8 | [System.Serializable]
9 | public class SkinPair {
10 | [SpineAttachment(currentSkinOnly: false, returnAttachmentPath: true, dataField: "skinSource")]
11 | public string sourceAttachment;
12 | [SpineSlot]
13 | public string targetSlot;
14 | [SpineAttachment(currentSkinOnly: true, placeholdersOnly: true)]
15 | public string targetAttachment;
16 | }
17 |
18 | public SkeletonDataAsset skinSource;
19 | public SkinPair[] skinning;
20 | public Skin customSkin;
21 |
22 | SkeletonRenderer skeletonRenderer;
23 | void Start() {
24 | skeletonRenderer = GetComponent();
25 | Skeleton skeleton = skeletonRenderer.skeleton;
26 |
27 | customSkin = new Skin("CustomSkin");
28 |
29 | foreach (var pair in skinning) {
30 | var attachment = SpineAttachment.GetAttachment(pair.sourceAttachment, skinSource);
31 | customSkin.AddAttachment(skeleton.FindSlotIndex(pair.targetSlot), pair.targetAttachment, attachment);
32 | }
33 |
34 | skeleton.SetSkin(customSkin);
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/spine-unity/Editor/AtlasAssetInspector.cs:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Spine Runtimes Software License
3 | * Version 2.1
4 | *
5 | * Copyright (c) 2013, Esoteric Software
6 | * All rights reserved.
7 | *
8 | * You are granted a perpetual, non-exclusive, non-sublicensable and
9 | * non-transferable license to install, execute and perform the Spine Runtimes
10 | * Software (the "Software") solely for internal use. Without the written
11 | * permission of Esoteric Software (typically granted by licensing Spine), you
12 | * may not (a) modify, translate, adapt or otherwise create derivative works,
13 | * improvements of the Software or develop new applications using the Software
14 | * or (b) remove, delete, alter or obscure any trademarks or any copyright,
15 | * trademark, patent or other intellectual property or proprietary rights
16 | * notices on or in the Software, including any copy thereof. Redistributions
17 | * in binary or source form must include this license and terms.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
22 | * EVENT SHALL ESOTERIC SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 | *****************************************************************************/
30 | using System;
31 | using System.Collections;
32 | using System.Collections.Generic;
33 | using System.Linq;
34 | using System.Reflection;
35 | using UnityEditor;
36 | using UnityEngine;
37 | using Spine;
38 |
39 |
40 | [CustomEditor(typeof(AtlasAsset))]
41 | public class AtlasAssetInspector : Editor {
42 | private SerializedProperty atlasFile, materials;
43 |
44 | void OnEnable () {
45 | SpineEditorUtilities.ConfirmInitialization();
46 | atlasFile = serializedObject.FindProperty("atlasFile");
47 | materials = serializedObject.FindProperty("materials");
48 | }
49 |
50 | override public void OnInspectorGUI () {
51 | serializedObject.Update();
52 | AtlasAsset asset = (AtlasAsset)target;
53 |
54 | EditorGUI.BeginChangeCheck();
55 | EditorGUILayout.PropertyField(atlasFile);
56 | EditorGUILayout.PropertyField(materials, true);
57 | if (EditorGUI.EndChangeCheck())
58 | serializedObject.ApplyModifiedProperties();
59 |
60 | if (materials.arraySize == 0) {
61 | EditorGUILayout.LabelField(new GUIContent("Error: Missing materials", SpineEditorUtilities.Icons.warning));
62 | return;
63 | }
64 |
65 | for (int i = 0; i < materials.arraySize; i++) {
66 | SerializedProperty prop = materials.GetArrayElementAtIndex(i);
67 | Material mat = (Material)prop.objectReferenceValue;
68 | if (mat == null) {
69 | EditorGUILayout.LabelField(new GUIContent("Error: Materials cannot be null", SpineEditorUtilities.Icons.warning));
70 | return;
71 | }
72 | }
73 |
74 |
75 |
76 | if (atlasFile.objectReferenceValue != null) {
77 | Atlas atlas = asset.GetAtlas();
78 | FieldInfo field = typeof(Atlas).GetField("regions", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.NonPublic);
79 | List regions = (List)field.GetValue(atlas);
80 | EditorGUILayout.LabelField("Regions");
81 | EditorGUI.indentLevel++;
82 | for (int i = 0; i < regions.Count; i++) {
83 | EditorGUILayout.LabelField(regions[i].name);
84 | }
85 | EditorGUI.indentLevel--;
86 | }
87 |
88 |
89 | if (serializedObject.ApplyModifiedProperties() ||
90 | (UnityEngine.Event.current.type == EventType.ValidateCommand && UnityEngine.Event.current.commandName == "UndoRedoPerformed")
91 | ) {
92 | asset.Reset();
93 | }
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/spine-unity/Editor/BoneFollowerInspector.cs:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Spine Runtimes Software License
3 | * Version 2.1
4 | *
5 | * Copyright (c) 2013, Esoteric Software
6 | * All rights reserved.
7 | *
8 | * You are granted a perpetual, non-exclusive, non-sublicensable and
9 | * non-transferable license to install, execute and perform the Spine Runtimes
10 | * Software (the "Software") solely for internal use. Without the written
11 | * permission of Esoteric Software (typically granted by licensing Spine), you
12 | * may not (a) modify, translate, adapt or otherwise create derivative works,
13 | * improvements of the Software or develop new applications using the Software
14 | * or (b) remove, delete, alter or obscure any trademarks or any copyright,
15 | * trademark, patent or other intellectual property or proprietary rights
16 | * notices on or in the Software, including any copy thereof. Redistributions
17 | * in binary or source form must include this license and terms.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
22 | * EVENT SHALL ESOTERIC SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 | *****************************************************************************/
30 | using System;
31 | using UnityEditor;
32 | using UnityEngine;
33 |
34 | [CustomEditor(typeof(BoneFollower))]
35 | public class BoneFollowerInspector : Editor {
36 | private SerializedProperty boneName, skeletonRenderer, followZPosition, followBoneRotation;
37 | BoneFollower component;
38 |
39 | void OnEnable () {
40 | skeletonRenderer = serializedObject.FindProperty("skeletonRenderer");
41 | boneName = serializedObject.FindProperty("boneName");
42 | followBoneRotation = serializedObject.FindProperty("followBoneRotation");
43 | followZPosition = serializedObject.FindProperty("followZPosition");
44 | component = (BoneFollower)target;
45 | ForceReload();
46 | }
47 |
48 | void FindRenderer () {
49 | if (skeletonRenderer.objectReferenceValue == null) {
50 | SkeletonRenderer parentRenderer = SkeletonUtility.GetInParent(component.transform);
51 |
52 | if (parentRenderer != null) {
53 | skeletonRenderer.objectReferenceValue = (UnityEngine.Object)parentRenderer;
54 | }
55 |
56 | }
57 | }
58 |
59 | void ForceReload () {
60 | if (component.skeletonRenderer != null) {
61 | if (component.skeletonRenderer.valid == false)
62 | component.skeletonRenderer.Reset();
63 | }
64 | }
65 |
66 | override public void OnInspectorGUI () {
67 | serializedObject.Update();
68 |
69 | FindRenderer();
70 |
71 | EditorGUILayout.PropertyField(skeletonRenderer);
72 |
73 | if (component.valid) {
74 | String[] bones = new String[1];
75 | try {
76 | bones = new String[component.skeletonRenderer.skeleton.Data.Bones.Count + 1];
77 | } catch {
78 |
79 | }
80 |
81 | bones[0] = "";
82 | for (int i = 0; i < bones.Length - 1; i++)
83 | bones[i + 1] = component.skeletonRenderer.skeleton.Data.Bones[i].Name;
84 | Array.Sort(bones);
85 | int boneIndex = Math.Max(0, Array.IndexOf(bones, boneName.stringValue));
86 |
87 | EditorGUILayout.BeginHorizontal();
88 | EditorGUILayout.LabelField("Bone");
89 | EditorGUIUtility.LookLikeControls();
90 | boneIndex = EditorGUILayout.Popup(boneIndex, bones);
91 | EditorGUILayout.EndHorizontal();
92 |
93 | boneName.stringValue = boneIndex == 0 ? null : bones[boneIndex];
94 | EditorGUILayout.PropertyField(followBoneRotation);
95 | EditorGUILayout.PropertyField(followZPosition);
96 | } else {
97 | GUILayout.Label("INVALID");
98 | }
99 |
100 | if (serializedObject.ApplyModifiedProperties() ||
101 | (Event.current.type == EventType.ValidateCommand && Event.current.commandName == "UndoRedoPerformed")
102 | ) {
103 | component.Reset();
104 | }
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/spine-unity/Editor/GUI/icon-animation.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/506638093/spine-optimize/108ef88947039b943a4886215750672fe9e45ff7/spine-unity/Editor/GUI/icon-animation.png
--------------------------------------------------------------------------------
/spine-unity/Editor/GUI/icon-animationRoot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/506638093/spine-optimize/108ef88947039b943a4886215750672fe9e45ff7/spine-unity/Editor/GUI/icon-animationRoot.png
--------------------------------------------------------------------------------
/spine-unity/Editor/GUI/icon-bone.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/506638093/spine-optimize/108ef88947039b943a4886215750672fe9e45ff7/spine-unity/Editor/GUI/icon-bone.png
--------------------------------------------------------------------------------
/spine-unity/Editor/GUI/icon-boneNib.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/506638093/spine-optimize/108ef88947039b943a4886215750672fe9e45ff7/spine-unity/Editor/GUI/icon-boneNib.png
--------------------------------------------------------------------------------
/spine-unity/Editor/GUI/icon-boundingBox.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/506638093/spine-optimize/108ef88947039b943a4886215750672fe9e45ff7/spine-unity/Editor/GUI/icon-boundingBox.png
--------------------------------------------------------------------------------
/spine-unity/Editor/GUI/icon-constraintNib.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/506638093/spine-optimize/108ef88947039b943a4886215750672fe9e45ff7/spine-unity/Editor/GUI/icon-constraintNib.png
--------------------------------------------------------------------------------
/spine-unity/Editor/GUI/icon-event.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/506638093/spine-optimize/108ef88947039b943a4886215750672fe9e45ff7/spine-unity/Editor/GUI/icon-event.png
--------------------------------------------------------------------------------
/spine-unity/Editor/GUI/icon-hingeChain.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/506638093/spine-optimize/108ef88947039b943a4886215750672fe9e45ff7/spine-unity/Editor/GUI/icon-hingeChain.png
--------------------------------------------------------------------------------
/spine-unity/Editor/GUI/icon-image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/506638093/spine-optimize/108ef88947039b943a4886215750672fe9e45ff7/spine-unity/Editor/GUI/icon-image.png
--------------------------------------------------------------------------------
/spine-unity/Editor/GUI/icon-mesh.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/506638093/spine-optimize/108ef88947039b943a4886215750672fe9e45ff7/spine-unity/Editor/GUI/icon-mesh.png
--------------------------------------------------------------------------------
/spine-unity/Editor/GUI/icon-null.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/506638093/spine-optimize/108ef88947039b943a4886215750672fe9e45ff7/spine-unity/Editor/GUI/icon-null.png
--------------------------------------------------------------------------------
/spine-unity/Editor/GUI/icon-poseBones.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/506638093/spine-optimize/108ef88947039b943a4886215750672fe9e45ff7/spine-unity/Editor/GUI/icon-poseBones.png
--------------------------------------------------------------------------------
/spine-unity/Editor/GUI/icon-skeleton.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/506638093/spine-optimize/108ef88947039b943a4886215750672fe9e45ff7/spine-unity/Editor/GUI/icon-skeleton.png
--------------------------------------------------------------------------------
/spine-unity/Editor/GUI/icon-skeletonUtility.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/506638093/spine-optimize/108ef88947039b943a4886215750672fe9e45ff7/spine-unity/Editor/GUI/icon-skeletonUtility.png
--------------------------------------------------------------------------------
/spine-unity/Editor/GUI/icon-skin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/506638093/spine-optimize/108ef88947039b943a4886215750672fe9e45ff7/spine-unity/Editor/GUI/icon-skin.png
--------------------------------------------------------------------------------
/spine-unity/Editor/GUI/icon-skinPlaceholder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/506638093/spine-optimize/108ef88947039b943a4886215750672fe9e45ff7/spine-unity/Editor/GUI/icon-skinPlaceholder.png
--------------------------------------------------------------------------------
/spine-unity/Editor/GUI/icon-skinsRoot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/506638093/spine-optimize/108ef88947039b943a4886215750672fe9e45ff7/spine-unity/Editor/GUI/icon-skinsRoot.png
--------------------------------------------------------------------------------
/spine-unity/Editor/GUI/icon-slot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/506638093/spine-optimize/108ef88947039b943a4886215750672fe9e45ff7/spine-unity/Editor/GUI/icon-slot.png
--------------------------------------------------------------------------------
/spine-unity/Editor/GUI/icon-slotRoot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/506638093/spine-optimize/108ef88947039b943a4886215750672fe9e45ff7/spine-unity/Editor/GUI/icon-slotRoot.png
--------------------------------------------------------------------------------
/spine-unity/Editor/GUI/icon-spine.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/506638093/spine-optimize/108ef88947039b943a4886215750672fe9e45ff7/spine-unity/Editor/GUI/icon-spine.png
--------------------------------------------------------------------------------
/spine-unity/Editor/GUI/icon-subMeshRenderer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/506638093/spine-optimize/108ef88947039b943a4886215750672fe9e45ff7/spine-unity/Editor/GUI/icon-subMeshRenderer.png
--------------------------------------------------------------------------------
/spine-unity/Editor/GUI/icon-warning.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/506638093/spine-optimize/108ef88947039b943a4886215750672fe9e45ff7/spine-unity/Editor/GUI/icon-warning.png
--------------------------------------------------------------------------------
/spine-unity/Editor/GUI/icon-weights.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/506638093/spine-optimize/108ef88947039b943a4886215750672fe9e45ff7/spine-unity/Editor/GUI/icon-weights.png
--------------------------------------------------------------------------------
/spine-unity/Editor/Menus.cs:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Spine Runtimes Software License
3 | * Version 2.1
4 | *
5 | * Copyright (c) 2013, Esoteric Software
6 | * All rights reserved.
7 | *
8 | * You are granted a perpetual, non-exclusive, non-sublicensable and
9 | * non-transferable license to install, execute and perform the Spine Runtimes
10 | * Software (the "Software") solely for internal use. Without the written
11 | * permission of Esoteric Software (typically granted by licensing Spine), you
12 | * may not (a) modify, translate, adapt or otherwise create derivative works,
13 | * improvements of the Software or develop new applications using the Software
14 | * or (b) remove, delete, alter or obscure any trademarks or any copyright,
15 | * trademark, patent or other intellectual property or proprietary rights
16 | * notices on or in the Software, including any copy thereof. Redistributions
17 | * in binary or source form must include this license and terms.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
22 | * EVENT SHALL ESOTERIC SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 | *****************************************************************************/
30 | using System;
31 | using System.IO;
32 | using UnityEditor;
33 | using UnityEngine;
34 | using Spine;
35 |
36 | public class Menus {
37 | [MenuItem("Assets/Create/Spine Atlas")]
38 | static public void CreateAtlas () {
39 | CreateAsset("New Atlas");
40 | }
41 |
42 | [MenuItem("Assets/Create/Spine SkeletonData")]
43 | static public void CreateSkeletonData () {
44 | CreateAsset("New SkeletonData");
45 | }
46 |
47 | static private void CreateAsset (String name) where T : ScriptableObject {
48 | var dir = "Assets/";
49 | var selected = Selection.activeObject;
50 | if (selected != null) {
51 | var assetDir = AssetDatabase.GetAssetPath(selected.GetInstanceID());
52 | if (assetDir.Length > 0 && Directory.Exists(assetDir))
53 | dir = assetDir + "/";
54 | }
55 | ScriptableObject asset = ScriptableObject.CreateInstance();
56 | AssetDatabase.CreateAsset(asset, dir + name + ".asset");
57 | AssetDatabase.SaveAssets();
58 | EditorUtility.FocusProjectWindow();
59 | Selection.activeObject = asset;
60 | }
61 |
62 | [MenuItem("GameObject/Create Other/Spine SkeletonRenderer")]
63 | static public void CreateSkeletonRendererGameObject () {
64 | GameObject gameObject = new GameObject("New SkeletonRenderer", typeof(SkeletonRenderer));
65 | EditorUtility.FocusProjectWindow();
66 | Selection.activeObject = gameObject;
67 | }
68 |
69 | [MenuItem("GameObject/Create Other/Spine SkeletonAnimation")]
70 | static public void CreateSkeletonAnimationGameObject () {
71 | GameObject gameObject = new GameObject("New SkeletonAnimation", typeof(SkeletonAnimation));
72 | EditorUtility.FocusProjectWindow();
73 | Selection.activeObject = gameObject;
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/spine-unity/Editor/SkeletonAnimationInspector.cs:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Spine Runtimes Software License
3 | * Version 2.1
4 | *
5 | * Copyright (c) 2013, Esoteric Software
6 | * All rights reserved.
7 | *
8 | * You are granted a perpetual, non-exclusive, non-sublicensable and
9 | * non-transferable license to install, execute and perform the Spine Runtimes
10 | * Software (the "Software") solely for internal use. Without the written
11 | * permission of Esoteric Software (typically granted by licensing Spine), you
12 | * may not (a) modify, translate, adapt or otherwise create derivative works,
13 | * improvements of the Software or develop new applications using the Software
14 | * or (b) remove, delete, alter or obscure any trademarks or any copyright,
15 | * trademark, patent or other intellectual property or proprietary rights
16 | * notices on or in the Software, including any copy thereof. Redistributions
17 | * in binary or source form must include this license and terms.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
22 | * EVENT SHALL ESOTERIC SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 | *****************************************************************************/
30 | using System;
31 | using UnityEditor;
32 | using UnityEngine;
33 | using Spine;
34 |
35 | [CustomEditor(typeof(SkeletonAnimation))]
36 | public class SkeletonAnimationInspector : SkeletonRendererInspector {
37 | protected SerializedProperty animationName, loop, timeScale;
38 | protected bool isPrefab;
39 |
40 | protected override void OnEnable () {
41 | base.OnEnable();
42 | animationName = serializedObject.FindProperty("_animationName");
43 | loop = serializedObject.FindProperty("loop");
44 | timeScale = serializedObject.FindProperty("timeScale");
45 |
46 | if (PrefabUtility.GetPrefabType(this.target) == PrefabType.Prefab)
47 | isPrefab = true;
48 |
49 |
50 | }
51 |
52 | protected override void gui () {
53 | base.gui();
54 |
55 | SkeletonAnimation component = (SkeletonAnimation)target;
56 | if (!component.valid)
57 | return;
58 |
59 | //catch case where SetAnimation was used to set track 0 without using AnimationName
60 | if (Application.isPlaying) {
61 | TrackEntry currentState = component.state.GetCurrent(0);
62 | if (currentState != null) {
63 | if (component.AnimationName != animationName.stringValue) {
64 | animationName.stringValue = currentState.Animation.Name;
65 | }
66 | }
67 | }
68 |
69 | EditorGUILayout.Space();
70 |
71 | //TODO: Refactor this to use GenericMenu and callbacks to avoid interfering with control by other behaviours.
72 | // Animation name.
73 | {
74 | String[] animations = new String[component.skeleton.Data.Animations.Count + 1];
75 | animations[0] = "";
76 | int animationIndex = 0;
77 | for (int i = 0; i < animations.Length - 1; i++) {
78 | String name = component.skeleton.Data.Animations[i].Name;
79 | animations[i + 1] = name;
80 | if (name == animationName.stringValue)
81 | animationIndex = i + 1;
82 | }
83 |
84 | animationIndex = EditorGUILayout.Popup("Animation", animationIndex, animations);
85 | String selectedAnimationName = animationIndex == 0 ? null : animations[animationIndex];
86 | if (component.AnimationName != selectedAnimationName) {
87 | component.AnimationName = selectedAnimationName;
88 | animationName.stringValue = selectedAnimationName;
89 | }
90 |
91 | }
92 |
93 | EditorGUILayout.PropertyField(loop);
94 | EditorGUILayout.PropertyField(timeScale);
95 | component.timeScale = Math.Max(component.timeScale, 0);
96 |
97 | EditorGUILayout.Space();
98 |
99 | if (!isPrefab) {
100 | if (component.GetComponent() == null) {
101 | if (GUILayout.Button(new GUIContent("Add Skeleton Utility", SpineEditorUtilities.Icons.skeletonUtility), GUILayout.Height(30))) {
102 | component.gameObject.AddComponent();
103 | }
104 | }
105 | }
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/spine-unity/Editor/SkeletonAnimatorInspector.cs:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Spine Runtimes Software License
3 | * Version 2.1
4 | *
5 | * Copyright (c) 2013, Esoteric Software
6 | * All rights reserved.
7 | *
8 | * You are granted a perpetual, non-exclusive, non-sublicensable and
9 | * non-transferable license to install, execute and perform the Spine Runtimes
10 | * Software (the "Software") solely for internal use. Without the written
11 | * permission of Esoteric Software (typically granted by licensing Spine), you
12 | * may not (a) modify, translate, adapt or otherwise create derivative works,
13 | * improvements of the Software or develop new applications using the Software
14 | * or (b) remove, delete, alter or obscure any trademarks or any copyright,
15 | * trademark, patent or other intellectual property or proprietary rights
16 | * notices on or in the Software, including any copy thereof. Redistributions
17 | * in binary or source form must include this license and terms.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
22 | * EVENT SHALL ESOTERIC SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 | *****************************************************************************/
30 |
31 | /*****************************************************************************
32 | * SkeletonAnimatorInspector created by Mitch Thompson
33 | * Full irrevocable rights and permissions granted to Esoteric Software
34 | *****************************************************************************/
35 | using System;
36 | using UnityEditor;
37 | using UnityEngine;
38 | using Spine;
39 |
40 | [CustomEditor(typeof(SkeletonAnimator))]
41 | public class SkeletonAnimatorInspector : SkeletonRendererInspector {
42 | protected SerializedProperty layerMixModes;
43 | protected bool isPrefab;
44 | protected override void OnEnable () {
45 | base.OnEnable();
46 | layerMixModes = serializedObject.FindProperty("layerMixModes");
47 |
48 | if (PrefabUtility.GetPrefabType(this.target) == PrefabType.Prefab)
49 | isPrefab = true;
50 | }
51 |
52 | protected override void gui () {
53 | base.gui();
54 |
55 | EditorGUILayout.PropertyField(layerMixModes, true);
56 |
57 | SkeletonAnimator component = (SkeletonAnimator)target;
58 | if (!component.valid)
59 | return;
60 |
61 | EditorGUILayout.Space();
62 |
63 | if (!isPrefab) {
64 | if (component.GetComponent() == null) {
65 | if (GUILayout.Button(new GUIContent("Add Skeleton Utility", SpineEditorUtilities.Icons.skeletonUtility), GUILayout.Height(30))) {
66 | component.gameObject.AddComponent();
67 | }
68 | }
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/spine-unity/Editor/SkeletonRendererInspector.cs:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Spine Runtimes Software License
3 | * Version 2.1
4 | *
5 | * Copyright (c) 2013, Esoteric Software
6 | * All rights reserved.
7 | *
8 | * You are granted a perpetual, non-exclusive, non-sublicensable and
9 | * non-transferable license to install, execute and perform the Spine Runtimes
10 | * Software (the "Software") solely for internal use. Without the written
11 | * permission of Esoteric Software (typically granted by licensing Spine), you
12 | * may not (a) modify, translate, adapt or otherwise create derivative works,
13 | * improvements of the Software or develop new applications using the Software
14 | * or (b) remove, delete, alter or obscure any trademarks or any copyright,
15 | * trademark, patent or other intellectual property or proprietary rights
16 | * notices on or in the Software, including any copy thereof. Redistributions
17 | * in binary or source form must include this license and terms.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
22 | * EVENT SHALL ESOTERIC SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 | *****************************************************************************/
30 | using System;
31 | using System.Reflection;
32 | using UnityEditor;
33 | using UnityEngine;
34 |
35 | [CustomEditor(typeof(SkeletonRenderer))]
36 | public class SkeletonRendererInspector : Editor {
37 | protected static bool advancedFoldout;
38 |
39 | protected SerializedProperty skeletonDataAsset, initialSkinName, normals, tangents, meshes, immutableTriangles, submeshSeparators, front;
40 |
41 | private static MethodInfo EditorGUILayoutSortingLayerField;
42 | protected SerializedObject rendererSerializedObject;
43 | protected SerializedProperty sortingLayerIDProperty;
44 |
45 | protected virtual void OnEnable () {
46 | SpineEditorUtilities.ConfirmInitialization();
47 | skeletonDataAsset = serializedObject.FindProperty("skeletonDataAsset");
48 | initialSkinName = serializedObject.FindProperty("initialSkinName");
49 | normals = serializedObject.FindProperty("calculateNormals");
50 | tangents = serializedObject.FindProperty("calculateTangents");
51 | meshes = serializedObject.FindProperty("renderMeshes");
52 | immutableTriangles = serializedObject.FindProperty("immutableTriangles");
53 | submeshSeparators = serializedObject.FindProperty("submeshSeparators");
54 | front = serializedObject.FindProperty("frontFacing");
55 |
56 | if(EditorGUILayoutSortingLayerField == null)
57 | EditorGUILayoutSortingLayerField = typeof(EditorGUILayout).GetMethod("SortingLayerField", BindingFlags.Static | BindingFlags.NonPublic, null, new Type[] { typeof(GUIContent), typeof(SerializedProperty), typeof(GUIStyle) }, null);
58 |
59 | rendererSerializedObject = new SerializedObject(((SkeletonRenderer)target).GetComponent());
60 | sortingLayerIDProperty = rendererSerializedObject.FindProperty("m_SortingLayerID");
61 | }
62 |
63 | protected virtual void gui () {
64 | SkeletonRenderer component = (SkeletonRenderer)target;
65 | EditorGUILayout.BeginHorizontal();
66 | EditorGUILayout.PropertyField(skeletonDataAsset);
67 | float reloadWidth = GUI.skin.label.CalcSize(new GUIContent("Reload")).x + 20;
68 | if (GUILayout.Button("Reload", GUILayout.Width(reloadWidth))) {
69 | if (component.skeletonDataAsset != null) {
70 | foreach (AtlasAsset aa in component.skeletonDataAsset.atlasAssets) {
71 | if (aa != null)
72 | aa.Reset();
73 | }
74 |
75 | component.skeletonDataAsset.Reset();
76 | }
77 | component.Reset();
78 | }
79 | EditorGUILayout.EndHorizontal();
80 |
81 | if (!component.valid) {
82 | component.Reset();
83 | component.LateUpdate();
84 | if (!component.valid)
85 | return;
86 | }
87 |
88 | // Initial skin name.
89 | {
90 | String[] skins = new String[component.skeleton.Data.Skins.Count];
91 | int skinIndex = 0;
92 | for (int i = 0; i < skins.Length; i++) {
93 | String name = component.skeleton.Data.Skins[i].Name;
94 | skins[i] = name;
95 | if (name == initialSkinName.stringValue)
96 | skinIndex = i;
97 | }
98 |
99 | skinIndex = EditorGUILayout.Popup("Initial Skin", skinIndex, skins);
100 | initialSkinName.stringValue = skins[skinIndex];
101 | }
102 |
103 | EditorGUILayout.Space();
104 |
105 | // Sorting Layers
106 | {
107 | var renderer = component.GetComponent();
108 | if(renderer != null) {
109 | EditorGUI.BeginChangeCheck();
110 |
111 | if(EditorGUILayoutSortingLayerField != null && sortingLayerIDProperty != null) {
112 | EditorGUILayoutSortingLayerField.Invoke(null, new object[] { new GUIContent("Sorting Layer"), sortingLayerIDProperty, EditorStyles.popup } );
113 | } else {
114 | renderer.sortingLayerID = EditorGUILayout.IntField("Sorting Layer ID", renderer.sortingLayerID);
115 | }
116 |
117 | renderer.sortingOrder = EditorGUILayout.IntField("Order in Layer", renderer.sortingOrder);
118 |
119 | if(EditorGUI.EndChangeCheck()) {
120 | rendererSerializedObject.ApplyModifiedProperties();
121 | EditorUtility.SetDirty(renderer);
122 | }
123 | }
124 | }
125 |
126 | // More Render Options...
127 | {
128 | advancedFoldout = EditorGUILayout.Foldout(advancedFoldout, "Advanced");
129 | if(advancedFoldout) {
130 | EditorGUI.indentLevel++;
131 | EditorGUILayout.PropertyField(meshes,
132 | new GUIContent("Render Meshes", "Disable to optimize rendering for skeletons that don't use meshes"));
133 | EditorGUILayout.PropertyField(immutableTriangles,
134 | new GUIContent("Immutable Triangles", "Enable to optimize rendering for skeletons that never change attachment visbility"));
135 | EditorGUILayout.PropertyField(normals);
136 | EditorGUILayout.PropertyField(tangents);
137 | EditorGUILayout.PropertyField(front);
138 | EditorGUILayout.PropertyField(submeshSeparators, true);
139 | EditorGUI.indentLevel--;
140 | }
141 | }
142 | }
143 |
144 | override public void OnInspectorGUI () {
145 | serializedObject.Update();
146 | gui();
147 | if (serializedObject.ApplyModifiedProperties() ||
148 | (Event.current.type == EventType.ValidateCommand && Event.current.commandName == "UndoRedoPerformed")
149 | ) {
150 | if (!Application.isPlaying)
151 | ((SkeletonRenderer)target).Reset();
152 | }
153 | }
154 |
155 | }
156 |
--------------------------------------------------------------------------------
/spine-unity/Shaders/Bones.shader:
--------------------------------------------------------------------------------
1 | // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
2 |
3 | Shader "Spine/Bones" {
4 | Properties {
5 | _Color ("Color", Color) = (0.5,0.5,0.5,0.5)
6 | _MainTex ("Particle Texture", 2D) = "white" {}
7 | }
8 |
9 | Category {
10 | Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" }
11 | Blend SrcAlpha OneMinusSrcAlpha
12 | AlphaTest Greater .01
13 | ColorMask RGB
14 |
15 | Lighting Off Cull Off ZTest Always ZWrite Off Fog { Mode Off }
16 |
17 | SubShader {
18 | Pass {
19 |
20 | CGPROGRAM
21 | #pragma vertex vert
22 | #pragma fragment frag
23 | #pragma multi_compile_particles
24 |
25 | #include "UnityCG.cginc"
26 |
27 | sampler2D _MainTex;
28 | fixed4 _Color;
29 |
30 | struct appdata_t {
31 | float4 vertex : POSITION;
32 | fixed4 color : COLOR;
33 | float2 texcoord : TEXCOORD0;
34 | };
35 |
36 | struct v2f {
37 | float4 vertex : SV_POSITION;
38 | fixed4 color : COLOR;
39 | float2 texcoord : TEXCOORD0;
40 | #ifdef SOFTPARTICLES_ON
41 | float4 projPos : TEXCOORD1;
42 | #endif
43 | };
44 |
45 | float4 _MainTex_ST;
46 |
47 | v2f vert (appdata_t v)
48 | {
49 | v2f o;
50 | o.vertex = UnityObjectToClipPos(v.vertex);
51 | #ifdef SOFTPARTICLES_ON
52 | o.projPos = ComputeScreenPos (o.vertex);
53 | COMPUTE_EYEDEPTH(o.projPos.z);
54 | #endif
55 | o.color = v.color;
56 | o.texcoord = TRANSFORM_TEX(v.texcoord,_MainTex);
57 | return o;
58 | }
59 |
60 | sampler2D_float _CameraDepthTexture;
61 |
62 |
63 | fixed4 frag (v2f i) : SV_Target
64 | {
65 | return 2.0f * i.color * _Color * tex2D(_MainTex, i.texcoord);
66 | }
67 | ENDCG
68 | }
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/spine-unity/Shaders/HiddenPass.mat:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!21 &2100000
4 | Material:
5 | serializedVersion: 6
6 | m_ObjectHideFlags: 0
7 | m_CorrespondingSourceObject: {fileID: 0}
8 | m_PrefabInstance: {fileID: 0}
9 | m_PrefabAsset: {fileID: 0}
10 | m_Name: HiddenPass
11 | m_Shader: {fileID: 4800000, guid: 913475501bf19374c84390868a9d6d3d, type: 3}
12 | m_ShaderKeywords:
13 | m_LightmapFlags: 4
14 | m_EnableInstancingVariants: 0
15 | m_DoubleSidedGI: 0
16 | m_CustomRenderQueue: -1
17 | stringTagMap: {}
18 | disabledShaderPasses: []
19 | m_SavedProperties:
20 | serializedVersion: 3
21 | m_TexEnvs:
22 | - _MainTex:
23 | m_Texture: {fileID: 0}
24 | m_Scale: {x: 1, y: 1}
25 | m_Offset: {x: 0, y: 0}
26 | m_Floats:
27 | - _Cutoff: 0.1
28 | - _InvFade: 1
29 | m_Colors:
30 | - _Color: {r: 1, g: 1, b: 1, a: 1}
31 | - _TintColor: {r: 0.5, g: 0.5, b: 0.5, a: 0}
32 |
--------------------------------------------------------------------------------
/spine-unity/Shaders/HiddenPass.shader:
--------------------------------------------------------------------------------
1 | Shader "Spine/HiddenPass" {
2 | SubShader
3 |
4 | {
5 |
6 | Tags {"Queue" = "Geometry-1" }
7 |
8 | Lighting Off
9 |
10 | Pass
11 |
12 | {
13 |
14 | ZWrite Off
15 |
16 | ColorMask 0
17 |
18 | }
19 |
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/spine-unity/Shaders/SkeletonLit.shader:
--------------------------------------------------------------------------------
1 | Shader "Spine/Skeleton Lit" {
2 | Properties {
3 | _Cutoff ("Shadow alpha cutoff", Range(0,1)) = 0.1
4 | _MainTex ("Texture to blend", 2D) = "black" {}
5 | }
6 | // 2 texture stage GPUs
7 | SubShader {
8 | Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" }
9 | LOD 100
10 |
11 | Cull Off
12 | ZWrite Off
13 | Blend One OneMinusSrcAlpha
14 |
15 | Pass {
16 | Tags { "LightMode"="Vertex" }
17 | ColorMaterial AmbientAndDiffuse
18 | Lighting On
19 | SetTexture [_MainTex] {
20 | Combine texture * primary DOUBLE, texture * primary
21 | }
22 | }
23 |
24 | Pass {
25 | Name "Caster"
26 | Tags { "LightMode"="ShadowCaster" }
27 | Offset 1, 1
28 |
29 | Fog { Mode Off }
30 | ZWrite On
31 | ZTest LEqual
32 | Cull Off
33 | Lighting Off
34 |
35 | CGPROGRAM
36 | #pragma vertex vert
37 | #pragma fragment frag
38 | #pragma multi_compile_shadowcaster
39 | #pragma fragmentoption ARB_precision_hint_fastest
40 | #include "UnityCG.cginc"
41 | struct v2f {
42 | V2F_SHADOW_CASTER;
43 | float2 uv : TEXCOORD1;
44 | };
45 |
46 | uniform float4 _MainTex_ST;
47 |
48 | v2f vert (appdata_base v) {
49 | v2f o;
50 | TRANSFER_SHADOW_CASTER(o)
51 | o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
52 | return o;
53 | }
54 |
55 | uniform sampler2D _MainTex;
56 | uniform fixed _Cutoff;
57 |
58 | float4 frag (v2f i) : COLOR {
59 | fixed4 texcol = tex2D(_MainTex, i.uv);
60 | clip(texcol.a - _Cutoff);
61 | SHADOW_CASTER_FRAGMENT(i)
62 | }
63 | ENDCG
64 | }
65 | }
66 | // 1 texture stage GPUs
67 | SubShader {
68 | Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" }
69 | LOD 100
70 |
71 | Cull Off
72 | ZWrite Off
73 | Blend One OneMinusSrcAlpha
74 |
75 | Pass {
76 | Tags { "LightMode"="Vertex" }
77 | ColorMaterial AmbientAndDiffuse
78 | Lighting On
79 | SetTexture [_MainTex] {
80 | Combine texture * primary DOUBLE, texture * primary
81 | }
82 | }
83 | }
84 | }
--------------------------------------------------------------------------------
/spine-unity/Shaders/Spine-Skeleton-BlendMode.shader:
--------------------------------------------------------------------------------
1 | Shader "Spine/Skeleton-BlendMode" {
2 | Properties {
3 | _Cutoff ("Shadow alpha cutoff", Range(0,1)) = 0.1
4 | [HDR]_Color("Color", Color) = (1,1,1,1)
5 | [Enum(UnityEngine.Rendering.BlendOp)] _BlendOp("Blend Op", Float) = 0.0
6 | [Enum(UnityEngine.Rendering.BlendMode)]_SrcBlend("Src Blend Mode", Int) = 0
7 | [Enum(UnityEngine.Rendering.BlendMode)]_DstBlend("Dst Blend Mode", Int) = 0
8 | [NoScaleOffset] _MainTex ("Main Texture", 2D) = "black" {}
9 | [Toggle(_STRAIGHT_ALPHA_INPUT)] _StraightAlphaInput("Straight Alpha Texture", Int) = 1
10 | [HideInInspector] _StencilRef("Stencil Reference", Float) = 1.0
11 | [HideInInspector][Enum(UnityEngine.Rendering.CompareFunction)] _StencilComp("Stencil Comparison", Float) = 8 // Set to Always as default
12 |
13 | // Outline properties are drawn via custom editor.
14 | [HideInInspector] _OutlineWidth("Outline Width", Range(0,8)) = 3.0
15 | [HideInInspector] _OutlineColor("Outline Color", Color) = (1,1,0,1)
16 | [HideInInspector] _OutlineReferenceTexWidth("Reference Texture Width", Int) = 1024
17 | [HideInInspector] _ThresholdEnd("Outline Threshold", Range(0,1)) = 0.25
18 | [HideInInspector] _OutlineSmoothness("Outline Smoothness", Range(0,1)) = 1.0
19 | [HideInInspector][MaterialToggle(_USE8NEIGHBOURHOOD_ON)] _Use8Neighbourhood("Sample 8 Neighbours", Float) = 1
20 | [HideInInspector] _OutlineMipLevel("Outline Mip Level", Range(0,3)) = 0
21 |
22 | [HideInInspector] _OpenMask("openMask",Int) = 0
23 | [HideInInspector] _Area("Area",Vector) = (0,0,1,1)
24 | }
25 |
26 | SubShader {
27 | Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" "PreviewType"="Plane" }
28 |
29 | Fog { Mode Off }
30 | BlendOp[_BlendOp]
31 | Blend[_SrcBlend][_DstBlend]
32 | Cull Off
33 | ZWrite Off
34 | Lighting Off
35 |
36 | Stencil {
37 | Ref[_StencilRef]
38 | Comp[_StencilComp]
39 | Pass Keep
40 | }
41 |
42 | CGINCLUDE
43 |
44 | #include "UnityCG.cginc"
45 |
46 | float4 _Color;
47 | sampler2D _MainTex;
48 |
49 | struct VertexInput {
50 | float4 vertex : POSITION;
51 | float2 uv : TEXCOORD0;
52 | float4 vertexColor : COLOR;
53 | };
54 |
55 | struct DistortionOutput {
56 | float4 pos : SV_POSITION;
57 | float2 uv : TEXCOORD0;
58 | float4 vertexColor : COLOR;
59 | };
60 |
61 | DistortionOutput vertDistortion(VertexInput v) {
62 | DistortionOutput o;
63 | o.pos = UnityObjectToClipPos(v.vertex);
64 | o.uv = v.uv;
65 | o.vertexColor = v.vertexColor;
66 | return o;
67 | }
68 |
69 | ENDCG
70 |
71 | // Normal
72 | Pass {
73 | Name "Normal"
74 |
75 | CGPROGRAM
76 | #pragma shader_feature _ _STRAIGHT_ALPHA_INPUT
77 | #pragma vertex vert
78 | #pragma fragment frag
79 |
80 | float4 _Area;
81 | int _OpenMask;
82 |
83 | struct VertexOutput {
84 | float4 pos : SV_POSITION;
85 | float2 uv : TEXCOORD0;
86 | float4 vertexColor : COLOR;
87 | float2 worldPos:TEXCOORD1;
88 | };
89 |
90 | VertexOutput vert (VertexInput v) {
91 | VertexOutput o;
92 | o.pos = UnityObjectToClipPos(v.vertex);
93 | o.uv = v.uv;
94 | o.vertexColor = v.vertexColor;
95 | o.worldPos = mul(unity_ObjectToWorld,v.vertex).xy;
96 | return o;
97 | }
98 |
99 | sampler2D _CameraDepthTexture;
100 | float _InvFade;
101 |
102 | float4 frag (VertexOutput i) : SV_Target {
103 | float4 texColor = tex2D(_MainTex, i.uv) * _Color;
104 |
105 | #if defined(_STRAIGHT_ALPHA_INPUT)
106 | texColor.rgb *= texColor.a;
107 | #endif
108 |
109 | bool inArea = true;
110 | if ( _OpenMask == 1)
111 | inArea = i.worldPos.x >= _Area.x && i.worldPos.x <= _Area.z && i.worldPos.y >= _Area.y && i.worldPos.y <= _Area.w;
112 |
113 | return inArea? (texColor * i.vertexColor):fixed4(0,0,0,0);
114 | }
115 | ENDCG
116 | }
117 |
118 | // SkillDistortion
119 | Pass {
120 | Name "SkillDistortionObject"
121 |
122 | Tags {"LightMode"="SkillDistortionObject"}
123 |
124 | CGPROGRAM
125 | #pragma vertex vertDistortion
126 | #pragma fragment frag
127 |
128 | float4 frag(DistortionOutput i) : SV_Target {
129 | float4 texColor = tex2D(_MainTex, i.uv) * i.vertexColor;
130 | return texColor.aaaa;
131 | }
132 | ENDCG
133 | }
134 |
135 | Pass {
136 | Name "Caster"
137 | Tags { "LightMode"="ShadowCaster" }
138 | Offset 1, 1
139 | ZWrite On
140 | ZTest LEqual
141 |
142 | Fog { Mode Off }
143 | Cull Off
144 | Lighting Off
145 |
146 | CGPROGRAM
147 | #pragma vertex vert
148 | #pragma fragment frag
149 | #pragma multi_compile_shadowcaster
150 | #pragma fragmentoption ARB_precision_hint_fastest
151 | fixed _Cutoff;
152 |
153 | struct VertexOutput {
154 | V2F_SHADOW_CASTER;
155 | float4 uvAndAlpha : TEXCOORD1;
156 | };
157 |
158 | VertexOutput vert (appdata_base v, float4 vertexColor : COLOR) {
159 | VertexOutput o;
160 | o.uvAndAlpha = v.texcoord;
161 | o.uvAndAlpha.a = vertexColor.a;
162 | TRANSFER_SHADOW_CASTER(o)
163 | return o;
164 | }
165 |
166 | float4 frag (VertexOutput i) : SV_Target {
167 | fixed4 texcol = tex2D(_MainTex, i.uvAndAlpha.xy);
168 | clip(texcol.a * i.uvAndAlpha.a - _Cutoff);
169 | SHADOW_CASTER_FRAGMENT(i)
170 | }
171 | ENDCG
172 | }
173 | }
174 | CustomEditor "SpineShaderWithOutlineGUI"
175 | }
176 |
--------------------------------------------------------------------------------
/spine-unity/Shaders/Spine-Skeleton-HDR.shader:
--------------------------------------------------------------------------------
1 | Shader "Spine/SkeletonHDR" {
2 | Properties {
3 | [HDR] _HDRColor("HDR Color", Color) = (1,1,1,1)
4 | _Cutoff ("Shadow alpha cutoff", Range(0,1)) = 0.1
5 | [NoScaleOffset] _MainTex ("Main Texture", 2D) = "black" {}
6 | [Toggle(_STRAIGHT_ALPHA_INPUT)] _StraightAlphaInput("Straight Alpha Texture", Int) = 1
7 | [HideInInspector] _StencilRef("Stencil Reference", Float) = 1.0
8 | [HideInInspector][Enum(UnityEngine.Rendering.CompareFunction)] _StencilComp("Stencil Comparison", Float) = 8 // Set to Always as default
9 |
10 | // Outline properties are drawn via custom editor.
11 | [HideInInspector] _OutlineWidth("Outline Width", Range(0,8)) = 3.0
12 | [HideInInspector] _OutlineColor("Outline Color", Color) = (1,1,0,1)
13 | [HideInInspector] _OutlineReferenceTexWidth("Reference Texture Width", Int) = 1024
14 | [HideInInspector] _ThresholdEnd("Outline Threshold", Range(0,1)) = 0.25
15 | [HideInInspector] _OutlineSmoothness("Outline Smoothness", Range(0,1)) = 1.0
16 | [HideInInspector][MaterialToggle(_USE8NEIGHBOURHOOD_ON)] _Use8Neighbourhood("Sample 8 Neighbours", Float) = 1
17 | [HideInInspector] _OutlineMipLevel("Outline Mip Level", Range(0,3)) = 0
18 |
19 | [HideInInspector] _OpenMask("openMask",Int) = 0
20 | [HideInInspector] _Area("Area",Vector) = (0,0,1,1)
21 | }
22 |
23 | SubShader {
24 | Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" "PreviewType"="Plane" }
25 |
26 | Pass //2d shadow
27 | {
28 | Stencil
29 | {
30 | Ref 0
31 | Comp equal
32 | Pass incrWrap
33 | Fail keep
34 | ZFail keep
35 | }
36 |
37 | Tags { "LightMode" = "ForwardBase" }
38 | Blend SrcAlpha OneMinusSrcAlpha
39 |
40 | Cull Off
41 | ZWrite Off
42 |
43 | Name "2d shadow"
44 | CGPROGRAM
45 | #pragma vertex vert
46 | #pragma fragment frag
47 | #pragma target 2.0
48 |
49 | #include "UnityCG.cginc"
50 |
51 | struct VertexInput {
52 | float4 vertex : POSITION;
53 | float4 color : COLOR;
54 | float2 texcoord : TEXCOORD0;
55 | UNITY_VERTEX_INPUT_INSTANCE_ID
56 | };
57 |
58 | struct VertexOutput {
59 | float4 vertex : SV_POSITION;
60 | fixed4 color : COLOR;
61 | half2 texcoord : TEXCOORD0;
62 | float4 worldPosition : TEXCOORD1;
63 | UNITY_VERTEX_OUTPUT_STEREO
64 | };
65 |
66 | float _DirectionalLightStrength;
67 | float4x4 _DirectionalLightMatrix;
68 | half4 _DirectionalLightShadowColor;
69 |
70 | VertexOutput vert(VertexInput IN) {
71 | VertexOutput OUT;
72 |
73 | UNITY_SETUP_INSTANCE_ID(IN);
74 | UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT);
75 |
76 | float3 WorldPos = mul(_DirectionalLightMatrix, IN.vertex).xyz;
77 | OUT.vertex = mul(UNITY_MATRIX_VP, float4(WorldPos, 1));
78 |
79 | OUT.texcoord = IN.texcoord;
80 |
81 | OUT.color = _DirectionalLightShadowColor.rgba * 0.2;
82 | OUT.color.a = IN.color.a * _DirectionalLightStrength;
83 |
84 | return OUT;
85 | }
86 |
87 | sampler2D _MainTex;
88 |
89 | fixed4 frag(VertexOutput IN) : SV_Target
90 | {
91 | fixed4 color = IN.color;
92 | half alpha = tex2D(_MainTex, IN.texcoord).a * color.a;
93 | clip(alpha - 0.001);
94 |
95 | return color;
96 | }
97 | ENDCG
98 | }
99 |
100 | Pass
101 | {
102 |
103 | Stencil
104 | {
105 | Ref [_StencilRef]
106 | Comp [_StencilComp]
107 | Pass Keep
108 | }
109 |
110 | Name "Normal"
111 |
112 | Fog { Mode Off }
113 | Cull Off
114 | ZWrite Off
115 | Blend One OneMinusSrcAlpha
116 | Lighting Off
117 |
118 | CGPROGRAM
119 | #pragma shader_feature _ _STRAIGHT_ALPHA_INPUT
120 | #pragma vertex vert
121 | #pragma fragment frag
122 | #include "UnityCG.cginc"
123 | sampler2D _MainTex;
124 |
125 | float4 _Area;
126 | int _OpenMask;
127 | float4 _HDRColor;
128 |
129 | struct VertexInput {
130 | float4 vertex : POSITION;
131 | float2 uv : TEXCOORD0;
132 | float4 vertexColor : COLOR;
133 | };
134 |
135 | struct VertexOutput {
136 | float4 pos : SV_POSITION;
137 | float2 uv : TEXCOORD0;
138 | float4 vertexColor : COLOR;
139 | float2 worldPos:TEXCOORD1;
140 | };
141 |
142 | VertexOutput vert (VertexInput v) {
143 | VertexOutput o;
144 | o.pos = UnityObjectToClipPos(v.vertex);
145 | o.uv = v.uv;
146 | o.vertexColor = v.vertexColor;
147 | o.worldPos = mul(unity_ObjectToWorld,v.vertex).xy;
148 | return o;
149 | }
150 |
151 | sampler2D _CameraDepthTexture;
152 | float _InvFade;
153 |
154 | float4 frag (VertexOutput i) : SV_Target {
155 | float4 texColor = tex2D(_MainTex, i.uv) * _HDRColor;
156 |
157 | #if defined(_STRAIGHT_ALPHA_INPUT)
158 | texColor.rgb *= texColor.a;
159 | #endif
160 |
161 | bool inArea = true;
162 | if ( _OpenMask == 1)
163 | inArea = i.worldPos.x >= _Area.x && i.worldPos.x <= _Area.z && i.worldPos.y >= _Area.y && i.worldPos.y <= _Area.w;
164 |
165 | return inArea? (texColor * i.vertexColor):fixed4(0,0,0,0);
166 | }
167 | ENDCG
168 | }
169 |
170 | Pass
171 | {
172 | Name "Caster"
173 | Tags { "LightMode"="ShadowCaster" }
174 | Offset 1, 1
175 | ZWrite On
176 | ZTest LEqual
177 |
178 | Fog { Mode Off }
179 | Cull Off
180 | Lighting Off
181 | Blend One OneMinusSrcAlpha
182 |
183 | CGPROGRAM
184 | #pragma vertex vert
185 | #pragma fragment frag
186 | #pragma multi_compile_shadowcaster
187 | #pragma fragmentoption ARB_precision_hint_fastest
188 | #include "UnityCG.cginc"
189 | sampler2D _MainTex;
190 | fixed _Cutoff;
191 |
192 | struct VertexOutput {
193 | V2F_SHADOW_CASTER;
194 | float4 uvAndAlpha : TEXCOORD1;
195 | };
196 |
197 | VertexOutput vert (appdata_base v, float4 vertexColor : COLOR) {
198 | VertexOutput o;
199 | o.uvAndAlpha = v.texcoord;
200 | o.uvAndAlpha.a = vertexColor.a;
201 | TRANSFER_SHADOW_CASTER(o)
202 | return o;
203 | }
204 |
205 | float4 frag (VertexOutput i) : SV_Target {
206 | fixed4 texcol = tex2D(_MainTex, i.uvAndAlpha.xy);
207 | clip(texcol.a * i.uvAndAlpha.a - _Cutoff);
208 | SHADOW_CASTER_FRAGMENT(i)
209 | }
210 | ENDCG
211 | }
212 | }
213 | CustomEditor "SpineShaderWithOutlineGUI"
214 | }
215 |
--------------------------------------------------------------------------------
/spine-unity/Shaders/Spine-Skeleton.shader:
--------------------------------------------------------------------------------
1 | Shader "Spine/Skeleton" {
2 | Properties {
3 | _Cutoff ("Shadow alpha cutoff", Range(0,1)) = 0.1
4 | [NoScaleOffset] _MainTex ("Main Texture", 2D) = "black" {}
5 | [Toggle(_STRAIGHT_ALPHA_INPUT)] _StraightAlphaInput("Straight Alpha Texture", Int) = 1
6 | [HideInInspector] _StencilRef("Stencil Reference", Float) = 1.0
7 | [HideInInspector][Enum(UnityEngine.Rendering.CompareFunction)] _StencilComp("Stencil Comparison", Float) = 8 // Set to Always as default
8 |
9 | // Outline properties are drawn via custom editor.
10 | [HideInInspector] _OutlineWidth("Outline Width", Range(0,8)) = 3.0
11 | [HideInInspector] _OutlineColor("Outline Color", Color) = (1,1,0,1)
12 | [HideInInspector] _OutlineReferenceTexWidth("Reference Texture Width", Int) = 1024
13 | [HideInInspector] _ThresholdEnd("Outline Threshold", Range(0,1)) = 0.25
14 | [HideInInspector] _OutlineSmoothness("Outline Smoothness", Range(0,1)) = 1.0
15 | [HideInInspector][MaterialToggle(_USE8NEIGHBOURHOOD_ON)] _Use8Neighbourhood("Sample 8 Neighbours", Float) = 1
16 | [HideInInspector] _OutlineMipLevel("Outline Mip Level", Range(0,3)) = 0
17 |
18 | [HideInInspector] _OpenMask("openMask",Int) = 0
19 | [HideInInspector] _Area("Area",Vector) = (0,0,1,1)
20 | }
21 |
22 | SubShader {
23 | Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" "PreviewType"="Plane" }
24 |
25 | Fog { Mode Off }
26 | Cull Off
27 | ZWrite Off
28 | Blend One OneMinusSrcAlpha
29 | Lighting Off
30 |
31 | Stencil {
32 | Ref[_StencilRef]
33 | Comp[_StencilComp]
34 | Pass Keep
35 | }
36 |
37 | CGINCLUDE
38 |
39 | #include "UnityCG.cginc"
40 |
41 | sampler2D _MainTex;
42 |
43 | struct VertexInput {
44 | float4 vertex : POSITION;
45 | float2 uv : TEXCOORD0;
46 | float4 vertexColor : COLOR;
47 | };
48 |
49 | struct DistortionOutput {
50 | float4 pos : SV_POSITION;
51 | float2 uv : TEXCOORD0;
52 | float4 vertexColor : COLOR;
53 | };
54 |
55 | DistortionOutput vertDistortion(VertexInput v) {
56 | DistortionOutput o;
57 | o.pos = UnityObjectToClipPos(v.vertex);
58 | o.uv = v.uv;
59 | o.vertexColor = v.vertexColor;
60 | return o;
61 | }
62 |
63 | ENDCG
64 |
65 | // Normal
66 | Pass {
67 | Name "Normal"
68 |
69 | CGPROGRAM
70 | #pragma shader_feature _ _STRAIGHT_ALPHA_INPUT
71 | #pragma vertex vert
72 | #pragma fragment frag
73 |
74 | float4 _Area;
75 | int _OpenMask;
76 |
77 | struct VertexOutput {
78 | float4 pos : SV_POSITION;
79 | float2 uv : TEXCOORD0;
80 | float4 vertexColor : COLOR;
81 | float2 worldPos:TEXCOORD1;
82 | };
83 |
84 | VertexOutput vert (VertexInput v) {
85 | VertexOutput o;
86 | o.pos = UnityObjectToClipPos(v.vertex);
87 | o.uv = v.uv;
88 | o.vertexColor = v.vertexColor;
89 | o.worldPos = mul(unity_ObjectToWorld,v.vertex).xy;
90 | return o;
91 | }
92 |
93 | sampler2D _CameraDepthTexture;
94 | float _InvFade;
95 |
96 | float4 frag (VertexOutput i) : SV_Target {
97 | float4 texColor = tex2D(_MainTex, i.uv);
98 |
99 | #if defined(_STRAIGHT_ALPHA_INPUT)
100 | texColor.rgb *= texColor.a;
101 | #endif
102 |
103 | bool inArea = true;
104 | if ( _OpenMask == 1)
105 | inArea = i.worldPos.x >= _Area.x && i.worldPos.x <= _Area.z && i.worldPos.y >= _Area.y && i.worldPos.y <= _Area.w;
106 |
107 | return inArea? (texColor * i.vertexColor):fixed4(0,0,0,0);
108 | }
109 | ENDCG
110 | }
111 |
112 | // SkillDistortion
113 | Pass {
114 | Name "SkillDistortionObject"
115 |
116 | Tags {"LightMode"="SkillDistortionObject"}
117 |
118 | CGPROGRAM
119 | #pragma vertex vertDistortion
120 | #pragma fragment frag
121 |
122 | float4 frag(DistortionOutput i) : SV_Target {
123 | float4 texColor = tex2D(_MainTex, i.uv) * i.vertexColor;
124 | return texColor.aaaa;
125 | }
126 | ENDCG
127 | }
128 |
129 | Pass {
130 | Name "Caster"
131 | Tags { "LightMode"="ShadowCaster" }
132 | Offset 1, 1
133 | ZWrite On
134 | ZTest LEqual
135 |
136 | Fog { Mode Off }
137 | Cull Off
138 | Lighting Off
139 |
140 | CGPROGRAM
141 | #pragma vertex vert
142 | #pragma fragment frag
143 | #pragma multi_compile_shadowcaster
144 | #pragma fragmentoption ARB_precision_hint_fastest
145 | fixed _Cutoff;
146 |
147 | struct VertexOutput {
148 | V2F_SHADOW_CASTER;
149 | float4 uvAndAlpha : TEXCOORD1;
150 | };
151 |
152 | VertexOutput vert (appdata_base v, float4 vertexColor : COLOR) {
153 | VertexOutput o;
154 | o.uvAndAlpha = v.texcoord;
155 | o.uvAndAlpha.a = vertexColor.a;
156 | TRANSFER_SHADOW_CASTER(o)
157 | return o;
158 | }
159 |
160 | float4 frag (VertexOutput i) : SV_Target {
161 | fixed4 texcol = tex2D(_MainTex, i.uvAndAlpha.xy);
162 | clip(texcol.a * i.uvAndAlpha.a - _Cutoff);
163 | SHADOW_CASTER_FRAGMENT(i)
164 | }
165 | ENDCG
166 | }
167 | }
168 | CustomEditor "SpineShaderWithOutlineGUI"
169 | }
170 |
--------------------------------------------------------------------------------
/spine-unity/SkeletonAnimationInterface.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 | using System.Collections;
3 |
4 | public delegate void UpdateBonesDelegate (SkeletonRenderer skeletonRenderer);
5 | public interface ISkeletonAnimation {
6 | event UpdateBonesDelegate UpdateLocal;
7 | event UpdateBonesDelegate UpdateWorld;
8 | event UpdateBonesDelegate UpdateComplete;
9 |
10 | void LateUpdate ();
11 | }
--------------------------------------------------------------------------------
/spine-unity/SkeletonAnimator.cs:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Spine Runtimes Software License
3 | * Version 2.1
4 | *
5 | * Copyright (c) 2013, Esoteric Software
6 | * All rights reserved.
7 | *
8 | * You are granted a perpetual, non-exclusive, non-sublicensable and
9 | * non-transferable license to install, execute and perform the Spine Runtimes
10 | * Software (the "Software") solely for internal use. Without the written
11 | * permission of Esoteric Software (typically granted by licensing Spine), you
12 | * may not (a) modify, translate, adapt or otherwise create derivative works,
13 | * improvements of the Software or develop new applications using the Software
14 | * or (b) remove, delete, alter or obscure any trademarks or any copyright,
15 | * trademark, patent or other intellectual property or proprietary rights
16 | * notices on or in the Software, including any copy thereof. Redistributions
17 | * in binary or source form must include this license and terms.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
22 | * EVENT SHALL ESOTERIC SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 | *****************************************************************************/
30 |
31 | /*****************************************************************************
32 | * SkeletonAnimator created by Mitch Thompson
33 | * Full irrevocable rights and permissions granted to Esoteric Software
34 | *****************************************************************************/
35 | using UnityEngine;
36 | using System.Collections;
37 | using System.Collections.Generic;
38 | using Spine;
39 |
40 | [RequireComponent(typeof(Animator))]
41 | public class SkeletonAnimator : SkeletonRenderer, ISkeletonAnimation {
42 |
43 | public enum MixMode { AlwaysMix, MixNext, SpineStyle }
44 | public MixMode[] layerMixModes = new MixMode[0];
45 |
46 | public event UpdateBonesDelegate UpdateLocal {
47 | add { _UpdateLocal += value; }
48 | remove { _UpdateLocal -= value; }
49 | }
50 |
51 | public event UpdateBonesDelegate UpdateWorld {
52 | add { _UpdateWorld += value; }
53 | remove { _UpdateWorld -= value; }
54 | }
55 |
56 | public event UpdateBonesDelegate UpdateComplete {
57 | add { _UpdateComplete += value; }
58 | remove { _UpdateComplete -= value; }
59 | }
60 |
61 | protected event UpdateBonesDelegate _UpdateLocal;
62 | protected event UpdateBonesDelegate _UpdateWorld;
63 | protected event UpdateBonesDelegate _UpdateComplete;
64 |
65 | Dictionary animationTable = new Dictionary();
66 | Animator animator;
67 |
68 | public override void Reset () {
69 | base.Reset();
70 | if (!valid)
71 | return;
72 |
73 | animationTable.Clear();
74 |
75 | var data = skeletonDataAsset.GetSkeletonData(true);
76 |
77 | foreach (var a in data.Animations) {
78 | animationTable.Add(a.Name, a);
79 | }
80 |
81 | animator = GetComponent();
82 |
83 |
84 | }
85 |
86 | void Update () {
87 | if (!valid)
88 | return;
89 |
90 | if (layerMixModes.Length != animator.layerCount) {
91 | System.Array.Resize(ref layerMixModes, animator.layerCount);
92 | }
93 |
94 | skeleton.Update(Time.deltaTime);
95 |
96 | //apply
97 | int layerCount = animator.layerCount;
98 | float deltaTime = Time.deltaTime;
99 | for (int i = 0; i < layerCount; i++) {
100 |
101 | float layerWeight = animator.GetLayerWeight(i);
102 | if (i == 0)
103 | layerWeight = 1;
104 |
105 | var stateInfo = animator.GetCurrentAnimatorStateInfo(i);
106 | var nextStateInfo = animator.GetNextAnimatorStateInfo(i);
107 |
108 | #if UNITY_5
109 | var clipInfo = animator.GetCurrentAnimatorClipInfo(i);
110 | var nextClipInfo = animator.GetNextAnimatorClipInfo(i);
111 | #else
112 | var clipInfo = animator.GetCurrentAnimatorClipInfo(i);
113 | var nextClipInfo = animator.GetNextAnimatorClipInfo(i);
114 | #endif
115 | MixMode mode = layerMixModes[i];
116 |
117 | if (mode == MixMode.AlwaysMix) {
118 | //always use Mix instead of Applying the first non-zero weighted clip
119 | foreach (var info in clipInfo) {
120 | float weight = info.weight * layerWeight;
121 | if (weight == 0)
122 | continue;
123 |
124 | float time = stateInfo.normalizedTime * info.clip.length;
125 | animationTable[info.clip.name].Mix(skeleton, Mathf.Max(0, time - deltaTime), time, stateInfo.loop, null, weight);
126 | }
127 |
128 | foreach (var info in nextClipInfo) {
129 | float weight = info.weight * layerWeight;
130 | if (weight == 0)
131 | continue;
132 |
133 | float time = nextStateInfo.normalizedTime * info.clip.length;
134 | animationTable[info.clip.name].Mix(skeleton, Mathf.Max(0, time - deltaTime), time, nextStateInfo.loop, null, weight);
135 | }
136 | } else if (mode >= MixMode.MixNext) {
137 | //apply first non-zero weighted clip
138 | int c = 0;
139 |
140 | for (; c < clipInfo.Length; c++) {
141 | var info = clipInfo[c];
142 | float weight = info.weight * layerWeight;
143 | if (weight == 0)
144 | continue;
145 |
146 | float time = stateInfo.normalizedTime * info.clip.length;
147 | animationTable[info.clip.name].Apply(skeleton, Mathf.Max(0, time - deltaTime), time, stateInfo.loop, null);
148 | break;
149 | }
150 |
151 | //mix the rest
152 | for (; c < clipInfo.Length; c++) {
153 | var info = clipInfo[c];
154 | float weight = info.weight * layerWeight;
155 | if (weight == 0)
156 | continue;
157 |
158 | float time = stateInfo.normalizedTime * info.clip.length;
159 | animationTable[info.clip.name].Mix(skeleton, Mathf.Max(0, time - deltaTime), time, stateInfo.loop, null, weight);
160 | }
161 |
162 | c = 0;
163 |
164 | //apply next clip directly instead of mixing (ie: no crossfade, ignores mecanim transition weights)
165 | if (mode == MixMode.SpineStyle) {
166 | for (; c < nextClipInfo.Length; c++) {
167 | var info = nextClipInfo[c];
168 | float weight = info.weight * layerWeight;
169 | if (weight == 0)
170 | continue;
171 |
172 | float time = nextStateInfo.normalizedTime * info.clip.length;
173 | animationTable[info.clip.name].Apply(skeleton, Mathf.Max(0, time - deltaTime), time, nextStateInfo.loop, null);
174 | break;
175 | }
176 | }
177 |
178 | //mix the rest
179 | for (; c < nextClipInfo.Length; c++) {
180 | var info = nextClipInfo[c];
181 | float weight = info.weight * layerWeight;
182 | if (weight == 0)
183 | continue;
184 |
185 | float time = nextStateInfo.normalizedTime * info.clip.length;
186 | animationTable[info.clip.name].Mix(skeleton, Mathf.Max(0, time - deltaTime), time, nextStateInfo.loop, null, weight);
187 | }
188 | }
189 | }
190 |
191 | if (_UpdateLocal != null)
192 | _UpdateLocal(this);
193 |
194 | skeleton.UpdateWorldTransform();
195 |
196 | if (_UpdateWorld != null) {
197 | _UpdateWorld(this);
198 | skeleton.UpdateWorldTransform();
199 | }
200 |
201 | if (_UpdateComplete != null) {
202 | _UpdateComplete(this);
203 | }
204 | }
205 | }
206 |
--------------------------------------------------------------------------------
/spine-unity/SkeletonDataAsset.cs:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Spine Runtimes Software License
3 | * Version 2.1
4 | *
5 | * Copyright (c) 2013, Esoteric Software
6 | * All rights reserved.
7 | *
8 | * You are granted a perpetual, non-exclusive, non-sublicensable and
9 | * non-transferable license to install, execute and perform the Spine Runtimes
10 | * Software (the "Software") solely for internal use. Without the written
11 | * permission of Esoteric Software (typically granted by licensing Spine), you
12 | * may not (a) modify, translate, adapt or otherwise create derivative works,
13 | * improvements of the Software or develop new applications using the Software
14 | * or (b) remove, delete, alter or obscure any trademarks or any copyright,
15 | * trademark, patent or other intellectual property or proprietary rights
16 | * notices on or in the Software, including any copy thereof. Redistributions
17 | * in binary or source form must include this license and terms.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
22 | * EVENT SHALL ESOTERIC SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 | *****************************************************************************/
30 |
31 | using System;
32 | using System.IO;
33 | using System.Collections.Generic;
34 | using UnityEngine;
35 | using Spine;
36 |
37 | public class SkeletonDataAsset : ScriptableObject {
38 | public AtlasAsset[] atlasAssets;
39 | #if SPINE_TK2D
40 | public tk2dSpriteCollectionData spriteCollection;
41 | #endif
42 | public TextAsset skeletonJSON;
43 | public float scale = 1;
44 | public String[] fromAnimation;
45 | public String[] toAnimation;
46 | public float[] duration;
47 | public float defaultMix;
48 | public RuntimeAnimatorController controller;
49 | private SkeletonData skeletonData;
50 | private AnimationStateData stateData;
51 |
52 | public void Reset() {
53 | skeletonData = null;
54 | stateData = null;
55 | }
56 |
57 | public SkeletonData GetSkeletonData(bool quiet) {
58 | if (atlasAssets == null) {
59 | atlasAssets = new AtlasAsset[0];
60 | if (!quiet)
61 | Debug.LogError("Atlas not set for SkeletonData asset: " + name, this);
62 | Reset();
63 | return null;
64 | }
65 |
66 | if (skeletonJSON == null) {
67 | if (!quiet)
68 | Debug.LogError("Skeleton JSON file not set for SkeletonData asset: " + name, this);
69 | Reset();
70 | return null;
71 | }
72 |
73 | #if !SPINE_TK2D
74 | if (atlasAssets.Length == 0) {
75 | Reset();
76 | return null;
77 | }
78 | #else
79 | if (atlasAssets.Length == 0 && spriteCollection == null) {
80 | Reset();
81 | return null;
82 | }
83 | #endif
84 |
85 | Atlas[] atlasArr = new Atlas[atlasAssets.Length];
86 | for (int i = 0; i < atlasAssets.Length; i++) {
87 | if (atlasAssets[i] == null) {
88 | Reset();
89 | return null;
90 | }
91 | atlasArr[i] = atlasAssets[i].GetAtlas();
92 | if (atlasArr[i] == null) {
93 | Reset();
94 | return null;
95 | }
96 | }
97 |
98 | if (skeletonData != null)
99 | return skeletonData;
100 |
101 | AttachmentLoader attachmentLoader;
102 | float skeletonDataScale;
103 |
104 | #if !SPINE_TK2D
105 | attachmentLoader = new AtlasAttachmentLoader(atlasArr);
106 | skeletonDataScale = scale;
107 | #else
108 | if (spriteCollection != null) {
109 | attachmentLoader = new SpriteCollectionAttachmentLoader(spriteCollection)
110 | skeletonDataScale = (1.0f / (spriteCollection.invOrthoSize * spriteCollection.halfTargetHeight) * scale) * 100f;
111 | } else {
112 | if (atlasArr.Length == 0) {
113 | Reset();
114 | if (!quiet) Debug.LogError("Atlas not set for SkeletonData asset: " + name, this);
115 | return null;
116 | }
117 | attachmentLoader = new AtlasAttachmentLoader(atlasArr);
118 | skeletonDataScale = scale;
119 | }
120 | #endif
121 |
122 | try
123 | {
124 | var skeletonName = skeletonJSON.name;
125 |
126 |
127 |
128 | if (skeletonData == null)
129 | {
130 | if (skeletonName.Contains(".skel"))
131 | {
132 | var input = new MemoryStream(skeletonJSON.bytes);
133 | var binary = new SkeletonBinary(attachmentLoader);
134 | binary.Scale = skeletonDataScale;
135 |
136 | #if UNITY_EDITOR
137 | if (!Application.isPlaying)
138 | {
139 | binary.CacheStrings = new List() { null, "" };
140 | binary.CacheOffsetVertices = new List();
141 | }
142 | #endif
143 |
144 | skeletonData = binary.ReadSkeletonData(input);
145 |
146 |
147 | #if UNITY_EDITOR
148 | if (skeletonData.version != "HuaHua2.0")
149 | {
150 | Debug.LogError($"Exist unconverted spine:{skeletonName} size:{input.Length}");
151 | }
152 |
153 | if (!Application.isPlaying && skeletonData.version != "HuaHua2.0")
154 | {
155 | //HuaHua
156 | var output = new MemoryStream();
157 | binary.WriteSkeletonData(output, skeletonData);
158 | var path = UnityEditor.AssetDatabase.GetAssetPath(this);
159 | path = path.Replace("_SkeletonData.asset", ".skel.bytes");
160 | File.WriteAllBytes(path, output.ToArray());
161 | }
162 | #endif
163 | }
164 | else
165 | {
166 | Debug.LogError($"Spine don't use json == {skeletonName}"); //HuaHua
167 | var input = new StringReader(skeletonJSON.text);
168 | var json = new SkeletonJson(attachmentLoader);
169 | json.Scale = skeletonDataScale;
170 | skeletonData = json.ReadSkeletonData(input);
171 |
172 | #if UNITY_EDITOR
173 | if (!Application.isPlaying)
174 | {
175 | //HuaHua
176 | var output = new MemoryStream();
177 | var binary = new SkeletonBinary(attachmentLoader);
178 | binary.Scale = skeletonDataScale;
179 | binary.WriteSkeletonData(output, skeletonData);
180 | var path = UnityEditor.AssetDatabase.GetAssetPath(this);
181 | path = path.Replace("_SkeletonData.asset", ".skel.bytes");
182 | File.WriteAllBytes(path, output.ToArray());
183 | }
184 | #endif
185 | }
186 | }
187 |
188 | } catch (Exception ex) {
189 | if (!quiet)
190 | Debug.LogError("Error reading skeleton file for SkeletonData asset: " + name + "\n" + ex.Message + "\n" + ex.StackTrace, this);
191 | return null;
192 | }
193 |
194 | stateData = new AnimationStateData(skeletonData);
195 | FillStateData();
196 |
197 | return skeletonData;
198 | }
199 |
200 | public void FillStateData () {
201 | if (stateData == null)
202 | return;
203 |
204 | stateData.DefaultMix = defaultMix;
205 | for (int i = 0, n = fromAnimation.Length; i < n; i++) {
206 | if (fromAnimation[i].Length == 0 || toAnimation[i].Length == 0)
207 | continue;
208 | stateData.SetMix(fromAnimation[i], toAnimation[i], duration[i]);
209 | }
210 | }
211 |
212 | public AnimationStateData GetAnimationStateData() {
213 | if (stateData != null)
214 | return stateData;
215 | GetSkeletonData(false);
216 | return stateData;
217 | }
218 | }
219 |
--------------------------------------------------------------------------------
/spine-unity/SkeletonExtensions.cs:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Spine Runtimes Software License
3 | * Version 2.1
4 | *
5 | * Copyright (c) 2013, Esoteric Software
6 | * All rights reserved.
7 | *
8 | * You are granted a perpetual, non-exclusive, non-sublicensable and
9 | * non-transferable license to install, execute and perform the Spine Runtimes
10 | * Software (the "Software") solely for internal use. Without the written
11 | * permission of Esoteric Software (typically granted by licensing Spine), you
12 | * may not (a) modify, translate, adapt or otherwise create derivative works,
13 | * improvements of the Software or develop new applications using the Software
14 | * or (b) remove, delete, alter or obscure any trademarks or any copyright,
15 | * trademark, patent or other intellectual property or proprietary rights
16 | * notices on or in the Software, including any copy thereof. Redistributions
17 | * in binary or source form must include this license and terms.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
22 | * EVENT SHALL ESOTERIC SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 | *****************************************************************************/
30 |
31 | /*****************************************************************************
32 | * Spine Extensions created by Mitch Thompson
33 | * Full irrevocable rights and permissions granted to Esoteric Software
34 | *****************************************************************************/
35 |
36 | using UnityEngine;
37 | using System.Collections;
38 | using Spine;
39 |
40 | public static class SkeletonExtensions {
41 |
42 | public static void SetColor (this Skeleton skeleton, Color color) {
43 | skeleton.A = color.a;
44 | skeleton.R = color.r;
45 | skeleton.G = color.g;
46 | skeleton.B = color.b;
47 | }
48 |
49 | public static void SetColor (this Skeleton skeleton, Color32 color) {
50 | skeleton.A = color.a / 255f;
51 | skeleton.R = color.r / 255f;
52 | skeleton.G = color.g / 255f;
53 | skeleton.B = color.b / 255f;
54 | }
55 |
56 | public static void SetColor (this Slot slot, Color color) {
57 | slot.A = color.a;
58 | slot.R = color.r;
59 | slot.G = color.g;
60 | slot.B = color.b;
61 | }
62 |
63 | public static void SetColor (this Slot slot, Color32 color) {
64 | slot.A = color.a / 255f;
65 | slot.R = color.r / 255f;
66 | slot.G = color.g / 255f;
67 | slot.B = color.b / 255f;
68 | }
69 |
70 | public static void SetColor (this RegionAttachment attachment, Color color) {
71 | attachment.A = color.a;
72 | attachment.R = color.r;
73 | attachment.G = color.g;
74 | attachment.B = color.b;
75 | }
76 |
77 | public static void SetColor (this RegionAttachment attachment, Color32 color) {
78 | attachment.A = color.a / 255f;
79 | attachment.R = color.r / 255f;
80 | attachment.G = color.g / 255f;
81 | attachment.B = color.b / 255f;
82 | }
83 |
84 | public static void SetColor (this MeshAttachment attachment, Color color) {
85 | attachment.A = color.a;
86 | attachment.R = color.r;
87 | attachment.G = color.g;
88 | attachment.B = color.b;
89 | }
90 |
91 | public static void SetColor (this MeshAttachment attachment, Color32 color) {
92 | attachment.A = color.a / 255f;
93 | attachment.R = color.r / 255f;
94 | attachment.G = color.g / 255f;
95 | attachment.B = color.b / 255f;
96 | }
97 |
98 | public static void SetColor (this SkinnedMeshAttachment attachment, Color color) {
99 | attachment.A = color.a;
100 | attachment.R = color.r;
101 | attachment.G = color.g;
102 | attachment.B = color.b;
103 | }
104 |
105 | public static void SetColor (this SkinnedMeshAttachment attachment, Color32 color) {
106 | attachment.A = color.a / 255f;
107 | attachment.R = color.r / 255f;
108 | attachment.G = color.g / 255f;
109 | attachment.B = color.b / 255f;
110 | }
111 |
112 | public static void SetPosition (this Bone bone, Vector2 position) {
113 | bone.X = position.x;
114 | bone.Y = position.y;
115 | }
116 |
117 | public static void SetPosition (this Bone bone, Vector3 position) {
118 | bone.X = position.x;
119 | bone.Y = position.y;
120 | }
121 |
122 | public static Attachment AttachUnitySprite (this Skeleton skeleton, string slotName, Sprite sprite, string shaderName = "Spine/Skeleton") {
123 | var att = sprite.ToRegionAttachment(shaderName);
124 | skeleton.FindSlot(slotName).Attachment = att;
125 |
126 | return att;
127 | }
128 |
129 | public static Attachment AddUnitySprite (this SkeletonData skeletonData, string slotName, Sprite sprite, string skinName = "", string shaderName = "Spine/Skeleton") {
130 | var att = sprite.ToRegionAttachment(shaderName);
131 |
132 | var slotIndex = skeletonData.FindSlotIndex(slotName);
133 | Skin skin = skeletonData.defaultSkin;
134 | if (skinName != "")
135 | skin = skeletonData.FindSkin(skinName);
136 |
137 | skin.AddAttachment(slotIndex, att.Name, att);
138 |
139 | return att;
140 | }
141 |
142 | public static RegionAttachment ToRegionAttachment (this Sprite sprite, string shaderName = "Spine/Skeleton") {
143 | var loader = new SpriteAttachmentLoader(sprite, Shader.Find(shaderName));
144 | var att = loader.NewRegionAttachment(null, sprite.name, "");
145 | loader = null;
146 | return att;
147 | }
148 | }
--------------------------------------------------------------------------------
/spine-unity/SkeletonUtility/Editor/SkeletonUtilitySubmeshRendererInspector.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 | using UnityEditor;
3 | using System;
4 | using System.Collections;
5 | using System.Reflection;
6 |
7 | [CustomEditor(typeof(SkeletonUtilitySubmeshRenderer))]
8 | public class SkeletonUtilitySubmeshRendererInspector : Editor {
9 |
10 | private static MethodInfo EditorGUILayoutSortingLayerField;
11 | protected SerializedObject rendererSerializedObject;
12 | protected SerializedProperty sortingLayerIDProperty;
13 |
14 | SkeletonUtilitySubmeshRenderer component;
15 |
16 | void OnEnable () {
17 | component = (SkeletonUtilitySubmeshRenderer)target;
18 |
19 | if (EditorGUILayoutSortingLayerField == null)
20 | EditorGUILayoutSortingLayerField = typeof(EditorGUILayout).GetMethod("SortingLayerField", BindingFlags.Static | BindingFlags.NonPublic, null, new Type[] { typeof(GUIContent), typeof(SerializedProperty), typeof(GUIStyle) }, null);
21 |
22 | rendererSerializedObject = new SerializedObject(((SkeletonUtilitySubmeshRenderer)target).GetComponent());
23 | sortingLayerIDProperty = rendererSerializedObject.FindProperty("m_SortingLayerID");
24 | }
25 |
26 | public override void OnInspectorGUI () {
27 | // Sorting Layers
28 | {
29 | var renderer = component.GetComponent();
30 | if (renderer != null) {
31 | EditorGUI.BeginChangeCheck();
32 |
33 | if (EditorGUILayoutSortingLayerField != null && sortingLayerIDProperty != null) {
34 | EditorGUILayoutSortingLayerField.Invoke(null, new object[] { new GUIContent("Sorting Layer"), sortingLayerIDProperty, EditorStyles.popup });
35 | } else {
36 | renderer.sortingLayerID = EditorGUILayout.IntField("Sorting Layer ID", renderer.sortingLayerID);
37 | }
38 |
39 | renderer.sortingOrder = EditorGUILayout.IntField("Order in Layer", renderer.sortingOrder);
40 |
41 | if (EditorGUI.EndChangeCheck()) {
42 | rendererSerializedObject.ApplyModifiedProperties();
43 | EditorUtility.SetDirty(renderer);
44 | }
45 | }
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/spine-unity/SkeletonUtility/SkeletonUtilityConstraint.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 | using System.Collections;
3 |
4 | [RequireComponent(typeof(SkeletonUtilityBone)), ExecuteInEditMode]
5 |
6 | public abstract class SkeletonUtilityConstraint : MonoBehaviour {
7 |
8 | protected SkeletonUtilityBone utilBone;
9 | protected SkeletonUtility skeletonUtility;
10 |
11 | protected virtual void OnEnable () {
12 | utilBone = GetComponent();
13 | skeletonUtility = SkeletonUtility.GetInParent(transform);
14 | skeletonUtility.RegisterConstraint(this);
15 | }
16 |
17 | protected virtual void OnDisable () {
18 | skeletonUtility.UnregisterConstraint(this);
19 | }
20 |
21 | public abstract void DoUpdate ();
22 | }
23 |
--------------------------------------------------------------------------------
/spine-unity/SkeletonUtility/SkeletonUtilityEyeConstraint.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 | using System.Collections;
3 |
4 | public class SkeletonUtilityEyeConstraint : SkeletonUtilityConstraint {
5 |
6 | public Transform[] eyes;
7 | public float radius = 0.5f;
8 | public Transform target;
9 | public Vector3 targetPosition;
10 | public float speed = 10;
11 | Vector3[] origins;
12 | Vector3 centerPoint;
13 |
14 | protected override void OnEnable () {
15 | if (!Application.isPlaying)
16 | return;
17 |
18 | base.OnEnable();
19 |
20 | Bounds centerBounds = new Bounds(eyes[0].localPosition, Vector3.zero);
21 | origins = new Vector3[eyes.Length];
22 | for (int i = 0; i < eyes.Length; i++) {
23 | origins[i] = eyes[i].localPosition;
24 | centerBounds.Encapsulate(origins[i]);
25 | }
26 |
27 | centerPoint = centerBounds.center;
28 | }
29 |
30 | protected override void OnDisable () {
31 | if (!Application.isPlaying)
32 | return;
33 |
34 | base.OnDisable();
35 | }
36 |
37 | public override void DoUpdate () {
38 |
39 | if (target != null)
40 | targetPosition = target.position;
41 |
42 | Vector3 goal = targetPosition;
43 |
44 | Vector3 center = transform.TransformPoint(centerPoint);
45 | Vector3 dir = goal - center;
46 |
47 | if (dir.magnitude > 1)
48 | dir.Normalize();
49 |
50 | for (int i = 0; i < eyes.Length; i++) {
51 | center = transform.TransformPoint(origins[i]);
52 | eyes[i].position = Vector3.MoveTowards(eyes[i].position, center + (dir * radius), speed * Time.deltaTime);
53 | }
54 |
55 | }
56 | }
--------------------------------------------------------------------------------
/spine-unity/SkeletonUtility/SkeletonUtilityGroundConstraint.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 | using System.Collections;
3 |
4 | [RequireComponent(typeof(SkeletonUtilityBone)), ExecuteInEditMode]
5 | public class SkeletonUtilityGroundConstraint : SkeletonUtilityConstraint {
6 |
7 | #if UNITY_4_3
8 | public LayerMask groundMask;
9 | public bool use2D = false;
10 | public bool useRadius = false;
11 | public float castRadius = 0.1f;
12 | public float castDistance = 5f;
13 | public float castOffset = 0;
14 | public float groundOffset = 0;
15 | public float adjustSpeed = 5;
16 | #else
17 | [Tooltip("LayerMask for what objects to raycast against")]
18 | public LayerMask groundMask;
19 | [Tooltip("The 2D")]
20 | public bool use2D = false;
21 | [Tooltip("Uses SphereCast for 3D mode and CircleCast for 2D mode")]
22 | public bool useRadius = false;
23 | [Tooltip("The Radius")]
24 | public float castRadius = 0.1f;
25 | [Tooltip("How high above the target bone to begin casting from")]
26 | public float castDistance = 5f;
27 | [Tooltip("X-Axis adjustment")]
28 | public float castOffset = 0;
29 | [Tooltip("Y-Axis adjustment")]
30 | public float groundOffset = 0;
31 | [Tooltip("How fast the target IK position adjusts to the ground. Use smaller values to prevent snapping")]
32 | public float adjustSpeed = 5;
33 | #endif
34 |
35 |
36 | Vector3 rayOrigin;
37 | Vector3 rayDir = new Vector3(0, -1, 0);
38 | float hitY;
39 | float lastHitY;
40 |
41 | protected override void OnEnable () {
42 | base.OnEnable();
43 | }
44 |
45 | protected override void OnDisable () {
46 | base.OnDisable();
47 | }
48 |
49 | public override void DoUpdate () {
50 | rayOrigin = transform.position + new Vector3(castOffset, castDistance, 0);
51 |
52 | hitY = float.MinValue;
53 | if (use2D) {
54 | RaycastHit2D hit;
55 |
56 | if (useRadius) {
57 | #if UNITY_4_3
58 | //NOTE: Unity 4.3.x does not have CircleCast
59 | hit = Physics2D.Raycast(rayOrigin , rayDir, castDistance + groundOffset, groundMask);
60 | #else
61 | hit = Physics2D.CircleCast(rayOrigin, castRadius, rayDir, castDistance + groundOffset, groundMask);
62 | #endif
63 | } else {
64 | hit = Physics2D.Raycast(rayOrigin, rayDir, castDistance + groundOffset, groundMask);
65 | }
66 |
67 | if (hit.collider != null) {
68 | hitY = hit.point.y + groundOffset;
69 | if (Application.isPlaying) {
70 | hitY = Mathf.MoveTowards(lastHitY, hitY, adjustSpeed * Time.deltaTime);
71 | }
72 | } else {
73 | if (Application.isPlaying)
74 | hitY = Mathf.MoveTowards(lastHitY, transform.position.y, adjustSpeed * Time.deltaTime);
75 | }
76 | } else {
77 | RaycastHit hit;
78 | bool validHit = false;
79 |
80 | if (useRadius) {
81 | validHit = Physics.SphereCast(rayOrigin, castRadius, rayDir, out hit, castDistance + groundOffset, groundMask);
82 | } else {
83 | validHit = Physics.Raycast(rayOrigin, rayDir, out hit, castDistance + groundOffset, groundMask);
84 | }
85 |
86 | if (validHit) {
87 | hitY = hit.point.y + groundOffset;
88 | if (Application.isPlaying) {
89 | hitY = Mathf.MoveTowards(lastHitY, hitY, adjustSpeed * Time.deltaTime);
90 | }
91 | } else {
92 | if (Application.isPlaying)
93 | hitY = Mathf.MoveTowards(lastHitY, transform.position.y, adjustSpeed * Time.deltaTime);
94 | }
95 | }
96 |
97 | Vector3 v = transform.position;
98 | v.y = Mathf.Clamp(v.y, Mathf.Min(lastHitY, hitY), float.MaxValue);
99 | transform.position = v;
100 |
101 | utilBone.bone.X = transform.localPosition.x;
102 | utilBone.bone.Y = transform.localPosition.y;
103 |
104 | lastHitY = hitY;
105 | }
106 |
107 | void OnDrawGizmos () {
108 | Vector3 hitEnd = rayOrigin + (rayDir * Mathf.Min(castDistance, rayOrigin.y - hitY));
109 | Vector3 clearEnd = rayOrigin + (rayDir * castDistance);
110 | Gizmos.DrawLine(rayOrigin, hitEnd);
111 |
112 | if (useRadius) {
113 | Gizmos.DrawLine(new Vector3(hitEnd.x - castRadius, hitEnd.y - groundOffset, hitEnd.z), new Vector3(hitEnd.x + castRadius, hitEnd.y - groundOffset, hitEnd.z));
114 | Gizmos.DrawLine(new Vector3(clearEnd.x - castRadius, clearEnd.y, clearEnd.z), new Vector3(clearEnd.x + castRadius, clearEnd.y, clearEnd.z));
115 | }
116 |
117 | Gizmos.color = Color.red;
118 | Gizmos.DrawLine(hitEnd, clearEnd);
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/spine-unity/SkeletonUtility/SkeletonUtilityKinematicShadow.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 | using System.Collections;
3 | using System.Collections.Generic;
4 |
5 | public class SkeletonUtilityKinematicShadow : MonoBehaviour {
6 | public bool hideShadow = true;
7 | public Transform parent;
8 | Dictionary shadowTable;
9 | GameObject shadowRoot;
10 |
11 | void Start () {
12 | shadowRoot = (GameObject)Instantiate(gameObject);
13 | if (hideShadow)
14 | shadowRoot.hideFlags = HideFlags.HideInHierarchy;
15 |
16 | if(parent == null)
17 | shadowRoot.transform.parent = transform.root;
18 | else
19 | shadowRoot.transform.parent = parent;
20 |
21 | shadowTable = new Dictionary();
22 |
23 | Destroy(shadowRoot.GetComponent());
24 |
25 | shadowRoot.transform.position = transform.position;
26 | shadowRoot.transform.rotation = transform.rotation;
27 |
28 | Vector3 scaleRef = transform.TransformPoint(Vector3.right);
29 | float scale = Vector3.Distance(transform.position, scaleRef);
30 | shadowRoot.transform.localScale = Vector3.one;
31 |
32 | var shadowJoints = shadowRoot.GetComponentsInChildren();
33 | foreach (Joint j in shadowJoints) {
34 | j.connectedAnchor *= scale;
35 | }
36 |
37 | var joints = GetComponentsInChildren();
38 | foreach (var j in joints)
39 | Destroy(j);
40 |
41 | var rbs = GetComponentsInChildren();
42 | foreach (var rb in rbs)
43 | Destroy(rb);
44 |
45 | var colliders = GetComponentsInChildren();
46 | foreach (var c in colliders)
47 | Destroy(c);
48 |
49 |
50 | //match by bone name
51 | var shadowBones = shadowRoot.GetComponentsInChildren();
52 | var bones = GetComponentsInChildren();
53 |
54 | //build bone lookup
55 | foreach (var b in bones) {
56 | if (b.gameObject == gameObject)
57 | continue;
58 |
59 | foreach (var sb in shadowBones) {
60 | if (sb.GetComponent() == null)
61 | continue;
62 |
63 | if (sb.boneName == b.boneName) {
64 | shadowTable.Add(sb.transform, b.transform);
65 | break;
66 | }
67 | }
68 | }
69 |
70 | foreach (var b in shadowBones)
71 | Destroy(b);
72 | }
73 |
74 | void FixedUpdate () {
75 | shadowRoot.GetComponent().MovePosition(transform.position);
76 | shadowRoot.GetComponent().MoveRotation(transform.rotation);
77 |
78 | foreach (var pair in shadowTable) {
79 | pair.Value.localPosition = pair.Key.localPosition;
80 | pair.Value.localRotation = pair.Key.localRotation;
81 | }
82 | }
83 | }
--------------------------------------------------------------------------------
/spine-unity/SkeletonUtility/SkeletonUtilitySubmeshRenderer.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 | using System.Collections;
3 |
4 | [ExecuteInEditMode]
5 | public class SkeletonUtilitySubmeshRenderer : MonoBehaviour {
6 | [System.NonSerialized]
7 | public Mesh mesh;
8 | public int submeshIndex = 0;
9 | public Material hiddenPassMaterial;
10 | Renderer cachedRenderer;
11 | MeshFilter filter;
12 | Material[] sharedMaterials;
13 |
14 | void Awake () {
15 | cachedRenderer = GetComponent();
16 | filter = GetComponent();
17 | sharedMaterials = new Material[0];
18 | }
19 |
20 | public void SetMesh (Renderer parentRenderer, Mesh mesh, Material mat) {
21 | if (cachedRenderer == null)
22 | return;
23 |
24 | cachedRenderer.enabled = true;
25 | filter.sharedMesh = mesh;
26 | if (cachedRenderer.sharedMaterials.Length != parentRenderer.sharedMaterials.Length) {
27 | sharedMaterials = parentRenderer.sharedMaterials;
28 | }
29 |
30 | for (int i = 0; i < sharedMaterials.Length; i++) {
31 | if (i == submeshIndex)
32 | sharedMaterials[i] = mat;
33 | else
34 | sharedMaterials[i] = hiddenPassMaterial;
35 | }
36 |
37 | cachedRenderer.sharedMaterials = sharedMaterials;
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/spine-unity/SpineAttributes.cs:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Spine Runtimes Software License
3 | * Version 2.1
4 | *
5 | * Copyright (c) 2013, Esoteric Software
6 | * All rights reserved.
7 | *
8 | * You are granted a perpetual, non-exclusive, non-sublicensable and
9 | * non-transferable license to install, execute and perform the Spine Runtimes
10 | * Software (the "Software") solely for internal use. Without the written
11 | * permission of Esoteric Software (typically granted by licensing Spine), you
12 | * may not (a) modify, translate, adapt or otherwise create derivative works,
13 | * improvements of the Software or develop new applications using the Software
14 | * or (b) remove, delete, alter or obscure any trademarks or any copyright,
15 | * trademark, patent or other intellectual property or proprietary rights
16 | * notices on or in the Software, including any copy thereof. Redistributions
17 | * in binary or source form must include this license and terms.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
22 | * EVENT SHALL ESOTERIC SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 | *****************************************************************************/
30 |
31 | /*****************************************************************************
32 | * Spine Attributes created by Mitch Thompson
33 | * Full irrevocable rights and permissions granted to Esoteric Software
34 | *****************************************************************************/
35 | using UnityEngine;
36 | using System.Collections;
37 |
38 | public class SpineSlot : PropertyAttribute {
39 | public string startsWith = "";
40 | public string dataField = "";
41 |
42 | ///
43 | /// Smart popup menu for Spine Slots
44 | ///
45 | /// Filters popup results to elements that begin with supplied string.
46 | /// If specified, a locally scoped field with the name supplied by in dataField will be used to fill the popup results.
47 | /// Valid types are SkeletonDataAsset and SkeletonRenderer (and derivatives).
48 | /// If left empty and the script the attribute is applied to is derived from Component, GetComponent() will be called as a fallback.
49 | ///
50 | public SpineSlot(string startsWith = "", string dataField = "") {
51 | this.startsWith = startsWith;
52 | this.dataField = dataField;
53 | }
54 | }
55 |
56 | public class SpineSkin : PropertyAttribute {
57 | public string startsWith = "";
58 | public string dataField = "";
59 |
60 | ///
61 | /// Smart popup menu for Spine Skins
62 | ///
63 | /// Filters popup results to elements that begin with supplied string.
64 | /// If specified, a locally scoped field with the name supplied by in dataField will be used to fill the popup results.
65 | /// Valid types are SkeletonDataAsset and SkeletonRenderer (and derivatives)
66 | /// If left empty and the script the attribute is applied to is derived from Component, GetComponent() will be called as a fallback.
67 | ///
68 | public SpineSkin(string startsWith = "", string dataField = "") {
69 | this.startsWith = startsWith;
70 | this.dataField = dataField;
71 | }
72 | }
73 | public class SpineAnimation : PropertyAttribute {
74 | public string startsWith = "";
75 | public string dataField = "";
76 |
77 | ///
78 | /// Smart popup menu for Spine Animations
79 | ///
80 | /// Filters popup results to elements that begin with supplied string.
81 | /// If specified, a locally scoped field with the name supplied by in dataField will be used to fill the popup results.
82 | /// Valid types are SkeletonDataAsset and SkeletonRenderer (and derivatives)
83 | /// If left empty and the script the attribute is applied to is derived from Component, GetComponent() will be called as a fallback.
84 | ///
85 | public SpineAnimation(string startsWith = "", string dataField = "") {
86 | this.startsWith = startsWith;
87 | this.dataField = dataField;
88 | }
89 | }
90 |
91 | public class SpineAttachment : PropertyAttribute {
92 | public bool returnAttachmentPath = false;
93 | public bool currentSkinOnly = false;
94 | public bool placeholdersOnly = false;
95 | public string dataField = "";
96 | public string slotField = "";
97 |
98 |
99 | public SpineAttachment() {
100 |
101 | }
102 |
103 | ///
104 | /// Smart popup menu for Spine Attachments
105 | ///
106 | /// Filters popup results to only include the current Skin. Only valid when a SkeletonRenderer is the data source.
107 | /// Returns a fully qualified path for an Attachment in the format "Skin/Slot/AttachmentName"
108 | /// Filters popup results to exclude attachments that are not children of Skin Placeholders
109 | /// If specified, a locally scoped field with the name supplied by in slotField will be used to limit the popup results to children of a named slot
110 | /// If specified, a locally scoped field with the name supplied by in dataField will be used to fill the popup results.
111 | /// Valid types are SkeletonDataAsset and SkeletonRenderer (and derivatives)
112 | /// If left empty and the script the attribute is applied to is derived from Component, GetComponent() will be called as a fallback.
113 | ///
114 | public SpineAttachment(bool currentSkinOnly = true, bool returnAttachmentPath = false, bool placeholdersOnly = false, string slotField = "", string dataField = "") {
115 | this.currentSkinOnly = currentSkinOnly;
116 | this.returnAttachmentPath = returnAttachmentPath;
117 | this.placeholdersOnly = placeholdersOnly;
118 | this.slotField = slotField;
119 | this.dataField = dataField;
120 | }
121 |
122 | public static Hierarchy GetHierarchy(string fullPath) {
123 | return new Hierarchy(fullPath);
124 | }
125 |
126 | public static Spine.Attachment GetAttachment(string attachmentPath, Spine.SkeletonData skeletonData) {
127 | var hierarchy = SpineAttachment.GetHierarchy(attachmentPath);
128 | if (hierarchy.name == "")
129 | return null;
130 |
131 | return skeletonData.FindSkin(hierarchy.skin).GetAttachment(skeletonData.FindSlotIndex(hierarchy.slot), hierarchy.name);
132 | }
133 |
134 | public static Spine.Attachment GetAttachment(string attachmentPath, SkeletonDataAsset skeletonDataAsset) {
135 | return GetAttachment(attachmentPath, skeletonDataAsset.GetSkeletonData(true));
136 | }
137 |
138 | public struct Hierarchy {
139 | public string skin;
140 | public string slot;
141 | public string name;
142 |
143 | public Hierarchy(string fullPath) {
144 | string[] chunks = fullPath.Split(new char[]{'/'}, System.StringSplitOptions.RemoveEmptyEntries);
145 | if (chunks.Length == 0) {
146 | skin = "";
147 | slot = "";
148 | name = "";
149 | return;
150 | }
151 | else if (chunks.Length < 2) {
152 | throw new System.Exception("Cannot generate Attachment Hierarchy from string! Not enough components! [" + fullPath + "]");
153 | }
154 | skin = chunks[0];
155 | slot = chunks[1];
156 | name = "";
157 | for (int i = 2; i < chunks.Length; i++) {
158 | name += chunks[i];
159 | }
160 | }
161 | }
162 | }
163 |
164 | public class SpineBone : PropertyAttribute {
165 | public string startsWith = "";
166 | public string dataField = "";
167 |
168 | ///
169 | /// Smart popup menu for Spine Bones
170 | ///
171 | /// Filters popup results to elements that begin with supplied string.
172 | /// If specified, a locally scoped field with the name supplied by in dataField will be used to fill the popup results.
173 | /// Valid types are SkeletonDataAsset and SkeletonRenderer (and derivatives)
174 | /// If left empty and the script the attribute is applied to is derived from Component, GetComponent() will be called as a fallback.
175 | ///
176 | public SpineBone(string startsWith = "", string dataField = "") {
177 | this.startsWith = startsWith;
178 | this.dataField = dataField;
179 | }
180 |
181 | public static Spine.Bone GetBone(string boneName, SkeletonRenderer renderer) {
182 | if (renderer.skeleton == null)
183 | return null;
184 |
185 | return renderer.skeleton.FindBone(boneName);
186 | }
187 |
188 | public static Spine.BoneData GetBoneData(string boneName, SkeletonDataAsset skeletonDataAsset) {
189 | var data = skeletonDataAsset.GetSkeletonData(true);
190 |
191 | return data.FindBone(boneName);
192 | }
193 | }
194 |
195 | public class SpineAtlasRegion : PropertyAttribute {
196 | //TODO: Standardize with Skeleton attributes
197 | //NOTE: For now, relies on locally scoped field named "atlasAsset" for source.
198 | }
--------------------------------------------------------------------------------
/spine-unity/SpriteAttacher.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 | using System.Collections;
3 | using System.Collections.Generic;
4 | using Spine;
5 |
6 | public class SpriteAttacher : MonoBehaviour {
7 |
8 |
9 | public bool attachOnStart = true;
10 | public bool keepLoaderInMemory = true;
11 |
12 | public Sprite sprite;
13 |
14 | [SpineSlot]
15 | public string slot;
16 |
17 | private SpriteAttachmentLoader loader;
18 | private RegionAttachment attachment;
19 |
20 | void Start () {
21 | if (attachOnStart)
22 | Attach();
23 | }
24 |
25 | public void Attach () {
26 | var skeletonRenderer = GetComponent();
27 |
28 | if (loader == null)
29 | //create loader instance, tell it what sprite and shader to use
30 | loader = new SpriteAttachmentLoader(sprite, Shader.Find("Spine/Skeleton"));
31 |
32 | if (attachment == null)
33 | attachment = loader.NewRegionAttachment(null, sprite.name, "");
34 |
35 | skeletonRenderer.skeleton.FindSlot(slot).Attachment = attachment;
36 |
37 | if (!keepLoaderInMemory)
38 | loader = null;
39 | }
40 | }
41 |
42 | public class SpriteAttachmentLoader : AttachmentLoader {
43 |
44 | //TODO: Memory cleanup functions
45 |
46 | //IMPORTANT: Make sure you clear this when you don't need it anymore. Goodluck.
47 | public static Dictionary atlasTable = new Dictionary();
48 |
49 | //Shouldn't need to clear this, should just prevent redoing premultiply alpha pass on packed atlases
50 | public static List premultipliedAtlasIds = new List();
51 |
52 | Sprite sprite;
53 | Shader shader;
54 |
55 | public SpriteAttachmentLoader (Sprite sprite, Shader shader) {
56 |
57 | if (sprite.packed && sprite.packingMode == SpritePackingMode.Tight) {
58 | Debug.LogError("Tight Packer Policy not supported yet!");
59 | return;
60 | }
61 |
62 | this.sprite = sprite;
63 | this.shader = shader;
64 |
65 | Texture2D tex = sprite.texture;
66 | //premultiply texture if it hasn't been yet
67 | int instanceId = tex.GetInstanceID();
68 | if (!premultipliedAtlasIds.Contains(instanceId)) {
69 | try {
70 | var colors = tex.GetPixels();
71 | Color c;
72 | float a;
73 | for (int i = 0; i < colors.Length; i++) {
74 | c = colors[i];
75 | a = c.a;
76 | c.r *= a;
77 | c.g *= a;
78 | c.b *= a;
79 | colors[i] = c;
80 | }
81 |
82 | tex.SetPixels(colors);
83 | tex.Apply();
84 |
85 | premultipliedAtlasIds.Add(instanceId);
86 | } catch {
87 | //texture is not readable! Can't pre-multiply it, you're on your own.
88 | }
89 | }
90 | }
91 |
92 | public RegionAttachment NewRegionAttachment (Skin skin, string name, string path) {
93 | RegionAttachment attachment = new RegionAttachment(name);
94 |
95 | Texture2D tex = sprite.texture;
96 | int instanceId = tex.GetInstanceID();
97 | AtlasRegion atlasRegion;
98 |
99 | //check cache first
100 | if (atlasTable.ContainsKey(instanceId)) {
101 | atlasRegion = atlasTable[instanceId];
102 | } else {
103 | //Setup new material
104 | Material mat = new Material(shader);
105 | if (sprite.packed)
106 | mat.name = "Unity Packed Sprite Material";
107 | else
108 | mat.name = sprite.name + " Sprite Material";
109 | mat.mainTexture = tex;
110 |
111 | //create faux-region to play nice with SkeletonRenderer
112 | atlasRegion = new AtlasRegion();
113 | AtlasPage page = new AtlasPage();
114 | page.rendererObject = mat;
115 | atlasRegion.page = page;
116 |
117 | //cache it
118 | atlasTable[instanceId] = atlasRegion;
119 | }
120 |
121 | Rect texRect = sprite.textureRect;
122 |
123 | //normalize rect to UV space of packed atlas
124 | texRect.x = Mathf.InverseLerp(0, tex.width, texRect.x);
125 | texRect.y = Mathf.InverseLerp(0, tex.height, texRect.y);
126 | texRect.width = Mathf.InverseLerp(0, tex.width, texRect.width);
127 | texRect.height = Mathf.InverseLerp(0, tex.height, texRect.height);
128 |
129 | Bounds bounds = sprite.bounds;
130 | Vector3 size = bounds.size;
131 |
132 | //TODO: make sure this rotation thing actually works
133 | bool rotated = false;
134 | if (sprite.packed)
135 | rotated = sprite.packingRotation == SpritePackingRotation.Any;
136 |
137 | //do some math and assign UVs and sizes
138 | attachment.SetUVs(texRect.xMin, texRect.yMax, texRect.xMax, texRect.yMin, rotated);
139 | attachment.RendererObject = atlasRegion;
140 | attachment.SetColor(Color.white);
141 | attachment.ScaleX = 1;
142 | attachment.ScaleY = 1;
143 | attachment.RegionOffsetX = sprite.rect.width * (0.5f - Mathf.InverseLerp(bounds.min.x, bounds.max.x, 0)) / sprite.pixelsPerUnit;
144 | attachment.RegionOffsetY = sprite.rect.height * (0.5f - Mathf.InverseLerp(bounds.min.y, bounds.max.y, 0)) / sprite.pixelsPerUnit;
145 | attachment.Width = size.x;
146 | attachment.Height = size.y;
147 | attachment.RegionWidth = size.x;
148 | attachment.RegionHeight = size.y;
149 | attachment.RegionOriginalWidth = size.x;
150 | attachment.RegionOriginalHeight = size.y;
151 | attachment.UpdateOffset();
152 |
153 | return attachment;
154 | }
155 |
156 | public MeshAttachment NewMeshAttachment (Skin skin, string name, string path) {
157 | //TODO: Unity 5 only
158 | throw new System.NotImplementedException();
159 | }
160 |
161 | public SkinnedMeshAttachment NewSkinnedMeshAttachment (Skin skin, string name, string path) {
162 | throw new System.NotImplementedException();
163 | }
164 |
165 | public BoundingBoxAttachment NewBoundingBoxAttachment (Skin skin, string name) {
166 | throw new System.NotImplementedException();
167 | }
168 | }
--------------------------------------------------------------------------------
/spine-unity/SpriteCollectionAttachmentLoader.cs:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Spine Runtimes Software License
3 | * Version 2.1
4 | *
5 | * Copyright (c) 2013, Esoteric Software
6 | * All rights reserved.
7 | *
8 | * You are granted a perpetual, non-exclusive, non-sublicensable and
9 | * non-transferable license to install, execute and perform the Spine Runtimes
10 | * Software (the "Software") solely for internal use. Without the written
11 | * permission of Esoteric Software (typically granted by licensing Spine), you
12 | * may not (a) modify, translate, adapt or otherwise create derivative works,
13 | * improvements of the Software or develop new applications using the Software
14 | * or (b) remove, delete, alter or obscure any trademarks or any copyright,
15 | * trademark, patent or other intellectual property or proprietary rights
16 | * notices on or in the Software, including any copy thereof. Redistributions
17 | * in binary or source form must include this license and terms.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
22 | * EVENT SHALL ESOTERIC SOFTARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 | *****************************************************************************/
30 |
31 | #if SPINE_TK2D
32 | using System;
33 | using UnityEngine;
34 | using Spine;
35 |
36 | // TODO: handle TPackerCW flip mode (probably not swap uv horizontaly)
37 |
38 | public class SpriteCollectionAttachmentLoader : AttachmentLoader {
39 | private tk2dSpriteCollectionData sprites;
40 | private float u, v, u2, v2;
41 | private bool regionRotated;
42 | private float regionOriginalWidth, regionOriginalHeight;
43 | private float regionWidth, regionHeight;
44 | private float regionOffsetX, regionOffsetY;
45 | private Material material;
46 |
47 | public SpriteCollectionAttachmentLoader (tk2dSpriteCollectionData sprites) {
48 | if (sprites == null)
49 | throw new ArgumentNullException("sprites cannot be null.");
50 | this.sprites = sprites;
51 | }
52 |
53 | private void ProcessSpriteDefinition (String name) {
54 | // Strip folder names.
55 | int index = name.LastIndexOfAny(new char[] {'/', '\\'});
56 | if (index != -1)
57 | name = name.Substring(index + 1);
58 |
59 | tk2dSpriteDefinition def = sprites.inst.GetSpriteDefinition(name);
60 |
61 | if (def == null) {
62 | Debug.Log("Sprite not found in atlas: " + name, sprites);
63 | throw new Exception("Sprite not found in atlas: " + name);
64 | }
65 | if (def.complexGeometry)
66 | throw new NotImplementedException("Complex geometry is not supported: " + name);
67 | if (def.flipped == tk2dSpriteDefinition.FlipMode.TPackerCW)
68 | throw new NotImplementedException("Only 2D Toolkit atlases are supported: " + name);
69 |
70 | Vector2 minTexCoords = Vector2.one, maxTexCoords = Vector2.zero;
71 | for (int i = 0; i < def.uvs.Length; ++i) {
72 | Vector2 uv = def.uvs[i];
73 | minTexCoords = Vector2.Min(minTexCoords, uv);
74 | maxTexCoords = Vector2.Max(maxTexCoords, uv);
75 | }
76 | regionRotated = def.flipped == tk2dSpriteDefinition.FlipMode.Tk2d;
77 | if (regionRotated) {
78 | float temp = minTexCoords.x;
79 | minTexCoords.x = maxTexCoords.x;
80 | maxTexCoords.x = temp;
81 | }
82 | u = minTexCoords.x;
83 | v = maxTexCoords.y;
84 | u2 = maxTexCoords.x;
85 | v2 = minTexCoords.y;
86 |
87 | regionOriginalWidth = (int)(def.untrimmedBoundsData[1].x / def.texelSize.x);
88 | regionOriginalHeight = (int)(def.untrimmedBoundsData[1].y / def.texelSize.y);
89 |
90 | regionWidth = (int)(def.boundsData[1].x / def.texelSize.x);
91 | regionHeight = (int)(def.boundsData[1].y / def.texelSize.y);
92 |
93 | float x0 = def.untrimmedBoundsData[0].x - def.untrimmedBoundsData[1].x / 2;
94 | float x1 = def.boundsData[0].x - def.boundsData[1].x / 2;
95 | regionOffsetX = (int)((x1 - x0) / def.texelSize.x);
96 |
97 | float y0 = def.untrimmedBoundsData[0].y - def.untrimmedBoundsData[1].y / 2;
98 | float y1 = def.boundsData[0].y - def.boundsData[1].y / 2;
99 | regionOffsetY = (int)((y1 - y0) / def.texelSize.y);
100 |
101 | material = def.materialInst;
102 | }
103 |
104 | public RegionAttachment NewRegionAttachment (Skin skin, String name, String path) {
105 | ProcessSpriteDefinition(path);
106 |
107 | RegionAttachment region = new RegionAttachment(name);
108 | region.Path = path;
109 | region.RendererObject = material;
110 | region.SetUVs(u, v, u2, v2, regionRotated);
111 | region.RegionOriginalWidth = regionOriginalWidth;
112 | region.RegionOriginalHeight = regionOriginalHeight;
113 | region.RegionWidth = regionWidth;
114 | region.RegionHeight = regionHeight;
115 | region.RegionOffsetX = regionOffsetX;
116 | region.RegionOffsetY = regionOffsetY;
117 | return region;
118 | }
119 |
120 | public MeshAttachment NewMeshAttachment (Skin skin, String name, String path) {
121 | ProcessSpriteDefinition(path);
122 |
123 | MeshAttachment mesh = new MeshAttachment(name);
124 | mesh.Path = path;
125 | mesh.RendererObject = material;
126 | mesh.RegionU = u;
127 | mesh.RegionV = v;
128 | mesh.RegionU2 = u2;
129 | mesh.RegionV2 = v2;
130 | mesh.RegionRotate = regionRotated;
131 | mesh.RegionOriginalWidth = regionOriginalWidth;
132 | mesh.RegionOriginalHeight = regionOriginalHeight;
133 | mesh.RegionWidth = regionWidth;
134 | mesh.RegionHeight = regionHeight;
135 | mesh.RegionOffsetX = regionOffsetX;
136 | mesh.RegionOffsetY = regionOffsetY;
137 | return mesh;
138 | }
139 |
140 | public SkinnedMeshAttachment NewSkinnedMeshAttachment (Skin skin, String name, String path) {
141 | ProcessSpriteDefinition(path);
142 |
143 | SkinnedMeshAttachment mesh = new SkinnedMeshAttachment(name);
144 | mesh.Path = path;
145 | mesh.RendererObject = material;
146 | mesh.RegionU = u;
147 | mesh.RegionV = v;
148 | mesh.RegionU2 = u2;
149 | mesh.RegionV2 = v2;
150 | mesh.RegionRotate = regionRotated;
151 | mesh.RegionOriginalWidth = regionOriginalWidth;
152 | mesh.RegionOriginalHeight = regionOriginalHeight;
153 | mesh.RegionWidth = regionWidth;
154 | mesh.RegionHeight = regionHeight;
155 | mesh.RegionOffsetX = regionOffsetX;
156 | mesh.RegionOffsetY = regionOffsetY;
157 | return mesh;
158 | }
159 |
160 | public BoundingBoxAttachment NewBoundingBoxAttachment (Skin skin, String name) {
161 | return new BoundingBoxAttachment(name);
162 | }
163 | }
164 | #endif
165 |
--------------------------------------------------------------------------------