瀏覽代碼

WIP C runtime.

NathanSweet 12 年之前
父節點
當前提交
32a9a09831
共有 38 個文件被更改,包括 2457 次插入0 次删除
  1. 131 0
      spine-c/.cproject
  2. 27 0
      spine-c/.project
  3. 68 0
      spine-c/.settings/org.eclipse.cdt.codan.core.prefs
  4. 13 0
      spine-c/.settings/org.eclipse.cdt.managedbuilder.core.prefs
  5. 98 0
      spine-c/data/spineboy-skeleton.json
  6. 278 0
      spine-c/data/spineboy-walk.json
  7. 166 0
      spine-c/data/spineboy.atlas
  8. 二進制
      spine-c/data/spineboy.png
  9. 14 0
      spine-c/src/SfmlRegionAttachment.c
  10. 23 0
      spine-c/src/SfmlRegionAttachment.h
  11. 16 0
      spine-c/src/SfmlSkeleton.c
  12. 23 0
      spine-c/src/SfmlSkeleton.h
  13. 27 0
      spine-c/src/main.c
  14. 22 0
      spine-c/src/spine/Attachment.c
  15. 32 0
      spine-c/src/spine/Attachment.h
  16. 65 0
      spine-c/src/spine/Bone.c
  17. 40 0
      spine-c/src/spine/Bone.h
  18. 16 0
      spine-c/src/spine/BoneData.c
  19. 27 0
      spine-c/src/spine/BoneData.h
  20. 43 0
      spine-c/src/spine/RegionAttachment.c
  21. 28 0
      spine-c/src/spine/RegionAttachment.h
  22. 176 0
      spine-c/src/spine/Skeleton.c
  23. 71 0
      spine-c/src/spine/Skeleton.h
  24. 46 0
      spine-c/src/spine/SkeletonData.c
  25. 40 0
      spine-c/src/spine/SkeletonData.h
  26. 175 0
      spine-c/src/spine/SkeletonJson.c
  27. 26 0
      spine-c/src/spine/SkeletonJson.h
  28. 52 0
      spine-c/src/spine/Skin.c
  29. 37 0
      spine-c/src/spine/Skin.h
  30. 58 0
      spine-c/src/spine/Slot.c
  31. 39 0
      spine-c/src/spine/Slot.h
  32. 27 0
      spine-c/src/spine/SlotData.c
  33. 29 0
      spine-c/src/spine/SlotData.h
  34. 391 0
      spine-c/src/spine/cJSON.c
  35. 84 0
      spine-c/src/spine/cJSON.h
  36. 15 0
      spine-c/src/spine/spine.h
  37. 17 0
      spine-c/src/spine/util.c
  38. 17 0
      spine-c/src/spine/util.h

+ 131 - 0
spine-c/.cproject

@@ -0,0 +1,131 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<?fileVersion 4.0.0?>
+
+<cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
+	<storageModule moduleId="org.eclipse.cdt.core.settings">
+		<cconfiguration id="cdt.managedbuild.config.gnu.mingw.exe.debug.784427509">
+			<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.config.gnu.mingw.exe.debug.784427509" moduleId="org.eclipse.cdt.core.settings" name="Debug">
+				<externalSettings/>
+				<extensions>
+					<extension id="org.eclipse.cdt.core.PE" point="org.eclipse.cdt.core.BinaryParser"/>
+					<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+				</extensions>
+			</storageModule>
+			<storageModule moduleId="cdtBuildSystem" version="4.0.0">
+				<configuration artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug,org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.mingw.exe.debug.784427509" name="Debug" parent="cdt.managedbuild.config.gnu.mingw.exe.debug">
+					<folderInfo id="cdt.managedbuild.config.gnu.mingw.exe.debug.784427509." name="/" resourcePath="">
+						<toolChain id="cdt.managedbuild.toolchain.gnu.mingw.exe.debug.1244859277" name="MinGW GCC" superClass="cdt.managedbuild.toolchain.gnu.mingw.exe.debug">
+							<targetPlatform id="cdt.managedbuild.target.gnu.platform.mingw.exe.debug.2141344127" name="Debug Platform" superClass="cdt.managedbuild.target.gnu.platform.mingw.exe.debug"/>
+							<builder buildPath="${workspace_loc:/spine-ctest/Debug}" id="cdt.managedbuild.tool.gnu.builder.mingw.base.2012621380" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="CDT Internal Builder" superClass="cdt.managedbuild.tool.gnu.builder.mingw.base"/>
+							<tool id="cdt.managedbuild.tool.gnu.assembler.mingw.exe.debug.1379375071" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.mingw.exe.debug">
+								<inputType id="cdt.managedbuild.tool.gnu.assembler.input.1840963518" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
+							</tool>
+							<tool id="cdt.managedbuild.tool.gnu.archiver.mingw.base.1581759609" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.mingw.base"/>
+							<tool id="cdt.managedbuild.tool.gnu.cpp.compiler.mingw.exe.debug.1773467815" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.mingw.exe.debug">
+								<option id="gnu.cpp.compiler.mingw.exe.debug.option.optimization.level.541156248" name="Optimization Level" superClass="gnu.cpp.compiler.mingw.exe.debug.option.optimization.level" value="gnu.cpp.compiler.optimization.level.none" valueType="enumerated"/>
+								<option id="gnu.cpp.compiler.mingw.exe.debug.option.debugging.level.393447411" name="Debug Level" superClass="gnu.cpp.compiler.mingw.exe.debug.option.debugging.level" value="gnu.cpp.compiler.debugging.level.max" valueType="enumerated"/>
+								<option id="gnu.cpp.compiler.option.include.paths.1471448443" name="Include paths (-I)" superClass="gnu.cpp.compiler.option.include.paths"/>
+								<inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.564303729" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
+							</tool>
+							<tool id="cdt.managedbuild.tool.gnu.c.compiler.mingw.exe.debug.613741168" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.mingw.exe.debug">
+								<option defaultValue="gnu.c.optimization.level.none" id="gnu.c.compiler.mingw.exe.debug.option.optimization.level.71579608" name="Optimization Level" superClass="gnu.c.compiler.mingw.exe.debug.option.optimization.level" valueType="enumerated"/>
+								<option id="gnu.c.compiler.mingw.exe.debug.option.debugging.level.2068803714" name="Debug Level" superClass="gnu.c.compiler.mingw.exe.debug.option.debugging.level" value="gnu.c.debugging.level.max" valueType="enumerated"/>
+								<option id="gnu.c.compiler.option.include.paths.2051361089" name="Include paths (-I)" superClass="gnu.c.compiler.option.include.paths" valueType="includePath">
+									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/src}&quot;"/>
+								</option>
+								<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.603555848" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
+							</tool>
+							<tool id="cdt.managedbuild.tool.gnu.c.linker.mingw.exe.debug.1030541714" name="MinGW C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.mingw.exe.debug"/>
+							<tool id="cdt.managedbuild.tool.gnu.cpp.linker.mingw.exe.debug.1176451976" name="MinGW C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.mingw.exe.debug">
+								<inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.365190259" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
+									<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
+									<additionalInput kind="additionalinput" paths="$(LIBS)"/>
+								</inputType>
+							</tool>
+						</toolChain>
+					</folderInfo>
+					<sourceEntries>
+						<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="src"/>
+					</sourceEntries>
+				</configuration>
+			</storageModule>
+			<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
+		</cconfiguration>
+		<cconfiguration id="cdt.managedbuild.config.gnu.mingw.exe.release.486571591">
+			<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.config.gnu.mingw.exe.release.486571591" moduleId="org.eclipse.cdt.core.settings" name="Release">
+				<externalSettings/>
+				<extensions>
+					<extension id="org.eclipse.cdt.core.PE" point="org.eclipse.cdt.core.BinaryParser"/>
+					<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+					<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+				</extensions>
+			</storageModule>
+			<storageModule moduleId="cdtBuildSystem" version="4.0.0">
+				<configuration artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release,org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.mingw.exe.release.486571591" name="Release" parent="cdt.managedbuild.config.gnu.mingw.exe.release">
+					<folderInfo id="cdt.managedbuild.config.gnu.mingw.exe.release.486571591." name="/" resourcePath="">
+						<toolChain id="cdt.managedbuild.toolchain.gnu.mingw.exe.release.547801112" name="MinGW GCC" superClass="cdt.managedbuild.toolchain.gnu.mingw.exe.release">
+							<targetPlatform id="cdt.managedbuild.target.gnu.platform.mingw.exe.release.1049429369" name="Debug Platform" superClass="cdt.managedbuild.target.gnu.platform.mingw.exe.release"/>
+							<builder buildPath="${workspace_loc:/spine-ctest/Release}" id="cdt.managedbuild.tool.gnu.builder.mingw.base.1315046895" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="CDT Internal Builder" superClass="cdt.managedbuild.tool.gnu.builder.mingw.base"/>
+							<tool id="cdt.managedbuild.tool.gnu.assembler.mingw.exe.release.1856824863" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.mingw.exe.release">
+								<inputType id="cdt.managedbuild.tool.gnu.assembler.input.708953425" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
+							</tool>
+							<tool id="cdt.managedbuild.tool.gnu.archiver.mingw.base.178989121" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.mingw.base"/>
+							<tool id="cdt.managedbuild.tool.gnu.cpp.compiler.mingw.exe.release.1784931142" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.mingw.exe.release">
+								<option id="gnu.cpp.compiler.mingw.exe.release.option.optimization.level.206313849" name="Optimization Level" superClass="gnu.cpp.compiler.mingw.exe.release.option.optimization.level" value="gnu.cpp.compiler.optimization.level.most" valueType="enumerated"/>
+								<option id="gnu.cpp.compiler.mingw.exe.release.option.debugging.level.1678928207" name="Debug Level" superClass="gnu.cpp.compiler.mingw.exe.release.option.debugging.level" value="gnu.cpp.compiler.debugging.level.none" valueType="enumerated"/>
+								<inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.1028062039" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
+							</tool>
+							<tool id="cdt.managedbuild.tool.gnu.c.compiler.mingw.exe.release.582721725" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.mingw.exe.release">
+								<option defaultValue="gnu.c.optimization.level.most" id="gnu.c.compiler.mingw.exe.release.option.optimization.level.286982170" name="Optimization Level" superClass="gnu.c.compiler.mingw.exe.release.option.optimization.level" valueType="enumerated"/>
+								<option id="gnu.c.compiler.mingw.exe.release.option.debugging.level.1168053493" name="Debug Level" superClass="gnu.c.compiler.mingw.exe.release.option.debugging.level" value="gnu.c.debugging.level.none" valueType="enumerated"/>
+								<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.575877567" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
+							</tool>
+							<tool id="cdt.managedbuild.tool.gnu.c.linker.mingw.exe.release.1145816016" name="MinGW C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.mingw.exe.release"/>
+							<tool id="cdt.managedbuild.tool.gnu.cpp.linker.mingw.exe.release.372884406" name="MinGW C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.mingw.exe.release">
+								<inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.17549823" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
+									<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
+									<additionalInput kind="additionalinput" paths="$(LIBS)"/>
+								</inputType>
+							</tool>
+						</toolChain>
+					</folderInfo>
+					<sourceEntries>
+						<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="src"/>
+					</sourceEntries>
+				</configuration>
+			</storageModule>
+			<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
+		</cconfiguration>
+	</storageModule>
+	<storageModule moduleId="cdtBuildSystem" version="4.0.0">
+		<project id="spine-ctest.cdt.managedbuild.target.gnu.mingw.exe.1872348731" name="Executable" projectType="cdt.managedbuild.target.gnu.mingw.exe"/>
+	</storageModule>
+	<storageModule moduleId="scannerConfiguration">
+		<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
+		<scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.mingw.exe.release.486571591;cdt.managedbuild.config.gnu.mingw.exe.release.486571591.;cdt.managedbuild.tool.gnu.cpp.compiler.mingw.exe.release.1784931142;cdt.managedbuild.tool.gnu.cpp.compiler.input.1028062039">
+			<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP"/>
+		</scannerConfigBuildInfo>
+		<scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.mingw.exe.debug.784427509;cdt.managedbuild.config.gnu.mingw.exe.debug.784427509.;cdt.managedbuild.tool.gnu.c.compiler.mingw.exe.debug.613741168;cdt.managedbuild.tool.gnu.c.compiler.input.603555848">
+			<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC"/>
+		</scannerConfigBuildInfo>
+		<scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.mingw.exe.release.486571591;cdt.managedbuild.config.gnu.mingw.exe.release.486571591.;cdt.managedbuild.tool.gnu.c.compiler.mingw.exe.release.582721725;cdt.managedbuild.tool.gnu.c.compiler.input.575877567">
+			<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC"/>
+		</scannerConfigBuildInfo>
+		<scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.mingw.exe.debug.784427509;cdt.managedbuild.config.gnu.mingw.exe.debug.784427509.;cdt.managedbuild.tool.gnu.cpp.compiler.mingw.exe.debug.1773467815;cdt.managedbuild.tool.gnu.cpp.compiler.input.564303729">
+			<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP"/>
+		</scannerConfigBuildInfo>
+	</storageModule>
+	<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
+	<storageModule moduleId="refreshScope" versionNumber="2">
+		<configuration configurationName="Release">
+			<resource resourceType="PROJECT" workspacePath="/spine-ctest"/>
+		</configuration>
+		<configuration configurationName="Debug">
+			<resource resourceType="PROJECT" workspacePath="/spine-ctest"/>
+		</configuration>
+	</storageModule>
+	<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
+</cproject>

