[Bf-blender-cvs] [aa00976] soc-2014-shapekey: Can mix shapekeys in editmode now

Grigory Revzin noreply at git.blender.org
Sun Jun 1 23:27:12 CEST 2014


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. @@




More information about the Bf-blender-cvs mailing list