├── docs
├── index.md
├── images
│ ├── warn.jpg
│ └── SpineExportSettings.png
└── LiveDemo
│ ├── character.png
│ ├── icons
│ ├── icon-16.png
│ ├── icon-32.png
│ ├── icon-64.png
│ ├── icon-128.png
│ ├── icon-256.png
│ ├── icon-512.png
│ └── loading-logo.png
│ ├── images
│ ├── shared-0-sheet0.png
│ ├── shared-0-sheet1.png
│ └── shared-0-sheet2.png
│ ├── scripts
│ ├── register-sw.js
│ ├── offlineclient.js
│ ├── workermain.js
│ ├── supportcheck.js
│ ├── jobworker.js
│ └── dispatchworker.js
│ ├── offline.json
│ ├── style.css
│ ├── appmanifest.json
│ ├── index.html
│ ├── sw.js
│ ├── data.json
│ └── character.atlas
├── placeHolder.ts
├── _config.yml
├── .vscode
└── settings.json
├── release.sh
├── dist
├── Spine-v1.0.0.c3addon
├── Spine-v1.1.0.c3addon
├── Spine-v1.10.0.c3addon
├── Spine-v1.11.0.c3addon
├── Spine-v1.11.1.c3addon
├── Spine-v1.11.2.c3addon
├── Spine-v1.12.0.c3addon
├── Spine-v1.12.1.c3addon
├── Spine-v1.13.0.c3addon
├── Spine-v1.14.0.c3addon
├── Spine-v1.14.1.c3addon
├── Spine-v1.15.0.c3addon
├── Spine-v1.15.1.c3addon
├── Spine-v1.15.2.c3addon
├── Spine-v1.16.0.c3addon
├── Spine-v1.16.1.c3addon
├── Spine-v1.16.2.c3addon
├── Spine-v1.16.3.c3addon
├── Spine-v1.17.0.c3addon
├── Spine-v1.18.0.c3addon
├── Spine-v1.19.0.c3addon
├── Spine-v1.2.0.c3addon
├── Spine-v1.20.0.c3addon
├── Spine-v1.21.0.c3addon
├── Spine-v1.21.1.c3addon
├── Spine-v1.21.2.c3addon
├── Spine-v1.22.0.c3addon
├── Spine-v1.22.1.c3addon
├── Spine-v1.22.2.c3addon
├── Spine-v1.23.0.c3addon
├── Spine-v1.24.0.c3addon
├── Spine-v1.25.0.c3addon
├── Spine-v1.25.1.c3addon
├── Spine-v1.25.2.c3addon
├── Spine-v1.25.3.c3addon
├── Spine-v1.26.0.c3addon
├── Spine-v1.26.1.c3addon
├── Spine-v1.27.0.c3addon
├── Spine-v1.27.1.c3addon
├── Spine-v1.27.2.c3addon
├── Spine-v1.27.3.c3addon
├── Spine-v1.3.0.c3addon
├── Spine-v1.30.0.c3addon
├── Spine-v1.30.1.c3addon
├── Spine-v1.31.0.c3addon
├── Spine-v1.31.1.c3addon
├── Spine-v1.32.0.c3addon
├── Spine-v1.33.0.c3addon
├── Spine-v1.33.1.c3addon
├── Spine-v1.34.0.c3addon
├── Spine-v1.34.1.c3addon
├── Spine-v1.34.2.c3addon
├── Spine-v1.35.0.c3addon
├── Spine-v1.36.0.c3addon
├── Spine-v1.36.1.c3addon
├── Spine-v1.36.2.c3addon
├── Spine-v1.36.3.c3addon
├── Spine-v1.36.4.c3addon
├── Spine-v1.36.5.c3addon
├── Spine-v1.36.6.c3addon
├── Spine-v1.36.7.c3addon
├── Spine-v1.36.8.c3addon
├── Spine-v1.36.9.c3addon
├── Spine-v1.37.0.c3addon
├── Spine-v1.38.0.c3addon
├── Spine-v1.39.0.c3addon
├── Spine-v1.39.1.c3addon
├── Spine-v1.4.0..c3addon
├── Spine-v1.4.1.c3addon
├── Spine-v1.4.2.c3addon
├── Spine-v1.4.3.c3addon
├── Spine-v1.4.4.c3addon
├── Spine-v1.4.5.c3addon
├── Spine-v1.4.6.c3addon
├── Spine-v1.40.0.c3addon
├── Spine-v1.41.0.c3addon
├── Spine-v1.41.1.c3addon
├── Spine-v1.41.2.c3addon
├── Spine-v1.42.0.c3addon
├── Spine-v1.43.0.c3addon
├── Spine-v1.44.0.c3addon
├── Spine-v1.45.0.c3addon
├── Spine-v1.46.0.c3addon
├── Spine-v1.47.0.c3addon
├── Spine-v1.47.1.c3addon
├── Spine-v1.47.2.c3addon
├── Spine-v1.47.3.c3addon
├── Spine-v1.47.4.c3addon
├── Spine-v1.47.5.c3addon
├── Spine-v1.48.0.c3addon
├── Spine-v1.49.0.c3addon
├── Spine-v1.5.0.c3addon
├── Spine-v1.50.0.c3addon
├── Spine-v1.50.1.c3addon
├── Spine-v1.50.2.c3addon
├── Spine-v1.51.0.c3addon
├── Spine-v1.51.1.c3addon
├── Spine-v1.52.0.c3addon
├── Spine-v1.53.0.c3addon
├── Spine-v1.54.0.c3addon
├── Spine-v1.55.0.c3addon
├── Spine-v1.55.1.c3addon
├── Spine-v1.6.0.c3addon
├── Spine-v1.7.0.c3addon
├── Spine-v1.8.0.c3addon
├── Spine-v1.9.0.c3addon
├── Spine-v2.0.0.c3addon
├── Spine-v2.0.1.c3addon
├── Spine-v2.1.0.c3addon
├── Spine-v2.2.0.c3addon
├── Spine-v2.3.0.c3addon
├── Spine-v2.3.1.c3addon
├── Spine-v2.4.0.c3addon
├── Spine-v2.5.0.c3addon
├── Spine-v2.6.0.c3addon
├── Spine-v2.6.1.c3addon
├── Spine-v2.6.2.c3addon
├── Spine-v2.7.0.c3addon
├── Spine-v2.7.1.c3addon
├── Spine-v2.8.0.c3addon
├── Spine-v2.8.2.c3addon
├── Spine-v2.8.3.c3addon
├── Spine-v2.8.4.c3addon
├── Spine-v2.9.0.c3addon
└── Spine-v2.9.1.c3addon
├── sample_projects
├── SpineMixandMatch.c3p
└── SpinePluginTest.c3p
├── src
├── type.js
├── c3runtime
│ ├── plugin.js
│ ├── type.js
│ ├── spine-bone-control.js
│ ├── spine-gl-cache.js
│ ├── conditions.js
│ ├── spine-palette.js
│ ├── expressions.js
│ ├── spine-draw.js
│ └── actions.js
├── addon.json
├── instance.js
└── plugin.js
├── tsconfig.json
├── LICENSE
├── Tracks.md
├── formatter
├── index.html
├── old.json
└── old_meshes.json
└── README.md
/docs/index.md:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/placeHolder.ts:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/_config.yml:
--------------------------------------------------------------------------------
1 | theme: jekyll-theme-midnight
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "editor.formatOnSave": false
3 | }
4 |
--------------------------------------------------------------------------------
/release.sh:
--------------------------------------------------------------------------------
1 | cd ./src
2 | zip -r ../dist/Spine-v$1.c3addon *
3 | cd ..
--------------------------------------------------------------------------------
/docs/images/warn.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/docs/images/warn.jpg
--------------------------------------------------------------------------------
/dist/Spine-v1.0.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.0.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.1.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.1.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.10.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.10.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.11.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.11.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.11.1.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.11.1.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.11.2.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.11.2.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.12.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.12.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.12.1.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.12.1.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.13.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.13.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.14.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.14.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.14.1.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.14.1.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.15.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.15.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.15.1.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.15.1.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.15.2.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.15.2.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.16.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.16.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.16.1.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.16.1.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.16.2.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.16.2.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.16.3.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.16.3.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.17.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.17.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.18.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.18.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.19.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.19.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.2.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.2.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.20.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.20.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.21.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.21.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.21.1.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.21.1.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.21.2.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.21.2.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.22.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.22.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.22.1.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.22.1.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.22.2.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.22.2.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.23.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.23.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.24.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.24.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.25.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.25.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.25.1.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.25.1.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.25.2.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.25.2.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.25.3.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.25.3.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.26.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.26.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.26.1.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.26.1.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.27.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.27.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.27.1.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.27.1.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.27.2.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.27.2.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.27.3.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.27.3.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.3.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.3.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.30.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.30.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.30.1.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.30.1.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.31.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.31.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.31.1.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.31.1.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.32.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.32.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.33.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.33.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.33.1.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.33.1.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.34.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.34.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.34.1.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.34.1.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.34.2.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.34.2.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.35.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.35.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.36.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.36.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.36.1.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.36.1.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.36.2.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.36.2.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.36.3.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.36.3.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.36.4.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.36.4.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.36.5.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.36.5.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.36.6.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.36.6.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.36.7.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.36.7.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.36.8.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.36.8.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.36.9.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.36.9.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.37.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.37.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.38.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.38.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.39.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.39.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.39.1.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.39.1.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.4.0..c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.4.0..c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.4.1.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.4.1.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.4.2.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.4.2.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.4.3.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.4.3.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.4.4.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.4.4.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.4.5.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.4.5.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.4.6.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.4.6.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.40.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.40.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.41.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.41.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.41.1.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.41.1.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.41.2.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.41.2.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.42.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.42.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.43.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.43.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.44.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.44.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.45.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.45.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.46.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.46.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.47.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.47.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.47.1.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.47.1.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.47.2.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.47.2.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.47.3.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.47.3.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.47.4.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.47.4.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.47.5.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.47.5.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.48.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.48.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.49.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.49.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.5.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.5.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.50.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.50.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.50.1.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.50.1.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.50.2.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.50.2.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.51.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.51.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.51.1.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.51.1.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.52.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.52.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.53.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.53.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.54.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.54.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.55.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.55.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.55.1.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.55.1.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.6.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.6.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.7.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.7.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.8.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.8.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v1.9.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v1.9.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v2.0.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v2.0.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v2.0.1.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v2.0.1.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v2.1.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v2.1.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v2.2.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v2.2.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v2.3.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v2.3.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v2.3.1.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v2.3.1.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v2.4.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v2.4.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v2.5.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v2.5.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v2.6.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v2.6.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v2.6.1.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v2.6.1.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v2.6.2.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v2.6.2.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v2.7.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v2.7.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v2.7.1.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v2.7.1.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v2.8.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v2.8.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v2.8.2.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v2.8.2.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v2.8.3.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v2.8.3.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v2.8.4.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v2.8.4.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v2.9.0.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v2.9.0.c3addon
--------------------------------------------------------------------------------
/dist/Spine-v2.9.1.c3addon:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/dist/Spine-v2.9.1.c3addon
--------------------------------------------------------------------------------
/docs/LiveDemo/character.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/docs/LiveDemo/character.png
--------------------------------------------------------------------------------
/docs/LiveDemo/icons/icon-16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/docs/LiveDemo/icons/icon-16.png
--------------------------------------------------------------------------------
/docs/LiveDemo/icons/icon-32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/docs/LiveDemo/icons/icon-32.png
--------------------------------------------------------------------------------
/docs/LiveDemo/icons/icon-64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/docs/LiveDemo/icons/icon-64.png
--------------------------------------------------------------------------------
/docs/LiveDemo/icons/icon-128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/docs/LiveDemo/icons/icon-128.png
--------------------------------------------------------------------------------
/docs/LiveDemo/icons/icon-256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/docs/LiveDemo/icons/icon-256.png
--------------------------------------------------------------------------------
/docs/LiveDemo/icons/icon-512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/docs/LiveDemo/icons/icon-512.png
--------------------------------------------------------------------------------
/docs/LiveDemo/icons/loading-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/docs/LiveDemo/icons/loading-logo.png
--------------------------------------------------------------------------------
/docs/images/SpineExportSettings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/docs/images/SpineExportSettings.png
--------------------------------------------------------------------------------
/sample_projects/SpineMixandMatch.c3p:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/sample_projects/SpineMixandMatch.c3p
--------------------------------------------------------------------------------
/sample_projects/SpinePluginTest.c3p:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/sample_projects/SpinePluginTest.c3p
--------------------------------------------------------------------------------
/docs/LiveDemo/images/shared-0-sheet0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/docs/LiveDemo/images/shared-0-sheet0.png
--------------------------------------------------------------------------------
/docs/LiveDemo/images/shared-0-sheet1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/docs/LiveDemo/images/shared-0-sheet1.png
--------------------------------------------------------------------------------
/docs/LiveDemo/images/shared-0-sheet2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gritsenko/c3_spine_plugin/HEAD/docs/LiveDemo/images/shared-0-sheet2.png
--------------------------------------------------------------------------------
/docs/LiveDemo/scripts/register-sw.js:
--------------------------------------------------------------------------------
1 | "use strict";window.C3_RegisterSW=async function(){if(navigator.serviceWorker)try{const a=await navigator.serviceWorker.register("sw.js",{scope:"./"});console.info("Registered service worker on "+a.scope)}catch(a){console.warn("Failed to register service worker: ",a)}};
--------------------------------------------------------------------------------
/src/type.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | {
3 | const C3 = self.C3;
4 |
5 | const PLUGIN_CLASS = SDK.Plugins.Gritsenko_Spine;
6 |
7 | PLUGIN_CLASS.Type = class SpineType extends SDK.ITypeBase
8 | {
9 | constructor(sdkPlugin, iObjectType)
10 | {
11 | super(sdkPlugin, iObjectType);
12 | }
13 | };
14 | }
--------------------------------------------------------------------------------
/src/c3runtime/plugin.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | {
3 | const C3 = self.C3;
4 |
5 | const DOM_COMPONENT_ID = "gritsenko-spine";
6 | //C3.Plugins.Gritsenko_Spine = class SpinePlugin extends C3.SDKDOMPluginBase
7 | C3.Plugins.Gritsenko_Spine = class SpinePlugin extends C3.SDKPluginBase {
8 | constructor(opts) {
9 | // super(opts);
10 | super(opts, DOM_COMPONENT_ID);
11 |
12 | }
13 |
14 | Release() {
15 | super.Release();
16 | }
17 | };
18 | }
--------------------------------------------------------------------------------
/docs/LiveDemo/offline.json:
--------------------------------------------------------------------------------
1 | {"version":1572343095362,"fileList":["scripts/c3runtime.js","data.json","style.css","scripts/offlineclient.js","images/shared-0-sheet0.png","images/shared-0-sheet1.png","images/shared-0-sheet2.png","scripts/main.js","scripts/dispatchworker.js","scripts/jobworker.js","scripts/workermain.js","scripts/supportcheck.js","icons/loading-logo.png","icons/icon-16.png","icons/icon-32.png","icons/icon-64.png","icons/icon-128.png","icons/icon-256.png","icons/icon-512.png","character.png","character.atlas","character.json","scripts/register-sw.js"]}
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es6",
4 | "allowJs": true,
5 | "checkJs": true,
6 | "moduleResolution": "node",
7 | "alwaysStrict": true,
8 | "strictNullChecks": false,
9 | "emitDeclarationOnly": true,
10 | "declaration": true,
11 | "outDir": "types",
12 | "removeComments": false
13 | },
14 | "files": [
15 | "placeHolder.ts",
16 | "src/c3runtime/instance.js",
17 | "src/c3runtime/spine-draw.js"
18 | ],
19 | "exclude": [
20 | "src/lang"
21 | ]
22 | }
--------------------------------------------------------------------------------
/docs/LiveDemo/scripts/offlineclient.js:
--------------------------------------------------------------------------------
1 | "use strict";{window.OfflineClientInfo=new class{constructor(){if(this._broadcastChannel="undefined"==typeof BroadcastChannel?null:new BroadcastChannel("offline"),this._queuedMessages=[],this._onMessageCallback=null,this._broadcastChannel){var a=this;this._broadcastChannel.onmessage=function(b){a._OnBroadcastChannelMessage(b)}}}_OnBroadcastChannelMessage(a){return this._onMessageCallback?void this._onMessageCallback(a):void this._queuedMessages.push(a)}SetMessageCallback(a){this._onMessageCallback=a;for(let b of this._queuedMessages)this._onMessageCallback(b);this._queuedMessages.length=0}}}
--------------------------------------------------------------------------------
/docs/LiveDemo/style.css:
--------------------------------------------------------------------------------
1 | html, body {
2 | padding: 0;
3 | margin: 0;
4 | overflow: hidden;
5 |
6 | background: #000000;
7 | color: white;
8 | }
9 |
10 | html, body, canvas {
11 | touch-action: none;
12 | touch-action-delay: none;
13 | }
14 |
15 | #notSupportedWrap {
16 | margin: 2em auto 1em auto;
17 | width: 75%;
18 | max-width: 45em;
19 | border: 2px solid #aaa;
20 | border-radius: 1em;
21 | padding: 2em;
22 | background-color: #f0f0f0;
23 | font-family: "Segoe UI", Frutiger, "Frutiger Linotype", "Dejavu Sans", "Helvetica Neue", Arial, sans-serif;
24 | color: black;
25 | }
26 |
27 | #notSupportedTitle {
28 | font-size: 1.8em;
29 | }
30 |
31 | .notSupportedMessage {
32 | font-size: 1.2em;
33 | }
34 |
35 | .notSupportedMessage em {
36 | color: #888;
37 | }
38 |
39 |
40 |
--------------------------------------------------------------------------------
/docs/LiveDemo/appmanifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "SpinePluginTest",
3 | "short_name": "SpinePluginTest",
4 | "description": "",
5 | "start_url": "index.html",
6 | "display": "fullscreen",
7 | "orientation": "landscape",
8 | "background_color": "#ffffff",
9 | "icons": [
10 | {
11 | "src": "icons/icon-16.png",
12 | "sizes": "16x16",
13 | "type": "image/png"
14 | },
15 | {
16 | "src": "icons/icon-32.png",
17 | "sizes": "32x32",
18 | "type": "image/png"
19 | },
20 | {
21 | "src": "icons/icon-64.png",
22 | "sizes": "64x64",
23 | "type": "image/png"
24 | },
25 | {
26 | "src": "icons/icon-128.png",
27 | "sizes": "128x128",
28 | "type": "image/png"
29 | },
30 | {
31 | "src": "icons/icon-256.png",
32 | "sizes": "256x256",
33 | "type": "image/png"
34 | },
35 | {
36 | "src": "icons/icon-512.png",
37 | "sizes": "512x512",
38 | "type": "image/png"
39 | }
40 | ]
41 | }
--------------------------------------------------------------------------------
/src/addon.json:
--------------------------------------------------------------------------------
1 | {
2 | "is-c3-addon": true,
3 | "type": "plugin",
4 | "name": "Spine",
5 | "id": "Gritsenko_Spine",
6 | "version": "2.9.1",
7 | "author": "Mikal and Igor Gritsenko",
8 | "website": "https://gritsenko.github.io/c3_spine_plugin",
9 | "documentation": "https://gritsenko.github.io/c3_spine_plugin",
10 | "description": "Spine addon - render to textures",
11 | "editor-scripts": [
12 | "plugin.js",
13 | "type.js",
14 | "instance.js"
15 | ],
16 | "file-list": [
17 | "c3runtime/plugin.js",
18 | "c3runtime/type.js",
19 | "c3runtime/instance.js",
20 | "c3runtime/conditions.js",
21 | "c3runtime/actions.js",
22 | "c3runtime/expressions.js",
23 | "c3runtime/spine-webgl.js",
24 | "c3runtime/spine-draw.js",
25 | "c3runtime/spine-gl-cache.js",
26 | "c3runtime/spine-palette.js",
27 | "c3runtime/spine-bone-control.js",
28 | "lang/en-US.json",
29 | "aces.json",
30 | "addon.json",
31 | "icon.svg",
32 | "instance.js",
33 | "plugin.js",
34 | "type.js"
35 | ]
36 | }
37 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Igor Gritsenko and MikalDev
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/docs/LiveDemo/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SpinePluginTest
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
This content requires JavaScript
24 |
JavaScript appears to be disabled. Please enable it to view this content.
25 |
This game was built in Construct - a free online game maker .
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/src/c3runtime/type.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | {
3 | const C3 = self.C3;
4 |
5 | C3.Plugins.Gritsenko_Spine.Type = class SpineType extends C3.SDKTypeBase
6 | {
7 | constructor(objectClass)
8 | {
9 | super(objectClass);
10 | }
11 |
12 | Release()
13 | {
14 | console.warn('[Spine] type.Release', this.GetObjectClass().GetName(), this._runtime.GetTickCount())
15 | super.Release();
16 | }
17 |
18 | OnCreate()
19 | {
20 | this.GetImageInfo().LoadAsset(this._runtime);
21 | this._skeletonDataInitialized = false;
22 | this._skeletonDataInitializing = false;
23 | this._skeletonJson = null;
24 | // Tag for asset manager for skeletonData assets.
25 | this._assetTag = null;
26 | // Skeleton instances to render
27 | this._skeletonInstances = {};
28 | this._rendered = false;
29 | this._tickCount = -1;
30 | this._assetPaths = {};
31 | this._initFailed = false;
32 | this._initOwner = -1;
33 | this._skeletonRenderQuality = 1;
34 | }
35 |
36 | LoadTextures(renderer)
37 | {
38 | return this.GetImageInfo().LoadStaticTexture(renderer,
39 | {
40 | linearSampling: this._runtime.IsLinearSampling()
41 | });
42 | }
43 |
44 | ReleaseTextures()
45 | {
46 | this.GetImageInfo().ReleaseTexture();
47 | }
48 | };
49 | }
--------------------------------------------------------------------------------
/Tracks.md:
--------------------------------------------------------------------------------
1 | # ACEs for adding track functionality
2 | ### 1.21.0 2020/12/04
3 |
4 | Developer manages animations and which track they are on.
5 | Specify track number for all ACEs as needed.
6 | {n} = parameter n
7 |
8 | Track number parameters will default to 0, so all current projects will continue to work as is.
9 |
10 | ## ACEs Changes
11 | ### Actions
12 | - *DONE* Set animation {0} start at {2}, (loop: {1}) on track {3}
13 | - *DONE* Set animation time in {0} to {1} on track {2}
14 | - *DONE* Delete animation on track {0} with mix {1}
15 | - *DONE* Set alpha on track {0}
16 |
17 | ### Expressions
18 | - *DONE* Get current animation name on track {0}
19 | - *DONE* Animation start time on track {0}
20 | - *DONE* Animation end time on track {0}
21 | - *DONE* Animation last time on track {0}
22 | - *DONE* Animation track time on track {0}
23 | - *DONE* Animation alpha on track {0}
24 |
25 | ### Conditions
26 | + *DONE* On animation {0} finished on track {1}
27 | + *DONE* On event {0} on track {1}
28 | + *DONE* Is animation {0} playing on track {1}
29 |
30 | ## Implementation notes
31 | - No change:
32 | - Play spine animation (stops all tracks)
33 | - Stop current spine animation (stops all tracks)
34 | - Set animation speed {0}x (all tracks)
35 |
36 | - For delete animation, use addEmptyAnimation or setEmptyAnimation with mix duration to blend, possibly add duration as parameter.
37 | - http://esotericsoftware.com/spine-api-reference#AnimationState-setEmptyAnimation
38 | - http://esotericsoftware.com/spine-api-reference#AnimationState-addEmptyAnimation
39 |
40 |
--------------------------------------------------------------------------------
/docs/LiveDemo/scripts/workermain.js:
--------------------------------------------------------------------------------
1 | "use strict";{async function a(a){if(c)throw new Error("already initialised");c=!0;const e=a["baseUrl"];self.devicePixelRatio=a["devicePixelRatio"];const f=a["workerDependencyScripts"].map((a)=>{let b=a;return b=a instanceof Blob?URL.createObjectURL(a):new URL(b,e).toString(),b}),g=[];self.runOnStartup=function(a){if("function"!=typeof a)throw new Error("runOnStartup called without a function");g.push(a)};const h=a["engineScripts"].map((a)=>new URL(a,e).toString());try{importScripts(...[...f,...h])}catch(a){return void console.error("[C3 runtime] Failed to load all engine scripts in worker: ",a)}const i=a["projectScripts"];if(i&&0a[1]))}catch(d){return console.error("[Preview] Error loading project scripts: ",d),void b(i,c,a["messagePort"])}}if(a["runOnStartupFunctions"]=g,"preview"===a["exportType"]&&"object"!=typeof self.C3.ScriptsInEvents){return console.error("[C3 runtime] Failed to load JavaScript code used in events. Check all your JavaScript code has valid syntax."),void a["messagePort"].postMessage({"type":"alert","message":"Failed to load JavaScript code used in events. Check all your JavaScript code has valid syntax."})}d=self["C3_CreateRuntime"](a),await self["C3_InitRuntime"](d,a)}function b(a,b,c){let d;for(const[e,f]of a)if(!b[e])try{importScripts(f)}catch(a){return d="scriptsInEvents.js"===e?"Failed to load JavaScript code used in events. Check all your JavaScript code has valid syntax.":`Failed to load project script '${e}'. Check all your JavaScript code has valid syntax.`,console.error("[Preview] "+d,a),void c.postMessage({"type":"alert","message":d})}}let c=!1,d=null;self.addEventListener("message",(b)=>{const c=b.data,d=c["type"];if("init-runtime"===d)a(c);else throw new Error(`unknown message '${d}'`)})}
--------------------------------------------------------------------------------
/docs/LiveDemo/scripts/supportcheck.js:
--------------------------------------------------------------------------------
1 | "use strict";(function(){var a=!!document.querySelector("script[src*=\"kaspersky\"]"),b=document.createElement("canvas"),c=!!(b.getContext("webgl")||b.getContext("experimental-webgl")),d=[];if(c||d.push("WebGL"),"undefined"==typeof WebAssembly&&d.push("WebAssembly"),0===d.length&&!a)window["C3_IsSupported"]=!0;else{var e=document.createElement("div");e.id="notSupportedWrap",document.body.appendChild(e);var f=document.createElement("h2");f.id="notSupportedTitle",f.textContent=a?"Kaspersky Internet Security broke this export":"Software update needed",e.appendChild(f);var g=document.createElement("p");g.className="notSupportedMessage";var h="This content is not supported because your device's software is out-of-date. ",i=navigator.userAgent;/android/i.test(i)?h+=" On Android, fix this by making sure the Android System Webview app has updates enabled and is up-to-date.":/iphone|ipad|ipod/i.test(i)?h+=" Note: the iOS simulator is not currently supported due to an Apple bug . If you are using the simulator, try testing on a real device instead.":(/msie/i.test(i)||/trident/i.test(i))&&!/edge\//i.test(i)?h+=" Note: Internet Explorer is not supported. Try using Chrome or Firefox instead.":a?h="It appears a script was added to this export by Kaspersky software. This prevents the exported project from working. Try disabling Kaspersky and exporting again.":h+="Try installing any available software updates. Alternatively try on a different device.",h+="Missing features: "+d.join(", ")+" User agent: "+navigator.userAgent+" ",g.innerHTML=h,e.appendChild(g)}})();
--------------------------------------------------------------------------------
/src/c3runtime/spine-bone-control.js:
--------------------------------------------------------------------------------
1 | // @ts-check
2 | "use strict";
3 |
4 | class SpineBoneControl {
5 | constructor(debug) {
6 | this._bones = {}
7 | this._debug = debug;
8 | }
9 |
10 | get bones() {return this._bones;}
11 | get debug() {return this._debug;}
12 |
13 | setBoneControl(bone, property, value) {
14 | if (!this.bones.hasOwnProperty(bone))
15 | {
16 | this.bones[bone] = {};
17 | this.bones[bone][property] = value;
18 | } else
19 | {
20 | this.bones[bone][property] = value;
21 | }
22 | }
23 |
24 | removeBoneControl(bone, property) {
25 | if (!this.bones.hasOwnProperty(bone) || !this.bones[bone].hasOwnProperty(property)) {console.warn('[Spine] removeBoneConrtol, no control', bone, property);return}
26 | delete this.bones[bone][property];
27 | }
28 |
29 | removeAllBoneControl(bone, property) {
30 | if (!this.bones.hasOwnProperty(bone)) {console.warn('[Spine] removeAllBoneConrtol, no contro', bone);return}
31 | delete this.bones[bone];
32 | }
33 |
34 | applyBoneControl(skeleton) {
35 | const bones = this.bones;
36 | for(let boneName in bones)
37 | {
38 | if(!bones[boneName].hasOwnProperty('__boneControlReference'))
39 | {
40 | let boneControlReference = skeleton.findBone(boneName);
41 | if (!boneControlReference) {console.warn('[Spine] applyBoneControl bone not found', boneName);continue;}
42 | // Cache reference
43 | bones[boneName].__boneControlReference = boneControlReference;
44 | }
45 |
46 | for(const property in bones[boneName])
47 | {
48 | // Ignore reference to bone
49 | if (property == '__boneControlReference') continue;
50 |
51 | bones[boneName].__boneControlReference[property] = bones[boneName][property];
52 | }
53 | }
54 | }
55 |
56 | }
57 |
58 | // @ts-ignore
59 | if (!globalThis.SpineBoneControl)
60 | {
61 | // @ts-ignore
62 | globalThis.SpineBoneControl = SpineBoneControl;
63 | }
64 |
--------------------------------------------------------------------------------
/docs/LiveDemo/scripts/jobworker.js:
--------------------------------------------------------------------------------
1 | "use strict";self.dispatchPort=null,self.outputPort=null,self.workerNumber=-1,self.activeJobId=null,self.sentBlobs=new Map,self.sentBuffers=new Map,self.JobHandlers={};function FlipImageData(a,b,c){const d=4*b,e=new Uint8Array(d),f=a.buffer;for(let g=0,h=Math.floor(c/2);g{const b=a.data,c=b["type"];return"init"===c?(self.workerNumber=b["number"],self.dispatchPort=b["dispatch-port"],self.dispatchPort.onmessage=OnDispatchWorkerMessage,void(self.outputPort=b["output-port"])):"terminate"===c?void self.close():void console.error("unknown message '"+c+"'")});function SendReady(){self.dispatchPort.postMessage({"type":"ready"}),self.outputPort.postMessage({"type":"ready"})}function SendError(a,b){a||self.outputPort.postMessage({"type":"error","jobId":self.activeJobId,"error":b.toString()}),SendDone()}function SendResult(a,b){if(!a){const a=b.transferables||[];self.outputPort.postMessage({"type":"result","jobId":self.activeJobId,"result":b.result},a)}SendDone()}function SendDone(){self.activeJobId=null,self.dispatchPort.postMessage({"type":"done"})}function SendProgress(a){self.outputPort.postMessage({"type":"progress","jobId":self.activeJobId,"progress":a})}function OnDispatchWorkerMessage(a){const b=a.data,c=b["type"];if("_import_scripts"===c)return void importScripts(...b["scripts"]);if("_send_blob"===c)return void self.sentBlobs.set(b["id"],b["blob"]);if("_send_buffer"===c)return void self.sentBuffers.set(b["id"],b["buffer"]);if("_testMessageChannel"===c)return void self.outputPort.postMessage({"type":"_testMessageChannelOk"});if("_ready"===c)return void SendReady();const d=b["jobId"],f=b["isBroadcast"],e=b["params"];let g;if(self.activeJobId=d,!self.JobHandlers.hasOwnProperty(c))return void console.error(`no handler for message type '${c}'`);try{g=self.JobHandlers[c](e)}catch(a){return void SendError(f,"Exception in job handler: "+a)}g&&g.then?g.then((a)=>SendResult(f,a)).catch((a)=>SendError(f,"Rejection in job handler: "+a)):SendResult(f,g)}
--------------------------------------------------------------------------------
/src/instance.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | {
3 | const C3 = self.C3;
4 |
5 | const PLUGIN_CLASS = SDK.Plugins.Gritsenko_Spine;
6 |
7 | PLUGIN_CLASS.Instance = class SpineInstance extends SDK.IWorldInstanceBase
8 | {
9 | constructor(sdkType, inst)
10 | {
11 | super(sdkType, inst);
12 | }
13 |
14 | Release()
15 | {}
16 |
17 | OnCreate()
18 | {
19 | }
20 |
21 | async LoadSpineFile(){
22 | }
23 |
24 | OnPlacedInLayout()
25 | {
26 | // Initialise to size of image
27 | this.OnMakeOriginalSize();
28 | }
29 |
30 | Draw(iRenderer, iDrawParams)
31 | {
32 | const texture = this.GetTexture();
33 |
34 | if (texture)
35 | {
36 | this._inst.ApplyBlendMode(iRenderer);
37 | iRenderer.SetTexture(texture);
38 | iRenderer.SetColor(this._inst.GetColor());
39 | iRenderer.Quad3(this._inst.GetQuad(), this.GetTexRect());
40 | }
41 | else
42 | {
43 | // render placeholder
44 | iRenderer.SetAlphaBlend();
45 | iRenderer.SetColorFillMode();
46 |
47 | if (this.HadTextureError()) iRenderer.SetColorRgba(0.25, 0, 0, 0.25);
48 | else iRenderer.SetColorRgba(0, 0, 0.1, 0.1);
49 |
50 | iRenderer.Quad(this._inst.GetQuad());
51 | }
52 | }
53 |
54 | GetTexture()
55 | {
56 | const image = this.GetObjectType().GetImage();
57 | return super.GetTexture(image);
58 | }
59 |
60 | IsOriginalSizeKnown()
61 | {
62 | return true;
63 | }
64 |
65 | GetOriginalWidth()
66 | {
67 | return this.GetObjectType().GetImage().GetWidth();
68 | }
69 |
70 | GetOriginalHeight()
71 | {
72 | return this.GetObjectType().GetImage().GetHeight();
73 | }
74 |
75 | OnMakeOriginalSize()
76 | {
77 | const image = this.GetObjectType().GetImage();
78 | this._inst.SetSize(image.GetWidth(), image.GetHeight());
79 | }
80 |
81 | HasDoubleTapHandler()
82 | {
83 | return true;
84 | }
85 |
86 | OnDoubleTap()
87 | {
88 | this.GetObjectType().EditImage();
89 | }
90 |
91 | OnPropertyChanged(id, value)
92 | {
93 | this.LoadSpineFile();
94 | }
95 |
96 | LoadC2Property(name, valueString)
97 | {
98 | return false; // not handled
99 | }
100 | };
101 | }
--------------------------------------------------------------------------------
/docs/LiveDemo/scripts/dispatchworker.js:
--------------------------------------------------------------------------------
1 | "use strict";self.inputPort=null,self.jobQueue=[],self.jobWorkers=[],self.sentBlobs=[],self.sentBuffers=[],self.importedScripts=[],self.lastBroadcasts=new Map;class JobWorker{constructor(a,b){this._port=a,this._number=b,this._isReady=!1,this._isBusy=!1,this._port.onmessage=(a)=>this._OnMessage(a.data)}ImportScripts(a){this._port.postMessage({"type":"_import_scripts","scripts":a})}SendBlob(a,b){this._port.postMessage({"type":"_send_blob","blob":a,"id":b})}SendBuffer(a,b){this._port.postMessage({"type":"_send_buffer","buffer":a,"id":b})}SendJob(a){if(this._isBusy||!this._isReady)throw new Error("cannot take job");this._isBusy=!0,this._port.postMessage(a,a["transferables"])}_InitBroadcast(a){this._port.postMessage(a,a["transferables"])}SendReady(){this._port.postMessage({"type":"_ready"})}IsReady(){return this._isReady}_OnReady(){this._isReady=!0,this.MaybeStartNextJob()}IsBusy(){return this._isBusy}GetNumber(){return this._number}_OnMessage(a){const b=a["type"];return"ready"===b?void this._OnReady():"done"===b?void this._OnJobDone():void console.error("unknown message from worker '"+b+"'")}_OnJobDone(){this._isBusy=!1,this.MaybeStartNextJob()}MaybeStartNextJob(){if(!this._isBusy&&this._isReady){const a=this._FindAvailableJob();if(-1!==a){const b=self.jobQueue[a],c=b["isBroadcast"];c?(b["doneFlags"][this._number]=!0,b["doneFlags"].every((a)=>a)&&self.jobQueue.splice(a,1)):self.jobQueue.splice(a,1),this.SendJob(b)}}}_FindAvailableJob(){for(let a=0,b=self.jobQueue.length;a{const b=a.data,c=b["type"];"_init"===c?(self.inputPort=b["in-port"],self.inputPort.onmessage=OnInputPortMessage):"_addJobWorker"===c&&AddJobWorker(b["port"])});function OnInputPortMessage(a){const b=a.data,c=b["type"];if("_cancel"===c)return void CancelJob(b.jobId);if("_import_scripts"===c){const a=b["scripts"];for(const b of self.jobWorkers)b.ImportScripts(a);return void self.importedScripts.push(a)}if("_send_blob"===c){const a=b["blob"],c=b["id"];for(const b of self.jobWorkers)b.SendBlob(a,c);return void self.sentBlobs.push([a,c])}if("_send_buffer"===c){const a=b["buffer"],c=b["id"];for(const b of self.jobWorkers)b.SendBuffer(a,c);return void self.sentBuffers.push([a,c])}if("_no_more_workers"===c)return self.sentBlobs.length=0,self.sentBuffers.length=0,self.importedScripts.length=0,void self.lastBroadcasts.clear();if("_testMessageChannel"===c)return void self.jobWorkers[0].TestMessageChannel();self.jobQueue.push(b),b["isBroadcast"]&&(b["doneFlags"]=Array(self.jobWorkers.length).fill(!1),b["transferables"]=[],self.lastBroadcasts.set(b["type"],b));for(const b of self.jobWorkers)b.MaybeStartNextJob()}
--------------------------------------------------------------------------------
/src/c3runtime/spine-gl-cache.js:
--------------------------------------------------------------------------------
1 | // @ts-check
2 | "use strict";
3 |
4 | class SpineGLCache {
5 | constructor(isWebGL2, gl) {
6 | this._oldFrameBuffer = null;
7 | this._extOESVAO = null;
8 | this._oldVAO = null;
9 | this._oldProgram = null;
10 | this._oldActive = null;
11 | this._oldTex = null;
12 | this._oldBinding = null;
13 | this._oldElement = null;
14 | this._oldClearColor = null;
15 | this._oldViewport = null;
16 | this._isWebGL2 = isWebGL2;
17 | this._gl = gl;
18 | this._scissor = null;
19 | this._scissorBox = null;
20 | }
21 |
22 | store() {
23 | // Save C3 webgl context
24 |
25 | const gl = this._gl;
26 | const isWebGL2 = this._isWebGL2;
27 |
28 | this._oldFrameBuffer = gl.getParameter(gl.FRAMEBUFFER_BINDING);
29 |
30 | // Save VAO (depends on gl version)
31 | if (!isWebGL2)
32 | {
33 | this._extOESVAO = gl.getExtension("OES_vertex_array_object");
34 | }
35 |
36 | if (isWebGL2)
37 | {
38 | this._oldVAO = gl.createVertexArray();
39 | this._oldVAO = gl.getParameter(gl.VERTEX_ARRAY_BINDING);
40 | } else
41 | {
42 | this._oldVAO = this._extOESVAO.createVertexArrayOES();
43 | this._oldVAO = gl.getParameter(this._extOESVAO.VERTEX_ARRAY_BINDING_OES);
44 | }
45 |
46 | // Save C3 wegl parameters to restore
47 | this._oldProgram = gl.getParameter(gl.CURRENT_PROGRAM);
48 | this._oldActive = gl.getParameter(gl.ACTIVE_TEXTURE);
49 | this._oldTex = gl.getParameter(gl.TEXTURE_BINDING_2D);
50 | this._oldBinding = gl.getParameter(gl.ARRAY_BUFFER_BINDING);
51 | this._oldElement = gl.getParameter(gl.ELEMENT_ARRAY_BUFFER_BINDING);
52 | this._oldClearColor = gl.getParameter(gl.COLOR_CLEAR_VALUE);
53 | this._oldViewport = gl.getParameter(gl.VIEWPORT);
54 | this._scissor = gl.getParameter(gl.SCISSOR_TEST);
55 | if (this._scissor) this._scissorBox = gl.getParameter(gl.SCISSOR_BOX);
56 | }
57 |
58 | restore() {
59 | const gl = this._gl;
60 |
61 | // Change back to C3 FB last used
62 | gl.bindFramebuffer(gl.FRAMEBUFFER, this._oldFrameBuffer);
63 |
64 | // Restore C3 webgl state
65 | gl.useProgram(this._oldProgram);
66 | if (this._isWebGL2)
67 | {
68 | gl.bindVertexArray(this._oldVAO);
69 | } else
70 | {
71 | this._extOESVAO.bindVertexArrayOES(this._oldVAO);
72 | }
73 | gl.activeTexture(this._oldActive);
74 | gl.bindTexture(gl.TEXTURE_2D, this._oldTex);
75 | gl.bindBuffer(gl.ARRAY_BUFFER, this._oldBinding);
76 | gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._oldElement);
77 | gl.clearColor(this._oldClearColor[0],this._oldClearColor[1],this._oldClearColor[2],this._oldClearColor[3])
78 | gl.enable(gl.BLEND);
79 | gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
80 | gl.viewport(this._oldViewport[0],this._oldViewport[1],this._oldViewport[2],this._oldViewport[3]);
81 | if (this._scissor) gl.enable(gl.SCISSOR_TEST);
82 | if (this._scissor) gl.scissor(this._scissorBox[0],this._scissorBox[1],this._scissorBox[2],this._scissorBox[3]);
83 | }
84 |
85 | // Save C3 webgl context, may be able to reduce some
86 | // Save VAO to restore
87 |
88 | }
89 |
90 | // @ts-ignore
91 | if (!globalThis.SpineGLCache)
92 | {
93 | // @ts-ignore
94 | globalThis.SpineGLCache = SpineGLCache;
95 | }
96 |
--------------------------------------------------------------------------------
/docs/LiveDemo/sw.js:
--------------------------------------------------------------------------------
1 | "use strict";const OFFLINE_DATA_FILE="offline.json",CACHE_NAME_PREFIX="c3offline",BROADCASTCHANNEL_NAME="offline",CONSOLE_PREFIX="[SW] ",LAZYLOAD_KEYNAME="",broadcastChannel="undefined"==typeof BroadcastChannel?null:new BroadcastChannel("offline");function PostBroadcastMessage(a){broadcastChannel&&setTimeout(()=>broadcastChannel.postMessage(a),3e3)}function Broadcast(a){PostBroadcastMessage({"type":a})}function BroadcastDownloadingUpdate(a){PostBroadcastMessage({"type":"downloading-update","version":a})}function BroadcastUpdateReady(a){PostBroadcastMessage({"type":"update-ready","version":a})}function IsUrlInLazyLoadList(a,b){if(!b)return!1;try{for(const c of b)if(new RegExp(c).test(a))return!0}catch(a){console.error("[SW] Error matching in lazy-load list: ",a)}return!1}function WriteLazyLoadListToStorage(a){return"undefined"==typeof localforage?Promise.resolve():localforage.setItem(LAZYLOAD_KEYNAME,a)}function ReadLazyLoadListFromStorage(){return"undefined"==typeof localforage?Promise.resolve([]):localforage.getItem(LAZYLOAD_KEYNAME)}function GetCacheBaseName(){return"c3offline-"+self.registration.scope}function GetCacheVersionName(a){return GetCacheBaseName()+"-v"+a}async function GetAvailableCacheNames(){const a=await caches.keys(),b=GetCacheBaseName();return a.filter((a)=>a.startsWith(b))}async function IsUpdatePending(){const a=await GetAvailableCacheNames();return 2<=a.length}async function GetMainPageUrl(){const a=await clients.matchAll({includeUncontrolled:!0,type:"window"});for(const b of a){let a=b.url;if(a.startsWith(self.registration.scope)&&(a=a.substring(self.registration.scope.length)),a&&"/"!==a)return a.startsWith("?")&&(a="/"+a),a}return""}function fetchWithBypass(a,b){return"string"==typeof a&&(a=new Request(a)),b?fetch(a.url,{headers:a.headers,mode:a.mode,credentials:a.credentials,redirect:a.redirect,cache:"no-store"}):fetch(a)}async function CreateCacheFromFileList(a,b,c){const d=await Promise.all(b.map((a)=>fetchWithBypass(a,c)));let e=!0;for(const f of d)f.ok||(e=!1,console.error("[SW] Error fetching '"+f.url+"' ("+f.status+" "+f.statusText+")"));if(!e)throw new Error("not all resources were fetched successfully");const f=await caches.open(a);try{return await Promise.all(d.map((a,c)=>f.put(b[c],a)))}catch(b){throw console.error("[SW] Error writing cache entries: ",b),caches.delete(a),b}}async function UpdateCheck(a){try{const b=await fetchWithBypass(OFFLINE_DATA_FILE,!0);if(!b.ok)throw new Error("offline.json responded with "+b.status+" "+b.statusText);const c=await b.json(),d=c.version,e=c.fileList,f=c.lazyLoad,g=GetCacheVersionName(d),h=await caches.has(g);if(h){const a=await IsUpdatePending();return void(a?(console.log("[SW] Update pending"),Broadcast("update-pending")):(console.log("[SW] Up to date"),Broadcast("up-to-date")))}const i=await GetMainPageUrl();e.unshift("./"),i&&-1===e.indexOf(i)&&e.unshift(i),console.log("[SW] Caching "+e.length+" files for offline use"),a?Broadcast("downloading"):BroadcastDownloadingUpdate(d),f&&(await WriteLazyLoadListToStorage(f)),await CreateCacheFromFileList(g,e,!a);const j=await IsUpdatePending();j?(console.log("[SW] All resources saved, update ready"),BroadcastUpdateReady(d)):(console.log("[SW] All resources saved, offline support ready"),Broadcast("offline-ready"))}catch(a){console.warn("[SW] Update check failed: ",a)}}self.addEventListener("install",(a)=>{a.waitUntil(UpdateCheck(!0).catch(()=>null))});async function GetCacheNameToUse(a,b){if(1===a.length||!b)return a[0];const c=await clients.matchAll();if(1caches.delete(a))),d}async function HandleFetch(a,b){const c=await GetAvailableCacheNames();if(!c.length)return fetch(a.request);const d=await GetCacheNameToUse(c,b),e=await caches.open(d),f=await e.match(a.request);if(f)return f;const g=await Promise.all([fetch(a.request),ReadLazyLoadListFromStorage()]),h=g[0],i=g[1];if(IsUrlInLazyLoadList(a.request.url,i))try{await e.put(a.request,h.clone())}catch(b){console.warn("[SW] Error caching '"+a.request.url+"': ",b)}return h}self.addEventListener("fetch",(a)=>{if(new URL(a.request.url).origin===location.origin){const b="navigate"===a.request.mode,c=HandleFetch(a,b);b&&a.waitUntil(c.then(()=>UpdateCheck(!1))),a.respondWith(c)}});
--------------------------------------------------------------------------------
/src/c3runtime/conditions.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | {
3 | const C3 = self.C3;
4 |
5 | C3.Plugins.Gritsenko_Spine.Cnds = {
6 |
7 | OnWebGLContextLost() {
8 | return true;
9 | },
10 |
11 | OnWebGLContextRestored() {
12 | return true;
13 | },
14 |
15 | OnSkeletonLoaded() {
16 | return true;
17 | },
18 |
19 | IsSkeletonLoaded() {
20 | return this.isLoaded;
21 | },
22 |
23 | OnAnimationFinished(animationName, trackIndex) {
24 | return (this.completeAnimationName == animationName) && (this.completeTrackIndex == trackIndex);
25 | },
26 |
27 | OnAnyAnimationFinished() {
28 | return true;
29 | },
30 |
31 | IsAnimationPlaying(animationName, trackIndex) {
32 | if (!this.isLoaded) return false;
33 | if (!this.skeletonInfo) return false;
34 | if (!this.skeletonInfo.skeleton) return false;
35 |
36 | const track = this.skeletonInfo.state.tracks[trackIndex];
37 | if (!track) return false;
38 |
39 | return (track.animation.name === animationName) && (track.trackIndex === trackIndex);
40 | },
41 | OnError() {
42 | return true;
43 | },
44 | OnEvent(eventName, trackIndex) {
45 | return (this.completeEventName === eventName) && (this.completeEventTrackIndex === trackIndex);
46 | },
47 | OnAnyEvent(trackIndex) {
48 | return (this.completeEventTrackIndex === trackIndex);
49 | },
50 | IsBoneControlPropertyActive(bone, propertyIndex) {
51 | let properties=['x','y','rotation','scaleX','scaleY'];
52 | let property = properties[propertyIndex];
53 |
54 | if (!this.spineBoneControl.bones.hasOwnProperty(bone)) return false;
55 | if (!this.spineBoneControl.bones[bone].hasOwnProperty(property)) return false;
56 |
57 | return true;
58 | },
59 |
60 | CompareValue(value, comparison, pathString){
61 | if(pathString === '') return false;
62 | let path = pathString.split('.');
63 | let result = this.GetValuePath(path,false);
64 | if (typeof result === 'object' || result === null) return false;
65 | switch (comparison)
66 | {
67 | case 0: return value === result;
68 | case 1: return value !== result;
69 | case 2: return value < result;
70 | case 3: return value <= result;
71 | case 4: return value > result;
72 | case 4: return value >= result;
73 | default: return false;
74 | }
75 | },
76 | ForEach(pathString) {
77 | if(pathString === '') return false;
78 | let path = pathString.split('.');
79 | let value = this.GetValuePath(path,false);
80 | if (typeof value !== "object" || value === null)
81 | return false;
82 | const runtime = this._runtime;
83 | const eventSheetManager = runtime.GetEventSheetManager();
84 | const currentEvent = runtime.GetCurrentEvent();
85 | const solModifiers = currentEvent.GetSolModifiers();
86 | const eventStack = runtime.GetEventStack();
87 | const oldFrame = eventStack.GetCurrentStackFrame();
88 | const newFrame = eventStack.Push(currentEvent);
89 | const oldKey = this.currentKey;
90 | const oldValue = this.currentValue;
91 | runtime.SetDebuggingEnabled(false);
92 | for (const [k,v] of Object.entries(value)) {
93 | this.currentKey = k;
94 | this.currentValue = v;
95 | eventSheetManager.PushCopySol(solModifiers);
96 | currentEvent.Retrigger(oldFrame, newFrame);
97 | eventSheetManager.PopSol(solModifiers)
98 | }
99 | runtime.SetDebuggingEnabled(true);
100 | this.currentKey = oldKey;
101 | this.currentValue = oldValue;
102 | eventStack.Pop();
103 | return false
104 | },
105 | };
106 | }
--------------------------------------------------------------------------------
/src/plugin.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | {
3 | const C3 = self.C3;
4 |
5 | const PLUGIN_ID = "Gritsenko_Spine";
6 | const PLUGIN_VERSION = "2.9.1";
7 | const PLUGIN_CATEGORY = "general";
8 |
9 | const PLUGIN_CLASS = SDK.Plugins.Gritsenko_Spine = class SpinePlugin extends SDK.IPluginBase {
10 | constructor() {
11 | super(PLUGIN_ID);
12 |
13 | SDK.Lang.PushContext("plugins." + PLUGIN_ID.toLowerCase());
14 |
15 | this._info.SetName(lang(".name"));
16 | this._info.SetDescription(lang(".description"));
17 | this._info.SetVersion(PLUGIN_VERSION);
18 | this._info.SetCategory(PLUGIN_CATEGORY);
19 | this._info.SetAuthor("Gritsenko and Mikal");
20 | this._info.SetHelpUrl(lang(".help-url"));
21 | this._info.SetPluginType("world"); // mark as world plugin, which can draw
22 | this._info.SetIsResizable(true); // allow to be resized
23 | this._info.SetIsRotatable(true); // allow to be rotated
24 | this._info.SetHasImage(true);
25 | this._info.SetSupportsEffects(true); // allow effects
26 | this._info.SetMustPreDraw(false);
27 | this._info.AddCommonPositionACEs();
28 | this._info.AddCommonAngleACEs();
29 | this._info.AddCommonAppearanceACEs();
30 | this._info.AddCommonZOrderACEs();
31 | this._info.AddCommonSizeACEs();
32 | this._info.SetSupportsColor(true);
33 | this._info.SetIsTiled(false);
34 | this._info.SetIsSingleGlobal(false);
35 | this._info.SetIsDeprecated(false);
36 | this._info.SetCanBeBundled(true);
37 | this._info.AddCommonSceneGraphACEs();
38 | this._info.SetSupportsZElevation(true);
39 |
40 | this._info.AddFileDependency({
41 | filename: "c3runtime/spine-webgl.js",
42 | type: "external-runtime-script"
43 | });
44 |
45 | this._info.AddFileDependency({
46 | filename: "c3runtime/spine-draw.js",
47 | type: "external-runtime-script"
48 | });
49 |
50 | this._info.AddFileDependency({
51 | filename: "c3runtime/spine-gl-cache.js",
52 | type: "external-runtime-script"
53 | });
54 |
55 | this._info.AddFileDependency({
56 | filename: "c3runtime/spine-bone-control.js",
57 | type: "external-runtime-script"
58 | });
59 |
60 | this._info.AddFileDependency({
61 | filename: "c3runtime/spine-palette.js",
62 | type: "external-runtime-script"
63 | });
64 | // this._info.SetDOMSideScripts(["c3runtime/spine-webgl.js"]);
65 |
66 |
67 | this._info.SetSupportedRuntimes(["c3"]);
68 |
69 | SDK.Lang.PushContext(".properties");
70 |
71 | this._info.SetProperties([
72 | new SDK.PluginProperty("text", "json", ".json"),
73 | new SDK.PluginProperty("text", "atlas", ".atlas"),
74 | new SDK.PluginProperty("text", "png", ".png"),
75 | new SDK.PluginProperty("text", "skin", "default"),
76 | new SDK.PluginProperty("text", "animation", "idle"),
77 | new SDK.PluginProperty("text", "skeleton", ""),
78 | new SDK.PluginProperty("float", "scale", 1),
79 | new SDK.PluginProperty("check", "pre-mult-alpha", false),
80 | new SDK.PluginProperty("check", "collisions", true),
81 | new SDK.PluginProperty("float", "default-mix", 0.0),
82 | new SDK.PluginProperty("float", "render-quality", 1.0),
83 | new SDK.PluginProperty("check", "keep-aspect-ratio", false),
84 | new SDK.PluginProperty("check", "debug", false),
85 | new SDK.PluginProperty("check", "bbox-override", false),
86 | new SDK.PluginProperty("float", "bbox-offset-x", -64.0),
87 | new SDK.PluginProperty("float", "bbox-offset-y", -64.0),
88 | new SDK.PluginProperty("float", "bbox-size-x", 128.0),
89 | new SDK.PluginProperty("float", "bbox-size-y", 128.0)
90 | ]);
91 | SDK.Lang.PopContext(); //.properties
92 | SDK.Lang.PopContext();
93 | }
94 | };
95 |
96 | PLUGIN_CLASS.Register(PLUGIN_ID, PLUGIN_CLASS);
97 | }
98 |
--------------------------------------------------------------------------------
/formatter/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Spine add-on for Construct 3 | c3_spine_plugin
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | Spine JSON export 3.3 to 3.8 format patcher
24 |
25 |
26 |
27 |
28 | Old json
29 |
31 |
32 |
33 | New json
34 |
36 |
37 |
38 |
39 |
40 |
41 | Convert!
42 |
43 |
44 |
45 |
46 |
158 |
159 |
160 |
161 |
162 |
--------------------------------------------------------------------------------
/docs/LiveDemo/data.json:
--------------------------------------------------------------------------------
1 | {"project":["SpinePluginTest",null,[[0,false,true,true,true,true,true,true,true,true],[2,true,false,false,false,false,false,false,false,false],[3,false,true,true,true,true,true,true,true,false],[4,true,false,false,false,false,false,false,false,false],[5,false,true,true,true,true,true,true,true,false],[6,true,false,false,false,false,false,false,false,false]],[["SpineCharacter",0,false,[],1,0,["images/shared-0-sheet0.png",3322,0,0,0,250,250],null,[["8Direction",1,971849326318143,0]],false,false,708886617025756,[],null,1],["Keyboard",2,false,[],0,0,null,null,[],false,false,448378265906156,[],null,2,[]],["Sprite",3,false,[],0,0,null,[["Animation 1",5,false,1,0,false,741410374589640,[["images/shared-0-sheet2.png",6695,0,0,168,248,1,0.5,0.5,[],[-0.49404761904761907,-0.4959677419354839,0,-0.5,0.48809523809523814,-0.4959677419354839,0.48809523809523814,0,0.29761904761904767,0.3629032258064516,0,0.3629032258064516,-0.3035714285714286,0.3629032258064516,-0.49404761904761907,0],0]]]],[],false,false,886700548662699,[],null,3],["Sprite2",3,false,[],0,0,null,[["Animation 1",5,false,1,0,false,717641720423608,[["images/shared-0-sheet1.png",14996,0,0,237,237,1,0.5,0.5,[],[-0.3270042194092827,-0.3270042194092827,0,-0.3396624472573839,0.2721518987341772,-0.27637130801687765,0.4620253164556962,0,0.26793248945147674,0.26793248945147674,0,0.36919831223628696,-0.2805907172995781,0.2763713080168776,-0.5,0],0]]]],[],false,false,108703857865790,[],null,4],["Browser",4,false,[],0,0,null,null,[],false,false,778747613166461,[],null,5,[]],["Text",5,false,[],0,0,null,null,[],false,false,650905651038003,[],null,6],["Mouse",6,false,[],0,0,null,null,[],false,false,258289131195630,[],null,7,[]],["AnimationText",5,false,[],0,0,null,null,[],false,false,638163697302026,[],null,8],["AnimationText2",5,false,[[229104675276951,1,"Value",9]],0,0,null,null,[],false,false,279098545763967,[],null,10],["AnimationText3",5,false,[[953542609703342,1,"Value",9]],0,0,null,null,[],false,false,906826237856803,[],null,11]],[],[["Layout 1",1708,960,false,"Event sheet 1",314783196911307,[["Layer 0",0,201656680313375,true,[201,188,165],false,1,1,1,false,false,1,0,0,[[[57,82,0,107.53079078915925,158.73592926018748,0,0,[1,1,1,1],0.5,0.5,0,0,[]],2,3,[],[],[true,"Animation 1",0,true]],[[200.64038681256912,207.64038681256912,0,238.56472277260414,238.56472277260414,0,0,[1,1,1,1],0.5,0.5,0,0,[]],0,10,[],[[200,1200,800,3,0,true,true]],["character.json","character.atlas","character.png","skin_1","01_idle","",0.7,true]],[[370,523,0,107.53079078915925,158.73592926018748,0,0,[1,1,1,1],0.5,0.5,0,0,[]],2,2,[],[],[true,"Animation 1",0,true]],[[413,766,0,107.53079078915925,158.73592926018748,0,0,[1,1,1,1],0.5,0.5,0,0,[]],2,4,[],[],[true,"Animation 1",0,true]],[[42,810,0,56.568542494923804,56.568542494923804,0,0,[1,1,1,0.5],0.5,0.5,0,0,[]],3,5,[],[],[true,"Animation 1",0,true]],[[79,792,0,264,41,0,0,[1,1,1,0.5],0,0,0,0,[]],5,7,[],[],["Assets from Murlykla",true,"Arial",17,0,true,false,[0.47058823529411764,0.47058823529411764,0.47058823529411764],0,0,0,true,0]],[[122,11,0,200,30,0,0,[1,1,1,1],0,0,0,0,[]],7,11,[],[],["Is Running ",true,"Arial",12,0,false,false,[0,0,0],0,0,0,true,0]],[[120,37,0,200,30,0,0,[1,1,1,1],0,0,0,0,[]],8,12,[0],[],["Any animation finished: 0",true,"Arial",12,0,false,false,[0,0,0],0,0,0,true,0]],[[120,63,0,200,30,0,0,[1,1,1,1],0,0,0,0,[]],9,13,[0],[],["Run animation finished: 0",true,"Arial",12,0,false,false,[0,0,0],0,0,0,true,0]]],[],0]],[],[]]],[["Event sheet 1",[[0,0,false,null,554690986948981,1,[[0,7,null,1,false,false,false,694463840700527,null]],[[-1,8,null,381813849675962,0,null,[[1,[0]],[3,1]]],[-2,"SetIdleState",null,612765897866696,0,null]]],[3,[false,"Main"],false,null,823723420148170,2,[[-1,9,null,0,false,false,false,0,false,[[1,[0]]]]],[],[[0,0,false,null,727071623645836,3,[[1,10,null,1,false,false,false,609606150967207,null,[[9,39]]]],[[0,11,null,288951721364919,0,null,[[16,false]]],[-2,"SetRunState",null,247184081469331,0,null]]],[0,0,false,null,530794082250574,4,[[1,12,null,0,false,true,false,460765857961525,null,[[9,39]]],[1,12,null,0,false,true,false,192265172835824,null,[[9,37]]],[1,12,null,0,false,true,false,679205180471502,null,[[9,38]]],[1,12,null,0,false,true,false,661767758020543,null,[[9,40]]],[-1,13,null,0,false,false,false,772655505680224,null]],[[-2,"SetIdleState",null,481431259685139,0,null]]],[0,0,false,null,336433050100178,5,[[1,10,null,1,false,false,false,782064121935287,null,[[9,37]]]],[[0,11,null,295920835649818,0,null,[[16,true]]],[-2,"SetRunState",null,787243115434873,0,null]]],[0,0,false,null,209014263658449,6,[[1,10,null,1,false,false,false,185905863038369,null,[[9,38]]]],[[-2,"SetRunState",null,482068393692473,0,null]]],[0,0,false,null,362044810182279,7,[[1,10,null,1,false,false,false,934502453496615,null,[[9,40]]]],[[-2,"SetRunState",null,827681765315319,0,null]]],[0,0,false,null,800428280887307,8,[[1,10,null,1,false,false,false,322609340410504,null,[[9,32]]]],[[0,14,null,248937731429421,0,null,[[1,[1]],[16,false]]]]],[0,0,false,null,961725521940944,9,[[0,15,null,1,false,false,false,709578475553517,null,[[1,[1]]]]],[[-2,"SetIdleState",null,415678932468507,0,null]]],[0,0,false,null,895148395534211,10,[[0,16,null,0,false,false,false,800554269029530,null,[[1,[2]]]]],[[7,17,null,422552093747724,0,null,[[7,[3]]]]]],[0,0,false,null,225137277339801,11,[[-1,18,null,0,false,false,false,970798890562933,null]],[[7,17,null,827322242916333,0,null,[[7,[4]]]]]],[4,["SetRunState",0,[],true],false,null,370032876731922,12,[[0,16,null,0,false,true,false,864968706504566,null,[[1,[2]]]]],[[0,14,null,425762001805630,0,null,[[1,[2]],[16,true]]]]],[4,["SetIdleState",0,[],true],false,null,688603524438358,13,[[0,16,null,0,false,true,false,312872308844273,null,[[1,[5]]]]],[[0,14,null,125777890775043,0,null,[[1,[6]],[16,true]]]]],[0,0,false,null,875931413505219,14,[[0,19,null,1,false,false,false,101075410889083,null]],[[8,20,null,738657914171619,0,null,[[10,0],[7,[7]]]],[8,17,null,641691253206969,0,null,[[7,[8,[2,8,false,0]]]]]]],[0,0,false,null,900400060664537,15,[[0,15,null,1,false,false,false,359173059817829,null,[[1,[2]]]]],[[9,20,null,490942428526294,0,null,[[10,0],[7,[7]]]],[9,17,null,824593299215093,0,null,[[7,[9,[2,9,false,0]]]]]]]]]]]],[],"media/",false,480,854,3,true,"trilinear",true,"1.0.0.0",true,false,3,2,14,false,true,1,true,false,[],"icons/",[],true,"680j78qw5qc","fonts/",[],"high-performance",[],"standard"]}
--------------------------------------------------------------------------------
/src/c3runtime/spine-palette.js:
--------------------------------------------------------------------------------
1 | // @ts-check
2 | "use strict";
3 |
4 | class SpinePalette {
5 | constructor(indexSize, paletteNumber) {
6 | // 4 elements, RGBA order
7 | this._palette = new Uint8Array(paletteNumber*indexSize*4);
8 | this._enable = false;
9 | this._indexSize = indexSize;
10 | this._paletteNumber = paletteNumber;
11 | this._slotPalette = {};
12 | this._slotPaletteOffset = {};
13 | this._paletteTexture = null;
14 | this._c3PaletteTexture = null;
15 | this._uploadNeeded = false;
16 | this._entryUploadNeeded = new Array(paletteNumber);
17 |
18 | this._palette.fill(255);
19 | this._entryUploadNeeded.fill(false);
20 | }
21 |
22 | get palette() { return this._palette;}
23 | get enable() { return this._enable;}
24 | get indexSize() { return this._indexSize;}
25 | get paletteNumber() { return this._paletteNumber;}
26 | set enable(value) { this._enable = value;}
27 | get slotPalette() { return this._slotPalette;}
28 | get slotPaletteOffset() { return this._slotPaletteOffset;}
29 | get paletteTexture() { return this._paletteTexture;}
30 | get uploadNeeded() { return this._uploadNeeded;}
31 | set uploadNeeded(value) { this._uploadNeeded = value;}
32 | get entryUploadNeeded() { return this._entryUploadNeeded;}
33 |
34 | createPaletteTexture(renderer)
35 | {
36 | let options = { mipMap: false, sampling: 'nearest', pixelFormat:'rgba8', wrapX: "repeat", wrapY: "repeat" }
37 | this._c3PaletteTexture = renderer.CreateDynamicTexture(this.indexSize, this.paletteNumber, options);
38 | this._paletteTexture = this._c3PaletteTexture._texture;
39 | }
40 |
41 | setSlotPalette(slotName, paletteNumber)
42 | {
43 | if (paletteNumber < 0 || paletteNumber >= this.paletteNumber) paletteNumber = 0;
44 | this._slotPalette[slotName] = Math.floor(paletteNumber);
45 | }
46 |
47 | setSlotPaletteOffset(slotName, paletteOffset)
48 | {
49 | this._slotPaletteOffset[slotName] = Math.floor(paletteOffset);
50 | }
51 |
52 | getSlotPalette(slotName)
53 | {
54 | if (this.slotPalette.hasOwnProperty(slotName))
55 | {
56 | return this._slotPalette[slotName];
57 | }
58 | // Default to palette 0
59 | return 0;
60 | }
61 |
62 | setColor(paletteNumber, index, color)
63 | {
64 | if (index < 0 || index > this.indexSize-1) return;
65 |
66 | const spineBatcher = globalThis.spineBatcher;
67 | this._palette[paletteNumber*this.indexSize*4+index*4+0] = spineBatcher.getRValue(color)*255;
68 | this._palette[paletteNumber*this.indexSize*4+index*4+1] = spineBatcher.getGValue(color)*255;
69 | this._palette[paletteNumber*this.indexSize*4+index*4+2] = spineBatcher.getBValue(color)*255;
70 | this._palette[paletteNumber*this.indexSize*4+index*4+3] = spineBatcher.getAValue(color)*255;
71 | this.uploadNeeded = true;
72 | }
73 |
74 | setDefaultColors(paletteNumber, colorScale, alphaScale)
75 | {
76 | let defaultPalette = [];
77 | if(this.indexSize == 8)
78 | {
79 | // DB8 https://github.com/geoffb/dawnbringer-palettes/blob/master/DB8/db8.txt
80 | defaultPalette = [ 'FF000000','FF55415F','FF646964','FFD77355','FF508CD7','FF64B964','FFE6C86E','FFDCF5FF'];
81 | } else if(this.indexSize == 16)
82 | {
83 | // DB16 https://github.com/geoffb/dawnbringer-palettes/blob/master/DB16/db16.txt
84 | defaultPalette = [ 'FF140C1C','FF442434','FF30346D','FF4E4A4F','FF854C30','FF346524','FFD04648','FF757161',
85 | 'FF597DCE','FFD27D2C','FF8595A1','FF6DAA2C','FFD2AA99','FF6DC2CA','FFDAD45E','FFDEEED6'];
86 | } else if(this.indexSize == 32)
87 | {
88 | // DB32 https://github.com/geoffb/dawnbringer-palettes/blob/master/DB32/db32.txt
89 | // defaultPalette = [ 'FF000000','FF222034','FF45283C','FF663931','FF8F563B','FFDF7126','FFD9A066','FFEEC39A',
90 | // 'FFFBF236','FF99E550','FF6ABE30','FF37946E','FF4B692F','FF524B24','FF323C39','FF3F3F74',
91 | // 'FF306082','FF5B6EE1','FF639BFF','FF5FCDE4','FFCBDBFC','FFFFFFFF','FF9BADB7','FF847E87',
92 | // 'FF696A6A','FF595652','FF76428A','FFAC3232','FFD95763','FFD77BBA','FF8F974A','FF8A6F30'];
93 |
94 | // ENDESGA 32 https://lospec.com/palette-list/endesga-32
95 | defaultPalette = [ 'FFbe4a2f','FFd77643','FFead4aa','FFe4a672','FFb86f50','FF733e39','FF3e2731','FFa22633',
96 | 'FFe43b44','FFf77622','FFfeae34','FFfee761','FF63c74d','FF3e8948','FF265c42','FF193c3e',
97 | 'FF124e89','FF0099db','FF2ce8f5','FFffffff','FFc0cbdc','FF8b9bb4','FF5a6988','FF3a4466',
98 | 'FF262b44','FF181425','FFff0044','FF68386c','FFb55088','FFf6757a','FFe8b796','FFc28569'];
99 | }
100 |
101 | for(let i = 0; i this.indexSize/8)
143 | // Upload entire palette if more updates needed
144 | {
145 | gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.indexSize, this.paletteNumber, 0, gl.RGBA, gl.UNSIGNED_BYTE, this._palette);
146 | this.entryUploadNeeded.fill(false);
147 | } else
148 | // Upload only dirty entries
149 | {
150 | // Create buffers per upload, so they do not block
151 | let entryBuffers = [];
152 | for(let i=0;i= this.skinNames.length || index < 0) return "";
33 |
34 | return this.skinNames[index];
35 | },
36 |
37 | /* ANIMATIONS */
38 | Animations() {
39 |
40 | if (!this.isLoaded) return "";
41 |
42 | return this.animationNames.join("\n");
43 | },
44 |
45 | CurrentAnimation(trackIndex){
46 | return this._currentAnimation(trackIndex)
47 | },
48 |
49 | AnimationsCount(){
50 |
51 | if (!this.isLoaded) return 0;
52 |
53 | return this.animationNames.length;
54 | },
55 |
56 |
57 | AnimationName(index){
58 |
59 | if (!this.isLoaded) return "";
60 | if (index >= this.animationNames.length || index < 0) return "";
61 |
62 | return this.animationNames[index];
63 | },
64 |
65 | Error(){
66 | return this.spineError;
67 | },
68 | TextureHeight(){
69 |
70 | if (!this.isLoaded) return 0;
71 |
72 | return this.textureHeight;
73 | },
74 | TextureWidth(){
75 |
76 | if (!this.isLoaded) return 0;
77 |
78 | return this.textureWidth;
79 | },
80 | AnimationStart(trackIndex){
81 | return this._animationStart(trackIndex);
82 | },
83 | AnimationEnd(trackIndex){
84 | return this._animationEnd(trackIndex);
85 | },
86 | AnimationLast(trackIndex){
87 |
88 | if (!this.isLoaded) return 0;
89 |
90 | const state = this.skeletonInfo.state;
91 | if(!state || !state.tracks) return 0;
92 | const track = state.tracks[trackIndex];
93 | if(!track) return 0;
94 |
95 | return track.animationLast;
96 | },
97 | TrackTime(trackIndex){
98 |
99 | if (!this.isLoaded) return 0;
100 |
101 | const state = this.skeletonInfo.state;
102 | if(!state || !state.tracks) return 0;
103 | const track = state.tracks[trackIndex];
104 | if(!track) return 0;
105 |
106 | return track.trackTime;
107 | },
108 | Alpha(trackIndex){
109 |
110 | if (!this.isLoaded) return 0;
111 |
112 | const state = this.skeletonInfo.state;
113 | if(!state || !state.tracks) return 0;
114 | const track = state.tracks[trackIndex];
115 | if(!track) return 0;
116 |
117 | return track.alpha;
118 | },
119 | SpineBBoxCenterX(slot, name){
120 |
121 | if (!this.isLoaded) return 0;
122 |
123 | let bBox = this.skeletonInfo.skeleton.getAttachmentByName(slot,name);
124 | if (!bBox) return 0;
125 |
126 | let points = this.skeletonInfo.skeletonBounds.getPolygon(bBox);
127 | let centerX = 0;
128 | for (let i = 0; i < points.length; i+=2)
129 | {
130 | centerX+=points[i];
131 | }
132 | centerX = centerX/(points.length/2)+this.skeletonInfo.bounds.offset.x+this.skeletonInfo.bounds.size.x;
133 | if (this.isMirrored) centerX = this.skeletonInfo.bounds.size.x - centerX;
134 |
135 | let wi = this.GetInstance().GetWorldInfo();
136 | let x = wi.GetX()-wi.GetWidth()/2+centerX/(this.textureWidth/wi.GetWidth());
137 | // If not rotated, return x
138 | if (wi.GetAngle() == 0) return x;
139 |
140 | let centerY = 0;
141 | for (let i = 1; i < points.length; i+=2)
142 | {
143 | centerY+=points[i];
144 | }
145 | centerY = this.skeletonInfo.bounds.size.y-centerY/(points.length/2)+this.skeletonInfo.bounds.offset.y;
146 | let y = wi.GetY()-wi.GetHeight()/2+centerY/(this.textureHeight/wi.GetHeight());
147 | // If rotated, return rotate centerX by angle around center
148 | return Math.cos(wi.GetAngle()) * (x-wi.GetX()) - Math.sin(wi.GetAngle()) * (y-wi.GetY()) + wi.GetX();
149 | },
150 |
151 | SpineBBoxCenterY(slot, name){
152 |
153 | if (!this.isLoaded) return 0;
154 |
155 | let bBox = this.skeletonInfo.skeleton.getAttachmentByName(slot,name);
156 | if (!bBox) return 0;
157 |
158 | let points = this.skeletonInfo.skeletonBounds.getPolygon(bBox);
159 | let centerY = 0;
160 | for (let i = 1; i < points.length; i+=2)
161 | {
162 | centerY+=points[i];
163 | }
164 | centerY = this.skeletonInfo.bounds.size.y-centerY/(points.length/2)+this.skeletonInfo.bounds.offset.y;
165 |
166 | let wi = this.GetInstance().GetWorldInfo();
167 | let y = wi.GetY()-wi.GetHeight()/2+centerY/(this.textureHeight/wi.GetHeight());
168 | if (wi.GetAngle() == 0) return y;
169 |
170 | let centerX = 0;
171 | for (let i = 0; i < points.length; i+=2)
172 | {
173 | centerX+=points[i];
174 | }
175 | centerX = centerX/(points.length/2)+this.skeletonInfo.bounds.offset.x+this.skeletonInfo.bounds.size.x;
176 | if (this.isMirrored) centerX = this.skeletonInfo.bounds.size.x - centerX;
177 | let x = wi.GetX()-wi.GetWidth()/2+centerX/(this.textureWidth/wi.GetWidth());
178 | // If rotated, return rotate centerX by angle around center
179 | return Math.sin(wi.GetAngle()) * (x-wi.GetX()) + Math.cos(wi.GetAngle()) * (y-wi.GetY()) + wi.GetY();
180 | },
181 |
182 | SpineBBoxGetPoly(slot,name)
183 | {
184 |
185 | if (!this.isLoaded) return JSON.stringify({});
186 |
187 | let bBox = this.skeletonInfo.skeleton.getAttachmentByName(slot,name);
188 | if (!bBox) return JSON.stringify({});
189 |
190 | let wi = this.GetInstance().GetWorldInfo();
191 | let x = wi.GetX();
192 | let y = wi.GetY();
193 | let halfHeight = wi.GetHeight()/2;
194 | let halfWidth = wi.GetWidth()/2;
195 | let angle = wi.GetAngle();
196 | let yScale = this.textureHeight/wi.GetHeight();
197 | let xScale = this.textureWidth/wi.GetWidth();
198 | let sizeY = this.skeletonInfo.bounds.size.y;
199 | let offsetY = this.skeletonInfo.bounds.offset.y;
200 | let sizeX = this.skeletonInfo.bounds.size.x;
201 | let offsetX = this.skeletonInfo.bounds.offset.x;
202 | let cosT = 0;
203 | let sinT = 0;
204 | // If rotated pre calculate cos and sin
205 | if (angle != 0)
206 | {
207 | cosT = Math.cos(angle);
208 | sinT = Math.sin(angle);
209 | }
210 |
211 | const points = Array.from(this.skeletonInfo.skeletonBounds.getPolygon(bBox));
212 | for(let i=0;i= 2.0 );
53 | } else if ( glVersion.indexOf( 'OpenGL ES' ) !== - 1 )
54 | {
55 |
56 | version = parseFloat( /^OpenGL\ ES\ ([0-9])/.exec( glVersion )[ 1 ] );
57 | this.isWebGL2 = ( version >= 3.0 );
58 | }
59 |
60 | if (this.isWebGL2)
61 | {
62 | this.myVAO = gl.createVertexArray();
63 | } else
64 | {
65 | let extOESVAO = gl.getExtension("OES_vertex_array_object");
66 | if (!extOESVAO)
67 | {
68 | console.error("Spine plugin error: webGL1 with no OES_vertex_array_object support"); // tell user they don't have the required extension or work around it
69 | return;
70 | }
71 | this.myVAO = extOESVAO.createVertexArrayOES();
72 | }
73 |
74 | this.mvp = new spine.Matrix4();
75 | this.shader = spine.Shader.newTwoColoredTextured(gl);
76 | this.batcher = new spine.PolygonBatcher(gl);
77 | this.renderer = new spine.SkeletonRenderer(gl);
78 | this.shapes = new spine.ShapeRenderer(gl);
79 |
80 | this._initialized = true;
81 |
82 | // C3 webgl state cache store / restore
83 | // @ts-ignore
84 | this._spineGLCache = new globalThis.SpineGLCache(this.isWebGL2, gl);
85 | }
86 |
87 | addInstance(instance, skeletonScale, uid)
88 | {
89 | this._skeletonInstances[uid] = {}
90 | this._skeletonInstances[uid].skeletonInfo = instance
91 | this._skeletonInstances[uid].initialized = false
92 | this._skeletonInstances[uid].skeletonScale = skeletonScale
93 | this._skeletonInstances[uid].onScreen = true
94 | this._skeletonInstances[uid].tracksComplete = false
95 | this._skeletonInstances[uid].renderOnce = true
96 | }
97 |
98 | removeInstance(uid)
99 | {
100 | if (!this._skeletonInstances[uid]) return
101 | delete this._skeletonInstances[uid]
102 | }
103 |
104 | setInstanceInitialized(uid)
105 | {
106 | if (!this._skeletonInstances[uid]) return
107 | this._skeletonInstances[uid].initialized = true
108 | }
109 |
110 | setInstanceFB(spineFB, uid)
111 | {
112 | if (!this._skeletonInstances[uid]) return
113 | this._skeletonInstances[uid].spineFB = spineFB
114 | }
115 |
116 | setInstancePalette(palette, uid)
117 | {
118 | if (!this._skeletonInstances[uid]) return
119 | this._skeletonInstances[uid].palette = palette;
120 | }
121 |
122 | setInstanceOnScreen(onScreen, uid)
123 | {
124 | if (!this._skeletonInstances[uid]) return
125 | this._skeletonInstances[uid].onScreen = onScreen;
126 | }
127 |
128 | setInstanceTracksComplete(tracksComplete, uid)
129 | {
130 | if (!this._skeletonInstances[uid]) return
131 | // If transitioning to tracksComplete, render one more time
132 | if (!this._skeletonInstances[uid].tracksComplete && tracksComplete)
133 | {
134 | this._skeletonInstances[uid].renderOnce = true
135 | }
136 | this._skeletonInstances[uid].tracksComplete = tracksComplete;
137 | }
138 |
139 | setInstanceRenderOnce(renderOnce, uid)
140 | {
141 | if (!this._skeletonInstances[uid]) return
142 |
143 | this._skeletonInstances[uid].renderOnce = renderOnce;
144 | }
145 |
146 | setInstanceAnimationStop(animationStop, uid)
147 | {
148 | if (!this._skeletonInstances[uid]) return
149 | this._skeletonInstances[uid].animationStop = animationStop;
150 | }
151 |
152 | resize(bounds, skeletonScale) {
153 | // magic
154 | var centerX = bounds.offset.x + (bounds.size.x) / 2;
155 | var centerY = bounds.offset.y + (bounds.size.y) / 2;
156 | var scaleX = bounds.size.x / (bounds.size.x);
157 | var scaleY = bounds.size.y / (bounds.size.y);
158 | var scale = Math.max(scaleX, scaleY) * (1/skeletonScale);
159 | if (scale < 1) scale = 1;
160 | var width = (bounds.size.x) * scale;
161 | var height = (bounds.size.y) * scale;
162 |
163 | this.mvp.ortho2d(centerX - width / 2, centerY - height / 2, width, height);
164 | }
165 |
166 | drawBatch() {
167 | if (this.debugVariables.renderDisable === 'enable')
168 | {
169 | this._rendered = true;
170 | return;
171 | }
172 |
173 | // @ts-ignore
174 | const spine = globalThis.spine;
175 |
176 | const gl = this.gl;
177 | const skeletonInstances = this._skeletonInstances;
178 |
179 | // End C3 Batch
180 | // this.c3wgl.EndBatch();
181 |
182 | if (!this._spineGLCacheStored || !(this._debugVariables.spineGLCache === "enable"))
183 | {
184 | this._spineGLCache.store();
185 | this._spineGLCacheStored = true;
186 | }
187 |
188 | // Bind to private VAO so Spine use does not impact C3 VAO
189 | if (this.isWebGL2)
190 | {
191 | gl.bindVertexArray(this.myVAO);
192 | } else
193 | {
194 | let extOESVAO = gl.getExtension("OES_vertex_array_object");
195 | extOESVAO.bindVertexArrayOES(this.myVAO);
196 | }
197 |
198 | let tickCount = this.runtime.GetTickCount();
199 |
200 | // Per instance render
201 | let index = 0;
202 | let count = 0;
203 | for (const uid in skeletonInstances)
204 | {
205 | const skeletonInstance = skeletonInstances[uid];
206 | const palette = skeletonInstance.palette;
207 |
208 | /*
209 | if (skeletonInstance.initialized && palette.uploadNeeded)
210 | {
211 | palette.uploadNeeded = false;
212 | palette.upload(gl.TEXTURE1, gl);
213 | }
214 | */
215 |
216 | const sequenceActive = skeletonInstance.skeletonInfo.skeleton.sequenceActive;
217 | const sequenceAutoplay = skeletonInstance.skeletonInfo.sequenceAutoplay
218 | const sequenceFPS = skeletonInstance.skeletonInfo.sequenceFPS
219 |
220 | if (skeletonInstance.initialized
221 | && (tickCount%this._renderRate == index%this._renderRate)
222 | && (sequenceActive || skeletonInstance.renderOnce ||
223 | (!skeletonInstance.tracksComplete
224 | && skeletonInstance.onScreen && !skeletonInstance.animationStop))) {
225 | count++;
226 | const bounds = skeletonInstance.skeletonInfo.bounds;
227 | const premultipliedAlpha = skeletonInstance.skeletonInfo.premultipliedAlpha;
228 |
229 | // Render to our targetTexture by binding the framebuffer to the SpineFB texture
230 | gl.bindFramebuffer(gl.FRAMEBUFFER, skeletonInstance.spineFB);
231 |
232 | // Set viewport
233 | gl.viewport(0, 0, bounds.size.x, bounds.size.y);
234 |
235 | // Set proper webgl blend for Spine render
236 | gl.enable(gl.BLEND);
237 | gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
238 |
239 | // Disable scissor (may be set by C3 renderer)
240 | gl.disable(gl.SCISSOR_TEST);
241 |
242 | gl.bindTexture(gl.TEXTURE_2D, null);
243 | gl.bindBuffer(gl.ARRAY_BUFFER, null);
244 | gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
245 |
246 | // Bind palette texture to texture unit 1
247 | gl.activeTexture(gl.TEXTURE1);
248 | gl.bindTexture(gl.TEXTURE_2D, palette.paletteTexture);
249 | gl.activeTexture(gl.TEXTURE0);
250 |
251 | // Bind the shader and set the texture and model-view-projection matrix.
252 | this.shader.bind();
253 | // YYY this.shader.setUniformi(spine.Shader.SAMPLER, 0);
254 | // YYY this.shader.setUniformi('u_palette', 1);
255 |
256 | // Resize
257 | this.resize(bounds, skeletonInstance.skeletonScale);
258 | this.shader.setUniform4x4f(spine.Shader.MVP_MATRIX, this.mvp.values);
259 |
260 | // Start the batch and tell the SkeletonRenderer to render the active skeleton.
261 | this.batcher.begin(this.shader);
262 |
263 | // Apply vertex effect
264 | this.renderer.vertexEffect = null;
265 |
266 | gl.clearColor(0, 0, 0, 0);
267 | gl.clear(gl.COLOR_BUFFER_BIT);
268 |
269 | // Render
270 | this.renderer.premultipliedAlpha = premultipliedAlpha;
271 | // YYY this.renderer.draw(this.batcher, skeletonInstance.skeletonInfo.skeleton, -1, -1, skeletonInstance.palette);
272 | this.renderer.draw(this.batcher, skeletonInstance.skeletonInfo.skeleton, -1, -1, null, sequenceAutoplay, sequenceFPS);
273 | this.batcher.end();
274 | this.shader.unbind();
275 | }
276 |
277 | if (skeletonInstance.initialized && palette.uploadNeeded)
278 | {
279 | palette.uploadNeeded = false;
280 | palette.upload(gl.TEXTURE1, gl);
281 | }
282 |
283 | index++;
284 | }
285 |
286 | this._rendered = true;
287 |
288 | this._spineGLCache.restore();
289 |
290 | }
291 |
292 | getRValue(rgb)
293 | {
294 | const ALPHAEX_SHIFT = 1024;
295 | const ALPHAEX_MAX = 1023;
296 | const RGBEX_SHIFT = 16384;
297 | const RGBEX_MAX = 8191;
298 | const RGBEX_MIN = -8192;
299 | if (rgb >= 0) return (rgb & 255) / 255;
300 | else {
301 | let v = Math.floor(-rgb / (RGBEX_SHIFT * RGBEX_SHIFT * ALPHAEX_SHIFT));
302 | if (v > RGBEX_MAX) v -= RGBEX_SHIFT;
303 | return v / 1024;
304 | }
305 | };
306 |
307 | getGValue(rgb)
308 | {
309 | const ALPHAEX_SHIFT = 1024;
310 | const ALPHAEX_MAX = 1023;
311 | const RGBEX_SHIFT = 16384;
312 | const RGBEX_MAX = 8191;
313 | const RGBEX_MIN = -8192;
314 | if (rgb >= 0) return ((rgb & 65280) >> 8) / 255;
315 | else {
316 | let v = Math.floor(
317 | (-rgb % (RGBEX_SHIFT * RGBEX_SHIFT * ALPHAEX_SHIFT)) /
318 | (RGBEX_SHIFT * ALPHAEX_SHIFT)
319 | );
320 | if (v > RGBEX_MAX) v -= RGBEX_SHIFT;
321 | return v / 1024;
322 | }
323 | };
324 |
325 | getBValue(rgb)
326 | {
327 | const ALPHAEX_SHIFT = 1024;
328 | const ALPHAEX_MAX = 1023;
329 | const RGBEX_SHIFT = 16384;
330 | const RGBEX_MAX = 8191;
331 | const RGBEX_MIN = -8192;
332 | if (rgb >= 0) return ((rgb & 16711680) >> 16) / 255;
333 | else {
334 | let v = Math.floor(
335 | (-rgb % (RGBEX_SHIFT * ALPHAEX_SHIFT)) / ALPHAEX_SHIFT
336 | );
337 | if (v > RGBEX_MAX) v -= RGBEX_SHIFT;
338 | return v / 1024;
339 | }
340 | };
341 |
342 | getAValue(rgb)
343 | {
344 | const ALPHAEX_SHIFT = 1024;
345 | const ALPHAEX_MAX = 1023;
346 | const RGBEX_SHIFT = 16384;
347 | const RGBEX_MAX = 8191;
348 | const RGBEX_MIN = -8192;
349 | if (rgb === 0 && 1 / rgb < 0) return 0;
350 | else if (rgb >= 0) return 1;
351 | else {
352 | const v = Math.floor(-rgb % ALPHAEX_SHIFT);
353 | return v / ALPHAEX_MAX;
354 | }
355 | };
356 |
357 | }
358 |
359 | // @ts-ignore
360 | if (!globalThis.spineBatcher)
361 | {
362 | console.info('[Spine] SpineBatcher init, 2.9.1, Spine 4.2.x compatible');
363 | // @ts-ignore
364 | globalThis.spineBatcher = new SpineBatch();
365 | }
--------------------------------------------------------------------------------
/src/c3runtime/actions.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | {
3 | const C3 = self.C3;
4 | const spineBatcher = globalThis.spineBatcher;
5 |
6 | C3.Plugins.Gritsenko_Spine.Acts = {
7 |
8 | SetSkin(skinName){
9 | this._setSkin(skinName);
10 | },
11 |
12 | Flip(isFlipped){
13 | this._flip(isFlipped);
14 | },
15 |
16 | SetAnimation(animationName, loop, start, trackIndex){
17 | this._setAnimation(animationName, loop, start, trackIndex);
18 | },
19 |
20 | SetAlpha(alpha, trackIndex){
21 | if (!this.skeletonInfo || !this.skeletonInfo.skeleton)
22 | {
23 | if (this.debug) console.warn('[Spine] SetAlpha, no state.', alpha, trackIndex, this.uid, this.runtime.GetTickCount());
24 | return;
25 | }
26 |
27 | const state = this.skeletonInfo.state;
28 | if(!state || !state.tracks) return;
29 | const track = state.tracks[trackIndex];
30 | if(!track) return;
31 |
32 | // Clamp alpha to 1-0
33 | track.alpha = Math.max(0,Math.min(1,alpha));
34 | this.SetRenderOnce(1.0, true, this.uid);
35 | },
36 |
37 | DeleteAnimation(trackIndex, mixDuration) {
38 | this._deleteAnimation(trackIndex, mixDuration);
39 | },
40 |
41 | Play(){
42 | this.playAnimation();
43 | this.SetRenderOnce(1.0, true, this.uid);
44 | },
45 |
46 | Stop(){
47 | this.stopAnimation();
48 | this.SetRenderOnce(0.0, false, this.uid);
49 | },
50 |
51 | UpdateBounds() {
52 | this.updateBounds();
53 | },
54 | SetAnimationSpeed(speed){
55 | this._setAnimationSpeed(speed);
56 | },
57 |
58 | SetRegion(slotName, attachmentName, regionName){
59 |
60 | if (!this.skeletonInfo || !this.skeletonInfo.skeleton)
61 | {
62 | if (this.debug) console.warn('[Spine] SetRegion, no skeleton.', slotName, attachmentName, regionName, this.uid, this.runtime.GetTickCount());
63 | return;
64 | }
65 |
66 | // First get the new region from the atlas.
67 | const atlas = this.skeletonInfo.atlas;
68 | const skeleton = this.skeletonInfo.skeleton;
69 |
70 | let region = atlas.findRegion(regionName);
71 | if (region == null) throw new Error("Region not found in atlas: " + regionName + " " + this.uid);
72 |
73 | // Get the existing attachment, if skin not on skeleton
74 | // let skin = skeleton.data.findSkin(skinName)
75 | let slotIndex = skeleton.data.findSlot(slotName).index
76 | // let existing = skin.getAttachment(slotIndex, 'hairs');
77 |
78 | // Alternatively if the skin is set on the skeleton, you can get it from the skeleton.
79 | let existing = skeleton.getAttachment(slotIndex, attachmentName);
80 |
81 | // Now do what AtlasAttachmentLoader does:
82 | // https://github.com/EsotericSoftware/spine-runtimes/blob/3.8/spine-ts/core/src/AtlasAttachmentLoader.ts#L42
83 | region.renderObject = region;
84 | existing.region = region;
85 | existing.updateRegion()
86 |
87 | this.SetRenderOnce(1.0, true, this.uid);
88 | },
89 |
90 | SetAttachment(slotName, attachmentName)
91 | {
92 | if (!this.skeletonInfo || !this.skeletonInfo.skeleton)
93 | {
94 | if (this.debug) console.warn('[Spine] SetAttachment, no skeleton.', slotName, attachmentName, this.uid, this.runtime.GetTickCount());
95 | return;
96 | }
97 |
98 | const skeleton = this.skeletonInfo.skeleton;
99 |
100 | skeleton.setAttachment(slotName,attachmentName);
101 | this.SetRenderOnce(1.0, true, this.uid);
102 | },
103 |
104 | CreateCustomSkin(skinName)
105 | {
106 | if (!this.skeletonInfo || !this.skeletonInfo.skeleton)
107 | {
108 | if (this.debug) console.warn('[Spine] CreateCustomSkin, no skeleton.', skinName, this.uid);
109 | return;
110 | }
111 |
112 | const skeleton = this.skeletonInfo.skeleton;
113 | // If already exists, just clear
114 | if (this.customSkins[skinName])
115 | {
116 | this.customSkins[skinName].clear();
117 | } else
118 | {
119 | this.customSkins[skinName] = new spine.Skin(skinName);
120 | }
121 | },
122 |
123 | AddCustomSkin(skinName,addSkinName)
124 | {
125 | this._addCustomSkin(skinName, addSkinName);
126 | },
127 |
128 | SetCustomSkin(skinName)
129 | {
130 | if (!this.skeletonInfo || !this.skeletonInfo.skeleton)
131 | {
132 | if (this.debug) console.warn('[Spine] SetCustomSkin, no skeleton', skinName, this.uid, this.runtime.GetTickCount());
133 | return;
134 | }
135 |
136 | this.skinName = skinName
137 | const skeleton = this.skeletonInfo.skeleton;
138 | skeleton.setSkin(this.customSkins[this.skinName]);
139 | skeleton.setSlotsToSetupPose();
140 |
141 | this.SetRenderOnce(1.0, true, this.uid);
142 | },
143 |
144 | SetCustomAttachmentColor(skinName, slotName, attachmentName, color)
145 | {
146 | if (!this.skeletonInfo || !this.skeletonInfo.skeleton)
147 | {
148 | if (this.debug) console.warn('[Spine] SetCustomAttachmentColor, no skeleton', skinName, slotName, attachmentName, color, this.uid, this.runtime.GetTickCount());
149 | return;
150 | }
151 |
152 | const skeleton = this.skeletonInfo.skeleton;
153 | let skin = this.customSkins[skinName];
154 | let slotIndex = skeleton.data.findSlot(slotName).index;
155 | let slot = skeleton.findSlot(slotName);
156 | let attachment = skin.getAttachment(slotIndex, attachmentName);
157 | let newAttachment = attachment.copy();
158 |
159 | let tint = new spine.Color(
160 | spineBatcher.getRValue(color),
161 | spineBatcher.getGValue(color),
162 | spineBatcher.getBValue(color),
163 | spineBatcher.getAValue(color));
164 |
165 | newAttachment.color = tint;
166 | skin.setAttachment(slotIndex, attachmentName, newAttachment);
167 | skeleton.setSkin(this.customSkins[skinName]);
168 | skeleton.setSlotsToSetupPose();
169 |
170 | this.SetRenderOnce(1.0, true, this.uid);
171 | },
172 |
173 | SetSlotColor(slotName, color)
174 | {
175 | this.slotColors[slotName] = color;
176 | this.SetRenderOnce(1.0, true, this.uid);
177 | },
178 |
179 | SetSlotDarkColor(slotName, darkColor)
180 | {
181 | this.slotDarkColors[slotName] = darkColor;
182 | this.SetRenderOnce(1.0, true, this.uid);
183 | },
184 |
185 | ApplySlotColors()
186 | {
187 | this._applySlotColors()
188 | },
189 |
190 | ResetSlotColors()
191 | {
192 | if (!this.skeletonInfo || !this.skeletonInfo.skeleton)
193 | {
194 | if (this.debug) console.warn('[Spine] ResetSlotColors, no skeleton.', this.uid, this.runtime.GetTickCount());
195 | return;
196 | }
197 |
198 | const skeleton = this.skeletonInfo.skeleton;
199 | this.slotColors = {};
200 | this.slotDarkColors = {};
201 | skeleton.setSlotsToSetupPose();
202 |
203 | this.SetRenderOnce(1.0, true, this.uid);
204 | },
205 |
206 | SetAnimationTime(units, time, trackIndex)
207 | {
208 | this._setAnimationTime(units, time, trackIndex);
209 | },
210 |
211 | UpdateBBoxes()
212 | {
213 | this.skeletonInfo.skeletonBounds.update(this.skeletonInfo.skeleton, true);
214 | },
215 |
216 | SetAnimationMix(fromName, toName, duration)
217 | {
218 | this._setAnimationMix(fromName, toName, duration);
219 | },
220 |
221 | SetObjectRenderRate(renderRate)
222 | {
223 | if (!globalThis.spineBatcher)
224 | {
225 | if (this.debug) console.warn('[Spine] SetObjectRenderRate, error no spineBatcher.', renderRate, this.uid, this.runtime.GetTickCount());
226 | return;
227 | }
228 |
229 | globalThis.spineBatcher.renderRate = renderRate;
230 | },
231 |
232 | SetDebug(enable)
233 | {
234 | this.debug = enable;
235 | },
236 |
237 | SetDebugVariable(name,value)
238 | {
239 | if (!spineBatcher) {console.warn('[Spine] SetDebugVariable, no spineBatcher',name,value);return}
240 | spineBatcher.debugVariables[name] = value;
241 | if (this.debug) console.info('[Spine] SetDebugVariable',name,value,spineBatcher.debugVariables);
242 | },
243 |
244 | SetBoneControl(bone, propertyIndex, value)
245 | {
246 | let properties=['x','y','rotation','scaleX','scaleY'];
247 | this.spineBoneControl.setBoneControl(bone, properties[propertyIndex], value);
248 |
249 | this.SetRenderOnce(0.017, true, this.uid);
250 | },
251 |
252 | RemoveBoneControl(bone, propertyIndex)
253 | {
254 | let properties=['x','y','rotation','scaleX','scaleY'];
255 | this.spineBoneControl.removeBoneControl(bone, properties[propertyIndex]);
256 |
257 | this.SetRenderOnce(0.017, true, this.uid);
258 | },
259 |
260 | RemoveAllBoneControl(bone)
261 | {
262 | this.spineBoneControl.removeAllBoneControl(bone);
263 |
264 | this.SetRenderOnce(0.017, true, this.uid);
265 | },
266 |
267 | SetSkeletondataRenderQuality(renderQuality)
268 | {
269 | this.sdkType._skeletonRenderQuality = renderQuality;
270 | const assetManager = this._sdkType._assetManager;
271 | const assetTag = this._sdkType._assetTag;
272 | this._sdkType._skeletonJson.scale = renderQuality;
273 | // JSON file with one skeleton, no name
274 | if (this.skeletonName == "")
275 | {
276 | // this._sdkType._skeletonData = this._sdkType._skeletonJson.readSkeletonData(this.assetManager.get(this.DEMO_NAME, this.jsonURI));
277 | this._sdkType._skeletonData = this._sdkType._skeletonJson.readSkeletonData(assetManager.get(this._sdkType._jsonURI));
278 | } else
279 | {
280 | this._sdkType._skeletonData = this._sdkType._skeletonJson.readSkeletonData(assetManager.get(this._sdkType._jsonURI) [this.skeletonName] );
281 | }
282 | },
283 |
284 | SetValue(value, pathString)
285 | {
286 | let path = pathString.split(".");
287 | this.SetValuePath(value, path);
288 | },
289 |
290 | SetNull(pathString)
291 | {
292 | let path = pathString.split(".");
293 | this.SetValuePath(null, path);
294 | },
295 |
296 | DeleteKey(pathString)
297 | {
298 | let path = pathString.split('.');
299 | let key = path.pop();
300 | let result = this.GetValuePath(path,false);
301 | if (typeof result !== 'object' || result === null) return;
302 | delete result[key];
303 | },
304 |
305 | SetJSON(jsonString, pathString)
306 | {
307 | try
308 | {
309 | if (pathString === "")
310 | {
311 | this.data = JSON.parse(jsonString);
312 | return;
313 | }
314 | let path = pathString.split('.');
315 | let key = path.pop();
316 | let result = this.GetValuePath(path,true);
317 | if (typeof result === 'object')
318 | {
319 | console.log('parse', JSON.parse(jsonString));
320 | result[key] = JSON.parse(jsonString);
321 | }
322 | }
323 | catch(err)
324 | {
325 | console.warn('[Spine] JSON parse error', err, jsonString);
326 | return false;
327 | }
328 | },
329 |
330 | EnablePaletteColor(enable)
331 | {
332 | if (!this.skeletonInfo || !this.skeletonInfo.skeleton)
333 | {
334 | if (this.debug) console.warn('[Spine] EnablePaletteColor, no skeleton', this.uid, this.runtime.GetTickCount());
335 | return;
336 | }
337 |
338 | if (enable === 0)
339 | {
340 | this.palette.enable = true;
341 | } else
342 | {
343 | this.palette.enable = false;
344 | }
345 | },
346 |
347 | SetSlotPalette(slotName, paletteNumber)
348 | {
349 | this.palette.setSlotPalette(slotName, paletteNumber);
350 | },
351 |
352 | SetSlotPaletteOffset(slotName, paletteOffset)
353 | {
354 | this.palette.setSlotPaletteOffset(slotName, paletteOffset);
355 | },
356 |
357 | SetPaletteDefaultColors(paletteNumber)
358 | {
359 | if (!this.skeletonInfo || !this.skeletonInfo.skeleton)
360 | {
361 | if (this.debug) console.warn('[Spine] SetPaletteDefaultColors, no skeleton', this.uid, this.runtime.GetTickCount());
362 | return;
363 | }
364 |
365 | this.palette.setDefaultColors(paletteNumber, 1.0, 1.0);
366 |
367 | this.palette.entryUploadNeeded[paletteNumber] = true;
368 | this.palette.uploadNeeded = true;
369 | },
370 |
371 | SetPaletteColor(paletteNumber, index, color)
372 | {
373 | if (!this.skeletonInfo || !this.skeletonInfo.skeleton)
374 | {
375 | if (this.debug) console.warn('[Spine] SetPaletteColor, no skeleton', this.uid, this.runtime.GetTickCount());
376 | return;
377 | }
378 |
379 | this.palette.setColor(paletteNumber, index, color)
380 |
381 | this.palette.entryUploadNeeded[paletteNumber] = true;
382 | this.palette.uploadNeeded = true;
383 | },
384 |
385 | SetAllPaletteColors(value)
386 | {
387 | let length = value.length;
388 | if (length/2 > this.palette.palette.length)
389 | {
390 | console.warn('[Spine] SetAllPaletteColorsFromString string too long:', length)
391 | }
392 | for(let i=0;i indexSize*2*4)
406 | {
407 | console.warn('[Spine] SetEntryPaletteColorsFromString string too long:', length)
408 | }
409 | for(let i=0;i [!WARNING]
3 | > project repository moved to the adderss:
4 | # https://github.com/MikalDev/c3_spine_plugin
5 |
6 | and the current repo will be archived
7 |
8 | ---
9 |
10 | ## Spine 4.2 add-on for Construct 3 - Must use Spine 4.2 export format
11 |
12 | ### Please support development of the C3 Spine plugin (thanks to all those kind folks who have donated so far!)
13 |
14 | [](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=T8VV6CJVP3X3S)
15 |
16 | If paypal does not work, you can try:
17 |
18 |
19 | - Commisions for specific new features are also accepted, contact Mikal via Twitter @kindeyegames or the Construct Community Discord server (Mikal).
20 |
21 | ## Important notes for Spine export files:
22 | - Requires Spine version 4.2.x Spine JSON files.
23 | - Spine 4.2.x JSON files require 2.4+ C3 addon version.
24 | - When exporting from Spine 4.2 use 4.2 export format.
25 | - In the Spine export dialogue box, under Runtime, set both 'Filter min' and 'Filter mag' to Linear or Nearest.
26 | - In the Packing settings, set Region Padding to 2 or higher (if you see lines around your images, it may be because padding is set to 0).
27 | - Max texture size, 4096x4096. multiple texture sheets supported (use comma separated list on C3 spine object's png path property).
28 |
29 | ## Additional Spine project guidelines:
30 | - Do not use minify on export of C3 project.
31 | - Worker mode supported for C3.
32 | - For jumping or large movments, animate Spine character 'in place', don't do large translations in the Spine project.
33 | - Use C3 events and movement to do the large translations in the C3 project instead (e.g. a long jump.)
34 | - If animation is clipping against the bounds of the C3 object, you can use the property bbox override and values to control the bounding box size and center offset. The values are based on Spine project coordinates.
35 | - Alternatively create a large transparent image in the Spine project behind your Spine character, this will can be used to set the bounding box size fot the C3 spine render.
36 |
37 | ## Multiple instances of a C3 Spine Object
38 | - Each C3 Spine Object (not instance), should load only one skeleton and only one atlas.
39 | - Other instances of the Spine Object must use the same skeleton and atlas, but can use different skins.
40 | - This new change reduces the size of the texture memory required for multiple instances of the same skeleton.
41 |
42 | ## Set region action
43 | - This action changes the current region texture on the skeleton/slot/placeholder of the current skin of the skeleton to a new region in the loaded atlas. All other instances of the same skeleton/skin will also change. This can be useful for customizing skins. Using skins is the typical way to do this.
44 |
45 | ## Custom skins
46 | - Runtime skins can be created, using *Create custom skin*, *Add custom skin* and *Set custom skin*.
47 |
48 | ## Slot color/dark color
49 | - Slot color can be set through *Set slot color* and *Set slot dark color*. The colors are applied using *Apply slot colors*. The slot colors will be reverted if a new skin is applied or if the Spine animation changes the slot colors. To reset the slot colors to the original colors, use *Reset slot colors*. Dark color will only be applied if 'Tint Black' is enabled for the slot in the Spine project.
50 |
51 | ## Render quality
52 | - This sets the resolution of the texture to render to. Lower quality requres less texture memory and GPU performance.
53 |
54 | ## Bounding Box Attachment
55 | - SpineBBoxCenterX, SpineBBoxCenterY espressions give the average of the named slot/bbox polygon points. Useful for attaching C3 Sprite object / collision box to the center of the Bounding Box.
56 | - The UpdateBBoxes updates the bounding box to the current point in the animation. It should be done just once per tick per instance, before the SpineBBoxCenterX/Y expressions are used.
57 | - SpineBBoxGetPoly expression returns poly points in JSON format array of named slot/bounding box attachment. Use C3 JSON object to parse and use points. The points are returned in top level JSON array [x0,y0, x1, y1,...]
58 | - [Spine Bounding Box Attachment Documentation](http://en.esotericsoftware.com/spine-bounding-boxes)
59 |
60 | ## Bone control ACEs
61 | - ACEs to override properties of bones (x,y,rotation, scale x, scale y), these are applied prior to IK transformation, but are useful for controlling 'endpoints' of IK, for example with an aim / crosshair bone.
62 |
63 | ## Bone position -> use Bounding Box attachments
64 | Current bone position values are not available, you can only 'force' their values.
65 |
66 | Instead if you want to use a Spine position to reference in C3, you should add a bounding box to the spine project attached to a bone where you want it (e.g. at the tip of a sword) and use the bounding box expressions to read the value of the bounding box (either the points of the box or the center.) The github site has a little more information on that (you also need to use the update bounding box ACE to get the latest values.) See above for more details.
67 |
68 | ## Render quality ACE
69 | - Controls Spine render resolution
70 | - Only apply to one Spine instance per Spine object (e.g. use pick top instance).
71 | - Wait 0.1S after applying (caution for race condition, reviewing need.)
72 | - After done, destroy all Spine instance and then recreate as needed with the new render quality.
73 |
74 | ## Load Files ACE
75 | - If no json path is defined on the Spine object, the files can be loaded during runtime (only once).
76 | - It is also possible to use URLs for paths besides local C3 files. One change required is to replace the atlas file's image file pointer(s), usually the first line in the file to their corresponding URLs (e.g. skeleton.png to https://cdn.mygame.com/spine/skeleton.png).
77 | - If using URLs, one thing to watch out for is cache behavior of browsers, in our game when we update our cdn hosted Spine files, we change their filenames to stop caching of old files (the new file names are fetched from another cdn config file, which is not cached.)
78 |
79 | ## Share your C3 and Spine plugin work!
80 | - Tweet your work @kindeyegames , @pix2d and #construct3, we'd be happy to see your work!
81 |
82 | ## Debugging issues
83 | - Make sure all file names are lowercase, including on export from Spine (the png file names are embedded into the atlas data also)
84 | - Check that file names in property match project file names
85 | - Check that animation names include animation 'folder' name also if you use folders for animations.
86 | - If only one skeleton, leave skeleton property blank.
87 | - Check the debug property, during runtime, open the dev console window and check for errors or warnings.
88 |
89 | ## Known issues / workarounds
90 | - Clipping on rendering, consider using bbxo override to set the render area and centering, do not use keep aspect when this is used.
91 | - Animation finished with animation mix causing another finished trigger see [issue](https://github.com/gritsenko/c3_spine_plugin/issues/44) for workaround.
92 | - No render of default skin w/ no bones assigned, instead assign default skin bones.
93 |
94 | ### Example export settings
95 | [](docs/images/SpineExportSettings.png)
96 |
97 | Add-on based on **Mikal's** sample from this [thread](https://www.construct.net/en/forum/construct-3/general-discussion-7/spine-animation-js-template-145940)
98 |
99 | ## Downloads
100 | [Current Add-on, Release 2.8.2, Spine 4.2 supported](https://github.com/gritsenko/c3_spine_plugin/releases/download/2.9.0/Spine-v2.9.0.c3addon)
101 |
102 | [Previous Add-on Releases](https://github.com/gritsenko/c3_spine_plugin/releases)
103 | #### Please support development of the C3 Spine plugin for Spine 4.x
104 | [](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=T8VV6CJVP3X3S)
105 | #### Please report issues to: [Issues](https://github.com/gritsenko/c3_spine_plugin/issues)
106 |
107 | ## Example project, simple load and multi-track animation and bone control
108 | [SpineboyAim.c3p](https://github.com/gritsenko/c3_spine_plugin/releases/download/2.8.2/SpineboyAim.c3p)
109 | [SpineMixandMatch-4-1.c3p](https://github.com/gritsenko/c3_spine_plugin/releases/download/2.8.2/SpineMixandMatch-4-1.c3p)
110 |
111 | ## LIVE DEMO
112 | [Live Demo](https://gritsenko.github.io/c3_spine_plugin/docs/LiveDemo/index.html)
113 |
114 | ## Spine Formatter (3.3+ to 3.8 JSON Format)
115 | Useful for Dragon Bones Spine JSON export and earlier Spine versions.
116 | Note that only addon version 1.x support 3.8 JSON Format
117 |
118 | [Spine Formatter](https://gritsenko.github.io/c3_spine_plugin/formatter/index.html)
119 |
120 | ## Current supported features
121 | - Load Spine json, atlas and pngs.
122 | - Select starting skin, skeleton, animation
123 | - Dynamically set existing skin defined in JSON
124 | - Mesh Deformations
125 | - Animation set, play, pause, trigger on animation complete.
126 | - Animation set time, play from beginning, current time, current ratio.
127 | - Animation finished, animation playing conditions.
128 | - Default mix interval for blending animations.
129 | - Per animation pair mix duration control.
130 | - Dynamic animation speed control.
131 | - Dynamic region changing for current skin attachments.
132 | - Events to trigger C3 triggers.
133 | - Render Quality property (upsample, downsample rendered image, improve quality vs save on GPU performance and texture memory.)
134 | - Add expressions TextureWidth, TextureHeight (texture size used to display Spine), based on original Spine bounds and RenderQuality setting.
135 | - Multiple skeleton instances (w/ variable skin) per Spine object (save on atlas texture memory usage and faster to spawn new instances.)
136 | - Batch render for improved performance with multiple Spine instances and objects.
137 | - Multiple atlas pages (multiple pngs).
138 | - Mix and Match skins, custom runtime skins.
139 | - C3 worker mode support.
140 | - Color/Dark Color for Slot at runtime.
141 | - BoundingBoxAttachment center expressions.
142 | - Set Object Render Rate, controls number of ticks per render of the Spine object, distributed amongst the number of instances of the object. This can reduce the CPU performance and GPU performance vs the frame rate of the render.
143 | - C3 Module mode support.
144 | - Animation track support.
145 | - Disable render to texture when offscreen or animation is complete/stopped (perf optimization)
146 | - Bone control.
147 | - Object C3 color control
148 | - Load Files at runtime (load json/atlas/png files once during runtime, watch for cache behavior if using URLs)
149 | - Attachment sequence animation supported (spine-ts 4.1 runtime)
150 |
151 | ## Wishlist
152 | - Preview Spine render in editor (dependent on C3 editor SDK updates)
153 |
154 | ## Release notes
155 | - 2.9.0 Add 4.2 support (physics)
156 | - 2.8.2 Fix C3 r234 compatability, fix set region ACE for 4.1 Spine SDK
157 | - 2.8.0 Add script interface for setSkin, flip
158 | - 2.7.0 Add Enable Sequence Autoplay ACE to enable sequence autoplay (autoplay sequence animations and fps)
159 | - 2.5.0 Add standard zElevation property and ACEs
160 | - 2.4.0 4.1.19 spine-ts runtime, compatible with Spine 4.1.x export files (sequence animations), Load Files ACE
161 | - 2.2.0 Add color property and ACEs, webgl / C3 special case render bug fix
162 | - 2.1.0 Add GetEventData expression, On any animation event condition
163 | - 2.0.1 Fix SpineBBoxCenterX to accept slot and name (previously was ignoring slot)
164 | - 2.0.0 4.0 spine-ts runtime, compatible with Spine 4.0.x export files
165 | - 1.55.1 Fix addCustomSkinOutfit update slot colors for dependent colors
166 | - 1.55.0 Add addCustomSkinOutfit skin tone
167 | - 1.54.0 Add addCustomSkinOutfit skin, color
168 | - 1.53.0 Add expressions for bbox and scale properties
169 | - 1.52.0 Add customSkinOutfit script interface
170 | - 1.51.1 Add icon, error handling for addCustomSkinOutfit
171 | - 1.50.2 Fix worker mode support for C3
172 | - 1.50.1 Fix slot color related to script add customskinoutfit
173 | - 1.50.0 Add hex color support for set slot color and set slot dark color ACEs
174 | - 1.49.0 Add scripting interface for animations.
175 | - 1.48.0 Scripting interface for Apply slot colors, scripting interface for addCustomSkinOutfit (quickly update custom skin from object)
176 | - 1.47.5 Make compatible with ProUI plugin for scroll lists
177 | - 1.47.3 Add bounding box override checkbox (can set bounding box in property, no need for transparent bounding box)
178 | - 1.46.0 More animation scripting interfaces
179 | - 1.45.0 Animation scripting interfaces
180 | - 1.44.0 Palette loading optimization (if only a few palette entries need update, just update those areas of the palette texture, otherwise update entire palette texture.)
181 | - 1.36.1 setTracksListner guard clause (do not crash if skeleton is not initialized or removed.)
182 | - 1.36.0 Init refactor (internal clean up)
183 | - 1.35.0 Fix current time event regression, no apply() in setAnimation (save some CPU)
184 | - 1.34.2 Fix bbox ACEs w/ flipped animation
185 | - 1.34.1 bone control optimization, repeated init bug fix.
186 | - 1.34.0 Add ACE for render quality control
187 | - 1.33.1 Add render once for Bone control actions
188 | - 1.33.0 Bone control Conditions and Expressions
189 | - 1.32.0 Bone control Actions
190 | - 1.31.0 Add gl parameter cache for future optimization to not get gl state parameters every tick.
191 | - 1.30.1 Disable idle animation updates (via debug variable control, set 'reduceAnimation' to 'enable'.
192 | - 1.27.3 Correct idle and offscreen detection
193 | - 1.27.2 Advance animation/slot render while off screen.
194 | - 1.27.1 Add updateCurrentAnimation check if animatioName exists and warn if not.
195 | - 1.27.0 Add parameters and UID to Action console warnings for debug.
196 | - 1.26.1 Return w/o JS error from Expression/Conditions if skeleton not loaded.
197 | - 1.26.0 Add per instance debug enable ACE, return w/o JS error from Actions if skeleton not loaded.
198 | - 1.25.3 Bug fix: animation complete hang, export module fix
199 | - 1.25.1 Advance animation 1s after applying set animation, apply color, set skin, so they will take effect when an animation mix value is present.
200 | - 1.25.0 Advance animation one tick after applying set animation, apply color, set skin, so they will take effect, fix Set and Apply color C3 module mode bugs.
201 | - 1.24.0 Disable render when animation is complete (end of animation) or animation is stopped (perf optimization).
202 | - 1.23.0 Disable render to texture when offscreen (perf optimization), animation continues for events, etc.
203 | - 1.22.2 Add animation track support. Default to track 0 for set, play, stop animation for backward compatability, add isSekeltonLoaded ACE. Add track alpha control to blend animation between tracks. (Feature commisioned by Adrian - thank you!)
204 | - 1.20.0 Add support for R266 module mode, add Set Object Render Rate ACE.
205 | - 1.19.0 Add Set animation mix {fromName} to {toName} with duration {seconds}.
206 | - 1.18.0 Add SpineBBoxGetPoly expression returns poly points in JSON format of named slot/bounding box attachment.
207 | - 1.17.0 Add debug property, SpineBBoxCenterX,Y expressions. UpdateBBoxes action.
208 | - 1.16.3 Add updateWorldTransform on animation set.
209 | - 1.16.2 Change behavior of *Set Animation w/ starting time* to not trigger events if the events were before the starting time.
210 | - 1.16.1 Bug fix for slot color (handle reset and new skin properly, only apply dark color if Tint Black is set in Spine project for slot).
211 | - 1.16.0 Add Set slot dark color, Apply Slot color, Reset Slot color. Add Set animation time and starting point of Set animation (beginning, current time, current ratio). Deprecated set color attachment (did not support dark color). (Feature commisioned by Adrian - thank you!)
212 | - 1.15.2 Add project sampling support to Spine C3 texture.
213 | - 1.15.1 Fix pixel rounding bug.
214 | - 1.15.0 Set Slot Color (temporary until new skin set), [*deprecated* Set Custom Color Attachment] Fix one frame animation bug.
215 | - 1.14.1 Fix PMA bug regression (introduced in 1.11.0)
216 | - 1.14.0 Add C3 worker mode support.
217 | - 1.13.0 Add runtime create skin and add skin ACEs and MixandMatch example project.
218 | - 1.12.1 Change path separator to comma instead of space to match existing skin paths separator.
219 | - 1.12.0 Add support for Atlas pages (multiple png, space separated), finish implmention of Set Attachment action, fix webgl1 support (revealed on iOS w/o weblg2 enabled.)
220 | - 1.11.2 Move spineBatcher.init() to prevent race condition (seen on iOS)
221 | - 1.11.1 Remove spine instance from batcher when C3 Spine instance calls Release() (e.g. C3 object destroyed.)
222 | - 1.11.0 Implement batch render for improved performance with multiple Spine objects and instances.
223 | - 1.10.0: Add Keep Aspect Ratio checkbox
224 | - 1.9.0: Change spine-webgl.js to external script rather than including in C3 DOM script on export.
225 | - 1.8.0: Instances of a spine object will use the original objects skelton info, reducing texture requirements and faster creation of an instance. Add render quality property. Add TextureHeight and TextureWidth ACEs.
226 | - 1.7.0: Add event trigger ACE (trigger when animation event occurs.)
227 | - 1.6.0: Add Set region action (change region(texture) of an attachment in a slot on the current skin. Useful for character customization.
228 |
229 | ## Scripting interface
230 |
231 | ### currentAnimation(trackIndex)
232 | - returns the value of the currentAnimation on trackIndex
233 | - trackIndex: number (track index)
234 | ### deleteAnimation(trackIndex, mixDuration)
235 | - trackIndex: number (track index)
236 | - mixDuration: number (mix duration in seconds)
237 | ### setAnimation(animationName, loop, start, trackIndex)
238 | - animationName: string (animation name)
239 | - loop: boolean (loop animation)
240 | - start: number (0: beginning, 1: current-time, 2: current-ratio)
241 | - trackIndex: number (track index)
242 | ### setAnimationMix(fromName, toName, duration)
243 | - fromName: string (animation name)
244 | - toName: string (animation name)
245 | - duration: number (mix duration in seconds)
246 | ### setAnimationSpeed(speed)
247 | - speed: number (speed multiplier)
248 | ### setAnimationTime(units, time, trackIndex)
249 | - units: number (0: time in ms, 1: ratio)
250 | - time: number (based on units)
251 | - trackIndex: number (track index)
252 | ### setSkin(skinName)
253 | - skinName: string (skin name)
254 | ### flip(flip)
255 | - flip: boolean (flip state)
256 |
--------------------------------------------------------------------------------
/formatter/old_meshes.json:
--------------------------------------------------------------------------------
1 | {"skeleton":{"width":847.2,"height":2178.4,"hash":" ","name":"Armature"},"bones":[{"x":605.8118400000001,"y":1019.10624,"name":"root"},{"length":444,"x":-628.5318400000001,"y":137.97376,"rotation":87.072,"name":"Body","parent":"root"},{"length":146.4,"x":-627.69184,"y":52.77376000000001,"rotation":-85.7388,"name":"Taz","parent":"root"},{"length":312,"x":484.18288000000007,"y":-163.48072000000002,"rotation":-154.0701,"name":"Shoulder_R","parent":"Body"},{"length":141.6,"x":452.9436,"y":2.50024,"rotation":26.1181,"name":"Neck","parent":"Body"},{"length":215.2,"x":386.77696,"y":192.00776,"rotation":177.6835,"name":"Shoulder_L","parent":"Body"},{"length":308.8,"x":187.64184,"y":-101.70344,"rotation":-7.9194,"name":"Befro_L","parent":"Taz"},{"length":311.20000000000005,"x":189.10608,"y":124.132,"rotation":-0.2395,"name":"Bedro_R","parent":"Taz"},{"length":299.2,"x":399.01984,"y":-1.7488800000000002,"rotation":-5.696,"name":"Leg_R","parent":"Bedro_R"},{"length":201.6,"x":272.94136,"y":-5.67504,"rotation":0.8911,"name":"Forearm_L","parent":"Shoulder_L"},{"length":192,"x":335.3432,"y":-3.17104,"rotation":-21.7736,"name":"Forearm_R","parent":"Shoulder_R"},{"length":308.8,"x":383.17776,"y":6.94256,"rotation":7.309,"name":"Leg_L","parent":"Befro_L"},{"length":195.2,"x":148.64848,"y":5.98864,"rotation":7.9806,"name":"Face","parent":"Neck"},{"length":32.800000000000004,"x":261.56072,"y":-6.40384,"rotation":0.5162,"name":"Rukav_L","parent":"Forearm_L"},{"length":60,"x":235.24008,"y":-17.44648,"rotation":-5.1997,"name":"Rukav_R","parent":"Forearm_R"},{"length":60.8,"x":51.138720000000006,"y":-67.16568,"rotation":-73.4269,"name":"Ear","parent":"Face"},{"length":197.6,"x":414.69208,"y":6.447360000000001,"rotation":-65.9554,"name":"Foot_L","parent":"Leg_L"},{"length":152.8,"x":398.33336,"y":-1.48184,"rotation":12.3463,"name":"Foot_R","parent":"Leg_R"},{"length":13.6,"x":80.03936,"y":4.8764,"rotation":-104.1628,"name":"Nijnee_veko_R","parent":"Face"},{"length":11.2,"x":106.97232,"y":77.22064,"rotation":64.7682,"name":"Nijnee_veko_L_","parent":"Face"},{"length":80.80000000000001,"x":53.09584,"y":-7.42336,"rotation":-15.0813,"name":"Wrist_L","parent":"Rukav_L"},{"length":97.6,"x":93.16616,"y":0.25320000000000004,"rotation":10.0369,"name":"Wrist_R","parent":"Rukav_R"},{"length":358.40000000000003,"x":141.07424,"y":6.7438400000000005,"rotation":19.9661,"name":"Pack_Front","parent":"Wrist_L"},{"length":161.60000000000002,"x":137.72512,"y":6.000800000000001,"rotation":-6.8441,"name":"Upper_lyamka","parent":"Wrist_R"},{"length":203.2,"x":205.56176,"y":7.15408,"rotation":-1.6757,"name":"Bag","parent":"Upper_lyamka"},{"length":140.8,"x":9.87816,"y":61.06960000000001,"rotation":6.0855,"name":"Pack_back","parent":"Pack_Front"},{"length":100.8,"x":305.67328000000003,"y":-30.65816,"rotation":-27.4539,"name":"Lower_lyamka","parent":"Bag"}],"slots":[{"name":"Pack_back","bone":"Pack_back","attachment":"MANGA_KAF_dragon/Pack_back"},{"name":"Wrist_L","bone":"Wrist_L","attachment":"MANGA_KAF_dragon/Wrist_L"},{"name":"Shoulder_L","bone":"Shoulder_L","attachment":"MANGA_KAF_dragon/Shoulder_L"},{"name":"Rukav_L","bone":"Rukav_L","attachment":"MANGA_KAF_dragon/Rukav_L"},{"name":"Forearm_L","bone":"Forearm_L","attachment":"MANGA_KAF_dragon/Forearm_L"},{"name":"Pack_Front","bone":"Pack_Front","attachment":"MANGA_KAF_dragon/Pack_Front"},{"name":"Body","bone":"Body","attachment":"MANGA_KAF_dragon/Body"},{"name":"Taz","bone":"Taz","attachment":"MANGA_KAF_dragon/Taz"},{"name":"Foot_L","bone":"Foot_L","attachment":"MANGA_KAF_dragon/Foot_L"},{"name":"Befro_L","bone":"Befro_L","attachment":"MANGA_KAF_dragon/Befro_L"},{"name":"Leg_L","bone":"Leg_L","attachment":"MANGA_KAF_dragon/Leg_L"},{"name":"Foot_R","bone":"Foot_R","attachment":"MANGA_KAF_dragon/Foot_R"},{"name":"Bedro_R","bone":"Bedro_R","attachment":"MANGA_KAF_dragon/Bedro_R"},{"name":"Leg_R","bone":"Leg_R","attachment":"MANGA_KAF_dragon/Leg_R"},{"name":"Jacket_R","bone":"Body","attachment":"MANGA_KAF_dragon/Jacket_R"},{"name":"Wrist_R","bone":"Wrist_R","attachment":"MANGA_KAF_dragon/Wrist_R"},{"name":"Lower_lyamka","bone":"Lower_lyamka","attachment":"MANGA_KAF_dragon/Lower_lyamka"},{"name":"Upper_lyamka","bone":"Upper_lyamka","attachment":"MANGA_KAF_dragon/Upper_lyamka"},{"name":"Bag","bone":"Bag","attachment":"MANGA_KAF_dragon/Bag"},{"name":"Jacket_L","bone":"Body","attachment":"MANGA_KAF_dragon/Jacket_L"},{"name":"Shoulder_R","bone":"Shoulder_R","attachment":"MANGA_KAF_dragon/Shoulder_R"},{"name":"Rukav_R","bone":"Rukav_R","attachment":"MANGA_KAF_dragon/Rukav_R"},{"name":"Forearm_R","bone":"Forearm_R","attachment":"MANGA_KAF_dragon/Forearm_R"},{"name":"Neck","bone":"Neck","attachment":"MANGA_KAF_dragon/Neck"},{"name":"Chain","bone":"Body","attachment":"MANGA_KAF_dragon/Chain"},{"name":"Face","bone":"Face","attachment":"MANGA_KAF_dragon/Face"},{"name":"Eye_R","bone":"Face","attachment":"MANGA_KAF_dragon/Eye_R"},{"name":"Nijnee_veko_R","bone":"Nijnee_veko_R","attachment":"MANGA_KAF_dragon/Nijnee_veko_R"},{"name":"Verh_veko_R","bone":"Face","attachment":"MANGA_KAF_dragon/Verh_veko_R"},{"name":"Eye_L","bone":"Face","attachment":"MANGA_KAF_dragon/Eye_L"},{"name":"Nijnee_veko_L_","bone":"Nijnee_veko_L_","attachment":"MANGA_KAF_dragon/Nijnee_veko_L_"},{"name":"Verh_veko_L_","bone":"Face","attachment":"MANGA_KAF_dragon/Verh_veko_L_"},{"name":"Under_eye_R","bone":"Face","attachment":"MANGA_KAF_dragon/Under_eye_R"},{"name":"Under_eye_L","bone":"Face","attachment":"MANGA_KAF_dragon/Under_eye_L"},{"name":"Nose","bone":"Face","attachment":"MANGA_KAF_dragon/Nose"},{"name":"LOB","bone":"Face","attachment":"MANGA_KAF_dragon/LOB"},{"name":"Eyebrow_L","bone":"Face","attachment":"MANGA_KAF_dragon/Eyebrow_L"},{"name":"Eyebrow_R","bone":"Face","attachment":"MANGA_KAF_dragon/Eyebrow_R"},{"name":"Mouth","bone":"Face","attachment":"MANGA_KAF_dragon/Mouth"},{"name":"Mustages","bone":"Face","attachment":"MANGA_KAF_dragon/Mustages"},{"name":"Ear","bone":"Ear","attachment":"MANGA_KAF_dragon/Ear"},{"name":"Hair","bone":"Face","attachment":"MANGA_KAF_dragon/Hair"}],"skins":{"default":{"Shoulder_R":{"MANGA_KAF_dragon/Shoulder_R":{"name":"MANGA_KAF_dragon/Shoulder_R","width":238,"height":454,"hull":4,"triangles":[1,0,3,0,2,3],"uvs":[0,0,1,0,0,1,1,1],"edges":[0,2,2,6,4,6,4,0],"vertices":[-55.95,6.07,39.9,224.36,359.38,-176.29,455.22,41.99],"type":"mesh"}},"Ear":{"MANGA_KAF_dragon/Ear":{"name":"MANGA_KAF_dragon/Ear","width":56,"height":97,"hull":4,"triangles":[1,0,3,0,2,3],"uvs":[0,0,1,0,0,1,1,1],"edges":[0,2,2,6,4,6,4,0],"vertices":[42.41,48.49,79.99,6.97,-29.36,-16.46,8.21,-57.98],"type":"mesh"}},"Hair":{"MANGA_KAF_dragon/Hair":{"name":"MANGA_KAF_dragon/Hair","width":284,"height":237,"hull":9,"triangles":[8,28,9,28,2,9,16,13,11,13,10,11,16,11,12,14,16,12,19,15,1,15,14,1,14,12,1,9,2,3,10,9,3,11,10,3,6,8,10,13,7,10,7,6,10,8,9,10,19,17,15,16,7,13,15,16,14,15,17,16,17,7,16,17,18,7,6,5,8,5,28,8,18,21,7,21,5,7,5,6,7,19,18,17,22,4,21,4,28,5,21,4,5,20,18,19,20,23,18,23,21,18,22,25,4,0,23,20,0,24,23,27,28,4,23,24,21,24,22,21,25,27,4,27,2,28,24,26,22,26,25,22,0,26,24,26,27,25,26,2,27],"uvs":[0,0,1,0,0,1,1,1,0.2303,0.70969,0.41339,0.70403,0.61418,0.67147,0.66738,0.4732,0.71268,0.87462,0.85564,0.96516,0.94461,0.76157,1,0.36539,1,0.22619,0.91717,0.42988,0.88108,0.14618,0.80508,0.09822,0.83672,0.32821,0.53732,0.08803,0.44366,0.17406,0.46575,0,0.31844,0,0.24759,0.34039,0.15846,0.44229,0.21619,0.26023,0.11355,0.28175,0.10965,0.57078,0,0.38369,0.05187,0.72616,0.16118,0.90512],"edges":[0,40,2,24,2,38,4,6,4,52,6,22,22,24,38,40,52,0],"vertices":[383.41,17.99,235.94,-224.72,181.03,140.95,33.56,-101.77,205.82,49.35,179.97,4.22,156.95,-48.52,189.22,-85.81,101.31,-47.44,61.9,-71.01,89.98,-117.64,162,-179.8,190.16,-196.91,161.16,-151.77,223.89,-177.88,244.81,-165.34,193.59,-144.74,286.35,-101.6,282.76,-68.29,314.72,-95.05,336.44,-59.3,278.01,-0.25,270.53,33.91,298.86,-2.49,309.64,25.07,251.72,61.55,305.76,65.17,228.8,94.68,176.46,90.16],"type":"mesh"}},"Under_eye_L":{"MANGA_KAF_dragon/Under_eye_L":{"name":"MANGA_KAF_dragon/Under_eye_L","width":42,"height":26,"x":98.16,"y":85.63,"rotation":-121.28}},"Body":{"MANGA_KAF_dragon/Body":{"name":"MANGA_KAF_dragon/Body","width":422,"height":629,"hull":4,"triangles":[1,0,3,0,2,3],"uvs":[0,0,1,0,0,1,1,1],"edges":[0,2,2,6,4,6,4,0],"vertices":[583.96,198.58,605.31,-223.28,-44.04,166.81,-22.69,-255.05],"type":"mesh"}},"Nijnee_veko_R":{"MANGA_KAF_dragon/Nijnee_veko_R":{"name":"MANGA_KAF_dragon/Nijnee_veko_R","width":20,"height":10,"x":8.55,"y":0.84,"rotation":-16.99}},"Chain":{"MANGA_KAF_dragon/Chain":{"name":"MANGA_KAF_dragon/Chain","width":180,"height":404,"hull":4,"triangles":[5,6,1,0,5,1,6,4,3,4,2,3,1,6,3,5,4,6,5,2,4,0,2,5],"uvs":[0,0,1,0,0,1,1,1,0.43189,0.61571,0.32998,0.32453,0.80746,0.31059],"edges":[0,2,2,6,4,6,4,0],"vertices":[589.98,130.43,598.69,-49.36,186.45,110.88,195.16,-68.91,345.29,40.74,461.89,64.76,471.68,-20.82],"type":"mesh"}},"Upper_lyamka":{"MANGA_KAF_dragon/Upper_lyamka":{"name":"MANGA_KAF_dragon/Upper_lyamka","width":183,"height":270,"x":94.7,"y":9.38,"rotation":90.67}},"Eyebrow_R":{"MANGA_KAF_dragon/Eyebrow_R":{"name":"MANGA_KAF_dragon/Eyebrow_R","width":59,"height":36,"x":107.55,"y":8.42,"rotation":-121.28}},"Mouth":{"MANGA_KAF_dragon/Mouth":{"name":"MANGA_KAF_dragon/Mouth","width":64,"height":22,"hull":4,"triangles":[1,0,3,0,2,3],"uvs":[0,0,1,0,0,1,1,1],"edges":[0,2,2,6,4,6,4,0],"vertices":[37.56,88.13,4.33,33.43,18.42,99.76,-14.81,45.06],"type":"mesh"}},"Nijnee_veko_L_":{"MANGA_KAF_dragon/Nijnee_veko_L_":{"name":"MANGA_KAF_dragon/Nijnee_veko_L_","width":17,"height":9,"x":4.28,"y":0.25,"rotation":173.95}},"Verh_veko_L_":{"MANGA_KAF_dragon/Verh_veko_L_":{"name":"MANGA_KAF_dragon/Verh_veko_L_","width":36,"height":22,"hull":4,"triangles":[1,0,3,0,2,3],"uvs":[0,0,1,0,0,1,1,1],"edges":[0,2,2,6,4,6,4,0],"vertices":[139.07,87.5,120.37,56.73,119.92,99.13,101.23,68.36],"type":"mesh"}},"Rukav_R":{"MANGA_KAF_dragon/Rukav_R":{"name":"MANGA_KAF_dragon/Rukav_R","width":86,"height":85,"x":37.09,"y":4.19,"rotation":93.86}},"Leg_R":{"MANGA_KAF_dragon/Leg_R":{"name":"MANGA_KAF_dragon/Leg_R","width":160,"height":473,"x":132.58,"y":-2.52,"rotation":91.56}},"Jacket_R":{"MANGA_KAF_dragon/Jacket_R":{"name":"MANGA_KAF_dragon/Jacket_R","width":268,"height":784,"hull":4,"triangles":[1,0,3,0,2,3],"uvs":[0,0,1,0,0,1,1,1],"edges":[0,2,2,6,4,6,4,0],"vertices":[594.93,-38.38,606.64,-306.12,-188.32,-72.61,-176.62,-340.36],"type":"mesh"}},"Nose":{"MANGA_KAF_dragon/Nose":{"name":"MANGA_KAF_dragon/Nose","width":54,"height":64,"hull":4,"triangles":[1,0,3,0,2,3],"uvs":[0,0,1,0,0,1,1,1],"edges":[0,2,2,6,4,6,4,0],"vertices":[114.55,59.17,86.6,13.44,59.95,92.55,31.99,46.82],"type":"mesh"}},"Rukav_L":{"MANGA_KAF_dragon/Rukav_L":{"name":"MANGA_KAF_dragon/Rukav_L","width":88,"height":66,"x":14.12,"y":-0.48,"rotation":93.73}},"Pack_back":{"MANGA_KAF_dragon/Pack_back":{"name":"MANGA_KAF_dragon/Pack_back","width":83,"height":486,"x":122.08,"y":9.36,"rotation":82.76}},"Face":{"MANGA_KAF_dragon/Face":{"name":"MANGA_KAF_dragon/Face","width":265,"height":346,"hull":4,"triangles":[1,0,3,0,2,3],"uvs":[0,0,1,0,0,1,1,1],"edges":[0,2,2,6,4,6,4,0],"vertices":[314.59,15.55,177.09,-210.76,18.55,195.42,-118.95,-30.89],"type":"mesh"}},"Bag":{"MANGA_KAF_dragon/Bag":{"name":"MANGA_KAF_dragon/Bag","width":366,"height":290,"hull":9,"triangles":[5,3,9,4,5,9,1,6,9,6,4,9,0,4,6,0,7,4,7,8,4,4,8,5,8,2,5],"uvs":[0,0,1,0,0,1,1,1,0.55757,0.33301,0.57968,1,0.87203,0,0,0.34469,0,0.85818,1,0.8694],"edges":[0,12,2,12,2,18,4,10,4,16,6,10,6,18,14,16,14,0],"vertices":[-10.54,-211.43,-25.52,154.66,279.62,-199.56,264.64,166.53,77.73,-3.35,270.94,12.66,-23.6,107.81,89.47,-207.34,238.47,-201.24,226.74,164.98],"type":"mesh"}},"Leg_L":{"MANGA_KAF_dragon/Leg_L":{"name":"MANGA_KAF_dragon/Leg_L","width":162,"height":495,"x":132.53,"y":-2.95,"rotation":86.24}},"Mustages":{"MANGA_KAF_dragon/Mustages":{"name":"MANGA_KAF_dragon/Mustages","width":71,"height":18,"hull":4,"triangles":[1,0,3,0,2,3],"uvs":[0,0,1,0,0,1,1,1],"edges":[0,2,2,6,4,6,4,0],"vertices":[55.4,86.69,18.43,25.84,40.36,95.83,3.39,34.98],"type":"mesh"}},"Forearm_L":{"MANGA_KAF_dragon/Forearm_L":{"name":"MANGA_KAF_dragon/Forearm_L","width":163,"height":330,"hull":4,"triangles":[1,0,3,0,2,3],"uvs":[0,0,1,0,0,1,1,1],"edges":[0,2,2,6,4,6,4,0],"vertices":[-58.38,-84.02,-70.45,78.73,270.32,-59.64,258.25,103.11],"type":"mesh"}},"Under_eye_R":{"MANGA_KAF_dragon/Under_eye_R":{"name":"MANGA_KAF_dragon/Under_eye_R","width":73,"height":39,"x":72.48,"y":2.99,"rotation":-121.15}},"Forearm_R":{"MANGA_KAF_dragon/Forearm_R":{"name":"MANGA_KAF_dragon/Forearm_R","width":166,"height":277,"hull":4,"triangles":[1,0,3,0,2,3],"uvs":[0,0,1,0,0,1,1,1],"edges":[0,2,2,6,4,6,4,0],"vertices":[-28.89,-73.52,-25,92.84,247.83,-79.99,251.72,86.37],"type":"mesh"}},"Foot_R":{"MANGA_KAF_dragon/Foot_R":{"name":"MANGA_KAF_dragon/Foot_R","width":207,"height":277,"x":76.79,"y":8.25,"rotation":79.22}},"Taz":{"MANGA_KAF_dragon/Taz":{"name":"MANGA_KAF_dragon/Taz","width":414,"height":301,"hull":8,"triangles":[6,8,1,1,8,3,8,7,3,9,8,6,4,9,6,8,5,7,9,5,8,2,5,9,0,2,9,4,0,9],"uvs":[0,0,1,0,0,1,1,1,0.26058,0,0.23236,1,0.62408,0,0.62927,1,0.54937,0.75687,0.28737,0.67087],"edges":[0,4,2,6,2,12,4,10,6,14,8,12,10,14,8,0],"vertices":[-106.5,-159.7,-75.88,253.57,193.48,-181.92,224.1,231.34,-98.52,-52.01,200.59,-85.9,-87.39,98.21,212.74,78.13,137.36,50.51,103.55,-55.85],"type":"mesh"}},"Foot_L":{"MANGA_KAF_dragon/Foot_L":{"name":"MANGA_KAF_dragon/Foot_L","width":339,"height":264,"x":77.47,"y":15.59,"rotation":152.19}},"Verh_veko_R":{"MANGA_KAF_dragon/Verh_veko_R":{"name":"MANGA_KAF_dragon/Verh_veko_R","width":49,"height":31,"hull":4,"triangles":[1,0,3,0,2,3],"uvs":[0,0,1,0,0,1,1,1],"edges":[0,2,2,6,4,6,4,0],"vertices":[112.58,8.14,87.24,-33.56,85.92,24.34,60.58,-17.36],"type":"mesh"}},"Eye_L":{"MANGA_KAF_dragon/Eye_L":{"name":"MANGA_KAF_dragon/Eye_L","width":15,"height":15,"hull":4,"triangles":[1,0,3,0,2,3],"uvs":[0,0,1,0,0,1,1,1],"edges":[0,2,2,6,4,6,4,0],"vertices":[125.71,77.82,117.82,64.83,112.72,85.72,104.83,72.72],"type":"mesh"}},"Eye_R":{"MANGA_KAF_dragon/Eye_R":{"name":"MANGA_KAF_dragon/Eye_R","width":18,"height":16,"hull":4,"triangles":[1,0,3,0,2,3],"uvs":[0,0,1,0,0,1,1,1],"edges":[0,2,2,6,4,6,4,0],"vertices":[97.98,-3.58,88.42,-19.3,84.3,4.73,74.75,-10.99],"type":"mesh"}},"Jacket_L":{"MANGA_KAF_dragon/Jacket_L":{"name":"MANGA_KAF_dragon/Jacket_L","width":142,"height":738,"hull":4,"triangles":[1,0,3,0,2,3],"uvs":[0,0,1,0,0,1,1,1],"edges":[0,2,2,6,4,6,4,0],"vertices":[558.02,220.74,564.97,79.31,-178.69,184.5,-171.74,43.07],"type":"mesh"}},"Bedro_R":{"MANGA_KAF_dragon/Bedro_R":{"name":"MANGA_KAF_dragon/Bedro_R","width":232,"height":501,"hull":4,"triangles":[1,0,3,0,2,3],"uvs":[0,0,1,0,0,1,1,1],"edges":[0,2,2,6,4,6,4,0],"vertices":[-101.67,-105.59,-84.95,125.81,397.83,-141.68,414.55,89.71],"type":"mesh"}},"LOB":{"MANGA_KAF_dragon/LOB":{"name":"MANGA_KAF_dragon/LOB","width":57,"height":21,"hull":4,"triangles":[1,0,3,0,2,3],"uvs":[0,0,1,0,0,1,1,1],"edges":[0,2,2,6,4,6,4,0],"vertices":[163.42,64.35,133.93,15.81,145.65,75.15,116.15,26.61],"type":"mesh"}},"Pack_Front":{"MANGA_KAF_dragon/Pack_Front":{"name":"MANGA_KAF_dragon/Pack_Front","width":271,"height":522,"hull":6,"triangles":[0,2,4,0,4,5,1,5,3,5,4,3],"uvs":[0,0,1,0,0,1,1,1,0.37721,1,0.45754,0],"edges":[0,4,2,6,2,10,4,8,6,8,10,0],"vertices":[-91.56,-88.14,-86.07,183,430.74,-98.71,436.22,172.44,432.81,3.57,-89.05,35.92],"type":"mesh"}},"Neck":{"MANGA_KAF_dragon/Neck":{"name":"MANGA_KAF_dragon/Neck","width":166,"height":224,"x":114.23,"y":-1.39,"rotation":-113.3}},"Wrist_R":{"MANGA_KAF_dragon/Wrist_R":{"name":"MANGA_KAF_dragon/Wrist_R","width":130,"height":203,"x":45.51,"y":16.29,"rotation":83.82}},"Lower_lyamka":{"MANGA_KAF_dragon/Lower_lyamka":{"name":"MANGA_KAF_dragon/Lower_lyamka","width":258,"height":210,"x":9.89,"y":5.06,"rotation":119.8}},"Eyebrow_L":{"MANGA_KAF_dragon/Eyebrow_L":{"name":"MANGA_KAF_dragon/Eyebrow_L","width":44,"height":11,"x":129.75,"y":76.8,"rotation":-121.28}},"Befro_L":{"MANGA_KAF_dragon/Befro_L":{"name":"MANGA_KAF_dragon/Befro_L","width":244,"height":523,"hull":4,"triangles":[1,0,3,0,2,3],"uvs":[0,0,1,0,0,1,1,1],"edges":[0,2,2,6,4,6,4,0],"vertices":[-105.07,-120.47,-120.17,123.06,417.13,-88.1,402.03,155.43],"type":"mesh"}},"Wrist_L":{"MANGA_KAF_dragon/Wrist_L":{"name":"MANGA_KAF_dragon/Wrist_L","width":100,"height":149,"x":32.68,"y":-5.36,"rotation":108.81}},"Shoulder_L":{"MANGA_KAF_dragon/Shoulder_L":{"name":"MANGA_KAF_dragon/Shoulder_L","width":134,"height":386,"x":125.22,"y":19.26,"rotation":95.13}}}},"animations":{"idle":{"bones":{"Body":{"translate":[{"time":0,"curve":[0.5,0,0.5,1]},{"time":0.3,"curve":[0.5,0,0.5,1],"y":-1.34},{"time":1.3333}],"rotate":[{"time":0,"curve":[0.5,0,0.5,1],"angle":-1.2},{"time":0.3,"curve":[0.5,0,0.5,1],"angle":-0.16},{"time":0.6667,"curve":[0.5,0,0.5,1],"angle":0.32},{"time":0.9667,"curve":[0.5,0,0.5,1],"angle":0.52},{"time":1,"curve":[0.5,0,0.5,1],"angle":0.53},{"time":1.3333,"curve":[0.5,0,0.5,1],"angle":1.41},{"time":1.9333,"curve":[0.5,0,0.5,1],"angle":0.1},{"time":2.3333,"curve":[0.5,0,0.5,1],"angle":-0.77},{"time":2.6666,"angle":-1.2}],"shear":[{"time":0,"curve":[0.5,0,0.5,1]},{"time":0.3,"curve":[0.5,0,0.5,1]},{"time":0.6667,"curve":[0.5,0,0.5,1]},{"time":0.9667,"curve":[0.5,0,0.5,1]},{"time":1,"curve":[0.5,0,0.5,1]},{"time":1.3333,"curve":[0.5,0,0.5,1]},{"time":1.9333,"curve":[0.5,0,0.5,1]},{"time":2.3333,"curve":[0.5,0,0.5,1]},{"time":2.6666}]},"Shoulder_R":{"translate":[{"time":0,"curve":[0.5,0,0.5,1],"x":-11.05,"y":-2.93},{"time":1.3333,"x":-0.18,"y":1.76},{"time":2.6666,"x":-11.05,"y":-2.93}],"rotate":[{"time":0,"curve":[0.5,0,0.5,1],"angle":0.39},{"time":1.3333,"curve":[0.5,0,0.5,1],"angle":-4.93},{"time":2.6666,"angle":0.39}],"shear":[{"time":0,"curve":[0.5,0,0.5,1]},{"time":1.3333,"curve":[0.5,0,0.5,1]},{"time":2.6666}]},"Neck":{"rotate":[{"time":0,"curve":[0.5,0,0.5,1],"angle":0},{"time":1.0333,"curve":[0.5,0,0.5,1],"angle":-6.22},{"time":2,"curve":[0.5,0,0.5,1],"angle":-3.82},{"time":2.6667,"angle":0}],"shear":[{"time":0,"curve":[0.5,0,0.5,1]},{"time":1.0333,"curve":[0.5,0,0.5,1]},{"time":2,"curve":[0.5,0,0.5,1]},{"time":2.6667}]},"Shoulder_L":{"rotate":[{"time":0,"curve":[0.5,0,0.5,1],"angle":-0.42},{"time":1.3333,"curve":[0.5,0,0.5,1],"angle":-3.35},{"time":2.6666,"angle":-0.42}],"shear":[{"time":0,"curve":[0.5,0,0.5,1]},{"time":1.3333,"curve":[0.5,0,0.5,1]},{"time":2.6666}]},"Forearm_R":{"rotate":[{"time":0,"curve":[0.5,0,0.5,1],"angle":0},{"time":1.3333,"curve":[0.5,0,0.5,1],"angle":3.2},{"time":2.6666,"angle":0}],"shear":[{"time":0,"curve":[0.5,0,0.5,1]},{"time":1.3333,"curve":[0.5,0,0.5,1]},{"time":2.6666}]},"Forearm_L":{"rotate":[{"time":0,"curve":[0.5,0,0.5,1],"angle":0},{"time":1.3333,"curve":[0.5,0,0.5,1],"angle":5.97},{"time":2.6666,"angle":0}],"shear":[{"time":0,"curve":[0.5,0,0.5,1]},{"time":1.3333,"curve":[0.5,0,0.5,1]},{"time":2.6666}]},"Face":{"translate":[{"time":0,"curve":[0.5,0,0.5,1]},{"time":0.6333,"curve":[0.5,0,0.5,1],"x":-3.75,"y":1.32},{"time":1.3333,"curve":[0.5,0,0.5,1],"x":-3.78,"y":-3.51},{"time":2.6666}],"rotate":[{"time":0,"curve":[0.5,0,0.5,1],"angle":-3.56},{"time":0.4,"curve":[0.5,0,0.5,1],"angle":-2.65},{"time":0.6333,"curve":[0.5,0,0.5,1],"angle":-2.21},{"time":1.3333,"curve":[0.5,0,0.5,1],"angle":-6.12},{"time":2.0333,"curve":[0.5,0,0.5,1],"angle":-6.06},{"time":2.6666,"angle":-3.56}],"shear":[{"time":0,"curve":[0.5,0,0.5,1]},{"time":0.4,"curve":[0.5,0,0.5,1]},{"time":0.6333,"curve":[0.5,0,0.5,1]},{"time":1.3333,"curve":[0.5,0,0.5,1]},{"time":2.0333,"curve":[0.5,0,0.5,1]},{"time":2.6666}]},"Rukav_L":{"rotate":[{"time":0,"curve":[0.5,0,0.5,1],"angle":0},{"time":1.3333,"curve":[0.5,0,0.5,1],"angle":-1.05},{"time":2.6666,"angle":0}],"shear":[{"time":0,"curve":[0.5,0,0.5,1]},{"time":1.3333,"curve":[0.5,0,0.5,1]},{"time":2.6666}]},"Rukav_R":{"rotate":[{"time":0,"curve":[0.5,0,0.5,1],"angle":0.23},{"time":1.0333,"curve":[0.5,0,0.5,1],"angle":3.32},{"time":2.6666,"angle":0.23}],"shear":[{"time":0,"curve":[0.5,0,0.5,1]},{"time":1.0333,"curve":[0.5,0,0.5,1]},{"time":2.6666}]},"Wrist_L":{"rotate":[{"time":0,"curve":[0.5,0,0.5,1],"angle":0},{"time":1.0667,"curve":[0.5,0,0.5,1],"angle":8.77},{"time":1.6334,"curve":[0.5,0,0.5,1],"angle":6.61},{"time":2.6667,"angle":0}],"shear":[{"time":0,"curve":[0.5,0,0.5,1]},{"time":1.0667,"curve":[0.5,0,0.5,1]},{"time":1.6334,"curve":[0.5,0,0.5,1]},{"time":2.6667}]},"Pack_Front":{"translate":[{"time":0,"curve":[0.5,0,0.5,1]},{"time":1.3,"curve":[0.5,0,0.5,1],"x":3.73,"y":-13.26},{"time":2.6667}],"rotate":[{"time":0,"curve":[0.5,0,0.5,1],"angle":0},{"time":1.3,"curve":[0.5,0,0.5,1],"angle":-11.45},{"time":2.6667,"angle":0}],"shear":[{"time":0,"curve":[0.5,0,0.5,1]},{"time":1.3,"curve":[0.5,0,0.5,1]},{"time":2.6667}]},"Upper_lyamka":{"rotate":[{"time":0,"curve":[0.5,0,0.5,1],"angle":0},{"time":1.3333,"curve":[0.5,0,0.5,1],"angle":-4.1},{"time":2.6666,"angle":0}],"shear":[{"time":0,"curve":[0.5,0,0.5,1]},{"time":1.3333,"curve":[0.5,0,0.5,1]},{"time":2.6666}]},"Pack_back":{"translate":[{"time":0,"curve":[0.5,0,0.5,1]},{"time":1.3333,"curve":[0.5,0,0.5,1],"x":-0.06,"y":-8.02},{"time":2.6666}],"rotate":[{"time":0,"curve":[0.5,0,0.5,1],"angle":0},{"time":1.3333,"curve":[0.5,0,0.5,1],"angle":-2.52},{"time":2.6666,"angle":0}],"shear":[{"time":0,"curve":[0.5,0,0.5,1]},{"time":1.3333,"curve":[0.5,0,0.5,1]},{"time":2.6666}]},"Lower_lyamka":{"translate":[{"time":0,"curve":[0.5,0,0.5,1]},{"time":1.3333,"curve":[0.5,0,0.5,1],"x":-7.65,"y":14.18},{"time":2.6666}],"rotate":[{"time":0,"curve":[0.5,0,0.5,1],"angle":0},{"time":1.3333,"curve":[0.5,0,0.5,1],"angle":5.43},{"time":2.6666,"angle":0}],"shear":[{"time":0,"curve":[0.5,0,0.5,1]},{"time":1.3333,"curve":[0.5,0,0.5,1]},{"time":2.6666}]},"Nijnee_veko_L_":{"translate":[{"time":0,"curve":[0.5,0,0.5,1]},{"time":0.2667,"curve":[0.5,0,0.5,1]},{"time":0.3334,"curve":[0.5,0,0.5,1],"x":3.65,"y":0.5},{"time":0.4001,"curve":[0.5,0,0.5,1]},{"time":1.1668,"curve":[0.5,0,0.5,1]},{"time":1.2335,"curve":[0.5,0,0.5,1],"x":3.65,"y":0.5},{"time":1.3002,"curve":[0.5,0,0.5,1]},{"time":2.1669,"curve":[0.5,0,0.5,1]},{"time":2.2336,"curve":[0.5,0,0.5,1],"x":3.65,"y":0.5},{"time":2.3003}]}},"deform":{"default":{"Jacket_R":{"MANGA_KAF_dragon/Jacket_R":[{"time":0,"curve":[0.5,0,0.5,1],"offset":4,"vertices":[-0.12,1.76]},{"time":0.3,"offset":2,"vertices":[-4.23,1.06,5.69,-2.01,-1.16,2.36]},{"time":0.7,"curve":[0.5,0,0.5,1],"offset":4,"vertices":[15.98,-8.68,-2.73,-2.32]},{"time":1.3333,"curve":[0.5,0,0.5,1],"offset":4,"vertices":[-1.68,-22.72,18.78,8.86]},{"time":1.6333,"offset":2,"vertices":[1.5,0.08,-9.9,-28.03,14.81,5.03]},{"time":2,"curve":[0.5,0,0.5,1],"offset":2,"vertices":[3.95,0.2,1.02,-11.75,8.34,-1.22]},{"time":2.3333,"offset":2,"vertices":[1.97,0.1,0.45,-5,17.12,-0.09]},{"time":2.6666,"offset":4,"vertices":[-0.12,1.76]}]},"Jacket_L":{"MANGA_KAF_dragon/Jacket_L":[{"time":0,"curve":[0.5,0,0.5,1],"offset":4,"vertices":[-0.18,3.44]},{"time":1.3333,"curve":[0.5,0,0.5,1],"vertices":[-0.27,-3.37,8.41,-9.26,-2.08,10.43,-20.01,27.48]},{"time":2.6666,"offset":4,"vertices":[1.54,3.56]}]},"Face":{"MANGA_KAF_dragon/Face":[{"time":0,"curve":[0.5,0,0.5,1],"offset":2,"vertices":[2.94,-2.62,0.44,1.26,3.53,3.24]},{"time":0.7333,"curve":[0.5,0,0.5,1],"offset":2,"vertices":[2.94,-2.62,0.44,1.26,3.53,3.24]},{"time":1.3333,"curve":[0.5,0,0.5,1],"vertices":[12.1,-13.81,-5.24,4.62,9.22,18.11,11.1,-0.13]},{"time":1.9666,"curve":[0.5,0,0.5,1],"vertices":[9.03,-10.3,-3.74,-2.04,6.99,13.83,8.68,-8.12]},{"time":2.6666,"offset":2,"vertices":[2.94,-2.62,0.44,1.26,3.53,3.24]}]},"Mouth":{"MANGA_KAF_dragon/Mouth":[{"time":0,"curve":[0.5,0,0.5,1],"offset":7,"vertices":[0]},{"time":1.3333,"curve":[0.5,0,0.5,1],"vertices":[-2.71,0.87,0,0,-2.55,-3.99,3.57,3.29]},{"time":2.6666,"offset":7,"vertices":[0]}]},"Mustages":{"MANGA_KAF_dragon/Mustages":[{"time":0,"curve":[0.5,0,0.5,1],"vertices":[-3.48,2.26,0.9,-0.62,-3.77,-1.57]},{"time":1.3333,"curve":[0.5,0,0.5,1],"vertices":[-4.92,-0.74,4.24,5.98,-9.64,-4.46,1.49,2.65]},{"time":2.6666,"vertices":[-3.48,2.26,0.9,-0.62,-3.77,-1.57]}]},"Nose":{"MANGA_KAF_dragon/Nose":[{"time":0,"curve":[0.5,0,0.5,1],"vertices":[-2.29,1.14,0,0,0,0,0.57,1.14]},{"time":1.3333,"curve":[0.5,0,0.5,1],"vertices":[-1.38,-3.96,0,0,-5.11,-6.74,3.93,6.33]},{"time":2.6666,"offset":6,"vertices":[0.57,1.14]}]},"Hair":{"MANGA_KAF_dragon/Hair":[{"time":0,"curve":[0.5,0,0.5,1],"offset":4,"vertices":[1.32,-0.39,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-10.93,-14.89,-6.88,-1.54]},{"time":0.2667,"curve":[0.5,0,0.5,1],"offset":2,"vertices":[2.23,4.61,0.1,0.74,0,0,1.04,0.59,-1.25,-3.07,-2.01,-1.2,-0.2,0.2,-0.75,-1.84,0.45,-0.81,0.02,-0.36,1.55,2.15,2.69,2.75,0.17,1.18,0.16,-0.06,2.17,5.16,-0.27,-2.11,0,0,0,0,-5.6,-0.42,-7.63,-8.7,6.55,0.02,2.01,1.11,0.69,0.54,-5.99,0.89,0.73,-2.62,-9.56,-13.04,-5.18,-0.62]},{"time":0.5667,"curve":[0.5,0,0.5,1],"offset":2,"vertices":[6.62,13.69,-2.29,2.97,0,0,3.08,1.73,-3.71,-9.12,-5.98,-3.57,-0.58,0.6,-2.24,-5.46,1.33,-2.39,0.08,-1.06,4.59,6.37,7.97,8.15,3.48,1.93,1.5,2.31,2.51,8.92,0.76,-0.81,0,0,-0.71,-6.08,-9.4,-5.86,-12.72,-10.42,9.84,1.05,2.2,-1.15,8.73,-0.37,-8.03,2.47,3.29,-2.66,-6.87,-9.37,-1.84,1.18]},{"time":0.8,"curve":[0.5,0,0.5,1],"offset":2,"vertices":[9.06,18.74,-3.63,4.22,0,0,4.22,2.36,-5.07,-12.48,-8.18,-4.89,-0.79,0.83,-3.06,-7.47,1.82,-3.27,0.12,-1.46,6.28,8.73,10.91,11.15,5.33,2.34,5.08,8.72,0.61,11.23,5.06,-3.15,0,0,1.09,-6.89,-16.78,-10.25,-10.93,-18.99,11.67,1.63,2.31,-2.41,2.8,2.19,-9.15,3.34,4.71,-2.69,-5.38,-7.33,0.02,2.18]},{"time":1.0667,"curve":[0.5,0,0.5,1],"vertices":[-15.83,-5.94,13.93,28.83,-6.3,6.69,0,0,6.48,3.64,-7.71,-22.5,-12.59,-7.52,-1.22,1.27,-4.7,-11.48,2.79,-5.02,0.18,-2.24,9.67,13.43,16.79,17.16,5.35,2.41,6.96,12.44,3.08,15.19,2.49,1.35,0.19,4.44,0,0,-15.34,2.53,-14.53,-2.5,10.67,8.1,7.74,0.52,4.3,3.37,-7.95,9.73,2.09,-1.2,-2.39,-3.26,3.74,4.18]},{"time":1.3334,"curve":[0.5,0,0.5,1],"offset":2,"vertices":[17.84,36.9,-8.43,8.68,0,0,8.3,4.66,-9.98,-24.57,-16.12,-9.63,-1.56,1.62,-6.02,-14.7,3.58,-6.42,0.23,-2.87,12.37,17.19,21.49,21.96,1.34,9.42,10.73,19.49,3.38,18.54,3.41,2.51,0,0,0,0,-8.69,-2.32,-6.63,4.94,11.41,8.52,6,-1.45,5.51,4.31,-10.03,11.26,0,0,0,0,6.71,5.78]},{"time":1.7667,"curve":[0.5,0,0.5,1],"offset":2,"vertices":[12.04,24.9,-5.26,5.73,0,0,5.6,3.14,-6.74,-16.59,-10.87,-6.5,-1.05,1.1,-4.06,-9.92,2.41,-4.34,0.15,-1.94,8.35,11.61,14.5,14.82,0.91,6.36,4.34,9.65,2.29,12.51,2.3,1.69,0,0,0,0,-5.87,-1.57,-4.48,3.34,5.79,2.58,3.68,3.29,3.72,2.91,-6.56,4.74,0,0,-3.55,-4.84,6.67,2.4]},{"time":2.1667,"curve":[0.5,0,0.5,1],"offset":2,"vertices":[6.68,13.84,-2.34,3.01,0,0,3.11,1.75,-3.74,-9.21,-6.04,-3.61,-0.59,0.61,-2.26,-5.51,1.34,-2.41,0.08,-1.08,4.64,6.45,8.06,8.24,0.5,3.53,3.73,8.54,1.27,6.95,1.27,0.94,0,0,0,0,-3.26,-0.87,-10.25,4.64,3.22,1.43,0,0,-1.2,0.73,-14.39,-2,0,0,-6.83,-9.31,6.64,-0.72]},{"time":2.4,"curve":[0.5,0,0.5,1],"offset":2,"vertices":[3.57,7.38,-0.63,1.42,0,0,1.66,0.93,-2,-4.92,-3.22,-1.93,-0.31,0.32,-1.2,-2.94,0.72,-1.29,0.05,-0.57,7.29,4.46,4.3,4.39,4.22,3.34,-7.01,2.13,0.68,3.71,2,-6.95,0,0,0,0,-1.73,-0.46,-1.33,0.99,1.72,0.76,0,0,1.11,0.86,0.94,2.54,0,0,-8.74,-11.92,6.62,-2.54]},{"time":2.6667,"offset":4,"vertices":[1.32,-0.39,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-10.93,-14.89,6.59,-4.62]}]},"LOB":{"MANGA_KAF_dragon/LOB":[{"time":0,"curve":[0.5,0,0.5,1],"vertices":[3.24,10.13,0,0,3.24,10.13,1.04,-1.23]},{"time":1.3333,"curve":[0.5,0,0.5,1],"vertices":[-2.54,-4.95,0,0,-2.54,-4.95,1.04,-1.23]},{"time":2.6666,"vertices":[3.24,10.13,0,0,3.24,10.13,1.04,-1.23]}]},"Chain":{"MANGA_KAF_dragon/Chain":[{"time":0,"curve":[0.5,0,0.5,1],"offset":4,"vertices":[0.19,-2.67,0.19,-2.67]},{"time":0.4,"curve":[0.5,0,0.5,1],"vertices":[2.76,-1.44,-0.43,-2.26,2.51,1.02,-4,2.66,2.43,-0.45,0.05,-1.81,0.31,-0.13]},{"time":0.8667,"curve":[0.5,0,0.5,1],"vertices":[7.5,-3.92,-1.16,-6.14,6.5,7.37,-11.22,11.83,3.43,1.43,1.43,0.33,-1.02,-2.75]},{"time":1.3334,"curve":[0.5,0,0.5,1],"vertices":[12.25,-6.4,-1.89,-10.02,10.48,13.72,-18.44,21,4.44,3.32,0.21,-8.04,1.37,-0.57]},{"time":1.7334,"curve":[0.5,0,0.5,1],"vertices":[8.58,-4.48,-1.33,-7.01,7.4,8.81,-11.64,16.63,14.01,-1.2,9.8,4.17,1.41,-5.5]},{"time":2.2334,"curve":[0.5,0,0.5,1],"vertices":[3.99,-2.08,-0.62,-3.26,8.51,0.5,-20.16,6.92,17.66,-0.2,13.43,0.8,-15.36,-4.8]},{"time":2.6667,"offset":4,"vertices":[0.19,-2.67,0.19,-2.67]}]},"Bag":{"MANGA_KAF_dragon/Bag":[{"time":0,"curve":[0.5,0,0.5,1],"offset":10,"vertices":[0.13,2.3]},{"time":1.3333,"curve":[0.5,0,0.5,1],"offset":2,"vertices":[1.72,-9.78,0,0,1.04,-11.68,-7.7,36.24,-8.56,39.28,0,0,0,0,0,0,1.72,-9.78]},{"time":1.6333,"offset":2,"vertices":[1.61,-9.15,0,0,0.98,-10.92,-7.2,33.9,-2.46,23.8,7.31,1.48,0,0,0,0,1.61,-9.15]},{"time":2.6666,"offset":10,"vertices":[0.13,2.3]}]},"Pack_Front":{"MANGA_KAF_dragon/Pack_Front":[{"time":0,"curve":[0.5,0,0.5,1],"vertices":[-0.82,-0.78,0,0,-0.82,-0.78]},{"time":0.7,"vertices":[-1.81,-12.37,0,0,-1.66,7.15,-25.19,-24.78,16.5,5.94]},{"time":1.3,"curve":[0.5,0,0.5,1],"vertices":[-2.55,-20.9,0,0,-18.91,11.33,-31.91,-42.98,-0.99,38.58]},{"time":2.0333,"vertices":[-11.22,-19.51,0,0,-11.07,0.01,-25.19,-24.78,8.77,7.6]},{"time":2.6666,"vertices":[-0.82,-0.78,0,0,-0.82,-0.78]}]},"Body":{"MANGA_KAF_dragon/Body":[{"time":0,"curve":[0.5,0,0.5,1],"offset":2,"vertices":[13.55,32.38,0,0,-6.57,35.58]},{"time":1.3333,"curve":[0.5,0,0.5,1],"offset":2,"vertices":[4.83,9.5,0,0,-5.68,1.83]},{"time":2.6666,"offset":2,"vertices":[13.55,32.38,0,0,-6.57,35.58]}]},"Ear":{"MANGA_KAF_dragon/Ear":[{"time":0,"curve":[0.5,0,0.5,1],"vertices":[-4.85,-0.74,-7.86,4.59,4.94,-4.56,1.42,-1.29]},{"time":1.3333,"curve":[0.5,0,0.5,1],"vertices":[-9.32,-7.18,-12.83,9.76,12.01,-15.2,3.8,5.34]},{"time":2.6666,"vertices":[-4.85,-0.74,-7.86,4.59,4.94,-4.56,1.42,-1.29]}]},"Taz":{"MANGA_KAF_dragon/Taz":[{"time":0,"curve":[0.5,0,0.5,1],"offset":4,"vertices":[-0.09,-1.24,-0.09,-1.24]},{"time":1.3333,"curve":[0.5,0,0.5,1],"offset":2,"vertices":[-16.44,-25.01,-0.09,-1.24,-25.95,-17.86,4.5,11.27,0,0,-0.5,0.88,9.21,-48.63,-5.96,-5.94,-0.12,20.06]},{"time":2.6666,"offset":4,"vertices":[-0.09,-1.24,-0.09,-1.24]}]},"Befro_L":{"MANGA_KAF_dragon/Befro_L":[{"time":0,"curve":[0.5,0,0.5,1],"offset":2,"vertices":[3,-7.46,0.78,-3.36,-3.36,12.37]},{"time":1.3333,"curve":[0.5,0,0.5,1],"vertices":[0.32,-5.07,0.16,-2.56,2.36,12.02,10.14,0.64]},{"time":2.6666,"offset":2,"vertices":[3,-7.46,0.78,-3.36,-3.36,12.37]}]},"Bedro_R":{"MANGA_KAF_dragon/Bedro_R":[{"time":0,"curve":[0.5,0,0.5,1],"offset":5,"vertices":[-0.18]},{"time":1.3333,"curve":[0.5,0,0.5,1],"vertices":[-1.81,-5.72,-21.42,11.93,18.15,4.98,-3.82,18.07]},{"time":2.6666,"offset":5,"vertices":[-0.18]}]},"Verh_veko_R":{"MANGA_KAF_dragon/Verh_veko_R":[{"time":0,"curve":[0.5,0,0.5,1],"offset":2,"vertices":[0.97,-0.93]},{"time":0.2333,"curve":[0.5,0,0.5,1],"offset":2,"vertices":[0.61,-0.75]},{"time":0.3333,"curve":[0.5,0,0.5,1],"vertices":[0.26,5.4,-5.15,2.75,-7.24,-9.99,-3.5,1.14]},{"time":0.4333,"curve":[0.5,0,0.5,1],"offset":2,"vertices":[0.61,-0.75]},{"time":1.2333,"curve":[0.5,0,0.5,1],"offset":2,"vertices":[0.61,-0.75]},{"time":1.3333,"curve":[0.5,0,0.5,1],"vertices":[0.26,5.4,-5.15,2.75,-7.24,-9.99,-3.5,1.14]},{"time":1.4333,"curve":[0.5,0,0.5,1],"offset":2,"vertices":[0.61,-0.75]},{"time":2.1,"curve":[0.5,0,0.5,1],"offset":2,"vertices":[0.61,-0.75]},{"time":2.2,"curve":[0.5,0,0.5,1],"vertices":[0.26,5.4,-5.15,2.75,-7.24,-9.99,-3.5,1.14]},{"time":2.3,"curve":[0.5,0,0.5,1],"offset":2,"vertices":[0.61,-0.75]},{"time":2.6667,"offset":2,"vertices":[0.97,-0.93]}]},"Verh_veko_L_":{"MANGA_KAF_dragon/Verh_veko_L_":[{"time":0,"curve":[0.5,0,0.5,1],"offset":6,"vertices":[0.27,0.09]},{"time":0.2333,"curve":[0.5,0,0.5,1],"offset":6,"vertices":[0.27,0.09]},{"time":0.3333,"curve":[0.5,0,0.5,1],"vertices":[-7.08,2.47,-3.8,1.69,-4.64,-2.44,-0.26,2.36]},{"time":0.4333,"curve":[0.5,0,0.5,1],"offset":6,"vertices":[0.27,0.09]},{"time":1.2333,"curve":[0.5,0,0.5,1],"offset":6,"vertices":[0.27,0.09]},{"time":1.3333,"curve":[0.5,0,0.5,1],"vertices":[-7.08,2.47,-3.8,1.69,-4.64,-2.44,-0.26,2.36]},{"time":1.4333,"curve":[0.5,0,0.5,1],"offset":6,"vertices":[0.27,0.09]},{"time":2.1,"curve":[0.5,0,0.5,1],"offset":6,"vertices":[0.27,0.09]},{"time":2.2,"curve":[0.5,0,0.5,1],"vertices":[-7.08,2.47,-3.8,1.69,-4.64,-2.44,-0.26,2.36]},{"time":2.3,"offset":6,"vertices":[0.27,0.09]}]},"Eye_L":{"MANGA_KAF_dragon/Eye_L":[{"time":0,"curve":[0.5,0,0.5,1],"vertices":[-0.52,0.75,-1.53,1.34,-0.52,0.75,-1.33,1.38]},{"time":0.2333,"curve":[0.5,0,0.5,1],"vertices":[-0.52,0.75,-1.53,1.34,-0.52,0.75,-1.33,1.38]},{"time":0.3333,"curve":[0.5,0,0.5,1],"vertices":[-1.82,3.18,-1.89,4.68,3.54,0.57,4.11,1.28]},{"time":0.4333,"curve":[0.5,0,0.5,1],"vertices":[-0.52,0.75,-1.53,1.34,-0.52,0.75,-1.33,1.38]},{"time":0.9333,"curve":[0.5,0,0.5,1],"vertices":[-0.52,0.75,-1.78,0.92,-0.52,0.75,-1.33,1.38]},{"time":1.2333,"curve":[0.5,0,0.5,1],"vertices":[-0.52,0.75,-1.53,1.34,-0.52,0.75,-1.33,1.38]},{"time":1.3333,"curve":[0.5,0,0.5,1],"vertices":[-1.82,3.18,-1.89,4.68,3.54,0.57,4.11,1.28]},{"time":1.4333,"curve":[0.5,0,0.5,1],"vertices":[-0.52,0.75,-1.53,1.34,-0.52,0.75,-1.33,1.38]},{"time":2.1,"curve":[0.5,0,0.5,1],"vertices":[-0.52,0.75,-1.53,1.34,-0.52,0.75,-1.33,1.38]},{"time":2.2,"curve":[0.5,0,0.5,1],"vertices":[-1.82,3.18,-1.89,4.68,3.54,0.57,4.11,1.28]},{"time":2.3,"vertices":[-0.52,0.75,-1.53,1.34,-0.52,0.75,-1.33,1.38]}]},"Forearm_R":{"MANGA_KAF_dragon/Forearm_R":[{"time":0,"curve":[0.5,0,0.5,1],"offset":4,"vertices":[-1.4]},{"time":1.3333,"curve":[0.5,0,0.5,1],"vertices":[5.6,10.67,16.54,1.37,1.36,-0.15,10.4,-15.67]},{"time":2.6666,"offset":4,"vertices":[-1.4]}]},"Forearm_L":{"MANGA_KAF_dragon/Forearm_L":[{"time":0,"curve":[0.5,0,0.5,1],"offset":4,"vertices":[0.12,-0.39]},{"time":1.3333,"curve":[0.5,0,0.5,1],"vertices":[1.33,5.57,-1.39,-9.73,0.12,-0.39,-2.72,-15.3]},{"time":2.6666,"offset":4,"vertices":[0.12,-0.39]}]},"Shoulder_R":{"MANGA_KAF_dragon/Shoulder_R":[{"time":0,"curve":[0,0,0.5,1],"offset":2,"vertices":[-7.53,5.9,-6.18,-22.24,-5.15,2.11]},{"time":1.3333,"curve":[0.5,0,0.5,1],"offset":4,"vertices":[-3.65,15.33,-0.67,-4.64]},{"time":2.6666,"offset":2,"vertices":[-7.53,5.9,-9.14,-21.03,-5.15,2.11]}]}}}}}}
--------------------------------------------------------------------------------