void draw_scene_channel(View2D *v2d, bDopeSheet *ads, Scene *sce, float ypos)
{
	DLRBT_Tree keys, blocks;
	
	BLI_dlrbTree_init(&keys);
	BLI_dlrbTree_init(&blocks);
	
	scene_to_keylist(ads, sce, &keys, &blocks);
	
	BLI_dlrbTree_linkedlist_sync(&keys);
	BLI_dlrbTree_linkedlist_sync(&blocks);
	
	draw_keylist(v2d, &keys, &blocks, ypos, 0);
	
	BLI_dlrbTree_free(&keys);
	BLI_dlrbTree_free(&blocks);
}
void draw_object_channel(View2D *v2d, bDopeSheet *ads, Object *ob, float ypos)
{
	DLRBT_Tree keys, blocks;
	
	BLI_dlrbTree_init(&keys);
	BLI_dlrbTree_init(&blocks);
	
	ob_to_keylist(ads, ob, &keys, &blocks);
	
	BLI_dlrbTree_linkedlist_sync(&keys);
	BLI_dlrbTree_linkedlist_sync(&blocks);
	
	draw_keylist(v2d, &keys, &blocks, ypos, 0);
	
	BLI_dlrbTree_free(&keys);
	BLI_dlrbTree_free(&blocks);
}
void draw_summary_channel(View2D *v2d, bAnimContext *ac, float ypos)
{
	DLRBT_Tree keys, blocks;
	
	BLI_dlrbTree_init(&keys);
	BLI_dlrbTree_init(&blocks);
	
	summary_to_keylist(ac, &keys, &blocks);
	
	BLI_dlrbTree_linkedlist_sync(&keys);
	BLI_dlrbTree_linkedlist_sync(&blocks);
	
	draw_keylist(v2d, &keys, &blocks, ypos, 0);
	
	BLI_dlrbTree_free(&keys);
	BLI_dlrbTree_free(&blocks);
}
示例#4
0
/* helper for time_draw_keyframes() */
static void time_draw_idblock_keyframes(View2D *v2d, ID *id, short onlysel)
{
	bDopeSheet ads = {NULL};
	DLRBT_Tree keys;
	ActKeyColumn *ak;

	float fac1 = (GS(id->name) == ID_GD) ? 0.8f : 0.6f; /* draw GPencil keys taller, to help distinguish them */
	float fac2 = 1.0f - fac1;

	float ymin = v2d->tot.ymin;
	float ymax = v2d->tot.ymax * fac1 + ymin * fac2;

	/* init binarytree-list for getting keyframes */
	BLI_dlrbTree_init(&keys);

	/* init dopesheet settings */
	if (onlysel)
		ads.filterflag |= ADS_FILTER_ONLYSEL;

	/* populate tree with keyframe nodes */
	switch (GS(id->name)) {
		case ID_SCE:
			scene_to_keylist(&ads, (Scene *)id, &keys, NULL);
			break;
		case ID_OB:
			ob_to_keylist(&ads, (Object *)id, &keys, NULL);
			break;
		case ID_GD:
			gpencil_to_keylist(&ads, (bGPdata *)id, &keys);
			break;
		case ID_CF:
			cachefile_to_keylist(&ads, (CacheFile *)id, &keys, NULL);
			break;
		default:
			break;
	}

	/* build linked-list for searching */
	BLI_dlrbTree_linkedlist_sync(&keys);

	/* start drawing keyframes
	 *	- we use the binary-search capabilities of the tree to only start from
	 *	  the first visible keyframe (last one can then be easily checked)
	 *	- draw within a single GL block to be faster
	 */
	glBegin(GL_LINES);
	for (ak = time_cfra_find_ak(keys.root, v2d->cur.xmin);
	     (ak) && (ak->cfra <= v2d->cur.xmax);
	     ak = ak->next)
	{
		glVertex2f(ak->cfra, ymin);
		glVertex2f(ak->cfra, ymax);
	}
	glEnd(); // GL_LINES

	/* free temp stuff */
	BLI_dlrbTree_free(&keys);
}
void draw_action_channel(View2D *v2d, AnimData *adt, bAction *act, float ypos)
{
	DLRBT_Tree keys, blocks;
	
	short locked = (act && act->id.lib != NULL);
	
	BLI_dlrbTree_init(&keys);
	BLI_dlrbTree_init(&blocks);
	
	action_to_keylist(adt, act, &keys, &blocks);
	
	BLI_dlrbTree_linkedlist_sync(&keys);
	BLI_dlrbTree_linkedlist_sync(&blocks);
	
	draw_keylist(v2d, &keys, &blocks, ypos, locked);
	
	BLI_dlrbTree_free(&keys);
	BLI_dlrbTree_free(&blocks);
}
示例#6
0
void draw_action_channel(View2D *v2d, AnimData *adt, bAction *act, float ypos, float yscale_fac)
{
	DLRBT_Tree keys, blocks;

	bool locked = (act && ID_IS_LINKED(act));

	BLI_dlrbTree_init(&keys);
	BLI_dlrbTree_init(&blocks);

	action_to_keylist(adt, act, &keys, &blocks);

	BLI_dlrbTree_linkedlist_sync(&keys);
	BLI_dlrbTree_linkedlist_sync(&blocks);

	draw_keylist(v2d, &keys, &blocks, ypos, yscale_fac, locked);

	BLI_dlrbTree_free(&keys);
	BLI_dlrbTree_free(&blocks);
}
示例#7
0
void draw_agroup_channel(View2D *v2d, AnimData *adt, bActionGroup *agrp, float ypos, float yscale_fac)
{
	DLRBT_Tree keys, blocks;

	bool locked = (agrp->flag & AGRP_PROTECTED) ||
	              ((adt && adt->action) && ID_IS_LINKED(adt->action));

	BLI_dlrbTree_init(&keys);
	BLI_dlrbTree_init(&blocks);

	agroup_to_keylist(adt, agrp, &keys, &blocks);

	BLI_dlrbTree_linkedlist_sync(&keys);
	BLI_dlrbTree_linkedlist_sync(&blocks);

	draw_keylist(v2d, &keys, &blocks, ypos, yscale_fac, locked);

	BLI_dlrbTree_free(&keys);
	BLI_dlrbTree_free(&blocks);
}
void draw_agroup_channel(View2D *v2d, AnimData *adt, bActionGroup *agrp, float ypos)
{
	DLRBT_Tree keys, blocks;
	
	short locked = (agrp->flag & AGRP_PROTECTED) ||
	               ((adt && adt->action) && (adt->action->id.lib));
	
	BLI_dlrbTree_init(&keys);
	BLI_dlrbTree_init(&blocks);
	
	agroup_to_keylist(adt, agrp, &keys, &blocks);
	
	BLI_dlrbTree_linkedlist_sync(&keys);
	BLI_dlrbTree_linkedlist_sync(&blocks);
	
	draw_keylist(v2d, &keys, &blocks, ypos, locked);
	
	BLI_dlrbTree_free(&keys);
	BLI_dlrbTree_free(&blocks);
}
示例#9
0
void draw_fcurve_channel(View2D *v2d, AnimData *adt, FCurve *fcu, float ypos, float yscale_fac)
{
	DLRBT_Tree keys, blocks;
	
	bool locked = (fcu->flag & FCURVE_PROTECTED) ||
	              ((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED)) ||
	              ((adt && adt->action) && ID_IS_LINKED_DATABLOCK(adt->action));
	
	BLI_dlrbTree_init(&keys);
	BLI_dlrbTree_init(&blocks);
	
	fcurve_to_keylist(adt, fcu, &keys, &blocks);
	
	BLI_dlrbTree_linkedlist_sync(&keys);
	BLI_dlrbTree_linkedlist_sync(&blocks);
	
	draw_keylist(v2d, &keys, &blocks, ypos, yscale_fac, locked);
	
	BLI_dlrbTree_free(&keys);
	BLI_dlrbTree_free(&blocks);
}
示例#10
0
void draw_fcurve_channel(View2D *v2d, AnimData *adt, FCurve *fcu, float ypos)
{
	DLRBT_Tree keys, blocks;
	
	short locked = (fcu->flag & FCURVE_PROTECTED) ||
	               ((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED)) ||
	               ((adt && adt->action) && (adt->action->id.lib));
	
	BLI_dlrbTree_init(&keys);
	BLI_dlrbTree_init(&blocks);
	
	fcurve_to_keylist(adt, fcu, &keys, &blocks);
	
	BLI_dlrbTree_linkedlist_sync(&keys);
	BLI_dlrbTree_linkedlist_sync(&blocks);
	
	draw_keylist(v2d, &keys, &blocks, ypos, locked);
	
	BLI_dlrbTree_free(&keys);
	BLI_dlrbTree_free(&blocks);
}
示例#11
0
void draw_masklay_channel(View2D *v2d, bDopeSheet *ads, MaskLayer *masklay, float ypos)
{
	DLRBT_Tree keys;

	BLI_dlrbTree_init(&keys);

	mask_to_keylist(ads, masklay, &keys);

	BLI_dlrbTree_linkedlist_sync(&keys);

	draw_keylist(v2d, &keys, NULL, ypos, (masklay->flag & MASK_LAYERFLAG_LOCKED));

	BLI_dlrbTree_free(&keys);
}
示例#12
0
void draw_gpl_channel(View2D *v2d, bDopeSheet *ads, bGPDlayer *gpl, float ypos)
{
	DLRBT_Tree keys;
	
	BLI_dlrbTree_init(&keys);
	
	gpl_to_keylist(ads, gpl, &keys);
	
	BLI_dlrbTree_linkedlist_sync(&keys);
	
	draw_keylist(v2d, &keys, NULL, ypos, (gpl->flag & GP_LAYER_LOCKED));
	
	BLI_dlrbTree_free(&keys);
}
示例#13
0
void draw_gpencil_channel(View2D *v2d, bDopeSheet *ads, bGPdata *gpd, float ypos)
{
	DLRBT_Tree keys;
	
	BLI_dlrbTree_init(&keys);
	
	gpencil_to_keylist(ads, gpd, &keys);
	
	BLI_dlrbTree_linkedlist_sync(&keys);
	
	draw_keylist(v2d, &keys, NULL, ypos, 0);
	
	BLI_dlrbTree_free(&keys);
}
示例#14
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);
}
示例#15
0
/* Draw the given motion path for an Object or a Bone 
 *  - assumes that the viewport has already been initialized properly
 *    i.e. draw_motion_paths_init() has been called
 */
