diff options
Diffstat (limited to 'source/blender/windowmanager')
-rw-r--r-- | source/blender/windowmanager/CMakeLists.txt | 47 | ||||
-rw-r--r-- | source/blender/windowmanager/SConscript | 5 | ||||
-rw-r--r-- | source/blender/windowmanager/WM_api.h | 18 | ||||
-rw-r--r-- | source/blender/windowmanager/WM_types.h | 14 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm.c | 11 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_apple.c | 8 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_draw.c | 8 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_event_system.c | 88 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_files.c | 126 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_init_exit.c | 26 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_keymap.c | 16 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_operators.c | 855 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_window.c | 29 | ||||
-rw-r--r-- | source/blender/windowmanager/wm.h | 2 |
14 files changed, 791 insertions, 462 deletions
diff --git a/source/blender/windowmanager/CMakeLists.txt b/source/blender/windowmanager/CMakeLists.txt index 6f03928e1fc..20ac3ba7077 100644 --- a/source/blender/windowmanager/CMakeLists.txt +++ b/source/blender/windowmanager/CMakeLists.txt @@ -26,23 +26,26 @@ set(INC . - ../nodes - ../gpu ../blenfont - ../blenlib - ../makesdna - ../makesrna ../blenkernel - ../imbuf + ../blenlib ../blenloader ../editors/include + ../gpu + ../imbuf + ../makesdna + ../makesrna + ../nodes ../render/extern/include - ../../../intern/guardedalloc - ../../../intern/memutil + ../../gameengine/BlenderRoutines ../../../intern/elbeem/extern ../../../intern/ghost + ../../../intern/guardedalloc + ../../../intern/memutil ../../../intern/opennl/extern - ../../../source/gameengine/BlenderRoutines +) + +set(INC_SYS ${ZLIB_INCLUDE_DIRS} ${OPENGL_INCLUDE_DIR} ${GLEW_INCLUDE_PATH} @@ -50,7 +53,6 @@ set(INC set(SRC intern/wm.c - intern/wm_apple.c intern/wm_cursors.c intern/wm_dragdrop.c intern/wm_draw.c @@ -87,17 +89,26 @@ if(WITH_OPENCOLLADA) endif() if(WITH_CODEC_QUICKTIME) - list(APPEND INC ../quicktime ${QUICKTIME_INC}) + list(APPEND INC + ../quicktime + ) + list(APPEND INC_SYS + ${QUICKTIME_INCLUDE_DIRS} + ) add_definitions(-DWITH_QUICKTIME) endif() if(WITH_CODEC_FFMPEG) - list(APPEND INC ${FFMPEG_INC}) + list(APPEND INC_SYS + ${FFMPEG_INCLUDE_DIRS} + ) add_definitions(-DWITH_FFMPEG) endif() if(WITH_PYTHON) - list(APPEND INC ../python ${PYTHON_INCLUDE_DIRS}) + list(APPEND INC + ../python + ) add_definitions(-DWITH_PYTHON) if(WITH_PYTHON_SECURITY) @@ -109,12 +120,16 @@ if(WITH_GAMEENGINE) add_definitions(-DWITH_GAMEENGINE) endif() -if(WITH_COCOA) - list(REMOVE_ITEM SRC "${CMAKE_CURRENT_SOURCE_DIR}/intern/wm_apple.c") +if(APPLE) + if(NOT WITH_COCOA) + list(APPEND SRC + intern/wm_apple.c + ) + endif() endif() if(WITH_BUILDINFO) add_definitions(-DNAN_BUILDINFO) endif() -blender_add_lib_nolist(bf_windowmanager "${SRC}" "${INC}") +blender_add_lib_nolist(bf_windowmanager "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/windowmanager/SConscript b/source/blender/windowmanager/SConscript index f52ac8ba3cb..5b6e8b1ab30 100644 --- a/source/blender/windowmanager/SConscript +++ b/source/blender/windowmanager/SConscript @@ -1,5 +1,6 @@ #!/usr/bin/python Import ('env') +import os sources = env.Glob('intern/*.c') @@ -32,8 +33,8 @@ if env['OURPLATFORM'] == 'linux2': if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc'): incs += ' ' + env['BF_PTHREADS_INC'] -if env['WITH_GHOST_COCOA']: - sources.remove('intern/wm_apple.c') +if env['OURPLATFORM'] != 'darwin' or env['WITH_GHOST_COCOA']: + sources.remove('intern' + os.sep + 'wm_apple.c') if env['BF_BUILDINFO']: defs.append('NAN_BUILDINFO') diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 1b4fff8cd13..e6325e2101a 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -95,7 +95,7 @@ void WM_window_open_temp (struct bContext *C, struct rcti *position, int type); int WM_read_homefile_exec(struct bContext *C, struct wmOperator *op); int WM_read_homefile (struct bContext *C, struct ReportList *reports, short from_memory); int WM_write_homefile (struct bContext *C, struct wmOperator *op); -void WM_read_file (struct bContext *C, const char *name, struct ReportList *reports); +void WM_read_file (struct bContext *C, const char *filepath, struct ReportList *reports); int WM_write_file (struct bContext *C, const char *target, int fileflags, struct ReportList *reports, int copy); void WM_read_autosavefile(struct bContext *C); void WM_autosave_init (struct wmWindowManager *wm); @@ -216,7 +216,7 @@ int WM_operator_confirm_message(struct bContext *C, struct wmOperator *op, con /* operator api */ void WM_operator_free (struct wmOperator *op); -void WM_operator_stack_clear(struct bContext *C); +void WM_operator_stack_clear(struct wmWindowManager *wm); struct wmOperatorType *WM_operatortype_find(const char *idnamem, int quiet); struct wmOperatorType *WM_operatortype_first(void); @@ -247,6 +247,8 @@ void WM_operator_properties_gesture_border(struct wmOperatorType *ot, int exten void WM_operator_properties_gesture_straightline(struct wmOperatorType *ot, int cursor); void WM_operator_properties_select_all(struct wmOperatorType *ot); +wmOperator *WM_operator_last_redo(const struct bContext *C); + /* MOVE THIS SOMEWHERE ELSE */ #define SEL_TOGGLE 0 #define SEL_SELECT 1 @@ -270,20 +272,26 @@ void WM_operator_py_idname(char *to, const char *from); /* *************** menu types ******************** */ struct MenuType *WM_menutype_find(const char *idname, int quiet); int WM_menutype_add(struct MenuType* mt); +int WM_menutype_contains(struct MenuType* mt); void WM_menutype_freelink(struct MenuType* mt); void WM_menutype_free(void); /* default operator callbacks for border/circle/lasso */ int WM_border_select_invoke (struct bContext *C, struct wmOperator *op, struct wmEvent *event); int WM_border_select_modal (struct bContext *C, struct wmOperator *op, struct wmEvent *event); +int WM_border_select_cancel(struct bContext *C, struct wmOperator *op); int WM_gesture_circle_invoke(struct bContext *C, struct wmOperator *op, struct wmEvent *event); int WM_gesture_circle_modal(struct bContext *C, struct wmOperator *op, struct wmEvent *event); +int WM_gesture_circle_cancel(struct bContext *C, struct wmOperator *op); int WM_gesture_lines_invoke(struct bContext *C, struct wmOperator *op, struct wmEvent *event); int WM_gesture_lines_modal(struct bContext *C, struct wmOperator *op, struct wmEvent *event); +int WM_gesture_lines_cancel(struct bContext *C, struct wmOperator *op); int WM_gesture_lasso_invoke(struct bContext *C, struct wmOperator *op, struct wmEvent *event); int WM_gesture_lasso_modal(struct bContext *C, struct wmOperator *op, struct wmEvent *event); +int WM_gesture_lasso_cancel(struct bContext *C, struct wmOperator *op); int WM_gesture_straightline_invoke(struct bContext *C, struct wmOperator *op, struct wmEvent *event); int WM_gesture_straightline_modal(struct bContext *C, struct wmOperator *op, struct wmEvent *event); +int WM_gesture_straightline_cancel(struct bContext *C, struct wmOperator *op); /* default operator for arearegions, generates event */ void WM_OT_tweak_gesture(struct wmOperatorType *ot); @@ -293,12 +301,6 @@ struct wmGesture *WM_gesture_new(struct bContext *C, struct wmEvent *event, int void WM_gesture_end(struct bContext *C, struct wmGesture *gesture); void WM_gestures_remove(struct bContext *C); - /* radial control operator */ -int WM_radial_control_invoke(struct bContext *C, struct wmOperator *op, struct wmEvent *event); -int WM_radial_control_modal(struct bContext *C, struct wmOperator *op, struct wmEvent *event); -void WM_OT_radial_control_partial(struct wmOperatorType *ot); -void WM_radial_control_string(struct wmOperator *op, char str[], int maxlen); - /* fileselecting support */ void WM_event_add_fileselect(struct bContext *C, struct wmOperator *op); void WM_event_fileselect_event(struct bContext *C, void *ophandle, int eventval); diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index 8748703ad8e..49bd3ede37d 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -61,6 +61,10 @@ struct ImBuf; #define OPTYPE_MACRO 8 #define OPTYPE_GRAB_POINTER 16 /* */ #define OPTYPE_PRESET 32 /* show preset menu */ +#define OPTYPE_INTERNAL 64 /* some operators are mainly for internal use + * and don't make sense to be accessed from the + * search menu, even if poll() returns TRUE. + * currently only used for the search toolbox */ /* context to call operator in for WM_operator_name_call */ /* rna_ui.c contains EnumPropertyItem's of these, keep in sync */ @@ -335,8 +339,8 @@ typedef struct wmEvent { short type; /* event code itself (short, is also in keymap) */ short val; /* press, release, scrollvalue */ - short x, y; /* mouse pointer position, screen coord */ - short mval[2]; /* region mouse position, name convention pre 2.5 :) */ + int x, y; /* mouse pointer position, screen coord */ + int mval[2]; /* region mouse position, name convention pre 2.5 :) */ short unicode; /* future, ghost? */ char ascii; /* from ghost */ char pad; @@ -344,9 +348,9 @@ typedef struct wmEvent { /* previous state */ short prevtype; short prevval; - short prevx, prevy; + int prevx, prevy; double prevclicktime; - short prevclickx, prevclicky; + int prevclickx, prevclicky; /* modifier states */ short shift, ctrl, alt, oskey; /* oskey is apple or windowskey, value denotes order of pressed */ @@ -494,7 +498,7 @@ typedef struct wmDrag { struct ImBuf *imb; /* if no icon but imbuf should be drawn around cursor */ float scale; - short sx, sy; + int sx, sy; char opname[240]; /* FILE_MAX */ /* if set, draws operator name*/ } wmDrag; diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c index 424c13f089f..a535c0bc1f8 100644 --- a/source/blender/windowmanager/intern/wm.c +++ b/source/blender/windowmanager/intern/wm.c @@ -137,9 +137,8 @@ void wm_operator_register(bContext *C, wmOperator *op) } -void WM_operator_stack_clear(bContext *C) +void WM_operator_stack_clear(wmWindowManager *wm) { - wmWindowManager *wm= CTX_wm_manager(C); wmOperator *op; while((op= wm->operators.first)) { @@ -147,7 +146,7 @@ void WM_operator_stack_clear(bContext *C) WM_operator_free(op); } - WM_event_add_notifier(C, NC_WM|ND_HISTORY, NULL); + WM_main_add_notifier(NC_WM|ND_HISTORY, NULL); } /* ****************************************** */ @@ -176,6 +175,12 @@ int WM_menutype_add(MenuType* mt) return 1; } +/* inefficient but only used for tooltip code */ +int WM_menutype_contains(MenuType* mt) +{ + return (mt != NULL && BLI_findindex(&menutypes, mt) != -1); +} + void WM_menutype_freelink(MenuType* mt) { BLI_freelinkN(&menutypes, mt); diff --git a/source/blender/windowmanager/intern/wm_apple.c b/source/blender/windowmanager/intern/wm_apple.c index 083500420a4..7748efb6f64 100644 --- a/source/blender/windowmanager/intern/wm_apple.c +++ b/source/blender/windowmanager/intern/wm_apple.c @@ -30,8 +30,7 @@ * \ingroup wm */ - -#ifdef __APPLE__ +/* note, this file builds on apple-carbon only! */ #include "BKE_context.h" #include "BKE_global.h" @@ -137,8 +136,3 @@ void wm_set_apple_prefsize(int scr_x, int scr_y) G.windowstate= 0; } } - - -#endif /* __APPLE__ */ - - diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c index c94ad74be72..4fe82917705 100644 --- a/source/blender/windowmanager/intern/wm_draw.c +++ b/source/blender/windowmanager/intern/wm_draw.c @@ -816,11 +816,3 @@ void wm_draw_region_clear(wmWindow *win, ARegion *ar) win->screen->do_draw= 1; } -static void wm_draw_region_modified(wmWindow *win, ARegion *ar) -{ - int drawmethod= wm_automatic_draw_method(win); - - if(ELEM(drawmethod, USER_DRAW_OVERLAP, USER_DRAW_OVERLAP_FLIP)) - ED_region_tag_redraw(ar); -} - diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index feff0393b88..ce3830b059c 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -340,7 +340,7 @@ static int wm_handler_ui_call(bContext *C, wmEventHandler *handler, wmEvent *eve int is_wheel= ELEM(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE); int retval; - /* UI is quite agressive with swallowing events, like scrollwheel */ + /* UI is quite aggressive with swallowing events, like scrollwheel */ /* I realize this is not extremely nice code... when UI gets keymaps it can be maybe smarter */ if(do_wheel_ui==0) { if(is_wheel) @@ -661,6 +661,11 @@ static void wm_region_mouse_co(bContext *C, wmEvent *event) event->mval[0]= event->x - ar->winrct.xmin; event->mval[1]= event->y - ar->winrct.ymin; } + else { + /* these values are invalid (avoid odd behavior by relying on old mval values) */ + event->mval[0]= -1; + event->mval[1]= -1; + } } static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event, PointerRNA *properties, ReportList *reports, short poll_only) @@ -1284,16 +1289,23 @@ static int wm_handler_fileselect_call(bContext *C, ListBase *handlers, wmEventHa if (handler->op_area == NULL) { bScreen *screen = CTX_wm_screen(C); sa = (ScrArea *)screen->areabase.first; - } else + } + else { sa = handler->op_area; + } - if(event->val==EVT_FILESELECT_OPEN) - ED_area_newspace(C, sa, SPACE_FILE); - else - ED_screen_full_newspace(C, sa, SPACE_FILE); /* sets context */ - + if(event->val==EVT_FILESELECT_OPEN) { + ED_area_newspace(C, sa, SPACE_FILE); /* 'sa' is modified in-place */ + } + else { + sa= ED_screen_full_newspace(C, sa, SPACE_FILE); /* sets context */ + } + + /* note, getting the 'sa' back from the context causes a nasty bug where the newly created + * 'sa' != CTX_wm_area(C). removed the line below and set 'sa' in the 'if' above */ + /* sa = CTX_wm_area(C); */ + /* settings for filebrowser, sfile is not operator owner but sends events */ - sa = CTX_wm_area(C); sfile= (SpaceFile*)sa->spacedata.first; sfile->op= handler->op; @@ -1565,7 +1577,7 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers) * so check for mouse moves too. * note2: the first click event will be handled but still used to create a * double click event if clicking again quickly. - * If no double click events are found itwill fallback to a single click. + * If no double click events are found it will fallback to a single click. * So a double click event can result in 2 successive single click calls * if its not handled by the keymap - campbell */ if ( (ABS(event->x - win->eventstate->prevclickx)) <= 2 && @@ -1776,6 +1788,8 @@ void wm_event_do_handlers(bContext *C) /* MVC demands to not draw in event handlers... but we need to leave it for ogl selecting etc */ wm_window_make_drawable(C, win); + wm_region_mouse_co(C, event); + /* first we do priority handlers, modal + some limited keymaps */ action |= wm_handlers_do(C, event, &win->modalhandlers); @@ -1811,10 +1825,12 @@ void wm_event_do_handlers(bContext *C) if(wm_event_inside_i(event, &ar->winrct)) { CTX_wm_region_set(C, ar); + /* call even on non mouse events, since the */ + wm_region_mouse_co(C, event); + /* does polls for drop regions and checks uibuts */ /* need to be here to make sure region context is true */ if(ELEM(event->type, MOUSEMOVE, EVT_DROP)) { - wm_region_mouse_co(C, event); wm_drags_check_ops(C, event); } @@ -1834,9 +1850,10 @@ void wm_event_do_handlers(bContext *C) CTX_wm_region_set(C, NULL); - if((action & WM_HANDLER_BREAK) == 0) + if((action & WM_HANDLER_BREAK) == 0) { + wm_region_mouse_co(C, event); /* only invalidates event->mval in this case */ action |= wm_handlers_do(C, event, &sa->handlers); - + } CTX_wm_area_set(C, NULL); /* NOTE: do not escape on WM_HANDLER_BREAK, mousemove needs handled for previous area */ @@ -1848,6 +1865,8 @@ void wm_event_do_handlers(bContext *C) CTX_wm_area_set(C, area_event_inside(C, event->x, event->y)); CTX_wm_region_set(C, region_event_inside(C, event->x, event->y)); + wm_region_mouse_co(C, event); + action |= wm_handlers_do(C, event, &win->handlers); /* fileread case */ @@ -2293,7 +2312,7 @@ static void update_tablet_data(wmWindow *win, wmEvent *event) /* imperfect but probably usable... draw/enable drags to other windows */ static wmWindow *wm_event_cursor_other_windows(wmWindowManager *wm, wmWindow *win, wmEvent *evt) { - short mx= evt->x, my= evt->y; + int mx= evt->x, my= evt->y; if(wm->windows.first== wm->windows.last) return NULL; @@ -2310,8 +2329,8 @@ static wmWindow *wm_event_cursor_other_windows(wmWindowManager *wm, wmWindow *wi return NULL; /* to desktop space */ - mx+= win->posx; - my+= win->posy; + mx += (int)win->posx; + my += (int)win->posy; /* check other windows to see if it has mouse inside */ for(owin= wm->windows.first; owin; owin= owin->next) { @@ -2319,8 +2338,8 @@ static wmWindow *wm_event_cursor_other_windows(wmWindowManager *wm, wmWindow *wi if(owin!=win) { if(mx-owin->posx >= 0 && my-owin->posy >= 0 && mx-owin->posx <= owin->sizex && my-owin->posy <= owin->sizey) { - evt->x= mx-owin->posx; - evt->y= my-owin->posy; + evt->x= mx - (int)owin->posx; + evt->y= my - (int)owin->posy; return owin; } @@ -2346,18 +2365,11 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U if(win->active) { GHOST_TEventCursorData *cd= customdata; wmEvent *lastevent= win->queue.last; - -#if defined(__APPLE__) && defined(GHOST_COCOA) - //Cocoa already uses coordinates with y=0 at bottom, and returns inwindow coordinates on mouse moved event - evt->x= cd->x; - evt->y= cd->y; -#else int cx, cy; GHOST_ScreenToClient(win->ghostwin, cd->x, cd->y, &cx, &cy); evt->x= cx; evt->y= (win->sizey-1) - cy; -#endif event.x= evt->x; event.y= evt->y; @@ -2404,21 +2416,17 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U event.type= MOUSEPAN; break; } -#if defined(__APPLE__) && defined(GHOST_COCOA) - //Cocoa already uses coordinates with y=0 at bottom, and returns inwindow coordinates on mouse moved event - event.x= evt->x = pd->x; - event.y = evt->y = pd->y; -#else + { - int cx, cy; - GHOST_ScreenToClient(win->ghostwin, pd->x, pd->y, &cx, &cy); - event.x= evt->x= cx; - event.y= evt->y= (win->sizey-1) - cy; + int cx, cy; + GHOST_ScreenToClient(win->ghostwin, pd->x, pd->y, &cx, &cy); + event.x= evt->x= cx; + event.y= evt->y= (win->sizey-1) - cy; } -#endif + // Use prevx/prevy so we can calculate the delta later event.prevx= event.x - pd->deltaX; - event.prevy= event.y - pd->deltaY; + event.prevy= event.y - (-pd->deltaY); update_tablet_data(win, &event); wm_event_add(win, &event); @@ -2441,6 +2449,16 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U else event.type= MIDDLEMOUSE; + if(win->active==0) { + int cx, cy; + + /* entering window, update mouse pos. (ghost sends win-activate *after* the mouseclick in window!) */ + wm_get_cursor_position(win, &cx, &cy); + + event.x= evt->x= cx; + event.y= evt->y= cy; + } + /* add to other window if event is there (not to both!) */ owin= wm_event_cursor_other_windows(wm, win, &event); if(owin) { diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index 2783504ae90..27fc0caeccc 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -57,6 +57,7 @@ #include "BLI_blenlib.h" #include "BLI_linklist.h" #include "BLI_utildefines.h" +#include "BLI_callbacks.h" #include "DNA_anim_types.h" #include "DNA_ipo_types.h" // XXX old animation system @@ -333,7 +334,7 @@ static int wm_read_exotic(Scene *UNUSED(scene), const char *name) return retval; } -void WM_read_file(bContext *C, const char *name, ReportList *reports) +void WM_read_file(bContext *C, const char *filepath, ReportList *reports) { int retval; @@ -342,10 +343,12 @@ void WM_read_file(bContext *C, const char *name, ReportList *reports) WM_cursor_wait(1); + BLI_exec_cb(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_PRE); + /* first try to append data from exotic file formats... */ /* it throws error box when file doesnt exist and returns -1 */ /* note; it should set some error message somewhere... (ton) */ - retval= wm_read_exotic(CTX_data_scene(C), name); + retval= wm_read_exotic(CTX_data_scene(C), filepath); /* we didn't succeed, now try to read Blender file */ if (retval == BKE_READ_EXOTIC_OK_BLEND) { @@ -356,7 +359,7 @@ void WM_read_file(bContext *C, const char *name, ReportList *reports) /* also exit screens and editors */ wm_window_match_init(C, &wmbase); - retval= BKE_read_file(C, name, reports); + retval= BKE_read_file(C, filepath, reports); G.save_over = 1; /* this flag is initialized by the operator but overwritten on read. @@ -392,6 +395,7 @@ void WM_read_file(bContext *C, const char *name, ReportList *reports) #ifdef WITH_PYTHON /* run any texts that were loaded in and flagged as modules */ BPY_driver_reset(); + BPY_app_handlers_reset(); BPY_modules_load_user(C); #endif CTX_wm_window_set(C, NULL); /* exits queues */ @@ -411,21 +415,22 @@ void WM_read_file(bContext *C, const char *name, ReportList *reports) // XXX undo_editmode_clear(); BKE_reset_undo(); BKE_write_undo(C, "original"); /* save current state */ - + + BLI_exec_cb(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_POST); } else if(retval == BKE_READ_EXOTIC_OK_OTHER) BKE_write_undo(C, "Import file"); else if(retval == BKE_READ_EXOTIC_FAIL_OPEN) { - BKE_reportf(reports, RPT_ERROR, "Can't read file: \"%s\", %s.", name, errno ? strerror(errno) : "Unable to open the file"); + BKE_reportf(reports, RPT_ERROR, "Can't read file: \"%s\", %s.", filepath, errno ? strerror(errno) : "Unable to open the file"); } else if(retval == BKE_READ_EXOTIC_FAIL_FORMAT) { - BKE_reportf(reports, RPT_ERROR, "File format is not supported in file: \"%s\".", name); + BKE_reportf(reports, RPT_ERROR, "File format is not supported in file: \"%s\".", filepath); } else if(retval == BKE_READ_EXOTIC_FAIL_PATH) { - BKE_reportf(reports, RPT_ERROR, "File path invalid: \"%s\".", name); + BKE_reportf(reports, RPT_ERROR, "File path invalid: \"%s\".", filepath); } else { - BKE_reportf(reports, RPT_ERROR, "Unknown error loading: \"%s\".", name); + BKE_reportf(reports, RPT_ERROR, "Unknown error loading: \"%s\".", filepath); BLI_assert(!"invalid 'retval'"); } @@ -485,15 +490,16 @@ int WM_read_homefile(bContext *C, ReportList *reports, short from_memory) /* prevent buggy files that had G_FILE_RELATIVE_REMAP written out by mistake. Screws up autosaves otherwise * can remove this eventually, only in a 2.53 and older, now its not written */ G.fileflags &= ~G_FILE_RELATIVE_REMAP; - + + /* check userdef before open window, keymaps etc */ + wm_init_userdef(C); + /* match the read WM with current WM */ wm_window_match_do(C, &wmbase); WM_check(C); /* opens window(s), checks keymaps */ G.main->name[0]= '\0'; - wm_init_userdef(C); - /* When loading factory settings, the reset solid OpenGL lights need to be applied. */ if (!G.background) GPU_default_lights(); @@ -517,6 +523,7 @@ int WM_read_homefile(bContext *C, ReportList *reports, short from_memory) BPY_string_exec(C, "__import__('addon_utils').reset_all()"); BPY_driver_reset(); + BPY_app_handlers_reset(); BPY_modules_load_user(C); } #endif @@ -544,7 +551,7 @@ void WM_read_history(void) struct RecentFile *recent; char *line; int num; - char *cfgdir = BLI_get_folder(BLENDER_CONFIG, NULL); + char *cfgdir = BLI_get_folder(BLENDER_USER_CONFIG, NULL); if (!cfgdir) return; @@ -620,31 +627,6 @@ static void write_history(void) } } -static void do_history(char *name, ReportList *reports) -{ - char tempname1[FILE_MAXDIR+FILE_MAXFILE], tempname2[FILE_MAXDIR+FILE_MAXFILE]; - int hisnr= U.versions; - - if(U.versions==0) return; - if(strlen(name)<2) return; - - while(hisnr > 1) { - BLI_snprintf(tempname1, sizeof(tempname1), "%s%d", name, hisnr-1); - BLI_snprintf(tempname2, sizeof(tempname2), "%s%d", name, hisnr); - - if(BLI_rename(tempname1, tempname2)) - BKE_report(reports, RPT_ERROR, "Unable to make version backup"); - - hisnr--; - } - - /* is needed when hisnr==1 */ - BLI_snprintf(tempname1, sizeof(tempname1), "%s%d", name, hisnr); - - if(BLI_rename(name, tempname1)) - BKE_report(reports, RPT_ERROR, "Unable to make version backup"); -} - static ImBuf *blend_file_thumb(Scene *scene, int **thumb_pt) { /* will be scaled down, but gives some nice oversampling */ @@ -653,8 +635,9 @@ static ImBuf *blend_file_thumb(Scene *scene, int **thumb_pt) char err_out[256]= "unknown"; *thumb_pt= NULL; - - if(G.background || scene->camera==NULL) + + /* scene can be NULL if running a script at startup and calling the save operator */ + if(G.background || scene==NULL || scene->camera==NULL) return NULL; /* gets scaled to BLEN_THUMB_SIZE */ @@ -693,9 +676,11 @@ static ImBuf *blend_file_thumb(Scene *scene, int **thumb_pt) int write_crash_blend(void) { char path[FILE_MAX]; + int fileflags = G.fileflags & ~(G_FILE_HISTORY); /* don't do file history on crash file */ + BLI_strncpy(path, G.main->name, sizeof(path)); BLI_replace_extension(path, sizeof(path), "_crash.blend"); - if(BLO_write_file(G.main, path, G.fileflags, NULL, NULL)) { + if(BLO_write_file(G.main, path, fileflags, NULL, NULL)) { printf("written: %s\n", path); return 1; } @@ -709,7 +694,7 @@ int WM_write_file(bContext *C, const char *target, int fileflags, ReportList *re { Library *li; int len; - char di[FILE_MAX]; + char filepath[FILE_MAX]; int *thumb= NULL; ImBuf *ibuf_thumb= NULL; @@ -726,18 +711,26 @@ int WM_write_file(bContext *C, const char *target, int fileflags, ReportList *re return -1; } - BLI_strncpy(di, target, FILE_MAX); - BLI_replace_extension(di, FILE_MAX, ".blend"); + BLI_strncpy(filepath, target, FILE_MAX); + BLI_replace_extension(filepath, FILE_MAX, ".blend"); /* dont use 'target' anymore */ /* send the OnSave event */ for (li= G.main->library.first; li; li= li->id.next) { - if (BLI_path_cmp(li->filepath, di) == 0) { - BKE_reportf(reports, RPT_ERROR, "Can't overwrite used library '%.200s'", di); + if (BLI_path_cmp(li->filepath, filepath) == 0) { + BKE_reportf(reports, RPT_ERROR, "Can't overwrite used library '%.200s'", filepath); return -1; } } + /* blend file thumbnail */ + /* save before exit_editmode, otherwise derivedmeshes for shared data corrupt #27765) */ + if(U.flag & USER_SAVE_PREVIEWS) { + ibuf_thumb= blend_file_thumb(CTX_data_scene(C), &thumb); + } + + BLI_exec_cb(G.main, NULL, BLI_CB_EVT_SAVE_PRE); + /* operator now handles overwrite checks */ if (G.fileflags & G_AUTOPACK) { @@ -750,16 +743,12 @@ int WM_write_file(bContext *C, const char *target, int fileflags, ReportList *re /* don't forget not to return without! */ WM_cursor_wait(1); - /* blend file thumbnail */ - ibuf_thumb= blend_file_thumb(CTX_data_scene(C), &thumb); + fileflags |= G_FILE_HISTORY; /* write file history */ - /* rename to .blend1, do this as last before write */ - do_history(di, reports); - - if (BLO_write_file(CTX_data_main(C), di, fileflags, reports, thumb)) { + if (BLO_write_file(CTX_data_main(C), filepath, fileflags, reports, thumb)) { if(!copy) { G.relbase_valid = 1; - BLI_strncpy(G.main->name, di, sizeof(G.main->name)); /* is guaranteed current file */ + BLI_strncpy(G.main->name, filepath, sizeof(G.main->name)); /* is guaranteed current file */ G.save_over = 1; /* disable untitled.blend convention */ } @@ -770,11 +759,16 @@ int WM_write_file(bContext *C, const char *target, int fileflags, ReportList *re if(fileflags & G_FILE_AUTOPLAY) G.fileflags |= G_FILE_AUTOPLAY; else G.fileflags &= ~G_FILE_AUTOPLAY; - write_history(); + /* prevent background mode scripts from clobbering history */ + if(!G.background) { + write_history(); + } + + BLI_exec_cb(G.main, NULL, BLI_CB_EVT_SAVE_POST); /* run this function after because the file cant be written before the blend is */ if (ibuf_thumb) { - ibuf_thumb= IMB_thumb_create(di, THB_NORMAL, THB_SOURCE_BLEND, ibuf_thumb); + ibuf_thumb= IMB_thumb_create(filepath, THB_NORMAL, THB_SOURCE_BLEND, ibuf_thumb); IMB_freeImBuf(ibuf_thumb); } @@ -798,20 +792,20 @@ int WM_write_homefile(bContext *C, wmOperator *op) { wmWindowManager *wm= CTX_wm_manager(C); wmWindow *win= CTX_wm_window(C); - char tstr[FILE_MAXDIR+FILE_MAXFILE]; + char filepath[FILE_MAXDIR+FILE_MAXFILE]; int fileflags; /* check current window and close it if temp */ if(win->screen->temp) wm_window_close(C, wm, win); - BLI_make_file_string("/", tstr, BLI_get_folder_create(BLENDER_USER_CONFIG, NULL), BLENDER_STARTUP_FILE); - printf("trying to save homefile at %s ", tstr); + BLI_make_file_string("/", filepath, BLI_get_folder_create(BLENDER_USER_CONFIG, NULL), BLENDER_STARTUP_FILE); + printf("trying to save homefile at %s ", filepath); /* force save as regular blend file */ - fileflags = G.fileflags & ~(G_FILE_COMPRESS | G_FILE_AUTOPLAY | G_FILE_LOCK | G_FILE_SIGN); + fileflags = G.fileflags & ~(G_FILE_COMPRESS | G_FILE_AUTOPLAY | G_FILE_LOCK | G_FILE_SIGN | G_FILE_HISTORY); - if(BLO_write_file(CTX_data_main(C), tstr, fileflags, op->reports, NULL) == 0) { + if(BLO_write_file(CTX_data_main(C), filepath, fileflags, op->reports, NULL) == 0) { printf("fail\n"); return OPERATOR_CANCELLED; } @@ -825,7 +819,7 @@ int WM_write_homefile(bContext *C, wmOperator *op) /************************ autosave ****************************/ -void wm_autosave_location(char *filename) +void wm_autosave_location(char *filepath) { char pidstr[32]; #ifdef WIN32 @@ -845,12 +839,12 @@ void wm_autosave_location(char *filename) * If there is no C:\tmp autosave fails. */ if (!BLI_exists(U.tempdir)) { savedir = BLI_get_folder_create(BLENDER_USER_AUTOSAVE, NULL); - BLI_make_file_string("/", filename, savedir, pidstr); + BLI_make_file_string("/", filepath, savedir, pidstr); return; } #endif - BLI_make_file_string("/", filename, U.tempdir, pidstr); + BLI_make_file_string("/", filepath, U.tempdir, pidstr); } void WM_autosave_init(wmWindowManager *wm) @@ -865,7 +859,7 @@ void wm_autosave_timer(const bContext *C, wmWindowManager *wm, wmTimer *UNUSED(w { wmWindow *win; wmEventHandler *handler; - char filename[FILE_MAX]; + char filepath[FILE_MAX]; int fileflags; WM_event_remove_timer(wm, NULL, wm->autosavetimer); @@ -880,13 +874,13 @@ void wm_autosave_timer(const bContext *C, wmWindowManager *wm, wmTimer *UNUSED(w } } - wm_autosave_location(filename); + wm_autosave_location(filepath); /* force save as regular blend file */ - fileflags = G.fileflags & ~(G_FILE_COMPRESS|G_FILE_AUTOPLAY |G_FILE_LOCK|G_FILE_SIGN); + fileflags = G.fileflags & ~(G_FILE_COMPRESS|G_FILE_AUTOPLAY |G_FILE_LOCK|G_FILE_SIGN|G_FILE_HISTORY); /* no error reporting to console */ - BLO_write_file(CTX_data_main(C), filename, fileflags, NULL, NULL); + BLO_write_file(CTX_data_main(C), filepath, fileflags, NULL, NULL); /* do timer after file write, just in case file write takes a long time */ wm->autosavetimer= WM_event_add_timer(wm, NULL, TIMERAUTOSAVE, U.savetime*60.0); diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index b09e264bd1d..4c280fe4341 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -48,6 +48,7 @@ #include "BKE_blender.h" #include "BKE_context.h" +#include "BKE_screen.h" #include "BKE_curve.h" #include "BKE_displist.h" #include "BKE_DerivedMesh.h" @@ -154,6 +155,8 @@ void WM_init(bContext *C, int argc, const char **argv) BPY_python_start(argc, argv); BPY_driver_reset(); + BPY_app_handlers_reset(); /* causes addon callbacks to be freed [#28068], + * but this is actually what we want. */ BPY_modules_load_user(C); #else (void)argc; /* unused */ @@ -168,6 +171,7 @@ void WM_init(bContext *C, int argc, const char **argv) if (!G.background) { GPU_extensions_init(); GPU_set_mipmap(!(U.gameflags & USER_DISABLE_MIPMAP)); + GPU_set_anisotropic(U.anisotropic_filter); UI_init(); } @@ -247,15 +251,7 @@ int WM_init_game(bContext *C) CTX_wm_window_set(C, win); sa = biggest_view3d(C); - - if(sa) - { - for(ar=sa->regionbase.first; ar; ar=ar->next) { - if(ar->regiontype == RGN_TYPE_WINDOW) { - break; - } - } - } + ar= BKE_area_find_region_type(sa, RGN_TYPE_WINDOW); // if we have a valid 3D view if (sa && ar) { @@ -335,7 +331,6 @@ static void free_openrecent(void) /* bad stuff*/ -extern ListBase editelems; extern wchar_t *copybuf; extern wchar_t *copybufinfo; @@ -387,7 +382,6 @@ void WM_exit(bContext *C) BKE_freecubetable(); - fastshade_free_render(); /* shaded view */ ED_preview_free_dbase(); /* frees a Main dbase, before free_blender! */ if(C && CTX_wm_manager(C)) @@ -401,10 +395,6 @@ void WM_exit(bContext *C) free_anim_drivers_copybuf(); free_fmodifiers_copybuf(); free_posebuf(); -// free_vertexpaint(); -// free_imagepaint(); - -// fsmenu_free(); BLF_exit(); @@ -427,11 +417,7 @@ void WM_exit(bContext *C) BPY_python_end(); #endif - if (!G.background) { -// XXX UI_filelist_free_icons(); - } - - GPU_buffer_pool_free(NULL); + GPU_global_buffer_pool_free(); GPU_free_unused_buffers(); GPU_extensions_exit(); diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c index 336acd9f9bf..1720c738dd7 100644 --- a/source/blender/windowmanager/intern/wm_keymap.c +++ b/source/blender/windowmanager/intern/wm_keymap.c @@ -493,17 +493,17 @@ static wmKeyMapItem *wm_keymap_item_find_props(const bContext *C, const char *op } else if(ELEM(opcontext, WM_OP_EXEC_REGION_CHANNELS, WM_OP_INVOKE_REGION_CHANNELS)) { if (!(ar && ar->regiontype == RGN_TYPE_CHANNELS)) - ar= BKE_area_find_region_type(sa, RGN_TYPE_CHANNELS); - - if(ar) - found= wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, compare_props, hotkey, keymap_r); + ar= BKE_area_find_region_type(sa, RGN_TYPE_CHANNELS); + + if(ar) + found= wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, compare_props, hotkey, keymap_r); } else if(ELEM(opcontext, WM_OP_EXEC_REGION_PREVIEW, WM_OP_INVOKE_REGION_PREVIEW)) { if (!(ar && ar->regiontype == RGN_TYPE_PREVIEW)) - ar= BKE_area_find_region_type(sa, RGN_TYPE_PREVIEW); - - if(ar) - found= wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, compare_props, hotkey, keymap_r); + ar= BKE_area_find_region_type(sa, RGN_TYPE_PREVIEW); + + if(ar) + found= wm_keymap_item_find_handlers(C, &ar->handlers, opname, opcontext, properties, compare_props, hotkey, keymap_r); } else { if(ar) diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 63a8ecc4043..29afdb570ea 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -56,11 +56,13 @@ #include "BLI_blenlib.h" #include "BLI_dynstr.h" /*for WM_operator_pystring */ #include "BLI_math.h" +#include "BLI_string.h" #include "BLI_utildefines.h" #include "BLO_readfile.h" #include "BKE_blender.h" +#include "BKE_brush.h" #include "BKE_context.h" #include "BKE_depsgraph.h" #include "BKE_idprop.h" @@ -440,10 +442,12 @@ void WM_operator_py_idname(char *to, const char *from) { char *sep= strstr(from, "_OT_"); if(sep) { - int i, ofs= (sep-from); - - for(i=0; i<ofs; i++) - to[i]= tolower(from[i]); + int ofs= (sep-from); + + /* note, we use ascii tolower instead of system tolower, because the + latter depends on the locale, and can lead to idname mistmatch */ + memcpy(to, from, sizeof(char)*ofs); + BLI_ascii_strtolower(to, ofs); to[ofs] = '.'; BLI_strncpy(to+(ofs+1), sep+4, OP_MAX_TYPENAME); @@ -461,10 +465,10 @@ void WM_operator_bl_idname(char *to, const char *from) char *sep= strchr(from, '.'); if(sep) { - int i, ofs= (sep-from); + int ofs= (sep-from); - for(i=0; i<ofs; i++) - to[i]= toupper(from[i]); + memcpy(to, from, sizeof(char)*ofs); + BLI_ascii_strtoupper(to, ofs); BLI_strncpy(to+ofs, "_OT_", OP_MAX_TYPENAME); BLI_strncpy(to+(ofs+4), sep+1, OP_MAX_TYPENAME); @@ -682,7 +686,7 @@ static void operator_enum_search_cb(const struct bContext *C, void *arg_ot, cons RNA_property_enum_items((bContext *)C, &ptr, prop, &item_array, NULL, &do_free); for(item= item_array; item->identifier; item++) { - /* note: need to give the intex rather then the dientifier because the enum can be freed */ + /* note: need to give the intex rather than the dientifier because the enum can be freed */ if(BLI_strcasestr(item->name, str)) if(0==uiSearchItemAdd(items, item->name, SET_INT_IN_POINTER(item->value), 0)) break; @@ -698,11 +702,16 @@ static void operator_enum_call_cb(struct bContext *C, void *arg1, void *arg2) wmOperatorType *ot= arg1; if(ot) { - PointerRNA props_ptr; - WM_operator_properties_create_ptr(&props_ptr, ot); - RNA_property_enum_set(&props_ptr, ot->prop, GET_INT_FROM_POINTER(arg2)); - WM_operator_name_call(C, ot->idname, WM_OP_EXEC_DEFAULT, &props_ptr); - WM_operator_properties_free(&props_ptr); + if(ot->prop) { + PointerRNA props_ptr; + WM_operator_properties_create_ptr(&props_ptr, ot); + RNA_property_enum_set(&props_ptr, ot->prop, GET_INT_FROM_POINTER(arg2)); + WM_operator_name_call(C, ot->idname, WM_OP_EXEC_DEFAULT, &props_ptr); + WM_operator_properties_free(&props_ptr); + } + else { + printf("operator_enum_call_cb: op->prop for '%s' is NULL\n", ot->idname); + } } } @@ -718,14 +727,14 @@ static uiBlock *wm_enum_search_menu(bContext *C, ARegion *ar, void *arg_op) block= uiBeginBlock(C, ar, "_popup", UI_EMBOSS); uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_RET_1|UI_BLOCK_MOVEMOUSE_QUIT); - //uiDefBut(block, LABEL, 0, op->type->name, 10, 10, 180, 19, NULL, 0.0, 0.0, 0, 0, ""); // ok, this isnt so easy... - but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, 256, 10, 10, 180, 19, 0, 0, ""); + //uiDefBut(block, LABEL, 0, op->type->name, 10, 10, 180, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, ""); // ok, this isnt so easy... + but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, 256, 10, 10, 9*UI_UNIT_X, UI_UNIT_Y, 0, 0, ""); uiButSetSearchFunc(but, operator_enum_search_cb, op->type, operator_enum_call_cb, NULL); /* fake button, it holds space for search items */ - uiDefBut(block, LABEL, 0, "", 10, 10 - uiSearchBoxhHeight(), 180, uiSearchBoxhHeight(), NULL, 0, 0, 0, 0, NULL); + uiDefBut(block, LABEL, 0, "", 10, 10 - uiSearchBoxhHeight(), 9*UI_UNIT_X, uiSearchBoxhHeight(), NULL, 0, 0, 0, 0, NULL); - uiPopupBoundsBlock(block, 6, 0, -20); /* move it downwards, mouse over button */ + uiPopupBoundsBlock(block, 6, 0, -UI_UNIT_Y); /* move it downwards, mouse over button */ uiEndBlock(C, block); event= *(win->eventstate); /* XXX huh huh? make api call */ @@ -876,6 +885,19 @@ int WM_operator_winactive(bContext *C) return 1; } +wmOperator *WM_operator_last_redo(const bContext *C) +{ + wmWindowManager *wm= CTX_wm_manager(C); + wmOperator *op; + + /* only for operators that are registered and did an undo push */ + for(op= wm->operators.last; op; op= op->prev) + if((op->type->flag & OPTYPE_REGISTER) && (op->type->flag & OPTYPE_UNDO)) + break; + + return op; +} + static uiBlock *wm_block_create_redo(bContext *C, ARegion *ar, void *arg_op) { wmOperator *op= arg_op; @@ -894,12 +916,21 @@ static uiBlock *wm_block_create_redo(bContext *C, ARegion *ar, void *arg_op) assert(op->type->flag & OPTYPE_REGISTER); uiBlockSetHandleFunc(block, ED_undo_operator_repeat_cb_evt, arg_op); - layout= uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, width, 20, style); + layout= uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, width, UI_UNIT_Y, style); if(ED_undo_valid(C, op->type->name)==0) uiLayoutSetEnabled(layout, 0); - uiLayoutOperatorButs(C, layout, op, NULL, 'H', UI_LAYOUT_OP_SHOW_TITLE); + if(op->type->flag & OPTYPE_MACRO) { + for(op= op->macro.first; op; op= op->next) { + uiItemL(layout, op->type->name, ICON_NONE); + uiLayoutOperatorButs(C, layout, op, NULL, 'H', UI_LAYOUT_OP_SHOW_TITLE); + } + } + else { + uiLayoutOperatorButs(C, layout, op, NULL, 'H', UI_LAYOUT_OP_SHOW_TITLE); + } + uiPopupBoundsBlock(block, 4, 0, 0); uiEndBlock(C, block); @@ -907,13 +938,28 @@ static uiBlock *wm_block_create_redo(bContext *C, ARegion *ar, void *arg_op) return block; } -/* Only invoked by OK button in popups created with wm_block_create_dialog() */ +typedef struct wmOpPopUp +{ + wmOperator *op; + int width; + int height; + int free_op; +} wmOpPopUp; + +/* Only invoked by OK button in popups created with wm_block_dialog_create() */ static void dialog_exec_cb(bContext *C, void *arg1, void *arg2) { - wmOperator *op= arg1; + wmOpPopUp *data= arg1; uiBlock *block= arg2; - WM_operator_call(C, op); + WM_operator_call(C, data->op); + + /* let execute handle freeing it */ + //data->free_op= FALSE; + //data->op= NULL; + + /* in this case, wm_operator_ui_popup_cancel wont run */ + MEM_freeN(data); uiPupBlockClose(C, block); } @@ -929,9 +975,9 @@ static void dialog_check_cb(bContext *C, void *op_ptr, void *UNUSED(arg)) } /* Dialogs are popups that require user verification (click OK) before exec */ -static uiBlock *wm_block_create_dialog(bContext *C, ARegion *ar, void *userData) +static uiBlock *wm_block_dialog_create(bContext *C, ARegion *ar, void *userData) { - struct { wmOperator *op; int width; int height; } * data = userData; + wmOpPopUp *data= userData; wmOperator *op= data->op; uiBlock *block; uiLayout *layout; @@ -959,8 +1005,8 @@ static uiBlock *wm_block_create_dialog(bContext *C, ARegion *ar, void *userData) col= uiLayoutColumn(layout, FALSE); col_block= uiLayoutGetBlock(col); /* Create OK button, the callback of which will execute op */ - btn= uiDefBut(col_block, BUT, 0, "OK", 0, -30, 0, 20, NULL, 0, 0, 0, 0, ""); - uiButSetFunc(btn, dialog_exec_cb, op, col_block); + btn= uiDefBut(col_block, BUT, 0, "OK", 0, -30, 0, UI_UNIT_Y, NULL, 0, 0, 0, 0, ""); + uiButSetFunc(btn, dialog_exec_cb, data, col_block); } /* center around the mouse */ @@ -970,9 +1016,9 @@ static uiBlock *wm_block_create_dialog(bContext *C, ARegion *ar, void *userData) return block; } -static uiBlock *wm_operator_create_ui(bContext *C, ARegion *ar, void *userData) +static uiBlock *wm_operator_ui_create(bContext *C, ARegion *ar, void *userData) { - struct { wmOperator *op; int width; int height; } * data = userData; + wmOpPopUp *data= userData; wmOperator *op= data->op; uiBlock *block; uiLayout *layout; @@ -993,6 +1039,28 @@ static uiBlock *wm_operator_create_ui(bContext *C, ARegion *ar, void *userData) return block; } +static void wm_operator_ui_popup_cancel(void *userData) +{ + wmOpPopUp *data= userData; + if(data->free_op && data->op) { + wmOperator *op= data->op; + WM_operator_free(op); + } + + MEM_freeN(data); +} + +int WM_operator_ui_popup(bContext *C, wmOperator *op, int width, int height) +{ + wmOpPopUp *data= MEM_callocN(sizeof(wmOpPopUp), "WM_operator_ui_popup"); + data->op= op; + data->width= width; + data->height= height; + data->free_op= TRUE; /* if this runs and gets registered we may want not to free it */ + uiPupBlockEx(C, wm_operator_ui_create, wm_operator_ui_popup_cancel, data); + return OPERATOR_RUNNING_MODAL; +} + /* operator menu needs undo, for redo callback */ int WM_operator_props_popup(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) { @@ -1012,28 +1080,19 @@ int WM_operator_props_popup(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) int WM_operator_props_dialog_popup(bContext *C, wmOperator *op, int width, int height) { - struct { wmOperator *op; int width; int height; } data; + wmOpPopUp *data= MEM_callocN(sizeof(wmOpPopUp), "WM_operator_props_dialog_popup"); - data.op= op; - data.width= width; - data.height= height; + data->op= op; + data->width= width; + data->height= height; + data->free_op= TRUE; /* if this runs and gets registered we may want not to free it */ /* op is not executed until popup OK but is clicked */ - uiPupBlock(C, wm_block_create_dialog, &data); + uiPupBlockEx(C, wm_block_dialog_create, wm_operator_ui_popup_cancel, data); return OPERATOR_RUNNING_MODAL; } -int WM_operator_ui_popup(bContext *C, wmOperator *op, int width, int height) -{ - struct { wmOperator *op; int width; int height; } data; - data.op = op; - data.width = width; - data.height = height; - uiPupBlock(C, wm_operator_create_ui, &data); - return OPERATOR_RUNNING_MODAL; -} - int WM_operator_redo_popup(bContext *C, wmOperator *op) { /* CTX_wm_reports(C) because operator is on stack, not active in event system */ @@ -1065,7 +1124,7 @@ static int wm_debug_menu_exec(bContext *C, wmOperator *op) static int wm_debug_menu_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) { RNA_int_set(op->ptr, "debug_value", G.rt); - return WM_operator_props_dialog_popup(C, op, 180, 20); + return WM_operator_props_dialog_popup(C, op, 9*UI_UNIT_X, UI_UNIT_Y); } static void WM_OT_debug_menu(wmOperatorType *ot) @@ -1163,8 +1222,8 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(ar uiBlockSetFunc(block, wm_block_splash_refreshmenu, block, NULL); #ifdef NAN_BUILDINFO - uiDefBut(block, LABEL, 0, version_str, 494-ver_width, 282-24, ver_width, 20, NULL, 0, 0, 0, 0, NULL); - uiDefBut(block, LABEL, 0, revision_str, 494-rev_width, 282-36, rev_width, 20, NULL, 0, 0, 0, 0, NULL); + uiDefBut(block, LABEL, 0, version_str, 494-ver_width, 282-24, ver_width, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL); + uiDefBut(block, LABEL, 0, revision_str, 494-rev_width, 282-36, rev_width, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL); #endif //NAN_BUILDINFO layout= uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 10, 2, 480, 110, style); @@ -1188,7 +1247,7 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(ar col = uiLayoutColumn(split, 0); uiItemL(col, "Links", ICON_NONE); uiItemStringO(col, "Donations", ICON_URL, "WM_OT_url_open", "url", "http://www.blender.org/blenderorg/blender-foundation/donation-payment/"); - uiItemStringO(col, "Release Log", ICON_URL, "WM_OT_url_open", "url", "http://www.blender.org/development/release-logs/blender-257/"); + uiItemStringO(col, "Release Log", ICON_URL, "WM_OT_url_open", "url", "http://www.blender.org/development/release-logs/blender-258/"); uiItemStringO(col, "Manual", ICON_URL, "WM_OT_url_open", "url", "http://wiki.blender.org/index.php/Doc:2.5/Manual"); uiItemStringO(col, "Blender Website", ICON_URL, "WM_OT_url_open", "url", "http://www.blender.org/"); uiItemStringO(col, "User Community", ICON_URL, "WM_OT_url_open", "url", "http://www.blender.org/community/user-community/"); // @@ -1255,7 +1314,10 @@ static void operator_search_cb(const struct bContext *C, void *UNUSED(arg), cons wmOperatorType *ot = WM_operatortype_first(); for(; ot; ot= ot->next) { - + + if((ot->flag & OPTYPE_INTERNAL) && (G.f & G_DEBUG) == 0) + continue; + if(BLI_strcasestr(ot->name, str)) { if(WM_operator_poll((bContext*)C, ot)) { char name[256]; @@ -1288,13 +1350,13 @@ static uiBlock *wm_block_search_menu(bContext *C, ARegion *ar, void *UNUSED(arg_ block= uiBeginBlock(C, ar, "_popup", UI_EMBOSS); uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_RET_1|UI_BLOCK_MOVEMOUSE_QUIT); - but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, 256, 10, 10, 180, 19, 0, 0, ""); + but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, 256, 10, 10, 9*UI_UNIT_X, UI_UNIT_Y, 0, 0, ""); uiButSetSearchFunc(but, operator_search_cb, NULL, operator_call_cb, NULL); /* fake button, it holds space for search items */ - uiDefBut(block, LABEL, 0, "", 10, 10 - uiSearchBoxhHeight(), 180, uiSearchBoxhHeight(), NULL, 0, 0, 0, 0, NULL); + uiDefBut(block, LABEL, 0, "", 10, 10 - uiSearchBoxhHeight(), 9*UI_UNIT_X, uiSearchBoxhHeight(), NULL, 0, 0, 0, 0, NULL); - uiPopupBoundsBlock(block, 6, 0, -20); /* move it downwards, mouse over button */ + uiPopupBoundsBlock(block, 6, 0, -UI_UNIT_Y); /* move it downwards, mouse over button */ uiEndBlock(C, block); event= *(win->eventstate); /* XXX huh huh? make api call */ @@ -1322,10 +1384,20 @@ static int wm_search_menu_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(ev /* op->poll */ static int wm_search_menu_poll(bContext *C) { - if(CTX_wm_window(C)==NULL) return 0; - if(CTX_wm_area(C) && CTX_wm_area(C)->spacetype==SPACE_CONSOLE) return 0; // XXX - so we can use the shortcut in the console - if(CTX_wm_area(C) && CTX_wm_area(C)->spacetype==SPACE_TEXT) return 0; // XXX - so we can use the spacebar in the text editor - if(CTX_data_edit_object(C) && CTX_data_edit_object(C)->type==OB_FONT) return 0; // XXX - so we can use the spacebar for entering text + if(CTX_wm_window(C)==NULL) { + return 0; + } + else { + ScrArea *sa= CTX_wm_area(C); + if(sa) { + if(sa->spacetype==SPACE_CONSOLE) return 0; // XXX - so we can use the shortcut in the console + if(sa->spacetype==SPACE_TEXT) return 0; // XXX - so we can use the spacebar in the text editor + } + else { + Object *editob= CTX_data_edit_object(C); + if(editob && editob->type==OB_FONT) return 0; // XXX - so we can use the spacebar for entering text + } + } return 1; } @@ -1357,6 +1429,8 @@ static void WM_OT_call_menu(wmOperatorType *ot) ot->exec= wm_call_menu_exec; ot->poll= WM_operator_winactive; + ot->flag= OPTYPE_INTERNAL; + RNA_def_string(ot->srna, "name", "", BKE_ST_MAXNAME, "Name", "Name of the menu"); } @@ -1428,7 +1502,7 @@ static void open_set_load_ui(wmOperator *op) static void open_set_use_scripts(wmOperator *op) { if(!RNA_property_is_set(op->ptr, "use_scripts")) { - /* use G_SCRIPT_AUTOEXEC rather then the userpref because this means if + /* use G_SCRIPT_AUTOEXEC rather than the userpref because this means if * the flag has been disabled from the command line, then opening * from the menu wont enable this setting. */ RNA_boolean_set(op->ptr, "use_scripts", (G.f & G_SCRIPT_AUTOEXEC)); @@ -1439,6 +1513,14 @@ static int wm_open_mainfile_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED( { const char *openname= G.main->name; + if(CTX_wm_window(C) == NULL) { + /* in rare cases this could happen, when trying to invoke in background + * mode on load for example. Don't use poll for this because exec() + * can still run without a window */ + BKE_report(op->reports, RPT_ERROR, "Context window not set"); + return OPERATOR_CANCELLED; + } + /* if possible, get the name of the most recently used .blend file */ if (G.recent_files.first) { struct RecentFile *recent = G.recent_files.first; @@ -1489,7 +1571,7 @@ static void WM_OT_open_mainfile(wmOperatorType *ot) ot->invoke= wm_open_mainfile_invoke; ot->exec= wm_open_mainfile_exec; - ot->poll= WM_operator_winactive; + /* ommit window poll so this can work in background mode */ WM_operator_properties_filesel(ot, FOLDERFILE|BLENDERFILE, FILE_BLENDER, FILE_OPENFILE, WM_FILESEL_FILEPATH); @@ -1610,12 +1692,12 @@ static int wm_link_append_exec(bContext *C, wmOperator *op) /* here appending/linking starts */ mainl = BLO_library_append_begin(C, &bh, libname); if(totfiles == 0) { - BLO_library_append_named_part(C, mainl, &bh, name, idcode, flag); + BLO_library_append_named_part_ex(C, mainl, &bh, name, idcode, flag); } else { RNA_BEGIN(op->ptr, itemptr, "files") { RNA_string_get(&itemptr, "name", name); - BLO_library_append_named_part(C, mainl, &bh, name, idcode, flag); + BLO_library_append_named_part_ex(C, mainl, &bh, name, idcode, flag); } RNA_END; } @@ -1908,7 +1990,7 @@ static void WM_OT_save_mainfile(wmOperatorType *ot) ot->invoke= wm_save_mainfile_invoke; ot->exec= wm_save_as_mainfile_exec; ot->check= blend_save_check; - ot->poll= NULL; + /* ommit window poll so this can work in background mode */ WM_operator_properties_filesel(ot, FOLDERFILE|BLENDERFILE, FILE_BLENDER, FILE_SAVE, WM_FILESEL_FILEPATH); RNA_def_boolean(ot->srna, "compress", 0, "Compress", "Write compressed .blend file"); @@ -1922,6 +2004,8 @@ static void WM_OT_save_mainfile(wmOperatorType *ot) static int wm_collada_export_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) { + int selected = 0; + if(!RNA_property_is_set(op->ptr, "filepath")) { char filepath[FILE_MAX]; BLI_strncpy(filepath, G.main->name, sizeof(filepath)); @@ -1938,6 +2022,7 @@ static int wm_collada_export_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED static int wm_collada_export_exec(bContext *C, wmOperator *op) { char filename[FILE_MAX]; + int selected; if(!RNA_property_is_set(op->ptr, "filepath")) { BKE_report(op->reports, RPT_ERROR, "No filename given"); @@ -1945,7 +2030,8 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) } RNA_string_get(op->ptr, "filepath", filename); - if(collada_export(CTX_data_scene(C), filename)) { + selected = RNA_boolean_get(op->ptr, "selected"); + if(collada_export(CTX_data_scene(C), filename, selected)) { return OPERATOR_FINISHED; } else { @@ -1963,6 +2049,8 @@ static void WM_OT_collada_export(wmOperatorType *ot) ot->poll= WM_operator_winactive; WM_operator_properties_filesel(ot, FOLDERFILE|COLLADAFILE, FILE_BLENDER, FILE_SAVE, WM_FILESEL_FILEPATH); + RNA_def_boolean(ot->srna, "selected", 0, "Export only selected", + "Export only selected elements"); } /* function used for WM_OT_save_mainfile too */ @@ -2030,6 +2118,8 @@ static void WM_OT_quit_blender(wmOperatorType *ot) /* *********************** */ +#if defined(WIN32) + static int wm_console_toggle_op(bContext *UNUSED(C), wmOperator *UNUSED(op)) { GHOST_toggleConsole(2); @@ -2046,6 +2136,8 @@ static void WM_OT_console_toggle(wmOperatorType *ot) ot->poll= WM_operator_winactive; } +#endif + /* ************ default paint cursors, draw always around cursor *********** */ /* - returns handler to free @@ -2208,6 +2300,13 @@ int WM_border_select_modal(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_RUNNING_MODAL; } +int WM_border_select_cancel(bContext *C, wmOperator *op) +{ + wm_gesture_end(C, op); + + return OPERATOR_CANCELLED; +} + /* **************** circle gesture *************** */ /* works now only for selection or modal paint stuff, calls exec while hold mouse, exit on release */ @@ -2304,6 +2403,13 @@ int WM_gesture_circle_modal(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_RUNNING_MODAL; } +int WM_gesture_circle_cancel(bContext *C, wmOperator *op) +{ + wm_gesture_end(C, op); + + return OPERATOR_CANCELLED; +} + #if 0 /* template to copy from */ void WM_OT_circle_gesture(wmOperatorType *ot) @@ -2482,7 +2588,7 @@ int WM_gesture_lasso_modal(bContext *C, wmOperator *op, wmEvent *event) } { - short x, y; + int x, y; short *lasso= gesture->customdata; lasso += (2 * gesture->points - 2); @@ -2520,6 +2626,20 @@ int WM_gesture_lines_modal(bContext *C, wmOperator *op, wmEvent *event) return WM_gesture_lasso_modal(C, op, event); } +int WM_gesture_lasso_cancel(bContext *C, wmOperator *op) +{ + wm_gesture_end(C, op); + + return OPERATOR_CANCELLED; +} + +int WM_gesture_lines_cancel(bContext *C, wmOperator *op) +{ + wm_gesture_end(C, op); + + return OPERATOR_CANCELLED; +} + #if 0 /* template to copy from */ @@ -2641,6 +2761,13 @@ int WM_gesture_straightline_modal(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_RUNNING_MODAL; } +int WM_gesture_straightline_cancel(bContext *C, wmOperator *op) +{ + wm_gesture_end(C, op); + + return OPERATOR_CANCELLED; +} + #if 0 /* template to copy from */ void WM_OT_straightline_gesture(wmOperatorType *ot) @@ -2665,272 +2792,475 @@ void WM_OT_straightline_gesture(wmOperatorType *ot) static const int WM_RADIAL_CONTROL_DISPLAY_SIZE = 200; -typedef struct wmRadialControl { - int mode; - float initial_value, value, max_value; - float col[4], tex_col[4]; +typedef struct { + PropertyType type; + PropertySubType subtype; + PointerRNA ptr, col_ptr, fill_col_ptr, rot_ptr, zoom_ptr, image_id_ptr; + PropertyRNA *prop, *col_prop, *fill_col_prop, *rot_prop, *zoom_prop; + StructRNA *image_id_srna; + float initial_value, current_value, min_value, max_value; int initial_mouse[2]; + unsigned int gltex; + ListBase orig_paintcursors; void *cursor; - GLuint tex; -} wmRadialControl; +} RadialControl; -static void wm_radial_control_paint(bContext *C, int x, int y, void *customdata) +static void radial_control_set_initial_mouse(RadialControl *rc, wmEvent *event) { - wmRadialControl *rc = (wmRadialControl*)customdata; - ARegion *ar = CTX_wm_region(C); - float r1=0.0f, r2=0.0f, r3=0.0f, angle=0.0f; + float d[2] = {0, 0}; + float zoom[2] = {1, 1}; - // int hit = 0; - - if(rc->mode == WM_RADIALCONTROL_STRENGTH) - rc->tex_col[3]= (rc->value + 0.5f); + rc->initial_mouse[0]= event->x; + rc->initial_mouse[1]= event->y; - if(rc->mode == WM_RADIALCONTROL_SIZE) { - r1= rc->value; - r2= rc->initial_value; - r3= r1; - } else if(rc->mode == WM_RADIALCONTROL_STRENGTH) { - r1= (1 - rc->value) * WM_RADIAL_CONTROL_DISPLAY_SIZE; - r2= r3= (float)WM_RADIAL_CONTROL_DISPLAY_SIZE; - } else if(rc->mode == WM_RADIALCONTROL_ANGLE) { - r1= r2= r3= (float)WM_RADIAL_CONTROL_DISPLAY_SIZE; - angle = rc->value; + switch(rc->subtype) { + case PROP_DISTANCE: + d[0] = rc->initial_value; + break; + case PROP_FACTOR: + d[0] = WM_RADIAL_CONTROL_DISPLAY_SIZE * (1 - rc->initial_value); + break; + case PROP_ANGLE: + d[0] = WM_RADIAL_CONTROL_DISPLAY_SIZE * cos(rc->initial_value); + d[1] = WM_RADIAL_CONTROL_DISPLAY_SIZE * sin(rc->initial_value); + break; + default: + return; } - /* Keep cursor in the original place */ - x = rc->initial_mouse[0] - ar->winrct.xmin; - y = rc->initial_mouse[1] - ar->winrct.ymin; + if(rc->zoom_prop) { + RNA_property_float_get_array(&rc->zoom_ptr, rc->zoom_prop, zoom); + d[0] *= zoom[0]; + d[1] *= zoom[1]; + } - glTranslatef((float)x, (float)y, 0.0f); + rc->initial_mouse[0]-= d[0]; + rc->initial_mouse[1]-= d[1]; +} - glEnable(GL_BLEND); +static void radial_control_set_tex(RadialControl *rc) +{ + ImBuf *ibuf; - if(rc->mode == WM_RADIALCONTROL_ANGLE) { - glRotatef(angle, 0, 0, 1); + switch(RNA_type_to_ID_code(rc->image_id_ptr.type)) { + case ID_BR: + if((ibuf = brush_gen_radial_control_imbuf(rc->image_id_ptr.data))) { + glGenTextures(1, &rc->gltex); + glBindTexture(GL_TEXTURE_2D, rc->gltex); + glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, ibuf->x, ibuf->y, 0, + GL_ALPHA, GL_FLOAT, ibuf->rect_float); + MEM_freeN(ibuf->rect_float); + MEM_freeN(ibuf); + } + break; + default: + break; } +} + +static void radial_control_paint_tex(RadialControl *rc, float radius, float alpha) +{ + float col[3] = {0, 0, 0}; + float rot; + + /* set fill color */ + if(rc->fill_col_prop) + RNA_property_float_get_array(&rc->fill_col_ptr, rc->fill_col_prop, col); + glColor4f(col[0], col[1], col[2], alpha); - if (rc->tex) { - glBindTexture(GL_TEXTURE_2D, rc->tex); + if(rc->gltex) { + glBindTexture(GL_TEXTURE_2D, rc->gltex); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + /* set up rotation if available */ + if(rc->rot_prop) { + rot = RNA_property_float_get(&rc->rot_ptr, rc->rot_prop); + glPushMatrix(); + glRotatef(RAD2DEGF(rot), 0, 0, 1); + } + + /* draw textured quad */ glEnable(GL_TEXTURE_2D); glBegin(GL_QUADS); - glColor4fv(rc->tex_col); glTexCoord2f(0,0); - glVertex2f(-r3, -r3); + glVertex2f(-radius, -radius); glTexCoord2f(1,0); - glVertex2f(r3, -r3); + glVertex2f(radius, -radius); glTexCoord2f(1,1); - glVertex2f(r3, r3); + glVertex2f(radius, radius); glTexCoord2f(0,1); - glVertex2f(-r3, r3); + glVertex2f(-radius, radius); glEnd(); glDisable(GL_TEXTURE_2D); + + /* undo rotation */ + if(rc->rot_prop) + glPopMatrix(); + } + else { + /* flat color if no texture available */ + glutil_draw_filled_arc(0, M_PI * 2, radius, 40); + } +} + +static void radial_control_paint_cursor(bContext *C, int x, int y, void *customdata) +{ + RadialControl *rc = customdata; + ARegion *ar = CTX_wm_region(C); + float r1=0.0f, r2=0.0f, tex_radius, alpha; + float zoom[2], col[3] = {1, 1, 1}; + + switch(rc->subtype) { + case PROP_DISTANCE: + r1= rc->current_value; + r2= rc->initial_value; + tex_radius= r1; + alpha = 0.75; + break; + case PROP_FACTOR: + r1= (1 - rc->current_value) * WM_RADIAL_CONTROL_DISPLAY_SIZE; + r2= tex_radius= WM_RADIAL_CONTROL_DISPLAY_SIZE; + alpha = rc->current_value / 2 + 0.5; + break; + case PROP_ANGLE: + r1= r2= tex_radius= WM_RADIAL_CONTROL_DISPLAY_SIZE; + alpha = 0.75; + break; + default: + tex_radius= WM_RADIAL_CONTROL_DISPLAY_SIZE; /* note, this is a dummy value */ + alpha = 0.75; + break; } - if(rc->mode == WM_RADIALCONTROL_ANGLE) { - glColor4fv(rc->col); - glEnable(GL_LINE_SMOOTH); - glRotatef(-angle, 0, 0, 1); + /* Keep cursor in the original place */ + x = rc->initial_mouse[0] - ar->winrct.xmin; + y = rc->initial_mouse[1] - ar->winrct.ymin; + glTranslatef((float)x, (float)y, 0.0f); + + glEnable(GL_BLEND); + glEnable(GL_LINE_SMOOTH); + + /* apply zoom if available */ + if(rc->zoom_prop) { + RNA_property_float_get_array(&rc->zoom_ptr, rc->zoom_prop, zoom); + glScalef(zoom[0], zoom[1], 1); + } + + /* draw rotated texture */ + radial_control_paint_tex(rc, tex_radius, alpha); + + /* set line color */ + if(rc->col_prop) + RNA_property_float_get_array(&rc->col_ptr, rc->col_prop, col); + glColor4f(col[0], col[1], col[2], 0.5); + + if(rc->subtype == PROP_ANGLE) { + glPushMatrix(); + /* draw original angle line */ + glRotatef(RAD2DEGF(rc->initial_value), 0, 0, 1); fdrawline(0.0f, 0.0f, (float)WM_RADIAL_CONTROL_DISPLAY_SIZE, 0.0f); - glRotatef(angle, 0, 0, 1); + /* draw new angle line */ + glRotatef(RAD2DEGF(rc->current_value - rc->initial_value), 0, 0, 1); fdrawline(0.0f, 0.0f, (float)WM_RADIAL_CONTROL_DISPLAY_SIZE, 0.0f); - glDisable(GL_LINE_SMOOTH); + glPopMatrix(); } - glColor4fv(rc->col); + /* draw circles on top */ glutil_draw_lined_arc(0.0, (float)(M_PI*2.0), r1, 40); glutil_draw_lined_arc(0.0, (float)(M_PI*2.0), r2, 40); + glDisable(GL_BLEND); + glDisable(GL_LINE_SMOOTH); } -int WM_radial_control_modal(bContext *C, wmOperator *op, wmEvent *event) +/* attempt to retrieve the rna pointer/property from an rna path; + returns 0 for failure, 1 for success, and also 1 if property is not + set */ +static int radial_control_get_path(PointerRNA *ctx_ptr, wmOperator *op, + const char *name, PointerRNA *r_ptr, + PropertyRNA **r_prop, int req_float, + int req_length, int allow_missing) { - wmRadialControl *rc = (wmRadialControl*)op->customdata; - int mode, initial_mouse[2], delta[2]; - float dist; - double new_value = RNA_float_get(op->ptr, "new_value"); - int ret = OPERATOR_RUNNING_MODAL; - // float initial_value = RNA_float_get(op->ptr, "initial_value"); + PropertyRNA *unused_prop; + int len; + char *str; - mode = RNA_enum_get(op->ptr, "mode"); - RNA_int_get_array(op->ptr, "initial_mouse", initial_mouse); + /* get an rna string path from the operator's properties */ + if(!(str = RNA_string_get_alloc(op->ptr, name, NULL, 0))) + return 1; - switch(event->type) { - case MOUSEMOVE: - delta[0]= initial_mouse[0] - event->x; - delta[1]= initial_mouse[1] - event->y; + if(str[0] == '\0') { + MEM_freeN(str); + return 1; + } - //if (mode == WM_RADIALCONTROL_SIZE) - // delta[0]+= initial_value; - //else if(mode == WM_RADIALCONTROL_STRENGTH) - // delta[0]+= WM_RADIAL_CONTROL_DISPLAY_SIZE * (1 - initial_value); - //else if(mode == WM_RADIALCONTROL_ANGLE) { - // delta[0]+= WM_RADIAL_CONTROL_DISPLAY_SIZE * cos(initial_value*M_PI/180.0f); - // delta[1]+= WM_RADIAL_CONTROL_DISPLAY_SIZE * sin(initial_value*M_PI/180.0f); - //} + if(!r_prop) + r_prop = &unused_prop; - dist= sqrtf(delta[0]*delta[0]+delta[1]*delta[1]); + /* get rna from path */ + if(!RNA_path_resolve(ctx_ptr, str, r_ptr, r_prop)) { + MEM_freeN(str); + if(allow_missing) + return 1; + else { + BKE_reportf(op->reports, RPT_ERROR, "Couldn't resolve path %s", name); + return 0; + } + } - if(mode == WM_RADIALCONTROL_SIZE) - new_value = dist; - else if(mode == WM_RADIALCONTROL_STRENGTH) { - new_value = 1 - dist / WM_RADIAL_CONTROL_DISPLAY_SIZE; - } else if(mode == WM_RADIALCONTROL_ANGLE) - new_value = ((int)(atan2f(delta[1], delta[0]) * (float)(180.0 / M_PI)) + 180); - - if(event->ctrl) { - if(mode == WM_RADIALCONTROL_STRENGTH) - new_value = ((int)ceilf(new_value * 10.f) * 10.0f) / 100.f; - else - new_value = ((int)new_value + 5) / 10*10; + /* if property is expected to be a float, check its type */ + if(req_float) { + if(!(*r_prop) || (RNA_property_type(*r_prop) != PROP_FLOAT)) { + MEM_freeN(str); + BKE_reportf(op->reports, RPT_ERROR, + "Property from path %s is not a float", name); + return 0; } - - break; - case ESCKEY: - case RIGHTMOUSE: - ret = OPERATOR_CANCELLED; - break; - case LEFTMOUSE: - case PADENTER: - op->type->exec(C, op); - ret = OPERATOR_FINISHED; - break; + } + + /* check property's array length */ + if(*r_prop && (len = RNA_property_array_length(r_ptr, *r_prop)) != req_length) { + MEM_freeN(str); + BKE_reportf(op->reports, RPT_ERROR, + "Property from path %s has length %d instead of %d", + name, len, req_length); + return 0; } - /* Clamp */ - if(new_value > rc->max_value) - new_value = rc->max_value; - else if(new_value < 0) - new_value = 0; + /* success */ + MEM_freeN(str); + return 1; +} - /* Update paint data */ - rc->value = (float)new_value; +/* initialize the rna pointers and properties using rna paths */ +static int radial_control_get_properties(bContext *C, wmOperator *op) +{ + RadialControl *rc = op->customdata; + PointerRNA ctx_ptr; - RNA_float_set(op->ptr, "new_value", rc->value); + RNA_pointer_create(NULL, &RNA_Context, C, &ctx_ptr); - if(ret != OPERATOR_RUNNING_MODAL) { - WM_paint_cursor_end(CTX_wm_manager(C), rc->cursor); - MEM_freeN(rc); - } - - ED_region_tag_redraw(CTX_wm_region(C)); + if(!radial_control_get_path(&ctx_ptr, op, "data_path", &rc->ptr, &rc->prop, 0, 0, 0)) + return 0; - //if (ret != OPERATOR_RUNNING_MODAL) { - // wmWindow *win = CTX_wm_window(C); - // WM_cursor_restore(win); - //} + /* data path is required */ + if(!rc->prop) + return 0; + + if(!radial_control_get_path(&ctx_ptr, op, "rotation_path", &rc->rot_ptr, &rc->rot_prop, 1, 0, 0)) + return 0; + if(!radial_control_get_path(&ctx_ptr, op, "color_path", &rc->col_ptr, &rc->col_prop, 1, 3, 0)) + return 0; + if(!radial_control_get_path(&ctx_ptr, op, "fill_color_path", &rc->fill_col_ptr, &rc->fill_col_prop, 1, 3, 0)) + return 0; + + /* slightly ugly; allow this property to not resolve + correctly. needed because 3d texture paint shares the same + keymap as 2d image paint */ + if(!radial_control_get_path(&ctx_ptr, op, "zoom_path", &rc->zoom_ptr, &rc->zoom_prop, 1, 2, 1)) + return 0; + + if(!radial_control_get_path(&ctx_ptr, op, "image_id", &rc->image_id_ptr, NULL, 0, 0, 0)) + return 0; + else if(rc->image_id_ptr.data) { + /* extra check, pointer must be to an ID */ + if(!RNA_struct_is_ID(rc->image_id_ptr.type)) { + BKE_report(op->reports, RPT_ERROR, + "Pointer from path image_id is not an ID"); + return 0; + } + } - return ret; + return 1; } -/* Expects the operator customdata to be an ImBuf (or NULL) */ -int WM_radial_control_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int radial_control_invoke(bContext *C, wmOperator *op, wmEvent *event) { - wmRadialControl *rc = MEM_callocN(sizeof(wmRadialControl), "radial control"); - // wmWindow *win = CTX_wm_window(C); - int mode = RNA_enum_get(op->ptr, "mode"); - float initial_value = RNA_float_get(op->ptr, "initial_value"); - //float initial_size = RNA_float_get(op->ptr, "initial_size"); - int mouse[2]; - - mouse[0]= event->x; - mouse[1]= event->y; + wmWindowManager *wm; + RadialControl *rc; + int min_value_int, max_value_int, step_int; + float step_float, precision; - //if (initial_size == 0) - // initial_size = WM_RADIAL_CONTROL_DISPLAY_SIZE; + if(!(op->customdata = rc = MEM_callocN(sizeof(RadialControl), "RadialControl"))) + return OPERATOR_CANCELLED; - if(mode == WM_RADIALCONTROL_SIZE) { - rc->max_value = 200; - mouse[0]-= (int)initial_value; - } - else if(mode == WM_RADIALCONTROL_STRENGTH) { - rc->max_value = 1; - mouse[0]-= (int)(WM_RADIAL_CONTROL_DISPLAY_SIZE * (1.0f - initial_value)); - } - else if(mode == WM_RADIALCONTROL_ANGLE) { - rc->max_value = 360; - mouse[0]-= (int)(WM_RADIAL_CONTROL_DISPLAY_SIZE * cos(initial_value)); - mouse[1]-= (int)(WM_RADIAL_CONTROL_DISPLAY_SIZE * sin(initial_value)); - initial_value *= 180.0f/(float)M_PI; + if(!radial_control_get_properties(C, op)) { + MEM_freeN(rc); + return OPERATOR_CANCELLED; } - if(op->customdata) { - ImBuf *im = (ImBuf*)op->customdata; - /* Build GL texture */ - glGenTextures(1, &rc->tex); - glBindTexture(GL_TEXTURE_2D, rc->tex); - glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, im->x, im->y, 0, GL_ALPHA, GL_FLOAT, im->rect_float); - MEM_freeN(im->rect_float); - MEM_freeN(im); + /* get type, initial, min, and max values of the property */ + switch((rc->type = RNA_property_type(rc->prop))) { + case PROP_INT: + rc->initial_value = RNA_property_int_get(&rc->ptr, rc->prop); + RNA_property_int_ui_range(&rc->ptr, rc->prop, &min_value_int, + &max_value_int, &step_int); + rc->min_value = min_value_int; + rc->max_value = max_value_int; + break; + case PROP_FLOAT: + rc->initial_value = RNA_property_float_get(&rc->ptr, rc->prop); + RNA_property_float_ui_range(&rc->ptr, rc->prop, &rc->min_value, + &rc->max_value, &step_float, &precision); + break; + default: + BKE_report(op->reports, RPT_ERROR, "Property must be an integer or a float"); + MEM_freeN(rc); + return OPERATOR_CANCELLED; } - RNA_float_get_array(op->ptr, "color", rc->col); - RNA_float_get_array(op->ptr, "texture_color", rc->tex_col); - - RNA_int_set_array(op->ptr, "initial_mouse", mouse); - RNA_float_set(op->ptr, "new_value", initial_value); + /* get subtype of property */ + rc->subtype = RNA_property_subtype(rc->prop); + if(!ELEM3(rc->subtype, PROP_DISTANCE, PROP_FACTOR, PROP_ANGLE)) { + BKE_report(op->reports, RPT_ERROR, "Property must be a distance, a factor, or an angle"); + MEM_freeN(rc); + return OPERATOR_CANCELLED; + } - op->customdata = rc; - rc->mode = mode; - rc->initial_value = initial_value; - rc->initial_mouse[0] = mouse[0]; - rc->initial_mouse[1] = mouse[1]; - rc->cursor = WM_paint_cursor_activate(CTX_wm_manager(C), op->type->poll, - wm_radial_control_paint, op->customdata); + rc->current_value = rc->initial_value; + radial_control_set_initial_mouse(rc, event); + radial_control_set_tex(rc); - //WM_cursor_modal(win, CURSOR_NONE); + /* temporarily disable other paint cursors */ + wm = CTX_wm_manager(C); + rc->orig_paintcursors = wm->paintcursors; + wm->paintcursors.first = wm->paintcursors.last = NULL; + + /* add radial control paint cursor */ + rc->cursor = WM_paint_cursor_activate(wm, op->type->poll, + radial_control_paint_cursor, rc); - /* add modal handler */ WM_event_add_modal_handler(C, op); - - WM_radial_control_modal(C, op, event); - + return OPERATOR_RUNNING_MODAL; } -/* Gets a descriptive string of the operation */ -void WM_radial_control_string(wmOperator *op, char str[], int maxlen) +static void radial_control_set_value(RadialControl *rc, float val) +{ + switch(rc->type) { + case PROP_INT: + RNA_property_int_set(&rc->ptr, rc->prop, val); + break; + case PROP_FLOAT: + RNA_property_float_set(&rc->ptr, rc->prop, val); + break; + default: + break; + } +} + +static int radial_control_cancel(bContext *C, wmOperator *op) { - int mode = RNA_enum_get(op->ptr, "mode"); - float v = RNA_float_get(op->ptr, "new_value"); + RadialControl *rc = op->customdata; + wmWindowManager *wm = CTX_wm_manager(C); + + WM_paint_cursor_end(wm, rc->cursor); + + /* restore original paint cursors */ + wm->paintcursors = rc->orig_paintcursors; + + /* not sure if this is a good notifier to use; + intended purpose is to update the UI so that the + new value is displayed in sliders/numfields */ + WM_event_add_notifier(C, NC_WINDOW, NULL); + + glDeleteTextures(1, &rc->gltex); - if(mode == WM_RADIALCONTROL_SIZE) - BLI_snprintf(str, maxlen, "Size: %d", (int)v); - else if(mode == WM_RADIALCONTROL_STRENGTH) - BLI_snprintf(str, maxlen, "Strength: %d", (int)v); - else if(mode == WM_RADIALCONTROL_ANGLE) - BLI_snprintf(str, maxlen, "Angle: %d", (int)(v * 180.0f/(float)M_PI)); + MEM_freeN(rc); + + return OPERATOR_CANCELLED; } -/** Important: this doesn't define an actual operator, it - just sets up the common parts of the radial control op. **/ -void WM_OT_radial_control_partial(wmOperatorType *ot) +static int radial_control_modal(bContext *C, wmOperator *op, wmEvent *event) { - static EnumPropertyItem radial_mode_items[] = { - {WM_RADIALCONTROL_SIZE, "SIZE", 0, "Size", ""}, - {WM_RADIALCONTROL_STRENGTH, "STRENGTH", 0, "Strength", ""}, - {WM_RADIALCONTROL_ANGLE, "ANGLE", 0, "Angle", ""}, - {0, NULL, 0, NULL, NULL}}; - static float color[4] = {1.0f, 1.0f, 1.0f, 0.5f}; - static float tex_color[4] = {1.0f, 1.0f, 1.0f, 1.0f}; + RadialControl *rc = op->customdata; + float new_value, dist, zoom[2]; + float delta[2], snap, ret = OPERATOR_RUNNING_MODAL; + + /* TODO: fix hardcoded events */ + + snap = event->ctrl; + + switch(event->type) { + case MOUSEMOVE: + delta[0]= rc->initial_mouse[0] - event->x; + delta[1]= rc->initial_mouse[1] - event->y; - /* Should be set in custom invoke() */ - RNA_def_float(ot->srna, "initial_value", 0, 0, FLT_MAX, "Initial Value", "", 0, FLT_MAX); + if(rc->zoom_prop) { + RNA_property_float_get_array(&rc->zoom_ptr, rc->zoom_prop, zoom); + delta[0] /= zoom[0]; + delta[1] /= zoom[1]; + } + + dist= sqrt(delta[0]*delta[0]+delta[1]*delta[1]); + + /* calculate new value and apply snapping */ + switch(rc->subtype) { + case PROP_DISTANCE: + new_value = dist; + if(snap) new_value = ((int)new_value + 5) / 10*10; + break; + case PROP_FACTOR: + new_value = 1 - dist / WM_RADIAL_CONTROL_DISPLAY_SIZE; + if(snap) new_value = ((int)ceil(new_value * 10.f) * 10.0f) / 100.f; + break; + case PROP_ANGLE: + new_value = atan2(delta[1], delta[0]) + M_PI; + if(snap) new_value = DEG2RADF(((int)RAD2DEGF(new_value) + 5) / 10*10); + break; + default: + new_value = dist; /* dummy value, should this ever happen? - campbell */ + break; + } + + /* clamp and update */ + CLAMP(new_value, rc->min_value, rc->max_value); + radial_control_set_value(rc, new_value); + rc->current_value = new_value; + break; + + case ESCKEY: + case RIGHTMOUSE: + /* cancelled; restore original value */ + radial_control_set_value(rc, rc->initial_value); + ret = OPERATOR_CANCELLED; + break; + + case LEFTMOUSE: + case PADENTER: + /* done; value already set */ + ret = OPERATOR_FINISHED; + break; + } - /* Set internally, should be used in custom exec() to get final value */ - RNA_def_float(ot->srna, "new_value", 0, 0, FLT_MAX, "New Value", "", 0, FLT_MAX); + ED_region_tag_redraw(CTX_wm_region(C)); + + if(ret != OPERATOR_RUNNING_MODAL) + radial_control_cancel(C, op); + + return ret; +} + +static void WM_OT_radial_control(wmOperatorType *ot) +{ + ot->name= "Radial Control"; + ot->idname= "WM_OT_radial_control"; - /* Should be set before calling operator */ - RNA_def_enum(ot->srna, "mode", radial_mode_items, 0, "Mode", ""); + ot->invoke= radial_control_invoke; + ot->modal= radial_control_modal; + ot->cancel= radial_control_cancel; - /* Internal */ - RNA_def_int_vector(ot->srna, "initial_mouse", 2, NULL, INT_MIN, INT_MAX, "Initial Mouse", "", INT_MIN, INT_MAX); + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING; - RNA_def_float_color(ot->srna, "color", 4, color, 0.0f, FLT_MAX, "Color", "Radial control color", 0.0f, 1.0f); - RNA_def_float_color(ot->srna, "texture_color", 4, tex_color, 0.0f, FLT_MAX, "Texture Color", "Radial control texture color", 0.0f, 1.0f); + /* all paths relative to the context */ + RNA_def_string(ot->srna, "data_path", "", 0, "Data Path", "Path of property to be set by the radial control."); + RNA_def_string(ot->srna, "rotation_path", "", 0, "Rotation Path", "Path of property used to rotate the texture display."); + RNA_def_string(ot->srna, "color_path", "", 0, "Color Path", "Path of property used to set the color of the control."); + RNA_def_string(ot->srna, "fill_color_path", "", 0, "Fill Color Path", "Path of property used to set the fill color of the control."); + RNA_def_string(ot->srna, "zoom_path", "", 0, "Zoom Path", "Path of property used to set the zoom level for the control."); + RNA_def_string(ot->srna, "image_id", "", 0, "Image ID", "Path of ID that is used to generate an image for the control."); } /* ************************** timer for testing ***************** */ @@ -3124,6 +3454,7 @@ void wm_operatortype_init(void) WM_operatortype_append(WM_OT_splash); WM_operatortype_append(WM_OT_search_menu); WM_operatortype_append(WM_OT_call_menu); + WM_operatortype_append(WM_OT_radial_control); #if defined(WIN32) WM_operatortype_append(WM_OT_console_toggle); #endif @@ -3236,10 +3567,12 @@ static void gesture_border_modal_keymap(wmKeyConfig *keyconf) /* items for modal map */ WM_modalkeymap_add_item(keymap, ESCKEY, KM_PRESS, KM_ANY, 0, GESTURE_MODAL_CANCEL); - WM_modalkeymap_add_item(keymap, RIGHTMOUSE, KM_ANY, KM_ANY, 0, GESTURE_MODAL_CANCEL); + /* Note: cancel only on press otherwise you cannot map this to RMB-gesture */ + WM_modalkeymap_add_item(keymap, RIGHTMOUSE, KM_PRESS, KM_ANY, 0, GESTURE_MODAL_CANCEL); WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_PRESS, 0, 0, GESTURE_MODAL_BEGIN); WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_RELEASE, KM_ANY, 0, GESTURE_MODAL_SELECT); + WM_modalkeymap_add_item(keymap, RIGHTMOUSE, KM_RELEASE, KM_ANY, 0, GESTURE_MODAL_SELECT); #if 0 // Durian guys like this WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_PRESS, KM_SHIFT, 0, GESTURE_MODAL_BEGIN); @@ -3418,38 +3751,38 @@ static EnumPropertyItem *rna_id_itemf(bContext *UNUSED(C), PointerRNA *UNUSED(pt } /* can add more as needed */ -EnumPropertyItem *RNA_action_itemf(bContext *C, PointerRNA *ptr, int *do_free) +EnumPropertyItem *RNA_action_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), int *do_free) { return rna_id_itemf(C, ptr, do_free, C ? (ID *)CTX_data_main(C)->action.first : NULL, FALSE); } -EnumPropertyItem *RNA_action_local_itemf(bContext *C, PointerRNA *ptr, int *do_free) +EnumPropertyItem *RNA_action_local_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), int *do_free) { return rna_id_itemf(C, ptr, do_free, C ? (ID *)CTX_data_main(C)->action.first : NULL, TRUE); } -EnumPropertyItem *RNA_group_itemf(bContext *C, PointerRNA *ptr, int *do_free) +EnumPropertyItem *RNA_group_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), int *do_free) { return rna_id_itemf(C, ptr, do_free, C ? (ID *)CTX_data_main(C)->group.first : NULL, FALSE); } -EnumPropertyItem *RNA_group_local_itemf(bContext *C, PointerRNA *ptr, int *do_free) +EnumPropertyItem *RNA_group_local_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), int *do_free) { return rna_id_itemf(C, ptr, do_free, C ? (ID *)CTX_data_main(C)->group.first : NULL, TRUE); } -EnumPropertyItem *RNA_image_itemf(bContext *C, PointerRNA *ptr, int *do_free) +EnumPropertyItem *RNA_image_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), int *do_free) { return rna_id_itemf(C, ptr, do_free, C ? (ID *)CTX_data_main(C)->image.first : NULL, FALSE); } -EnumPropertyItem *RNA_image_local_itemf(bContext *C, PointerRNA *ptr, int *do_free) +EnumPropertyItem *RNA_image_local_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), int *do_free) { return rna_id_itemf(C, ptr, do_free, C ? (ID *)CTX_data_main(C)->image.first : NULL, TRUE); } -EnumPropertyItem *RNA_scene_itemf(bContext *C, PointerRNA *ptr, int *do_free) +EnumPropertyItem *RNA_scene_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), int *do_free) { return rna_id_itemf(C, ptr, do_free, C ? (ID *)CTX_data_main(C)->scene.first : NULL, FALSE); } -EnumPropertyItem *RNA_scene_local_itemf(bContext *C, PointerRNA *ptr, int *do_free) +EnumPropertyItem *RNA_scene_local_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), int *do_free) { return rna_id_itemf(C, ptr, do_free, C ? (ID *)CTX_data_main(C)->scene.first : NULL, TRUE); } diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index 5cf2f8932f5..9b1695be67a 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -271,9 +271,11 @@ void wm_window_close(bContext *C, wmWindowManager *wm, wmWindow *win) void wm_window_title(wmWindowManager *wm, wmWindow *win) { - /* handle the 'temp' window */ + /* handle the 'temp' window, only set title when not set before */ if(win->screen && win->screen->temp) { - GHOST_SetTitle(win->ghostwin, "Blender"); + char *title= GHOST_GetTitle(win->ghostwin); + if(title==NULL || title[0]==0) + GHOST_SetTitle(win->ghostwin, "Blender"); } else { @@ -671,13 +673,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr private) GHOST_ScreenToClient(win->ghostwin, wx, wy, &cx, &cy); win->eventstate->x= cx; - -#if defined(__APPLE__) && defined(GHOST_COCOA) - //Cocoa already uses coordinates with y=0 at bottom - win->eventstate->y= cy; -#else win->eventstate->y= (win->sizey-1) - cy; -#endif win->addmousemove= 1; /* enables highlighted buttons */ @@ -794,20 +790,13 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr private) wmEvent event; GHOST_TEventDragnDropData *ddd= GHOST_GetEventData(evt); int cx, cy, wx, wy; - /* entering window, update mouse pos */ GHOST_GetCursorPosition(g_system, &wx, &wy); GHOST_ScreenToClient(win->ghostwin, wx, wy, &cx, &cy); win->eventstate->x= cx; - -#if defined(__APPLE__) && defined(GHOST_COCOA) - //Cocoa already uses coordinates with y=0 at bottom - win->eventstate->y= cy; -#else win->eventstate->y= (win->sizey-1) - cy; -#endif event= *(win->eventstate); /* copy last state, like mouse coords */ @@ -1009,6 +998,8 @@ void WM_event_remove_timer(wmWindowManager *wm, wmWindow *UNUSED(win), wmTimer * if(wt==timer) break; if(wt) { + if(wm->reports.reporttimer == wt) + wm->reports.reporttimer= NULL; BLI_remlink(&wm->timers, wt); if(wt->customdata) @@ -1145,12 +1136,7 @@ void wm_get_cursor_position(wmWindow *win, int *x, int *y) { GHOST_GetCursorPosition(g_system, x, y); GHOST_ScreenToClient(win->ghostwin, *x, *y, x, y); -#if defined(__APPLE__) && defined(GHOST_COCOA) - //Cocoa has silly exception that should be fixed at the ghost level - //(ghost is an allegory for an invisible system specific code) -#else *y = (win->sizey-1) - *y; -#endif } /* ******************* exported api ***************** */ @@ -1183,9 +1169,8 @@ void WM_cursor_warp(wmWindow *win, int x, int y) if (win && win->ghostwin) { int oldx=x, oldy=y; -#if !defined(__APPLE__) || !defined(GHOST_COCOA) y= win->sizey -y - 1; -#endif + GHOST_ClientToScreen(win->ghostwin, x, y, &x, &y); GHOST_SetCursorPosition(g_system, x, y); diff --git a/source/blender/windowmanager/wm.h b/source/blender/windowmanager/wm.h index f73652125b1..fd279c31f3c 100644 --- a/source/blender/windowmanager/wm.h +++ b/source/blender/windowmanager/wm.h @@ -78,7 +78,7 @@ void wm_autosave_timer(const bContext *C, wmWindowManager *wm, wmTimer *wt); void wm_autosave_timer_ended(wmWindowManager *wm); void wm_autosave_delete(void); void wm_autosave_read(bContext *C, struct ReportList *reports); -void wm_autosave_location(char *filename); +void wm_autosave_location(char *filepath); /* hack to store circle select size - campbell, must replace with nice operator memory */ #define GESTURE_MEMORY |