+ 27 - 0
spine-c/.project

@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>spine-c</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
+			<triggers>clean,full,incremental,</triggers>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
+			<triggers>full,incremental,</triggers>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.cdt.core.cnature</nature>
+		<nature>org.eclipse.cdt.core.ccnature</nature>
+		<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
+		<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
+	</natures>
+</projectDescription>

+ 68 - 0
spine-c/.settings/org.eclipse.cdt.codan.core.prefs

@@ -0,0 +1,68 @@
+eclipse.preferences.version=1
+org.eclipse.cdt.codan.checkers.errnoreturn=Warning
+org.eclipse.cdt.codan.checkers.errnoreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},implicit\=>false}
+org.eclipse.cdt.codan.checkers.errreturnvalue=Error
+org.eclipse.cdt.codan.checkers.errreturnvalue.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
+org.eclipse.cdt.codan.checkers.noreturn=Error
+org.eclipse.cdt.codan.checkers.noreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},implicit\=>false}
+org.eclipse.cdt.codan.internal.checkers.AbstractClassCreation=Error
+org.eclipse.cdt.codan.internal.checkers.AbstractClassCreation.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
+org.eclipse.cdt.codan.internal.checkers.AmbiguousProblem=Error
+org.eclipse.cdt.codan.internal.checkers.AmbiguousProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
+org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem=Warning
+org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
+org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem=Error
+org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
+org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem=-Warning
+org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},no_break_comment\=>"no break",last_case_param\=>true,empty_case_param\=>false}
+org.eclipse.cdt.codan.internal.checkers.CatchByReference=Warning
+org.eclipse.cdt.codan.internal.checkers.CatchByReference.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},unknown\=>false,exceptions\=>()}
+org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem=Error
+org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
+org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization=Warning
+org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},skip\=>true}
+org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem=Error
+org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
+org.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem=Error
+org.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
+org.eclipse.cdt.codan.internal.checkers.InvalidArguments=Error
+org.eclipse.cdt.codan.internal.checkers.InvalidArguments.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
+org.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem=Error
+org.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
+org.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem=Error
+org.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
+org.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem=Error
+org.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
+org.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem=Error
+org.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
+org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker=-Info
+org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},pattern\=>"^[a-z]",macro\=>true,exceptions\=>()}
+org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem=Warning
+org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
+org.eclipse.cdt.codan.internal.checkers.OverloadProblem=Error
+org.eclipse.cdt.codan.internal.checkers.OverloadProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
+org.eclipse.cdt.codan.internal.checkers.RedeclarationProblem=Error
+org.eclipse.cdt.codan.internal.checkers.RedeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
+org.eclipse.cdt.codan.internal.checkers.RedefinitionProblem=Error
+org.eclipse.cdt.codan.internal.checkers.RedefinitionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
+org.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem=-Warning
+org.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
+org.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem=-Warning
+org.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
+org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem=Warning
+org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},macro\=>true,exceptions\=>()}
+org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem=Warning
+org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},paramNot\=>false}
+org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem=Warning
+org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},else\=>false,afterelse\=>false}
+org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem=Error
+org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
+org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem=Warning
+org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},macro\=>true}
+org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem=Warning
+org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},macro\=>true}
+org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem=Warning
+org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},macro\=>true,exceptions\=>("@(\#)","$Id")}
+org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem=Error
+org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
+useParentScope=false

+ 13 - 0
spine-c/.settings/org.eclipse.cdt.managedbuilder.core.prefs

@@ -0,0 +1,13 @@
+eclipse.preferences.version=1
+environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.mingw.exe.debug.784427509/CPATH/delimiter=;
+environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.mingw.exe.debug.784427509/CPATH/operation=remove
+environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.mingw.exe.debug.784427509/CPLUS_INCLUDE_PATH/delimiter=;
+environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.mingw.exe.debug.784427509/CPLUS_INCLUDE_PATH/operation=remove
+environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.mingw.exe.debug.784427509/C_INCLUDE_PATH/delimiter=;
+environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.mingw.exe.debug.784427509/C_INCLUDE_PATH/operation=remove
+environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.mingw.exe.debug.784427509/append=true
+environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.mingw.exe.debug.784427509/appendContributed=true
+environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.mingw.exe.debug.784427509/LIBRARY_PATH/delimiter=;
+environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.mingw.exe.debug.784427509/LIBRARY_PATH/operation=remove
+environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.mingw.exe.debug.784427509/append=true
+environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.mingw.exe.debug.784427509/appendContributed=true

+ 98 - 0
spine-c/data/spineboy-skeleton.json

@@ -0,0 +1,98 @@
+{
+"bones": [
+	{ "name": "root", "length": 0 },
+	{ "name": "hip", "parent": "root", "length": 0, "x": 0.64, "y": 114.41 },
+	{ "name": "left upper leg", "parent": "hip", "length": 50.39, "x": 14.45, "y": 2.81, "rotation": -89.09 },
+	{ "name": "left lower leg", "parent": "left upper leg", "length": 56.45, "x": 51.78, "y": 3.46, "rotation": -16.65 },
+	{ "name": "left foot", "parent": "left lower leg", "length": 46.5, "x": 64.02, "y": -8.67, "rotation": 102.43 },
+	{ "name": "right upper leg", "parent": "hip", "length": 45.76, "x": -18.27, "rotation": -101.13 },
+	{ "name": "right lower leg", "parent": "right upper leg", "length": 58.52, "x": 50.21, "y": 0.6, "rotation": -10.7 },
+	{ "name": "right foot", "parent": "right lower leg", "length": 45.45, "x": 64.88, "y": 0.04, "rotation": 110.3 },
+	{ "name": "torso", "parent": "hip", "length": 85.82, "x": -6.42, "y": 1.97, "rotation": 94.95 },
+	{ "name": "neck", "parent": "torso", "length": 18.38, "x": 83.64, "y": -1.78, "rotation": 0.9 },
+	{ "name": "head", "parent": "neck", "length": 68.28, "x": 19.09, "y": 6.97, "rotation": -8.94 },
+	{ "name": "right shoulder", "parent": "torso", "length": 49.95, "x": 81.9, "y": 6.79, "rotation": 130.6 },
+	{ "name": "right arm", "parent": "right shoulder", "length": 36.74, "x": 49.95, "y": -0.12, "rotation": 40.12 },
+	{ "name": "right hand", "parent": "right arm", "length": 15.32, "x": 36.9, "y": 0.34, "rotation": 2.35 },
+	{ "name": "left shoulder", "parent": "torso", "length": 44.19, "x": 78.96, "y": -15.75, "rotation": -156.96 },
+	{ "name": "left arm", "parent": "left shoulder", "length": 35.62, "x": 44.19, "y": -0.01, "rotation": 28.16 },
+	{ "name": "left hand", "parent": "left arm", "length": 11.52, "x": 35.62, "y": 0.07, "rotation": 2.7 },
+	{ "name": "pelvis", "parent": "hip", "length": 0, "x": 1.41, "y": -6.57 }
+],
+"slots": [
+	{ "name": "template", "bone": "root", "color": "ff898c86" },
+	{ "name": "left shoulder", "bone": "left shoulder", "attachment": "left-shoulder" },
+	{ "name": "left arm", "bone": "left arm", "attachment": "left-arm" },
+	{ "name": "left hand", "bone": "left hand", "attachment": "left-hand" },
+	{ "name": "left foot", "bone": "left foot", "attachment": "left-foot" },
+	{ "name": "left lower leg", "bone": "left lower leg", "attachment": "left-lower-leg" },
+	{ "name": "left upper leg", "bone": "left upper leg", "attachment": "left-upper-leg" },
+	{ "name": "pelvis", "bone": "pelvis", "attachment": "pelvis" },
+	{ "name": "right foot", "bone": "right foot", "attachment": "right-foot" },
+	{ "name": "right lower leg", "bone": "right lower leg", "attachment": "right-lower-leg" },
+	{ "name": "right upper leg", "bone": "right upper leg", "attachment": "right-upper-leg" },
+	{ "name": "torso", "bone": "torso", "attachment": "torso" },
+	{ "name": "neck", "bone": "neck", "attachment": "neck" },
+	{ "name": "head", "bone": "head", "attachment": "head" },
+	{ "name": "eyes", "bone": "head", "attachment": "eyes" },
+	{ "name": "right shoulder", "bone": "right shoulder", "attachment": "right-shoulder" },
+	{ "name": "right arm", "bone": "right arm", "attachment": "right-arm" },
+	{ "name": "right hand", "bone": "right hand", "attachment": "right-hand" }
+],
+"skins": {
+	"default": {
+		"left shoulder": {
+			"left-shoulder": { "x": 23.74, "y": 0.11, "rotation": 62.01, "width": 34, "height": 53 }
+		},
+		"left arm": {
+			"left-arm": { "x": 15.11, "y": -0.44, "rotation": 33.84, "width": 35, "height": 29 }
+		},
+		"left hand": {
+			"left-hand": { "x": 0.75, "y": 1.86, "rotation": 31.14, "width": 35, "height": 38 }
+		},
+		"left foot": {
+			"left-foot": { "x": 24.35, "y": 8.88, "rotation": 3.32, "width": 65, "height": 30 }
+		},
+		"left lower leg": {
+			"left-lower-leg": { "x": 24.55, "y": -1.92, "rotation": 105.75, "width": 49, "height": 64 }
+		},
+		"left upper leg": {
+			"left-upper-leg": { "x": 26.12, "y": -1.85, "rotation": 89.09, "width": 33, "height": 67 }
+		},
+		"pelvis": {
+			"pelvis": { "x": -4.83, "y": 10.62, "width": 63, "height": 47 }
+		},
+		"right foot": {
+			"right-foot": { "x": 19.02, "y": 8.47, "rotation": 1.52, "width": 67, "height": 30 }
+		},
+		"right lower leg": {
+			"right-lower-leg": { "x": 23.28, "y": -2.59, "rotation": 111.83, "width": 51, "height": 64 }
+		},
+		"right upper leg": {
+			"right-upper-leg": { "x": 23.03, "y": 0.25, "rotation": 101.13, "width": 44, "height": 70 }
+		},
+		"torso": {
+			"torso": { "x": 44.57, "y": -7.08, "rotation": -94.95, "width": 68, "height": 92 }
+		},
+		"neck": {
+			"neck": { "x": 9.42, "y": -3.66, "rotation": -100.15, "width": 34, "height": 28 }
+		},
+		"head": {
+			"head": { "x": 53.94, "y": -5.75, "rotation": -86.9, "width": 121, "height": 132 }
+		},
+		"eyes": {
+			"eyes": { "x": 28.94, "y": -32.92, "rotation": -86.9, "width": 34, "height": 27 },
+			"eyes-closed": { "x": 28.77, "y": -32.86, "rotation": -86.9, "width": 34, "height": 27 }
+		},
+		"right shoulder": {
+			"right-shoulder": { "x": 25.86, "y": 0.03, "rotation": 134.44, "width": 52, "height": 51 }
+		},
+		"right arm": {
+			"right-arm": { "x": 18.34, "y": -2.64, "rotation": 94.32, "width": 21, "height": 45 }
+		},
+		"right hand": {
+			"right-hand": { "x": 6.82, "y": 1.25, "rotation": 91.96, "width": 32, "height": 32 }
+		}
+	}
+}
+}

