main.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627
  1. /******************************************************************************
  2. * Spine Runtimes License Agreement
  3. * Last updated January 1, 2020. Replaces all prior versions.
  4. *
  5. * Copyright (c) 2013-2020, Esoteric Software LLC
  6. *
  7. * Integration of the Spine Runtimes into software or otherwise creating
  8. * derivative works of the Spine Runtimes is permitted under the terms and
  9. * conditions of Section 2 of the Spine Editor License Agreement:
  10. * http://esotericsoftware.com/spine-editor-license
  11. *
  12. * Otherwise, it is permitted to integrate the Spine Runtimes into software
  13. * or otherwise create derivative works of the Spine Runtimes (collectively,
  14. * "Products"), provided that each user of the Products must obtain their own
  15. * Spine Editor license and redistribution of the Products in any form must
  16. * include this license and copyright notice.
  17. *
  18. * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
  19. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  20. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  21. * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
  22. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  23. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
  24. * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
  25. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  26. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  27. * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28. *****************************************************************************/
  29. #include <SFML/Graphics.hpp>
  30. #include <iostream>
  31. #include <spine/Debug.h>
  32. #include <spine/Log.h>
  33. #include <spine/spine-sfml.h>
  34. using namespace std;
  35. using namespace spine;
  36. #include <memory>
  37. template<typename T, typename... Args>
  38. unique_ptr<T> make_unique_test(Args &&...args) {
  39. return unique_ptr<T>(new T(forward<Args>(args)...));
  40. }
  41. void callback(AnimationState *state, EventType type, TrackEntry *entry, Event *event) {
  42. SP_UNUSED(state);
  43. const String &animationName = (entry && entry->getAnimation()) ? entry->getAnimation()->getName() : String("");
  44. switch (type) {
  45. case EventType_Start:
  46. printf("%d start: %s\n", entry->getTrackIndex(), animationName.buffer());
  47. break;
  48. case EventType_Interrupt:
  49. printf("%d interrupt: %s\n", entry->getTrackIndex(), animationName.buffer());
  50. break;
  51. case EventType_End:
  52. printf("%d end: %s\n", entry->getTrackIndex(), animationName.buffer());
  53. break;
  54. case EventType_Complete:
  55. printf("%d complete: %s\n", entry->getTrackIndex(), animationName.buffer());
  56. break;
  57. case EventType_Dispose:
  58. printf("%d dispose: %s\n", entry->getTrackIndex(), animationName.buffer());
  59. break;
  60. case EventType_Event:
  61. printf("%d event: %s, %s: %d, %f, %s %f %f\n", entry->getTrackIndex(), animationName.buffer(), event->getData().getName().buffer(), event->getIntValue(), event->getFloatValue(),
  62. event->getStringValue().buffer(), event->getVolume(), event->getBalance());
  63. break;
  64. }
  65. fflush(stdout);
  66. }
  67. shared_ptr<SkeletonData> readSkeletonJsonData(const String &filename, Atlas *atlas, float scale) {
  68. SkeletonJson json(atlas);
  69. json.setScale(scale);
  70. auto skeletonData = json.readSkeletonDataFile(filename);
  71. if (!skeletonData) {
  72. printf("%s\n", json.getError().buffer());
  73. exit(0);
  74. }
  75. return shared_ptr<SkeletonData>(skeletonData);
  76. }
  77. shared_ptr<SkeletonData> readSkeletonBinaryData(const char *filename, Atlas *atlas, float scale) {
  78. SkeletonBinary binary(atlas);
  79. binary.setScale(scale);
  80. auto skeletonData = binary.readSkeletonDataFile(filename);
  81. if (!skeletonData) {
  82. printf("%s\n", binary.getError().buffer());
  83. exit(0);
  84. }
  85. return shared_ptr<SkeletonData>(skeletonData);
  86. }
  87. void testcase(void func(SkeletonData *skeletonData, Atlas *atlas),
  88. const char *jsonName, const char *binaryName, const char *atlasName,
  89. float scale) {
  90. SP_UNUSED(jsonName);
  91. SFMLTextureLoader textureLoader;
  92. auto atlas = make_unique_test<Atlas>(atlasName, &textureLoader);
  93. auto skeletonData = readSkeletonJsonData(jsonName, atlas.get(), scale);
  94. func(skeletonData.get(), atlas.get());//
  95. skeletonData = readSkeletonBinaryData(binaryName, atlas.get(), scale);
  96. func(skeletonData.get(), atlas.get());
  97. }
  98. void spineboy(SkeletonData *skeletonData, Atlas *atlas) {
  99. SP_UNUSED(atlas);
  100. SkeletonBounds bounds;
  101. // Configure mixing.
  102. AnimationStateData stateData(skeletonData);
  103. stateData.setMix("walk", "jump", 0.2f);
  104. stateData.setMix("jump", "run", 0.2f);
  105. SkeletonDrawable drawable(skeletonData, &stateData);
  106. drawable.timeScale = 1;
  107. drawable.setUsePremultipliedAlpha(true);
  108. Skeleton *skeleton = drawable.skeleton;
  109. skeleton->setToSetupPose();
  110. skeleton->setPosition(320, 590);
  111. skeleton->updateWorldTransform();
  112. Slot *headSlot = skeleton->findSlot("head");
  113. drawable.state->setListener(callback);
  114. drawable.state->addAnimation(0, "walk", true, 0);
  115. drawable.state->addAnimation(0, "jump", false, 3);
  116. drawable.state->addAnimation(0, "run", true, 0);
  117. sf::RenderWindow window(sf::VideoMode(640, 640), "Spine SFML - spineboy");
  118. window.setFramerateLimit(60);
  119. sf::Event event;
  120. sf::Clock deltaClock;
  121. while (window.isOpen()) {
  122. while (window.pollEvent(event))
  123. if (event.type == sf::Event::Closed) window.close();
  124. float delta = deltaClock.getElapsedTime().asSeconds();
  125. deltaClock.restart();
  126. bounds.update(*skeleton, true);
  127. sf::Vector2i position = sf::Mouse::getPosition(window);
  128. if (bounds.containsPoint((float) position.x, (float) position.y)) {
  129. headSlot->getColor().g = 0;
  130. headSlot->getColor().b = 0;
  131. } else {
  132. headSlot->getColor().g = 1;
  133. headSlot->getColor().b = 1;
  134. }
  135. drawable.update(delta);
  136. window.clear();
  137. window.draw(drawable);
  138. window.display();
  139. }
  140. }
  141. void ikDemo(SkeletonData *skeletonData, Atlas *atlas) {
  142. SP_UNUSED(atlas);
  143. SkeletonBounds bounds;
  144. // Create the SkeletonDrawable and position it
  145. AnimationStateData stateData(skeletonData);
  146. SkeletonDrawable drawable(skeletonData, &stateData);
  147. drawable.timeScale = 1;
  148. drawable.setUsePremultipliedAlpha(true);
  149. drawable.skeleton->setPosition(320, 590);
  150. // Queue the "walk" animation on the first track.
  151. drawable.state->setAnimation(0, "walk", true);
  152. // Queue the "aim" animation on a higher track.
  153. // It consists of a single frame that positions
  154. // the back arm and gun such that they point at
  155. // the "crosshair" bone. By setting this
  156. // animation on a higher track, it overrides
  157. // any changes to the back arm and gun made
  158. // by the walk animation, allowing us to
  159. // mix the two. The mouse position following
  160. // is performed in the render() method below.
  161. drawable.state->setAnimation(1, "aim", true);
  162. sf::RenderWindow window(sf::VideoMode(640, 640), "Spine SFML - IK Demo");
  163. window.setFramerateLimit(60);
  164. sf::Event event;
  165. sf::Clock deltaClock;
  166. while (window.isOpen()) {
  167. while (window.pollEvent(event))
  168. if (event.type == sf::Event::Closed) window.close();
  169. float delta = deltaClock.getElapsedTime().asSeconds();
  170. deltaClock.restart();
  171. // Update and apply the animations to the skeleton,
  172. // then calculate the world transforms of every bone.
  173. // This is needed so we can call Bone#worldToLocal()
  174. // later.
  175. drawable.update(delta);
  176. // Position the "crosshair" bone at the mouse
  177. // location. We do this before calling
  178. // skeleton.updateWorldTransform() below, so
  179. // our change is incorporated before the IK
  180. // constraint is applied.
  181. //
  182. // When setting the crosshair bone position
  183. // to the mouse position, we need to translate
  184. // from "mouse space" to "local bone space". Note that the local
  185. // bone space is calculated using the bone's parent
  186. // worldToLocal() function!
  187. sf::Vector2i mouseCoords = sf::Mouse::getPosition(window);
  188. float boneCoordsX = 0, boneCoordsY = 0;
  189. Bone *crosshair = drawable.skeleton->findBone("crosshair");// Should be cached.
  190. crosshair->getParent()->worldToLocal(mouseCoords.x, mouseCoords.y, boneCoordsX, boneCoordsY);
  191. crosshair->setX(boneCoordsX);
  192. crosshair->setY(boneCoordsY);
  193. // Calculate final world transform with the
  194. // crosshair bone set to the mouse cursor
  195. // position.
  196. drawable.skeleton->updateWorldTransform();
  197. window.clear();
  198. window.draw(drawable);
  199. window.display();
  200. }
  201. }
  202. void goblins(SkeletonData *skeletonData, Atlas *atlas) {
  203. SP_UNUSED(atlas);
  204. SkeletonDrawable drawable(skeletonData);
  205. drawable.timeScale = 1;
  206. drawable.setUsePremultipliedAlpha(true);
  207. Skeleton *skeleton = drawable.skeleton;
  208. skeleton->setSkin("goblingirl");
  209. skeleton->setSlotsToSetupPose();
  210. skeleton->setPosition(320, 590);
  211. skeleton->updateWorldTransform();
  212. drawable.state->setAnimation(0, "walk", true);
  213. sf::RenderWindow window(sf::VideoMode(640, 640), "Spine SFML - goblins");
  214. window.setFramerateLimit(60);
  215. sf::Event event;
  216. sf::Clock deltaClock;
  217. while (window.isOpen()) {
  218. while (window.pollEvent(event))
  219. if (event.type == sf::Event::Closed) window.close();
  220. float delta = deltaClock.getElapsedTime().asSeconds();
  221. deltaClock.restart();
  222. drawable.update(delta);
  223. window.clear();
  224. window.draw(drawable);
  225. window.display();
  226. }
  227. }
  228. void raptor(SkeletonData *skeletonData, Atlas *atlas) {
  229. SP_UNUSED(atlas);
  230. SkeletonDrawable drawable(skeletonData);
  231. drawable.timeScale = 1;
  232. drawable.setUsePremultipliedAlpha(true);
  233. PowInterpolation pow2(2);
  234. PowOutInterpolation powOut2(2);
  235. SwirlVertexEffect effect(400, powOut2);
  236. effect.setCenterY(-200);
  237. drawable.vertexEffect = &effect;
  238. Skeleton *skeleton = drawable.skeleton;
  239. skeleton->setPosition(320, 590);
  240. skeleton->updateWorldTransform();
  241. drawable.state->setAnimation(0, "walk", true);
  242. drawable.state->addAnimation(1, "gun-grab", false, 2);
  243. sf::RenderWindow window(sf::VideoMode(640, 640), "Spine SFML - raptor");
  244. window.setFramerateLimit(60);
  245. sf::Event event;
  246. sf::Clock deltaClock;
  247. float swirlTime = 0;
  248. while (window.isOpen()) {
  249. while (window.pollEvent(event))
  250. if (event.type == sf::Event::Closed) window.close();
  251. float delta = deltaClock.getElapsedTime().asSeconds();
  252. deltaClock.restart();
  253. swirlTime += delta;
  254. float percent = MathUtil::fmod(swirlTime, 2);
  255. if (percent > 1) percent = 1 - (percent - 1);
  256. effect.setAngle(pow2.interpolate(-60.0f, 60.0f, percent));
  257. drawable.update(delta);
  258. window.clear();
  259. window.draw(drawable);
  260. window.display();
  261. }
  262. }
  263. void tank(SkeletonData *skeletonData, Atlas *atlas) {
  264. SP_UNUSED(atlas);
  265. SkeletonDrawable drawable(skeletonData);
  266. drawable.timeScale = 1;
  267. drawable.setUsePremultipliedAlpha(true);
  268. Skeleton *skeleton = drawable.skeleton;
  269. skeleton->setPosition(500, 590);
  270. skeleton->updateWorldTransform();
  271. drawable.state->setAnimation(0, "drive", true);
  272. sf::RenderWindow window(sf::VideoMode(640, 640), "Spine SFML - tank");
  273. window.setFramerateLimit(60);
  274. sf::Event event;
  275. sf::Clock deltaClock;
  276. while (window.isOpen()) {
  277. while (window.pollEvent(event))
  278. if (event.type == sf::Event::Closed) window.close();
  279. float delta = deltaClock.getElapsedTime().asSeconds();
  280. deltaClock.restart();
  281. drawable.update(delta);
  282. window.clear();
  283. window.draw(drawable);
  284. window.display();
  285. }
  286. }
  287. void vine(SkeletonData *skeletonData, Atlas *atlas) {
  288. SP_UNUSED(atlas);
  289. SkeletonDrawable drawable(skeletonData);
  290. drawable.timeScale = 1;
  291. drawable.setUsePremultipliedAlpha(true);
  292. Skeleton *skeleton = drawable.skeleton;
  293. skeleton->setPosition(320, 590);
  294. skeleton->updateWorldTransform();
  295. drawable.state->setAnimation(0, "grow", true);
  296. sf::RenderWindow window(sf::VideoMode(640, 640), "Spine SFML - vine");
  297. window.setFramerateLimit(60);
  298. sf::Event event;
  299. sf::Clock deltaClock;
  300. while (window.isOpen()) {
  301. while (window.pollEvent(event))
  302. if (event.type == sf::Event::Closed) window.close();
  303. float delta = deltaClock.getElapsedTime().asSeconds();
  304. deltaClock.restart();
  305. drawable.update(delta);
  306. window.clear();
  307. window.draw(drawable);
  308. window.display();
  309. }
  310. }
  311. void stretchyman(SkeletonData *skeletonData, Atlas *atlas) {
  312. SP_UNUSED(atlas);
  313. SkeletonDrawable drawable(skeletonData);
  314. drawable.timeScale = 1;
  315. drawable.setUsePremultipliedAlpha(true);
  316. Skeleton *skeleton = drawable.skeleton;
  317. skeleton->setPosition(100, 590);
  318. skeleton->updateWorldTransform();
  319. drawable.state->setAnimation(0, "sneak", true);
  320. sf::RenderWindow window(sf::VideoMode(640, 640), "Spine SFML - Streatchyman");
  321. window.setFramerateLimit(60);
  322. sf::Event event;
  323. sf::Clock deltaClock;
  324. while (window.isOpen()) {
  325. while (window.pollEvent(event))
  326. if (event.type == sf::Event::Closed) window.close();
  327. float delta = deltaClock.getElapsedTime().asSeconds();
  328. deltaClock.restart();
  329. drawable.update(delta);
  330. window.clear();
  331. window.draw(drawable);
  332. window.display();
  333. }
  334. }
  335. void stretchymanStrechyIk(SkeletonData *skeletonData, Atlas *atlas) {
  336. SP_UNUSED(atlas);
  337. SkeletonDrawable *drawable = new SkeletonDrawable(skeletonData);
  338. drawable->timeScale = 1;
  339. drawable->setUsePremultipliedAlpha(true);
  340. Skeleton *skeleton = drawable->skeleton;
  341. skeleton->setPosition(100, 590);
  342. skeleton->updateWorldTransform();
  343. drawable->state->setAnimation(0, "sneak", true);
  344. sf::RenderWindow window(sf::VideoMode(640, 640), "Spine SFML - Streatchyman Stretchy IK");
  345. window.setFramerateLimit(60);
  346. sf::Event event;
  347. sf::Clock deltaClock;
  348. while (window.isOpen()) {
  349. while (window.pollEvent(event))
  350. if (event.type == sf::Event::Closed) window.close();
  351. float delta = deltaClock.getElapsedTime().asSeconds();
  352. deltaClock.restart();
  353. drawable->update(delta);
  354. window.clear();
  355. window.draw(*drawable);
  356. window.display();
  357. }
  358. delete drawable;
  359. }
  360. void coin(SkeletonData *skeletonData, Atlas *atlas) {
  361. SP_UNUSED(atlas);
  362. SkeletonDrawable drawable(skeletonData);
  363. drawable.timeScale = 1;
  364. drawable.setUsePremultipliedAlpha(true);
  365. Skeleton *skeleton = drawable.skeleton;
  366. skeleton->setPosition(320, 320);
  367. skeleton->updateWorldTransform();
  368. drawable.state->setAnimation(0, "animation", true);
  369. sf::RenderWindow window(sf::VideoMode(640, 640), "Spine SFML - coin");
  370. window.setFramerateLimit(60);
  371. sf::Event event;
  372. sf::Clock deltaClock;
  373. while (window.isOpen()) {
  374. while (window.pollEvent(event)) {
  375. if (event.type == sf::Event::Closed) window.close();
  376. }
  377. float delta = deltaClock.getElapsedTime().asSeconds();
  378. deltaClock.restart();
  379. drawable.update(delta);
  380. window.clear();
  381. window.draw(drawable);
  382. window.display();
  383. }
  384. }
  385. void owl(SkeletonData *skeletonData, Atlas *atlas) {
  386. SP_UNUSED(atlas);
  387. SkeletonDrawable drawable(skeletonData);
  388. drawable.timeScale = 1;
  389. drawable.setUsePremultipliedAlpha(true);
  390. Skeleton *skeleton = drawable.skeleton;
  391. skeleton->setPosition(320, 400);
  392. skeleton->updateWorldTransform();
  393. drawable.state->setAnimation(0, "idle", true);
  394. drawable.state->setAnimation(1, "blink", true);
  395. TrackEntry *left = drawable.state->setAnimation(2, "left", true);
  396. TrackEntry *right = drawable.state->setAnimation(3, "right", true);
  397. TrackEntry *up = drawable.state->setAnimation(4, "up", true);
  398. TrackEntry *down = drawable.state->setAnimation(5, "down", true);
  399. left->setAlpha(0);
  400. left->setMixBlend(MixBlend_Add);
  401. right->setAlpha(0);
  402. right->setMixBlend(MixBlend_Add);
  403. up->setAlpha(0);
  404. up->setMixBlend(MixBlend_Add);
  405. down->setAlpha(0);
  406. down->setMixBlend(MixBlend_Add);
  407. // drawable.state->setAnimation(5, "blink", true);
  408. sf::RenderWindow window(sf::VideoMode(640, 640), "Spine SFML - owl");
  409. window.setFramerateLimit(60);
  410. sf::Event event;
  411. sf::Clock deltaClock;
  412. while (window.isOpen()) {
  413. while (window.pollEvent(event)) {
  414. if (event.type == sf::Event::Closed) window.close();
  415. if (event.type == sf::Event::MouseMoved) {
  416. float x = event.mouseMove.x / 640.0f;
  417. left->setAlpha((MathUtil::max(x, 0.5f) - 0.5f) * 2);
  418. right->setAlpha((0.5f - MathUtil::min(x, 0.5f)) * 2);
  419. float y = event.mouseMove.y / 640.0f;
  420. down->setAlpha((MathUtil::max(y, 0.5f) - 0.5f) * 2);
  421. up->setAlpha((0.5f - MathUtil::min(y, 0.5f)) * 2);
  422. }
  423. }
  424. float delta = deltaClock.getElapsedTime().asSeconds();
  425. deltaClock.restart();
  426. drawable.update(delta);
  427. window.clear();
  428. window.draw(drawable);
  429. window.display();
  430. }
  431. }
  432. void mixAndMatch(SkeletonData *skeletonData, Atlas *atlas) {
  433. SP_UNUSED(atlas);
  434. SkeletonDrawable drawable(skeletonData);
  435. drawable.timeScale = 1;
  436. drawable.setUsePremultipliedAlpha(true);
  437. Skeleton *skeleton = drawable.skeleton;
  438. Skin skin("mix-and-match");
  439. skin.addSkin(skeletonData->findSkin("skin-base"));
  440. skin.addSkin(skeletonData->findSkin("nose/short"));
  441. skin.addSkin(skeletonData->findSkin("eyelids/girly"));
  442. skin.addSkin(skeletonData->findSkin("eyes/violet"));
  443. skin.addSkin(skeletonData->findSkin("hair/brown"));
  444. skin.addSkin(skeletonData->findSkin("clothes/hoodie-orange"));
  445. skin.addSkin(skeletonData->findSkin("legs/pants-jeans"));
  446. skin.addSkin(skeletonData->findSkin("accessories/bag"));
  447. skin.addSkin(skeletonData->findSkin("accessories/hat-red-yellow"));
  448. skeleton->setSkin(&skin);
  449. skeleton->setSlotsToSetupPose();
  450. skeleton->setPosition(320, 590);
  451. skeleton->updateWorldTransform();
  452. drawable.state->setAnimation(0, "dance", true);
  453. sf::RenderWindow window(sf::VideoMode(640, 640), "Spine SFML - goblins");
  454. window.setFramerateLimit(60);
  455. sf::Event event;
  456. sf::Clock deltaClock;
  457. while (window.isOpen()) {
  458. while (window.pollEvent(event))
  459. if (event.type == sf::Event::Closed) window.close();
  460. float delta = deltaClock.getElapsedTime().asSeconds();
  461. deltaClock.restart();
  462. drawable.update(delta);
  463. window.clear();
  464. window.draw(drawable);
  465. window.display();
  466. }
  467. }
  468. /**
  469. * Used for debugging purposes during runtime development
  470. */
  471. void test(SkeletonData *skeletonData, Atlas *atlas) {
  472. SP_UNUSED(atlas);
  473. Skeleton skeleton(skeletonData);
  474. AnimationStateData animationStateData(skeletonData);
  475. AnimationState animationState(&animationStateData);
  476. animationState.setAnimation(0, "idle", true);
  477. float d = 3;
  478. for (int i = 0; i < 1; i++) {
  479. animationState.update(d);
  480. animationState.apply(skeleton);
  481. skeleton.updateWorldTransform();
  482. d += 0.1f;
  483. }
  484. }
  485. DebugExtension dbgExtension(SpineExtension::getInstance());
  486. int main() {
  487. SpineExtension::setInstance(&dbgExtension);
  488. testcase(ikDemo, "data/spineboy-pro.json", "data/spineboy-pro.skel", "data/spineboy-pma.atlas", 0.6f);
  489. testcase(mixAndMatch, "data/mix-and-match-pro.json", "data/mix-and-match-pro.skel", "data/mix-and-match-pma.atlas", 0.5f);
  490. testcase(coin, "data/coin-pro.json", "data/coin-pro.skel", "data/coin-pma.atlas", 0.5f);
  491. testcase(owl, "data/owl-pro.json", "data/owl-pro.skel", "data/owl-pma.atlas", 0.5f);
  492. testcase(spineboy, "data/spineboy-pro.json", "data/spineboy-pro.skel", "data/spineboy-pma.atlas", 0.6f);
  493. testcase(raptor, "data/raptor-pro.json", "data/raptor-pro.skel", "data/raptor-pma.atlas", 0.5f);
  494. testcase(vine, "data/vine-pro.json", "data/vine-pro.skel", "data/vine-pma.atlas", 0.5f);
  495. testcase(tank, "data/tank-pro.json", "data/tank-pro.skel", "data/tank-pma.atlas", 0.2f);
  496. testcase(raptor, "data/raptor-pro.json", "data/raptor-pro.skel", "data/raptor-pma.atlas", 0.5f);
  497. testcase(goblins, "data/goblins-pro.json", "data/goblins-pro.skel", "data/goblins-pma.atlas", 1.4f);
  498. testcase(stretchyman, "data/stretchyman-pro.json", "data/stretchyman-pro.skel", "data/stretchyman-pma.atlas", 0.6f);
  499. dbgExtension.reportLeaks();
  500. return 0;
  501. }