From 0e682ce1941237fe4dcb4a7fca787c0d11634f50 Mon Sep 17 00:00:00 2001 From: Ken Hughes Date: Sun, 19 Nov 2006 06:07:24 +0000 Subject: [PATCH] Animation system: Bugfix #5027: Deleting Shape key sometimes caused corruption to Ipo curves. sort_key() was moving key but not resorting adrcodes for keys and Ipo curves. Also changed behavior of sort_key() so that it only resorts one key; all the places which currently call it only do so after changing one key (the previous code was moving the key one location at a time through the keyblock list). --- source/blender/blenkernel/intern/key.c | 73 +++++++++++++++++++++----- 1 file changed, 59 insertions(+), 14 deletions(-) diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c index 05eaeec7ff9..e4d7181c66b 100644 --- a/source/blender/blenkernel/intern/key.c +++ b/source/blender/blenkernel/intern/key.c @@ -185,27 +185,72 @@ void make_local_key(Key *key) make_local_ipo(key->ipo); } +/* + * Sort shape keys and Ipo curves after a change. This assumes that at most + * one key was moved, which is a valid assumption for the places it's + * currently being called. + */ void sort_keys(Key *key) { KeyBlock *kb; - int doit=1; - - while(doit) { - doit= 0; - - for(kb= key->block.first; kb; kb= kb->next) { - if(kb->next) { - if(kb->pos > kb->next->pos) { - BLI_remlink(&key->block, kb); - - BLI_insertlink(&key->block, kb->next, kb); - - doit= 1; + short i, adrcode; + IpoCurve *icu = NULL; + KeyBlock *kb2; + + /* locate the key which is out of position */ + for( kb= key->block.first; kb; kb= kb->next ) + if( kb->next && kb->pos > kb->next->pos ) + break; + + /* if we find a key, move it */ + if( kb ) { + kb = kb->next; /* next key is the out-of-order one */ + BLI_remlink(&key->block, kb); + + /* find the right location and insert before */ + for( kb2=key->block.first; kb2; kb2= kb2->next ) { + if( kb2->pos > kb->pos ) { + BLI_insertlink(&key->block, kb2->prev, kb); + break; + } + } + + /* if more than one Ipo curve, see if this key had a curve */ + + if(key->ipo && key->ipo->curve.first != key->ipo->curve.last ) { + for(icu= key->ipo->curve.first; icu; icu= icu->next) { + /* if we find the curve, remove it and reinsert in the + right place */ + if(icu->adrcode==kb->adrcode) { + IpoCurve *icu2; + BLI_remlink(&key->ipo->curve, icu); + for(icu2= key->ipo->curve.first; icu2; icu2= icu2->next) { + if(icu2->adrcode >= kb2->adrcode) { + BLI_insertlink(&key->ipo->curve, icu2->prev, icu); + break; + } + } break; } } - } + } + + /* kb points at the moved key, icu at the moved ipo (if it exists). + * go back now and renumber adrcodes */ + + /* first new code */ + adrcode = kb2->adrcode; + for( i = kb->adrcode - adrcode; i >= 0; --i, ++adrcode ) { + /* if the next ipo curve matches the current key, renumber it */ + if(icu && icu->adrcode == kb->adrcode ) { + icu->adrcode = adrcode; + icu = icu->next; + } + /* renumber the shape key */ + kb->adrcode = adrcode; + kb = kb->next; + } } /* new rule; first key is refkey, this to match drawing channels... */