+ 278 - 0
spine-c/data/spineboy-walk.json

@@ -0,0 +1,278 @@
+{
+"bones": {
+	"left upper leg": {
+		"rotate": [
+			{ "time": 0, "angle": -26.55 },
+			{ "time": 0.1333, "angle": -8.78 },
+			{ "time": 0.2666, "angle": 9.51 },
+			{ "time": 0.4, "angle": 30.74 },
+			{ "time": 0.5333, "angle": 25.33 },
+			{ "time": 0.6666, "angle": 26.11 },
+			{ "time": 0.8, "angle": -7.7 },
+			{ "time": 0.9333, "angle": -21.19 },
+			{ "time": 1.0666, "angle": -26.55 }
+		],
+		"translate": [
+			{ "time": 0, "x": -3, "y": -2.25 },
+			{ "time": 0.4, "x": -2.18, "y": -2.25 },
+			{ "time": 1.0666, "x": -3, "y": -2.25 }
+		]
+	},
+	"right upper leg": {
+		"rotate": [
+			{ "time": 0, "angle": 42.45 },
+			{ "time": 0.1333, "angle": 52.1 },
+			{ "time": 0.2666, "angle": 5.96 },
+			{ "time": 0.5333, "angle": -16.93 },
+			{ "time": 0.6666, "angle": 1.89 },
+			{
+				"time": 0.8,
+				"angle": 28.06,
+				"curve": [ 0.462, 0.11, 1, 1 ]
+			},
+			{
+				"time": 0.9333,
+				"angle": 58.68,
+				"curve": [ 0.5, 0.02, 1, 1 ]
+			},
+			{ "time": 1.0666, "angle": 42.45 }
+		],
+		"translate": [
+			{ "time": 0, "x": 8.11, "y": -2.36 },
+			{ "time": 0.1333, "x": 10.03, "y": -2.56 },
+			{ "time": 0.4, "x": 2.76, "y": -2.97 },
+			{ "time": 0.5333, "x": 2.76, "y": -2.81 },
+			{ "time": 0.9333, "x": 8.67, "y": -2.54 },
+			{ "time": 1.0666, "x": 8.11, "y": -2.36 }
+		]
+	},
+	"left lower leg": {
+		"rotate": [
+			{ "time": 0, "angle": -10.21 },
+			{ "time": 0.1333, "angle": -55.64 },
+			{ "time": 0.2666, "angle": -68.12 },
+			{ "time": 0.5333, "angle": 5.11 },
+			{ "time": 0.6666, "angle": -28.29 },
+			{ "time": 0.8, "angle": 4.08 },
+			{ "time": 0.9333, "angle": 3.53 },
+			{ "time": 1.0666, "angle": -10.21 }
+		]
+	},
+	"left foot": {
+		"rotate": [
+			{ "time": 0, "angle": -3.69 },
+			{ "time": 0.1333, "angle": -10.42 },
+			{ "time": 0.2666, "angle": -17.14 },
+			{ "time": 0.4, "angle": -2.83 },
+			{ "time": 0.5333, "angle": -3.87 },
+			{ "time": 0.6666, "angle": 2.78 },
+			{ "time": 0.8, "angle": 1.68 },
+			{ "time": 0.9333, "angle": -8.54 },
+			{ "time": 1.0666, "angle": -3.69 }
+		]
+	},
+	"right shoulder": {
+		"rotate": [
+			{
+				"time": 0,
+				"angle": 20.89,
+				"curve": [ 0.264, 0, 0.75, 1 ]
+			},
+			{
+				"time": 0.1333,
+				"angle": 3.72,
+				"curve": [ 0.272, 0, 0.841, 1 ]
+			},
+			{ "time": 0.6666, "angle": -278.28 },
+			{ "time": 1.0666, "angle": 20.89 }
+		],
+		"translate": [
+			{ "time": 0, "x": -7.84, "y": 7.19 },
+			{ "time": 0.1333, "x": -6.36, "y": 6.42 },
+			{ "time": 0.6666, "x": -11.07, "y": 5.25 },
+			{ "time": 1.0666, "x": -7.84, "y": 7.19 }
+		]
+	},
+	"right arm": {
+		"rotate": [
+			{
+				"time": 0,
+				"angle": -4.02,
+				"curve": [ 0.267, 0, 0.804, 0.99 ]
+			},
+			{
+				"time": 0.1333,
+				"angle": -13.99,
+				"curve": [ 0.341, 0, 1, 1 ]
+			},
+			{
+				"time": 0.6666,
+				"angle": 36.54,
+				"curve": [ 0.307, 0, 0.787, 0.99 ]
+			},
+			{ "time": 1.0666, "angle": -4.02 }
+		]
+	},
+	"right hand": {
+		"rotate": [
+			{ "time": 0, "angle": 22.92 },
+			{ "time": 0.4, "angle": -8.97 },
+			{ "time": 0.6666, "angle": 0.51 },
+			{ "time": 1.0666, "angle": 22.92 }
+		]
+	},
+	"left shoulder": {
+		"rotate": [
+			{ "time": 0, "angle": -1.47 },
+			{ "time": 0.1333, "angle": 13.6 },
+			{ "time": 0.6666, "angle": 280.74 },
+			{ "time": 1.0666, "angle": -1.47 }
+		],
+		"translate": [
+			{ "time": 0, "x": -1.76, "y": 0.56 },
+			{ "time": 0.6666, "x": -2.47, "y": 8.14 },
+			{ "time": 1.0666, "x": -1.76, "y": 0.56 }
+		]
+	},
+	"left hand": {
+		"rotate": [
+			{
+				"time": 0,
+				"angle": 11.58,
+				"curve": [ 0.169, 0.37, 0.632, 1.55 ]
+			},
+			{
+				"time": 0.1333,
+				"angle": 28.13,
+				"curve": [ 0.692, 0, 0.692, 0.99 ]
+			},
+			{
+				"time": 0.6666,
+				"angle": -27.42,
+				"curve": [ 0.117, 0.41, 0.738, 1.76 ]
+			},
+			{ "time": 0.8, "angle": -36.32 },
+			{ "time": 1.0666, "angle": 11.58 }
+		]
+	},
+	"left arm": {
+		"rotate": [
+			{ "time": 0, "angle": -8.27 },
+			{ "time": 0.1333, "angle": 18.43 },
+			{ "time": 0.6666, "angle": 0.88 },
+			{ "time": 1.0666, "angle": -8.27 }
+		]
+	},
+	"torso": {
+		"rotate": [
+			{ "time": 0, "angle": -10.28 },
+			{
+				"time": 0.1333,
+				"angle": -15.38,
+				"curve": [ 0.545, 0, 1, 1 ]
+			},
+			{
+				"time": 0.4,
+				"angle": -9.78,
+				"curve": [ 0.58, 0.17, 1, 1 ]
+			},
+			{ "time": 0.6666, "angle": -15.75 },
+			{ "time": 0.9333, "angle": -7.06 },
+			{ "time": 1.0666, "angle": -10.28 }
+		],
+		"translate": [
+			{ "time": 0, "x": -3.67, "y": 1.68 },
+			{ "time": 0.1333, "x": -3.67, "y": 0.68 },
+			{ "time": 0.4, "x": -3.67, "y": 1.97 },
+			{ "time": 0.6666, "x": -3.67, "y": -0.14 },
+			{ "time": 1.0666, "x": -3.67, "y": 1.68 }
+		]
+	},
+	"right foot": {
+		"rotate": [
+			{ "time": 0, "angle": -5.25 },
+			{ "time": 0.2666, "angle": -4.08 },
+			{ "time": 0.4, "angle": -6.45 },
+			{ "time": 0.5333, "angle": -5.39 },
+			{ "time": 0.8, "angle": -11.68 },
+			{ "time": 0.9333, "angle": 0.46 },
+			{ "time": 1.0666, "angle": -5.25 }
+		]
+	},
+	"right lower leg": {
+		"rotate": [
+			{ "time": 0, "angle": -3.39 },
+			{ "time": 0.1333, "angle": -45.53 },
+			{ "time": 0.2666, "angle": -2.59 },
+			{ "time": 0.5333, "angle": -19.53 },
+			{ "time": 0.6666, "angle": -64.8 },
+			{
+				"time": 0.8,
+				"angle": -82.56,
+				"curve": [ 0.557, 0.18, 1, 1 ]
+			},
+			{ "time": 1.0666, "angle": -3.39 }
+		]
+	},
+	"hip": {
+		"rotate": [
+			{ "time": 0, "angle": 0, "curve": "stepped" },
+			{ "time": 1.0666, "angle": 0 }
+		],
+		"translate": [
+			{ "time": 0, "x": 0, "y": 0 },
+			{
+				"time": 0.1333,
+				"x": 0,
+				"y": -7.61,
+				"curve": [ 0.272, 0.86, 1, 1 ]
+			},
+			{ "time": 0.4, "x": 0, "y": 8.7 },
+			{ "time": 0.5333, "x": 0, "y": -0.41 },
+			{
+				"time": 0.6666,
+				"x": 0,
+				"y": -7.05,
+				"curve": [ 0.235, 0.89, 1, 1 ]
+			},
+			{ "time": 0.8, "x": 0, "y": 2.92 },
+			{ "time": 0.9333, "x": 0, "y": 6.78 },
+			{ "time": 1.0666, "x": 0, "y": 0 }
+		]
+	},
+	"neck": {
+		"rotate": [
+			{ "time": 0, "angle": 3.6 },
+			{ "time": 0.1333, "angle": 17.49 },
+			{ "time": 0.2666, "angle": 6.1 },
+			{ "time": 0.4, "angle": 3.45 },
+			{ "time": 0.5333, "angle": 5.17 },
+			{ "time": 0.6666, "angle": 18.36 },
+			{ "time": 0.8, "angle": 6.09 },
+			{ "time": 0.9333, "angle": 2.28 },
+			{ "time": 1.0666, "angle": 3.6 }
+		]
+	},
+	"head": {
+		"rotate": [
+			{
+				"time": 0,
+				"angle": 3.6,
+				"curve": [ 0, 0, 0.704, 1.61 ]
+			},
+			{ "time": 0.1666, "angle": -0.2 },
+			{ "time": 0.2666, "angle": 6.1 },
+			{ "time": 0.4, "angle": 3.45 },
+			{
+				"time": 0.5333,
+				"angle": 5.17,
+				"curve": [ 0, 0, 0.704, 1.61 ]
+			},
+			{ "time": 0.7, "angle": 1.1 },
+			{ "time": 0.8, "angle": 6.09 },
+			{ "time": 0.9333, "angle": 2.28 },
+			{ "time": 1.0666, "angle": 3.6 }
+		]
+	}
+}
+}

+ 166 - 0
spine-c/data/spineboy.atlas

