[Bf-blender-cvs] [2939cda] soc-2014-shapekey: Added Commit To Another Shape

Grigory Revzin noreply at git.blender.org
Sun Jul 6 00:01:26 CEST 2014


Commit: 2939cda6b2b5b17fbb7a9d557bb565bc91106e3c
Author: Grigory Revzin
Date:   Sun Jul 6 01:58:54 2014 +0400
https://developer.blender.org/rB2939cda6b2b5b17fbb7a9d557bb565bc91106e3c

Added Commit To Another Shape

This new operator allows you to change shapes while editing, helping if you've edited the wrong shape.

Implementation-wise had to slightly change the way editmode undo is pushed and popped, this operator messed with it. Now RealMesh keyblocks will be restored from the stored UndoMesh on undo pop.

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

M	source/blender/blenkernel/BKE_key.h
M	source/blender/blenkernel/intern/key.c
M	source/blender/blenkernel/intern/paint.c
M	source/blender/bmesh/intern/bmesh_mesh_conv.c
M	source/blender/bmesh/intern/bmesh_mesh_conv.h
M	source/blender/bmesh/operators/bmo_mesh_conv.c
M	source/blender/editors/mesh/editmesh_tools.c
M	source/blender/editors/mesh/editmesh_utils.c
M	source/blender/editors/mesh/mesh_intern.h
M	source/blender/editors/mesh/mesh_ops.c
M	source/blender/python/bmesh/bmesh_py_types.c

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

diff --git a/source/blender/blenkernel/BKE_key.h b/source/blender/blenkernel/BKE_key.h
index e56cba4..e77427a 100644
--- a/source/blender/blenkernel/BKE_key.h
+++ b/source/blender/blenkernel/BKE_key.h
@@ -57,6 +57,9 @@ Key		   *BKE_key_add(ID *id);
 Key		   *BKE_key_copy(Key *key);
 Key		   *BKE_key_copy_nolib(Key *key);
 void        BKE_key_make_local(Key *key);
+/* overwrites data in 'to' with data in 'from', frees old 'to' data. 
+ * does not touch any library data, animation data and ID and from */
+void		BKE_key_overwrite_data(Key *from, Key *to);
 void        BKE_key_sort(Key *key);
 
 void key_curve_position_weights(float t, float data[4], int type);
diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c
index 11062e9..e5bba52 100644
--- a/source/blender/blenkernel/intern/key.c
+++ b/source/blender/blenkernel/intern/key.c
@@ -186,6 +186,48 @@ Key *BKE_key_copy(Key *key)
 	return keyn;
 }
 
+void BKE_key_overwrite_data(Key *from, Key *to)
+{
+	KeyBlock *kbt, *kbf;
+
+	LISTBASE_ITER_FWD(to->block, kbt) {
+		if (kbt->data)
+			MEM_freeN(kbt->data);
+	}
+
+	if (to->scratch.data) {
+		MEM_freeN(to->scratch.data);
+		to->scratch.data = NULL;
+	}
+
+	if (from->scratch.data) {
+		to->scratch.data = MEM_dupallocN(from->scratch.data);
+	}
+
+	BLI_freelistN(&to->block);
+	BLI_duplicatelist(&to->block, &from->block);
+
+	kbf = from->block.first;
+	kbt = to->block.first;
+
+	while (kbf) {
+		if (kbf->data) {
+			kbt->data = MEM_dupallocN(kbf->data);
+		}
+		if (kbf == from->refkey) to->refkey = kbt;
+		if (kbf == from->scratch.origin) to->scratch.origin = kbt;
+
+		kbf = kbf->next;
+		kbt = kbt->next;
+	}
+
+	to->mix_mode = from->mix_mode;
+	to->type = from->type;
+	to->slurph = from->slurph;
+	to->ctime = from->ctime;
+	to->uidgen = from->uidgen;
+}
+
 
 Key *BKE_key_copy_nolib(Key *key)
 {
@@ -2085,7 +2127,6 @@ float    *BKE_keyblock_get_active_value(Object *ob, KeyBlock *kb)
 	else return &kb->curval;
 }
 
-
 /* ================== Scratch stuff ======================  */
 
 void BKE_key_init_scratch(Object *ob) 
@@ -2094,7 +2135,7 @@ void BKE_key_init_scratch(Object *ob)
 	KeyBlock *kb = BKE_keyblock_from_object(ob);
 	if (key && kb && key->totkey > 0) {
 		key->scratch.origin = kb;
-		key->scratch.data = MEM_mallocN(key->elemsize * kb->totelem, "scratch keyblock data");
+		key->scratch.data = MEM_mallocN(key->elemsize * kb->totelem, __func__);
 		memcpy(key->scratch.data, kb->data, key->elemsize * kb->totelem);
 	}
 }
diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c
index 9a144b5..8ff8ee3 100644
--- a/source/blender/blenkernel/intern/paint.c
+++ b/source/blender/blenkernel/intern/paint.c
@@ -422,7 +422,7 @@ static void sculptsession_bm_to_me_update_data_only(Object *ob, bool reorder)
 			}
 			if (reorder)
 				BM_log_mesh_elems_reorder(ss->bm, ss->bm_log);
