예제 #1
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);
}
예제 #2
0
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);
}
예제 #3
0
static void mouse_action_keys(bAnimContext *ac, const int mval[2], short select_mode, bool column, bool same_channel)
{
	ListBase anim_data = {NULL, NULL};
	DLRBT_Tree anim_keys;
	bAnimListElem *ale;
	int filter;
	
	View2D *v2d = &ac->ar->v2d;
	bDopeSheet *ads = NULL;
	int channel_index;
	bool found = false;
	float frame = 0.0f; /* frame of keyframe under mouse - NLA corrections not applied/included */
	float selx = 0.0f;  /* frame of keyframe under mouse */
	float key_hsize;
	float x, y;
	rctf rectf;
	
	/* get dopesheet info */
	if (ac->datatype == ANIMCONT_DOPESHEET)
		ads = ac->data;
	
	/* 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, ACHANNEL_STEP(ac), 0, (float)ACHANNEL_HEIGHT_HALF(ac), x, y, NULL, &channel_index);
	
	/* x-range to check is +/- 7px for standard keyframe under standard dpi/y-scale (in screen/region-space),
	 * on either side of mouse click (size of keyframe icon)
	 */
	key_hsize = ACHANNEL_HEIGHT(ac) * 0.8f;    /* standard channel height (to allow for some slop) */
	key_hsize = roundf(key_hsize / 2.0f);      /* half-size (for either side), but rounded up to nearest int (for easier targetting) */
	
	UI_view2d_region_to_view(v2d, mval[0] - (int)key_hsize, mval[1], &rectf.xmin, &rectf.ymin);
	UI_view2d_region_to_view(v2d, mval[0] + (int)key_hsize, mval[1], &rectf.xmax, &rectf.ymax);
	
	/* 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_action_keys()\n", channel_index);
		ANIM_animdata_freelist(&anim_data);
		return;
	}
	else {
		/* found match - must return here... */
		AnimData *adt = ANIM_nla_mapping_get(ac, ale);
		ActKeyColumn *ak, *akn = NULL;
		
		/* make list of keyframes */
		BLI_dlrbTree_init(&anim_keys);
		
		if (ale->key_data) {
			switch (ale->datatype) {
				case ALE_SCE:
				{
					Scene *scene = (Scene *)ale->key_data;
					scene_to_keylist(ads, scene, &anim_keys, NULL);
					break;
				}
				case ALE_OB:
				{
					Object *ob = (Object *)ale->key_data;
					ob_to_keylist(ads, ob, &anim_keys, NULL);
					break;
				}
				case ALE_ACT:
				{
					bAction *act = (bAction *)ale->key_data;
					action_to_keylist(adt, act, &anim_keys, NULL);
					break;
				}
				case ALE_FCURVE:
				{
					FCurve *fcu = (FCurve *)ale->key_data;
					fcurve_to_keylist(adt, fcu, &anim_keys, NULL);
					break;
				}
			}
		}
		else if (ale->type == ANIMTYPE_SUMMARY) {
			/* dopesheet summary covers everything */
			summary_to_keylist(ac, &anim_keys, NULL);
		}
		else if (ale->type == ANIMTYPE_GROUP) {
			// TODO: why don't we just give groups key_data too?
			bActionGroup *agrp = (bActionGroup *)ale->data;
			agroup_to_keylist(adt, agrp, &anim_keys, NULL);
		}
		else if (ale->type == ANIMTYPE_GPLAYER) {
			// TODO: why don't we just give gplayers key_data too?
			bGPDlayer *gpl = (bGPDlayer *)ale->data;
			gpl_to_keylist(ads, gpl, &anim_keys);
		}
		else if (ale->type == ANIMTYPE_MASKLAYER) {
			// TODO: why don't we just give masklayers key_data too?
			MaskLayer *masklay = (MaskLayer *)ale->data;
			mask_to_keylist(ads, masklay, &anim_keys);
		}

		/* start from keyframe at root of BST, traversing until we find one within the range that was clicked on */
		for (ak = anim_keys.root; ak; ak = akn) {
			if (IN_RANGE(ak->cfra, rectf.xmin, rectf.xmax)) {
				/* set the frame to use, and apply inverse-correction for NLA-mapping 
				 * so that the frame will get selected by the selection functions without
				 * requiring to map each frame once again...
				 */
				selx = BKE_nla_tweakedit_remap(adt, ak->cfra, NLATIME_CONVERT_UNMAP);
				frame = ak->cfra;
				found = true;
				break;
			}
			else if (ak->cfra < rectf.xmin)
				akn = ak->right;
			else
				akn = ak->left;
		}
		
		/* remove active channel from list of channels for separate treatment (since it's needed later on) */
		BLI_remlink(&anim_data, ale);
		
		/* cleanup temporary lists */
		BLI_dlrbTree_free(&anim_keys);
		
		/* free list of channels, since it's not used anymore */
		ANIM_animdata_freelist(&anim_data);
	}
	
	/* 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 keyframes */
		deselect_action_keys(ac, 0, SELECT_SUBTRACT);
		
		/* highlight channel clicked on */
		if (ELEM(ac->datatype, ANIMCONT_ACTION, ANIMCONT_DOPESHEET)) {
			/* deselect all other channels first */
			ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
			
			/* Highlight Action-Group or F-Curve? */
			if (ale && ale->data) {
				if (ale->type == ANIMTYPE_GROUP) {
					bActionGroup *agrp = ale->data;
					
					agrp->flag |= AGRP_SELECTED;
					ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, agrp, ANIMTYPE_GROUP);
				}
				else if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) {
					FCurve *fcu = ale->data;
					
					fcu->flag |= FCURVE_SELECTED;
					ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, fcu, ale->type);
				}
			}
		}
		else if (ac->datatype == ANIMCONT_GPENCIL) {
			/* deselect all other channels first */
			ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
			
			/* Highlight GPencil Layer */
			if ((ale && ale->data) && (ale->type == ANIMTYPE_GPLAYER)) {
				bGPDlayer *gpl = ale->data;
				
				gpl->flag |= GP_LAYER_SELECT;
				//gpencil_layer_setactive(gpd, gpl);
			}
		}
		else if (ac->datatype == ANIMCONT_MASK) {
			/* deselect all other channels first */
			ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);

			/* Highlight GPencil Layer */
			if ((ale && ale->data) && (ale->type == ANIMTYPE_MASKLAYER)) {
				MaskLayer *masklay = ale->data;

				masklay->flag |= MASK_LAYERFLAG_SELECT;
				//gpencil_layer_setactive(gpd, gpl);
			}
		}
	}
	
	/* only select keyframes if we clicked on a valid channel and hit something */
	if (ale) {
		if (found) {
			/* apply selection to keyframes */
			if (column) {
				/* select all keyframes in the same frame as the one we hit on the active channel 
				 * [T41077]: "frame" not "selx" here (i.e. no NLA corrections yet) as the code here
				 *            does that itself again as it needs to work on multiple datablocks 
				 */
				actkeys_mselect_column(ac, select_mode, frame);
			}
			else if (same_channel) {
				/* select all keyframes in the active channel */
				actkeys_mselect_channel_only(ac, ale, select_mode);	
			}
			else {
				/* select the nominated keyframe on the given frame */
				actkeys_mselect_single(ac, ale, select_mode, selx);
			}
		}
		
		/* free this channel */
		MEM_freeN(ale);
	}
}
예제 #4
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;
}