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