Browse Source

Merge branch '4.1' of https://github.com/esotericsoftware/spine-runtimes into 4.1

badlogic 2 years ago
parent
commit
27f758458b
100 changed files with 2544 additions and 371 deletions
  1. 2 2
      .github/actions/setup-godot-deps/action.yml
  2. 7 8
      .github/workflows/format-check.yml
  3. 368 0
      .github/workflows/spine-godot-v4.yml
  4. 25 25
      .github/workflows/spine-godot.yml
  5. 6 4
      .github/workflows/spine-libgdx.yml
  6. 4 3
      .github/workflows/spine-ts.yml
  7. 4 0
      .gitignore
  8. 4 2
      CHANGELOG.md
  9. 5 0
      spine-c/spine-c/src/spine/Atlas.c
  10. 194 193
      spine-c/spine-c/src/spine/SkeletonJson.c
  11. 15 15
      spine-cocos2dx/spine-cocos2dx/src/spine/SkeletonRenderer.cpp
  12. 1 1
      spine-cocos2dx/spine-cocos2dx/src/spine/spine-cocos2dx.cpp
  13. 3 3
      spine-cocos2dx/spine-cocos2dx/src/spine/v4/SkeletonBatch.cpp
  14. 3 3
      spine-cocos2dx/spine-cocos2dx/src/spine/v4/SkeletonTwoColorBatch.cpp
  15. 11 4
      spine-cpp/spine-cpp/include/spine/AnimationState.h
  16. 4 2
      spine-cpp/spine-cpp/include/spine/Atlas.h
  17. 6 6
      spine-cpp/spine-cpp/include/spine/Bone.h
  18. 3 1
      spine-cpp/spine-cpp/include/spine/ConstraintData.h
  19. 1 1
      spine-cpp/spine-cpp/include/spine/Debug.h
  20. 0 3
      spine-cpp/spine-cpp/include/spine/IkConstraint.h
  21. 2 0
      spine-cpp/spine-cpp/include/spine/IkConstraintData.h
  22. 3 0
      spine-cpp/spine-cpp/include/spine/MathUtil.h
  23. 1 1
      spine-cpp/spine-cpp/include/spine/MeshAttachment.h
  24. 8 11
      spine-cpp/spine-cpp/include/spine/PathConstraint.h
  25. 2 1
      spine-cpp/spine-cpp/include/spine/PathConstraintData.h
  26. 2 2
      spine-cpp/spine-cpp/include/spine/RegionAttachment.h
  27. 1 1
      spine-cpp/spine-cpp/include/spine/SkeletonBinary.h
  28. 11 0
      spine-cpp/spine-cpp/include/spine/SkeletonBounds.h
  29. 2 7
      spine-cpp/spine-cpp/include/spine/SpineString.h
  30. 32 0
      spine-cpp/spine-cpp/include/spine/TransformConstraintData.h
  31. 2 2
      spine-cpp/spine-cpp/include/spine/VertexAttachment.h
  32. 1 1
      spine-cpp/spine-cpp/include/spine/Vertices.h
  33. 21 9
      spine-cpp/spine-cpp/src/spine/AnimationState.cpp
  34. 8 6
      spine-cpp/spine-cpp/src/spine/Atlas.cpp
  35. 0 2
      spine-cpp/spine-cpp/src/spine/AtlasAttachmentLoader.cpp
  36. 67 26
      spine-cpp/spine-cpp/src/spine/Bone.cpp
  37. 2 0
      spine-cpp/spine-cpp/src/spine/ConstraintData.cpp
  38. 4 0
      spine-cpp/spine-cpp/src/spine/Extension.cpp
  39. 6 3
      spine-cpp/spine-cpp/src/spine/IkConstraint.cpp
  40. 2 0
      spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp
  41. 5 5
      spine-cpp/spine-cpp/src/spine/MeshAttachment.cpp
  42. 2 0
      spine-cpp/spine-cpp/src/spine/PathConstraintData.cpp
  43. 1 2
      spine-cpp/spine-cpp/src/spine/RegionAttachment.cpp
  44. 0 2
      spine-cpp/spine-cpp/src/spine/Sequence.cpp
  45. 3 3
      spine-cpp/spine-cpp/src/spine/Skeleton.cpp
  46. 7 8
      spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp
  47. 13 0
      spine-cpp/spine-cpp/src/spine/SkeletonBounds.cpp
  48. 1 1
      spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp
  49. 62 0
      spine-cpp/spine-cpp/src/spine/TransformConstraintData.cpp
  50. 2 2
      spine-cpp/spine-cpp/src/spine/VertexAttachment.cpp
  51. 30 0
      spine-flutter/.gitignore
  52. 42 0
      spine-flutter/.metadata
  53. 3 0
      spine-flutter/.pubignore
  54. 45 0
      spine-flutter/.vscode/launch.json
  55. 39 0
      spine-flutter/CHANGELOG.md
  56. 26 0
      spine-flutter/LICENSE
  57. 77 0
      spine-flutter/README.md
  58. 4 0
      spine-flutter/analysis_options.yaml
  59. 9 0
      spine-flutter/android/.gitignore
  60. 59 0
      spine-flutter/android/build.gradle
  61. 1 0
      spine-flutter/android/settings.gradle
  62. 3 0
      spine-flutter/android/src/main/AndroidManifest.xml
  63. 25 0
      spine-flutter/compile-wasm.sh
  64. 46 0
      spine-flutter/example/.gitignore
  65. 16 0
      spine-flutter/example/README.md
  66. 29 0
      spine-flutter/example/analysis_options.yaml
  67. 13 0
      spine-flutter/example/android/.gitignore
  68. 71 0
      spine-flutter/example/android/app/build.gradle
  69. 8 0
      spine-flutter/example/android/app/src/debug/AndroidManifest.xml
  70. 34 0
      spine-flutter/example/android/app/src/main/AndroidManifest.xml
  71. 6 0
      spine-flutter/example/android/app/src/main/kotlin/com/example/example/MainActivity.kt
  72. 6 0
      spine-flutter/example/android/app/src/main/kotlin/com/example/spine_flutter_example/MainActivity.kt
  73. 12 0
      spine-flutter/example/android/app/src/main/res/drawable-v21/launch_background.xml
  74. 12 0
      spine-flutter/example/android/app/src/main/res/drawable/launch_background.xml
  75. BIN
      spine-flutter/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
  76. BIN
      spine-flutter/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
  77. BIN
      spine-flutter/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
  78. BIN
      spine-flutter/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
  79. BIN
      spine-flutter/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
  80. 18 0
      spine-flutter/example/android/app/src/main/res/values-night/styles.xml
  81. 18 0
      spine-flutter/example/android/app/src/main/res/values/styles.xml
  82. 8 0
      spine-flutter/example/android/app/src/profile/AndroidManifest.xml
  83. 31 0
      spine-flutter/example/android/build.gradle
  84. 3 0
      spine-flutter/example/android/gradle.properties
  85. 6 0
      spine-flutter/example/android/gradle/wrapper/gradle-wrapper.properties
  86. 11 0
      spine-flutter/example/android/settings.gradle
  87. 409 0
      spine-flutter/example/assets/chibi/chibi-stickers.atlas
  88. BIN
      spine-flutter/example/assets/chibi/chibi-stickers.skel
  89. BIN
      spine-flutter/example/assets/chibi/chibi-stickers.webp
  90. BIN
      spine-flutter/example/assets/dragon-ess.skel
  91. 123 0
      spine-flutter/example/assets/dragon.atlas
  92. BIN
      spine-flutter/example/assets/dragon.png
  93. BIN
      spine-flutter/example/assets/dragon_2.png
  94. BIN
      spine-flutter/example/assets/dragon_3.png
  95. BIN
      spine-flutter/example/assets/dragon_4.png
  96. BIN
      spine-flutter/example/assets/dragon_5.png
  97. BIN
      spine-flutter/example/assets/dragon_6.png
  98. BIN
      spine-flutter/example/assets/mix-and-match-pro.skel
  99. 362 0
      spine-flutter/example/assets/mix-and-match.atlas
  100. BIN
      spine-flutter/example/assets/mix-and-match.png

+ 2 - 2
.github/actions/setup-godot-deps/action.yml

@@ -12,7 +12,7 @@ runs:
   steps:
   steps:
     # Use python 3.x release (works cross platform)
     # Use python 3.x release (works cross platform)
     - name: Set up Python 3.x
     - name: Set up Python 3.x
-      uses: actions/setup-python@v2
+      uses: actions/setup-python@v4
       with:
       with:
         # Semantic version range syntax or exact version of a Python version
         # Semantic version range syntax or exact version of a Python version
         python-version: ${{ inputs.python-version }}
         python-version: ${{ inputs.python-version }}
@@ -23,5 +23,5 @@ runs:
       shell: bash
       shell: bash
       run: |
       run: |
         python -c "import sys; print(sys.version)"
         python -c "import sys; print(sys.version)"
-        python -m pip install scons
+        python -m pip install scons==4.4.0
         scons --version
         scons --version

+ 7 - 8
.github/workflows/format-check.yml

@@ -14,11 +14,11 @@ jobs:
         sudo apt update
         sudo apt update
         sudo apt install -y --force-yes curl xz-utils libicu-dev git dos2unix libncurses5
         sudo apt install -y --force-yes curl xz-utils libicu-dev git dos2unix libncurses5
 
 
-    - uses: actions/checkout@v1      
+    - uses: actions/checkout@v3      
 
 
     - name: Cache Clang
     - name: Cache Clang
       id: cache-clang
       id: cache-clang
-      uses: actions/cache@v2
+      uses: actions/cache@v3
       with:
       with:
         path: clang
         path: clang
         key: ${{ runner.os }}-clang-13-0-1
         key: ${{ runner.os }}-clang-13-0-1
@@ -31,20 +31,19 @@ jobs:
         mv clang+llvm-13.0.1-x86_64-linux-gnu-ubuntu-18.04 clang
         mv clang+llvm-13.0.1-x86_64-linux-gnu-ubuntu-18.04 clang
 
 
     - name: Install dotnet
     - name: Install dotnet
-      uses: actions/setup-dotnet@v1
+      uses: actions/setup-dotnet@v3
       with:
       with:
-          dotnet-version: "6.0.x"      
-          include-prerelease: true   
+          dotnet-version: "6.0.x"          
     - run: dotnet tool install -g dotnet-format    
     - run: dotnet tool install -g dotnet-format    
           
           
     - name: Install Node and dependenceis    
     - name: Install Node and dependenceis    
-      uses: actions/setup-node@v1       
+      uses: actions/setup-node@v3 
       with:
       with:
         node-version: "16"
         node-version: "16"
     - run: npm install -g typescript typescript-formatter        
     - run: npm install -g typescript typescript-formatter        
 
 
     - name: Install JDK
     - name: Install JDK
-      uses: actions/setup-java@v2   
+      uses: actions/setup-java@v3 
       with:
       with:
         distribution: 'zulu'
         distribution: 'zulu'
         java-version: "16"          
         java-version: "16"          
@@ -60,7 +59,7 @@ jobs:
         git diff > format-diff.txt          
         git diff > format-diff.txt          
 
 
     - name: Archive formatting result
     - name: Archive formatting result
-      uses: actions/upload-artifact@v2
+      uses: actions/upload-artifact@v3
       with:
       with:
         name: format-diff
         name: format-diff
         path: format-diff.txt
         path: format-diff.txt

+ 368 - 0
.github/workflows/spine-godot-v4.yml

