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) 2008 Blender Foundation. 00019 * All rights reserved. 00020 * 00021 * Contributor(s): Blender Foundation, Joshua Leung 00022 * 00023 * ***** END GPL LICENSE BLOCK ***** 00024 */ 00025 00031 #include <math.h> 00032 00033 #include "MEM_guardedalloc.h" 00034 00035 #include "DNA_userdef_types.h" 00036 00037 #include "BLI_blenlib.h" 00038 #include "BLI_utildefines.h" 00039 00040 #include "BKE_context.h" 00041 00042 #include "RNA_access.h" 00043 #include "RNA_define.h" 00044 00045 #include "WM_api.h" 00046 #include "WM_types.h" 00047 00048 00049 #include "ED_screen.h" 00050 00051 #include "UI_view2d.h" 00052 #include "UI_interface.h" 00053 00054 #include "PIL_time.h" /* USER_ZOOM_CONT */ 00055 00056 static int view2d_poll(bContext *C) 00057 { 00058 ARegion *ar= CTX_wm_region(C); 00059 00060 return (ar != NULL) && (ar->v2d.flag & V2D_IS_INITIALISED); 00061 } 00062 00063 /* ********************************************************* */ 00064 /* VIEW PANNING OPERATOR */ 00065 00066 /* This group of operators come in several forms: 00067 * 1) Modal 'dragging' with MMB - where movement of mouse dictates amount to pan view by 00068 * 2) Scrollwheel 'steps' - rolling mousewheel by one step moves view by predefined amount 00069 * 00070 * In order to make sure this works, each operator must define the following RNA-Operator Props: 00071 * deltax, deltay - define how much to move view by (relative to zoom-correction factor) 00072 */ 00073 00074 /* ------------------ Shared 'core' stuff ---------------------- */ 00075 00076 /* temp customdata for operator */ 00077 typedef struct v2dViewPanData { 00078 bScreen *sc; /* screen where view pan was initiated */ 00079 ScrArea *sa; /* area where view pan was initiated */ 00080 ARegion *ar; /* region where view pan was initiated */ 00081 View2D *v2d; /* view2d we're operating in */ 00082 00083 float facx, facy; /* amount to move view relative to zoom */ 00084 00085 /* options for version 1 */ 00086 int startx, starty; /* mouse x/y values in window when operator was initiated */ 00087 int lastx, lasty; /* previous x/y values of mouse in window */ 00088 int invoke_event; /* event starting pan, for modal exit */ 00089 00090 short in_scroller; /* for MMB in scrollers (old feature in past, but now not that useful) */ 00091 } v2dViewPanData; 00092 00093 /* initialise panning customdata */ 00094 static int view_pan_init(bContext *C, wmOperator *op) 00095 { 00096 ARegion *ar= CTX_wm_region(C); 00097 v2dViewPanData *vpd; 00098 View2D *v2d; 00099 float winx, winy; 00100 00101 /* regions now have v2d-data by default, so check for region */ 00102 if (ar == NULL) 00103 return 0; 00104 00105 /* check if panning is allowed at all */ 00106 v2d= &ar->v2d; 00107 if ((v2d->keepofs & V2D_LOCKOFS_X) && (v2d->keepofs & V2D_LOCKOFS_Y)) 00108 return 0; 00109 00110 /* set custom-data for operator */ 00111 vpd= MEM_callocN(sizeof(v2dViewPanData), "v2dViewPanData"); 00112 op->customdata= vpd; 00113 00114 /* set pointers to owners */ 00115 vpd->sc= CTX_wm_screen(C); 00116 vpd->sa= CTX_wm_area(C); 00117 vpd->v2d= v2d; 00118 vpd->ar = ar; 00119 00120 /* calculate translation factor - based on size of view */ 00121 winx= (float)(ar->winrct.xmax - ar->winrct.xmin + 1); 00122 winy= (float)(ar->winrct.ymax - ar->winrct.ymin + 1); 00123 vpd->facx= (v2d->cur.xmax - v2d->cur.xmin) / winx; 00124 vpd->facy= (v2d->cur.ymax - v2d->cur.ymin) / winy; 00125 00126 return 1; 00127 } 00128 00129 /* apply transform to view (i.e. adjust 'cur' rect) */ 00130 static void view_pan_apply(wmOperator *op) 00131 { 00132 v2dViewPanData *vpd= op->customdata; 00133 View2D *v2d= vpd->v2d; 00134 float dx, dy; 00135 00136 /* calculate amount to move view by */ 00137 dx= vpd->facx * (float)RNA_int_get(op->ptr, "deltax"); 00138 dy= vpd->facy * (float)RNA_int_get(op->ptr, "deltay"); 00139 00140 /* only move view on an axis if change is allowed */ 00141 if ((v2d->keepofs & V2D_LOCKOFS_X)==0) { 00142 v2d->cur.xmin += dx; 00143 v2d->cur.xmax += dx; 00144 } 00145 if ((v2d->keepofs & V2D_LOCKOFS_Y)==0) { 00146 v2d->cur.ymin += dy; 00147 v2d->cur.ymax += dy; 00148 } 00149 00150 /* validate that view is in valid configuration after this operation */ 00151 UI_view2d_curRect_validate(v2d); 00152 00153 /* request updates to be done... */ 00154 ED_region_tag_redraw(vpd->ar); 00155 00156 UI_view2d_sync(vpd->sc, vpd->sa, v2d, V2D_LOCK_COPY); 00157 00158 /* exceptions */ 00159 if (vpd->sa->spacetype==SPACE_OUTLINER) { 00160 /* don't rebuild full tree, since we're just changing our view */ 00161 SpaceOops *soops= vpd->sa->spacedata.first; 00162 soops->storeflag |= SO_TREESTORE_REDRAW; 00163 } 00164 } 00165 00166 /* cleanup temp customdata */ 00167 static void view_pan_exit(wmOperator *op) 00168 { 00169 if (op->customdata) { 00170 MEM_freeN(op->customdata); 00171 op->customdata= NULL; 00172 } 00173 } 00174 00175 /* ------------------ Modal Drag Version (1) ---------------------- */ 00176 00177 /* for 'redo' only, with no user input */ 00178 static int view_pan_exec(bContext *C, wmOperator *op) 00179 { 00180 if (!view_pan_init(C, op)) 00181 return OPERATOR_CANCELLED; 00182 00183 view_pan_apply(op); 00184 view_pan_exit(op); 00185 return OPERATOR_FINISHED; 00186 } 00187 00188 /* set up modal operator and relevant settings */ 00189 static int view_pan_invoke(bContext *C, wmOperator *op, wmEvent *event) 00190 { 00191 wmWindow *window= CTX_wm_window(C); 00192 v2dViewPanData *vpd; 00193 View2D *v2d; 00194 00195 /* set up customdata */ 00196 if (!view_pan_init(C, op)) 00197 return OPERATOR_PASS_THROUGH; 00198 00199 vpd= op->customdata; 00200 v2d= vpd->v2d; 00201 00202 /* set initial settings */ 00203 vpd->startx= vpd->lastx= event->x; 00204 vpd->starty= vpd->lasty= event->y; 00205 vpd->invoke_event= event->type; 00206 00207 if (event->type == MOUSEPAN) { 00208 RNA_int_set(op->ptr, "deltax", event->prevx - event->x); 00209 RNA_int_set(op->ptr, "deltay", event->prevy - event->y); 00210 00211 view_pan_apply(op); 00212 view_pan_exit(op); 00213 return OPERATOR_FINISHED; 00214 } 00215 00216 RNA_int_set(op->ptr, "deltax", 0); 00217 RNA_int_set(op->ptr, "deltay", 0); 00218 00219 if (v2d->keepofs & V2D_LOCKOFS_X) 00220 WM_cursor_modal(window, BC_NS_SCROLLCURSOR); 00221 else if (v2d->keepofs & V2D_LOCKOFS_Y) 00222 WM_cursor_modal(window, BC_EW_SCROLLCURSOR); 00223 else 00224 WM_cursor_modal(window, BC_NSEW_SCROLLCURSOR); 00225 00226 /* add temp handler */ 00227 WM_event_add_modal_handler(C, op); 00228 00229 return OPERATOR_RUNNING_MODAL; 00230 } 00231 00232 /* handle user input - calculations of mouse-movement need to be done here, not in the apply callback! */ 00233 static int view_pan_modal(bContext *C, wmOperator *op, wmEvent *event) 00234 { 00235 v2dViewPanData *vpd= op->customdata; 00236 00237 /* execute the events */ 00238 switch (event->type) { 00239 case MOUSEMOVE: 00240 { 00241 /* calculate new delta transform, then store mouse-coordinates for next-time */ 00242 RNA_int_set(op->ptr, "deltax", (vpd->lastx - event->x)); 00243 RNA_int_set(op->ptr, "deltay", (vpd->lasty - event->y)); 00244 00245 vpd->lastx= event->x; 00246 vpd->lasty= event->y; 00247 00248 view_pan_apply(op); 00249 } 00250 break; 00251 /* XXX - Mode switching isn't implemented. See comments in 36818. 00252 * switch to zoom * 00253 case LEFTMOUSE: 00254 if (event->val==KM_PRESS) { 00255 * calculate overall delta mouse-movement for redo * 00256 RNA_int_set(op->ptr, "deltax", (vpd->startx - vpd->lastx)); 00257 RNA_int_set(op->ptr, "deltay", (vpd->starty - vpd->lasty)); 00258 00259 view_pan_exit(op); 00260 WM_cursor_restore(CTX_wm_window(C)); 00261 WM_operator_name_call(C, "VIEW2D_OT_zoom", WM_OP_INVOKE_DEFAULT, NULL); 00262 return OPERATOR_FINISHED; 00263 }*/ 00264 00265 default: 00266 if (event->type == vpd->invoke_event || event->type==ESCKEY) { 00267 if (event->val==KM_RELEASE) { 00268 /* calculate overall delta mouse-movement for redo */ 00269 RNA_int_set(op->ptr, "deltax", (vpd->startx - vpd->lastx)); 00270 RNA_int_set(op->ptr, "deltay", (vpd->starty - vpd->lasty)); 00271 00272 view_pan_exit(op); 00273 WM_cursor_restore(CTX_wm_window(C)); 00274 00275 return OPERATOR_FINISHED; 00276 } 00277 } 00278 break; 00279 } 00280 00281 return OPERATOR_RUNNING_MODAL; 00282 } 00283 00284 static int view_pan_cancel(bContext *UNUSED(C), wmOperator *op) 00285 { 00286 view_pan_exit(op); 00287 return OPERATOR_CANCELLED; 00288 } 00289 00290 static void VIEW2D_OT_pan(wmOperatorType *ot) 00291 { 00292 /* identifiers */ 00293 ot->name= "Pan View"; 00294 ot->description= "Pan the view"; 00295 ot->idname= "VIEW2D_OT_pan"; 00296 00297 /* api callbacks */ 00298 ot->exec= view_pan_exec; 00299 ot->invoke= view_pan_invoke; 00300 ot->modal= view_pan_modal; 00301 ot->cancel= view_pan_cancel; 00302 00303 /* operator is modal */ 00304 ot->flag= OPTYPE_BLOCKING|OPTYPE_GRAB_POINTER; 00305 00306 /* rna - must keep these in sync with the other operators */ 00307 RNA_def_int(ot->srna, "deltax", 0, INT_MIN, INT_MAX, "Delta X", "", INT_MIN, INT_MAX); 00308 RNA_def_int(ot->srna, "deltay", 0, INT_MIN, INT_MAX, "Delta Y", "", INT_MIN, INT_MAX); 00309 } 00310 00311 /* ------------------ Scrollwheel Versions (2) ---------------------- */ 00312 00313 /* this operator only needs this single callback, where it callsthe view_pan_*() methods */ 00314 static int view_scrollright_exec(bContext *C, wmOperator *op) 00315 { 00316 v2dViewPanData *vpd; 00317 00318 /* initialise default settings (and validate if ok to run) */ 00319 if (!view_pan_init(C, op)) 00320 return OPERATOR_PASS_THROUGH; 00321 00322 /* also, check if can pan in horizontal axis */ 00323 vpd= op->customdata; 00324 if (vpd->v2d->keepofs & V2D_LOCKOFS_X) { 00325 view_pan_exit(op); 00326 return OPERATOR_PASS_THROUGH; 00327 } 00328 00329 /* set RNA-Props - only movement in positive x-direction */ 00330 RNA_int_set(op->ptr, "deltax", 20); 00331 RNA_int_set(op->ptr, "deltay", 0); 00332 00333 /* apply movement, then we're done */ 00334 view_pan_apply(op); 00335 view_pan_exit(op); 00336 00337 return OPERATOR_FINISHED; 00338 } 00339 00340 static void VIEW2D_OT_scroll_right(wmOperatorType *ot) 00341 { 00342 /* identifiers */ 00343 ot->name= "Scroll Right"; 00344 ot->description= "Scroll the view right"; 00345 ot->idname= "VIEW2D_OT_scroll_right"; 00346 00347 /* api callbacks */ 00348 ot->exec= view_scrollright_exec; 00349 00350 /* rna - must keep these in sync with the other operators */ 00351 RNA_def_int(ot->srna, "deltax", 0, INT_MIN, INT_MAX, "Delta X", "", INT_MIN, INT_MAX); 00352 RNA_def_int(ot->srna, "deltay", 0, INT_MIN, INT_MAX, "Delta Y", "", INT_MIN, INT_MAX); 00353 } 00354 00355 00356 00357 /* this operator only needs this single callback, where it callsthe view_pan_*() methods */ 00358 static int view_scrollleft_exec(bContext *C, wmOperator *op) 00359 { 00360 v2dViewPanData *vpd; 00361 00362 /* initialise default settings (and validate if ok to run) */ 00363 if (!view_pan_init(C, op)) 00364 return OPERATOR_PASS_THROUGH; 00365 00366 /* also, check if can pan in horizontal axis */ 00367 vpd= op->customdata; 00368 if (vpd->v2d->keepofs & V2D_LOCKOFS_X) { 00369 view_pan_exit(op); 00370 return OPERATOR_PASS_THROUGH; 00371 } 00372 00373 /* set RNA-Props - only movement in negative x-direction */ 00374 RNA_int_set(op->ptr, "deltax", -20); 00375 RNA_int_set(op->ptr, "deltay", 0); 00376 00377 /* apply movement, then we're done */ 00378 view_pan_apply(op); 00379 view_pan_exit(op); 00380 00381 return OPERATOR_FINISHED; 00382 } 00383 00384 static void VIEW2D_OT_scroll_left(wmOperatorType *ot) 00385 { 00386 /* identifiers */ 00387 ot->name= "Scroll Left"; 00388 ot->description= "Scroll the view left"; 00389 ot->idname= "VIEW2D_OT_scroll_left"; 00390 00391 /* api callbacks */ 00392 ot->exec= view_scrollleft_exec; 00393 00394 /* rna - must keep these in sync with the other operators */ 00395 RNA_def_int(ot->srna, "deltax", 0, INT_MIN, INT_MAX, "Delta X", "", INT_MIN, INT_MAX); 00396 RNA_def_int(ot->srna, "deltay", 0, INT_MIN, INT_MAX, "Delta Y", "", INT_MIN, INT_MAX); 00397 } 00398 00399 00400 /* this operator only needs this single callback, where it callsthe view_pan_*() methods */ 00401 static int view_scrolldown_exec(bContext *C, wmOperator *op) 00402 { 00403 v2dViewPanData *vpd; 00404 00405 /* initialise default settings (and validate if ok to run) */ 00406 if (!view_pan_init(C, op)) 00407 return OPERATOR_PASS_THROUGH; 00408 00409 /* also, check if can pan in vertical axis */ 00410 vpd= op->customdata; 00411 if (vpd->v2d->keepofs & V2D_LOCKOFS_Y) { 00412 view_pan_exit(op); 00413 return OPERATOR_PASS_THROUGH; 00414 } 00415 00416 /* set RNA-Props */ 00417 RNA_int_set(op->ptr, "deltax", 0); 00418 RNA_int_set(op->ptr, "deltay", -40); 00419 00420 if(RNA_boolean_get(op->ptr, "page")) { 00421 ARegion *ar= CTX_wm_region(C); 00422 RNA_int_set(op->ptr, "deltay", ar->v2d.mask.ymin - ar->v2d.mask.ymax); 00423 } 00424 00425 /* apply movement, then we're done */ 00426 view_pan_apply(op); 00427 view_pan_exit(op); 00428 00429 return OPERATOR_FINISHED; 00430 } 00431 00432 static void VIEW2D_OT_scroll_down(wmOperatorType *ot) 00433 { 00434 /* identifiers */ 00435 ot->name= "Scroll Down"; 00436 ot->description= "Scroll the view down"; 00437 ot->idname= "VIEW2D_OT_scroll_down"; 00438 00439 /* api callbacks */ 00440 ot->exec= view_scrolldown_exec; 00441 00442 /* rna - must keep these in sync with the other operators */ 00443 RNA_def_int(ot->srna, "deltax", 0, INT_MIN, INT_MAX, "Delta X", "", INT_MIN, INT_MAX); 00444 RNA_def_int(ot->srna, "deltay", 0, INT_MIN, INT_MAX, "Delta Y", "", INT_MIN, INT_MAX); 00445 RNA_def_boolean(ot->srna, "page", 0, "Page", "Scroll down one page"); 00446 } 00447 00448 00449 00450 /* this operator only needs this single callback, where it callsthe view_pan_*() methods */ 00451 static int view_scrollup_exec(bContext *C, wmOperator *op) 00452 { 00453 v2dViewPanData *vpd; 00454 00455 /* initialise default settings (and validate if ok to run) */ 00456 if (!view_pan_init(C, op)) 00457 return OPERATOR_PASS_THROUGH; 00458 00459 /* also, check if can pan in vertical axis */ 00460 vpd= op->customdata; 00461 if (vpd->v2d->keepofs & V2D_LOCKOFS_Y) { 00462 view_pan_exit(op); 00463 return OPERATOR_PASS_THROUGH; 00464 } 00465 00466 /* set RNA-Props */ 00467 RNA_int_set(op->ptr, "deltax", 0); 00468 RNA_int_set(op->ptr, "deltay", 40); 00469 00470 if(RNA_boolean_get(op->ptr, "page")) { 00471 ARegion *ar= CTX_wm_region(C); 00472 RNA_int_set(op->ptr, "deltay", ar->v2d.mask.ymax - ar->v2d.mask.ymin); 00473 } 00474 00475 /* apply movement, then we're done */ 00476 view_pan_apply(op); 00477 view_pan_exit(op); 00478 00479 return OPERATOR_FINISHED; 00480 } 00481 00482 static void VIEW2D_OT_scroll_up(wmOperatorType *ot) 00483 { 00484 /* identifiers */ 00485 ot->name= "Scroll Up"; 00486 ot->description= "Scroll the view up"; 00487 ot->idname= "VIEW2D_OT_scroll_up"; 00488 00489 /* api callbacks */ 00490 ot->exec= view_scrollup_exec; 00491 00492 /* rna - must keep these in sync with the other operators */ 00493 RNA_def_int(ot->srna, "deltax", 0, INT_MIN, INT_MAX, "Delta X", "", INT_MIN, INT_MAX); 00494 RNA_def_int(ot->srna, "deltay", 0, INT_MIN, INT_MAX, "Delta Y", "", INT_MIN, INT_MAX); 00495 RNA_def_boolean(ot->srna, "page", 0, "Page", "Scroll up one page"); 00496 } 00497 00498 /* ********************************************************* */ 00499 /* SINGLE-STEP VIEW ZOOMING OPERATOR */ 00500 00501 /* This group of operators come in several forms: 00502 * 1) Scrollwheel 'steps' - rolling mousewheel by one step zooms view by predefined amount 00503 * 2) Scrollwheel 'steps' + alt + ctrl/shift - zooms view on one axis only (ctrl=x, shift=y) // XXX this could be implemented... 00504 * 3) Pad +/- Keys - pressing each key moves the zooms the view by a predefined amount 00505 * 00506 * In order to make sure this works, each operator must define the following RNA-Operator Props: 00507 * zoomfacx, zoomfacy - These two zoom factors allow for non-uniform scaling. 00508 * It is safe to scale by 0, as these factors are used to determine 00509 * amount to enlarge 'cur' by 00510 */ 00511 00512 /* ------------------ 'Shared' stuff ------------------------ */ 00513 00514 /* temp customdata for operator */ 00515 typedef struct v2dViewZoomData { 00516 View2D *v2d; /* view2d we're operating in */ 00517 ARegion *ar; 00518 00519 /* needed for continuous zoom */ 00520 wmTimer *timer; 00521 double timer_lastdraw; 00522 00523 int lastx, lasty; /* previous x/y values of mouse in window */ 00524 int invoke_event; /* event type that invoked, for modal exits */ 00525 float dx, dy; /* running tally of previous delta values (for obtaining final zoom) */ 00526 float mx_2d, my_2d; /* initial mouse location in v2d coords */ 00527 } v2dViewZoomData; 00528 00529 00530 /* initialise panning customdata */ 00531 static int view_zoomdrag_init(bContext *C, wmOperator *op) 00532 { 00533 ARegion *ar= CTX_wm_region(C); 00534 v2dViewZoomData *vzd; 00535 View2D *v2d; 00536 00537 /* regions now have v2d-data by default, so check for region */ 00538 if (ar == NULL) 00539 return 0; 00540 v2d= &ar->v2d; 00541 00542 /* check that 2d-view is zoomable */ 00543 if ((v2d->keepzoom & V2D_LOCKZOOM_X) && (v2d->keepzoom & V2D_LOCKZOOM_Y)) 00544 return 0; 00545 00546 /* set custom-data for operator */ 00547 vzd= MEM_callocN(sizeof(v2dViewZoomData), "v2dViewZoomData"); 00548 op->customdata= vzd; 00549 00550 /* set pointers to owners */ 00551 vzd->v2d= v2d; 00552 vzd->ar = ar; 00553 00554 return 1; 00555 } 00556 00557 /* check if step-zoom can be applied */ 00558 static int view_zoom_poll(bContext *C) 00559 { 00560 ARegion *ar= CTX_wm_region(C); 00561 View2D *v2d; 00562 00563 /* check if there's a region in context to work with */ 00564 if (ar == NULL) 00565 return 0; 00566 v2d= &ar->v2d; 00567 00568 /* check that 2d-view is zoomable */ 00569 if ((v2d->keepzoom & V2D_LOCKZOOM_X) && (v2d->keepzoom & V2D_LOCKZOOM_Y)) 00570 return 0; 00571 00572 /* view is zoomable */ 00573 return 1; 00574 } 00575 00576 /* apply transform to view (i.e. adjust 'cur' rect) */ 00577 static void view_zoomstep_apply(bContext *C, wmOperator *op) 00578 { 00579 v2dViewZoomData *vzd= op->customdata; 00580 ARegion *ar= CTX_wm_region(C); 00581 View2D *v2d= &ar->v2d; 00582 float dx, dy, facx, facy; 00583 00584 /* calculate amount to move view by, ensuring symmetry so the 00585 * old zoom level is restored after zooming back the same amount 00586 */ 00587 facx= RNA_float_get(op->ptr, "zoomfacx"); 00588 facy= RNA_float_get(op->ptr, "zoomfacy"); 00589 00590 if (facx >= 0.0f) { 00591 dx= (v2d->cur.xmax - v2d->cur.xmin) * facx; 00592 dy= (v2d->cur.ymax - v2d->cur.ymin) * facy; 00593 } 00594 else { 00595 dx= ((v2d->cur.xmax - v2d->cur.xmin)/(1.0f + 2.0f*facx)) * facx; 00596 dy= ((v2d->cur.ymax - v2d->cur.ymin)/(1.0f + 2.0f*facy)) * facy; 00597 } 00598 00599 /* only resize view on an axis if change is allowed */ 00600 if ((v2d->keepzoom & V2D_LOCKZOOM_X)==0) { 00601 if (v2d->keepofs & V2D_LOCKOFS_X) { 00602 v2d->cur.xmax -= 2*dx; 00603 } 00604 else if (v2d->keepofs & V2D_KEEPOFS_X) { 00605 if (v2d->align & V2D_ALIGN_NO_POS_X) 00606 v2d->cur.xmin += 2*dx; 00607 else 00608 v2d->cur.xmax -= 2*dx; 00609 } 00610 else { 00611 if (U.uiflag & USER_ZOOM_TO_MOUSEPOS) { 00612 float mval_fac = (vzd->mx_2d - v2d->cur.xmin) / (v2d->cur.xmax-v2d->cur.xmin); 00613 float mval_faci = 1.0f - mval_fac; 00614 float ofs= (mval_fac * dx) - (mval_faci * dx); 00615 00616 v2d->cur.xmin += ofs + dx; 00617 v2d->cur.xmax += ofs - dx; 00618 } 00619 else { 00620 v2d->cur.xmin += dx; 00621 v2d->cur.xmax -= dx; 00622 } 00623 } 00624 } 00625 if ((v2d->keepzoom & V2D_LOCKZOOM_Y)==0) { 00626 if (v2d->keepofs & V2D_LOCKOFS_Y) { 00627 v2d->cur.ymax -= 2*dy; 00628 } 00629 else if (v2d->keepofs & V2D_KEEPOFS_Y) { 00630 if (v2d->align & V2D_ALIGN_NO_POS_Y) 00631 v2d->cur.ymin += 2*dy; 00632 else 00633 v2d->cur.ymax -= 2*dy; 00634 } 00635 else { 00636 if (U.uiflag & USER_ZOOM_TO_MOUSEPOS) { 00637 float mval_fac = (vzd->my_2d - v2d->cur.ymin) / (v2d->cur.ymax-v2d->cur.ymin); 00638 float mval_faci = 1.0f - mval_fac; 00639 float ofs= (mval_fac * dy) - (mval_faci * dy); 00640 00641 v2d->cur.ymin += ofs + dy; 00642 v2d->cur.ymax += ofs - dy; 00643 } 00644 else { 00645 v2d->cur.ymin += dy; 00646 v2d->cur.ymax -= dy; 00647 } 00648 } 00649 } 00650 00651 /* validate that view is in valid configuration after this operation */ 00652 UI_view2d_curRect_validate(v2d); 00653 00654 /* request updates to be done... */ 00655 ED_region_tag_redraw(vzd->ar); 00656 UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY); 00657 } 00658 00659 /* --------------- Individual Operators ------------------- */ 00660 00661 /* cleanup temp customdata */ 00662 static void view_zoomstep_exit(wmOperator *op) 00663 { 00664 if (op->customdata) { 00665 MEM_freeN(op->customdata); 00666 op->customdata= NULL; 00667 } 00668 } 00669 00670 /* this operator only needs this single callback, where it calls the view_zoom_*() methods */ 00671 static int view_zoomin_exec(bContext *C, wmOperator *op) 00672 { 00673 /* check that there's an active region, as View2D data resides there */ 00674 if (!view_zoom_poll(C)) 00675 return OPERATOR_PASS_THROUGH; 00676 00677 /* set RNA-Props - zooming in by uniform factor */ 00678 RNA_float_set(op->ptr, "zoomfacx", 0.0375f); 00679 RNA_float_set(op->ptr, "zoomfacy", 0.0375f); 00680 00681 /* apply movement, then we're done */ 00682 view_zoomstep_apply(C, op); 00683 00684 view_zoomstep_exit(op); 00685 00686 return OPERATOR_FINISHED; 00687 } 00688 00689 static int view_zoomin_invoke(bContext *C, wmOperator *op, wmEvent *event) 00690 { 00691 v2dViewZoomData *vzd; 00692 00693 if (!view_zoomdrag_init(C, op)) 00694 return OPERATOR_PASS_THROUGH; 00695 00696 vzd= op->customdata; 00697 00698 if (U.uiflag & USER_ZOOM_TO_MOUSEPOS) { 00699 ARegion *ar= CTX_wm_region(C); 00700 00701 /* store initial mouse position (in view space) */ 00702 UI_view2d_region_to_view(&ar->v2d, 00703 event->mval[0], event->mval[1], 00704 &vzd->mx_2d, &vzd->my_2d); 00705 } 00706 00707 return view_zoomin_exec(C, op); 00708 } 00709 00710 static void VIEW2D_OT_zoom_in(wmOperatorType *ot) 00711 { 00712 /* identifiers */ 00713 ot->name= "Zoom In"; 00714 ot->description= "Zoom in the view"; 00715 ot->idname= "VIEW2D_OT_zoom_in"; 00716 00717 /* api callbacks */ 00718 ot->invoke= view_zoomin_invoke; 00719 // ot->exec= view_zoomin_exec; // XXX, needs view_zoomdrag_init called first. 00720 ot->poll= view_zoom_poll; 00721 00722 /* rna - must keep these in sync with the other operators */ 00723 RNA_def_float(ot->srna, "zoomfacx", 0, -FLT_MAX, FLT_MAX, "Zoom Factor X", "", -FLT_MAX, FLT_MAX); 00724 RNA_def_float(ot->srna, "zoomfacy", 0, -FLT_MAX, FLT_MAX, "Zoom Factor Y", "", -FLT_MAX, FLT_MAX); 00725 } 00726 00727 /* this operator only needs this single callback, where it callsthe view_zoom_*() methods */ 00728 static int view_zoomout_exec(bContext *C, wmOperator *op) 00729 { 00730 /* check that there's an active region, as View2D data resides there */ 00731 if (!view_zoom_poll(C)) 00732 return OPERATOR_PASS_THROUGH; 00733 00734 /* set RNA-Props - zooming in by uniform factor */ 00735 RNA_float_set(op->ptr, "zoomfacx", -0.0375f); 00736 RNA_float_set(op->ptr, "zoomfacy", -0.0375f); 00737 00738 /* apply movement, then we're done */ 00739 view_zoomstep_apply(C, op); 00740 00741 view_zoomstep_exit(op); 00742 00743 return OPERATOR_FINISHED; 00744 } 00745 00746 static int view_zoomout_invoke(bContext *C, wmOperator *op, wmEvent *event) 00747 { 00748 v2dViewZoomData *vzd; 00749 00750 if (!view_zoomdrag_init(C, op)) 00751 return OPERATOR_PASS_THROUGH; 00752 00753 vzd= op->customdata; 00754 00755 if(U.uiflag & USER_ZOOM_TO_MOUSEPOS) { 00756 ARegion *ar= CTX_wm_region(C); 00757 00758 /* store initial mouse position (in view space) */ 00759 UI_view2d_region_to_view(&ar->v2d, 00760 event->mval[0], event->mval[1], 00761 &vzd->mx_2d, &vzd->my_2d); 00762 } 00763 00764 return view_zoomout_exec(C, op); 00765 } 00766 00767 static void VIEW2D_OT_zoom_out(wmOperatorType *ot) 00768 { 00769 /* identifiers */ 00770 ot->name= "Zoom Out"; 00771 ot->description= "Zoom out the view"; 00772 ot->idname= "VIEW2D_OT_zoom_out"; 00773 00774 /* api callbacks */ 00775 ot->invoke= view_zoomout_invoke; 00776 // ot->exec= view_zoomout_exec; // XXX, needs view_zoomdrag_init called first. 00777 ot->poll= view_zoom_poll; 00778 00779 /* rna - must keep these in sync with the other operators */ 00780 RNA_def_float(ot->srna, "zoomfacx", 0, -FLT_MAX, FLT_MAX, "Zoom Factor X", "", -FLT_MAX, FLT_MAX); 00781 RNA_def_float(ot->srna, "zoomfacy", 0, -FLT_MAX, FLT_MAX, "Zoom Factor Y", "", -FLT_MAX, FLT_MAX); 00782 } 00783 00784 /* ********************************************************* */ 00785 /* DRAG-ZOOM OPERATOR */ 00786 00787 /* MMB Drag - allows non-uniform scaling by dragging mouse 00788 * 00789 * In order to make sure this works, each operator must define the following RNA-Operator Props: 00790 * deltax, deltay - amounts to add to each side of the 'cur' rect 00791 */ 00792 00793 /* apply transform to view (i.e. adjust 'cur' rect) */ 00794 static void view_zoomdrag_apply(bContext *C, wmOperator *op) 00795 { 00796 v2dViewZoomData *vzd= op->customdata; 00797 View2D *v2d= vzd->v2d; 00798 float dx, dy; 00799 00800 /* get amount to move view by */ 00801 dx= RNA_float_get(op->ptr, "deltax"); 00802 dy= RNA_float_get(op->ptr, "deltay"); 00803 00804 /* continous zoom shouldn't move that fast... */ 00805 if (U.viewzoom == USER_ZOOM_CONT) { // XXX store this setting as RNA prop? 00806 double time= PIL_check_seconds_timer(); 00807 float time_step= (float)(time - vzd->timer_lastdraw); 00808 00809 dx *= time_step * 0.5f; 00810 dy *= time_step * 0.5f; 00811 00812 vzd->timer_lastdraw= time; 00813 } 00814 00815 /* only move view on an axis if change is allowed */ 00816 if ((v2d->keepzoom & V2D_LOCKZOOM_X)==0) { 00817 if (v2d->keepofs & V2D_LOCKOFS_X) { 00818 v2d->cur.xmax -= 2*dx; 00819 } 00820 else { 00821 if (U.uiflag & USER_ZOOM_TO_MOUSEPOS) { 00822 float mval_fac = (vzd->mx_2d - v2d->cur.xmin) / (v2d->cur.xmax-v2d->cur.xmin); 00823 float mval_faci = 1.0f - mval_fac; 00824 float ofs= (mval_fac * dx) - (mval_faci * dx); 00825 00826 v2d->cur.xmin += ofs + dx; 00827 v2d->cur.xmax += ofs - dx; 00828 } 00829 else { 00830 v2d->cur.xmin += dx; 00831 v2d->cur.xmax -= dx; 00832 } 00833 } 00834 } 00835 if ((v2d->keepzoom & V2D_LOCKZOOM_Y)==0) { 00836 if (v2d->keepofs & V2D_LOCKOFS_Y) { 00837 v2d->cur.ymax -= 2*dy; 00838 } 00839 else { 00840 if (U.uiflag & USER_ZOOM_TO_MOUSEPOS) { 00841 float mval_fac = (vzd->my_2d - v2d->cur.ymin) / (v2d->cur.ymax-v2d->cur.ymin); 00842 float mval_faci = 1.0f - mval_fac; 00843 float ofs= (mval_fac * dy) - (mval_faci * dy); 00844 00845 v2d->cur.ymin += ofs + dy; 00846 v2d->cur.ymax += ofs - dy; 00847 } 00848 else { 00849 v2d->cur.ymin += dy; 00850 v2d->cur.ymax -= dy; 00851 } 00852 } 00853 } 00854 00855 /* validate that view is in valid configuration after this operation */ 00856 UI_view2d_curRect_validate(v2d); 00857 00858 /* request updates to be done... */ 00859 ED_region_tag_redraw(vzd->ar); 00860 UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY); 00861 } 00862 00863 /* cleanup temp customdata */ 00864 static void view_zoomdrag_exit(bContext *C, wmOperator *op) 00865 { 00866 if (op->customdata) { 00867 v2dViewZoomData *vzd= op->customdata; 00868 00869 if(vzd->timer) 00870 WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), vzd->timer); 00871 00872 MEM_freeN(op->customdata); 00873 op->customdata= NULL; 00874 } 00875 } 00876 00877 static int view_zoomdrag_cancel(bContext *C, wmOperator *op) 00878 { 00879 view_zoomdrag_exit(C, op); 00880 00881 return OPERATOR_CANCELLED; 00882 } 00883 00884 /* for 'redo' only, with no user input */ 00885 static int view_zoomdrag_exec(bContext *C, wmOperator *op) 00886 { 00887 if (!view_zoomdrag_init(C, op)) 00888 return OPERATOR_PASS_THROUGH; 00889 00890 view_zoomdrag_apply(C, op); 00891 view_zoomdrag_exit(C, op); 00892 return OPERATOR_FINISHED; 00893 } 00894 00895 /* set up modal operator and relevant settings */ 00896 static int view_zoomdrag_invoke(bContext *C, wmOperator *op, wmEvent *event) 00897 { 00898 wmWindow *window= CTX_wm_window(C); 00899 v2dViewZoomData *vzd; 00900 View2D *v2d; 00901 00902 /* set up customdata */ 00903 if (!view_zoomdrag_init(C, op)) 00904 return OPERATOR_PASS_THROUGH; 00905 00906 vzd= op->customdata; 00907 v2d= vzd->v2d; 00908 00909 if (event->type == MOUSEZOOM) { 00910 float dx, dy, fac; 00911 00912 vzd->lastx= event->prevx; 00913 vzd->lasty= event->prevy; 00914 00915 /* As we have only 1D information (magnify value), feed both axes 00916 * with magnify information that is stored in x axis 00917 */ 00918 fac= 0.01f * (event->x - event->prevx); 00919 dx= fac * (v2d->cur.xmax - v2d->cur.xmin) / 10.0f; 00920 dy= fac * (v2d->cur.ymax - v2d->cur.ymin) / 10.0f; 00921 00922 RNA_float_set(op->ptr, "deltax", dx); 00923 RNA_float_set(op->ptr, "deltay", dy); 00924 00925 view_zoomdrag_apply(C, op); 00926 view_zoomdrag_exit(C, op); 00927 return OPERATOR_FINISHED; 00928 } 00929 00930 /* set initial settings */ 00931 vzd->lastx= event->x; 00932 vzd->lasty= event->y; 00933 RNA_float_set(op->ptr, "deltax", 0); 00934 RNA_float_set(op->ptr, "deltay", 0); 00935 00936 /* for modal exit test */ 00937 vzd->invoke_event= event->type; 00938 00939 if (U.uiflag & USER_ZOOM_TO_MOUSEPOS) { 00940 ARegion *ar= CTX_wm_region(C); 00941 00942 /* store initial mouse position (in view space) */ 00943 UI_view2d_region_to_view(&ar->v2d, 00944 event->mval[0], event->mval[1], 00945 &vzd->mx_2d, &vzd->my_2d); 00946 } 00947 00948 if (v2d->keepofs & V2D_LOCKOFS_X) 00949 WM_cursor_modal(window, BC_NS_SCROLLCURSOR); 00950 else if (v2d->keepofs & V2D_LOCKOFS_Y) 00951 WM_cursor_modal(window, BC_EW_SCROLLCURSOR); 00952 else 00953 WM_cursor_modal(window, BC_NSEW_SCROLLCURSOR); 00954 00955 /* add temp handler */ 00956 WM_event_add_modal_handler(C, op); 00957 00958 if (U.viewzoom == USER_ZOOM_CONT) { 00959 /* needs a timer to continue redrawing */ 00960 vzd->timer= WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.01f); 00961 vzd->timer_lastdraw= PIL_check_seconds_timer(); 00962 } 00963 00964 return OPERATOR_RUNNING_MODAL; 00965 } 00966 00967 /* handle user input - calculations of mouse-movement need to be done here, not in the apply callback! */ 00968 static int view_zoomdrag_modal(bContext *C, wmOperator *op, wmEvent *event) 00969 { 00970 v2dViewZoomData *vzd= op->customdata; 00971 View2D *v2d= vzd->v2d; 00972 00973 /* execute the events */ 00974 if (event->type == TIMER && event->customdata == vzd->timer) { 00975 view_zoomdrag_apply(C, op); 00976 } 00977 else if(event->type == MOUSEMOVE) { 00978 float dx, dy; 00979 00980 /* calculate new delta transform, based on zooming mode */ 00981 if (U.viewzoom == USER_ZOOM_SCALE) { 00982 /* 'scale' zooming */ 00983 float dist; 00984 00985 /* x-axis transform */ 00986 dist = (v2d->mask.xmax - v2d->mask.xmin) / 2.0f; 00987 dx= 1.0f - (fabsf(vzd->lastx - dist) + 2.0f) / (fabsf(event->x - dist) + 2.0f); 00988 dx*= 0.5f * (v2d->cur.xmax - v2d->cur.xmin); 00989 00990 /* y-axis transform */ 00991 dist = (v2d->mask.ymax - v2d->mask.ymin) / 2.0f; 00992 dy= 1.0f - (fabsf(vzd->lasty - dist) + 2.0f) / (fabsf(event->y - dist) + 2.0f); 00993 dy*= 0.5f * (v2d->cur.ymax - v2d->cur.ymin); 00994 } 00995 else { 00996 /* 'continuous' or 'dolly' */ 00997 float fac; 00998 00999 /* x-axis transform */ 01000 fac= 0.01f * (event->x - vzd->lastx); 01001 dx= fac * (v2d->cur.xmax - v2d->cur.xmin); 01002 01003 /* y-axis transform */ 01004 fac= 0.01f * (event->y - vzd->lasty); 01005 dy= fac * (v2d->cur.ymax - v2d->cur.ymin); 01006 #if 0 01007 /* continous zoom shouldn't move that fast... */ 01008 if (U.viewzoom == USER_ZOOM_CONT) { // XXX store this setting as RNA prop? 01009 double time= PIL_check_seconds_timer(); 01010 float time_step= (float)(time - vzd->timer_lastdraw); 01011 01012 dx /= (0.1f / time_step); 01013 dy /= (0.1f / time_step); 01014 01015 vzd->timer_lastdraw= time; 01016 } 01017 #endif 01018 } 01019 01020 /* set transform amount, and add current deltas to stored total delta (for redo) */ 01021 RNA_float_set(op->ptr, "deltax", dx); 01022 RNA_float_set(op->ptr, "deltay", dy); 01023 vzd->dx += dx; 01024 vzd->dy += dy; 01025 01026 /* store mouse coordinates for next time, if not doing continuous zoom 01027 * - continuous zoom only depends on distance of mouse to starting point to determine rate of change 01028 */ 01029 if (U.viewzoom != USER_ZOOM_CONT) { // XXX store this setting as RNA prop? 01030 vzd->lastx= event->x; 01031 vzd->lasty= event->y; 01032 } 01033 01034 /* apply zooming */ 01035 view_zoomdrag_apply(C, op); 01036 } 01037 else if (event->type == vzd->invoke_event || event->type==ESCKEY) { 01038 if (event->val == KM_RELEASE) { 01039 01040 /* for redo, store the overall deltas - need to respect zoom-locks here... */ 01041 if ((v2d->keepzoom & V2D_LOCKZOOM_X)==0) 01042 RNA_float_set(op->ptr, "deltax", vzd->dx); 01043 else 01044 RNA_float_set(op->ptr, "deltax", 0); 01045 01046 if ((v2d->keepzoom & V2D_LOCKZOOM_Y)==0) 01047 RNA_float_set(op->ptr, "deltay", vzd->dy); 01048 else 01049 RNA_float_set(op->ptr, "deltay", 0); 01050 01051 /* free customdata */ 01052 view_zoomdrag_exit(C, op); 01053 WM_cursor_restore(CTX_wm_window(C)); 01054 01055 return OPERATOR_FINISHED; 01056 } 01057 } 01058 01059 return OPERATOR_RUNNING_MODAL; 01060 } 01061 01062 static void VIEW2D_OT_zoom(wmOperatorType *ot) 01063 { 01064 /* identifiers */ 01065 ot->name= "Zoom 2D View"; 01066 ot->description= "Zoom in/out the view"; 01067 ot->idname= "VIEW2D_OT_zoom"; 01068 01069 /* api callbacks */ 01070 ot->exec= view_zoomdrag_exec; 01071 ot->invoke= view_zoomdrag_invoke; 01072 ot->modal= view_zoomdrag_modal; 01073 ot->cancel= view_zoomdrag_cancel; 01074 01075 ot->poll= view_zoom_poll; 01076 01077 /* operator is repeatable */ 01078 // ot->flag= OPTYPE_BLOCKING; 01079 01080 /* rna - must keep these in sync with the other operators */ 01081 RNA_def_float(ot->srna, "deltax", 0, -FLT_MAX, FLT_MAX, "Delta X", "", -FLT_MAX, FLT_MAX); 01082 RNA_def_float(ot->srna, "deltay", 0, -FLT_MAX, FLT_MAX, "Delta Y", "", -FLT_MAX, FLT_MAX); 01083 } 01084 01085 /* ********************************************************* */ 01086 /* BORDER-ZOOM */ 01087 01088 /* The user defines a rect using standard borderselect tools, and we use this rect to 01089 * define the new zoom-level of the view in the following ways: 01090 * 1) LEFTMOUSE - zoom in to view 01091 * 2) RIGHTMOUSE - zoom out of view 01092 * 01093 * Currently, these key mappings are hardcoded, but it shouldn't be too important to 01094 * have custom keymappings for this... 01095 */ 01096 01097 static int view_borderzoom_exec(bContext *C, wmOperator *op) 01098 { 01099 ARegion *ar= CTX_wm_region(C); 01100 View2D *v2d= &ar->v2d; 01101 rctf rect; 01102 int gesture_mode; 01103 01104 /* convert coordinates of rect to 'tot' rect coordinates */ 01105 UI_view2d_region_to_view(v2d, RNA_int_get(op->ptr, "xmin"), RNA_int_get(op->ptr, "ymin"), &rect.xmin, &rect.ymin); 01106 UI_view2d_region_to_view(v2d, RNA_int_get(op->ptr, "xmax"), RNA_int_get(op->ptr, "ymax"), &rect.xmax, &rect.ymax); 01107 01108 /* check if zooming in/out view */ 01109 gesture_mode= RNA_int_get(op->ptr, "gesture_mode"); 01110 01111 if (gesture_mode == GESTURE_MODAL_IN) { 01112 /* zoom in: 01113 * - 'cur' rect will be defined by the coordinates of the border region 01114 * - just set the 'cur' rect to have the same coordinates as the border region 01115 * if zoom is allowed to be changed 01116 */ 01117 if ((v2d->keepzoom & V2D_LOCKZOOM_X)==0) { 01118 v2d->cur.xmin= rect.xmin; 01119 v2d->cur.xmax= rect.xmax; 01120 } 01121 if ((v2d->keepzoom & V2D_LOCKZOOM_Y)==0) { 01122 v2d->cur.ymin= rect.ymin; 01123 v2d->cur.ymax= rect.ymax; 01124 } 01125 } 01126 else /* if (gesture_mode == GESTURE_MODAL_OUT) */ { 01127 /* zoom out: 01128 * - the current 'cur' rect coordinates are going to end upwhere the 'rect' ones are, 01129 * but the 'cur' rect coordinates will need to be adjusted to take in more of the view 01130 * - calculate zoom factor, and adjust using center-point 01131 */ 01132 float zoom, center, size; 01133 01134 // TODO: is this zoom factor calculation valid? It seems to produce same results everytime... 01135 if ((v2d->keepzoom & V2D_LOCKZOOM_X)==0) { 01136 size= (v2d->cur.xmax - v2d->cur.xmin); 01137 zoom= size / (rect.xmax - rect.xmin); 01138 center= (v2d->cur.xmax + v2d->cur.xmin) * 0.5f; 01139 01140 v2d->cur.xmin= center - (size * zoom); 01141 v2d->cur.xmax= center + (size * zoom); 01142 } 01143 if ((v2d->keepzoom & V2D_LOCKZOOM_Y)==0) { 01144 size= (v2d->cur.ymax - v2d->cur.ymin); 01145 zoom= size / (rect.ymax - rect.ymin); 01146 center= (v2d->cur.ymax + v2d->cur.ymin) * 0.5f; 01147 01148 v2d->cur.ymin= center - (size * zoom); 01149 v2d->cur.ymax= center + (size * zoom); 01150 } 01151 } 01152 01153 /* validate that view is in valid configuration after this operation */ 01154 UI_view2d_curRect_validate(v2d); 01155 01156 /* request updates to be done... */ 01157 ED_region_tag_redraw(ar); 01158 UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY); 01159 01160 return OPERATOR_FINISHED; 01161 } 01162 01163 static void VIEW2D_OT_zoom_border(wmOperatorType *ot) 01164 { 01165 /* identifiers */ 01166 ot->name= "Zoom to Border"; 01167 ot->description= "Zoom in the view to the nearest item contained in the border"; 01168 ot->idname= "VIEW2D_OT_zoom_border"; 01169 01170 /* api callbacks */ 01171 ot->invoke= WM_border_select_invoke; 01172 ot->exec= view_borderzoom_exec; 01173 ot->modal= WM_border_select_modal; 01174 ot->cancel= WM_border_select_cancel; 01175 01176 ot->poll= view_zoom_poll; 01177 01178 /* rna */ 01179 RNA_def_int(ot->srna, "gesture_mode", 0, INT_MIN, INT_MAX, "Gesture Mode", "", INT_MIN, INT_MAX); 01180 RNA_def_int(ot->srna, "xmin", 0, INT_MIN, INT_MAX, "X Min", "", INT_MIN, INT_MAX); 01181 RNA_def_int(ot->srna, "xmax", 0, INT_MIN, INT_MAX, "X Max", "", INT_MIN, INT_MAX); 01182 RNA_def_int(ot->srna, "ymin", 0, INT_MIN, INT_MAX, "Y Min", "", INT_MIN, INT_MAX); 01183 RNA_def_int(ot->srna, "ymax", 0, INT_MIN, INT_MAX, "Y Max", "", INT_MIN, INT_MAX); 01184 } 01185 01186 /* ********************************************************* */ 01187 /* SCROLLERS */ 01188 01189 /* Scrollers should behave in the following ways, when clicked on with LMB (and dragged): 01190 * 1) 'Handles' on end of 'bubble' - when the axis that the scroller represents is zoomable, 01191 * enlarge 'cur' rect on the relevant side 01192 * 2) 'Bubble'/'bar' - just drag, and bar should move with mouse (view pans opposite) 01193 * 01194 * In order to make sure this works, each operator must define the following RNA-Operator Props: 01195 * deltax, deltay - define how much to move view by (relative to zoom-correction factor) 01196 */ 01197 01198 /* customdata for scroller-invoke data */ 01199 typedef struct v2dScrollerMove { 01200 View2D *v2d; /* View2D data that this operation affects */ 01201 ARegion *ar; /* region that the scroller is in */ 01202 01203 short scroller; /* scroller that mouse is in ('h' or 'v') */ 01204 short zone; /* -1 is min zoomer, 0 is bar, 1 is max zoomer */ // XXX find some way to provide visual feedback of this (active color?) 01205 01206 float fac; /* view adjustment factor, based on size of region */ 01207 float delta; /* amount moved by mouse on axis of interest */ 01208 01209 float scrollbarwidth; /* width of the scrollbar itself, used for page up/down clicks */ 01210 int scrollbar_orig; /* initial location of scrollbar x/y, mouse relative */ 01211 01212 int lastx, lasty; /* previous mouse coordinates (in screen coordinates) for determining movement */ 01213 } v2dScrollerMove; 01214 01215 01216 /* View2DScrollers is typedef'd in UI_view2d.h 01217 * This is a CUT DOWN VERSION of the 'real' version, which is defined in view2d.c, as we only need focus bubble info 01218 * WARNING: the start of this struct must not change, so that it stays in sync with the 'real' version 01219 * For now, we don't need to have a separate (internal) header for structs like this... 01220 */ 01221 struct View2DScrollers { 01222 /* focus bubbles */ 01223 int vert_min, vert_max; /* vertical scrollbar */ 01224 int hor_min, hor_max; /* horizontal scrollbar */ 01225 }; 01226 01227 /* quick enum for vsm->zone (scroller handles) */ 01228 enum { 01229 SCROLLHANDLE_MIN= -1, 01230 SCROLLHANDLE_BAR, 01231 SCROLLHANDLE_MAX, 01232 SCROLLHANDLE_MIN_OUTSIDE, 01233 SCROLLHANDLE_MAX_OUTSIDE 01234 } /*eV2DScrollerHandle_Zone*/; 01235 01236 /* ------------------------ */ 01237 01238 /* check if mouse is within scroller handle 01239 * - mouse = relevant mouse coordinate in region space 01240 * - sc_min, sc_max = extents of scroller 'groove' (potential available space for scroller) 01241 * - sh_min, sh_max = positions of scrollbar handles 01242 */ 01243 static short mouse_in_scroller_handle(int mouse, int sc_min, int sc_max, int sh_min, int sh_max) 01244 { 01245 short in_min, in_max, in_bar, out_min, out_max, in_view=1; 01246 01247 /* firstly, check if 01248 * - 'bubble' fills entire scroller 01249 * - 'bubble' completely out of view on either side 01250 */ 01251 if ((sh_min <= sc_min) && (sh_max >= sc_max)) in_view= 0; 01252 if (sh_min == sh_max) { 01253 if (sh_min <= sc_min) in_view= 0; 01254 if (sh_max >= sc_max) in_view= 0; 01255 } 01256 else { 01257 if (sh_max <= sc_min) in_view= 0; 01258 if (sh_min >= sc_max) in_view= 0; 01259 } 01260 01261 01262 if (in_view == 0) { 01263 return SCROLLHANDLE_BAR; 01264 } 01265 01266 /* check if mouse is in or past either handle */ 01267 // TODO: check if these extents are still valid or not 01268 in_max= ( (mouse >= (sh_max - V2D_SCROLLER_HANDLE_SIZE)) && (mouse <= (sh_max + V2D_SCROLLER_HANDLE_SIZE)) ); 01269 in_min= ( (mouse <= (sh_min + V2D_SCROLLER_HANDLE_SIZE)) && (mouse >= (sh_min - V2D_SCROLLER_HANDLE_SIZE)) ); 01270 in_bar= ( (mouse < (sh_max - V2D_SCROLLER_HANDLE_SIZE)) && (mouse > (sh_min + V2D_SCROLLER_HANDLE_SIZE)) ); 01271 out_min= mouse < (sh_min - V2D_SCROLLER_HANDLE_SIZE); 01272 out_max= mouse > (sh_max + V2D_SCROLLER_HANDLE_SIZE); 01273 01274 if (in_bar) 01275 return SCROLLHANDLE_BAR; 01276 else if (in_max) 01277 return SCROLLHANDLE_MAX; 01278 else if (in_min) 01279 return SCROLLHANDLE_MIN; 01280 else if (out_min) 01281 return SCROLLHANDLE_MIN_OUTSIDE; 01282 else if (out_max) 01283 return SCROLLHANDLE_MAX_OUTSIDE; 01284 01285 /* unlikely to happen, though we just cover it in case */ 01286 return SCROLLHANDLE_BAR; 01287 } 01288 01289 /* initialise customdata for scroller manipulation operator */ 01290 static void scroller_activate_init(bContext *C, wmOperator *op, wmEvent *event, short in_scroller) 01291 { 01292 v2dScrollerMove *vsm; 01293 View2DScrollers *scrollers; 01294 ARegion *ar= CTX_wm_region(C); 01295 View2D *v2d= &ar->v2d; 01296 float mask_size; 01297 01298 /* set custom-data for operator */ 01299 vsm= MEM_callocN(sizeof(v2dScrollerMove), "v2dScrollerMove"); 01300 op->customdata= vsm; 01301 01302 /* set general data */ 01303 vsm->v2d= v2d; 01304 vsm->ar= ar; 01305 vsm->scroller= in_scroller; 01306 01307 /* store mouse-coordinates, and convert mouse/screen coordinates to region coordinates */ 01308 vsm->lastx = event->x; 01309 vsm->lasty = event->y; 01310 /* 'zone' depends on where mouse is relative to bubble 01311 * - zooming must be allowed on this axis, otherwise, default to pan 01312 */ 01313 scrollers= UI_view2d_scrollers_calc(C, v2d, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY); 01314 01315 01316 if (in_scroller == 'h') { 01317 /* horizontal scroller - calculate adjustment factor first */ 01318 mask_size= (float)(v2d->hor.xmax - v2d->hor.xmin); 01319 vsm->fac= (v2d->tot.xmax - v2d->tot.xmin) / mask_size; 01320 01321 /* get 'zone' (i.e. which part of scroller is activated) */ 01322 vsm->zone= mouse_in_scroller_handle(event->mval[0], v2d->hor.xmin, v2d->hor.xmax, scrollers->hor_min, scrollers->hor_max); 01323 01324 if ((v2d->keepzoom & V2D_LOCKZOOM_X) && ELEM(vsm->zone, SCROLLHANDLE_MIN, SCROLLHANDLE_MAX)) { 01325 /* default to scroll, as handles not usable */ 01326 vsm->zone= SCROLLHANDLE_BAR; 01327 } 01328 01329 vsm->scrollbarwidth = scrollers->hor_max - scrollers->hor_min; 01330 vsm->scrollbar_orig = ((scrollers->hor_max + scrollers->hor_min) / 2) + ar->winrct.xmin; 01331 } 01332 else { 01333 /* vertical scroller - calculate adjustment factor first */ 01334 mask_size= (float)(v2d->vert.ymax - v2d->vert.ymin); 01335 vsm->fac= (v2d->tot.ymax - v2d->tot.ymin) / mask_size; 01336 01337 /* get 'zone' (i.e. which part of scroller is activated) */ 01338 vsm->zone= mouse_in_scroller_handle(event->mval[1], v2d->vert.ymin, v2d->vert.ymax, scrollers->vert_min, scrollers->vert_max); 01339 01340 if ((v2d->keepzoom & V2D_LOCKZOOM_Y) && ELEM(vsm->zone, SCROLLHANDLE_MIN, SCROLLHANDLE_MAX)) { 01341 /* default to scroll, as handles not usable */ 01342 vsm->zone= SCROLLHANDLE_BAR; 01343 } 01344 01345 vsm->scrollbarwidth = scrollers->vert_max - scrollers->vert_min; 01346 vsm->scrollbar_orig = ((scrollers->vert_max + scrollers->vert_min) / 2) + + ar->winrct.ymin; 01347 } 01348 01349 UI_view2d_scrollers_free(scrollers); 01350 ED_region_tag_redraw(ar); 01351 } 01352 01353 /* cleanup temp customdata */ 01354 static void scroller_activate_exit(bContext *C, wmOperator *op) 01355 { 01356 if (op->customdata) { 01357 v2dScrollerMove *vsm= op->customdata; 01358 01359 vsm->v2d->scroll_ui &= ~(V2D_SCROLL_H_ACTIVE|V2D_SCROLL_V_ACTIVE); 01360 01361 MEM_freeN(op->customdata); 01362 op->customdata= NULL; 01363 01364 ED_region_tag_redraw(CTX_wm_region(C)); 01365 } 01366 } 01367 01368 static int scroller_activate_cancel(bContext *C, wmOperator *op) 01369 { 01370 scroller_activate_exit(C, op); 01371 01372 return OPERATOR_CANCELLED; 01373 } 01374 01375 /* apply transform to view (i.e. adjust 'cur' rect) */ 01376 static void scroller_activate_apply(bContext *C, wmOperator *op) 01377 { 01378 v2dScrollerMove *vsm= op->customdata; 01379 View2D *v2d= vsm->v2d; 01380 float temp; 01381 01382 /* calculate amount to move view by */ 01383 temp= vsm->fac * vsm->delta; 01384 01385 /* type of movement */ 01386 switch (vsm->zone) { 01387 case SCROLLHANDLE_MIN: 01388 /* only expand view on axis if zoom is allowed */ 01389 if ((vsm->scroller == 'h') && !(v2d->keepzoom & V2D_LOCKZOOM_X)) 01390 v2d->cur.xmin -= temp; 01391 if ((vsm->scroller == 'v') && !(v2d->keepzoom & V2D_LOCKZOOM_Y)) 01392 v2d->cur.ymin -= temp; 01393 break; 01394 01395 case SCROLLHANDLE_MAX: 01396 01397 /* only expand view on axis if zoom is allowed */ 01398 if ((vsm->scroller == 'h') && !(v2d->keepzoom & V2D_LOCKZOOM_X)) 01399 v2d->cur.xmax += temp; 01400 if ((vsm->scroller == 'v') && !(v2d->keepzoom & V2D_LOCKZOOM_Y)) 01401 v2d->cur.ymax += temp; 01402 break; 01403 01404 case SCROLLHANDLE_MIN_OUTSIDE: 01405 case SCROLLHANDLE_MAX_OUTSIDE: 01406 case SCROLLHANDLE_BAR: 01407 default: 01408 /* only move view on an axis if panning is allowed */ 01409 if ((vsm->scroller == 'h') && !(v2d->keepofs & V2D_LOCKOFS_X)) { 01410 v2d->cur.xmin += temp; 01411 v2d->cur.xmax += temp; 01412 } 01413 if ((vsm->scroller == 'v') && !(v2d->keepofs & V2D_LOCKOFS_Y)) { 01414 v2d->cur.ymin += temp; 01415 v2d->cur.ymax += temp; 01416 } 01417 break; 01418 01419 } 01420 01421 /* validate that view is in valid configuration after this operation */ 01422 UI_view2d_curRect_validate(v2d); 01423 01424 /* request updates to be done... */ 01425 ED_region_tag_redraw(vsm->ar); 01426 UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY); 01427 } 01428 01429 /* handle user input for scrollers - calculations of mouse-movement need to be done here, not in the apply callback! */ 01430 static int scroller_activate_modal(bContext *C, wmOperator *op, wmEvent *event) 01431 { 01432 v2dScrollerMove *vsm= op->customdata; 01433 01434 /* execute the events */ 01435 switch (event->type) { 01436 case MOUSEMOVE: 01437 { 01438 /* calculate new delta transform, then store mouse-coordinates for next-time */ 01439 if (ELEM(vsm->zone, SCROLLHANDLE_BAR, SCROLLHANDLE_MAX)) { 01440 /* if using bar (i.e. 'panning') or 'max' zoom widget */ 01441 switch (vsm->scroller) { 01442 case 'h': /* horizontal scroller - so only horizontal movement ('cur' moves opposite to mouse) */ 01443 vsm->delta= (float)(event->x - vsm->lastx); 01444 break; 01445 case 'v': /* vertical scroller - so only vertical movement ('cur' moves opposite to mouse) */ 01446 vsm->delta= (float)(event->y - vsm->lasty); 01447 break; 01448 } 01449 } 01450 else if (vsm->zone == SCROLLHANDLE_MIN) { 01451 /* using 'min' zoom widget */ 01452 switch (vsm->scroller) { 01453 case 'h': /* horizontal scroller - so only horizontal movement ('cur' moves with mouse) */ 01454 vsm->delta= (float)(vsm->lastx - event->x); 01455 break; 01456 case 'v': /* vertical scroller - so only vertical movement ('cur' moves with to mouse) */ 01457 vsm->delta= (float)(vsm->lasty - event->y); 01458 break; 01459 } 01460 } 01461 01462 /* store previous coordinates */ 01463 vsm->lastx= event->x; 01464 vsm->lasty= event->y; 01465 01466 scroller_activate_apply(C, op); 01467 } 01468 break; 01469 01470 case LEFTMOUSE: 01471 case MIDDLEMOUSE: 01472 if (event->val==KM_RELEASE) { 01473 /* single-click was in empty space outside bubble, so scroll by 1 'page' */ 01474 if (ELEM(vsm->zone, SCROLLHANDLE_MIN_OUTSIDE, SCROLLHANDLE_MAX_OUTSIDE)) { 01475 if (vsm->zone == SCROLLHANDLE_MIN_OUTSIDE) 01476 vsm->delta = -vsm->scrollbarwidth * 0.8f; 01477 else if (vsm->zone == SCROLLHANDLE_MAX_OUTSIDE) 01478 vsm->delta = vsm->scrollbarwidth * 0.8f; 01479 01480 scroller_activate_apply(C, op); 01481 scroller_activate_exit(C, op); 01482 return OPERATOR_FINISHED; 01483 } 01484 01485 /* otherwise, end the drag action */ 01486 if (vsm->lastx || vsm->lasty) { 01487 scroller_activate_exit(C, op); 01488 return OPERATOR_FINISHED; 01489 } 01490 } 01491 break; 01492 01493 } 01494 01495 return OPERATOR_RUNNING_MODAL; 01496 } 01497 01498 01499 /* a click (or click drag in progress) should have occurred, so check if it happened in scrollbar */ 01500 static int scroller_activate_invoke(bContext *C, wmOperator *op, wmEvent *event) 01501 { 01502 ARegion *ar= CTX_wm_region(C); 01503 View2D *v2d= &ar->v2d; 01504 short in_scroller= 0; 01505 01506 /* check if mouse in scrollbars, if they're enabled */ 01507 in_scroller= UI_view2d_mouse_in_scrollers(C, v2d, event->x, event->y); 01508 01509 /* if in a scroller, init customdata then set modal handler which will catch mousedown to start doing useful stuff */ 01510 if (in_scroller) { 01511 v2dScrollerMove *vsm; 01512 01513 /* initialise customdata */ 01514 scroller_activate_init(C, op, event, in_scroller); 01515 vsm= (v2dScrollerMove *)op->customdata; 01516 01517 /* support for quick jump to location - gtk and qt do this on linux */ 01518 if (event->type == MIDDLEMOUSE) { 01519 switch (vsm->scroller) { 01520 case 'h': /* horizontal scroller - so only horizontal movement ('cur' moves opposite to mouse) */ 01521 vsm->delta= (float)(event->x - vsm->scrollbar_orig); 01522 break; 01523 case 'v': /* vertical scroller - so only vertical movement ('cur' moves opposite to mouse) */ 01524 vsm->delta= (float)(event->y - vsm->scrollbar_orig); 01525 break; 01526 } 01527 scroller_activate_apply(C, op); 01528 01529 vsm->zone= SCROLLHANDLE_BAR; 01530 } 01531 01532 /* check if zoom zones are inappropriate (i.e. zoom widgets not shown), so cannot continue 01533 * NOTE: see view2d.c for latest conditions, and keep this in sync with that 01534 */ 01535 if (ELEM(vsm->zone, SCROLLHANDLE_MIN, SCROLLHANDLE_MAX)) { 01536 if ( ((vsm->scroller=='h') && (v2d->scroll & V2D_SCROLL_SCALE_HORIZONTAL)==0) || 01537 ((vsm->scroller=='v') && (v2d->scroll & V2D_SCROLL_SCALE_VERTICAL)==0) ) 01538 { 01539 /* switch to bar (i.e. no scaling gets handled) */ 01540 vsm->zone= SCROLLHANDLE_BAR; 01541 } 01542 } 01543 01544 /* check if zone is inappropriate (i.e. 'bar' but panning is banned), so cannot continue */ 01545 if (vsm->zone == SCROLLHANDLE_BAR) { 01546 if ( ((vsm->scroller=='h') && (v2d->keepofs & V2D_LOCKOFS_X)) || 01547 ((vsm->scroller=='v') && (v2d->keepofs & V2D_LOCKOFS_Y)) ) 01548 { 01549 /* free customdata initialised */ 01550 scroller_activate_exit(C, op); 01551 01552 /* can't catch this event for ourselves, so let it go to someone else? */ 01553 return OPERATOR_PASS_THROUGH; 01554 } 01555 } 01556 01557 /* zone is also inappropriate if scroller is not visible... */ 01558 if ( ((vsm->scroller=='h') && (v2d->scroll & (V2D_SCROLL_HORIZONTAL_HIDE|V2D_SCROLL_HORIZONTAL_FULLR))) || 01559 ((vsm->scroller=='v') && (v2d->scroll & (V2D_SCROLL_VERTICAL_HIDE|V2D_SCROLL_VERTICAL_FULLR))) ) 01560 { 01561 /* free customdata initialised */ 01562 scroller_activate_exit(C, op); 01563 01564 /* can't catch this event for ourselves, so let it go to someone else? */ 01565 /* XXX note: if handlers use mask rect to clip input, input will fail for this case */ 01566 return OPERATOR_PASS_THROUGH; 01567 } 01568 01569 /* activate the scroller */ 01570 if (vsm->scroller=='h') 01571 v2d->scroll_ui |= V2D_SCROLL_H_ACTIVE; 01572 else 01573 v2d->scroll_ui |= V2D_SCROLL_V_ACTIVE; 01574 01575 /* still ok, so can add */ 01576 WM_event_add_modal_handler(C, op); 01577 return OPERATOR_RUNNING_MODAL; 01578 } 01579 else { 01580 /* not in scroller, so nothing happened... (pass through let's something else catch event) */ 01581 return OPERATOR_PASS_THROUGH; 01582 } 01583 } 01584 01585 /* LMB-Drag in Scrollers - not repeatable operator! */ 01586 static void VIEW2D_OT_scroller_activate(wmOperatorType *ot) 01587 { 01588 /* identifiers */ 01589 ot->name= "Scroller Activate"; 01590 ot->description= "Scroll view by mouse click and drag"; 01591 ot->idname= "VIEW2D_OT_scroller_activate"; 01592 01593 /* flags */ 01594 ot->flag= OPTYPE_BLOCKING; 01595 01596 /* api callbacks */ 01597 ot->invoke= scroller_activate_invoke; 01598 ot->modal= scroller_activate_modal; 01599 ot->cancel= scroller_activate_cancel; 01600 01601 ot->poll= view2d_poll; 01602 } 01603 01604 /* ********************************************************* */ 01605 /* RESET */ 01606 01607 static int reset_exec(bContext *C, wmOperator *UNUSED(op)) 01608 { 01609 uiStyle *style= UI_GetStyle(); 01610 ARegion *ar= CTX_wm_region(C); 01611 View2D *v2d= &ar->v2d; 01612 int winx, winy; 01613 01614 /* zoom 1.0 */ 01615 winx= (float)(v2d->mask.xmax - v2d->mask.xmin + 1); 01616 winy= (float)(v2d->mask.ymax - v2d->mask.ymin + 1); 01617 01618 v2d->cur.xmax= v2d->cur.xmin + winx; 01619 v2d->cur.ymax= v2d->cur.ymin + winy; 01620 01621 /* align */ 01622 if (v2d->align) { 01623 /* posx and negx flags are mutually exclusive, so watch out */ 01624 if ((v2d->align & V2D_ALIGN_NO_POS_X) && !(v2d->align & V2D_ALIGN_NO_NEG_X)) { 01625 v2d->cur.xmax= 0.0f; 01626 v2d->cur.xmin= -winx*style->panelzoom; 01627 } 01628 else if ((v2d->align & V2D_ALIGN_NO_NEG_X) && !(v2d->align & V2D_ALIGN_NO_POS_X)) { 01629 v2d->cur.xmax= winx*style->panelzoom; 01630 v2d->cur.xmin= 0.0f; 01631 } 01632 01633 /* - posx and negx flags are mutually exclusive, so watch out */ 01634 if ((v2d->align & V2D_ALIGN_NO_POS_Y) && !(v2d->align & V2D_ALIGN_NO_NEG_Y)) { 01635 v2d->cur.ymax= 0.0f; 01636 v2d->cur.ymin= -winy*style->panelzoom; 01637 } 01638 else if ((v2d->align & V2D_ALIGN_NO_NEG_Y) && !(v2d->align & V2D_ALIGN_NO_POS_Y)) { 01639 v2d->cur.ymax= winy*style->panelzoom; 01640 v2d->cur.ymin= 0.0f; 01641 } 01642 } 01643 01644 /* validate that view is in valid configuration after this operation */ 01645 UI_view2d_curRect_validate(v2d); 01646 01647 /* request updates to be done... */ 01648 ED_region_tag_redraw(ar); 01649 UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY); 01650 01651 return OPERATOR_FINISHED; 01652 } 01653 01654 static void VIEW2D_OT_reset(wmOperatorType *ot) 01655 { 01656 /* identifiers */ 01657 ot->name= "Reset View"; 01658 ot->description= "Reset the view"; 01659 ot->idname= "VIEW2D_OT_reset"; 01660 01661 /* api callbacks */ 01662 ot->exec= reset_exec; 01663 ot->poll= view2d_poll; 01664 } 01665 01666 /* ********************************************************* */ 01667 /* Registration */ 01668 01669 void UI_view2d_operatortypes(void) 01670 { 01671 WM_operatortype_append(VIEW2D_OT_pan); 01672 01673 WM_operatortype_append(VIEW2D_OT_scroll_left); 01674 WM_operatortype_append(VIEW2D_OT_scroll_right); 01675 WM_operatortype_append(VIEW2D_OT_scroll_up); 01676 WM_operatortype_append(VIEW2D_OT_scroll_down); 01677 01678 WM_operatortype_append(VIEW2D_OT_zoom_in); 01679 WM_operatortype_append(VIEW2D_OT_zoom_out); 01680 01681 WM_operatortype_append(VIEW2D_OT_zoom); 01682 WM_operatortype_append(VIEW2D_OT_zoom_border); 01683 01684 WM_operatortype_append(VIEW2D_OT_scroller_activate); 01685 01686 WM_operatortype_append(VIEW2D_OT_reset); 01687 } 01688 01689 void UI_view2d_keymap(wmKeyConfig *keyconf) 01690 { 01691 wmKeyMap *keymap= WM_keymap_find(keyconf, "View2D", 0, 0); 01692 wmKeyMapItem *kmi; 01693 01694 /* scrollers */ 01695 WM_keymap_add_item(keymap, "VIEW2D_OT_scroller_activate", LEFTMOUSE, KM_PRESS, 0, 0); 01696 WM_keymap_add_item(keymap, "VIEW2D_OT_scroller_activate", MIDDLEMOUSE, KM_PRESS, 0, 0); 01697 01698 /* pan/scroll */ 01699 WM_keymap_add_item(keymap, "VIEW2D_OT_pan", MIDDLEMOUSE, KM_PRESS, 0, 0); 01700 WM_keymap_add_item(keymap, "VIEW2D_OT_pan", MIDDLEMOUSE, KM_PRESS, KM_SHIFT, 0); 01701 01702 WM_keymap_add_item(keymap, "VIEW2D_OT_pan", MOUSEPAN, 0, 0, 0); 01703 01704 WM_keymap_add_item(keymap, "VIEW2D_OT_scroll_right", WHEELDOWNMOUSE, KM_PRESS, KM_CTRL, 0); 01705 WM_keymap_add_item(keymap, "VIEW2D_OT_scroll_left", WHEELUPMOUSE, KM_PRESS, KM_CTRL, 0); 01706 01707 WM_keymap_add_item(keymap, "VIEW2D_OT_scroll_down", WHEELDOWNMOUSE, KM_PRESS, KM_SHIFT, 0); 01708 WM_keymap_add_item(keymap, "VIEW2D_OT_scroll_up", WHEELUPMOUSE, KM_PRESS, KM_SHIFT, 0); 01709 01710 /* zoom - single step */ 01711 WM_keymap_add_item(keymap, "VIEW2D_OT_zoom_out", WHEELOUTMOUSE, KM_PRESS, 0, 0); 01712 WM_keymap_add_item(keymap, "VIEW2D_OT_zoom_in", WHEELINMOUSE, KM_PRESS, 0, 0); 01713 WM_keymap_add_item(keymap, "VIEW2D_OT_zoom_out", PADMINUS, KM_PRESS, 0, 0); 01714 WM_keymap_add_item(keymap, "VIEW2D_OT_zoom_in", PADPLUSKEY, KM_PRESS, 0, 0); 01715 01716 /* scroll up/down - no modifiers, only when zoom fails */ 01717 /* these may fail if zoom is disallowed, in which case they should pass on event */ 01718 WM_keymap_add_item(keymap, "VIEW2D_OT_scroll_down", WHEELDOWNMOUSE, KM_PRESS, 0, 0); 01719 WM_keymap_add_item(keymap, "VIEW2D_OT_scroll_up", WHEELUPMOUSE, KM_PRESS, 0, 0); 01720 /* these may be necessary if vertical scroll is disallowed */ 01721 WM_keymap_add_item(keymap, "VIEW2D_OT_scroll_right", WHEELDOWNMOUSE, KM_PRESS, 0, 0); 01722 WM_keymap_add_item(keymap, "VIEW2D_OT_scroll_left", WHEELUPMOUSE, KM_PRESS, 0, 0); 01723 01724 /* alternatives for page up/down to scroll */ 01725 #if 0 // XXX disabled, since this causes conflicts with hotkeys in animation editors 01726 /* scroll up/down may fall through to left/right */ 01727 WM_keymap_add_item(keymap, "VIEW2D_OT_scroll_down", PAGEDOWNKEY, KM_PRESS, 0, 0); 01728 WM_keymap_add_item(keymap, "VIEW2D_OT_scroll_up", PAGEUPKEY, KM_PRESS, 0, 0); 01729 WM_keymap_add_item(keymap, "VIEW2D_OT_scroll_right", PAGEDOWNKEY, KM_PRESS, 0, 0); 01730 WM_keymap_add_item(keymap, "VIEW2D_OT_scroll_left", PAGEUPKEY, KM_PRESS, 0, 0); 01731 /* shift for moving view left/right with page up/down */ 01732 WM_keymap_add_item(keymap, "VIEW2D_OT_scroll_right", PAGEDOWNKEY, KM_PRESS, KM_SHIFT, 0); 01733 WM_keymap_add_item(keymap, "VIEW2D_OT_scroll_left", PAGEUPKEY, KM_PRESS, KM_SHIFT, 0); 01734 #endif 01735 01736 /* zoom - drag */ 01737 WM_keymap_add_item(keymap, "VIEW2D_OT_zoom", MIDDLEMOUSE, KM_PRESS, KM_CTRL, 0); 01738 WM_keymap_add_item(keymap, "VIEW2D_OT_zoom", MOUSEZOOM, 0, 0, 0); 01739 01740 /* borderzoom - drag */ 01741 WM_keymap_add_item(keymap, "VIEW2D_OT_zoom_border", BKEY, KM_PRESS, KM_SHIFT, 0); 01742 01743 /* Alternative keymap for buttons listview */ 01744 keymap= WM_keymap_find(keyconf, "View2D Buttons List", 0, 0); 01745 01746 WM_keymap_add_item(keymap, "VIEW2D_OT_scroller_activate", LEFTMOUSE, KM_PRESS, 0, 0); 01747 WM_keymap_add_item(keymap, "VIEW2D_OT_scroller_activate", MIDDLEMOUSE, KM_PRESS, 0, 0); 01748 01749 WM_keymap_add_item(keymap, "VIEW2D_OT_pan", MIDDLEMOUSE, KM_PRESS, 0, 0); 01750 WM_keymap_add_item(keymap, "VIEW2D_OT_pan", MOUSEPAN, 0, 0, 0); 01751 WM_keymap_add_item(keymap, "VIEW2D_OT_scroll_down", WHEELDOWNMOUSE, KM_PRESS, 0, 0); 01752 WM_keymap_add_item(keymap, "VIEW2D_OT_scroll_up", WHEELUPMOUSE, KM_PRESS, 0, 0); 01753 01754 kmi = WM_keymap_add_item(keymap, "VIEW2D_OT_scroll_down", PAGEDOWNKEY, KM_PRESS, 0, 0); 01755 RNA_boolean_set(kmi->ptr, "page", TRUE); 01756 kmi = WM_keymap_add_item(keymap, "VIEW2D_OT_scroll_up", PAGEUPKEY, KM_PRESS, 0, 0); 01757 RNA_boolean_set(kmi->ptr, "page", TRUE); 01758 01759 WM_keymap_add_item(keymap, "VIEW2D_OT_zoom", MIDDLEMOUSE, KM_PRESS, KM_CTRL, 0); 01760 WM_keymap_add_item(keymap, "VIEW2D_OT_zoom", MOUSEZOOM, 0, 0, 0); 01761 WM_keymap_add_item(keymap, "VIEW2D_OT_zoom_out", PADMINUS, KM_PRESS, 0, 0); 01762 WM_keymap_add_item(keymap, "VIEW2D_OT_zoom_in", PADPLUSKEY, KM_PRESS, 0, 0); 01763 WM_keymap_add_item(keymap, "VIEW2D_OT_reset", HOMEKEY, KM_PRESS, 0, 0); 01764 } 01765