Example #1
0
static int create_plane_track_tracks_exec(bContext *C, wmOperator *op)
{
  SpaceClip *sc = CTX_wm_space_clip(C);
  MovieClip *clip = ED_space_clip_get_clip(sc);
  MovieTracking *tracking = &clip->tracking;
  MovieTrackingPlaneTrack *plane_track;
  ListBase *tracks_base = BKE_tracking_get_active_tracks(tracking);
  ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
  int framenr = ED_space_clip_get_clip_frame_number(sc);

  plane_track = BKE_tracking_plane_track_add(tracking, plane_tracks_base, tracks_base, framenr);

  if (plane_track == NULL) {
    BKE_report(op->reports, RPT_ERROR, "Need at least 4 selected point tracks to create a plane");
    return OPERATOR_CANCELLED;
  }
  else {
    BKE_tracking_tracks_deselect_all(tracks_base);

    plane_track->flag |= SELECT;
    clip->tracking.act_track = NULL;
    clip->tracking.act_plane_track = plane_track;

    /* Compute homoraphies and apply them on marker's corner, so we've got
     * quite nice motion from the very beginning.
     */
    BKE_tracking_track_plane_from_existing_motion(plane_track, framenr);
  }

  WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);

  return OPERATOR_FINISHED;
}
static MovieTrackingPlaneTrack *tracking_plane_marker_check_slide(
        bContext *C,
        const wmEvent *event,
        int *corner_r)
{
	const float distance_clip_squared = 12.0f * 12.0f;
	SpaceClip *sc = CTX_wm_space_clip(C);
	ARegion *ar = CTX_wm_region(C);
	MovieClip *clip = ED_space_clip_get_clip(sc);
	MovieTracking *tracking = &clip->tracking;
	int width, height;
	float co[2];
	ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
	int framenr = ED_space_clip_get_clip_frame_number(sc);

	ED_space_clip_get_size(sc, &width, &height);
	if (width == 0 || height == 0) {
		return NULL;
	}

	ED_clip_mouse_pos(sc, ar, event->mval, co);

	float min_distance_squared = FLT_MAX;
	int min_corner = -1;
	MovieTrackingPlaneTrack *min_plane_track = NULL;
	for (MovieTrackingPlaneTrack *plane_track = plane_tracks_base->first;
	     plane_track != NULL;
	     plane_track = plane_track->next)
	{
		if (PLANE_TRACK_VIEW_SELECTED(plane_track)) {
			MovieTrackingPlaneMarker *plane_marker =
			        BKE_tracking_plane_marker_get(plane_track, framenr);
			for (int i = 0; i < 4; i++) {
				float distance_squared =
				        mouse_to_plane_slide_zone_distance_squared(
				                co,
				                plane_marker->corners[i],
				                width,
				                height);

				if (distance_squared < min_distance_squared) {
					min_distance_squared = distance_squared;
					min_corner = i;
					min_plane_track = plane_track;
				}
			}
		}
	}

	if (min_distance_squared < distance_clip_squared / sc->zoom) {
		if (corner_r != NULL) {
			*corner_r = min_corner;
		}
		return min_plane_track;
	}

	return NULL;
}
Example #3
0
/* Draw all kind of tracks. */
static void draw_tracking_tracks(SpaceClip *sc, Scene *scene, ARegion *ar, MovieClip *clip,
                                 int width, int height, float zoomx, float zoomy)
{
	float x, y;
	MovieTracking *tracking = &clip->tracking;
	ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
	ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
	MovieTrackingTrack *track, *act_track;
	MovieTrackingPlaneTrack *plane_track, *active_plane_track;
	MovieTrackingMarker *marker;
	int framenr = ED_space_clip_get_clip_frame_number(sc);
	int undistort = sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT;
	float *marker_pos = NULL, *fp, *active_pos = NULL, cur_pos[2];

	/* ** find window pixel coordinates of origin ** */

	/* UI_view2d_view_to_region_no_clip return integer values, this could
	 * lead to 1px flickering when view is locked to selection during playbeck.
	 * to avoid this flickering, calculate base point in the same way as it happens
	 * in UI_view2d_view_to_region_no_clip, but do it in floats here */

	UI_view2d_view_to_region_fl(&ar->v2d, 0.0f, 0.0f, &x, &y);

	glPushMatrix();
	glTranslatef(x, y, 0);

	glPushMatrix();
	glScalef(zoomx, zoomy, 0);
	glMultMatrixf(sc->stabmat);
	glScalef(width, height, 0);

	act_track = BKE_tracking_track_get_active(tracking);

	/* Draw plane tracks */
	active_plane_track = BKE_tracking_plane_track_get_active(tracking);
	for (plane_track = plane_tracks_base->first;
	     plane_track;
	     plane_track = plane_track->next)
	{
		if ((plane_track->flag & PLANE_TRACK_HIDDEN) == 0) {
			draw_plane_track(sc, scene, plane_track, framenr, plane_track == active_plane_track, width, height);
		}
	}

	if (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT) {
		int count = 0;

		/* count */
		track = tracksbase->first;
		while (track) {
			if ((track->flag & TRACK_HIDDEN) == 0) {
				marker = BKE_tracking_marker_get(track, framenr);

				if (MARKER_VISIBLE(sc, track, marker))
					count++;
			}

			track = track->next;
		}

		/* undistort */
		if (count) {
			marker_pos = MEM_callocN(2 * sizeof(float) * count, "draw_tracking_tracks marker_pos");

			track = tracksbase->first;
			fp = marker_pos;
			while (track) {
				if ((track->flag & TRACK_HIDDEN) == 0) {
					marker = BKE_tracking_marker_get(track, framenr);

					if (MARKER_VISIBLE(sc, track, marker)) {
						ED_clip_point_undistorted_pos(sc, marker->pos, fp);

						if (track == act_track)
							active_pos = fp;

						fp += 2;
					}
				}

				track = track->next;
			}
		}
	}

	if (sc->flag & SC_SHOW_TRACK_PATH) {
		track = tracksbase->first;
		while (track) {
			if ((track->flag & TRACK_HIDDEN) == 0)
				draw_track_path(sc, clip, track);

			track = track->next;
		}
	}

	/* markers outline and non-selected areas */
	track = tracksbase->first;
	fp = marker_pos;
	while (track) {
		if ((track->flag & TRACK_HIDDEN) == 0) {
			marker = BKE_tracking_marker_get(track, framenr);

			if (MARKER_VISIBLE(sc, track, marker)) {
				copy_v2_v2(cur_pos, fp ? fp : marker->pos);

				draw_marker_outline(sc, track, marker, cur_pos, width, height);
				draw_marker_areas(sc, track, marker, cur_pos, width, height, 0, 0);
				draw_marker_slide_zones(sc, track, marker, cur_pos, 1, 0, 0, width, height);
				draw_marker_slide_zones(sc, track, marker, cur_pos, 0, 0, 0, width, height);

				if (fp)
					fp += 2;
			}
		}

		track = track->next;
	}

	/* selected areas only, so selection wouldn't be overlapped by
	 * non-selected areas */
	track = tracksbase->first;
	fp = marker_pos;
	while (track) {
		if ((track->flag & TRACK_HIDDEN) == 0) {
			int act = track == act_track;
			marker = BKE_tracking_marker_get(track, framenr);

			if (MARKER_VISIBLE(sc, track, marker)) {
				if (!act) {
					copy_v2_v2(cur_pos, fp ? fp : marker->pos);

					draw_marker_areas(sc, track, marker, cur_pos, width, height, 0, 1);
					draw_marker_slide_zones(sc, track, marker, cur_pos, 0, 1, 0, width, height);
				}

				if (fp)
					fp += 2;
			}
		}

		track = track->next;
	}

	/* active marker would be displayed on top of everything else */
	if (act_track) {
		if ((act_track->flag & TRACK_HIDDEN) == 0) {
			marker = BKE_tracking_marker_get(act_track, framenr);

			if (MARKER_VISIBLE(sc, act_track, marker)) {
				copy_v2_v2(cur_pos, active_pos ? active_pos : marker->pos);

				draw_marker_areas(sc, act_track, marker, cur_pos, width, height, 1, 1);
				draw_marker_slide_zones(sc, act_track, marker, cur_pos, 0, 1, 1, width, height);
			}
		}
	}

	if (sc->flag & SC_SHOW_BUNDLES) {
		MovieTrackingObject *object = BKE_tracking_object_get_active(tracking);
		float pos[4], vec[4], mat[4][4], aspy;

		glEnable(GL_POINT_SMOOTH);
		glPointSize(3.0f);

		aspy = 1.0f / clip->tracking.camera.pixel_aspect;
		BKE_tracking_get_projection_matrix(tracking, object, framenr, width, height, mat);

		track = tracksbase->first;
		while (track) {
			if ((track->flag & TRACK_HIDDEN) == 0 && track->flag & TRACK_HAS_BUNDLE) {
				marker = BKE_tracking_marker_get(track, framenr);

				if (MARKER_VISIBLE(sc, track, marker)) {
					float npos[2];
					copy_v3_v3(vec, track->bundle_pos);
					vec[3] = 1;

					mul_v4_m4v4(pos, mat, vec);

					pos[0] = (pos[0] / (pos[3] * 2.0f) + 0.5f) * width;
					pos[1] = (pos[1] / (pos[3] * 2.0f) + 0.5f) * height * aspy;

					BKE_tracking_distort_v2(tracking, pos, npos);

					if (npos[0] >= 0.0f && npos[1] >= 0.0f && npos[0] <= width && npos[1] <= height * aspy) {
						vec[0] = (marker->pos[0] + track->offset[0]) * width;
						vec[1] = (marker->pos[1] + track->offset[1]) * height * aspy;

						sub_v2_v2(vec, npos);

						if (len_squared_v2(vec) < (3.0f * 3.0f))
							glColor3f(0.0f, 1.0f, 0.0f);
						else
							glColor3f(1.0f, 0.0f, 0.0f);

						glBegin(GL_POINTS);
						if (undistort)
							glVertex3f(pos[0] / width, pos[1] / (height * aspy), 0);
						else
							glVertex3f(npos[0] / width, npos[1] / (height * aspy), 0);
						glEnd();
					}
				}
			}

			track = track->next;
		}

		glPointSize(1.0f);
		glDisable(GL_POINT_SMOOTH);
	}

	glPopMatrix();

	if (sc->flag & SC_SHOW_NAMES) {
		/* scaling should be cleared before drawing texts, otherwise font would also be scaled */
		track = tracksbase->first;
		fp = marker_pos;
		while (track) {
			if ((track->flag & TRACK_HIDDEN) == 0) {
				marker = BKE_tracking_marker_get(track, framenr);

				if (MARKER_VISIBLE(sc, track, marker)) {
					int act = track == act_track;

					copy_v2_v2(cur_pos, fp ? fp : marker->pos);

					draw_marker_texts(sc, track, marker, cur_pos, act, width, height, zoomx, zoomy);

					if (fp)
						fp += 2;
				}
			}

			track = track->next;
		}
	}

	glPopMatrix();

	if (marker_pos)
		MEM_freeN(marker_pos);
}
Example #4
0
void clip_delete_track(bContext *C, MovieClip *clip, MovieTrackingTrack *track)
{
	MovieTracking *tracking = &clip->tracking;
	MovieTrackingStabilization *stab = &tracking->stabilization;
	MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking);
	MovieTrackingPlaneTrack *plane_track, *next_plane_track;
	ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
	ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
	bool has_bundle = false, update_stab = false;
	char track_name_escaped[MAX_NAME], prefix[MAX_NAME * 2];

	if (track == act_track)
		tracking->act_track = NULL;

	if (track == stab->rot_track) {
		stab->rot_track = NULL;

		update_stab = true;
	}

	/* handle reconstruction display in 3d viewport */
	if (track->flag & TRACK_HAS_BUNDLE)
		has_bundle = true;

	/* Make sure no plane will use freed track */
	for (plane_track = plane_tracks_base->first;
	     plane_track;
	     plane_track = next_plane_track)
	{
		bool found = false;
		int i;

		next_plane_track = plane_track->next;

		for (i = 0; i < plane_track->point_tracksnr; i++) {
			if (plane_track->point_tracks[i] == track) {
				found = true;
				break;
			}
		}

		if (!found) {
			continue;
		}

		if (plane_track->point_tracksnr > 4) {
			int track_index;
			MovieTrackingTrack **new_point_tracks;

			new_point_tracks = MEM_mallocN(sizeof(*new_point_tracks) * (plane_track->point_tracksnr - 1),
			                               "new point tracks array");

			for (i = 0, track_index = 0; i < plane_track->point_tracksnr; i++) {
				if (plane_track->point_tracks[i] != track) {
					new_point_tracks[track_index++] = plane_track->point_tracks[i];
				}
			}

			MEM_freeN(plane_track->point_tracks);
			plane_track->point_tracks = new_point_tracks;
			plane_track->point_tracksnr--;
		}
		else {
			/* Delete planes with less than 3 point tracks in it. */
			BKE_tracking_plane_track_free(plane_track);
			BLI_freelinkN(plane_tracks_base, plane_track);
		}
	}

	/* Delete f-curves associated with the track (such as weight, i.e.) */
	BLI_strescape(track_name_escaped, track->name, sizeof(track_name_escaped));
	BLI_snprintf(prefix, sizeof(prefix), "tracks[\"%s\"]", track_name_escaped);
	BKE_animdata_fix_paths_remove(&clip->id, prefix);

	BKE_tracking_track_free(track);
	BLI_freelinkN(tracksbase, track);

	WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);

	if (update_stab) {
		tracking->stabilization.ok = false;
		WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, clip);
	}

	DAG_id_tag_update(&clip->id, 0);

	if (has_bundle)
		WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL);
}
static int select_all_exec(bContext *C, wmOperator *op)
{
	SpaceClip *sc = CTX_wm_space_clip(C);
	MovieClip *clip = ED_space_clip_get_clip(sc);
	MovieTracking *tracking = &clip->tracking;
	MovieTrackingTrack *track = NULL;   /* selected track */
	MovieTrackingPlaneTrack *plane_track = NULL;   /* selected plane track */
	MovieTrackingMarker *marker;
	ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
	ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
	int action = RNA_enum_get(op->ptr, "action");
	int framenr = ED_space_clip_get_clip_frame_number(sc);
	bool has_selection = false;

	if (action == SEL_TOGGLE) {
		action = SEL_SELECT;

		for (track = tracksbase->first; track; track = track->next) {
			if (TRACK_VIEW_SELECTED(sc, track)) {
				marker = BKE_tracking_marker_get(track, framenr);

				if (MARKER_VISIBLE(sc, track, marker)) {
					action = SEL_DESELECT;
					break;
				}
			}
		}

		for (plane_track = plane_tracks_base->first;
		     plane_track;
		     plane_track = plane_track->next)
		{
			if (PLANE_TRACK_VIEW_SELECTED(plane_track)) {
				action = SEL_DESELECT;
				break;
			}
		}
	}

	for (track = tracksbase->first; track; track = track->next) {
		if ((track->flag & TRACK_HIDDEN) == 0) {
			marker = BKE_tracking_marker_get(track, framenr);

			if (MARKER_VISIBLE(sc, track, marker)) {
				switch (action) {
					case SEL_SELECT:
						track->flag |= SELECT;
						track->pat_flag |= SELECT;
						track->search_flag |= SELECT;
						break;
					case SEL_DESELECT:
						track->flag &= ~SELECT;
						track->pat_flag &= ~SELECT;
						track->search_flag &= ~SELECT;
						break;
					case SEL_INVERT:
						track->flag ^= SELECT;
						track->pat_flag ^= SELECT;
						track->search_flag ^= SELECT;
						break;
				}
			}
		}

		if (TRACK_VIEW_SELECTED(sc, track))
			has_selection = true;
	}

	for (plane_track = plane_tracks_base->first;
	     plane_track;
	     plane_track = plane_track->next)
	{
		if ((plane_track->flag & PLANE_TRACK_HIDDEN) == 0) {
			switch (action) {
				case SEL_SELECT:
					plane_track->flag |= SELECT;
					break;
				case SEL_DESELECT:
					plane_track->flag &= ~SELECT;
					break;
				case SEL_INVERT:
					plane_track->flag ^= SELECT;
					break;
			}
			if (plane_track->flag & SELECT) {
				has_selection = true;
			}
		}
	}

	if (!has_selection)
		sc->flag &= ~SC_LOCK_SELECTION;

	BKE_tracking_dopesheet_tag_update(tracking);

	WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL);

	return OPERATOR_FINISHED;
}
static int circle_select_exec(bContext *C, wmOperator *op)
{
	SpaceClip *sc = CTX_wm_space_clip(C);
	ARegion *ar = CTX_wm_region(C);

	MovieClip *clip = ED_space_clip_get_clip(sc);
	MovieTracking *tracking = &clip->tracking;
	MovieTrackingTrack *track;
	MovieTrackingPlaneTrack *plane_track;
	ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
	ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
	int x, y, radius, width, height, mode;
	bool changed = false;
	float zoomx, zoomy, offset[2], ellipse[2];
	int framenr = ED_space_clip_get_clip_frame_number(sc);

	/* get operator properties */
	x = RNA_int_get(op->ptr, "x");
	y = RNA_int_get(op->ptr, "y");
	radius = RNA_int_get(op->ptr, "radius");

	mode = RNA_int_get(op->ptr, "gesture_mode");

	/* compute ellipse and position in unified coordinates */
	ED_space_clip_get_size(sc, &width, &height);
	ED_space_clip_get_zoom(sc, ar, &zoomx, &zoomy);

	ellipse[0] = width * zoomx / radius;
	ellipse[1] = height * zoomy / radius;

	ED_clip_point_stable_pos(sc, ar, x, y, &offset[0], &offset[1]);

	/* do selection */
	track = tracksbase->first;
	while (track) {
		if ((track->flag & TRACK_HIDDEN) == 0) {
			MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);

			if (MARKER_VISIBLE(sc, track, marker) && marker_inside_ellipse(marker, offset, ellipse)) {
				if (mode == GESTURE_MODAL_SELECT)
					BKE_tracking_track_flag_set(track, TRACK_AREA_ALL, SELECT);
				else
					BKE_tracking_track_flag_clear(track, TRACK_AREA_ALL, SELECT);

				changed = true;
			}
		}

		track = track->next;
	}

	for (plane_track = plane_tracks_base->first;
	     plane_track;
	     plane_track = plane_track->next)
	{
		if ((plane_track->flag & PLANE_TRACK_HIDDEN) == 0) {
			MovieTrackingPlaneMarker *plane_marker =
				BKE_tracking_plane_marker_get(plane_track, framenr);
			int i;

			for (i = 0; i < 4; i++) {
				if (point_inside_ellipse(plane_marker->corners[i], offset, ellipse)) {
					if (mode == GESTURE_MODAL_SELECT) {
						plane_track->flag |= SELECT;
					}
					else {
						plane_track->flag &= ~SELECT;
					}
				}
			}

			changed = true;
		}
	}

	if (changed) {
		BKE_tracking_dopesheet_tag_update(tracking);

		WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL);

		return OPERATOR_FINISHED;
	}

	return OPERATOR_CANCELLED;
}
static int do_lasso_select_marker(bContext *C, const int mcords[][2], const short moves, bool select)
{
	SpaceClip *sc = CTX_wm_space_clip(C);
	ARegion *ar = CTX_wm_region(C);

	MovieClip *clip = ED_space_clip_get_clip(sc);
	MovieTracking *tracking = &clip->tracking;
	MovieTrackingTrack *track;
	MovieTrackingPlaneTrack *plane_track;
	ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
	ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
	rcti rect;
	bool changed = false;
	int framenr = ED_space_clip_get_clip_frame_number(sc);

	/* get rectangle from operator */
	BLI_lasso_boundbox(&rect, mcords, moves);

	/* do actual selection */
	track = tracksbase->first;
	while (track) {
		if ((track->flag & TRACK_HIDDEN) == 0) {
			MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);

			if (MARKER_VISIBLE(sc, track, marker)) {
				float screen_co[2];

				/* marker in screen coords */
				ED_clip_point_stable_pos__reverse(sc, ar, marker->pos, screen_co);

				if (BLI_rcti_isect_pt(&rect, screen_co[0], screen_co[1]) &&
				    BLI_lasso_is_point_inside(mcords, moves, screen_co[0], screen_co[1], V2D_IS_CLIPPED))
				{
					if (select)
						BKE_tracking_track_flag_set(track, TRACK_AREA_ALL, SELECT);
					else
						BKE_tracking_track_flag_clear(track, TRACK_AREA_ALL, SELECT);
				}

				changed = true;
			}
		}

		track = track->next;
	}

	for (plane_track = plane_tracks_base->first;
	     plane_track;
	     plane_track = plane_track->next)
	{
		if ((plane_track->flag & PLANE_TRACK_HIDDEN) == 0) {
			MovieTrackingPlaneMarker *plane_marker =
				BKE_tracking_plane_marker_get(plane_track, framenr);
			int i;

			for (i = 0; i < 4; i++) {
				float screen_co[2];

				/* marker in screen coords */
				ED_clip_point_stable_pos__reverse(sc, ar, plane_marker->corners[i], screen_co);

				if (BLI_rcti_isect_pt(&rect, screen_co[0], screen_co[1]) &&
				    BLI_lasso_is_point_inside(mcords, moves, screen_co[0], screen_co[1], V2D_IS_CLIPPED))
				{
					if (select) {
						plane_track->flag |= SELECT;
					}
					else {
						plane_track->flag &= ~SELECT;
					}
				}
			}

			changed = true;
		}
	}

	if (changed) {
		BKE_tracking_dopesheet_tag_update(tracking);

		WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL);
	}

	return changed;
}
static int border_select_exec(bContext *C, wmOperator *op)
{
	SpaceClip *sc = CTX_wm_space_clip(C);
	ARegion *ar = CTX_wm_region(C);

	MovieClip *clip = ED_space_clip_get_clip(sc);
	MovieTracking *tracking = &clip->tracking;
	MovieTrackingTrack *track;
	MovieTrackingPlaneTrack *plane_track;
	ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
	ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
	rcti rect;
	rctf rectf;
	bool changed = false;
	int mode, extend;
	int framenr = ED_space_clip_get_clip_frame_number(sc);

	/* get rectangle from operator */
	WM_operator_properties_border_to_rcti(op, &rect);

	ED_clip_point_stable_pos(sc, ar, rect.xmin, rect.ymin, &rectf.xmin, &rectf.ymin);
	ED_clip_point_stable_pos(sc, ar, rect.xmax, rect.ymax, &rectf.xmax, &rectf.ymax);

	mode = RNA_int_get(op->ptr, "gesture_mode");
	extend = RNA_boolean_get(op->ptr, "extend");

	/* do actual selection */
	track = tracksbase->first;
	while (track) {
		if ((track->flag & TRACK_HIDDEN) == 0) {
			MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);

			if (MARKER_VISIBLE(sc, track, marker)) {
				if (BLI_rctf_isect_pt_v(&rectf, marker->pos)) {
					if (mode == GESTURE_MODAL_SELECT)
						BKE_tracking_track_flag_set(track, TRACK_AREA_ALL, SELECT);
					else
						BKE_tracking_track_flag_clear(track, TRACK_AREA_ALL, SELECT);
				}
				else if (!extend) {
					BKE_tracking_track_flag_clear(track, TRACK_AREA_ALL, SELECT);
				}

				changed = true;
			}
		}

		track = track->next;
	}

	for (plane_track = plane_tracks_base->first;
	     plane_track;
	     plane_track = plane_track->next)
	{
		if ((plane_track->flag & PLANE_TRACK_HIDDEN) == 0) {
			MovieTrackingPlaneMarker *plane_marker =
				BKE_tracking_plane_marker_get(plane_track, framenr);
			int i;

			for (i = 0; i < 4; i++) {
				if (BLI_rctf_isect_pt_v(&rectf, plane_marker->corners[i])) {
					if (mode == GESTURE_MODAL_SELECT) {
						plane_track->flag |= SELECT;
					}
					else {
						plane_track->flag &= ~SELECT;
					}
				}
				else if (!extend) {
					plane_track->flag &= ~SELECT;
				}
			}

			changed = true;
		}
	}

	if (changed) {
		BKE_tracking_dopesheet_tag_update(tracking);

		WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL);

		return OPERATOR_FINISHED;
	}

	return OPERATOR_CANCELLED;
}
static int mouse_select(bContext *C, float co[2], int extend)
{
	SpaceClip *sc = CTX_wm_space_clip(C);
	MovieClip *clip = ED_space_clip_get_clip(sc);
	MovieTracking *tracking = &clip->tracking;
	ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
	ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
	MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking);
	MovieTrackingTrack *track;
	MovieTrackingPlaneTrack *plane_track;
	float distance_to_track, distance_to_plane_track;

	track = find_nearest_track(sc, tracksbase, co, &distance_to_track);
	plane_track = find_nearest_plane_track(sc, plane_tracks_base, co, &distance_to_plane_track);

	/* Between track and plane we choose closest to the mouse for selection here. */
	if (track && plane_track) {
		if (distance_to_track < distance_to_plane_track) {
			plane_track = NULL;
		}
		else {
			track = NULL;
		}
	}

	if (!extend) {
		delect_all_plane_tracks(plane_tracks_base);
	}

	if (track) {
		int area = track_mouse_area(C, co, track);

		if (!extend || !TRACK_VIEW_SELECTED(sc, track))
			area = TRACK_AREA_ALL;

		if (extend && TRACK_AREA_SELECTED(track, area)) {
			if (track == act_track) {
				BKE_tracking_track_deselect(track, area);
			}
			else {
				clip->tracking.act_track = track;
				clip->tracking.act_plane_track = NULL;
			}
		}
		else {
			if (area == TRACK_AREA_POINT)
				area = TRACK_AREA_ALL;

			BKE_tracking_track_select(tracksbase, track, area, extend);
			clip->tracking.act_track = track;
			clip->tracking.act_plane_track = NULL;
		}
	}
	else if (plane_track) {
		if (!extend) {
			delect_all_tracks(tracksbase);
		}

		if (PLANE_TRACK_VIEW_SELECTED(plane_track)) {
			if (extend) {
				plane_track->flag &= ~SELECT;
			}
		}
		else {
			plane_track->flag |= SELECT;
		}

		clip->tracking.act_track = NULL;
		clip->tracking.act_plane_track = plane_track;
	}

	if (!extend) {
		sc->xlockof = 0.0f;
		sc->ylockof = 0.0f;
	}

	BKE_tracking_dopesheet_tag_update(tracking);

	WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL);

	return OPERATOR_FINISHED;
}