[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [11444] trunk/blender/source/blender: Visual Keying refactor

Roland Hess rolandh at reed-witting.com
Tue Jul 31 15:37:59 CEST 2007


Revision: 11444
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=11444
Author:   harkyman
Date:     2007-07-31 15:37:59 +0200 (Tue, 31 Jul 2007)

Log Message:
-----------
Visual Keying refactor

This code was always kludgy and this clean it up a bit.

insertmatrixkey() has been properly renamed insertkey_float().

Matrix calculations have been excised from the interface code,
and placed in insertmatrixkey(), so that you can call it from
anywhere without preliminaries and the proper values are calced
based on the passed adr code.

By much request, several semi-bug reports and discussion with
production animators, visual keying is now used automatic
for objects and bones that have constraints that cause them
to ignore their Ipos (CopyLoc, TrackTo, etc.). In those cases,
visual keying is used instead of the normal Ipo insertion
method. This "auto" functionality is toggled from the 
"Use Visual Keying" button found along with "Needed" and
"Available" in the Edit Methods prefs.

Logic as to which constraints trigger visual keying on
which adrcodes can be tweaked in match_adr_constraint()
src/editipo.c

This has been tested by a couple of people, myself included,
but I may not have hit every constraint case, so evolutionary
feedback is welcome.

Modified Paths:
--------------
    trunk/blender/source/blender/blenkernel/BKE_global.h
    trunk/blender/source/blender/include/BSE_editipo.h
    trunk/blender/source/blender/src/editipo.c
    trunk/blender/source/blender/src/space.c

Modified: trunk/blender/source/blender/blenkernel/BKE_global.h
===================================================================
--- trunk/blender/source/blender/blenkernel/BKE_global.h	2007-07-31 12:36:03 UTC (rev 11443)
+++ trunk/blender/source/blender/blenkernel/BKE_global.h	2007-07-31 13:37:59 UTC (rev 11444)
@@ -191,6 +191,8 @@
 #define G_DRAWSHARP     (1 << 28) /* draw edges with the sharp flag */
 #define G_SCULPTMODE    (1 << 29)
 
+#define G_AUTOMATKEYS	(1 << 30)
+
 /* G.fileflags */
 
 #define G_AUTOPACK               (1 << 0)

Modified: trunk/blender/source/blender/include/BSE_editipo.h
===================================================================
--- trunk/blender/source/blender/include/BSE_editipo.h	2007-07-31 12:36:03 UTC (rev 11443)
+++ trunk/blender/source/blender/include/BSE_editipo.h	2007-07-31 13:37:59 UTC (rev 11444)
@@ -158,8 +158,8 @@
 void borderselect_ipo_key(struct Ipo *ipo, float xmin, float xmax, int val);
 void borderselect_icu_key(struct IpoCurve *icu, float xmin, float xmax, 
 						  int (*select_function)(struct BezTriple *));
-void insertmatrixkey(ID *id, int blocktype, char *actname, char *constname, int adrcode, float matrixvalue);
-
+int insertmatrixkey(ID *id, int blocktype, char *actname, char *constname, int adrcode);
+void insertfloatkey(ID *id, int blocktype, char *actname, char *constname, int adrcode, float floatkey);
 void select_ipo_key(struct Ipo *ipo, float selx, int sel);
 void select_icu_key(struct IpoCurve *icu, float selx, int selectmode);
 void setexprap_ipoloop(struct Ipo *ipo, int code);

Modified: trunk/blender/source/blender/src/editipo.c
===================================================================
--- trunk/blender/source/blender/src/editipo.c	2007-07-31 12:36:03 UTC (rev 11443)
+++ trunk/blender/source/blender/src/editipo.c	2007-07-31 13:37:59 UTC (rev 11444)
@@ -20,7 +20,8 @@
  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
  * All rights reserved.
  *
- * Contributor(s): Blender Foundation, 2005. Full recode
+ * Contributor(s): Blender Foundation, 2005. Full recode.
+ * Roland Hess, 2007. Visual Key refactor.
  *
  * ***** END GPL LICENSE BLOCK *****
  */
@@ -2154,42 +2155,271 @@
 		return KEYNEEDED_JUSTADD;
 }
 
