Finding the active strip in tweak mode (or NLA edit mode)

Hello all,

I’m working on adding some UI features to the animation system that will make the relationship between the action clip and the action strip in the NLA system a little more intuitive. One of the things I’ve done is add a green box to the action editor and the curve editor that shows the bounds of the action strip being edited while in tweak mode. I think this makes it a lot easier to understand what editing the start and end points of the action strip and action clip change.


I’ve got it working (if not tested extensively) but I feel like there must be a better way of finding the active action strip.

For example in the file space_graph.c:

  • I use animationcontext.scene flags to test if nla editing is on
  • then use ANIM_animdata_filter() to get a list of bAnimListElem from the animation context
  • then I iterate over these looking for one that has the “actstrip” pointer set

Anybody know a more direct way of getting the active action strip? Any pitfalls I’m missing?

Thanks - Andrew

	NlaStrip * actstrip = NULL;
	
	if (ANIM_animdata_get_context(C, &ac)) {
		
		
		/* draw bounds of active NLA strip in the graph editor when in tweak mode
		 * All of this is just to 1) test if we are in tweak mode (aka NLA edit mode) and
		 * 2) to retrieve the active strip.
		 * TODO: IS THERE A BETTER WAY TO GET THE ACTIVE STRIP?
		 */
		
		/* are we in tweak mode? */
		if (ac.scene->flag & SCE_NLA_EDIT_ON)
		{
			ListBase anim_data = {NULL, NULL};
			bAnimListElem *ale;
			
			/* get a list of the AnimData blocks being shown in the NLA */
			int filter;
			filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_ANIMDATA);
			ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
			
			/* iterate through the animation data list elements looking for one that has an active strip */
			for (ale=anim_data.first; ale; ale=ale->next) 
			{
				AnimData *adt= ANIM_nla_mapping_get(&ac, ale);
				if (!ELEM(NULL, adt, adt->actstrip))
				{
					actstrip = adt->actstrip;
					glColor4f(0.0f, 1.0f, 0.0f, 0.2f);
					graph_draw_action_strip_bounds(actstrip, v2d);
					break; /* there will be one for each active channel; only need one so break after first one */
				}

			}
		}
					
		/* draw ghost curves */
		graph_draw_ghost_curves(&ac, sipo, ar);
		
		/* draw curves twice - unselected, then selected, so that the are fewer occlusion problems */
		graph_draw_curves(&ac, sipo, ar, grid, 0);
		graph_draw_curves(&ac, sipo, ar, grid, 1);
		
		/* XXX the slow way to set tot rect... but for nice sliders needed (ton) */
		get_graph_keyframe_extents(&ac, &v2d->tot.xmin, &v2d->tot.xmax, &v2d->tot.ymin, &v2d->tot.ymax, FALSE);
		/* extra offset so that these items are visible */
		v2d->tot.xmin -= 10.0f;
		v2d->tot.xmax += 10.0f;
	}

Hi,

Interesting idea.

In the grander scheme of things, especially taking into account a bug report such as http://projects.blender.org/tracker/index.php?func=detail&aid=28468&group_id=9&atid=498, this approach will probably be the most flexible and adaptable way.

If you’re really worried about speed and optimising for a common case, then simply checking the active object’s animdata for an active strip should be sufficient. However, this is probably not that ideal, since it excludes the majority of other places where NLA can be used, and practically starts favouring armatures exclusively again.

Just a quick notes about the code you’ve got:

  1. AnimData *adt= …;

You can really just get away with doing
AnimData *adt = ale->adt; // or perhaps even: AnimData adt = (AnimData)ale->data;

  1. Beware the memory leak. anim_data needs to be freed after the loop :wink:

Aligorith