Blender V2.61 - r43446
|
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 }