Esempio n. 1
0
/* event can enterkey, then it opens/closes */
static int outliner_item_activate(bContext *C, wmOperator *op, wmEvent *event)
{
	Scene *scene= CTX_data_scene(C);
	ARegion *ar= CTX_wm_region(C);
	SpaceOops *soops= CTX_wm_space_outliner(C);
	TreeElement *te;
	float fmval[2];
	int extend= RNA_boolean_get(op->ptr, "extend");

	UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], fmval, fmval+1);

	if ( !ELEM3(soops->outlinevis, SO_DATABLOCKS, SO_USERDEF, SO_KEYMAP) &&
	     !(soops->flag & SO_HIDE_RESTRICTCOLS) &&
	     (fmval[0] > ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX))
	{
		return OPERATOR_CANCELLED;
	}

	for(te= soops->tree.first; te; te= te->next) {
		if(do_outliner_item_activate(C, scene, ar, soops, te, extend, fmval)) break;
	}
	
	if(te) {
		ED_undo_push(C, "Outliner click event");
	}
	else {
		short selecting= -1;
		int row;
		
		/* get row number - 100 here is just a dummy value since we don't need the column */
		UI_view2d_listview_view_to_cell(&ar->v2d, 1000, UI_UNIT_Y, 0.0f, OL_Y_OFFSET, 
						fmval[0], fmval[1], NULL, &row);
		
		/* select relevant row */
		if(outliner_select(soops, &soops->tree, &row, &selecting)) {
		
			soops->storeflag |= SO_TREESTORE_REDRAW;
		
			/* no need for undo push here, only changing outliner data which is
			 * scene level - campbell */
			/* ED_undo_push(C, "Outliner selection event"); */
		}
	}
	
	ED_region_tag_redraw(ar);

	return OPERATOR_FINISHED;
}
Esempio n. 2
0
/* handle clicking */
static int nlachannels_mouseclick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
	bAnimContext ac;
	SpaceNla *snla;
	ARegion *ar;
	View2D *v2d;
	int channel_index;
	int notifierFlags = 0;
	short selectmode;
	float x, y;
	
	/* get editor data */
	if (ANIM_animdata_get_context(C, &ac) == 0)
		return OPERATOR_CANCELLED;
		
	/* get useful pointers from animation context data */
	snla = (SpaceNla *)ac.sl;
	ar = ac.ar;
	v2d = &ar->v2d;
	
	/* select mode is either replace (deselect all, then add) or add/extend */
	if (RNA_boolean_get(op->ptr, "extend"))
		selectmode = SELECT_INVERT;
	else
		selectmode = SELECT_REPLACE;
	
	/* figure out which channel user clicked in 
	 * Note: although channels technically start at y= NLACHANNEL_FIRST, we need to adjust by half a channel's height
	 *		so that the tops of channels get caught ok. Since NLACHANNEL_FIRST is really NLACHANNEL_HEIGHT, we simply use
	 *		NLACHANNEL_HEIGHT_HALF.
	 */
	UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &x, &y);
	UI_view2d_listview_view_to_cell(v2d, NLACHANNEL_NAMEWIDTH, NLACHANNEL_STEP(snla), 0, (float)NLACHANNEL_HEIGHT_HALF(snla), x, y, NULL, &channel_index);
	
	/* handle mouse-click in the relevant channel then */
	notifierFlags = mouse_nla_channels(C, &ac, x, channel_index, selectmode);
	
	/* set notifier that things have changed */
	WM_event_add_notifier(C, NC_ANIMATION | notifierFlags, NULL);
	
	return OPERATOR_FINISHED;
}
Esempio n. 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);
	}
}
Esempio n. 4
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);
	}
}