├── .gitattributes
├── .gitignore
├── BinToJson
├── App.config
├── BinToJson.csproj
├── Program.cs
├── Properties
│ └── AssemblyInfo.cs
├── SkelDataConverter.cs
└── packages.config
├── LICENSE
├── Program.cs
├── README.md
├── spine-csharp.sln
└── spine-csharp
├── LICENSE
├── Properties
└── AssemblyInfo.cs
├── README.md
├── SpineBinaryConverter.sln
├── nuget
└── Spine.1.6.18.nuspec
├── spine-csharp.csproj
└── src
├── Animation.cs
├── AnimationState.cs
├── AnimationStateData.cs
├── Atlas.cs
├── Attachments
├── AtlasAttachmentLoader.cs
├── Attachment.cs
├── AttachmentLoader.cs
├── AttachmentType.cs
├── BoundingBoxAttachment.cs
├── MeshAttachment.cs
├── PathAttachment.cs
├── RegionAttachment.cs
└── VertexAttachment.cs
├── BlendMode.cs
├── Bone.cs
├── BoneData.cs
├── Event.cs
├── EventData.cs
├── ExposedList.cs
├── IUpdatable.cs
├── IkConstraint.cs
├── IkConstraintData.cs
├── Json.cs
├── MathUtils.cs
├── PathConstraint.cs
├── PathConstraintData.cs
├── Skeleton.cs
├── SkeletonBinary.cs
├── SkeletonBounds.cs
├── SkeletonData.cs
├── SkeletonJson.cs
├── Skin.cs
├── Slot.cs
├── SlotData.cs
├── TransformConstraint.cs
└── TransformConstraintData.cs
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.userosscache
8 | *.sln.docstates
9 |
10 | # User-specific files (MonoDevelop/Xamarin Studio)
11 | *.userprefs
12 |
13 | # Build results
14 | [Dd]ebug/
15 | [Dd]ebugPublic/
16 | [Rr]elease/
17 | [Rr]eleases/
18 | x64/
19 | x86/
20 | bld/
21 | [Bb]in/
22 | [Oo]bj/
23 | [Ll]og/
24 |
25 | # Visual Studio 2015 cache/options directory
26 | .vs/
27 | # Uncomment if you have tasks that create the project's static files in wwwroot
28 | #wwwroot/
29 |
30 | # MSTest test Results
31 | [Tt]est[Rr]esult*/
32 | [Bb]uild[Ll]og.*
33 |
34 | # NUNIT
35 | *.VisualState.xml
36 | TestResult.xml
37 |
38 | # Build Results of an ATL Project
39 | [Dd]ebugPS/
40 | [Rr]eleasePS/
41 | dlldata.c
42 |
43 | # DNX
44 | project.lock.json
45 | project.fragment.lock.json
46 | artifacts/
47 |
48 | *_i.c
49 | *_p.c
50 | *_i.h
51 | *.ilk
52 | *.meta
53 | *.obj
54 | *.pch
55 | *.pdb
56 | *.pgc
57 | *.pgd
58 | *.rsp
59 | *.sbr
60 | *.tlb
61 | *.tli
62 | *.tlh
63 | *.tmp
64 | *.tmp_proj
65 | *.log
66 | *.vspscc
67 | *.vssscc
68 | .builds
69 | *.pidb
70 | *.svclog
71 | *.scc
72 |
73 | # Chutzpah Test files
74 | _Chutzpah*
75 |
76 | # Visual C++ cache files
77 | ipch/
78 | *.aps
79 | *.ncb
80 | *.opendb
81 | *.opensdf
82 | *.sdf
83 | *.cachefile
84 | *.VC.db
85 | *.VC.VC.opendb
86 |
87 | # Visual Studio profiler
88 | *.psess
89 | *.vsp
90 | *.vspx
91 | *.sap
92 |
93 | # TFS 2012 Local Workspace
94 | $tf/
95 |
96 | # Guidance Automation Toolkit
97 | *.gpState
98 |
99 | # ReSharper is a .NET coding add-in
100 | _ReSharper*/
101 | *.[Rr]e[Ss]harper
102 | *.DotSettings.user
103 |
104 | # JustCode is a .NET coding add-in
105 | .JustCode
106 |
107 | # TeamCity is a build add-in
108 | _TeamCity*
109 |
110 | # DotCover is a Code Coverage Tool
111 | *.dotCover
112 |
113 | # NCrunch
114 | _NCrunch_*
115 | .*crunch*.local.xml
116 | nCrunchTemp_*
117 |
118 | # MightyMoose
119 | *.mm.*
120 | AutoTest.Net/
121 |
122 | # Web workbench (sass)
123 | .sass-cache/
124 |
125 | # Installshield output folder
126 | [Ee]xpress/
127 |
128 | # DocProject is a documentation generator add-in
129 | DocProject/buildhelp/
130 | DocProject/Help/*.HxT
131 | DocProject/Help/*.HxC
132 | DocProject/Help/*.hhc
133 | DocProject/Help/*.hhk
134 | DocProject/Help/*.hhp
135 | DocProject/Help/Html2
136 | DocProject/Help/html
137 |
138 | # Click-Once directory
139 | publish/
140 |
141 | # Publish Web Output
142 | *.[Pp]ublish.xml
143 | *.azurePubxml
144 | # TODO: Comment the next line if you want to checkin your web deploy settings
145 | # but database connection strings (with potential passwords) will be unencrypted
146 | #*.pubxml
147 | *.publishproj
148 |
149 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
150 | # checkin your Azure Web App publish settings, but sensitive information contained
151 | # in these scripts will be unencrypted
152 | PublishScripts/
153 |
154 | # NuGet Packages
155 | *.nupkg
156 | # The packages folder can be ignored because of Package Restore
157 | **/packages/*
158 | # except build/, which is used as an MSBuild target.
159 | !**/packages/build/
160 | # Uncomment if necessary however generally it will be regenerated when needed
161 | #!**/packages/repositories.config
162 | # NuGet v3's project.json files produces more ignoreable files
163 | *.nuget.props
164 | *.nuget.targets
165 |
166 | # Microsoft Azure Build Output
167 | csx/
168 | *.build.csdef
169 |
170 | # Microsoft Azure Emulator
171 | ecf/
172 | rcf/
173 |
174 | # Windows Store app package directories and files
175 | AppPackages/
176 | BundleArtifacts/
177 | Package.StoreAssociation.xml
178 | _pkginfo.txt
179 |
180 | # Visual Studio cache files
181 | # files ending in .cache can be ignored
182 | *.[Cc]ache
183 | # but keep track of directories ending in .cache
184 | !*.[Cc]ache/
185 |
186 | # Others
187 | ClientBin/
188 | ~$*
189 | *~
190 | *.dbmdl
191 | *.dbproj.schemaview
192 | *.jfm
193 | *.pfx
194 | *.publishsettings
195 | node_modules/
196 | orleans.codegen.cs
197 |
198 | # Since there are multiple workflows, uncomment next line to ignore bower_components
199 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
200 | #bower_components/
201 |
202 | # RIA/Silverlight projects
203 | Generated_Code/
204 |
205 | # Backup & report files from converting an old project file
206 | # to a newer Visual Studio version. Backup files are not needed,
207 | # because we have git ;-)
208 | _UpgradeReport_Files/
209 | Backup*/
210 | UpgradeLog*.XML
211 | UpgradeLog*.htm
212 |
213 | # SQL Server files
214 | *.mdf
215 | *.ldf
216 |
217 | # Business Intelligence projects
218 | *.rdl.data
219 | *.bim.layout
220 | *.bim_*.settings
221 |
222 | # Microsoft Fakes
223 | FakesAssemblies/
224 |
225 | # GhostDoc plugin setting file
226 | *.GhostDoc.xml
227 |
228 | # Node.js Tools for Visual Studio
229 | .ntvs_analysis.dat
230 |
231 | # Visual Studio 6 build log
232 | *.plg
233 |
234 | # Visual Studio 6 workspace options file
235 | *.opt
236 |
237 | # Visual Studio LightSwitch build output
238 | **/*.HTMLClient/GeneratedArtifacts
239 | **/*.DesktopClient/GeneratedArtifacts
240 | **/*.DesktopClient/ModelManifest.xml
241 | **/*.Server/GeneratedArtifacts
242 | **/*.Server/ModelManifest.xml
243 | _Pvt_Extensions
244 |
245 | # Paket dependency manager
246 | .paket/paket.exe
247 | paket-files/
248 |
249 | # FAKE - F# Make
250 | .fake/
251 |
252 | # JetBrains Rider
253 | .idea/
254 | *.sln.iml
255 |
256 | # CodeRush
257 | .cr/
258 |
259 | # Python Tools for Visual Studio (PTVS)
260 | __pycache__/
261 | *.pyc
--------------------------------------------------------------------------------
/BinToJson/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/BinToJson/BinToJson.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {81612927-658C-4DAD-BF1C-06C5B274EFB5}
8 | Exe
9 | BinToJson
10 | BinToJson
11 | v4.7.1
12 | 512
13 | true
14 | true
15 |
16 |
17 |
18 | AnyCPU
19 | true
20 | full
21 | false
22 | bin\Debug\
23 | DEBUG;TRACE
24 | prompt
25 | 4
26 |
27 |
28 | AnyCPU
29 | pdbonly
30 | true
31 | bin\Release\
32 | TRACE
33 | prompt
34 | 4
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 | {94144e22-2431-4a8f-ac04-dec22f7edd8f}
63 | spine-csharp
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/BinToJson/Program.cs:
--------------------------------------------------------------------------------
1 | using Spine;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using System.IO;
8 | using System.Web.Script.Serialization;
9 |
10 | namespace BinToJson
11 | {
12 |
13 | class Program
14 | {
15 | //Requires a skeleton file as input
16 | static void Main(string[] args) {
17 | if (args.Length < 1) {
18 | Console.WriteLine("Usage: Drag a binary Spine skeleton file onto this executable and this outputs a json-ified version in the same directory");
19 | Console.ReadLine();
20 | return;
21 | }
22 | SkeletonData skeletonData;
23 | string fileName = args[0];
24 |
25 | //determines if the input file is json or bytes
26 | Atlas atlas = new Atlas();
27 | if (fileName.Contains("json")) {
28 | //Converting json -> json is unnecessary, but makes bug-checking significantly easier
29 | var sb = new SkeletonJson(atlas);
30 | skeletonData = sb.ReadSkeletonData(fileName);
31 | } else {
32 | var sb = new SkeletonBinary(atlas);
33 | skeletonData = sb.ReadSkeletonData(fileName);
34 | }
35 | //Takes the skeletonData and converts it into a serializable object
36 | Dictionary jsonFile = SkelDataConverter.FromSkeletonData(skeletonData);
37 |
38 | //convert object to json string for storing
39 | JavaScriptSerializer jsonSerializer = new JavaScriptSerializer();
40 | string json = jsonSerializer.Serialize(jsonFile);
41 |
42 |
43 | //Output file to same directory as input with "name 1", does not allow overwrites
44 | string preExtension = fileName.Substring(0, fileName.LastIndexOf('.'));
45 | int addNum = 1;
46 | string fullerName = preExtension;
47 | while(File.Exists(fullerName + ".json")) {
48 | fullerName = preExtension +" " + addNum;
49 | addNum++;
50 | }
51 | File.WriteAllText(fullerName+".json", json);
52 |
53 |
54 | }
55 |
56 |
57 |
58 | }
59 |
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/BinToJson/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 | [assembly: AssemblyTitle("BinToJson")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("BinToJson")]
13 | [assembly: AssemblyCopyright("Copyright © 2019")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("81612927-658c-4dad-bf1c-06c5b274efb5")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/BinToJson/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Program.cs:
--------------------------------------------------------------------------------
1 | using Spine;
2 | using System;
3 |
4 | namespace BinaryToJson
5 | {
6 | class Program
7 | {
8 | static void Main(string[] args) {
9 | if (args.Length < 1) {
10 | Console.WriteLine("Usage: Drag a binary Spine skeleton file onto this executable and this outputs a json-ified version");
11 | Console.ReadLine();
12 | return;
13 | }
14 | string fileName = args[0];
15 | Atlas atlas = new Atlas();
16 |
17 | var sb = new SkeletonBinary(atlas);
18 | sb.ReadSkeletonData(fileName);
19 |
20 |
21 | Console.ReadLine();
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SpineBinaryConverter
2 | Old Spine binary formats are unreadable with the current Spine animation program, and no backwards compatible version exists to edit Spine binary files before version 3.5. To fix this problem, this program takes old Spine skeleton binary files and converts them to the JSON equivelent so they can be parsed.
3 |
4 | ## Notices
5 | Currently, this repository uses spine-sharp version 3.4 from the [Spine runtimes](https://github.com/EsotericSoftware/spine-runtimes ) and therefore only parses version 3.4 binary files. It is possible to switch out the spine-sharp folder in this repository for a different version on the Spine-sharp github, but doing so will cause the program to fail to compile. More info in the Unfinished Work section under Version Swaping.
6 |
7 |
8 |
9 | ## Unfinished Work: ~85% Complete
10 | 1. Color Support: color timelines are unparsed, so files that change color over time will be unable to do so.
11 | 2. Event Support: files with interactable elements will not parse successfully and throw an error when trying to parse Events.
12 | 3. Version Swaping: Small changes were made to the original spine-sharp project to make parsing binary files easier. Currently the Deformation animations section has been changed to read pre-deformed vertices and offset.
13 |
14 | ## Usage
15 | Simply drag the skeleton file onto the exectuable to run the conversion process. The new file will be output to the same directory as the original file.
16 |
17 | ## Executables
18 | Latest Windows executable in releases or [here](https://github.com/PeterMoras/SpineBinaryConverter/releases/download/v0.85/SpineBinaryConverter.zip)
19 |
--------------------------------------------------------------------------------
/spine-csharp.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.28307.168
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "spine-csharp", "spine-csharp.csproj", "{94144E22-2431-4A8F-AC04-DEC22F7EDD8F}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BinToJson", "..\BinToJson\BinToJson.csproj", "{81612927-658C-4DAD-BF1C-06C5B274EFB5}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | Release|Any CPU = Release|Any CPU
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {94144E22-2431-4A8F-AC04-DEC22F7EDD8F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
17 | {94144E22-2431-4A8F-AC04-DEC22F7EDD8F}.Debug|Any CPU.Build.0 = Debug|Any CPU
18 | {94144E22-2431-4A8F-AC04-DEC22F7EDD8F}.Release|Any CPU.ActiveCfg = Release|Any CPU
19 | {94144E22-2431-4A8F-AC04-DEC22F7EDD8F}.Release|Any CPU.Build.0 = Release|Any CPU
20 | {81612927-658C-4DAD-BF1C-06C5B274EFB5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21 | {81612927-658C-4DAD-BF1C-06C5B274EFB5}.Debug|Any CPU.Build.0 = Debug|Any CPU
22 | {81612927-658C-4DAD-BF1C-06C5B274EFB5}.Release|Any CPU.ActiveCfg = Release|Any CPU
23 | {81612927-658C-4DAD-BF1C-06C5B274EFB5}.Release|Any CPU.Build.0 = Release|Any CPU
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | GlobalSection(ExtensibilityGlobals) = postSolution
29 | SolutionGuid = {8CFA80F9-4049-4F55-AC91-073BAD2AD8D6}
30 | EndGlobalSection
31 | GlobalSection(MonoDevelopProperties) = preSolution
32 | StartupItem = spine-csharp.csproj
33 | EndGlobalSection
34 | EndGlobal
35 |
--------------------------------------------------------------------------------
/spine-csharp/LICENSE:
--------------------------------------------------------------------------------
1 | Spine Runtimes Software License v2.5
2 |
3 | Copyright (c) 2013-2016, Esoteric Software
4 | All rights reserved.
5 |
6 | You are granted a perpetual, non-exclusive, non-sublicensable, and
7 | non-transferable license to use, install, execute, and perform the Spine
8 | Runtimes software and derivative works solely for personal or internal
9 | use. Without the written permission of Esoteric Software (see Section 2 of
10 | the Spine Software License Agreement), you may not (a) modify, translate,
11 | adapt, or develop new applications using the Spine Runtimes or otherwise
12 | create derivative works or improvements of the Spine Runtimes or (b) remove,
13 | delete, alter, or obscure any trademarks or any copyright, trademark, patent,
14 | or other intellectual property or proprietary rights notices on or in the
15 | Software, including any copy thereof. Redistributions in binary or source
16 | form must include this license and terms.
17 |
18 | THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
19 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
21 | EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF
24 | USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25 | IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 | POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------------
/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 | [assembly: AssemblyTitle("spine-csharp")]
9 | [assembly: AssemblyProduct("spine-csharp")]
10 | [assembly: AssemblyDescription("")]
11 | [assembly: AssemblyCompany("Esoteric Software")]
12 | [assembly: AssemblyCopyright("Copyright © Esoteric Software 2013-2016")]
13 | [assembly: AssemblyTrademark("")]
14 | [assembly: AssemblyCulture("")]
15 |
16 | // Setting ComVisible to false makes the types in this assembly not visible
17 | // to COM components. If you need to access a type in this assembly from
18 | // COM, set the ComVisible attribute to true on that type. Only Windows
19 | // assemblies support COM.
20 | [assembly: ComVisible(false)]
21 |
22 | // On Windows, the following GUID is for the ID of the typelib if this
23 | // project is exposed to COM. On other platforms, it unique identifies the
24 | // title storage container when deploying this assembly to the device.
25 | [assembly: Guid("3ac8567e-9ae8-4624-87b9-a84f0101c629")]
26 |
27 | // Version information for an assembly consists of the following four values:
28 | //
29 | // Major Version
30 | // Minor Version
31 | // Build Number
32 | // Revision
33 | //
34 | [assembly: AssemblyVersion("1.0.0.0")]
35 |
--------------------------------------------------------------------------------
/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 | ## Licensing
6 |
7 | This Spine Runtime may only be used for personal or internal use, typically to evaluate Spine before purchasing. If you would like to incorporate a Spine Runtime into your applications, distribute software containing a Spine Runtime, or modify a Spine Runtime, then you will need a valid [Spine license](https://esotericsoftware.com/spine-purchase). Please see the [Spine Runtimes Software License](https://github.com/EsotericSoftware/spine-runtimes/blob/master/LICENSE) for detailed information.
8 |
9 | The Spine Runtimes are developed with the intent to be used with data exported from Spine. By purchasing Spine, `Section 2` of the [Spine Software License](https://esotericsoftware.com/files/license.txt) grants the right to create and distribute derivative works of the Spine Runtimes.
10 |
11 | ## Spine version
12 |
13 | spine-csharp works with data exported from the latest, non-beta version of Spine.
14 |
15 | spine-csharp supports all Spine features.
16 |
17 | ## Setup
18 |
19 | 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).
20 | 1. Open the `spine-csharp.sln` Visual Studio 2015 Community project file.
21 |
22 | Alternatively, the contents of the `spine-csharp/src` directory can be copied into your project.
23 |
24 | ## Runtimes Extending spine-csharp
25 |
26 | - [spine-monogame](https://github.com/EsotericSoftware/spine-runtimes/blob/master/spine-monogame)
27 | - [spine-tk2d](https://github.com/EsotericSoftware/spine-runtimes/blob/master/spine-tk2d)
28 | - [spine-unity](https://github.com/EsotericSoftware/spine-runtimes/blob/master/spine-unity)
29 | - [spine-xna](https://github.com/EsotericSoftware/spine-runtimes/blob/master/spine-xna)
30 |
--------------------------------------------------------------------------------
/spine-csharp/SpineBinaryConverter.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.28307.168
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "spine-csharp", "spine-csharp.csproj", "{94144E22-2431-4A8F-AC04-DEC22F7EDD8F}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BinToJson", "..\BinToJson\BinToJson.csproj", "{81612927-658C-4DAD-BF1C-06C5B274EFB5}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | Release|Any CPU = Release|Any CPU
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {94144E22-2431-4A8F-AC04-DEC22F7EDD8F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
17 | {94144E22-2431-4A8F-AC04-DEC22F7EDD8F}.Debug|Any CPU.Build.0 = Debug|Any CPU
18 | {94144E22-2431-4A8F-AC04-DEC22F7EDD8F}.Release|Any CPU.ActiveCfg = Release|Any CPU
19 | {94144E22-2431-4A8F-AC04-DEC22F7EDD8F}.Release|Any CPU.Build.0 = Release|Any CPU
20 | {81612927-658C-4DAD-BF1C-06C5B274EFB5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21 | {81612927-658C-4DAD-BF1C-06C5B274EFB5}.Debug|Any CPU.Build.0 = Debug|Any CPU
22 | {81612927-658C-4DAD-BF1C-06C5B274EFB5}.Release|Any CPU.ActiveCfg = Release|Any CPU
23 | {81612927-658C-4DAD-BF1C-06C5B274EFB5}.Release|Any CPU.Build.0 = Release|Any CPU
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | GlobalSection(ExtensibilityGlobals) = postSolution
29 | SolutionGuid = {8CFA80F9-4049-4F55-AC91-073BAD2AD8D6}
30 | EndGlobalSection
31 | GlobalSection(MonoDevelopProperties) = preSolution
32 | StartupItem = spine-csharp.csproj
33 | EndGlobalSection
34 | EndGlobal
35 |
--------------------------------------------------------------------------------
/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/spine-csharp.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {94144E22-2431-4A8F-AC04-DEC22F7EDD8F}
5 | 9.0.21022
6 | 2.0
7 | Debug
8 | x86
9 | Library
10 | Properties
11 | Spine
12 | spine-csharp
13 | v4.7.1
14 |
15 |
16 | v4.0
17 | Windows
18 | HiDef
19 | 99dfd52d-8beb-4e5c-a68b-365be39e8064
20 | Library
21 |
22 |
23 | 3.5
24 |
25 |
26 |
27 | true
28 | bin\Debug\
29 | DEBUG;TRACE;WINDOWS
30 | true
31 | full
32 | AnyCPU
33 | false
34 | prompt
35 | false
36 |
37 |
38 | bin\Release\
39 | TRACE;WINDOWS
40 | true
41 | true
42 | pdbonly
43 | AnyCPU
44 | false
45 | prompt
46 | false
47 |
48 |
49 |
50 |
51 |
52 | 4.0
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 | Code
61 |
62 |
63 | Code
64 |
65 |
66 | Code
67 |
68 |
69 | Code
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 | Code
82 |
83 |
84 | Code
85 |
86 |
87 | Code
88 |
89 |
90 | Code
91 |
92 |
93 | Code
94 |
95 |
96 | Code
97 |
98 |
99 | Code
100 |
101 |
102 | Code
103 |
104 |
105 | Code
106 |
107 |
108 |
109 | Code
110 |
111 |
112 |
113 |
114 | Code
115 |
116 |
117 | Code
118 |
119 |
120 | Code
121 |
122 |
123 | Code
124 |
125 |
126 | Code
127 |
128 |
129 | Code
130 |
131 |
132 | Code
133 |
134 |
135 | Code
136 |
137 |
138 | Code
139 |
140 |
141 | Code
142 |
143 |
144 |
145 |
146 |
154 |
--------------------------------------------------------------------------------
/spine-csharp/src/AnimationState.cs:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Spine Runtimes Software License v2.5
3 | *
4 | * Copyright (c) 2013-2016, Esoteric Software
5 | * All rights reserved.
6 | *
7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and
8 | * non-transferable license to use, install, execute, and perform the Spine
9 | * Runtimes software and derivative works solely for personal or internal
10 | * use. Without the written permission of Esoteric Software (see Section 2 of
11 | * the Spine Software License Agreement), you may not (a) modify, translate,
12 | * adapt, or develop new applications using the Spine Runtimes or otherwise
13 | * create derivative works or improvements of the Spine Runtimes or (b) remove,
14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent,
15 | * or other intellectual property or proprietary rights notices on or in the
16 | * Software, including any copy thereof. Redistributions in binary or source
17 | * 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 SOFTWARE 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, BUSINESS INTERRUPTION, OR LOSS OF
25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 | * POSSIBILITY OF SUCH DAMAGE.
29 | *****************************************************************************/
30 |
31 | using System;
32 | using System.Collections.Generic;
33 | using System.Text;
34 |
35 | namespace Spine {
36 | public class AnimationState {
37 | private AnimationStateData data;
38 | private ExposedList tracks = new ExposedList();
39 | private ExposedList events = new ExposedList();
40 | private float timeScale = 1;
41 |
42 | public AnimationStateData Data { get { return data; } }
43 | /// A list of tracks that have animations, which may contain nulls.
44 | public ExposedList Tracks { get { return tracks; } }
45 | public float TimeScale { get { return timeScale; } set { timeScale = value; } }
46 |
47 | public delegate void StartEndDelegate (AnimationState state, int trackIndex);
48 | public event StartEndDelegate Start;
49 | public event StartEndDelegate End;
50 |
51 | public delegate void EventDelegate (AnimationState state, int trackIndex, Event e);
52 | public event EventDelegate Event;
53 |
54 | public delegate void CompleteDelegate (AnimationState state, int trackIndex, int loopCount);
55 | public event CompleteDelegate Complete;
56 |
57 | public AnimationState (AnimationStateData data) {
58 | if (data == null) throw new ArgumentNullException("data", "data cannot be null.");
59 | this.data = data;
60 | }
61 |
62 | public void Update (float delta) {
63 | delta *= timeScale;
64 | for (int i = 0; i < tracks.Count; i++) {
65 | TrackEntry current = tracks.Items[i];
66 | if (current == null) continue;
67 |
68 | float trackDelta = delta * current.timeScale;
69 | float time = current.time + trackDelta;
70 | float endTime = current.endTime;
71 |
72 | current.time = time;
73 | if (current.previous != null) {
74 | current.previous.time += trackDelta;
75 | current.mixTime += trackDelta;
76 | }
77 |
78 | // Check if completed the animation or a loop iteration.
79 | if (current.loop ? (current.lastTime % endTime > time % endTime) : (current.lastTime < endTime && time >= endTime)) {
80 | int count = (int)(time / endTime);
81 | current.OnComplete(this, i, count);
82 | if (Complete != null) Complete(this, i, count);
83 | }
84 |
85 | TrackEntry next = current.next;
86 | if (next != null) {
87 | next.time = current.lastTime - next.delay;
88 | if (next.time >= 0) SetCurrent(i, next);
89 | } else {
90 | // End non-looping animation when it reaches its end time and there is no next entry.
91 | if (!current.loop && current.lastTime >= current.endTime) ClearTrack(i);
92 | }
93 | }
94 | }
95 |
96 | public void Apply (Skeleton skeleton) {
97 | ExposedList events = this.events;
98 |
99 | for (int i = 0; i < tracks.Count; i++) {
100 | TrackEntry current = tracks.Items[i];
101 | if (current == null) continue;
102 |
103 | events.Clear();
104 |
105 | float time = current.time;
106 | bool loop = current.loop;
107 | if (!loop && time > current.endTime) time = current.endTime;
108 |
109 | TrackEntry previous = current.previous;
110 | if (previous == null) {
111 | if (current.mix == 1)
112 | current.animation.Apply(skeleton, current.lastTime, time, loop, events);
113 | else
114 | current.animation.Mix(skeleton, current.lastTime, time, loop, events, current.mix);
115 | } else {
116 | float previousTime = previous.time;
117 | if (!previous.loop && previousTime > previous.endTime) previousTime = previous.endTime;
118 | previous.animation.Apply(skeleton, previous.lastTime, previousTime, previous.loop, null);
119 | // Remove the line above, and uncomment the line below, to allow previous animations to fire events during mixing.
120 | //previous.animation.Apply(skeleton, previous.lastTime, previousTime, previous.loop, events);
121 | previous.lastTime = previousTime;
122 |
123 | float alpha = current.mixTime / current.mixDuration * current.mix;
124 | if (alpha >= 1) {
125 | alpha = 1;
126 | current.previous = null;
127 | }
128 | current.animation.Mix(skeleton, current.lastTime, time, loop, events, alpha);
129 | }
130 |
131 | for (int ii = 0, nn = events.Count; ii < nn; ii++) {
132 | Event e = events.Items[ii];
133 | current.OnEvent(this, i, e);
134 | if (Event != null) Event(this, i, e);
135 | }
136 |
137 | current.lastTime = current.time;
138 | }
139 | }
140 |
141 | public void ClearTracks () {
142 | for (int i = 0, n = tracks.Count; i < n; i++)
143 | ClearTrack(i);
144 | tracks.Clear();
145 | }
146 |
147 | public void ClearTrack (int trackIndex) {
148 | if (trackIndex >= tracks.Count) return;
149 | TrackEntry current = tracks.Items[trackIndex];
150 | if (current == null) return;
151 |
152 | current.OnEnd(this, trackIndex);
153 | if (End != null) End(this, trackIndex);
154 |
155 | tracks.Items[trackIndex] = null;
156 | }
157 |
158 | private TrackEntry ExpandToIndex (int index) {
159 | if (index < tracks.Count) return tracks.Items[index];
160 | while (index >= tracks.Count)
161 | tracks.Add(null);
162 | return null;
163 | }
164 |
165 | private void SetCurrent (int index, TrackEntry entry) {
166 | TrackEntry current = ExpandToIndex(index);
167 | if (current != null) {
168 | TrackEntry previous = current.previous;
169 | current.previous = null;
170 |
171 | current.OnEnd(this, index);
172 | if (End != null) End(this, index);
173 |
174 | entry.mixDuration = data.GetMix(current.animation, entry.animation);
175 | if (entry.mixDuration > 0) {
176 | entry.mixTime = 0;
177 | // If a mix is in progress, mix from the closest animation.
178 | if (previous != null && current.mixTime / current.mixDuration < 0.5f)
179 | entry.previous = previous;
180 | else
181 | entry.previous = current;
182 | }
183 | }
184 |
185 | tracks.Items[index] = entry;
186 |
187 | entry.OnStart(this, index);
188 | if (Start != null) Start(this, index);
189 | }
190 |
191 | ///
192 | public TrackEntry SetAnimation (int trackIndex, String animationName, bool loop) {
193 | Animation animation = data.skeletonData.FindAnimation(animationName);
194 | if (animation == null) throw new ArgumentException("Animation not found: " + animationName, "animationName");
195 | return SetAnimation(trackIndex, animation, loop);
196 | }
197 |
198 | /// Set the current animation. Any queued animations are cleared.
199 | public TrackEntry SetAnimation (int trackIndex, Animation animation, bool loop) {
200 | if (animation == null) throw new ArgumentNullException("animation", "animation cannot be null.");
201 | TrackEntry entry = new TrackEntry();
202 | entry.animation = animation;
203 | entry.loop = loop;
204 | entry.time = 0;
205 | entry.endTime = animation.Duration;
206 | SetCurrent(trackIndex, entry);
207 | return entry;
208 | }
209 |
210 | ///
211 | public TrackEntry AddAnimation (int trackIndex, String animationName, bool loop, float delay) {
212 | Animation animation = data.skeletonData.FindAnimation(animationName);
213 | if (animation == null) throw new ArgumentException("Animation not found: " + animationName, "animationName");
214 | return AddAnimation(trackIndex, animation, loop, delay);
215 | }
216 |
217 | /// Adds an animation to be played delay seconds after the current or last queued animation.
218 | /// May be <= 0 to use duration of previous animation minus any mix duration plus the negative delay.
219 | public TrackEntry AddAnimation (int trackIndex, Animation animation, bool loop, float delay) {
220 | if (animation == null) throw new ArgumentNullException("animation", "animation cannot be null.");
221 | TrackEntry entry = new TrackEntry();
222 | entry.animation = animation;
223 | entry.loop = loop;
224 | entry.time = 0;
225 | entry.endTime = animation.Duration;
226 |
227 | TrackEntry last = ExpandToIndex(trackIndex);
228 | if (last != null) {
229 | while (last.next != null)
230 | last = last.next;
231 | last.next = entry;
232 | } else
233 | tracks.Items[trackIndex] = entry;
234 |
235 | if (delay <= 0) {
236 | if (last != null)
237 | delay += last.endTime - data.GetMix(last.animation, animation);
238 | else
239 | delay = 0;
240 | }
241 | entry.delay = delay;
242 |
243 | return entry;
244 | }
245 |
246 | /// May be null.
247 | public TrackEntry GetCurrent (int trackIndex) {
248 | if (trackIndex >= tracks.Count) return null;
249 | return tracks.Items[trackIndex];
250 | }
251 |
252 | override public String ToString () {
253 | StringBuilder buffer = new StringBuilder();
254 | for (int i = 0, n = tracks.Count; i < n; i++) {
255 | TrackEntry entry = tracks.Items[i];
256 | if (entry == null) continue;
257 | if (buffer.Length > 0) buffer.Append(", ");
258 | buffer.Append(entry.ToString());
259 | }
260 | if (buffer.Length == 0) return "";
261 | return buffer.ToString();
262 | }
263 | }
264 |
265 | public class TrackEntry {
266 | internal TrackEntry next, previous;
267 | internal Animation animation;
268 | internal bool loop;
269 | internal float delay, time, lastTime = -1, endTime, timeScale = 1;
270 | internal float mixTime, mixDuration, mix = 1;
271 |
272 | public Animation Animation { get { return animation; } }
273 | public float Delay { get { return delay; } set { delay = value; } }
274 | public float Time { get { return time; } set { time = value; } }
275 | public float LastTime { get { return lastTime; } set { lastTime = value; } }
276 | public float EndTime { get { return endTime; } set { endTime = value; } }
277 | public float TimeScale { get { return timeScale; } set { timeScale = value; } }
278 | public float Mix { get { return mix; } set { mix = value; } }
279 | public bool Loop { get { return loop; } set { loop = value; } }
280 |
281 | public event AnimationState.StartEndDelegate Start;
282 | public event AnimationState.StartEndDelegate End;
283 | public event AnimationState.EventDelegate Event;
284 | public event AnimationState.CompleteDelegate Complete;
285 |
286 | internal void OnStart (AnimationState state, int index) {
287 | if (Start != null) Start(state, index);
288 | }
289 |
290 | internal void OnEnd (AnimationState state, int index) {
291 | if (End != null) End(state, index);
292 | }
293 |
294 | internal void OnEvent (AnimationState state, int index, Event e) {
295 | if (Event != null) Event(state, index, e);
296 | }
297 |
298 | internal void OnComplete (AnimationState state, int index, int loopCount) {
299 | if (Complete != null) Complete(state, index, loopCount);
300 | }
301 |
302 | override public String ToString () {
303 | return animation == null ? "" : animation.name;
304 | }
305 | }
306 | }
307 |
--------------------------------------------------------------------------------
/spine-csharp/src/AnimationStateData.cs:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Spine Runtimes Software License v2.5
3 | *
4 | * Copyright (c) 2013-2016, Esoteric Software
5 | * All rights reserved.
6 | *
7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and
8 | * non-transferable license to use, install, execute, and perform the Spine
9 | * Runtimes software and derivative works solely for personal or internal
10 | * use. Without the written permission of Esoteric Software (see Section 2 of
11 | * the Spine Software License Agreement), you may not (a) modify, translate,
12 | * adapt, or develop new applications using the Spine Runtimes or otherwise
13 | * create derivative works or improvements of the Spine Runtimes or (b) remove,
14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent,
15 | * or other intellectual property or proprietary rights notices on or in the
16 | * Software, including any copy thereof. Redistributions in binary or source
17 | * 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 SOFTWARE 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, BUSINESS INTERRUPTION, OR LOSS OF
25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 | * 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 animationToMixTime = new Dictionary(AnimationPairComparer.Instance);
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 | if (skeletonData == null) throw new ArgumentException ("skeletonData cannot be null.");
45 | this.skeletonData = skeletonData;
46 | }
47 |
48 | public void SetMix (String fromName, String toName, float duration) {
49 | Animation from = skeletonData.FindAnimation(fromName);
50 | if (from == null) throw new ArgumentException("Animation not found: " + fromName);
51 | Animation to = skeletonData.FindAnimation(toName);
52 | if (to == null) throw new ArgumentException("Animation not found: " + toName);
53 | SetMix(from, to, duration);
54 | }
55 |
56 | public void SetMix (Animation from, Animation to, float duration) {
57 | if (from == null) throw new ArgumentNullException("from", "from cannot be null.");
58 | if (to == null) throw new ArgumentNullException("to", "to cannot be null.");
59 | AnimationPair key = new AnimationPair(from, to);
60 | animationToMixTime.Remove(key);
61 | animationToMixTime.Add(key, duration);
62 | }
63 |
64 | public float GetMix (Animation from, Animation to) {
65 | AnimationPair key = new AnimationPair(from, to);
66 | float duration;
67 | if (animationToMixTime.TryGetValue(key, out duration)) return duration;
68 | return defaultMix;
69 | }
70 |
71 | struct AnimationPair {
72 | public readonly Animation a1;
73 | public readonly Animation a2;
74 |
75 | public AnimationPair (Animation a1, Animation a2) {
76 | this.a1 = a1;
77 | this.a2 = a2;
78 | }
79 | }
80 |
81 | // Avoids boxing in the dictionary.
82 | class AnimationPairComparer : IEqualityComparer {
83 | internal static readonly AnimationPairComparer Instance = new AnimationPairComparer();
84 |
85 | bool IEqualityComparer.Equals (AnimationPair x, AnimationPair y) {
86 | return ReferenceEquals(x.a1, y.a1) && ReferenceEquals(x.a2, y.a2);
87 | }
88 |
89 | int IEqualityComparer.GetHashCode (AnimationPair obj) {
90 | // from Tuple.CombineHashCodes // return (((h1 << 5) + h1) ^ h2);
91 | int h1 = obj.a1.GetHashCode();
92 | return (((h1 << 5) + h1) ^ obj.a2.GetHashCode());
93 | }
94 | }
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/spine-csharp/src/Atlas.cs:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Spine Runtimes Software License v2.5
3 | *
4 | * Copyright (c) 2013-2016, Esoteric Software
5 | * All rights reserved.
6 | *
7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and
8 | * non-transferable license to use, install, execute, and perform the Spine
9 | * Runtimes software and derivative works solely for personal or internal
10 | * use. Without the written permission of Esoteric Software (see Section 2 of
11 | * the Spine Software License Agreement), you may not (a) modify, translate,
12 | * adapt, or develop new applications using the Spine Runtimes or otherwise
13 | * create derivative works or improvements of the Spine Runtimes or (b) remove,
14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent,
15 | * or other intellectual property or proprietary rights notices on or in the
16 | * Software, including any copy thereof. Redistributions in binary or source
17 | * 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 SOFTWARE 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, BUSINESS INTERRUPTION, OR LOSS OF
25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 | * POSSIBILITY OF SUCH DAMAGE.
29 | *****************************************************************************/
30 |
31 | using System;
32 | using System.Collections.Generic;
33 | using System.IO;
34 | using System.Reflection;
35 |
36 | #if WINDOWS_STOREAPP
37 | using System.Threading.Tasks;
38 | using Windows.Storage;
39 | #endif
40 |
41 | namespace Spine {
42 | public class Atlas {
43 | List pages = new List();
44 | List regions = new List();
45 | TextureLoader textureLoader;
46 |
47 | #if !(UNITY_5 || UNITY_4 || UNITY_WSA || UNITY_WP8 || UNITY_WP8_1) // !UNITY
48 | #if WINDOWS_STOREAPP
49 | private async Task ReadFile(string path, TextureLoader textureLoader) {
50 | var folder = Windows.ApplicationModel.Package.Current.InstalledLocation;
51 | var file = await folder.GetFileAsync(path).AsTask().ConfigureAwait(false);
52 | using (var reader = new StreamReader(await file.OpenStreamForReadAsync().ConfigureAwait(false))) {
53 | try {
54 | Load(reader, Path.GetDirectoryName(path), textureLoader);
55 | } catch (Exception ex) {
56 | throw new Exception("Error reading atlas file: " + path, ex);
57 | }
58 | }
59 | }
60 |
61 | public Atlas(String path, TextureLoader textureLoader) {
62 | this.ReadFile(path, textureLoader).Wait();
63 | }
64 | #else
65 |
66 | public Atlas (String path, TextureLoader textureLoader) {
67 |
68 | #if WINDOWS_PHONE
69 | Stream stream = Microsoft.Xna.Framework.TitleContainer.OpenStream(path);
70 | using (StreamReader reader = new StreamReader(stream)) {
71 | #else
72 | using (StreamReader reader = new StreamReader(path)) {
73 | #endif // WINDOWS_PHONE
74 |
75 | try {
76 | Load(reader, Path.GetDirectoryName(path), textureLoader);
77 | } catch (Exception ex) {
78 | throw new Exception("Error reading atlas file: " + path, ex);
79 | }
80 |
81 | }
82 | }
83 | #endif // WINDOWS_STOREAPP
84 |
85 | #endif // !(UNITY)
86 | public Atlas() {
87 | //initialize empty atlas
88 | }
89 | public Atlas (TextReader reader, String dir, TextureLoader textureLoader) {
90 | Load(reader, dir, textureLoader);
91 | }
92 |
93 | public Atlas (List pages, List regions) {
94 | this.pages = pages;
95 | this.regions = regions;
96 | this.textureLoader = null;
97 | }
98 |
99 | private void Load (TextReader reader, String imagesDir, TextureLoader textureLoader) {
100 | if (textureLoader == null) throw new ArgumentNullException("textureLoader cannot be null.");
101 | this.textureLoader = textureLoader;
102 |
103 | String[] tuple = new String[4];
104 | AtlasPage page = null;
105 | while (true) {
106 | String line = reader.ReadLine();
107 | if (line == null) break;
108 | if (line.Trim().Length == 0)
109 | page = null;
110 | else if (page == null) {
111 | page = new AtlasPage();
112 | page.name = line;
113 |
114 | if (ReadTuple(reader, tuple) == 2) { // size is only optional for an atlas packed with an old TexturePacker.
115 | page.width = int.Parse(tuple[0]);
116 | page.height = int.Parse(tuple[1]);
117 | ReadTuple(reader, tuple);
118 | }
119 | page.format = (Format)Enum.Parse(typeof(Format), tuple[0], false);
120 |
121 | ReadTuple(reader, tuple);
122 | page.minFilter = (TextureFilter)Enum.Parse(typeof(TextureFilter), tuple[0], false);
123 | page.magFilter = (TextureFilter)Enum.Parse(typeof(TextureFilter), tuple[1], false);
124 |
125 | String direction = ReadValue(reader);
126 | page.uWrap = TextureWrap.ClampToEdge;
127 | page.vWrap = TextureWrap.ClampToEdge;
128 | if (direction == "x")
129 | page.uWrap = TextureWrap.Repeat;
130 | else if (direction == "y")
131 | page.vWrap = TextureWrap.Repeat;
132 | else if (direction == "xy")
133 | page.uWrap = page.vWrap = TextureWrap.Repeat;
134 |
135 | textureLoader.Load(page, Path.Combine(imagesDir, line));
136 |
137 | pages.Add(page);
138 |
139 | } else {
140 | AtlasRegion region = new AtlasRegion();
141 | region.name = line;
142 | region.page = page;
143 |
144 | region.rotate = Boolean.Parse(ReadValue(reader));
145 |
146 | ReadTuple(reader, tuple);
147 | int x = int.Parse(tuple[0]);
148 | int y = int.Parse(tuple[1]);
149 |
150 | ReadTuple(reader, tuple);
151 | int width = int.Parse(tuple[0]);
152 | int height = int.Parse(tuple[1]);
153 |
154 | region.u = x / (float)page.width;
155 | region.v = y / (float)page.height;
156 | if (region.rotate) {
157 | region.u2 = (x + height) / (float)page.width;
158 | region.v2 = (y + width) / (float)page.height;
159 | } else {
160 | region.u2 = (x + width) / (float)page.width;
161 | region.v2 = (y + height) / (float)page.height;
162 | }
163 | region.x = x;
164 | region.y = y;
165 | region.width = Math.Abs(width);
166 | region.height = Math.Abs(height);
167 |
168 | if (ReadTuple(reader, tuple) == 4) { // split is optional
169 | region.splits = new int[] {int.Parse(tuple[0]), int.Parse(tuple[1]),
170 | int.Parse(tuple[2]), int.Parse(tuple[3])};
171 |
172 | if (ReadTuple(reader, tuple) == 4) { // pad is optional, but only present with splits
173 | region.pads = new int[] {int.Parse(tuple[0]), int.Parse(tuple[1]),
174 | int.Parse(tuple[2]), int.Parse(tuple[3])};
175 |
176 | ReadTuple(reader, tuple);
177 | }
178 | }
179 |
180 | region.originalWidth = int.Parse(tuple[0]);
181 | region.originalHeight = int.Parse(tuple[1]);
182 |
183 | ReadTuple(reader, tuple);
184 | region.offsetX = int.Parse(tuple[0]);
185 | region.offsetY = int.Parse(tuple[1]);
186 |
187 | region.index = int.Parse(ReadValue(reader));
188 |
189 | regions.Add(region);
190 | }
191 | }
192 | }
193 |
194 | static String ReadValue (TextReader reader) {
195 | String line = reader.ReadLine();
196 | int colon = line.IndexOf(':');
197 | if (colon == -1) throw new Exception("Invalid line: " + line);
198 | return line.Substring(colon + 1).Trim();
199 | }
200 |
201 | /// Returns the number of tuple values read (1, 2 or 4).
202 | static int ReadTuple (TextReader reader, String[] tuple) {
203 | String line = reader.ReadLine();
204 | int colon = line.IndexOf(':');
205 | if (colon == -1) throw new Exception("Invalid line: " + line);
206 | int i = 0, lastMatch = colon + 1;
207 | for (; i < 3; i++) {
208 | int comma = line.IndexOf(',', lastMatch);
209 | if (comma == -1) break;
210 | tuple[i] = line.Substring(lastMatch, comma - lastMatch).Trim();
211 | lastMatch = comma + 1;
212 | }
213 | tuple[i] = line.Substring(lastMatch).Trim();
214 | return i + 1;
215 | }
216 |
217 | public void FlipV () {
218 | for (int i = 0, n = regions.Count; i < n; i++) {
219 | AtlasRegion region = regions[i];
220 | region.v = 1 - region.v;
221 | region.v2 = 1 - region.v2;
222 | }
223 | }
224 |
225 | /// Returns the first region found with the specified name. This method uses string comparison to find the region, so the result
226 | /// should be cached rather than calling this method multiple times.
227 | /// The region, or null.
228 | public AtlasRegion FindRegion (String name) {
229 | for (int i = 0, n = regions.Count; i < n; i++)
230 | if (regions[i].name == name) return regions[i];
231 | return null;
232 | }
233 |
234 | public void Dispose () {
235 | if (textureLoader == null) return;
236 | for (int i = 0, n = pages.Count; i < n; i++)
237 | textureLoader.Unload(pages[i].rendererObject);
238 | }
239 | }
240 |
241 | public enum Format {
242 | Alpha,
243 | Intensity,
244 | LuminanceAlpha,
245 | RGB565,
246 | RGBA4444,
247 | RGB888,
248 | RGBA8888
249 | }
250 |
251 | public enum TextureFilter {
252 | Nearest,
253 | Linear,
254 | MipMap,
255 | MipMapNearestNearest,
256 | MipMapLinearNearest,
257 | MipMapNearestLinear,
258 | MipMapLinearLinear
259 | }
260 |
261 | public enum TextureWrap {
262 | MirroredRepeat,
263 | ClampToEdge,
264 | Repeat
265 | }
266 |
267 | public class AtlasPage {
268 | public String name;
269 | public Format format;
270 | public TextureFilter minFilter;
271 | public TextureFilter magFilter;
272 | public TextureWrap uWrap;
273 | public TextureWrap vWrap;
274 | public Object rendererObject;
275 | public int width, height;
276 | }
277 |
278 | public class AtlasRegion {
279 | public AtlasPage page;
280 | public String name;
281 | public int x, y, width, height;
282 | public float u, v, u2, v2;
283 | public float offsetX, offsetY;
284 | public int originalWidth, originalHeight;
285 | public int index;
286 | public bool rotate;
287 | public int[] splits;
288 | public int[] pads;
289 | }
290 |
291 | public interface TextureLoader {
292 | void Load (AtlasPage page, String path);
293 | void Unload (Object texture);
294 | }
295 | }
296 |
--------------------------------------------------------------------------------
/spine-csharp/src/Attachments/AtlasAttachmentLoader.cs:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Spine Runtimes Software License v2.5
3 | *
4 | * Copyright (c) 2013-2016, Esoteric Software
5 | * All rights reserved.
6 | *
7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and
8 | * non-transferable license to use, install, execute, and perform the Spine
9 | * Runtimes software and derivative works solely for personal or internal
10 | * use. Without the written permission of Esoteric Software (see Section 2 of
11 | * the Spine Software License Agreement), you may not (a) modify, translate,
12 | * adapt, or develop new applications using the Spine Runtimes or otherwise
13 | * create derivative works or improvements of the Spine Runtimes or (b) remove,
14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent,
15 | * or other intellectual property or proprietary rights notices on or in the
16 | * Software, including any copy thereof. Redistributions in binary or source
17 | * 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 SOFTWARE 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, BUSINESS INTERRUPTION, OR LOSS OF
25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 | * POSSIBILITY OF SUCH DAMAGE.
29 | *****************************************************************************/
30 |
31 | using System;
32 |
33 | namespace Spine {
34 | public class AtlasAttachmentLoader : AttachmentLoader {
35 | private Atlas[] atlasArray;
36 |
37 | public AtlasAttachmentLoader (params Atlas[] atlasArray) {
38 | if (atlasArray == null) throw new ArgumentNullException("atlas array cannot be null.");
39 | this.atlasArray = atlasArray;
40 | }
41 |
42 | public RegionAttachment NewRegionAttachment (Skin skin, String name, String path) {
43 | AtlasRegion region = FindRegion(path);
44 | if (region == null)
45 | region = new AtlasRegion();
46 | if (region == null) throw new Exception("Region not found in atlas: " + path + " (region attachment: " + name + ")");
47 | RegionAttachment attachment = new RegionAttachment(name);
48 | attachment.RendererObject = region;
49 | attachment.SetUVs(region.u, region.v, region.u2, region.v2, region.rotate);
50 | attachment.regionOffsetX = region.offsetX;
51 | attachment.regionOffsetY = region.offsetY;
52 | attachment.regionWidth = region.width;
53 | attachment.regionHeight = region.height;
54 | attachment.regionOriginalWidth = region.originalWidth;
55 | attachment.regionOriginalHeight = region.originalHeight;
56 | return attachment;
57 | }
58 |
59 | public MeshAttachment NewMeshAttachment (Skin skin, String name, String path) {
60 |
61 | AtlasRegion region = FindRegion(path);
62 | if (region == null)
63 | region = new AtlasRegion();
64 | if (region == null) throw new Exception("Region not found in atlas: " + path + " (mesh attachment: " + name + ")");
65 | MeshAttachment attachment = new MeshAttachment(name);
66 | attachment.RendererObject = region;
67 | attachment.RegionU = region.u;
68 | attachment.RegionV = region.v;
69 | attachment.RegionU2 = region.u2;
70 | attachment.RegionV2 = region.v2;
71 | attachment.RegionRotate = region.rotate;
72 | attachment.regionOffsetX = region.offsetX;
73 | attachment.regionOffsetY = region.offsetY;
74 | attachment.regionWidth = region.width;
75 | attachment.regionHeight = region.height;
76 | attachment.regionOriginalWidth = region.originalWidth;
77 | attachment.regionOriginalHeight = region.originalHeight;
78 | return attachment;
79 | }
80 |
81 | public BoundingBoxAttachment NewBoundingBoxAttachment (Skin skin, String name) {
82 | return new BoundingBoxAttachment(name);
83 | }
84 |
85 | public PathAttachment NewPathAttachment (Skin skin, String name) {
86 | return new PathAttachment (name);
87 | }
88 |
89 | public AtlasRegion FindRegion (string name) {
90 | AtlasRegion region;
91 |
92 | for (int i = 0; i < atlasArray.Length; i++) {
93 | region = atlasArray[i].FindRegion(name);
94 | if (region != null)
95 | return region;
96 | }
97 |
98 | return null;
99 | }
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/spine-csharp/src/Attachments/Attachment.cs:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Spine Runtimes Software License v2.5
3 | *
4 | * Copyright (c) 2013-2016, Esoteric Software
5 | * All rights reserved.
6 | *
7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and
8 | * non-transferable license to use, install, execute, and perform the Spine
9 | * Runtimes software and derivative works solely for personal or internal
10 | * use. Without the written permission of Esoteric Software (see Section 2 of
11 | * the Spine Software License Agreement), you may not (a) modify, translate,
12 | * adapt, or develop new applications using the Spine Runtimes or otherwise
13 | * create derivative works or improvements of the Spine Runtimes or (b) remove,
14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent,
15 | * or other intellectual property or proprietary rights notices on or in the
16 | * Software, including any copy thereof. Redistributions in binary or source
17 | * 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 SOFTWARE 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, BUSINESS INTERRUPTION, OR LOSS OF
25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 | * 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 | public String Type { get; set; }
37 |
38 | public Attachment (String name) {
39 | if (name == null) throw new ArgumentNullException("name", "name cannot be null");
40 | Name = name;
41 | // Type = type;
42 | }
43 |
44 | override public String ToString () {
45 | return Name;
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/spine-csharp/src/Attachments/AttachmentLoader.cs:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Spine Runtimes Software License v2.5
3 | *
4 | * Copyright (c) 2013-2016, Esoteric Software
5 | * All rights reserved.
6 | *
7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and
8 | * non-transferable license to use, install, execute, and perform the Spine
9 | * Runtimes software and derivative works solely for personal or internal
10 | * use. Without the written permission of Esoteric Software (see Section 2 of
11 | * the Spine Software License Agreement), you may not (a) modify, translate,
12 | * adapt, or develop new applications using the Spine Runtimes or otherwise
13 | * create derivative works or improvements of the Spine Runtimes or (b) remove,
14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent,
15 | * or other intellectual property or proprietary rights notices on or in the
16 | * Software, including any copy thereof. Redistributions in binary or source
17 | * 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 SOFTWARE 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, BUSINESS INTERRUPTION, OR LOSS OF
25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 | * 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 | BoundingBoxAttachment NewBoundingBoxAttachment (Skin skin, String name);
43 |
44 | /// May be null to not load any attachment
45 | PathAttachment NewPathAttachment (Skin skin, String name);
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/spine-csharp/src/Attachments/AttachmentType.cs:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Spine Runtimes Software License v2.5
3 | *
4 | * Copyright (c) 2013-2016, Esoteric Software
5 | * All rights reserved.
6 | *
7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and
8 | * non-transferable license to use, install, execute, and perform the Spine
9 | * Runtimes software and derivative works solely for personal or internal
10 | * use. Without the written permission of Esoteric Software (see Section 2 of
11 | * the Spine Software License Agreement), you may not (a) modify, translate,
12 | * adapt, or develop new applications using the Spine Runtimes or otherwise
13 | * create derivative works or improvements of the Spine Runtimes or (b) remove,
14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent,
15 | * or other intellectual property or proprietary rights notices on or in the
16 | * Software, including any copy thereof. Redistributions in binary or source
17 | * 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 SOFTWARE 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, BUSINESS INTERRUPTION, OR LOSS OF
25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 | * POSSIBILITY OF SUCH DAMAGE.
29 | *****************************************************************************/
30 |
31 | namespace Spine {
32 | public enum AttachmentType {
33 | Region, Boundingbox, Mesh, Linkedmesh, Path
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/spine-csharp/src/Attachments/BoundingBoxAttachment.cs:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Spine Runtimes Software License v2.5
3 | *
4 | * Copyright (c) 2013-2016, Esoteric Software
5 | * All rights reserved.
6 | *
7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and
8 | * non-transferable license to use, install, execute, and perform the Spine
9 | * Runtimes software and derivative works solely for personal or internal
10 | * use. Without the written permission of Esoteric Software (see Section 2 of
11 | * the Spine Software License Agreement), you may not (a) modify, translate,
12 | * adapt, or develop new applications using the Spine Runtimes or otherwise
13 | * create derivative works or improvements of the Spine Runtimes or (b) remove,
14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent,
15 | * or other intellectual property or proprietary rights notices on or in the
16 | * Software, including any copy thereof. Redistributions in binary or source
17 | * 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 SOFTWARE 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, BUSINESS INTERRUPTION, OR LOSS OF
25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 | * 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 : VertexAttachment {
36 | public BoundingBoxAttachment (string name)
37 | : base(name) {
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/spine-csharp/src/Attachments/MeshAttachment.cs:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Spine Runtimes Software License v2.5
3 | *
4 | * Copyright (c) 2013-2016, Esoteric Software
5 | * All rights reserved.
6 | *
7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and
8 | * non-transferable license to use, install, execute, and perform the Spine
9 | * Runtimes software and derivative works solely for personal or internal
10 | * use. Without the written permission of Esoteric Software (see Section 2 of
11 | * the Spine Software License Agreement), you may not (a) modify, translate,
12 | * adapt, or develop new applications using the Spine Runtimes or otherwise
13 | * create derivative works or improvements of the Spine Runtimes or (b) remove,
14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent,
15 | * or other intellectual property or proprietary rights notices on or in the
16 | * Software, including any copy thereof. Redistributions in binary or source
17 | * 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 SOFTWARE 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, BUSINESS INTERRUPTION, OR LOSS OF
25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 | * POSSIBILITY OF SUCH DAMAGE.
29 | *****************************************************************************/
30 |
31 | using System;
32 |
33 | namespace Spine {
34 | /// Attachment that displays a texture region using a mesh.
35 | public class MeshAttachment : VertexAttachment {
36 | internal float regionOffsetX, regionOffsetY, regionWidth, regionHeight, regionOriginalWidth, regionOriginalHeight;
37 | internal float[] uvs, regionUVs;
38 | internal int[] triangles;
39 | internal float r = 1, g = 1, b = 1, a = 1;
40 | internal int hulllength;
41 | internal MeshAttachment parentMesh;
42 | internal bool inheritDeform;
43 |
44 | public int HullLength { get { return hulllength; } set { hulllength = value; } }
45 | public float[] RegionUVs { get { return regionUVs; } set { regionUVs = value; } }
46 | public float[] UVs { get { return uvs; } set { uvs = value; } }
47 | public int[] Triangles { get { return triangles; } set { triangles = value; } }
48 |
49 | public float R { get { return r; } set { r = value; } }
50 | public float G { get { return g; } set { g = value; } }
51 | public float B { get { return b; } set { b = value; } }
52 | public float A { get { return a; } set { a = value; } }
53 |
54 | public String Path { get; set; }
55 | public Object RendererObject { get; set; }
56 | public float RegionU { get; set; }
57 | public float RegionV { get; set; }
58 | public float RegionU2 { get; set; }
59 | public float RegionV2 { get; set; }
60 | public bool RegionRotate { get; set; }
61 | public float RegionOffsetX { get { return regionOffsetX; } set { regionOffsetX = value; } }
62 | public float RegionOffsetY { get { return regionOffsetY; } set { regionOffsetY = value; } } // Pixels stripped from the bottom left, unrotated.
63 | public float RegionWidth { get { return regionWidth; } set { regionWidth = value; } }
64 | public float RegionHeight { get { return regionHeight; } set { regionHeight = value; } } // Unrotated, stripped size.
65 | public float RegionOriginalWidth { get { return regionOriginalWidth; } set { regionOriginalWidth = value; } }
66 | public float RegionOriginalHeight { get { return regionOriginalHeight; } set { regionOriginalHeight = value; } } // Unrotated, unstripped size.
67 |
68 | public bool InheritDeform { get { return inheritDeform; } set { inheritDeform = value; } }
69 |
70 | public MeshAttachment ParentMesh {
71 | get { return parentMesh; }
72 | set {
73 | parentMesh = value;
74 | if (value != null) {
75 | bones = value.bones;
76 | vertices = value.vertices;
77 | worldVerticesLength = value.worldVerticesLength;
78 | regionUVs = value.regionUVs;
79 | triangles = value.triangles;
80 | HullLength = value.HullLength;
81 | Edges = value.Edges;
82 | Width = value.Width;
83 | Height = value.Height;
84 | }
85 | }
86 | }
87 |
88 | // Nonessential.
89 | public int[] Edges { get; set; }
90 | public float Width { get; set; }
91 | public float Height { get; set; }
92 |
93 | public MeshAttachment (string name)
94 | : base(name) {
95 | }
96 |
97 | public void UpdateUVs () {
98 | float u = RegionU, v = RegionV, width = RegionU2 - RegionU, height = RegionV2 - RegionV;
99 |
100 | float[] regionUVs = this.regionUVs;
101 | if (this.uvs == null || this.uvs.Length != regionUVs.Length) this.uvs = new float[regionUVs.Length];
102 | float[] uvs = this.uvs;
103 | if (RegionRotate) {
104 | for (int i = 0, n = uvs.Length; i < n; i += 2) {
105 | uvs[i] = u + regionUVs[i + 1] * width;
106 | uvs[i + 1] = v + height - regionUVs[i] * height;
107 | }
108 | } else {
109 | for (int i = 0, n = uvs.Length; i < n; i += 2) {
110 | uvs[i] = u + regionUVs[i] * width;
111 | uvs[i + 1] = v + regionUVs[i + 1] * height;
112 | }
113 | }
114 | }
115 |
116 | override public bool ApplyDeform (VertexAttachment sourceAttachment) {
117 | return this == sourceAttachment || (inheritDeform && parentMesh == sourceAttachment);
118 | }
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/spine-csharp/src/Attachments/PathAttachment.cs:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Spine Runtimes Software License v2.5
3 | *
4 | * Copyright (c) 2013-2016, Esoteric Software
5 | * All rights reserved.
6 | *
7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and
8 | * non-transferable license to use, install, execute, and perform the Spine
9 | * Runtimes software and derivative works solely for personal or internal
10 | * use. Without the written permission of Esoteric Software (see Section 2 of
11 | * the Spine Software License Agreement), you may not (a) modify, translate,
12 | * adapt, or develop new applications using the Spine Runtimes or otherwise
13 | * create derivative works or improvements of the Spine Runtimes or (b) remove,
14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent,
15 | * or other intellectual property or proprietary rights notices on or in the
16 | * Software, including any copy thereof. Redistributions in binary or source
17 | * 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 SOFTWARE 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, BUSINESS INTERRUPTION, OR LOSS OF
25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 | * POSSIBILITY OF SUCH DAMAGE.
29 | *****************************************************************************/
30 |
31 | using System;
32 | using System.Collections.Generic;
33 |
34 | namespace Spine {
35 | public class PathAttachment : VertexAttachment {
36 | internal float[] lengths;
37 | internal bool closed, constantSpeed;
38 |
39 |
40 | /// The length in the setup pose from the start of the path to the end of each curve.
41 | public float[] Lengths { get { return lengths; } set { lengths = value; } }
42 | public bool Closed { get { return closed; } set { closed = value; } }
43 | public bool ConstantSpeed { get { return constantSpeed; } set { constantSpeed = value; } }
44 |
45 | public PathAttachment (String name)
46 | : base(name) {
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/spine-csharp/src/Attachments/RegionAttachment.cs:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Spine Runtimes Software License v2.5
3 | *
4 | * Copyright (c) 2013-2016, Esoteric Software
5 | * All rights reserved.
6 | *
7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and
8 | * non-transferable license to use, install, execute, and perform the Spine
9 | * Runtimes software and derivative works solely for personal or internal
10 | * use. Without the written permission of Esoteric Software (see Section 2 of
11 | * the Spine Software License Agreement), you may not (a) modify, translate,
12 | * adapt, or develop new applications using the Spine Runtimes or otherwise
13 | * create derivative works or improvements of the Spine Runtimes or (b) remove,
14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent,
15 | * or other intellectual property or proprietary rights notices on or in the
16 | * Software, including any copy thereof. Redistributions in binary or source
17 | * 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 SOFTWARE 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, BUSINESS INTERRUPTION, OR LOSS OF
25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 | * 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 rotation = this.rotation;
114 | float cos = MathUtils.CosDeg(rotation);
115 | float sin = MathUtils.SinDeg(rotation);
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 | Skeleton skeleton = bone.skeleton;
139 | float x = skeleton.x + bone.worldX, y = skeleton.y + bone.worldY;
140 | float a = bone.a, b = bone.b, c = bone.c, d = bone.d;
141 | float[] offset = this.offset;
142 | worldVertices[X1] = offset[X1] * a + offset[Y1] * b + x;
143 | worldVertices[Y1] = offset[X1] * c + offset[Y1] * d + y;
144 | worldVertices[X2] = offset[X2] * a + offset[Y2] * b + x;
145 | worldVertices[Y2] = offset[X2] * c + offset[Y2] * d + y;
146 | worldVertices[X3] = offset[X3] * a + offset[Y3] * b + x;
147 | worldVertices[Y3] = offset[X3] * c + offset[Y3] * d + y;
148 | worldVertices[X4] = offset[X4] * a + offset[Y4] * b + x;
149 | worldVertices[Y4] = offset[X4] * c + offset[Y4] * d + y;
150 | }
151 | }
152 | }
153 |
--------------------------------------------------------------------------------
/spine-csharp/src/Attachments/VertexAttachment.cs:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Spine Runtimes Software License v2.5
3 | *
4 | * Copyright (c) 2013-2016, Esoteric Software
5 | * All rights reserved.
6 | *
7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and
8 | * non-transferable license to use, install, execute, and perform the Spine
9 | * Runtimes software and derivative works solely for personal or internal
10 | * use. Without the written permission of Esoteric Software (see Section 2 of
11 | * the Spine Software License Agreement), you may not (a) modify, translate,
12 | * adapt, or develop new applications using the Spine Runtimes or otherwise
13 | * create derivative works or improvements of the Spine Runtimes or (b) remove,
14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent,
15 | * or other intellectual property or proprietary rights notices on or in the
16 | * Software, including any copy thereof. Redistributions in binary or source
17 | * 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 SOFTWARE 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, BUSINESS INTERRUPTION, OR LOSS OF
25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 | * POSSIBILITY OF SUCH DAMAGE.
29 | *****************************************************************************/
30 |
31 | using System;
32 | using System.Collections.Generic;
33 |
34 | namespace Spine {
35 | /// >An attachment with vertices that are transformed by one or more bones and can be deformed by a slot's vertices.
36 | public class VertexAttachment : Attachment {
37 | internal int[] bones;
38 | internal float[] vertices;
39 | internal int worldVerticesLength;
40 |
41 | public int[] Bones { get { return bones; } set { bones = value; } }
42 | public float[] Vertices { get { return vertices; } set { vertices = value; } }
43 | public int WorldVerticesLength { get { return worldVerticesLength; } set { worldVerticesLength = value; } }
44 |
45 | public VertexAttachment (String name)
46 | : base(name) {
47 | }
48 |
49 | public void ComputeWorldVertices (Slot slot, float[] worldVertices) {
50 | ComputeWorldVertices(slot, 0, worldVerticesLength, worldVertices, 0);
51 | }
52 |
53 | public void ComputeWorldVertices (Slot slot, int start, int count, float[] worldVertices, int offset) {
54 | count += offset;
55 | Skeleton skeleton = slot.Skeleton;
56 | float x = skeleton.x, y = skeleton.y;
57 | var deformArray = slot.attachmentVertices;
58 | float[] vertices = this.vertices;
59 | int[] bones = this.bones;
60 | if (bones == null) {
61 | if (deformArray.Count > 0) vertices = deformArray.Items;
62 | Bone bone = slot.bone;
63 | x += bone.worldX;
64 | y += bone.worldY;
65 | float a = bone.a, b = bone.b, c = bone.c, d = bone.d;
66 | for (int vv = start, w = offset; w < count; vv += 2, w += 2) {
67 | float vx = vertices[vv], vy = vertices[vv + 1];
68 | worldVertices[w] = vx * a + vy * b + x;
69 | worldVertices[w + 1] = vx * c + vy * d + y;
70 | }
71 | return;
72 | }
73 | int v = 0, skip = 0;
74 | for (int i = 0; i < start; i += 2) {
75 | int n = bones[v];
76 | v += n + 1;
77 | skip += n;
78 | }
79 | Bone[] skeletonBones = skeleton.Bones.Items;
80 | if (deformArray.Count == 0) {
81 | for (int w = offset, b = skip * 3; w < count; w += 2) {
82 | float wx = x, wy = y;
83 | int n = bones[v++];
84 | n += v;
85 | for (; v < n; v++, b += 3) {
86 | Bone bone = skeletonBones[bones[v]];
87 | float vx = vertices[b], vy = vertices[b + 1], weight = vertices[b + 2];
88 | wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight;
89 | wy += (vx * bone.c + vy * bone.d + bone.worldY) * weight;
90 | }
91 | worldVertices[w] = wx;
92 | worldVertices[w + 1] = wy;
93 | }
94 | } else {
95 | float[] deform = deformArray.Items;
96 | for (int w = offset, b = skip * 3, f = skip << 1; w < count; w += 2) {
97 | float wx = x, wy = y;
98 | int n = bones[v++];
99 | n += v;
100 | for (; v < n; v++, b += 3, f += 2) {
101 | Bone bone = skeletonBones[bones[v]];
102 | float vx = vertices[b] + deform[f], vy = vertices[b + 1] + deform[f + 1], weight = vertices[b + 2];
103 | wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight;
104 | wy += (vx * bone.c + vy * bone.d + bone.worldY) * weight;
105 | }
106 | worldVertices[w] = wx;
107 | worldVertices[w + 1] = wy;
108 | }
109 | }
110 | }
111 |
112 | /// Returns true if a deform originally applied to the specified attachment should be applied to this attachment.
113 | virtual public bool ApplyDeform (VertexAttachment sourceAttachment) {
114 | return this == sourceAttachment;
115 | }
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/spine-csharp/src/BlendMode.cs:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Spine Runtimes Software License v2.5
3 | *
4 | * Copyright (c) 2013-2016, Esoteric Software
5 | * All rights reserved.
6 | *
7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and
8 | * non-transferable license to use, install, execute, and perform the Spine
9 | * Runtimes software and derivative works solely for personal or internal
10 | * use. Without the written permission of Esoteric Software (see Section 2 of
11 | * the Spine Software License Agreement), you may not (a) modify, translate,
12 | * adapt, or develop new applications using the Spine Runtimes or otherwise
13 | * create derivative works or improvements of the Spine Runtimes or (b) remove,
14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent,
15 | * or other intellectual property or proprietary rights notices on or in the
16 | * Software, including any copy thereof. Redistributions in binary or source
17 | * 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 SOFTWARE 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, BUSINESS INTERRUPTION, OR LOSS OF
25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 | * POSSIBILITY OF SUCH DAMAGE.
29 | *****************************************************************************/
30 |
31 | namespace Spine {
32 | public enum BlendMode {
33 | normal, additive, multiply, screen
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/spine-csharp/src/Bone.cs:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Spine Runtimes Software License v2.5
3 | *
4 | * Copyright (c) 2013-2016, Esoteric Software
5 | * All rights reserved.
6 | *
7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and
8 | * non-transferable license to use, install, execute, and perform the Spine
9 | * Runtimes software and derivative works solely for personal or internal
10 | * use. Without the written permission of Esoteric Software (see Section 2 of
11 | * the Spine Software License Agreement), you may not (a) modify, translate,
12 | * adapt, or develop new applications using the Spine Runtimes or otherwise
13 | * create derivative works or improvements of the Spine Runtimes or (b) remove,
14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent,
15 | * or other intellectual property or proprietary rights notices on or in the
16 | * Software, including any copy thereof. Redistributions in binary or source
17 | * 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 SOFTWARE 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, BUSINESS INTERRUPTION, OR LOSS OF
25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 | * POSSIBILITY OF SUCH DAMAGE.
29 | *****************************************************************************/
30 |
31 | using System;
32 |
33 | namespace Spine {
34 | public class Bone : IUpdatable {
35 | static public bool yDown;
36 |
37 | internal BoneData data;
38 | internal Skeleton skeleton;
39 | internal Bone parent;
40 | internal ExposedList children = new ExposedList();
41 | internal float x, y, rotation, scaleX, scaleY, shearX, shearY;
42 | internal float appliedRotation;
43 |
44 | internal float a, b, worldX;
45 | internal float c, d, worldY;
46 | internal float worldSignX, worldSignY;
47 |
48 | internal bool sorted;
49 |
50 | public BoneData Data { get { return data; } }
51 | public Skeleton Skeleton { get { return skeleton; } }
52 | public Bone Parent { get { return parent; } }
53 | public ExposedList Children { get { return children; } }
54 | public float X { get { return x; } set { x = value; } }
55 | public float Y { get { return y; } set { y = value; } }
56 | public float Rotation { get { return rotation; } set { rotation = value; } }
57 | /// The rotation, as calculated by any constraints.
58 | public float AppliedRotation { get { return appliedRotation; } set { appliedRotation = value; } }
59 | public float ScaleX { get { return scaleX; } set { scaleX = value; } }
60 | public float ScaleY { get { return scaleY; } set { scaleY = value; } }
61 | public float ShearX { get { return shearX; } set { shearX = value; } }
62 | public float ShearY { get { return shearY; } set { shearY = value; } }
63 |
64 | public float A { get { return a; } }
65 | public float B { get { return b; } }
66 | public float C { get { return c; } }
67 | public float D { get { return d; } }
68 | public float WorldX { get { return worldX; } }
69 | public float WorldY { get { return worldY; } }
70 | public float WorldSignX { get { return worldSignX; } }
71 | public float WorldSignY { get { return worldSignY; } }
72 | public float WorldRotationX { get { return MathUtils.Atan2(c, a) * MathUtils.radDeg; } }
73 | public float WorldRotationY { get { return MathUtils.Atan2(d, b) * MathUtils.radDeg; } }
74 | public float WorldScaleX { get { return (float)Math.Sqrt(a * a + c * c) * worldSignX; } }
75 | public float WorldScaleY { get { return (float)Math.Sqrt(b * b + d * d) * worldSignY; } }
76 |
77 | /// May be null.
78 | public Bone (BoneData data, Skeleton skeleton, Bone parent) {
79 | if (data == null) throw new ArgumentNullException("data", "data cannot be null.");
80 | if (skeleton == null) throw new ArgumentNullException("skeleton", "skeleton cannot be null.");
81 | this.data = data;
82 | this.skeleton = skeleton;
83 | this.parent = parent;
84 | SetToSetupPose();
85 | }
86 |
87 | /// Same as . This method exists for Bone to implement .
88 | public void Update () {
89 | UpdateWorldTransform(x, y, rotation, scaleX, scaleY, shearX, shearY);
90 | }
91 |
92 | /// Computes the world transform using the parent bone and this bone's local transform.
93 | public void UpdateWorldTransform () {
94 | UpdateWorldTransform(x, y, rotation, scaleX, scaleY, shearX, shearY);
95 | }
96 |
97 | /// Computes the world transform using the parent bone and the specified local transform.
98 | public void UpdateWorldTransform (float x, float y, float rotation, float scaleX, float scaleY, float shearX, float shearY) {
99 | appliedRotation = rotation;
100 |
101 | float rotationY = rotation + 90 + shearY;
102 | float la = MathUtils.CosDeg(rotation + shearX) * scaleX, lb = MathUtils.CosDeg(rotationY) * scaleY;
103 | float lc = MathUtils.SinDeg(rotation + shearX) * scaleX, ld = MathUtils.SinDeg(rotationY) * scaleY;
104 |
105 | Bone parent = this.parent;
106 | if (parent == null) { // Root bone.
107 | Skeleton skeleton = this.skeleton;
108 | if (skeleton.flipX) {
109 | x = -x;
110 | la = -la;
111 | lb = -lb;
112 | }
113 | if (skeleton.flipY != yDown) {
114 | y = -y;
115 | lc = -lc;
116 | ld = -ld;
117 | }
118 | a = la;
119 | b = lb;
120 | c = lc;
121 | d = ld;
122 | worldX = x;
123 | worldY = y;
124 | worldSignX = Math.Sign(scaleX);
125 | worldSignY = Math.Sign(scaleY);
126 | return;
127 | }
128 |
129 | float pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d;
130 | worldX = pa * x + pb * y + parent.worldX;
131 | worldY = pc * x + pd * y + parent.worldY;
132 | worldSignX = parent.worldSignX * Math.Sign(scaleX);
133 | worldSignY = parent.worldSignY * Math.Sign(scaleY);
134 |
135 | if (data.inheritRotation && data.inheritScale) {
136 | a = pa * la + pb * lc;
137 | b = pa * lb + pb * ld;
138 | c = pc * la + pd * lc;
139 | d = pc * lb + pd * ld;
140 | } else {
141 | if (data.inheritRotation) { // No scale inheritance.
142 | pa = 1;
143 | pb = 0;
144 | pc = 0;
145 | pd = 1;
146 | do {
147 | float cos = MathUtils.CosDeg(parent.appliedRotation), sin = MathUtils.SinDeg(parent.appliedRotation);
148 | float temp = pa * cos + pb * sin;
149 | pb = pb * cos - pa * sin;
150 | pa = temp;
151 | temp = pc * cos + pd * sin;
152 | pd = pd * cos - pc * sin;
153 | pc = temp;
154 |
155 | if (!parent.data.inheritRotation) break;
156 | parent = parent.parent;
157 | } while (parent != null);
158 | a = pa * la + pb * lc;
159 | b = pa * lb + pb * ld;
160 | c = pc * la + pd * lc;
161 | d = pc * lb + pd * ld;
162 | } else if (data.inheritScale) { // No rotation inheritance.
163 | pa = 1;
164 | pb = 0;
165 | pc = 0;
166 | pd = 1;
167 | do {
168 | float cos = MathUtils.CosDeg(parent.appliedRotation), sin = MathUtils.SinDeg(parent.appliedRotation);
169 | float psx = parent.scaleX, psy = parent.scaleY;
170 | float za = cos * psx, zb = sin * psy, zc = sin * psx, zd = cos * psy;
171 | float temp = pa * za + pb * zc;
172 | pb = pb * zd - pa * zb;
173 | pa = temp;
174 | temp = pc * za + pd * zc;
175 | pd = pd * zd - pc * zb;
176 | pc = temp;
177 |
178 | if (psx >= 0) sin = -sin;
179 | temp = pa * cos + pb * sin;
180 | pb = pb * cos - pa * sin;
181 | pa = temp;
182 | temp = pc * cos + pd * sin;
183 | pd = pd * cos - pc * sin;
184 | pc = temp;
185 |
186 | if (!parent.data.inheritScale) break;
187 | parent = parent.parent;
188 | } while (parent != null);
189 | a = pa * la + pb * lc;
190 | b = pa * lb + pb * ld;
191 | c = pc * la + pd * lc;
192 | d = pc * lb + pd * ld;
193 | } else {
194 | a = la;
195 | b = lb;
196 | c = lc;
197 | d = ld;
198 | }
199 | if (skeleton.flipX) {
200 | a = -a;
201 | b = -b;
202 | }
203 | if (skeleton.flipY != yDown) {
204 | c = -c;
205 | d = -d;
206 | }
207 | }
208 | }
209 |
210 | public void SetToSetupPose () {
211 | BoneData data = this.data;
212 | x = data.x;
213 | y = data.y;
214 | rotation = data.rotation;
215 | scaleX = data.scaleX;
216 | scaleY = data.scaleY;
217 | shearX = data.shearX;
218 | shearY = data.shearY;
219 | }
220 |
221 | public float WorldToLocalRotationX {
222 | get {
223 | Bone parent = this.parent;
224 | if (parent == null) return rotation;
225 | float pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d, a = this.a, c = this.c;
226 | return MathUtils.Atan2(pa * c - pc * a, pd * a - pb * c) * MathUtils.radDeg;
227 | }
228 | }
229 |
230 | public float WorldToLocalRotationY {
231 | get {
232 | Bone parent = this.parent;
233 | if (parent == null) return rotation;
234 | float pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d, b = this.b, d = this.d;
235 | return MathUtils.Atan2(pa * d - pc * b, pd * b - pb * d) * MathUtils.radDeg;
236 | }
237 | }
238 |
239 | public void RotateWorld (float degrees) {
240 | float a = this.a, b = this.b, c = this.c, d = this.d;
241 | float cos = MathUtils.CosDeg(degrees), sin = MathUtils.SinDeg(degrees);
242 | this.a = cos * a - sin * c;
243 | this.b = cos * b - sin * d;
244 | this.c = sin * a + cos * c;
245 | this.d = sin * b + cos * d;
246 | }
247 |
248 | ///
249 | /// Computes the local transform from the world transform. This can be useful to perform processing on the local transform
250 | /// after the world transform has been modified directly (eg, by a constraint).
251 | ///
252 | /// Some redundant information is lost by the world transform, such as -1,-1 scale versus 180 rotation. The computed local
253 | /// transform values may differ from the original values but are functionally the same.
254 | ///
255 | public void UpdateLocalTransform () {
256 | Bone parent = this.parent;
257 | if (parent == null) {
258 | x = worldX;
259 | y = worldY;
260 | rotation = MathUtils.Atan2(c, a) * MathUtils.radDeg;
261 | scaleX = (float)Math.Sqrt(a * a + c * c);
262 | scaleY = (float)Math.Sqrt(b * b + d * d);
263 | float det = a * d - b * c;
264 | shearX = 0;
265 | shearY = MathUtils.Atan2(a * b + c * d, det) * MathUtils.radDeg;
266 | return;
267 | }
268 | float pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d;
269 | float pid = 1 / (pa * pd - pb * pc);
270 | float dx = worldX - parent.worldX, dy = worldY - parent.worldY;
271 | x = (dx * pd * pid - dy * pb * pid);
272 | y = (dy * pa * pid - dx * pc * pid);
273 | float ia = pid * pd;
274 | float id = pid * pa;
275 | float ib = pid * pb;
276 | float ic = pid * pc;
277 | float ra = ia * a - ib * c;
278 | float rb = ia * b - ib * d;
279 | float rc = id * c - ic * a;
280 | float rd = id * d - ic * b;
281 | shearX = 0;
282 | scaleX = (float)Math.Sqrt(ra * ra + rc * rc);
283 | if (scaleX > 0.0001f) {
284 | float det = ra * rd - rb * rc;
285 | scaleY = det / scaleX;
286 | shearY = MathUtils.Atan2(ra * rb + rc * rd, det) * MathUtils.radDeg;
287 | rotation = MathUtils.Atan2(rc, ra) * MathUtils.radDeg;
288 | } else {
289 | scaleX = 0;
290 | scaleY = (float)Math.Sqrt(rb * rb + rd * rd);
291 | shearY = 0;
292 | rotation = 90 - MathUtils.Atan2(rd, rb) * MathUtils.radDeg;
293 | }
294 | appliedRotation = rotation;
295 | }
296 |
297 | public void WorldToLocal (float worldX, float worldY, out float localX, out float localY) {
298 | float a = this.a, b = this.b, c = this.c, d = this.d;
299 | float invDet = 1 / (a * d - b * c);
300 | float x = worldX - this.worldX, y = worldY - this.worldY;
301 | localX = (x * d * invDet - y * b * invDet);
302 | localY = (y * a * invDet - x * c * invDet);
303 | }
304 |
305 | public void LocalToWorld (float localX, float localY, out float worldX, out float worldY) {
306 | worldX = localX * a + localY * b + this.worldX;
307 | worldY = localX * c + localY * d + this.worldY;
308 | }
309 |
310 | override public String ToString () {
311 | return data.name;
312 | }
313 | }
314 | }
315 |
--------------------------------------------------------------------------------
/spine-csharp/src/BoneData.cs:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Spine Runtimes Software License v2.5
3 | *
4 | * Copyright (c) 2013-2016, Esoteric Software
5 | * All rights reserved.
6 | *
7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and
8 | * non-transferable license to use, install, execute, and perform the Spine
9 | * Runtimes software and derivative works solely for personal or internal
10 | * use. Without the written permission of Esoteric Software (see Section 2 of
11 | * the Spine Software License Agreement), you may not (a) modify, translate,
12 | * adapt, or develop new applications using the Spine Runtimes or otherwise
13 | * create derivative works or improvements of the Spine Runtimes or (b) remove,
14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent,
15 | * or other intellectual property or proprietary rights notices on or in the
16 | * Software, including any copy thereof. Redistributions in binary or source
17 | * 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 SOFTWARE 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, BUSINESS INTERRUPTION, OR LOSS OF
25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 | * POSSIBILITY OF SUCH DAMAGE.
29 | *****************************************************************************/
30 |
31 | using System;
32 |
33 | namespace Spine {
34 | public class BoneData {
35 | internal int index;
36 | internal String name;
37 | internal BoneData parent;
38 | internal float length;
39 | internal float x, y, rotation, scaleX = 1, scaleY = 1, shearX, shearY;
40 | internal bool inheritRotation = true, inheritScale = true;
41 |
42 | /// May be null.
43 | public int Index { get { return index; } }
44 | public String Name { get { return name; } }
45 | public BoneData Parent { get { return parent; } }
46 | public float Length { get { return length; } set { length = value; } }
47 | public float X { get { return x; } set { x = value; } }
48 | public float Y { get { return y; } set { y = value; } }
49 | public float Rotation { get { return rotation; } set { rotation = value; } }
50 | public float ScaleX { get { return scaleX; } set { scaleX = value; } }
51 | public float ScaleY { get { return scaleY; } set { scaleY = value; } }
52 | public float ShearX { get { return shearX; } set { shearX = value; } }
53 | public float ShearY { get { return shearY; } set { shearY = value; } }
54 | public bool InheritRotation { get { return inheritRotation; } set { inheritRotation = value; } }
55 | public bool InheritScale { get { return inheritScale; } set { inheritScale = value; } }
56 |
57 | /// May be null.
58 | public BoneData (int index, String name, BoneData parent) {
59 | if (index < 0) throw new ArgumentException("index must be >= 0", "index");
60 | if (name == null) throw new ArgumentNullException("name", "name cannot be null.");
61 | this.index = index;
62 | this.name = name;
63 | this.parent = parent;
64 | }
65 |
66 | override public String ToString () {
67 | return name;
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/spine-csharp/src/Event.cs:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Spine Runtimes Software License v2.5
3 | *
4 | * Copyright (c) 2013-2016, Esoteric Software
5 | * All rights reserved.
6 | *
7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and
8 | * non-transferable license to use, install, execute, and perform the Spine
9 | * Runtimes software and derivative works solely for personal or internal
10 | * use. Without the written permission of Esoteric Software (see Section 2 of
11 | * the Spine Software License Agreement), you may not (a) modify, translate,
12 | * adapt, or develop new applications using the Spine Runtimes or otherwise
13 | * create derivative works or improvements of the Spine Runtimes or (b) remove,
14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent,
15 | * or other intellectual property or proprietary rights notices on or in the
16 | * Software, including any copy thereof. Redistributions in binary or source
17 | * 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 SOFTWARE 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, BUSINESS INTERRUPTION, OR LOSS OF
25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 | * 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 | public float Time { get; private set; }
40 |
41 | public Event (float time, EventData data) {
42 | if (data == null) throw new ArgumentNullException("data", "data cannot be null.");
43 | Time = time;
44 | Data = data;
45 | }
46 |
47 | override public String ToString () {
48 | return Data.Name;
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/spine-csharp/src/EventData.cs:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Spine Runtimes Software License v2.5
3 | *
4 | * Copyright (c) 2013-2016, Esoteric Software
5 | * All rights reserved.
6 | *
7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and
8 | * non-transferable license to use, install, execute, and perform the Spine
9 | * Runtimes software and derivative works solely for personal or internal
10 | * use. Without the written permission of Esoteric Software (see Section 2 of
11 | * the Spine Software License Agreement), you may not (a) modify, translate,
12 | * adapt, or develop new applications using the Spine Runtimes or otherwise
13 | * create derivative works or improvements of the Spine Runtimes or (b) remove,
14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent,
15 | * or other intellectual property or proprietary rights notices on or in the
16 | * Software, including any copy thereof. Redistributions in binary or source
17 | * 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 SOFTWARE 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, BUSINESS INTERRUPTION, OR LOSS OF
25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 | * 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", "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/IUpdatable.cs:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Spine Runtimes Software License v2.5
3 | *
4 | * Copyright (c) 2013-2016, Esoteric Software
5 | * All rights reserved.
6 | *
7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and
8 | * non-transferable license to use, install, execute, and perform the Spine
9 | * Runtimes software and derivative works solely for personal or internal
10 | * use. Without the written permission of Esoteric Software (see Section 2 of
11 | * the Spine Software License Agreement), you may not (a) modify, translate,
12 | * adapt, or develop new applications using the Spine Runtimes or otherwise
13 | * create derivative works or improvements of the Spine Runtimes or (b) remove,
14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent,
15 | * or other intellectual property or proprietary rights notices on or in the
16 | * Software, including any copy thereof. Redistributions in binary or source
17 | * 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 SOFTWARE 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, BUSINESS INTERRUPTION, OR LOSS OF
25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 | * POSSIBILITY OF SUCH DAMAGE.
29 | *****************************************************************************/
30 |
31 | using System;
32 |
33 | namespace Spine {
34 | public interface IUpdatable {
35 | void Update ();
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/spine-csharp/src/IkConstraint.cs:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Spine Runtimes Software License v2.5
3 | *
4 | * Copyright (c) 2013-2016, Esoteric Software
5 | * All rights reserved.
6 | *
7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and
8 | * non-transferable license to use, install, execute, and perform the Spine
9 | * Runtimes software and derivative works solely for personal or internal
10 | * use. Without the written permission of Esoteric Software (see Section 2 of
11 | * the Spine Software License Agreement), you may not (a) modify, translate,
12 | * adapt, or develop new applications using the Spine Runtimes or otherwise
13 | * create derivative works or improvements of the Spine Runtimes or (b) remove,
14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent,
15 | * or other intellectual property or proprietary rights notices on or in the
16 | * Software, including any copy thereof. Redistributions in binary or source
17 | * 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 SOFTWARE 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, BUSINESS INTERRUPTION, OR LOSS OF
25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 | * POSSIBILITY OF SUCH DAMAGE.
29 | *****************************************************************************/
30 |
31 | using System;
32 |
33 | namespace Spine {
34 | public class IkConstraint : IUpdatable {
35 | internal IkConstraintData data;
36 | internal ExposedList bones = new ExposedList();
37 | internal Bone target;
38 | internal float mix;
39 | internal int bendDirection;
40 |
41 | internal int level;
42 |
43 | public IkConstraintData Data { get { return data; } }
44 | public ExposedList Bones { get { return bones; } }
45 | public Bone Target { get { return target; } set { target = value; } }
46 | public int BendDirection { get { return bendDirection; } set { bendDirection = value; } }
47 | public float Mix { get { return mix; } set { mix = value; } }
48 |
49 | public IkConstraint (IkConstraintData data, Skeleton skeleton) {
50 | if (data == null) throw new ArgumentNullException("data", "data cannot be null.");
51 | if (skeleton == null) throw new ArgumentNullException("skeleton", "skeleton cannot be null.");
52 | this.data = data;
53 | mix = data.mix;
54 | bendDirection = data.bendDirection;
55 |
56 | bones = new ExposedList(data.bones.Count);
57 | foreach (BoneData boneData in data.bones)
58 | bones.Add(skeleton.FindBone(boneData.name));
59 | target = skeleton.FindBone(data.target.name);
60 | }
61 |
62 | public void Update () {
63 | Apply();
64 | }
65 |
66 | public void Apply () {
67 | Bone target = this.target;
68 | ExposedList bones = this.bones;
69 | switch (bones.Count) {
70 | case 1:
71 | Apply(bones.Items[0], target.worldX, target.worldY, mix);
72 | break;
73 | case 2:
74 | Apply(bones.Items[0], bones.Items[1], target.worldX, target.worldY, bendDirection, mix);
75 | break;
76 | }
77 | }
78 |
79 | override public String ToString () {
80 | return data.name;
81 | }
82 |
83 | /// Adjusts the bone rotation so the tip is as close to the target position as possible. The target is specified
84 | /// in the world coordinate system.
85 | static public void Apply (Bone bone, float targetX, float targetY, float alpha) {
86 | Bone pp = bone.parent;
87 | float id = 1 / (pp.a * pp.d - pp.b * pp.c);
88 | float x = targetX - pp.worldX, y = targetY - pp.worldY;
89 | float tx = (x * pp.d - y * pp.b) * id - bone.x, ty = (y * pp.a - x * pp.c) * id - bone.y;
90 | float rotationIK = MathUtils.Atan2(ty, tx) * MathUtils.radDeg - bone.shearX - bone.rotation;
91 | if (bone.scaleX < 0) rotationIK += 180;
92 | if (rotationIK > 180)
93 | rotationIK -= 360;
94 | else if (rotationIK < -180) rotationIK += 360;
95 | bone.UpdateWorldTransform(bone.x, bone.y, bone.rotation + rotationIK * alpha, bone.scaleX, bone.scaleY,
96 | bone.shearX, bone.shearY);
97 | }
98 |
99 | /// Adjusts the parent and child bone rotations so the tip of the child is as close to the target position as
100 | /// possible. The target is specified in the world coordinate system.
101 | /// A direct descendant of the parent bone.
102 | static public void Apply (Bone parent, Bone child, float targetX, float targetY, int bendDir, float alpha) {
103 | if (alpha == 0) {
104 | child.UpdateWorldTransform ();
105 | return;
106 | }
107 | float px = parent.x, py = parent.y, psx = parent.scaleX, psy = parent.scaleY, csx = child.scaleX;
108 | int os1, os2, s2;
109 | if (psx < 0) {
110 | psx = -psx;
111 | os1 = 180;
112 | s2 = -1;
113 | } else {
114 | os1 = 0;
115 | s2 = 1;
116 | }
117 | if (psy < 0) {
118 | psy = -psy;
119 | s2 = -s2;
120 | }
121 | if (csx < 0) {
122 | csx = -csx;
123 | os2 = 180;
124 | } else
125 | os2 = 0;
126 | float cx = child.x, cy, cwx, cwy, a = parent.a, b = parent.b, c = parent.c, d = parent.d;
127 | bool u = Math.Abs(psx - psy) <= 0.0001f;
128 | if (!u) {
129 | cy = 0;
130 | cwx = a * cx + parent.worldX;
131 | cwy = c * cx + parent.worldY;
132 | } else {
133 | cy = child.y;
134 | cwx = a * cx + b * cy + parent.worldX;
135 | cwy = c * cx + d * cy + parent.worldY;
136 | }
137 | Bone pp = parent.parent;
138 | a = pp.a;
139 | b = pp.b;
140 | c = pp.c;
141 | d = pp.d;
142 | float id = 1 / (a * d - b * c), x = targetX - pp.worldX, y = targetY - pp.worldY;
143 | float tx = (x * d - y * b) * id - px, ty = (y * a - x * c) * id - py;
144 | x = cwx - pp.worldX;
145 | y = cwy - pp.worldY;
146 | float dx = (x * d - y * b) * id - px, dy = (y * a - x * c) * id - py;
147 | float l1 = (float)Math.Sqrt(dx * dx + dy * dy), l2 = child.data.length * csx, a1, a2;
148 | if (u) {
149 | l2 *= psx;
150 | float cos = (tx * tx + ty * ty - l1 * l1 - l2 * l2) / (2 * l1 * l2);
151 | if (cos < -1)
152 | cos = -1;
153 | else if (cos > 1) cos = 1;
154 | a2 = (float)Math.Acos(cos) * bendDir;
155 | a = l1 + l2 * cos;
156 | b = l2 * MathUtils.Sin(a2);
157 | a1 = MathUtils.Atan2(ty * a - tx * b, tx * a + ty * b);
158 | } else {
159 | a = psx * l2;
160 | b = psy * l2;
161 | float aa = a * a, bb = b * b, dd = tx * tx + ty * ty, ta = MathUtils.Atan2(ty, tx);
162 | c = bb * l1 * l1 + aa * dd - aa * bb;
163 | float c1 = -2 * bb * l1, c2 = bb - aa;
164 | d = c1 * c1 - 4 * c2 * c;
165 | if (d >= 0) {
166 | float q = (float)Math.Sqrt(d);
167 | if (c1 < 0) q = -q;
168 | q = -(c1 + q) / 2;
169 | float r0 = q / c2, r1 = c / q;
170 | float r = Math.Abs(r0) < Math.Abs(r1) ? r0 : r1;
171 | if (r * r <= dd) {
172 | y = (float)Math.Sqrt(dd - r * r) * bendDir;
173 | a1 = ta - MathUtils.Atan2(y, r);
174 | a2 = MathUtils.Atan2(y / psy, (r - l1) / psx);
175 | goto outer;
176 | }
177 | }
178 | float minAngle = 0, minDist = float.MaxValue, minX = 0, minY = 0;
179 | float maxAngle = 0, maxDist = 0, maxX = 0, maxY = 0;
180 | x = l1 + a;
181 | d = x * x;
182 | if (d > maxDist) {
183 | maxAngle = 0;
184 | maxDist = d;
185 | maxX = x;
186 | }
187 | x = l1 - a;
188 | d = x * x;
189 | if (d < minDist) {
190 | minAngle = MathUtils.PI;
191 | minDist = d;
192 | minX = x;
193 | }
194 | float angle = (float)Math.Acos(-a * l1 / (aa - bb));
195 | x = a * MathUtils.Cos(angle) + l1;
196 | y = b * MathUtils.Sin(angle);
197 | d = x * x + y * y;
198 | if (d < minDist) {
199 | minAngle = angle;
200 | minDist = d;
201 | minX = x;
202 | minY = y;
203 | }
204 | if (d > maxDist) {
205 | maxAngle = angle;
206 | maxDist = d;
207 | maxX = x;
208 | maxY = y;
209 | }
210 | if (dd <= (minDist + maxDist) / 2) {
211 | a1 = ta - MathUtils.Atan2(minY * bendDir, minX);
212 | a2 = minAngle * bendDir;
213 | } else {
214 | a1 = ta - MathUtils.Atan2(maxY * bendDir, maxX);
215 | a2 = maxAngle * bendDir;
216 | }
217 | }
218 | outer:
219 | float os = MathUtils.Atan2(cy, cx) * s2;
220 | float rotation = parent.rotation;
221 | a1 = (a1 - os) * MathUtils.radDeg + os1 - rotation;
222 | if (a1 > 180)
223 | a1 -= 360;
224 | else if (a1 < -180) a1 += 360;
225 | parent.UpdateWorldTransform(px, py, rotation + a1 * alpha, parent.scaleX, parent.scaleY, 0, 0);
226 | rotation = child.rotation;
227 | a2 = ((a2 + os) * MathUtils.radDeg - child.shearX) * s2 + os2 - rotation;
228 | if (a2 > 180)
229 | a2 -= 360;
230 | else if (a2 < -180) a2 += 360;
231 | child.UpdateWorldTransform(cx, cy, rotation + a2 * alpha, child.scaleX, child.scaleY, child.shearX, child.shearY);
232 | }
233 | }
234 | }
235 |
--------------------------------------------------------------------------------
/spine-csharp/src/IkConstraintData.cs:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Spine Runtimes Software License v2.5
3 | *
4 | * Copyright (c) 2013-2016, Esoteric Software
5 | * All rights reserved.
6 | *
7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and
8 | * non-transferable license to use, install, execute, and perform the Spine
9 | * Runtimes software and derivative works solely for personal or internal
10 | * use. Without the written permission of Esoteric Software (see Section 2 of
11 | * the Spine Software License Agreement), you may not (a) modify, translate,
12 | * adapt, or develop new applications using the Spine Runtimes or otherwise
13 | * create derivative works or improvements of the Spine Runtimes or (b) remove,
14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent,
15 | * or other intellectual property or proprietary rights notices on or in the
16 | * Software, including any copy thereof. Redistributions in binary or source
17 | * 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 SOFTWARE 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, BUSINESS INTERRUPTION, OR LOSS OF
25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 | * 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", "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/Json.cs:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Spine Runtimes Software License v2.5
3 | *
4 | * Copyright (c) 2013-2016, Esoteric Software
5 | * All rights reserved.
6 | *
7 | * You are granted a perpetual, non-exclusive, non-sublicensable, and
8 | * non-transferable license to use, install, execute, and perform the Spine
9 | * Runtimes software and derivative works solely for personal or internal
10 | * use. Without the written permission of Esoteric Software (see Section 2 of
11 | * the Spine Software License Agreement), you may not (a) modify, translate,
12 | * adapt, or develop new applications using the Spine Runtimes or otherwise
13 | * create derivative works or improvements of the Spine Runtimes or (b) remove,
14 | * delete, alter, or obscure any trademarks or any copyright, trademark, patent,
15 | * or other intellectual property or proprietary rights notices on or in the
16 | * Software, including any copy thereof. Redistributions in binary or source
17 | * 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 SOFTWARE 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, BUSINESS INTERRUPTION, OR LOSS OF
25 | * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
26 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 | * POSSIBILITY OF SUCH DAMAGE.
29 | *****************************************************************************/
30 |
31 | using System;
32 | using System.IO;
33 | using System.Text;
34 | using System.Collections;
35 | using System.Globalization;
36 | using System.Collections.Generic;
37 |
38 | namespace Spine {
39 | public static class Json {
40 | public static object Deserialize (TextReader text) {
41 | var parser = new SharpJson.JsonDecoder();
42 | parser.parseNumbersAsFloat = true;
43 | return parser.Decode(text.ReadToEnd());
44 | }
45 | }
46 | }
47 |
48 | /**
49 | *
50 | * Copyright (c) 2016 Adriano Tinoco d'Oliveira Rezende
51 | *
52 | * Based on the JSON parser by Patrick van Bergen
53 | * http://techblog.procurios.nl/k/news/view/14605/14863/how-do-i-write-my-own-parser-(for-json).html
54 | *
55 | * Changes made:
56 | *
57 | * - Optimized parser speed (deserialize roughly near 3x faster than original)
58 | * - Added support to handle lexer/parser error messages with line numbers
59 | * - Added more fine grained control over type conversions during the parsing
60 | * - Refactory API (Separate Lexer code from Parser code and the Encoder from Decoder)
61 | *
62 | *
63 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
64 | * and associated documentation files (the "Software"), to deal in the Software without restriction,
65 | * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
66 | * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
67 | * subject to the following conditions:
68 | * The above copyright notice and this permission notice shall be included in all copies or substantial
69 | * portions of the Software.
70 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
71 | * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
72 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
73 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
74 | * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
75 | *
76 | */
77 | namespace SharpJson
78 | {
79 | class Lexer
80 | {
81 | public enum Token {
82 | None,
83 | Null,
84 | True,
85 | False,
86 | Colon,
87 | Comma,
88 | String,
89 | Number,
90 | CurlyOpen,
91 | CurlyClose,
92 | SquaredOpen,
93 | SquaredClose,
94 | };
95 |
96 | public bool hasError {
97 | get {
98 | return !success;
99 | }
100 | }
101 |
102 | public int lineNumber {
103 | get;
104 | private set;
105 | }
106 |
107 | public bool parseNumbersAsFloat {
108 | get;
109 | set;
110 | }
111 |
112 | char[] json;
113 | int index = 0;
114 | bool success = true;
115 | char[] stringBuffer = new char[4096];
116 |
117 | public Lexer(string text)
118 | {
119 | Reset();
120 |
121 | json = text.ToCharArray();
122 | parseNumbersAsFloat = false;
123 | }
124 |
125 | public void Reset()
126 | {
127 | index = 0;
128 | lineNumber = 1;
129 | success = true;
130 | }
131 |
132 | public string ParseString()
133 | {
134 | int idx = 0;
135 | StringBuilder builder = null;
136 |
137 | SkipWhiteSpaces();
138 |
139 | // "
140 | char c = json[index++];
141 |
142 | bool failed = false;
143 | bool complete = false;
144 |
145 | while (!complete && !failed) {
146 | if (index == json.Length)
147 | break;
148 |
149 | c = json[index++];
150 | if (c == '"') {
151 | complete = true;
152 | break;
153 | } else if (c == '\\') {
154 | if (index == json.Length)
155 | break;
156 |
157 | c = json[index++];
158 |
159 | switch (c) {
160 | case '"':
161 | stringBuffer[idx++] = '"';
162 | break;
163 | case '\\':
164 | stringBuffer[idx++] = '\\';
165 | break;
166 | case '/':
167 | stringBuffer[idx++] = '/';
168 | break;
169 | case 'b':
170 | stringBuffer[idx++] = '\b';
171 | break;
172 | case'f':
173 | stringBuffer[idx++] = '\f';
174 | break;
175 | case 'n':
176 | stringBuffer[idx++] = '\n';
177 | break;
178 | case 'r':
179 | stringBuffer[idx++] = '\r';
180 | break;
181 | case 't':
182 | stringBuffer[idx++] = '\t';
183 | break;
184 | case 'u':
185 | int remainingLength = json.Length - index;
186 | if (remainingLength >= 4) {
187 | var hex = new string(json, index, 4);
188 |
189 | // XXX: handle UTF
190 | stringBuffer[idx++] = (char) Convert.ToInt32(hex, 16);
191 |
192 | // skip 4 chars
193 | index += 4;
194 | } else {
195 | failed = true;
196 | }
197 | break;
198 | }
199 | } else {
200 | stringBuffer[idx++] = c;
201 | }
202 |
203 | if (idx >= stringBuffer.Length) {
204 | if (builder == null)
205 | builder = new StringBuilder();
206 |
207 | builder.Append(stringBuffer, 0, idx);
208 | idx = 0;
209 | }
210 | }
211 |
212 | if (!complete) {
213 | success = false;
214 | return null;
215 | }
216 |
217 | if (builder != null)
218 | return builder.ToString ();
219 | else
220 | return new string (stringBuffer, 0, idx);
221 | }
222 |
223 | string GetNumberString()
224 | {
225 | SkipWhiteSpaces();
226 |
227 | int lastIndex = GetLastIndexOfNumber(index);
228 | int charLength = (lastIndex - index) + 1;
229 |
230 | var result = new string (json, index, charLength);
231 |
232 | index = lastIndex + 1;
233 |
234 | return result;
235 | }
236 |
237 | public float ParseFloatNumber()
238 | {
239 | float number;
240 | var str = GetNumberString ();
241 |
242 | if (!float.TryParse (str, NumberStyles.Float, CultureInfo.InvariantCulture, out number))
243 | return 0;
244 |
245 | return number;
246 | }
247 |
248 | public double ParseDoubleNumber()
249 | {
250 | double number;
251 | var str = GetNumberString ();
252 |
253 | if (!double.TryParse(str, NumberStyles.Any, CultureInfo.InvariantCulture, out number))
254 | return 0;
255 |
256 | return number;
257 | }
258 |
259 | int GetLastIndexOfNumber(int index)
260 | {
261 | int lastIndex;
262 |
263 | for (lastIndex = index; lastIndex < json.Length; lastIndex++) {
264 | char ch = json[lastIndex];
265 |
266 | if ((ch < '0' || ch > '9') && ch != '+' && ch != '-'
267 | && ch != '.' && ch != 'e' && ch != 'E')
268 | break;
269 | }
270 |
271 | return lastIndex - 1;
272 | }
273 |
274 | void SkipWhiteSpaces()
275 | {
276 | for (; index < json.Length; index++) {
277 | char ch = json[index];
278 |
279 | if (ch == '\n')
280 | lineNumber++;
281 |
282 | if (!char.IsWhiteSpace(json[index]))
283 | break;
284 | }
285 | }
286 |
287 | public Token LookAhead()
288 | {
289 | SkipWhiteSpaces();
290 |
291 | int savedIndex = index;
292 | return NextToken(json, ref savedIndex);
293 | }
294 |
295 | public Token NextToken()
296 | {
297 | SkipWhiteSpaces();
298 | return NextToken(json, ref index);
299 | }
300 |
301 | static Token NextToken(char[] json, ref int index)
302 | {
303 | if (index == json.Length)
304 | return Token.None;
305 |
306 | char c = json[index++];
307 |
308 | switch (c) {
309 | case '{':
310 | return Token.CurlyOpen;
311 | case '}':
312 | return Token.CurlyClose;
313 | case '[':
314 | return Token.SquaredOpen;
315 | case ']':
316 | return Token.SquaredClose;
317 | case ',':
318 | return Token.Comma;
319 | case '"':
320 | return Token.String;
321 | case '0': case '1': case '2': case '3': case '4':
322 | case '5': case '6': case '7': case '8': case '9':
323 | case '-':
324 | return Token.Number;
325 | case ':':
326 | return Token.Colon;
327 | }
328 |
329 | index--;
330 |
331 | int remainingLength = json.Length - index;
332 |
333 | // false
334 | if (remainingLength >= 5) {
335 | if (json[index] == 'f' &&
336 | json[index + 1] == 'a' &&
337 | json[index + 2] == 'l' &&
338 | json[index + 3] == 's' &&
339 | json[index + 4] == 'e') {
340 | index += 5;
341 | return Token.False;
342 | }
343 | }
344 |
345 | // true
346 | if (remainingLength >= 4) {
347 | if (json[index] == 't' &&
348 | json[index + 1] == 'r' &&
349 | json[index + 2] == 'u' &&
350 | json[index + 3] == 'e') {
351 | index += 4;
352 | return Token.True;
353 | }
354 | }
355 |
356 | // null
357 | if (remainingLength >= 4) {
358 | if (json[index] == 'n' &&
359 | json[index + 1] == 'u' &&
360 | json[index + 2] == 'l' &&
361 | json[index + 3] == 'l') {
362 | index += 4;
363 | return Token.Null;
364 | }
365 | }
366 |
367 | return Token.None;
368 | }
369 | }
370 |
371 | public class JsonDecoder
372 | {
373 | public string errorMessage {
374 | get;
375 | private set;
376 | }
377 |
378 | public bool parseNumbersAsFloat {
379 | get;
380 | set;
381 | }
382 |
383 | Lexer lexer;
384 |
385 | public JsonDecoder()
386 | {
387 | errorMessage = null;
388 | parseNumbersAsFloat = false;
389 | }
390 |
391 | public object Decode(string text)
392 | {
393 | errorMessage = null;
394 |
395 | lexer = new Lexer(text);
396 | lexer.parseNumbersAsFloat = parseNumbersAsFloat;
397 |
398 | return ParseValue();
399 | }
400 |
401 | public static object DecodeText(string text)
402 | {
403 | var builder = new JsonDecoder();
404 | return builder.Decode(text);
405 | }
406 |
407 | IDictionary ParseObject()
408 | {
409 | var table = new Dictionary();
410 |
411 | // {
412 | lexer.NextToken();
413 |
414 | while (true) {
415 | var token = lexer.LookAhead();
416 |
417 | switch (token) {
418 | case Lexer.Token.None:
419 | TriggerError("Invalid token");
420 | return null;
421 | case Lexer.Token.Comma:
422 | lexer.NextToken();
423 | break;
424 | case Lexer.Token.CurlyClose:
425 | lexer.NextToken();
426 | return table;
427 | default:
428 | // name
429 | string name = EvalLexer(lexer.ParseString());
430 |
431 | if (errorMessage != null)
432 | return null;
433 |
434 | // :
435 | token = lexer.NextToken();
436 |
437 | if (token != Lexer.Token.Colon) {
438 | TriggerError("Invalid token; expected ':'");
439 | return null;
440 | }
441 |
442 | // value
443 | object value = ParseValue();
444 |
445 | if (errorMessage != null)
446 | return null;
447 |
448 | table[name] = value;
449 | break;
450 | }
451 | }
452 |
453 | //return null; // Unreachable code
454 | }
455 |
456 | IList