-void insertkey(ID *id, int blocktype, char *actname, char *constname, int adrcode)
+/* a duplicate of insertkey that does not check for routing to insertmatrixkey 
+	to avoid recursion problems */
+static void insertkey_nonrecurs(ID *id, int blocktype, char *actname, char *constname, int adrcode)
 {
 	IpoCurve *icu;
 	Object *ob;
 	void *poin= NULL;
 	float curval, cfra;
 	int vartype;
+	int matset=0;
 	
-	icu= verify_ipocurve(id, blocktype, actname, constname, adrcode);
+	if (matset==0) {
+		icu= verify_ipocurve(id, blocktype, actname, constname, adrcode);
+		
+		if(icu) {
+			
+			poin= get_context_ipo_poin(id, blocktype, actname, icu, &vartype);
+			
+			if(poin) {
+				curval= read_ipo_poin(poin, vartype);
+				
+				cfra= frame_to_float(CFRA);
+				
+				/* if action is mapped in NLA, it returns a correction */
+				if(actname && actname[0] && GS(id->name)==ID_OB)
+					cfra= get_action_frame((Object *)id, cfra);
+				
+				if( GS(id->name)==ID_OB ) {
+					ob= (Object *)id;
+					if(ob->sf!=0.0 && (ob->ipoflag & OB_OFFS_OB) ) {
+						/* actually frametofloat calc again! */
+						cfra-= ob->sf*G.scene->r.framelen;
+					}
+				}
+				
+				insert_vert_ipo(icu, cfra, curval);
+			}
+		}
+	}
+}
+
+int insertmatrixkey(ID *id, int blocktype, char *actname, char *constname, int adrcode)
+{
+	int matindex=0;
+	/* branch on adrcode and blocktype, generating the proper matrix-based
+	values to send to insertfloatkey */
+	if (GS(id->name)==ID_OB) {
+		Object *ob= (Object *)id;
+
+		if ( blocktype==ID_OB ){ //working with an object
+			if ((ob)&&!(ob->parent)) {
+				if ((adrcode==OB_ROT_X)||(adrcode==OB_ROT_Y)||(adrcode==OB_ROT_Z)) { //get a rotation
+					switch (adrcode) {
+						case OB_ROT_X:
+							matindex=0;
+							break;
+						case OB_ROT_Y:
+							matindex=1;
+							break;
+						case OB_ROT_Z:
+							matindex=2;
+							break;
+					}
+					float eul[3];
+					Mat4ToEul(ob->obmat, eul);
+					insertfloatkey(id, ID_OB, actname, NULL, adrcode, eul[matindex]*(5.72958));
+					return 1;
+				} else if ((adrcode==OB_LOC_X)||(adrcode==OB_LOC_Y)||(adrcode==OB_LOC_Z)) {//get a translation
+					switch (adrcode) {
+						case OB_LOC_X:
+							matindex=0;
+							break;
+						case OB_LOC_Y:
+							matindex=1;
+							break;
+						case OB_LOC_Z:
+							matindex=2;
+							break;
+					}
+					insertfloatkey(id, ID_OB, actname, NULL, adrcode, ob->obmat[3][matindex]);
+					return 1;
+				}
+			}
+		} else if ( blocktype==ID_PO) { //working with a pose channel
+			bPoseChannel *pchan= get_pose_channel(ob->pose, actname);
+			if (pchan) {
+				if ((adrcode==AC_LOC_X)||(adrcode==AC_LOC_Y)||(adrcode==AC_LOC_Z)) {
+					switch (adrcode) {
+						case AC_LOC_X:
+							matindex=0;
+							break;
+						case AC_LOC_Y:
+							matindex=1;
+							break;
+						case AC_LOC_Z:
+							matindex=2;
+							break;
+					}
+					if (!(pchan->bone->parent)||((pchan->bone->parent)&&!(pchan->bone->flag&BONE_CONNECTED))) { /* don't use for non-connected child bones */
+						float delta_mat[4][4]; 
+						armature_mat_pose_to_delta(delta_mat, pchan->pose_mat, pchan->bone->arm_mat);
+						insertfloatkey(id, ID_PO, pchan->name, NULL, adrcode, delta_mat[3][matindex]);
+						return 1;
+					}
+				} else if ((adrcode==AC_QUAT_W)||(adrcode==AC_QUAT_X)||(adrcode==AC_QUAT_Y)||(adrcode==AC_QUAT_Z)) { 
+					switch (adrcode) {
+						case AC_QUAT_W:
+							matindex=0;
+							break;
+						case AC_QUAT_X:
+							matindex=1;
+							break;
+						case AC_QUAT_Y:
+							matindex=2;
+							break;
+						case AC_QUAT_Z:
+							matindex=3;
+							break;
+					}
+					if (!(pchan->bone->parent)||((pchan->bone->parent)&&!(pchan->bone->flag&BONE_HINGE))) {  /* don't use for non-hinged child bones */
+						float delta_mat[4][4],trimat[3][3];
+						float localQuat[4];
+						armature_mat_pose_to_delta(delta_mat, pchan->pose_mat, pchan->bone->arm_mat);
+						/* Fixed this bit up from the old "hacky" version, as it was called.
+							Not sure of the origin of Mat3ToQuat_is_ok or why its in there. In most cases, this
+							produces the same result of the "hacky" version, and in some
+							cases the results seem to be better. But whatever the case, this is unideal, as
+							we're decomposing a 3x3 rotation matrix into a quat, which is
+							not a discrete operation.											*/
+						Mat3CpyMat4(trimat, delta_mat);
+						Mat3ToQuat_is_ok(trimat, localQuat);
+						insertfloatkey(id, ID_PO, pchan->name, NULL, adrcode, localQuat[matindex]);
+						return 1;
+					}
+				}
+			}
+		}
+	}
+	/* failed to set a matrix key -- use traditional, but the non-recursing version */
+	insertkey_nonrecurs(id,blocktype,actname,constname,adrcode);
+	return 0;
+}
+
+static int match_adr_constraint(ID * id, int blocktype, char *actname, int adrcode)
+{	/* This function matches constraint blocks with adrcodes to see if the
+		visual keying method should be used. For example, an object looking to key
+		location and having a CopyLoc constraint would return true. */
+		
+	Object *ob=NULL;
+	int foundmatch=0;
+	int searchtype=0;
+	bConstraint *conref=NULL, *con=NULL;
 	
-	if(icu) {
+	/*Retrieve constraint list*/
+	if( GS(id->name)==ID_OB ) 
+		ob= (Object *)id;
+	if (ob) {
+		if (blocktype==ID_PO) {
+			bPoseChannel *pchan= get_pose_channel(ob->pose, actname);
+			conref=pchan->constraints.first;
+		} else if (blocktype==ID_OB) {
+			conref=ob->constraints.first;
+		}
 		
-		poin= get_context_ipo_poin(id, blocktype, actname, icu, &vartype);
+		if (conref) {
+			/*Set search type: 1 is for translation contraints, 2 is for rotation*/
+			if ((adrcode==OB_LOC_X)||(adrcode==OB_LOC_Y)||(adrcode==OB_LOC_Z)||(adrcode==AC_LOC_X)||(adrcode==AC_LOC_Y)||(adrcode==AC_LOC_Z)) {
+				searchtype=1;
+			} else if ((adrcode==OB_ROT_X)||(adrcode==OB_ROT_Y)||(adrcode==OB_ROT_Z)||(adrcode==AC_QUAT_W)||(adrcode==AC_QUAT_X)||(adrcode==AC_QUAT_Y)||(adrcode==AC_QUAT_Z)) {
+				searchtype=2;
+			}
+			
+			if (searchtype>0) {
+				for (con=conref; (con)&&(foundmatch==0); con=con->next) {
+					switch (con->type) {
+					/* match constraint types to which kinds of keying they would affect */
+						case CONSTRAINT_TYPE_CHILDOF:
+							foundmatch=1;
+							break;
+						case CONSTRAINT_TYPE_TRACKTO:
+							if (searchtype==2) foundmatch=1;
+							break;
+						case CONSTRAINT_TYPE_FOLLOWPATH:
+							foundmatch=1;
+							break;
+						case CONSTRAINT_TYPE_ROTLIMIT:
+							if (searchtype==2) foundmatch=1;
+							break;
+						case CONSTRAINT_TYPE_LOCLIMIT:
+							if (searchtype==1) foundmatch=1;
+							break;
+						case CONSTRAINT_TYPE_ROTLIKE:
+							if (searchtype==2) foundmatch=1;
+							break;
+						case CONSTRAINT_TYPE_LOCLIKE:
+							if (searchtype==1) foundmatch=1;
+							break;
+						case CONSTRAINT_TYPE_LOCKTRACK:
+							if (searchtype==2) foundmatch=1;
+							break;
+						case CONSTRAINT_TYPE_DISTANCELIMIT:
+							if (searchtype==1) foundmatch=1;
+							break;
+						case CONSTRAINT_TYPE_MINMAX:
+							if (searchtype==1) foundmatch=1;
+							break;
+						case CONSTRAINT_TYPE_TRANSFORM:
+							foundmatch=1;
+							break;
+						default:
+							break;
+					}
+				}
+			}
+		}
+	}
+	
+	return foundmatch;
+			
+}
+
+void insertkey(ID *id, int blocktype, char *actname, char *constname, int adrcode)
+{
+	IpoCurve *icu;
+	Object *ob;
+	void *poin= NULL;
+	float curval, cfra;
+	int vartype;
+	int matset=0;
+	
+	if ((G.flags&G_AUTOMATKEYS)&&(match_adr_constraint(id, blocktype, actname, adrcode))) {
+		matset=insertmatrixkey(id, blocktype, actname, constname, adrcode);
+	} 
+	if (matset==0) {
+		icu= verify_ipocurve(id, blocktype, actname, constname, adrcode);
 		
-		if(poin) {
-			curval= read_ipo_poin(poin, vartype);
+		if(icu) {
 			
-			cfra= frame_to_float(CFRA);
+			poin= get_context_ipo_poin(id, blocktype, actname, icu, &vartype);
 			
-			/* if action is mapped in NLA, it returns a correction */
-			if(actname && actname[0] && GS(id->name)==ID_OB)
-				cfra= get_action_frame((Object *)id, cfra);
-			
-			if( GS(id->name)==ID_OB ) {
-				ob= (Object *)id;
-				if(ob->sf!=0.0 && (ob->ipoflag & OB_OFFS_OB) ) {
-					/* actually frametofloat calc again! */
-					cfra-= ob->sf*G.scene->r.framelen;
+			if(poin) {
+				curval= read_ipo_poin(poin, vartype);
+				

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list