From 4342bcfa7da0f24492cf40ef78e1f965a83b75ef Mon Sep 17 00:00:00 2001 From: Harald Csaszar Date: Fri, 15 Feb 2019 13:04:22 +0100 Subject: [PATCH 1/4] [unity] Fixed compile errors with TK2D define due to asmdef files preventing dependency. Closes #1280. --- .../Editor/SpineEditorUtilities.cs | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineEditorUtilities.cs b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineEditorUtilities.cs index d6de0651e..16ebf3490 100644 --- a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineEditorUtilities.cs +++ b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineEditorUtilities.cs @@ -1785,6 +1785,9 @@ namespace Spine.Unity.Editor { internal static void EnableTK2D () { bool added = false; + + DisableSpineAsmdefFiles(); + foreach (BuildTargetGroup group in System.Enum.GetValues(typeof(BuildTargetGroup))) { if (IsInvalidGroup(group)) continue; @@ -1811,6 +1814,9 @@ namespace Spine.Unity.Editor { internal static void DisableTK2D () { bool removed = false; + + EnableSpineAsmdefFiles(); + foreach (BuildTargetGroup group in System.Enum.GetValues(typeof(BuildTargetGroup))) { if (IsInvalidGroup(group)) continue; @@ -1833,6 +1839,31 @@ namespace Spine.Unity.Editor { Debug.LogWarning("Already Removed Scripting Define Symbol " + SPINE_TK2D_DEFINE); } } + + internal static void DisableSpineAsmdefFiles() { + SetAsmdefFileActive("spine-unity-editor", false); + SetAsmdefFileActive("spine-unity", false); + } + + internal static void EnableSpineAsmdefFiles() { + SetAsmdefFileActive("spine-unity-editor", true); + SetAsmdefFileActive("spine-unity", true); + } + + internal static void SetAsmdefFileActive(string filename, bool setActive) { + + string typeSearchString = setActive ? " t:textasset" : " t:asmdef"; + string[] guids = AssetDatabase.FindAssets(filename + typeSearchString); + foreach (string guid in guids) { + string currentPath = AssetDatabase.GUIDToAssetPath(guid); + string targetPath = System.IO.Path.ChangeExtension(currentPath, setActive ? "asmdef" : "txt"); + if (System.IO.File.Exists(currentPath)) { + System.IO.File.Copy(currentPath, targetPath); + System.IO.File.Copy(currentPath + ".meta", targetPath + ".meta"); + } + AssetDatabase.DeleteAsset(currentPath); + } + } } } From f5709a7bbc79733646d49581c78a0e93939974eb Mon Sep 17 00:00:00 2001 From: badlogic Date: Mon, 18 Feb 2019 11:38:39 +0100 Subject: [PATCH 2/4] [c] Fixes #1282, animation state was missing a null check when iterating mixed out track entries. --- .../spine-c/include/spine/AnimationState.h | 8 +- spine-c/spine-c/src/spine/AnimationState.c | 1 + spine-sfml/c/example/main.cpp | 265 ++++++++++++++++-- spine-sfml/cpp/example/main.cpp | 5 +- 4 files changed, 252 insertions(+), 27 deletions(-) diff --git a/spine-c/spine-c/include/spine/AnimationState.h b/spine-c/spine-c/include/spine/AnimationState.h index b44726924..edcd4b6db 100644 --- a/spine-c/spine-c/include/spine/AnimationState.h +++ b/spine-c/spine-c/include/spine/AnimationState.h @@ -176,11 +176,11 @@ typedef spAnimationState AnimationState; #define AnimationState_setAnimation(...) spAnimationState_setAnimation(__VA_ARGS__) #define AnimationState_addAnimationByName(...) spAnimationState_addAnimationByName(__VA_ARGS__) #define AnimationState_addAnimation(...) spAnimationState_addAnimation(__VA_ARGS__) -#define AnimationState_setEmptyAnimation(...) spAnimatinState_setEmptyAnimation(__VA_ARGS__) -#define AnimationState_addEmptyAnimation(...) spAnimatinState_addEmptyAnimation(__VA_ARGS__) -#define AnimationState_setEmptyAnimations(...) spAnimatinState_setEmptyAnimations(__VA_ARGS__) +#define AnimationState_setEmptyAnimation(...) spAnimationState_setEmptyAnimation(__VA_ARGS__) +#define AnimationState_addEmptyAnimation(...) spAnimationState_addEmptyAnimation(__VA_ARGS__) +#define AnimationState_setEmptyAnimations(...) spAnimationState_setEmptyAnimations(__VA_ARGS__) #define AnimationState_getCurrent(...) spAnimationState_getCurrent(__VA_ARGS__) -#define AnimationState_clearListenerNotifications(...) spAnimatinState_clearListenerNotifications(__VA_ARGS__) +#define AnimationState_clearListenerNotifications(...) spAnimationState_clearListenerNotifications(__VA_ARGS__) #endif #ifdef __cplusplus diff --git a/spine-c/spine-c/src/spine/AnimationState.c b/spine-c/spine-c/src/spine/AnimationState.c index 22a7f45a1..890d3dae2 100644 --- a/spine-c/spine-c/src/spine/AnimationState.c +++ b/spine-c/spine-c/src/spine/AnimationState.c @@ -862,6 +862,7 @@ void _spAnimationState_animationsChanged (spAnimationState* self) { for (;i < n; i++) { entry = self->tracks[i]; + if (!entry) continue; while (entry->mixingFrom != 0) entry = entry->mixingFrom; do { diff --git a/spine-sfml/c/example/main.cpp b/spine-sfml/c/example/main.cpp index 6e1232c50..a2e284df3 100644 --- a/spine-sfml/c/example/main.cpp +++ b/spine-sfml/c/example/main.cpp @@ -44,25 +44,25 @@ void callback (AnimationState* state, EventType type, TrackEntry* entry, Event* const char* animationName = (entry && entry->animation) ? entry->animation->name : 0; switch (type) { - case ANIMATION_START: - printf("%d start: %s\n", entry->trackIndex, animationName); - break; - case ANIMATION_INTERRUPT: - printf("%d interrupt: %s\n", entry->trackIndex, animationName); - break; - case ANIMATION_END: - printf("%d end: %s\n", entry->trackIndex, animationName); - break; - case ANIMATION_COMPLETE: - printf("%d complete: %s\n", entry->trackIndex, animationName); - break; - case ANIMATION_DISPOSE: - printf("%d dispose: %s\n", entry->trackIndex, animationName); - break; - case ANIMATION_EVENT: - printf("%d event: %s, %s: %d, %f, %s %f %f\n", entry->trackIndex, animationName, event->data->name, event->intValue, event->floatValue, - event->stringValue, event->volume, event->balance); - break; + case ANIMATION_START: + printf("%d start: %s\n", entry->trackIndex, animationName); + break; + case ANIMATION_INTERRUPT: + printf("%d interrupt: %s\n", entry->trackIndex, animationName); + break; + case ANIMATION_END: + printf("%d end: %s\n", entry->trackIndex, animationName); + break; + case ANIMATION_COMPLETE: + printf("%d complete: %s\n", entry->trackIndex, animationName); + break; + case ANIMATION_DISPOSE: + printf("%d dispose: %s\n", entry->trackIndex, animationName); + break; + case ANIMATION_EVENT: + printf("%d event: %s, %s: %d, %f, %s %f %f\n", entry->trackIndex, animationName, event->data->name, event->intValue, event->floatValue, + event->stringValue, event->volume, event->balance); + break; } fflush(stdout); } @@ -92,17 +92,19 @@ SkeletonData* readSkeletonBinaryData (const char* filename, Atlas* atlas, float } void testcase (void func(SkeletonData* skeletonData, Atlas* atlas), - const char* jsonName, const char* binaryName, const char* atlasName, - float scale) { + const char* jsonName, const char* binaryName, const char* atlasName, + float scale) { Atlas* atlas = Atlas_createFromFile(atlasName, 0); SkeletonData* skeletonData = readSkeletonJsonData(jsonName, atlas, scale); func(skeletonData, atlas); SkeletonData_dispose(skeletonData); + /* skeletonData = readSkeletonBinaryData(binaryName, atlas, scale); func(skeletonData, atlas); SkeletonData_dispose(skeletonData); + */ Atlas_dispose(atlas); } @@ -421,6 +423,221 @@ void owl (SkeletonData* skeletonData, Atlas* atlas) { } } +/* + test code +*/ +void animationchanged_nullpointertest(SkeletonData* skeletonData, Atlas* atlas) { + SkeletonBounds* bounds = SkeletonBounds_create(); + + // Configure mixing. + AnimationStateData* stateData = AnimationStateData_create(skeletonData); + AnimationStateData_setMixByName(stateData, "walk", "jump", 0.2f); + AnimationStateData_setMixByName(stateData, "jump", "run", 0.2f); + + SkeletonDrawable* drawable = new SkeletonDrawable(skeletonData, stateData); + drawable->timeScale = 1; + drawable->setUsePremultipliedAlpha(true); + + Skeleton* skeleton = drawable->skeleton; + Skeleton_setToSetupPose(skeleton); + + skeleton->x = 320; + skeleton->y = 590; + Skeleton_updateWorldTransform(skeleton); + + drawable->state->listener = callback; + AnimationState_addAnimationByName(drawable->state, 0, "walk", true, 0); + AnimationState_addEmptyAnimation(drawable->state, 0, 1.0f, 0.0f); + + sf::RenderWindow window(sf::VideoMode(640, 640), "Spine SFML - spineboy"); + window.setFramerateLimit(60); + sf::Event event; + sf::Clock deltaClock; + while (window.isOpen()) { + while (window.pollEvent(event)) + if (event.type == sf::Event::Closed) window.close(); + + float delta = deltaClock.getElapsedTime().asSeconds(); + deltaClock.restart(); + + drawable->update(delta); + + window.clear(); + window.draw(*drawable); + window.display(); + } + + SkeletonBounds_dispose(bounds); + delete drawable; +} + +void multitrack_animationmixtest(SkeletonData* skeletonData, Atlas* atlas) { + SkeletonDrawable* drawable = new SkeletonDrawable(skeletonData); + drawable->timeScale = 1; + drawable->setUsePremultipliedAlpha(false); + + // setup mixing + drawable->state->data->defaultMix = 0.5f; + + Skeleton* skeleton = drawable->skeleton; + skeleton->x = 320; + skeleton->y = 400; + skeleton->scaleX = 1.0f; + skeleton->scaleY = 1.0f; + Skeleton_updateWorldTransform(skeleton); + + + // track[0] = base ... none animation + // track[1] = anim1 -> anim2 -> anim1 -> ... + AnimationState_setAnimationByName(drawable->state, 0, "base", true); + AnimationState_setAnimationByName(drawable->state, 1, "anim1", false); + + sf::RenderWindow window(sf::VideoMode(640, 640), "Spine SFML - animation mixing test on track[1]"); + window.setFramerateLimit(60); + sf::Event event; + sf::Clock deltaClock; + + float sumtime = 999.0f; + int animationindex = 0; + + while (window.isOpen()) { + while (window.pollEvent(event)) + if (event.type == sf::Event::Closed) window.close(); + + float delta = deltaClock.getElapsedTime().asSeconds(); + deltaClock.restart(); + + // motion switch + sumtime += delta; + if (sumtime > 3.0f) { + if (animationindex == 0) + AnimationState_setAnimationByName(drawable->state, 1, "anim1", false); + else + AnimationState_setAnimationByName(drawable->state, 1, "anim2", false); + sumtime = 0.0f; + animationindex = (animationindex + 1) & 1; + } + + // draw + drawable->update(delta); + window.clear(); + window.draw(*drawable); + window.display(); + } + + delete drawable; +} + +void multitrack_addmixtest(SkeletonData* skeletonData, Atlas* atlas) { + SkeletonDrawable* drawable = new SkeletonDrawable(skeletonData); + + drawable->timeScale = 1; + drawable->setUsePremultipliedAlpha(false); + + // use track index + int usetrackindex = 1; // 1 or 0 + + // setup mixing + drawable->state->data->defaultMix = 0.5f; + { + Skeleton* skeleton = drawable->skeleton; + skeleton->x = 320; + skeleton->y = 400; + skeleton->scaleX = 1.0f; + skeleton->scaleY = 1.0f; + Skeleton_updateWorldTransform(skeleton); + } + + // track[0](replace) = base ... none animation + // track[1](add) = anim1 -> anim2 -> anim1 -> ... + spTrackEntry* track; + + AnimationState_setAnimationByName(drawable->state, 0, "base", true); + track = AnimationState_setAnimationByName(drawable->state, usetrackindex, "anim1", false); + track->mixBlend = SP_MIX_BLEND_ADD; // mixAdd + + sf::RenderWindow window(sf::VideoMode(640, 640), "Spine SFML - mixAdd animation mixing test on track[1]"); + window.setFramerateLimit(60); + sf::Event event; + sf::Clock deltaClock; + + float sumtime = 999.0f; + int animationindex = 0; + + while (window.isOpen()) { + while (window.pollEvent(event)) + if (event.type == sf::Event::Closed) window.close(); + + float delta = deltaClock.getElapsedTime().asSeconds(); + deltaClock.restart(); + + // motion switch + sumtime += delta; + if (sumtime > 3.0f) { + std::string name; + if (animationindex == 0) + track = AnimationState_setAnimationByName(drawable->state, usetrackindex, "anim1", false); + else + track = AnimationState_setAnimationByName(drawable->state, usetrackindex, "anim2", false); + + track->mixBlend = SP_MIX_BLEND_ADD; + + sumtime = 0.0f; + animationindex = (animationindex + 1) & 1; + } + + // draw + drawable->update(delta); + window.clear(); + window.draw(*drawable); + window.display(); + } + + delete drawable; +} + +void skeleton_scaletest(SkeletonData* skeletonData, Atlas* atlas) { + SkeletonDrawable* drawable = new SkeletonDrawable(skeletonData); + drawable->timeScale = 1; + drawable->setUsePremultipliedAlpha(false); + + // setup mixing + drawable->state->data->defaultMix = 0.5f; + + Skeleton* skeleton = drawable->skeleton; + skeleton->x = 320; + skeleton->y = 400; + skeleton->scaleX = 0.6f; + skeleton->scaleY = 0.6f; + Skeleton_updateWorldTransform(skeleton); + + + // track[0] = base ... none animation + // track[1] = anim1 -> anim2 -> anim1 -> ... + AnimationState_setAnimationByName(drawable->state, 0, "base", true); + + sf::RenderWindow window(sf::VideoMode(640, 640), "Spine SFML - skeleton scale test"); + window.setFramerateLimit(60); + sf::Event event; + sf::Clock deltaClock; + + while (window.isOpen()) { + while (window.pollEvent(event)) + if (event.type == sf::Event::Closed) window.close(); + + float delta = deltaClock.getElapsedTime().asSeconds(); + deltaClock.restart(); + + // draw + drawable->update(delta); + window.clear(); + window.draw(*drawable); + window.display(); + } + + delete drawable; +} + /** * Used for debugging purposes during runtime development */ @@ -449,6 +666,11 @@ void test (SkeletonData* skeletonData, Atlas* atlas) { } int main () { + // testcase(multitrack_animationmixtest, "data/testmodel/skeleton.json", "data/testmodel/skeleton.skel", "data/testmodel/skeleton.atlas", 0.6f); + // testcase(multitrack_addmixtest, "data/testmodel/skeleton.json", "data/testmodel/skeleton.skel", "data/testmodel/skeleton.atlas", 0.6f); + // testcase(skeleton_scaletest, "data/testmodel/skeleton.json", "data/testmodel/skeleton.skel", "data/testmodel/skeleton.atlas", 0.6f); + testcase(animationchanged_nullpointertest, "data/spineboy-pro.json", "data/spineboy-pro.skel", "data/spineboy-pma.atlas", 0.6f); + /* testcase(test, "data/tank-pro.json", "data/tank-pro.skel", "data/tank-pma.atlas", 1.0f); testcase(spineboy, "data/spineboy-pro.json", "data/spineboy-pro.skel", "data/spineboy-pma.atlas", 0.6f); testcase(stretchyman, "data/stretchyman-stretchy-ik-pro.json", "data/stretchyman-stretchy-ik-pro.skel", "data/stretchyman-pma.atlas", 0.6f); @@ -459,5 +681,6 @@ int main () { testcase(raptor, "data/raptor-pro.json", "data/raptor-pro.skel", "data/raptor-pma.atlas", 0.5f); testcase(goblins, "data/goblins-pro.json", "data/goblins-pro.skel", "data/goblins-pma.atlas", 1.4f); testcase(stretchyman, "data/stretchyman-pro.json", "data/stretchyman-pro.skel", "data/stretchyman-pma.atlas", 0.6f); + */ return 0; } diff --git a/spine-sfml/cpp/example/main.cpp b/spine-sfml/cpp/example/main.cpp index 4bccbdef9..2ebd3c174 100644 --- a/spine-sfml/cpp/example/main.cpp +++ b/spine-sfml/cpp/example/main.cpp @@ -126,8 +126,9 @@ void spineboy (SkeletonData* skeletonData, Atlas* atlas) { drawable.state->setListener(callback); drawable.state->addAnimation(0, "walk", true, 0); - drawable.state->addAnimation(0, "jump", false, 3); - drawable.state->addAnimation(0, "run", true, 0); + //drawable.state->addAnimation(0, "jump", false, 3); + //drawable.state->addAnimation(0, "run", true, 0); + drawable.state->addEmptyAnimation(0, 1, 0); sf::RenderWindow window(sf::VideoMode(640, 640), "Spine SFML - spineboy"); window.setFramerateLimit(60); From 688b661c12552de2784982f7591fdda659653532 Mon Sep 17 00:00:00 2001 From: badlogic Date: Mon, 18 Feb 2019 11:39:19 +0100 Subject: [PATCH 3/4] Revert "[c] Fixes #1282, animation state was missing a null check when iterating mixed out track entries." This reverts commit f5709a7bbc79733646d49581c78a0e93939974eb. --- .../spine-c/include/spine/AnimationState.h | 8 +- spine-c/spine-c/src/spine/AnimationState.c | 1 - spine-sfml/c/example/main.cpp | 265 ++---------------- spine-sfml/cpp/example/main.cpp | 5 +- 4 files changed, 27 insertions(+), 252 deletions(-) diff --git a/spine-c/spine-c/include/spine/AnimationState.h b/spine-c/spine-c/include/spine/AnimationState.h index edcd4b6db..b44726924 100644 --- a/spine-c/spine-c/include/spine/AnimationState.h +++ b/spine-c/spine-c/include/spine/AnimationState.h @@ -176,11 +176,11 @@ typedef spAnimationState AnimationState; #define AnimationState_setAnimation(...) spAnimationState_setAnimation(__VA_ARGS__) #define AnimationState_addAnimationByName(...) spAnimationState_addAnimationByName(__VA_ARGS__) #define AnimationState_addAnimation(...) spAnimationState_addAnimation(__VA_ARGS__) -#define AnimationState_setEmptyAnimation(...) spAnimationState_setEmptyAnimation(__VA_ARGS__) -#define AnimationState_addEmptyAnimation(...) spAnimationState_addEmptyAnimation(__VA_ARGS__) -#define AnimationState_setEmptyAnimations(...) spAnimationState_setEmptyAnimations(__VA_ARGS__) +#define AnimationState_setEmptyAnimation(...) spAnimatinState_setEmptyAnimation(__VA_ARGS__) +#define AnimationState_addEmptyAnimation(...) spAnimatinState_addEmptyAnimation(__VA_ARGS__) +#define AnimationState_setEmptyAnimations(...) spAnimatinState_setEmptyAnimations(__VA_ARGS__) #define AnimationState_getCurrent(...) spAnimationState_getCurrent(__VA_ARGS__) -#define AnimationState_clearListenerNotifications(...) spAnimationState_clearListenerNotifications(__VA_ARGS__) +#define AnimationState_clearListenerNotifications(...) spAnimatinState_clearListenerNotifications(__VA_ARGS__) #endif #ifdef __cplusplus diff --git a/spine-c/spine-c/src/spine/AnimationState.c b/spine-c/spine-c/src/spine/AnimationState.c index 890d3dae2..22a7f45a1 100644 --- a/spine-c/spine-c/src/spine/AnimationState.c +++ b/spine-c/spine-c/src/spine/AnimationState.c @@ -862,7 +862,6 @@ void _spAnimationState_animationsChanged (spAnimationState* self) { for (;i < n; i++) { entry = self->tracks[i]; - if (!entry) continue; while (entry->mixingFrom != 0) entry = entry->mixingFrom; do { diff --git a/spine-sfml/c/example/main.cpp b/spine-sfml/c/example/main.cpp index a2e284df3..6e1232c50 100644 --- a/spine-sfml/c/example/main.cpp +++ b/spine-sfml/c/example/main.cpp @@ -44,25 +44,25 @@ void callback (AnimationState* state, EventType type, TrackEntry* entry, Event* const char* animationName = (entry && entry->animation) ? entry->animation->name : 0; switch (type) { - case ANIMATION_START: - printf("%d start: %s\n", entry->trackIndex, animationName); - break; - case ANIMATION_INTERRUPT: - printf("%d interrupt: %s\n", entry->trackIndex, animationName); - break; - case ANIMATION_END: - printf("%d end: %s\n", entry->trackIndex, animationName); - break; - case ANIMATION_COMPLETE: - printf("%d complete: %s\n", entry->trackIndex, animationName); - break; - case ANIMATION_DISPOSE: - printf("%d dispose: %s\n", entry->trackIndex, animationName); - break; - case ANIMATION_EVENT: - printf("%d event: %s, %s: %d, %f, %s %f %f\n", entry->trackIndex, animationName, event->data->name, event->intValue, event->floatValue, - event->stringValue, event->volume, event->balance); - break; + case ANIMATION_START: + printf("%d start: %s\n", entry->trackIndex, animationName); + break; + case ANIMATION_INTERRUPT: + printf("%d interrupt: %s\n", entry->trackIndex, animationName); + break; + case ANIMATION_END: + printf("%d end: %s\n", entry->trackIndex, animationName); + break; + case ANIMATION_COMPLETE: + printf("%d complete: %s\n", entry->trackIndex, animationName); + break; + case ANIMATION_DISPOSE: + printf("%d dispose: %s\n", entry->trackIndex, animationName); + break; + case ANIMATION_EVENT: + printf("%d event: %s, %s: %d, %f, %s %f %f\n", entry->trackIndex, animationName, event->data->name, event->intValue, event->floatValue, + event->stringValue, event->volume, event->balance); + break; } fflush(stdout); } @@ -92,19 +92,17 @@ SkeletonData* readSkeletonBinaryData (const char* filename, Atlas* atlas, float } void testcase (void func(SkeletonData* skeletonData, Atlas* atlas), - const char* jsonName, const char* binaryName, const char* atlasName, - float scale) { + const char* jsonName, const char* binaryName, const char* atlasName, + float scale) { Atlas* atlas = Atlas_createFromFile(atlasName, 0); SkeletonData* skeletonData = readSkeletonJsonData(jsonName, atlas, scale); func(skeletonData, atlas); SkeletonData_dispose(skeletonData); - /* skeletonData = readSkeletonBinaryData(binaryName, atlas, scale); func(skeletonData, atlas); SkeletonData_dispose(skeletonData); - */ Atlas_dispose(atlas); } @@ -423,221 +421,6 @@ void owl (SkeletonData* skeletonData, Atlas* atlas) { } } -/* - test code -*/ -void animationchanged_nullpointertest(SkeletonData* skeletonData, Atlas* atlas) { - SkeletonBounds* bounds = SkeletonBounds_create(); - - // Configure mixing. - AnimationStateData* stateData = AnimationStateData_create(skeletonData); - AnimationStateData_setMixByName(stateData, "walk", "jump", 0.2f); - AnimationStateData_setMixByName(stateData, "jump", "run", 0.2f); - - SkeletonDrawable* drawable = new SkeletonDrawable(skeletonData, stateData); - drawable->timeScale = 1; - drawable->setUsePremultipliedAlpha(true); - - Skeleton* skeleton = drawable->skeleton; - Skeleton_setToSetupPose(skeleton); - - skeleton->x = 320; - skeleton->y = 590; - Skeleton_updateWorldTransform(skeleton); - - drawable->state->listener = callback; - AnimationState_addAnimationByName(drawable->state, 0, "walk", true, 0); - AnimationState_addEmptyAnimation(drawable->state, 0, 1.0f, 0.0f); - - sf::RenderWindow window(sf::VideoMode(640, 640), "Spine SFML - spineboy"); - window.setFramerateLimit(60); - sf::Event event; - sf::Clock deltaClock; - while (window.isOpen()) { - while (window.pollEvent(event)) - if (event.type == sf::Event::Closed) window.close(); - - float delta = deltaClock.getElapsedTime().asSeconds(); - deltaClock.restart(); - - drawable->update(delta); - - window.clear(); - window.draw(*drawable); - window.display(); - } - - SkeletonBounds_dispose(bounds); - delete drawable; -} - -void multitrack_animationmixtest(SkeletonData* skeletonData, Atlas* atlas) { - SkeletonDrawable* drawable = new SkeletonDrawable(skeletonData); - drawable->timeScale = 1; - drawable->setUsePremultipliedAlpha(false); - - // setup mixing - drawable->state->data->defaultMix = 0.5f; - - Skeleton* skeleton = drawable->skeleton; - skeleton->x = 320; - skeleton->y = 400; - skeleton->scaleX = 1.0f; - skeleton->scaleY = 1.0f; - Skeleton_updateWorldTransform(skeleton); - - - // track[0] = base ... none animation - // track[1] = anim1 -> anim2 -> anim1 -> ... - AnimationState_setAnimationByName(drawable->state, 0, "base", true); - AnimationState_setAnimationByName(drawable->state, 1, "anim1", false); - - sf::RenderWindow window(sf::VideoMode(640, 640), "Spine SFML - animation mixing test on track[1]"); - window.setFramerateLimit(60); - sf::Event event; - sf::Clock deltaClock; - - float sumtime = 999.0f; - int animationindex = 0; - - while (window.isOpen()) { - while (window.pollEvent(event)) - if (event.type == sf::Event::Closed) window.close(); - - float delta = deltaClock.getElapsedTime().asSeconds(); - deltaClock.restart(); - - // motion switch - sumtime += delta; - if (sumtime > 3.0f) { - if (animationindex == 0) - AnimationState_setAnimationByName(drawable->state, 1, "anim1", false); - else - AnimationState_setAnimationByName(drawable->state, 1, "anim2", false); - sumtime = 0.0f; - animationindex = (animationindex + 1) & 1; - } - - // draw - drawable->update(delta); - window.clear(); - window.draw(*drawable); - window.display(); - } - - delete drawable; -} - -void multitrack_addmixtest(SkeletonData* skeletonData, Atlas* atlas) { - SkeletonDrawable* drawable = new SkeletonDrawable(skeletonData); - - drawable->timeScale = 1; - drawable->setUsePremultipliedAlpha(false); - - // use track index - int usetrackindex = 1; // 1 or 0 - - // setup mixing - drawable->state->data->defaultMix = 0.5f; - { - Skeleton* skeleton = drawable->skeleton; - skeleton->x = 320; - skeleton->y = 400; - skeleton->scaleX = 1.0f; - skeleton->scaleY = 1.0f; - Skeleton_updateWorldTransform(skeleton); - } - - // track[0](replace) = base ... none animation - // track[1](add) = anim1 -> anim2 -> anim1 -> ... - spTrackEntry* track; - - AnimationState_setAnimationByName(drawable->state, 0, "base", true); - track = AnimationState_setAnimationByName(drawable->state, usetrackindex, "anim1", false); - track->mixBlend = SP_MIX_BLEND_ADD; // mixAdd - - sf::RenderWindow window(sf::VideoMode(640, 640), "Spine SFML - mixAdd animation mixing test on track[1]"); - window.setFramerateLimit(60); - sf::Event event; - sf::Clock deltaClock; - - float sumtime = 999.0f; - int animationindex = 0; - - while (window.isOpen()) { - while (window.pollEvent(event)) - if (event.type == sf::Event::Closed) window.close(); - - float delta = deltaClock.getElapsedTime().asSeconds(); - deltaClock.restart(); - - // motion switch - sumtime += delta; - if (sumtime > 3.0f) { - std::string name; - if (animationindex == 0) - track = AnimationState_setAnimationByName(drawable->state, usetrackindex, "anim1", false); - else - track = AnimationState_setAnimationByName(drawable->state, usetrackindex, "anim2", false); - - track->mixBlend = SP_MIX_BLEND_ADD; - - sumtime = 0.0f; - animationindex = (animationindex + 1) & 1; - } - - // draw - drawable->update(delta); - window.clear(); - window.draw(*drawable); - window.display(); - } - - delete drawable; -} - -void skeleton_scaletest(SkeletonData* skeletonData, Atlas* atlas) { - SkeletonDrawable* drawable = new SkeletonDrawable(skeletonData); - drawable->timeScale = 1; - drawable->setUsePremultipliedAlpha(false); - - // setup mixing - drawable->state->data->defaultMix = 0.5f; - - Skeleton* skeleton = drawable->skeleton; - skeleton->x = 320; - skeleton->y = 400; - skeleton->scaleX = 0.6f; - skeleton->scaleY = 0.6f; - Skeleton_updateWorldTransform(skeleton); - - - // track[0] = base ... none animation - // track[1] = anim1 -> anim2 -> anim1 -> ... - AnimationState_setAnimationByName(drawable->state, 0, "base", true); - - sf::RenderWindow window(sf::VideoMode(640, 640), "Spine SFML - skeleton scale test"); - window.setFramerateLimit(60); - sf::Event event; - sf::Clock deltaClock; - - while (window.isOpen()) { - while (window.pollEvent(event)) - if (event.type == sf::Event::Closed) window.close(); - - float delta = deltaClock.getElapsedTime().asSeconds(); - deltaClock.restart(); - - // draw - drawable->update(delta); - window.clear(); - window.draw(*drawable); - window.display(); - } - - delete drawable; -} - /** * Used for debugging purposes during runtime development */ @@ -666,11 +449,6 @@ void test (SkeletonData* skeletonData, Atlas* atlas) { } int main () { - // testcase(multitrack_animationmixtest, "data/testmodel/skeleton.json", "data/testmodel/skeleton.skel", "data/testmodel/skeleton.atlas", 0.6f); - // testcase(multitrack_addmixtest, "data/testmodel/skeleton.json", "data/testmodel/skeleton.skel", "data/testmodel/skeleton.atlas", 0.6f); - // testcase(skeleton_scaletest, "data/testmodel/skeleton.json", "data/testmodel/skeleton.skel", "data/testmodel/skeleton.atlas", 0.6f); - testcase(animationchanged_nullpointertest, "data/spineboy-pro.json", "data/spineboy-pro.skel", "data/spineboy-pma.atlas", 0.6f); - /* testcase(test, "data/tank-pro.json", "data/tank-pro.skel", "data/tank-pma.atlas", 1.0f); testcase(spineboy, "data/spineboy-pro.json", "data/spineboy-pro.skel", "data/spineboy-pma.atlas", 0.6f); testcase(stretchyman, "data/stretchyman-stretchy-ik-pro.json", "data/stretchyman-stretchy-ik-pro.skel", "data/stretchyman-pma.atlas", 0.6f); @@ -681,6 +459,5 @@ int main () { testcase(raptor, "data/raptor-pro.json", "data/raptor-pro.skel", "data/raptor-pma.atlas", 0.5f); testcase(goblins, "data/goblins-pro.json", "data/goblins-pro.skel", "data/goblins-pma.atlas", 1.4f); testcase(stretchyman, "data/stretchyman-pro.json", "data/stretchyman-pro.skel", "data/stretchyman-pma.atlas", 0.6f); - */ return 0; } diff --git a/spine-sfml/cpp/example/main.cpp b/spine-sfml/cpp/example/main.cpp index 2ebd3c174..4bccbdef9 100644 --- a/spine-sfml/cpp/example/main.cpp +++ b/spine-sfml/cpp/example/main.cpp @@ -126,9 +126,8 @@ void spineboy (SkeletonData* skeletonData, Atlas* atlas) { drawable.state->setListener(callback); drawable.state->addAnimation(0, "walk", true, 0); - //drawable.state->addAnimation(0, "jump", false, 3); - //drawable.state->addAnimation(0, "run", true, 0); - drawable.state->addEmptyAnimation(0, 1, 0); + drawable.state->addAnimation(0, "jump", false, 3); + drawable.state->addAnimation(0, "run", true, 0); sf::RenderWindow window(sf::VideoMode(640, 640), "Spine SFML - spineboy"); window.setFramerateLimit(60); From 9bbd2c61757c34eaec2c4326dc692e5fd7b75a71 Mon Sep 17 00:00:00 2001 From: badlogic Date: Mon, 18 Feb 2019 11:42:23 +0100 Subject: [PATCH 4/4] [c] Fixes #1282, animation state was missing a null check when iterating mixed out track entries. --- spine-c/spine-c/src/spine/AnimationState.c | 1 + 1 file changed, 1 insertion(+) diff --git a/spine-c/spine-c/src/spine/AnimationState.c b/spine-c/spine-c/src/spine/AnimationState.c index 22a7f45a1..890d3dae2 100644 --- a/spine-c/spine-c/src/spine/AnimationState.c +++ b/spine-c/spine-c/src/spine/AnimationState.c @@ -862,6 +862,7 @@ void _spAnimationState_animationsChanged (spAnimationState* self) { for (;i < n; i++) { entry = self->tracks[i]; + if (!entry) continue; while (entry->mixingFrom != 0) entry = entry->mixingFrom; do {