@@ -0,0 +1,166 @@
+
+../data/spineboy.png
+format: RGBA8888
+filter: Nearest,Nearest
+repeat: none
+head
+  rotate: false
+  xy: 1, 122
+  size: 121, 132
+  orig: 121, 132
+  offset: 0, 0
+  index: -1
+torso
+  rotate: false
+  xy: 1, 28
+  size: 68, 92
+  orig: 68, 92
+  offset: 0, 0
+  index: -1
+left-pant-bottom
+  rotate: false
+  xy: 1, 4
+  size: 44, 22
+  orig: 44, 22
+  offset: 0, 0
+  index: -1
+right-pant-bottom
+  rotate: false
+  xy: 47, 8
+  size: 46, 18
+  orig: 46, 18
+  offset: 0, 0
+  index: -1
+right-upper-leg
+  rotate: false
+  xy: 71, 50
+  size: 44, 70
+  orig: 44, 70
+  offset: 0, 0
+  index: -1
+pelvis
+  rotate: false
+  xy: 95, 1
+  size: 63, 47
+  orig: 63, 47
+  offset: 0, 0
+  index: -1
+left-upper-leg
+  rotate: false
+  xy: 117, 53
+  size: 33, 67
+  orig: 33, 67
+  offset: 0, 0
+  index: -1
+right-foot
+  rotate: false
+  xy: 160, 224
+  size: 67, 30
+  orig: 67, 30
+  offset: 0, 0
+  index: -1
+left-shoulder
+  rotate: false
+  xy: 124, 201
+  size: 34, 53
+  orig: 34, 53
+  offset: 0, 0
+  index: -1
+left-ankle
+  rotate: false
+  xy: 229, 222
+  size: 25, 32
+  orig: 25, 32
+  offset: 0, 0
+  index: -1
+left-foot
+  rotate: false
+  xy: 160, 192
+  size: 65, 30
+  orig: 65, 30
+  offset: 0, 0
+  index: -1
+neck
+  rotate: false
+  xy: 124, 171
+  size: 34, 28
+  orig: 34, 28
+  offset: 0, 0
+  index: -1
+right-arm
+  rotate: false
+  xy: 124, 124
+  size: 21, 45
+  orig: 21, 45
+  offset: 0, 0
+  index: -1
+right-ankle
+  rotate: false
+  xy: 227, 190
+  size: 25, 30
+  orig: 25, 30
+  offset: 0, 0
+  index: -1
+left-hand
+  rotate: false
+  xy: 147, 131
+  size: 35, 38
+  orig: 35, 38
+  offset: 0, 0
+  index: -1
+left-arm
+  rotate: false
+  xy: 184, 161
+  size: 35, 29
+  orig: 35, 29
+  offset: 0, 0
+  index: -1
+eyes-closed
+  rotate: false
+  xy: 221, 161
+  size: 34, 27
+  orig: 34, 27
+  offset: 0, 0
+  index: -1
+right-lower-leg
+  rotate: false
+  xy: 152, 65
+  size: 51, 64
+  orig: 51, 64
+  offset: 0, 0
+  index: -1
+right-foot-idle
+  rotate: false
+  xy: 184, 131
+  size: 53, 28
+  orig: 53, 28
+  offset: 0, 0
+  index: -1
+left-lower-leg
+  rotate: false
+  xy: 205, 65
+  size: 49, 64
+  orig: 49, 64
+  offset: 0, 0
+  index: -1
+right-shoulder
+  rotate: false
+  xy: 160, 12
+  size: 52, 51
+  orig: 52, 51
+  offset: 0, 0
+  index: -1
+eyes
+  rotate: false
+  xy: 214, 36
+  size: 34, 27
+  orig: 34, 27
+  offset: 0, 0
+  index: -1
+right-hand
+  rotate: false
+  xy: 214, 2
+  size: 32, 32
+  orig: 32, 32
+  offset: 0, 0
+  index: -1

二進制
spine-c/data/spineboy.png


+ 14 - 0
spine-c/src/SfmlRegionAttachment.c

@@ -0,0 +1,14 @@
+#include "SfmlRegionAttachment.h"
+#include <stdlib.h>
+
+void SfmlRegionAttachment_dispose (Attachment* attachment) {
+	SfmlRegionAttachment* this = (SfmlRegionAttachment*)attachment;
+	RegionAttachment_dispose(&this->super);
+}
+
+SfmlRegionAttachment* SfmlRegionAttachment_create (const char* name) {
+	SfmlRegionAttachment* this = calloc(1, sizeof(SfmlRegionAttachment));
+	RegionAttachment_init(&this->super, name);
+	((Attachment*)this)->_dispose = SfmlRegionAttachment_dispose;
+	return this;
+}

+ 23 - 0
spine-c/src/SfmlRegionAttachment.h

@@ -0,0 +1,23 @@
+#ifndef SPINE_SFMLREGIONATTACHMENT_H_
+#define SPINE_SFMLREGIONATTACHMENT_H_
+
+#include <spine/RegionAttachment.h>
+
+#ifdef __cplusplus
+namespace spine {
+extern "C" {
+#endif
+
+typedef struct {
+	RegionAttachment super;
+	int meow;
+} SfmlRegionAttachment;
+
+SfmlRegionAttachment* SfmlRegionAttachment_create (const char* name);
+
+#ifdef __cplusplus
+}
+}
+#endif
+
+#endif /* SPINE_SFMLREGIONATTACHMENT_H_ */

+ 16 - 0
spine-c/src/SfmlSkeleton.c

@@ -0,0 +1,16 @@
+#include "SfmlSkeleton.h"
+#include <stdlib.h>
+
+void SfmlSkeleton_dispose (Skeleton* skeleton) {
+	// SfmlSkeleton* this = (SfmlSkeleton*)skeleton;
+}
+
+Skeleton* Skeleton_create (SkeletonData* data) {
+	SfmlSkeleton* this = calloc(1, sizeof(SfmlSkeleton));
+	Skeleton_init(&this->super, data);
+	this->super._dispose = SfmlSkeleton_dispose;
+	return &this->super;
+}
+
+void Skeleton_draw (Skeleton* skeleton) {
+}

+ 23 - 0
spine-c/src/SfmlSkeleton.h

@@ -0,0 +1,23 @@
+#ifndef SPINE_SFMLSKELETON_H_
+#define SPINE_SFMLSKELETON_H_
+
+#include <spine/Skeleton.h>
+
+#ifdef __cplusplus
+namespace spine {extern "C" {
+#endif
+
+typedef struct {
+	Skeleton super;
+	int meow;
+} SfmlSkeleton;
+
+Skeleton* Skeleton_create (SkeletonData* data);
+
+void Skeleton_draw ();
+
+#ifdef __cplusplus
+}}
+#endif
+
+#endif /* SPINE_SFMLSKELETON_H_ */

+ 27 - 0
spine-c/src/main.c

@@ -0,0 +1,27 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <spine/spine.h>
+#include "SfmlSkeleton.h"
+#include "spine/cJSON.h"
+
+int main (void) {
+	//BoneData *boneData = BoneData_create("meow");
+
+	//printf("name: %s\n", boneData->name);
+	//printf("length struct: %f\n", boneData->length);
+
+	//SkeletonData* data =
+	SkeletonJson_readSkeletonDataFile("data/spineboy-skeleton.json");
+	printf("error: %s\n", SkeletonJson_getError());
+
+	SkeletonData *skeletonData = SkeletonData_create();
+	Skeleton* skeleton = Skeleton_create(skeletonData);
+	//Skeleton_something(skeleton);
+	printf("meow? %d\n", ((SfmlSkeleton*)skeleton)->meow);
+	Skeleton_dispose(skeleton);
+	printf("meow? %d\n", ((SfmlSkeleton*)skeleton)->meow);
+
+	return 0;
+}

+ 22 - 0
spine-c/src/spine/Attachment.c

@@ -0,0 +1,22 @@
+#include <spine/Attachment.h>
+#include <spine/util.h>
+
+static AttachmentLoader loader;
+
+void Attachment_setAttachmentLoader (AttachmentLoader value) {
+	loader = value;
+}
+
+AttachmentLoader Attachment_getAttachmentLoader () {
+	return loader;
+}
+
+void Attachment_init (Attachment* this, const char* name) {
+	MALLOC_STR(this->name, name);
+}
+
+void Attachment_dispose (Attachment* this) {
+	this->_dispose(this);
+	FREE(this->name)
+	FREE(this)
+}

+ 32 - 0
spine-c/src/spine/Attachment.h

@@ -0,0 +1,32 @@
+#ifndef SPINE_ATTACHMENT_H_
+#define SPINE_ATTACHMENT_H_
+
+#ifdef __cplusplus
+namespace spine {
+extern "C" {
+#endif
+
+typedef enum {
+	ATTACHMENT_REGION, ATTACHMENT_REGION_SEQUENCE
+} AttachmentType;
+
+typedef struct Attachment Attachment;
+struct Attachment {
+	const char* const name;
+	void (*_dispose) (Attachment* attachment);
+};
+
+typedef Attachment* (*AttachmentLoader) (AttachmentType type, const char* name);
+
+void Attachment_setAttachmentLoader (AttachmentLoader loader);
+AttachmentLoader Attachment_getAttachmentLoader ();
+
+void Attachment_init (Attachment* attachment, const char* name);
+void Attachment_dispose (Attachment* attachment);
+
+#ifdef __cplusplus
+}
+}
+#endif
+
+#endif /* SPINE_ATTACHMENT_H_ */

+ 65 - 0
spine-c/src/spine/Bone.c

@@ -0,0 +1,65 @@
+#include <spine/Bone.h>
+#include <math.h>
+#include <spine/util.h>
+
+static int yDown;
+
+void Bone_setYDown (int value) {
+	yDown = value;
+}
+
+Bone* Bone_create (BoneData* data, Bone* parent) {
+	Bone* this = calloc(1, sizeof(Bone));
+	CAST(BoneData*, this->data) = data;
+	CAST(Bone*, this->parent) = parent;
+	this->scaleX = 1;
+	this->scaleY = 1;
+	return this;
+}
+
+void Bone_dispose (Bone* this) {
+	FREE(this)
+}
+
+void Bone_setToBindPose (Bone* this) {
+	this->x = this->data->x;
+	this->y = this->data->y;
+	this->rotation = this->data->rotation;
+	this->scaleX = this->data->scaleX;
+	this->scaleY = this->data->scaleY;
+}
+
+void Bone_updateWorldTransform (Bone* this, int flipX, int flipY) {
+	if (this->parent) {
+		CAST(float, this->worldX) = this->x * this->parent->m00 + this->y * this->parent->m01 + this->parent->worldX;
+		CAST(float, this->worldY) = this->x * this->parent->m10 + this->y * this->parent->m11 + this->parent->worldY;
+		CAST(float, this->worldScaleX) = this->parent->worldScaleX * this->scaleX;
+		CAST(float, this->worldScaleY) = this->parent->worldScaleY * this->scaleY;
+		CAST(float, this->worldRotation) = this->parent->worldRotation + this->rotation;
+	} else {
+		CAST(float, this->worldX) = this->x;
+		CAST(float, this->worldY) = this->y;
+		CAST(float, this->worldScaleX) = this->scaleX;
+		CAST(float, this->worldScaleY) = this->scaleY;
+		CAST(float, this->worldRotation) = this->rotation;
+	}
+	float radians = (float)(this->worldRotation * 3.1415926535897932385 / 180);
+	float cos = cosf(radians);
+	float sin = sinf(radians);
+	CAST(float, this->m00) = cos * this->worldScaleX;
+	CAST(float, this->m10) = sin * this->worldScaleX;
+	CAST(float, this->m01) = -sin * this->worldScaleY;
+	CAST(float, this->m11) = cos * this->worldScaleY;
+	if (flipX) {
+		CAST(float, this->m00) = -this->m00;
+		CAST(float, this->m01) = -this->m01;
+	}
+	if (flipY) {
+		CAST(float, this->m10) = -this->m10;
+		CAST(float, this->m11) = -this->m11;
+	}
+	if (yDown) {
+		CAST(float, this->m10) = -this->m10;
+		CAST(float, this->m11) = -this->m11;
+	}
+}

+ 40 - 0
spine-c/src/spine/Bone.h

@@ -0,0 +1,40 @@
+#ifndef SPINE_BONE_H_
+#define SPINE_BONE_H_
+
+#include <spine/BoneData.h>
+
+#ifdef __cplusplus
+namespace spine {
+extern "C" {
+#endif
+
+typedef struct Bone Bone;
+struct Bone {
+	BoneData* const data;
+	Bone* const parent;
+	float x, y;
+	float rotation;
+	float scaleX, scaleY;
+
+	float const m00, m01, worldX; // a b x
+	float const m10, m11, worldY; // c d y
+	float const worldRotation;
+	float const worldScaleX, worldScaleY;
+};
+
+void Bone_setYDown (int yDown);
+
+/** @param parent May be zero. */
+Bone* Bone_create (BoneData* data, Bone* parent);
+void Bone_dispose (Bone* bone);
+
+void Bone_setToBindPose (Bone* bone);
+
+void Bone_updateWorldTransform (Bone* bone, int flipX, int flipY);
+
+#ifdef __cplusplus
+}
+}
+#endif
+
+#endif /* SPINE_BONE_H_ */

+ 16 - 0
spine-c/src/spine/BoneData.c

@@ -0,0 +1,16 @@
+#include <spine/BoneData.h>
+#include <spine/util.h>
+
+BoneData* BoneData_create (const char* name, BoneData* parent) {
+	BoneData* this = calloc(1, sizeof(BoneData));
+	MALLOC_STR(this->name, name)
+	CAST(BoneData*, this->parent) = parent;
+	this->scaleX = 1;
+	this->scaleY = 1;
+	return this;
+}
+
+void BoneData_dispose (BoneData* this) {
+	FREE(this->name)
+	FREE(this)
+}

