|
Blender
V2.59
|
00001 /* 00002 * $Id: screen_ops.c 38855 2011-07-30 15:45:27Z ton $ 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 * ***** END GPL LICENSE BLOCK ***** 00025 */ 00026 00032 #include <math.h> 00033 #include <string.h> 00034 00035 #include "MEM_guardedalloc.h" 00036 00037 #include "BLI_math.h" 00038 #include "BLI_blenlib.h" 00039 #include "BLI_editVert.h" 00040 #include "BLI_dlrbTree.h" 00041 #include "BLI_utildefines.h" 00042 00043 #include "DNA_armature_types.h" 00044 #include "DNA_lattice_types.h" 00045 #include "DNA_object_types.h" 00046 #include "DNA_curve_types.h" 00047 #include "DNA_scene_types.h" 00048 #include "DNA_meta_types.h" 00049 00050 #include "BKE_context.h" 00051 #include "BKE_customdata.h" 00052 #include "BKE_global.h" 00053 #include "BKE_main.h" 00054 #include "BKE_mesh.h" 00055 #include "BKE_report.h" 00056 #include "BKE_scene.h" 00057 #include "BKE_screen.h" 00058 #include "BKE_sound.h" 00059 00060 #include "WM_api.h" 00061 #include "WM_types.h" 00062 00063 #include "ED_util.h" 00064 #include "ED_image.h" 00065 #include "ED_screen.h" 00066 #include "ED_object.h" 00067 #include "ED_armature.h" 00068 #include "ED_screen_types.h" 00069 #include "ED_keyframes_draw.h" 00070 #include "ED_view3d.h" 00071 00072 #include "RNA_access.h" 00073 #include "RNA_define.h" 00074 00075 #include "UI_interface.h" 00076 #include "UI_resources.h" 00077 00078 #include "wm_window.h" 00079 00080 #include "screen_intern.h" /* own module include */ 00081 00082 #define KM_MODAL_CANCEL 1 00083 #define KM_MODAL_APPLY 2 00084 #define KM_MODAL_STEP10 3 00085 #define KM_MODAL_STEP10_OFF 4 00086 00087 /* ************** Exported Poll tests ********************** */ 00088 00089 int ED_operator_regionactive(bContext *C) 00090 { 00091 if(CTX_wm_window(C)==NULL) return 0; 00092 if(CTX_wm_screen(C)==NULL) return 0; 00093 if(CTX_wm_region(C)==NULL) return 0; 00094 return 1; 00095 } 00096 00097 int ED_operator_areaactive(bContext *C) 00098 { 00099 if(CTX_wm_window(C)==NULL) return 0; 00100 if(CTX_wm_screen(C)==NULL) return 0; 00101 if(CTX_wm_area(C)==NULL) return 0; 00102 return 1; 00103 } 00104 00105 int ED_operator_screenactive(bContext *C) 00106 { 00107 if(CTX_wm_window(C)==NULL) return 0; 00108 if(CTX_wm_screen(C)==NULL) return 0; 00109 return 1; 00110 } 00111 00112 /* XXX added this to prevent anim state to change during renders */ 00113 static int ED_operator_screenactive_norender(bContext *C) 00114 { 00115 if(G.rendering) return 0; 00116 if(CTX_wm_window(C)==NULL) return 0; 00117 if(CTX_wm_screen(C)==NULL) return 0; 00118 return 1; 00119 } 00120 00121 00122 static int screen_active_editable(bContext *C) 00123 { 00124 if(ED_operator_screenactive(C)) { 00125 /* no full window splitting allowed */ 00126 if(CTX_wm_screen(C)->full != SCREENNORMAL) 00127 return 0; 00128 return 1; 00129 } 00130 return 0; 00131 } 00132 00133 /* when mouse is over area-edge */ 00134 int ED_operator_screen_mainwinactive(bContext *C) 00135 { 00136 if(CTX_wm_window(C)==NULL) return 0; 00137 if(CTX_wm_screen(C)==NULL) return 0; 00138 if (CTX_wm_screen(C)->subwinactive!=CTX_wm_screen(C)->mainwin) return 0; 00139 return 1; 00140 } 00141 00142 int ED_operator_scene_editable(bContext *C) 00143 { 00144 Scene *scene= CTX_data_scene(C); 00145 if(scene && scene->id.lib==NULL) 00146 return 1; 00147 return 0; 00148 } 00149 00150 int ED_operator_objectmode(bContext *C) 00151 { 00152 Scene *scene= CTX_data_scene(C); 00153 Object *obact= CTX_data_active_object(C); 00154 00155 if(scene==NULL || scene->id.lib) 00156 return 0; 00157 if( CTX_data_edit_object(C) ) 00158 return 0; 00159 00160 /* add a check for ob->mode too? */ 00161 if(obact && obact->mode) 00162 return 0; 00163 00164 return 1; 00165 } 00166 00167 00168 static int ed_spacetype_test(bContext *C, int type) 00169 { 00170 if(ED_operator_areaactive(C)) { 00171 SpaceLink *sl= (SpaceLink *)CTX_wm_space_data(C); 00172 return sl && (sl->spacetype == type); 00173 } 00174 return 0; 00175 } 00176 00177 int ED_operator_view3d_active(bContext *C) 00178 { 00179 return ed_spacetype_test(C, SPACE_VIEW3D); 00180 } 00181 00182 int ED_operator_region_view3d_active(bContext *C) 00183 { 00184 if(CTX_wm_region_view3d(C)) 00185 return TRUE; 00186 00187 CTX_wm_operator_poll_msg_set(C, "expected a view3d region"); 00188 return FALSE; 00189 } 00190 00191 /* generic for any view2d which uses anim_ops */ 00192 int ED_operator_animview_active(bContext *C) 00193 { 00194 if(ED_operator_areaactive(C)) { 00195 SpaceLink *sl= (SpaceLink *)CTX_wm_space_data(C); 00196 if (sl && (ELEM6(sl->spacetype, SPACE_SEQ, SPACE_SOUND, SPACE_ACTION, SPACE_NLA, SPACE_IPO, SPACE_TIME))) 00197 return TRUE; 00198 } 00199 00200 CTX_wm_operator_poll_msg_set(C, "expected an timeline/animation area to be active"); 00201 return 0; 00202 } 00203 00204 int ED_operator_timeline_active(bContext *C) 00205 { 00206 return ed_spacetype_test(C, SPACE_TIME); 00207 } 00208 00209 int ED_operator_outliner_active(bContext *C) 00210 { 00211 return ed_spacetype_test(C, SPACE_OUTLINER); 00212 } 00213 00214 int ED_operator_outliner_active_no_editobject(bContext *C) 00215 { 00216 if(ed_spacetype_test(C, SPACE_OUTLINER)) { 00217 Object *ob = ED_object_active_context(C); 00218 Object *obedit= CTX_data_edit_object(C); 00219 if(ob && ob == obedit) 00220 return 0; 00221 else 00222 return 1; 00223 } 00224 return 0; 00225 } 00226 00227 int ED_operator_file_active(bContext *C) 00228 { 00229 return ed_spacetype_test(C, SPACE_FILE); 00230 } 00231 00232 int ED_operator_action_active(bContext *C) 00233 { 00234 return ed_spacetype_test(C, SPACE_ACTION); 00235 } 00236 00237 int ED_operator_buttons_active(bContext *C) 00238 { 00239 return ed_spacetype_test(C, SPACE_BUTS); 00240 } 00241 00242 int ED_operator_node_active(bContext *C) 00243 { 00244 SpaceNode *snode= CTX_wm_space_node(C); 00245 00246 if(snode && snode->edittree) 00247 return 1; 00248 00249 return 0; 00250 } 00251 00252 // XXX rename 00253 int ED_operator_graphedit_active(bContext *C) 00254 { 00255 return ed_spacetype_test(C, SPACE_IPO); 00256 } 00257 00258 int ED_operator_sequencer_active(bContext *C) 00259 { 00260 return ed_spacetype_test(C, SPACE_SEQ); 00261 } 00262 00263 int ED_operator_image_active(bContext *C) 00264 { 00265 return ed_spacetype_test(C, SPACE_IMAGE); 00266 } 00267 00268 int ED_operator_nla_active(bContext *C) 00269 { 00270 return ed_spacetype_test(C, SPACE_NLA); 00271 } 00272 00273 int ED_operator_logic_active(bContext *C) 00274 { 00275 return ed_spacetype_test(C, SPACE_LOGIC); 00276 } 00277 00278 int ED_operator_info_active(bContext *C) 00279 { 00280 return ed_spacetype_test(C, SPACE_INFO); 00281 } 00282 00283 00284 int ED_operator_console_active(bContext *C) 00285 { 00286 return ed_spacetype_test(C, SPACE_CONSOLE); 00287 } 00288 00289 int ED_operator_object_active(bContext *C) 00290 { 00291 Object *ob = ED_object_active_context(C); 00292 return ((ob != NULL) && !(ob->restrictflag & OB_RESTRICT_VIEW)); 00293 } 00294 00295 int ED_operator_object_active_editable(bContext *C) 00296 { 00297 Object *ob = ED_object_active_context(C); 00298 return ((ob != NULL) && !(ob->id.lib) && !(ob->restrictflag & OB_RESTRICT_VIEW)); 00299 } 00300 00301 int ED_operator_object_active_editable_mesh(bContext *C) 00302 { 00303 Object *ob = ED_object_active_context(C); 00304 return ((ob != NULL) && !(ob->id.lib) && !(ob->restrictflag & OB_RESTRICT_VIEW) && ob->type == OB_MESH && !(((ID *)ob->data)->lib)); 00305 } 00306 00307 int ED_operator_object_active_editable_font(bContext *C) 00308 { 00309 Object *ob = ED_object_active_context(C); 00310 return ((ob != NULL) && !(ob->id.lib) && !(ob->restrictflag & OB_RESTRICT_VIEW) && ob->type == OB_FONT); 00311 } 00312 00313 int ED_operator_editmesh(bContext *C) 00314 { 00315 Object *obedit= CTX_data_edit_object(C); 00316 if(obedit && obedit->type==OB_MESH) 00317 return NULL != ((Mesh *)obedit->data)->edit_mesh; 00318 return 0; 00319 } 00320 00321 int ED_operator_editmesh_view3d(bContext *C) 00322 { 00323 return ED_operator_editmesh(C) && ED_operator_view3d_active(C); 00324 } 00325 00326 int ED_operator_editmesh_region_view3d(bContext *C) 00327 { 00328 if(ED_operator_editmesh(C) && CTX_wm_region_view3d(C)) 00329 return 1; 00330 00331 CTX_wm_operator_poll_msg_set(C, "expected a view3d region & editmesh"); 00332 return 0; 00333 } 00334 00335 int ED_operator_editarmature(bContext *C) 00336 { 00337 Object *obedit= CTX_data_edit_object(C); 00338 if(obedit && obedit->type==OB_ARMATURE) 00339 return NULL != ((bArmature *)obedit->data)->edbo; 00340 return 0; 00341 } 00342 00343 int ED_operator_posemode(bContext *C) 00344 { 00345 Object *obact= CTX_data_active_object(C); 00346 00347 if (obact && !(obact->mode & OB_MODE_EDIT)) { 00348 Object *obpose; 00349 if((obpose= ED_object_pose_armature(obact))) { 00350 if((obact == obpose) || (obact->mode & OB_MODE_WEIGHT_PAINT)) { 00351 return 1; 00352 } 00353 } 00354 } 00355 00356 return 0; 00357 } 00358 00359 /* wrapper for ED_space_image_show_uvedit */ 00360 int ED_operator_uvedit(bContext *C) 00361 { 00362 SpaceImage *sima= CTX_wm_space_image(C); 00363 Object *obedit= CTX_data_edit_object(C); 00364 return ED_space_image_show_uvedit(sima, obedit); 00365 } 00366 00367 int ED_operator_uvmap(bContext *C) 00368 { 00369 Object *obedit= CTX_data_edit_object(C); 00370 EditMesh *em= NULL; 00371 00372 if(obedit && obedit->type==OB_MESH) 00373 em= BKE_mesh_get_editmesh((Mesh *)obedit->data); 00374 00375 if(em && (em->faces.first)) { 00376 BKE_mesh_end_editmesh(obedit->data, em); 00377 return 1; 00378 } 00379 00380 if(obedit) 00381 BKE_mesh_end_editmesh(obedit->data, em); 00382 return 0; 00383 } 00384 00385 int ED_operator_editsurfcurve(bContext *C) 00386 { 00387 Object *obedit= CTX_data_edit_object(C); 00388 if(obedit && ELEM(obedit->type, OB_CURVE, OB_SURF)) 00389 return NULL != ((Curve *)obedit->data)->editnurb; 00390 return 0; 00391 } 00392 00393 int ED_operator_editsurfcurve_region_view3d(bContext *C) 00394 { 00395 if(ED_operator_editsurfcurve(C) && CTX_wm_region_view3d(C)) 00396 return 1; 00397 00398 CTX_wm_operator_poll_msg_set(C, "expected a view3d region & editcurve"); 00399 return 0; 00400 } 00401 00402 int ED_operator_editcurve(bContext *C) 00403 { 00404 Object *obedit= CTX_data_edit_object(C); 00405 if(obedit && obedit->type==OB_CURVE) 00406 return NULL != ((Curve *)obedit->data)->editnurb; 00407 return 0; 00408 } 00409 00410 int ED_operator_editsurf(bContext *C) 00411 { 00412 Object *obedit= CTX_data_edit_object(C); 00413 if(obedit && obedit->type==OB_SURF) 00414 return NULL != ((Curve *)obedit->data)->editnurb; 00415 return 0; 00416 } 00417 00418 int ED_operator_editfont(bContext *C) 00419 { 00420 Object *obedit= CTX_data_edit_object(C); 00421 if(obedit && obedit->type==OB_FONT) 00422 return NULL != ((Curve *)obedit->data)->editfont; 00423 return 0; 00424 } 00425 00426 int ED_operator_editlattice(bContext *C) 00427 { 00428 Object *obedit= CTX_data_edit_object(C); 00429 if(obedit && obedit->type==OB_LATTICE) 00430 return NULL != ((Lattice *)obedit->data)->editlatt; 00431 return 0; 00432 } 00433 00434 int ED_operator_editmball(bContext *C) 00435 { 00436 Object *obedit= CTX_data_edit_object(C); 00437 if(obedit && obedit->type==OB_MBALL) 00438 return NULL != ((MetaBall *)obedit->data)->editelems; 00439 return 0; 00440 } 00441 00442 /* *************************** action zone operator ************************** */ 00443 00444 /* operator state vars used: 00445 none 00446 00447 functions: 00448 00449 apply() set actionzone event 00450 00451 exit() free customdata 00452 00453 callbacks: 00454 00455 exec() never used 00456 00457 invoke() check if in zone 00458 add customdata, put mouseco and area in it 00459 add modal handler 00460 00461 modal() accept modal events while doing it 00462 call apply() with gesture info, active window, nonactive window 00463 call exit() and remove handler when LMB confirm 00464 00465 */ 00466 00467 typedef struct sActionzoneData { 00468 ScrArea *sa1, *sa2; 00469 AZone *az; 00470 int x, y, gesture_dir, modifier; 00471 } sActionzoneData; 00472 00473 /* used by other operators too */ 00474 static ScrArea *screen_areahascursor(bScreen *scr, int x, int y) 00475 { 00476 ScrArea *sa= NULL; 00477 sa= scr->areabase.first; 00478 while(sa) { 00479 if(BLI_in_rcti(&sa->totrct, x, y)) break; 00480 sa= sa->next; 00481 } 00482 00483 return sa; 00484 } 00485 00486 /* quick poll to save operators to be created and handled */ 00487 static int actionzone_area_poll(bContext *C) 00488 { 00489 wmWindow *win= CTX_wm_window(C); 00490 ScrArea *sa= CTX_wm_area(C); 00491 00492 if(sa && win) { 00493 AZone *az; 00494 int x= win->eventstate->x; 00495 int y= win->eventstate->y; 00496 00497 for(az= sa->actionzones.first; az; az= az->next) 00498 if(BLI_in_rcti(&az->rect, x, y)) 00499 return 1; 00500 } 00501 return 0; 00502 } 00503 00504 AZone *is_in_area_actionzone(ScrArea *sa, int x, int y) 00505 { 00506 AZone *az= NULL; 00507 00508 for(az= sa->actionzones.first; az; az= az->next) { 00509 if(BLI_in_rcti(&az->rect, x, y)) { 00510 if(az->type == AZONE_AREA) { 00511 /* no triangle intersect but a hotspot circle based on corner */ 00512 int radius= (x-az->x1)*(x-az->x1) + (y-az->y1)*(y-az->y1); 00513 00514 if(radius <= AZONESPOT*AZONESPOT) 00515 break; 00516 } 00517 else if(az->type == AZONE_REGION) { 00518 break; 00519 } 00520 } 00521 } 00522 00523 return az; 00524 } 00525 00526 00527 static void actionzone_exit(wmOperator *op) 00528 { 00529 if(op->customdata) 00530 MEM_freeN(op->customdata); 00531 op->customdata= NULL; 00532 } 00533 00534 /* send EVT_ACTIONZONE event */ 00535 static void actionzone_apply(bContext *C, wmOperator *op, int type) 00536 { 00537 wmEvent event; 00538 wmWindow *win= CTX_wm_window(C); 00539 sActionzoneData *sad= op->customdata; 00540 00541 sad->modifier= RNA_int_get(op->ptr, "modifier"); 00542 00543 event= *(win->eventstate); /* XXX huh huh? make api call */ 00544 if(type==AZONE_AREA) 00545 event.type= EVT_ACTIONZONE_AREA; 00546 else 00547 event.type= EVT_ACTIONZONE_REGION; 00548 event.customdata= op->customdata; 00549 event.customdatafree= TRUE; 00550 op->customdata= NULL; 00551 00552 wm_event_add(win, &event); 00553 } 00554 00555 static int actionzone_invoke(bContext *C, wmOperator *op, wmEvent *event) 00556 { 00557 AZone *az= is_in_area_actionzone(CTX_wm_area(C), event->x, event->y); 00558 sActionzoneData *sad; 00559 00560 /* quick escape */ 00561 if(az==NULL) 00562 return OPERATOR_PASS_THROUGH; 00563 00564 /* ok we do the actionzone */ 00565 sad= op->customdata= MEM_callocN(sizeof(sActionzoneData), "sActionzoneData"); 00566 sad->sa1= CTX_wm_area(C); 00567 sad->az= az; 00568 sad->x= event->x; sad->y= event->y; 00569 00570 /* region azone directly reacts on mouse clicks */ 00571 if(sad->az->type==AZONE_REGION) { 00572 actionzone_apply(C, op, AZONE_REGION); 00573 actionzone_exit(op); 00574 return OPERATOR_FINISHED; 00575 } 00576 else { 00577 /* add modal handler */ 00578 WM_event_add_modal_handler(C, op); 00579 00580 return OPERATOR_RUNNING_MODAL; 00581 } 00582 } 00583 00584 00585 static int actionzone_modal(bContext *C, wmOperator *op, wmEvent *event) 00586 { 00587 sActionzoneData *sad= op->customdata; 00588 int deltax, deltay; 00589 int mindelta= sad->az->type==AZONE_REGION?1:12; 00590 00591 switch(event->type) { 00592 case MOUSEMOVE: 00593 /* calculate gesture direction */ 00594 deltax= (event->x - sad->x); 00595 deltay= (event->y - sad->y); 00596 00597 if(deltay > ABS(deltax)) 00598 sad->gesture_dir= 'n'; 00599 else if(deltax > ABS(deltay)) 00600 sad->gesture_dir= 'e'; 00601 else if(deltay < -ABS(deltax)) 00602 sad->gesture_dir= 's'; 00603 else 00604 sad->gesture_dir= 'w'; 00605 00606 /* gesture is large enough? */ 00607 if(ABS(deltax) > mindelta || ABS(deltay) > mindelta) { 00608 00609 /* second area, for join */ 00610 sad->sa2= screen_areahascursor(CTX_wm_screen(C), event->x, event->y); 00611 /* apply sends event */ 00612 actionzone_apply(C, op, sad->az->type); 00613 actionzone_exit(op); 00614 00615 return OPERATOR_FINISHED; 00616 } 00617 break; 00618 case ESCKEY: 00619 actionzone_exit(op); 00620 return OPERATOR_CANCELLED; 00621 case LEFTMOUSE: 00622 actionzone_exit(op); 00623 return OPERATOR_CANCELLED; 00624 00625 } 00626 00627 return OPERATOR_RUNNING_MODAL; 00628 } 00629 00630 static int actionzone_cancel(bContext *UNUSED(C), wmOperator *op) 00631 { 00632 actionzone_exit(op); 00633 00634 return OPERATOR_CANCELLED; 00635 } 00636 00637 static void SCREEN_OT_actionzone(wmOperatorType *ot) 00638 { 00639 /* identifiers */ 00640 ot->name= "Handle area action zones"; 00641 ot->description= "Handle area action zones for mouse actions/gestures"; 00642 ot->idname= "SCREEN_OT_actionzone"; 00643 00644 ot->invoke= actionzone_invoke; 00645 ot->modal= actionzone_modal; 00646 ot->poll= actionzone_area_poll; 00647 ot->cancel= actionzone_cancel; 00648 00649 ot->flag= OPTYPE_BLOCKING; 00650 00651 RNA_def_int(ot->srna, "modifier", 0, 0, 2, "modifier", "modifier state", 0, 2); 00652 } 00653 00654 /* ************** swap area operator *********************************** */ 00655 00656 /* operator state vars used: 00657 sa1 start area 00658 sa2 area to swap with 00659 00660 functions: 00661 00662 init() set custom data for operator, based on actionzone event custom data 00663 00664 cancel() cancel the operator 00665 00666 exit() cleanup, send notifier 00667 00668 callbacks: 00669 00670 invoke() gets called on shift+lmb drag in actionzone 00671 call init(), add handler 00672 00673 modal() accept modal events while doing it 00674 00675 */ 00676 00677 typedef struct sAreaSwapData { 00678 ScrArea *sa1, *sa2; 00679 } sAreaSwapData; 00680 00681 static int area_swap_init(wmOperator *op, wmEvent *event) 00682 { 00683 sAreaSwapData *sd= NULL; 00684 sActionzoneData *sad= event->customdata; 00685 00686 if(sad==NULL || sad->sa1==NULL) 00687 return 0; 00688 00689 sd= MEM_callocN(sizeof(sAreaSwapData), "sAreaSwapData"); 00690 sd->sa1= sad->sa1; 00691 sd->sa2= sad->sa2; 00692 op->customdata= sd; 00693 00694 return 1; 00695 } 00696 00697 00698 static void area_swap_exit(bContext *C, wmOperator *op) 00699 { 00700 WM_cursor_restore(CTX_wm_window(C)); 00701 if(op->customdata) 00702 MEM_freeN(op->customdata); 00703 op->customdata= NULL; 00704 } 00705 00706 static int area_swap_cancel(bContext *C, wmOperator *op) 00707 { 00708 area_swap_exit(C, op); 00709 return OPERATOR_CANCELLED; 00710 } 00711 00712 static int area_swap_invoke(bContext *C, wmOperator *op, wmEvent *event) 00713 { 00714 00715 if(!area_swap_init(op, event)) 00716 return OPERATOR_PASS_THROUGH; 00717 00718 /* add modal handler */ 00719 WM_cursor_modal(CTX_wm_window(C), BC_SWAPAREA_CURSOR); 00720 WM_event_add_modal_handler(C, op); 00721 00722 return OPERATOR_RUNNING_MODAL; 00723 00724 } 00725 00726 static int area_swap_modal(bContext *C, wmOperator *op, wmEvent *event) 00727 { 00728 sActionzoneData *sad= op->customdata; 00729 00730 switch(event->type) { 00731 case MOUSEMOVE: 00732 /* second area, for join */ 00733 sad->sa2= screen_areahascursor(CTX_wm_screen(C), event->x, event->y); 00734 break; 00735 case LEFTMOUSE: /* release LMB */ 00736 if(event->val==KM_RELEASE) { 00737 if(!sad->sa2 || sad->sa1 == sad->sa2) { 00738 00739 return area_swap_cancel(C, op); 00740 } 00741 00742 ED_area_tag_redraw(sad->sa1); 00743 ED_area_tag_redraw(sad->sa2); 00744 00745 ED_area_swapspace(C, sad->sa1, sad->sa2); 00746 00747 area_swap_exit(C, op); 00748 00749 WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL); 00750 00751 return OPERATOR_FINISHED; 00752 } 00753 break; 00754 00755 case ESCKEY: 00756 return area_swap_cancel(C, op); 00757 } 00758 return OPERATOR_RUNNING_MODAL; 00759 } 00760 00761 static void SCREEN_OT_area_swap(wmOperatorType *ot) 00762 { 00763 ot->name= "Swap areas"; 00764 ot->description= "Swap selected areas screen positions"; 00765 ot->idname= "SCREEN_OT_area_swap"; 00766 00767 ot->invoke= area_swap_invoke; 00768 ot->modal= area_swap_modal; 00769 ot->poll= ED_operator_areaactive; 00770 ot->cancel= area_swap_cancel; 00771 00772 ot->flag= OPTYPE_BLOCKING; 00773 } 00774 00775 /* *********** Duplicate area as new window operator ****************** */ 00776 00777 /* operator callback */ 00778 static int area_dupli_invoke(bContext *C, wmOperator *op, wmEvent *event) 00779 { 00780 wmWindow *newwin, *win; 00781 bScreen *newsc, *sc; 00782 ScrArea *sa; 00783 rcti rect; 00784 00785 win= CTX_wm_window(C); 00786 sc= CTX_wm_screen(C); 00787 sa= CTX_wm_area(C); 00788 00789 /* XXX hrmf! */ 00790 if(event->type==EVT_ACTIONZONE_AREA) { 00791 sActionzoneData *sad= event->customdata; 00792 00793 if(sad==NULL) 00794 return OPERATOR_PASS_THROUGH; 00795 00796 sa= sad->sa1; 00797 } 00798 00799 /* poll() checks area context, but we don't accept full-area windows */ 00800 if(sc->full != SCREENNORMAL) { 00801 if(event->type==EVT_ACTIONZONE_AREA) 00802 actionzone_exit(op); 00803 return OPERATOR_CANCELLED; 00804 } 00805 00806 /* adds window to WM */ 00807 rect= sa->totrct; 00808 BLI_translate_rcti(&rect, win->posx, win->posy); 00809 newwin= WM_window_open(C, &rect); 00810 00811 /* allocs new screen and adds to newly created window, using window size */ 00812 newsc= ED_screen_add(newwin, CTX_data_scene(C), sc->id.name+2); 00813 newwin->screen= newsc; 00814 00815 /* copy area to new screen */ 00816 area_copy_data((ScrArea *)newsc->areabase.first, sa, 0); 00817 00818 ED_area_tag_redraw((ScrArea *)newsc->areabase.first); 00819 00820 /* screen, areas init */ 00821 WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL); 00822 00823 if(event->type==EVT_ACTIONZONE_AREA) 00824 actionzone_exit(op); 00825 00826 return OPERATOR_FINISHED; 00827 } 00828 00829 static void SCREEN_OT_area_dupli(wmOperatorType *ot) 00830 { 00831 ot->name= "Duplicate Area into New Window"; 00832 ot->description= "Duplicate selected area into new window"; 00833 ot->idname= "SCREEN_OT_area_dupli"; 00834 00835 ot->invoke= area_dupli_invoke; 00836 ot->poll= ED_operator_areaactive; 00837 } 00838 00839 00840 /* ************** move area edge operator *********************************** */ 00841 00842 /* operator state vars used: 00843 x, y mouse coord near edge 00844 delta movement of edge 00845 00846 functions: 00847 00848 init() set default property values, find edge based on mouse coords, test 00849 if the edge can be moved, select edges, calculate min and max movement 00850 00851 apply() apply delta on selection 00852 00853 exit() cleanup, send notifier 00854 00855 cancel() cancel moving 00856 00857 callbacks: 00858 00859 exec() execute without any user interaction, based on properties 00860 call init(), apply(), exit() 00861 00862 invoke() gets called on mouse click near edge 00863 call init(), add handler 00864 00865 modal() accept modal events while doing it 00866 call apply() with delta motion 00867 call exit() and remove handler 00868 00869 */ 00870 00871 typedef struct sAreaMoveData { 00872 int bigger, smaller, origval, step; 00873 char dir; 00874 } sAreaMoveData; 00875 00876 /* helper call to move area-edge, sets limits */ 00877 static void area_move_set_limits(bScreen *sc, int dir, int *bigger, int *smaller) 00878 { 00879 ScrArea *sa; 00880 int areaminy= ED_area_headersize()+1; 00881 00882 /* we check all areas and test for free space with MINSIZE */ 00883 *bigger= *smaller= 100000; 00884 00885 for(sa= sc->areabase.first; sa; sa= sa->next) { 00886 if(dir=='h') { 00887 int y1= sa->v2->vec.y - sa->v1->vec.y-areaminy; 00888 00889 /* if top or down edge selected, test height */ 00890 if(sa->v1->flag && sa->v4->flag) 00891 *bigger= MIN2(*bigger, y1); 00892 else if(sa->v2->flag && sa->v3->flag) 00893 *smaller= MIN2(*smaller, y1); 00894 } 00895 else { 00896 int x1= sa->v4->vec.x - sa->v1->vec.x-AREAMINX; 00897 00898 /* if left or right edge selected, test width */ 00899 if(sa->v1->flag && sa->v2->flag) 00900 *bigger= MIN2(*bigger, x1); 00901 else if(sa->v3->flag && sa->v4->flag) 00902 *smaller= MIN2(*smaller, x1); 00903 } 00904 } 00905 } 00906 00907 /* validate selection inside screen, set variables OK */ 00908 /* return 0: init failed */ 00909 static int area_move_init (bContext *C, wmOperator *op) 00910 { 00911 bScreen *sc= CTX_wm_screen(C); 00912 ScrEdge *actedge; 00913 sAreaMoveData *md; 00914 int x, y; 00915 00916 /* required properties */ 00917 x= RNA_int_get(op->ptr, "x"); 00918 y= RNA_int_get(op->ptr, "y"); 00919 00920 /* setup */ 00921 actedge= screen_find_active_scredge(sc, x, y); 00922 if(actedge==NULL) return 0; 00923 00924 md= MEM_callocN(sizeof(sAreaMoveData), "sAreaMoveData"); 00925 op->customdata= md; 00926 00927 md->dir= scredge_is_horizontal(actedge)?'h':'v'; 00928 if(md->dir=='h') md->origval= actedge->v1->vec.y; 00929 else md->origval= actedge->v1->vec.x; 00930 00931 select_connected_scredge(sc, actedge); 00932 /* now all vertices with 'flag==1' are the ones that can be moved. */ 00933 00934 area_move_set_limits(sc, md->dir, &md->bigger, &md->smaller); 00935 00936 return 1; 00937 } 00938 00939 /* moves selected screen edge amount of delta, used by split & move */ 00940 static void area_move_apply_do(bContext *C, int origval, int delta, int dir, int bigger, int smaller) 00941 { 00942 wmWindow *win= CTX_wm_window(C); 00943 bScreen *sc= CTX_wm_screen(C); 00944 ScrVert *v1; 00945 ScrArea *sa; 00946 int areaminy= ED_area_headersize()+1; 00947 00948 delta= CLAMPIS(delta, -smaller, bigger); 00949 00950 for (v1= sc->vertbase.first; v1; v1= v1->next) { 00951 if (v1->flag) { 00952 /* that way a nice AREAGRID */ 00953 if((dir=='v') && v1->vec.x>0 && v1->vec.x<win->sizex-1) { 00954 v1->vec.x= origval + delta; 00955 if(delta != bigger && delta != -smaller) v1->vec.x-= (v1->vec.x % AREAGRID); 00956 } 00957 if((dir=='h') && v1->vec.y>0 && v1->vec.y<win->sizey-1) { 00958 v1->vec.y= origval + delta; 00959 00960 v1->vec.y+= AREAGRID-1; 00961 v1->vec.y-= (v1->vec.y % AREAGRID); 00962 00963 /* prevent too small top header */ 00964 if(v1->vec.y > win->sizey-areaminy) 00965 v1->vec.y= win->sizey-areaminy; 00966 } 00967 } 00968 } 00969 00970 for(sa= sc->areabase.first; sa; sa= sa->next) { 00971 if(sa->v1->flag || sa->v2->flag || sa->v3->flag || sa->v4->flag) 00972 ED_area_tag_redraw(sa); 00973 } 00974 00975 WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL); /* redraw everything */ 00976 } 00977 00978 static void area_move_apply(bContext *C, wmOperator *op) 00979 { 00980 sAreaMoveData *md= op->customdata; 00981 int delta; 00982 00983 delta= RNA_int_get(op->ptr, "delta"); 00984 area_move_apply_do(C, md->origval, delta, md->dir, md->bigger, md->smaller); 00985 } 00986 00987 static void area_move_exit(bContext *C, wmOperator *op) 00988 { 00989 if(op->customdata) 00990 MEM_freeN(op->customdata); 00991 op->customdata= NULL; 00992 00993 /* this makes sure aligned edges will result in aligned grabbing */ 00994 removedouble_scrverts(CTX_wm_screen(C)); 00995 removedouble_scredges(CTX_wm_screen(C)); 00996 } 00997 00998 static int area_move_exec(bContext *C, wmOperator *op) 00999 { 01000 if(!area_move_init(C, op)) 01001 return OPERATOR_CANCELLED; 01002 01003 area_move_apply(C, op); 01004 area_move_exit(C, op); 01005 01006 return OPERATOR_FINISHED; 01007 } 01008 01009 /* interaction callback */ 01010 static int area_move_invoke(bContext *C, wmOperator *op, wmEvent *event) 01011 { 01012 RNA_int_set(op->ptr, "x", event->x); 01013 RNA_int_set(op->ptr, "y", event->y); 01014 01015 if(!area_move_init(C, op)) 01016 return OPERATOR_PASS_THROUGH; 01017 01018 /* add temp handler */ 01019 WM_event_add_modal_handler(C, op); 01020 01021 return OPERATOR_RUNNING_MODAL; 01022 } 01023 01024 static int area_move_cancel(bContext *C, wmOperator *op) 01025 { 01026 01027 RNA_int_set(op->ptr, "delta", 0); 01028 area_move_apply(C, op); 01029 area_move_exit(C, op); 01030 01031 return OPERATOR_CANCELLED; 01032 } 01033 01034 /* modal callback for while moving edges */ 01035 static int area_move_modal(bContext *C, wmOperator *op, wmEvent *event) 01036 { 01037 sAreaMoveData *md= op->customdata; 01038 int delta, x, y; 01039 01040 /* execute the events */ 01041 switch(event->type) { 01042 case MOUSEMOVE: 01043 01044 x= RNA_int_get(op->ptr, "x"); 01045 y= RNA_int_get(op->ptr, "y"); 01046 01047 delta= (md->dir == 'v')? event->x - x: event->y - y; 01048 if(md->step) delta= delta - (delta % md->step); 01049 RNA_int_set(op->ptr, "delta", delta); 01050 01051 area_move_apply(C, op); 01052 break; 01053 01054 case EVT_MODAL_MAP: 01055 01056 switch (event->val) { 01057 case KM_MODAL_APPLY: 01058 area_move_exit(C, op); 01059 return OPERATOR_FINISHED; 01060 01061 case KM_MODAL_CANCEL: 01062 return area_move_cancel(C, op); 01063 01064 case KM_MODAL_STEP10: 01065 md->step= 10; 01066 break; 01067 case KM_MODAL_STEP10_OFF: 01068 md->step= 0; 01069 break; 01070 } 01071 } 01072 01073 return OPERATOR_RUNNING_MODAL; 01074 } 01075 01076 static void SCREEN_OT_area_move(wmOperatorType *ot) 01077 { 01078 /* identifiers */ 01079 ot->name= "Move area edges"; 01080 ot->description= "Move selected area edges"; 01081 ot->idname= "SCREEN_OT_area_move"; 01082 01083 ot->exec= area_move_exec; 01084 ot->invoke= area_move_invoke; 01085 ot->cancel= area_move_cancel; 01086 ot->modal= area_move_modal; 01087 ot->poll= ED_operator_screen_mainwinactive; /* when mouse is over area-edge */ 01088 01089 ot->flag= OPTYPE_BLOCKING; 01090 01091 /* rna */ 01092 RNA_def_int(ot->srna, "x", 0, INT_MIN, INT_MAX, "X", "", INT_MIN, INT_MAX); 01093 RNA_def_int(ot->srna, "y", 0, INT_MIN, INT_MAX, "Y", "", INT_MIN, INT_MAX); 01094 RNA_def_int(ot->srna, "delta", 0, INT_MIN, INT_MAX, "Delta", "", INT_MIN, INT_MAX); 01095 } 01096 01097 /* ************** split area operator *********************************** */ 01098 01099 /* 01100 operator state vars: 01101 fac spit point 01102 dir direction 'v' or 'h' 01103 01104 operator customdata: 01105 area pointer to (active) area 01106 x, y last used mouse pos 01107 (more, see below) 01108 01109 functions: 01110 01111 init() set default property values, find area based on context 01112 01113 apply() split area based on state vars 01114 01115 exit() cleanup, send notifier 01116 01117 cancel() remove duplicated area 01118 01119 callbacks: 01120 01121 exec() execute without any user interaction, based on state vars 01122 call init(), apply(), exit() 01123 01124 invoke() gets called on mouse click in action-widget 01125 call init(), add modal handler 01126 call apply() with initial motion 01127 01128 modal() accept modal events while doing it 01129 call move-areas code with delta motion 01130 call exit() or cancel() and remove handler 01131 01132 */ 01133 01134 #define SPLIT_STARTED 1 01135 #define SPLIT_PROGRESS 2 01136 01137 typedef struct sAreaSplitData { 01138 int x, y; /* last used mouse position */ 01139 01140 int origval; /* for move areas */ 01141 int bigger, smaller; /* constraints for moving new edge */ 01142 int delta; /* delta move edge */ 01143 int origmin, origsize; /* to calculate fac, for property storage */ 01144 int previewmode; /* draw previewline, then split */ 01145 01146 ScrEdge *nedge; /* new edge */ 01147 ScrArea *sarea; /* start area */ 01148 ScrArea *narea; /* new area */ 01149 01150 } sAreaSplitData; 01151 01152 /* generic init, menu case, doesn't need active area */ 01153 static int area_split_menu_init(bContext *C, wmOperator *op) 01154 { 01155 sAreaSplitData *sd; 01156 01157 /* custom data */ 01158 sd= (sAreaSplitData*)MEM_callocN(sizeof (sAreaSplitData), "op_area_split"); 01159 op->customdata= sd; 01160 01161 sd->sarea= CTX_wm_area(C); 01162 01163 if(sd->sarea) { 01164 int dir= RNA_enum_get(op->ptr, "direction"); 01165 01166 if(dir=='h') 01167 sd->sarea->flag |= AREA_FLAG_DRAWSPLIT_H; 01168 else 01169 sd->sarea->flag |= AREA_FLAG_DRAWSPLIT_V; 01170 } 01171 return 1; 01172 } 01173 01174 /* generic init, no UI stuff here, assumes active area */ 01175 static int area_split_init(bContext *C, wmOperator *op) 01176 { 01177 ScrArea *sa= CTX_wm_area(C); 01178 sAreaSplitData *sd; 01179 int areaminy= ED_area_headersize()+1; 01180 int dir; 01181 01182 /* required context */ 01183 if(sa==NULL) return 0; 01184 01185 /* required properties */ 01186 dir= RNA_enum_get(op->ptr, "direction"); 01187 01188 /* minimal size */ 01189 if(dir=='v' && sa->winx < 2*AREAMINX) return 0; 01190 if(dir=='h' && sa->winy < 2*areaminy) return 0; 01191 01192 /* custom data */ 01193 sd= (sAreaSplitData*)MEM_callocN(sizeof (sAreaSplitData), "op_area_split"); 01194 op->customdata= sd; 01195 01196 sd->sarea= sa; 01197 sd->origsize= dir=='v' ? sa->winx:sa->winy; 01198 sd->origmin = dir=='v' ? sa->totrct.xmin:sa->totrct.ymin; 01199 01200 return 1; 01201 } 01202 01203 /* with sa as center, sb is located at: 0=W, 1=N, 2=E, 3=S */ 01204 /* used with split operator */ 01205 static ScrEdge *area_findsharededge(bScreen *screen, ScrArea *sa, ScrArea *sb) 01206 { 01207 ScrVert *sav1= sa->v1; 01208 ScrVert *sav2= sa->v2; 01209 ScrVert *sav3= sa->v3; 01210 ScrVert *sav4= sa->v4; 01211 ScrVert *sbv1= sb->v1; 01212 ScrVert *sbv2= sb->v2; 01213 ScrVert *sbv3= sb->v3; 01214 ScrVert *sbv4= sb->v4; 01215 01216 if(sav1==sbv4 && sav2==sbv3) { /* sa to right of sb = W */ 01217 return screen_findedge(screen, sav1, sav2); 01218 } 01219 else if(sav2==sbv1 && sav3==sbv4) { /* sa to bottom of sb = N */ 01220 return screen_findedge(screen, sav2, sav3); 01221 } 01222 else if(sav3==sbv2 && sav4==sbv1) { /* sa to left of sb = E */ 01223 return screen_findedge(screen, sav3, sav4); 01224 } 01225 else if(sav1==sbv2 && sav4==sbv3) { /* sa on top of sb = S*/ 01226 return screen_findedge(screen, sav1, sav4); 01227 } 01228 01229 return NULL; 01230 } 01231 01232 01233 /* do the split, return success */ 01234 static int area_split_apply(bContext *C, wmOperator *op) 01235 { 01236 bScreen *sc= CTX_wm_screen(C); 01237 sAreaSplitData *sd= (sAreaSplitData *)op->customdata; 01238 float fac; 01239 int dir; 01240 01241 fac= RNA_float_get(op->ptr, "factor"); 01242 dir= RNA_enum_get(op->ptr, "direction"); 01243 01244 sd->narea= area_split(sc, sd->sarea, dir, fac, 0); /* 0 = no merge */ 01245 01246 if(sd->narea) { 01247 ScrVert *sv; 01248 01249 sd->nedge= area_findsharededge(sc, sd->sarea, sd->narea); 01250 01251 /* select newly created edge, prepare for moving edge */ 01252 for(sv= sc->vertbase.first; sv; sv= sv->next) 01253 sv->flag = 0; 01254 01255 sd->nedge->v1->flag= 1; 01256 sd->nedge->v2->flag= 1; 01257 01258 if(dir=='h') sd->origval= sd->nedge->v1->vec.y; 01259 else sd->origval= sd->nedge->v1->vec.x; 01260 01261 ED_area_tag_redraw(sd->sarea); 01262 ED_area_tag_redraw(sd->narea); 01263 01264 WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL); 01265 01266 return 1; 01267 } 01268 01269 return 0; 01270 } 01271 01272 static void area_split_exit(bContext *C, wmOperator *op) 01273 { 01274 if (op->customdata) { 01275 sAreaSplitData *sd= (sAreaSplitData *)op->customdata; 01276 if(sd->sarea) ED_area_tag_redraw(sd->sarea); 01277 if(sd->narea) ED_area_tag_redraw(sd->narea); 01278 01279 if(sd->sarea) 01280 sd->sarea->flag &= ~(AREA_FLAG_DRAWSPLIT_H|AREA_FLAG_DRAWSPLIT_V); 01281 01282 MEM_freeN(op->customdata); 01283 op->customdata = NULL; 01284 } 01285 01286 WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL); 01287 01288 /* this makes sure aligned edges will result in aligned grabbing */ 01289 removedouble_scrverts(CTX_wm_screen(C)); 01290 removedouble_scredges(CTX_wm_screen(C)); 01291 } 01292 01293 01294 /* UI callback, adds new handler */ 01295 static int area_split_invoke(bContext *C, wmOperator *op, wmEvent *event) 01296 { 01297 sAreaSplitData *sd; 01298 int dir; 01299 01300 /* no full window splitting allowed */ 01301 if(CTX_wm_screen(C)->full != SCREENNORMAL) 01302 return OPERATOR_CANCELLED; 01303 01304 if(event->type==EVT_ACTIONZONE_AREA) { 01305 sActionzoneData *sad= event->customdata; 01306 01307 if(sad->modifier>0) { 01308 return OPERATOR_PASS_THROUGH; 01309 } 01310 01311 /* verify *sad itself */ 01312 if(sad==NULL || sad->sa1==NULL || sad->az==NULL) 01313 return OPERATOR_PASS_THROUGH; 01314 01315 /* is this our *sad? if areas not equal it should be passed on */ 01316 if(CTX_wm_area(C)!=sad->sa1 || sad->sa1!=sad->sa2) 01317 return OPERATOR_PASS_THROUGH; 01318 01319 /* prepare operator state vars */ 01320 if(sad->gesture_dir=='n' || sad->gesture_dir=='s') { 01321 dir= 'h'; 01322 RNA_float_set(op->ptr, "factor", ((float)(event->x - sad->sa1->v1->vec.x)) / (float)sad->sa1->winx); 01323 } 01324 else { 01325 dir= 'v'; 01326 RNA_float_set(op->ptr, "factor", ((float)(event->y - sad->sa1->v1->vec.y)) / (float)sad->sa1->winy); 01327 } 01328 RNA_enum_set(op->ptr, "direction", dir); 01329 01330 /* general init, also non-UI case, adds customdata, sets area and defaults */ 01331 if(!area_split_init(C, op)) 01332 return OPERATOR_PASS_THROUGH; 01333 01334 } 01335 else { 01336 ScrEdge *actedge; 01337 int x, y; 01338 01339 /* retrieve initial mouse coord, so we can find the active edge */ 01340 if(RNA_property_is_set(op->ptr, "mouse_x")) 01341 x= RNA_int_get(op->ptr, "mouse_x"); 01342 else 01343 x= event->x; 01344 01345 if(RNA_property_is_set(op->ptr, "mouse_y")) 01346 y= RNA_int_get(op->ptr, "mouse_y"); 01347 else 01348 y= event->x; 01349 01350 actedge= screen_find_active_scredge(CTX_wm_screen(C), x, y); 01351 if(actedge==NULL) 01352 return OPERATOR_CANCELLED; 01353 01354 dir= scredge_is_horizontal(actedge)?'v':'h'; 01355 01356 RNA_enum_set(op->ptr, "direction", dir); 01357 01358 /* special case, adds customdata, sets defaults */ 01359 if(!area_split_menu_init(C, op)) 01360 return OPERATOR_CANCELLED; 01361 01362 } 01363 01364 sd= (sAreaSplitData *)op->customdata; 01365 01366 sd->x= event->x; 01367 sd->y= event->y; 01368 01369 if(event->type==EVT_ACTIONZONE_AREA) { 01370 01371 /* do the split */ 01372 if(area_split_apply(C, op)) { 01373 area_move_set_limits(CTX_wm_screen(C), dir, &sd->bigger, &sd->smaller); 01374 01375 /* add temp handler for edge move or cancel */ 01376 WM_event_add_modal_handler(C, op); 01377 01378 return OPERATOR_RUNNING_MODAL; 01379 } 01380 } 01381 else { 01382 sd->previewmode= 1; 01383 /* add temp handler for edge move or cancel */ 01384 WM_event_add_modal_handler(C, op); 01385 01386 return OPERATOR_RUNNING_MODAL; 01387 01388 } 01389 01390 return OPERATOR_PASS_THROUGH; 01391 } 01392 01393 /* function to be called outside UI context, or for redo */ 01394 static int area_split_exec(bContext *C, wmOperator *op) 01395 { 01396 01397 if(!area_split_init(C, op)) 01398 return OPERATOR_CANCELLED; 01399 01400 area_split_apply(C, op); 01401 area_split_exit(C, op); 01402 01403 return OPERATOR_FINISHED; 01404 } 01405 01406 01407 static int area_split_cancel(bContext *C, wmOperator *op) 01408 { 01409 sAreaSplitData *sd= (sAreaSplitData *)op->customdata; 01410 01411 if(sd->previewmode) { 01412 } 01413 else { 01414 if (screen_area_join(C, CTX_wm_screen(C), sd->sarea, sd->narea)) { 01415 if (CTX_wm_area(C) == sd->narea) { 01416 CTX_wm_area_set(C, NULL); 01417 CTX_wm_region_set(C, NULL); 01418 } 01419 sd->narea = NULL; 01420 } 01421 } 01422 area_split_exit(C, op); 01423 01424 return OPERATOR_CANCELLED; 01425 } 01426 01427 static int area_split_modal(bContext *C, wmOperator *op, wmEvent *event) 01428 { 01429 sAreaSplitData *sd= (sAreaSplitData *)op->customdata; 01430 float fac; 01431 int dir; 01432 01433 /* execute the events */ 01434 switch(event->type) { 01435 case MOUSEMOVE: 01436 dir= RNA_enum_get(op->ptr, "direction"); 01437 01438 sd->delta= (dir == 'v')? event->x - sd->origval: event->y - sd->origval; 01439 if(sd->previewmode==0) 01440 area_move_apply_do(C, sd->origval, sd->delta, dir, sd->bigger, sd->smaller); 01441 else { 01442 if(sd->sarea) { 01443 sd->sarea->flag &= ~(AREA_FLAG_DRAWSPLIT_H|AREA_FLAG_DRAWSPLIT_V); 01444 ED_area_tag_redraw(sd->sarea); 01445 } 01446 sd->sarea= screen_areahascursor(CTX_wm_screen(C), event->x, event->y); /* area context not set */ 01447 01448 if(sd->sarea) { 01449 ED_area_tag_redraw(sd->sarea); 01450 if (dir=='v') { 01451 sd->origsize= sd->sarea->winx; 01452 sd->origmin= sd->sarea->totrct.xmin; 01453 sd->sarea->flag |= AREA_FLAG_DRAWSPLIT_V; 01454 } 01455 else { 01456 sd->origsize= sd->sarea->winy; 01457 sd->origmin= sd->sarea->totrct.ymin; 01458 sd->sarea->flag |= AREA_FLAG_DRAWSPLIT_H; 01459 } 01460 } 01461 01462 CTX_wm_window(C)->screen->do_draw= 1; 01463 01464 } 01465 01466 fac= (dir == 'v') ? event->x-sd->origmin : event->y-sd->origmin; 01467 RNA_float_set(op->ptr, "factor", fac / (float)sd->origsize); 01468 01469 break; 01470 01471 case LEFTMOUSE: 01472 if(sd->previewmode) { 01473 area_split_apply(C, op); 01474 area_split_exit(C, op); 01475 return OPERATOR_FINISHED; 01476 } 01477 else { 01478 if(event->val==KM_RELEASE) { /* mouse up */ 01479 area_split_exit(C, op); 01480 return OPERATOR_FINISHED; 01481 } 01482 } 01483 break; 01484 case RIGHTMOUSE: /* cancel operation */ 01485 case ESCKEY: 01486 return area_split_cancel(C, op); 01487 } 01488 01489 return OPERATOR_RUNNING_MODAL; 01490 } 01491 01492 static EnumPropertyItem prop_direction_items[] = { 01493 {'h', "HORIZONTAL", 0, "Horizontal", ""}, 01494 {'v', "VERTICAL", 0, "Vertical", ""}, 01495 {0, NULL, 0, NULL, NULL}}; 01496 01497 static void SCREEN_OT_area_split(wmOperatorType *ot) 01498 { 01499 ot->name = "Split area"; 01500 ot->description= "Split selected area into new windows"; 01501 ot->idname = "SCREEN_OT_area_split"; 01502 01503 ot->exec= area_split_exec; 01504 ot->invoke= area_split_invoke; 01505 ot->modal= area_split_modal; 01506 ot->cancel= area_split_cancel; 01507 01508 ot->poll= screen_active_editable; 01509 ot->flag= OPTYPE_BLOCKING; 01510 01511 /* rna */ 01512 RNA_def_enum(ot->srna, "direction", prop_direction_items, 'h', "Direction", ""); 01513 RNA_def_float(ot->srna, "factor", 0.5f, 0.0, 1.0, "Factor", "", 0.0, 1.0); 01514 RNA_def_int(ot->srna, "mouse_x", -100, INT_MIN, INT_MAX, "Mouse X", "", INT_MIN, INT_MAX); 01515 RNA_def_int(ot->srna, "mouse_y", -100, INT_MIN, INT_MAX, "Mouse Y", "", INT_MIN, INT_MAX); 01516 } 01517 01518 01519 01520 /* ************** scale region edge operator *********************************** */ 01521 01522 typedef struct RegionMoveData { 01523 AZone *az; 01524 ARegion *ar; 01525 ScrArea *sa; 01526 int bigger, smaller, origval; 01527 int origx, origy; 01528 int maxsize; 01529 AZEdge edge; 01530 01531 } RegionMoveData; 01532 01533 01534 static int area_max_regionsize(ScrArea *sa, ARegion *scalear, AZEdge edge) 01535 { 01536 ARegion *ar; 01537 int dist; 01538 01539 if(edge==AE_RIGHT_TO_TOPLEFT || edge==AE_LEFT_TO_TOPRIGHT) { 01540 dist = sa->totrct.xmax - sa->totrct.xmin; 01541 } else { /* AE_BOTTOM_TO_TOPLEFT, AE_TOP_TO_BOTTOMRIGHT */ 01542 dist = sa->totrct.ymax - sa->totrct.ymin; 01543 } 01544 01545 /* subtractwidth of regions on opposite side 01546 * prevents dragging regions into other opposite regions */ 01547 for (ar=sa->regionbase.first; ar; ar=ar->next) 01548 { 01549 if (ar == scalear) 01550 continue; 01551 01552 if (scalear->alignment == RGN_ALIGN_TOP && ar->alignment == RGN_ALIGN_BOTTOM) 01553 dist -= ar->winy; 01554 else if (scalear->alignment == RGN_ALIGN_BOTTOM && ar->alignment == RGN_ALIGN_TOP) 01555 dist -= ar->winy; 01556 else if (scalear->alignment == RGN_ALIGN_LEFT && ar->alignment == RGN_ALIGN_RIGHT) 01557 dist -= ar->winx; 01558 else if (scalear->alignment == RGN_ALIGN_RIGHT && ar->alignment == RGN_ALIGN_LEFT) 01559 dist -= ar->winx; 01560 01561 /* case of regions in regions, like operator properties panel */ 01562 /* these can sit on top of other regions such as headers, so account for this */ 01563 else if (edge == AE_BOTTOM_TO_TOPLEFT && scalear->alignment & RGN_ALIGN_TOP && ar->alignment == RGN_ALIGN_TOP && ar->regiontype == RGN_TYPE_HEADER) 01564 dist -= ar->winy; 01565 else if (edge == AE_TOP_TO_BOTTOMRIGHT && scalear->alignment & RGN_ALIGN_BOTTOM && ar->alignment == RGN_ALIGN_BOTTOM && ar->regiontype == RGN_TYPE_HEADER) 01566 dist -= ar->winy; 01567 } 01568 01569 return dist; 01570 } 01571 01572 static int region_scale_invoke(bContext *C, wmOperator *op, wmEvent *event) 01573 { 01574 sActionzoneData *sad= event->customdata; 01575 AZone *az; 01576 01577 if(event->type!=EVT_ACTIONZONE_REGION) { 01578 BKE_report(op->reports, RPT_ERROR, "Can only scale region size from an action zone"); 01579 return OPERATOR_CANCELLED; 01580 } 01581 01582 az = sad->az; 01583 01584 if(az->ar) { 01585 RegionMoveData *rmd= MEM_callocN(sizeof(RegionMoveData), "RegionMoveData"); 01586 int maxsize; 01587 01588 op->customdata= rmd; 01589 01590 rmd->az = az; 01591 rmd->ar= az->ar; 01592 rmd->sa = sad->sa1; 01593 rmd->edge= az->edge; 01594 rmd->origx= event->x; 01595 rmd->origy= event->y; 01596 rmd->maxsize = area_max_regionsize(rmd->sa, rmd->ar, rmd->edge); 01597 01598 /* if not set we do now, otherwise it uses type */ 01599 if(rmd->ar->sizex==0) 01600 rmd->ar->sizex= rmd->ar->type->prefsizex; 01601 if(rmd->ar->sizey==0) 01602 rmd->ar->sizey= rmd->ar->type->prefsizey; 01603 01604 /* now copy to regionmovedata */ 01605 if(rmd->edge==AE_LEFT_TO_TOPRIGHT || rmd->edge==AE_RIGHT_TO_TOPLEFT) { 01606 rmd->origval= rmd->ar->sizex; 01607 } else { 01608 rmd->origval= rmd->ar->sizey; 01609 } 01610 01611 /* limit headers to standard height for now */ 01612 if (rmd->ar->regiontype == RGN_TYPE_HEADER) 01613 maxsize = rmd->ar->type->prefsizey; 01614 else 01615 maxsize = 1000; 01616 01617 CLAMP(rmd->maxsize, 0, maxsize); 01618 01619 /* add temp handler */ 01620 WM_event_add_modal_handler(C, op); 01621 01622 return OPERATOR_RUNNING_MODAL; 01623 } 01624 01625 return OPERATOR_FINISHED; 01626 } 01627 01628 static int region_scale_modal(bContext *C, wmOperator *op, wmEvent *event) 01629 { 01630 RegionMoveData *rmd= op->customdata; 01631 int delta; 01632 01633 /* execute the events */ 01634 switch(event->type) { 01635 case MOUSEMOVE: 01636 01637 if(rmd->edge==AE_LEFT_TO_TOPRIGHT || rmd->edge==AE_RIGHT_TO_TOPLEFT) { 01638 delta= event->x - rmd->origx; 01639 if(rmd->edge==AE_LEFT_TO_TOPRIGHT) delta= -delta; 01640 01641 rmd->ar->sizex= rmd->origval + delta; 01642 CLAMP(rmd->ar->sizex, 0, rmd->maxsize); 01643 01644 if(rmd->ar->sizex < UI_UNIT_X) { 01645 rmd->ar->sizex= rmd->origval; 01646 if(!(rmd->ar->flag & RGN_FLAG_HIDDEN)) 01647 ED_region_toggle_hidden(C, rmd->ar); 01648 } 01649 else if(rmd->ar->flag & RGN_FLAG_HIDDEN) 01650 ED_region_toggle_hidden(C, rmd->ar); 01651 } 01652 else { 01653 int maxsize=0; 01654 delta= event->y - rmd->origy; 01655 if(rmd->edge==AE_BOTTOM_TO_TOPLEFT) delta= -delta; 01656 01657 rmd->ar->sizey= rmd->origval + delta; 01658 CLAMP(rmd->ar->sizey, 0, rmd->maxsize); 01659 01660 if(rmd->ar->regiontype == RGN_TYPE_TOOL_PROPS) { 01661 /* this calculation seems overly verbose 01662 * can someone explain why this method is necessary? - campbell */ 01663 maxsize = rmd->maxsize - ((rmd->sa->headertype==HEADERTOP)?UI_UNIT_Y*2:UI_UNIT_Y) - (UI_UNIT_Y/4); 01664 } 01665 01666 /* note, 'UI_UNIT_Y/4' means you need to drag the header almost 01667 * all the way down for it to become hidden, this is done 01668 * otherwise its too easy to do this by accident */ 01669 if(rmd->ar->sizey < UI_UNIT_Y/4 || (maxsize > 0 && (rmd->ar->sizey > maxsize)) ) { 01670 rmd->ar->sizey= rmd->origval; 01671 if(!(rmd->ar->flag & RGN_FLAG_HIDDEN)) 01672 ED_region_toggle_hidden(C, rmd->ar); 01673 } 01674 else if(rmd->ar->flag & RGN_FLAG_HIDDEN) 01675 ED_region_toggle_hidden(C, rmd->ar); 01676 } 01677 ED_area_tag_redraw(rmd->sa); 01678 WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL); 01679 01680 break; 01681 01682 case LEFTMOUSE: 01683 if(event->val==KM_RELEASE) { 01684 01685 if(ABS(event->x - rmd->origx) < 2 && ABS(event->y - rmd->origy) < 2) { 01686 if(rmd->ar->flag & RGN_FLAG_HIDDEN) { 01687 ED_region_toggle_hidden(C, rmd->ar); 01688 ED_area_tag_redraw(rmd->sa); 01689 WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL); 01690 } 01691 } 01692 MEM_freeN(op->customdata); 01693 op->customdata = NULL; 01694 01695 return OPERATOR_FINISHED; 01696 } 01697 break; 01698 01699 case ESCKEY: 01700 ; 01701 } 01702 01703 return OPERATOR_RUNNING_MODAL; 01704 } 01705 01706 int region_scale_cancel(bContext *UNUSED(C), wmOperator *op) 01707 { 01708 MEM_freeN(op->customdata); 01709 op->customdata = NULL; 01710 01711 return OPERATOR_CANCELLED; 01712 } 01713 01714 static void SCREEN_OT_region_scale(wmOperatorType *ot) 01715 { 01716 /* identifiers */ 01717 ot->name= "Scale Region Size"; 01718 ot->description= "Scale selected area"; 01719 ot->idname= "SCREEN_OT_region_scale"; 01720 01721 ot->invoke= region_scale_invoke; 01722 ot->modal= region_scale_modal; 01723 ot->cancel= region_scale_cancel; 01724 01725 ot->poll= ED_operator_areaactive; 01726 01727 ot->flag= OPTYPE_BLOCKING; 01728 } 01729 01730 01731 /* ************** frame change operator ***************************** */ 01732 01733 /* function to be called outside UI context, or for redo */ 01734 static int frame_offset_exec(bContext *C, wmOperator *op) 01735 { 01736 int delta; 01737 01738 delta = RNA_int_get(op->ptr, "delta"); 01739 01740 CTX_data_scene(C)->r.cfra += delta; 01741 CTX_data_scene(C)->r.subframe = 0.f; 01742 01743 sound_seek_scene(C); 01744 01745 WM_event_add_notifier(C, NC_SCENE|ND_FRAME, CTX_data_scene(C)); 01746 01747 return OPERATOR_FINISHED; 01748 } 01749 01750 static void SCREEN_OT_frame_offset(wmOperatorType *ot) 01751 { 01752 ot->name = "Frame Offset"; 01753 ot->idname = "SCREEN_OT_frame_offset"; 01754 01755 ot->exec= frame_offset_exec; 01756 01757 ot->poll= ED_operator_screenactive_norender; 01758 ot->flag= 0; 01759 01760 /* rna */ 01761 RNA_def_int(ot->srna, "delta", 0, INT_MIN, INT_MAX, "Delta", "", INT_MIN, INT_MAX); 01762 } 01763 01764 01765 /* function to be called outside UI context, or for redo */ 01766 static int frame_jump_exec(bContext *C, wmOperator *op) 01767 { 01768 Scene *scene= CTX_data_scene(C); 01769 wmTimer *animtimer= CTX_wm_screen(C)->animtimer; 01770 01771 /* Don't change CFRA directly if animtimer is running as this can cause 01772 * first/last frame not to be actually shown (bad since for example physics 01773 * simulations aren't reset properly). 01774 */ 01775 if(animtimer) { 01776 ScreenAnimData *sad = animtimer->customdata; 01777 01778 sad->flag |= ANIMPLAY_FLAG_USE_NEXT_FRAME; 01779 01780 if (RNA_boolean_get(op->ptr, "end")) 01781 sad->nextfra= PEFRA; 01782 else 01783 sad->nextfra= PSFRA; 01784 } 01785 else { 01786 if (RNA_boolean_get(op->ptr, "end")) 01787 CFRA= PEFRA; 01788 else 01789 CFRA= PSFRA; 01790 01791 sound_seek_scene(C); 01792 01793 WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene); 01794 } 01795 01796 return OPERATOR_FINISHED; 01797 } 01798 01799 static void SCREEN_OT_frame_jump(wmOperatorType *ot) 01800 { 01801 ot->name = "Jump to Endpoint"; 01802 ot->description= "Jump to first/last frame in frame range"; 01803 ot->idname = "SCREEN_OT_frame_jump"; 01804 01805 ot->exec= frame_jump_exec; 01806 01807 ot->poll= ED_operator_screenactive_norender; 01808 ot->flag= OPTYPE_UNDO; 01809 01810 /* rna */ 01811 RNA_def_boolean(ot->srna, "end", 0, "Last Frame", "Jump to the last frame of the frame range."); 01812 } 01813 01814 01815 /* ************** jump to keyframe operator ***************************** */ 01816 01817 /* function to be called outside UI context, or for redo */ 01818 static int keyframe_jump_exec(bContext *C, wmOperator *op) 01819 { 01820 Scene *scene= CTX_data_scene(C); 01821 Object *ob= CTX_data_active_object(C); 01822 bDopeSheet ads= {NULL}; 01823 DLRBT_Tree keys; 01824 ActKeyColumn *ak; 01825 float cfra; 01826 short next= RNA_boolean_get(op->ptr, "next"); 01827 short done = 0; 01828 01829 /* sanity checks */ 01830 if (scene == NULL) 01831 return OPERATOR_CANCELLED; 01832 01833 cfra= (float)(CFRA); 01834 01835 /* init binarytree-list for getting keyframes */ 01836 BLI_dlrbTree_init(&keys); 01837 01838 /* populate tree with keyframe nodes */ 01839 scene_to_keylist(&ads, scene, &keys, NULL); 01840 01841 if (ob) 01842 ob_to_keylist(&ads, ob, &keys, NULL); 01843 01844 /* build linked-list for searching */ 01845 BLI_dlrbTree_linkedlist_sync(&keys); 01846 01847 /* find matching keyframe in the right direction */ 01848 do { 01849 if (next) 01850 ak= (ActKeyColumn *)BLI_dlrbTree_search_next(&keys, compare_ak_cfraPtr, &cfra); 01851 else 01852 ak= (ActKeyColumn *)BLI_dlrbTree_search_prev(&keys, compare_ak_cfraPtr, &cfra); 01853 01854 if (ak) { 01855 if (CFRA != (int)ak->cfra) { 01856 /* this changes the frame, so set the frame and we're done */ 01857 CFRA= (int)ak->cfra; 01858 done = 1; 01859 } 01860 else { 01861 /* make this the new starting point for the search */ 01862 cfra = ak->cfra; 01863 } 01864 } 01865 } while ((ak != NULL) && (done == 0)); 01866 01867 /* any success? */ 01868 if (done == 0) 01869 BKE_report(op->reports, RPT_INFO, "No more keyframes to jump to in this direction"); 01870 01871 /* free temp stuff */ 01872 BLI_dlrbTree_free(&keys); 01873 01874 sound_seek_scene(C); 01875 01876 WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene); 01877 01878 return OPERATOR_FINISHED; 01879 } 01880 01881 static void SCREEN_OT_keyframe_jump(wmOperatorType *ot) 01882 { 01883 ot->name = "Jump to Keyframe"; 01884 ot->description= "Jump to previous/next keyframe"; 01885 ot->idname = "SCREEN_OT_keyframe_jump"; 01886 01887 ot->exec= keyframe_jump_exec; 01888 01889 ot->poll= ED_operator_screenactive_norender; 01890 ot->flag= OPTYPE_UNDO; 01891 01892 /* rna */ 01893 RNA_def_boolean(ot->srna, "next", 1, "Next Keyframe", ""); 01894 } 01895 01896 /* ************** switch screen operator ***************************** */ 01897 01898 01899 /* function to be called outside UI context, or for redo */ 01900 static int screen_set_exec(bContext *C, wmOperator *op) 01901 { 01902 bScreen *screen= CTX_wm_screen(C); 01903 bScreen *screen_prev= screen; 01904 01905 ScrArea *sa= CTX_wm_area(C); 01906 int tot= BLI_countlist(&CTX_data_main(C)->screen); 01907 int delta= RNA_int_get(op->ptr, "delta"); 01908 01909 /* temp screens are for userpref or render display */ 01910 if(screen->temp) 01911 return OPERATOR_CANCELLED; 01912 01913 if(delta==1) { 01914 while(tot--) { 01915 screen= screen->id.next; 01916 if(screen==NULL) screen= CTX_data_main(C)->screen.first; 01917 if(screen->winid==0 && screen->full==0 && screen != screen_prev) 01918 break; 01919 } 01920 } 01921 else if(delta== -1) { 01922 while(tot--) { 01923 screen= screen->id.prev; 01924 if(screen==NULL) screen= CTX_data_main(C)->screen.last; 01925 if(screen->winid==0 && screen->full==0 && screen != screen_prev) 01926 break; 01927 } 01928 } 01929 else { 01930 screen= NULL; 01931 } 01932 01933 if(screen && screen_prev != screen) { 01934 /* return to previous state before switching screens */ 01935 if(sa && sa->full) { 01936 ED_screen_full_restore(C, sa); /* may free 'screen_prev' */ 01937 } 01938 01939 ED_screen_set(C, screen); 01940 return OPERATOR_FINISHED; 01941 } 01942 return OPERATOR_CANCELLED; 01943 } 01944 01945 static void SCREEN_OT_screen_set(wmOperatorType *ot) 01946 { 01947 ot->name = "Set Screen"; 01948 ot->description= "Cycle through available screens"; 01949 ot->idname = "SCREEN_OT_screen_set"; 01950 01951 ot->exec= screen_set_exec; 01952 ot->poll= ED_operator_screenactive; 01953 01954 /* rna */ 01955 RNA_def_int(ot->srna, "delta", 0, INT_MIN, INT_MAX, "Delta", "", INT_MIN, INT_MAX); 01956 } 01957 01958 /* ************** screen full-area operator ***************************** */ 01959 01960 01961 /* function to be called outside UI context, or for redo */ 01962 static int screen_full_area_exec(bContext *C, wmOperator *UNUSED(op)) 01963 { 01964 bScreen *screen = CTX_wm_screen(C); 01965 ScrArea *sa=NULL; 01966 01967 /* search current screen for 'fullscreen' areas */ 01968 /* prevents restoring info header, when mouse is over it */ 01969 for (sa=screen->areabase.first; sa; sa=sa->next) { 01970 if (sa->full) break; 01971 } 01972 01973 if(sa==NULL) sa= CTX_wm_area(C); 01974 01975 ED_screen_full_toggle(C, CTX_wm_window(C), sa); 01976 return OPERATOR_FINISHED; 01977 } 01978 01979 static void SCREEN_OT_screen_full_area(wmOperatorType *ot) 01980 { 01981 ot->name = "Toggle Full Screen"; 01982 ot->description= "Toggle display selected area as fullscreen"; 01983 ot->idname = "SCREEN_OT_screen_full_area"; 01984 01985 ot->exec= screen_full_area_exec; 01986 ot->poll= ED_operator_areaactive; 01987 ot->flag= 0; 01988 01989 } 01990 01991 01992 01993 /* ************** join area operator ********************************************** */ 01994 01995 /* operator state vars used: 01996 x1, y1 mouse coord in first area, which will disappear 01997 x2, y2 mouse coord in 2nd area, which will become joined 01998 01999 functions: 02000 02001 init() find edge based on state vars 02002 test if the edge divides two areas, 02003 store active and nonactive area, 02004 02005 apply() do the actual join 02006 02007 exit() cleanup, send notifier 02008 02009 callbacks: 02010 02011 exec() calls init, apply, exit 02012 02013 invoke() sets mouse coords in x,y 02014 call init() 02015 add modal handler 02016 02017 modal() accept modal events while doing it 02018 call apply() with active window and nonactive window 02019 call exit() and remove handler when LMB confirm 02020 02021 */ 02022 02023 typedef struct sAreaJoinData 02024 { 02025 ScrArea *sa1; /* first area to be considered */ 02026 ScrArea *sa2; /* second area to be considered */ 02027 ScrArea *scr; /* designed for removal */ 02028 02029 } sAreaJoinData; 02030 02031 02032 /* validate selection inside screen, set variables OK */ 02033 /* return 0: init failed */ 02034 /* XXX todo: find edge based on (x,y) and set other area? */ 02035 static int area_join_init(bContext *C, wmOperator *op) 02036 { 02037 ScrArea *sa1, *sa2; 02038 sAreaJoinData* jd= NULL; 02039 int x1, y1; 02040 int x2, y2; 02041 int shared= 0; 02042 02043 /* required properties, make negative to get return 0 if not set by caller */ 02044 x1= RNA_int_get(op->ptr, "min_x"); 02045 y1= RNA_int_get(op->ptr, "min_y"); 02046 x2= RNA_int_get(op->ptr, "max_x"); 02047 y2= RNA_int_get(op->ptr, "max_y"); 02048 02049 sa1 = screen_areahascursor(CTX_wm_screen(C), x1, y1); 02050 sa2 = screen_areahascursor(CTX_wm_screen(C), x2, y2); 02051 if(sa1==NULL || sa2==NULL || sa1==sa2) 02052 return 0; 02053 02054 /* do areas share an edge? */ 02055 if(sa1->v1==sa2->v1 || sa1->v1==sa2->v2 || sa1->v1==sa2->v3 || sa1->v1==sa2->v4) shared++; 02056 if(sa1->v2==sa2->v1 || sa1->v2==sa2->v2 || sa1->v2==sa2->v3 || sa1->v2==sa2->v4) shared++; 02057 if(sa1->v3==sa2->v1 || sa1->v3==sa2->v2 || sa1->v3==sa2->v3 || sa1->v3==sa2->v4) shared++; 02058 if(sa1->v4==sa2->v1 || sa1->v4==sa2->v2 || sa1->v4==sa2->v3 || sa1->v4==sa2->v4) shared++; 02059 if(shared!=2) { 02060 printf("areas don't share edge\n"); 02061 return 0; 02062 } 02063 02064 jd = (sAreaJoinData*)MEM_callocN(sizeof (sAreaJoinData), "op_area_join"); 02065 02066 jd->sa1 = sa1; 02067 jd->sa1->flag |= AREA_FLAG_DRAWJOINFROM; 02068 jd->sa2 = sa2; 02069 jd->sa2->flag |= AREA_FLAG_DRAWJOINTO; 02070 02071 op->customdata= jd; 02072 02073 return 1; 02074 } 02075 02076 /* apply the join of the areas (space types) */ 02077 static int area_join_apply(bContext *C, wmOperator *op) 02078 { 02079 sAreaJoinData *jd = (sAreaJoinData *)op->customdata; 02080 if (!jd) return 0; 02081 02082 if(!screen_area_join(C, CTX_wm_screen(C), jd->sa1, jd->sa2)){ 02083 return 0; 02084 } 02085 if (CTX_wm_area(C) == jd->sa2) { 02086 CTX_wm_area_set(C, NULL); 02087 CTX_wm_region_set(C, NULL); 02088 } 02089 02090 return 1; 02091 } 02092 02093 /* finish operation */ 02094 static void area_join_exit(bContext *C, wmOperator *op) 02095 { 02096 if (op->customdata) { 02097 MEM_freeN(op->customdata); 02098 op->customdata = NULL; 02099 } 02100 02101 /* this makes sure aligned edges will result in aligned grabbing */ 02102 removedouble_scredges(CTX_wm_screen(C)); 02103 removenotused_scredges(CTX_wm_screen(C)); 02104 removenotused_scrverts(CTX_wm_screen(C)); 02105 } 02106 02107 static int area_join_exec(bContext *C, wmOperator *op) 02108 { 02109 if(!area_join_init(C, op)) 02110 return OPERATOR_CANCELLED; 02111 02112 area_join_apply(C, op); 02113 area_join_exit(C, op); 02114 02115 return OPERATOR_FINISHED; 02116 } 02117 02118 /* interaction callback */ 02119 static int area_join_invoke(bContext *C, wmOperator *op, wmEvent *event) 02120 { 02121 02122 if(event->type==EVT_ACTIONZONE_AREA) { 02123 sActionzoneData *sad= event->customdata; 02124 02125 if(sad->modifier>0) { 02126 return OPERATOR_PASS_THROUGH; 02127 } 02128 02129 /* verify *sad itself */ 02130 if(sad==NULL || sad->sa1==NULL || sad->sa2==NULL) 02131 return OPERATOR_PASS_THROUGH; 02132 02133 /* is this our *sad? if areas equal it should be passed on */ 02134 if(sad->sa1==sad->sa2) 02135 return OPERATOR_PASS_THROUGH; 02136 02137 /* prepare operator state vars */ 02138 RNA_int_set(op->ptr, "min_x", sad->x); 02139 RNA_int_set(op->ptr, "min_y", sad->y); 02140 RNA_int_set(op->ptr, "max_x", event->x); 02141 RNA_int_set(op->ptr, "max_y", event->y); 02142 } 02143 02144 02145 if(!area_join_init(C, op)) 02146 return OPERATOR_PASS_THROUGH; 02147 02148 /* add temp handler */ 02149 WM_event_add_modal_handler(C, op); 02150 02151 return OPERATOR_RUNNING_MODAL; 02152 } 02153 02154 static int area_join_cancel(bContext *C, wmOperator *op) 02155 { 02156 sAreaJoinData *jd = (sAreaJoinData *)op->customdata; 02157 02158 if (jd->sa1) { 02159 jd->sa1->flag &= ~AREA_FLAG_DRAWJOINFROM; 02160 jd->sa1->flag &= ~AREA_FLAG_DRAWJOINTO; 02161 } 02162 if (jd->sa2) { 02163 jd->sa2->flag &= ~AREA_FLAG_DRAWJOINFROM; 02164 jd->sa2->flag &= ~AREA_FLAG_DRAWJOINTO; 02165 } 02166 02167 WM_event_add_notifier(C, NC_WINDOW, NULL); 02168 02169 area_join_exit(C, op); 02170 02171 return OPERATOR_CANCELLED; 02172 } 02173 02174 /* modal callback while selecting area (space) that will be removed */ 02175 static int area_join_modal(bContext *C, wmOperator *op, wmEvent *event) 02176 { 02177 bScreen *sc= CTX_wm_screen(C); 02178 sAreaJoinData *jd = (sAreaJoinData *)op->customdata; 02179 02180 /* execute the events */ 02181 switch(event->type) { 02182 02183 case MOUSEMOVE: 02184 { 02185 ScrArea *sa = screen_areahascursor(sc, event->x, event->y); 02186 int dir; 02187 02188 if (sa) { 02189 if (jd->sa1 != sa) { 02190 dir = area_getorientation(jd->sa1, sa); 02191 if (dir >= 0) { 02192 if (jd->sa2) jd->sa2->flag &= ~AREA_FLAG_DRAWJOINTO; 02193 jd->sa2 = sa; 02194 jd->sa2->flag |= AREA_FLAG_DRAWJOINTO; 02195 } 02196 else { 02197 /* we are not bordering on the previously selected area 02198 we check if area has common border with the one marked for removal 02199 in this case we can swap areas. 02200 */ 02201 dir = area_getorientation(sa, jd->sa2); 02202 if (dir >= 0) { 02203 if (jd->sa1) jd->sa1->flag &= ~AREA_FLAG_DRAWJOINFROM; 02204 if (jd->sa2) jd->sa2->flag &= ~AREA_FLAG_DRAWJOINTO; 02205 jd->sa1 = jd->sa2; 02206 jd->sa2 = sa; 02207 if (jd->sa1) jd->sa1->flag |= AREA_FLAG_DRAWJOINFROM; 02208 if (jd->sa2) jd->sa2->flag |= AREA_FLAG_DRAWJOINTO; 02209 } 02210 else { 02211 if (jd->sa2) jd->sa2->flag &= ~AREA_FLAG_DRAWJOINTO; 02212 jd->sa2 = NULL; 02213 } 02214 } 02215 WM_event_add_notifier(C, NC_WINDOW, NULL); 02216 } 02217 else { 02218 /* we are back in the area previously selected for keeping 02219 * we swap the areas if possible to allow user to choose */ 02220 if (jd->sa2 != NULL) { 02221 if (jd->sa1) jd->sa1->flag &= ~AREA_FLAG_DRAWJOINFROM; 02222 if (jd->sa2) jd->sa2->flag &= ~AREA_FLAG_DRAWJOINTO; 02223 jd->sa1 = jd->sa2; 02224 jd->sa2 = sa; 02225 if (jd->sa1) jd->sa1->flag |= AREA_FLAG_DRAWJOINFROM; 02226 if (jd->sa2) jd->sa2->flag |= AREA_FLAG_DRAWJOINTO; 02227 dir = area_getorientation(jd->sa1, jd->sa2); 02228 if (dir < 0) { 02229 printf("oops, didn't expect that!\n"); 02230 } 02231 } 02232 else { 02233 dir = area_getorientation(jd->sa1, sa); 02234 if (dir >= 0) { 02235 if (jd->sa2) jd->sa2->flag &= ~AREA_FLAG_DRAWJOINTO; 02236 jd->sa2 = sa; 02237 jd->sa2->flag |= AREA_FLAG_DRAWJOINTO; 02238 } 02239 } 02240 WM_event_add_notifier(C, NC_WINDOW, NULL); 02241 } 02242 } 02243 } 02244 break; 02245 case LEFTMOUSE: 02246 if(event->val==KM_RELEASE) { 02247 ED_area_tag_redraw(jd->sa1); 02248 ED_area_tag_redraw(jd->sa2); 02249 02250 area_join_apply(C, op); 02251 WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL); 02252 area_join_exit(C, op); 02253 return OPERATOR_FINISHED; 02254 } 02255 break; 02256 02257 case RIGHTMOUSE: 02258 case ESCKEY: 02259 return area_join_cancel(C, op); 02260 } 02261 02262 return OPERATOR_RUNNING_MODAL; 02263 } 02264 02265 /* Operator for joining two areas (space types) */ 02266 static void SCREEN_OT_area_join(wmOperatorType *ot) 02267 { 02268 /* identifiers */ 02269 ot->name= "Join area"; 02270 ot->description= "Join selected areas into new window"; 02271 ot->idname= "SCREEN_OT_area_join"; 02272 02273 /* api callbacks */ 02274 ot->exec= area_join_exec; 02275 ot->invoke= area_join_invoke; 02276 ot->modal= area_join_modal; 02277 ot->poll= screen_active_editable; 02278 ot->cancel= area_join_cancel; 02279 02280 ot->flag= OPTYPE_BLOCKING|OPTYPE_INTERNAL; 02281 02282 /* rna */ 02283 RNA_def_int(ot->srna, "min_x", -100, INT_MIN, INT_MAX, "X 1", "", INT_MIN, INT_MAX); 02284 RNA_def_int(ot->srna, "min_y", -100, INT_MIN, INT_MAX, "Y 1", "", INT_MIN, INT_MAX); 02285 RNA_def_int(ot->srna, "max_x", -100, INT_MIN, INT_MAX, "X 2", "", INT_MIN, INT_MAX); 02286 RNA_def_int(ot->srna, "max_y", -100, INT_MIN, INT_MAX, "Y 2", "", INT_MIN, INT_MAX); 02287 } 02288 02289 /* ******************************* */ 02290 02291 static int screen_area_options_invoke(bContext *C, wmOperator *op, wmEvent *event) 02292 { 02293 uiPopupMenu *pup; 02294 uiLayout *layout; 02295 PointerRNA ptr1, ptr2; 02296 ScrEdge *actedge= screen_find_active_scredge(CTX_wm_screen(C), event->x, event->y); 02297 02298 if(actedge==NULL) return OPERATOR_CANCELLED; 02299 02300 pup= uiPupMenuBegin(C, op->type->name, ICON_NONE); 02301 layout= uiPupMenuLayout(pup); 02302 02303 WM_operator_properties_create(&ptr1, "SCREEN_OT_area_join"); 02304 02305 /* mouse cursor on edge, '4' can fail on wide edges... */ 02306 RNA_int_set(&ptr1, "min_x", event->x+4); 02307 RNA_int_set(&ptr1, "min_y", event->y+4); 02308 RNA_int_set(&ptr1, "max_x", event->x-4); 02309 RNA_int_set(&ptr1, "max_y", event->y-4); 02310 02311 WM_operator_properties_create(&ptr2, "SCREEN_OT_area_split"); 02312 02313 /* store initial mouse cursor position */ 02314 RNA_int_set(&ptr2, "mouse_x", event->x); 02315 RNA_int_set(&ptr2, "mouse_y", event->y); 02316 02317 uiItemFullO(layout, "SCREEN_OT_area_split", "Split Area", ICON_NONE, ptr2.data, WM_OP_INVOKE_DEFAULT, 0); 02318 uiItemFullO(layout, "SCREEN_OT_area_join", "Join Area", ICON_NONE, ptr1.data, WM_OP_INVOKE_DEFAULT, 0); 02319 02320 uiPupMenuEnd(C, pup); 02321 02322 return OPERATOR_CANCELLED; 02323 } 02324 02325 static void SCREEN_OT_area_options(wmOperatorType *ot) 02326 { 02327 /* identifiers */ 02328 ot->name= "Area Options"; 02329 ot->description= "Operations for splitting and merging"; 02330 ot->idname= "SCREEN_OT_area_options"; 02331 02332 /* api callbacks */ 02333 ot->invoke= screen_area_options_invoke; 02334 02335 ot->poll= ED_operator_screen_mainwinactive; 02336 } 02337 02338 02339 /* ******************************* */ 02340 02341 02342 static int spacedata_cleanup(bContext *C, wmOperator *op) 02343 { 02344 Main *bmain= CTX_data_main(C); 02345 bScreen *screen; 02346 ScrArea *sa; 02347 int tot= 0; 02348 02349 for(screen= bmain->screen.first; screen; screen= screen->id.next) { 02350 for(sa= screen->areabase.first; sa; sa= sa->next) { 02351 if(sa->spacedata.first != sa->spacedata.last) { 02352 SpaceLink *sl= sa->spacedata.first; 02353 02354 BLI_remlink(&sa->spacedata, sl); 02355 tot+= BLI_countlist(&sa->spacedata); 02356 BKE_spacedata_freelist(&sa->spacedata); 02357 BLI_addtail(&sa->spacedata, sl); 02358 } 02359 } 02360 } 02361 BKE_reportf(op->reports, RPT_INFO, "Removed amount of editors: %d", tot); 02362 02363 return OPERATOR_FINISHED; 02364 } 02365 02366 static void SCREEN_OT_spacedata_cleanup(wmOperatorType *ot) 02367 { 02368 /* identifiers */ 02369 ot->name= "Clean-up space-data"; 02370 ot->description= "Remove unused settings for invisible editors"; 02371 ot->idname= "SCREEN_OT_spacedata_cleanup"; 02372 02373 /* api callbacks */ 02374 ot->exec= spacedata_cleanup; 02375 ot->poll= WM_operator_winactive; 02376 02377 } 02378 02379 /* ************** repeat last operator ***************************** */ 02380 02381 static int repeat_last_exec(bContext *C, wmOperator *UNUSED(op)) 02382 { 02383 wmOperator *lastop= CTX_wm_manager(C)->operators.last; 02384 02385 if(lastop) 02386 WM_operator_repeat(C, lastop); 02387 02388 return OPERATOR_CANCELLED; 02389 } 02390 02391 static void SCREEN_OT_repeat_last(wmOperatorType *ot) 02392 { 02393 /* identifiers */ 02394 ot->name= "Repeat Last"; 02395 ot->description= "Repeat last action"; 02396 ot->idname= "SCREEN_OT_repeat_last"; 02397 02398 /* api callbacks */ 02399 ot->exec= repeat_last_exec; 02400 02401 ot->poll= ED_operator_screenactive; 02402 02403 } 02404 02405 static int repeat_history_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) 02406 { 02407 wmWindowManager *wm= CTX_wm_manager(C); 02408 wmOperator *lastop; 02409 uiPopupMenu *pup; 02410 uiLayout *layout; 02411 int items, i; 02412 02413 items= BLI_countlist(&wm->operators); 02414 if(items==0) 02415 return OPERATOR_CANCELLED; 02416 02417 pup= uiPupMenuBegin(C, op->type->name, ICON_NONE); 02418 layout= uiPupMenuLayout(pup); 02419 02420 for (i=items-1, lastop= wm->operators.last; lastop; lastop= lastop->prev, i--) 02421 uiItemIntO(layout, lastop->type->name, ICON_NONE, op->type->idname, "index", i); 02422 02423 uiPupMenuEnd(C, pup); 02424 02425 return OPERATOR_CANCELLED; 02426 } 02427 02428 static int repeat_history_exec(bContext *C, wmOperator *op) 02429 { 02430 wmWindowManager *wm= CTX_wm_manager(C); 02431 02432 op= BLI_findlink(&wm->operators, RNA_int_get(op->ptr, "index")); 02433 if(op) { 02434 /* let's put it as last operator in list */ 02435 BLI_remlink(&wm->operators, op); 02436 BLI_addtail(&wm->operators, op); 02437 02438 WM_operator_repeat(C, op); 02439 } 02440 02441 return OPERATOR_FINISHED; 02442 } 02443 02444 static void SCREEN_OT_repeat_history(wmOperatorType *ot) 02445 { 02446 /* identifiers */ 02447 ot->name= "Repeat History"; 02448 ot->description= "Display menu for previous actions performed"; 02449 ot->idname= "SCREEN_OT_repeat_history"; 02450 02451 /* api callbacks */ 02452 ot->invoke= repeat_history_invoke; 02453 ot->exec= repeat_history_exec; 02454 02455 ot->poll= ED_operator_screenactive; 02456 02457 RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "", 0, 1000); 02458 } 02459 02460 /* ********************** redo operator ***************************** */ 02461 02462 static int redo_last_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(event)) 02463 { 02464 wmOperator *lastop= WM_operator_last_redo(C); 02465 02466 if(lastop) 02467 WM_operator_redo_popup(C, lastop); 02468 02469 return OPERATOR_CANCELLED; 02470 } 02471 02472 static void SCREEN_OT_redo_last(wmOperatorType *ot) 02473 { 02474 /* identifiers */ 02475 ot->name= "Redo Last"; 02476 ot->description= "Display menu for last action performed"; 02477 ot->idname= "SCREEN_OT_redo_last"; 02478 02479 /* api callbacks */ 02480 ot->invoke= redo_last_invoke; 02481 02482 ot->poll= ED_operator_screenactive; 02483 } 02484 02485 /* ************** region four-split operator ***************************** */ 02486 02487 /* insert a region in the area region list */ 02488 static int region_quadview_exec(bContext *C, wmOperator *op) 02489 { 02490 ARegion *ar= CTX_wm_region(C); 02491 02492 /* some rules... */ 02493 if(ar->regiontype!=RGN_TYPE_WINDOW) 02494 BKE_report(op->reports, RPT_ERROR, "Only window region can be 4-splitted"); 02495 else if(ar->alignment==RGN_ALIGN_QSPLIT) { 02496 ScrArea *sa= CTX_wm_area(C); 02497 ARegion *arn; 02498 02499 /* keep current region */ 02500 ar->alignment= 0; 02501 02502 if(sa->spacetype==SPACE_VIEW3D) { 02503 RegionView3D *rv3d= ar->regiondata; 02504 rv3d->viewlock= 0; 02505 rv3d->rflag &= ~RV3D_CLIPPING; 02506 } 02507 02508 for(ar= sa->regionbase.first; ar; ar= arn) { 02509 arn= ar->next; 02510 if(ar->alignment==RGN_ALIGN_QSPLIT) { 02511 ED_region_exit(C, ar); 02512 BKE_area_region_free(sa->type, ar); 02513 BLI_remlink(&sa->regionbase, ar); 02514 MEM_freeN(ar); 02515 } 02516 } 02517 ED_area_tag_redraw(sa); 02518 WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL); 02519 } 02520 else if(ar->next) 02521 BKE_report(op->reports, RPT_ERROR, "Only last region can be 4-splitted"); 02522 else { 02523 ScrArea *sa= CTX_wm_area(C); 02524 ARegion *newar; 02525 int count; 02526 02527 ar->alignment= RGN_ALIGN_QSPLIT; 02528 02529 for(count=0; count<3; count++) { 02530 newar= BKE_area_region_copy(sa->type, ar); 02531 BLI_addtail(&sa->regionbase, newar); 02532 } 02533 02534 /* lock views and set them */ 02535 if(sa->spacetype==SPACE_VIEW3D) { 02536 /* run ED_view3d_lock() so the correct 'rv3d->viewquat' is set, 02537 * otherwise when restoring rv3d->localvd the 'viewquat' won't 02538 * match the 'view', set on entering localview See: [#26315], 02539 * 02540 * We could avoid manipulating rv3d->localvd here if exiting 02541 * localview with a 4-split would assign these view locks */ 02542 RegionView3D *rv3d; 02543 02544 rv3d= ar->regiondata; 02545 rv3d->viewlock= RV3D_LOCKED; rv3d->view= RV3D_VIEW_FRONT; rv3d->persp= RV3D_ORTHO; 02546 ED_view3d_lock(rv3d); 02547 if (rv3d->localvd) { rv3d->localvd->view = rv3d->view; rv3d->localvd->persp = rv3d->persp; copy_qt_qt(rv3d->localvd->viewquat, rv3d->viewquat);} 02548 02549 ar= ar->next; 02550 rv3d= ar->regiondata; 02551 rv3d->viewlock= RV3D_LOCKED; rv3d->view= RV3D_VIEW_TOP; rv3d->persp= RV3D_ORTHO; 02552 ED_view3d_lock(rv3d); 02553 if (rv3d->localvd) { rv3d->localvd->view = rv3d->view; rv3d->localvd->persp = rv3d->persp; copy_qt_qt(rv3d->localvd->viewquat, rv3d->viewquat);} 02554 02555 ar= ar->next; 02556 rv3d= ar->regiondata; 02557 rv3d->viewlock= RV3D_LOCKED; rv3d->view= RV3D_VIEW_RIGHT; rv3d->persp= RV3D_ORTHO; 02558 ED_view3d_lock(rv3d); 02559 if (rv3d->localvd) { rv3d->localvd->view = rv3d->view; rv3d->localvd->persp = rv3d->persp; copy_qt_qt(rv3d->localvd->viewquat, rv3d->viewquat);} 02560 02561 ar= ar->next; 02562 rv3d= ar->regiondata; 02563 rv3d->view= RV3D_VIEW_CAMERA; rv3d->persp= RV3D_CAMOB; 02564 ED_view3d_lock(rv3d); 02565 if (rv3d->localvd) {rv3d->localvd->view = rv3d->view; rv3d->localvd->persp = rv3d->persp; copy_qt_qt(rv3d->localvd->viewquat, rv3d->viewquat);} 02566 } 02567 ED_area_tag_redraw(sa); 02568 WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL); 02569 } 02570 02571 02572 return OPERATOR_FINISHED; 02573 } 02574 02575 static void SCREEN_OT_region_quadview(wmOperatorType *ot) 02576 { 02577 /* identifiers */ 02578 ot->name= "Toggle Quad View"; 02579 ot->description= "Split selected area into camera, front, right & top views"; 02580 ot->idname= "SCREEN_OT_region_quadview"; 02581 02582 /* api callbacks */ 02583 // ot->invoke= WM_operator_confirm; 02584 ot->exec= region_quadview_exec; 02585 ot->poll= ED_operator_region_view3d_active; 02586 ot->flag= 0; 02587 } 02588 02589 02590 02591 /* ************** region flip operator ***************************** */ 02592 02593 /* flip a region alignment */ 02594 static int region_flip_exec(bContext *C, wmOperator *UNUSED(op)) 02595 { 02596 ARegion *ar= CTX_wm_region(C); 02597 02598 if (!ar) 02599 return OPERATOR_CANCELLED; 02600 02601 if(ar->alignment==RGN_ALIGN_TOP) 02602 ar->alignment= RGN_ALIGN_BOTTOM; 02603 else if(ar->alignment==RGN_ALIGN_BOTTOM) 02604 ar->alignment= RGN_ALIGN_TOP; 02605 else if(ar->alignment==RGN_ALIGN_LEFT) 02606 ar->alignment= RGN_ALIGN_RIGHT; 02607 else if(ar->alignment==RGN_ALIGN_RIGHT) 02608 ar->alignment= RGN_ALIGN_LEFT; 02609 02610 ED_area_tag_redraw(CTX_wm_area(C)); 02611 WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL); 02612 02613 return OPERATOR_FINISHED; 02614 } 02615 02616 02617 static void SCREEN_OT_region_flip(wmOperatorType *ot) 02618 { 02619 /* identifiers */ 02620 ot->name= "Flip Region"; 02621 ot->idname= "SCREEN_OT_region_flip"; 02622 02623 /* api callbacks */ 02624 ot->exec= region_flip_exec; 02625 ot->poll= ED_operator_areaactive; 02626 ot->flag= 0; 02627 } 02628 02629 /* ************** header flip operator ***************************** */ 02630 02631 /* flip a header region alignment */ 02632 static int header_flip_exec(bContext *C, wmOperator *UNUSED(op)) 02633 { 02634 ARegion *ar= CTX_wm_region(C); 02635 02636 /* find the header region 02637 * - try context first, but upon failing, search all regions in area... 02638 */ 02639 if((ar == NULL) || (ar->regiontype != RGN_TYPE_HEADER)) { 02640 ScrArea *sa= CTX_wm_area(C); 02641 ar= BKE_area_find_region_type(sa, RGN_TYPE_HEADER); 02642 02643 /* don't do anything if no region */ 02644 if(ar == NULL) 02645 return OPERATOR_CANCELLED; 02646 } 02647 02648 /* copied from SCREEN_OT_region_flip */ 02649 if(ar->alignment==RGN_ALIGN_TOP) 02650 ar->alignment= RGN_ALIGN_BOTTOM; 02651 else if(ar->alignment==RGN_ALIGN_BOTTOM) 02652 ar->alignment= RGN_ALIGN_TOP; 02653 else if(ar->alignment==RGN_ALIGN_LEFT) 02654 ar->alignment= RGN_ALIGN_RIGHT; 02655 else if(ar->alignment==RGN_ALIGN_RIGHT) 02656 ar->alignment= RGN_ALIGN_LEFT; 02657 02658 ED_area_tag_redraw(CTX_wm_area(C)); 02659 02660 WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL); 02661 02662 return OPERATOR_FINISHED; 02663 } 02664 02665 02666 static void SCREEN_OT_header_flip(wmOperatorType *ot) 02667 { 02668 /* identifiers */ 02669 ot->name= "Flip Header Region"; 02670 ot->idname= "SCREEN_OT_header_flip"; 02671 02672 /* api callbacks */ 02673 ot->exec= header_flip_exec; 02674 02675 ot->poll= ED_operator_areaactive; 02676 ot->flag= 0; 02677 } 02678 02679 /* ************** header tools operator ***************************** */ 02680 02681 static int header_toolbox_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(event)) 02682 { 02683 ScrArea *sa= CTX_wm_area(C); 02684 ARegion *ar= CTX_wm_region(C); 02685 uiPopupMenu *pup; 02686 uiLayout *layout; 02687 02688 pup= uiPupMenuBegin(C, "Header", ICON_NONE); 02689 layout= uiPupMenuLayout(pup); 02690 02691 // XXX SCREEN_OT_region_flip doesn't work - gets wrong context for active region, so added custom operator 02692 if (ar->alignment == RGN_ALIGN_TOP) 02693 uiItemO(layout, "Flip to Bottom", ICON_NONE, "SCREEN_OT_header_flip"); 02694 else 02695 uiItemO(layout, "Flip to Top", ICON_NONE, "SCREEN_OT_header_flip"); 02696 02697 uiItemS(layout); 02698 02699 /* file browser should be fullscreen all the time, but other regions can be maximised/restored... */ 02700 if (sa->spacetype != SPACE_FILE) { 02701 if (sa->full) 02702 uiItemO(layout, "Tile Area", ICON_NONE, "SCREEN_OT_screen_full_area"); 02703 else 02704 uiItemO(layout, "Maximize Area", ICON_NONE, "SCREEN_OT_screen_full_area"); 02705 } 02706 02707 uiPupMenuEnd(C, pup); 02708 02709 return OPERATOR_CANCELLED; 02710 } 02711 02712 static void SCREEN_OT_header_toolbox(wmOperatorType *ot) 02713 { 02714 /* identifiers */ 02715 ot->name= "Header Toolbox"; 02716 ot->description="Display header region toolbox"; 02717 ot->idname= "SCREEN_OT_header_toolbox"; 02718 02719 /* api callbacks */ 02720 ot->invoke= header_toolbox_invoke; 02721 } 02722 02723 /* ****************** anim player, with timer ***************** */ 02724 02725 static int match_area_with_refresh(int spacetype, int refresh) 02726 { 02727 switch (spacetype) { 02728 case SPACE_TIME: 02729 if (refresh & SPACE_TIME) 02730 return 1; 02731 break; 02732 } 02733 02734 return 0; 02735 } 02736 02737 static int match_region_with_redraws(int spacetype, int regiontype, int redraws) 02738 { 02739 if(regiontype==RGN_TYPE_WINDOW) { 02740 02741 switch (spacetype) { 02742 case SPACE_VIEW3D: 02743 if(redraws & TIME_ALL_3D_WIN) 02744 return 1; 02745 break; 02746 case SPACE_IPO: 02747 case SPACE_ACTION: 02748 case SPACE_NLA: 02749 if(redraws & TIME_ALL_ANIM_WIN) 02750 return 1; 02751 break; 02752 case SPACE_TIME: 02753 /* if only 1 window or 3d windows, we do timeline too */ 02754 if(redraws & (TIME_ALL_ANIM_WIN|TIME_REGION|TIME_ALL_3D_WIN)) 02755 return 1; 02756 break; 02757 case SPACE_BUTS: 02758 if(redraws & TIME_ALL_BUTS_WIN) 02759 return 1; 02760 break; 02761 case SPACE_SEQ: 02762 if(redraws & (TIME_SEQ|TIME_ALL_ANIM_WIN)) 02763 return 1; 02764 break; 02765 case SPACE_NODE: 02766 if(redraws & (TIME_NODES)) 02767 return 1; 02768 break; 02769 case SPACE_IMAGE: 02770 if(redraws & TIME_ALL_IMAGE_WIN) 02771 return 1; 02772 break; 02773 02774 } 02775 } 02776 else if(regiontype==RGN_TYPE_UI) { 02777 if(redraws & TIME_ALL_BUTS_WIN) 02778 return 1; 02779 } 02780 else if(regiontype==RGN_TYPE_HEADER) { 02781 if(spacetype==SPACE_TIME) 02782 return 1; 02783 } 02784 else if (regiontype==RGN_TYPE_PREVIEW) { 02785 switch (spacetype) { 02786 case SPACE_SEQ: 02787 if(redraws & (TIME_SEQ|TIME_ALL_ANIM_WIN)) 02788 return 1; 02789 break; 02790 } 02791 } 02792 return 0; 02793 } 02794 02795 static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), wmEvent *event) 02796 { 02797 bScreen *screen= CTX_wm_screen(C); 02798 02799 if(screen->animtimer && screen->animtimer==event->customdata) { 02800 Scene *scene= CTX_data_scene(C); 02801 wmTimer *wt= screen->animtimer; 02802 ScreenAnimData *sad= wt->customdata; 02803 ScrArea *sa; 02804 int sync; 02805 float time; 02806 02807 /* sync, don't sync, or follow scene setting */ 02808 if (sad->flag & ANIMPLAY_FLAG_SYNC) sync= 1; 02809 else if (sad->flag & ANIMPLAY_FLAG_NO_SYNC) sync= 0; 02810 else sync= (scene->flag & SCE_FRAME_DROP); 02811 02812 if((scene->audio.flag & AUDIO_SYNC) && !(sad->flag & ANIMPLAY_FLAG_REVERSE) && finite(time = sound_sync_scene(scene))) 02813 scene->r.cfra = (double)time * FPS + 0.5; 02814 else 02815 { 02816 if (sync) { 02817 int step = floor(wt->duration * FPS); 02818 /* skip frames */ 02819 if (sad->flag & ANIMPLAY_FLAG_REVERSE) 02820 scene->r.cfra -= step; 02821 else 02822 scene->r.cfra += step; 02823 wt->duration -= ((double)step)/FPS; 02824 } 02825 else { 02826 /* one frame +/- */ 02827 if (sad->flag & ANIMPLAY_FLAG_REVERSE) 02828 scene->r.cfra--; 02829 else 02830 scene->r.cfra++; 02831 } 02832 } 02833 02834 /* reset 'jumped' flag before checking if we need to jump... */ 02835 sad->flag &= ~ANIMPLAY_FLAG_JUMPED; 02836 02837 if (sad->flag & ANIMPLAY_FLAG_REVERSE) { 02838 /* jump back to end? */ 02839 if (PRVRANGEON) { 02840 if (scene->r.cfra < scene->r.psfra) { 02841 scene->r.cfra= scene->r.pefra; 02842 sad->flag |= ANIMPLAY_FLAG_JUMPED; 02843 } 02844 } 02845 else { 02846 if (scene->r.cfra < scene->r.sfra) { 02847 scene->r.cfra= scene->r.efra; 02848 sad->flag |= ANIMPLAY_FLAG_JUMPED; 02849 } 02850 } 02851 } 02852 else { 02853 /* jump back to start? */ 02854 if (PRVRANGEON) { 02855 if (scene->r.cfra > scene->r.pefra) { 02856 scene->r.cfra= scene->r.psfra; 02857 sad->flag |= ANIMPLAY_FLAG_JUMPED; 02858 } 02859 } 02860 else { 02861 if (scene->r.cfra > scene->r.efra) { 02862 scene->r.cfra= scene->r.sfra; 02863 sad->flag |= ANIMPLAY_FLAG_JUMPED; 02864 } 02865 } 02866 } 02867 02868 /* next frame overriden by user action (pressed jump to first/last frame) */ 02869 if(sad->flag & ANIMPLAY_FLAG_USE_NEXT_FRAME) { 02870 scene->r.cfra = sad->nextfra; 02871 sad->flag &= ~ANIMPLAY_FLAG_USE_NEXT_FRAME; 02872 sad->flag |= ANIMPLAY_FLAG_JUMPED; 02873 } 02874 02875 if (sad->flag & ANIMPLAY_FLAG_JUMPED) 02876 sound_seek_scene(C); 02877 02878 /* since we follow drawflags, we can't send notifier but tag regions ourselves */ 02879 ED_update_for_newframe(CTX_data_main(C), scene, screen, 1); 02880 02881 for (sa= screen->areabase.first; sa; sa= sa->next) { 02882 ARegion *ar; 02883 for (ar= sa->regionbase.first; ar; ar= ar->next) { 02884 if (ar==sad->ar) 02885 ED_region_tag_redraw(ar); 02886 else 02887 if (match_region_with_redraws(sa->spacetype, ar->regiontype, sad->redraws)) 02888 ED_region_tag_redraw(ar); 02889 } 02890 02891 if (match_area_with_refresh(sa->spacetype, sad->refresh)) 02892 ED_area_tag_refresh(sa); 02893 } 02894 02895 /* update frame rate info too 02896 * NOTE: this may not be accurate enough, since we might need this after modifiers/etc. 02897 * have been calculated instead of just before updates have been done? 02898 */ 02899 ED_refresh_viewport_fps(C); 02900 02901 /* recalculate the timestep for the timer now that we've finished calculating this, 02902 * since the frames-per-second value may have been changed 02903 */ 02904 // TODO: this may make evaluation a bit slower if the value doesn't change... any way to avoid this? 02905 wt->timestep= (1.0/FPS); 02906 02907 return OPERATOR_FINISHED; 02908 } 02909 return OPERATOR_PASS_THROUGH; 02910 } 02911 02912 static void SCREEN_OT_animation_step(wmOperatorType *ot) 02913 { 02914 /* identifiers */ 02915 ot->name= "Animation Step"; 02916 ot->description= "Step through animation by position"; 02917 ot->idname= "SCREEN_OT_animation_step"; 02918 02919 /* api callbacks */ 02920 ot->invoke= screen_animation_step; 02921 02922 ot->poll= ED_operator_screenactive_norender; 02923 02924 } 02925 02926 /* ****************** anim player, starts or ends timer ***************** */ 02927 02928 /* toggle operator */ 02929 int ED_screen_animation_play(bContext *C, int sync, int mode) 02930 { 02931 bScreen *screen= CTX_wm_screen(C); 02932 Scene *scene = CTX_data_scene(C); 02933 02934 if (screen->animtimer) { 02935 /* stop playback now */ 02936 ED_screen_animation_timer(C, 0, 0, 0, 0); 02937 sound_stop_scene(scene); 02938 } 02939 else { 02940 int refresh= SPACE_TIME; /* these settings are currently only available from a menu in the TimeLine */ 02941 02942 if (mode == 1) // XXX only play audio forwards!? 02943 sound_play_scene(scene); 02944 02945 ED_screen_animation_timer(C, screen->redraws_flag, refresh, sync, mode); 02946 02947 if (screen->animtimer) { 02948 wmTimer *wt= screen->animtimer; 02949 ScreenAnimData *sad= wt->customdata; 02950 02951 sad->ar= CTX_wm_region(C); 02952 } 02953 } 02954 02955 return OPERATOR_FINISHED; 02956 } 02957 02958 static int screen_animation_play_exec(bContext *C, wmOperator *op) 02959 { 02960 int mode= (RNA_boolean_get(op->ptr, "reverse")) ? -1 : 1; 02961 int sync= -1; 02962 02963 if (RNA_property_is_set(op->ptr, "sync")) 02964 sync= (RNA_boolean_get(op->ptr, "sync")); 02965 02966 return ED_screen_animation_play(C, sync, mode); 02967 } 02968 02969 static void SCREEN_OT_animation_play(wmOperatorType *ot) 02970 { 02971 /* identifiers */ 02972 ot->name= "Play Animation"; 02973 ot->description= "Play animation"; 02974 ot->idname= "SCREEN_OT_animation_play"; 02975 02976 /* api callbacks */ 02977 ot->exec= screen_animation_play_exec; 02978 02979 ot->poll= ED_operator_screenactive_norender; 02980 02981 RNA_def_boolean(ot->srna, "reverse", 0, "Play in Reverse", "Animation is played backwards"); 02982 RNA_def_boolean(ot->srna, "sync", 0, "Sync", "Drop frames to maintain framerate"); 02983 } 02984 02985 static int screen_animation_cancel_exec(bContext *C, wmOperator *op) 02986 { 02987 bScreen *screen= CTX_wm_screen(C); 02988 02989 if (screen->animtimer) { 02990 if(RNA_boolean_get(op->ptr, "restore_frame")) { 02991 ScreenAnimData *sad= screen->animtimer->customdata; 02992 Scene *scene= CTX_data_scene(C); 02993 02994 /* reset current frame before stopping, and just send a notifier to deal with the rest 02995 * (since playback still needs to be stopped) 02996 */ 02997 scene->r.cfra= sad->sfra; 02998 02999 WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene); 03000 } 03001 03002 /* call the other "toggling" operator to clean up now */ 03003 ED_screen_animation_play(C, 0, 0); 03004 } 03005 03006 return OPERATOR_PASS_THROUGH; 03007 } 03008 03009 static void SCREEN_OT_animation_cancel(wmOperatorType *ot) 03010 { 03011 /* identifiers */ 03012 ot->name= "Cancel Animation"; 03013 ot->description= "Cancel animation, returning to the original frame"; 03014 ot->idname= "SCREEN_OT_animation_cancel"; 03015 03016 /* api callbacks */ 03017 ot->exec= screen_animation_cancel_exec; 03018 03019 ot->poll= ED_operator_screenactive; 03020 03021 RNA_def_boolean(ot->srna, "restore_frame", TRUE, "Restore Frame", "Restore the frame when animation was initialized."); 03022 } 03023 03024 /* ************** border select operator (template) ***************************** */ 03025 03026 /* operator state vars used: (added by default WM callbacks) 03027 xmin, ymin 03028 xmax, ymax 03029 03030 customdata: the wmGesture pointer 03031 03032 callbacks: 03033 03034 exec() has to be filled in by user 03035 03036 invoke() default WM function 03037 adds modal handler 03038 03039 modal() default WM function 03040 accept modal events while doing it, calls exec(), handles ESC and border drawing 03041 03042 poll() has to be filled in by user for context 03043 */ 03044 #if 0 03045 static int border_select_do(bContext *C, wmOperator *op) 03046 { 03047 int event_type= RNA_int_get(op->ptr, "event_type"); 03048 03049 if(event_type==LEFTMOUSE) 03050 printf("border select do select\n"); 03051 else if(event_type==RIGHTMOUSE) 03052 printf("border select deselect\n"); 03053 else 03054 printf("border select do something\n"); 03055 03056 return 1; 03057 } 03058 03059 static void SCREEN_OT_border_select(wmOperatorType *ot) 03060 { 03061 /* identifiers */ 03062 ot->name= "Border select"; 03063 ot->idname= "SCREEN_OT_border_select"; 03064 03065 /* api callbacks */ 03066 ot->exec= border_select_do; 03067 ot->invoke= WM_border_select_invoke; 03068 ot->modal= WM_border_select_modal; 03069 ot->cancel= WM_border_select_cancel; 03070 03071 ot->poll= ED_operator_areaactive; 03072 03073 /* rna */ 03074 RNA_def_int(ot->srna, "event_type", 0, INT_MIN, INT_MAX, "Event Type", "", INT_MIN, INT_MAX); 03075 RNA_def_int(ot->srna, "xmin", 0, INT_MIN, INT_MAX, "X Min", "", INT_MIN, INT_MAX); 03076 RNA_def_int(ot->srna, "xmax", 0, INT_MIN, INT_MAX, "X Max", "", INT_MIN, INT_MAX); 03077 RNA_def_int(ot->srna, "ymin", 0, INT_MIN, INT_MAX, "Y Min", "", INT_MIN, INT_MAX); 03078 RNA_def_int(ot->srna, "ymax", 0, INT_MIN, INT_MAX, "Y Max", "", INT_MIN, INT_MAX); 03079 03080 } 03081 #endif 03082 03083 /* *********************** generic fullscreen 'back' button *************** */ 03084 03085 03086 static int fullscreen_back_exec(bContext *C, wmOperator *op) 03087 { 03088 bScreen *screen = CTX_wm_screen(C); 03089 ScrArea *sa=NULL; 03090 03091 /* search current screen for 'fullscreen' areas */ 03092 for (sa=screen->areabase.first; sa; sa=sa->next) { 03093 if (sa->full) break; 03094 } 03095 if (!sa) { 03096 BKE_report(op->reports, RPT_ERROR, "No fullscreen areas were found."); 03097 return OPERATOR_CANCELLED; 03098 } 03099 03100 ED_screen_full_restore(C, sa); 03101 03102 return OPERATOR_FINISHED; 03103 } 03104 03105 static void SCREEN_OT_back_to_previous(struct wmOperatorType *ot) 03106 { 03107 /* identifiers */ 03108 ot->name= "Back to Previous Screen"; 03109 ot->description= "Revert back to the original screen layout, before fullscreen area overlay"; 03110 ot->idname= "SCREEN_OT_back_to_previous"; 03111 03112 /* api callbacks */ 03113 ot->exec= fullscreen_back_exec; 03114 ot->poll= ED_operator_screenactive; 03115 } 03116 03117 /* *********** show user pref window ****** */ 03118 03119 static int userpref_show_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event) 03120 { 03121 rcti rect; 03122 int sizex, sizey; 03123 03124 sizex= 800; 03125 sizey= 480; 03126 03127 /* some magic to calculate postition */ 03128 rect.xmin= event->x + CTX_wm_window(C)->posx - sizex/2; 03129 rect.ymin= event->y + CTX_wm_window(C)->posy - sizey/2; 03130 rect.xmax= rect.xmin + sizex; 03131 rect.ymax= rect.ymin + sizey; 03132 03133 /* changes context! */ 03134 WM_window_open_temp(C, &rect, WM_WINDOW_USERPREFS); 03135 03136 return OPERATOR_FINISHED; 03137 } 03138 03139 03140 static void SCREEN_OT_userpref_show(struct wmOperatorType *ot) 03141 { 03142 /* identifiers */ 03143 ot->name= "Show/Hide User Preferences"; 03144 ot->description= "Show/hide user preferences"; 03145 ot->idname= "SCREEN_OT_userpref_show"; 03146 03147 /* api callbacks */ 03148 ot->invoke= userpref_show_invoke; 03149 ot->poll= ED_operator_screenactive; 03150 } 03151 03152 /********************* new screen operator *********************/ 03153 03154 static int screen_new_exec(bContext *C, wmOperator *UNUSED(op)) 03155 { 03156 wmWindow *win= CTX_wm_window(C); 03157 bScreen *sc= CTX_wm_screen(C); 03158 03159 sc= ED_screen_duplicate(win, sc); 03160 WM_event_add_notifier(C, NC_SCREEN|ND_SCREENBROWSE, sc); 03161 03162 return OPERATOR_FINISHED; 03163 } 03164 03165 static void SCREEN_OT_new(wmOperatorType *ot) 03166 { 03167 /* identifiers */ 03168 ot->name= "New Screen"; 03169 ot->description= "Add a new screen"; 03170 ot->idname= "SCREEN_OT_new"; 03171 03172 /* api callbacks */ 03173 ot->exec= screen_new_exec; 03174 ot->poll= WM_operator_winactive; 03175 03176 /* flags */ 03177 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 03178 } 03179 03180 /********************* delete screen operator *********************/ 03181 03182 static int screen_delete_exec(bContext *C, wmOperator *UNUSED(op)) 03183 { 03184 bScreen *sc= CTX_wm_screen(C); 03185 03186 WM_event_add_notifier(C, NC_SCREEN|ND_SCREENDELETE, sc); 03187 03188 return OPERATOR_FINISHED; 03189 } 03190 03191 static void SCREEN_OT_delete(wmOperatorType *ot) 03192 { 03193 /* identifiers */ 03194 ot->name= "Delete Screen"; //was scene 03195 ot->description= "Delete active screen"; 03196 ot->idname= "SCREEN_OT_delete"; 03197 03198 /* api callbacks */ 03199 ot->exec= screen_delete_exec; 03200 03201 /* flags */ 03202 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 03203 } 03204 03205 /********************* new scene operator *********************/ 03206 03207 static int scene_new_exec(bContext *C, wmOperator *op) 03208 { 03209 Scene *newscene, *scene= CTX_data_scene(C); 03210 bScreen *screen= CTX_wm_screen(C); 03211 Main *bmain= CTX_data_main(C); 03212 int type= RNA_enum_get(op->ptr, "type"); 03213 03214 if(type == SCE_COPY_NEW) { 03215 newscene= add_scene("Scene"); 03216 } 03217 else { /* different kinds of copying */ 03218 newscene= copy_scene(scene, type); 03219 03220 /* these can't be handled in blenkernel curently, so do them here */ 03221 if(type == SCE_COPY_LINK_DATA) { 03222 ED_object_single_users(bmain, newscene, 0); 03223 } 03224 else if(type == SCE_COPY_FULL) { 03225 ED_object_single_users(bmain, newscene, 1); 03226 } 03227 } 03228 03229 /* this notifier calls ED_screen_set_scene, doing a lot of UI stuff, not for inside event loops */ 03230 WM_event_add_notifier(C, NC_SCENE|ND_SCENEBROWSE, newscene); 03231 03232 if(screen) 03233 screen->scene= newscene; 03234 03235 return OPERATOR_FINISHED; 03236 } 03237 03238 static void SCENE_OT_new(wmOperatorType *ot) 03239 { 03240 static EnumPropertyItem type_items[]= { 03241 {SCE_COPY_NEW, "NEW", 0, "New", "Add new scene"}, 03242 {SCE_COPY_EMPTY, "EMPTY", 0, "Copy Settings", "Make a copy without any objects"}, 03243 {SCE_COPY_LINK_OB, "LINK_OBJECTS", 0, "Link Objects", "Link to the objects from the current scene"}, 03244 {SCE_COPY_LINK_DATA, "LINK_OBJECT_DATA", 0, "Link Object Data", "Copy objects linked to data from the current scene"}, 03245 {SCE_COPY_FULL, "FULL_COPY", 0, "Full Copy", "Make a full copy of the current scene"}, 03246 {0, NULL, 0, NULL, NULL}}; 03247 03248 /* identifiers */ 03249 ot->name= "New Scene"; 03250 ot->description= "Add new scene by type"; 03251 ot->idname= "SCENE_OT_new"; 03252 03253 /* api callbacks */ 03254 ot->exec= scene_new_exec; 03255 ot->invoke= WM_menu_invoke; 03256 03257 /* flags */ 03258 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 03259 03260 /* properties */ 03261 ot->prop= RNA_def_enum(ot->srna, "type", type_items, 0, "Type", ""); 03262 } 03263 03264 /********************* delete scene operator *********************/ 03265 03266 static int scene_delete_exec(bContext *C, wmOperator *UNUSED(op)) 03267 { 03268 Scene *scene= CTX_data_scene(C); 03269 03270 WM_event_add_notifier(C, NC_SCENE|NA_REMOVED, scene); 03271 03272 return OPERATOR_FINISHED; 03273 } 03274 03275 static void SCENE_OT_delete(wmOperatorType *ot) 03276 { 03277 /* identifiers */ 03278 ot->name= "Delete Scene"; 03279 ot->description= "Delete active scene"; 03280 ot->idname= "SCENE_OT_delete"; 03281 03282 /* api callbacks */ 03283 ot->exec= scene_delete_exec; 03284 03285 /* flags */ 03286 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 03287 } 03288 03289 /* **************** Assigning operatortypes to global list, adding handlers **************** */ 03290 03291 03292 /* called in spacetypes.c */ 03293 void ED_operatortypes_screen(void) 03294 { 03295 /* generic UI stuff */ 03296 WM_operatortype_append(SCREEN_OT_actionzone); 03297 WM_operatortype_append(SCREEN_OT_repeat_last); 03298 WM_operatortype_append(SCREEN_OT_repeat_history); 03299 WM_operatortype_append(SCREEN_OT_redo_last); 03300 03301 /* screen tools */ 03302 WM_operatortype_append(SCREEN_OT_area_move); 03303 WM_operatortype_append(SCREEN_OT_area_split); 03304 WM_operatortype_append(SCREEN_OT_area_join); 03305 WM_operatortype_append(SCREEN_OT_area_options); 03306 WM_operatortype_append(SCREEN_OT_area_dupli); 03307 WM_operatortype_append(SCREEN_OT_area_swap); 03308 WM_operatortype_append(SCREEN_OT_region_quadview); 03309 WM_operatortype_append(SCREEN_OT_region_scale); 03310 WM_operatortype_append(SCREEN_OT_region_flip); 03311 WM_operatortype_append(SCREEN_OT_header_flip); 03312 WM_operatortype_append(SCREEN_OT_header_toolbox); 03313 WM_operatortype_append(SCREEN_OT_screen_set); 03314 WM_operatortype_append(SCREEN_OT_screen_full_area); 03315 WM_operatortype_append(SCREEN_OT_back_to_previous); 03316 WM_operatortype_append(SCREEN_OT_spacedata_cleanup); 03317 WM_operatortype_append(SCREEN_OT_screenshot); 03318 WM_operatortype_append(SCREEN_OT_screencast); 03319 WM_operatortype_append(SCREEN_OT_userpref_show); 03320 03321 /*frame changes*/ 03322 WM_operatortype_append(SCREEN_OT_frame_offset); 03323 WM_operatortype_append(SCREEN_OT_frame_jump); 03324 WM_operatortype_append(SCREEN_OT_keyframe_jump); 03325 03326 WM_operatortype_append(SCREEN_OT_animation_step); 03327 WM_operatortype_append(SCREEN_OT_animation_play); 03328 WM_operatortype_append(SCREEN_OT_animation_cancel); 03329 03330 /* new/delete */ 03331 WM_operatortype_append(SCREEN_OT_new); 03332 WM_operatortype_append(SCREEN_OT_delete); 03333 WM_operatortype_append(SCENE_OT_new); 03334 WM_operatortype_append(SCENE_OT_delete); 03335 03336 /* tools shared by more space types */ 03337 WM_operatortype_append(ED_OT_undo); 03338 WM_operatortype_append(ED_OT_undo_push); 03339 WM_operatortype_append(ED_OT_redo); 03340 WM_operatortype_append(ED_OT_undo_history); 03341 03342 } 03343 03344 static void keymap_modal_set(wmKeyConfig *keyconf) 03345 { 03346 static EnumPropertyItem modal_items[] = { 03347 {KM_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""}, 03348 {KM_MODAL_APPLY, "APPLY", 0, "Apply", ""}, 03349 {KM_MODAL_STEP10, "STEP10", 0, "Steps on", ""}, 03350 {KM_MODAL_STEP10_OFF, "STEP10_OFF", 0, "Steps off", ""}, 03351 {0, NULL, 0, NULL, NULL}}; 03352 wmKeyMap *keymap; 03353 03354 /* Standard Modal keymap ------------------------------------------------ */ 03355 keymap= WM_modalkeymap_add(keyconf, "Standard Modal Map", modal_items); 03356 03357 WM_modalkeymap_add_item(keymap, ESCKEY, KM_PRESS, KM_ANY, 0, KM_MODAL_CANCEL); 03358 WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_ANY, KM_ANY, 0, KM_MODAL_APPLY); 03359 WM_modalkeymap_add_item(keymap, RETKEY, KM_PRESS, KM_ANY, 0, KM_MODAL_APPLY); 03360 WM_modalkeymap_add_item(keymap, PADENTER, KM_PRESS, KM_ANY, 0, KM_MODAL_APPLY); 03361 03362 WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_PRESS, KM_ANY, 0, KM_MODAL_STEP10); 03363 WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_RELEASE, KM_ANY, 0, KM_MODAL_STEP10_OFF); 03364 03365 WM_modalkeymap_assign(keymap, "SCREEN_OT_area_move"); 03366 03367 } 03368 03369 static int open_file_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UNUSED(event)) 03370 { 03371 if(drag->type==WM_DRAG_PATH) { 03372 if(drag->icon==ICON_FILE_BLEND) 03373 return 1; 03374 } 03375 return 0; 03376 } 03377 03378 static void open_file_drop_copy(wmDrag *drag, wmDropBox *drop) 03379 { 03380 /* copy drag path to properties */ 03381 RNA_string_set(drop->ptr, "filepath", drag->path); 03382 drop->opcontext= WM_OP_EXEC_DEFAULT; 03383 } 03384 03385 03386 /* called in spacetypes.c */ 03387 void ED_keymap_screen(wmKeyConfig *keyconf) 03388 { 03389 ListBase *lb; 03390 wmKeyMap *keymap; 03391 //wmKeyMapItem *kmi; 03392 03393 /* Screen Editing ------------------------------------------------ */ 03394 keymap= WM_keymap_find(keyconf, "Screen Editing", 0, 0); 03395 03396 RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_actionzone", LEFTMOUSE, KM_PRESS, 0, 0)->ptr, "modifier", 0); 03397 RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_actionzone", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0)->ptr, "modifier", 1); 03398 RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_actionzone", LEFTMOUSE, KM_PRESS, KM_CTRL, 0)->ptr, "modifier", 2); 03399 03400 /* screen tools */ 03401 WM_keymap_verify_item(keymap, "SCREEN_OT_area_split", EVT_ACTIONZONE_AREA, 0, 0, 0); 03402 WM_keymap_verify_item(keymap, "SCREEN_OT_area_join", EVT_ACTIONZONE_AREA, 0, 0, 0); 03403 WM_keymap_verify_item(keymap, "SCREEN_OT_area_dupli", EVT_ACTIONZONE_AREA, 0, KM_SHIFT, 0); 03404 WM_keymap_verify_item(keymap, "SCREEN_OT_area_swap", EVT_ACTIONZONE_AREA, 0, KM_CTRL, 0); 03405 WM_keymap_verify_item(keymap, "SCREEN_OT_region_scale", EVT_ACTIONZONE_REGION, 0, 0, 0); 03406 /* area move after action zones */ 03407 WM_keymap_verify_item(keymap, "SCREEN_OT_area_move", LEFTMOUSE, KM_PRESS, 0, 0); 03408 03409 WM_keymap_verify_item(keymap, "SCREEN_OT_area_options", RIGHTMOUSE, KM_PRESS, 0, 0); 03410 03411 03412 /* Header Editing ------------------------------------------------ */ 03413 keymap= WM_keymap_find(keyconf, "Header", 0, 0); 03414 03415 WM_keymap_add_item(keymap, "SCREEN_OT_header_toolbox", RIGHTMOUSE, KM_PRESS, 0, 0); 03416 03417 /* Screen General ------------------------------------------------ */ 03418 keymap= WM_keymap_find(keyconf, "Screen", 0, 0); 03419 03420 /* standard timers */ 03421 WM_keymap_add_item(keymap, "SCREEN_OT_animation_step", TIMER0, KM_ANY, KM_ANY, 0); 03422 03423 03424 RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_screen_set", RIGHTARROWKEY, KM_PRESS, KM_CTRL, 0)->ptr, "delta", 1); 03425 RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_screen_set", LEFTARROWKEY, KM_PRESS, KM_CTRL, 0)->ptr, "delta", -1); 03426 WM_keymap_add_item(keymap, "SCREEN_OT_screen_full_area", UPARROWKEY, KM_PRESS, KM_CTRL, 0); 03427 WM_keymap_add_item(keymap, "SCREEN_OT_screen_full_area", DOWNARROWKEY, KM_PRESS, KM_CTRL, 0); 03428 WM_keymap_add_item(keymap, "SCREEN_OT_screen_full_area", SPACEKEY, KM_PRESS, KM_SHIFT, 0); 03429 WM_keymap_add_item(keymap, "SCREEN_OT_screenshot", F3KEY, KM_PRESS, KM_CTRL, 0); 03430 WM_keymap_add_item(keymap, "SCREEN_OT_screencast", F3KEY, KM_PRESS, KM_ALT, 0); 03431 03432 /* tests */ 03433 WM_keymap_add_item(keymap, "SCREEN_OT_region_quadview", QKEY, KM_PRESS, KM_CTRL|KM_ALT, 0); 03434 WM_keymap_verify_item(keymap, "SCREEN_OT_repeat_history", F3KEY, KM_PRESS, 0, 0); 03435 WM_keymap_add_item(keymap, "SCREEN_OT_repeat_last", RKEY, KM_PRESS, KM_SHIFT, 0); 03436 WM_keymap_verify_item(keymap, "SCREEN_OT_region_flip", F5KEY, KM_PRESS, 0, 0); 03437 WM_keymap_verify_item(keymap, "SCREEN_OT_redo_last", F6KEY, KM_PRESS, 0, 0); 03438 WM_keymap_verify_item(keymap, "SCRIPT_OT_reload", F8KEY, KM_PRESS, 0, 0); 03439 03440 /* files */ 03441 WM_keymap_add_item(keymap, "FILE_OT_execute", RETKEY, KM_PRESS, 0, 0); 03442 WM_keymap_add_item(keymap, "FILE_OT_execute", PADENTER, KM_PRESS, 0, 0); 03443 WM_keymap_add_item(keymap, "FILE_OT_cancel", ESCKEY, KM_PRESS, 0, 0); 03444 03445 /* undo */ 03446 #ifdef __APPLE__ 03447 WM_keymap_add_item(keymap, "ED_OT_undo", ZKEY, KM_PRESS, KM_OSKEY, 0); 03448 WM_keymap_add_item(keymap, "ED_OT_redo", ZKEY, KM_PRESS, KM_SHIFT|KM_OSKEY, 0); 03449 WM_keymap_add_item(keymap, "ED_OT_undo_history", ZKEY, KM_PRESS, KM_ALT|KM_OSKEY, 0); 03450 #endif 03451 WM_keymap_add_item(keymap, "ED_OT_undo", ZKEY, KM_PRESS, KM_CTRL, 0); 03452 WM_keymap_add_item(keymap, "ED_OT_redo", ZKEY, KM_PRESS, KM_SHIFT|KM_CTRL, 0); 03453 WM_keymap_add_item(keymap, "ED_OT_undo_history", ZKEY, KM_PRESS, KM_ALT|KM_CTRL, 0); 03454 03455 03456 /* render */ 03457 WM_keymap_add_item(keymap, "RENDER_OT_render", F12KEY, KM_PRESS, 0, 0); 03458 RNA_boolean_set(WM_keymap_add_item(keymap, "RENDER_OT_render", F12KEY, KM_PRESS, KM_CTRL, 0)->ptr, "animation", 1); 03459 WM_keymap_add_item(keymap, "RENDER_OT_view_cancel", ESCKEY, KM_PRESS, 0, 0); 03460 WM_keymap_add_item(keymap, "RENDER_OT_view_show", F11KEY, KM_PRESS, 0, 0); 03461 WM_keymap_add_item(keymap, "RENDER_OT_play_rendered_anim", F11KEY, KM_PRESS, KM_CTRL, 0); 03462 03463 /* user prefs */ 03464 #ifdef __APPLE__ 03465 WM_keymap_add_item(keymap, "SCREEN_OT_userpref_show", COMMAKEY, KM_PRESS, KM_OSKEY, 0); 03466 #endif 03467 WM_keymap_add_item(keymap, "SCREEN_OT_userpref_show", UKEY, KM_PRESS, KM_CTRL|KM_ALT, 0); 03468 03469 03470 /* Anim Playback ------------------------------------------------ */ 03471 keymap= WM_keymap_find(keyconf, "Frames", 0, 0); 03472 03473 /* frame offsets */ 03474 RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_offset", UPARROWKEY, KM_PRESS, 0, 0)->ptr, "delta", 10); 03475 RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_offset", DOWNARROWKEY, KM_PRESS, 0, 0)->ptr, "delta", -10); 03476 RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_offset", LEFTARROWKEY, KM_PRESS, 0, 0)->ptr, "delta", -1); 03477 RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_offset", RIGHTARROWKEY, KM_PRESS, 0, 0)->ptr, "delta", 1); 03478 03479 RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_offset", WHEELDOWNMOUSE, KM_PRESS, KM_ALT, 0)->ptr, "delta", 1); 03480 RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_offset", WHEELUPMOUSE, KM_PRESS, KM_ALT, 0)->ptr, "delta", -1); 03481 03482 RNA_boolean_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_jump", UPARROWKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "end", 1); 03483 RNA_boolean_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_jump", DOWNARROWKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "end", 0); 03484 RNA_boolean_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_jump", RIGHTARROWKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "end", 1); 03485 RNA_boolean_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_jump", LEFTARROWKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "end", 0); 03486 03487 WM_keymap_add_item(keymap, "SCREEN_OT_keyframe_jump", PAGEUPKEY, KM_PRESS, KM_CTRL, 0); 03488 RNA_boolean_set(WM_keymap_add_item(keymap, "SCREEN_OT_keyframe_jump", PAGEDOWNKEY, KM_PRESS, KM_CTRL, 0)->ptr, "next", 0); 03489 03490 WM_keymap_add_item(keymap, "SCREEN_OT_keyframe_jump", MEDIALAST, KM_PRESS, 0, 0); 03491 RNA_boolean_set(WM_keymap_add_item(keymap, "SCREEN_OT_keyframe_jump", MEDIAFIRST, KM_PRESS, 0, 0)->ptr, "next", 0); 03492 03493 /* play (forward and backwards) */ 03494 WM_keymap_add_item(keymap, "SCREEN_OT_animation_play", AKEY, KM_PRESS, KM_ALT, 0); 03495 RNA_boolean_set(WM_keymap_add_item(keymap, "SCREEN_OT_animation_play", AKEY, KM_PRESS, KM_ALT|KM_SHIFT, 0)->ptr, "reverse", 1); 03496 WM_keymap_add_item(keymap, "SCREEN_OT_animation_cancel", ESCKEY, KM_PRESS, 0, 0); 03497 03498 WM_keymap_add_item(keymap, "SCREEN_OT_animation_play", MEDIAPLAY, KM_PRESS, 0, 0); 03499 WM_keymap_add_item(keymap, "SCREEN_OT_animation_cancel", MEDIASTOP, KM_PRESS, 0, 0); 03500 03501 /* Alternative keys for animation and sequencer playing */ 03502 #if 0 // XXX: disabled for restoring later... bad implementation 03503 keymap= WM_keymap_find(keyconf, "Frames", 0, 0); 03504 kmi = WM_keymap_add_item(keymap, "SCREEN_OT_animation_play", RIGHTARROWKEY, KM_PRESS, KM_ALT, 0); 03505 RNA_boolean_set(kmi->ptr, "cycle_speed", 1); 03506 03507 kmi = WM_keymap_add_item(keymap, "SCREEN_OT_animation_play", LEFTARROWKEY, KM_PRESS, KM_ALT, 0); 03508 RNA_boolean_set(kmi->ptr, "reverse", 1); 03509 RNA_boolean_set(kmi->ptr, "cycle_speed", 1); 03510 03511 WM_keymap_add_item(keymap, "SCREEN_OT_animation_play", DOWNARROWKEY, KM_PRESS, KM_ALT, 0); 03512 #endif 03513 03514 /* dropbox for entire window */ 03515 lb= WM_dropboxmap_find("Window", 0, 0); 03516 WM_dropbox_add(lb, "WM_OT_open_mainfile", open_file_drop_poll, open_file_drop_copy); 03517 03518 keymap_modal_set(keyconf); 03519 } 03520