Blender  V2.59
anim_markers.c
Go to the documentation of this file.
00001 /*
00002  * $Id: anim_markers.c 38086 2011-07-04 15:09:02Z campbellbarton $
00003  *
00004  * ***** BEGIN GPL LICENSE BLOCK *****
00005  *
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License
00008  * as published by the Free Software Foundation; either version 2
00009  * of the License, or (at your option) any later version. 
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software Foundation,
00018  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00019  *
00020  * The Original Code is Copyright (C) 2008 Blender Foundation.
00021  * All rights reserved.
00022  *
00023  * 
00024  * Contributor(s): Blender Foundation
00025  *
00026  * ***** END GPL LICENSE BLOCK *****
00027  */
00028 
00034 #include <math.h>
00035 
00036 #include "MEM_guardedalloc.h"
00037 
00038 #include "DNA_scene_types.h"
00039 #include "DNA_object_types.h"
00040 
00041 #include "RNA_access.h"
00042 #include "RNA_define.h"
00043 #include "RNA_enum_types.h"
00044 
00045 #include "BLI_blenlib.h"
00046 #include "BLI_utildefines.h"
00047 
00048 #include "BKE_context.h"
00049 #include "BKE_fcurve.h"
00050 #include "BKE_main.h"
00051 #include "BKE_report.h"
00052 #include "BKE_scene.h"
00053 #include "BKE_screen.h"
00054 
00055 #include "WM_api.h"
00056 #include "WM_types.h"
00057 
00058 #include "BIF_gl.h"
00059 #include "BIF_glutil.h"
00060 
00061 #include "UI_interface.h"
00062 #include "UI_interface_icons.h"
00063 #include "UI_view2d.h"
00064 #include "UI_resources.h"
00065 
00066 #include "ED_anim_api.h"
00067 #include "ED_markers.h"
00068 #include "ED_screen.h"
00069 #include "ED_util.h"
00070 #include "ED_numinput.h"
00071 #include "ED_object.h"
00072 #include "ED_transform.h"
00073 #include "ED_types.h"
00074 
00075 /* ************* Marker API **************** */
00076 
00077 /* helper function for getting the list of markers to work on */
00078 static ListBase *context_get_markers(Scene *scene, ScrArea *sa)
00079 {
00080         /* local marker sets... */
00081         if (sa) {
00082                 if (sa->spacetype == SPACE_ACTION) {
00083                         SpaceAction *saction = (SpaceAction *)sa->spacedata.first;
00084                         
00085                         /* local markers can only be shown when there's only a single active action to grab them from 
00086                          *      - flag only takes effect when there's an action, otherwise it can get too confusing?
00087                          */
00088                         if (ELEM(saction->mode, SACTCONT_ACTION, SACTCONT_SHAPEKEY) && (saction->action)) 
00089                         {
00090                                 if (saction->flag & SACTION_POSEMARKERS_SHOW)
00091                                         return &saction->action->markers;
00092                         }
00093                 }
00094         }
00095         
00096         /* default to using the scene's markers */
00097         return &scene->markers;
00098 }
00099 
00100 /* ............. */
00101 
00102 /* public API for getting markers from context */
00103 ListBase *ED_context_get_markers(const bContext *C)
00104 {
00105         return context_get_markers(CTX_data_scene(C), CTX_wm_area(C));
00106 }
00107 
00108 /* public API for getting markers from "animation" context */
00109 ListBase *ED_animcontext_get_markers(const bAnimContext *ac)
00110 {
00111         if (ac)
00112                 return context_get_markers(ac->scene, ac->sa);
00113         else
00114                 return NULL;
00115 }
00116 
00117 /* --------------------------------- */
00118 
00119 /* Apply some transformation to markers after the fact 
00120  * < markers: list of markers to affect - this may or may not be the scene markers list, so don't assume anything
00121  * < scene: current scene (for getting current frame)
00122  * < mode: (TfmMode) transform mode that this transform is for
00123  * < value: from the transform code, this is t->vec[0] (which is delta transform for grab/extend, and scale factor for scale)
00124  * < side: (B/L/R) for 'extend' functionality, which side of current frame to use
00125  */
00126 int ED_markers_post_apply_transform (ListBase *markers, Scene *scene, int mode, float value, char side)
00127 {
00128         TimeMarker *marker;
00129         float cfra = (float)CFRA;
00130         int changed = 0;
00131         
00132         /* sanity check */
00133         if (markers == NULL)
00134                 return changed;
00135         
00136         /* affect selected markers - it's unlikely that we will want to affect all in this way? */
00137         for (marker = markers->first; marker; marker = marker->next) {
00138                 if (marker->flag & SELECT) {
00139                         switch (mode) {
00140                                 case TFM_TIME_TRANSLATE:
00141                                 case TFM_TIME_EXTEND:
00142                                 {
00143                                         /* apply delta if marker is on the right side of the current frame */
00144                                         if ((side=='B') ||
00145                                                 (side=='L' && marker->frame < cfra) || 
00146                                             (side=='R' && marker->frame >= cfra))
00147                                         {
00148                                                 marker->frame += (int)floorf(value + 0.5f);
00149                                                 changed++;
00150                                         }
00151                                 }
00152                                         break;
00153                                         
00154                                 case TFM_TIME_SCALE:
00155                                 {       
00156                                         /* rescale the distance between the marker and the current frame */
00157                                         marker->frame= cfra + (int)floorf(((float)(marker->frame - cfra) * value) + 0.5f);
00158                                         changed++;
00159                                 }
00160                                         break;
00161                         }
00162                 }
00163         }
00164         
00165         return changed;
00166 }
00167 
00168 /* --------------------------------- */
00169 
00170 /* Get the marker that is closest to this point */
00171 /* XXX for select, the min_dist should be small */
00172 TimeMarker *ED_markers_find_nearest_marker (ListBase *markers, float x) 
00173 {
00174         TimeMarker *marker, *nearest=NULL;
00175         float dist, min_dist= 1000000;
00176         
00177         if (markers) {
00178                 for (marker= markers->first; marker; marker= marker->next) {
00179                         dist = ABS((float)marker->frame - x);
00180                         
00181                         if (dist < min_dist) {
00182                                 min_dist= dist;
00183                                 nearest= marker;
00184                         }
00185                 }
00186         }
00187         
00188         return nearest;
00189 }
00190 
00191 /* Return the time of the marker that occurs on a frame closest to the given time */
00192 int ED_markers_find_nearest_marker_time (ListBase *markers, float x)
00193 {
00194         TimeMarker *nearest= ED_markers_find_nearest_marker(markers, x);
00195         return (nearest) ? (nearest->frame) : (int)floor(x + 0.5f);
00196 }
00197 
00198 
00199 void ED_markers_get_minmax (ListBase *markers, short sel, float *first, float *last)
00200 {
00201         TimeMarker *marker;
00202         float min, max;
00203         int selcount = 0;
00204         
00205         /* sanity check */
00206         //printf("markers = %p -  %p, %p \n", markers, markers->first, markers->last);
00207         if (markers == NULL) {
00208                 *first = 0.0f;
00209                 *last = 0.0f;
00210                 return;
00211         }
00212         
00213         if (markers->first && markers->last) {
00214                 TimeMarker *fm= markers->first;
00215                 TimeMarker *lm= markers->last;
00216                 
00217                 min= (float)fm->frame;
00218                 max= (float)lm->frame;
00219         }
00220         else {
00221                 *first = 0.0f;
00222                 *last = 0.0f;
00223                 return;
00224         }
00225         
00226         /* count how many markers are usable - see later */
00227         if (sel) {
00228                 for (marker= markers->first; marker; marker= marker->next) {
00229                         if (marker->flag & SELECT)
00230                                 selcount++;
00231                 }
00232         }
00233         else
00234                 selcount= BLI_countlist(markers);
00235         
00236         /* if only selected are to be considered, only consider the selected ones
00237          * (optimisation for not searching list) 
00238          */
00239         if (selcount > 1) {
00240                 for (marker= markers->first; marker; marker= marker->next) {
00241                         if (sel) {
00242                                 if (marker->flag & SELECT) {
00243                                         if (marker->frame < min)
00244                                                 min= (float)marker->frame;
00245                                         if (marker->frame > max)
00246                                                 max= (float)marker->frame;
00247                                 }
00248                         }
00249                         else {
00250                                 if (marker->frame < min)
00251                                         min= (float)marker->frame;
00252                                 if (marker->frame > max)
00253                                         max= (float)marker->frame;
00254                         }       
00255                 }
00256         }
00257         
00258         /* set the min/max values */
00259         *first= min;
00260         *last= max;
00261 }
00262 
00263 /* --------------------------------- */
00264 
00265 /* Adds a marker to list of cfra elems */
00266 static void add_marker_to_cfra_elem(ListBase *lb, TimeMarker *marker, short only_sel)
00267 {
00268         CfraElem *ce, *cen;
00269         
00270         /* should this one only be considered if it is selected? */
00271         if ((only_sel) && ((marker->flag & SELECT)==0))
00272                 return;
00273         
00274         /* insertion sort - try to find a previous cfra elem */
00275         for (ce= lb->first; ce; ce= ce->next) {
00276                 if (ce->cfra == marker->frame) {
00277                         /* do because of double keys */
00278                         if (marker->flag & SELECT) 
00279                                 ce->sel= marker->flag;
00280                         return;
00281                 }
00282                 else if (ce->cfra > marker->frame) break;
00283         }       
00284         
00285         cen= MEM_callocN(sizeof(CfraElem), "add_to_cfra_elem"); 
00286         if (ce) BLI_insertlinkbefore(lb, ce, cen);
00287         else BLI_addtail(lb, cen);
00288 
00289         cen->cfra= marker->frame;
00290         cen->sel= marker->flag;
00291 }
00292 
00293 /* This function makes a list of all the markers. The only_sel
00294  * argument is used to specify whether only the selected markers
00295  * are added.
00296  */
00297 void ED_markers_make_cfra_list(ListBase *markers, ListBase *lb, short only_sel)
00298 {
00299         TimeMarker *marker;
00300         
00301         if (markers == NULL)
00302                 return;
00303         
00304         for (marker= markers->first; marker; marker= marker->next)
00305                 add_marker_to_cfra_elem(lb, marker, only_sel);
00306 }
00307 
00308 /* --------------------------------- */
00309 
00310 /* Get the first selected marker */
00311 TimeMarker *ED_markers_get_first_selected(ListBase *markers)
00312 {
00313         TimeMarker *marker;
00314         
00315         if (markers) {
00316                 for (marker = markers->first; marker; marker = marker->next) {
00317                         if (marker->flag & SELECT)
00318                                 return marker;
00319                 }
00320         }
00321         
00322         return NULL;
00323 }
00324 
00325 /* --------------------------------- */
00326 
00327 /* Print debugging prints of list of markers 
00328  * BSI's: do NOT make static or put in if-defs as "unused code". That's too much trouble when we need to use for quick debuggging!
00329  */
00330 void debug_markers_print_list(ListBase *markers)
00331 {
00332         TimeMarker *marker;
00333         
00334         if (markers == NULL) {
00335                 printf("No markers list to print debug for\n");
00336                 return;
00337         }
00338         
00339         printf("List of markers follows: -----\n");
00340         
00341         for (marker = markers->first; marker; marker = marker->next) {
00342                 printf("\t'%s' on %d at %p with %d\n", marker->name, marker->frame, (void *)marker, marker->flag);
00343         }
00344         
00345         printf("End of list ------------------\n");
00346 }
00347 
00348 /* ************* Marker Drawing ************ */
00349 
00350 /* function to draw markers */
00351 static void draw_marker(View2D *v2d, TimeMarker *marker, int cfra, int flag)
00352 {
00353         float xpos, ypixels, xscale, yscale;
00354         int icon_id= 0;
00355         
00356         xpos = marker->frame;
00357         
00358         /* no time correction for framelen! space is drawn with old values */
00359         ypixels= v2d->mask.ymax-v2d->mask.ymin;
00360         UI_view2d_getscale(v2d, &xscale, &yscale);
00361         
00362         glScalef(1.0f/xscale, 1.0f, 1.0f);
00363         
00364         glEnable(GL_BLEND);
00365         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);                      
00366         
00367         /* vertical line - dotted */
00368 #ifdef DURIAN_CAMERA_SWITCH
00369         if ((marker->camera) || (flag & DRAW_MARKERS_LINES))
00370 #else
00371         if (flag & DRAW_MARKERS_LINES)
00372 #endif
00373         {
00374                 setlinestyle(3);
00375                 
00376                 if (marker->flag & SELECT)
00377                         glColor4ub(255, 255, 255, 96);
00378                 else
00379                         glColor4ub(0, 0, 0, 96);
00380                 
00381                 glBegin(GL_LINES);
00382                         glVertex2f((xpos*xscale)+0.5f, 12.0f);
00383                         glVertex2f((xpos*xscale)+0.5f, (v2d->cur.ymax+12.0f)*yscale);
00384                 glEnd();
00385                 
00386                 setlinestyle(0);
00387         }
00388         
00389         /* 5 px to offset icon to align properly, space / pixels corrects for zoom */
00390         if (flag & DRAW_MARKERS_LOCAL) {
00391                 icon_id= (marker->flag & ACTIVE) ? ICON_PMARKER_ACT : 
00392                 (marker->flag & SELECT) ? ICON_PMARKER_SEL : 
00393                 ICON_PMARKER;
00394         }
00395         else {
00396                 icon_id= (marker->flag & SELECT) ? ICON_MARKER_HLT : 
00397                 ICON_MARKER;
00398         }
00399         
00400         UI_icon_draw(xpos*xscale-5.0f, 16.0f, icon_id);
00401         
00402         glDisable(GL_BLEND);
00403         
00404         /* and the marker name too, shifted slightly to the top-right */
00405         if (marker->name && marker->name[0]) {
00406                 float x, y;
00407                 
00408                 if (marker->flag & SELECT) {
00409                         UI_ThemeColor(TH_TEXT_HI);
00410                         x= xpos*xscale + 4.0f;
00411                         y= (ypixels <= 39.0f)? (ypixels-10.0f) : 29.0f;
00412                 }
00413                 else {
00414                         UI_ThemeColor(TH_TEXT);
00415                         if((marker->frame <= cfra) && (marker->frame+5 > cfra)) {
00416                                 x= xpos*xscale + 4.0f;
00417                                 y= (ypixels <= 39.0f)? (ypixels - 10.0f) : 29.0f;
00418                         }
00419                         else {
00420                                 x= xpos*xscale + 4.0f;
00421                                 y= 17.0f;
00422                         }
00423                 }
00424 
00425 #ifdef DURIAN_CAMERA_SWITCH
00426                 if(marker->camera && (marker->camera->restrictflag & OB_RESTRICT_RENDER)) {
00427                         float col[4];
00428                         glGetFloatv(GL_CURRENT_COLOR, col);
00429                         col[3]= 0.4;
00430                         glColor4fv(col);
00431                 }
00432 #endif
00433 
00434                 UI_DrawString(x, y, marker->name);
00435         }
00436         
00437         glScalef(xscale, 1.0f, 1.0f);
00438 }
00439 
00440 /* Draw Scene-Markers in time window */
00441 void draw_markers_time(const bContext *C, int flag)
00442 {
00443         ListBase *markers= ED_context_get_markers(C);
00444         View2D *v2d= UI_view2d_fromcontext(C);
00445         TimeMarker *marker;
00446         
00447         if (markers == NULL)
00448                 return;
00449         
00450         /* unselected markers are drawn at the first time */
00451         for (marker= markers->first; marker; marker= marker->next) {
00452                 if ((marker->flag & SELECT) == 0) 
00453                         draw_marker(v2d, marker, CTX_data_scene(C)->r.cfra, flag);
00454         }
00455         
00456         /* selected markers are drawn later */
00457         for (marker= markers->first; marker; marker= marker->next) {
00458                 if (marker->flag & SELECT) 
00459                         draw_marker(v2d, marker, CTX_data_scene(C)->r.cfra, flag);
00460         }
00461 }
00462 
00463 /* ************************ Marker Wrappers API ********************* */
00464 /* These wrappers allow marker operators to function within the confines 
00465  * of standard animation editors, such that they can coexist with the 
00466  * primary operations of those editors.
00467  */
00468 
00469 /* ------------------------ */
00470 
00471 /* special poll() which checks if there are selected markers first */
00472 static int ed_markers_poll_selected_markers(bContext *C)
00473 {
00474         ListBase *markers = ED_context_get_markers(C);
00475         
00476         /* first things first: markers can only exist in timeline views */
00477         if (ED_operator_animview_active(C) == 0)
00478                 return 0;
00479                 
00480         /* check if some marker is selected */
00481         return ED_markers_get_first_selected(markers) != NULL;
00482 }
00483 
00484 /* special poll() which checks if there are any markers at all first */
00485 static int ed_markers_poll_markers_exist(bContext *C)
00486 {
00487         ListBase *markers = ED_context_get_markers(C);
00488         
00489         /* first things first: markers can only exist in timeline views */
00490         if (ED_operator_animview_active(C) == 0)
00491                 return 0;
00492                 
00493         /* list of markers must exist, as well as some markers in it! */
00494         return (markers && markers->first);
00495 }
00496  
00497 /* ------------------------ */ 
00498 
00499 /* Second-tier invoke() callback that performs context validation before running the  
00500  * "custom"/third-tier invoke() callback supplied as the last arg (which would normally
00501  * be the operator's invoke() callback elsewhere)
00502  *
00503  * < invoke_func: (fn(bContext*, wmOperator*, wmEvent*)=int) "standard" invoke function 
00504  *                      that operator would otherwise have used. If NULL, the operator's standard
00505  *                      exec() callback will be called instead in the appropriate places.
00506  */
00507 static int ed_markers_opwrap_invoke_custom(bContext *C, wmOperator *op, wmEvent *evt, 
00508                 int (*invoke_func)(bContext*,wmOperator*,wmEvent*))
00509 {
00510         ScrArea *sa = CTX_wm_area(C);
00511         int retval = OPERATOR_PASS_THROUGH;
00512         
00513         /* removed check for Y coord of event, keymap has bounbox now */
00514         
00515         /* allow operator to run now */
00516         if (invoke_func)
00517                 retval = invoke_func(C, op, evt);
00518         else if (op->type->exec)
00519                 retval = op->type->exec(C, op);
00520         else
00521                 BKE_report(op->reports, RPT_ERROR, "Programming error: operator doesn't actually have code to do anything!");
00522                 
00523         /* return status modifications - for now, make this spacetype dependent as above */
00524         if (sa->spacetype != SPACE_TIME) {
00525                 /* unless successful, must add "pass-through" to let normal operator's have a chance at tackling this event */
00526                 if (retval != OPERATOR_FINISHED)
00527                         retval |= OPERATOR_PASS_THROUGH;
00528         }
00529         
00530         return retval;
00531 }
00532 
00533 /* standard wrapper - first-tier invoke() callback to be directly assigned to operator typedata
00534  * for operators which don't need any special invoke calls. Any operators with special invoke calls
00535  * though will need to implement their own wrapper which calls the second-tier callback themselves
00536  * (passing through the custom invoke function they use)
00537  */
00538 static int ed_markers_opwrap_invoke(bContext *C, wmOperator *op, wmEvent *evt)
00539 {
00540         return ed_markers_opwrap_invoke_custom(C, op, evt, NULL);
00541 }
00542 
00543 /* ************************** add markers *************************** */
00544 
00545 /* add TimeMarker at curent frame */
00546 static int ed_marker_add(bContext *C, wmOperator *UNUSED(op))
00547 {
00548         ListBase *markers= ED_context_get_markers(C);
00549         TimeMarker *marker;
00550         int frame= CTX_data_scene(C)->r.cfra;
00551         
00552         if (markers == NULL)
00553                 return OPERATOR_CANCELLED;
00554         
00555         /* two markers can't be at the same place */
00556         for (marker= markers->first; marker; marker= marker->next) {
00557                 if (marker->frame == frame) 
00558                         return OPERATOR_CANCELLED;
00559         }
00560         
00561         /* deselect all */
00562         for (marker= markers->first; marker; marker= marker->next)
00563                 marker->flag &= ~SELECT;
00564         
00565         marker = MEM_callocN(sizeof(TimeMarker), "TimeMarker");
00566         marker->flag= SELECT;
00567         marker->frame= frame;
00568         BLI_snprintf(marker->name, sizeof(marker->name), "F_%02d", frame); // XXX - temp code only
00569         BLI_addtail(markers, marker);
00570         
00571         WM_event_add_notifier(C, NC_SCENE|ND_MARKERS, NULL);
00572         WM_event_add_notifier(C, NC_ANIMATION|ND_MARKERS, NULL);
00573         
00574         return OPERATOR_FINISHED;
00575 }
00576 
00577 static void MARKER_OT_add(wmOperatorType *ot)
00578 {
00579         /* identifiers */
00580         ot->name= "Add Time Marker";
00581         ot->description= "Add a new time marker";
00582         ot->idname= "MARKER_OT_add";
00583         
00584         /* api callbacks */
00585         ot->exec= ed_marker_add;
00586         ot->invoke = ed_markers_opwrap_invoke;
00587         ot->poll= ED_operator_animview_active;
00588         
00589         /* flags */
00590         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00591 }
00592 
00593 /* ************************** transform markers *************************** */
00594 
00595 
00596 /* operator state vars used:  
00597         frs: delta movement
00598 
00599 functions:
00600 
00601         init()   check selection, add customdata with old values and some lookups
00602 
00603         apply()  do the actual movement
00604 
00605         exit()  cleanup, send notifier
00606 
00607         cancel() to escape from modal
00608 
00609 callbacks:
00610 
00611         exec()  calls init, apply, exit 
00612 
00613         invoke() calls init, adds modal handler
00614 
00615         modal() accept modal events while doing it, ends with apply and exit, or cancel
00616 
00617 */
00618 
00619 typedef struct MarkerMove {
00620         SpaceLink *slink;
00621         ListBase *markers;
00622         int event_type;         /* store invoke-event, to verify */
00623         int *oldframe, evtx, firstx;
00624         NumInput num;
00625 } MarkerMove;
00626 
00627 /* copy selection to temp buffer */
00628 /* return 0 if not OK */
00629 static int ed_marker_move_init(bContext *C, wmOperator *op)
00630 {
00631         ListBase *markers= ED_context_get_markers(C);
00632         MarkerMove *mm;
00633         TimeMarker *marker;
00634         int totmark=0;
00635         int a;
00636 
00637         if(markers == NULL) return 0;
00638         
00639         for (marker= markers->first; marker; marker= marker->next)
00640                 if (marker->flag & SELECT) totmark++;
00641         
00642         if (totmark==0) return 0;
00643         
00644         op->customdata= mm= MEM_callocN(sizeof(MarkerMove), "Markermove");
00645         mm->slink= CTX_wm_space_data(C);
00646         mm->markers= markers;
00647         mm->oldframe= MEM_callocN(totmark*sizeof(int), "MarkerMove oldframe");
00648 
00649         initNumInput(&mm->num);
00650         mm->num.idx_max = 0; /* one axis */
00651         mm->num.flag |= NUM_NO_FRACTION;
00652         mm->num.increment = 1.0f;
00653         
00654         for (a=0, marker= markers->first; marker; marker= marker->next) {
00655                 if (marker->flag & SELECT) {
00656                         mm->oldframe[a]= marker->frame;
00657                         a++;
00658                 }
00659         }
00660         
00661         return 1;
00662 }
00663 
00664 /* free stuff */
00665 static void ed_marker_move_exit(bContext *C, wmOperator *op)
00666 {
00667         MarkerMove *mm= op->customdata;
00668         
00669         /* free data */
00670         MEM_freeN(mm->oldframe);
00671         MEM_freeN(op->customdata);
00672         op->customdata= NULL;
00673         
00674         /* clear custom header prints */
00675         ED_area_headerprint(CTX_wm_area(C), NULL);
00676 }
00677 
00678 static int ed_marker_move_invoke(bContext *C, wmOperator *op, wmEvent *evt)
00679 {
00680         if(ed_marker_move_init(C, op)) {
00681                 MarkerMove *mm= op->customdata;
00682                 
00683                 mm->evtx= evt->x;
00684                 mm->firstx= evt->x;
00685                 mm->event_type= evt->type;
00686                 
00687                 /* add temp handler */
00688                 WM_event_add_modal_handler(C, op);
00689                 
00690                 /* reset frs delta */
00691                 RNA_int_set(op->ptr, "frames", 0);
00692                 
00693                 return OPERATOR_RUNNING_MODAL;
00694         }
00695         
00696         return OPERATOR_CANCELLED;
00697 }
00698 
00699 static int ed_marker_move_invoke_wrapper(bContext *C, wmOperator *op, wmEvent *evt)
00700 {
00701         return ed_markers_opwrap_invoke_custom(C, op, evt, ed_marker_move_invoke);
00702 }
00703 
00704 /* note, init has to be called succesfully */
00705 static void ed_marker_move_apply(wmOperator *op)
00706 {
00707         MarkerMove *mm= op->customdata;
00708         TimeMarker *marker;
00709         int a, offs;
00710         
00711         offs= RNA_int_get(op->ptr, "frames");
00712         for (a=0, marker= mm->markers->first; marker; marker= marker->next) {
00713                 if (marker->flag & SELECT) {
00714                         marker->frame= mm->oldframe[a] + offs;
00715                         a++;
00716                 }
00717         }
00718 }
00719 
00720 /* only for modal */
00721 static int ed_marker_move_cancel(bContext *C, wmOperator *op)
00722 {
00723         RNA_int_set(op->ptr, "frames", 0);
00724         ed_marker_move_apply(op);
00725         ed_marker_move_exit(C, op);     
00726         
00727         WM_event_add_notifier(C, NC_SCENE|ND_MARKERS, NULL);
00728         WM_event_add_notifier(C, NC_ANIMATION|ND_MARKERS, NULL);
00729 
00730         return OPERATOR_CANCELLED;
00731 }
00732 
00733 
00734 
00735 static int ed_marker_move_modal(bContext *C, wmOperator *op, wmEvent *evt)
00736 {
00737         Scene *scene= CTX_data_scene(C);
00738         MarkerMove *mm= op->customdata;
00739         View2D *v2d= UI_view2d_fromcontext(C);
00740         TimeMarker *marker, *selmarker=NULL;
00741         float dx, fac;
00742         char str[256];
00743                 
00744         switch(evt->type) {
00745                 case ESCKEY:
00746                         ed_marker_move_cancel(C, op);
00747                         return OPERATOR_CANCELLED;
00748                 
00749                 case RIGHTMOUSE:
00750                         /* press = user manually demands transform to be cancelled */
00751                         if (evt->val == KM_PRESS) {
00752                                 ed_marker_move_cancel(C, op);
00753                                 return OPERATOR_CANCELLED;
00754                         }
00755                         /* else continue; <--- see if release event should be caught for tweak-end */
00756                 
00757                 case RETKEY:
00758                 case PADENTER:
00759                 case LEFTMOUSE:
00760                 case MIDDLEMOUSE:
00761                         if (WM_modal_tweak_exit(evt, mm->event_type)) {
00762                                 ed_marker_move_exit(C, op);
00763                                 WM_event_add_notifier(C, NC_SCENE|ND_MARKERS, NULL);
00764                                 WM_event_add_notifier(C, NC_ANIMATION|ND_MARKERS, NULL);
00765                                 return OPERATOR_FINISHED;
00766                         }
00767                         break;
00768                 case MOUSEMOVE:
00769                         if (hasNumInput(&mm->num))
00770                                 break;
00771                         
00772                         dx= v2d->mask.xmax-v2d->mask.xmin;
00773                         dx= (v2d->cur.xmax-v2d->cur.xmin)/dx;
00774                         
00775                         if (evt->x != mm->evtx) {       /* XXX maybe init for firsttime */
00776                                 int a, offs, totmark=0;
00777                                 
00778                                 mm->evtx= evt->x;
00779                                 
00780                                 fac= ((float)(evt->x - mm->firstx)*dx);
00781                                 
00782                                 if (ELEM(mm->slink->spacetype, SPACE_TIME, SPACE_SOUND)) 
00783                                         apply_keyb_grid(evt->shift, evt->ctrl, &fac, 0.0, FPS, 0.1*FPS, 0);
00784                                 else
00785                                         apply_keyb_grid(evt->shift, evt->ctrl, &fac, 0.0, 1.0, 0.1, 0 /*was: U.flag & USER_AUTOGRABGRID*/);
00786                                 
00787                                 offs= (int)fac;
00788                                 RNA_int_set(op->ptr, "frames", offs);
00789                                 ed_marker_move_apply(op);
00790                                 
00791                                 /* cruft below is for header print */
00792                                 for (a=0, marker= mm->markers->first; marker; marker= marker->next) {
00793                                         if (marker->flag & SELECT) {
00794                                                 selmarker= marker;
00795                                                 a++; totmark++;
00796                                         }
00797                                 }
00798                                 
00799                                 if (totmark==1) {       
00800                                         /* we print current marker value */
00801                                         if (ELEM(mm->slink->spacetype, SPACE_TIME, SPACE_SOUND)) {
00802                                                 SpaceTime *stime= (SpaceTime *)mm->slink;
00803                                                 if (stime->flag & TIME_DRAWFRAMES) 
00804                                                         BLI_snprintf(str, sizeof(str), "Marker %d offset %d", selmarker->frame, offs);
00805                                                 else 
00806                                                         BLI_snprintf(str, sizeof(str), "Marker %.2f offset %.2f", FRA2TIME(selmarker->frame), FRA2TIME(offs));
00807                                         }
00808                                         else if (mm->slink->spacetype == SPACE_ACTION) {
00809                                                 SpaceAction *saction= (SpaceAction *)mm->slink;
00810                                                 if (saction->flag & SACTION_DRAWTIME)
00811                                                         BLI_snprintf(str, sizeof(str), "Marker %.2f offset %.2f", FRA2TIME(selmarker->frame), FRA2TIME(offs));
00812                                                 else
00813                                                         BLI_snprintf(str, sizeof(str), "Marker %.2f offset %.2f", (double)(selmarker->frame), (double)(offs));
00814                                         }
00815                                         else {
00816                                                 BLI_snprintf(str, sizeof(str), "Marker %.2f offset %.2f", (double)(selmarker->frame), (double)(offs));
00817                                         }
00818                                 }
00819                                 else {
00820                                         /* we only print the offset */
00821                                         if (ELEM(mm->slink->spacetype, SPACE_TIME, SPACE_SOUND)) { 
00822                                                 SpaceTime *stime= (SpaceTime *)mm->slink;
00823                                                 if (stime->flag & TIME_DRAWFRAMES) 
00824                                                         BLI_snprintf(str, sizeof(str), "Marker offset %d ", offs);
00825                                                 else 
00826                                                         BLI_snprintf(str, sizeof(str), "Marker offset %.2f ", FRA2TIME(offs));
00827                                         }
00828                                         else if (mm->slink->spacetype == SPACE_ACTION) {
00829                                                 SpaceAction *saction= (SpaceAction *)mm->slink;
00830                                                 if (saction->flag & SACTION_DRAWTIME)
00831                                                         BLI_snprintf(str, sizeof(str), "Marker offset %.2f ", FRA2TIME(offs));
00832                                                 else
00833                                                         BLI_snprintf(str, sizeof(str), "Marker offset %.2f ", (double)(offs));
00834                                         }
00835                                         else {
00836                                                 BLI_snprintf(str, sizeof(str), "Marker offset %.2f ", (double)(offs));
00837                                         }
00838                                 }
00839                                 
00840                                 WM_event_add_notifier(C, NC_SCENE|ND_MARKERS, NULL);
00841                                 WM_event_add_notifier(C, NC_ANIMATION|ND_MARKERS, NULL);
00842                                 ED_area_headerprint(CTX_wm_area(C), str);
00843                         }
00844         }
00845 
00846         if (evt->val==KM_PRESS) {
00847                 float vec[3];
00848                 char str_tx[256];
00849                 
00850                 if (handleNumInput(&mm->num, evt))
00851                 {
00852                         applyNumInput(&mm->num, vec);
00853                         outputNumInput(&mm->num, str_tx);
00854                         
00855                         RNA_int_set(op->ptr, "frames", vec[0]);
00856                         ed_marker_move_apply(op);
00857                         // ed_marker_header_update(C, op, str, (int)vec[0]);
00858                         // strcat(str, str_tx);
00859                         BLI_snprintf(str, sizeof(str), "Marker offset %s", str_tx);
00860                         ED_area_headerprint(CTX_wm_area(C), str);
00861                         
00862                         WM_event_add_notifier(C, NC_SCENE|ND_MARKERS, NULL);
00863                         WM_event_add_notifier(C, NC_ANIMATION|ND_MARKERS, NULL);
00864                 }
00865         }
00866 
00867         return OPERATOR_RUNNING_MODAL;
00868 }
00869 
00870 static int ed_marker_move_exec(bContext *C, wmOperator *op)
00871 {
00872         if(ed_marker_move_init(C, op)) {
00873                 ed_marker_move_apply(op);
00874                 ed_marker_move_exit(C, op);
00875                 return OPERATOR_FINISHED;
00876         }
00877         return OPERATOR_PASS_THROUGH;
00878 }
00879 
00880 static void MARKER_OT_move(wmOperatorType *ot)
00881 {
00882         /* identifiers */
00883         ot->name= "Move Time Marker";
00884         ot->description= "Move selected time marker(s)";
00885         ot->idname= "MARKER_OT_move";
00886         
00887         /* api callbacks */
00888         ot->exec= ed_marker_move_exec;
00889         ot->invoke= ed_marker_move_invoke_wrapper;
00890         ot->modal= ed_marker_move_modal;
00891         ot->poll= ed_markers_poll_selected_markers;
00892         ot->cancel= ed_marker_move_cancel;
00893         
00894         /* flags */
00895         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING|OPTYPE_GRAB_POINTER;
00896         
00897         /* rna storage */
00898         RNA_def_int(ot->srna, "frames", 0, INT_MIN, INT_MAX, "Frames", "", INT_MIN, INT_MAX);
00899 }
00900 
00901 /* ************************** duplicate markers *************************** */
00902 
00903 /* operator state vars used:  
00904         frs: delta movement
00905 
00906 functions:
00907 
00908         apply()  do the actual duplicate
00909 
00910 callbacks:
00911 
00912         exec()  calls apply, move_exec
00913 
00914         invoke() calls apply, move_invoke
00915 
00916         modal() uses move_modal
00917 
00918 */
00919 
00920 
00921 /* duplicate selected TimeMarkers */
00922 static void ed_marker_duplicate_apply(bContext *C)
00923 {
00924         ListBase *markers= ED_context_get_markers(C);
00925         TimeMarker *marker, *newmarker;
00926         
00927         if (markers == NULL) 
00928                 return;
00929 
00930         /* go through the list of markers, duplicate selected markers and add duplicated copies
00931          * to the begining of the list (unselect original markers) 
00932          */
00933         for (marker= markers->first; marker; marker= marker->next) {
00934                 if (marker->flag & SELECT) {
00935                         /* unselect selected marker */
00936                         marker->flag &= ~SELECT;
00937                         
00938                         /* create and set up new marker */
00939                         newmarker = MEM_callocN(sizeof(TimeMarker), "TimeMarker");
00940                         newmarker->flag= SELECT;
00941                         newmarker->frame= marker->frame;
00942                         BLI_strncpy(newmarker->name, marker->name, sizeof(marker->name));
00943                         
00944 #ifdef DURIAN_CAMERA_SWITCH
00945                         newmarker->camera= marker->camera;
00946 #endif
00947 
00948                         /* new marker is added to the begining of list */
00949                         // FIXME: bad ordering!
00950                         BLI_addhead(markers, newmarker);
00951                 }
00952         }
00953 }
00954 
00955 static int ed_marker_duplicate_exec(bContext *C, wmOperator *op)
00956 {
00957         ed_marker_duplicate_apply(C);
00958         ed_marker_move_exec(C, op);     /* assumes frs delta set */
00959         
00960         return OPERATOR_FINISHED;
00961         
00962 }
00963 
00964 static int ed_marker_duplicate_invoke(bContext *C, wmOperator *op, wmEvent *evt)
00965 {
00966         ed_marker_duplicate_apply(C);
00967         return ed_marker_move_invoke(C, op, evt);
00968 }
00969 
00970 static int ed_marker_duplicate_invoke_wrapper(bContext *C, wmOperator *op, wmEvent *evt)
00971 {
00972         return ed_markers_opwrap_invoke_custom(C, op, evt, ed_marker_duplicate_invoke);
00973 }
00974 
00975 static void MARKER_OT_duplicate(wmOperatorType *ot)
00976 {
00977         /* identifiers */
00978         ot->name= "Duplicate Time Marker";
00979         ot->description= "Duplicate selected time marker(s)";
00980         ot->idname= "MARKER_OT_duplicate";
00981         
00982         /* api callbacks */
00983         ot->exec= ed_marker_duplicate_exec;
00984         ot->invoke= ed_marker_duplicate_invoke_wrapper;
00985         ot->modal= ed_marker_move_modal;
00986         ot->poll= ed_markers_poll_selected_markers;
00987         ot->cancel= ed_marker_move_cancel;
00988         
00989         /* flags */
00990         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00991         
00992         /* rna storage */
00993         RNA_def_int(ot->srna, "frames", 0, INT_MIN, INT_MAX, "Frames", "", INT_MIN, INT_MAX);
00994 }
00995 
00996 /* ************************** selection ************************************/
00997 
00998 /* select/deselect TimeMarker at current frame */
00999 static void select_timeline_marker_frame(ListBase *markers, int frame, unsigned char shift)
01000 {
01001         TimeMarker *marker;
01002         int select=0;
01003         
01004         for (marker= markers->first; marker; marker= marker->next) {
01005                 /* if Shift is not set, then deselect Markers */
01006                 if (!shift) marker->flag &= ~SELECT;
01007                 
01008                 /* this way a not-shift select will allways give 1 selected marker */
01009                 if ((marker->frame == frame) && (!select)) {
01010                         if (marker->flag & SELECT) 
01011                                 marker->flag &= ~SELECT;
01012                         else
01013                                 marker->flag |= SELECT;
01014                         select = 1;
01015                 }
01016         }
01017 }
01018 
01019 static int ed_marker_select(bContext *C, wmEvent *evt, int extend, int camera)
01020 {
01021         ListBase *markers= ED_context_get_markers(C);
01022         View2D *v2d= UI_view2d_fromcontext(C);
01023         float viewx;
01024         int x, y, cfra;
01025         
01026         if (markers == NULL)
01027                 return OPERATOR_PASS_THROUGH;
01028 
01029         x= evt->x - CTX_wm_region(C)->winrct.xmin;
01030         y= evt->y - CTX_wm_region(C)->winrct.ymin;
01031         
01032         UI_view2d_region_to_view(v2d, x, y, &viewx, NULL);      
01033         
01034         cfra= ED_markers_find_nearest_marker_time(markers, viewx);
01035         
01036         if (extend)
01037                 select_timeline_marker_frame(markers, cfra, 1);
01038         else
01039                 select_timeline_marker_frame(markers, cfra, 0);
01040         
01041 #ifdef DURIAN_CAMERA_SWITCH
01042 
01043         if (camera) {
01044                 Scene *scene= CTX_data_scene(C);
01045                 Base *base;
01046                 TimeMarker *marker;
01047                 int sel= 0;
01048                 
01049                 if (!extend)
01050                         scene_deselect_all(scene);
01051                 
01052                 for (marker= markers->first; marker; marker= marker->next) {
01053                         if(marker->frame==cfra) {
01054                                 sel= (marker->flag & SELECT);
01055                                 break;
01056                         }
01057                 }
01058                 
01059                 for (marker= markers->first; marker; marker= marker->next) {
01060                         if (marker->camera) {
01061                                 if (marker->frame==cfra) {
01062                                         base= object_in_scene(marker->camera, scene);
01063                                         if (base) {
01064                                                 ED_base_object_select(base, sel);
01065                                                 if(sel)
01066                                                         ED_base_object_activate(C, base);
01067                                         }
01068                                 }
01069                         }
01070                 }
01071                 
01072                 WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, scene);
01073         }
01074 #endif
01075 
01076         WM_event_add_notifier(C, NC_SCENE|ND_MARKERS, NULL);
01077         WM_event_add_notifier(C, NC_ANIMATION|ND_MARKERS, NULL);
01078 
01079         /* allowing tweaks, but needs OPERATOR_FINISHED, otherwise renaming fails... [#25987] */
01080         return OPERATOR_FINISHED|OPERATOR_PASS_THROUGH;
01081 }
01082 
01083 static int ed_marker_select_invoke(bContext *C, wmOperator *op, wmEvent *evt)
01084 {
01085         short extend= RNA_boolean_get(op->ptr, "extend");
01086         short camera= 0;
01087 #ifdef DURIAN_CAMERA_SWITCH
01088         camera= RNA_boolean_get(op->ptr, "camera");
01089 #endif
01090         return ed_marker_select(C, evt, extend, camera);
01091 }
01092 
01093 static int ed_marker_select_invoke_wrapper(bContext *C, wmOperator *op, wmEvent *evt)
01094 {
01095         return ed_markers_opwrap_invoke_custom(C, op, evt, ed_marker_select_invoke);
01096 }
01097 
01098 static void MARKER_OT_select(wmOperatorType *ot)
01099 {
01100         /* identifiers */
01101         ot->name= "Select Time Marker";
01102         ot->description= "Select time marker(s)";
01103         ot->idname= "MARKER_OT_select";
01104         
01105         /* api callbacks */
01106         ot->invoke= ed_marker_select_invoke_wrapper;
01107         ot->poll= ed_markers_poll_markers_exist;
01108         
01109         /* flags */
01110         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
01111 
01112         RNA_def_boolean(ot->srna, "extend", 0, "Extend", "extend the selection");
01113 #ifdef DURIAN_CAMERA_SWITCH
01114         RNA_def_boolean(ot->srna, "camera", 0, "Camera", "Select the camera");
01115 #endif
01116 }
01117 
01118 /* *************************** border select markers **************** */
01119 
01120 /* operator state vars used: (added by default WM callbacks)   
01121         xmin, ymin     
01122         xmax, ymax     
01123 
01124 customdata: the wmGesture pointer, with subwindow
01125 
01126 callbacks:
01127 
01128         exec()  has to be filled in by user
01129 
01130         invoke() default WM function
01131                         adds modal handler
01132 
01133         modal() default WM function 
01134                         accept modal events while doing it, calls exec(), handles ESC and border drawing
01135 
01136         poll()  has to be filled in by user for context
01137 */
01138 
01139 static int ed_marker_border_select_exec(bContext *C, wmOperator *op)
01140 {
01141         View2D *v2d= UI_view2d_fromcontext(C);
01142         ListBase *markers= ED_context_get_markers(C);
01143         TimeMarker *marker;
01144         float xminf, xmaxf, yminf, ymaxf;
01145         int gesture_mode= RNA_int_get(op->ptr, "gesture_mode");
01146         int xmin= RNA_int_get(op->ptr, "xmin");
01147         int xmax= RNA_int_get(op->ptr, "xmax");
01148         int ymin= RNA_int_get(op->ptr, "ymin");
01149         int ymax= RNA_int_get(op->ptr, "ymax");
01150         
01151         UI_view2d_region_to_view(v2d, xmin, ymin, &xminf, &yminf);      
01152         UI_view2d_region_to_view(v2d, xmax, ymax, &xmaxf, &ymaxf);      
01153         
01154         if (markers == NULL)
01155                 return 0;
01156         
01157         /* XXX marker context */
01158         for (marker= markers->first; marker; marker= marker->next) {
01159                 if ((marker->frame > xminf) && (marker->frame <= xmaxf)) {
01160                         switch (gesture_mode) {
01161                                 case GESTURE_MODAL_SELECT:
01162                                         marker->flag |= SELECT;
01163                                         break;
01164                                 case GESTURE_MODAL_DESELECT:
01165                                         marker->flag &= ~SELECT;
01166                                         break;
01167                         }
01168                 }
01169         }
01170         
01171         WM_event_add_notifier(C, NC_SCENE|ND_MARKERS, NULL);
01172         WM_event_add_notifier(C, NC_ANIMATION|ND_MARKERS, NULL);
01173 
01174         return 1;
01175 }
01176 
01177 static int ed_marker_select_border_invoke_wrapper(bContext *C, wmOperator *op, wmEvent *evt)
01178 {
01179         return ed_markers_opwrap_invoke_custom(C, op, evt, WM_border_select_invoke);
01180 }
01181 
01182 static void MARKER_OT_select_border(wmOperatorType *ot)
01183 {
01184         /* identifiers */
01185         ot->name= "Marker Border select";
01186         ot->description= "Select all time markers using border selection";
01187         ot->idname= "MARKER_OT_select_border";
01188         
01189         /* api callbacks */
01190         ot->exec= ed_marker_border_select_exec;
01191         ot->invoke= ed_marker_select_border_invoke_wrapper;
01192         ot->modal= WM_border_select_modal;
01193         ot->cancel= WM_border_select_cancel;
01194         
01195         ot->poll= ed_markers_poll_markers_exist;
01196         
01197         /* flags */
01198         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
01199         
01200         /* rna */
01201         WM_operator_properties_gesture_border(ot, FALSE);
01202 }
01203 
01204 /* *********************** (de)select all ***************** */
01205 
01206 static int ed_marker_select_all_exec(bContext *C, wmOperator *op)
01207 {
01208         ListBase *markers= ED_context_get_markers(C);
01209         TimeMarker *marker;
01210         int action = RNA_enum_get(op->ptr, "action");
01211 
01212         if (markers == NULL)
01213                 return OPERATOR_CANCELLED;
01214 
01215         if (action == SEL_TOGGLE) {
01216                 action = (ED_markers_get_first_selected(markers) != NULL) ? SEL_DESELECT : SEL_SELECT;
01217         }
01218         
01219         for(marker= markers->first; marker; marker= marker->next) {
01220                 switch (action) {
01221                 case SEL_SELECT:
01222                         marker->flag |= SELECT;
01223                         break;
01224                 case SEL_DESELECT:
01225                         marker->flag &= ~SELECT;
01226                         break;
01227                 case SEL_INVERT:
01228                         marker->flag ^= SELECT;
01229                         break;
01230                 }
01231         }
01232         
01233         WM_event_add_notifier(C, NC_SCENE|ND_MARKERS, NULL);
01234         WM_event_add_notifier(C, NC_ANIMATION|ND_MARKERS, NULL);
01235 
01236         return OPERATOR_FINISHED;
01237 }
01238 
01239 static void MARKER_OT_select_all(wmOperatorType *ot)
01240 {
01241         /* identifiers */
01242         ot->name= "(De)select all markers";
01243         ot->description= "Change selection of all time markers";
01244         ot->idname= "MARKER_OT_select_all";
01245         
01246         /* api callbacks */
01247         ot->exec= ed_marker_select_all_exec;
01248         ot->invoke = ed_markers_opwrap_invoke;
01249         ot->poll= ed_markers_poll_markers_exist;
01250         
01251         /* flags */
01252         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
01253         
01254         /* rna */
01255         WM_operator_properties_select_all(ot);
01256 }
01257 
01258 /* ***************** remove marker *********************** */
01259 
01260 /* remove selected TimeMarkers */
01261 static int ed_marker_delete_exec(bContext *C, wmOperator *UNUSED(op))
01262 {
01263         ListBase *markers= ED_context_get_markers(C);
01264         TimeMarker *marker, *nmarker;
01265         short changed= 0;
01266         
01267         if (markers == NULL)
01268                 return OPERATOR_CANCELLED;
01269         
01270         for (marker= markers->first; marker; marker= nmarker) {
01271                 nmarker= marker->next;
01272                 if (marker->flag & SELECT) {
01273                         BLI_freelinkN(markers, marker);
01274                         changed= 1;
01275                 }
01276         }
01277         
01278         if (changed) {
01279                 WM_event_add_notifier(C, NC_SCENE|ND_MARKERS, NULL);
01280                 WM_event_add_notifier(C, NC_ANIMATION|ND_MARKERS, NULL);
01281         }
01282         
01283         return OPERATOR_FINISHED;
01284 }
01285 
01286 static int ed_marker_delete_invoke_wrapper(bContext *C, wmOperator *op, wmEvent *evt)
01287 {
01288         // XXX: must we keep these confirmations?
01289         return ed_markers_opwrap_invoke_custom(C, op, evt, WM_operator_confirm);
01290 }
01291 
01292 static void MARKER_OT_delete(wmOperatorType *ot)
01293 {
01294         /* identifiers */
01295         ot->name= "Delete Markers";
01296         ot->description= "Delete selected time marker(s)";
01297         ot->idname= "MARKER_OT_delete";
01298         
01299         /* api callbacks */
01300         ot->invoke= ed_marker_delete_invoke_wrapper;
01301         ot->exec= ed_marker_delete_exec;
01302         ot->poll= ed_markers_poll_selected_markers;
01303         
01304         /* flags */
01305         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;  
01306 }
01307 
01308 
01309 /* **************** rename marker ***************** */
01310 
01311 /* rename first selected TimeMarker */
01312 static int ed_marker_rename_exec(bContext *C, wmOperator *op)
01313 {
01314         TimeMarker *marker= ED_markers_get_first_selected(ED_context_get_markers(C));
01315 
01316         if (marker) {
01317                 RNA_string_get(op->ptr, "name", marker->name);
01318                 
01319                 WM_event_add_notifier(C, NC_SCENE|ND_MARKERS, NULL);
01320                 WM_event_add_notifier(C, NC_ANIMATION|ND_MARKERS, NULL);
01321                 
01322                 return OPERATOR_FINISHED;
01323         }
01324         else {
01325                 return OPERATOR_CANCELLED;
01326         }
01327 }
01328 
01329 static int ed_marker_rename_invoke_wrapper(bContext *C, wmOperator *op, wmEvent *evt)
01330 {
01331         /* must initialise the marker name first if there is a marker selected */
01332         TimeMarker *marker = ED_markers_get_first_selected(ED_context_get_markers(C));
01333         if (marker)
01334                 RNA_string_set(op->ptr, "name", marker->name);
01335         
01336         /* now see if the operator is usable */
01337         return ed_markers_opwrap_invoke_custom(C, op, evt, WM_operator_props_popup);
01338 }
01339 
01340 static void MARKER_OT_rename(wmOperatorType *ot)
01341 {
01342         /* identifiers */
01343         ot->name= "Rename Marker";
01344         ot->description= "Rename first selected time marker";
01345         ot->idname= "MARKER_OT_rename";
01346         
01347         /* api callbacks */
01348         ot->invoke= ed_marker_rename_invoke_wrapper;
01349         ot->exec= ed_marker_rename_exec;
01350         ot->poll= ed_markers_poll_selected_markers;
01351         
01352         /* flags */
01353         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;  
01354         
01355         /* properties */
01356         ot->prop = RNA_def_string(ot->srna, "name", "RenamedMarker", sizeof(((TimeMarker *)NULL)->name), "Name", "New name for marker");
01357         //RNA_def_boolean(ot->srna, "ensure_unique", 0, "Ensure Unique", "Ensure that new name is unique within collection of markers");
01358 }
01359 
01360 /* **************** make links to scene ***************** */
01361 
01362 static int ed_marker_make_links_scene_exec(bContext *C, wmOperator *op)
01363 {
01364         ListBase *markers= ED_context_get_markers(C);
01365         Scene *scene_to= BLI_findlink(&CTX_data_main(C)->scene, RNA_enum_get(op->ptr, "scene"));
01366         TimeMarker *marker, *marker_new;
01367 
01368         if (scene_to==NULL) {
01369                 BKE_report(op->reports, RPT_ERROR, "Scene not found");
01370                 return OPERATOR_CANCELLED;
01371         }
01372 
01373         if (scene_to == CTX_data_scene(C)) {
01374                 BKE_report(op->reports, RPT_ERROR, "Can't re-link markers into the same scene");
01375                 return OPERATOR_CANCELLED;
01376         }
01377 
01378         /* copy markers */
01379         for (marker= markers->first; marker; marker= marker->next) {
01380                 if (marker->flag & SELECT) {
01381                         marker_new= MEM_dupallocN(marker);
01382                         marker_new->prev= marker_new->next = NULL;
01383                         
01384                         BLI_addtail(&scene_to->markers, marker_new);
01385                 }
01386         }
01387 
01388         return OPERATOR_FINISHED;
01389 }
01390 
01391 static void MARKER_OT_make_links_scene(wmOperatorType *ot)
01392 {
01393         PropertyRNA *prop;
01394 
01395         /* identifiers */
01396         ot->name= "Make Links to Scene";
01397         ot->description= "Copy selected markers to another scene";
01398         ot->idname= "MARKER_OT_make_links_scene";
01399 
01400         /* api callbacks */
01401         ot->exec= ed_marker_make_links_scene_exec;
01402         ot->invoke = ed_markers_opwrap_invoke;
01403         ot->poll= ed_markers_poll_selected_markers;
01404 
01405         /* flags */
01406         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
01407 
01408         /* properties */
01409         prop= RNA_def_enum(ot->srna, "scene", DummyRNA_NULL_items, 0, "Scene", "");
01410         RNA_def_enum_funcs(prop, RNA_scene_itemf);
01411         ot->prop= prop;
01412 
01413 }
01414 
01415 #ifdef DURIAN_CAMERA_SWITCH
01416 /* ******************************* camera bind marker ***************** */
01417 
01418 static int ed_marker_camera_bind_exec(bContext *C, wmOperator *UNUSED(op))
01419 {
01420         bScreen *sc= CTX_wm_screen(C);
01421         Scene *scene= CTX_data_scene(C);
01422         Object *ob = CTX_data_active_object(C);
01423         ListBase *markers= ED_context_get_markers(C);
01424         TimeMarker *marker;
01425 
01426         marker= ED_markers_get_first_selected(markers);
01427         if(marker == NULL)
01428                 return OPERATOR_CANCELLED;
01429 
01430         marker->camera= ob;
01431 
01432         /* camera may have changes */
01433         scene_camera_switch_update(scene);
01434         BKE_screen_view3d_scene_sync(sc);
01435 
01436         WM_event_add_notifier(C, NC_SCENE|ND_MARKERS, NULL);
01437         WM_event_add_notifier(C, NC_ANIMATION|ND_MARKERS, NULL);
01438         WM_event_add_notifier(C, NC_SCENE|NA_EDITED, scene); /* so we get view3d redraws */
01439 
01440         return OPERATOR_FINISHED;
01441 }
01442 
01443 static void MARKER_OT_camera_bind(wmOperatorType *ot)
01444 {
01445         /* identifiers */
01446         ot->name= "Bind Camera to Markers";
01447         ot->description= "Bind the active camera to selected markers(s)";
01448         ot->idname= "MARKER_OT_camera_bind";
01449 
01450         /* api callbacks */
01451         ot->exec= ed_marker_camera_bind_exec;
01452         ot->invoke = ed_markers_opwrap_invoke;
01453         ot->poll= ed_markers_poll_selected_markers;
01454 
01455         /* flags */
01456         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
01457 }
01458 #endif
01459 
01460 /* ************************** registration **********************************/
01461 
01462 /* called in screen_ops.c:ED_operatortypes_screen() */
01463 void ED_operatortypes_marker(void)
01464 {
01465         WM_operatortype_append(MARKER_OT_add);
01466         WM_operatortype_append(MARKER_OT_move);
01467         WM_operatortype_append(MARKER_OT_duplicate);
01468         WM_operatortype_append(MARKER_OT_select);
01469         WM_operatortype_append(MARKER_OT_select_border);
01470         WM_operatortype_append(MARKER_OT_select_all);
01471         WM_operatortype_append(MARKER_OT_delete);
01472         WM_operatortype_append(MARKER_OT_rename);
01473         WM_operatortype_append(MARKER_OT_make_links_scene);
01474 #ifdef DURIAN_CAMERA_SWITCH
01475         WM_operatortype_append(MARKER_OT_camera_bind);
01476 #endif
01477 }
01478 
01479 /* called in screen_ops.c:ED_keymap_screen() */
01480 void ED_marker_keymap(wmKeyConfig *keyconf)
01481 {
01482         wmKeyMap *keymap= WM_keymap_find(keyconf, "Markers", 0, 0);
01483         wmKeyMapItem *kmi;
01484         
01485         WM_keymap_verify_item(keymap, "MARKER_OT_add", MKEY, KM_PRESS, 0, 0);
01486         WM_keymap_verify_item(keymap, "MARKER_OT_move", EVT_TWEAK_S, KM_ANY, 0, 0);
01487         WM_keymap_verify_item(keymap, "MARKER_OT_duplicate", DKEY, KM_PRESS, KM_SHIFT, 0);
01488         WM_keymap_verify_item(keymap, "MARKER_OT_select", SELECTMOUSE, KM_PRESS, 0, 0);
01489         RNA_boolean_set(WM_keymap_add_item(keymap, "MARKER_OT_select", SELECTMOUSE, KM_PRESS, KM_SHIFT, 0)->ptr, "extend", 1);
01490 
01491 #ifdef DURIAN_CAMERA_SWITCH
01492         kmi= WM_keymap_add_item(keymap, "MARKER_OT_select", SELECTMOUSE, KM_PRESS, KM_CTRL, 0);
01493         RNA_boolean_set(kmi->ptr, "camera", 1);
01494 
01495         kmi= WM_keymap_add_item(keymap, "MARKER_OT_select", SELECTMOUSE, KM_PRESS, KM_SHIFT|KM_CTRL, 0);
01496         RNA_boolean_set(kmi->ptr, "extend", 1);
01497         RNA_boolean_set(kmi->ptr, "camera", 1);
01498 #endif
01499         
01500         WM_keymap_verify_item(keymap, "MARKER_OT_select_border", BKEY, KM_PRESS, 0, 0);
01501         WM_keymap_verify_item(keymap, "MARKER_OT_select_all", AKEY, KM_PRESS, 0, 0);
01502         WM_keymap_verify_item(keymap, "MARKER_OT_delete", XKEY, KM_PRESS, 0, 0);
01503         WM_keymap_verify_item(keymap, "MARKER_OT_delete", DELKEY, KM_PRESS, 0, 0);
01504         WM_keymap_verify_item(keymap, "MARKER_OT_rename", MKEY, KM_PRESS, KM_CTRL, 0);
01505         
01506         WM_keymap_add_item(keymap, "MARKER_OT_move", GKEY, KM_PRESS, 0, 0);
01507 #ifdef DURIAN_CAMERA_SWITCH
01508         WM_keymap_add_item(keymap, "MARKER_OT_camera_bind", BKEY, KM_PRESS, KM_CTRL, 0);
01509 #endif
01510 }