+ 27 - 0
spine-c/src/spine/BoneData.h

@@ -0,0 +1,27 @@
+#ifndef SPINE_BONEDATA_H_
+#define SPINE_BONEDATA_H_
+
+#ifdef __cplusplus
+namespace spine {
+extern "C" {
+#endif
+
+typedef struct BoneData BoneData;
+struct BoneData {
+	const char* const name;
+	BoneData* const parent;
+	float length;
+	float x, y;
+	float rotation;
+	float scaleX, scaleY;
+};
+
+BoneData* BoneData_create (const char* name, BoneData* parent);
+void BoneData_dispose (BoneData* boneData);
+
+#ifdef __cplusplus
+}
+}
+#endif
+
+#endif /* SPINE_BONEDATA_H_ */

+ 43 - 0
spine-c/src/spine/RegionAttachment.c

@@ -0,0 +1,43 @@
+#include <spine/RegionAttachment.h>
+#include <math.h>
+#include <spine/util.h>
+
+void RegionAttachment_init (RegionAttachment* this, const char* name) {
+	Attachment_init(&this->super, name);
+	this->scaleX = 1;
+	this->scaleY = 1;
+}
+
+void RegionAttachment_dispose (RegionAttachment* this) {
+	Attachment_dispose(&this->super);
+}
+
+void RegionAttachment_updateOffset (RegionAttachment* this) {
+	float localX2 = this->width / 2;
+	float localY2 = this->height / 2;
+	float localX = -localX2;
+	float localY = -localY2;
+	localX *= this->scaleX;
+	localY *= this->scaleY;
+	localX2 *= this->scaleX;
+	localY2 *= this->scaleY;
+	float radians = (float)(this->rotation * 3.1415926535897932385 / 180);
+	float cos = cosf(radians);
+	float sin = sinf(radians);
+	float localXCos = localX * cos + this->x;
+	float localXSin = localX * sin;
+	float localYCos = localY * cos + this->y;
+	float localYSin = localY * sin;
+	float localX2Cos = localX2 * cos + this->x;
+	float localX2Sin = localX2 * sin;
+	float localY2Cos = localY2 * cos + this->y;
+	float localY2Sin = localY2 * sin;
+	this->offset[0] = localXCos - localYSin;
+	this->offset[1] = localYCos + localXSin;
+	this->offset[2] = localXCos - localY2Sin;
+	this->offset[3] = localY2Cos + localXSin;
+	this->offset[4] = localX2Cos - localY2Sin;
+	this->offset[5] = localY2Cos + localX2Sin;
+	this->offset[6] = localX2Cos - localYSin;
+	this->offset[7] = localYCos + localX2Sin;
+}

+ 28 - 0
spine-c/src/spine/RegionAttachment.h

@@ -0,0 +1,28 @@
+#ifndef SPINE_REGIONATTACHMENT_H_
+#define SPINE_REGIONATTACHMENT_H_
+
+#include <spine/Attachment.h>
+
+#ifdef __cplusplus
+namespace spine {
+extern "C" {
+#endif
+
+typedef struct RegionAttachment RegionAttachment;
+struct RegionAttachment {
+	Attachment super;
+	float x, y, scaleX, scaleY, rotation, width, height;
+	float offset[8];
+};
+
+void RegionAttachment_init (RegionAttachment* this, const char* name);
+void RegionAttachment_dispose (RegionAttachment* attachment);
+
+void RegionAttachment_updateOffset (RegionAttachment* attachment);
+
+#ifdef __cplusplus
+}
+}
+#endif
+
+#endif /* SPINE_REGIONATTACHMENT_H_ */

+ 176 - 0
spine-c/src/spine/Skeleton.c

@@ -0,0 +1,176 @@
+#include <spine/Skeleton.h>
+#include <spine/util.h>
+
+void Skeleton_init (Skeleton* this, SkeletonData* data) {
+	CAST(SkeletonData*, this->data) = data;
+
+	this->boneCount = this->data->boneCount;
+	this->bones = malloc(sizeof(Bone*) * this->boneCount);
+	int i, ii;
+	for (i = 0; i < this->boneCount; ++i) {
+		BoneData* boneData = this->data->bones[i];
+		Bone* parent = 0;
+		if (boneData->parent) {
+			// Find parent bone.
+			for (ii = 0; ii < this->boneCount; ++ii) {
+				if (data->bones[ii] == boneData->parent) {
+					parent = this->bones[ii];
+					break;
+				}
+			}
+		}
+		this->bones[i] = Bone_create(boneData, parent);
+	}
+
+	this->slotCount = data->slotCount;
+	this->slots = malloc(sizeof(Slot*) * this->slotCount);
+	for (i = 0; i < this->slotCount; ++i) {
+		SlotData *slotData = data->slots[i];
+
+		// Find bone for the slotData's boneData.
+		Bone *bone;
+		for (ii = 0; ii < this->boneCount; ++ii) {
+			if (data->bones[ii] == slotData->boneData) {
+				bone = this->bones[ii];
+				break;
+			}
+		}
+
+		this->slots[i] = Slot_create(slotData, this, bone);
+	}
+
+	this->drawOrder = malloc(sizeof(Slot*) * this->slotCount);
+	memcpy(this->drawOrder, this->slots, sizeof(Slot*) * this->slotCount);
+}
+
+void Skeleton_dispose (Skeleton* this) {
+	if (this->_dispose) this->_dispose(this);
+
+	int i;
+	for (i = 0; i < this->boneCount; ++i)
+		Bone_dispose(this->bones[i]);
+	FREE(this->bones)
+
+	FREE(this->slots)
+	for (i = 0; i < this->slotCount; ++i)
+		Slot_dispose(this->slots[i]);
+
+	FREE(this->drawOrder)
+
+	FREE(this)
+}
+
+void Skeleton_updateWorldTransform (const Skeleton* this) {
+	int i;
+	for (i = 0; i < this->boneCount; ++i)
+		Bone_updateWorldTransform(this->bones[i], this->flipX, this->flipY);
+}
+
+void Skeleton_setToBindPose (const Skeleton* this) {
+	Skeleton_setBonesToBindPose(this);
+	Skeleton_setSlotsToBindPose(this);
+}
+
+void Skeleton_setBonesToBindPose (const Skeleton* this) {
+	int i;
+	for (i = 0; i < this->boneCount; ++i)
+		Bone_setToBindPose(this->bones[i]);
+}
+
+void Skeleton_setSlotsToBindPose (const Skeleton* this) {
+	int i;
+	for (i = 0; i < this->slotCount; ++i)
+		Slot_setToBindPose(this->slots[i]);
+}
+
+Bone* Skeleton_getRootBone (const Skeleton* this) {
+	if (this->boneCount == 0) return 0;
+	return this->bones[0];
+}
+
+Bone* Skeleton_findBone (const Skeleton* this, const char* boneName) {
+	int i;
+	for (i = 0; i < this->boneCount; ++i)
+		if (this->data->bones[i]->name == boneName) return this->bones[i];
+	return 0;
+}
+
+int Skeleton_findBoneIndex (const Skeleton* this, const char* boneName) {
+	int i;
+	for (i = 0; i < this->boneCount; ++i)
+		if (this->data->bones[i]->name == boneName) return i;
+	return -1;
+}
+
+Slot* Skeleton_findSlot (const Skeleton* this, const char* slotName) {
+	int i;
+	for (i = 0; i < this->slotCount; ++i)
+		if (this->data->slots[i]->name == slotName) return this->slots[i];
+	return 0;
+}
+
+int Skeleton_findSlotIndex (const Skeleton* this, const char* slotName) {
+	int i;
+	for (i = 0; i < this->slotCount; ++i)
+		if (this->data->slots[i]->name == slotName) return i;
+	return -1;
+}
+
+int Skeleton_setSkinByName (Skeleton* this, const char* skinName) {
+	Skin *skin = SkeletonData_findSkin(this->data, skinName);
+	if (!skin) return 0;
+	Skeleton_setSkin(this, skin);
+	return 1;
+}
+
+void Skeleton_setSkin (Skeleton* this, Skin* newSkin) {
+	if (this->skin && newSkin) {
+		// Attach each attachment in the new skin if the corresponding attachment in the old skin is currently attached.
+		const SkinEntry *entry = this->skin->entryList;
+		while (entry) {
+			Slot *slot = this->slots[entry->slotIndex];
+			if (slot->attachment == entry->attachment) {
+				Attachment *attachment = Skin_getAttachment(newSkin, entry->slotIndex, entry->name);
+				if (attachment) Slot_setAttachment(slot, attachment);
+			}
+			entry = entry->next;
+		}
+	}
+	CAST(Skin*, this->skin) = newSkin;
+}
+
+Attachment* Skeleton_getAttachmentForSlotName (const Skeleton* this, const char* slotName, const char* attachmentName) {
+	int slotIndex = SkeletonData_findSlotIndex(this->data, slotName);
+	return Skeleton_getAttachmentForSlotIndex(this, slotIndex, attachmentName);
+}
+
+Attachment* Skeleton_getAttachmentForSlotIndex (const Skeleton* this, int slotIndex, const char* attachmentName) {
+	if (slotIndex == -1) return 0;
+	if (this->skin) {
+		Attachment *attachment = Skin_getAttachment(this->skin, slotIndex, attachmentName);
+		if (attachment) return attachment;
+	}
+	if (this->data->defaultSkin) {
+		Attachment *attachment = Skin_getAttachment(this->data->defaultSkin, slotIndex, attachmentName);
+		if (attachment) return attachment;
+	}
+	return 0;
+}
+
+int Skeleton_setAttachment (Skeleton* this, const char* slotName, const char* attachmentName) {
+	int i;
+	for (i = 0; i < this->slotCount; ++i) {
+		Slot *slot = this->slots[i];
+		if (slot->data->name == slotName) {
+			Attachment* attachment = Skeleton_getAttachmentForSlotIndex(this, i, attachmentName);
+			if (!attachment) return 0;
+			Slot_setAttachment(slot, attachment);
+			return 1;
+		}
+	}
+	return 0;
+}
+
+void Skeleton_update (Skeleton* this, float deltaTime) {
+	this->time += deltaTime;
+}

+ 71 - 0
spine-c/src/spine/Skeleton.h

@@ -0,0 +1,71 @@
+#ifndef SPINE_SKELETON_H_
+#define SPINE_SKELETON_H_
+
+#include <spine/SkeletonData.h>
+#include <spine/Slot.h>
+#include <spine/Skin.h>
+
+#ifdef __cplusplus
+namespace spine {
+extern "C" {
+#endif
+
+typedef struct Skeleton Skeleton;
+struct Skeleton {
+	SkeletonData* const data;
+
+	int boneCount;
+	Bone** bones;
+
+	int slotCount;
+	Slot** slots;
+	Slot** drawOrder;
+
+	Skin* const skin;
+	float r, g, b, a;
+	float time;
+	int flipX, flipY;
+
+	void (*_dispose) (Skeleton* skeleton);
+};
+
+void Skeleton_init (Skeleton* skeleton, SkeletonData* data);
+void Skeleton_dispose (Skeleton* skeleton);
+
+void Skeleton_updateWorldTransform (const Skeleton* skeleton);
+
+void Skeleton_setToBindPose (const Skeleton* skeleton);
+void Skeleton_setBonesToBindPose (const Skeleton* skeleton);
+void Skeleton_setSlotsToBindPose (const Skeleton* skeleton);
+
+Bone* Skeleton_getRootBone (const Skeleton* skeleton);
+/** Returns 0 if the bone could not be found. */
+Bone* Skeleton_findBone (const Skeleton* skeleton, const char* boneName);
+/** Returns -1 if the bone could not be found. */
+int Skeleton_findBoneIndex (const Skeleton* skeleton, const char* boneName);
+
+/** Returns 0 if the slot could not be found. */
+Slot* Skeleton_findSlot (const Skeleton* skeleton, const char* slotName);
+/** Returns -1 if the slot could not be found. */
+int Skeleton_findSlotIndex (const Skeleton* skeleton, const char* slotName);
+
+/** Returns 0 if the skin could not be found. */
+int Skeleton_setSkinByName (Skeleton* skeleton, const char* skinName);
+/** @param skin May be 0.*/
+void Skeleton_setSkin (Skeleton* skeleton, Skin* skin);
+
+/** Returns 0 if the slot or attachment could not be found. */
+Attachment* Skeleton_getAttachmentForSlotName (const Skeleton* skeleton, const char* slotName, const char* attachmentName);
+/** Returns 0 if the slot or attachment could not be found. */
+Attachment* Skeleton_getAttachmentForSlotIndex (const Skeleton* this, int slotIndex, const char* attachmentName);
+/** Returns 0 if the slot or attachment could not be found. */
+int Skeleton_setAttachment (Skeleton* skeleton, const char* slotName, const char* attachmentName);
+
+void Skeleton_update (Skeleton* this, float deltaTime);
+
+#ifdef __cplusplus
+}
+}
+#endif
+
+#endif /* SPINE_SKELETON_H_*/

