[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [38172] branches/soc-2011-pepper/source/ blender: Outliner RMB Menu - AnimData mangement

Joshua Leung aligorith at gmail.com
Thu Jul 7 05:35:48 CEST 2011


Revision: 38172
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=38172
Author:   aligorith
Date:     2011-07-07 03:35:48 +0000 (Thu, 07 Jul 2011)
Log Message:
-----------
Outliner RMB Menu - AnimData mangement

* When clicking on "Animation" items in the Outliner, there's now a
menu containing from which you can change the action used, and
refresh/delete all drivers.

* Moved action-setting logic for AnimData actions to a single utility
function in anim_sys, since this was starting to be done in too many
places already.

* Fixed Outliner refresh bug after changing the active action

Modified Paths:
--------------
    branches/soc-2011-pepper/source/blender/blenkernel/BKE_animsys.h
    branches/soc-2011-pepper/source/blender/blenkernel/intern/anim_sys.c
    branches/soc-2011-pepper/source/blender/editors/space_outliner/outliner.c
    branches/soc-2011-pepper/source/blender/editors/space_outliner/outliner_intern.h
    branches/soc-2011-pepper/source/blender/editors/space_outliner/outliner_ops.c
    branches/soc-2011-pepper/source/blender/editors/space_outliner/space_outliner.c
    branches/soc-2011-pepper/source/blender/makesrna/intern/rna_animation.c
    branches/soc-2011-pepper/source/blender/makesrna/intern/rna_nla.c

Modified: branches/soc-2011-pepper/source/blender/blenkernel/BKE_animsys.h
===================================================================
--- branches/soc-2011-pepper/source/blender/blenkernel/BKE_animsys.h	2011-07-07 00:59:48 UTC (rev 38171)
+++ branches/soc-2011-pepper/source/blender/blenkernel/BKE_animsys.h	2011-07-07 03:35:48 UTC (rev 38172)
@@ -41,6 +41,7 @@
 struct KS_Path;
 
 struct PointerRNA;
+struct ReportList;
 struct bAction;
 struct bActionGroup;
 struct AnimMapper;
@@ -57,6 +58,9 @@
 /* Add AnimData to the given ID-block */
 struct AnimData *BKE_id_add_animdata(struct ID *id);
 
+/* Set active action used by AnimData from the given ID-block */
+short BKE_animdata_set_action(struct ReportList *reports, struct ID *id, struct bAction *act);
+
 /* Free AnimData */
 void BKE_free_animdata(struct ID *id);
 

Modified: branches/soc-2011-pepper/source/blender/blenkernel/intern/anim_sys.c
===================================================================
--- branches/soc-2011-pepper/source/blender/blenkernel/intern/anim_sys.c	2011-07-07 00:59:48 UTC (rev 38171)
+++ branches/soc-2011-pepper/source/blender/blenkernel/intern/anim_sys.c	2011-07-07 03:35:48 UTC (rev 38172)
@@ -56,6 +56,7 @@
 #include "BKE_global.h"
 #include "BKE_main.h"
 #include "BKE_library.h"
+#include "BKE_report.h"
 #include "BKE_utildefines.h"
 
 #include "RNA_access.h"
@@ -144,6 +145,59 @@
 		return NULL;
 }
 
+/* Action Setter --------------------------------------- */
+
+/* Called when user tries to change the active action of an AnimData block (via RNA, Outliner, etc.) */
+short BKE_animdata_set_action (ReportList *reports, ID *id, bAction *act)
+{
+	AnimData *adt = BKE_animdata_from_id(id);
+	short ok = 0;
+	
+	/* animdata validity check */
+	if (adt == NULL) {
+		BKE_report(reports, RPT_WARNING, "No AnimData to set action on");
+		return ok;
+	}
+	
+	/* active action is only editable when it is not a tweaking strip 
+	 * see rna_AnimData_action_editable() in rna_animation.c
+	 */
+	if ((adt->flag & ADT_NLA_EDIT_ON) || (adt->actstrip) || (adt->tmpact)) {
+		/* cannot remove, otherwise things turn to custard */
+		BKE_report(reports, RPT_ERROR, "Cannot change action, as it is still being edited in NLA");
+		return ok;
+	}
+	
+	/* manage usercount for current action */
+	if (adt->action)
+		id_us_min((ID*)adt->action);
+	
+	/* assume that AnimData's action can in fact be edited... */
+	if (act) {
+		/* action must have same type as owner */
+		if (ELEM(act->idroot, 0, GS(id->name))) {
+			/* can set */
+			adt->action = act;
+			id_us_plus((ID*)adt->action);
+			ok = 1;
+		}
+		else {
+			/* cannot set */
+			BKE_reportf(reports, RPT_ERROR,
+					"Couldn't set Action '%s' onto ID '%s', as it doesn't have suitably rooted paths for this purpose", 
+					act->id.name+2, id->name);
+			//ok = 0;
+		}
+	}
+	else {
+		/* just clearing the action... */
+		adt->action = NULL;
+		ok = 1;
+	}
+	
+	return ok;
+}
+
 /* Freeing -------------------------------------------- */
 
 /* Free AnimData used by the nominated ID-block, and clear ID-block's AnimData pointer */

