[Bf-blender-cvs] [1b8a785] master: Armature: add armature dissolve

Campbell Barton noreply at git.blender.org
Fri Jun 12 19:24:40 CEST 2015


Commit: 1b8a785d83c85c2b9d605985c377191663ea13fb
Author: Campbell Barton
Date:   Sat Jun 13 03:20:07 2015 +1000
Branches: master
https://developer.blender.org/rB1b8a785d83c85c2b9d605985c377191663ea13fb

Armature: add armature dissolve

Works like mesh dissolve (access from delete or Ctrl+X)

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

M	release/scripts/startup/bl_ui/space_view3d.py
M	source/blender/blenkernel/BKE_action.h
M	source/blender/blenkernel/intern/action.c
M	source/blender/editors/armature/armature_edit.c
M	source/blender/editors/armature/armature_intern.h
M	source/blender/editors/armature/armature_ops.c
M	source/blender/editors/armature/armature_utils.c

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

diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index 43859a3..830c70e 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -2789,6 +2789,20 @@ class VIEW3D_MT_edit_armature_roll(Menu):
 
         layout.operator("transform.transform", text="Set Roll").mode = 'BONE_ROLL'
 
+
+class VIEW3D_MT_edit_armature_delete(Menu):
+    bl_label = "Delete"
+
+    def draw(self, context):
+        layout = self.layout
+
+        layout.operator("armature.delete", text="Delete Bones")
+
+        layout.separator()
+
+        layout.operator("armature.dissolve", text="Dissolve")
+
+
 # ********** Panel **********
 
 
diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h
index fdb465f..3fceef5 100644
--- a/source/blender/blenkernel/BKE_action.h
+++ b/source/blender/blenkernel/BKE_action.h
@@ -140,6 +140,10 @@ void                 BKE_pose_channels_free_ex(struct bPose *pose, bool do_id_us
 void                 BKE_pose_channels_hash_make(struct bPose *pose);
 void                 BKE_pose_channels_hash_free(struct bPose *pose);
 
+void BKE_pose_channels_remove(
+        struct Object *ob,
+        bool (*filter_fn)(const char *bone_name, void *user_data), void *user_data);
+
 void                 BKE_pose_free(struct bPose *pose);
 void                 BKE_pose_free_ex(struct bPose *pose, bool do_id_user);
 void                 BKE_pose_copy_data(struct bPose **dst, struct bPose *src, const bool copy_constraints);
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index 7e09ad3..1b73978 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -717,6 +717,57 @@ void BKE_pose_channels_hash_free(bPose *pose)
 }
 
 /**
+ * Selectively remove pose channels.
+ */
+void BKE_pose_channels_remove(
+        Object *ob,
+        bool (*filter_fn)(const char *bone_name, void *user_data), void *user_data)
+{
+	/*  First erase any associated pose channel */
+	if (ob->pose) {
+		bPoseChannel *pchan, *pchan_next;
+		bConstraint *con;
+
+		for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan_next) {
+			pchan_next = pchan->next;
+
+			if (filter_fn(pchan->name, user_data)) {
+				BKE_pose_channel_free(pchan);
+				if (ob->pose->chanhash) {
+					BLI_ghash_remove(ob->pose->chanhash, pchan->name, NULL, NULL);
+				}
+				BLI_freelinkN(&ob->pose->chanbase, pchan);
+			}
+			else {
+				for (con = pchan->constraints.first; con; con = con->next) {
+					const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
+					ListBase targets = {NULL, NULL};
+					bConstraintTarget *ct;
+
+					if (cti && cti->get_constraint_targets) {
+						cti->get_constraint_targets(con, &targets);
+
+						for (ct = targets.first; ct; ct = ct->next) {
+							if (ct->tar == ob) {
+								if (ct->subtarget[0]) {
+									if (filter_fn(ct->subtarget, user_data)) {
+										con->flag |= CONSTRAINT_DISABLE;
+										ct->subtarget[0] = 0;
+									}
+								}
+							}
+						}
+
+						if (cti->flush_constraint_targets)
+							cti->flush_constraint_targets(con, &targets, 0);
+					}
+				}
+			}
+		}
+	}
+}
+
+/**
  * Deallocates a pose channel.
  * Does not free the pose channel itself.
  */
