Commit: aa009766d66fefcc5b66170124b0b8ad049478ae
Author: Grigory Revzin
Date:   Mon Jun 2 01:26:15 2014 +0400
https://developer.blender.org/rBaa009766d66fefcc5b66170124b0b8ad049478ae

Can mix shapekeys in editmode now

The user can now edit a shape key on top of a mix.

The difference to the master is that the 'Apply Shape Keys in Editmode' is gone 
completely. You can either pin the shapekey or edit on top of a mix: 
http://screenshot.su/img/a1/70/dc/a170dc61123ee1648e8a6dc3394b3812.jpg, and 
that is all.

The user can select the values that he wants to use in the mix: the 
animation-driven values (KeyBlock->curval) or a temporary mix value visible 
only in editmode.

Implementation-wise this is sort of an emulation of the shape keys modifier 
behavior. On editmode enter, the mesh keyblocks get evaluated and that is put 
in the edit coordinates. On shapekey switch or editmode exit the underlying mix 
gets subtracted from the editmesh cos, the resulting isolated shape coordinates 
gets adjusted for value (we store data with 1.0 values only!) and than 
processed as a normal (pinned) shape key update. Then the mesh gets 
re-evaluated, etc.

There is some optimization potential which will be explored!

Undo might be broken at the moment, this is the next thing to do.

===================================================================

M       release/scripts/startup/bl_ui/properties_data_mesh.py
M       source/blender/blenkernel/BKE_key.h
M       source/blender/blenkernel/intern/key.c
M       source/blender/blenkernel/intern/modifier.c
M       source/blender/blenloader/intern/versioning_270.c
M       source/blender/editors/include/ED_mesh.h
M       source/blender/editors/mesh/editmesh_utils.c
M       source/blender/editors/object/object_shapekey.c
M       source/blender/makesrna/intern/rna_key.c
M       source/blender/makesrna/intern/rna_object.c

===================================================================

diff --git a/release/scripts/startup/bl_ui/properties_data_mesh.py 
b/release/scripts/startup/bl_ui/properties_data_mesh.py
index 848876b..b3a5fca 100644
--- a/release/scripts/startup/bl_ui/properties_data_mesh.py
+++ b/release/scripts/startup/bl_ui/properties_data_mesh.py
@@ -94,10 +94,7 @@ class MESH_UL_shape_keys(UIList):
             row = split.row(align=True)
             if key_block.mute:
                 row.active = False
-
-            if not item.id_data.use_relative:
-                               row.prop(key_block, "frame", text="", 
emboss=False)
-                       elif index > 0:
+            if not item.relative_key or index > 0:
                 draw_shape_value(obj, key_block, row)
             else:
                 row.label(text="")
diff --git a/source/blender/blenkernel/BKE_key.h 
b/source/blender/blenkernel/BKE_key.h
index 1232907..ce8da7d 100644
--- a/source/blender/blenkernel/BKE_key.h
+++ b/source/blender/blenkernel/BKE_key.h
@@ -93,9 +93,14 @@ void BKE_key_editdata_to_scratch(Object *ob, bool 
shapedata_indeces_in_sync);
 /* populates the current editdata from scratch shapekey */
 void BKE_key_editdata_from_scratch(Object *ob);
 
+/* ==== editmote evaluation ==== */
+
 /* evaluates the current shape key situation and puts it into the editmesh 
coordinates */
 void BKE_key_eval_editmesh_rel(BMEditMesh *edbm, bool pinned);
 
+/* evaluates a relative mesh keyblock and puts the resulting offsets in 
out_offsets */
+void BKE_key_block_mesh_eval_rel(Object *ob, Key *key, KeyBlock *kb, bool 
use_vgroup, float (*out_offsets)[3]);
+
 /* ========================= */
 
 // needed for the GE