void draw_motion_path_instance(Scene *scene, 
                               Object *ob, bPoseChannel *pchan, bAnimVizSettings *avs, bMotionPath *mpath)
{
	//RegionView3D *rv3d = ar->regiondata;
	bMotionPathVert *mpv, *mpv_start;
	int i, stepsize = avs->path_step;
	int sfra, efra, sind, len;
	
	/* get frame ranges */
	if (avs->path_type == MOTIONPATH_TYPE_ACFRA) {
		/* With "Around Current", we only choose frames from around 
		 * the current frame to draw.
		 */
		sfra = CFRA - avs->path_bc;
		efra = CFRA + avs->path_ac;
	}
	else {
		/* Use the current display range */
		sfra = avs->path_sf;
		efra = avs->path_ef;
	}
	
	/* no matter what, we can only show what is in the cache and no more 
	 * - abort if whole range is past ends of path
	 * - otherwise clamp endpoints to extents of path
	 */
	if (sfra < mpath->start_frame) {
		/* start clamp */
		sfra = mpath->start_frame;
	}
	if (efra > mpath->end_frame) {
		/* end clamp */
		efra = mpath->end_frame;
	}
	
	if ((sfra > mpath->end_frame) || (efra < mpath->start_frame)) {
		/* whole path is out of bounds */
		return;
	}
	
	len = efra - sfra;
	
	if ((len <= 0) || (mpath->points == NULL)) {
		return;
	}
	
	/* get pointers to parts of path */
	sind = sfra - mpath->start_frame;
	mpv_start = (mpath->points + sind);
	
	/* draw curve-line of path */
	glShadeModel(GL_SMOOTH);
	
	glBegin(GL_LINE_STRIP);
	for (i = 0, mpv = mpv_start; i < len; i++, mpv++) {
		short sel = (pchan) ? (pchan->bone->flag & BONE_SELECTED) : (ob->flag & SELECT);
		float intensity;  /* how faint */
		
		int frame = sfra + i;
		int blend_base = (abs(frame - CFRA) == 1) ? TH_CFRAME : TH_BACK; /* "bleed" cframe color to ease color blending */
		
		/* set color
		 * - more intense for active/selected bones, less intense for unselected bones
		 * - black for before current frame, green for current frame, blue for after current frame
		 * - intensity decreases as distance from current frame increases
		 */
#define SET_INTENSITY(A, B, C, min, max) (((1.0f - ((C - B) / (C - A))) * (max - min)) + min)
		if (frame < CFRA) {
			/* black - before cfra */
			if (sel) {
				/* intensity = 0.5f; */
				intensity = SET_INTENSITY(sfra, i, CFRA, 0.25f, 0.75f);
			}
			else {
				/* intensity = 0.8f; */
				intensity = SET_INTENSITY(sfra, i, CFRA, 0.68f, 0.92f);
			}
			UI_ThemeColorBlend(TH_WIRE, blend_base, intensity);
		}
		else if (frame > CFRA) {
			/* blue - after cfra */
			if (sel) {
				/* intensity = 0.5f; */
				intensity = SET_INTENSITY(CFRA, i, efra, 0.25f, 0.75f);
			}
			else {
				/* intensity = 0.8f; */
				intensity = SET_INTENSITY(CFRA, i, efra, 0.68f, 0.92f);
			}
			UI_ThemeColorBlend(TH_BONE_POSE, blend_base, intensity);
		}
		else {
			/* green - on cfra */
			if (sel) {
				intensity = 0.5f;
			}
			else {
				intensity = 0.99f;
			}
			UI_ThemeColorBlendShade(TH_CFRAME, TH_BACK, intensity, 10);
		}
#undef SET_INTENSITY

		/* draw a vertex with this color */
		glVertex3fv(mpv->co);
	}
	
	glEnd();
	glShadeModel(GL_FLAT);
	
	glPointSize(1.0);
	
	/* draw little black point at each frame
	 * NOTE: this is not really visible/noticeable
	 */
	glBegin(GL_POINTS);
	for (i = 0, mpv = mpv_start; i < len; i++, mpv++)
		glVertex3fv(mpv->co);
	glEnd();
	
	/* Draw little white dots at each framestep value */
	UI_ThemeColor(TH_TEXT_HI);
	glBegin(GL_POINTS);
	for (i = 0, mpv = mpv_start; i < len; i += stepsize, mpv += stepsize)
		glVertex3fv(mpv->co);
	glEnd();
	
	/* Draw big green dot where the current frame is 
	 * NOTE: this is only done when keyframes are shown, since this adds similar types of clutter
	 */
	if ((avs->path_viewflag & MOTIONPATH_VIEW_KFRAS) &&
	    (sfra < CFRA) && (CFRA <= efra))
	{
		UI_ThemeColor(TH_CFRAME);
		glPointSize(6.0f);
		
		glBegin(GL_POINTS);
		mpv = mpv_start + (CFRA - sfra);
		glVertex3fv(mpv->co);
		glEnd();
		
		UI_ThemeColor(TH_TEXT_HI);
	}
	
	/* XXX, this isn't up to date but probably should be kept so. */
	invert_m4_m4(ob->imat, ob->obmat);
	
	/* Draw frame numbers at each framestep value */
	if (avs->path_viewflag & MOTIONPATH_VIEW_FNUMS) {
		unsigned char col[4];
		UI_GetThemeColor3ubv(TH_TEXT_HI, col);
		col[3] = 255;
		
		for (i = 0, mpv = mpv_start; i < len; i += stepsize, mpv += stepsize) {
			int frame = sfra + i;
			char numstr[32];
			size_t numstr_len;
			float co[3];
			
			/* only draw framenum if several consecutive highlighted points don't occur on same point */
			if (i == 0) {
				numstr_len = sprintf(numstr, " %d", frame);
				mul_v3_m4v3(co, ob->imat, mpv->co);
				view3d_cached_text_draw_add(co, numstr, numstr_len,
				                            0, V3D_CACHE_TEXT_WORLDSPACE | V3D_CACHE_TEXT_ASCII, col);
			}
			else if ((i >= stepsize) && (i < len - stepsize)) {
				bMotionPathVert *mpvP = (mpv - stepsize);
				bMotionPathVert *mpvN = (mpv + stepsize);
				
				if ((equals_v3v3(mpv->co, mpvP->co) == 0) || (equals_v3v3(mpv->co, mpvN->co) == 0)) {
					numstr_len = sprintf(numstr, " %d", frame);
					mul_v3_m4v3(co, ob->imat, mpv->co);
					view3d_cached_text_draw_add(co, numstr, numstr_len,
					                            0, V3D_CACHE_TEXT_WORLDSPACE | V3D_CACHE_TEXT_ASCII, col);
				}
			}
		}
	}
	
	/* Keyframes - dots and numbers */
	if (avs->path_viewflag & MOTIONPATH_VIEW_KFRAS) {
		unsigned char col[4];
		
		AnimData *adt = BKE_animdata_from_id(&ob->id);
		DLRBT_Tree keys;
		
		/* build list of all keyframes in active action for object or pchan */
		BLI_dlrbTree_init(&keys);
		
		if (adt) {
			/* it is assumed that keyframes for bones are all grouped in a single group
			 * unless an option is set to always use the whole action
			 */
			if ((pchan) && (avs->path_viewflag & MOTIONPATH_VIEW_KFACT) == 0) {
				bActionGroup *agrp = BKE_action_group_find_name(adt->action, pchan->name);
				
				if (agrp) {
					agroup_to_keylist(adt, agrp, &keys, NULL);
					BLI_dlrbTree_linkedlist_sync(&keys);
				}
			}
			else {
				action_to_keylist(adt, adt->action, &keys, NULL);
				BLI_dlrbTree_linkedlist_sync(&keys);
			}
		}
		
		/* Draw slightly-larger yellow dots at each keyframe */
		UI_GetThemeColor3ubv(TH_VERTEX_SELECT, col);
		col[3] = 255;
		
		glPointSize(4.0f);
		glColor3ubv(col);
		
		glBegin(GL_POINTS);
		for (i = 0, mpv = mpv_start; i < len; i++, mpv++) {
			int    frame = sfra + i; 
			float mframe = (float)(frame);
			
			if (BLI_dlrbTree_search_exact(&keys, compare_ak_cfraPtr, &mframe))
				glVertex3fv(mpv->co);
		}
		glEnd();
		
		/* Draw frame numbers of keyframes  */
		if (avs->path_viewflag & MOTIONPATH_VIEW_KFNOS) {
			float co[3];
			for (i = 0, mpv = mpv_start; i < len; i++, mpv++) {
				float mframe = (float)(sfra + i);
				
				if (BLI_dlrbTree_search_exact(&keys, compare_ak_cfraPtr, &mframe)) {
					char numstr[32];
					size_t numstr_len;
					
					numstr_len = sprintf(numstr, " %d", (sfra + i));
					mul_v3_m4v3(co, ob->imat, mpv->co);
					view3d_cached_text_draw_add(co, numstr, numstr_len,
					                            0, V3D_CACHE_TEXT_WORLDSPACE | V3D_CACHE_TEXT_ASCII, col);
				}
			}
		}
		
		BLI_dlrbTree_free(&keys);
	}
}
示例#16
0
static bool find_prev_next_keyframes(struct bContext *C, int *nextfra, int *prevfra)
{
	Scene *scene = CTX_data_scene(C);
	Object *ob = CTX_data_active_object(C);
	bGPdata *gpd = CTX_data_gpencil_data(C);
	Mask *mask = CTX_data_edit_mask(C);
	bDopeSheet ads = {NULL};
	DLRBT_Tree keys;
	ActKeyColumn *aknext, *akprev;
	float cfranext, cfraprev;
	bool donenext = false, doneprev = false;
	int nextcount = 0, prevcount = 0;

	cfranext = cfraprev = (float)(CFRA);

	/* init binarytree-list for getting keyframes */
	BLI_dlrbTree_init(&keys);

	/* seed up dummy dopesheet context with flags to perform necessary filtering */
	if ((scene->flag & SCE_KEYS_NO_SELONLY) == 0) {
		/* only selected channels are included */
		ads.filterflag |= ADS_FILTER_ONLYSEL;
	}

	/* populate tree with keyframe nodes */
	scene_to_keylist(&ads, scene, &keys, NULL);

	if (ob)
		ob_to_keylist(&ads, ob, &keys, NULL);

	gpencil_to_keylist(&ads, gpd, &keys);

	if (mask) {
		MaskLayer *masklay = BKE_mask_layer_active(mask);
		mask_to_keylist(&ads, masklay, &keys);
	}

	/* build linked-list for searching */
	BLI_dlrbTree_linkedlist_sync(&keys);

	/* find matching keyframe in the right direction */
	do {
		aknext = (ActKeyColumn *)BLI_dlrbTree_search_next(&keys, compare_ak_cfraPtr, &cfranext);

		if (aknext) {
			if (CFRA == (int)aknext->cfra) {
				/* make this the new starting point for the search and ignore */
				cfranext = aknext->cfra;
			}
			else {
				/* this changes the frame, so set the frame and we're done */
				if (++nextcount == U.view_frame_keyframes)
					donenext = true;
			}
			cfranext = aknext->cfra;
		}
	} while ((aknext != NULL) && (donenext == false));

	do {
		akprev = (ActKeyColumn *)BLI_dlrbTree_search_prev(&keys, compare_ak_cfraPtr, &cfraprev);

		if (akprev) {
			if (CFRA == (int)akprev->cfra) {
				/* make this the new starting point for the search */
			}
			else {
				/* this changes the frame, so set the frame and we're done */
				if (++prevcount == U.view_frame_keyframes)
					doneprev = true;
			}
			cfraprev = akprev->cfra;
		}
	} while ((akprev != NULL) && (doneprev == false));

	/* free temp stuff */
	BLI_dlrbTree_free(&keys);

	/* any success? */
	if (doneprev || donenext) {
		if (doneprev)
			*prevfra = cfraprev;
		else
			*prevfra = CFRA - (cfranext - CFRA);

		if (donenext)
			*nextfra = cfranext;
		else
			*nextfra = CFRA + (CFRA - cfraprev);

		return true;
	}

	return false;
}
示例#17
0
/* get frame on which the "hold" for the bone ends 
 * XXX: this may not really work that well if a bone moves on some channels and not others
 *      if this happens to be a major issue, scrap this, and just make this happen
 *		independently per F-Curve
 */
