mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2025-12-20 09:16:01 +08:00
[c] Fixes #1282, animation state was missing a null check when iterating mixed out track entries.
This commit is contained in:
parent
125b999cae
commit
f5709a7bbc
@ -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
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -100,9 +100,11 @@ void testcase (void func(SkeletonData* skeletonData, Atlas* atlas),
|
||||
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;
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user