Пример #1
0
/* draw the keyframes in the specified Action */
static void nla_action_draw_keyframes(AnimData *adt, bAction *act, View2D *v2d, float y, float ymin, float ymax)
{
	DLRBT_Tree keys;
	ActKeyColumn *ak;
	float xscale, f1, f2;
	float color[4];
	
	/* get a list of the keyframes with NLA-scaling applied */
	BLI_dlrbTree_init(&keys);
	action_to_keylist(adt, act, &keys, NULL);
	BLI_dlrbTree_linkedlist_sync(&keys);
	
	if (ELEM(NULL, act, keys.first))
		return;
	
	/* draw a darkened region behind the strips 
	 *	- get and reset the background color, this time without the alpha to stand out better 
	 *	  (amplified alpha is used instead)
	 */
	nla_action_get_color(adt, act, color);
	color[3] *= 2.5f;
	
	glColor4fv(color);
	/*  - draw a rect from the first to the last frame (no extra overlaps for now)
	 *	  that is slightly stumpier than the track background (hardcoded 2-units here)
	 */
	f1 = ((ActKeyColumn *)keys.first)->cfra;
	f2 = ((ActKeyColumn *)keys.last)->cfra;
	
	glRectf(f1, ymin + 2, f2, ymax - 2);
	
	
	/* get View2D scaling factor */
	UI_view2d_scale_get(v2d, &xscale, NULL);
	
	/* for now, color is hardcoded to be black */
	glColor3f(0.0f, 0.0f, 0.0f);
	
	/* just draw each keyframe as a simple dot (regardless of the selection status) 
	 *	- size is 3.0f which is smaller than the editable keyframes, so that there is a distinction
	 */
	for (ak = keys.first; ak; ak = ak->next)
		draw_keyframe_shape(ak->cfra, y, xscale, 3.0f, 0, ak->key_type, KEYFRAME_SHAPE_FRAME, 1.0f);
	
	/* free icons */
	BLI_dlrbTree_free(&keys);
}
Пример #2
0
void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *ar)
{
	ListBase anim_data = {NULL, NULL};
	bAnimListElem *ale;
	int filter;
	
	View2D *v2d = &ar->v2d;
	float y = 0.0f;
	size_t items;
	int height;
	
	/* build list of channels to draw */
	filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
	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.
	 */
	height = ((items * NLACHANNEL_STEP(snla)) + (NLACHANNEL_HEIGHT(snla) * 2));
	/* don't use totrect set, as the width stays the same 
	 * (NOTE: this is ok here, the configuration is pretty straightforward) 
	 */
	v2d->tot.ymin = (float)(-height);
	
	/* loop through channels, and set up drawing depending on their type  */
	y = (float)(-NLACHANNEL_HEIGHT(snla));
	
	for (ale = anim_data.first; ale; ale = ale->next) {
		const float yminc = (float)(y - NLACHANNEL_HEIGHT_HALF(snla));
		const float ymaxc = (float)(y + NLACHANNEL_HEIGHT_HALF(snla));
		
		/* check if visible */
		if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
		    IN_RANGE(ymaxc, 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)) {
							/* draw the visualization of the strip */
							nla_draw_strip(snla, adt, nlt, strip, v2d, yminc, ymaxc);
							
							/* add the text for this strip to the cache */
							nla_draw_strip_text(adt, nlt, strip, index, v2d, yminc, ymaxc);
							
							/* 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, yminc, ymaxc);
						}
					}
					break;
				}
				case ANIMTYPE_NLAACTION:
				{
					AnimData *adt = ale->adt;
					float color[4];
					
					/* 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
					 */
					glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
					glEnable(GL_BLEND);
						
					/* get colors for drawing */
					nla_action_get_color(adt, ale->data, color);
					glColor4fv(color);
					
					/* draw slightly shifted up for greater separation from standard channels,
					 * but also slightly shorter for some more contrast when viewing the strips
					 */
					glRectf(v2d->cur.xmin, yminc + NLACHANNEL_SKIP, v2d->cur.xmax, ymaxc - NLACHANNEL_SKIP);
					
					/* draw keyframes in the action */
					nla_action_draw_keyframes(adt, ale->data, v2d, y, yminc + NLACHANNEL_SKIP, ymaxc - NLACHANNEL_SKIP);
					
					/* draw 'embossed' lines above and below the strip for effect */
					/* white base-lines */
					glLineWidth(2.0f);
					glColor4f(1.0f, 1.0f, 1.0f, 0.3);
					fdrawline(v2d->cur.xmin, yminc + NLACHANNEL_SKIP, v2d->cur.xmax, yminc + NLACHANNEL_SKIP);
					fdrawline(v2d->cur.xmin, ymaxc - NLACHANNEL_SKIP, v2d->cur.xmax, ymaxc - NLACHANNEL_SKIP);
					
					/* black top-lines */
					glLineWidth(1.0f);
					glColor3f(0.0f, 0.0f, 0.0f);
					fdrawline(v2d->cur.xmin, yminc + NLACHANNEL_SKIP, v2d->cur.xmax, yminc + NLACHANNEL_SKIP);
					fdrawline(v2d->cur.xmin, ymaxc - NLACHANNEL_SKIP, v2d->cur.xmax, ymaxc - NLACHANNEL_SKIP);
					
					glDisable(GL_BLEND);
					break;
				}
			}
		}
		
		/* adjust y-position for next one */
		y -= NLACHANNEL_STEP(snla);
	}
	
	/* free tempolary channels */
	ANIM_animdata_freelist(&anim_data);
}
Пример #3
0
// TODO: depreceate this code...
static void draw_nla_channel_list_gl(bAnimContext *ac, ListBase *anim_data, View2D *v2d, float y)
{
	SpaceNla *snla = (SpaceNla *)ac->sl;
	bAnimListElem *ale;
	float x = 0.0f;
	
	/* loop through channels, and set up drawing depending on their type  */
	for (ale = anim_data->first; ale; ale = ale->next) {
		const float yminc = (float)(y - NLACHANNEL_HEIGHT_HALF(snla));
		const float ymaxc = (float)(y + NLACHANNEL_HEIGHT_HALF(snla));
		const float ydatac = (float)(y - 0.35f * U.widget_unit);
		
		/* check if visible */
		if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
		    IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) )
		{
			AnimData *adt = ale->adt;
			
			short indent = 0, offset = 0, sel = 0, group = 0;
			int special = -1;
			char name[128];
			bool do_draw = false;
			
			/* determine what needs to be drawn */
			switch (ale->type) {
				case ANIMTYPE_NLAACTION: /* NLA Action-Line */
				{
					bAction *act = (bAction *)ale->data;
					
					group = 5;
					
					special = ICON_ACTION;
					
					BLI_strncpy(name, act ? act->id.name + 2 : "<No Action>", sizeof(name));

					/* draw manually still */
					do_draw = TRUE;
					break;
				}
				default: /* handled by standard channel-drawing API */
					/* (draw backdrops only...) */
					ANIM_channel_draw(ac, ale, yminc, ymaxc);
					break;
			}
			
			/* if special types, draw manually for now... */
			if (do_draw) {
				if (ale->id) {
					/* special exception for textures */
					if (GS(ale->id->name) == ID_TE) {
						offset = 0.7f * U.widget_unit;
						indent = 1;
					}
					/* special exception for nodetrees */
					else if (GS(ale->id->name) == ID_NT) {
						bNodeTree *ntree = (bNodeTree *)ale->id;
						
						switch (ntree->type) {
							case NTREE_SHADER:
							{
								/* same as for textures */
								offset = 0.7f * U.widget_unit;
								indent = 1;
								break;
							}
							case NTREE_TEXTURE:
							{
								/* even more */
								offset = U.widget_unit;
								indent = 1;
								break;
							}
							default:
								/* normal will do */
								offset = 0.7f * U.widget_unit;
								break;
						}
					}
					else {
						offset = 0.7f * U.widget_unit;
					}
				}
				else {
					offset = 0;
				}
				
				/* now, start drawing based on this information */
				glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
				glEnable(GL_BLEND);
				
				/* draw backing strip behind channel name */
				if (group == 5) {
					float color[4];
					
					/* Action Line
					 *   The alpha values action_get_color returns are only useful for drawing 
					 *   strips backgrounds but here we're doing channel list backgrounds instead
					 *   so we ignore that and use our own when needed
					 */
					nla_action_get_color(adt, (bAction *)ale->data, color);
					
					if (adt && (adt->flag & ADT_NLA_EDIT_ON)) {
						/* Yes, the color vector has 4 components, BUT we only want to be using 3 of them! */
						glColor3fv(color);
					}
					else {
						float alpha = (adt && (adt->flag & ADT_NLA_SOLO_TRACK)) ? 0.3f : 1.0f;
						glColor4f(color[0], color[1], color[2], alpha);
					}
					
					offset += 0.35f * U.widget_unit * indent;
					
					/* only on top two corners, to show that this channel sits on top of the preceding ones */
					uiSetRoundBox(UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT);
					
					/* draw slightly shifted up vertically to look like it has more separation from other channels,
					 * but we then need to slightly shorten it so that it doesn't look like it overlaps
					 */
					uiDrawBox(GL_POLYGON, x + offset,  yminc + NLACHANNEL_SKIP, (float)v2d->cur.xmax, ymaxc + NLACHANNEL_SKIP - 1, 8);
					
					/* clear group value, otherwise we cause errors... */
					group = 0;
				}
				
				
				/* draw special icon indicating certain data-types */
				if (special > -1) {
					/* for normal channels */
					UI_icon_draw(x + offset, ydatac, special);
					offset += 0.85f * U.widget_unit;
				}
				glDisable(GL_BLEND);
				
				/* draw name */
				if (sel)
					UI_ThemeColor(TH_TEXT_HI);
				else
					UI_ThemeColor(TH_TEXT);
				offset += 3;
				UI_DrawString(x + offset, y - 4, name);
				
				/* reset offset - for RHS of panel */
				offset = 0;
				
				/* set blending again, as text drawing may clear it */
				glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
				glEnable(GL_BLEND);
				
				
				/* draw NLA-action line 'status-icons' - only when there's an action */
				if ((ale->type == ANIMTYPE_NLAACTION) && (ale->data)) {
					offset += 0.8f * U.widget_unit;
					
					/* now draw some indicator icons  */
					if ((adt) && (adt->flag & ADT_NLA_EDIT_ON)) {
						/* toggle for tweaking with mapping/no-mapping (i.e. 'in place editing' toggle) */
						// for now, use pin icon to symbolise this
						if (adt->flag & ADT_NLA_EDIT_NOMAP)
							UI_icon_draw((float)(v2d->cur.xmax - offset), ydatac, ICON_PINNED);
						else
							UI_icon_draw((float)(v2d->cur.xmax - offset), ydatac, ICON_UNPINNED);
						
						fdrawline((float)(v2d->cur.xmax - offset), yminc,
						          (float)(v2d->cur.xmax - offset), ymaxc);
						offset += 0.8f * U.widget_unit;
						
						/* 'tweaking action' indicator - not a button */
						UI_icon_draw((float)(v2d->cur.xmax - offset), ydatac, ICON_EDIT);
					}
					else {
						/* XXX firstly draw a little rect to help identify that it's different from the toggles */
						glBegin(GL_LINE_LOOP);
						glVertex2f((float)v2d->cur.xmax - offset - 1, y - 0.35f * U.widget_unit);
						glVertex2f((float)v2d->cur.xmax - offset - 1, y + 0.45f * U.widget_unit);
						glVertex2f((float)v2d->cur.xmax - 1, y + 0.45f * U.widget_unit);
						glVertex2f((float)v2d->cur.xmax - 1, y - 0.35f * U.widget_unit);
						glEnd();
						
						/* 'push down' icon for normal active-actions */
						UI_icon_draw((float)v2d->cur.xmax - offset, ydatac, ICON_FREEZE);
					}
				}
				
				glDisable(GL_BLEND);
			}
		}
		
		/* adjust y-position for next one */
		y -= NLACHANNEL_STEP(snla);
	}
}
Пример #4
0
// TODO: depreceate this code...
static void draw_nla_channel_list_gl(bAnimContext *ac, ListBase *anim_data, View2D *v2d, float y)
{
	SpaceNla *snla = (SpaceNla *)ac->sl;
	bAnimListElem *ale;
	float x = 0.0f;
	
	/* loop through channels, and set up drawing depending on their type  */	
	for (ale = anim_data->first; ale; ale = ale->next) {
		const float yminc = (float)(y - NLACHANNEL_HEIGHT_HALF(snla));
		const float ymaxc = (float)(y + NLACHANNEL_HEIGHT_HALF(snla));
		const float ydatac = (float)(y - 7);
		
		/* check if visible */
		if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
		    IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) )
		{
			AnimData *adt = ale->adt;
			
			short indent = 0, offset = 0, sel = 0, group = 0, nonSolo = 0;
			int expand = -1, protect = -1, special = -1, mute = -1;
			char name[128];
			short do_draw = FALSE;
			
			/* determine what needs to be drawn */
			switch (ale->type) {
				case ANIMTYPE_NLATRACK: /* NLA Track */
				{
					NlaTrack *nlt = (NlaTrack *)ale->data;
					
					/* 'solo' as the 'special' button? */
					if (nlt->flag & NLATRACK_SOLO)
						special = ICON_SOLO_ON;
					else
						special = ICON_SOLO_OFF;
						
					/* if this track is active and we're tweaking it, don't draw these toggles */
					// TODO: need a special macro for this...
					if (((nlt->flag & NLATRACK_ACTIVE) && (nlt->flag & NLATRACK_DISABLED)) == 0) {
						if (nlt->flag & NLATRACK_MUTED)
							mute = ICON_MUTE_IPO_ON;
						else
							mute = ICON_MUTE_IPO_OFF;
							
						if (EDITABLE_NLT(nlt))
							protect = ICON_UNLOCKED;
						else
							protect = ICON_LOCKED;
					}
					
					/* is track enabled for solo drawing? */
					if ((adt) && (adt->flag & ADT_NLA_SOLO_TRACK)) {
						if ((nlt->flag & NLATRACK_SOLO) == 0) {
							/* tag for special non-solo handling; also hide the mute toggles */
							nonSolo = 1;
							mute = 0;
						}
					}
						
					sel = SEL_NLT(nlt);
					BLI_strncpy(name, nlt->name, sizeof(name));
					
					/* draw manually still */
					do_draw = TRUE;
				}
				break;
				case ANIMTYPE_NLAACTION: /* NLA Action-Line */
				{
					bAction *act = (bAction *)ale->data;
					
					group = 5;
					
					special = ICON_ACTION;
					
					if (act)
						BLI_snprintf(name, sizeof(name), "%s", act->id.name + 2);
					else
						BLI_strncpy(name, "<No Action>", sizeof(name));
						
					/* draw manually still */
					do_draw = TRUE;
				}
				break;
					
				default: /* handled by standard channel-drawing API */
					// draw backdrops only...
					ANIM_channel_draw(ac, ale, yminc, ymaxc);
					break;
			}	
			
			/* if special types, draw manually for now... */
			if (do_draw) {
				if (ale->id) {
					/* special exception for textures */
					if (GS(ale->id->name) == ID_TE) {
						offset = 14;
						indent = 1;
					}
					/* special exception for nodetrees */
					else if (GS(ale->id->name) == ID_NT) {
						bNodeTree *ntree = (bNodeTree *)ale->id;
						
						switch (ntree->type) {
							case NTREE_SHADER:
							{
								/* same as for textures */
								offset = 14;
								indent = 1;
							}
							break;
								
							case NTREE_TEXTURE:
							{
								/* even more */
								offset = 21;
								indent = 1;
							}	
							break;
								
							default:
								/* normal will do */
								offset = 14;
								break;
						}
					}
					else {
						offset = 14;
					}
				}
				else {
					offset = 0;
				}
				
				/* now, start drawing based on this information */
				glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
				glEnable(GL_BLEND);
				
				/* draw backing strip behind channel name */
				// FIXME: hardcoded colors!!!
				if (group == 5) {
					float color[4];
					
					/* Action Line
					 *   The alpha values action_get_color returns are only useful for drawing 
					 *   strips backgrounds but here we're doing channel list backgrounds instead
					 *   so we ignore that and use our own when needed
					 */
					nla_action_get_color(adt, (bAction *)ale->data, color);
					
					if (adt && (adt->flag & ADT_NLA_EDIT_ON)) {
						/* Yes, the color vector has 4 components, BUT we only want to be using 3 of them! */
						glColor3fv(color);
					}
					else {
						float alpha = (adt && (adt->flag & ADT_NLA_SOLO_TRACK)) ? 0.3 : 1.0f;
						glColor4f(color[0], color[1], color[2], alpha);
					}
					
					offset += 7 * indent;
					
					/* only on top two corners, to show that this channel sits on top of the preceding ones */
					uiSetRoundBox(UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT);
					
					/* draw slightly shifted up vertically to look like it has more separation from other channels,
					 * but we then need to slightly shorten it so that it doesn't look like it overlaps
					 */
					uiDrawBox(GL_POLYGON, x + offset,  yminc + NLACHANNEL_SKIP, (float)v2d->cur.xmax, ymaxc + NLACHANNEL_SKIP - 1, 8);
					
					/* clear group value, otherwise we cause errors... */
					group = 0;
				}
				else {
					/* NLA tracks - darker color if not solo track when we're showing solo */
					UI_ThemeColorShade(TH_HEADER, ((nonSolo == 0) ? 20 : -20));
					
					indent += group;
					offset += 7 * indent;
					glBegin(GL_QUADS);
					glVertex2f(x + offset, yminc);
					glVertex2f(x + offset, ymaxc);
					glVertex2f((float)v2d->cur.xmax, ymaxc);
					glVertex2f((float)v2d->cur.xmax, yminc);
					glEnd();
				}
				
				/* draw expand/collapse triangle */
				if (expand > 0) {
					UI_icon_draw(x + offset, ydatac, expand);
					offset += 17;
				}
				
				/* draw special icon indicating certain data-types */
				if (special > -1) {
					/* for normal channels */
					UI_icon_draw(x + offset, ydatac, special);
					offset += 17;
				}
				glDisable(GL_BLEND);
				
				/* draw name */
				if (sel)
					UI_ThemeColor(TH_TEXT_HI);
				else
					UI_ThemeColor(TH_TEXT);
				offset += 3;
				UI_DrawString(x + offset, y - 4, name);
				
				/* reset offset - for RHS of panel */
				offset = 0;
				
				/* set blending again, as text drawing may clear it */
				glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
				glEnable(GL_BLEND);
				
				/* draw protect 'lock' */
				if (protect > -1) {
					offset = 16;
					UI_icon_draw((float)(v2d->cur.xmax - offset), ydatac, protect);
				}
				
				/* draw mute 'eye' */
				if (mute > -1) {
					offset += 16;
					UI_icon_draw((float)(v2d->cur.xmax - offset), ydatac, mute);
				}
				
				/* draw NLA-action line 'status-icons' - only when there's an action */
				if ((ale->type == ANIMTYPE_NLAACTION) && (ale->data)) {
					AnimData *adt = ale->adt;
					
					offset += 16;
					
					/* now draw some indicator icons  */
					if ((adt) && (adt->flag & ADT_NLA_EDIT_ON)) {
						/* toggle for tweaking with mapping/no-mapping (i.e. 'in place editing' toggle) */
						// for now, use pin icon to symbolise this
						if (adt->flag & ADT_NLA_EDIT_NOMAP)
							UI_icon_draw((float)(v2d->cur.xmax - offset), ydatac, ICON_PINNED);
						else
							UI_icon_draw((float)(v2d->cur.xmax - offset), ydatac, ICON_UNPINNED);
						
						fdrawline((float)(v2d->cur.xmax - offset), yminc,
						          (float)(v2d->cur.xmax - offset), ymaxc);
						offset += 16;
						
						/* 'tweaking action' indicator - not a button */
						UI_icon_draw((float)(v2d->cur.xmax - offset), ydatac, ICON_EDIT);
					}
					else {
						/* XXX firstly draw a little rect to help identify that it's different from the toggles */
						glBegin(GL_LINE_LOOP);
						glVertex2f((float)v2d->cur.xmax - offset - 1, y - 7);
						glVertex2f((float)v2d->cur.xmax - offset - 1, y + 9);
						glVertex2f((float)v2d->cur.xmax - 1, y + 9);
						glVertex2f((float)v2d->cur.xmax - 1, y - 7);
						glEnd(); // GL_LINES
						
						/* 'push down' icon for normal active-actions */
						UI_icon_draw((float)v2d->cur.xmax - offset, ydatac, ICON_FREEZE);
					}
				}
				
				glDisable(GL_BLEND);
			}
		}
		
		/* adjust y-position for next one */
		y -= NLACHANNEL_STEP(snla);
	}
}
Пример #5
0
/* draw the keyframes in the specified Action */
static void nla_action_draw_keyframes(
    View2D *v2d, AnimData *adt, bAction *act, float y, float ymin, float ymax)
{
  /* get a list of the keyframes with NLA-scaling applied */
  DLRBT_Tree keys;
  BLI_dlrbTree_init(&keys);
  action_to_keylist(adt, act, &keys, 0);

  if (ELEM(NULL, act, keys.first)) {
    return;
  }

  /* draw a darkened region behind the strips
   * - get and reset the background color, this time without the alpha to stand out better
   *   (amplified alpha is used instead)
   */
  float color[4];
  nla_action_get_color(adt, act, color);
  color[3] *= 2.5f;

  GPUVertFormat *format = immVertexFormat();
  uint pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);

  immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);

  immUniformColor4fv(color);

  /* - draw a rect from the first to the last frame (no extra overlaps for now)
   *   that is slightly stumpier than the track background (hardcoded 2-units here)
   */
  float f1 = ((ActKeyColumn *)keys.first)->cfra;
  float f2 = ((ActKeyColumn *)keys.last)->cfra;

  immRectf(pos_id, f1, ymin + 2, f2, ymax - 2);
  immUnbindProgram();

  /* count keys before drawing */
  /* Note: It's safe to cast DLRBT_Tree, as it's designed to degrade down to a ListBase */
  uint key_len = BLI_listbase_count((ListBase *)&keys);

  if (key_len > 0) {
    format = immVertexFormat();
    pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
    uint size_id = GPU_vertformat_attr_add(format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
    uint color_id = GPU_vertformat_attr_add(
        format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
    uint outline_color_id = GPU_vertformat_attr_add(
        format, "outlineColor", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
    uint flags_id = GPU_vertformat_attr_add(format, "flags", GPU_COMP_U32, 1, GPU_FETCH_INT);
    immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND);
    GPU_program_point_size(true);
    immUniform2f("ViewportSize", BLI_rcti_size_x(&v2d->mask) + 1, BLI_rcti_size_y(&v2d->mask) + 1);
    immBegin(GPU_PRIM_POINTS, key_len);

    /* - disregard the selection status of keyframes so they draw a certain way
     * - size is 6.0f which is smaller than the editable keyframes, so that there is a distinction
     */
    for (ActKeyColumn *ak = keys.first; ak; ak = ak->next) {
      draw_keyframe_shape(ak->cfra,
                          y,
                          6.0f,
                          false,
                          ak->key_type,
                          KEYFRAME_SHAPE_FRAME,
                          1.0f,
                          pos_id,
                          size_id,
                          color_id,
                          outline_color_id,
                          flags_id,
                          KEYFRAME_HANDLE_NONE,
                          KEYFRAME_EXTREME_NONE);
    }

    immEnd();
    GPU_program_point_size(false);
    immUnbindProgram();
  }

  /* free icons */
  BLI_dlrbTree_free(&keys);
}
Пример #6
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);
}