Blender V2.61 - r43446

clip_graph_ops.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version. 
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2011 Blender Foundation.
00019  * All rights reserved.
00020  *
00021  *
00022  * Contributor(s): Blender Foundation,
00023  *                 Sergey Sharybin
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  */
00027 
00032 #include "DNA_object_types.h"   /* SELECT */
00033 
00034 #include "MEM_guardedalloc.h"
00035 
00036 #include "BLI_utildefines.h"
00037 #include "BLI_math.h"
00038 #include "BLI_listbase.h"
00039 
00040 #include "BKE_context.h"
00041 #include "BKE_movieclip.h"
00042 #include "BKE_tracking.h"
00043 
00044 #include "WM_api.h"
00045 #include "WM_types.h"
00046 
00047 #include "ED_screen.h"
00048 #include "ED_clip.h"
00049 
00050 #include "UI_interface.h"
00051 
00052 #include "RNA_access.h"
00053 #include "RNA_define.h"
00054 
00055 #include "UI_view2d.h"
00056 
00057 #include "clip_intern.h"    // own include
00058 
00059 /******************** common graph-editing utilities ********************/
00060 
00061 typedef struct {
00062     int action;
00063 } SelectUserData;
00064 
00065 static void toggle_selection_cb(void *userdata, MovieTrackingMarker *marker)
00066 {
00067     SelectUserData *data= (SelectUserData *)userdata;
00068 
00069     switch(data->action) {
00070         case SEL_SELECT:
00071             marker->flag|= MARKER_GRAPH_SEL;
00072             break;
00073         case SEL_DESELECT:
00074             marker->flag&= ~MARKER_GRAPH_SEL;
00075             break;
00076         case SEL_INVERT:
00077             marker->flag^= MARKER_GRAPH_SEL;
00078             break;
00079     }
00080 }
00081 
00082 /******************** mouse select operator ********************/
00083 
00084 typedef struct {
00085     int coord,      /* coordinate index of found entuty (0 = X-axis, 1 = Y-axis) */
00086         has_prev;       /* if there's valid coordinate of previous point of curve segment */
00087 
00088     float min_dist,     /* minimal distance between mouse and currently found entuty */
00089           mouse_co[2],  /* mouse coordinate */
00090           prev_co[2],   /* coordinate of previeous point of segment */
00091           min_co[2];    /* coordinate of entity with minimal distance */
00092 
00093     MovieTrackingTrack *track;  /* nearest found track */
00094     MovieTrackingMarker *marker;    /* nearest found marker */
00095 } MouseSelectUserData;
00096 
00097 static void find_nearest_tracking_segment_cb(void *userdata, MovieTrackingTrack *track,
00098             MovieTrackingMarker *marker, int coord, float val)
00099 {
00100     MouseSelectUserData *data= userdata;
00101     float co[2]= {marker->framenr, val};
00102 
00103     if(data->has_prev) {
00104         float d= dist_to_line_segment_v2(data->mouse_co, data->prev_co, co);
00105 
00106         if(data->track==NULL || d<data->min_dist) {
00107             data->track= track;
00108             data->min_dist= d;
00109             data->coord= coord;
00110             copy_v2_v2(data->min_co, co);
00111         }
00112     }
00113 
00114     data->has_prev= 1;
00115     copy_v2_v2(data->prev_co, co);
00116 }
00117 
00118 void find_nearest_tracking_segment_end_cb(void *userdata)
00119 {
00120     MouseSelectUserData *data= userdata;
00121 
00122     data->has_prev= 0;
00123 }
00124 
00125 static void find_nearest_tracking_knot_cb(void *userdata, MovieTrackingTrack *track,
00126             MovieTrackingMarker *marker, int coord, float val)
00127 {
00128     MouseSelectUserData *data= userdata;
00129     float dx= marker->framenr-data->mouse_co[0], dy= val-data->mouse_co[1];
00130     float d= dx*dx+dy*dy;
00131 
00132     if(data->marker==NULL || d<data->min_dist) {
00133         float co[2]= {marker->framenr, val};
00134 
00135         data->track= track;
00136         data->marker= marker;
00137         data->min_dist= d;
00138         data->coord= coord;
00139         copy_v2_v2(data->min_co, co);
00140     }
00141 
00142 }
00143 
00144 static void mouse_select_init_data(MouseSelectUserData *userdata, float *co)
00145 {
00146     memset(userdata, 0, sizeof(MouseSelectUserData));
00147     userdata->min_dist= FLT_MAX;
00148     copy_v2_v2(userdata->mouse_co, co);
00149 }
00150 
00151 static int mouse_select_knot(bContext *C, float co[2], int extend)
00152 {
00153     SpaceClip *sc= CTX_wm_space_clip(C);
00154     MovieClip *clip= ED_space_clip(sc);
00155     ARegion *ar= CTX_wm_region(C);
00156     View2D *v2d= &ar->v2d;
00157     MovieTracking *tracking= &clip->tracking;
00158     MovieTrackingTrack *act_track= BKE_tracking_active_track(tracking);
00159     static const int delta= 6;
00160 
00161     if(act_track) {
00162         MouseSelectUserData userdata;
00163 
00164         mouse_select_init_data(&userdata, co);
00165         clip_graph_tracking_values_iterate_track(sc, act_track,
00166                     &userdata, find_nearest_tracking_knot_cb, NULL, NULL);
00167 
00168         if(userdata.marker) {
00169             int x1, y1, x2, y2;
00170 
00171             UI_view2d_view_to_region(v2d, co[0], co[1], &x1, &y1);
00172             UI_view2d_view_to_region(v2d, userdata.min_co[0], userdata.min_co[1], &x2, &y2);
00173 
00174             if(abs(x2-x1)<=delta && abs(y2-y1)<=delta) {
00175                 if(!extend) {
00176                     SelectUserData selectdata = {SEL_DESELECT};
00177                     clip_graph_tracking_iterate(sc, &selectdata, toggle_selection_cb);
00178                 }
00179 
00180                 userdata.marker->flag|= MARKER_GRAPH_SEL;
00181 
00182                 return 1;
00183             }
00184         }
00185     }
00186 
00187     return 0;
00188 }
00189 
00190 static int mouse_select_curve(bContext *C, float co[2], int extend)
00191 {
00192     SpaceClip *sc= CTX_wm_space_clip(C);
00193     MovieClip *clip= ED_space_clip(sc);
00194     MovieTracking *tracking= &clip->tracking;
00195     MovieTrackingTrack *act_track= BKE_tracking_active_track(tracking);
00196     MouseSelectUserData userdata;
00197 
00198     mouse_select_init_data(&userdata, co);
00199     clip_graph_tracking_values_iterate(sc, &userdata, find_nearest_tracking_segment_cb, NULL, find_nearest_tracking_segment_end_cb);
00200 
00201     if(userdata.track) {
00202         if(extend) {
00203             if(act_track==userdata.track) {
00204                 /* currently only single curve can be selected (selected curve represents active track) */
00205                 act_track= NULL;
00206             }
00207         }
00208         else if(act_track!=userdata.track) {
00209             MovieTrackingMarker *marker;
00210             SelectUserData selectdata = {SEL_DESELECT};
00211 
00212             tracking->act_track= userdata.track;
00213 
00214             /* make active track be centered to screen */
00215             marker= BKE_tracking_get_marker(userdata.track, sc->user.framenr);
00216 
00217             clip_view_center_to_point(sc, marker->pos[0], marker->pos[1]);
00218 
00219             /* deselect all knots on newly selected curve */
00220             clip_graph_tracking_iterate(sc, &selectdata, toggle_selection_cb);
00221         }
00222 
00223         return 1;
00224     }
00225 
00226     return 0;
00227 }
00228 
00229 static int mouse_select(bContext *C, float co[2], int extend)
00230 {
00231     int sel= 0;
00232 
00233     /* first try to select knot on selected curves */
00234     sel= mouse_select_knot(C, co, extend);
00235 
00236     if(!sel) {
00237         /* if there's no close enough knot to mouse osition, select nearest curve */
00238         sel= mouse_select_curve(C, co, extend);
00239     }
00240 
00241     if(sel)
00242         WM_event_add_notifier(C, NC_GEOM|ND_SELECT, NULL);
00243 
00244     return OPERATOR_FINISHED;
00245 }
00246 
00247 static int select_exec(bContext *C, wmOperator *op)
00248 {
00249     float co[2];
00250     int  extend= RNA_boolean_get(op->ptr, "extend");
00251 
00252     RNA_float_get_array(op->ptr, "location", co);
00253 
00254     return mouse_select(C, co, extend);
00255 }
00256 
00257 static int select_invoke(bContext *C, wmOperator *op, wmEvent *event)
00258 {
00259     ARegion *ar= CTX_wm_region(C);
00260     float co[2];
00261 
00262     UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &co[0], &co[1]);
00263     RNA_float_set_array(op->ptr, "location", co);
00264 
00265     return select_exec(C, op);
00266 }
00267 
00268 void CLIP_OT_graph_select(wmOperatorType *ot)
00269 {
00270     /* identifiers */
00271     ot->name= "Select";
00272     ot->description= "Select graph curves";
00273     ot->idname= "CLIP_OT_graph_select";
00274 
00275     /* api callbacks */
00276     ot->exec= select_exec;
00277     ot->invoke= select_invoke;
00278     ot->poll= ED_space_clip_poll;
00279 
00280     /* flags */
00281     ot->flag= OPTYPE_UNDO;
00282 
00283     /* properties */
00284     RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX,
00285         "Location", "Mouse location to select nearest entity", -100.0f, 100.0f);
00286     RNA_def_boolean(ot->srna, "extend", 0,
00287         "Extend", "Extend selection rather than clearing the existing selection");
00288 }
00289 
00290 /******************** delete curve operator ********************/
00291 
00292 static int delete_curve_exec(bContext *C, wmOperator *UNUSED(op))
00293 {
00294     SpaceClip *sc= CTX_wm_space_clip(C);
00295     MovieClip *clip= ED_space_clip(sc);
00296     MovieTracking *tracking= &clip->tracking;
00297     ListBase *tracksbase= BKE_tracking_get_tracks(tracking);
00298     MovieTrackingTrack *act_track= BKE_tracking_active_track(tracking);
00299 
00300     if(act_track)
00301         clip_delete_track(C, clip, tracksbase, act_track);
00302 
00303     return OPERATOR_FINISHED;
00304 }
00305 
00306 void CLIP_OT_graph_delete_curve(wmOperatorType *ot)
00307 {
00308     /* identifiers */
00309     ot->name= "Delete Curve";
00310     ot->description= "Delete selected curves";
00311     ot->idname= "CLIP_OT_graph_delete_curve";
00312 
00313     /* api callbacks */
00314     ot->invoke= WM_operator_confirm;
00315     ot->exec= delete_curve_exec;
00316     ot->poll= ED_space_clip_poll;
00317 
00318     /* flags */
00319     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00320 }
00321 
00322 /******************** delete knot operator ********************/
00323 
00324 static int delete_knot_exec(bContext *C, wmOperator *UNUSED(op))
00325 {
00326     SpaceClip *sc= CTX_wm_space_clip(C);
00327     MovieClip *clip= ED_space_clip(sc);
00328     MovieTracking *tracking= &clip->tracking;
00329     ListBase *tracksbase= BKE_tracking_get_tracks(tracking);
00330     MovieTrackingTrack *act_track= BKE_tracking_active_track(tracking);
00331 
00332     if(act_track) {
00333         int a= 0;
00334 
00335         while(a<act_track->markersnr) {
00336             MovieTrackingMarker *marker= &act_track->markers[a];
00337 
00338             if(marker->flag&MARKER_GRAPH_SEL)
00339                 clip_delete_marker(C, clip, tracksbase, act_track, marker);
00340             else
00341                 a++;
00342         }
00343     }
00344 
00345     return OPERATOR_FINISHED;
00346 }
00347 
00348 void CLIP_OT_graph_delete_knot(wmOperatorType *ot)
00349 {
00350     /* identifiers */
00351     ot->name= "Delete Knot";
00352     ot->description= "Delete curve knots";
00353     ot->idname= "CLIP_OT_graph_delete_knot";
00354 
00355     /* api callbacks */
00356     ot->exec= delete_knot_exec;
00357     ot->poll= ED_space_clip_poll;
00358 
00359     /* flags */
00360     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00361 }