Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/space_clip/clip_graph_ops.c')
-rw-r--r--source/blender/editors/space_clip/clip_graph_ops.c356
1 files changed, 356 insertions, 0 deletions
diff --git a/source/blender/editors/space_clip/clip_graph_ops.c b/source/blender/editors/space_clip/clip_graph_ops.c
new file mode 100644
index 00000000000..831b225386a
--- /dev/null
+++ b/source/blender/editors/space_clip/clip_graph_ops.c
@@ -0,0 +1,356 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2011 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation,
+ * Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/space_clip/clip_graph_ops.c
+ * \ingroup spclip
+ */
+
+#include "DNA_object_types.h" /* SELECT */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_math.h"
+#include "BLI_listbase.h"
+
+#include "BKE_context.h"
+#include "BKE_movieclip.h"
+#include "BKE_tracking.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_screen.h"
+#include "ED_clip.h"
+
+#include "UI_interface.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "UI_view2d.h"
+
+#include "clip_intern.h" // own include
+
+/******************** common graph-editing utilities ********************/
+
+typedef struct {
+ int action;
+} SelectUserData;
+
+static void toggle_selection_cb(void *userdata, MovieTrackingMarker *marker)
+{
+ SelectUserData *data= (SelectUserData *)userdata;
+
+ switch(data->action) {
+ case SEL_SELECT:
+ marker->flag|= MARKER_GRAPH_SEL;
+ break;
+ case SEL_DESELECT:
+ marker->flag&= ~MARKER_GRAPH_SEL;
+ break;
+ case SEL_INVERT:
+ marker->flag^= MARKER_GRAPH_SEL;
+ break;
+ }
+}
+
+/******************** mouse select operator ********************/
+
+typedef struct {
+ int coord, /* coordinate index of found entuty (0 = X-axis, 1 = Y-axis) */
+ has_prev; /* if there's valid coordinate of previous point of curve segment */
+
+ float min_dist, /* minimal distance between mouse and currently found entuty */
+ mouse_co[2], /* mouse coordinate */
+ prev_co[2], /* coordinate of previeous point of segment */
+ min_co[2]; /* coordinate of entity with minimal distance */
+
+ MovieTrackingTrack *track; /* nearest found track */
+ MovieTrackingMarker *marker; /* nearest found marker */
+} MouseSelectUserData;
+
+static void find_nearest_tracking_segment_cb(void *userdata, MovieTrackingTrack *track,
+ MovieTrackingMarker *marker, int coord, float val)
+{
+ MouseSelectUserData *data= userdata;
+ float co[2]= {marker->framenr, val};
+
+ if(data->has_prev) {
+ float d= dist_to_line_segment_v2(data->mouse_co, data->prev_co, co);
+
+ if(data->track==NULL || d<data->min_dist) {
+ data->track= track;
+ data->min_dist= d;
+ data->coord= coord;
+ copy_v2_v2(data->min_co, co);
+ }
+ }
+
+ data->has_prev= 1;
+ copy_v2_v2(data->prev_co, co);
+}
+
+void find_nearest_tracking_segment_end_cb(void *userdata)
+{
+ MouseSelectUserData *data= userdata;
+
+ data->has_prev= 0;
+}
+
+static void find_nearest_tracking_knot_cb(void *userdata, MovieTrackingTrack *track,
+ MovieTrackingMarker *marker, int coord, float val)
+{
+ MouseSelectUserData *data= userdata;
+ float dx= marker->framenr-data->mouse_co[0], dy= val-data->mouse_co[1];
+ float d= dx*dx+dy*dy;
+
+ if(data->marker==NULL || d<data->min_dist) {
+ float co[2]= {marker->framenr, val};
+
+ data->track= track;
+ data->marker= marker;
+ data->min_dist= d;
+ data->coord= coord;
+ copy_v2_v2(data->min_co, co);
+ }
+
+}
+
+static void mouse_select_init_data(MouseSelectUserData *userdata, float *co)
+{
+ memset(userdata, 0, sizeof(MouseSelectUserData));
+ userdata->min_dist= FLT_MAX;
+ copy_v2_v2(userdata->mouse_co, co);
+}
+
+static int mouse_select_knot(bContext *C, float co[2], int extend)
+{
+ SpaceClip *sc= CTX_wm_space_clip(C);
+ MovieClip *clip= ED_space_clip(sc);
+ ARegion *ar= CTX_wm_region(C);
+ View2D *v2d= &ar->v2d;
+ MovieTracking *tracking= &clip->tracking;
+ static const int delta= 6;
+
+ if(tracking->act_track) {
+ MouseSelectUserData userdata;
+
+ mouse_select_init_data(&userdata, co);
+ clip_graph_tracking_values_iterate_track(sc, tracking->act_track,
+ &userdata, find_nearest_tracking_knot_cb, NULL, NULL);
+
+ if(userdata.marker) {
+ int x1, y1, x2, y2;
+
+ UI_view2d_view_to_region(v2d, co[0], co[1], &x1, &y1);
+ UI_view2d_view_to_region(v2d, userdata.min_co[0], userdata.min_co[1], &x2, &y2);
+
+ if(abs(x2-x1)<=delta && abs(y2-y1)<=delta) {
+ if(!extend) {
+ SelectUserData selectdata = {SEL_DESELECT};
+ clip_graph_tracking_iterate(sc, &selectdata, toggle_selection_cb);
+ }
+
+ userdata.marker->flag|= MARKER_GRAPH_SEL;
+
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int mouse_select_curve(bContext *C, float co[2], int extend)
+{
+ SpaceClip *sc= CTX_wm_space_clip(C);
+ MovieClip *clip= ED_space_clip(sc);
+ MovieTracking *tracking= &clip->tracking;
+ MouseSelectUserData userdata;
+
+ mouse_select_init_data(&userdata, co);
+ clip_graph_tracking_values_iterate(sc, &userdata, find_nearest_tracking_segment_cb, NULL, find_nearest_tracking_segment_end_cb);
+
+ if(userdata.track) {
+ if(extend) {
+ if(tracking->act_track==userdata.track) {
+ /* currently only single curve can be selected (selected curve represents active track) */
+ tracking->act_track= NULL;
+ }
+ }
+ else if(tracking->act_track!=userdata.track) {
+ MovieTrackingMarker *marker;
+ SelectUserData selectdata = {SEL_DESELECT};
+
+ tracking->act_track= userdata.track;
+
+ /* make active track be centered to screen */
+ marker= BKE_tracking_get_marker(userdata.track, sc->user.framenr);
+
+ clip_view_center_to_point(sc, marker->pos[0], marker->pos[1]);
+
+ /* deselect all knots on newly selected curve */
+ clip_graph_tracking_iterate(sc, &selectdata, toggle_selection_cb);
+ }
+
+ return 1;
+ }
+
+ return 0;
+}
+
+static int mouse_select(bContext *C, float co[2], int extend)
+{
+ int sel= 0;
+
+ /* first try to select knot on selected curves */
+ sel= mouse_select_knot(C, co, extend);
+
+ if(!sel) {
+ /* if there's no close enough knot to mouse osition, select nearest curve */
+ sel= mouse_select_curve(C, co, extend);
+ }
+
+ if(sel)
+ WM_event_add_notifier(C, NC_GEOM|ND_SELECT, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+static int select_exec(bContext *C, wmOperator *op)
+{
+ float co[2];
+ int extend= RNA_boolean_get(op->ptr, "extend");
+
+ RNA_float_get_array(op->ptr, "location", co);
+
+ return mouse_select(C, co, extend);
+}
+
+static int select_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ ARegion *ar= CTX_wm_region(C);
+ float co[2];
+
+ UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &co[0], &co[1]);
+ RNA_float_set_array(op->ptr, "location", co);
+
+ return select_exec(C, op);
+}
+
+void CLIP_OT_graph_select(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Select";
+ ot->description= "Select graph curves";
+ ot->idname= "CLIP_OT_graph_select";
+
+ /* api callbacks */
+ ot->exec= select_exec;
+ ot->invoke= select_invoke;
+ ot->poll= ED_space_clip_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX,
+ "Location", "Mouse location to select nearest entity closest to", -100.0f, 100.0f);
+ RNA_def_boolean(ot->srna, "extend", 0,
+ "Extend", "Extend selection rather than clearing the existing selection");
+}
+
+/******************** delete curve operator ********************/
+
+static int delete_curve_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ SpaceClip *sc= CTX_wm_space_clip(C);
+ MovieClip *clip= ED_space_clip(sc);
+ MovieTracking *tracking= &clip->tracking;
+
+ if(tracking->act_track)
+ clip_delete_track(C, clip, tracking->act_track);
+
+ return OPERATOR_FINISHED;
+}
+
+void CLIP_OT_graph_delete_curve(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Delete Curve";
+ ot->description= "Delete selected curves";
+ ot->idname= "CLIP_OT_graph_delete_curve";
+
+ /* api callbacks */
+ ot->invoke= WM_operator_confirm;
+ ot->exec= delete_curve_exec;
+ ot->poll= ED_space_clip_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/******************** delete knot operator ********************/
+
+static int delete_knot_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ SpaceClip *sc= CTX_wm_space_clip(C);
+ MovieClip *clip= ED_space_clip(sc);
+ MovieTracking *tracking= &clip->tracking;
+
+ if(tracking->act_track) {
+ int a= 0;
+ MovieTrackingTrack *track= tracking->act_track;
+
+ while(a<track->markersnr) {
+ MovieTrackingMarker *marker= &track->markers[a];
+
+ if(marker->flag&MARKER_GRAPH_SEL)
+ clip_delete_marker(C, clip, track, marker);
+ else
+ a++;
+ }
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void CLIP_OT_graph_delete_knot(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Delete Knot";
+ ot->description= "Delete curve knots";
+ ot->idname= "CLIP_OT_graph_delete_knot";
+
+ /* api callbacks */
+ ot->exec= delete_knot_exec;
+ ot->poll= ED_space_clip_poll;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}