+ 46 - 0
spine-c/src/spine/SkeletonData.c

@@ -0,0 +1,46 @@
+#include <spine/SkeletonData.h>
+#include <spine/util.h>
+
+SkeletonData* SkeletonData_create () {
+	SkeletonData* this = calloc(1, sizeof(SkeletonData));
+	return this;
+}
+
+void SkeletonData_dispose (SkeletonData* this) {
+	FREE(this)
+}
+
+BoneData* SkeletonData_findBone (const SkeletonData* this, const char* boneName) {
+	int i;
+	for (i = 0; i < this->boneCount; ++i)
+		if (strcmp(this->bones[i]->name, boneName) == 0) return this->bones[i];
+	return 0;
+}
+
+int SkeletonData_findBoneIndex (const SkeletonData* this, const char* boneName) {
+	int i;
+	for (i = 0; i < this->boneCount; ++i)
+		if (strcmp(this->bones[i]->name, boneName) == 0) return i;
+	return 0;
+}
+
+SlotData* SkeletonData_findSlot (const SkeletonData* this, const char* slotName) {
+	int i;
+	for (i = 0; i < this->slotCount; ++i)
+		if (strcmp(this->slots[i]->name, slotName) == 0) return this->slots[i];
+	return 0;
+}
+
+int SkeletonData_findSlotIndex (const SkeletonData* this, const char* slotName) {
+	int i;
+	for (i = 0; i < this->slotCount; ++i)
+		if (strcmp(this->slots[i]->name, slotName) == 0) return i;
+	return 0;
+}
+
+Skin* SkeletonData_findSkin (const SkeletonData* this, const char* skinName) {
+	int i;
+	for (i = 0; i < this->skinCount; ++i)
+		if (strcmp(this->skins[i]->name, skinName) == 0) return this->skins[i];
+	return 0;
+}

+ 40 - 0
spine-c/src/spine/SkeletonData.h

@@ -0,0 +1,40 @@
+#ifndef SPINE_SKELETONDATA_H_
+#define SPINE_SKELETONDATA_H_
+
+#include <spine/BoneData.h>
+#include <spine/SlotData.h>
+#include <spine/Skin.h>
+
+#ifdef __cplusplus
+namespace spine {extern "C" {
+#endif
+
+typedef struct {
+	int boneCount;
+	BoneData** bones;
+
+	int slotCount;
+	SlotData** slots;
+
+	int skinCount;
+	Skin** skins;
+
+	Skin* defaultSkin;
+} SkeletonData;
+
+SkeletonData* SkeletonData_create ();
+void SkeletonData_dispose (SkeletonData* skeletonData);
+
+BoneData* SkeletonData_findBone (const SkeletonData* skeletonData, const char* boneName);
+int SkeletonData_findBoneIndex (const SkeletonData* skeletonData, const char* boneName);
+
+SlotData* SkeletonData_findSlot (const SkeletonData* skeletonData, const char* slotName);
+int SkeletonData_findSlotIndex (const SkeletonData* skeletonData, const char* slotName);
+
+Skin* SkeletonData_findSkin (const SkeletonData* skeletonData, const char* skinName);
+
+#ifdef __cplusplus
+}}
+#endif
+
+#endif /* SPINE_SKELETONDATA_H_ */

+ 175 - 0
spine-c/src/spine/SkeletonJson.c

@@ -0,0 +1,175 @@
+#include <spine/SkeletonJson.h>
+#include <math.h>
+#include <spine/util.h>
+#include <spine/cJSON.h>
+#include <spine/RegionAttachment.h>
+
+#include <stdio.h>
+
+static float scale;
+static const char* error;
+
+void SkeletonJson_setScale (float value) {
+	scale = value;
+}
+
+void* SkeletonJson_setError (cJSON* root, const char* value1, const char* value2) {
+	FREE(error)
+	char message[256];
+	strcpy(message, value1);
+	int length = strlen(value1);
+	if (value2) strncat(message + length, value2, 256 - length);
+	MALLOC_STR(error, message)
+	if (root) cJSON_dispose(root);
+	return 0;
+}
+
+const char* SkeletonJson_getError () {
+	return error;
+}
+
+static float toColor (const char* value, int index) {
+	if (strlen(value) != 8) return -1;
+	value += index * 2;
+	char digits[3];
+	digits[0] = *value;
+	digits[1] = *(value + 1);
+	digits[2] = '\0';
+	char* error;
+	int color = strtoul(digits, &error, 16);
+	if (*error != 0) return -1;
+	return color / (float)255;
+}
+
+SkeletonData* SkeletonJson_readSkeletonDataFile (const char* path) {
+	char* data = readFile(path);
+	if (!data) return SkeletonJson_setError(0, "Unable to read file: ", path);
+	SkeletonData* skeletonData = SkeletonJson_readSkeletonData(data);
+	free(data);
+	return skeletonData;
+}
+
+SkeletonData* SkeletonJson_readSkeletonData (const char* json) {
+	FREE(error)
+	error = 0;
+
+	cJSON* root = cJSON_Parse(json);
+	if (!root) return SkeletonJson_setError(0, "Invalid JSON: ", cJSON_GetErrorPtr());
+
+	SkeletonData* skeletonData = SkeletonData_create();
+	int i, ii, iii;
+
+	cJSON* bones = cJSON_GetObjectItem(root, "bones");
+	int boneCount = cJSON_GetArraySize(bones);
+	skeletonData->bones = malloc(sizeof(BoneData*) * boneCount);
+	for (i = 0; i < boneCount; ++i) {
+		cJSON* boneMap = cJSON_GetArrayItem(bones, i);
+
+		const char* boneName = cJSON_GetObjectString(boneMap, "name", 0);
+
+		BoneData* parent = 0;
+		const char* parentName = cJSON_GetObjectString(boneMap, "parent", 0);
+		if (parentName) {
+			parent = SkeletonData_findBone(skeletonData, parentName);
+			if (!parent) return SkeletonJson_setError(root, "Parent bone not found: ", parentName);
+		}
+
+		BoneData* boneData = BoneData_create(boneName, parent);
+		boneData->length = cJSON_GetObjectFloat(boneMap, "parent", 0) * scale;
+		boneData->x = cJSON_GetObjectFloat(boneMap, "x", 0) * scale;
+		boneData->y = cJSON_GetObjectFloat(boneMap, "y", 0) * scale;
+		boneData->rotation = cJSON_GetObjectFloat(boneMap, "rotation", 0);
+		boneData->scaleX = cJSON_GetObjectFloat(boneMap, "scaleX", 1);
+		boneData->scaleY = cJSON_GetObjectFloat(boneMap, "scaleY", 1);
+
+		skeletonData->bones[i] = boneData;
+		skeletonData->boneCount++;
+	}
+
+	cJSON* slots = cJSON_GetObjectItem(root, "slots");
+	if (slots) {
+		int slotCount = cJSON_GetArraySize(slots);
+		skeletonData->slots = malloc(sizeof(SlotData*) * slotCount);
+		for (i = 0; i < slotCount; ++i) {
+			cJSON* slotMap = cJSON_GetArrayItem(slots, i);
+
+			const char* slotName = cJSON_GetObjectString(slotMap, "name", 0);
+
+			const char* boneName = cJSON_GetObjectString(slotMap, "bone", 0);
+			BoneData* boneData = SkeletonData_findBone(skeletonData, boneName);
+			if (!boneData) return SkeletonJson_setError(root, "Slot bone not found: ", boneName);
+
+			SlotData* slotData = SlotData_create(slotName, boneData);
+
+			const char* color = cJSON_GetObjectString(slotMap, "color", 0);
+			if (color) {
+				slotData->r = toColor(color, 0);
+				slotData->g = toColor(color, 1);
+				slotData->b = toColor(color, 2);
+				slotData->a = toColor(color, 3);
+			}
+
+			cJSON *attachmentItem = cJSON_GetObjectItem(slotMap, "attachment");
+			if (attachmentItem) SlotData_setAttachmentName(slotData, attachmentItem->valuestring);
+
+			skeletonData->slots[i] = slotData;
+			skeletonData->slotCount++;
+		}
+	}
+
+	cJSON* skinsMap = cJSON_GetObjectItem(root, "skins");
+	if (skinsMap) {
+		int skinCount = cJSON_GetArraySize(skinsMap);
+		skeletonData->skins = malloc(sizeof(Skin*) * skinCount);
+		for (i = 0; i < skinCount; ++i) {
+			cJSON* slotMap = cJSON_GetArrayItem(skinsMap, i);
+			const char* skinName = slotMap->name;
+			Skin *skin = Skin_create(skinName);
+			skeletonData->skins[i] = skin;
+			skeletonData->skinCount++;
+			if (strcmp(skinName, "default") == 0) skeletonData->defaultSkin = skin;
+
+			int slotNameCount = cJSON_GetArraySize(slotMap);
+			for (ii = 0; ii < slotNameCount; ++ii) {
+				cJSON* attachmentsMap = cJSON_GetArrayItem(slotMap, ii);
+				const char* slotName = attachmentsMap->name;
+				int slotIndex = SkeletonData_findSlotIndex(skeletonData, slotName);
+
+				int attachmentCount = cJSON_GetArraySize(attachmentsMap);
+				for (iii = 0; iii < attachmentCount; ++iii) {
+					cJSON* attachmentMap = cJSON_GetArrayItem(attachmentsMap, iii);
+					const char* attachmentName = attachmentMap->name;
+
+					const char* typeString = cJSON_GetObjectString(attachmentMap, "type", "region");
+					AttachmentType type;
+					if (strcmp(typeString, "region") == 0)
+						type = ATTACHMENT_REGION;
+					else if (strcmp(typeString, "regionSequence") == 0)
+						type = ATTACHMENT_REGION_SEQUENCE;
+					else
+						return SkeletonJson_setError(root, "Unknown attachment type: ", typeString);
+
+					Attachment* attachment = Attachment_getAttachmentLoader()(type,
+							cJSON_GetObjectString(attachmentMap, "name", attachmentName));
+
+					if (type == ATTACHMENT_REGION || type == ATTACHMENT_REGION_SEQUENCE) {
+						RegionAttachment* regionAttachment = (RegionAttachment*)attachment;
+						regionAttachment->x = cJSON_GetObjectFloat(attachmentMap, "x", 0) * scale;
+						regionAttachment->y = cJSON_GetObjectFloat(attachmentMap, "y", 0) * scale;
+						regionAttachment->scaleX = cJSON_GetObjectFloat(attachmentMap, "scaleX", 1);
+						regionAttachment->scaleY = cJSON_GetObjectFloat(attachmentMap, "scaleY", 1);
+						regionAttachment->rotation = cJSON_GetObjectFloat(attachmentMap, "rotation", 0);
+						regionAttachment->width = cJSON_GetObjectFloat(attachmentMap, "width", 32) * scale;
+						regionAttachment->height = cJSON_GetObjectFloat(attachmentMap, "height", 32) * scale;
+						RegionAttachment_updateOffset(regionAttachment);
+					}
+
+					Skin_addAttachment(skin, slotIndex, attachmentName, attachment);
+				}
+			}
+		}
+	}
+
+	cJSON_dispose(root);
+	return skeletonData;
+}

+ 26 - 0
spine-c/src/spine/SkeletonJson.h