@@ -0,0 +1,368 @@
+name: Build and Publish Godot 4.0 editor and templates
+
+on:
+  push:
+    paths:
+      - ".github/workflows/spine-godot.yml"
+      - 'spine-godot/**'
+      - 'spine-cpp/**'
+  workflow_dispatch:
+
+env:
+  AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
+  AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
+  AWS_EC2_METADATA_DISABLED: true
+  EM_VERSION: 3.1.18
+  GODOT_TAG: 4.0-stable
+  GODOT_VERSION: 4.0.stable
+
+jobs:
+
+  godot-editor-windows:
+    runs-on: windows-latest
+    steps:
+      - uses: actions/checkout@v3
+        with:
+          fetch-depth: 0
+
+      - name: Setup python and scons
+        uses: ./.github/actions/setup-godot-deps
+
+      - name: Build Godot artifact
+        shell: bash
+        run: |          
+          ./spine-godot/build/setup.sh $GODOT_TAG false
+          ./spine-godot/build/build-v4.sh       
+
+      - name: Upload artifacts
+        uses: actions/upload-artifact@v3
+        with:
+          name: godot-editor-windows.zip
+          path: spine-godot/godot/bin/godot.windows.editor.x86_64.exe
+
+  godot-editor-linux:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v3
+        with:
+          fetch-depth: 0
+
+      - name: Setup python and scons
+        uses: ./.github/actions/setup-godot-deps
+
+      - name: Build Godot artifact
+        shell: bash
+        run: |          
+          sudo apt-get update
+          sudo apt-get install build-essential scons pkg-config libx11-dev libxcursor-dev libxinerama-dev libgl1-mesa-dev libglu-dev libasound2-dev libpulse-dev libudev-dev libxi-dev libxrandr-dev
+          ./spine-godot/build/setup.sh $GODOT_TAG false
+          ./spine-godot/build/build-v4.sh
+
+      - name: Upload artifacts
+        uses: actions/upload-artifact@v3
+        with:
+          name: godot-editor-linux.zip
+          path: spine-godot/godot/bin/godot.linuxbsd.editor.x86_64
+
+  godot-editor-macos:
+    runs-on: macos-latest
+    steps:
+      - uses: actions/checkout@v3
+        with:
+          fetch-depth: 0
+
+      - name: Setup python and scons
+        uses: ./.github/actions/setup-godot-deps
+
+      - name: Build Godot artifact
+        shell: bash
+        run: |
+          ./spine-godot/build/install-macos-vulkan-sdk.sh
+          ./spine-godot/build/setup.sh $GODOT_TAG false
+          ./spine-godot/build/build-v4.sh
+          pushd spine-godot/godot/bin
+          zip -r godot-editor-macos.zip Godot.app
+          popd          
+
+      - name: Upload artifacts
+        uses: actions/upload-artifact@v3
+        with:
+          name: godot-editor-macos.zip
+          path: spine-godot/godot/bin/godot-editor-macos.zip
+
+  godot-template-ios:
+    runs-on: macos-latest
+    steps:
+      - uses: actions/checkout@v3
+        with:
+          fetch-depth: 0
+
+      - name: Setup python and scons
+        uses: ./.github/actions/setup-godot-deps   
+
+      - name: Build Godot artifact
+        run: |     
+          ./spine-godot/build/install-macos-vulkan-sdk.sh     
+          ./spine-godot/build/setup.sh $GODOT_TAG false
+          ./spine-godot/build/build-templates-v4.sh ios
+
+      - name: Upload artifacts
+        uses: actions/upload-artifact@v3
+        with:
+          name: godot-template-ios.zip
+          path: spine-godot/godot/bin/ios.zip
+
+  godot-template-macos:
+    runs-on: macos-latest
+    steps:
+      - uses: actions/checkout@v3
+        with:
+          fetch-depth: 0
+
+      - name: Setup python and scons
+        uses: ./.github/actions/setup-godot-deps   
+
+      - name: Build Godot artifact
+        run: |          
+          ./spine-godot/build/install-macos-vulkan-sdk.sh
+          ./spine-godot/build/setup.sh $GODOT_TAG false
+          ./spine-godot/build/build-templates-v4.sh macos
+
+      - name: Upload artifacts
+        uses: actions/upload-artifact@v3
+        with:
+          name: godot-template-macos.zip
+          path: spine-godot/godot/bin/macos.zip
+
+  godot-template-linux:
+    runs-on: ubuntu-18.04
+    steps:
+      - uses: actions/checkout@v3
+        with:
+          fetch-depth: 0
+
+      - name: Setup python and scons
+        uses: ./.github/actions/setup-godot-deps   
+
+      - name: Build Godot artifact
+        run: |          
+          sudo apt-get update
+          sudo apt-get install build-essential scons pkg-config libx11-dev libxcursor-dev libxinerama-dev libgl1-mesa-dev libglu-dev libasound2-dev libpulse-dev libudev-dev libxi-dev libxrandr-dev
+          ./spine-godot/build/setup.sh $GODOT_TAG false
+          ./spine-godot/build/build-templates-v4.sh linux
+
+      - name: Upload artifacts debug
+        uses: actions/upload-artifact@v3
+        with:
+          name: godot-template-linux-debug.zip
+          path: spine-godot/godot/bin/linux_x11_64_debug
+
+      - name: Upload artifacts release
+        uses: actions/upload-artifact@v3
+        with:
+          name: godot-template-linux-release.zip
+          path: spine-godot/godot/bin/linux_x11_64_release
+
+  godot-template-windows:
+    runs-on: windows-latest
+    steps:
+      - uses: actions/checkout@v3
+        with:
+          fetch-depth: 0
+
+      - name: Setup python and scons
+        uses: ./.github/actions/setup-godot-deps
+
+      - name: Build Godot artifact
+        shell: bash
+        run: |
+          ./spine-godot/build/setup.sh $GODOT_TAG false
+          ./spine-godot/build/build-templates-v4.sh windows
+
+      - name: Upload artifacts debug
+        uses: actions/upload-artifact@v3
+        with:
+          name: godot-template-windows-debug.zip
+          path: spine-godot/godot/bin/windows_debug_x86_64.exe
+
+      - name: Upload artifacts release
+        uses: actions/upload-artifact@v3
+        with:
+          name: godot-template-windows-release.zip
+          path: spine-godot/godot/bin/windows_release_x86_64.exe
+
+  godot-template-android:
+    runs-on: ubuntu-20.04
+    steps:
+      - uses: actions/checkout@v3
+        with:
+          fetch-depth: 0
+
+      # Azure repositories are not reliable, we need to prevent azure giving us packages.
+      - name: Make apt sources.list use the default Ubuntu repositories
+        run: |
+          sudo rm -f /etc/apt/sources.list.d/*
+          sudo cp -f spine-godot/build/sources.lst /etc/apt/sources.list
+          sudo apt-get update
+          
+      - name: Set up Java 11
+        uses: actions/setup-java@v1
+        with:
+          java-version: 11
+
+      - name: Setup python and scons
+        uses: ./.github/actions/setup-godot-deps
+
+      - name: Build Godot artifact
+        shell: bash
+        run: |
+          ./spine-godot/build/setup.sh $GODOT_TAG false
+          ./spine-godot/build/build-templates-v4.sh android
+
+      - name: Upload artifacts debug
+        uses: actions/upload-artifact@v3
+        with:
+          name: godot-template-android-debug.zip
+          path: spine-godot/godot/bin/android_debug.apk
+
+      - name: Upload artifacts release
+        uses: actions/upload-artifact@v3
+        with:
+          name: godot-template-android-release.zip
+          path: spine-godot/godot/bin/android_release.apk
+
+      - name: Upload artifacts source
+        uses: actions/upload-artifact@v3
+        with:
+          name: godot-template-android-source.zip
+          path: spine-godot/godot/bin/android_source.zip
+
+  godot-template-web:
+    runs-on: ubuntu-20.04
+    steps:
+      - uses: actions/checkout@v3
+        with:
+          fetch-depth: 0
+
+      - name: Set up Emscripten latest
+        uses: mymindstorm/setup-emsdk@v11
+        with:
+          version: ${{env.EM_VERSION}}          
+
+      - name: Verify Emscripten setup
+        run: |
+          emcc -v
+
+      - name: Setup python and scons
+        uses: ./.github/actions/setup-godot-deps   
+
+      - name: Build Godot artifact
+        run: |          
+          ./spine-godot/build/setup.sh $GODOT_TAG false
+          ./spine-godot/build/build-templates-v4.sh web
+
+      - name: Upload artifacts debug
+        uses: actions/upload-artifact@v3
+        with:
+          name: godot-template-web-debug.zip
+          path: spine-godot/godot/bin/web_debug.zip
+
+      - name: Upload artifacts release
+        uses: actions/upload-artifact@v3
+        with:
+          name: godot-template-web-release.zip
+          path: spine-godot/godot/bin/web_release.zip
+
+  upload-to-s3:
+    needs: [godot-editor-windows, godot-editor-linux, godot-editor-macos, godot-template-ios, godot-template-macos, godot-template-windows, godot-template-linux, godot-template-android, godot-template-web]
+    runs-on: ubuntu-latest
+    steps:
+      - name: Download godot-editor-windows artifact
+        uses: actions/download-artifact@v2
+        with:
+          name: godot-editor-windows.zip
+
+      - name: Download godot-editor-linux artifact
+        uses: actions/download-artifact@v2
+        with:
+          name: godot-editor-linux.zip
+
+      - name: Download godot-editor-macos artifact
+        uses: actions/download-artifact@v2
+        with:
+          name: godot-editor-macos.zip
+
+      - name: Download godot-template-ios artifact
+        uses: actions/download-artifact@v2
+        with:
+          name: godot-template-ios.zip
+
+      - name: Download godot-template-macos artifact
+        uses: actions/download-artifact@v2
+        with:
+          name: godot-template-macos.zip
+
+      - name: Download godot-template-windows-release artifact
+        uses: actions/download-artifact@v2
+        with:
+          name: godot-template-windows-release.zip
+
+      - name: Download godot-template-windows-debug artifact
+        uses: actions/download-artifact@v2
+        with:
+          name: godot-template-windows-debug.zip
+
+      - name: Download godot-template-linux-release artifact
+        uses: actions/download-artifact@v2
+        with:
+          name: godot-template-linux-release.zip
+          
+      - name: Download godot-template-linux-debug artifact
+        uses: actions/download-artifact@v2
+        with:
+          name: godot-template-linux-debug.zip
+
+      - name: Download godot-template-android-release artifact
+        uses: actions/download-artifact@v2
+        with:
+          name: godot-template-android-release.zip
+          
+      - name: Download godot-template-android-debug artifact
+        uses: actions/download-artifact@v2
+        with:
+          name: godot-template-android-debug.zip
+
+      - name: Download godot-template-android-source artifact
+        uses: actions/download-artifact@v2
+        with:
+          name: godot-template-android-source.zip
+
+      - name: Download godot-template-web-release artifact
+        uses: actions/download-artifact@v2
+        with:
+          name: godot-template-web-release.zip
+          
+      - name: Download godot-template-web-debug artifact
+        uses: actions/download-artifact@v2
+        with:
+          name: godot-template-web-debug.zip
+
+      - name: Upload artifacts to S3
+        shell: bash
+        if: env.AWS_ACCESS_KEY_ID != null
+        run: |
+          BRANCH=${GITHUB_REF#refs/heads/}
+          echo "branch: $BRANCH"
+          mv godot.windows.editor.x86_64.exe godot-$BRANCH-$GODOT_TAG.exe
+          mv godot.linuxbsd.editor.x86_64 godot-$BRANCH-$GODOT_TAG
+          zip godot-editor-windows.zip godot-$BRANCH-$GODOT_TAG.exe
+          zip godot-editor-linux.zip godot-$BRANCH-$GODOT_TAG
+          aws s3 cp godot-editor-windows.zip s3://spine-godot/$BRANCH/$GODOT_TAG/
+          aws s3 cp godot-editor-linux.zip s3://spine-godot/$BRANCH/$GODOT_TAG/
+          aws s3 cp godot-editor-macos.zip s3://spine-godot/$BRANCH/$GODOT_TAG/
+          echo "$GODOT_VERSION" > version.txt
+          ls -lah
+          zip spine-godot-templates-$BRANCH-$GODOT_TAG.zip ios.zip macos.zip windows_debug_x86_64.exe windows_release_x86_64.exe linux_x11_64_debug linux_x11_64_release web_debug.zip web_release.zip android_release.apk android_debug.apk android_source.zip version.txt
+          aws s3 cp spine-godot-templates-$BRANCH-$GODOT_TAG.zip s3://spine-godot/$BRANCH/$GODOT_TAG/spine-godot-templates-$BRANCH-$GODOT_TAG.tpz
+
+  

+ 25 - 25
.github/workflows/spine-godot.yml

@@ -12,7 +12,7 @@ env:
   AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
   AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
   AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
   AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
   AWS_EC2_METADATA_DISABLED: true
   AWS_EC2_METADATA_DISABLED: true
-  EM_VERSION: 3.1.10
+  EM_VERSION: 3.1.14
   GODOT_TAG: 3.5.1-stable
   GODOT_TAG: 3.5.1-stable
   GODOT_VERSION: 3.5.1.stable
   GODOT_VERSION: 3.5.1.stable
 
 
@@ -21,7 +21,7 @@ jobs:
   godot-editor-windows:
   godot-editor-windows:
     runs-on: windows-latest
     runs-on: windows-latest
     steps:
     steps:
-      - uses: actions/checkout@v2
+      - uses: actions/checkout@v3
         with:
         with:
           fetch-depth: 0
           fetch-depth: 0
 
 
@@ -35,7 +35,7 @@ jobs:
           ./spine-godot/build/build.sh release_debug          
           ./spine-godot/build/build.sh release_debug          
 
 
       - name: Upload artifacts
       - name: Upload artifacts
-        uses: actions/upload-artifact@v2
+        uses: actions/upload-artifact@v3
         with:
         with:
           name: godot-editor-windows.zip
           name: godot-editor-windows.zip
           path: spine-godot/godot/bin/godot.windows.opt.tools.64.exe
           path: spine-godot/godot/bin/godot.windows.opt.tools.64.exe
@@ -43,7 +43,7 @@ jobs:
   godot-editor-linux:
   godot-editor-linux:
     runs-on: ubuntu-latest
     runs-on: ubuntu-latest
     steps:
     steps:
-      - uses: actions/checkout@v2
+      - uses: actions/checkout@v3
         with:
         with:
           fetch-depth: 0
           fetch-depth: 0
 
 
@@ -59,7 +59,7 @@ jobs:
           ./spine-godot/build/build.sh release_debug          
           ./spine-godot/build/build.sh release_debug          
 
 
       - name: Upload artifacts
       - name: Upload artifacts
-        uses: actions/upload-artifact@v2
+        uses: actions/upload-artifact@v3
         with:
         with:
           name: godot-editor-linux.zip
           name: godot-editor-linux.zip
           path: spine-godot/godot/bin/godot.x11.opt.tools.64
           path: spine-godot/godot/bin/godot.x11.opt.tools.64
@@ -67,7 +67,7 @@ jobs:
   godot-editor-macos:
   godot-editor-macos:
     runs-on: macos-latest
     runs-on: macos-latest
     steps:
     steps:
-      - uses: actions/checkout@v2
+      - uses: actions/checkout@v3
         with:
         with:
           fetch-depth: 0
           fetch-depth: 0
 
 
@@ -84,7 +84,7 @@ jobs:
           popd          
           popd          
 
 
       - name: Upload artifacts
       - name: Upload artifacts
-        uses: actions/upload-artifact@v2
+        uses: actions/upload-artifact@v3
         with:
         with:
           name: godot-editor-macos.zip
           name: godot-editor-macos.zip
           path: spine-godot/godot/bin/godot-editor-macos.zip
           path: spine-godot/godot/bin/godot-editor-macos.zip
@@ -92,7 +92,7 @@ jobs:
   godot-template-ios:
   godot-template-ios:
     runs-on: macos-latest
     runs-on: macos-latest
     steps:
     steps:
-      - uses: actions/checkout@v2
+      - uses: actions/checkout@v3
         with:
         with:
           fetch-depth: 0
           fetch-depth: 0
 
 
@@ -105,7 +105,7 @@ jobs:
           ./spine-godot/build/build-templates.sh ios
           ./spine-godot/build/build-templates.sh ios
 
 
       - name: Upload artifacts
       - name: Upload artifacts
-        uses: actions/upload-artifact@v2
+        uses: actions/upload-artifact@v3
         with:
         with:
           name: godot-template-ios.zip
           name: godot-template-ios.zip
           path: spine-godot/godot/bin/iphone.zip
           path: spine-godot/godot/bin/iphone.zip
@@ -113,7 +113,7 @@ jobs:
   godot-template-macos:
   godot-template-macos:
     runs-on: macos-latest
     runs-on: macos-latest
     steps:
     steps:
-      - uses: actions/checkout@v2
+      - uses: actions/checkout@v3
         with:
         with:
           fetch-depth: 0
           fetch-depth: 0
 
 
@@ -126,7 +126,7 @@ jobs:
           ./spine-godot/build/build-templates.sh macos
           ./spine-godot/build/build-templates.sh macos
 
 
       - name: Upload artifacts
       - name: Upload artifacts
-        uses: actions/upload-artifact@v2
+        uses: actions/upload-artifact@v3
         with:
         with:
           name: godot-template-macos.zip
           name: godot-template-macos.zip
           path: spine-godot/godot/bin/osx.zip
           path: spine-godot/godot/bin/osx.zip
@@ -134,7 +134,7 @@ jobs:
   godot-template-linux:
   godot-template-linux:
     runs-on: ubuntu-18.04
     runs-on: ubuntu-18.04
     steps:
     steps:
-      - uses: actions/checkout@v2
+      - uses: actions/checkout@v3
         with:
         with:
           fetch-depth: 0
           fetch-depth: 0
 
 
@@ -149,13 +149,13 @@ jobs:
           ./spine-godot/build/build-templates.sh linux
           ./spine-godot/build/build-templates.sh linux
 
 
       - name: Upload artifacts debug
       - name: Upload artifacts debug
-        uses: actions/upload-artifact@v2
+        uses: actions/upload-artifact@v3
         with:
         with:
           name: godot-template-linux-debug.zip
           name: godot-template-linux-debug.zip
           path: spine-godot/godot/bin/linux_x11_64_debug
           path: spine-godot/godot/bin/linux_x11_64_debug
 
 
       - name: Upload artifacts release
       - name: Upload artifacts release
-        uses: actions/upload-artifact@v2
+        uses: actions/upload-artifact@v3
         with:
         with:
           name: godot-template-linux-release.zip
           name: godot-template-linux-release.zip
           path: spine-godot/godot/bin/linux_x11_64_release
           path: spine-godot/godot/bin/linux_x11_64_release
@@ -163,7 +163,7 @@ jobs:
   godot-template-windows:
   godot-template-windows:
     runs-on: windows-latest
     runs-on: windows-latest
     steps:
     steps:
-      - uses: actions/checkout@v2
+      - uses: actions/checkout@v3
         with:
         with:
           fetch-depth: 0
           fetch-depth: 0
 
 
@@ -177,13 +177,13 @@ jobs:
           ./spine-godot/build/build-templates.sh windows
           ./spine-godot/build/build-templates.sh windows
 
 
       - name: Upload artifacts debug
       - name: Upload artifacts debug
-        uses: actions/upload-artifact@v2
+        uses: actions/upload-artifact@v3
         with:
         with:
           name: godot-template-windows-debug.zip
           name: godot-template-windows-debug.zip
           path: spine-godot/godot/bin/windows_64_debug.exe
           path: spine-godot/godot/bin/windows_64_debug.exe
 
 
       - name: Upload artifacts release
       - name: Upload artifacts release
-        uses: actions/upload-artifact@v2
+        uses: actions/upload-artifact@v3
         with:
         with:
           name: godot-template-windows-release.zip
           name: godot-template-windows-release.zip
           path: spine-godot/godot/bin/windows_64_release.exe
           path: spine-godot/godot/bin/windows_64_release.exe
@@ -191,7 +191,7 @@ jobs:
   godot-template-android:
   godot-template-android:
     runs-on: ubuntu-20.04
     runs-on: ubuntu-20.04
     steps:
     steps:
-      - uses: actions/checkout@v2
+      - uses: actions/checkout@v3
         with:
         with:
           fetch-depth: 0
           fetch-depth: 0
 
 
@@ -217,19 +217,19 @@ jobs:
           ./spine-godot/build/build-templates.sh android
           ./spine-godot/build/build-templates.sh android
 
 
       - name: Upload artifacts debug
       - name: Upload artifacts debug
-        uses: actions/upload-artifact@v2
+        uses: actions/upload-artifact@v3
         with:
         with:
           name: godot-template-android-debug.zip
           name: godot-template-android-debug.zip
           path: spine-godot/godot/bin/android_debug.apk
           path: spine-godot/godot/bin/android_debug.apk
 
 
       - name: Upload artifacts release
       - name: Upload artifacts release
-        uses: actions/upload-artifact@v2
+        uses: actions/upload-artifact@v3
         with:
         with:
           name: godot-template-android-release.zip
           name: godot-template-android-release.zip
           path: spine-godot/godot/bin/android_release.apk
           path: spine-godot/godot/bin/android_release.apk
 
 
       - name: Upload artifacts source
       - name: Upload artifacts source
-        uses: actions/upload-artifact@v2
+        uses: actions/upload-artifact@v3
         with:
         with:
           name: godot-template-android-source.zip
           name: godot-template-android-source.zip
           path: spine-godot/godot/bin/android_source.zip
           path: spine-godot/godot/bin/android_source.zip
@@ -237,12 +237,12 @@ jobs:
   godot-template-web:
   godot-template-web:
     runs-on: ubuntu-20.04
     runs-on: ubuntu-20.04
     steps:
     steps:
-      - uses: actions/checkout@v2
+      - uses: actions/checkout@v3
         with:
         with:
           fetch-depth: 0
           fetch-depth: 0
 
 
       - name: Set up Emscripten latest
       - name: Set up Emscripten latest
-        uses: mymindstorm/setup-emsdk@v10
+        uses: mymindstorm/setup-emsdk@v11
         with:
         with:
           version: ${{env.EM_VERSION}}          
           version: ${{env.EM_VERSION}}          
 
 
@@ -259,13 +259,13 @@ jobs:
           ./spine-godot/build/build-templates.sh web
           ./spine-godot/build/build-templates.sh web
 
 
       - name: Upload artifacts debug
       - name: Upload artifacts debug
-        uses: actions/upload-artifact@v2
+        uses: actions/upload-artifact@v3
         with:
         with:
           name: godot-template-web-debug.zip
           name: godot-template-web-debug.zip
           path: spine-godot/godot/bin/webassembly_debug.zip
           path: spine-godot/godot/bin/webassembly_debug.zip
 
 
       - name: Upload artifacts release
       - name: Upload artifacts release
-        uses: actions/upload-artifact@v2
+        uses: actions/upload-artifact@v3
         with:
         with:
           name: godot-template-web-release.zip
           name: godot-template-web-release.zip
           path: spine-godot/godot/bin/webassembly_release.zip
           path: spine-godot/godot/bin/webassembly_release.zip

+ 6 - 4
.github/workflows/spine-libgdx.yml

@@ -4,22 +4,24 @@ on:
   push:
   push:
     paths:
     paths:
       - 'spine-libgdx/**'
       - 'spine-libgdx/**'
+  workflow_dispatch:
 
 
 jobs:
 jobs:
   build:
   build:
     runs-on: ubuntu-latest
     runs-on: ubuntu-latest
     steps:
     steps:
-    - uses: actions/checkout@v1
+    - uses: actions/checkout@v3
     - name: Set up JDK 1.8
     - name: Set up JDK 1.8
-      uses: actions/setup-java@v1
+      uses: actions/setup-java@v3 
       with:
       with:
-        java-version: 1.8
+        distribution: 'zulu'
+        java-version: "8"       
         server-id: sonatype-nexus-snapshots
         server-id: sonatype-nexus-snapshots
         server-username: MAVEN_USERNAME
         server-username: MAVEN_USERNAME
         server-password: MAVEN_PASSWORD
         server-password: MAVEN_PASSWORD
 
 
     - name: Cache Maven packages
     - name: Cache Maven packages
-      uses: actions/cache@v2
+      uses: actions/cache@v3
       with:
       with:
         path: ~/.m2
         path: ~/.m2
         key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
         key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}

+ 4 - 3
.github/workflows/spine-ts.yml

@@ -4,16 +4,17 @@ on:
   push:
   push:
     paths:
     paths:
       - 'spine-ts/**'
       - 'spine-ts/**'
+  workflow_dispatch:
 
 
 jobs:
 jobs:
   build:
   build:
     runs-on: ubuntu-latest
     runs-on: ubuntu-latest
     steps:
     steps:
-    - uses: actions/checkout@v1
+    - uses: actions/checkout@v3
     - name: Setup TypeScript
     - name: Setup TypeScript
-      uses: actions/setup-node@v1
+      uses: actions/setup-node@v3
       with:
       with:
-        node-version: '16.6.2'    
+        node-version: '16'    
     - name: Build spine-ts
     - name: Build spine-ts
       working-directory: spine-ts
       working-directory: spine-ts
       env:
       env:

+ 4 - 0
.gitignore

@@ -183,3 +183,7 @@ spine-godot/.clang-format
 spine-ts/spine-phaser/dist
 spine-ts/spine-phaser/dist
 spine-godot/.cache
 spine-godot/.cache
 spine-godot/build/compile_commands.json
 spine-godot/build/compile_commands.json
+
+spine-flutter/ios/Classes/spine-cpp
+spine-flutter/macos/Classes/spine-cpp
+spine-flutter/src/spine-cpp

+ 4 - 2
CHANGELOG.md

@@ -27,7 +27,9 @@
   * Support for `shortestRotation` in animation state. See https://github.com/esotericsoftware/spine-runtimes/issues/2027.
   * Support for `shortestRotation` in animation state. See https://github.com/esotericsoftware/spine-runtimes/issues/2027.
   * Added CMake parameter `SPINE_SANITIZE` which will enable sanitizers on macOS and Linux.
   * Added CMake parameter `SPINE_SANITIZE` which will enable sanitizers on macOS and Linux.
     * Added `SPINE_MAJOR_VERSION`, `SPINE_MINOR_VERSION`, and `SPINE_VERSION_STRING`. Parsing skeleton .JSON and .skel files will report an error if the skeleton version does not match the runtime version.
     * Added `SPINE_MAJOR_VERSION`, `SPINE_MINOR_VERSION`, and `SPINE_VERSION_STRING`. Parsing skeleton .JSON and .skel files will report an error if the skeleton version does not match the runtime version.
+  * Added `SkeletonBounds::getBoundingBox()`, `SkeletonBounds::getPolygons()`, and `SkeletonBounds::getBoundingBoxes()`.
 * **Breaking changes**
 * **Breaking changes**
+  * `RegionAttachment` and `MeshAttachment` no longer implement `HasRendererObject`.
   * `RegionAttachment` and `MeshAttachment` now contain a `TextureRegion*` instead of encoding region fields directly.
   * `RegionAttachment` and `MeshAttachment` now contain a `TextureRegion*` instead of encoding region fields directly.
   * `AttachmentLoader::newRegionAttachment()` and `AttachmentLoader::newMeshAttachment()` now take an additional `Sequence*` parameter.
   * `AttachmentLoader::newRegionAttachment()` and `AttachmentLoader::newMeshAttachment()` now take an additional `Sequence*` parameter.
   * `MeshAttachment::updateUVs()` was renamed to `MeshAttachment::updateRegion()`.
   * `MeshAttachment::updateUVs()` was renamed to `MeshAttachment::updateRegion()`.
@@ -36,7 +38,7 @@
   * `VertexAttachment::getDeformAttachment()` was renamed to `VertexAttachment::getTimelineAttachment()`.
   * `VertexAttachment::getDeformAttachment()` was renamed to `VertexAttachment::getTimelineAttachment()`.
   * `Skeleton::update()` has been removed.
   * `Skeleton::update()` has been removed.
   * `Skeleton::getTime()` has been removed.
   * `Skeleton::getTime()` has been removed.
-  * `VertexEffect` has been removed.
+  * `VertexEffect` has been removed.  
   
   
 ### Cocos2d-x
 ### Cocos2d-x
 
 
@@ -143,7 +145,7 @@
   * `VertexEffect` has been removed.
   * `VertexEffect` has been removed.
 
 
 ### WebGL backend
 ### WebGL backend
-  * `PolygonBatcher.start()` now disables culling and restores the previous state on `PolygonBatcher.end()`.
+  * `PolygonBatcher` can now disable culling automatically if the static variable `PolygonBatcher.disableCulling` is set to true.
   * Added `SpineCanvas`, a simpler way to render a scene via spine-webgl. See `spine-ts/spine-webgl/examples/barebones.html` and `spine-ts/spine-webgl/examples/mix-and-match.html`.
   * Added `SpineCanvas`, a simpler way to render a scene via spine-webgl. See `spine-ts/spine-webgl/examples/barebones.html` and `spine-ts/spine-webgl/examples/mix-and-match.html`.
 
 
 ### Canvas backend
 ### Canvas backend

+ 5 - 0
spine-c/spine-c/src/spine/Atlas.c

@@ -99,6 +99,11 @@ spAtlasPage *spAtlasPage_create(spAtlas *atlas, const char *name) {
 	spAtlasPage *self = NEW(spAtlasPage);
 	spAtlasPage *self = NEW(spAtlasPage);
 	CONST_CAST(spAtlas *, self->atlas) = atlas;
 	CONST_CAST(spAtlas *, self->atlas) = atlas;
 	MALLOC_STR(self->name, name);
 	MALLOC_STR(self->name, name);
+    self->minFilter = SP_ATLAS_NEAREST;
+    self->magFilter = SP_ATLAS_NEAREST;
+    self->format = SP_ATLAS_RGBA8888;
+    self->uWrap = SP_ATLAS_CLAMPTOEDGE;
+    self->vWrap = SP_ATLAS_CLAMPTOEDGE;
 	return self;
 	return self;
 }
 }
 
 

+ 194 - 193
spine-c/spine-c/src/spine/SkeletonJson.c

@@ -120,7 +120,7 @@ static int readCurve(Json *curve, spCurveTimeline *timeline, int bezier, int fra
 					 float value1, float value2, float scale) {
 					 float value1, float value2, float scale) {
 	float cx1, cy1, cx2, cy2;
 	float cx1, cy1, cx2, cy2;
 	if (curve->type == Json_String && strcmp(curve->valueString, "stepped") == 0) {
 	if (curve->type == Json_String && strcmp(curve->valueString, "stepped") == 0) {
-		if (value != 0) spCurveTimeline_setStepped(timeline, frame);
+		spCurveTimeline_setStepped(timeline, frame);
 		return bezier;
 		return bezier;
 	}
 	}
 	curve = Json_getItemAtIndex(curve, value << 2);
 	curve = Json_getItemAtIndex(curve, value << 2);
@@ -1097,7 +1097,7 @@ spSkeletonData *spSkeletonJson_readSkeletonData(spSkeletonJson *self, const char
 									  toColor(dark, 0),
 									  toColor(dark, 0),
 									  toColor(dark, 1),
 									  toColor(dark, 1),
 									  toColor(dark, 2),
 									  toColor(dark, 2),
-									  toColor(dark, 3));
+									  1.0f);
 			}
 			}
 
 
 			item = Json_getItem(slotMap, "attachment");
 			item = Json_getItem(slotMap, "attachment");
@@ -1354,220 +1354,221 @@ spSkeletonData *spSkeletonJson_readSkeletonData(spSkeletonJson *self, const char
 			skeletonData->skins[skeletonData->skinsCount++] = skin;
 			skeletonData->skins[skeletonData->skinsCount++] = skin;
 			if (strcmp(skin->name, "default") == 0) skeletonData->defaultSkin = skin;
 			if (strcmp(skin->name, "default") == 0) skeletonData->defaultSkin = skin;
 
 
-			for (attachmentsMap = Json_getItem(skinMap,
-											   "attachments")
-										  ->child;
-				 attachmentsMap; attachmentsMap = attachmentsMap->next) {
-				spSlotData *slot = spSkeletonData_findSlot(skeletonData, attachmentsMap->name);
-				Json *attachmentMap;
-
-				for (attachmentMap = attachmentsMap->child; attachmentMap; attachmentMap = attachmentMap->next) {
-					spAttachment *attachment;
-					const char *skinAttachmentName = attachmentMap->name;
-					const char *attachmentName = Json_getString(attachmentMap, "name", skinAttachmentName);
-					const char *path = Json_getString(attachmentMap, "path", attachmentName);
-					const char *color;
-					Json *entry;
-					spSequence *sequence;
-
-					const char *typeString = Json_getString(attachmentMap, "type", "region");
-					spAttachmentType type;
-					if (strcmp(typeString, "region") == 0) type = SP_ATTACHMENT_REGION;
-					else if (strcmp(typeString, "mesh") == 0)
-						type = SP_ATTACHMENT_MESH;
-					else if (strcmp(typeString, "linkedmesh") == 0)
-						type = SP_ATTACHMENT_LINKED_MESH;
-					else if (strcmp(typeString, "boundingbox") == 0)
-						type = SP_ATTACHMENT_BOUNDING_BOX;
-					else if (strcmp(typeString, "path") == 0)
-						type = SP_ATTACHMENT_PATH;
-					else if (strcmp(typeString, "clipping") == 0)
-						type = SP_ATTACHMENT_CLIPPING;
-					else if (strcmp(typeString, "point") == 0)
-						type = SP_ATTACHMENT_POINT;
-					else {
-						spSkeletonData_dispose(skeletonData);
-						_spSkeletonJson_setError(self, root, "Unknown attachment type: ", typeString);
-						return NULL;
-					}
-
-					sequence = readSequence(Json_getItem(attachmentMap, "sequence"));
-					attachment = spAttachmentLoader_createAttachment(self->attachmentLoader, skin, type, attachmentName,
-																	 path, sequence);
-					if (!attachment) {
-						if (self->attachmentLoader->error1) {
+			skinPart = Json_getItem(skinMap, "attachments");
+			if (skinPart) {
+				for (attachmentsMap = skinPart->child; attachmentsMap; attachmentsMap = attachmentsMap->next) {
+					spSlotData *slot = spSkeletonData_findSlot(skeletonData, attachmentsMap->name);
+					Json *attachmentMap;
+
+					for (attachmentMap = attachmentsMap->child; attachmentMap; attachmentMap = attachmentMap->next) {
+						spAttachment *attachment;
+						const char *skinAttachmentName = attachmentMap->name;
+						const char *attachmentName = Json_getString(attachmentMap, "name", skinAttachmentName);
+						const char *path = Json_getString(attachmentMap, "path", attachmentName);
+						const char *color;
+						Json *entry;
+						spSequence *sequence;
+
+						const char *typeString = Json_getString(attachmentMap, "type", "region");
+						spAttachmentType type;
+						if (strcmp(typeString, "region") == 0) type = SP_ATTACHMENT_REGION;
+						else if (strcmp(typeString, "mesh") == 0)
+							type = SP_ATTACHMENT_MESH;
+						else if (strcmp(typeString, "linkedmesh") == 0)
+							type = SP_ATTACHMENT_LINKED_MESH;
+						else if (strcmp(typeString, "boundingbox") == 0)
+							type = SP_ATTACHMENT_BOUNDING_BOX;
+						else if (strcmp(typeString, "path") == 0)
+							type = SP_ATTACHMENT_PATH;
+						else if (strcmp(typeString, "clipping") == 0)
+							type = SP_ATTACHMENT_CLIPPING;
+						else if (strcmp(typeString, "point") == 0)
+							type = SP_ATTACHMENT_POINT;
+						else {
 							spSkeletonData_dispose(skeletonData);
 							spSkeletonData_dispose(skeletonData);
-							_spSkeletonJson_setError(self, root, self->attachmentLoader->error1,
-													 self->attachmentLoader->error2);
+							_spSkeletonJson_setError(self, root, "Unknown attachment type: ", typeString);
 							return NULL;
 							return NULL;
 						}
 						}
-						continue;
-					}
 
 
-					switch (attachment->type) {
-						case SP_ATTACHMENT_REGION: {
-							spRegionAttachment *region = SUB_CAST(spRegionAttachment, attachment);
-							if (path) MALLOC_STR(region->path, path);
-							region->x = Json_getFloat(attachmentMap, "x", 0) * self->scale;
-							region->y = Json_getFloat(attachmentMap, "y", 0) * self->scale;
-							region->scaleX = Json_getFloat(attachmentMap, "scaleX", 1);
-							region->scaleY = Json_getFloat(attachmentMap, "scaleY", 1);
-							region->rotation = Json_getFloat(attachmentMap, "rotation", 0);
-							region->width = Json_getFloat(attachmentMap, "width", 32) * self->scale;
-							region->height = Json_getFloat(attachmentMap, "height", 32) * self->scale;
-							region->sequence = sequence;
-
-							color = Json_getString(attachmentMap, "color", 0);
-							if (color) {
-								spColor_setFromFloats(&region->color,
-													  toColor(color, 0),
-													  toColor(color, 1),
-													  toColor(color, 2),
-													  toColor(color, 3));
+						sequence = readSequence(Json_getItem(attachmentMap, "sequence"));
+						attachment = spAttachmentLoader_createAttachment(self->attachmentLoader, skin, type,
+																		 attachmentName,
+																		 path, sequence);
+						if (!attachment) {
+							if (self->attachmentLoader->error1) {
+								spSkeletonData_dispose(skeletonData);
+								_spSkeletonJson_setError(self, root, self->attachmentLoader->error1,
+														 self->attachmentLoader->error2);
+								return NULL;
 							}
 							}
+							continue;
+						}
 
 
-							if (region->region != NULL) spRegionAttachment_updateRegion(region);
+						switch (attachment->type) {
+							case SP_ATTACHMENT_REGION: {
+								spRegionAttachment *region = SUB_CAST(spRegionAttachment, attachment);
+								if (path) MALLOC_STR(region->path, path);
+								region->x = Json_getFloat(attachmentMap, "x", 0) * self->scale;
+								region->y = Json_getFloat(attachmentMap, "y", 0) * self->scale;
+								region->scaleX = Json_getFloat(attachmentMap, "scaleX", 1);
+								region->scaleY = Json_getFloat(attachmentMap, "scaleY", 1);
+								region->rotation = Json_getFloat(attachmentMap, "rotation", 0);
+								region->width = Json_getFloat(attachmentMap, "width", 32) * self->scale;
+								region->height = Json_getFloat(attachmentMap, "height", 32) * self->scale;
+								region->sequence = sequence;
+
+								color = Json_getString(attachmentMap, "color", 0);
+								if (color) {
+									spColor_setFromFloats(&region->color,
+														  toColor(color, 0),
+														  toColor(color, 1),
+														  toColor(color, 2),
+														  toColor(color, 3));
+								}
 
 
-							spAttachmentLoader_configureAttachment(self->attachmentLoader, attachment);
-							break;
-						}
-						case SP_ATTACHMENT_MESH:
-						case SP_ATTACHMENT_LINKED_MESH: {
-							spMeshAttachment *mesh = SUB_CAST(spMeshAttachment, attachment);
-
-							MALLOC_STR(mesh->path, path);
-
-							color = Json_getString(attachmentMap, "color", 0);
-							if (color) {
-								spColor_setFromFloats(&mesh->color,
-													  toColor(color, 0),
-													  toColor(color, 1),
-													  toColor(color, 2),
-													  toColor(color, 3));
+								if (region->region != NULL) spRegionAttachment_updateRegion(region);
+
+								spAttachmentLoader_configureAttachment(self->attachmentLoader, attachment);
+								break;
 							}
 							}
+							case SP_ATTACHMENT_MESH:
+							case SP_ATTACHMENT_LINKED_MESH: {
+								spMeshAttachment *mesh = SUB_CAST(spMeshAttachment, attachment);
+
+								MALLOC_STR(mesh->path, path);
+
+								color = Json_getString(attachmentMap, "color", 0);
+								if (color) {
+									spColor_setFromFloats(&mesh->color,
+														  toColor(color, 0),
+														  toColor(color, 1),
+														  toColor(color, 2),
+														  toColor(color, 3));
+								}
 
 
-							mesh->width = Json_getFloat(attachmentMap, "width", 32) * self->scale;
-							mesh->height = Json_getFloat(attachmentMap, "height", 32) * self->scale;
-							mesh->sequence = sequence;
+								mesh->width = Json_getFloat(attachmentMap, "width", 32) * self->scale;
+								mesh->height = Json_getFloat(attachmentMap, "height", 32) * self->scale;
+								mesh->sequence = sequence;
 
 
-							entry = Json_getItem(attachmentMap, "parent");
-							if (!entry) {
-								int verticesLength;
-								entry = Json_getItem(attachmentMap, "triangles");
-								mesh->trianglesCount = entry->size;
-								mesh->triangles = MALLOC(unsigned short, entry->size);
-								for (entry = entry->child, ii = 0; entry; entry = entry->next, ++ii)
-									mesh->triangles[ii] = (unsigned short) entry->valueInt;
+								entry = Json_getItem(attachmentMap, "parent");
+								if (!entry) {
+									int verticesLength;
+									entry = Json_getItem(attachmentMap, "triangles");
+									mesh->trianglesCount = entry->size;
+									mesh->triangles = MALLOC(unsigned short, entry->size);
+									for (entry = entry->child, ii = 0; entry; entry = entry->next, ++ii)
+										mesh->triangles[ii] = (unsigned short) entry->valueInt;
 
 
-								entry = Json_getItem(attachmentMap, "uvs");
-								verticesLength = entry->size;
-								mesh->regionUVs = MALLOC(float, verticesLength);
-								for (entry = entry->child, ii = 0; entry; entry = entry->next, ++ii)
-									mesh->regionUVs[ii] = entry->valueFloat;
+									entry = Json_getItem(attachmentMap, "uvs");
+									verticesLength = entry->size;
+									mesh->regionUVs = MALLOC(float, verticesLength);
+									for (entry = entry->child, ii = 0; entry; entry = entry->next, ++ii)
+										mesh->regionUVs[ii] = entry->valueFloat;
 
 
-								_readVertices(self, attachmentMap, SUPER(mesh), verticesLength);
+									_readVertices(self, attachmentMap, SUPER(mesh), verticesLength);
 
 
-								if (mesh->region != NULL) spMeshAttachment_updateRegion(mesh);
+									if (mesh->region != NULL) spMeshAttachment_updateRegion(mesh);
 
 
-								mesh->hullLength = Json_getInt(attachmentMap, "hull", 0);
+									mesh->hullLength = Json_getInt(attachmentMap, "hull", 0);
 
 
-								entry = Json_getItem(attachmentMap, "edges");
-								if (entry) {
-									mesh->edgesCount = entry->size;
-									mesh->edges = MALLOC(int, entry->size);
-									for (entry = entry->child, ii = 0; entry; entry = entry->next, ++ii)
-										mesh->edges[ii] = entry->valueInt;
-								}
+									entry = Json_getItem(attachmentMap, "edges");
+									if (entry) {
+										mesh->edgesCount = entry->size;
+										mesh->edges = MALLOC(int, entry->size);
+										for (entry = entry->child, ii = 0; entry; entry = entry->next, ++ii)
+											mesh->edges[ii] = entry->valueInt;
+									}
 
 
-								spAttachmentLoader_configureAttachment(self->attachmentLoader, attachment);
-							} else {
-								int inheritTimelines = Json_getInt(attachmentMap, "timelines", 1);
-								_spSkeletonJson_addLinkedMesh(self, SUB_CAST(spMeshAttachment, attachment),
-															  Json_getString(attachmentMap, "skin", 0), slot->index,
-															  entry->valueString, inheritTimelines);
-							}
-							break;
-						}
-						case SP_ATTACHMENT_BOUNDING_BOX: {
-							spBoundingBoxAttachment *box = SUB_CAST(spBoundingBoxAttachment, attachment);
-							int vertexCount = Json_getInt(attachmentMap, "vertexCount", 0) << 1;
-							_readVertices(self, attachmentMap, SUPER(box), vertexCount);
-							box->super.verticesCount = vertexCount;
-							color = Json_getString(attachmentMap, "color", 0);
-							if (color) {
-								spColor_setFromFloats(&box->color,
-													  toColor(color, 0),
-													  toColor(color, 1),
-													  toColor(color, 2),
-													  toColor(color, 3));
+									spAttachmentLoader_configureAttachment(self->attachmentLoader, attachment);
+								} else {
+									int inheritTimelines = Json_getInt(attachmentMap, "timelines", 1);
+									_spSkeletonJson_addLinkedMesh(self, SUB_CAST(spMeshAttachment, attachment),
+																  Json_getString(attachmentMap, "skin", 0), slot->index,
+																  entry->valueString, inheritTimelines);
+								}
+								break;
 							}
 							}
-							spAttachmentLoader_configureAttachment(self->attachmentLoader, attachment);
-							break;
-						}
-						case SP_ATTACHMENT_PATH: {
-							spPathAttachment *pathAttachment = SUB_CAST(spPathAttachment, attachment);
-							int vertexCount = 0;
-							pathAttachment->closed = Json_getInt(attachmentMap, "closed", 0);
-							pathAttachment->constantSpeed = Json_getInt(attachmentMap, "constantSpeed", 1);
-							vertexCount = Json_getInt(attachmentMap, "vertexCount", 0);
-							_readVertices(self, attachmentMap, SUPER(pathAttachment), vertexCount << 1);
-
-							pathAttachment->lengthsLength = vertexCount / 3;
-							pathAttachment->lengths = MALLOC(float, pathAttachment->lengthsLength);
-
-							curves = Json_getItem(attachmentMap, "lengths");
-							for (curves = curves->child, ii = 0; curves; curves = curves->next, ++ii)
-								pathAttachment->lengths[ii] = curves->valueFloat * self->scale;
-							color = Json_getString(attachmentMap, "color", 0);
-							if (color) {
-								spColor_setFromFloats(&pathAttachment->color,
-													  toColor(color, 0),
-													  toColor(color, 1),
-													  toColor(color, 2),
-													  toColor(color, 3));
+							case SP_ATTACHMENT_BOUNDING_BOX: {
+								spBoundingBoxAttachment *box = SUB_CAST(spBoundingBoxAttachment, attachment);
+								int vertexCount = Json_getInt(attachmentMap, "vertexCount", 0) << 1;
+								_readVertices(self, attachmentMap, SUPER(box), vertexCount);
+								box->super.verticesCount = vertexCount;
+								color = Json_getString(attachmentMap, "color", 0);
+								if (color) {
+									spColor_setFromFloats(&box->color,
+														  toColor(color, 0),
+														  toColor(color, 1),
+														  toColor(color, 2),
+														  toColor(color, 3));
+								}
+								spAttachmentLoader_configureAttachment(self->attachmentLoader, attachment);
+								break;
 							}
 							}
-							break;
-						}
-						case SP_ATTACHMENT_POINT: {
-							spPointAttachment *point = SUB_CAST(spPointAttachment, attachment);
-							point->x = Json_getFloat(attachmentMap, "x", 0) * self->scale;
-							point->y = Json_getFloat(attachmentMap, "y", 0) * self->scale;
-							point->rotation = Json_getFloat(attachmentMap, "rotation", 0);
-
-							color = Json_getString(attachmentMap, "color", 0);
-							if (color) {
-								spColor_setFromFloats(&point->color,
-													  toColor(color, 0),
-													  toColor(color, 1),
-													  toColor(color, 2),
-													  toColor(color, 3));
+							case SP_ATTACHMENT_PATH: {
+								spPathAttachment *pathAttachment = SUB_CAST(spPathAttachment, attachment);
+								int vertexCount = 0;
+								pathAttachment->closed = Json_getInt(attachmentMap, "closed", 0);
+								pathAttachment->constantSpeed = Json_getInt(attachmentMap, "constantSpeed", 1);
+								vertexCount = Json_getInt(attachmentMap, "vertexCount", 0);
+								_readVertices(self, attachmentMap, SUPER(pathAttachment), vertexCount << 1);
+
+								pathAttachment->lengthsLength = vertexCount / 3;
+								pathAttachment->lengths = MALLOC(float, pathAttachment->lengthsLength);
+
+								curves = Json_getItem(attachmentMap, "lengths");
+								for (curves = curves->child, ii = 0; curves; curves = curves->next, ++ii)
+									pathAttachment->lengths[ii] = curves->valueFloat * self->scale;
+								color = Json_getString(attachmentMap, "color", 0);
+								if (color) {
+									spColor_setFromFloats(&pathAttachment->color,
+														  toColor(color, 0),
+														  toColor(color, 1),
+														  toColor(color, 2),
+														  toColor(color, 3));
+								}
+								break;
 							}
 							}
-							break;
-						}
-						case SP_ATTACHMENT_CLIPPING: {
-							spClippingAttachment *clip = SUB_CAST(spClippingAttachment, attachment);
-							int vertexCount = 0;
-							const char *end = Json_getString(attachmentMap, "end", 0);
-							if (end) {
-								spSlotData *endSlot = spSkeletonData_findSlot(skeletonData, end);
-								clip->endSlot = endSlot;
+							case SP_ATTACHMENT_POINT: {
+								spPointAttachment *point = SUB_CAST(spPointAttachment, attachment);
+								point->x = Json_getFloat(attachmentMap, "x", 0) * self->scale;
+								point->y = Json_getFloat(attachmentMap, "y", 0) * self->scale;
+								point->rotation = Json_getFloat(attachmentMap, "rotation", 0);
+
+								color = Json_getString(attachmentMap, "color", 0);
+								if (color) {
+									spColor_setFromFloats(&point->color,
+														  toColor(color, 0),
+														  toColor(color, 1),
+														  toColor(color, 2),
+														  toColor(color, 3));
+								}
+								break;
 							}
 							}
-							vertexCount = Json_getInt(attachmentMap, "vertexCount", 0) << 1;
-							_readVertices(self, attachmentMap, SUPER(clip), vertexCount);
-							color = Json_getString(attachmentMap, "color", 0);
-							if (color) {
-								spColor_setFromFloats(&clip->color,
-													  toColor(color, 0),
-													  toColor(color, 1),
-													  toColor(color, 2),
-													  toColor(color, 3));
+							case SP_ATTACHMENT_CLIPPING: {
+								spClippingAttachment *clip = SUB_CAST(spClippingAttachment, attachment);
+								int vertexCount = 0;
+								const char *end = Json_getString(attachmentMap, "end", 0);
+								if (end) {
+									spSlotData *endSlot = spSkeletonData_findSlot(skeletonData, end);
+									clip->endSlot = endSlot;
+								}
+								vertexCount = Json_getInt(attachmentMap, "vertexCount", 0) << 1;
+								_readVertices(self, attachmentMap, SUPER(clip), vertexCount);
+								color = Json_getString(attachmentMap, "color", 0);
+								if (color) {
+									spColor_setFromFloats(&clip->color,
+														  toColor(color, 0),
+														  toColor(color, 1),
+														  toColor(color, 2),
+														  toColor(color, 3));
+								}
+								spAttachmentLoader_configureAttachment(self->attachmentLoader, attachment);
+								break;
 							}
 							}
-							spAttachmentLoader_configureAttachment(self->attachmentLoader, attachment);
-							break;
 						}
 						}
-					}
 
 
-					spSkin_setAttachment(skin, slot->index, skinAttachmentName, attachment);
+						spSkin_setAttachment(skin, slot->index, skinAttachmentName, attachment);
+					}
 				}
 				}
 			}
 			}
 		}
 		}

+ 15 - 15
spine-cocos2dx/spine-cocos2dx/src/spine/SkeletonRenderer.cpp

@@ -269,7 +269,7 @@ namespace spine {
 		Color darkColor;
 		Color darkColor;
 		const float darkPremultipliedAlpha = _premultipliedAlpha ? 1.f : 0;
 		const float darkPremultipliedAlpha = _premultipliedAlpha ? 1.f : 0;
 		TwoColorTrianglesCommand *lastTwoColorTrianglesCommand = nullptr;
 		TwoColorTrianglesCommand *lastTwoColorTrianglesCommand = nullptr;
-		for (int i = 0, n = _skeleton->getSlots().size(); i < n; ++i) {
+		for (int i = 0, n = (int)_skeleton->getSlots().size(); i < n; ++i) {
 			Slot *slot = _skeleton->getDrawOrder()[i];
 			Slot *slot = _skeleton->getDrawOrder()[i];
 
 
 			if (nothingToDraw(*slot, _startSlotIndex, _endSlotIndex)) {
 			if (nothingToDraw(*slot, _startSlotIndex, _endSlotIndex)) {
@@ -284,7 +284,7 @@ namespace spine {
 
 
 			if (slot->getAttachment()->getRTTI().isExactly(RegionAttachment::rtti)) {
 			if (slot->getAttachment()->getRTTI().isExactly(RegionAttachment::rtti)) {
 				RegionAttachment *attachment = static_cast<RegionAttachment *>(slot->getAttachment());
 				RegionAttachment *attachment = static_cast<RegionAttachment *>(slot->getAttachment());
-                texture = (Texture2D*)((AtlasRegion*)attachment->getRegion())->page->getRendererObject();
+				texture = (Texture2D*)((AtlasRegion*)attachment->getRegion())->page->texture;
 
 
 				float *dstTriangleVertices = nullptr;
 				float *dstTriangleVertices = nullptr;
 				int dstStride = 0;// in floats
 				int dstStride = 0;// in floats
@@ -322,7 +322,7 @@ namespace spine {
 				color = attachment->getColor();
 				color = attachment->getColor();
 			} else if (slot->getAttachment()->getRTTI().isExactly(MeshAttachment::rtti)) {
 			} else if (slot->getAttachment()->getRTTI().isExactly(MeshAttachment::rtti)) {
 				MeshAttachment *attachment = (MeshAttachment *) slot->getAttachment();
 				MeshAttachment *attachment = (MeshAttachment *) slot->getAttachment();
-                texture = (Texture2D*)((AtlasRegion*)attachment->getRegion())->page->getRendererObject();
+				texture = (Texture2D*)((AtlasRegion*)attachment->getRegion())->page->texture;
 
 
 				float *dstTriangleVertices = nullptr;
 				float *dstTriangleVertices = nullptr;
 				int dstStride = 0;// in floats
 				int dstStride = 0;// in floats
@@ -330,8 +330,8 @@ namespace spine {
 				if (hasSingleTint) {
 				if (hasSingleTint) {
 					triangles.indices = attachment->getTriangles().buffer();
 					triangles.indices = attachment->getTriangles().buffer();
 					triangles.indexCount = (unsigned short)attachment->getTriangles().size();
 					triangles.indexCount = (unsigned short)attachment->getTriangles().size();
-					triangles.verts = batch->allocateVertices(attachment->getWorldVerticesLength() / 2);
-					triangles.vertCount = attachment->getWorldVerticesLength() / 2;
+					triangles.verts = batch->allocateVertices((int)attachment->getWorldVerticesLength() / 2);
+					triangles.vertCount = (int)attachment->getWorldVerticesLength() / 2;
                     for (int v = 0, i = 0; v < triangles.vertCount; v++, i += 2) {
                     for (int v = 0, i = 0; v < triangles.vertCount; v++, i += 2) {
                         auto &texCoords = triangles.verts[v].texCoords;
                         auto &texCoords = triangles.verts[v].texCoords;
                         texCoords.u = attachment->getUVs()[i];
                         texCoords.u = attachment->getUVs()[i];
@@ -343,8 +343,8 @@ namespace spine {
 				} else {
 				} else {
 					trianglesTwoColor.indices = attachment->getTriangles().buffer();
 					trianglesTwoColor.indices = attachment->getTriangles().buffer();
 					trianglesTwoColor.indexCount = (unsigned short)attachment->getTriangles().size();
 					trianglesTwoColor.indexCount = (unsigned short)attachment->getTriangles().size();
-					trianglesTwoColor.verts = twoColorBatch->allocateVertices(attachment->getWorldVerticesLength() / 2);
-					trianglesTwoColor.vertCount = attachment->getWorldVerticesLength() / 2;
+					trianglesTwoColor.verts = twoColorBatch->allocateVertices((int)attachment->getWorldVerticesLength() / 2);
+					trianglesTwoColor.vertCount = (int)attachment->getWorldVerticesLength() / 2;
                     for (int v = 0, i = 0; v < trianglesTwoColor.vertCount; v++, i += 2) {
                     for (int v = 0, i = 0; v < trianglesTwoColor.vertCount; v++, i += 2) {
                         auto &texCoords = trianglesTwoColor.verts[v].texCoords;
                         auto &texCoords = trianglesTwoColor.verts[v].texCoords;
                         texCoords.u = attachment->getUVs()[i];
                         texCoords.u = attachment->getUVs()[i];
@@ -408,9 +408,9 @@ namespace spine {
 						continue;
 						continue;
 					}
 					}
 
 
-					triangles.vertCount = _clipper->getClippedVertices().size() / 2;
+					triangles.vertCount = (int)_clipper->getClippedVertices().size() / 2;
 					triangles.verts = batch->allocateVertices(triangles.vertCount);
 					triangles.verts = batch->allocateVertices(triangles.vertCount);
-					triangles.indexCount = _clipper->getClippedTriangles().size();
+					triangles.indexCount = (int)_clipper->getClippedTriangles().size();
 					triangles.indices = batch->allocateIndices(triangles.indexCount);
 					triangles.indices = batch->allocateIndices(triangles.indexCount);
 					memcpy(triangles.indices, _clipper->getClippedTriangles().buffer(), sizeof(unsigned short) * _clipper->getClippedTriangles().size());
 					memcpy(triangles.indices, _clipper->getClippedTriangles().buffer(), sizeof(unsigned short) * _clipper->getClippedTriangles().size());
 
 
@@ -454,9 +454,9 @@ namespace spine {
 						continue;
 						continue;
 					}
 					}
 
 
-					trianglesTwoColor.vertCount = _clipper->getClippedVertices().size() / 2;
+					trianglesTwoColor.vertCount = (int)_clipper->getClippedVertices().size() / 2;
 					trianglesTwoColor.verts = twoColorBatch->allocateVertices(trianglesTwoColor.vertCount);
 					trianglesTwoColor.verts = twoColorBatch->allocateVertices(trianglesTwoColor.vertCount);
-					trianglesTwoColor.indexCount = _clipper->getClippedTriangles().size();
+					trianglesTwoColor.indexCount = (int)_clipper->getClippedTriangles().size();
 					trianglesTwoColor.indices = twoColorBatch->allocateIndices(trianglesTwoColor.indexCount);
 					trianglesTwoColor.indices = twoColorBatch->allocateIndices(trianglesTwoColor.indexCount);
 					memcpy(trianglesTwoColor.indices, _clipper->getClippedTriangles().buffer(), sizeof(unsigned short) * _clipper->getClippedTriangles().size());
 					memcpy(trianglesTwoColor.indices, _clipper->getClippedTriangles().buffer(), sizeof(unsigned short) * _clipper->getClippedTriangles().size());
 
 
@@ -576,7 +576,7 @@ namespace spine {
 			drawNode->setLineWidth(2.0f);
 			drawNode->setLineWidth(2.0f);
 #endif
 #endif
 			V3F_C4B_T2F_Quad quad;
 			V3F_C4B_T2F_Quad quad;
-			for (int i = 0, n = _skeleton->getSlots().size(); i < n; i++) {
+			for (int i = 0, n = (int)_skeleton->getSlots().size(); i < n; i++) {
 				Slot *slot = _skeleton->getDrawOrder()[i];
 				Slot *slot = _skeleton->getDrawOrder()[i];
 
 
 				if (!slot->getBone().isActive()) continue;
 				if (!slot->getBone().isActive()) continue;
@@ -606,7 +606,7 @@ namespace spine {
 #else
 #else
 			drawNode->setLineWidth(2.0f);
 			drawNode->setLineWidth(2.0f);
 #endif
 #endif
-			for (int i = 0, n = _skeleton->getBones().size(); i < n; i++) {
+			for (int i = 0, n = (int)_skeleton->getBones().size(); i < n; i++) {
 				Bone *bone = _skeleton->getBones()[i];
 				Bone *bone = _skeleton->getBones()[i];
 				if (!bone->isActive()) continue;
 				if (!bone->isActive()) continue;
 				float x = bone->getData().getLength() * bone->getA() + bone->getWorldX();
 				float x = bone->getData().getLength() * bone->getA() + bone->getWorldX();
@@ -615,7 +615,7 @@ namespace spine {
 			}
 			}
 			// Bone origins.
 			// Bone origins.
 			auto color = Color4F::BLUE;// Root bone is blue.
 			auto color = Color4F::BLUE;// Root bone is blue.
-			for (int i = 0, n = _skeleton->getBones().size(); i < n; i++) {
+			for (int i = 0, n = (int)_skeleton->getBones().size(); i < n; i++) {
 				Bone *bone = _skeleton->getBones()[i];
 				Bone *bone = _skeleton->getBones()[i];
 				if (!bone->isActive()) continue;
 				if (!bone->isActive()) continue;
 				drawNode->drawPoint(Vec2(bone->getWorldX(), bone->getWorldY()), 4, color);
 				drawNode->drawPoint(Vec2(bone->getWorldX(), bone->getWorldY()), 4, color);
@@ -630,7 +630,7 @@ namespace spine {
 #else
 #else
 			drawNode->setLineWidth(2.0f);
 			drawNode->setLineWidth(2.0f);
 #endif
 #endif
-			for (int i = 0, n = _skeleton->getSlots().size(); i < n; ++i) {
+			for (int i = 0, n = (int)_skeleton->getSlots().size(); i < n; ++i) {
 				Slot *slot = _skeleton->getDrawOrder()[i];
 				Slot *slot = _skeleton->getDrawOrder()[i];
 				if (!slot->getBone().isActive()) continue;
 				if (!slot->getBone().isActive()) continue;
 				if (!slot->getAttachment() || !slot->getAttachment()->getRTTI().isExactly(MeshAttachment::rtti)) continue;
 				if (!slot->getAttachment() || !slot->getAttachment()->getRTTI().isExactly(MeshAttachment::rtti)) continue;

+ 1 - 1
spine-cocos2dx/spine-cocos2dx/src/spine/spine-cocos2dx.cpp

@@ -114,7 +114,7 @@ void Cocos2dTextureLoader::load(AtlasPage &page, const spine::String &path) {
 #endif
 #endif
 		texture->setTexParameters(textureParams);
 		texture->setTexParameters(textureParams);
 
 
-		page.setRendererObject(texture);
+		page.texture = texture;
 		page.width = texture->getPixelsWide();
 		page.width = texture->getPixelsWide();
 		page.height = texture->getPixelsHigh();
 		page.height = texture->getPixelsHigh();
 	}
 	}

+ 3 - 3
spine-cocos2dx/spine-cocos2dx/src/spine/v4/SkeletonBatch.cpp

@@ -132,7 +132,7 @@ namespace spine {
 	unsigned short *SkeletonBatch::allocateIndices(uint32_t numIndices) {
 	unsigned short *SkeletonBatch::allocateIndices(uint32_t numIndices) {
 		if (_indices.getCapacity() - _indices.size() < numIndices) {
 		if (_indices.getCapacity() - _indices.size() < numIndices) {
 			unsigned short *oldData = _indices.buffer();
 			unsigned short *oldData = _indices.buffer();
-			int oldSize = _indices.size();
+			int oldSize = (int)_indices.size();
 			_indices.ensureCapacity(_indices.size() + numIndices);
 			_indices.ensureCapacity(_indices.size() + numIndices);
 			unsigned short *newData = _indices.buffer();
 			unsigned short *newData = _indices.buffer();
 			for (uint32_t i = 0; i < this->_nextFreeCommand; i++) {
 			for (uint32_t i = 0; i < this->_nextFreeCommand; i++) {
@@ -187,8 +187,8 @@ namespace spine {
 
 
 	cocos2d::TrianglesCommand *SkeletonBatch::nextFreeCommand() {
 	cocos2d::TrianglesCommand *SkeletonBatch::nextFreeCommand() {
 		if (_commandsPool.size() <= _nextFreeCommand) {
 		if (_commandsPool.size() <= _nextFreeCommand) {
-			unsigned int newSize = _commandsPool.size() * 2 + 1;
-			for (int i = _commandsPool.size(); i < newSize; i++) {
+			unsigned int newSize = (int)_commandsPool.size() * 2 + 1;
+			for (int i = (int)_commandsPool.size(); i < newSize; i++) {
 				_commandsPool.push_back(createNewTrianglesCommand());
 				_commandsPool.push_back(createNewTrianglesCommand());
 			}
 			}
 		}
 		}

+ 3 - 3
spine-cocos2dx/spine-cocos2dx/src/spine/v4/SkeletonTwoColorBatch.cpp

@@ -321,7 +321,7 @@ namespace spine {
 	unsigned short *SkeletonTwoColorBatch::allocateIndices(uint32_t numIndices) {
 	unsigned short *SkeletonTwoColorBatch::allocateIndices(uint32_t numIndices) {
 		if (_indices.getCapacity() - _indices.size() < numIndices) {
 		if (_indices.getCapacity() - _indices.size() < numIndices) {
 			unsigned short *oldData = _indices.buffer();
 			unsigned short *oldData = _indices.buffer();
-			int oldSize = _indices.size();
+			int oldSize = (int)_indices.size();
 			_indices.ensureCapacity(_indices.size() + numIndices);
 			_indices.ensureCapacity(_indices.size() + numIndices);
 			unsigned short *newData = _indices.buffer();
 			unsigned short *newData = _indices.buffer();
 			for (uint32_t i = 0; i < this->_nextFreeCommand; i++) {
 			for (uint32_t i = 0; i < this->_nextFreeCommand; i++) {
@@ -406,8 +406,8 @@ namespace spine {
 
 
 	TwoColorTrianglesCommand *SkeletonTwoColorBatch::nextFreeCommand() {
 	TwoColorTrianglesCommand *SkeletonTwoColorBatch::nextFreeCommand() {
 		if (_commandsPool.size() <= _nextFreeCommand) {
 		if (_commandsPool.size() <= _nextFreeCommand) {
-			unsigned int newSize = _commandsPool.size() * 2 + 1;
-			for (int i = _commandsPool.size(); i < newSize; i++) {
+			unsigned int newSize = (int)_commandsPool.size() * 2 + 1;
+			for (int i = (int)_commandsPool.size(); i < newSize; i++) {
 				_commandsPool.push_back(new TwoColorTrianglesCommand());
 				_commandsPool.push_back(new TwoColorTrianglesCommand());
 			}
 			}
 		}
 		}

+ 11 - 4
spine-cpp/spine-cpp/include/spine/AnimationState.h

@@ -45,7 +45,7 @@
 
 
 namespace spine {
 namespace spine {
 	enum EventType {
 	enum EventType {
-		EventType_Start,
+		EventType_Start = 0,
 		EventType_Interrupt,
 		EventType_Interrupt,
 		EventType_End,
 		EventType_End,
 		EventType_Complete,
 		EventType_Complete,
@@ -311,14 +311,13 @@ namespace spine {
 	private:
 	private:
 		Vector<EventQueueEntry> _eventQueueEntries;
 		Vector<EventQueueEntry> _eventQueueEntries;
 		AnimationState &_state;
 		AnimationState &_state;
-		Pool<TrackEntry> &_trackEntryPool;
 		bool _drainDisabled;
 		bool _drainDisabled;
 
 
-		static EventQueue *newEventQueue(AnimationState &state, Pool<TrackEntry> &trackEntryPool);
+		static EventQueue *newEventQueue(AnimationState &state);
 
 
 		static EventQueueEntry newEventQueueEntry(EventType eventType, TrackEntry *entry, Event *event = NULL);
 		static EventQueueEntry newEventQueueEntry(EventType eventType, TrackEntry *entry, Event *event = NULL);
 
 
-		EventQueue(AnimationState &state, Pool<TrackEntry> &trackEntryPool);
+		EventQueue(AnimationState &state);
 
 
 		~EventQueue();
 		~EventQueue();
 
 
@@ -429,6 +428,12 @@ namespace spine {
 
 
 		void enableQueue();
 		void enableQueue();
 
 
+		void setManualTrackEntryDisposal(bool inValue);
+
+        bool getManualTrackEntryDisposal();
+
+		void disposeTrackEntry(TrackEntry *entry);
+
 	private:
 	private:
 		static const int Subsequent = 0;
 		static const int Subsequent = 0;
 		static const int First = 1;
 		static const int First = 1;
@@ -456,6 +461,8 @@ namespace spine {
 
 
 		float _timeScale;
 		float _timeScale;
 
 
+		bool _manualTrackEntryDisposal;
+
 		static Animation *getEmptyAnimation();
 		static Animation *getEmptyAnimation();
 
 
 		static void
 		static void

+ 4 - 2
spine-cpp/spine-cpp/include/spine/Atlas.h

@@ -73,7 +73,7 @@ namespace spine {
 		TextureWrap_Repeat
 		TextureWrap_Repeat
 	};
 	};
 
 
-	class SP_API AtlasPage : public SpineObject, public HasRendererObject {
+	class SP_API AtlasPage : public SpineObject {
 	public:
 	public:
 		String name;
 		String name;
 		String texturePath;
 		String texturePath;
@@ -84,11 +84,13 @@ namespace spine {
 		TextureWrap vWrap;
 		TextureWrap vWrap;
 		int width, height;
 		int width, height;
 		bool pma;
 		bool pma;
+        int index;
+        void *texture;
 
 
 		explicit AtlasPage(const String &inName) : name(inName), format(Format_RGBA8888),
 		explicit AtlasPage(const String &inName) : name(inName), format(Format_RGBA8888),
 												   minFilter(TextureFilter_Nearest),
 												   minFilter(TextureFilter_Nearest),
 												   magFilter(TextureFilter_Nearest), uWrap(TextureWrap_ClampToEdge),
 												   magFilter(TextureFilter_Nearest), uWrap(TextureWrap_ClampToEdge),
-												   vWrap(TextureWrap_ClampToEdge), width(0), height(0), pma(false) {
+												   vWrap(TextureWrap_ClampToEdge), width(0), height(0), pma(false), index(0), texture(NULL) {
 		}
 		}
 	};
 	};
 
 

+ 6 - 6
spine-cpp/spine-cpp/include/spine/Bone.h

@@ -113,6 +113,12 @@ namespace spine {
 		void
 		void
 		updateWorldTransform(float x, float y, float rotation, float scaleX, float scaleY, float shearX, float shearY);
 		updateWorldTransform(float x, float y, float rotation, float scaleX, float scaleY, float shearX, float shearY);
 
 
+        /// Computes the individual applied transform values from the world transform. This can be useful to perform processing using
+		/// the applied transform after the world transform has been modified directly (eg, by a constraint)..
+		///
+		/// Some information is ambiguous in the world transform, such as -1,-1 scale versus 180 rotation.
+		void updateAppliedTransform();
+
 		void setToSetupPose();
 		void setToSetupPose();
 
 
 		void worldToLocal(float worldX, float worldY, float &outLocalX, float &outLocalY);
 		void worldToLocal(float worldX, float worldY, float &outLocalX, float &outLocalY);
@@ -260,12 +266,6 @@ namespace spine {
 		float _c, _d, _worldY;
 		float _c, _d, _worldY;
 		bool _sorted;
 		bool _sorted;
 		bool _active;
 		bool _active;
-
-		/// Computes the individual applied transform values from the world transform. This can be useful to perform processing using
-		/// the applied transform after the world transform has been modified directly (eg, by a constraint)..
-		///
-		/// Some information is ambiguous in the world transform, such as -1,-1 scale versus 180 rotation.
-		void updateAppliedTransform();
 	};
 	};
 }
 }
 
 

+ 3 - 1
spine-cpp/spine-cpp/include/spine/ConstraintData.h

@@ -34,9 +34,11 @@
 #include <spine/SpineString.h>
 #include <spine/SpineString.h>
 
 
 namespace spine {
 namespace spine {
-/// The interface for all constraints.
+	/// The interface for all constraints.
 	class SP_API ConstraintData : public SpineObject {
 	class SP_API ConstraintData : public SpineObject {
 
 
+	RTTI_DECL
+
 	public:
 	public:
 		ConstraintData(const String &name);
 		ConstraintData(const String &name);
 
 

+ 1 - 1
spine-cpp/spine-cpp/include/spine/Debug.h

@@ -62,7 +62,7 @@ namespace spine {
 					   it->second.address);
 					   it->second.address);
 			}
 			}
 			printf("allocations: %zu, reallocations: %zu, frees: %zu\n", _allocations, _reallocations, _frees);
 			printf("allocations: %zu, reallocations: %zu, frees: %zu\n", _allocations, _reallocations, _frees);
-			if (_allocated.empty()) printf("No leaks detected");
+			if (_allocated.empty()) printf("No leaks detected\n");
 		}
 		}
 
 
 		void clearAllocations() {
 		void clearAllocations() {

+ 0 - 3
spine-cpp/spine-cpp/include/spine/IkConstraint.h

@@ -64,9 +64,6 @@ namespace spine {
 
 
 		IkConstraint(IkConstraintData &data, Skeleton &skeleton);
 		IkConstraint(IkConstraintData &data, Skeleton &skeleton);
 
 
-		/// Applies the constraint to the constrained bones.
-		void apply();
-
 		virtual void update();
 		virtual void update();
 
 
 		virtual int getOrder();
 		virtual int getOrder();

+ 2 - 0
spine-cpp/spine-cpp/include/spine/IkConstraintData.h

@@ -50,6 +50,8 @@ namespace spine {
 		friend class IkConstraintTimeline;
 		friend class IkConstraintTimeline;
 
 
 	public:
 	public:
+		RTTI_DECL
+
 		explicit IkConstraintData(const String &name);
 		explicit IkConstraintData(const String &name);
 
 
 		/// The bones that are constrained by this IK Constraint.
 		/// The bones that are constrained by this IK Constraint.

+ 3 - 0
spine-cpp/spine-cpp/include/spine/MathUtil.h

@@ -33,6 +33,9 @@
 #include <spine/SpineObject.h>
 #include <spine/SpineObject.h>
 
 
 #include <string.h>
 #include <string.h>
+// Needed for older MSVC versions
+#undef min
+#undef max
 
 
 namespace spine {
 namespace spine {
 
 

+ 1 - 1
spine-cpp/spine-cpp/include/spine/MeshAttachment.h

@@ -39,7 +39,7 @@
 
 
 namespace spine {
 namespace spine {
 	/// Attachment that displays a texture region using a mesh.
 	/// Attachment that displays a texture region using a mesh.
-	class SP_API MeshAttachment : public VertexAttachment, public HasRendererObject {
+	class SP_API MeshAttachment : public VertexAttachment {
 		friend class SkeletonBinary;
 		friend class SkeletonBinary;
 
 
 		friend class SkeletonJson;
 		friend class SkeletonJson;

+ 8 - 11
spine-cpp/spine-cpp/include/spine/PathConstraint.h

@@ -59,13 +59,18 @@ namespace spine {
 	public:
 	public:
 		PathConstraint(PathConstraintData &data, Skeleton &skeleton);
 		PathConstraint(PathConstraintData &data, Skeleton &skeleton);
 
 
-		/// Applies the constraint to the constrained bones.
-		void apply();
-
 		virtual void update();
 		virtual void update();
 
 
 		virtual int getOrder();
 		virtual int getOrder();
 
 
+        PathConstraintData &getData();
+
+        Vector<Bone *> &getBones();
+
+        Slot *getTarget();
+
+        void setTarget(Slot *inValue);
+
 		float getPosition();
 		float getPosition();
 
 
 		void setPosition(float inValue);
 		void setPosition(float inValue);
@@ -86,14 +91,6 @@ namespace spine {
 
 
 		void setMixY(float inValue);
 		void setMixY(float inValue);
 
 
-		Vector<Bone *> &getBones();
-
-		Slot *getTarget();
-
-		void setTarget(Slot *inValue);
-
-		PathConstraintData &getData();
-
 		bool isActive();
 		bool isActive();
 
 
 		void setActive(bool inValue);
 		void setActive(bool inValue);

+ 2 - 1
spine-cpp/spine-cpp/include/spine/PathConstraintData.h

@@ -57,8 +57,9 @@ namespace spine {
 		friend class PathConstraintPositionTimeline;
 		friend class PathConstraintPositionTimeline;
 
 
 		friend class PathConstraintSpacingTimeline;
 		friend class PathConstraintSpacingTimeline;
-
 	public:
 	public:
+		RTTI_DECL
+
 		explicit PathConstraintData(const String &name);
 		explicit PathConstraintData(const String &name);
 
 
 		Vector<BoneData *> &getBones();
 		Vector<BoneData *> &getBones();

+ 2 - 2
spine-cpp/spine-cpp/include/spine/RegionAttachment.h

@@ -44,7 +44,7 @@ namespace spine {
 	class Bone;
 	class Bone;
 
 
 	/// Attachment that displays a texture region.
 	/// Attachment that displays a texture region.
-	class SP_API RegionAttachment : public Attachment, public HasRendererObject {
+	class SP_API RegionAttachment : public Attachment {
 		friend class SkeletonBinary;
 		friend class SkeletonBinary;
 
 
 		friend class SkeletonJson;
 		friend class SkeletonJson;
@@ -61,7 +61,7 @@ namespace spine {
 		void updateRegion();
 		void updateRegion();
 
 
 		/// Transforms the attachment's four vertices to world coordinates.
 		/// Transforms the attachment's four vertices to world coordinates.
-		/// @param bone The parent bone.
+		/// @param slot The parent slot.
 		/// @param worldVertices The output world vertices. Must have a length greater than or equal to offset + 8.
 		/// @param worldVertices The output world vertices. Must have a length greater than or equal to offset + 8.
 		/// @param offset The worldVertices index to begin writing values.
 		/// @param offset The worldVertices index to begin writing values.
 		/// @param stride The number of worldVertices entries between the value pairs written.
 		/// @param stride The number of worldVertices entries between the value pairs written.

+ 1 - 1
spine-cpp/spine-cpp/include/spine/SkeletonBinary.h

@@ -147,7 +147,7 @@ namespace spine {
 		Attachment *readAttachment(DataInput *input, Skin *skin, int slotIndex, const String &attachmentName,
 		Attachment *readAttachment(DataInput *input, Skin *skin, int slotIndex, const String &attachmentName,
 								   SkeletonData *skeletonData, bool nonessential);
 								   SkeletonData *skeletonData, bool nonessential);
 
 
-		void readVertices(DataInput *input, Vector<float> &vertices, Vector<size_t> &bones, int vertexCount);
+		void readVertices(DataInput *input, Vector<float> &vertices, Vector<int> &bones, int vertexCount);
 
 
 		void readFloatArray(DataInput *input, int n, float scale, Vector<float> &array);
 		void readFloatArray(DataInput *input, int n, float scale, Vector<float> &array);
 
 

+ 11 - 0
spine-cpp/spine-cpp/include/spine/SkeletonBounds.h

@@ -81,8 +81,19 @@ namespace spine {
 		/// Returns true if the polygon contains the line segment.
 		/// Returns true if the polygon contains the line segment.
 		bool intersectsSegment(Polygon *polygon, float x1, float y1, float x2, float y2);
 		bool intersectsSegment(Polygon *polygon, float x1, float y1, float x2, float y2);
 
 
+        /// Returns the polygon for the given bounding box attachment or null if no
+        /// polygon can be found for the attachment. Requires a call to update() first.
 		Polygon *getPolygon(BoundingBoxAttachment *attachment);
 		Polygon *getPolygon(BoundingBoxAttachment *attachment);
 
 
+        /// Returns the bounding box for the given polygon or null. Requires a call to update() first.
+        BoundingBoxAttachment * getBoundingBox(Polygon *polygon);
+
+        /// Returns all polygons or an empty vector. Requires a call to update() first.
+        Vector<Polygon *> &getPolygons();
+
+        /// Returns all bounding boxes. Requires a call to update() first.
+        Vector<BoundingBoxAttachment *> &getBoundingBoxes();
+
 		float getWidth();
 		float getWidth();
 
 
 		float getHeight();
 		float getHeight();

+ 2 - 7
spine-cpp/spine-cpp/include/spine/SpineString.h

@@ -36,11 +36,6 @@
 #include <string.h>
 #include <string.h>
 #include <stdio.h>
 #include <stdio.h>
 
 
-// Required for sprintf on MSVC
-#ifdef _MSC_VER
-#pragma warning(disable:4996)
-#endif
-
 namespace spine {
 namespace spine {
 	class SP_API String : public SpineObject {
 	class SP_API String : public SpineObject {
 	public:
 	public:
@@ -170,14 +165,14 @@ namespace spine {
 
 
 		String &append(int other) {
 		String &append(int other) {
 			char str[100];
 			char str[100];
-			sprintf(str, "%i", other);
+			snprintf(str, 100, "%i", other);
 			append(str);
 			append(str);
 			return *this;
 			return *this;
 		}
 		}
 
 
 		String &append(float other) {
 		String &append(float other) {
 			char str[100];
 			char str[100];
-			sprintf(str, "%f", other);
+			snprintf(str, 100, "%f", other);
 			append(str);
 			append(str);
 			return *this;
 			return *this;
 		}
 		}

+ 32 - 0
spine-cpp/spine-cpp/include/spine/TransformConstraintData.h

@@ -50,40 +50,72 @@ namespace spine {
 		friend class TransformConstraintTimeline;
 		friend class TransformConstraintTimeline;
 
 
 	public:
 	public:
+		RTTI_DECL
+
 		explicit TransformConstraintData(const String &name);
 		explicit TransformConstraintData(const String &name);
 
 
 		Vector<BoneData *> &getBones();
 		Vector<BoneData *> &getBones();
 
 
 		BoneData *getTarget();
 		BoneData *getTarget();
 
 
+        void setTarget(BoneData *target);
+
 		float getMixRotate();
 		float getMixRotate();
 
 
+        void setMixRotate(float mixRotate);
+
 		float getMixX();
 		float getMixX();
 
 
+        void setMixX(float mixX);
+
 		float getMixY();
 		float getMixY();
 
 
+        void setMixY(float mixY);
+
 		float getMixScaleX();
 		float getMixScaleX();
 
 
+        void setMixScaleX(float mixScaleX);
+
 		float getMixScaleY();
 		float getMixScaleY();
 
 
+        void setMixScaleY(float mixScaleY);
+
 		float getMixShearY();
 		float getMixShearY();
 
 
+        void setMixShearY(float mixShearY);
+
 		float getOffsetRotation();
 		float getOffsetRotation();
 
 
+        void setOffsetRotation(float offsetRotation);
+
 		float getOffsetX();
 		float getOffsetX();
 
 
+        void setOffsetX(float offsetX);
+
 		float getOffsetY();
 		float getOffsetY();
 
 
+        void setOffsetY(float offsetY);
+
 		float getOffsetScaleX();
 		float getOffsetScaleX();
 
 
+        void setOffsetScaleX(float offsetScaleX);
+
 		float getOffsetScaleY();
 		float getOffsetScaleY();
 
 
+        void setOffsetScaleY(float offsetScaleY);
+
 		float getOffsetShearY();
 		float getOffsetShearY();
 
 
+        void setOffsetShearY(float offsetShearY);
+
 		bool isRelative();
 		bool isRelative();
 
 
+        void setRelative(bool isRelative);
+
 		bool isLocal();
 		bool isLocal();
 
 
+        void setLocal(bool isLocal);
+
 	private:
 	private:
 		Vector<BoneData *> _bones;
 		Vector<BoneData *> _bones;
 		BoneData *_target;
 		BoneData *_target;

+ 2 - 2
spine-cpp/spine-cpp/include/spine/VertexAttachment.h

@@ -71,7 +71,7 @@ namespace spine {
 		/// Gets a unique ID for this attachment.
 		/// Gets a unique ID for this attachment.
 		int getId();
 		int getId();
 
 
-		Vector <size_t> &getBones();
+		Vector<int> &getBones();
 
 
 		Vector<float> &getVertices();
 		Vector<float> &getVertices();
 
 
@@ -86,7 +86,7 @@ namespace spine {
 		void copyTo(VertexAttachment *other);
 		void copyTo(VertexAttachment *other);
 
 
 	protected:
 	protected:
-		Vector <size_t> _bones;
+		Vector <int> _bones;
 		Vector<float> _vertices;
 		Vector<float> _vertices;
 		size_t _worldVerticesLength;
 		size_t _worldVerticesLength;
 		Attachment *_timelineAttachment;
 		Attachment *_timelineAttachment;

+ 1 - 1
spine-cpp/spine-cpp/include/spine/Vertices.h

@@ -35,7 +35,7 @@
 namespace spine {
 namespace spine {
 	class SP_API Vertices : public SpineObject {
 	class SP_API Vertices : public SpineObject {
 	public:
 	public:
-		Vector <size_t> _bones;
+		Vector <int> _bones;
 		Vector<float> _vertices;
 		Vector<float> _vertices;
 	};
 	};
 }
 }

+ 21 - 9
spine-cpp/spine-cpp/src/spine/AnimationState.cpp

@@ -211,17 +211,16 @@ EventQueueEntry::EventQueueEntry(EventType eventType, TrackEntry *trackEntry, Ev
 																							  _event(event) {
 																							  _event(event) {
 }
 }
 
 
-EventQueue *EventQueue::newEventQueue(AnimationState &state, Pool<TrackEntry> &trackEntryPool) {
-	return new (__FILE__, __LINE__) EventQueue(state, trackEntryPool);
+EventQueue *EventQueue::newEventQueue(AnimationState &state) {
+	return new (__FILE__, __LINE__) EventQueue(state);
 }
 }
 
 
 EventQueueEntry EventQueue::newEventQueueEntry(EventType eventType, TrackEntry *entry, Event *event) {
 EventQueueEntry EventQueue::newEventQueueEntry(EventType eventType, TrackEntry *entry, Event *event) {
 	return EventQueueEntry(eventType, entry, event);
 	return EventQueueEntry(eventType, entry, event);
 }
 }
 
 
-EventQueue::EventQueue(AnimationState &state, Pool<TrackEntry> &trackEntryPool) : _state(state),
-																				  _trackEntryPool(trackEntryPool),
-																				  _drainDisabled(false) {
+EventQueue::EventQueue(AnimationState &state) : _state(state),
+												_drainDisabled(false) {
 }
 }
 
 
 EventQueue::~EventQueue() {
 EventQueue::~EventQueue() {
@@ -295,8 +294,7 @@ void EventQueue::drain() {
 				else
 				else
 					state._listenerObject->callback(&state, EventType_Dispose, trackEntry, NULL);
 					state._listenerObject->callback(&state, EventType_Dispose, trackEntry, NULL);
 
 
-				trackEntry->reset();
-				_trackEntryPool.free(trackEntry);
+				if (!_state.getManualTrackEntryDisposal()) _state.disposeTrackEntry(trackEntry);
 				break;
 				break;
 			case EventType_Event:
 			case EventType_Event:
 				if (!trackEntry->_listenerObject)
 				if (!trackEntry->_listenerObject)
@@ -315,12 +313,13 @@ void EventQueue::drain() {
 }
 }
 
 
 AnimationState::AnimationState(AnimationStateData *data) : _data(data),
 AnimationState::AnimationState(AnimationStateData *data) : _data(data),
-														   _queue(EventQueue::newEventQueue(*this, _trackEntryPool)),
+														   _queue(EventQueue::newEventQueue(*this)),
 														   _animationsChanged(false),
 														   _animationsChanged(false),
 														   _listener(dummyOnAnimationEventFunc),
 														   _listener(dummyOnAnimationEventFunc),
 														   _listenerObject(NULL),
 														   _listenerObject(NULL),
 														   _unkeyedState(0),
 														   _unkeyedState(0),
-														   _timeScale(1) {
+														   _timeScale(1),
+														   _manualTrackEntryDisposal(false) {
 }
 }
 
 
 AnimationState::~AnimationState() {
 AnimationState::~AnimationState() {
@@ -666,6 +665,19 @@ void AnimationState::enableQueue() {
 	_queue->_drainDisabled = false;
 	_queue->_drainDisabled = false;
 }
 }
 
 
+void AnimationState::setManualTrackEntryDisposal(bool inValue) {
+	_manualTrackEntryDisposal = inValue;
+}
+
+bool AnimationState::getManualTrackEntryDisposal() {
+	return _manualTrackEntryDisposal;
+}
+
+void AnimationState::disposeTrackEntry(TrackEntry *entry) {
+	entry->reset();
+	_trackEntryPool.free(entry);
+}
+
 Animation *AnimationState::getEmptyAnimation() {
 Animation *AnimationState::getEmptyAnimation() {
 	static Vector<Timeline *> timelines;
 	static Vector<Timeline *> timelines;
 	static Animation ret(String("<empty>"), timelines, 0);
 	static Animation ret(String("<empty>"), timelines, 0);

+ 8 - 6
spine-cpp/spine-cpp/src/spine/Atlas.cpp

@@ -69,7 +69,7 @@ Atlas::Atlas(const char *data, int length, const char *dir, TextureLoader *textu
 Atlas::~Atlas() {
 Atlas::~Atlas() {
 	if (_textureLoader) {
 	if (_textureLoader) {
 		for (size_t i = 0, n = _pages.size(); i < n; ++i) {
 		for (size_t i = 0, n = _pages.size(); i < n; ++i) {
-			_textureLoader->unload(_pages[i]->getRendererObject());
+			_textureLoader->unload(_pages[i]->texture);
 		}
 		}
 	}
 	}
 	ContainerUtil::cleanUpVectorOfPointers(_pages);
 	ContainerUtil::cleanUpVectorOfPointers(_pages);
@@ -108,21 +108,21 @@ struct SimpleString {
 		while (isspace((unsigned char) *start) && start < end)
 		while (isspace((unsigned char) *start) && start < end)
 			start++;
 			start++;
 		if (start == end) {
 		if (start == end) {
-			length = end - start;
+			length = (int) (end - start);
 			return *this;
 			return *this;
 		}
 		}
 		end--;
 		end--;
 		while (((unsigned char) *end == '\r') && end >= start)
 		while (((unsigned char) *end == '\r') && end >= start)
 			end--;
 			end--;
 		end++;
 		end++;
-		length = end - start;
+		length = (int) (end - start);
 		return *this;
 		return *this;
 	}
 	}
 
 
 	int indexOf(char needle) {
 	int indexOf(char needle) {
 		char *c = start;
 		char *c = start;
 		while (c < end) {
 		while (c < end) {
-			if (*c == needle) return c - start;
+			if (*c == needle) return (int) (c - start);
 			c++;
 			c++;
 		}
 		}
 		return -1;
 		return -1;
@@ -131,7 +131,7 @@ struct SimpleString {
 	int indexOf(char needle, int at) {
 	int indexOf(char needle, int at) {
 		char *c = start + at;
 		char *c = start + at;
 		while (c < end) {
 		while (c < end) {
-			if (*c == needle) return c - start;
+			if (*c == needle) return (int) (c - start);
 			c++;
 			c++;
 		}
 		}
 		return -1;
 		return -1;
@@ -150,7 +150,7 @@ struct SimpleString {
 		SimpleString result;
 		SimpleString result;
 		result.start = start + s;
 		result.start = start + s;
 		result.end = end;
 		result.end = end;
-		result.length = result.end - result.start;
+		result.length = (int) (result.end - result.start);
 		return result;
 		return result;
 	}
 	}
 
 
@@ -286,10 +286,12 @@ void Atlas::load(const char *begin, int length, const char *dir, bool createText
 			} else {
 			} else {
 				page->texturePath = String(path, true);
 				page->texturePath = String(path, true);
 			}
 			}
+			page->index = (int) _pages.size();
 			_pages.add(page);
 			_pages.add(page);
 		} else {
 		} else {
 			AtlasRegion *region = new (__FILE__, __LINE__) AtlasRegion();
 			AtlasRegion *region = new (__FILE__, __LINE__) AtlasRegion();
 			region->page = page;
 			region->page = page;
+			region->rendererObject = page->texture;
 			region->name = String(line->copy(), true);
 			region->name = String(line->copy(), true);
 			while (true) {
 			while (true) {
 				line = reader.readLine();
 				line = reader.readLine();

+ 0 - 2
spine-cpp/spine-cpp/src/spine/AtlasAttachmentLoader.cpp

@@ -63,7 +63,6 @@ namespace spine {
 		} else {
 		} else {
 			AtlasRegion *region = findRegion(path);
 			AtlasRegion *region = findRegion(path);
 			if (!region) return NULL;
 			if (!region) return NULL;
-			attachment->setRendererObject(region);
 			attachment->setRegion(region);
 			attachment->setRegion(region);
 		}
 		}
 		return attachment;
 		return attachment;
@@ -78,7 +77,6 @@ namespace spine {
 		} else {
 		} else {
 			AtlasRegion *region = findRegion(path);
 			AtlasRegion *region = findRegion(path);
 			if (!region) return NULL;
 			if (!region) return NULL;
-			attachment->setRendererObject(region);
 			attachment->setRegion(region);
 			attachment->setRegion(region);
 		}
 		}
 		return attachment;
 		return attachment;

+ 67 - 26
spine-cpp/spine-cpp/src/spine/Bone.cpp

@@ -192,7 +192,6 @@ void Bone::updateWorldTransform(float x, float y, float rotation, float scaleX,
 			_b = za * lb + zb * ld;
 			_b = za * lb + zb * ld;
 			_c = zc * la + zd * lc;
 			_c = zc * la + zd * lc;
 			_d = zc * lb + zd * ld;
 			_d = zc * lb + zd * ld;
-			break;
 		}
 		}
 	}
 	}
 	_a *= _skeleton.getScaleX();
 	_a *= _skeleton.getScaleX();
@@ -496,33 +495,75 @@ void Bone::updateAppliedTransform() {
 		_ascaleY = MathUtil::sqrt(_b * _b + _d * _d);
 		_ascaleY = MathUtil::sqrt(_b * _b + _d * _d);
 		_ashearX = 0;
 		_ashearX = 0;
 		_ashearY = MathUtil::atan2(_a * _b + _c * _d, _a * _d - _b * _c) * MathUtil::Rad_Deg;
 		_ashearY = MathUtil::atan2(_a * _b + _c * _d, _a * _d - _b * _c) * MathUtil::Rad_Deg;
+	}
+	float pa = parent->_a, pb = parent->_b, pc = parent->_c, pd = parent->_d;
+	float pid = 1 / (pa * pd - pb * pc);
+	float ia = pd * pid, ib = pb * pid, ic = pc * pid, id = pa * pid;
+	float dx = _worldX - parent->_worldX, dy = _worldY - parent->_worldY;
+	_ax = (dx * ia - dy * ib);
+	_ay = (dy * id - dx * ic);
+
+	float ra, rb, rc, rd;
+	if (_data.getTransformMode() == TransformMode_OnlyTranslation) {
+		ra = _a;
+		rb = _b;
+		rc = _c;
+		rd = _d;
 	} else {
 	} else {
-		float pa = parent->_a, pb = parent->_b, pc = parent->_c, pd = parent->_d;
-		float pid = 1 / (pa * pd - pb * pc);
-		float dx = _worldX - parent->_worldX, dy = _worldY - parent->_worldY;
-		float ia = pid * pd;
-		float id = pid * pa;
-		float ib = pid * pb;
-		float ic = pid * pc;
-		float ra = ia * _a - ib * _c;
-		float rb = ia * _b - ib * _d;
-		float rc = id * _c - ic * _a;
-		float rd = id * _d - ic * _b;
-		_ax = (dx * pd * pid - dy * pb * pid);
-		_ay = (dy * pa * pid - dx * pc * pid);
-		_ashearX = 0;
-		_ascaleX = MathUtil::sqrt(ra * ra + rc * rc);
-		if (_ascaleX > 0.0001f) {
-			float det = ra * rd - rb * rc;
-			_ascaleY = det / _ascaleX;
-			_ashearY = MathUtil::atan2(ra * rb + rc * rd, det) * MathUtil::Rad_Deg;
-			_arotation = MathUtil::atan2(rc, ra) * MathUtil::Rad_Deg;
-		} else {
-			_ascaleX = 0;
-			_ascaleY = MathUtil::sqrt(rb * rb + rd * rd);
-			_ashearY = 0;
-			_arotation = 90 - MathUtil::atan2(rd, rb) * MathUtil::Rad_Deg;
+		switch (_data.getTransformMode()) {
+			case TransformMode_NoRotationOrReflection: {
+				float s = MathUtil::abs(pa * pd - pb * pc) / (pa * pa + pc * pc);
+				float sa = pa / _skeleton.getScaleX();
+				float sc = pc / _skeleton.getScaleY();
+				pb = -sc * s * _skeleton.getScaleX();
+				pd = sa * s * _skeleton.getScaleY();
+				pid = 1 / (pa * pd - pb * pc);
+				ia = pd * pid;
+				ib = pb * pid;
+				break;
+			}
+			case TransformMode_NoScale:
+			case TransformMode_NoScaleOrReflection: {
+				float cos = MathUtil::cosDeg(_rotation), sin = MathUtil::sinDeg(_rotation);
+				pa = (pa * cos + pb * sin) / _skeleton.getScaleX();
+				pc = (pc * cos + pd * sin) / _skeleton.getScaleY();
+				float s = MathUtil::sqrt(pa * pa + pc * pc);
+				if (s > 0.00001f) s = 1 / s;
+				pa *= s;
+				pc *= s;
+				s = MathUtil::sqrt(pa * pa + pc * pc);
+				if (_data.getTransformMode() == TransformMode_NoScale && pid < 0 != (_skeleton.getScaleX() < 0 != _skeleton.getScaleY() < 0)) s = -s;
+				float r = MathUtil::Pi / 2 + MathUtil::atan2(pc, pa);
+				pb = MathUtil::cos(r) * s;
+				pd = MathUtil::sin(r) * s;
+				pid = 1 / (pa * pd - pb * pc);
+				ia = pd * pid;
+				ib = pb * pid;
+				ic = pc * pid;
+				id = pa * pid;
+				break;
+			}
+			default:
+				break;
 		}
 		}
+		ra = ia * _a - ib * _c;
+		rb = ia * _b - ib * _d;
+		rc = id * _c - ic * _a;
+		rd = id * _d - ic * _b;
+	}
+
+	_ashearX = 0;
+	_ascaleX = MathUtil::sqrt(ra * ra + rc * rc);
+	if (_ascaleX > 0.0001f) {
+		float det = ra * rd - rb * rc;
+		_ascaleY = det / _ascaleX;
+		_ashearY = -MathUtil::atan2(ra * rb + rc * rd, det) * MathUtil::Rad_Deg;
+		_arotation = MathUtil::atan2(rc, ra) * MathUtil::Rad_Deg;
+	} else {
+		_ascaleX = 0;
+		_ascaleY = MathUtil::sqrt(rb * rb + rd * rd);
+		_ashearY = 0;
+		_arotation = 90 - MathUtil::atan2(rd, rb) * MathUtil::Rad_Deg;
 	}
 	}
 }
 }
 
 

+ 2 - 0
spine-cpp/spine-cpp/src/spine/ConstraintData.cpp

@@ -31,6 +31,8 @@
 
 
 using namespace spine;
 using namespace spine;
 
 
+RTTI_IMPL_NOPARENT(ConstraintData)
+
 ConstraintData::ConstraintData(const String &name) : _name(name), _order(0), _skinRequired(false) {
 ConstraintData::ConstraintData(const String &name) : _name(name), _order(0), _skinRequired(false) {
 }
 }
 
 

+ 4 - 0
spine-cpp/spine-cpp/src/spine/Extension.cpp

@@ -104,6 +104,7 @@ void DefaultSpineExtension::_free(void *mem, const char *file, int line) {
 }
 }
 
 
 char *DefaultSpineExtension::_readFile(const String &path, int *length) {
 char *DefaultSpineExtension::_readFile(const String &path, int *length) {
+#ifndef __EMSCRIPTEN__
 	char *data;
 	char *data;
 	FILE *file = fopen(path.buffer(), "rb");
 	FILE *file = fopen(path.buffer(), "rb");
 	if (!file) return 0;
 	if (!file) return 0;
@@ -117,6 +118,9 @@ char *DefaultSpineExtension::_readFile(const String &path, int *length) {
 	fclose(file);
 	fclose(file);
 
 
 	return data;
 	return data;
+#else
+	return nullptr;
+#endif
 }
 }
 
 
 DefaultSpineExtension::DefaultSpineExtension() : SpineExtension() {
 DefaultSpineExtension::DefaultSpineExtension() : SpineExtension() {

+ 6 - 3
spine-cpp/spine-cpp/src/spine/IkConstraint.cpp

@@ -154,11 +154,13 @@ void IkConstraint::apply(Bone &parent, Bone &child, float targetX, float targetY
 	}
 	}
 	x = targetX - pp->_worldX;
 	x = targetX - pp->_worldX;
 	y = targetY - pp->_worldY;
 	y = targetY - pp->_worldY;
-	tx = (x * d - y * b) * id - px, ty = (y * a - x * c) * id - py;
+	tx = (x * d - y * b) * id - px;
+	ty = (y * a - x * c) * id - py;
 	dd = tx * tx + ty * ty;
 	dd = tx * tx + ty * ty;
 	if (softness != 0) {
 	if (softness != 0) {
 		softness *= psx * (csx + 1) * 0.5f;
 		softness *= psx * (csx + 1) * 0.5f;
-		td = MathUtil::sqrt(dd), sd = td - l1 - l2 * psx + softness;
+		td = MathUtil::sqrt(dd);
+		sd = td - l1 - l2 * psx + softness;
 		if (sd > 0) {
 		if (sd > 0) {
 			p = MathUtil::min(1.0f, sd / (softness * 2)) - 1;
 			p = MathUtil::min(1.0f, sd / (softness * 2)) - 1;
 			p = (sd - softness * (1 - p * p)) / td;
 			p = (sd - softness * (1 - p * p)) / td;
@@ -188,7 +190,8 @@ void IkConstraint::apply(Bone &parent, Bone &child, float targetX, float targetY
 		b = l2 * MathUtil::sin(a2);
 		b = l2 * MathUtil::sin(a2);
 		a1 = MathUtil::atan2(ty * a - tx * b, tx * a + ty * b);
 		a1 = MathUtil::atan2(ty * a - tx * b, tx * a + ty * b);
 	} else {
 	} else {
-		a = psx * l2, b = psy * l2;
+		a = psx * l2;
+		b = psy * l2;
 		float aa = a * a, bb = b * b, ll = l1 * l1, ta = MathUtil::atan2(ty, tx);
 		float aa = a * a, bb = b * b, ll = l1 * l1, ta = MathUtil::atan2(ty, tx);
 		float c0 = bb * ll + aa * dd - aa * bb, c1 = -2 * bb * l1, c2 = bb - aa;
 		float c0 = bb * ll + aa * dd - aa * bb, c1 = -2 * bb * l1, c2 = bb - aa;
 		d = c1 * c1 - 4 * c2 * c0;
 		d = c1 * c1 - 4 * c2 * c0;

+ 2 - 0
spine-cpp/spine-cpp/src/spine/IkConstraintData.cpp

@@ -33,6 +33,8 @@
 
 
 using namespace spine;
 using namespace spine;
 
 
+RTTI_IMPL(IkConstraintData, ConstraintData)
+
 IkConstraintData::IkConstraintData(const String &name) : ConstraintData(name),
 IkConstraintData::IkConstraintData(const String &name) : ConstraintData(name),
 														 _target(NULL),
 														 _target(NULL),
 														 _bendDirection(1),
 														 _bendDirection(1),

+ 5 - 5
spine-cpp/spine-cpp/src/spine/MeshAttachment.cpp

@@ -28,13 +28,12 @@
  *****************************************************************************/
  *****************************************************************************/
 
 
 #include <spine/MeshAttachment.h>
 #include <spine/MeshAttachment.h>