diff --git a/source/blender/editors/armature/armature_edit.c b/source/blender/editors/armature/armature_edit.c
index d4df777..b3297db 100644
--- a/source/blender/editors/armature/armature_edit.c
+++ b/source/blender/editors/armature/armature_edit.c
@@ -42,6 +42,7 @@
 
 #include "BLI_blenlib.h"
 #include "BLI_math.h"
+#include "BLI_ghash.h"
 
 #include "BKE_action.h"
 #include "BKE_armature.h"
@@ -1233,13 +1234,21 @@ void ARMATURE_OT_split(wmOperatorType *ot)
 
 /* ********************************* Delete ******************************* */
 
+static bool armature_delete_ebone_cb(const char *bone_name, void *arm_p)
+{
+	bArmature *arm = arm_p;
+	EditBone *ebone;
+
+	ebone = ED_armature_bone_find_name(arm->edbo, bone_name);
+	return (ebone && (ebone->flag & BONE_SELECTED) && (arm->layer & ebone->layer));
+}
+
 /* previously delete_armature */
 /* only editmode! */
 static int armature_delete_selected_exec(bContext *C, wmOperator *UNUSED(op))
 {
 	bArmature *arm;
 	EditBone *curBone, *ebone_next;
-	bConstraint *con;
 	Object *obedit = CTX_data_edit_object(C); // XXX get from context
 	bool changed = false;
 	arm = obedit->data;
@@ -1250,48 +1259,8 @@ static int armature_delete_selected_exec(bContext *C, wmOperator *UNUSED(op))
 	
 	armature_select_mirrored(arm);
 	
-	/*  First erase any associated pose channel */
-	if (obedit->pose) {
-		bPoseChannel *pchan, *pchan_next;
-		for (pchan = obedit->pose->chanbase.first; pchan; pchan = pchan_next) {
-			pchan_next = pchan->next;
-			curBone = ED_armature_bone_find_name(arm->edbo, pchan->name);
-			
-			if (curBone && (curBone->flag & BONE_SELECTED) && (arm->layer & curBone->layer)) {
-				BKE_pose_channel_free(pchan);
-				BKE_pose_channels_hash_free(obedit->pose);
-				BLI_freelinkN(&obedit->pose->chanbase, pchan);
-			}
-			else {
-				for (con = pchan->constraints.first; con; con = con->next) {
-					const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
-					ListBase targets = {NULL, NULL};
-					bConstraintTarget *ct;
-					
-					if (cti && cti->get_constraint_targets) {
-						cti->get_constraint_targets(con, &targets);
-						
-						for (ct = targets.first; ct; ct = ct->next) {
-							if (ct->tar == obedit) {
-								if (ct->subtarget[0]) {
-									curBone = ED_armature_bone_find_name(arm->edbo, ct->subtarget);
-									if (curBone && (curBone->flag & BONE_SELECTED) && (arm->layer & curBone->layer)) {
-										con->flag |= CONSTRAINT_DISABLE;
-										ct->subtarget[0] = 0;
-									}
-								}
-							}
-						}
-						
-						if (cti->flush_constraint_targets)
-							cti->flush_constraint_targets(con, &targets, 0);
-					}
-				}
-			}
-		}
-	}
-	
-	
+	BKE_pose_channels_remove(obedit, armature_delete_ebone_cb, arm);
+
 	for (curBone = arm->edbo->first; curBone; curBone = ebone_next) {
 		ebone_next = curBone->next;
 		if (arm->layer & curBone->layer) {
@@ -1329,6 +1298,170 @@ void ARMATURE_OT_delete(wmOperatorType *ot)
 	ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
 
+static bool armature_dissolve_ebone_cb(const char *bone_name, void *arm_p)
+{
+	bArmature *arm = arm_p;
+	EditBone *ebone;
+
+	ebone = ED_armature_bone_find_name(arm->edbo, bone_name);
+	return (ebone && (ebone->flag & BONE_DONE));
+}
+
+static int armature_dissolve_selected_exec(bContext *C, wmOperator *UNUSED(op))
+{
+	bArmature *arm;
+	EditBone *ebone, *ebone_next;
+	Object *obedit = CTX_data_edit_object(C);
+	bool changed = false;
+
+	/* store for mirror */
+	GHash *ebone_flag_orig = NULL;
+	int ebone_num = 0;
+
+	arm = obedit->data;
+
+	for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+		ebone->temp.p = NULL;
+		ebone->flag &= ~BONE_DONE;
+		ebone_num++;
+	}
+
+	if (arm->flag & ARM_MIRROR_EDIT) {
+		GHashIterator gh_iter;
+
+		ebone_flag_orig = BLI_ghash_ptr_new_ex(__func__, ebone_num);
+		for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+			union { int flag; void *p; } val = {0};
+			val.flag = ebone->flag;
+			BLI_ghash_insert(ebone_flag_orig, ebone, val.p);
+		}
+
+		armature_select_mirrored_ex(arm, BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL);
+
+		GHASH_ITER (gh_iter, ebone_flag_orig) {
+			union { int flag; void *p; } *val_p = (void *)BLI_ghashIterator_getValue_p(&gh_iter);
+			ebone = BLI_ghashIterator_getKey(&gh_iter);
+			val_p->flag = ebone->flag & ~val_p->flag;
+		}
+	}
+
+	for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+		if (ebone->parent && ebone->flag & BONE_CONNECTED) {
+			if (ebone->parent->temp.ebone == ebone->parent) {
+				/* ignore */
+			}
+			else if (ebone->parent->temp.ebone) {
+				/* set ignored */
+				ebone->parent->temp.ebone = ebone->parent;
+			}
+			else {
+				/* set child */
+				ebone->parent->temp.ebone = ebone;
+			}
+		}
+	}
+
+	/* cleanup multiple used bones */
+	for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+		if (ebone->temp.ebone == ebone) {
+			ebone->temp.ebone = NULL;
+		}
+	}
+
+	for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+		/* break connections for unseen bones */
+		if (((arm->layer & ebone->layer) &&
+		     ((ED_armature_ebone_selectflag_get(ebone) & (BONE_TIPSEL | BONE_SELECTED)))) == 0)
+		{
+			ebone->temp.ebone = NULL;
+		}
+
+		if (((arm->layer & ebone->layer) &&
+		    ((ED_armature_ebone_selectflag_get(ebone) & (BONE_ROOTSEL | BONE_SELECTED)))) == 0)
+		{
+			if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
+				ebone->parent->temp.ebone = NULL;
+			}
+
+		}
+	}
+
+	for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+
+		if (ebone->parent &&
+		    (ebone->parent->temp.ebone == ebone))
+		{
+			ebone->flag |= BONE_DONE;
+		}
+	}
+
+	BKE_pose_channels_remove(obedit, armature_dissolve_ebone_cb, arm);
+
+	for (ebone = arm->edbo->first; ebone; ebone = ebone_next) {
+		ebone_next = ebone->next;
+
+		if (ebone->flag & BONE_DONE) {
+			copy_v3_v3(ebone->parent->tail, ebone->tail);
+			ebone->parent->rad_tail = ebone->rad_tail;
+
+			ED_armature_edit_bone_remove(arm, ebone);
+			changed = true;
+		}
+	}
+
+	if (changed) {
+		for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+			if (ebone->parent &&
+			    ebone->parent->temp.ebone &&
+			    (ebone->flag & BONE_CONNECTED) == 0)
+			{
+				ebone->flag |= BONE_CONNECTED;
+				ebone->rad_head = ebone->parent->rad_head;
+			}
+		}
+
+		if (arm->flag & ARM_MIRROR_EDIT) {
+			for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
+				union { int flag; void *p; } *val_p = (void *)BLI_ghash_lookup_p(ebone_flag_orig, ebone);
+				if (val_p && val_p->flag) {
+					ebone->flag &= ~val_p->flag;
+				}
+			}
+		}
+	}
+
+	if (arm->flag & ARM_MIRROR_EDIT) {
+		BLI_ghash_free(ebone_flag_orig, NULL, NULL);
+	}
+
+	if (!changed) {
+		return OPERATOR_CANCELLED;
+	}
+
+	ED_armature_sync_selection(arm->edbo);
+
+	WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
+
+	return OPERATOR_FINISHED;
+}
+
+void ARM

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list