示例#1
0
void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *ar)
{
  View2D *v2d = &ar->v2d;
  const float pixelx = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask);
  const float text_margin_x = (8 * UI_DPI_FAC) * pixelx;

  /* build list of channels to draw */
  ListBase anim_data = {NULL, NULL};
  int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
  size_t items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);

  /* Update max-extent of channels here (taking into account scrollers):
   * - this is done to allow the channel list to be scrollable, but must be done here
   *   to avoid regenerating the list again and/or also because channels list is drawn first
   * - offset of NLACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for
   *   start of list offset, and the second is as a correction for the scrollers.
   */
  int height = NLACHANNEL_TOT_HEIGHT(ac, items);
  v2d->tot.ymin = -height;

  /* loop through channels, and set up drawing depending on their type  */
  float ymax = NLACHANNEL_FIRST_TOP(ac);

  for (bAnimListElem *ale = anim_data.first; ale; ale = ale->next, ymax -= NLACHANNEL_STEP(snla)) {
    float ymin = ymax - NLACHANNEL_HEIGHT(snla);
    float ycenter = (ymax + ymin) / 2.0f;

    /* check if visible */
    if (IN_RANGE(ymin, v2d->cur.ymin, v2d->cur.ymax) ||
        IN_RANGE(ymax, v2d->cur.ymin, v2d->cur.ymax)) {
      /* data to draw depends on the type of channel */
      switch (ale->type) {
        case ANIMTYPE_NLATRACK: {
          AnimData *adt = ale->adt;
          NlaTrack *nlt = (NlaTrack *)ale->data;
          NlaStrip *strip;
          int index;

          /* draw each strip in the track (if visible) */
          for (strip = nlt->strips.first, index = 1; strip; strip = strip->next, index++) {
            if (BKE_nlastrip_within_bounds(strip, v2d->cur.xmin, v2d->cur.xmax)) {
              const float xminc = strip->start + text_margin_x;
              const float xmaxc = strip->end + text_margin_x;

              /* draw the visualization of the strip */
              nla_draw_strip(snla, adt, nlt, strip, v2d, ymin, ymax);

              /* add the text for this strip to the cache */
              if (xminc < xmaxc) {
                nla_draw_strip_text(adt, nlt, strip, index, v2d, xminc, xmaxc, ymin, ymax);
              }

              /* if transforming strips (only real reason for temp-metas currently),
               * add to the cache the frame numbers of the strip's extents
               */
              if (strip->flag & NLASTRIP_FLAG_TEMP_META) {
                nla_draw_strip_frames_text(nlt, strip, v2d, ymin, ymax);
              }
            }
          }
          break;
        }
        case ANIMTYPE_NLAACTION: {
          AnimData *adt = ale->adt;

          uint pos = GPU_vertformat_attr_add(
              immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
          immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);

          /* just draw a semi-shaded rect spanning the width of the viewable area if there's data,
           * and a second darker rect within which we draw keyframe indicator dots if there's data
           */
          GPU_blend_set_func_separate(
              GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
          GPU_blend(true);

          /* get colors for drawing */
          float color[4];
          nla_action_get_color(adt, ale->data, color);
          immUniformColor4fv(color);

          /* draw slightly shifted up for greater separation from standard channels,
           * but also slightly shorter for some more contrast when viewing the strips
           */
          immRectf(
              pos, v2d->cur.xmin, ymin + NLACHANNEL_SKIP, v2d->cur.xmax, ymax - NLACHANNEL_SKIP);

          /* draw 'embossed' lines above and below the strip for effect */
          /* white base-lines */
          GPU_line_width(2.0f);
          immUniformColor4f(1.0f, 1.0f, 1.0f, 0.3f);
          immBegin(GPU_PRIM_LINES, 4);
          immVertex2f(pos, v2d->cur.xmin, ymin + NLACHANNEL_SKIP);
          immVertex2f(pos, v2d->cur.xmax, ymin + NLACHANNEL_SKIP);
          immVertex2f(pos, v2d->cur.xmin, ymax - NLACHANNEL_SKIP);
          immVertex2f(pos, v2d->cur.xmax, ymax - NLACHANNEL_SKIP);
          immEnd();

          /* black top-lines */
          GPU_line_width(1.0f);
          immUniformColor3f(0.0f, 0.0f, 0.0f);
          immBegin(GPU_PRIM_LINES, 4);
          immVertex2f(pos, v2d->cur.xmin, ymin + NLACHANNEL_SKIP);
          immVertex2f(pos, v2d->cur.xmax, ymin + NLACHANNEL_SKIP);
          immVertex2f(pos, v2d->cur.xmin, ymax - NLACHANNEL_SKIP);
          immVertex2f(pos, v2d->cur.xmax, ymax - NLACHANNEL_SKIP);
          immEnd();

          /* TODO: these lines but better --^ */

          immUnbindProgram();

          /* draw keyframes in the action */
          nla_action_draw_keyframes(
              v2d, adt, ale->data, ycenter, ymin + NLACHANNEL_SKIP, ymax - NLACHANNEL_SKIP);

          GPU_blend(false);
          break;
        }
      }
    }
  }

  /* free tempolary channels */
  ANIM_animdata_freelist(&anim_data);
}
示例#2
0
/* select strip directly under mouse */
static void mouse_nla_strips(bContext *C, bAnimContext *ac, const int mval[2], short select_mode)
{
	ListBase anim_data = {NULL, NULL};
	bAnimListElem *ale = NULL;
	int filter;
	
	SpaceNla *snla = (SpaceNla *)ac->sl;
	View2D *v2d = &ac->ar->v2d;
	Scene *scene = ac->scene;
	NlaStrip *strip = NULL;
	int channel_index;
	float xmin, xmax;
	float x, y;
	
	
	/* use View2D to determine the index of the channel (i.e a row in the list) where keyframe was */
	UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y);
	UI_view2d_listview_view_to_cell(v2d, 0, NLACHANNEL_STEP(snla), 0, (float)NLACHANNEL_HEIGHT_HALF(snla), x, y, NULL, &channel_index);
	
	/* x-range to check is +/- 7 (in screen/region-space) on either side of mouse click 
	 * (that is the size of keyframe icons, so user should be expecting similar tolerances) 
	 */
	xmin = UI_view2d_region_to_view_x(v2d, mval[0] - 7);
	xmax = UI_view2d_region_to_view_x(v2d, mval[0] + 7);
	
	/* filter data */
	filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
	ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
	
	/* try to get channel */
	ale = BLI_findlink(&anim_data, channel_index);
	if (ale == NULL) {
		/* channel not found */
		printf("Error: animation channel (index = %d) not found in mouse_nla_strips()\n", channel_index);
		ANIM_animdata_freelist(&anim_data);
		return;
	}
	else {
		/* found some channel - we only really should do somethign when its an Nla-Track */
		if (ale->type == ANIMTYPE_NLATRACK) {
			NlaTrack *nlt = (NlaTrack *)ale->data;
			
			/* loop over NLA-strips in this track, trying to find one which occurs in the necessary bounds */
			for (strip = nlt->strips.first; strip; strip = strip->next) {
				if (BKE_nlastrip_within_bounds(strip, xmin, xmax))
					break;
			}
		}
		
		/* remove active channel from list of channels for separate treatment (since it's needed later on) */
		BLI_remlink(&anim_data, ale);
		
		/* free list of channels, since it's not used anymore */
		ANIM_animdata_freelist(&anim_data);
	}
	
	/* if currently in tweakmode, exit tweakmode before changing selection states
	 * now that we've found our target...
	 */
	if (scene->flag & SCE_NLA_EDIT_ON)
		WM_operator_name_call(C, "NLA_OT_tweakmode_exit", WM_OP_EXEC_DEFAULT, NULL);
	
	/* for replacing selection, firstly need to clear existing selection */
	if (select_mode == SELECT_REPLACE) {
		/* reset selection mode for next steps */
		select_mode = SELECT_ADD;
		
		/* deselect all strips */
		deselect_nla_strips(ac, 0, SELECT_SUBTRACT);
		
		/* deselect all other channels first */
		ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
	}
	
	/* only select strip if we clicked on a valid channel and hit something */
	if (ale) {
		/* select the strip accordingly (if a matching one was found) */
		if (strip) {
			select_mode = selmodes_to_flagmodes(select_mode);
			ACHANNEL_SET_FLAG(strip, select_mode, NLASTRIP_FLAG_SELECT);
			
			/* if we selected it, we can make it active too
			 *	- we always need to clear the active strip flag though... 
			 *  - as well as selecting its track...
			 */
			deselect_nla_strips(ac, DESELECT_STRIPS_CLEARACTIVE, 0);
			
			if (strip->flag & NLASTRIP_FLAG_SELECT) {
				strip->flag |= NLASTRIP_FLAG_ACTIVE;
				
				/* Highlight NLA-Track */
				if (ale->type == ANIMTYPE_NLATRACK) {
					NlaTrack *nlt = (NlaTrack *)ale->data;
					
					nlt->flag |= NLATRACK_SELECTED;
					ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, nlt, ANIMTYPE_NLATRACK);
				}
			}
		}
		
		/* free this channel */
		MEM_freeN(ale);
	}
}