Modified: branches/soc-2011-pepper/source/blender/editors/space_outliner/outliner.c
===================================================================
--- branches/soc-2011-pepper/source/blender/editors/space_outliner/outliner.c	2011-07-07 00:59:48 UTC (rev 38171)
+++ branches/soc-2011-pepper/source/blender/editors/space_outliner/outliner.c	2011-07-07 03:35:48 UTC (rev 38172)
@@ -101,6 +101,7 @@
 
 #include "RNA_access.h"
 #include "RNA_define.h"
+#include "RNA_enum_types.h"
 
 #include "ED_keyframing.h"
 
@@ -3170,29 +3171,10 @@
 	}
 }
 
-static void unlink_action_cb(bContext *C, Scene *UNUSED(scene), TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *UNUSED(tselem))
+static void unlink_action_cb(bContext *C, Scene *UNUSED(scene), TreeElement *UNUSED(te), TreeStoreElem *tsep, TreeStoreElem *UNUSED(tselem))
 {
-	IdAdtTemplate *iat = (IdAdtTemplate *)tsep->id;
-	AnimData *adt = iat->adt;
-	
-	//printf("iat = '%s' | act = '%s'\n", iat->id.name, tselem->id->name);
-	
-	/* active action is only editable when it is not a tweaking strip 
-	 * see rna_AnimData_action_editable() in rna_animation.c
-	 */
-	if ((adt->flag & ADT_NLA_EDIT_ON) || (adt->actstrip) || (adt->tmpact)) {
-		/* cannot remove, otherwise things turn to custard */
-		ReportList *reports = CTX_wm_reports(C);
-		
-		// FIXME: this only gets shown in info-window, since this is global not operator report
-		BKE_report(reports, RPT_ERROR, "Cannot unlink action, as it is still being edited in NLA");
-		
-		return;
-	}
-	
-	/* remove action... */
-	id_us_min((ID*)adt->action);
-	adt->action = NULL;
+	/* just set action to NULL */
+	BKE_animdata_set_action(CTX_wm_reports(C), tsep->id, NULL);
 }
 
 static void unlink_material_cb(bContext *UNUSED(C), Scene *UNUSED(scene), TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *UNUSED(tselem))
@@ -3414,6 +3396,36 @@
 
 /* ******************************************** */
 