diff --git a/source/blender/blenkernel/intern/key.c 
b/source/blender/blenkernel/intern/key.c
index ca151f9..153a8e2 100644
--- a/source/blender/blenkernel/intern/key.c
+++ b/source/blender/blenkernel/intern/key.c
@@ -2090,8 +2090,8 @@ void BKE_key_init_scratch(Object *ob)
                key->scratch.origin = kb;
                if (!key->scratch.data) {
                        key->scratch.data = MEM_mallocN(key->elemsize * 
kb->totelem, "scratch keyblock data");
-                       memcpy(key->scratch.data, kb->data, key->elemsize * 
kb->totelem);
                }
+               memcpy(key->scratch.data, kb->data, key->elemsize * 
kb->totelem);
        }
 }
 
@@ -2190,7 +2190,7 @@ void key_block_mesh_get_deltas(Key *key, KeyBlock *kb, 
float (*out_deltas)[3])
                sub_v3_v3v3(out_deltas[a], kb_cos[a], basis_cos[a]);
 }
 
-void key_block_mesh_eval_rel(Object *ob, Key *key, KeyBlock *kb, bool 
use_vgroup, float (*out_offsets)[3])
+void BKE_key_block_mesh_eval_rel(Object *ob, Key *key, KeyBlock *kb, bool 
use_vgroup, float (*out_offsets)[3])
 {
        int a;
        float *per_vertex_weights = NULL;
@@ -2218,14 +2218,13 @@ void key_block_mesh_eval_rel(Object *ob, Key *key, 
KeyBlock *kb, bool use_vgroup
 
 void key_block_mesh_eval_scratch(Object *ob, Key *key, float (*out_offsets)[3])
 {
-       /* we need to eval the regular key, but with scratch's data */
+       /* we need to eval a regular key, but with scratch's data */
        ScratchKeyBlock *skb = &key->scratch;
        KeyBlock bogus; 
-       bogus.data = skb->data;
-
-       BKE_keyblock_copy_settings(&bogus, skb->origin);
+       
+       bogus = *skb->origin;
 
-       key_block_mesh_eval_rel(ob, key, &bogus, false, out_offsets);
+       BKE_key_block_mesh_eval_rel(ob, key, &bogus, false, out_offsets);
 }
 
 void BKE_key_eval_editmesh_rel(BMEditMesh *edbm, bool pinned) 
@@ -2266,7 +2265,7 @@ void BKE_key_eval_editmesh_rel(BMEditMesh *edbm, bool 
pinned)
                        if (a == 0 || a == act_shape_index)
                                continue;
                        
-                       key_block_mesh_eval_rel(edbm->ob, key, kb, true, 
kb_offsets_cos);
+                       BKE_key_block_mesh_eval_rel(edbm->ob, key, kb, true, 
kb_offsets_cos);
 
                        KB_FOR_EACH_CO(kb, b) {
                                add_v3_v3(out_vcos[b], kb_offsets_cos[b]);
diff --git a/source/blender/blenkernel/intern/modifier.c 
b/source/blender/blenkernel/intern/modifier.c
index 5f8a2e1..e26d97d 100644
--- a/source/blender/blenkernel/intern/modifier.c
+++ b/source/blender/blenkernel/intern/modifier.c
@@ -521,11 +521,6 @@ ModifierData *modifiers_getVirtualModifierList(Object *ob, 
VirtualModifierData *
 
        /* shape key modifier, not yet for curves */
        if (ELEM(ob->type, OB_MESH, OB_LATTICE) && key) {
-               if (ob->type == OB_MESH && key->pin)
-                       virtualModifierData->smd.modifier.mode |= 
eModifierMode_Editmode | eModifierMode_OnCage;
-               else
-                       virtualModifierData->smd.modifier.mode &= 
~eModifierMode_Editmode | eModifierMode_OnCage;
-
                virtualModifierData->smd.modifier.next = md;
                md = &virtualModifierData->smd.modifier;
        }
diff --git a/source/blender/blenloader/intern/versioning_270.c 
b/source/blender/blenloader/intern/versioning_270.c
index 0b01fa7..6fc7e21 100644
--- a/source/blender/blenloader/intern/versioning_270.c
+++ b/source/blender/blenloader/intern/versioning_270.c
@@ -257,21 +257,16 @@ void blo_do_versions_270(FileData *fd, Library 
*UNUSED(lib), Main *main)
                /* XXX insert appropriate version later!*/
                Scene *sc;
                Key *k;
-               Object *ob;
+               //Object *ob;
 
                /* Enable auto-committing shape keys! */
                for (sc = main->scene.first; sc; sc = sc->id.next) {
                        sc->toolsettings->kb_auto_commit = true;
                }
 
+               /* set mixing to be governed by animdata */
                for (k = main->key.first; k; k = k->id.next) {
                        k->mix_mode = KEY_MIX_FROM_ANIMDATA;
-
-                       for (ob = main->object.first; ob; ob = ob->id.next) {
-                               if (BKE_key_from_object(ob) == k) {
-                                       k->pin = ob->shapeflag != 0;
-                               }
-                       }
                }
        }
 
diff --git a/source/blender/editors/include/ED_mesh.h 
b/source/blender/editors/include/ED_mesh.h
index 44b36e8..910431b 100644
--- a/source/blender/editors/include/ED_mesh.h
+++ b/source/blender/editors/include/ED_mesh.h
@@ -104,7 +104,8 @@ bool EDBM_mesh_from_editmesh(struct Object *obedit, bool 
do_free);
 /* updates the active shape, recalculates the key blocks */
 void EDBM_handle_active_shape_update(struct Object *ob, struct Scene *s);
 
-void EDBM_commit_scratch_to_active(struct Object *ob, struct Scene *s);
+/* commit the scratch keyblock's contents to the active keyblock, recalc the 
keyblocks */
+void EDBM_commit_scratch_to_active(struct Object *ob, struct Scene *s, bool 
key_is_pinned);
 void EDBM_update_scratch_from_active(struct Object *ob);
 
 
diff --git a/source/blender/editors/mesh/editmesh_utils.c 
b/source/blender/editors/mesh/editmesh_utils.c
index a019c57..c3edf84 100644
--- a/source/blender/editors/mesh/editmesh_utils.c
+++ b/source/blender/editors/mesh/editmesh_utils.c
@@ -492,6 +492,12 @@ void EDBM_flag_enable_all(BMEditMesh *em, const char hflag)
 * The idea: detect if topology hadn't changed. If it had, run the heavy-duty 
tools from bmesh_mesh_conv.c.
 */
 
+void shapekey_zero_warn(KeyBlock *kb) 
+{
+       /* TODO: raise a UI warning */
+       printf("Warning: can't commit the scratch shape key: %s->value = 
0.0\n", kb->name);
+}
+
 void update_bmesh_shapes(Object *ob)
 {
        Key *key = BKE_key_from_object(ob);
@@ -503,11 +509,11 @@ void update_bmesh_shapes(Object *ob)
                CustomData *vdata = &bm->vdata;
                KeyBlock *kb;
                int i, j, index;
-               float(*kbco)[3] = NULL;
+               float (*kbco)[3] = NULL;
                float *cdco = NULL;
 
                LISTBASE_ITER_FWD_INDEX(key->block, kb, i) {
-                       /* find any keyblocks that don't have a correspoing 
CD_SHAPEKEY */
+                       /* find any keyblocks that don't have a corresponding 
CD_SHAPEKEY */
                        index = CustomData_get_named_layer_index(vdata, 
CD_SHAPEKEY, kb->name);
                        if (index == -1) {
                                /* this code can hardly ever be ran, but 
theoretically, if there's a new keyblock somehow... */
@@ -523,17 +529,25 @@ void update_bmesh_shapes(Object *ob)
                                copy_v3_v3(cdco, kbco[j]);
                        }
                }
+
+               kb = BLI_findlink(&key->block, ob->shapenr - 1);
+               kbco = kb->data;
+               /* fix up the editcos along the CD_SHAPEKEY too */
+               BM_ITER_MESH_INDEX(v, &iter, bm, BM_VERTS_OF_MESH, j) {
+                       copy_v3_v3(v->co, kbco[j]);
+               }
+
        }
 }
 
-void recalc_keyblocks_from_scratch(Object *ob)
+void recalc_keyblocks_from_scratch(Object *ob, bool pinned)
 {
        Key *k = BKE_key_from_object(ob);
        Mesh *me = ob->data;
 
        ScratchKeyBlock *skb = &k->scratch;
        KeyBlock *old_active = skb->origin,
-               *kb = BKE_keyblock_from_object(ob);
+               *kb;
 
        ListBase kbs = k->block;
 
@@ -542,12 +556,46 @@ void recalc_keyblocks_from_scratch(Object *ob)
 
        float (*offsets_co)[3] = NULL;
        float (*skb_co)[3] = skb->data;
-       float (*kb_co)[3];
+       float (*kb_co)[3] = NULL;
 
        if (k->type == KEY_RELATIVE) {
-               /* find all keyblocks that are the basis for the active 
keyblock */
-               LISTBASE_ITER_FWD_INDEX(kbs, kb, a) {
 
+               if (!pinned) {
+                       float scratch_val = *BKE_keyblock_get_active_value(k, 
old_active);
+                       KeyBlock *old_kb_base = BLI_findlink(&kbs, 
old_active->relative);
+                       float (*old_kb_baseco)[3] = old_kb_base->data;
+
+                       BLI_assert(fabs(scratch_val) > 0.001f);
+
+                       float (*submix_kb_offset_co)[3] = 
MEM_callocN(sizeof(float) * 3 * old_active->totelem, __func__);
+                       /* if the key wasn't pinned, it means we have to 
subtract all other keys from the scratch
+                               * from the mix before getting the offsets */
+                       LISTBASE_ITER_FWD_INDEX(kbs, kb, a) {
+                               if (a == old_index || a == 0)
+                                       continue;
+                               BKE_key_block_mesh_eval_rel(ob, k, kb, false, 
submix_kb_offset_co);
+                               for (b = 0; b < old_active->totelem; ++b) {
+                                       sub_v3_v3(skb_co[b], 
submix_kb_offset_co[b]);
+                               }
+                       }
+
+                       for (b = 0; b < old_active->totelem; ++b) {
+                               /* now for a less intuitive operation - weight 
correction.
+                                * data in keyblock should ALWAYS correspond to 
keyblock @ 1.0 value,
+                                * but while editing a mix, we don't necessary 
have 1.0 value, so let's correct for it
+                               /* see 
http://wiki.blender.org/index.php/File:Gsoc-keys-mix-recalc-relations.png */
+                               sub_v3_v3(skb_co[b], old_kb_baseco[b]);
+                               /* scale the offset to 1.0 value */
+                               mul_v3_fl(skb_co[b], 1.0f / scratch_val);
+                               /* add the basis back */
+                               add_v3_v3(skb_co[b], old_kb_baseco[b]);
+                       }
+
+                       MEM_freeN(submix_kb_offset_co);
+               }
+
+               LISTBASE_ITER_FWD_INDEX(kbs, kb, a) {
+                       /* for all keyblocks, find their relative keyblock */
                        if (kb != k->refkey)
                                BLI_assert(kb->relative != a);
                        /* kb can't be relative to itself (except for refkey, 
it can trigger strange asserts and doesn't matter) */
@@ -557,7 +605,7 @@ void recalc_keyblocks_from_scratch(Object *ob)
                                /* need to propagate the offsets */
                                if (!offsets_co) {
                                        /* calculate them if we haven't already 
*/
-                                       

@@ Diff output truncated at 10240 characters. @@

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to