@@ -0,0 +1,26 @@
+#ifndef SPINE_SKELETONJSON_H_
+#define SPINE_SKELETONJSON_H_
+
+#include <spine/Attachment.h>
+#include <spine/SkeletonData.h>
+
+#ifdef __cplusplus
+namespace spine {
+extern "C" {
+#endif
+
+void SkeletonJson_setScale (float scale);
+
+SkeletonData* SkeletonJson_readSkeletonData (const char* json);
+SkeletonData* SkeletonJson_readSkeletonDataFile (const char* path);
+
+// Animation* readAnimation (char* json, const SkeletonData *skeletonData) const;
+
+const char* SkeletonJson_getError ();
+
+#ifdef __cplusplus
+}
+}
+#endif
+
+#endif /* SPINE_SKELETONJSON_H_ */

+ 52 - 0
spine-c/src/spine/Skin.c

@@ -0,0 +1,52 @@
+#include <spine/Skin.h>
+#include <spine/util.h>
+
+SkinEntry* SkinEntry_create (int slotIndex, const char* name, Attachment* attachment) {
+	SkinEntry* entry = calloc(1, sizeof(SkinEntry));
+	entry->slotIndex = slotIndex;
+	MALLOC_STR(entry->name, name)
+	entry->attachment = attachment;
+	return entry;
+}
+
+void SkinEntry_dispose (SkinEntry* entry) {
+	if (entry->next) SkinEntry_dispose((SkinEntry*)entry->next);
+	Attachment_dispose(entry->attachment);
+	FREE(entry->name)
+	FREE(entry)
+}
+
+//
+
+Skin* Skin_create (const char* name) {
+	Skin* this = calloc(1, sizeof(Skin));
+	MALLOC_STR(this->name, name)
+	return this;
+}
+
+void Skin_dispose (Skin* this) {
+	SkinEntry_dispose((SkinEntry*)this->entryList);
+	FREE(this->name)
+	FREE(this)
+}
+
+void Skin_addAttachment (Skin* this, int slotIndex, const char* name, Attachment* attachment) {
+	SkinEntry* newEntry = SkinEntry_create(slotIndex, name, attachment);
+	SkinEntry* entry = (SkinEntry*)this->entryList;
+	if (!entry)
+		entry = newEntry;
+	else {
+		while (entry->next)
+			entry = (SkinEntry*)entry->next;
+		entry->next = newEntry;
+	}
+}
+
+Attachment* Skin_getAttachment (const Skin* this, int slotIndex, const char* name) {
+	const SkinEntry* entry = this->entryList;
+	while (entry) {
+		if (entry->slotIndex == slotIndex && strcmp(entry->name, name) == 0) return entry->attachment;
+		entry = entry->next;
+	}
+	return 0;
+}

+ 37 - 0
spine-c/src/spine/Skin.h

@@ -0,0 +1,37 @@
+#ifndef SPINE_SKIN_H_
+#define SPINE_SKIN_H_
+
+#include <spine/Attachment.h>
+
+#ifdef __cplusplus
+namespace spine {
+extern "C" {
+#endif
+
+typedef struct SkinEntry SkinEntry;
+struct SkinEntry {
+	int slotIndex;
+	const char* name;
+	Attachment* attachment;
+	const SkinEntry* next;
+};
+
+typedef struct {
+	const char* const name;
+	const SkinEntry* const entryList;
+} Skin;
+
+Skin* Skin_create (const char* name);
+void Skin_dispose (Skin* skin);
+
+/** The Skin owns the attachment. */
+void Skin_addAttachment (Skin* skin, int slotIndex, const char* name, Attachment* attachment);
+/** May return null. */
+Attachment* Skin_getAttachment (const Skin* skin, int slotIndex, const char* name);
+
+#ifdef __cplusplus
+}
+}
+#endif
+
+#endif /* SPINE_SKIN_H_ */

+ 58 - 0
spine-c/src/spine/Slot.c

@@ -0,0 +1,58 @@
+#include <spine/Slot.h>
+#include <spine/util.h>
+#include <spine/Skeleton.h>
+
+typedef struct {
+	Slot slot;
+	float attachmentTime;
+} Private;
+
+Slot* Slot_create (SlotData* data, Skeleton* skeleton, Bone* bone) {
+	Private* private = calloc(1, sizeof(Private));
+	Slot* this = &private->slot;
+	CAST(SlotData*, this->data) = data;
+	CAST(Skeleton*, this->skeleton) = skeleton;
+	CAST(Bone*, this->bone) = bone;
+	this->r = 1;
+	this->g = 1;
+	this->b = 1;
+	this->a = 1;
+	return this;
+}
+
+void Slot_dispose (Slot* this) {
+	FREE(this);
+}
+
+/** @param attachment May be null. */
+void Slot_setAttachment (Slot* this, Attachment* attachment) {
+	CAST(Attachment*, this->attachment) = attachment;
+	((Private*)this)->attachmentTime = this->skeleton->time;
+}
+
+void Slot_setAttachmentTime (Slot* this, float time) {
+	((Private*)this)->attachmentTime = this->skeleton->time - time;
+}
+
+float Slot_getAttachmentTime (const Slot* this) {
+	return this->skeleton->time - ((Private*)this)->attachmentTime;
+}
+
+void Slot_setToBindPose (Slot* this) {
+	this->r = this->data->r;
+	this->g = this->data->g;
+	this->b = this->data->b;
+	this->a = this->data->a;
+
+	Attachment* attachment = 0;
+	if (this->data->attachmentName) {
+		int i;
+		for (i = 0; i < this->skeleton->data->slotCount; ++i) {
+			if (this->data == this->skeleton->data->slots[i]) {
+				attachment = Skeleton_getAttachmentForSlotIndex(this->skeleton, i, this->data->attachmentName);
+				break;
+			}
+		}
+	}
+	Slot_setAttachment(this, attachment);
+}

+ 39 - 0
spine-c/src/spine/Slot.h

@@ -0,0 +1,39 @@
+#ifndef SPINE_SLOT_H_
+#define SPINE_SLOT_H_
+
+#include <spine/Bone.h>
+#include <spine/Attachment.h>
+#include <spine/SlotData.h>
+
+#ifdef __cplusplus
+namespace spine {
+extern "C" {
+#endif
+
+struct Skeleton;
+
+typedef struct {
+	SlotData* const data;
+	struct Skeleton* const skeleton;
+	Bone* const bone;
+	float r, g, b, a;
+	Attachment* const attachment;
+} Slot;
+
+Slot* Slot_create (SlotData* data, struct Skeleton* skeleton, Bone* bone);
+void Slot_dispose (Slot* slot);
+
+/** @param attachment May be null. */
+void Slot_setAttachment (Slot* slot, Attachment* attachment);
+
+void Slot_setAttachmentTime (Slot* slot, float time);
+float Slot_getAttachmentTime (const Slot* slot);
+
+void Slot_setToBindPose (Slot* slot);
+
+#ifdef __cplusplus
+}
+}
+#endif
+
+#endif /* SPINE_SLOT_H_ */

+ 27 - 0
spine-c/src/spine/SlotData.c

@@ -0,0 +1,27 @@
+#include <spine/SlotData.h>
+#include <spine/util.h>
+
+SlotData* SlotData_create (const char* name, BoneData* boneData) {
+	SlotData* this = calloc(1, sizeof(SlotData));
+	MALLOC_STR(this->name, name)
+	CAST(BoneData*, this->boneData) = boneData;
+	this->r = 1;
+	this->g = 1;
+	this->b = 1;
+	this->a = 1;
+	return this;
+}
+
+void SlotData_dispose (SlotData* this) {
+	FREE(this->name);
+	FREE(this->attachmentName);
+	FREE(this);
+}
+
+void SlotData_setAttachmentName (SlotData* this, const char* attachmentName) {
+	FREE(this->attachmentName);
+	if (attachmentName)
+		MALLOC_STR(this->attachmentName, attachmentName)
+	else
+		CAST(char*, this->attachmentName) = 0;
+}

+ 29 - 0
spine-c/src/spine/SlotData.h

@@ -0,0 +1,29 @@
+#ifndef SPINE_SLOTDATA_H_
+#define SPINE_SLOTDATA_H_
+
+#include <spine/BoneData.h>
+
+#ifdef __cplusplus
+namespace spine {
+extern "C" {
+#endif
+
+typedef struct {
+	const char* const name;
+	const BoneData* const boneData;
+	const char* const attachmentName;
+	float r, g, b, a;
+} SlotData;
+
+SlotData* SlotData_create (const char* name, BoneData* boneData);
+void SlotData_dispose (SlotData* slotData);
+
+/** @param attachmentName May be zero. */
+void SlotData_setAttachmentName (SlotData* this, const char* attachmentName);
+
+#ifdef __cplusplus
+}
+}
+#endif
+
+#endif /* SPINE_SLOTDATA_H_ */

+ 391 - 0
spine-c/src/spine/cJSON.c