-			BM_mesh_bm_to_me(ss->bm, ob->data, false);
+			BM_mesh_bm_to_me(ss->bm, ob->data, false, true);
 		}
 	}
 }
diff --git a/source/blender/bmesh/intern/bmesh_mesh_conv.c b/source/blender/bmesh/intern/bmesh_mesh_conv.c
index 05f3ff5..ca87c1c 100644
--- a/source/blender/bmesh/intern/bmesh_mesh_conv.c
+++ b/source/blender/bmesh/intern/bmesh_mesh_conv.c
@@ -566,7 +566,7 @@ BLI_INLINE void bmesh_quick_edgedraw_flag(MEdge *med, BMEdge *e)
 	}
 }
 
-void BM_mesh_bm_to_me(BMesh *bm, Mesh *me, bool do_tessface)
+void BM_mesh_bm_to_me(BMesh *bm, Mesh *me, bool do_tessface, bool do_keys)
 {
 	MLoop *mloop;
 	MPoly *mpoly;
@@ -814,7 +814,7 @@ void BM_mesh_bm_to_me(BMesh *bm, Mesh *me, bool do_tessface)
 
 	/* see comment below, this logic is in twice */
 
-	if (me->key) {
+	if (me->key && do_keys) {
 		const int cd_shape_keyindex_offset = CustomData_get_offset(&bm->vdata, CD_SHAPE_KEYINDEX);
 
 		KeyBlock *currkey;
diff --git a/source/blender/bmesh/intern/bmesh_mesh_conv.h b/source/blender/bmesh/intern/bmesh_mesh_conv.h
index ab9d7a0..b1f5a28 100644
--- a/source/blender/bmesh/intern/bmesh_mesh_conv.h
+++ b/source/blender/bmesh/intern/bmesh_mesh_conv.h
@@ -41,6 +41,6 @@ char BM_mesh_cd_flag_from_bmesh(BMesh *bm);
 
 void BM_mesh_bm_from_me(BMesh *bm, struct Mesh *me,
                         const bool calc_face_normal, const bool set_key, int act_key_nr);
-void BM_mesh_bm_to_me(BMesh *bm, struct Mesh *me, bool do_tessface);
+void BM_mesh_bm_to_me(BMesh *bm, struct Mesh *me, bool do_tessface, bool do_shapes);
 
 #endif /* __BMESH_MESH_CONV_H__ */
diff --git a/source/blender/bmesh/operators/bmo_mesh_conv.c b/source/blender/bmesh/operators/bmo_mesh_conv.c
index d124aaa..7e31997 100644
--- a/source/blender/bmesh/operators/bmo_mesh_conv.c
+++ b/source/blender/bmesh/operators/bmo_mesh_conv.c
@@ -69,5 +69,5 @@ void bmo_bmesh_to_mesh_exec(BMesh *bm, BMOperator *op)
 	/* Object *ob = BMO_slot_ptr_get(op, "object"); */
 	const bool dotess = !BMO_slot_bool_get(op->slots_in, "skip_tessface");
 
-	BM_mesh_bm_to_me(bm, me, dotess);
+	BM_mesh_bm_to_me(bm, me, dotess, true);
 }
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index 55ad303..79916f9 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -54,6 +54,7 @@
 #include "BKE_texture.h"
 #include "BKE_main.h"
 #include "BKE_editmesh.h"
+#include "BKE_key.h"
 
 #include "BLF_translation.h"
 
@@ -2091,32 +2092,22 @@ static int edbm_blend_from_shape_exec(bContext *C, wmOperator *op)
 static EnumPropertyItem *shape_itemf(bContext *C, PointerRNA *UNUSED(ptr),  PropertyRNA *UNUSED(prop), bool *r_free)
 {	
 	Object *obedit = CTX_data_edit_object(C);
-	BMEditMesh *em;
 	EnumPropertyItem *item = NULL;
-	int totitem = 0;
+	Key *k = BKE_key_from_object(obedit);
+	KeyBlock *kb;
+	int totitem = 0, i;
 
-	if ((obedit && obedit->type == OB_MESH) &&
-	    (em = BKE_editmesh_from_object(obedit)) &&
-	    CustomData_has_layer(&em->bm->vdata, CD_SHAPEKEY))
-	{
-		EnumPropertyItem tmp = {0, "", 0, "", ""};
-		int a;
+	if (obedit && obedit->type == OB_MESH && BKE_keyblock_from_object(obedit)) {
+		EnumPropertyItem tmp = { 0, "", 0, "", "" };
 
-		for (a = 0; a < em->bm->vdata.totlayer; a++) {
-			if (em->bm->vdata.layers[a].type != CD_SHAPEKEY)
-				continue;
-
-			tmp.value = totitem;
-			tmp.identifier = em->bm->vdata.layers[a].name;
-			tmp.name = em->bm->vdata.layers[a].name;
-			/* RNA_enum_item_add sets totitem itself! */
+		LISTBASE_ITER_FWD_INDEX(k->block, kb, i) {
+			tmp.value = i;
+			tmp.identifier = tmp.name = kb->name;
 			RNA_enum_item_add(&item, &totitem, &tmp);
 		}
 	}
-
 	RNA_enum_item_end(&item, &totitem);
 	*r_free = true;
-
 	return item;
 }
 
@@ -2216,6 +2207,65 @@ void MESH_OT_solidify(wmOperatorType *ot)
 	RNA_def_property_ui_range(prop, -10, 10, 0.1, 4);
 }
 
+static int shape_key_commit_to_another_poll(bContext *C)
+{
+	Object *obedit = CTX_data_edit_object(C);
+	Key *key = BKE_key_from_object(obedit);
+	return (ED_operator_editmesh(C) && key && BLI_countlist(&key->block) > 1);
+}
+
+static int shape_key_commit_to_another_exec(bContext *C, wmOperator *op)
+{
+
+	Object *obedit = CTX_data_edit_object(C);
+
+	Mesh *_debugme = obedit->data;
+	Key *k = BKE_key_from_object(obedit);
+	BMEditMesh *em = BKE_editmesh_from_object(obedit);
+	KeyBlock *act_kb = BKE_keyblock_from_object(obedit);
+	int tgt_shape_idx = RNA_enum_get(op->ptr, "shape");
+	int totkey = BLI_countlist(&k->block);
+	KeyBlock *tgt_kb = BLI_findlink(&k->block, tgt_shape_idx);
+	
+	if (tgt_shape_idx == obedit->shapenr - 1)
+		return OPERATOR_FINISHED;
+
+	BLI_assert(totkey > 1);
+
+	/* forbid if some of the sizes are different */
+	if (act_kb->totelem != tgt_kb->totelem || tgt_kb->totelem != em->bm->totvert || act_kb->totelem != em->bm->totvert) {
+		BKE_report(op->reports, RPT_ERROR, "Cannot commit to another shape - edit data topology has changed!");
+		return OPERATOR_CANCELLED;
+	}
+
+	/* don't really 'commit', just force switch to another shape without recalc --
+	 * will look all the same from the user side */
+	em->bm->shapenr = obedit->shapenr = tgt_shape_idx + 1;
+	EDBM_update_scratch_from_active(obedit);
+	EDBM_update_generic(em, false, false);
+
+	return OPERATOR_FINISHED;
+}
+
+void MESH_OT_shape_key_commit_to_another(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name = "Commit To Another Shape";
+	ot->idname = "OBJECT_OT_shape_key_commit_to_another";
+	ot->description = "Commit the edited shape into another shape. Resets the current shape.";
+
+	/* api callbacks */
+	ot->poll = shape_key_commit_to_another_poll;
+	ot->exec = shape_key_commit_to_another_exec;
+
+	/* flags */
+	ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+	PropertyRNA* prop = RNA_def_enum(ot->srna, "shape", DummyRNA_NULL_items, 0, "Shape", "Shape key to commit to");
+	RNA_def_enum_funcs(prop, shape_itemf);
+	RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
+}
+
 /* ******************************************************************** */
 /* Knife Subdivide Tool.  Subdivides edges intersected by a mouse trail
  * drawn by user.
@@ -2586,7 +2636,7 @@ static Base *mesh_separate_tagged(Main *bmain, Scene *scene, Base *base_old, BMe
 
 	BM_mesh_normals_update(bm_new);
 
-	BM_mesh_bm_to_me(bm_new, base_new->object->data, false);
+	BM_mesh_bm_to_me(bm_new, base_new->object->data, false, true);
 
 	BM_mesh_free(bm_new);
 	((Mesh *)base_new->object->data)->edit_btmesh = NULL;
@@ -2866,7 +2916,7 @@ static int edbm_separate_exec(bContext *C, wmOperator *op)
 					else                BLI_assert(0);
 
 					if (retval_iter) {
-						BM_mesh_bm_to_me(bm_old, me, false);
+						BM_mesh_bm_to_me(bm_old, me, false, true);
 
 						DAG_id_tag_update(&me->id, OB_RECALC_DATA);
 						WM_event_add_notifier(C, NC_GEOM | ND_DATA, me);
diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c
index ab6744a..ddd7fbb 100644
--- a/source/blender/editors/mesh/editmesh_utils.c
+++ b/source/blender/editors/mesh/editmesh_utils.c
@@ -393,7 +393,7 @@ void EDBM_mesh_load(Object *ob)
 	Mesh *me = ob->data;
 	BMesh *bm = me->edit_btmesh->bm;
 
-	BM_mesh_bm_to_me(bm, me, false);
+	BM_mesh_bm_to_me(bm, me, false, true);
 
 #ifdef USE_TESSFACE_DEFAULT
 	BKE_mesh_tessface_calc(me);
@@ -608,7 +608,7 @@ void EDBM_com

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list