4 * ***** BEGIN GPL LICENSE BLOCK *****
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 * The Original Code is Copyright (C) 2008 Blender Foundation.
21 * All rights reserved.
24 * ***** END GPL LICENSE BLOCK *****
29 #include "MEM_guardedalloc.h"
31 #include "BLI_arithb.h"
32 #include "BLI_blenlib.h"
33 #include "BLI_editVert.h"
35 #include "DNA_armature_types.h"
36 #include "DNA_image_types.h"
37 #include "DNA_object_types.h"
38 #include "DNA_mesh_types.h"
39 #include "DNA_curve_types.h"
40 #include "DNA_scene_types.h"
42 #include "BKE_blender.h"
43 #include "BKE_context.h"
44 #include "BKE_customdata.h"
45 #include "BKE_global.h"
46 #include "BKE_image.h"
47 #include "BKE_idprop.h"
48 #include "BKE_library.h"
50 #include "BKE_multires.h"
51 #include "BKE_report.h"
52 #include "BKE_screen.h"
53 #include "BKE_utildefines.h"
59 #include "ED_screen.h"
60 #include "ED_screen_types.h"
62 #include "RE_pipeline.h"
63 #include "IMB_imbuf.h"
64 #include "IMB_imbuf_types.h"
66 #include "RNA_access.h"
67 #include "RNA_define.h"
69 #include "UI_interface.h"
70 #include "UI_resources.h"
72 #include "screen_intern.h" /* own module include */
74 /* ************** Exported Poll tests ********************** */
76 int ED_operator_regionactive(bContext *C)
78 if(CTX_wm_window(C)==NULL) return 0;
79 if(CTX_wm_screen(C)==NULL) return 0;
80 if(CTX_wm_region(C)==NULL) return 0;
84 int ED_operator_areaactive(bContext *C)
86 if(CTX_wm_window(C)==NULL) return 0;
87 if(CTX_wm_screen(C)==NULL) return 0;
88 if(CTX_wm_area(C)==NULL) return 0;
92 int ED_operator_screenactive(bContext *C)
94 if(CTX_wm_window(C)==NULL) return 0;
95 if(CTX_wm_screen(C)==NULL) return 0;
99 /* when mouse is over area-edge */
100 int ED_operator_screen_mainwinactive(bContext *C)
102 if(CTX_wm_window(C)==NULL) return 0;
103 if(CTX_wm_screen(C)==NULL) return 0;
104 if (CTX_wm_screen(C)->subwinactive!=CTX_wm_screen(C)->mainwin) return 0;
108 int ED_operator_scene_editable(bContext *C)
110 Scene *scene= CTX_data_scene(C);
111 if(scene && scene->id.lib==NULL)
116 static int ed_spacetype_test(bContext *C, int type)
118 if(ED_operator_areaactive(C)) {
119 SpaceLink *sl= (SpaceLink *)CTX_wm_space_data(C);
120 return sl && (sl->spacetype == type);
125 int ED_operator_view3d_active(bContext *C)
127 return ed_spacetype_test(C, SPACE_VIEW3D);
130 int ED_operator_timeline_active(bContext *C)
132 return ed_spacetype_test(C, SPACE_TIME);
135 int ED_operator_outliner_active(bContext *C)
137 if(ed_spacetype_test(C, SPACE_OOPS)) {
138 SpaceOops *so= (SpaceOops *)CTX_wm_space_data(C);
139 return (so->type == SO_OUTLINER);
144 int ED_operator_file_active(bContext *C)
146 return ed_spacetype_test(C, SPACE_FILE);
149 int ED_operator_action_active(bContext *C)
151 return ed_spacetype_test(C, SPACE_ACTION);
154 int ED_operator_buttons_active(bContext *C)
156 return ed_spacetype_test(C, SPACE_BUTS);
159 int ED_operator_node_active(bContext *C)
161 if(ed_spacetype_test(C, SPACE_NODE)) {
162 SpaceNode *snode= (SpaceNode *)CTX_wm_space_data(C);
169 int ED_operator_ipo_active(bContext *C)
171 return ed_spacetype_test(C, SPACE_IPO);
174 int ED_operator_sequencer_active(bContext *C)
176 return ed_spacetype_test(C, SPACE_SEQ);
179 int ED_operator_image_active(bContext *C)
181 return ed_spacetype_test(C, SPACE_IMAGE);
184 int ED_operator_object_active(bContext *C)
186 return NULL != CTX_data_active_object(C);
189 int ED_operator_editmesh(bContext *C)
191 Object *obedit= CTX_data_edit_object(C);
192 if(obedit && obedit->type==OB_MESH)
193 return NULL != ((Mesh *)obedit->data)->edit_mesh;
197 int ED_operator_editarmature(bContext *C)
199 Object *obedit= CTX_data_edit_object(C);
200 if(obedit && obedit->type==OB_ARMATURE)
201 return NULL != ((bArmature *)obedit->data)->edbo;
205 int ED_operator_posemode(bContext *C)
207 Object *obact= CTX_data_active_object(C);
208 Object *obedit= CTX_data_edit_object(C);
210 if ((obact != obedit) && (obact) && (obact->type==OB_ARMATURE))
211 return (obact->flag & OB_POSEMODE)!=0;
217 int ED_operator_uvedit(bContext *C)
219 Object *obedit= CTX_data_edit_object(C);
222 if(obedit && obedit->type==OB_MESH)
223 em= ((Mesh *)obedit->data)->edit_mesh;
225 if(em && (em->faces.first) && (CustomData_has_layer(&em->fdata, CD_MTFACE)))
231 int ED_operator_uvmap(bContext *C)
233 Object *obedit= CTX_data_edit_object(C);
236 if(obedit && obedit->type==OB_MESH)
237 em= ((Mesh *)obedit->data)->edit_mesh;
239 if(em && (em->faces.first))
245 int ED_operator_editsurfcurve(bContext *C)
247 Object *obedit= CTX_data_edit_object(C);
248 if(obedit && ELEM(obedit->type, OB_CURVE, OB_SURF))
249 return NULL != ((Curve *)obedit->data)->editnurb;
254 int ED_operator_editcurve(bContext *C)
256 Object *obedit= CTX_data_edit_object(C);
257 if(obedit && obedit->type==OB_CURVE)
258 return NULL != ((Curve *)obedit->data)->editnurb;
262 int ED_operator_editsurf(bContext *C)
264 Object *obedit= CTX_data_edit_object(C);
265 if(obedit && obedit->type==OB_SURF)
266 return NULL != ((Curve *)obedit->data)->editnurb;
270 int ED_operator_editfont(bContext *C)
272 Object *obedit= CTX_data_edit_object(C);
273 if(obedit && obedit->type==OB_FONT)
274 return NULL != ((Curve *)obedit->data)->editfont;
278 /* *************************** action zone operator ************************** */
280 /* operator state vars used:
285 apply() set actionzone event
287 exit() free customdata
293 invoke() check if in zone
294 add customdata, put mouseco and area in it
297 modal() accept modal events while doing it
298 call apply() with gesture info, active window, nonactive window
299 call exit() and remove handler when LMB confirm
303 typedef struct sActionzoneData {
306 int x, y, gesture_dir, modifier;
309 /* used by other operators too */
310 static ScrArea *screen_areahascursor(bScreen *scr, int x, int y)
313 sa= scr->areabase.first;
315 if(BLI_in_rcti(&sa->totrct, x, y)) break;
323 AZone *is_in_area_actionzone(ScrArea *sa, int x, int y)
328 for(az= sa->actionzones.first, i= 0; az; az= az->next, i++) {
329 if(az->type == AZONE_TRI) {
330 if(IsPointInTri2DInts(az->x1, az->y1, az->x2, az->y2, x, y))
333 if(az->type == AZONE_QUAD) {
334 if(az->x1 < x && x < az->x2 && az->y1 < y && y < az->y2)
342 static int actionzone_invoke(bContext *C, wmOperator *op, wmEvent *event)
344 AZone *az= is_in_area_actionzone(CTX_wm_area(C), event->x, event->y);
345 sActionzoneData *sad;
349 return OPERATOR_PASS_THROUGH;
351 /* ok we do the actionzone */
352 sad= op->customdata= MEM_callocN(sizeof(sActionzoneData), "sActionzoneData");
353 sad->sa1= CTX_wm_area(C);
355 sad->x= event->x; sad->y= event->y;
357 /* add modal handler */
358 WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
360 return OPERATOR_RUNNING_MODAL;
363 static void actionzone_exit(bContext *C, wmOperator *op)
366 MEM_freeN(op->customdata);
367 op->customdata= NULL;
370 /* send EVT_ACTIONZONE event */
371 static void actionzone_apply(bContext *C, wmOperator *op)
374 wmWindow *win= CTX_wm_window(C);
375 sActionzoneData *sad= op->customdata;
376 sad->modifier= RNA_int_get(op->ptr, "modifier");
378 event= *(win->eventstate); /* XXX huh huh? make api call */
379 event.type= EVT_ACTIONZONE;
380 event.customdata= op->customdata;
381 event.customdatafree= TRUE;
382 op->customdata= NULL;
384 wm_event_add(win, &event);
387 static int actionzone_modal(bContext *C, wmOperator *op, wmEvent *event)
389 sActionzoneData *sad= op->customdata;
392 switch(event->type) {
394 /* calculate gesture direction */
395 deltax= (event->x - sad->x);
396 deltay= (event->y - sad->y);
398 if(deltay > ABS(deltax))
399 sad->gesture_dir= AZONE_N;
400 else if(deltax > ABS(deltay))
401 sad->gesture_dir= AZONE_E;
402 else if(deltay < -ABS(deltax))
403 sad->gesture_dir= AZONE_S;
405 sad->gesture_dir= AZONE_W;
407 /* gesture is large enough? */
408 if(ABS(deltax) > 12 || ABS(deltay) > 12) {
410 /* second area, for join */
411 sad->sa2= screen_areahascursor(CTX_wm_screen(C), event->x, event->y);
412 /* apply sends event */
413 actionzone_apply(C, op);
414 actionzone_exit(C, op);
416 return OPERATOR_FINISHED;
421 actionzone_exit(C, op);
422 return OPERATOR_CANCELLED;
425 return OPERATOR_RUNNING_MODAL;
428 void SCREEN_OT_actionzone(wmOperatorType *ot)
431 ot->name= "Handle area action zones";
432 ot->idname= "SCREEN_OT_actionzone";
434 ot->invoke= actionzone_invoke;
435 ot->modal= actionzone_modal;
437 ot->poll= ED_operator_areaactive;
438 RNA_def_int(ot->srna, "modifier", 0, 0, 2, "modifier", "modifier state", 0, 2);
441 /* ************** swap area operator *********************************** */
443 /* operator state vars used:
445 sa2 area to swap with
449 init() set custom data for operator, based on actionzone event custom data
451 cancel() cancel the operator
453 exit() cleanup, send notifier
457 invoke() gets called on shift+lmb drag in actionzone
458 call init(), add handler
460 modal() accept modal events while doing it
464 typedef struct sAreaSwapData {
468 static int area_swap_init(bContext *C, wmOperator *op, wmEvent *event)
470 sAreaSwapData *sd= NULL;
471 sActionzoneData *sad= event->customdata;
473 if(sad==NULL || sad->sa1==NULL)
476 sd= MEM_callocN(sizeof(sAreaSwapData), "sAreaSwapData");
485 static void area_swap_exit(bContext *C, wmOperator *op)
488 MEM_freeN(op->customdata);
489 op->customdata= NULL;
492 static int area_swap_cancel(bContext *C, wmOperator *op)
494 area_swap_exit(C, op);
495 return OPERATOR_CANCELLED;
498 static int area_swap_invoke(bContext *C, wmOperator *op, wmEvent *event)
501 if(!area_swap_init(C, op, event))
502 return OPERATOR_PASS_THROUGH;
504 /* add modal handler */
505 WM_cursor_modal(CTX_wm_window(C), BC_SWAPAREA_CURSOR);
506 WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
508 return OPERATOR_RUNNING_MODAL;
512 static int area_swap_modal(bContext *C, wmOperator *op, wmEvent *event)
514 sActionzoneData *sad= op->customdata;
516 switch(event->type) {
518 /* second area, for join */
519 sad->sa2= screen_areahascursor(CTX_wm_screen(C), event->x, event->y);
521 case LEFTMOUSE: /* release LMB */
523 if(sad->sa1 == sad->sa2) {
525 return area_swap_cancel(C, op);
527 ED_area_swapspace(C, sad->sa1, sad->sa2);
529 area_swap_exit(C, op);
531 WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL);
533 return OPERATOR_FINISHED;
538 return area_swap_cancel(C, op);
540 return OPERATOR_RUNNING_MODAL;
543 void SCREEN_OT_area_swap(wmOperatorType *ot)
545 ot->name= "Swap areas";
546 ot->idname= "SCREEN_OT_area_swap";
548 ot->invoke= area_swap_invoke;
549 ot->modal= area_swap_modal;
550 ot->poll= ED_operator_areaactive;
553 /* *********** Duplicate area as new window operator ****************** */
555 /* operator callback */
556 static int area_dupli_invoke(bContext *C, wmOperator *op, wmEvent *event)
558 wmWindow *newwin, *win;
562 sActionzoneData *sad= event->customdata;
565 return OPERATOR_PASS_THROUGH;
567 win= CTX_wm_window(C);
568 sc= CTX_wm_screen(C);
571 /* poll() checks area context, but we don't accept full-area windows */
572 if(sc->full != SCREENNORMAL) {
573 actionzone_exit(C, op);
574 return OPERATOR_CANCELLED;
577 /* adds window to WM */
579 BLI_translate_rcti(&rect, win->posx, win->posy);
580 newwin= WM_window_open(C, &rect);
582 /* allocs new screen and adds to newly created window, using window size */
583 newsc= screen_add(newwin, CTX_data_scene(C), sc->id.name+2);
584 newwin->screen= newsc;
586 /* copy area to new screen */
587 area_copy_data((ScrArea *)newsc->areabase.first, sa, 0);
589 /* screen, areas init */
590 WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL);
592 actionzone_exit(C, op);
594 return OPERATOR_FINISHED;
597 void SCREEN_OT_area_dupli(wmOperatorType *ot)
599 ot->name= "Duplicate Area into New Window";
600 ot->idname= "SCREEN_OT_area_dupli";
602 ot->invoke= area_dupli_invoke;
603 ot->poll= ED_operator_areaactive;
607 /* ************** move area edge operator *********************************** */
609 /* operator state vars used:
610 x, y mouse coord near edge
611 delta movement of edge
615 init() set default property values, find edge based on mouse coords, test
616 if the edge can be moved, select edges, calculate min and max movement
618 apply() apply delta on selection
620 exit() cleanup, send notifier
622 cancel() cancel moving
626 exec() execute without any user interaction, based on properties
627 call init(), apply(), exit()
629 invoke() gets called on mouse click near edge
630 call init(), add handler
632 modal() accept modal events while doing it
633 call apply() with delta motion
634 call exit() and remove handler
638 typedef struct sAreaMoveData {
639 int bigger, smaller, origval;
643 /* helper call to move area-edge, sets limits */
644 static void area_move_set_limits(bScreen *sc, int dir, int *bigger, int *smaller)
648 /* we check all areas and test for free space with MINSIZE */
649 *bigger= *smaller= 100000;
651 for(sa= sc->areabase.first; sa; sa= sa->next) {
653 int y1= sa->v2->vec.y - sa->v1->vec.y-AREAMINY;
655 /* if top or down edge selected, test height */
656 if(sa->v1->flag && sa->v4->flag)
657 *bigger= MIN2(*bigger, y1);
658 else if(sa->v2->flag && sa->v3->flag)
659 *smaller= MIN2(*smaller, y1);
662 int x1= sa->v4->vec.x - sa->v1->vec.x-AREAMINX;
664 /* if left or right edge selected, test width */
665 if(sa->v1->flag && sa->v2->flag)
666 *bigger= MIN2(*bigger, x1);
667 else if(sa->v3->flag && sa->v4->flag)
668 *smaller= MIN2(*smaller, x1);
673 /* validate selection inside screen, set variables OK */
674 /* return 0: init failed */
675 static int area_move_init (bContext *C, wmOperator *op)
677 bScreen *sc= CTX_wm_screen(C);
682 /* required properties */
683 x= RNA_int_get(op->ptr, "x");
684 y= RNA_int_get(op->ptr, "y");
687 actedge= screen_find_active_scredge(sc, x, y);
688 if(actedge==NULL) return 0;
690 md= MEM_callocN(sizeof(sAreaMoveData), "sAreaMoveData");
693 md->dir= scredge_is_horizontal(actedge)?'h':'v';
694 if(md->dir=='h') md->origval= actedge->v1->vec.y;
695 else md->origval= actedge->v1->vec.x;
697 select_connected_scredge(sc, actedge);
698 /* now all vertices with 'flag==1' are the ones that can be moved. */
700 area_move_set_limits(sc, md->dir, &md->bigger, &md->smaller);
705 /* moves selected screen edge amount of delta, used by split & move */
706 static void area_move_apply_do(bContext *C, int origval, int delta, int dir, int bigger, int smaller)
708 wmWindow *win= CTX_wm_window(C);
709 bScreen *sc= CTX_wm_screen(C);
712 delta= CLAMPIS(delta, -smaller, bigger);
714 for (v1= sc->vertbase.first; v1; v1= v1->next) {
716 /* that way a nice AREAGRID */
717 if((dir=='v') && v1->vec.x>0 && v1->vec.x<win->sizex-1) {
718 v1->vec.x= origval + delta;
719 if(delta != bigger && delta != -smaller) v1->vec.x-= (v1->vec.x % AREAGRID);
721 if((dir=='h') && v1->vec.y>0 && v1->vec.y<win->sizey-1) {
722 v1->vec.y= origval + delta;
724 v1->vec.y+= AREAGRID-1;
725 v1->vec.y-= (v1->vec.y % AREAGRID);
727 /* prevent too small top header */
728 if(v1->vec.y > win->sizey-AREAMINY)
729 v1->vec.y= win->sizey-AREAMINY;
734 WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL);
737 static void area_move_apply(bContext *C, wmOperator *op)
739 sAreaMoveData *md= op->customdata;
742 delta= RNA_int_get(op->ptr, "delta");
743 area_move_apply_do(C, md->origval, delta, md->dir, md->bigger, md->smaller);
746 static void area_move_exit(bContext *C, wmOperator *op)
749 MEM_freeN(op->customdata);
750 op->customdata= NULL;
752 /* this makes sure aligned edges will result in aligned grabbing */
753 removedouble_scrverts(CTX_wm_screen(C));
754 removedouble_scredges(CTX_wm_screen(C));
757 static int area_move_exec(bContext *C, wmOperator *op)
759 if(!area_move_init(C, op))
760 return OPERATOR_CANCELLED;
762 area_move_apply(C, op);
763 area_move_exit(C, op);
765 return OPERATOR_FINISHED;
768 /* interaction callback */
769 static int area_move_invoke(bContext *C, wmOperator *op, wmEvent *event)
771 RNA_int_set(op->ptr, "x", event->x);
772 RNA_int_set(op->ptr, "y", event->y);
774 if(!area_move_init(C, op))
775 return OPERATOR_PASS_THROUGH;
777 /* add temp handler */
778 WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
780 return OPERATOR_RUNNING_MODAL;
783 static int area_move_cancel(bContext *C, wmOperator *op)
786 RNA_int_set(op->ptr, "delta", 0);
787 area_move_apply(C, op);
788 area_move_exit(C, op);
790 return OPERATOR_CANCELLED;
793 /* modal callback for while moving edges */
794 static int area_move_modal(bContext *C, wmOperator *op, wmEvent *event)
801 x= RNA_int_get(op->ptr, "x");
802 y= RNA_int_get(op->ptr, "y");
804 /* execute the events */
805 switch(event->type) {
807 delta= (md->dir == 'v')? event->x - x: event->y - y;
808 RNA_int_set(op->ptr, "delta", delta);
810 area_move_apply(C, op);
815 area_move_exit(C, op);
816 return OPERATOR_FINISHED;
821 return area_move_cancel(C, op);
824 return OPERATOR_RUNNING_MODAL;
827 void SCREEN_OT_area_move(wmOperatorType *ot)
830 ot->name= "Move area edges";
831 ot->idname= "SCREEN_OT_area_move";
833 ot->exec= area_move_exec;
834 ot->invoke= area_move_invoke;
835 ot->cancel= area_move_cancel;
836 ot->modal= area_move_modal;
838 ot->poll= ED_operator_screen_mainwinactive; /* when mouse is over area-edge */
841 RNA_def_int(ot->srna, "x", 0, INT_MIN, INT_MAX, "X", "", INT_MIN, INT_MAX);
842 RNA_def_int(ot->srna, "y", 0, INT_MIN, INT_MAX, "Y", "", INT_MIN, INT_MAX);
843 RNA_def_int(ot->srna, "delta", 0, INT_MIN, INT_MAX, "Delta", "", INT_MIN, INT_MAX);
846 /* ************** split area operator *********************************** */
851 dir direction 'v' or 'h'
854 area pointer to (active) area
855 x, y last used mouse pos
860 init() set default property values, find area based on context
862 apply() split area based on state vars
864 exit() cleanup, send notifier
866 cancel() remove duplicated area
870 exec() execute without any user interaction, based on state vars
871 call init(), apply(), exit()
873 invoke() gets called on mouse click in action-widget
874 call init(), add modal handler
875 call apply() with initial motion
877 modal() accept modal events while doing it
878 call move-areas code with delta motion
879 call exit() or cancel() and remove handler
883 #define SPLIT_STARTED 1
884 #define SPLIT_PROGRESS 2
886 typedef struct sAreaSplitData
888 int x, y; /* last used mouse position */
890 int origval; /* for move areas */
891 int bigger, smaller; /* constraints for moving new edge */
892 int delta; /* delta move edge */
893 int origmin, origsize; /* to calculate fac, for property storage */
895 ScrEdge *nedge; /* new edge */
896 ScrArea *sarea; /* start area */
897 ScrArea *narea; /* new area */
900 /* generic init, no UI stuff here */
901 static int area_split_init(bContext *C, wmOperator *op)
903 ScrArea *sa= CTX_wm_area(C);
907 /* required context */
908 if(sa==NULL) return 0;
910 /* required properties */
911 dir= RNA_enum_get(op->ptr, "direction");
914 if(dir=='v' && sa->winx < 2*AREAMINX) return 0;
915 if(dir=='h' && sa->winy < 2*AREAMINY) return 0;
918 sd= (sAreaSplitData*)MEM_callocN(sizeof (sAreaSplitData), "op_area_split");
922 sd->origsize= dir=='v' ? sa->winx:sa->winy;
923 sd->origmin = dir=='v' ? sa->totrct.xmin:sa->totrct.ymin;
928 /* with sa as center, sb is located at: 0=W, 1=N, 2=E, 3=S */
929 /* used with split operator */
930 static ScrEdge *area_findsharededge(bScreen *screen, ScrArea *sa, ScrArea *sb)
932 ScrVert *sav1= sa->v1;
933 ScrVert *sav2= sa->v2;
934 ScrVert *sav3= sa->v3;
935 ScrVert *sav4= sa->v4;
936 ScrVert *sbv1= sb->v1;
937 ScrVert *sbv2= sb->v2;
938 ScrVert *sbv3= sb->v3;
939 ScrVert *sbv4= sb->v4;
941 if(sav1==sbv4 && sav2==sbv3) { /* sa to right of sb = W */
942 return screen_findedge(screen, sav1, sav2);
944 else if(sav2==sbv1 && sav3==sbv4) { /* sa to bottom of sb = N */
945 return screen_findedge(screen, sav2, sav3);
947 else if(sav3==sbv2 && sav4==sbv1) { /* sa to left of sb = E */
948 return screen_findedge(screen, sav3, sav4);
950 else if(sav1==sbv2 && sav4==sbv3) { /* sa on top of sb = S*/
951 return screen_findedge(screen, sav1, sav4);
958 /* do the split, return success */
959 static int area_split_apply(bContext *C, wmOperator *op)
961 bScreen *sc= CTX_wm_screen(C);
962 sAreaSplitData *sd= (sAreaSplitData *)op->customdata;
966 fac= RNA_float_get(op->ptr, "factor");
967 dir= RNA_enum_get(op->ptr, "direction");
969 sd->narea= area_split(CTX_wm_window(C), sc, sd->sarea, dir, fac);
974 sd->nedge= area_findsharededge(sc, sd->sarea, sd->narea);
976 /* select newly created edge, prepare for moving edge */
977 for(sv= sc->vertbase.first; sv; sv= sv->next)
980 sd->nedge->v1->flag= 1;
981 sd->nedge->v2->flag= 1;
983 if(dir=='h') sd->origval= sd->nedge->v1->vec.y;
984 else sd->origval= sd->nedge->v1->vec.x;
986 WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL);
994 static void area_split_exit(bContext *C, wmOperator *op)
996 if (op->customdata) {
997 MEM_freeN(op->customdata);
998 op->customdata = NULL;
1001 WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL);
1003 /* this makes sure aligned edges will result in aligned grabbing */
1004 removedouble_scrverts(CTX_wm_screen(C));
1005 removedouble_scredges(CTX_wm_screen(C));
1009 /* UI callback, adds new handler */
1010 static int area_split_invoke(bContext *C, wmOperator *op, wmEvent *event)
1014 if(event->type==EVT_ACTIONZONE) {
1015 sActionzoneData *sad= event->customdata;
1018 if(sad->modifier>0) {
1019 return OPERATOR_PASS_THROUGH;
1022 /* verify *sad itself */
1023 if(sad==NULL || sad->sa1==NULL || sad->az==NULL)
1024 return OPERATOR_PASS_THROUGH;
1026 /* is this our *sad? if areas not equal it should be passed on */
1027 if(CTX_wm_area(C)!=sad->sa1 || sad->sa1!=sad->sa2)
1028 return OPERATOR_PASS_THROUGH;
1030 /* prepare operator state vars */
1031 if(sad->gesture_dir==AZONE_N || sad->gesture_dir==AZONE_S) {
1033 RNA_float_set(op->ptr, "factor", ((float)(event->x - sad->sa1->v1->vec.x)) / (float)sad->sa1->winx);
1037 RNA_float_set(op->ptr, "factor", ((float)(event->y - sad->sa1->v1->vec.y)) / (float)sad->sa1->winy);
1039 RNA_enum_set(op->ptr, "direction", dir);
1041 /* general init, also non-UI case, adds customdata, sets area and defaults */
1042 if(!area_split_init(C, op))
1043 return OPERATOR_PASS_THROUGH;
1045 sd= (sAreaSplitData *)op->customdata;
1051 if(area_split_apply(C, op)) {
1052 area_move_set_limits(CTX_wm_screen(C), dir, &sd->bigger, &sd->smaller);
1054 /* add temp handler for edge move or cancel */
1055 WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
1057 return OPERATOR_RUNNING_MODAL;
1062 /* nonmodal for now */
1063 return op->type->exec(C, op);
1066 return OPERATOR_PASS_THROUGH;
1069 /* function to be called outside UI context, or for redo */
1070 static int area_split_exec(bContext *C, wmOperator *op)
1073 if(!area_split_init(C, op))
1074 return OPERATOR_CANCELLED;
1076 area_split_apply(C, op);
1077 area_split_exit(C, op);
1079 return OPERATOR_FINISHED;
1083 static int area_split_cancel(bContext *C, wmOperator *op)
1085 sAreaSplitData *sd= (sAreaSplitData *)op->customdata;
1087 if (screen_area_join(C, CTX_wm_screen(C), sd->sarea, sd->narea)) {
1088 if (CTX_wm_area(C) == sd->narea) {
1089 CTX_wm_area_set(C, NULL);
1090 CTX_wm_region_set(C, NULL);
1094 area_split_exit(C, op);
1096 return OPERATOR_CANCELLED;
1099 static int area_split_modal(bContext *C, wmOperator *op, wmEvent *event)
1101 sAreaSplitData *sd= (sAreaSplitData *)op->customdata;
1105 /* execute the events */
1106 switch(event->type) {
1108 dir= RNA_enum_get(op->ptr, "direction");
1110 sd->delta= (dir == 'v')? event->x - sd->origval: event->y - sd->origval;
1111 area_move_apply_do(C, sd->origval, sd->delta, dir, sd->bigger, sd->smaller);
1113 fac= (dir == 'v') ? event->x-sd->origmin : event->y-sd->origmin;
1114 RNA_float_set(op->ptr, "factor", fac / (float)sd->origsize);
1116 WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL);
1120 if(event->val==0) { /* mouse up */
1121 area_split_exit(C, op);
1122 return OPERATOR_FINISHED;
1125 case RIGHTMOUSE: /* cancel operation */
1127 return area_split_cancel(C, op);
1130 return OPERATOR_RUNNING_MODAL;
1133 static EnumPropertyItem prop_direction_items[] = {
1134 {'h', "HORIZONTAL", "Horizontal", ""},
1135 {'v', "VERTICAL", "Vertical", ""},
1136 {0, NULL, NULL, NULL}};
1138 void SCREEN_OT_area_split(wmOperatorType *ot)
1140 ot->name = "Split area";
1141 ot->idname = "SCREEN_OT_area_split";
1143 ot->exec= area_split_exec;
1144 ot->invoke= area_split_invoke;
1145 ot->modal= area_split_modal;
1147 ot->poll= ED_operator_areaactive;
1148 ot->flag= OPTYPE_REGISTER;
1151 RNA_def_enum(ot->srna, "direction", prop_direction_items, 'h', "Direction", "");
1152 RNA_def_float(ot->srna, "factor", 0.5f, 0.0, 1.0, "Factor", "", 0.0, 1.0);
1155 /* ************** frame change operator ***************************** */
1158 /* function to be called outside UI context, or for redo */
1159 static int frame_offset_exec(bContext *C, wmOperator *op)
1163 delta = RNA_int_get(op->ptr, "delta");
1165 CTX_data_scene(C)->r.cfra += delta;
1167 WM_event_add_notifier(C, NC_SCENE|ND_FRAME, CTX_data_scene(C));
1169 return OPERATOR_FINISHED;
1172 void SCREEN_OT_frame_offset(wmOperatorType *ot)
1174 ot->name = "Frame Offset";
1175 ot->idname = "SCREEN_OT_frame_offset";
1177 ot->exec= frame_offset_exec;
1179 ot->poll= ED_operator_screenactive;
1183 RNA_def_int(ot->srna, "delta", 0, INT_MIN, INT_MAX, "Delta", "", INT_MIN, INT_MAX);
1186 /* ************** switch screen operator ***************************** */
1189 /* function to be called outside UI context, or for redo */
1190 static int screen_set_exec(bContext *C, wmOperator *op)
1192 bScreen *screen= CTX_wm_screen(C);
1193 ScrArea *sa= CTX_wm_area(C);
1194 int tot= BLI_countlist(&CTX_data_main(C)->screen);
1195 int delta= RNA_int_get(op->ptr, "delta");
1197 /* this screen is 'fake', solve later XXX */
1199 return OPERATOR_CANCELLED;
1203 screen= screen->id.next;
1204 if(screen==NULL) screen= CTX_data_main(C)->screen.first;
1205 if(screen->winid==0 && screen->full==0)
1209 else if(delta== -1) {
1211 screen= screen->id.prev;
1212 if(screen==NULL) screen= CTX_data_main(C)->screen.last;
1213 if(screen->winid==0 && screen->full==0)
1222 ED_screen_set(C, screen);
1223 return OPERATOR_FINISHED;
1225 return OPERATOR_CANCELLED;
1228 void SCREEN_OT_screen_set(wmOperatorType *ot)
1230 ot->name = "Set Screen";
1231 ot->idname = "SCREEN_OT_screen_set";
1233 ot->exec= screen_set_exec;
1234 ot->poll= ED_operator_screenactive;
1237 RNA_def_pointer_runtime(ot->srna, "screen", &RNA_Screen, "Screen", "");
1238 RNA_def_int(ot->srna, "delta", 0, INT_MIN, INT_MAX, "Delta", "", INT_MIN, INT_MAX);
1241 /* ************** screen full-area operator ***************************** */
1244 /* function to be called outside UI context, or for redo */
1245 static int screen_full_area_exec(bContext *C, wmOperator *op)
1247 ed_screen_fullarea(C, CTX_wm_area(C));
1248 return OPERATOR_FINISHED;
1251 void SCREEN_OT_screen_full_area(wmOperatorType *ot)
1253 ot->name = "Toggle Make Area Fullscreen";
1254 ot->idname = "SCREEN_OT_screen_full_area";
1256 ot->exec= screen_full_area_exec;
1257 ot->poll= ED_operator_areaactive;
1264 /* ************** join area operator ********************************************** */
1266 /* operator state vars used:
1267 x1, y1 mouse coord in first area, which will disappear
1268 x2, y2 mouse coord in 2nd area, which will become joined
1272 init() find edge based on state vars
1273 test if the edge divides two areas,
1274 store active and nonactive area,
1276 apply() do the actual join
1278 exit() cleanup, send notifier
1282 exec() calls init, apply, exit
1284 invoke() sets mouse coords in x,y
1288 modal() accept modal events while doing it
1289 call apply() with active window and nonactive window
1290 call exit() and remove handler when LMB confirm
1294 typedef struct sAreaJoinData
1296 ScrArea *sa1; /* first area to be considered */
1297 ScrArea *sa2; /* second area to be considered */
1298 ScrArea *scr; /* designed for removal */
1303 /* validate selection inside screen, set variables OK */
1304 /* return 0: init failed */
1305 /* XXX todo: find edge based on (x,y) and set other area? */
1306 static int area_join_init(bContext *C, wmOperator *op)
1309 sAreaJoinData* jd= NULL;
1313 /* required properties, make negative to get return 0 if not set by caller */
1314 x1= RNA_int_get(op->ptr, "x1");
1315 y1= RNA_int_get(op->ptr, "y1");
1316 x2= RNA_int_get(op->ptr, "x2");
1317 y2= RNA_int_get(op->ptr, "y2");
1319 sa1 = screen_areahascursor(CTX_wm_screen(C), x1, y1);
1320 sa2 = screen_areahascursor(CTX_wm_screen(C), x2, y2);
1321 if(sa1==NULL || sa2==NULL || sa1==sa2)
1324 jd = (sAreaJoinData*)MEM_callocN(sizeof (sAreaJoinData), "op_area_join");
1327 jd->sa1->flag |= AREA_FLAG_DRAWJOINFROM;
1329 jd->sa2->flag |= AREA_FLAG_DRAWJOINTO;
1336 /* apply the join of the areas (space types) */
1337 static int area_join_apply(bContext *C, wmOperator *op)
1339 sAreaJoinData *jd = (sAreaJoinData *)op->customdata;
1342 if(!screen_area_join(C, CTX_wm_screen(C), jd->sa1, jd->sa2)){
1345 if (CTX_wm_area(C) == jd->sa2) {
1346 CTX_wm_area_set(C, NULL);
1347 CTX_wm_region_set(C, NULL);
1353 /* finish operation */
1354 static void area_join_exit(bContext *C, wmOperator *op)
1356 if (op->customdata) {
1357 MEM_freeN(op->customdata);
1358 op->customdata = NULL;
1361 /* this makes sure aligned edges will result in aligned grabbing */
1362 removedouble_scredges(CTX_wm_screen(C));
1363 removenotused_scredges(CTX_wm_screen(C));
1364 removenotused_scrverts(CTX_wm_screen(C));
1367 static int area_join_exec(bContext *C, wmOperator *op)
1369 if(!area_join_init(C, op))
1370 return OPERATOR_CANCELLED;
1372 area_join_apply(C, op);
1373 area_join_exit(C, op);
1375 return OPERATOR_FINISHED;
1378 /* interaction callback */
1379 static int area_join_invoke(bContext *C, wmOperator *op, wmEvent *event)
1382 if(event->type==EVT_ACTIONZONE) {
1383 sActionzoneData *sad= event->customdata;
1385 if(sad->modifier>0) {
1386 return OPERATOR_PASS_THROUGH;
1389 /* verify *sad itself */
1390 if(sad==NULL || sad->sa1==NULL || sad->sa2==NULL)
1391 return OPERATOR_PASS_THROUGH;
1393 /* is this our *sad? if areas equal it should be passed on */
1394 if(sad->sa1==sad->sa2)
1395 return OPERATOR_PASS_THROUGH;
1397 /* prepare operator state vars */
1398 RNA_int_set(op->ptr, "x1", sad->x);
1399 RNA_int_set(op->ptr, "y1", sad->y);
1400 RNA_int_set(op->ptr, "x2", event->x);
1401 RNA_int_set(op->ptr, "y2", event->y);
1403 if(!area_join_init(C, op))
1404 return OPERATOR_PASS_THROUGH;
1406 /* add temp handler */
1407 WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
1409 return OPERATOR_RUNNING_MODAL;
1412 return OPERATOR_PASS_THROUGH;
1415 static int area_join_cancel(bContext *C, wmOperator *op)
1417 sAreaJoinData *jd = (sAreaJoinData *)op->customdata;
1420 jd->sa1->flag &= ~AREA_FLAG_DRAWJOINFROM;
1421 jd->sa1->flag &= ~AREA_FLAG_DRAWJOINTO;
1424 jd->sa2->flag &= ~AREA_FLAG_DRAWJOINFROM;
1425 jd->sa2->flag &= ~AREA_FLAG_DRAWJOINTO;
1428 WM_event_add_notifier(C, NC_WINDOW, NULL);
1430 area_join_exit(C, op);
1432 return OPERATOR_CANCELLED;
1435 /* modal callback while selecting area (space) that will be removed */
1436 static int area_join_modal(bContext *C, wmOperator *op, wmEvent *event)
1438 bScreen *sc= CTX_wm_screen(C);
1439 sAreaJoinData *jd = (sAreaJoinData *)op->customdata;
1441 /* execute the events */
1442 switch(event->type) {
1446 ScrArea *sa = screen_areahascursor(sc, event->x, event->y);
1450 if (jd->sa1 != sa) {
1451 dir = area_getorientation(sc, jd->sa1, sa);
1453 if (jd->sa2) jd->sa2->flag &= ~AREA_FLAG_DRAWJOINTO;
1455 jd->sa2->flag |= AREA_FLAG_DRAWJOINTO;
1458 /* we are not bordering on the previously selected area
1459 we check if area has common border with the one marked for removal
1460 in this case we can swap areas.
1462 dir = area_getorientation(sc, sa, jd->sa2);
1464 if (jd->sa1) jd->sa1->flag &= ~AREA_FLAG_DRAWJOINFROM;
1465 if (jd->sa2) jd->sa2->flag &= ~AREA_FLAG_DRAWJOINTO;
1468 if (jd->sa1) jd->sa1->flag |= AREA_FLAG_DRAWJOINFROM;
1469 if (jd->sa2) jd->sa2->flag |= AREA_FLAG_DRAWJOINTO;
1472 if (jd->sa2) jd->sa2->flag &= ~AREA_FLAG_DRAWJOINTO;
1476 WM_event_add_notifier(C, NC_WINDOW, NULL);
1479 /* we are back in the area previously selected for keeping
1480 * we swap the areas if possible to allow user to choose */
1481 if (jd->sa2 != NULL) {
1482 if (jd->sa1) jd->sa1->flag &= ~AREA_FLAG_DRAWJOINFROM;
1483 if (jd->sa2) jd->sa2->flag &= ~AREA_FLAG_DRAWJOINTO;
1486 if (jd->sa1) jd->sa1->flag |= AREA_FLAG_DRAWJOINFROM;
1487 if (jd->sa2) jd->sa2->flag |= AREA_FLAG_DRAWJOINTO;
1488 dir = area_getorientation(sc, jd->sa1, jd->sa2);
1490 printf("oops, didn't expect that!\n");
1494 dir = area_getorientation(sc, jd->sa1, sa);
1496 if (jd->sa2) jd->sa2->flag &= ~AREA_FLAG_DRAWJOINTO;
1498 jd->sa2->flag |= AREA_FLAG_DRAWJOINTO;
1501 WM_event_add_notifier(C, NC_WINDOW, NULL);
1508 area_join_apply(C, op);
1509 WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL);
1510 area_join_exit(C, op);
1511 return OPERATOR_FINISHED;
1516 return area_join_cancel(C, op);
1519 return OPERATOR_RUNNING_MODAL;
1522 /* Operator for joining two areas (space types) */
1523 void SCREEN_OT_area_join(wmOperatorType *ot)
1526 ot->name= "Join area";
1527 ot->idname= "SCREEN_OT_area_join";
1530 ot->exec= area_join_exec;
1531 ot->invoke= area_join_invoke;
1532 ot->modal= area_join_modal;
1534 ot->poll= ED_operator_areaactive;
1537 RNA_def_int(ot->srna, "x1", -100, INT_MIN, INT_MAX, "X 1", "", INT_MIN, INT_MAX);
1538 RNA_def_int(ot->srna, "y1", -100, INT_MIN, INT_MAX, "Y 1", "", INT_MIN, INT_MAX);
1539 RNA_def_int(ot->srna, "x2", -100, INT_MIN, INT_MAX, "X 2", "", INT_MIN, INT_MAX);
1540 RNA_def_int(ot->srna, "y2", -100, INT_MIN, INT_MAX, "Y 2", "", INT_MIN, INT_MAX);
1543 /* ************** repeat last operator ***************************** */
1545 static int repeat_last_exec(bContext *C, wmOperator *op)
1547 wmOperator *lastop= CTX_wm_manager(C)->operators.last;
1550 WM_operator_repeat(C, lastop);
1552 return OPERATOR_CANCELLED;
1555 void SCREEN_OT_repeat_last(wmOperatorType *ot)
1558 ot->name= "Repeat Last";
1559 ot->idname= "SCREEN_OT_repeat_last";
1562 ot->exec= repeat_last_exec;
1564 ot->poll= ED_operator_screenactive;
1568 static int repeat_history_invoke(bContext *C, wmOperator *op, wmEvent *event)
1570 wmWindowManager *wm= CTX_wm_manager(C);
1575 items= BLI_countlist(&wm->operators);
1577 return OPERATOR_CANCELLED;
1579 head= uiPupMenuBegin(op->type->name, 0);
1581 for (i=items-1, lastop= wm->operators.last; lastop; lastop= lastop->prev, i--)
1582 uiMenuItemIntO(head, lastop->type->name, 0, op->type->idname, "index", i);
1584 uiPupMenuEnd(C, head);
1586 return OPERATOR_CANCELLED;
1589 static int repeat_history_exec(bContext *C, wmOperator *op)
1591 wmWindowManager *wm= CTX_wm_manager(C);
1593 op= BLI_findlink(&wm->operators, RNA_int_get(op->ptr, "index"));
1595 /* let's put it as last operator in list */
1596 BLI_remlink(&wm->operators, op);
1597 BLI_addtail(&wm->operators, op);
1599 WM_operator_repeat(C, op);
1602 return OPERATOR_FINISHED;
1605 void SCREEN_OT_repeat_history(wmOperatorType *ot)
1608 ot->name= "Repeat History";
1609 ot->idname= "SCREEN_OT_repeat_history";
1612 ot->invoke= repeat_history_invoke;
1613 ot->exec= repeat_history_exec;
1615 ot->poll= ED_operator_screenactive;
1617 RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "", 0, 1000);
1620 /* ********************** redo operator ***************************** */
1622 static void redo_last_cb(bContext *C, void *arg_op, void *arg2)
1624 wmOperator *lastop= arg_op;
1628 WM_operator_repeat(C, lastop);
1633 static uiBlock *ui_block_create_redo_last(bContext *C, ARegion *ar, void *arg_op)
1635 wmWindowManager *wm= CTX_wm_manager(C);
1636 wmOperator *op= arg_op;
1641 block= uiBeginBlock(C, ar, "redo_last_popup", UI_EMBOSS, UI_HELV);
1642 uiBlockClearFlag(block, UI_BLOCK_LOOP);
1643 uiBlockSetFlag(block, UI_BLOCK_KEEP_OPEN|UI_BLOCK_RET_1);
1644 uiBlockSetFunc(block, redo_last_cb, arg_op, NULL);
1646 if(!op->properties) {
1647 IDPropertyTemplate val = {0};
1648 op->properties= IDP_New(IDP_GROUP, val, "wmOperatorProperties");
1651 RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr);
1652 height= uiDefAutoButsRNA(C, block, &ptr);
1654 uiPopupBoundsBlock(block, 4.0f, 0, 0);
1655 uiEndBlock(C, block);
1660 static int redo_last_invoke(bContext *C, wmOperator *op, wmEvent *event)
1662 wmWindowManager *wm= CTX_wm_manager(C);
1665 /* only for operators that are registered and did an undo push */
1666 for(lastop= wm->operators.last; lastop; lastop= lastop->prev)
1667 if((lastop->type->flag & OPTYPE_REGISTER) && (lastop->type->flag & OPTYPE_UNDO))
1671 return OPERATOR_CANCELLED;
1673 uiPupBlock(C, ui_block_create_redo_last, lastop);
1675 return OPERATOR_CANCELLED;
1678 void SCREEN_OT_redo_last(wmOperatorType *ot)
1681 ot->name= "Redo Last";
1682 ot->idname= "SCREEN_OT_redo_last";
1685 ot->invoke= redo_last_invoke;
1687 ot->poll= ED_operator_screenactive;
1690 /* ************** region split operator ***************************** */
1692 /* insert a region in the area region list */
1693 static int region_split_exec(bContext *C, wmOperator *op)
1695 ARegion *ar= CTX_wm_region(C);
1697 if(ar->regiontype==RGN_TYPE_HEADER)
1698 BKE_report(op->reports, RPT_ERROR, "Cannot split header");
1699 else if(ar->alignment==RGN_ALIGN_QSPLIT)
1700 BKE_report(op->reports, RPT_ERROR, "Cannot split further");
1702 ScrArea *sa= CTX_wm_area(C);
1703 ARegion *newar= BKE_area_region_copy(sa->type, ar);
1704 int dir= RNA_enum_get(op->ptr, "type");
1706 BLI_insertlinkafter(&sa->regionbase, ar, newar);
1708 newar->alignment= ar->alignment;
1711 ar->alignment= RGN_ALIGN_HSPLIT;
1713 ar->alignment= RGN_ALIGN_VSPLIT;
1715 WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL);
1718 return OPERATOR_FINISHED;
1721 void SCREEN_OT_region_split(wmOperatorType *ot)
1724 ot->name= "Split Region";
1725 ot->idname= "SCREEN_OT_region_split";
1728 ot->invoke= WM_menu_invoke;
1729 ot->exec= region_split_exec;
1730 ot->poll= ED_operator_areaactive;
1732 RNA_def_enum(ot->srna, "type", prop_direction_items, 'h', "Direction", "");
1735 /* ************** region four-split operator ***************************** */
1737 /* insert a region in the area region list */
1738 static int region_foursplit_exec(bContext *C, wmOperator *op)
1740 ARegion *ar= CTX_wm_region(C);
1743 if(ar->regiontype!=RGN_TYPE_WINDOW)
1744 BKE_report(op->reports, RPT_ERROR, "Only window region can be 4-splitted");
1745 else if(ar->alignment==RGN_ALIGN_QSPLIT) {
1746 ScrArea *sa= CTX_wm_area(C);
1749 /* keep current region */
1752 if(sa->spacetype==SPACE_VIEW3D) {
1753 RegionView3D *rv3d= ar->regiondata;
1755 rv3d->rflag &= ~RV3D_CLIPPING;
1758 for(ar= sa->regionbase.first; ar; ar= arn) {
1760 if(ar->alignment==RGN_ALIGN_QSPLIT) {
1761 ED_region_exit(C, ar);
1762 BKE_area_region_free(sa->type, ar);
1763 BLI_remlink(&sa->regionbase, ar);
1767 WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL);
1770 BKE_report(op->reports, RPT_ERROR, "Only last region can be 4-splitted");
1772 ScrArea *sa= CTX_wm_area(C);
1776 ar->alignment= RGN_ALIGN_QSPLIT;
1778 for(count=0; count<3; count++) {
1779 newar= BKE_area_region_copy(sa->type, ar);
1780 BLI_addtail(&sa->regionbase, newar);
1783 /* lock views and set them */
1784 if(sa->spacetype==SPACE_VIEW3D) {
1787 rv3d= ar->regiondata;
1788 rv3d->viewlock= RV3D_LOCKED; rv3d->view= V3D_VIEW_FRONT; rv3d->persp= V3D_ORTHO;
1791 rv3d= ar->regiondata;
1792 rv3d->viewlock= RV3D_LOCKED; rv3d->view= V3D_VIEW_TOP; rv3d->persp= V3D_ORTHO;
1795 rv3d= ar->regiondata;
1796 rv3d->viewlock= RV3D_LOCKED; rv3d->view= V3D_VIEW_RIGHT; rv3d->persp= V3D_ORTHO;
1799 rv3d= ar->regiondata;
1800 rv3d->view= V3D_VIEW_CAMERA; rv3d->persp= V3D_CAMOB;
1803 WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL);
1807 return OPERATOR_FINISHED;
1810 void SCREEN_OT_region_foursplit(wmOperatorType *ot)
1813 ot->name= "Split Region in 4 Parts";
1814 ot->idname= "SCREEN_OT_region_foursplit";
1817 ot->invoke= WM_operator_confirm;
1818 ot->exec= region_foursplit_exec;
1819 ot->poll= ED_operator_areaactive;
1820 ot->flag= OPTYPE_REGISTER;
1825 /* ************** region flip operator ***************************** */
1827 /* flip a region alignment */
1828 static int region_flip_exec(bContext *C, wmOperator *op)
1830 ARegion *ar= CTX_wm_region(C);
1832 if(ar->alignment==RGN_ALIGN_TOP)
1833 ar->alignment= RGN_ALIGN_BOTTOM;
1834 else if(ar->alignment==RGN_ALIGN_BOTTOM)
1835 ar->alignment= RGN_ALIGN_TOP;
1836 else if(ar->alignment==RGN_ALIGN_LEFT)
1837 ar->alignment= RGN_ALIGN_RIGHT;
1838 else if(ar->alignment==RGN_ALIGN_RIGHT)
1839 ar->alignment= RGN_ALIGN_LEFT;
1841 WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL);
1842 printf("executed region flip\n");
1844 return OPERATOR_FINISHED;
1847 static void testfunc(bContext *C, void *argv, int arg)
1849 printf("arg %d\n", arg);
1852 static void newlevel1(bContext *C, uiMenuItem *head, void *arg)
1854 uiMenuFunc(head, testfunc, NULL);
1856 uiMenuItemVal(head, "First", ICON_PROP_ON, 1);
1857 uiMenuItemVal(head, "Second", ICON_PROP_CON, 2);
1858 uiMenuItemVal(head, "Third", ICON_SMOOTHCURVE, 3);
1859 uiMenuItemVal(head, "Fourth", ICON_SHARPCURVE, 4);
1862 static int testing123(bContext *C, wmOperator *op, wmEvent *event)
1864 uiMenuItem *head= uiPupMenuBegin("Hello world", 0);
1866 uiMenuContext(head, WM_OP_EXEC_DEFAULT);
1867 uiMenuItemO(head, ICON_PROP_ON, "SCREEN_OT_region_flip");
1868 uiMenuItemO(head, ICON_PROP_CON, "SCREEN_OT_screen_full_area");
1869 uiMenuItemO(head, ICON_SMOOTHCURVE, "SCREEN_OT_region_foursplit");
1870 uiMenuLevel(head, "Submenu", newlevel1);
1872 uiPupMenuEnd(C, head);
1874 /* this operator is only for a menu, not used further */
1875 return OPERATOR_CANCELLED;
1878 void SCREEN_OT_region_flip(wmOperatorType *ot)
1881 ot->name= "Flip Region";
1882 ot->idname= "SCREEN_OT_region_flip";
1885 ot->invoke= testing123; // XXX WM_operator_confirm;
1886 ot->exec= region_flip_exec;
1888 ot->poll= ED_operator_areaactive;
1889 ot->flag= OPTYPE_REGISTER;
1891 RNA_def_int(ot->srna, "test", 0, INT_MIN, INT_MAX, "test", "", INT_MIN, INT_MAX);
1895 /* ****************** anim player, typically with timer ***************** */
1897 static int screen_animation_play(bContext *C, wmOperator *op, wmEvent *event)
1899 bScreen *screen= CTX_wm_screen(C);
1901 if(screen->animtimer==event->customdata) {
1902 Scene *scene= CTX_data_scene(C);
1904 if(scene->audio.flag & AUDIO_SYNC) {
1905 wmTimer *wt= screen->animtimer;
1906 int step = floor(wt->duration * FPS);
1907 scene->r.cfra += step;
1908 wt->duration -= ((float)step)/FPS;
1913 if (scene->r.psfra) {
1914 if(scene->r.cfra > scene->r.pefra)
1915 scene->r.cfra= scene->r.psfra;
1918 if(scene->r.cfra > scene->r.efra)
1919 scene->r.cfra= scene->r.sfra;
1922 WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
1924 return OPERATOR_FINISHED;
1926 return OPERATOR_PASS_THROUGH;
1929 void SCREEN_OT_animation_play(wmOperatorType *ot)
1932 ot->name= "Animation player";
1933 ot->idname= "SCREEN_OT_animation_play";
1936 ot->invoke= screen_animation_play;
1938 ot->poll= ED_operator_screenactive;
1942 /* ************** border select operator (template) ***************************** */
1944 /* operator state vars used: (added by default WM callbacks)
1948 customdata: the wmGesture pointer
1952 exec() has to be filled in by user
1954 invoke() default WM function
1957 modal() default WM function
1958 accept modal events while doing it, calls exec(), handles ESC and border drawing
1960 poll() has to be filled in by user for context
1963 static int border_select_do(bContext *C, wmOperator *op)
1965 int event_type= RNA_int_get(op->ptr, "event_type");
1967 if(event_type==LEFTMOUSE)
1968 printf("border select do select\n");
1969 else if(event_type==RIGHTMOUSE)
1970 printf("border select deselect\n");
1972 printf("border select do something\n");
1977 void SCREEN_OT_border_select(wmOperatorType *ot)
1980 ot->name= "Border select";
1981 ot->idname= "SCREEN_OT_border_select";
1984 ot->exec= border_select_do;
1985 ot->invoke= WM_border_select_invoke;
1986 ot->modal= WM_border_select_modal;
1988 ot->poll= ED_operator_areaactive;
1991 RNA_def_int(ot->srna, "event_type", 0, INT_MIN, INT_MAX, "Event Type", "", INT_MIN, INT_MAX);
1992 RNA_def_int(ot->srna, "xmin", 0, INT_MIN, INT_MAX, "X Min", "", INT_MIN, INT_MAX);
1993 RNA_def_int(ot->srna, "xmax", 0, INT_MIN, INT_MAX, "X Max", "", INT_MIN, INT_MAX);
1994 RNA_def_int(ot->srna, "ymin", 0, INT_MIN, INT_MAX, "Y Min", "", INT_MIN, INT_MAX);
1995 RNA_def_int(ot->srna, "ymax", 0, INT_MIN, INT_MAX, "Y Max", "", INT_MIN, INT_MAX);
2000 /* ****************************** render invoking ***************** */
2002 /* set callbacks, exported to sequence render too.
2003 Only call in foreground (UI) renders. */
2005 /* returns biggest area that is not uv/image editor. Note that it uses buttons */
2006 /* window as the last possible alternative. */
2007 static ScrArea *biggest_non_image_area(bContext *C)
2009 bScreen *sc= CTX_wm_screen(C);
2010 ScrArea *sa, *big= NULL;
2011 int size, maxsize= 0, bwmaxsize= 0;
2014 for(sa= sc->areabase.first; sa; sa= sa->next) {
2015 if(sa->winx > 10 && sa->winy > 10) {
2016 size= sa->winx*sa->winy;
2017 if(sa->spacetype == SPACE_BUTS) {
2018 if(foundwin == 0 && size > bwmaxsize) {
2023 else if(sa->spacetype != SPACE_IMAGE && size > maxsize) {
2034 static ScrArea *biggest_area(bContext *C)
2036 bScreen *sc= CTX_wm_screen(C);
2037 ScrArea *sa, *big= NULL;
2038 int size, maxsize= 0;
2040 for(sa= sc->areabase.first; sa; sa= sa->next) {
2041 size= sa->winx*sa->winy;
2042 if(size > maxsize) {
2051 static ScrArea *find_area_showing_r_result(bContext *C)
2053 bScreen *sc= CTX_wm_screen(C);
2057 /* find an imagewindow showing render result */
2058 for(sa=sc->areabase.first; sa; sa= sa->next) {
2059 if(sa->spacetype==SPACE_IMAGE) {
2060 sima= sa->spacedata.first;
2061 if(sima->image && sima->image->type==IMA_TYPE_R_RESULT)
2068 static void screen_set_image_output(bContext *C)
2073 sa= find_area_showing_r_result(C);
2076 /* find largest open non-image area */
2077 sa= biggest_non_image_area(C);
2079 ED_area_newspace(C, sa, SPACE_IMAGE);
2080 sima= sa->spacedata.first;
2082 /* makes ESC go back to prev space */
2083 sima->flag |= SI_PREVSPACE;
2086 /* use any area of decent size */
2087 sa= biggest_area(C);
2088 if(sa->spacetype!=SPACE_IMAGE) {
2089 // XXX newspace(sa, SPACE_IMAGE);
2090 sima= sa->spacedata.first;
2092 /* makes ESC go back to prev space */
2093 sima->flag |= SI_PREVSPACE;
2098 sima= sa->spacedata.first;
2100 /* get the correct image, and scale it */
2101 sima->image= BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result");
2103 if(G.displaymode==2) { // XXX
2105 sima->flag |= SI_FULLWINDOW;
2107 ed_screen_fullarea(C, sa);
2113 /* executes blocking render */
2114 static int screen_render_exec(bContext *C, wmOperator *op)
2116 Scene *scene= CTX_data_scene(C);
2117 Render *re= RE_GetRender(scene->id.name);
2120 re= RE_NewRender(scene->id.name);
2122 RE_test_break_cb(re, NULL, (int (*)(void *)) blender_test_break);
2124 if(RNA_boolean_get(op->ptr, "anim"))
2125 RE_BlenderAnim(re, scene, scene->r.sfra, scene->r.efra, scene->frame_step);
2127 RE_BlenderFrame(re, scene, scene->r.cfra);
2129 // no redraw needed, we leave state as we entered it
2130 ED_update_for_newframe(C, 1);
2132 WM_event_add_notifier(C, NC_SCENE|ND_RENDER_RESULT, scene);
2134 return OPERATOR_FINISHED;
2137 typedef struct RenderJob {
2148 static void render_freejob(void *rjv)
2155 /* called inside thread! */
2156 static void image_rect_update(void *rjv, RenderResult *rr, volatile rcti *renrect)
2160 float x1, y1, *rectf= NULL;
2161 int ymin, ymax, xmin, xmax;
2165 ibuf= BKE_image_get_ibuf(rj->image, &rj->iuser);
2166 if(ibuf==NULL) return;
2168 /* if renrect argument, we only refresh scanlines */
2170 /* if ymax==recty, rendering of layer is ready, we should not draw, other things happen... */
2171 if(rr->renlay==NULL || renrect->ymax>=rr->recty)
2174 /* xmin here is first subrect x coord, xmax defines subrect width */
2175 xmin = renrect->xmin + rr->crop;
2176 xmax = renrect->xmax - xmin - rr->crop;
2179 ymin= renrect->ymin + rr->crop;
2180 ymax= renrect->ymax - ymin - rr->crop;
2183 renrect->ymin= renrect->ymax;
2187 xmin = ymin = rr->crop;
2188 xmax = rr->rectx - 2*rr->crop;
2189 ymax = rr->recty - 2*rr->crop;
2192 /* xmin ymin is in tile coords. transform to ibuf */
2193 rxmin= rr->tilerect.xmin + xmin;
2194 if(rxmin >= ibuf->x) return;
2195 rymin= rr->tilerect.ymin + ymin;
2196 if(rymin >= ibuf->y) return;
2198 if(rxmin + xmax > ibuf->x)
2199 xmax= ibuf->x - rxmin;
2200 if(rymin + ymax > ibuf->y)
2201 ymax= ibuf->y - rymin;
2203 if(xmax < 1 || ymax < 1) return;
2205 /* find current float rect for display, first case is after composit... still weak */
2212 if(rr->renlay==NULL || rr->renlay->rectf==NULL) return;
2213 rectf= rr->renlay->rectf;
2216 if(rectf==NULL) return;
2218 rectf+= 4*(rr->rectx*ymin + xmin);
2219 rectc= (char *)(ibuf->rect + ibuf->x*rymin + rxmin);
2221 for(y1= 0; y1<ymax; y1++) {
2225 /* XXX temp. because crop offset */
2226 if( rectc >= (char *)(ibuf->rect)) {
2227 for(x1= 0; x1<xmax; x1++, rf += 4, rc+=4) {
2228 rc[0]= FTOCHAR(rf[0]);
2229 rc[1]= FTOCHAR(rf[1]);
2230 rc[2]= FTOCHAR(rf[2]);
2231 rc[3]= FTOCHAR(rf[3]);
2234 rectf += 4*rr->rectx;
2238 /* make jobs timer to send notifier */
2239 *(rj->do_update)= 1;
2242 static void render_startjob(void *rjv, short *stop, short *do_update)
2247 rj->do_update= do_update;
2250 RE_BlenderAnim(rj->re, rj->scene, rj->scene->r.sfra, rj->scene->r.efra, rj->scene->frame_step);
2252 RE_BlenderFrame(rj->re, rj->scene, rj->scene->r.cfra);
2255 /* called by render, check job 'stop' value or the global */
2256 static int render_breakjob(void *rjv)
2262 if(rj->stop && *(rj->stop))
2268 static int screen_render_modal(bContext *C, wmOperator *op, wmEvent *event)
2270 /* no running blender, remove handler and pass through */
2271 if(0==WM_jobs_test(CTX_wm_manager(C), CTX_data_scene(C)))
2272 return OPERATOR_FINISHED|OPERATOR_PASS_THROUGH;
2274 /* running render */
2275 switch (event->type) {
2277 return OPERATOR_RUNNING_MODAL;
2280 return OPERATOR_PASS_THROUGH;
2283 /* using context, starts job */
2284 static int screen_render_invoke(bContext *C, wmOperator *op, wmEvent *event)
2286 /* new render clears all callbacks */
2287 Scene *scene= CTX_data_scene(C);
2293 /* only one job at a time */
2294 if(WM_jobs_test(CTX_wm_manager(C), scene))
2295 return OPERATOR_CANCELLED;
2297 /* handle UI stuff */
2300 /* flush multires changes (for sculpt) */
2301 multires_force_update(CTX_data_active_object(C));
2303 // get editmode results
2305 // get view3d layer, local layer, make this nice api call to render
2308 /* ensure at least 1 area shows result */
2309 screen_set_image_output(C);
2311 /* job custom data */
2312 rj= MEM_callocN(sizeof(RenderJob), "render job");
2314 rj->win= CTX_wm_window(C);
2315 rj->anim= RNA_boolean_get(op->ptr, "anim");
2316 rj->iuser.scene= scene;
2320 steve= WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene);
2321 WM_jobs_customdata(steve, rj, render_freejob);
2322 WM_jobs_timer(steve, 0.2, NC_SCENE|ND_RENDER_RESULT, 0);
2323 WM_jobs_callbacks(steve, render_startjob, NULL, NULL);
2325 /* get a render result image, and make sure it is empty */
2326 ima= BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result");
2327 BKE_image_signal(ima, NULL, IMA_SIGNAL_FREE);
2330 /* setup new render */
2331 re= RE_NewRender(scene->id.name);
2332 RE_test_break_cb(re, rj, render_breakjob);
2333 RE_display_draw_cb(re, rj, image_rect_update);
2337 // BKE_report in render!
2338 // RE_error_cb(re, error_cb);
2340 WM_jobs_start(steve);
2345 WM_event_add_notifier(C, NC_SCENE|ND_RENDER_RESULT, scene);
2347 /* add modal handler for ESC */
2348 WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
2350 return OPERATOR_RUNNING_MODAL;
2354 /* contextual render, using current scene, view3d? */
2355 void SCREEN_OT_render(wmOperatorType *ot)
2359 ot->idname= "SCREEN_OT_render";
2362 ot->invoke= screen_render_invoke;
2363 ot->modal= screen_render_modal;
2364 ot->exec= screen_render_exec;
2366 ot->poll= ED_operator_screenactive;
2368 RNA_def_int(ot->srna, "layers", 0, 0, INT_MAX, "Layers", "", 0, INT_MAX);
2369 RNA_def_boolean(ot->srna, "anim", 0, "Animation", "");
2372 /* *********************** cancel render viewer *************** */
2374 static int render_view_cancel_exec(bContext *C, wmOperator *unused)
2376 ScrArea *sa= CTX_wm_area(C);
2377 SpaceImage *sima= sa->spacedata.first;
2379 if(sima->flag & SI_PREVSPACE) {
2380 sima->flag &= ~SI_PREVSPACE;
2382 if(sima->flag & SI_FULLWINDOW) {
2383 sima->flag &= ~SI_FULLWINDOW;
2384 ED_screen_full_prevspace(C);
2387 ED_area_prevspace(C);
2389 else if(sima->flag & SI_FULLWINDOW) {
2390 sima->flag &= ~SI_FULLWINDOW;
2391 ed_screen_fullarea(C, sa);
2394 return OPERATOR_FINISHED;
2397 void SCREEN_OT_render_view_cancel(struct wmOperatorType *ot)
2400 ot->name= "Cancel Render View";
2401 ot->idname= "SCREEN_OT_render_view_cancel";
2404 ot->exec= render_view_cancel_exec;
2405 ot->poll= ED_operator_image_active;
2409 /* **************** Assigning operatortypes to global list, adding handlers **************** */
2411 /* called in spacetypes.c */
2412 void ED_operatortypes_screen(void)
2414 /* generic UI stuff */
2415 WM_operatortype_append(SCREEN_OT_actionzone);
2416 WM_operatortype_append(SCREEN_OT_repeat_last);
2417 WM_operatortype_append(SCREEN_OT_repeat_history);
2418 WM_operatortype_append(SCREEN_OT_redo_last);
2421 WM_operatortype_append(SCREEN_OT_area_move);
2422 WM_operatortype_append(SCREEN_OT_area_split);
2423 WM_operatortype_append(SCREEN_OT_area_join);
2424 WM_operatortype_append(SCREEN_OT_area_dupli);
2425 WM_operatortype_append(SCREEN_OT_area_swap);
2426 WM_operatortype_append(SCREEN_OT_region_split);
2427 WM_operatortype_append(SCREEN_OT_region_foursplit);
2428 WM_operatortype_append(SCREEN_OT_region_flip);
2429 WM_operatortype_append(SCREEN_OT_screen_set);
2430 WM_operatortype_append(SCREEN_OT_screen_full_area);
2431 WM_operatortype_append(SCREEN_OT_screenshot);
2432 WM_operatortype_append(SCREEN_OT_screencast);
2435 WM_operatortype_append(SCREEN_OT_frame_offset);
2436 WM_operatortype_append(SCREEN_OT_animation_play);
2439 WM_operatortype_append(SCREEN_OT_render);
2440 WM_operatortype_append(SCREEN_OT_render_view_cancel);
2442 /* tools shared by more space types */
2443 WM_operatortype_append(ED_OT_undo);
2444 WM_operatortype_append(ED_OT_redo);
2448 /* called in spacetypes.c */
2449 void ED_keymap_screen(wmWindowManager *wm)
2451 ListBase *keymap= WM_keymap_listbase(wm, "Screen", 0, 0);
2453 /* standard timers */
2454 WM_keymap_add_item(keymap, "SCREEN_OT_animation_play", TIMER0, KM_ANY, KM_ANY, 0);
2456 RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_actionzone", LEFTMOUSE, KM_PRESS, 0, 0)->ptr, "modifier", 0);
2457 RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_actionzone", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0)->ptr, "modifier", 1);
2458 RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_actionzone", LEFTMOUSE, KM_PRESS, KM_ALT, 0)->ptr, "modifier", 2);
2461 WM_keymap_verify_item(keymap, "SCREEN_OT_area_move", LEFTMOUSE, KM_PRESS, 0, 0);
2462 WM_keymap_verify_item(keymap, "SCREEN_OT_area_split", EVT_ACTIONZONE, 0, 0, 0);
2463 WM_keymap_verify_item(keymap, "SCREEN_OT_area_join", EVT_ACTIONZONE, 0, 0, 0);
2464 WM_keymap_verify_item(keymap, "SCREEN_OT_area_dupli", EVT_ACTIONZONE, 0, KM_SHIFT, 0);
2465 WM_keymap_verify_item(keymap, "SCREEN_OT_area_swap", EVT_ACTIONZONE, 0, KM_ALT, 0);
2466 RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_screen_set", RIGHTARROWKEY, KM_PRESS, KM_CTRL, 0)->ptr, "delta", 1);
2467 RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_screen_set", LEFTARROWKEY, KM_PRESS, KM_CTRL, 0)->ptr, "delta", -1);
2468 WM_keymap_add_item(keymap, "SCREEN_OT_screen_full_area", UPARROWKEY, KM_PRESS, KM_CTRL, 0);
2469 WM_keymap_add_item(keymap, "SCREEN_OT_screen_full_area", DOWNARROWKEY, KM_PRESS, KM_CTRL, 0);
2470 WM_keymap_add_item(keymap, "SCREEN_OT_screen_full_area", SPACEKEY, KM_PRESS, KM_CTRL, 0);
2471 WM_keymap_add_item(keymap, "SCREEN_OT_screenshot", F3KEY, KM_PRESS, KM_CTRL, 0);
2472 WM_keymap_add_item(keymap, "SCREEN_OT_screencast", F3KEY, KM_PRESS, KM_ALT, 0);
2475 WM_keymap_add_item(keymap, "SCREEN_OT_region_split", SKEY, KM_PRESS, KM_CTRL|KM_ALT, 0);
2476 WM_keymap_add_item(keymap, "SCREEN_OT_region_foursplit", SKEY, KM_PRESS, KM_CTRL|KM_ALT|KM_SHIFT, 0);
2478 WM_keymap_verify_item(keymap, "SCREEN_OT_repeat_history", F3KEY, KM_PRESS, 0, 0);
2479 WM_keymap_verify_item(keymap, "SCREEN_OT_repeat_last", F4KEY, KM_PRESS, 0, 0);
2480 WM_keymap_add_item(keymap, "SCREEN_OT_region_flip", F5KEY, KM_PRESS, 0, 0);
2481 WM_keymap_verify_item(keymap, "SCREEN_OT_redo_last", F6KEY, KM_PRESS, 0, 0);
2484 WM_keymap_add_item(keymap, "FILE_OT_exec", RETKEY, KM_PRESS, 0, 0);
2485 WM_keymap_add_item(keymap, "FILE_OT_cancel", ESCKEY, KM_PRESS, 0, 0);
2488 WM_keymap_add_item(keymap, "ED_OT_undo", ZKEY, KM_PRESS, KM_CTRL, 0);
2489 WM_keymap_add_item(keymap, "ED_OT_undo", ZKEY, KM_PRESS, KM_OSKEY, 0);
2490 WM_keymap_add_item(keymap, "ED_OT_redo", ZKEY, KM_PRESS, KM_SHIFT|KM_CTRL, 0);
2491 WM_keymap_add_item(keymap, "ED_OT_redo", ZKEY, KM_PRESS, KM_SHIFT|KM_OSKEY, 0);
2494 WM_keymap_add_item(keymap, "SCREEN_OT_render", F12KEY, KM_PRESS, 0, 0);
2495 WM_keymap_add_item(keymap, "SCREEN_OT_render_view_cancel", ESCKEY, KM_PRESS, 0, 0);
2498 keymap= WM_keymap_listbase(wm, "Frames", 0, 0);
2499 RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_offset", UPARROWKEY, KM_PRESS, 0, 0)->ptr, "delta", 10);
2500 RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_offset", DOWNARROWKEY, KM_PRESS, 0, 0)->ptr, "delta", -10);
2501 RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_offset", LEFTARROWKEY, KM_PRESS, 0, 0)->ptr, "delta", -1);
2502 RNA_int_set(WM_keymap_add_item(keymap, "SCREEN_OT_frame_offset", RIGHTARROWKEY, KM_PRESS, 0, 0)->ptr, "delta", 1);