@@ -0,0 +1,391 @@
+/*
+ Copyright (c) 2009 Dave Gamble
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ */
+
+/* cJSON */
+/* JSON parser in C. */
+
+#include <spine/cJSON.h>
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+#include <stdlib.h>
+#include <float.h>
+#include <limits.h>
+#include <ctype.h>
+
+static const char* ep;
+
+const char* cJSON_GetErrorPtr (void) {
+	return ep;
+}
+
+static int cJSON_strcasecmp (const char* s1, const char* s2) {
+	if (!s1) return (s1 == s2) ? 0 : 1;
+	if (!s2) return 1;
+	for (; tolower(*s1) == tolower(*s2); ++s1, ++s2)
+		if (*s1 == 0) return 0;
+	return tolower(*(const unsigned char*)s1) - tolower(*(const unsigned char*)s2);
+}
+
+/* Internal constructor. */
+static cJSON *cJSON_create_Item (void) {
+	cJSON* node = (cJSON*)malloc(sizeof(cJSON));
+	if (node) memset(node, 0, sizeof(cJSON));
+	return node;
+}
+
+/* Delete a cJSON structure. */
+void cJSON_dispose (cJSON *c) {
+	cJSON *next;
+	while (c) {
+		next = c->next;
+		if (!(c->type & cJSON_IsReference) && c->child) cJSON_dispose(c->child);
+		if (!(c->type & cJSON_IsReference) && c->valuestring) free((char*)c->valuestring);
+		if (c->name) free((char*)c->name);
+		free(c);
+		c = next;
+	}
+}
+
+/* Parse the input text to generate a number, and populate the result into item. */
+static const char* parse_number (cJSON *item, const char* num) {
+	float n = 0, sign = 1, scale = 0;
+	int subscale = 0, signsubscale = 1;
+
+	/* Could use sscanf for this? */
+	if (*num == '-') sign = -1, num++; /* Has sign? */
+	if (*num == '0') num++; /* is zero */
+	if (*num >= '1' && *num <= '9') do
+		n = (n * 10.0) + (*num++ - '0');
+	while (*num >= '0' && *num <= '9'); /* Number? */
+	if (*num == '.' && num[1] >= '0' && num[1] <= '9') {
+		num++;
+		do
+			n = (n * 10.0) + (*num++ - '0'), scale--;
+		while (*num >= '0' && *num <= '9');
+	} /* Fractional part? */
+	if (*num == 'e' || *num == 'E') /* Exponent? */
+	{
+		num++;
+		if (*num == '+')
+			num++;
+		else if (*num == '-') signsubscale = -1, num++; /* With sign? */
+		while (*num >= '0' && *num <= '9')
+			subscale = (subscale * 10) + (*num++ - '0'); /* Number? */
+	}
+
+	n = sign * n * pow(10.0, (scale + subscale * signsubscale)); /* number = +/- number.fraction * 10^+/- exponent */
+
+	item->valuefloat = n;
+	item->valueint = (int)n;
+	item->type = cJSON_Number;
+	return num;
+}
+
+/* Parse the input text into an unescaped cstring, and populate item. */
+static const unsigned char firstByteMark[7] = {0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC};
+static const char* parse_string (cJSON *item, const char* str) {
+	const char* ptr = str + 1;
+	char* ptr2;
+	char* out;
+	int len = 0;
+	unsigned uc, uc2;
+	if (*str != '\"') {
+		ep = str;
+		return 0;
+	} /* not a string! */
+
+	while (*ptr != '\"' && *ptr && ++len)
+		if (*ptr++ == '\\') ptr++; /* Skip escaped quotes. */
+
+	out = (char*)malloc(len + 1); /* This is how long we need for the string, roughly. */
+	if (!out) return 0;
+
+	ptr = str + 1;
+	ptr2 = out;
+	while (*ptr != '\"' && *ptr) {
+		if (*ptr != '\\')
+			*ptr2++ = *ptr++;
+		else {
+			ptr++;
+			switch (*ptr) {
+			case 'b':
+				*ptr2++ = '\b';
+				break;
+			case 'f':
+				*ptr2++ = '\f';
+				break;
+			case 'n':
+				*ptr2++ = '\n';
+				break;
+			case 'r':
+				*ptr2++ = '\r';
+				break;
+			case 't':
+				*ptr2++ = '\t';
+				break;
+			case 'u': /* transcode utf16 to utf8. */
+				sscanf(ptr + 1, "%4x", &uc);
+				ptr += 4; /* get the unicode char. */
+
+				if ((uc >= 0xDC00 && uc <= 0xDFFF) || uc == 0) break; /* check for invalid.	*/
+
+				if (uc >= 0xD800 && uc <= 0xDBFF) /* UTF16 surrogate pairs.	*/
+				{
+					if (ptr[1] != '\\' || ptr[2] != 'u') break; /* missing second-half of surrogate.	*/
+					sscanf(ptr + 3, "%4x", &uc2);
+					ptr += 6;
+					if (uc2 < 0xDC00 || uc2 > 0xDFFF) break; /* invalid second-half of surrogate.	*/
+					uc = 0x10000 + (((uc & 0x3FF) << 10) | (uc2 & 0x3FF));
+				}
+
+				len = 4;
+				if (uc < 0x80)
+					len = 1;
+				else if (uc < 0x800)
+					len = 2;
+				else if (uc < 0x10000) len = 3;
+				ptr2 += len;
+
+				switch (len) {
+				case 4:
+					*--ptr2 = ((uc | 0x80) & 0xBF);
+					uc >>= 6;
+				case 3:
+					*--ptr2 = ((uc | 0x80) & 0xBF);
+					uc >>= 6;
+				case 2:
+					*--ptr2 = ((uc | 0x80) & 0xBF);
+					uc >>= 6;
+				case 1:
+					*--ptr2 = (uc | firstByteMark[len]);
+				}
+				ptr2 += len;
+				break;
+			default:
+				*ptr2++ = *ptr;
+				break;
+			}
+			ptr++;
+		}
+	}
+	*ptr2 = 0;
+	if (*ptr == '\"') ptr++;
+	item->valuestring = out;
+	item->type = cJSON_String;
+	return ptr;
+}
+
+/* Predeclare these prototypes. */
+static const char* parse_value (cJSON *item, const char* value);
+static const char* parse_array (cJSON *item, const char* value);
+static const char* parse_object (cJSON *item, const char* value);
+
+/* Utility to jump whitespace and cr/lf */
+static const char* skip (const char* in) {
+	while (in && *in && (unsigned char)*in <= 32)
+		in++;
+	return in;
+}
+
+/* Parse an object - create a new root, and populate. */
+cJSON *cJSON_ParseWithOpts (const char* value, const char* *return_parse_end, int require_null_terminated) {
+	const char* end = 0;
+	cJSON *c = cJSON_create_Item();
+	ep = 0;
+	if (!c) return 0; /* memory fail */
+
+	end = parse_value(c, skip(value));
+	if (!end) {
+		cJSON_dispose(c);
+		return 0;
+	} /* parse failure. ep is set. */
+
+	/* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
+	if (require_null_terminated) {
+		end = skip(end);
+		if (*end) {
+			cJSON_dispose(c);
+			ep = end;
+			return 0;
+		}
+	}
+	if (return_parse_end) *return_parse_end = end;
+	return c;
+}
+
+/* Default options for cJSON_Parse */
+cJSON *cJSON_Parse (const char* value) {
+	return cJSON_ParseWithOpts(value, 0, 0);
+}
+
+/* Parser core - when encountering text, process appropriately. */
+static const char* parse_value (cJSON *item, const char* value) {
+	if (!value) return 0; /* Fail on null. */
+	if (!strncmp(value, "null", 4)) {
+		item->type = cJSON_NULL;
+		return value + 4;
+	}
+	if (!strncmp(value, "false", 5)) {
+		item->type = cJSON_False;
+		return value + 5;
+	}
+	if (!strncmp(value, "true", 4)) {
+		item->type = cJSON_True;
+		item->valueint = 1;
+		return value + 4;
+	}
+	if (*value == '\"') {
+		return parse_string(item, value);
+	}
+	if (*value == '-' || (*value >= '0' && *value <= '9')) {
+		return parse_number(item, value);
+	}
+	if (*value == '[') {
+		return parse_array(item, value);
+	}
+	if (*value == '{') {
+		return parse_object(item, value);
+	}
+
+	ep = value;
+	return 0; /* failure. */
+}
+
+/* Build an array from input text. */
+static const char* parse_array (cJSON *item, const char* value) {
+	cJSON *child;
+	if (*value != '[') {
+		ep = value;
+		return 0;
+	} /* not an array! */
+
+	item->type = cJSON_Array;
+	value = skip(value + 1);
+	if (*value == ']') return value + 1; /* empty array. */
+
+	item->child = child = cJSON_create_Item();
+	if (!item->child) return 0; /* memory fail */
+	value = skip(parse_value(child, skip(value))); /* skip any spacing, get the value. */
+	if (!value) return 0;
+
+	while (*value == ',') {
+		cJSON *new_item;
+		if (!(new_item = cJSON_create_Item())) return 0; /* memory fail */
+		child->next = new_item;
+		new_item->prev = child;
+		child = new_item;
+		value = skip(parse_value(child, skip(value + 1)));
+		if (!value) return 0; /* memory fail */
+	}
+
+	if (*value == ']') return value + 1; /* end of array */
+	ep = value;
+	return 0; /* malformed. */
+}
+
+/* Build an object from the text. */
+static const char* parse_object (cJSON *item, const char* value) {
+	cJSON *child;
+	if (*value != '{') {
+		ep = value;
+		return 0;
+	} /* not an object! */
+
+	item->type = cJSON_Object;
+	value = skip(value + 1);
+	if (*value == '}') return value + 1; /* empty array. */
+
+	item->child = child = cJSON_create_Item();
+	if (!item->child) return 0;
+	value = skip(parse_string(child, skip(value)));
+	if (!value) return 0;
+	child->name = child->valuestring;
+	child->valuestring = 0;
+	if (*value != ':') {
+		ep = value;
+		return 0;
+	} /* fail! */
+	value = skip(parse_value(child, skip(value + 1))); /* skip any spacing, get the value. */
+	if (!value) return 0;
+
+	while (*value == ',') {
+		cJSON *new_item;
+		if (!(new_item = cJSON_create_Item())) return 0; /* memory fail */
+		child->next = new_item;
+		new_item->prev = child;
+		child = new_item;
+		value = skip(parse_string(child, skip(value + 1)));
+		if (!value) return 0;
+		child->name = child->valuestring;
+		child->valuestring = 0;
+		if (*value != ':') {
+			ep = value;
+			return 0;
+		} /* fail! */
+		value = skip(parse_value(child, skip(value + 1))); /* skip any spacing, get the value. */
+		if (!value) return 0;
+	}
+
+	if (*value == '}') return value + 1; /* end of array */
+	ep = value;
+	return 0; /* malformed. */
+}
+
+/* Get Array size/item / object item. */
+int cJSON_GetArraySize (cJSON *array) {
+	cJSON *c = array->child;
+	int i = 0;
+	while (c)
+		i++, c = c->next;
+	return i;
+}
+
+cJSON *cJSON_GetArrayItem (cJSON *array, int item) {
+	cJSON *c = array->child;
+	while (c && item > 0)
+		item--, c = c->next;
+	return c;
+}
+
+cJSON *cJSON_GetObjectItem (cJSON *object, const char* string) {
+	cJSON *c = object->child;
+	while (c && cJSON_strcasecmp(c->name, string))
+		c = c->next;
+	return c;
+}
+
+const char* cJSON_GetObjectString (cJSON* object, const char* name, const char* defaultValue) {
+	object = cJSON_GetObjectItem(object, name);
+	if (object) return object->valuestring;
+	return defaultValue;
+}
+
+float cJSON_GetObjectFloat (cJSON* value, const char* name, float defaultValue) {
+	value = cJSON_GetObjectItem(value, name);
+	return value ? value->valuefloat : defaultValue;
+}
+
+int cJSON_GetObjectInt (cJSON* value, const char* name, int defaultValue) {
+	value = cJSON_GetObjectItem(value, name);
+	return value ? value->valuefloat : defaultValue;
+}

+ 84 - 0
spine-c/src/spine/cJSON.h

@@ -0,0 +1,84 @@
+/*
+ Copyright (c) 2009 Dave Gamble
+ 
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ */
+
+/* Esoteric Software: Removed everything except parsing, added cJSON_GetObject*, formatted, double to float. */
+
+#ifndef cJSON__h
+#define cJSON__h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdlib.h>
+
+/* cJSON Types: */
+#define cJSON_False 0
+#define cJSON_True 1
+#define cJSON_NULL 2
+#define cJSON_Number 3
+#define cJSON_String 4
+#define cJSON_Array 5
+#define cJSON_Object 6
+
+#define cJSON_IsReference 256
+
+/* The cJSON structure: */
+typedef struct cJSON {
+	struct cJSON *next, *prev; /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
+	struct cJSON *child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
+
+	int type; /* The type of the item, as above. */
+
+	const char* valuestring; /* The item's string, if type==cJSON_String */
+	int valueint; /* The item's number, if type==cJSON_Number */
+	float valuefloat; /* The item's number, if type==cJSON_Number */
+
+	const char* name; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
+} cJSON;
+
+/* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_dispose when finished. */
+extern cJSON *cJSON_Parse (const char* value);
+
+/* Delete a cJSON entity and all subentities. */
+extern void cJSON_dispose (cJSON *c);
+
+/* Returns the number of items in an array (or object). */
+extern int cJSON_GetArraySize (cJSON *array);
+
+/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */
+extern cJSON *cJSON_GetArrayItem (cJSON *array, int item);
+
+/* Get item "string" from object. Case insensitive. */
+extern cJSON *cJSON_GetObjectItem (cJSON *object, const char* string);
+extern const char* cJSON_GetObjectString (cJSON* object, const char* name, const char* defaultValue);
+extern float cJSON_GetObjectFloat (cJSON* value, const char* name, float defaultValue);
+extern int cJSON_GetObjectInt (cJSON* value, const char* name, int defaultValue);
+
+/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
+extern const char* cJSON_GetErrorPtr (void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 15 - 0
spine-c/src/spine/spine.h

@@ -0,0 +1,15 @@
+#ifndef SPINE_SPINE_H_
+#define SPINE_SPINE_H_
+
+#include <spine/Attachment.h>
+#include <spine/Bone.h>
+#include <spine/BoneData.h>
+#include <spine/RegionAttachment.h>
+#include <spine/Skeleton.h>
+#include <spine/SkeletonData.h>
+#include <spine/SkeletonJson.h>
+#include <spine/Skin.h>
+#include <spine/Slot.h>
+#include <spine/SlotData.h>
+
+#endif /* SPINE_SPINE_H_ */

+ 17 - 0
spine-c/src/spine/util.c

@@ -0,0 +1,17 @@
+#include <spine/util.h>
+
+char* readFile (const char* path) {
+	FILE *file = fopen(path, "rb");
+	if (!file) return 0;
+
+	fseek(file, 0, SEEK_END);
+	long length = ftell(file);
+	fseek(file, 0, SEEK_SET);
+
+	char* data = (char*)malloc(sizeof(char) * length + 1);
+	fread(data, sizeof(char), length, file);
+	fclose(file);
+	data[length] = '\0';
+
+	return data;
+}

+ 17 - 0
spine-c/src/spine/util.h

@@ -0,0 +1,17 @@
+#ifndef SPINE_UTIL_H_
+#define SPINE_UTIL_H_
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+/** Used to cast away const on an lvalue. */
+#define CAST(TYPE,VALUE) *(TYPE*)&VALUE
+
+#define MALLOC_STR(TO,FROM) strcpy(CAST(char*, TO) = malloc(strlen(FROM)), FROM);
+
+#define FREE(E) free((void*)E);
+
+char* readFile (const char* path);
+
+#endif /* SPINE_UTIL_H_ */