static float pose_propagate_get_boneHoldEndFrame(Object *ob, tPChanFCurveLink *pfl, float startFrame)
{
	DLRBT_Tree keys, blocks;
	ActKeyBlock *ab;
	
	AnimData *adt = ob->adt;
	LinkData *ld;
	float endFrame = startFrame;
	
	/* set up optimized data-structures for searching for relevant keyframes + holds */
	BLI_dlrbTree_init(&keys);
	BLI_dlrbTree_init(&blocks);
	
	for (ld = pfl->fcurves.first; ld; ld = ld->next) {
		FCurve *fcu = (FCurve *)ld->data;
		fcurve_to_keylist(adt, fcu, &keys, &blocks);
	}
	
	BLI_dlrbTree_linkedlist_sync(&keys);
	BLI_dlrbTree_linkedlist_sync(&blocks);
	
	/* find the long keyframe (i.e. hold), and hence obtain the endFrame value 
	 *	- the best case would be one that starts on the frame itself
	 */
	ab = (ActKeyBlock *)BLI_dlrbTree_search_exact(&blocks, compare_ab_cfraPtr, &startFrame);
	
	if (actkeyblock_is_valid(ab, &keys) == 0) {
		/* There are only two cases for no-exact match:
		 *  1) the current frame is just before another key but not on a key itself
		 *  2) the current frame is on a key, but that key doesn't link to the next
		 *
		 * If we've got the first case, then we can search for another block, 
		 * otherwise forget it, as we'd be overwriting some valid data.
		 */
		if (BLI_dlrbTree_search_exact(&keys, compare_ak_cfraPtr, &startFrame) == NULL) {
			/* we've got case 1, so try the one after */
			ab = (ActKeyBlock *)BLI_dlrbTree_search_next(&blocks, compare_ab_cfraPtr, &startFrame);
			
			if (actkeyblock_is_valid(ab, &keys) == 0) {
				/* try the block before this frame then as last resort */
				ab = (ActKeyBlock *)BLI_dlrbTree_search_prev(&blocks, compare_ab_cfraPtr, &startFrame);
				
				/* whatever happens, stop searching now... */
				if (actkeyblock_is_valid(ab, &keys) == 0) {
					/* restrict range to just the frame itself 
					 * i.e. everything is in motion, so no holds to safely overwrite
					 */
					ab = NULL;
				}
			}
		}
		else {
			/* we've got case 2 - set ab to NULL just in case, since we shouldn't do anything in this case */
			ab = NULL;
		}
	}
	
	/* check if we can go any further than we've already gone */
	if (ab) {
		/* go to next if it is also valid and meets "extension" criteria */
		while (ab->next) {
			ActKeyBlock *abn = (ActKeyBlock *)ab->next;
			
			/* must be valid */
			if (actkeyblock_is_valid(abn, &keys) == 0)
				break;
			/* should start on the same frame that the last ended on */
			if (ab->end != abn->start)
				break;
			/* should have the same number of curves */
			if (ab->totcurve != abn->totcurve)
				break;
			/* should have the same value 
			 * XXX: this may be a bit fuzzy on larger data sets, so be careful
			 */
			if (ab->val != abn->val)
				break;
				
			/* we can extend the bounds to the end of this "next" block now */
			ab = abn;
		}
		
		/* end frame can now take the value of the end of the block */
		endFrame = ab->end;
	}
	
	/* free temp memory */
	BLI_dlrbTree_free(&keys);
	BLI_dlrbTree_free(&blocks);
	
	/* return the end frame we've found */
	return endFrame;
}
示例#18
0
/* This tool automagically generates/validates poselib data so that it corresponds to the data 
 * in the action. This is for use in making existing actions usable as poselibs.
 */