+static void unlinkact_animdata_cb(int UNUSED(event), TreeElement *UNUSED(te), TreeStoreElem *tselem)
+{
+	/* just set action to NULL */
+	BKE_animdata_set_action(NULL, tselem->id, NULL);
+}
+
+static void cleardrivers_animdata_cb(int UNUSED(event), TreeElement *UNUSED(te), TreeStoreElem *tselem)
+{
+	IdAdtTemplate *iat = (IdAdtTemplate *)tselem->id;
+	
+	/* just free drivers - stored as a list of F-Curves */
+	free_fcurves(&iat->adt->drivers);
+}
+
+static void refreshdrivers_animdata_cb(int UNUSED(event), TreeElement *UNUSED(te), TreeStoreElem *tselem)
+{
+	IdAdtTemplate *iat = (IdAdtTemplate *)tselem->id;
+	FCurve *fcu;
+	
+	/* loop over drivers, performing refresh (i.e. check graph_buttons.c and rna_fcurve.c for details) */
+	for (fcu = iat->adt->drivers.first; fcu; fcu= fcu->next) {
+		fcu->flag &= ~FCURVE_DISABLED;
+		
+		if (fcu->driver)
+			fcu->driver->flag &= ~DRIVER_FLAG_INVALID;
+	}
+}
+
+/* --------------------------------- */
+
 static void pchan_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tselem))
 {
 	bPoseChannel *pchan= (bPoseChannel *)te->directdata;
@@ -3775,6 +3787,224 @@
 
 /* **************************************** */
 
+static void outliner_do_id_set_operation(SpaceOops *soops, int type, ListBase *lb, ID *newid,
+										 void (*operation_cb)(TreeElement *, TreeStoreElem *, TreeStoreElem *, ID *))
+{
+	TreeElement *te;
+	TreeStoreElem *tselem;
+	
+	for (te=lb->first; te; te= te->next) {
+		tselem= TREESTORE(te);
+		if (tselem->flag & TSE_SELECTED) {
+			if(tselem->type==type) {
+				TreeStoreElem *tsep = TREESTORE(te->parent);
+				operation_cb(te, tselem, tsep, newid);
+			}
+		}
+		if ((tselem->flag & TSE_CLOSED)==0) {
+			outliner_do_id_set_operation(soops, type, &te->subtree, newid, operation_cb);
+		}
+	}
+}
+
+/* ------------------------------------------ */
+
+static void actionset_id_cb(TreeElement *te, TreeStoreElem *tselem, TreeStoreElem *tsep, ID *actId)
+{
+	bAction *act = (bAction *)actId;
+	
+	if (tselem->type == TSE_ANIM_DATA) {
+		/* "animation" entries - action is child of this */
+		BKE_animdata_set_action(NULL, tselem->id, act);
+	}
+	/* TODO: if any other "expander" channels which own actions need to support this menu, 
+	 * add: tselem->type = ...
+	 */
+	else if (tsep && (tsep->type == TSE_ANIM_DATA)) {
+		/* "animation" entries case again */
+		BKE_animdata_set_action(NULL, tsep->id, act);
+	}
+	// TODO: other cases not supported yet
+}
+
+static int outliner_action_set_exec(bContext *C, wmOperator *op)
+{
+	SpaceOops *soops= CTX_wm_space_outliner(C);
+	int scenelevel=0, objectlevel=0, idlevel=0, datalevel=0;
+	
+	bAction *act;
+	
+	/* check for invalid states */
+	if (soops == NULL)
+		return OPERATOR_CANCELLED;
+	set_operation_types(soops, &soops->tree, &scenelevel, &objectlevel, &idlevel, &datalevel);
+	
+	/* get action to use */
+	act= BLI_findlink(&CTX_data_main(C)->action, RNA_enum_get(op->ptr, "action"));
+	
+	if (act == NULL) {
+		BKE_report(op->reports, RPT_ERROR, "No valid Action to add.");
+		return OPERATOR_CANCELLED;
+	}
+	else if (act->idroot == 0) {
+		/* hopefully in this case (i.e. library of userless actions), the user knows what they're doing... */
+		BKE_reportf(op->reports, RPT_WARNING,
+			"Action '%s' does not specify what datablocks it can be used on. Try setting the 'ID Root Type' setting from the Datablocks Editor for this Action to avoid future problems",
+			act->id.name+2);
+	}
+	
+	/* perform action if valid channel */
+	if (datalevel == TSE_ANIM_DATA)
+		outliner_do_id_set_operation(soops, datalevel, &soops->tree, (ID*)act, actionset_id_cb);
+	else if (idlevel == ID_AC)
+		outliner_do_id_set_operation(soops, idlevel, &soops->tree, (ID*)act, actionset_id_cb);
+	else
+		return OPERATOR_CANCELLED;
+		
+	/* set notifier that things have changed */
+	WM_event_add_notifier(C, NC_ANIMATION|ND_NLA_ACTCHANGE, NULL);
+	ED_undo_push(C, "Set action");
+	
+	/* done */
+	return OPERATOR_FINISHED;
+}
+
+void OUTLINER_OT_action_set(wmOperatorType *ot)
+{
+	PropertyRNA *prop;
+
+	/* identifiers */
+	ot->name= "Outliner Set Action";
+	ot->idname= "OUTLINER_OT_action_set";
+	ot->description= "Change the active action used";
+	
+	/* api callbacks */
+	ot->invoke= WM_enum_search_invoke;
+	ot->exec= outliner_action_set_exec;
+	ot->poll= ED_operator_outliner_active;
+	
+	/* flags */
+	ot->flag= 0;
+	
+	/* props */
+		// TODO: this would be nicer as an ID-pointer...
+	prop= RNA_def_enum(ot->srna, "action", DummyRNA_NULL_items, 0, "Action", "");
+	RNA_def_enum_funcs(prop, RNA_action_itemf);
+	ot->prop= prop;
+}
+
+/* **************************************** */
+
+typedef enum eOutliner_AnimDataOps {
+	OUTLINER_ANIMOP_INVALID = 0,
+	
+	OUTLINER_ANIMOP_SET_ACT,
+	OUTLINER_ANIMOP_CLEAR_ACT,
+	
+	OUTLINER_ANIMOP_REFRESH_DRV,
+	OUTLINER_ANIMOP_CLEAR_DRV
+	
+	//OUTLINER_ANIMOP_COPY_DRIVERS,
+	//OUTLINER_ANIMOP_PASTE_DRIVERS
+} eOutliner_AnimDataOps;
+
+static EnumPropertyItem prop_animdata_op_types[] = {
+	{OUTLINER_ANIMOP_SET_ACT, "SET_ACT", 0, "Set Action", ""},
+	{OUTLINER_ANIMOP_CLEAR_ACT, "CLEAR_ACT", 0, "Unlink Action", ""},
+	{OUTLINER_ANIMOP_REFRESH_DRV, "REFRESH_DRIVERS", 0, "Refresh Drivers", ""},
+	//{OUTLINER_ANIMOP_COPY_DRIVERS, "COPY_DRIVERS", 0, "Copy Drivers", ""},
+	//{OUTLINER_ANIMOP_PASTE_DRIVERS, "PASTE_DRIVERS", 0, "Paste Drivers", ""},
+	{OUTLINER_ANIMOP_CLEAR_DRV, "CLEAR_DRIVERS", 0, "Clear Drivers", ""},
+	{0, NULL, 0, NULL, NULL}
+};
+
+static int outliner_animdata_operation_exec(bContext *C, wmOperator *op)
+{
+	SpaceOops *soops= CTX_wm_space_outliner(C);

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list