-#include <spine/HasRendererObject.h>
 
 
 using namespace spine;
 using namespace spine;
 
 
 RTTI_IMPL(MeshAttachment, VertexAttachment)
 RTTI_IMPL(MeshAttachment, VertexAttachment)
 
 
-MeshAttachment::MeshAttachment(const String &name) : VertexAttachment(name), HasRendererObject(),
+MeshAttachment::MeshAttachment(const String &name) : VertexAttachment(name),
 													 _parentMesh(NULL),
 													 _parentMesh(NULL),
 													 _path(),
 													 _path(),
 													 _color(1, 1, 1, 1),
 													 _color(1, 1, 1, 1),
@@ -53,10 +52,13 @@ void MeshAttachment::updateRegion() {
 		_uvs.setSize(_regionUVs.size(), 0);
 		_uvs.setSize(_regionUVs.size(), 0);
 	}
 	}
 
 
+	if (_region == nullptr) {
+		return;
+	}
+
 	int i = 0, n = (int) _regionUVs.size();
 	int i = 0, n = (int) _regionUVs.size();
 	float u = _region->u, v = _region->v;
 	float u = _region->u, v = _region->v;
 	float width = 0, height = 0;
 	float width = 0, height = 0;
-
 	switch (_region->degrees) {
 	switch (_region->degrees) {
 		case 90: {
 		case 90: {
 			float textureWidth = _region->height / (_region->u2 - _region->u);
 			float textureWidth = _region->height / (_region->u2 - _region->u);
@@ -203,7 +205,6 @@ Attachment *MeshAttachment::copy() {
 	if (_parentMesh) return newLinkedMesh();
 	if (_parentMesh) return newLinkedMesh();
 
 
 	MeshAttachment *copy = new (__FILE__, __LINE__) MeshAttachment(getName());
 	MeshAttachment *copy = new (__FILE__, __LINE__) MeshAttachment(getName());
-	copy->setRendererObject(getRendererObject());
 	copy->setRegion(_region);
 	copy->setRegion(_region);
 	copy->setSequence(_sequence != NULL ? _sequence->copy() : NULL);
 	copy->setSequence(_sequence != NULL ? _sequence->copy() : NULL);
 	copy->_path = _path;
 	copy->_path = _path;
@@ -224,7 +225,6 @@ Attachment *MeshAttachment::copy() {
 
 
 MeshAttachment *MeshAttachment::newLinkedMesh() {
 MeshAttachment *MeshAttachment::newLinkedMesh() {
 	MeshAttachment *copy = new (__FILE__, __LINE__) MeshAttachment(getName());
 	MeshAttachment *copy = new (__FILE__, __LINE__) MeshAttachment(getName());
-	copy->setRendererObject(getRendererObject());
 	copy->setRegion(_region);
 	copy->setRegion(_region);
 	copy->_path = _path;
 	copy->_path = _path;
 	copy->_color.set(_color);
 	copy->_color.set(_color);

+ 2 - 0
spine-cpp/spine-cpp/src/spine/PathConstraintData.cpp

@@ -36,6 +36,8 @@
 
 
 using namespace spine;
 using namespace spine;
 
 
+RTTI_IMPL(PathConstraintData, ConstraintData)
+
 PathConstraintData::PathConstraintData(const String &name) : ConstraintData(name),
 PathConstraintData::PathConstraintData(const String &name) : ConstraintData(name),
 															 _target(NULL),
 															 _target(NULL),
 															 _positionMode(PositionMode_Fixed),
 															 _positionMode(PositionMode_Fixed),

+ 1 - 2
spine-cpp/spine-cpp/src/spine/RegionAttachment.cpp

@@ -47,7 +47,7 @@ const int RegionAttachment::URY = 5;
 const int RegionAttachment::BRX = 6;
 const int RegionAttachment::BRX = 6;
 const int RegionAttachment::BRY = 7;
 const int RegionAttachment::BRY = 7;
 
 
-RegionAttachment::RegionAttachment(const String &name) : Attachment(name), HasRendererObject(),
+RegionAttachment::RegionAttachment(const String &name) : Attachment(name),
 														 _x(0),
 														 _x(0),
 														 _y(0),
 														 _y(0),
 														 _rotation(0),
 														 _rotation(0),
@@ -259,7 +259,6 @@ spine::Color &RegionAttachment::getColor() {
 Attachment *RegionAttachment::copy() {
 Attachment *RegionAttachment::copy() {
 	RegionAttachment *copy = new (__FILE__, __LINE__) RegionAttachment(getName());
 	RegionAttachment *copy = new (__FILE__, __LINE__) RegionAttachment(getName());
 	copy->_region = _region;
 	copy->_region = _region;
-	copy->setRendererObject(getRendererObject());
 	copy->_path = _path;
 	copy->_path = _path;
 	copy->_x = _x;
 	copy->_x = _x;
 	copy->_y = _y;
 	copy->_y = _y;

+ 0 - 2
spine-cpp/spine-cpp/src/spine/Sequence.cpp

@@ -66,7 +66,6 @@ void Sequence::apply(Slot *slot, Attachment *attachment) {
 	if (attachment->getRTTI().isExactly(RegionAttachment::rtti)) {
 	if (attachment->getRTTI().isExactly(RegionAttachment::rtti)) {
 		RegionAttachment *regionAttachment = static_cast<RegionAttachment *>(attachment);
 		RegionAttachment *regionAttachment = static_cast<RegionAttachment *>(attachment);
 		if (regionAttachment->getRegion() != region) {
 		if (regionAttachment->getRegion() != region) {
-			regionAttachment->setRendererObject(region);
 			regionAttachment->setRegion(region);
 			regionAttachment->setRegion(region);
 			regionAttachment->updateRegion();
 			regionAttachment->updateRegion();
 		}
 		}
@@ -75,7 +74,6 @@ void Sequence::apply(Slot *slot, Attachment *attachment) {
 	if (attachment->getRTTI().isExactly(MeshAttachment::rtti)) {
 	if (attachment->getRTTI().isExactly(MeshAttachment::rtti)) {
 		MeshAttachment *meshAttachment = static_cast<MeshAttachment *>(attachment);
 		MeshAttachment *meshAttachment = static_cast<MeshAttachment *>(attachment);
 		if (meshAttachment->getRegion() != region) {
 		if (meshAttachment->getRegion() != region) {
-			meshAttachment->setRendererObject(region);
 			meshAttachment->setRegion(region);
 			meshAttachment->setRegion(region);
 			meshAttachment->updateRegion();
 			meshAttachment->updateRegion();
 		}
 		}

+ 3 - 3
spine-cpp/spine-cpp/src/spine/Skeleton.cpp

@@ -425,8 +425,8 @@ PathConstraint *Skeleton::findPathConstraint(const String &constraintName) {
 void Skeleton::getBounds(float &outX, float &outY, float &outWidth, float &outHeight, Vector<float> &outVertexBuffer) {
 void Skeleton::getBounds(float &outX, float &outY, float &outWidth, float &outHeight, Vector<float> &outVertexBuffer) {
 	float minX = FLT_MAX;
 	float minX = FLT_MAX;
 	float minY = FLT_MAX;
 	float minY = FLT_MAX;
-	float maxX = FLT_MIN;
-	float maxY = FLT_MIN;
+	float maxX = -FLT_MAX;
+	float maxY = -FLT_MAX;
 
 
 	for (size_t i = 0; i < _drawOrder.size(); ++i) {
 	for (size_t i = 0; i < _drawOrder.size(); ++i) {
 		Slot *slot = _drawOrder[i];
 		Slot *slot = _drawOrder[i];
@@ -653,7 +653,7 @@ void Skeleton::sortPathConstraintAttachment(Skin *skin, size_t slotIndex, Bone &
 
 
 void Skeleton::sortPathConstraintAttachment(Attachment *attachment, Bone &slotBone) {
 void Skeleton::sortPathConstraintAttachment(Attachment *attachment, Bone &slotBone) {
 	if (attachment == NULL || !attachment->getRTTI().instanceOf(PathAttachment::rtti)) return;
 	if (attachment == NULL || !attachment->getRTTI().instanceOf(PathAttachment::rtti)) return;
-	Vector<size_t> &pathBones = static_cast<PathAttachment *>(attachment)->getBones();
+	Vector<int> &pathBones = static_cast<PathAttachment *>(attachment)->getBones();
 	if (pathBones.size() == 0)
 	if (pathBones.size() == 0)
 		sortBone(&slotBone);
 		sortBone(&slotBone);
 	else {
 	else {

+ 7 - 8
spine-cpp/spine-cpp/src/spine/SkeletonBinary.cpp

@@ -109,9 +109,9 @@ SkeletonData *SkeletonBinary::readSkeletonData(const unsigned char *binary, cons
 	int lowHash = readInt(input);
 	int lowHash = readInt(input);
 	int hightHash = readInt(input);
 	int hightHash = readInt(input);
 	String hashString;
 	String hashString;
-	sprintf(buffer, "%x", hightHash);
+	snprintf(buffer, 16, "%x", hightHash);
 	hashString.append(buffer);
 	hashString.append(buffer);
-	sprintf(buffer, "%x", lowHash);
+	snprintf(buffer, 16, "%x", lowHash);
 	hashString.append(buffer);
 	hashString.append(buffer);
 	skeletonData->_hash = hashString;
 	skeletonData->_hash = hashString;
 
 
@@ -120,7 +120,7 @@ SkeletonData *SkeletonBinary::readSkeletonData(const unsigned char *binary, cons
 
 
 	if (!skeletonData->_version.startsWith(SPINE_VERSION_STRING)) {
 	if (!skeletonData->_version.startsWith(SPINE_VERSION_STRING)) {
 		char errorMsg[255];
 		char errorMsg[255];
-		sprintf(errorMsg, "Skeleton version %s does not match runtime version %s", skeletonData->_version.buffer(), SPINE_VERSION_STRING);
+		snprintf(errorMsg, 255, "Skeleton version %s does not match runtime version %s", skeletonData->_version.buffer(), SPINE_VERSION_STRING);
 		setError(errorMsg, "");
 		setError(errorMsg, "");
 		return NULL;
 		return NULL;
 	}
 	}
@@ -564,7 +564,7 @@ Attachment *SkeletonBinary::readAttachment(DataInput *input, Skin *skin, int slo
 			Vector<float> uvs;
 			Vector<float> uvs;
 			Vector<unsigned short> triangles;
 			Vector<unsigned short> triangles;
 			Vector<float> vertices;
 			Vector<float> vertices;
-			Vector<size_t> bones;
+			Vector<int> bones;
 			int hullLength;
 			int hullLength;
 			Sequence *sequence;
 			Sequence *sequence;
 			float width = 0;
 			float width = 0;
@@ -702,7 +702,7 @@ Attachment *SkeletonBinary::readAttachment(DataInput *input, Skin *skin, int slo
 	return NULL;
 	return NULL;
 }
 }
 
 
-void SkeletonBinary::readVertices(DataInput *input, Vector<float> &vertices, Vector<size_t> &bones, int vertexCount) {
+void SkeletonBinary::readVertices(DataInput *input, Vector<float> &vertices, Vector<int> &bones, int vertexCount) {
 	float scale = _scale;
 	float scale = _scale;
 	int verticesLength = vertexCount << 1;
 	int verticesLength = vertexCount << 1;
 
 
@@ -1010,7 +1010,7 @@ Animation *SkeletonBinary::readAnimation(const String &name, DataInput *input, S
 						timeline->setFrame(frame, time, a);
 						timeline->setFrame(frame, time, a);
 						if (frame == frameLast) break;
 						if (frame == frameLast) break;
 						float time2 = readFloat(input);
 						float time2 = readFloat(input);
-						float a2 = readByte(input) / 255;
+						float a2 = readByte(input) / 255.0;
 						switch (readSByte(input)) {
 						switch (readSByte(input)) {
 							case CURVE_STEPPED:
 							case CURVE_STEPPED:
 								timeline->setStepped(frame);
 								timeline->setStepped(frame);
@@ -1249,7 +1249,6 @@ Animation *SkeletonBinary::readAnimation(const String &name, DataInput *input, S
 					setError("Attachment not found: ", attachmentName);
 					setError("Attachment not found: ", attachmentName);
 					return NULL;
 					return NULL;
 				}
 				}
-				VertexAttachment *attachment = static_cast<VertexAttachment *>(baseAttachment);
 				unsigned int timelineType = readByte(input);
 				unsigned int timelineType = readByte(input);
 				int frameCount = readVarint(input, true);
 				int frameCount = readVarint(input, true);
 				int frameLast = frameCount - 1;
 				int frameLast = frameCount - 1;
@@ -1312,7 +1311,7 @@ Animation *SkeletonBinary::readAnimation(const String &name, DataInput *input, S
 						break;
 						break;
 					}
 					}
 					case ATTACHMENT_SEQUENCE: {
 					case ATTACHMENT_SEQUENCE: {
-						SequenceTimeline *timeline = new (__FILE__, __LINE__) SequenceTimeline(frameCount, slotIndex, attachment);
+						SequenceTimeline *timeline = new (__FILE__, __LINE__) SequenceTimeline(frameCount, slotIndex, baseAttachment);
 						for (int frame = 0; frame < frameCount; frame++) {
 						for (int frame = 0; frame < frameCount; frame++) {
 							float time = readFloat(input);
 							float time = readFloat(input);
 							int modeAndIndex = readInt(input);
 							int modeAndIndex = readInt(input);

+ 13 - 0
spine-cpp/spine-cpp/src/spine/SkeletonBounds.cpp

@@ -185,6 +185,19 @@ spine::Polygon *SkeletonBounds::getPolygon(BoundingBoxAttachment *attachment) {
 	return index == -1 ? NULL : _polygons[index];
 	return index == -1 ? NULL : _polygons[index];
 }
 }
 
 
+BoundingBoxAttachment *SkeletonBounds::getBoundingBox(Polygon *polygon) {
+	int index = _polygons.indexOf(polygon);
+	return index == -1 ? NULL : _boundingBoxes[index];
+}
+
+Vector<Polygon *> &SkeletonBounds::getPolygons() {
+	return _polygons;
+}
+
+Vector<BoundingBoxAttachment *> &SkeletonBounds::getBoundingBoxes() {
+	return _boundingBoxes;
+}
+
 float SkeletonBounds::getWidth() {
 float SkeletonBounds::getWidth() {
 	return _maxX - _minX;
 	return _maxX - _minX;
 }
 }

+ 1 - 1
spine-cpp/spine-cpp/src/spine/SkeletonJson.cpp

@@ -152,7 +152,7 @@ SkeletonData *SkeletonJson::readSkeletonData(const char *json) {
 		skeletonData->_version = Json::getString(skeleton, "spine", 0);
 		skeletonData->_version = Json::getString(skeleton, "spine", 0);
 		if (!skeletonData->_version.startsWith(SPINE_VERSION_STRING)) {
 		if (!skeletonData->_version.startsWith(SPINE_VERSION_STRING)) {
 			char errorMsg[255];
 			char errorMsg[255];
-			sprintf(errorMsg, "Skeleton version %s does not match runtime version %s", skeletonData->_version.buffer(), SPINE_VERSION_STRING);
+			snprintf(errorMsg, 255, "Skeleton version %s does not match runtime version %s", skeletonData->_version.buffer(), SPINE_VERSION_STRING);
 			setError(NULL, errorMsg, "");
 			setError(NULL, errorMsg, "");
 			return NULL;
 			return NULL;
 		}
 		}

+ 62 - 0
spine-cpp/spine-cpp/src/spine/TransformConstraintData.cpp

@@ -35,6 +35,8 @@
 
 
 using namespace spine;
 using namespace spine;
 
 
+RTTI_IMPL(TransformConstraintData, ConstraintData)
+
 TransformConstraintData::TransformConstraintData(const String &name) : ConstraintData(name),
 TransformConstraintData::TransformConstraintData(const String &name) : ConstraintData(name),
 																	   _target(NULL),
 																	   _target(NULL),
 																	   _mixRotate(0),
 																	   _mixRotate(0),
@@ -116,3 +118,63 @@ bool TransformConstraintData::isRelative() {
 bool TransformConstraintData::isLocal() {
 bool TransformConstraintData::isLocal() {
 	return _local;
 	return _local;
 }
 }
+
+void TransformConstraintData::setTarget(BoneData *target) {
+	_target = target;
+}
+
+void TransformConstraintData::setMixRotate(float mixRotate) {
+	_mixRotate = mixRotate;
+}
+
+void TransformConstraintData::setMixX(float mixX) {
+	_mixX = mixX;
+}
+
+void TransformConstraintData::setMixY(float mixY) {
+	_mixY = mixY;
+}
+
+void TransformConstraintData::setMixScaleX(float mixScaleX) {
+	_mixScaleX = mixScaleX;
+}
+
+void TransformConstraintData::setMixScaleY(float mixScaleY) {
+	_mixScaleY = mixScaleY;
+}
+
+void TransformConstraintData::setMixShearY(float mixShearY) {
+	_mixShearY = mixShearY;
+}
+
+void TransformConstraintData::setOffsetRotation(float offsetRotation) {
+	_offsetRotation = offsetRotation;
+}
+
+void TransformConstraintData::setOffsetX(float offsetX) {
+	_offsetX = offsetX;
+}
+
+void TransformConstraintData::setOffsetY(float offsetY) {
+	_offsetY = offsetY;
+}
+
+void TransformConstraintData::setOffsetScaleX(float offsetScaleX) {
+	_offsetScaleX = offsetScaleX;
+}
+
+void TransformConstraintData::setOffsetScaleY(float offsetScaleY) {
+	_offsetScaleY = offsetScaleY;
+}
+
+void TransformConstraintData::setOffsetShearY(float offsetShearY) {
+	_offsetShearY = offsetShearY;
+}
+
+void TransformConstraintData::setRelative(bool isRelative) {
+	_relative = isRelative;
+}
+
+void TransformConstraintData::setLocal(bool isLocal) {
+	_local = isLocal;
+}

+ 2 - 2
spine-cpp/spine-cpp/src/spine/VertexAttachment.cpp

@@ -64,7 +64,7 @@ void VertexAttachment::computeWorldVertices(Slot &slot, size_t start, size_t cou
 	Skeleton &skeleton = slot._bone._skeleton;
 	Skeleton &skeleton = slot._bone._skeleton;
 	Vector<float> *deformArray = &slot.getDeform();
 	Vector<float> *deformArray = &slot.getDeform();
 	Vector<float> *vertices = &_vertices;
 	Vector<float> *vertices = &_vertices;
-	Vector<size_t> &bones = _bones;
+	Vector<int> &bones = _bones;
 	if (bones.size() == 0) {
 	if (bones.size() == 0) {
 		if (deformArray->size() > 0) vertices = deformArray;
 		if (deformArray->size() > 0) vertices = deformArray;
 
 
@@ -130,7 +130,7 @@ int VertexAttachment::getId() {
 	return _id;
 	return _id;
 }
 }
 
 
-Vector<size_t> &VertexAttachment::getBones() {
+Vector<int> &VertexAttachment::getBones() {
 	return _bones;
 	return _bones;
 }
 }
 
 

+ 30 - 0
spine-flutter/.gitignore

@@ -0,0 +1,30 @@
+# Miscellaneous
+*.class
+*.log
+*.pyc
+*.swp
+.DS_Store
+.atom/
+.buildlog/
+.history
+.svn/
+migrate_working_dir/
+
+# IntelliJ related
+*.iml
+*.ipr
+*.iws
+.idea/
+
+# The .vscode folder contains launch configuration and tasks you configure in
+# VS Code which you may wish to be included in version control, so this line
+# is commented out by default.
+#.vscode/
+
+# Flutter/Dart/Pub related
+# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
+/pubspec.lock
+**/doc/api/
+.dart_tool/
+.packages
+build/

+ 42 - 0
spine-flutter/.metadata

@@ -0,0 +1,42 @@
+# This file tracks properties of this Flutter project.
+# Used by Flutter tool to assess capabilities and perform upgrades etc.
+#
+# This file should be version controlled.
+
+version:
+  revision: f1875d570e39de09040c8f79aa13cc56baab8db1
+  channel: stable
+
+project_type: plugin_ffi
+
+# Tracks metadata for the flutter migrate command
+migration:
+  platforms:
+    - platform: root
+      create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
+      base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
+    - platform: android
+      create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
+      base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
+    - platform: ios
+      create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
+      base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
+    - platform: linux
+      create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
+      base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
+    - platform: macos
+      create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
+      base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
+    - platform: windows
+      create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
+      base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
+
+  # User provided section
+
+  # List of Local paths (relative to this file) that should be
+  # ignored by the migrate tool.
+  #
+  # Files that are not part of the templates will be ignored by default.
+  unmanaged_files:
+    - 'lib/main.dart'
+    - 'ios/Runner.xcodeproj/project.pbxproj'

+ 3 - 0
spine-flutter/.pubignore

@@ -0,0 +1,3 @@
+!src/spine-cpp
+!ios/Classes/spine-cpp
+!macos/Classes/spine-cpp

+ 45 - 0
spine-flutter/.vscode/launch.json

@@ -0,0 +1,45 @@
+{
+    // Use IntelliSense to learn about possible attributes.
+    // Hover to view descriptions of existing attributes.
+    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
+    "version": "0.2.0",
+    "configurations": [
+        {
+            "name": "spine-flutter",
+            "request": "launch",
+            "type": "dart"
+        },
+        {
+            "name": "spine-flutter (profile mode)",
+            "request": "launch",
+            "type": "dart",
+            "flutterMode": "profile"
+        },
+        {
+            "name": "spine-flutter (release mode)",
+            "request": "launch",
+            "type": "dart",
+            "flutterMode": "release"
+        },
+        {
+            "name": "example",
+            "cwd": "example",
+            "request": "launch",
+            "type": "dart"
+        },
+        {
+            "name": "example (profile mode)",
+            "cwd": "example",
+            "request": "launch",
+            "type": "dart",
+            "flutterMode": "profile"
+        },
+        {
+            "name": "example (release mode)",
+            "cwd": "example",
+            "request": "launch",
+            "type": "dart",
+            "flutterMode": "release"
+        }
+    ]
+}

+ 39 - 0
spine-flutter/CHANGELOG.md

@@ -0,0 +1,39 @@
+# 4.1.1
+* Backport to 4.1 spine-runtimes branch.
+* Blend mode support.
+* Hot-reload support. The underlying `SkeletonDrawable` will be retained if the asset file names and type provided to the `SpineWidget` constructor has not changed.
+
+# 4.2.11
+* Update README.md with setup and development instructions.
+
+# 4.2.10
+* Update README.md to point to Junji's Dart-only Spine runtime.
+
+# 4.2.9
+* Fix atlas parsing.
+
+# 4.2.8
+* Change reversed positional argument order in `SpineWidget` constructors.
+
+# 4.2.7
+* Change package name from  `esotericsoftware_spine_flutter` to `spine_flutter`.
+
+# 4.2.6
+* Fix analyzer errors, fix code style to adhere to Dart standards.
+
+# 4.2.5
+* Implemented batching of render commands, reducing the number of draw calls. 60/120fps for 100 Spineboys on all platforms.
+
+# 0.0.4
+* Clean-up `fromAsset()` factory methods so the atlas comes before skeleton data file name.
+* Rename `Vector2` to `Vec2`.
+* Make the bundle configurable in `SpineWidget.asset()`.
+
+# 0.0.3
+* Lower macOS deployment target to 10.11.
+
+# 0.0.2
+* Fix package name in build system `spine_flutter` > `esotericsoftware_spine_flutter`.
+
+# 0.0.1
+Initial test release.

+ 26 - 0
spine-flutter/LICENSE

@@ -0,0 +1,26 @@
+Spine Runtimes License Agreement
+Last updated September 24, 2021. Replaces all prior versions.
+
+Copyright (c) 2013-2021, Esoteric Software LLC
+
+Integration of the Spine Runtimes into software or otherwise creating
+derivative works of the Spine Runtimes is permitted under the terms and
+conditions of Section 2 of the Spine Editor License Agreement:
+http://esotericsoftware.com/spine-editor-license
+
+Otherwise, it is permitted to integrate the Spine Runtimes into software
+or otherwise create derivative works of the Spine Runtimes (collectively,
+"Products"), provided that each user of the Products must obtain their own
+Spine Editor license and redistribution of the Products in any form must
+include this license and copyright notice.
+
+THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
+BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ 77 - 0
spine-flutter/README.md

@@ -0,0 +1,77 @@
+# spine-flutter
+
+The spine-godot runtime provides functionality to load, manipulate and render [Spine](https://esotericsoftware.com) skeletal animation data using [Flutter](https://flutter.dev/). spine-flutter is based on [spine-cpp](../spine-cpp) and supports desktop and mobile Flutter deployment targets. spine-flutter does not support Flutter's web deployment target.
+
+# See the [spine-flutter documentation](https://esotericsoftware.com/spine-flutter) for in-depth information.
+
+The `spine_flutter` package name was previously used to publish the [Spine Flutter Runtime in plain Dart](https://github.com/jtakakura/spine_flutter/) by Junji Takakura. Junji has kindly transferred the package name to us and is now publishing his Dart-only Spine Flutter Runtime under the package name [spine_flutter_dart](https://pub.dev/packages/spine_flutter_dart).
+
+## Licensing
+
+You are welcome to evaluate the Spine Runtimes and the examples we provide in this repository free of charge.
+
+You can integrate the Spine Runtimes into your software free of charge, but users of your software must have their own [Spine license](https://esotericsoftware.com/spine-purchase). Please make your users aware of this requirement! This option is often chosen by those making development tools, such as an SDK, game toolkit, or software library.
+
+In order to distribute your software containing the Spine Runtimes to others that don't have a Spine license, you need a [Spine license](https://esotericsoftware.com/spine-purchase) at the time of integration. Then you can distribute your software containing the Spine Runtimes however you like, provided others don't modify it or use it to create new software. If others want to do that, they'll need their own Spine license.
+
+For the official legal terms governing the Spine Runtimes, please read the [Spine Runtimes License Agreement](https://esotericsoftware.com/spine-runtimes-license) and Section 2 of the [Spine Editor License Agreement](https://esotericsoftware.com/spine-editor-license#s2).
+
+## Spine version
+
+spine-flutter works with data exported from Spine 4.2.xx.
+
+spine-flutter supports all Spine features, except two-color tinting and the screen blend mode.
+
+## Supported platforms
+The spine-flutter runtime works on desktop, mobile and web. Web deployment requires canvaskit, which will add about 2mb of dependencies to your web deployment. You can compile your app for web with Canvaskit like this:
+
+```
+flutter build web --web-renderer canvaskit
+```
+
+## Setup
+To add `spine_flutter` to your Flutter project, add the following dependency to your `pubspec.yaml` file:
+
+```yaml
+dependencies:
+  ...
+  spine_flutter: ^4.2.11
+```
+
+In your `main()`, add these two lines in the beginning to initialize the Spine Flutter runtime:
+
+```dart
+void main() {
+    WidgetsFlutterBinding.ensureInitialized();
+    await initSpineFlutter(enableMemoryDebugging: false);
+    ...
+}
+```
+
+## Example
+If you have pulled the `spine_flutter` package from [pub.dev](https://pub.dev) directly, you can run the example in the `example/` folder as is:
+
+```bash
+cd path/to/downloaded/spine_flutter
+cd example
+flutter run
+```
+
+Otherwise you can run the example like this:
+
+1. install the [Flutter SDK](https://docs.flutter.dev/get-started/install), then run `flutter doctor` which will instruct you what other dependencies to install.
+2. Clone this repository `git clone https://github.com/esotericsoftware/spine-runtimes`
+3. Run `setup.sh` in the `spine-flutter/` folder. On Windows, you can use [Git Bash](https://gitforwindows.org/) included in Git for Window to run the `setup.sh` Bash script.
+
+You can then open `spine-flutter` in an IDE or editor of your choice that supports Flutter, like [IntelliJ IDEA/Android Studio](https://docs.flutter.dev/get-started/editor?tab=androidstudio) or [Visual Studio Code](https://docs.flutter.dev/get-started/editor?tab=vscode) to inspect and run the example. 
+
+Alternatively, you can run the example from the [command line](https://docs.flutter.dev/get-started/test-drive?tab=terminal).
+
+## Development
+If all you modify are the Dart sources of the plugin, then the development setup is the same as the setup described under "Example" above.
+
+If you need to work on the `dart:ffi` bindings for `spine-cpp`, you will also need to install [Emscripten](https://emscripten.org/docs/getting_started/downloads.html).
+
+To generate the bindings based on the `src/spine_flutter.h` header, run `dart run ffigen --config ffigen.yaml`. After the bindings have been generated, you must replace the line `import 'dart:ffi' as ffi;` with `import 'ffi_proxy.dart' as ffi;` in the file `src/spine_flutter_bindings_generated.dart`. Otherwise the bindings will not compile for the web.
+
+If you made changes to `spine-cpp` or the source files in `src/`, you must run `compile-wasm.sh`. This will compile `spine-cpp` and the bindings for the Web and place updated versions of `libspine_flutter.js` and `libspine_flutter.wasm` in the `lib/assets/` folder. For web builds, the `initSpineFlutterFFI()` function in `lib/init_web.dart` will load these files from the package's asset bundle.

+ 4 - 0
spine-flutter/analysis_options.yaml

@@ -0,0 +1,4 @@
+include: package:flutter_lints/flutter.yaml
+
+# Additional information about this file can be found at
+# https://dart.dev/guides/language/analysis-options

+ 9 - 0
spine-flutter/android/.gitignore

@@ -0,0 +1,9 @@
+*.iml
+.gradle
+/local.properties
+/.idea/workspace.xml
+/.idea/libraries
+.DS_Store
+/build
+/captures
+.cxx

+ 59 - 0
spine-flutter/android/build.gradle

@@ -0,0 +1,59 @@
+// The Android Gradle Plugin builds the native code with the Android NDK.
+
+group 'com.example.spine_flutter'
+version '1.0'
+
+buildscript {
+    repositories {
+        google()
+        mavenCentral()
+    }
+
+    dependencies {
+        // The Android Gradle Plugin knows how to build native code with the NDK.
+        classpath 'com.android.tools.build:gradle:7.1.2'
+    }
+}
+
+rootProject.allprojects {
+    repositories {
+        google()
+        mavenCentral()
+    }
+}
+
+apply plugin: 'com.android.library'
+
+android {
+    // Bumping the plugin compileSdkVersion requires all clients of this plugin
+    // to bump the version in their app.
+    compileSdkVersion 31
+
+    // Bumping the plugin ndkVersion requires all clients of this plugin to bump
+    // the version in their app and to download a newer version of the NDK.
+    ndkVersion "21.1.6352462"
+
+    // Invoke the shared CMake build with the Android Gradle Plugin.
+    externalNativeBuild {
+        cmake {
+            path "../src/CMakeLists.txt"
+
+            // The default CMake version for the Android Gradle Plugin is 3.10.2.
+            // https://developer.android.com/studio/projects/install-ndk#vanilla_cmake
+            //
+            // The Flutter tooling requires that developers have CMake 3.10 or later
+            // installed. You should not increase this version, as doing so will cause
+            // the plugin to fail to compile for some customers of the plugin.
+            // version "3.10.2"
+        }
+    }
+
+    compileOptions {
+        sourceCompatibility JavaVersion.VERSION_1_8
+        targetCompatibility JavaVersion.VERSION_1_8
+    }
+
+    defaultConfig {
+        minSdkVersion 16
+    }
+}

+ 1 - 0
spine-flutter/android/settings.gradle

@@ -0,0 +1 @@
+rootProject.name = 'spine_flutter'

+ 3 - 0
spine-flutter/android/src/main/AndroidManifest.xml

@@ -0,0 +1,3 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+  package="com.example.spine_flutter">
+</manifest>

+ 25 - 0
spine-flutter/compile-wasm.sh

@@ -0,0 +1,25 @@
+#!/bin/sh
+dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
+pushd $dir > /dev/null
+mkdir -p lib/assets/
+# Need to use -O2, as -O3 applies the Closure compiler to native function names.
+# The entries for exported functions in Module.asm will be scrambled so
+# EmscriptenModule._fromJs() is unable to parse them and link them with original
+# names set on the module, e.g. Module._spine_get_major_version.
+emcc \
+	-Isrc/spine-cpp/include \
+	-O2 --closure 1 -fno-rtti -fno-exceptions -lc++abi -lc++ \
+	-s STRICT=1 \
+	-s LLD_REPORT_UNDEFINED \
+	-s MODULARIZE=1 \
+	-s ALLOW_MEMORY_GROWTH=1 \
+	-s ALLOW_TABLE_GROWTH \
+	-s MALLOC=emmalloc \
+	-s EXPORT_ALL=1 \
+	-s EXPORTED_FUNCTIONS='["_malloc", "_free"]' \
+	--no-entry \
+	-s EXPORT_NAME=libspine_flutter \
+	src/spine_flutter.cpp `find src/spine-cpp/src -type f` \
+	-o lib/assets/libspine_flutter.js
+	ls -lah lib/assets
+popd

+ 46 - 0
spine-flutter/example/.gitignore

@@ -0,0 +1,46 @@
+# Miscellaneous
+*.class
+*.log
+*.pyc
+*.swp
+.DS_Store
+.atom/
+.buildlog/
+.history
+.svn/
+migrate_working_dir/
+
+# IntelliJ related
+*.iml
+*.ipr
+*.iws
+.idea/
+
+# The .vscode folder contains launch configuration and tasks you configure in
+# VS Code which you may wish to be included in version control, so this line
+# is commented out by default.
+#.vscode/
+
+# Flutter/Dart/Pub related
+**/doc/api/
+**/ios/Flutter/.last_build_id
+.dart_tool/
+.flutter-plugins
+.flutter-plugins-dependencies
+.packages
+.pub-cache/
+.pub/
+/build/
+
+# Web related
+
+# Symbolication related
+app.*.symbols
+
+# Obfuscation related
+app.*.map.json
+
+# Android Studio will place build artifacts here
+/android/app/debug
+/android/app/profile
+/android/app/release

+ 16 - 0
spine-flutter/example/README.md

@@ -0,0 +1,16 @@
+# spine_flutter_example
+
+Demonstrates how to use the spine_flutter plugin.
+
+## Getting Started
+
+This project is a starting point for a Flutter application.
+
+A few resources to get you started if this is your first Flutter project:
+
+- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
+- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
+
+For help getting started with Flutter development, view the
+[online documentation](https://docs.flutter.dev/), which offers tutorials,
+samples, guidance on mobile development, and a full API reference.

+ 29 - 0
spine-flutter/example/analysis_options.yaml

@@ -0,0 +1,29 @@
+# This file configures the analyzer, which statically analyzes Dart code to
+# check for errors, warnings, and lints.
+#
+# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
+# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
+# invoked from the command line by running `flutter analyze`.
+
+# The following line activates a set of recommended lints for Flutter apps,
+# packages, and plugins designed to encourage good coding practices.
+include: package:flutter_lints/flutter.yaml
+
+linter:
+  # The lint rules applied to this project can be customized in the
+  # section below to disable rules from the `package:flutter_lints/flutter.yaml`
+  # included above or to enable additional rules. A list of all available lints
+  # and their documentation is published at
+  # https://dart-lang.github.io/linter/lints/index.html.
+  #
+  # Instead of disabling a lint rule for the entire project in the
+  # section below, it can also be suppressed for a single line of code
+  # or a specific dart file by using the `// ignore: name_of_lint` and
+  # `// ignore_for_file: name_of_lint` syntax on the line or in the file
+  # producing the lint.
+  rules:
+    # avoid_print: false  # Uncomment to disable the `avoid_print` rule
+    # prefer_single_quotes: true  # Uncomment to enable the `prefer_single_quotes` rule
+
+# Additional information about this file can be found at
+# https://dart.dev/guides/language/analysis-options

+ 13 - 0
spine-flutter/example/android/.gitignore

@@ -0,0 +1,13 @@
+gradle-wrapper.jar
+/.gradle
+/captures/
+/gradlew
+/gradlew.bat
+/local.properties
+GeneratedPluginRegistrant.java
+
+# Remember to never publicly share your keystore.
+# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
+key.properties
+**/*.keystore
+**/*.jks

+ 71 - 0
spine-flutter/example/android/app/build.gradle

@@ -0,0 +1,71 @@
+def localProperties = new Properties()
+def localPropertiesFile = rootProject.file('local.properties')
+if (localPropertiesFile.exists()) {
+    localPropertiesFile.withReader('UTF-8') { reader ->
+        localProperties.load(reader)
+    }
+}
+
+def flutterRoot = localProperties.getProperty('flutter.sdk')
+if (flutterRoot == null) {
+    throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
+}
+
+def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
+if (flutterVersionCode == null) {
+    flutterVersionCode = '1'
+}
+
+def flutterVersionName = localProperties.getProperty('flutter.versionName')
+if (flutterVersionName == null) {
+    flutterVersionName = '1.0'
+}
+
+apply plugin: 'com.android.application'
+apply plugin: 'kotlin-android'
+apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
+
+android {
+    compileSdkVersion flutter.compileSdkVersion
+    ndkVersion flutter.ndkVersion
+
+    compileOptions {
+        sourceCompatibility JavaVersion.VERSION_1_8
+        targetCompatibility JavaVersion.VERSION_1_8
+    }
+
+    kotlinOptions {
+        jvmTarget = '1.8'
+    }
+
+    sourceSets {
+        main.java.srcDirs += 'src/main/kotlin'
+    }
+
+    defaultConfig {
+        // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
+        applicationId "com.example.spine_flutter_example"
+        // You can update the following values to match your application needs.
+        // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration.
+        minSdkVersion flutter.minSdkVersion
+        targetSdkVersion flutter.targetSdkVersion
+        versionCode flutterVersionCode.toInteger()
+        versionName flutterVersionName
+    }
+
+    buildTypes {
+        release {
+            // TODO: Add your own signing config for the release build.
+            // Signing with the debug keys for now, so `flutter run --release` works.
+            signingConfig signingConfigs.debug
+        }
+    }
+}
+
+flutter {
+    source '../..'
+}
+
+dependencies {
+    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+}

+ 8 - 0
spine-flutter/example/android/app/src/debug/AndroidManifest.xml

@@ -0,0 +1,8 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.spine_flutter_example">
+    <!-- The INTERNET permission is required for development. Specifically,
+         the Flutter tool needs it to communicate with the running application
+         to allow setting breakpoints, to provide hot reload, etc.
+    -->
+    <uses-permission android:name="android.permission.INTERNET"/>
+</manifest>

+ 34 - 0
spine-flutter/example/android/app/src/main/AndroidManifest.xml

@@ -0,0 +1,34 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.spine_flutter_example">
+   <application
+        android:label="spine_flutter_example"
+        android:name="${applicationName}"
+        android:icon="@mipmap/ic_launcher">
+        <activity
+            android:name=".MainActivity"
+            android:exported="true"
+            android:launchMode="singleTop"
+            android:theme="@style/LaunchTheme"
+            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
+            android:hardwareAccelerated="true"
+            android:windowSoftInputMode="adjustResize">
+            <!-- Specifies an Android theme to apply to this Activity as soon as
+                 the Android process has started. This theme is visible to the user
+                 while the Flutter UI initializes. After that, this theme continues
+                 to determine the Window background behind the Flutter UI. -->
+            <meta-data
+              android:name="io.flutter.embedding.android.NormalTheme"
+              android:resource="@style/NormalTheme"
+              />
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+        </activity>
+        <!-- Don't delete the meta-data below.
+             This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
+        <meta-data
+            android:name="flutterEmbedding"
+            android:value="2" />
+    </application>
+</manifest>

+ 6 - 0
spine-flutter/example/android/app/src/main/kotlin/com/example/example/MainActivity.kt

@@ -0,0 +1,6 @@
+package com.example.example
+
+import io.flutter.embedding.android.FlutterActivity
+
+class MainActivity: FlutterActivity() {
+}

+ 6 - 0
spine-flutter/example/android/app/src/main/kotlin/com/example/spine_flutter_example/MainActivity.kt

@@ -0,0 +1,6 @@
+package com.example.spine_flutter_example
+
+import io.flutter.embedding.android.FlutterActivity
+
+class MainActivity: FlutterActivity() {
+}

+ 12 - 0
spine-flutter/example/android/app/src/main/res/drawable-v21/launch_background.xml

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Modify this file to customize your launch splash screen -->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="?android:colorBackground" />
+
+    <!-- You can insert your own image assets here -->
+    <!-- <item>
+        <bitmap
+            android:gravity="center"
+            android:src="@mipmap/launch_image" />
+    </item> -->
+</layer-list>

+ 12 - 0
spine-flutter/example/android/app/src/main/res/drawable/launch_background.xml

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Modify this file to customize your launch splash screen -->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@android:color/white" />
+
+    <!-- You can insert your own image assets here -->
+    <!-- <item>
+        <bitmap
+            android:gravity="center"
+            android:src="@mipmap/launch_image" />
+    </item> -->
+</layer-list>

BIN
spine-flutter/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png


BIN
spine-flutter/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png


BIN
spine-flutter/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png


BIN
spine-flutter/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png


BIN
spine-flutter/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png


+ 18 - 0
spine-flutter/example/android/app/src/main/res/values-night/styles.xml

@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
+    <style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
+        <!-- Show a splash screen on the activity. Automatically removed when
+             the Flutter engine draws its first frame -->
+        <item name="android:windowBackground">@drawable/launch_background</item>
+    </style>
+    <!-- Theme applied to the Android Window as soon as the process has started.
+         This theme determines the color of the Android Window while your
+         Flutter UI initializes, as well as behind your Flutter UI while its
+         running.
+
+         This Theme is only used starting with V2 of Flutter's Android embedding. -->
+    <style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
+        <item name="android:windowBackground">?android:colorBackground</item>
+    </style>
+</resources>

+ 18 - 0
spine-flutter/example/android/app/src/main/res/values/styles.xml

@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
+    <style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
+        <!-- Show a splash screen on the activity. Automatically removed when
+             the Flutter engine draws its first frame -->
+        <item name="android:windowBackground">@drawable/launch_background</item>
+    </style>
+    <!-- Theme applied to the Android Window as soon as the process has started.
+         This theme determines the color of the Android Window while your
+         Flutter UI initializes, as well as behind your Flutter UI while its
+         running.
+
+         This Theme is only used starting with V2 of Flutter's Android embedding. -->
+    <style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
+        <item name="android:windowBackground">?android:colorBackground</item>
+    </style>
+</resources>

+ 8 - 0
spine-flutter/example/android/app/src/profile/AndroidManifest.xml

@@ -0,0 +1,8 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.spine_flutter_example">
+    <!-- The INTERNET permission is required for development. Specifically,
+         the Flutter tool needs it to communicate with the running application
+         to allow setting breakpoints, to provide hot reload, etc.
+    -->
+    <uses-permission android:name="android.permission.INTERNET"/>
+</manifest>

+ 31 - 0
spine-flutter/example/android/build.gradle

@@ -0,0 +1,31 @@
+buildscript {
+    ext.kotlin_version = '1.6.10'
+    repositories {
+        google()
+        mavenCentral()
+    }
+
+    dependencies {
+        classpath 'com.android.tools.build:gradle:7.1.2'
+        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+    }
+}
+
+allprojects {
+    repositories {
+        google()
+        mavenCentral()
+    }
+}
+
+rootProject.buildDir = '../build'
+subprojects {
+    project.buildDir = "${rootProject.buildDir}/${project.name}"
+}
+subprojects {
+    project.evaluationDependsOn(':app')
+}
+
+task clean(type: Delete) {
+    delete rootProject.buildDir
+}

+ 3 - 0
spine-flutter/example/android/gradle.properties

@@ -0,0 +1,3 @@
+org.gradle.jvmargs=-Xmx1536M
+android.useAndroidX=true
+android.enableJetifier=true

+ 6 - 0
spine-flutter/example/android/gradle/wrapper/gradle-wrapper.properties

@@ -0,0 +1,6 @@
+#Fri Jun 23 08:50:38 CEST 2017
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip

+ 11 - 0
spine-flutter/example/android/settings.gradle

@@ -0,0 +1,11 @@
+include ':app'
+
+def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
+def properties = new Properties()
+
+assert localPropertiesFile.exists()
+localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
+
+def flutterSdkPath = properties.getProperty("flutter.sdk")
+assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
+apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"

+ 409 - 0
spine-flutter/example/assets/chibi/chibi-stickers.atlas

@@ -0,0 +1,409 @@
+chibi-stickers.webp
+size:2017,491
+filter:Linear,Linear
+scale:0.5
+common/angry-mark
+bounds:1801,65,42,41
+common/big-purple-fear
+bounds:1640,212,134,71
+offsets:0,0,134,72
+rotate:90
+common/big-tear
+bounds:1454,15,33,82
+common/eye-3
+bounds:1611,2,15,26
+rotate:90
+common/eye-closed-happy
+bounds:1685,348,25,9
+common/eye-dafault
+bounds:1993,51,22,21
+common/eye-equal
+bounds:1271,146,25,15
+common/eye-fire
+bounds:1673,49,26,28
+common/eye-half-open
+bounds:1475,101,26,16
+rotate:90
+common/eye-heart
+bounds:1094,2,26,23
+rotate:90
+common/eye-reverse-v
+bounds:1945,26,26,16
+common/eye-sideway-v
+bounds:945,2,21,23
+rotate:90
+common/eye-slant-close
+bounds:321,72,23,16
+common/eye-small-dot
+bounds:1120,146,14,14
+offsets:0,1,15,15
+common/eye-sparkle
+bounds:1810,4,30,29
+rotate:90
+common/eye-star
+bounds:534,235,29,27
+rotate:90
+common/eye-twirl
+bounds:970,2,21,23
+rotate:90
+common/eye-u
+bounds:733,238,24,17
+rotate:90
+common/eye-x
+bounds:1993,74,25,22
+rotate:90
+common/lamp
+bounds:1319,2,47,65
+common/mouth-3
+bounds:1581,2,15,28
+rotate:90
+common/mouth-bracket
+bounds:1450,2,34,11
+common/mouth-doubt
+bounds:1639,2,26,15
+common/mouth-fangs
+bounds:549,300,39,14
+rotate:90
+common/mouth-line
+bounds:1601,212,36,7
+common/mouth-neutral
+bounds:807,2,27,12
+common/mouth-o-tall
+bounds:1993,101,22,33
+common/mouth-open-smile
+bounds:359,33,36,22
+rotate:90
+common/mouth-rectangle
+bounds:875,2,35,21
+common/mouth-reverse-v
+bounds:1368,2,27,10
+common/mouth-s
+bounds:2003,262,41,11
+rotate:90
+common/mouth-smile-little
+bounds:1928,71,33,19
+rotate:90
+common/mouth-toungue-sticking-out
+bounds:912,2,31,21
+common/mouth-u
+bounds:383,33,36,19
+rotate:90
+common/mouth-v
+bounds:563,235,27,14
+rotate:90
+common/mouth-x
+bounds:1944,4,21,20
+common/purple-fear-lines
+bounds:1807,108,48,28
+common/shadow
+bounds:359,2,111,29
+offsets:1,1,113,31
+common/small-drop-line
+bounds:1925,22,16,17
+rotate:90
+common/small-purple-fear
+bounds:1941,451,54,38
+common/tear
+bounds:995,3,20,19
+rotate:90
+erikari/arm
+bounds:1383,99,28,90
+rotate:90
+erikari/arm-shoulder-decoration
+bounds:1765,2,32,43
+rotate:90
+erikari/back-hair
+bounds:565,348,158,141
+erikari/back-hair-long
+bounds:2,235,220,254
+erikari/blush
+bounds:555,43,29,18
+rotate:90
+erikari/body
+bounds:575,2,70,98
+rotate:90
+erikari/bracelet
+bounds:1841,2,33,11
+rotate:90
+erikari/collar
+bounds:1320,99,61,62
+erikari/ear
+bounds:105,2,34,42
+rotate:90
+erikari/eyebrow
+bounds:2003,241,19,12
+offsets:0,0,20,12
+rotate:90
+erikari/hair-front
+bounds:517,103,130,65
+rotate:90
+erikari/hair-side
+bounds:1137,176,43,132
+rotate:90
+erikari/hat-border
+bounds:1685,450,254,39
+erikari/hat-top
+bounds:346,71,160,60
+rotate:90
+erikari/head-base
+bounds:1060,221,143,125
+erikari/leg
+bounds:2,8,28,101
+rotate:90
+erikari/leg-decoration
+bounds:1412,2,36,13
+erikari/skirt
+bounds:224,233,164,101
+erikari/strawberries-decoration
+bounds:1271,163,112,56
+harri/arm
+bounds:1320,69,28,90
+rotate:90
+harri/back-hair
+bounds:725,348,158,141
+harri/back-hair-long
+bounds:1412,17,40,80
+harri/beard
+bounds:1397,2,10,11
+rotate:90
+harri/blush
+bounds:1240,156,29,18
+luke/blush
+bounds:1240,156,29,18
+nate/blush
+bounds:1240,156,29,18
+spineboy/blush
+bounds:1240,156,29,18
+harri/body
+bounds:675,2,70,98
+rotate:90
+harri/body-decoration
+bounds:287,2,70,67
+harri/ear
+bounds:149,2,34,42
+rotate:90
+soeren/ear
+bounds:149,2,34,42
+rotate:90
+spineboy/ear
+bounds:149,2,34,42
+rotate:90
+harri/eyebrow
+bounds:2003,305,22,12
+rotate:90
+harri/hair-front
+bounds:1866,358,143,90
+harri/head-base
+bounds:1205,221,143,125
+luke/head-base
+bounds:1205,221,143,125
+soeren/head-base
+bounds:1205,221,143,125
+spineboy/head-base
+bounds:1205,221,143,125
+harri/leg
+bounds:1017,132,28,101
+rotate:90
+harri/sword
+bounds:565,264,185,82
+luke/arm
+bounds:1489,71,28,90
+rotate:90
+luke/arm-shoulder-decoration
+bounds:1801,36,31,27
+luke/back-hair
+bounds:885,348,158,141
+luke/body
+bounds:775,16,70,98
+rotate:90
+luke/eyebrow
+bounds:836,2,27,12
+nate/eyebrow
+bounds:836,2,27,12
+spineboy/eyebrow
+bounds:836,2,27,12
+luke/face-cover
+bounds:224,336,169,153
+luke/glasses-shadow
+bounds:584,181,147,81
+luke/hair-decoration
+bounds:408,103,130,107
+rotate:90
+luke/hair-front
+bounds:1013,162,122,57
+luke/leg
+bounds:1016,30,28,101
+rotate:90
+luke/shield
+bounds:1495,131,88,104
+rotate:90
+luke/skirt
+bounds:1845,73,81,31
+luke/sword
+bounds:1601,139,102,71
+offsets:0,0,104,71
+mario/arm
+bounds:1489,41,28,90
+rotate:90
+mario/back-hair
+bounds:395,341,168,148
+mario/back-hair-long
+bounds:194,2,86,91
+rotate:90
+mario/beard
+bounds:1858,136,147,93
+mario/blush
+bounds:1854,17,29,18
+mario/body
+bounds:1018,60,70,98
+rotate:90
+mario/ear
+bounds:1949,100,34,42
+rotate:90
+mario/eyebrow
+bounds:287,71,32,17
+mario/hair-front
+bounds:874,158,137,66
+mario/head-base
+bounds:1350,221,143,125
+mario/leg
+bounds:1137,146,28,101
+rotate:90
+misaki/arm
+bounds:1489,11,28,90
+rotate:90
+misaki/back-hair
+bounds:1045,348,158,141
+misaki/back-hair-long
+bounds:2,38,190,195
+misaki/belt
+bounds:1016,2,76,26
+misaki/blush
+bounds:1925,40,29,18
+rotate:90
+misaki/body
+bounds:1701,36,70,98
+rotate:90
+misaki/ear
+bounds:1949,64,34,42
+rotate:90
+misaki/eyebrow
+bounds:775,2,30,12
+misaki/glasses
+bounds:875,72,141,35
+misaki/glasses-side
+bounds:1240,146,8,23
+rotate:90
+misaki/hair-front
+bounds:733,88,140,59
+misaki/hair-side
+bounds:875,109,47,140
+rotate:90
+misaki/head-base
+bounds:1495,221,143,125
+misaki/leg
+bounds:1601,109,28,101
+rotate:90
+misaki/skirt
+bounds:1385,129,108,90
+nate/arm
+bounds:1581,49,28,90
+rotate:90
+nate/back-hair
+bounds:1205,348,158,141
+nate/beard
+bounds:584,111,147,68
+nate/body
+bounds:1120,74,70,98
+rotate:90
+nate/ear
+bounds:1845,37,34,42
+rotate:90
+nate/glasses
+bounds:584,74,141,35
+nate/glasses-side
+bounds:555,33,8,16
+rotate:90
+nate/hair-front
+bounds:390,235,142,65
+nate/head-base
+bounds:1713,232,143,125
+nate/leg
+bounds:1704,108,28,101
+rotate:90
+sinisa/arm
+bounds:1581,19,28,90
+rotate:90
+sinisa/back-hair
+bounds:1365,348,158,141
+sinisa/beard
+bounds:875,25,139,45
+sinisa/blush
+bounds:1945,44,29,18
+sinisa/body
+bounds:1119,2,70,98
+rotate:90
+sinisa/body-decoration
+bounds:555,74,27,27
+sinisa/ear
+bounds:1889,29,34,42
+sinisa/eyebrow
+bounds:1997,451,38,18
+offsets:0,0,38,19
+rotate:90
+sinisa/hair-front
+bounds:1713,138,143,92
+sinisa/head-base
+bounds:1858,231,143,125
+sinisa/leg
+bounds:1495,101,28,101
+rotate:90
+soeren/arm
+bounds:1673,6,28,90
+rotate:90
+soeren/back-hair
+bounds:194,90,150,141
+soeren/beard
+bounds:408,33,145,68
+soeren/blush
+bounds:1885,9,29,18
+soeren/body
+bounds:1219,2,70,98
+rotate:90
+soeren/eyebrow
+bounds:2003,329,27,12
+rotate:90
+soeren/glasses
+bounds:395,302,152,37
+soeren/glasses-side
+bounds:1486,2,7,20
+rotate:90
+soeren/glove
+bounds:1368,14,42,53
+soeren/hair-front
+bounds:752,233,159,113
+soeren/leg
+bounds:1598,79,28,101
+rotate:90
+spineboy/arm
+bounds:1857,106,28,90
+rotate:90
+spineboy/arm-decoration
+bounds:534,266,32,29
+rotate:90
+spineboy/arm-shoulder-decoration
+bounds:1973,19,23,23
+spineboy/back-hair
+bounds:1525,348,158,141
+spineboy/body
+bounds:1220,74,70,98
+rotate:90
+spineboy/glasses
+bounds:1685,359,179,89
+spineboy/glasses-shadow
+bounds:733,149,139,82
+spineboy/hair-front
+bounds:913,226,145,120
+spineboy/leg
+bounds:472,2,29,101
+rotate:90

BIN
spine-flutter/example/assets/chibi/chibi-stickers.skel


BIN
spine-flutter/example/assets/chibi/chibi-stickers.webp


BIN
spine-flutter/example/assets/dragon-ess.skel


+ 123 - 0
spine-flutter/example/assets/dragon.atlas

@@ -0,0 +1,123 @@
+dragon.png
+	size: 1024, 1024
+	filter: Linear, Linear
+back
+	bounds: 564, 534, 190, 185
+chest
+	bounds: 2, 645, 136, 122
+chin
+	bounds: 140, 619, 214, 146
+front-toe-a
+	bounds: 2, 862, 29, 50
+	rotate: 90
+front-toe-b
+	bounds: 467, 835, 56, 57
+	rotate: 90
+head
+	bounds: 756, 398, 296, 260
+	rotate: 90
+left-front-leg
+	bounds: 599, 834, 84, 57
+left-front-thigh
+	bounds: 782, 819, 84, 72
+left-rear-leg
+	bounds: 356, 558, 206, 177
+left-rear-thigh
+	bounds: 216, 767, 91, 149
+	rotate: 90
+left-wing01
+	bounds: 2, 268, 264, 589
+	rotate: 90
+left-wing02
+	bounds: 2, 2, 264, 589
+	rotate: 90
+right-front-leg
+	bounds: 113, 769, 101, 89
+right-front-thigh
+	bounds: 758, 709, 108, 108
+right-rear-leg
+	bounds: 640, 721, 116, 100
+right-rear-thigh
+	bounds: 367, 742, 91, 149
+	rotate: 90
+right-rear-toe
+	bounds: 2, 781, 109, 77
+tail01
+	bounds: 868, 696, 120, 153
+	rotate: 90
+tail02
+	bounds: 518, 737, 95, 120
+	rotate: 90
+tail03
+	bounds: 868, 818, 73, 92
+	rotate: 90
+tail04
+	bounds: 526, 835, 56, 71
+	rotate: 90
+tail05
+	bounds: 406, 839, 52, 59
+	rotate: 90
+tail06
+	bounds: 685, 823, 95, 68
+thiagobrayner
+	bounds: 54, 860, 350, 31
+
+dragon_2.png
+	size: 1024, 1024
+	filter: Linear, Linear
+left-wing03
+	bounds: 2, 534, 264, 589
+	rotate: 90
+left-wing04
+	bounds: 2, 268, 264, 589
+	rotate: 90
+left-wing05
+	bounds: 593, 209, 264, 589
+left-wing06
+	bounds: 2, 2, 264, 589
+	rotate: 90
+
+dragon_3.png
+	size: 1024, 1024
+	filter: Linear, Linear
+left-wing07
+	bounds: 2, 694, 264, 589
+	rotate: 90
+left-wing08
+	bounds: 2, 428, 264, 589
+	rotate: 90
+left-wing09
+	bounds: 593, 369, 264, 589
+right-wing01
+	bounds: 2, 2, 365, 643
+	rotate: 90
+
+dragon_4.png
+	size: 1024, 1024
+	filter: Linear, Linear
+right-wing02
+	bounds: 2, 369, 365, 643
+right-wing03
+	bounds: 369, 369, 365, 643
+right-wing04
+	bounds: 2, 2, 365, 643
+	rotate: 90
+
+dragon_5.png
+	size: 1024, 1024
+	filter: Linear, Linear
+right-wing05
+	bounds: 2, 369, 365, 643
+right-wing06
+	bounds: 369, 369, 365, 643
+right-wing07
+	bounds: 2, 2, 365, 643
+	rotate: 90
+
+dragon_6.png
+	size: 1024, 1024
+	filter: Linear, Linear
+right-wing08
+	bounds: 2, 2, 365, 643
+right-wing09
+	bounds: 369, 2, 365, 643

BIN
spine-flutter/example/assets/dragon.png


BIN
spine-flutter/example/assets/dragon_2.png


BIN
spine-flutter/example/assets/dragon_3.png


BIN
spine-flutter/example/assets/dragon_4.png


BIN
spine-flutter/example/assets/dragon_5.png


BIN
spine-flutter/example/assets/dragon_6.png


BIN
spine-flutter/example/assets/mix-and-match-pro.skel


+ 362 - 0
spine-flutter/example/assets/mix-and-match.atlas

@@ -0,0 +1,362 @@
+mix-and-match.png
+	size: 1024, 512
+	filter: Linear, Linear
+	scale: 0.5
+base-head
+	bounds: 587, 2, 95, 73
+boy/arm-front
+	bounds: 558, 271, 36, 115
+boy/backpack
+	bounds: 235, 109, 119, 153
+boy/backpack-pocket
+	bounds: 328, 73, 34, 62
+	rotate: 90
+boy/backpack-strap-front
+	bounds: 665, 79, 38, 88
+boy/backpack-up
+	bounds: 395, 364, 21, 70
+	rotate: 90
+boy/body
+	bounds: 251, 264, 97, 132
+	rotate: 90
+boy/boot-ribbon-front
+	bounds: 648, 131, 9, 11
+boy/collar
+	bounds: 744, 4, 73, 29
+	rotate: 90
+boy/ear
+	bounds: 383, 109, 19, 23
+	rotate: 90
+boy/eye-back-low-eyelid
+	bounds: 739, 284, 17, 6
+	rotate: 90
+boy/eye-back-pupil
+	bounds: 832, 443, 8, 9
+	rotate: 90
+boy/eye-back-up-eyelid
+	bounds: 558, 264, 23, 5
+boy/eye-back-up-eyelid-back
+	bounds: 802, 491, 19, 10
+	rotate: 90
+boy/eye-front-low-eyelid
+	bounds: 386, 363, 22, 7
+	rotate: 90
+boy/eye-front-pupil
+	bounds: 816, 389, 9, 9
+boy/eye-front-up-eyelid
+	bounds: 160, 71, 31, 6
+	rotate: 90
+boy/eye-front-up-eyelid-back
+	bounds: 801, 434, 26, 9
+	rotate: 90
+boy/eye-iris-back
+	bounds: 618, 264, 17, 17
+boy/eye-iris-front
+	bounds: 727, 264, 18, 18
+boy/eye-white-back
+	bounds: 580, 131, 20, 12
+boy/eye-white-front
+	bounds: 510, 130, 27, 13
+boy/eyebrow-back
+	bounds: 751, 88, 20, 11
+	rotate: 90
+boy/eyebrow-front
+	bounds: 483, 130, 25, 11
+boy/hair-back
+	bounds: 494, 388, 122, 81
+	rotate: 90
+boy/hair-bangs
+	bounds: 667, 284, 70, 37
+boy/hair-side
+	bounds: 789, 374, 25, 43
+boy/hand-backfingers
+	bounds: 467, 364, 19, 21
+boy/hand-front-fingers
+	bounds: 488, 364, 19, 21
+boy/hat
+	bounds: 615, 417, 93, 56
+	rotate: 90
+boy/leg-front
+	bounds: 138, 104, 31, 158
+boy/mouth-close
+	bounds: 551, 365, 21, 5
+	rotate: 90
+girl-blue-cape/mouth-close
+	bounds: 551, 365, 21, 5
+	rotate: 90
+girl-spring-dress/mouth-close
+	bounds: 551, 365, 21, 5
+	rotate: 90
+girl/mouth-close
+	bounds: 551, 365, 21, 5
+	rotate: 90
+boy/mouth-smile
+	bounds: 705, 79, 29, 7
+boy/nose
+	bounds: 836, 473, 17, 10
+	rotate: 90
+boy/pompom
+	bounds: 747, 273, 48, 43
+	rotate: 90
+boy/zip
+	bounds: 648, 144, 14, 23
+girl-blue-cape/back-eyebrow
+	bounds: 602, 131, 18, 12
+girl-blue-cape/body-dress
+	bounds: 2, 264, 109, 246
+girl-blue-cape/body-ribbon
+	bounds: 615, 283, 50, 38
+girl-blue-cape/cape-back
+	bounds: 2, 69, 134, 193
+girl-blue-cape/cape-back-up
+	bounds: 386, 387, 123, 106
+	rotate: 90
+girl-blue-cape/cape-ribbon
+	bounds: 675, 264, 50, 18
+girl-blue-cape/cape-shoulder-back
+	bounds: 751, 110, 49, 59
+girl-blue-cape/cape-shoulder-front
+	bounds: 113, 264, 62, 76
+	rotate: 90
+girl-blue-cape/cape-up-front
+	bounds: 399, 264, 98, 117
+	rotate: 90
+girl-blue-cape/ear
+	bounds: 775, 2, 19, 23
+girl-spring-dress/ear
+	bounds: 775, 2, 19, 23
+girl/ear
+	bounds: 775, 2, 19, 23
+girl-blue-cape/eye-back-low-eyelid
+	bounds: 802, 463, 17, 6
+girl-spring-dress/eye-back-low-eyelid
+	bounds: 802, 463, 17, 6
+girl/eye-back-low-eyelid
+	bounds: 802, 463, 17, 6
+girl-blue-cape/eye-back-pupil
+	bounds: 816, 367, 8, 9
+girl-spring-dress/eye-back-pupil
+	bounds: 816, 367, 8, 9
+girl/eye-back-pupil
+	bounds: 816, 367, 8, 9
+girl-blue-cape/eye-back-up-eyelid
+	bounds: 554, 131, 24, 12
+girl-spring-dress/eye-back-up-eyelid
+	bounds: 554, 131, 24, 12
+girl/eye-back-up-eyelid
+	bounds: 554, 131, 24, 12
+girl-blue-cape/eye-back-up-eyelid-back
+	bounds: 832, 453, 17, 11
+	rotate: 90
+girl-spring-dress/eye-back-up-eyelid-back
+	bounds: 832, 453, 17, 11
+	rotate: 90
+girl/eye-back-up-eyelid-back
+	bounds: 832, 453, 17, 11
+	rotate: 90
+girl-blue-cape/eye-front-low-eyelid
+	bounds: 739, 303, 18, 6
+	rotate: 90
+girl-spring-dress/eye-front-low-eyelid
+	bounds: 739, 303, 18, 6
+	rotate: 90
+girl/eye-front-low-eyelid
+	bounds: 739, 303, 18, 6
+	rotate: 90
+girl-blue-cape/eye-front-pupil
+	bounds: 816, 378, 9, 9
+girl-spring-dress/eye-front-pupil
+	bounds: 816, 378, 9, 9
+girl/eye-front-pupil
+	bounds: 816, 378, 9, 9
+girl-blue-cape/eye-front-up-eyelid
+	bounds: 392, 77, 30, 14
+	rotate: 90
+girl-spring-dress/eye-front-up-eyelid
+	bounds: 392, 77, 30, 14
+	rotate: 90
+girl/eye-front-up-eyelid
+	bounds: 392, 77, 30, 14
+	rotate: 90
+girl-blue-cape/eye-front-up-eyelid-back
+	bounds: 455, 130, 26, 11
+girl-spring-dress/eye-front-up-eyelid-back
+	bounds: 455, 130, 26, 11
+girl/eye-front-up-eyelid-back
+	bounds: 455, 130, 26, 11
+girl-blue-cape/eye-iris-back
+	bounds: 637, 264, 17, 17
+girl-blue-cape/eye-iris-front
+	bounds: 802, 471, 18, 18
+girl-blue-cape/eye-white-back
+	bounds: 596, 264, 20, 16
+girl-spring-dress/eye-white-back
+	bounds: 596, 264, 20, 16
+girl-blue-cape/eye-white-front
+	bounds: 796, 5, 20, 16
+	rotate: 90
+girl-spring-dress/eye-white-front
+	bounds: 796, 5, 20, 16
+	rotate: 90
+girl/eye-white-front
+	bounds: 796, 5, 20, 16
+	rotate: 90
+girl-blue-cape/front-eyebrow
+	bounds: 608, 149, 18, 12
+	rotate: 90
+girl-blue-cape/hair-back
+	bounds: 508, 145, 117, 98
+	rotate: 90
+girl-blue-cape/hair-bangs
+	bounds: 673, 419, 91, 40
+	rotate: 90
+girl-blue-cape/hair-head-side-back
+	bounds: 196, 331, 30, 52
+	rotate: 90
+girl-blue-cape/hair-head-side-front
+	bounds: 738, 323, 41, 42
+girl-blue-cape/hair-side
+	bounds: 473, 3, 36, 71
+girl-blue-cape/hand-front-fingers
+	bounds: 509, 365, 19, 21
+girl-spring-dress/hand-front-fingers
+	bounds: 509, 365, 19, 21
+girl-blue-cape/leg-front
+	bounds: 168, 72, 30, 158
+	rotate: 90
+girl-blue-cape/mouth-smile
+	bounds: 736, 79, 29, 7
+girl-spring-dress/mouth-smile
+	bounds: 736, 79, 29, 7
+girl/mouth-smile
+	bounds: 736, 79, 29, 7
+girl-blue-cape/nose
+	bounds: 747, 264, 11, 7
+girl-spring-dress/nose
+	bounds: 747, 264, 11, 7
+girl/nose
+	bounds: 747, 264, 11, 7
+girl-blue-cape/sleeve-back
+	bounds: 767, 79, 42, 29
+girl-blue-cape/sleeve-front
+	bounds: 408, 76, 52, 119
+	rotate: 90
+girl-spring-dress/arm-front
+	bounds: 596, 282, 17, 111
+girl-spring-dress/back-eyebrow
+	bounds: 801, 420, 18, 12
+girl-spring-dress/body-up
+	bounds: 179, 4, 64, 66
+girl-spring-dress/cloak-down
+	bounds: 775, 27, 50, 50
+girl-spring-dress/cloak-up
+	bounds: 360, 7, 64, 58
+	rotate: 90
+girl-spring-dress/eye-iris-back
+	bounds: 656, 264, 17, 17
+girl-spring-dress/eye-iris-front
+	bounds: 814, 492, 18, 18
+girl-spring-dress/front-eyebrow
+	bounds: 822, 472, 18, 12
+	rotate: 90
+girl-spring-dress/hair-back
+	bounds: 196, 363, 147, 93
+	rotate: 90
+girl-spring-dress/hair-bangs
+	bounds: 696, 326, 91, 40
+	rotate: 90
+girl-spring-dress/hair-head-side-back
+	bounds: 529, 76, 30, 52
+girl-spring-dress/hair-head-side-front
+	bounds: 781, 323, 41, 42
+girl-spring-dress/hair-side
+	bounds: 511, 3, 36, 71
+girl-spring-dress/leg-front
+	bounds: 171, 104, 30, 158
+girl-spring-dress/neck
+	bounds: 138, 70, 20, 32
+girl-spring-dress/shoulder-ribbon
+	bounds: 622, 131, 36, 24
+	rotate: 90
+girl-spring-dress/skirt
+	bounds: 113, 328, 182, 81
+	rotate: 90
+girl-spring-dress/underskirt
+	bounds: 2, 2, 175, 65
+girl/arm-front
+	bounds: 577, 395, 36, 115
+girl/back-eyebrow
+	bounds: 834, 492, 18, 12
+	rotate: 90
+girl/bag-base
+	bounds: 191, 264, 62, 58
+	rotate: 90
+girl/bag-strap-front
+	bounds: 385, 265, 12, 96
+girl/bag-top
+	bounds: 738, 367, 49, 50
+girl/body
+	bounds: 356, 130, 97, 132
+girl/boot-ribbon-front
+	bounds: 539, 130, 13, 13
+girl/eye-iris-back
+	bounds: 821, 424, 17, 17
+girl/eye-iris-front
+	bounds: 812, 443, 18, 18
+girl/eye-white-back
+	bounds: 814, 5, 20, 16
+	rotate: 90
+girl/front-eyebrow
+	bounds: 816, 400, 18, 12
+	rotate: 90
+girl/hair-back
+	bounds: 291, 363, 147, 93
+	rotate: 90
+girl/hair-bangs
+	bounds: 715, 419, 91, 40
+	rotate: 90
+girl/hair-flap-down-front
+	bounds: 288, 5, 70, 65
+girl/hair-head-side-back
+	bounds: 561, 77, 30, 52
+girl/hair-head-side-front
+	bounds: 757, 419, 41, 42
+	rotate: 90
+girl/hair-patch
+	bounds: 245, 4, 66, 41
+	rotate: 90
+girl/hair-side
+	bounds: 549, 3, 36, 71
+girl/hair-strand-back-1
+	bounds: 684, 3, 58, 74
+girl/hair-strand-back-2
+	bounds: 692, 171, 91, 58
+	rotate: 90
+girl/hair-strand-back-3
+	bounds: 615, 323, 92, 79
+	rotate: 90
+girl/hair-strand-front-1
+	bounds: 518, 269, 38, 94
+girl/hair-strand-front-2
+	bounds: 593, 79, 70, 50
+girl/hair-strand-front-3
+	bounds: 705, 88, 44, 81
+girl/hand-front-fingers
+	bounds: 530, 365, 19, 21
+girl/hat
+	bounds: 608, 169, 93, 82
+	rotate: 90
+girl/leg-front
+	bounds: 203, 104, 30, 158
+girl/pompom
+	bounds: 757, 462, 48, 43
+	rotate: 90
+girl/scarf
+	bounds: 455, 143, 119, 51
+	rotate: 90
+girl/scarf-back
+	bounds: 420, 2, 72, 51
+	rotate: 90
+girl/zip
+	bounds: 356, 109, 19, 25
+	rotate: 90

BIN
spine-flutter/example/assets/mix-and-match.png


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