static int poselib_sanitise_exec (bContext *C, wmOperator *op)
{
	Object *ob = get_poselib_object(C);
	bAction *act = (ob)? ob->poselib : NULL;
	DLRBT_Tree keys;
	ActKeyColumn *ak;
	TimeMarker *marker, *markern;
	
	/* validate action */
	if (act == NULL)  {
		BKE_report(op->reports, RPT_WARNING, "No Action to validate");
		return OPERATOR_CANCELLED;
	}
	
	/* determine which frames have keys */
	BLI_dlrbTree_init(&keys);
		action_to_keylist(NULL, act, &keys, NULL);
	BLI_dlrbTree_linkedlist_sync(&keys);
	
	/* for each key, make sure there is a corresponding pose */
	for (ak= keys.first; ak; ak= ak->next) {
		/* check if any pose matches this */
		// TODO: don't go looking through the list like this every time...
		for (marker= act->markers.first; marker; marker= marker->next) {
			if (IS_EQ(marker->frame, (double)ak->cfra)) {
				marker->flag = -1;
				break;
			}
		}
		
		/* add new if none found */
		if (marker == NULL) {
			/* add pose to poselib */
			marker= MEM_callocN(sizeof(TimeMarker), "ActionMarker");
			
			BLI_strncpy(marker->name, "Pose", sizeof(marker->name));
			
			marker->frame= (int)ak->cfra;
			marker->flag= -1;
			
			BLI_addtail(&act->markers, marker);
		}
	}
	
	/* remove all untagged poses (unused), and remove all tags */
	for (marker= act->markers.first; marker; marker= markern) {
		markern= marker->next;
		
		if (marker->flag != -1)
			BLI_freelinkN(&act->markers, marker);
		else
			marker->flag = 0;
	}
	
	/* free temp memory */
	BLI_dlrbTree_free(&keys);
	
	/* send notifiers for this - using keyframe editing notifiers, since action 
	 * may be being shown in anim editors as active action 
	 */
	WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME|NA_EDITED, NULL);
	
	return OPERATOR_FINISHED;
}
示例#19
0
/* common code for invoke() methods */
static int pose_slide_invoke_common(bContext *C, wmOperator *op, tPoseSlideOp *pso)
{
	tPChanFCurveLink *pfl;
	AnimData *adt = pso->ob->adt;
	wmWindow *win = CTX_wm_window(C);
	
	/* for each link, add all its keyframes to the search tree */
	for (pfl = pso->pfLinks.first; pfl; pfl = pfl->next) {
		LinkData *ld;
		
		/* do this for each F-Curve */
		for (ld = pfl->fcurves.first; ld; ld = ld->next) {
			FCurve *fcu = (FCurve *)ld->data;
			fcurve_to_keylist(adt, fcu, &pso->keys, NULL);
		}
	}
	
	/* consolidate these keyframes, and figure out the nearest ones */
	BLI_dlrbTree_linkedlist_sync(&pso->keys);
	
	/* cancel if no keyframes found... */
	if (pso->keys.root) {
		ActKeyColumn *ak;
		float cframe = (float)pso->cframe;
		
		/* firstly, check if the current frame is a keyframe... */
		ak = (ActKeyColumn *)BLI_dlrbTree_search_exact(&pso->keys, compare_ak_cfraPtr, &cframe);
		
		if (ak == NULL) {
			/* current frame is not a keyframe, so search */
			ActKeyColumn *pk = (ActKeyColumn *)BLI_dlrbTree_search_prev(&pso->keys, compare_ak_cfraPtr, &cframe);
			ActKeyColumn *nk = (ActKeyColumn *)BLI_dlrbTree_search_next(&pso->keys, compare_ak_cfraPtr, &cframe);
			
			/* new set the frames */
			/* prev frame */
			pso->prevFrame = (pk) ? (pk->cfra) : (pso->cframe - 1);
			RNA_int_set(op->ptr, "prev_frame", pso->prevFrame);
			/* next frame */
			pso->nextFrame = (nk) ? (nk->cfra) : (pso->cframe + 1);
			RNA_int_set(op->ptr, "next_frame", pso->nextFrame);
		}
		else {
			/* current frame itself is a keyframe, so just take keyframes on either side */
			/* prev frame */
			pso->prevFrame = (ak->prev) ? (ak->prev->cfra) : (pso->cframe - 1);
			RNA_int_set(op->ptr, "prev_frame", pso->prevFrame);
			/* next frame */
			pso->nextFrame = (ak->next) ? (ak->next->cfra) : (pso->cframe + 1);
			RNA_int_set(op->ptr, "next_frame", pso->nextFrame);
		}
	}
	else {
		BKE_report(op->reports, RPT_ERROR, "No keyframes to slide between");
		pose_slide_exit(op);
		return OPERATOR_CANCELLED;
	}
	
	/* initial apply for operator... */
	/* TODO: need to calculate percentage for initial round too... */
	pose_slide_apply(C, pso);
	
	/* depsgraph updates + redraws */
	pose_slide_refresh(C, pso);
	
	/* set cursor to indicate modal */
	WM_cursor_modal_set(win, BC_EW_SCROLLCURSOR);
	
	/* header print */
	pose_slide_draw_status(pso);
	
	/* add a modal handler for this operator */
	WM_event_add_modal_handler(C, op);
	return OPERATOR_RUNNING_MODAL;
}